Kernel: VFS caches currently open inodes

This commit is contained in:
Bananymous 2023-03-16 15:31:33 +02:00
parent 1292be71b2
commit 1f2ceeb329
2 changed files with 32 additions and 10 deletions

View File

@ -1,5 +1,7 @@
#pragma once
#include <BAN/HashMap.h>
#include <BAN/String.h>
#include <kernel/FS/FileSystem.h>
#include <kernel/Storage/StorageController.h>
@ -13,7 +15,9 @@ namespace Kernel
static VirtualFileSystem& get();
virtual ~VirtualFileSystem() {};
virtual const BAN::RefPtr<Inode> root_inode() const override { return m_root_inode; }
virtual const BAN::RefPtr<Inode> root_inode() const override;
void close_inode(BAN::StringView);
BAN::ErrorOr<BAN::RefPtr<Inode>> from_absolute_path(BAN::StringView);
@ -22,9 +26,8 @@ namespace Kernel
BAN::ErrorOr<void> initialize_impl();
private:
BAN::RefPtr<Inode> m_root_inode;
BAN::Vector<StorageController*> m_storage_controllers;
BAN::HashMap<BAN::String, BAN::RefPtr<Inode>> m_open_inodes;
BAN::Vector<StorageController*> m_storage_controllers;
};
}

View File

@ -93,7 +93,7 @@ namespace Kernel
{
if (partition.name() == "banan-root"sv)
{
if (m_root_inode)
if (root_inode())
dwarnln("multiple root partitions found");
else
{
@ -103,32 +103,51 @@ namespace Kernel
else
// FIXME: We leave a dangling pointer to ext2fs. This might be okay since
// root fs sould probably be always mounted
m_root_inode = ext2fs_or_error.release_value()->root_inode();
TRY(m_open_inodes.insert("/"sv, ext2fs_or_error.release_value()->root_inode()));
}
}
}
}
}
if (m_root_inode.empty())
if (!root_inode())
derrorln("Could not locate root partition");
return {};
}
const BAN::RefPtr<Inode> VirtualFileSystem::root_inode() const
{
if (!m_open_inodes.contains("/"sv))
return nullptr;
return m_open_inodes["/"sv];
}
void VirtualFileSystem::close_inode(BAN::StringView path)
{
ASSERT(m_open_inodes.contains(path));
// Delete the cached inode, if we are the only one holding a reference to it
if (m_open_inodes[path]->ref_count() == 1)
m_open_inodes.remove(path);
}
BAN::ErrorOr<BAN::RefPtr<Inode>> VirtualFileSystem::from_absolute_path(BAN::StringView path)
{
if (path.front() != '/')
return BAN::Error::from_c_string("Path must be an absolute path");
ASSERT(path.front() == '/');
if (m_open_inodes.contains(path))
return m_open_inodes[path];
auto inode = root_inode();
if (!inode)
return BAN::Error::from_c_string("No root inode available");
auto path_parts = TRY(path.split('/'));
for (BAN::StringView part : path_parts)
inode = TRY(inode->directory_find(part));
TRY(m_open_inodes.insert(path, inode));
return inode;
}