diff --git a/VirtualFileSystem/Ext2FileSystem.cpp b/VirtualFileSystem/Ext2FileSystem.cpp index 0d265456ab..564937f019 100644 --- a/VirtualFileSystem/Ext2FileSystem.cpp +++ b/VirtualFileSystem/Ext2FileSystem.cpp @@ -561,7 +561,7 @@ bool Ext2Inode::traverse_as_directory(Function callback) const +bool Ext2FileSystem::deprecated_enumerateDirectoryInode(InodeIdentifier inode, Function callback) const { ASSERT(inode.fsid() == id()); ASSERT(isDirectoryInode(inode.index())); @@ -599,7 +599,7 @@ bool Ext2FileSystem::addInodeToDirectory(unsigned directoryInode, unsigned inode Vector entries; bool nameAlreadyExists = false; - enumerateDirectoryInode({ id(), directoryInode }, [&] (const DirectoryEntry& entry) { + deprecated_enumerateDirectoryInode({ id(), directoryInode }, [&] (const DirectoryEntry& entry) { if (!strcmp(entry.name, name.characters())) { nameAlreadyExists = true; return false; @@ -1139,40 +1139,55 @@ InodeIdentifier Ext2FileSystem::find_parent_of_inode(InodeIdentifier inode_id) c InodeIdentifier foundParent; for (auto& directory : directories_in_group) { - directory->traverse_as_directory([inode, directory, &foundParent] (auto& entry) { - if (entry.inode == inode->identifier()) { - foundParent = directory->identifier(); - return false; - } - return true; - }); - if (foundParent.isValid()) + if (!directory->reverse_lookup(inode->identifier()).isNull()) { + foundParent = directory->identifier(); break; + } } return foundParent; } +void Ext2Inode::populate_lookup_cache() +{ + { + LOCKER(m_lock); + if (!m_lookup_cache.isEmpty()) + return; + } + HashMap children; + + traverse_as_directory([&children] (auto& entry) { + children.set(String(entry.name, entry.name_length), entry.inode.index()); + return true; + }); + + LOCKER(m_lock); + if (!m_lookup_cache.isEmpty()) + return; + m_lookup_cache = move(children); +} + InodeIdentifier Ext2Inode::lookup(const String& name) { ASSERT(is_directory()); - - if (m_child_cache.isEmpty()) { - HashMap children; - - traverse_as_directory([&children] (auto& entry) { - children.set(String(entry.name, entry.name_length), entry.inode.index()); - return true; - }); - - LOCKER(m_lock); - m_child_cache = move(children); - } - + populate_lookup_cache(); LOCKER(m_lock); - auto it = m_child_cache.find(name); - if (it != m_child_cache.end()) + auto it = m_lookup_cache.find(name); + if (it != m_lookup_cache.end()) return { fsid(), (*it).value }; - + return { }; +} + +String Ext2Inode::reverse_lookup(InodeIdentifier child_id) +{ + ASSERT(is_directory()); + ASSERT(child_id.fsid() == fsid()); + populate_lookup_cache(); + LOCKER(m_lock); + for (auto it : m_lookup_cache) { + if (it.value == child_id.index()) + return it.key; + } return { }; } diff --git a/VirtualFileSystem/Ext2FileSystem.h b/VirtualFileSystem/Ext2FileSystem.h index d35da38142..c5c0b3445b 100644 --- a/VirtualFileSystem/Ext2FileSystem.h +++ b/VirtualFileSystem/Ext2FileSystem.h @@ -26,6 +26,9 @@ private: virtual void populate_metadata() const override; virtual bool traverse_as_directory(Function) override; virtual InodeIdentifier lookup(const String& name) override; + virtual String reverse_lookup(InodeIdentifier) override; + + void populate_lookup_cache(); Ext2FileSystem& fs(); const Ext2FileSystem& fs() const; @@ -33,7 +36,7 @@ private: SpinLock m_lock; Vector m_block_list; - HashMap m_child_cache; + HashMap m_lookup_cache; ext2_inode m_raw_inode; }; @@ -71,7 +74,6 @@ private: virtual const char* class_name() const override; virtual InodeIdentifier rootInode() const override; virtual bool writeInode(InodeIdentifier, const ByteBuffer&) override; - virtual bool enumerateDirectoryInode(InodeIdentifier, Function) const override; virtual InodeMetadata inodeMetadata(InodeIdentifier) const override; virtual bool set_mtime(InodeIdentifier, dword timestamp) override; virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size) override; @@ -102,6 +104,8 @@ private: unsigned m_blockGroupCount { 0 }; + bool deprecated_enumerateDirectoryInode(InodeIdentifier, Function) const; + mutable ByteBuffer m_cachedSuperBlock; mutable ByteBuffer m_cachedBlockGroupDescriptorTable; diff --git a/VirtualFileSystem/FileSystem.cpp b/VirtualFileSystem/FileSystem.cpp index 925c561333..8cc9e0b281 100644 --- a/VirtualFileSystem/FileSystem.cpp +++ b/VirtualFileSystem/FileSystem.cpp @@ -37,20 +37,6 @@ FileSystem* FileSystem::fromID(dword id) return nullptr; } -String FileSystem::name_of_child_in_directory(InodeIdentifier parent, InodeIdentifier child) const -{ - String name; - bool success = enumerateDirectoryInode(parent, [&] (auto& entry) { - if (entry.inode == child) { - name = entry.name; - return false; - } - return true; - }); - ASSERT(success); - return name; -} - ByteBuffer CoreInode::read_entire(FileDescriptor* descriptor) { return fs().readEntireInode(identifier(), descriptor); diff --git a/VirtualFileSystem/FileSystem.h b/VirtualFileSystem/FileSystem.h index 80277c5ae2..7f2ec9939e 100644 --- a/VirtualFileSystem/FileSystem.h +++ b/VirtualFileSystem/FileSystem.h @@ -43,7 +43,6 @@ public: InodeIdentifier inode; byte fileType { 0 }; }; - virtual bool enumerateDirectoryInode(InodeIdentifier, Function) const = 0; virtual bool set_mtime(InodeIdentifier, dword timestamp) = 0; virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size) = 0; @@ -54,7 +53,6 @@ public: virtual RetainPtr get_inode(InodeIdentifier) const = 0; ByteBuffer readEntireInode(InodeIdentifier, FileDescriptor* = nullptr) const; - String name_of_child_in_directory(InodeIdentifier parent, InodeIdentifier child) const; protected: FileSystem(); @@ -85,7 +83,7 @@ public: virtual Unix::ssize_t read_bytes(Unix::off_t, Unix::size_t, byte* buffer, FileDescriptor*) = 0; virtual bool traverse_as_directory(Function) = 0; virtual InodeIdentifier lookup(const String& name) = 0; - + virtual String reverse_lookup(InodeIdentifier) = 0; protected: CoreInode(FileSystem& fs, unsigned index) diff --git a/VirtualFileSystem/SyntheticFileSystem.cpp b/VirtualFileSystem/SyntheticFileSystem.cpp index 20f7a6d17d..220712a2b7 100644 --- a/VirtualFileSystem/SyntheticFileSystem.cpp +++ b/VirtualFileSystem/SyntheticFileSystem.cpp @@ -131,33 +131,6 @@ InodeIdentifier SyntheticFileSystem::rootInode() const return { id(), 1 }; } -bool SyntheticFileSystem::enumerateDirectoryInode(InodeIdentifier inode, Function callback) const -{ - InterruptDisabler disabler; - ASSERT(inode.fsid() == id()); -#ifdef SYNTHFS_DEBUG - kprintf("synthfs: enumerateDirectoryInode %u\n", inode.index()); -#endif - - auto it = m_inodes.find(inode.index()); - if (it == m_inodes.end()) { - kprintf("SynthFS: enumerateDirectoryInode with invalid inode %u\n", inode.index()); - return false; - } - const auto& synthfs_inode = *(*it).value; - if (!synthfs_inode.m_metadata.isDirectory()) { - kprintf("SynthFS: enumerateDirectoryInode with non-directory inode %u\n", inode.index()); - return false; - } - - callback({ ".", 1, synthfs_inode.m_metadata.inode, 2 }); - callback({ "..", 2, synthfs_inode.m_parent, 2 }); - - for (auto& child : synthfs_inode.m_children) - callback({ child->m_name.characters(), child->m_name.length(), child->m_metadata.inode, child->m_metadata.isDirectory() ? (byte)2 : (byte)1 }); - return true; -} - InodeMetadata SyntheticFileSystem::inodeMetadata(InodeIdentifier inode) const { InterruptDisabler disabler; @@ -334,3 +307,13 @@ InodeIdentifier SynthFSInode::lookup(const String& name) } return { }; } + +String SynthFSInode::reverse_lookup(InodeIdentifier child_id) +{ + ASSERT(is_directory()); + for (auto& child : m_children) { + if (child->identifier() == child_id) + return child->m_name; + } + return { }; +} diff --git a/VirtualFileSystem/SyntheticFileSystem.h b/VirtualFileSystem/SyntheticFileSystem.h index a1afc053d1..de14e53a47 100644 --- a/VirtualFileSystem/SyntheticFileSystem.h +++ b/VirtualFileSystem/SyntheticFileSystem.h @@ -15,7 +15,6 @@ public: virtual const char* class_name() const override; virtual InodeIdentifier rootInode() const override; virtual bool writeInode(InodeIdentifier, const ByteBuffer&) override; - virtual bool enumerateDirectoryInode(InodeIdentifier, Function) const override; virtual InodeMetadata inodeMetadata(InodeIdentifier) const override; virtual bool set_mtime(InodeIdentifier, dword timestamp) override; virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size) override; @@ -55,6 +54,7 @@ private: virtual void populate_metadata() const override; virtual bool traverse_as_directory(Function) override; virtual InodeIdentifier lookup(const String& name) override; + virtual String reverse_lookup(InodeIdentifier) override; SyntheticFileSystem& fs(); const SyntheticFileSystem& fs() const; diff --git a/VirtualFileSystem/VirtualFileSystem.cpp b/VirtualFileSystem/VirtualFileSystem.cpp index e5dd3c60e9..e351d653b6 100644 --- a/VirtualFileSystem/VirtualFileSystem.cpp +++ b/VirtualFileSystem/VirtualFileSystem.cpp @@ -486,7 +486,8 @@ String VFS::absolute_path(CoreInode& core_inode) if (auto* mount = find_mount_for_host(parent)) parent = mount->guest(); builder.append('/'); - builder.append(parent.fileSystem()->name_of_child_in_directory(parent, child)); + auto parent_inode = get_inode(parent); + builder.append(parent_inode->reverse_lookup(child)); } return builder.build(); }