aboutsummaryrefslogtreecommitdiff
path: root/kernel/src/filesystem/vfs.cpp
diff options
context:
space:
mode:
authorMarcel Braun <marcel.braun@ost.ch>2026-05-16 14:20:38 +0200
committerMarcel Braun <marcel.braun@ost.ch>2026-05-16 14:20:38 +0200
commit106e9731aaf856f940592c02953e49a496555822 (patch)
treef3916a9865d03ebb574bac7d5496f6ec85d638ed /kernel/src/filesystem/vfs.cpp
parentd22812dbf54a9fd8ecd558a94bf4ee789caf8011 (diff)
parent5b40e4a28307eed814adb46188c3f6783651d286 (diff)
downloadkernel-106e9731aaf856f940592c02953e49a496555822.tar.xz
kernel-106e9731aaf856f940592c02953e49a496555822.zip
Merge branch 'mount-reference-count' into 'develop-BA-FS26'
Mount reference count See merge request teachos/kernel!37
Diffstat (limited to 'kernel/src/filesystem/vfs.cpp')
-rw-r--r--kernel/src/filesystem/vfs.cpp97
1 files changed, 58 insertions, 39 deletions
diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp
index f5d57be..8636d0f 100644
--- a/kernel/src/filesystem/vfs.cpp
+++ b/kernel/src/filesystem/vfs.cpp
@@ -20,6 +20,7 @@
#include <optional>
#include <ranges>
#include <string_view>
+#include <utility>
namespace
{
@@ -46,20 +47,13 @@ namespace kernel::filesystem
root_fs->mount(nullptr);
auto root_fs_root_dentry = kstd::make_shared<dentry>(nullptr, root_fs->root_inode(), "/");
- m_mount_table.add_mount(kstd::make_shared<mount>(nullptr, root_fs_root_dentry, root_fs, nullptr));
+ auto root_mount = kstd::make_shared<mount>(nullptr, root_fs_root_dentry, root_fs, nullptr);
+ m_mount_table.add_mount(root_mount);
// mount devfs at /dev (inside rootfs, temporary, will be shadowed)
auto device_fs = kstd::make_shared<devfs::filesystem>();
device_fs->mount(nullptr);
-
- if (auto dev_mount_point_dentry = resolve_path("/dev"))
- {
- do_mount_internal(dev_mount_point_dentry, device_fs);
- }
- else
- {
- kapi::system::panic("[FILESYSTEM] failed to resolve /dev for initial devfs mount.");
- }
+ graft_persistent_device_fs(device_fs);
// mount boot fs at / (shadows rootfs), re-graft devfs
if (auto boot_device_dentry = resolve_path("/dev/ram0"))
@@ -68,7 +62,7 @@ namespace kernel::filesystem
{
if (auto root_dentry = resolve_path("/"))
{
- do_mount_internal(root_dentry, boot_root_fs);
+ do_mount_internal(root_dentry, root_mount, boot_root_fs);
graft_persistent_device_fs(device_fs);
}
}
@@ -87,7 +81,26 @@ namespace kernel::filesystem
auto vfs::open(std::string_view path) -> kstd::shared_ptr<dentry>
{
- return resolve_path(path);
+ auto [dentry, mount] = resolve_path_internal(path);
+ if (!dentry || !mount)
+ {
+ return nullptr;
+ }
+ mount->increment_ref_count();
+ return dentry;
+ }
+
+ auto vfs::close(std::string_view path) -> operation_result
+ {
+ if (auto mount = find_mount(path))
+ {
+ if (mount->decrement_ref_count())
+ {
+ return operation_result::success;
+ }
+ return operation_result::close_failed;
+ }
+ return operation_result::invalid_path;
}
auto vfs::do_mount(std::string_view source, std::string_view target) -> operation_result
@@ -97,13 +110,15 @@ namespace kernel::filesystem
return operation_result::invalid_path;
}
- if (auto mount_point_dentry = resolve_path(target))
+ auto [mount_point_dentry, mount_context] = resolve_path_internal(target);
+
+ if (mount_point_dentry && mount_context)
{
if (auto source_dentry = resolve_path(source))
{
if (auto fs = kernel::filesystem::filesystem::probe_and_mount(source_dentry->get_inode()))
{
- do_mount_internal(mount_point_dentry, fs);
+ do_mount_internal(mount_point_dentry, mount_context, fs);
return operation_result::success;
}
return operation_result::invalid_filesystem;
@@ -125,25 +140,18 @@ namespace kernel::filesystem
{
return operation_result::success;
}
-
- if (remove_result == mount_table::operation_result::has_child_mounts)
+ else if (remove_result == mount_table::operation_result::mount_not_found)
{
- return operation_result::unmount_failed;
+ return operation_result::mount_point_not_found;
}
- return operation_result::mount_point_not_found;
+ return operation_result::unmount_failed;
}
auto vfs::do_mount_internal(kstd::shared_ptr<dentry> const & mount_point_dentry,
- kstd::shared_ptr<filesystem> const & fs) -> void
+ kstd::shared_ptr<mount> const & parent_mount, kstd::shared_ptr<filesystem> const & fs)
+ -> void
{
- auto parent_mount_dentry = mount_point_dentry->find_mount_root_dentry();
- kstd::shared_ptr<mount> parent_mount = nullptr;
- if (parent_mount_dentry)
- {
- parent_mount = m_mount_table.find_exact_mount(parent_mount_dentry->get_absolute_path().view());
- }
-
auto new_fs_root =
kstd::make_shared<dentry>(mount_point_dentry->get_parent(), fs->root_inode(), mount_point_dentry->get_name());
auto new_mount = kstd::make_shared<mount>(mount_point_dentry, new_fs_root, fs, parent_mount);
@@ -152,27 +160,28 @@ namespace kernel::filesystem
auto vfs::graft_persistent_device_fs(kstd::shared_ptr<devfs::filesystem> const & device_fs) -> void
{
- if (auto new_root_dentry = resolve_path("/"))
+ auto [root_mount_point_dentry, root_mount] = resolve_path_internal("/");
+ if (root_mount_point_dentry && root_mount)
{
- auto dev_dentry = new_root_dentry->find_child("dev");
+ auto dev_dentry = root_mount_point_dentry->find_child("dev");
if (!dev_dentry)
{
- dev_dentry = kstd::make_shared<dentry>(new_root_dentry, device_fs->root_inode(), "dev");
- new_root_dentry->add_child(dev_dentry);
+ dev_dentry = kstd::make_shared<dentry>(root_mount_point_dentry, device_fs->root_inode(), "dev");
+ root_mount_point_dentry->add_child(dev_dentry);
}
- do_mount_internal(dev_dentry, device_fs);
+ do_mount_internal(dev_dentry, root_mount, device_fs);
}
}
- auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr<dentry>
+ auto vfs::resolve_path_internal(std::string_view path) -> std::pair<kstd::shared_ptr<dentry>, kstd::shared_ptr<mount>>
{
if (!path::is_valid_absolute_path(path))
{
- return nullptr;
+ return {nullptr, nullptr};
}
- auto current_mount = m_mount_table.find_exact_mount("/");
+ auto current_mount = m_mount_table.find_mount("/");
if (!current_mount)
{
kapi::system::panic("[FILESYSTEM] no root mount found.");
@@ -225,7 +234,7 @@ namespace kernel::filesystem
auto found_inode = current_fs->lookup(current_dentry->get_inode(), part.view());
if (!found_inode)
{
- return nullptr;
+ return {nullptr, nullptr};
}
next_dentry = kstd::make_shared<dentry>(current_dentry, found_inode, part.view());
@@ -233,7 +242,7 @@ namespace kernel::filesystem
}
else if (next_dentry->has_flag(dentry::dentry_flags::is_mount_point))
{
- current_mount = m_mount_table.find_exact_mount(next_dentry->get_absolute_path().view());
+ current_mount = m_mount_table.find_mount(next_dentry->get_absolute_path().view());
if (!current_mount)
{
kapi::system::panic("[FILESYSTEM] mount for dentry with mounted flag not found.");
@@ -246,7 +255,7 @@ namespace kernel::filesystem
{
if (symlink_counter++ > constants::symloop_max)
{
- return nullptr;
+ return {nullptr, nullptr};
}
kstd::vector<uint8_t> buffer(constants::symlink_max_path_length);
@@ -261,7 +270,7 @@ namespace kernel::filesystem
if (path::is_valid_absolute_path(symbolic_link_path))
{
- current_mount = m_mount_table.find_exact_mount("/");
+ current_mount = m_mount_table.find_mount("/");
current_dentry = current_mount->get_root_dentry();
}
continue;
@@ -269,9 +278,19 @@ namespace kernel::filesystem
current_dentry = next_dentry;
}
+ return {current_dentry, current_mount};
+ }
- return current_dentry;
+ auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr<dentry>
+ {
+ return resolve_path_internal(path).first;
}
+
+ auto vfs::find_mount(std::string_view path) -> kstd::shared_ptr<mount>
+ {
+ return resolve_path_internal(path).second;
+ }
+
} // namespace kernel::filesystem
namespace kernel::tests::filesystem::vfs