mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:27:35 +00:00
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.
This commit is contained in:
parent
8fa2d7104a
commit
5f434bc00b
7 changed files with 48 additions and 18 deletions
|
@ -1152,3 +1152,27 @@ InodeIdentifier Ext2FileSystem::find_parent_of_inode(InodeIdentifier inode_id) c
|
||||||
|
|
||||||
return foundParent;
|
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 { };
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ private:
|
||||||
virtual Unix::ssize_t read_bytes(Unix::off_t, Unix::size_t, byte* buffer, FileDescriptor*) override;
|
virtual Unix::ssize_t read_bytes(Unix::off_t, Unix::size_t, byte* buffer, FileDescriptor*) override;
|
||||||
virtual void populate_metadata() const override;
|
virtual void populate_metadata() const override;
|
||||||
virtual bool traverse_as_directory(Function<bool(const FileSystem::DirectoryEntry&)>) override;
|
virtual bool traverse_as_directory(Function<bool(const FileSystem::DirectoryEntry&)>) override;
|
||||||
|
virtual InodeIdentifier lookup(const String& name) override;
|
||||||
|
|
||||||
Ext2FileSystem& fs();
|
Ext2FileSystem& fs();
|
||||||
const Ext2FileSystem& fs() const;
|
const Ext2FileSystem& fs() const;
|
||||||
|
@ -32,6 +33,7 @@ private:
|
||||||
|
|
||||||
SpinLock m_lock;
|
SpinLock m_lock;
|
||||||
Vector<unsigned> m_block_list;
|
Vector<unsigned> m_block_list;
|
||||||
|
HashMap<String, unsigned> m_child_cache;
|
||||||
ext2_inode m_raw_inode;
|
ext2_inode m_raw_inode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -37,19 +37,6 @@ FileSystem* FileSystem::fromID(dword id)
|
||||||
return nullptr;
|
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 FileSystem::name_of_child_in_directory(InodeIdentifier parent, InodeIdentifier child) const
|
||||||
{
|
{
|
||||||
String name;
|
String name;
|
||||||
|
|
|
@ -53,7 +53,6 @@ public:
|
||||||
|
|
||||||
virtual RetainPtr<CoreInode> get_inode(InodeIdentifier) const = 0;
|
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;
|
ByteBuffer readEntireInode(InodeIdentifier, FileDescriptor* = nullptr) const;
|
||||||
String name_of_child_in_directory(InodeIdentifier parent, InodeIdentifier child) const;
|
String name_of_child_in_directory(InodeIdentifier parent, InodeIdentifier child) const;
|
||||||
|
|
||||||
|
@ -81,10 +80,12 @@ public:
|
||||||
InodeIdentifier identifier() const { return { fsid(), index() }; }
|
InodeIdentifier identifier() const { return { fsid(), index() }; }
|
||||||
const InodeMetadata& metadata() const { if (!m_metadata.isValid()) { populate_metadata(); } return m_metadata; }
|
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 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 bool traverse_as_directory(Function<bool(const FileSystem::DirectoryEntry&)>) = 0;
|
||||||
|
virtual InodeIdentifier lookup(const String& name) = 0;
|
||||||
|
|
||||||
ByteBuffer read_entire(FileDescriptor* = nullptr);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CoreInode(FileSystem& fs, unsigned index)
|
CoreInode(FileSystem& fs, unsigned index)
|
||||||
|
|
|
@ -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 });
|
callback({ child->m_name.characters(), child->m_name.length(), child->m_metadata.inode, child->m_metadata.isDirectory() ? (byte)2 : (byte)1 });
|
||||||
return true;
|
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 { };
|
||||||
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ private:
|
||||||
virtual Unix::ssize_t read_bytes(Unix::off_t, Unix::size_t, byte* buffer, FileDescriptor*) override;
|
virtual Unix::ssize_t read_bytes(Unix::off_t, Unix::size_t, byte* buffer, FileDescriptor*) override;
|
||||||
virtual void populate_metadata() const override;
|
virtual void populate_metadata() const override;
|
||||||
virtual bool traverse_as_directory(Function<bool(const FileSystem::DirectoryEntry&)>) override;
|
virtual bool traverse_as_directory(Function<bool(const FileSystem::DirectoryEntry&)>) override;
|
||||||
|
virtual InodeIdentifier lookup(const String& name) override;
|
||||||
|
|
||||||
SyntheticFileSystem& fs();
|
SyntheticFileSystem& fs();
|
||||||
const SyntheticFileSystem& fs() const;
|
const SyntheticFileSystem& fs() const;
|
||||||
|
|
|
@ -525,7 +525,8 @@ InodeIdentifier VFS::resolve_path(const String& path, int& error, InodeIdentifie
|
||||||
return { };
|
return { };
|
||||||
}
|
}
|
||||||
auto parent = crumb_id;
|
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()) {
|
if (!crumb_id.isValid()) {
|
||||||
#ifdef VFS_DEBUG
|
#ifdef VFS_DEBUG
|
||||||
kprintf("child <%s>(%u) not found in directory, %02u:%08u\n", part.characters(), part.length(), parent.fsid(), parent.index());
|
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");
|
kprintf(" -- is guest\n");
|
||||||
#endif
|
#endif
|
||||||
auto mount = find_mount_for_guest(crumb_id);
|
auto mount = find_mount_for_guest(crumb_id);
|
||||||
crumb_id = mount->host();
|
auto dir_inode = get_inode(mount->host());
|
||||||
crumb_id = crumb_id.fileSystem()->child_of_directory_inode_with_name(crumb_id, "..");
|
crumb_id = dir_inode->lookup("..");
|
||||||
}
|
}
|
||||||
metadata = crumb_id.metadata();
|
metadata = crumb_id.metadata();
|
||||||
if (metadata.isSymbolicLink()) {
|
if (metadata.isSymbolicLink()) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue