Add CoreInode::reverse_lookup().

Getting the absolute path of an ext2fs inode now uses the lookup cache
which makes it a lot faster.
This commit is contained in:
Andreas Kling 2018-11-15 17:04:55 +01:00
parent 5f434bc00b
commit eced5f11e3
Notes: sideshowbarker 2024-07-19 16:10:30 +09:00
7 changed files with 61 additions and 74 deletions

View file

@ -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;
}
void Ext2Inode::populate_lookup_cache()
{
{
LOCKER(m_lock);
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());
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);
}
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 { };
}

View file

@ -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;

View file

@ -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);

View file

@ -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)

View file

@ -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 { };
}

View file

@ -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;

View file

@ -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();
}