aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/kernel/vfs.cpp90
-rw-r--r--kernel/kernel/vfs.hpp4
-rw-r--r--kernel/kernel/vfs.tests.cpp22
-rw-r--r--kernel/kernel/vfs/dentry.cpp5
-rw-r--r--kernel/kernel/vfs/dentry.hpp4
-rw-r--r--kernel/kernel/vfs/mount.cpp11
-rw-r--r--kernel/kernel/vfs/mount.hpp8
-rw-r--r--kernel/kernel/vfs/mount_table.cpp10
-rw-r--r--kernel/kernel/vfs/mount_table.hpp9
9 files changed, 92 insertions, 71 deletions
diff --git a/kernel/kernel/vfs.cpp b/kernel/kernel/vfs.cpp
index 5f729406..742af328 100644
--- a/kernel/kernel/vfs.cpp
+++ b/kernel/kernel/vfs.cpp
@@ -84,36 +84,56 @@ namespace kernel::vfs
}
auto [device_fs_root, device_fs_data] = *device_fs_mount_result;
- graft_persistent_device_fs(*devfs, device_fs_root, device_fs_data);
+ auto root_devfs_mount = resolve_path_internal("/").transform([&](auto res) {
+ auto [root_dentry, root_mount] = res;
+ auto dev_dentry = kstd::make_shared<dentry>(root_dentry, device_fs_root, "dev");
+ root_dentry->add_child(dev_dentry);
+ auto mount = mount::attach(dev_dentry, *devfs, device_fs_root, device_fs_data, root_mount, nullptr);
+ m_mount_table.add_mount(mount);
+ return mount;
+ });
+
+ if (!root_devfs_mount)
+ {
+ kapi::system::panic("[OS:FS] failed to mount initial devfs!", root_devfs_mount.error());
+ }
- // mount boot fs at / (shadows rootfs), re-graft devfs
- auto [boot_device_dentry, boot_device_mount_context] =
- resolve_path_internal("/dev/ram0").value_or(std::pair{nullptr, nullptr});
- if (boot_device_dentry && boot_device_mount_context)
+ auto resolved = resolve_path_internal("/dev/ram0");
+ if (!resolved)
{
- auto driver = driver_registry::get().match(boot_device_dentry->inode());
- if (!driver)
- {
- kstd::println(kstd::print_sink::stderr, "[OS:FS] Missing driver for root disk!");
- return;
- }
+ kapi::system::panic("[OS:FS] Failed to resolve boot disk!", resolved.error());
+ }
- auto root_dentry = resolve_path("/");
- if (!root_dentry)
- {
- kapi::system::panic("[OS:FS] No root directory found!");
- }
+ auto [boot_device_dentry, boot_device_mount_context] = *resolved;
- auto mount =
- mount::create(*root_dentry, *driver, root_mount, boot_device_mount_context, boot_device_dentry->inode());
+ auto driver = driver_registry::get().match(boot_device_dentry->inode());
+ if (!driver)
+ {
+ kstd::println(kstd::print_sink::stderr, "[OS:FS] Missing driver for root disk!");
+ return;
+ }
- if (!mount)
+ auto mount = mount::create(nullptr, *driver, nullptr, boot_device_mount_context, boot_device_dentry->inode());
+ if (!mount)
+ {
+ kapi::system::panic("[OS:FS] failed to mount boot FS", mount.error());
+ }
+ m_mount_table.add_mount(*mount);
+
+ auto real_dev_dentry = resolve_path("/dev");
+ if (!real_dev_dentry)
+ {
+ if (auto result = mkdir("/dev"); !result)
{
- kapi::system::panic("[OS:FS] failed to mount boot FS", mount.error());
+ kapi::system::panic("[OS:FS] Failed to create devfs mount point!", result.error());
}
- m_mount_table.add_mount(*mount);
+ real_dev_dentry = resolve_path("/dev");
+ }
- graft_persistent_device_fs(*devfs, device_fs_root, device_fs_data);
+ m_mount_table.move_mount(*root_devfs_mount, *real_dev_dentry, *mount);
+ if (auto result = m_mount_table.remove_mount(root_mount); !result)
+ {
+ kapi::system::panic("[OS:FS] Failed to unmount early rootfs!", result.error());
}
}
@@ -303,25 +323,6 @@ namespace kernel::vfs
return kstd::failure(errc::no_such_file_or_directory);
}
- auto vfs::graft_persistent_device_fs(kstd::shared_ptr<filesystem> const & device_fs,
- kstd::shared_ptr<inode> const & root_inode,
- kstd::shared_ptr<driver_state> driver_data) -> void
- {
- auto [root_mount_point_dentry, root_mount] = resolve_path_internal("/").value_or(std::pair{nullptr, nullptr});
- if (root_mount_point_dentry && root_mount)
- {
- auto dev_dentry = root_mount_point_dentry->find_child("dev");
- if (!dev_dentry)
- {
- dev_dentry = kstd::make_shared<dentry>(root_mount_point_dentry, root_inode, "dev");
- root_mount_point_dentry->add_child(dev_dentry);
- }
-
- auto new_mount = mount::attach(dev_dentry, device_fs, root_inode, driver_data, root_mount, nullptr);
- m_mount_table.add_mount(new_mount);
- }
- }
-
auto vfs::resolve_path_internal(std::string_view path) const -> kstd::result<std::pair<dentry_ptr, mount_ptr>>
{
if (!path::is_valid_absolute_path(path))
@@ -360,8 +361,6 @@ namespace kernel::vfs
if (part == "..")
{
- auto parent_dentry = current_dentry->parent();
-
if (current_dentry == current_mount->root_dentry())
{
if (current_mount->mount_path() == "/")
@@ -371,12 +370,13 @@ namespace kernel::vfs
if (auto parent_mount = current_mount->parent_mount())
{
+ current_dentry = current_mount->mount_dentry()->parent();
current_mount = parent_mount;
- current_dentry = parent_dentry;
+ continue;
}
}
- current_dentry = parent_dentry;
+ current_dentry = current_dentry->parent();
continue;
}
diff --git a/kernel/kernel/vfs.hpp b/kernel/kernel/vfs.hpp
index 8688536a..4528ab2e 100644
--- a/kernel/kernel/vfs.hpp
+++ b/kernel/kernel/vfs.hpp
@@ -124,10 +124,6 @@ namespace kernel::vfs
[[nodiscard]] auto find_mount(std::string_view path) const -> kstd::result<mount_ptr>;
- auto graft_persistent_device_fs(kstd::shared_ptr<filesystem> const & device_fs,
- kstd::shared_ptr<inode> const & root_inode,
- kstd::shared_ptr<driver_state> driver_data) -> void;
-
auto create_inode(std::string_view path, kapi::filesystem::file_type type,
std::optional<kapi::filesystem::device_number> raw_device = std::nullopt) -> kstd::result<void>;
diff --git a/kernel/kernel/vfs.tests.cpp b/kernel/kernel/vfs.tests.cpp
index 0c807082..f766a992 100644
--- a/kernel/kernel/vfs.tests.cpp
+++ b/kernel/kernel/vfs.tests.cpp
@@ -238,28 +238,6 @@ SCENARIO_METHOD(kernel::tests::vfs::storage_boot_module_vfs_fixture, "VFS with f
REQUIRE(dev_ram_32 != nullptr);
}
- THEN("boot root can be unmounted and remounted again but /dev is not re-grafted")
- {
- auto info_1 = vfs.open("/information/info_1.txt");
- REQUIRE(info_1 != nullptr);
-
- REQUIRE(vfs.close(info_1.value()->absolute_path()));
-
- REQUIRE(vfs.unmount("/dev"));
- REQUIRE(vfs.unmount("/"));
-
- info_1 = vfs.open("/information/info_1.txt");
- REQUIRE(info_1.error() == kstd::errc::no_such_file_or_directory);
-
- REQUIRE(vfs.mount("/dev/ram0", "/"));
-
- info_1 = vfs.open("/information/info_1.txt");
- REQUIRE(info_1 != nullptr);
-
- auto dev_ram_0 = vfs.open("/dev/ram0");
- REQUIRE(dev_ram_0.error() == kstd::errc::no_such_file_or_directory);
- }
-
THEN("mount with null file system fails")
{
REQUIRE(vfs.mount("/closed.txt", "/information").error() == kstd::errc::not_supported);
diff --git a/kernel/kernel/vfs/dentry.cpp b/kernel/kernel/vfs/dentry.cpp
index a7bfc3cb..c22dc0e2 100644
--- a/kernel/kernel/vfs/dentry.cpp
+++ b/kernel/kernel/vfs/dentry.cpp
@@ -93,4 +93,9 @@ namespace kernel::vfs
{
return (m_flags & static_cast<uint32_t>(flag)) != 0;
}
+
+ auto dentry::set_parent(dentry_ptr const & parent) -> void
+ {
+ m_parent = parent;
+ }
} // namespace kernel::vfs \ No newline at end of file
diff --git a/kernel/kernel/vfs/dentry.hpp b/kernel/kernel/vfs/dentry.hpp
index b15a6f6c..13dea2a3 100644
--- a/kernel/kernel/vfs/dentry.hpp
+++ b/kernel/kernel/vfs/dentry.hpp
@@ -87,6 +87,10 @@ namespace kernel::vfs
[[nodiscard]] auto has_flag(dentry_flags flag) const -> bool;
private:
+ friend struct mount_table;
+
+ auto set_parent(dentry_ptr const & parent) -> void;
+
kstd::string m_name;
kstd::weak_ptr<dentry> m_parent;
kstd::vector<dentry_ptr> m_children;
diff --git a/kernel/kernel/vfs/mount.cpp b/kernel/kernel/vfs/mount.cpp
index b5fdfa39..76f72e22 100644
--- a/kernel/kernel/vfs/mount.cpp
+++ b/kernel/kernel/vfs/mount.cpp
@@ -138,4 +138,15 @@ namespace kernel::vfs
{
return m_ref_count;
}
+
+ auto mount::set_mount_dentry(dentry_ptr const & mount_dentry) -> void
+ {
+ m_mount_dentry = mount_dentry;
+ }
+
+ auto mount::set_parent_mount(mount_ptr const & parent_mount) -> void
+ {
+ m_parent_mount = parent_mount;
+ }
+
} // namespace kernel::vfs \ No newline at end of file
diff --git a/kernel/kernel/vfs/mount.hpp b/kernel/kernel/vfs/mount.hpp
index beecb759..b0993dd3 100644
--- a/kernel/kernel/vfs/mount.hpp
+++ b/kernel/kernel/vfs/mount.hpp
@@ -86,6 +86,8 @@ namespace kernel::vfs
[[nodiscard]] auto ref_count() const -> size_t;
private:
+ friend struct mount_table;
+
//! Create a new mount with the given parameters.
//!
//! @param mount_dentry The directory entry where the filesystem is mounted.
@@ -98,6 +100,12 @@ namespace kernel::vfs
mount_ptr const & parent_mount, mount_ptr const & source_mount,
kstd::shared_ptr<vfs::driver_state> driver_state);
+ //! Set the directory entry where the filesystem is mounted.
+ auto set_mount_dentry(dentry_ptr const & mount_dentry) -> void;
+
+ //! Set the parent mount this this mount was attached beneath.
+ auto set_parent_mount(mount_ptr const & parent_mount) -> void;
+
dentry_ptr m_mount_dentry{};
dentry_ptr m_root_dentry{};
filesystem_ptr m_filesystem{};
diff --git a/kernel/kernel/vfs/mount_table.cpp b/kernel/kernel/vfs/mount_table.cpp
index 01127697..43dff516 100644
--- a/kernel/kernel/vfs/mount_table.cpp
+++ b/kernel/kernel/vfs/mount_table.cpp
@@ -83,6 +83,16 @@ namespace kernel::vfs
return (mount_it != m_mounts.end()) ? *mount_it : nullptr;
}
+ auto mount_table::move_mount(kstd::shared_ptr<mount> const & mount, kstd::shared_ptr<dentry> const & mount_point,
+ kstd::shared_ptr<struct mount> const & parent) -> void
+ {
+ mount->mount_dentry()->unset_flag(dentry::dentry_flags::is_mount_point);
+ mount->root_dentry()->set_parent(mount_point->parent());
+ mount->set_mount_dentry(mount_point);
+ mount->set_parent_mount(parent);
+ mount_point->set_flag(dentry::dentry_flags::is_mount_point);
+ }
+
auto mount_table::find_mount_iterator(std::string_view path) const
-> kstd::vector<kstd::shared_ptr<mount>>::const_iterator
{
diff --git a/kernel/kernel/vfs/mount_table.hpp b/kernel/kernel/vfs/mount_table.hpp
index 140aebac..731b0ad8 100644
--- a/kernel/kernel/vfs/mount_table.hpp
+++ b/kernel/kernel/vfs/mount_table.hpp
@@ -1,6 +1,7 @@
#ifndef TEACHOS_KERNEL_VFS_MOUNT_TABLE_HPP
#define TEACHOS_KERNEL_VFS_MOUNT_TABLE_HPP
+#include <kernel/vfs/dentry.hpp>
#include <kernel/vfs/mount.hpp>
#include <kstd/memory.hpp>
@@ -37,6 +38,14 @@ namespace kernel::vfs
//! @return A pointer to the mount with the exact matching path on success, nullpointer otherwise.
[[nodiscard]] auto find_mount(std::string_view path) const -> kstd::shared_ptr<mount>;
+ //! Move the mount attachment of an existing mount
+ //!
+ //! @param mount The mount to modify.
+ //! @param mount_point The new location the mount is mounted on.
+ //! @param parent The new parent mount of the mount.
+ auto move_mount(kstd::shared_ptr<mount> const & mount, kstd::shared_ptr<dentry> const & mount_point,
+ kstd::shared_ptr<struct mount> const & parent) -> void;
+
private:
[[nodiscard]] auto has_child_mounts(kstd::shared_ptr<mount> const & parent_mount) const -> bool;
[[nodiscard]] auto find_mount_iterator(std::string_view path) const