diff options
Diffstat (limited to 'kernel/src/filesystem/vfs.cpp')
| -rw-r--r-- | kernel/src/filesystem/vfs.cpp | 97 |
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 |
