mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-22 12:35:14 +00:00
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:
parent
5f434bc00b
commit
eced5f11e3
Notes:
sideshowbarker
2024-07-19 16:10:30 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/eced5f11e39
7 changed files with 61 additions and 74 deletions
|
@ -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 { };
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 { };
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue