aboutsummaryrefslogtreecommitdiff
path: root/kernel/src/filesystem
diff options
context:
space:
mode:
authorLukas Oesch <lukasoesch20@gmail.com>2026-03-28 17:28:32 +0100
committerLukas Oesch <lukasoesch20@gmail.com>2026-03-28 17:28:32 +0100
commita6f93bf8df0dbfa7d19aa1168bfc8b052e41c42f (patch)
treeb07657406fd2ce67e69819326b0c76e9409ef77c /kernel/src/filesystem
parent4f7ae11655807acf68f49637cc9dd01a03af36d5 (diff)
downloadteachos-a6f93bf8df0dbfa7d19aa1168bfc8b052e41c42f.tar.xz
teachos-a6f93bf8df0dbfa7d19aa1168bfc8b052e41c42f.zip
fix vfs mount with /dev & /a and rootfs & devfs
Diffstat (limited to 'kernel/src/filesystem')
-rw-r--r--kernel/src/filesystem/devfs/devfs_filesystem.cpp3
-rw-r--r--kernel/src/filesystem/mount.cpp11
-rw-r--r--kernel/src/filesystem/mount_table.cpp29
-rw-r--r--kernel/src/filesystem/rootfs/rootfs_filesystem.cpp2
-rw-r--r--kernel/src/filesystem/vfs.cpp122
5 files changed, 82 insertions, 85 deletions
diff --git a/kernel/src/filesystem/devfs/devfs_filesystem.cpp b/kernel/src/filesystem/devfs/devfs_filesystem.cpp
index cfd2d88..c4cd81a 100644
--- a/kernel/src/filesystem/devfs/devfs_filesystem.cpp
+++ b/kernel/src/filesystem/devfs/devfs_filesystem.cpp
@@ -13,10 +13,11 @@
namespace filesystem::devfs
{
- auto devfs_filesystem::mount(kstd::shared_ptr<devices::device> const & /*device*/) -> int
+ auto devfs_filesystem::mount(kstd::shared_ptr<devices::device> const &) -> int
{
m_root_inode = kstd::make_shared<devfs_root_inode>();
build_device_inode_table();
+
return 0;
}
diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp
index d9937dc..afc07fa 100644
--- a/kernel/src/filesystem/mount.cpp
+++ b/kernel/src/filesystem/mount.cpp
@@ -6,14 +6,16 @@
#include "kernel/filesystem/filesystem.hpp"
#include <kstd/memory>
+#include <kstd/string>
#include <string_view>
namespace filesystem
{
mount::mount(kstd::shared_ptr<dentry> const & mount_dentry, kstd::shared_ptr<dentry> const & root_dentry,
- kstd::shared_ptr<filesystem> const & fs)
- : m_mount_dentry(mount_dentry)
+ kstd::shared_ptr<filesystem> const & fs, std::string_view mount_path)
+ : m_mount_path(mount_path)
+ , m_mount_dentry(mount_dentry)
, m_root_dentry(root_dentry)
, m_filesystem(fs)
{
@@ -37,4 +39,9 @@ namespace filesystem
{
return m_root_dentry;
}
+
+ auto mount::get_mount_path() const -> std::string_view
+ {
+ return m_mount_path.view();
+ }
} // namespace filesystem \ No newline at end of file
diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp
index 681c2b9..b9e57d4 100644
--- a/kernel/src/filesystem/mount_table.cpp
+++ b/kernel/src/filesystem/mount_table.cpp
@@ -1,11 +1,11 @@
#include "kernel/filesystem/mount_table.hpp"
-#include "kernel/filesystem/dentry.hpp"
#include "kernel/filesystem/mount.hpp"
#include <kstd/memory>
-#include <algorithm>
+#include <cstddef>
+#include <string_view>
namespace filesystem
{
@@ -14,16 +14,25 @@ namespace filesystem
m_mounts.push_back(mount);
}
- auto mount_table::get_root_mount() const -> kstd::shared_ptr<mount>
+ auto mount_table::find_longest_prefix_mount(std::string_view path) const -> kstd::shared_ptr<mount>
{
- auto it = std::ranges::find_if(m_mounts, [](auto const & mount) { return mount->get_mount_dentry() == nullptr; });
- return it != m_mounts.end() ? *it : nullptr;
- }
+ kstd::shared_ptr<mount> mount_with_longest_prefix = nullptr;
+ std::size_t best_len = 0;
- auto mount_table::find_mount_by_dentry(kstd::shared_ptr<dentry> const & dentry) -> kstd::shared_ptr<mount>
- {
- auto it = std::ranges::find_if(m_mounts, [&](auto const & mnt) { return mnt->get_mount_dentry() == dentry; });
+ for (auto const & mount : m_mounts)
+ {
+ auto mp = mount->get_mount_path();
+
+ // /a/b/c should match /a/b but not /a/bb or /a/b/c/d, / should match everything
+ bool is_prefix = path.starts_with(mp) && (mp == "/" || path.size() == mp.size() || path[mp.size()] == '/');
+
+ if (is_prefix && mp.size() >= best_len)
+ {
+ mount_with_longest_prefix = mount;
+ best_len = mp.size();
+ }
+ }
- return it != m_mounts.end() ? *it : nullptr;
+ return mount_with_longest_prefix;
}
} // namespace filesystem \ No newline at end of file
diff --git a/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp b/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp
index e819fc7..22502aa 100644
--- a/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp
+++ b/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp
@@ -10,7 +10,7 @@
namespace filesystem::rootfs
{
- auto rootfs_filesystem::mount(kstd::shared_ptr<devices::device> const & /*device*/) -> int
+ auto rootfs_filesystem::mount(kstd::shared_ptr<devices::device> const &) -> int
{
auto rfs_inode = kstd::make_shared<rootfs_inode>();
rfs_inode->add_child("dev");
diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp
index 40c97f8..da7fa05 100644
--- a/kernel/src/filesystem/vfs.cpp
+++ b/kernel/src/filesystem/vfs.cpp
@@ -37,11 +37,11 @@ namespace filesystem
auto vfs::init_internal() -> void
{
- auto virtual_fs = kstd::make_shared<rootfs::rootfs_filesystem>();
- virtual_fs->mount(nullptr);
+ auto root_fs = kstd::make_shared<rootfs::rootfs_filesystem>();
+ root_fs->mount(nullptr);
- auto virtual_root_dentry = kstd::make_shared<dentry>(nullptr, virtual_fs->root_inode(), "/");
- m_mount_table.add_mount(kstd::make_shared<mount>(nullptr, virtual_root_dentry, virtual_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, ""));
auto storage_mgmt = devices::storage::storage_management::get();
if (auto boot_device = storage_mgmt.determine_boot_device())
@@ -49,24 +49,12 @@ namespace filesystem
// 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);
-
- if (do_mount("/", boot_root_fs) != 0)
- {
- kapi::system::panic("[FILESYSTEM] failed to mount root filesystem.");
- }
-
- auto device_fs = kstd::make_shared<devfs::devfs_filesystem>();
- device_fs->mount(nullptr);
-
- if (do_mount("/dev", device_fs) != 0)
- {
- kapi::system::panic("[FILESYSTEM] failed to mount devfs at /dev.");
- }
- }
- else
- {
- // TODO BA-FS26 ?? what when no boot_device == no modules loaded??
+ 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 &
@@ -107,77 +95,69 @@ namespace filesystem
return -1; // TODO BA-FS26 panic or errorcode?
}
- if (auto mount_dentry = resolve_path(path))
+ if (auto mount_point_dentry = resolve_path(path))
{
- // 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_dentry, filesystem->root_inode());
- auto new_mount = kstd::make_shared<mount>(mount_dentry, new_fs_root, filesystem);
- m_mount_table.add_mount(new_mount);
- mount_dentry->set_flag(dentry::dentry_flags::dcache_mounted);
-
+ do_mount_internal(path, mount_point_dentry, filesystem);
return 0;
}
return -1;
}
+ 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 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);
+ }
+
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() == '/')
+ if (path.empty() || path.front() != '/')
+ return nullptr;
+
+ // 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)
{
- auto root_mount = m_mount_table.get_root_mount();
- if (!root_mount)
- {
- kapi::system::panic("[FILESYSTEM] no root mount found.");
- }
+ kapi::system::panic("[FILESYSTEM] no root mount found.");
+ }
- auto current_dentry = root_mount->root_dentry();
- auto current_fs = root_mount->get_filesystem();
+ auto current_dentry = best_mount->root_dentry();
+ auto current_fs = best_mount->get_filesystem();
- auto path_parts =
- std::views::split(path, '/') | std::views::filter([](auto const & part) { return !part.empty(); });
- for (auto const & part : path_parts)
+ 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)
+ {
+ std::string_view part_view{part};
+
+ auto next_dentry = current_dentry->find_child(part_view);
+ if (!next_dentry)
{
- std::string_view part_view{part};
- auto next_dentry = current_dentry->find_child(part_view);
-
- if (!next_dentry)
- {
- if (auto found_inode = current_fs->lookup(current_dentry->get_inode(), part_view))
- {
- next_dentry = kstd::make_shared<dentry>(current_dentry, found_inode, part_view);
- current_dentry->add_child(next_dentry);
- }
- else
- {
- return nullptr;
- }
- }
-
- // TODO BA-FS26 use while to allow stacked mounts?
- if (next_dentry->has_flag(dentry::dentry_flags::dcache_mounted))
- {
- auto found_mount = m_mount_table.find_mount_by_dentry(next_dentry);
- if (!found_mount)
- kapi::system::panic("[FILESYSTEM] dcache_mounted set but no covering mount found.");
- current_fs = found_mount->get_filesystem();
- current_dentry = found_mount->root_dentry();
- }
- else
- {
- current_dentry = next_dentry;
- }
+ 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 current_dentry;
+ current_dentry = next_dentry;
}
- return nullptr;
+ return current_dentry;
}
} // namespace filesystem \ No newline at end of file