mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 09:08:12 +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
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;
|
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(inode.fsid() == id());
|
||||||
ASSERT(isDirectoryInode(inode.index()));
|
ASSERT(isDirectoryInode(inode.index()));
|
||||||
|
@ -599,7 +599,7 @@ bool Ext2FileSystem::addInodeToDirectory(unsigned directoryInode, unsigned inode
|
||||||
|
|
||||||
Vector<DirectoryEntry> entries;
|
Vector<DirectoryEntry> entries;
|
||||||
bool nameAlreadyExists = false;
|
bool nameAlreadyExists = false;
|
||||||
enumerateDirectoryInode({ id(), directoryInode }, [&] (const DirectoryEntry& entry) {
|
deprecated_enumerateDirectoryInode({ id(), directoryInode }, [&] (const DirectoryEntry& entry) {
|
||||||
if (!strcmp(entry.name, name.characters())) {
|
if (!strcmp(entry.name, name.characters())) {
|
||||||
nameAlreadyExists = true;
|
nameAlreadyExists = true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -1139,40 +1139,55 @@ InodeIdentifier Ext2FileSystem::find_parent_of_inode(InodeIdentifier inode_id) c
|
||||||
|
|
||||||
InodeIdentifier foundParent;
|
InodeIdentifier foundParent;
|
||||||
for (auto& directory : directories_in_group) {
|
for (auto& directory : directories_in_group) {
|
||||||
directory->traverse_as_directory([inode, directory, &foundParent] (auto& entry) {
|
if (!directory->reverse_lookup(inode->identifier()).isNull()) {
|
||||||
if (entry.inode == inode->identifier()) {
|
foundParent = directory->identifier();
|
||||||
foundParent = directory->identifier();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
if (foundParent.isValid())
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return foundParent;
|
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)
|
InodeIdentifier Ext2Inode::lookup(const String& name)
|
||||||
{
|
{
|
||||||
ASSERT(is_directory());
|
ASSERT(is_directory());
|
||||||
|
populate_lookup_cache();
|
||||||
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);
|
LOCKER(m_lock);
|
||||||
auto it = m_child_cache.find(name);
|
auto it = m_lookup_cache.find(name);
|
||||||
if (it != m_child_cache.end())
|
if (it != m_lookup_cache.end())
|
||||||
return { fsid(), (*it).value };
|
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 { };
|
return { };
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,9 @@ private:
|
||||||
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;
|
virtual InodeIdentifier lookup(const String& name) override;
|
||||||
|
virtual String reverse_lookup(InodeIdentifier) override;
|
||||||
|
|
||||||
|
void populate_lookup_cache();
|
||||||
|
|
||||||
Ext2FileSystem& fs();
|
Ext2FileSystem& fs();
|
||||||
const Ext2FileSystem& fs() const;
|
const Ext2FileSystem& fs() const;
|
||||||
|
@ -33,7 +36,7 @@ private:
|
||||||
|
|
||||||
SpinLock m_lock;
|
SpinLock m_lock;
|
||||||
Vector<unsigned> m_block_list;
|
Vector<unsigned> m_block_list;
|
||||||
HashMap<String, unsigned> m_child_cache;
|
HashMap<String, unsigned> m_lookup_cache;
|
||||||
ext2_inode m_raw_inode;
|
ext2_inode m_raw_inode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -71,7 +74,6 @@ private:
|
||||||
virtual const char* class_name() const override;
|
virtual const char* class_name() const override;
|
||||||
virtual InodeIdentifier rootInode() const override;
|
virtual InodeIdentifier rootInode() const override;
|
||||||
virtual bool writeInode(InodeIdentifier, const ByteBuffer&) 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 InodeMetadata inodeMetadata(InodeIdentifier) const override;
|
||||||
virtual bool set_mtime(InodeIdentifier, dword timestamp) override;
|
virtual bool set_mtime(InodeIdentifier, dword timestamp) override;
|
||||||
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size) 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 };
|
unsigned m_blockGroupCount { 0 };
|
||||||
|
|
||||||
|
bool deprecated_enumerateDirectoryInode(InodeIdentifier, Function<bool(const DirectoryEntry&)>) const;
|
||||||
|
|
||||||
mutable ByteBuffer m_cachedSuperBlock;
|
mutable ByteBuffer m_cachedSuperBlock;
|
||||||
mutable ByteBuffer m_cachedBlockGroupDescriptorTable;
|
mutable ByteBuffer m_cachedBlockGroupDescriptorTable;
|
||||||
|
|
||||||
|
|
|
@ -37,20 +37,6 @@ FileSystem* FileSystem::fromID(dword id)
|
||||||
return nullptr;
|
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)
|
ByteBuffer CoreInode::read_entire(FileDescriptor* descriptor)
|
||||||
{
|
{
|
||||||
return fs().readEntireInode(identifier(), descriptor);
|
return fs().readEntireInode(identifier(), descriptor);
|
||||||
|
|
|
@ -43,7 +43,6 @@ public:
|
||||||
InodeIdentifier inode;
|
InodeIdentifier inode;
|
||||||
byte fileType { 0 };
|
byte fileType { 0 };
|
||||||
};
|
};
|
||||||
virtual bool enumerateDirectoryInode(InodeIdentifier, Function<bool(const DirectoryEntry&)>) const = 0;
|
|
||||||
|
|
||||||
virtual bool set_mtime(InodeIdentifier, dword timestamp) = 0;
|
virtual bool set_mtime(InodeIdentifier, dword timestamp) = 0;
|
||||||
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size) = 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;
|
virtual RetainPtr<CoreInode> get_inode(InodeIdentifier) const = 0;
|
||||||
|
|
||||||
ByteBuffer readEntireInode(InodeIdentifier, FileDescriptor* = nullptr) const;
|
ByteBuffer readEntireInode(InodeIdentifier, FileDescriptor* = nullptr) const;
|
||||||
String name_of_child_in_directory(InodeIdentifier parent, InodeIdentifier child) const;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FileSystem();
|
FileSystem();
|
||||||
|
@ -85,7 +83,7 @@ public:
|
||||||
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;
|
virtual InodeIdentifier lookup(const String& name) = 0;
|
||||||
|
virtual String reverse_lookup(InodeIdentifier) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CoreInode(FileSystem& fs, unsigned index)
|
CoreInode(FileSystem& fs, unsigned index)
|
||||||
|
|
|
@ -131,33 +131,6 @@ InodeIdentifier SyntheticFileSystem::rootInode() const
|
||||||
return { id(), 1 };
|
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
|
InodeMetadata SyntheticFileSystem::inodeMetadata(InodeIdentifier inode) const
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
|
@ -334,3 +307,13 @@ InodeIdentifier SynthFSInode::lookup(const String& name)
|
||||||
}
|
}
|
||||||
return { };
|
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 const char* class_name() const override;
|
||||||
virtual InodeIdentifier rootInode() const override;
|
virtual InodeIdentifier rootInode() const override;
|
||||||
virtual bool writeInode(InodeIdentifier, const ByteBuffer&) 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 InodeMetadata inodeMetadata(InodeIdentifier) const override;
|
||||||
virtual bool set_mtime(InodeIdentifier, dword timestamp) override;
|
virtual bool set_mtime(InodeIdentifier, dword timestamp) override;
|
||||||
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size) 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 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;
|
virtual InodeIdentifier lookup(const String& name) override;
|
||||||
|
virtual String reverse_lookup(InodeIdentifier) override;
|
||||||
|
|
||||||
SyntheticFileSystem& fs();
|
SyntheticFileSystem& fs();
|
||||||
const SyntheticFileSystem& fs() const;
|
const SyntheticFileSystem& fs() const;
|
||||||
|
|
|
@ -486,7 +486,8 @@ String VFS::absolute_path(CoreInode& core_inode)
|
||||||
if (auto* mount = find_mount_for_host(parent))
|
if (auto* mount = find_mount_for_host(parent))
|
||||||
parent = mount->guest();
|
parent = mount->guest();
|
||||||
builder.append('/');
|
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();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue