aboutsummaryrefslogtreecommitdiff
path: root/kernel/src/filesystem/vfs.cpp
diff options
context:
space:
mode:
authorMarcel Braun <marcel.braun@ost.ch>2026-03-28 19:16:27 +0100
committerMarcel Braun <marcel.braun@ost.ch>2026-03-28 19:16:27 +0100
commit2864e0b061f923a3c73c608b9c27ca4a7116e27c (patch)
tree7175be5fcaa789e0bfd6d0aeb4e7f6ac756cabf6 /kernel/src/filesystem/vfs.cpp
parent05269b10e50a80f557c2be475904ff15dc1bbec4 (diff)
parent8a9bf5a90b7f46d5c615b55a3fc418b419db4926 (diff)
downloadteachos-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.cpp146
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