瀏覽代碼

Add CoreInode::reverse_lookup().

Getting the absolute path of an ext2fs inode now uses the lookup cache
which makes it a lot faster.
Andreas Kling 6 年之前
父節點
當前提交
eced5f11e3

+ 39 - 24
VirtualFileSystem/Ext2FileSystem.cpp

@@ -561,7 +561,7 @@ bool Ext2Inode::traverse_as_directory(Function<bool(const FileSystem::DirectoryE
     return true;
 }
 
-bool Ext2FileSystem::enumerateDirectoryInode(InodeIdentifier inode, Function<bool(const DirectoryEntry&)> callback) const
+bool Ext2FileSystem::deprecated_enumerateDirectoryInode(InodeIdentifier inode, Function<bool(const DirectoryEntry&)> callback) const
 {
     ASSERT(inode.fsid() == id());
     ASSERT(isDirectoryInode(inode.index()));
@@ -599,7 +599,7 @@ bool Ext2FileSystem::addInodeToDirectory(unsigned directoryInode, unsigned inode
 
     Vector<DirectoryEntry> 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;
 }
 
-InodeIdentifier Ext2Inode::lookup(const String& name)
+void Ext2Inode::populate_lookup_cache()
 {
-    ASSERT(is_directory());
-
-    if (m_child_cache.isEmpty()) {
-        HashMap<String, unsigned> 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);
+        if (!m_lookup_cache.isEmpty())
+            return;
     }
+    HashMap<String, unsigned> 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());
+    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 { };
 }

+ 6 - 2
VirtualFileSystem/Ext2FileSystem.h

@@ -26,6 +26,9 @@ private:
     virtual void populate_metadata() const override;
     virtual bool traverse_as_directory(Function<bool(const FileSystem::DirectoryEntry&)>) 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<unsigned> m_block_list;
-    HashMap<String, unsigned> m_child_cache;
+    HashMap<String, unsigned> 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<bool(const DirectoryEntry&)>) 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<bool(const DirectoryEntry&)>) const;
+
     mutable ByteBuffer m_cachedSuperBlock;
     mutable ByteBuffer m_cachedBlockGroupDescriptorTable;
 

+ 0 - 14
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);

+ 1 - 3
VirtualFileSystem/FileSystem.h

@@ -43,7 +43,6 @@ public:
         InodeIdentifier inode;
         byte fileType { 0 };
     };
-    virtual bool enumerateDirectoryInode(InodeIdentifier, Function<bool(const DirectoryEntry&)>) 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<CoreInode> 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<bool(const FileSystem::DirectoryEntry&)>) = 0;
     virtual InodeIdentifier lookup(const String& name) = 0;
-
+    virtual String reverse_lookup(InodeIdentifier) = 0;
 
 protected:
     CoreInode(FileSystem& fs, unsigned index)

+ 10 - 27
VirtualFileSystem/SyntheticFileSystem.cpp

@@ -131,33 +131,6 @@ InodeIdentifier SyntheticFileSystem::rootInode() const
     return { id(), 1 };
 }
 
-bool SyntheticFileSystem::enumerateDirectoryInode(InodeIdentifier inode, Function<bool(const DirectoryEntry&)> 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 { };
+}

+ 1 - 1
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<bool(const DirectoryEntry&)>) 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<bool(const FileSystem::DirectoryEntry&)>) override;
     virtual InodeIdentifier lookup(const String& name) override;
+    virtual String reverse_lookup(InodeIdentifier) override;
 
     SyntheticFileSystem& fs();
     const SyntheticFileSystem& fs() const;

+ 2 - 1
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();
 }