Ver código fonte

Add CoreInode::lookup() for directory lookups.

Also add a name-to-inode lookup cache to Ext2Inode. This seems like a great
speedup for filesystem traversal.
Andreas Kling 6 anos atrás
pai
commit
5f434bc00b

+ 24 - 0
VirtualFileSystem/Ext2FileSystem.cpp

@@ -1152,3 +1152,27 @@ InodeIdentifier Ext2FileSystem::find_parent_of_inode(InodeIdentifier inode_id) c
 
     return foundParent;
 }
+
+InodeIdentifier Ext2Inode::lookup(const String& name)
+{
+    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);
+    }
+
+    LOCKER(m_lock);
+    auto it = m_child_cache.find(name);
+    if (it != m_child_cache.end())
+        return { fsid(), (*it).value };
+
+    return { };
+}

+ 2 - 0
VirtualFileSystem/Ext2FileSystem.h

@@ -25,6 +25,7 @@ private:
     virtual Unix::ssize_t read_bytes(Unix::off_t, Unix::size_t, byte* buffer, FileDescriptor*) override;
     virtual void populate_metadata() const override;
     virtual bool traverse_as_directory(Function<bool(const FileSystem::DirectoryEntry&)>) override;
+    virtual InodeIdentifier lookup(const String& name) override;
 
     Ext2FileSystem& fs();
     const Ext2FileSystem& fs() const;
@@ -32,6 +33,7 @@ private:
 
     SpinLock m_lock;
     Vector<unsigned> m_block_list;
+    HashMap<String, unsigned> m_child_cache;
     ext2_inode m_raw_inode;
 };
 

+ 0 - 13
VirtualFileSystem/FileSystem.cpp

@@ -37,19 +37,6 @@ FileSystem* FileSystem::fromID(dword id)
     return nullptr;
 }
 
-InodeIdentifier FileSystem::child_of_directory_inode_with_name(InodeIdentifier inode, const String& name) const
-{
-    InodeIdentifier foundInode;
-    enumerateDirectoryInode(inode, [&] (const DirectoryEntry& entry) {
-        if (!strcmp(entry.name, name.characters())) {
-            foundInode = entry.inode;
-            return false;
-        }
-        return true;
-    });
-    return foundInode;
-}
-
 String FileSystem::name_of_child_in_directory(InodeIdentifier parent, InodeIdentifier child) const
 {
     String name;

+ 3 - 2
VirtualFileSystem/FileSystem.h

@@ -53,7 +53,6 @@ public:
 
     virtual RetainPtr<CoreInode> get_inode(InodeIdentifier) const = 0;
 
-    InodeIdentifier child_of_directory_inode_with_name(InodeIdentifier, const String& name) const;
     ByteBuffer readEntireInode(InodeIdentifier, FileDescriptor* = nullptr) const;
     String name_of_child_in_directory(InodeIdentifier parent, InodeIdentifier child) const;
 
@@ -81,10 +80,12 @@ public:
     InodeIdentifier identifier() const { return { fsid(), index() }; }
     const InodeMetadata& metadata() const { if (!m_metadata.isValid()) { populate_metadata(); } return m_metadata; }
 
+    ByteBuffer read_entire(FileDescriptor* = nullptr);
+
     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;
 
-    ByteBuffer read_entire(FileDescriptor* = nullptr);
 
 protected:
     CoreInode(FileSystem& fs, unsigned index)

+ 14 - 0
VirtualFileSystem/SyntheticFileSystem.cpp

@@ -320,3 +320,17 @@ bool SynthFSInode::traverse_as_directory(Function<bool(const FileSystem::Directo
         callback({ child->m_name.characters(), child->m_name.length(), child->m_metadata.inode, child->m_metadata.isDirectory() ? (byte)2 : (byte)1 });
     return true;
 }
+
+InodeIdentifier SynthFSInode::lookup(const String& name)
+{
+    ASSERT(is_directory());
+    if (name == ".")
+        return identifier();
+    if (name == "..")
+        return m_parent;
+    for (auto& child : m_children) {
+        if (child->m_name == name)
+            return child->identifier();
+    }
+    return { };
+}

+ 1 - 0
VirtualFileSystem/SyntheticFileSystem.h

@@ -54,6 +54,7 @@ private:
     virtual Unix::ssize_t read_bytes(Unix::off_t, Unix::size_t, byte* buffer, FileDescriptor*) override;
     virtual void populate_metadata() const override;
     virtual bool traverse_as_directory(Function<bool(const FileSystem::DirectoryEntry&)>) override;
+    virtual InodeIdentifier lookup(const String& name) override;
 
     SyntheticFileSystem& fs();
     const SyntheticFileSystem& fs() const;

+ 4 - 3
VirtualFileSystem/VirtualFileSystem.cpp

@@ -525,7 +525,8 @@ InodeIdentifier VFS::resolve_path(const String& path, int& error, InodeIdentifie
             return { };
         }
         auto parent = crumb_id;
-        crumb_id = crumb_id.fileSystem()->child_of_directory_inode_with_name(crumb_id, part);
+        auto dir_inode = get_inode(crumb_id);
+        crumb_id = dir_inode->lookup(part);
         if (!crumb_id.isValid()) {
 #ifdef VFS_DEBUG
             kprintf("child <%s>(%u) not found in directory, %02u:%08u\n", part.characters(), part.length(), parent.fsid(), parent.index());
@@ -547,8 +548,8 @@ InodeIdentifier VFS::resolve_path(const String& path, int& error, InodeIdentifie
             kprintf("  -- is guest\n");
 #endif
             auto mount = find_mount_for_guest(crumb_id);
-            crumb_id = mount->host();
-            crumb_id = crumb_id.fileSystem()->child_of_directory_inode_with_name(crumb_id, "..");
+            auto dir_inode = get_inode(mount->host());
+            crumb_id = dir_inode->lookup("..");
         }
         metadata = crumb_id.metadata();
         if (metadata.isSymbolicLink()) {