diff options
| author | Marcel Braun <marcel.braun@ost.ch> | 2026-03-28 19:16:27 +0100 |
|---|---|---|
| committer | Marcel Braun <marcel.braun@ost.ch> | 2026-03-28 19:16:27 +0100 |
| commit | 2864e0b061f923a3c73c608b9c27ca4a7116e27c (patch) | |
| tree | 7175be5fcaa789e0bfd6d0aeb4e7f6ac756cabf6 /kernel/src/filesystem/vfs.cpp | |
| parent | 05269b10e50a80f557c2be475904ff15dc1bbec4 (diff) | |
| parent | 8a9bf5a90b7f46d5c615b55a3fc418b419db4926 (diff) | |
| download | teachos-2864e0b061f923a3c73c608b9c27ca4a7116e27c.tar.xz teachos-2864e0b061f923a3c73c608b9c27ca4a7116e27c.zip | |
Merge branch 'vfs' into 'develop-BA-FS26'
implement basic vfs
See merge request teachos/kernel!16
Diffstat (limited to 'kernel/src/filesystem/vfs.cpp')
| -rw-r--r-- | kernel/src/filesystem/vfs.cpp | 146 |
1 files changed, 94 insertions, 52 deletions
diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 4e0b6bf..7a90531 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -2,20 +2,19 @@ #include "kapi/system.hpp" -#include "kernel/devices/device.hpp" #include "kernel/devices/storage/storage_management.hpp" -#include "kernel/filesystem/custody.hpp" -#include "kernel/filesystem/device_file.hpp" +#include "kernel/filesystem/dentry.hpp" +#include "kernel/filesystem/devfs/devfs_filesystem.hpp" #include "kernel/filesystem/ext2/ext2_filesystem.hpp" -#include "kernel/filesystem/inode.hpp" -#include "kernel/filesystem/inode_file.hpp" +#include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/mount.hpp" #include "kernel/filesystem/open_file_description.hpp" +#include "kernel/filesystem/rootfs/rootfs_filesystem.hpp" #include <kstd/memory> -#include <algorithm> #include <optional> +#include <ranges> #include <string_view> namespace filesystem @@ -33,26 +32,29 @@ namespace filesystem } active_vfs.emplace(vfs{}); + active_vfs->init_internal(); + } - auto storage_mgmt = devices::storage::storage_management::get(); - if (auto boot_device = storage_mgmt.determine_boot_device()) - { - active_vfs->m_root_fs = kstd::make_shared<ext2::ext2_filesystem>(); - if (active_vfs->m_root_fs->mount(boot_device) != 0) - { - kapi::system::panic("[FILESYSTEM] Failed to mount root filesystem."); - } + auto vfs::init_internal() -> void + { + auto root_fs = kstd::make_shared<rootfs::rootfs_filesystem>(); + root_fs->mount(nullptr); - active_vfs->m_root_mount = mount{"/", active_vfs->m_root_fs}; + 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, "")); - std::ranges::for_each(storage_mgmt.all_controllers(), [&](auto controller) { - std::ranges::for_each(controller->all_devices(), [&](auto device) { active_vfs->make_device_node(device); }); - }); - } - else + auto storage_mgmt = devices::storage::storage_management::get(); + if (auto boot_device = storage_mgmt.determine_boot_device()) { - // TODO BA-FS26 ?? what when no boot_device == no modules loaded?? + // TODO BA-FS26 detect fs type from boot device and load corresponding fs, for now just assume ext2 + auto boot_root_fs = kstd::make_shared<ext2::ext2_filesystem>(); + boot_root_fs->mount(boot_device); + do_mount_internal("/", root_fs_root_dentry, boot_root_fs); } + + auto device_fs = kstd::make_shared<devfs::devfs_filesystem>(); + device_fs->mount(nullptr); + do_mount_internal("/dev", root_fs_root_dentry, device_fs); } auto vfs::get() -> vfs & @@ -65,58 +67,98 @@ namespace filesystem return *active_vfs; } - auto vfs::open(std::string_view path) -> std::optional<open_file_description> + auto vfs::open(std::string_view path) -> kstd::shared_ptr<open_file_description> { - if (auto custody = resolve_path(path)) + if (auto dentry = resolve_path(path)) { - auto node = custody->get_inode(); - if (node->is_device()) - { - auto current_device_file = kstd::make_shared<device_file>(node->backing_device()); - current_device_file->open(); - return open_file_description{current_device_file}; - } - - auto current_inode_file = kstd::make_shared<inode_file>(node); - current_inode_file->open(); - return open_file_description{current_inode_file}; + return kstd::make_shared<open_file_description>(dentry->get_inode()); } - return std::nullopt; + return nullptr; } - auto vfs::make_device_node(kstd::shared_ptr<devices::device> const & device) -> void + auto vfs::do_mount(std::string_view path, kstd::shared_ptr<filesystem> const & filesystem) -> int { - if (!device) + if (!filesystem) { - kapi::system::panic("[FILESYSTEM] make_device_node called with null device."); + return -1; // TODO BA-FS26 panic or errorcode? } - m_device_nodes.push_back(device_node_entry{device->name(), kstd::make_shared<inode>(device)}); + if (path.empty() || path.front() != '/') + { + return -1; // TODO BA-FS26 panic or errorcode? + } + + // TODO BA-FS26 better path validation + if ((path.size() > 1 && path.back() == '/')) + { + return -1; // TODO BA-FS26 panic or errorcode? + } + + if (auto mount_point_dentry = resolve_path(path)) + { + do_mount_internal(path, mount_point_dentry, filesystem); + return 0; + } + + return -1; } - auto vfs::resolve_path(std::string_view path) -> std::optional<custody> + auto vfs::do_mount_internal(std::string_view path, kstd::shared_ptr<dentry> const & mount_point_dentry, + kstd::shared_ptr<filesystem> const & fs) -> void { - // TODO BA-FS26 implement real path resolution with mounts and directories etc. - // For now, just support device nodes at /dev/<device_name>. + // TODO BA-FS26 check if mount point is already mounted and handle it (unmount old fs, fail, etc.) + auto new_fs_root = kstd::make_shared<dentry>(mount_point_dentry, fs->root_inode()); + auto new_mount = kstd::make_shared<mount>(mount_point_dentry, new_fs_root, fs, path); + m_mount_table.add_mount(new_mount); + mount_point_dentry->set_flag(dentry::dentry_flags::dcache_mounted); + } + + auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr<dentry> + { + // TODO BA-FS26 implement full path resolution semantics. + // TODO BA-FS26 better path validation + // TODO BA-FS26 implement a path parser (maybe in libs?) and use it here and in do_mount + + if (path.empty() || path.front() != '/') + return nullptr; - constexpr auto device_prefix = std::string_view{"/dev/"}; - if (path.starts_with(device_prefix)) + // TODO BA-FS26 longest match in mount_table -> jump into final fs directly + // TODO BA-FS26 performance optimization first check mounted_flag O(1) then check mount_table O(n) + + auto best_mount = m_mount_table.find_longest_prefix_mount(path); + if (!best_mount) + { + kapi::system::panic("[FILESYSTEM] no root mount found."); + } + + auto current_dentry = best_mount->root_dentry(); + auto current_fs = best_mount->get_filesystem(); + + std::string_view remaining = path.substr(best_mount->get_mount_path().size()); + + auto path_parts = + std::views::split(remaining, '/') | std::views::filter([](auto const & part) { return !part.empty(); }); + + for (auto const & part : path_parts) { - auto const device_name = path.substr(device_prefix.size()); - auto entry = std::ranges::find_if(m_device_nodes, [&](auto const & device_entry) { - return device_entry.has_value() && device_entry->name == device_name; - }); + std::string_view part_view{part}; - if (entry != m_device_nodes.end()) + auto next_dentry = current_dentry->find_child(part_view); + if (!next_dentry) { - return custody{nullptr, entry->value().node}; + auto found_inode = current_fs->lookup(current_dentry->get_inode(), part_view); + if (!found_inode) + return nullptr; + + next_dentry = kstd::make_shared<dentry>(current_dentry, found_inode, part_view); + current_dentry->add_child(next_dentry); } - return std::nullopt; + current_dentry = next_dentry; } - return std::nullopt; + return current_dentry; } } // namespace filesystem
\ No newline at end of file |
