diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-07-25 13:52:43 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-07-25 13:52:43 +0200 |
| commit | 948453d3d073de207274535376d7274e82f04bc6 (patch) | |
| tree | 6cb36b1f4e6902693a2a14b22b178e351a9a5cfb | |
| parent | db92fcd2a865889dbf5cc524f2c27e5855167e9c (diff) | |
| download | kernel-948453d3d073de207274535376d7274e82f04bc6.tar.xz kernel-948453d3d073de207274535376d7274e82f04bc6.zip | |
kernel: subscribe devfs to the number registry
| -rw-r--r-- | kernel/kapi/filesystem.tests.cpp | 9 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/devfs/filesystem.cpp | 34 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/devfs/filesystem.hpp | 12 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/devfs/filesystem.tests.cpp | 35 |
4 files changed, 57 insertions, 33 deletions
diff --git a/kernel/kapi/filesystem.tests.cpp b/kernel/kapi/filesystem.tests.cpp index 1cd2c610..80fc7d3f 100644 --- a/kernel/kapi/filesystem.tests.cpp +++ b/kernel/kapi/filesystem.tests.cpp @@ -276,10 +276,17 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap REQUIRE(kapi::filesystem::umount("/information")); } } +} + +// NOTE: This must be it's own scenario, because it relies on concrete minor numbers, which in turn depend on global +// singleton state that only resets on a new scenario. +SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, + "Kapi filesystem resolves a persistent device node to the matching devfs entry", "[kapi][filesystem]") +{ + auto image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_devnode_fs.img"; GIVEN("A real image file containing a device node") { - auto image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_devnode_fs.img"; REQUIRE(std::filesystem::exists(image_path)); REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module_devnode"}, {image_path})); diff --git a/kernel/kernel/filesystem/devfs/filesystem.cpp b/kernel/kernel/filesystem/devfs/filesystem.cpp index b97884e6..c8447a2d 100644 --- a/kernel/kernel/filesystem/devfs/filesystem.cpp +++ b/kernel/kernel/filesystem/devfs/filesystem.cpp @@ -11,12 +11,12 @@ #include <kapi/filesystem.hpp> -#include <kstd/flat_map.hpp> #include <kstd/memory.hpp> #include <kstd/result.hpp> -#include <kstd/string.hpp> #include <kstd/system_error.hpp> +#include <kstd/vector.hpp> +#include <algorithm> #include <optional> #include <string_view> @@ -46,7 +46,15 @@ namespace kernel::filesystem::devfs auto filesystem::mount(kstd::shared_ptr<kernel::filesystem::inode> const &) -> kstd::result<void> { m_root_inode = kstd::make_shared<inode>(); - build_device_inode_table(); + + std::ranges::for_each(device_number_registry::get().all(), [&](auto const & numbered) { + if (auto device = numbered.device.lock()) + { + m_inodes.emplace_back(numbered.name, kstd::make_shared<device_inode>(device)); + } + }); + + device_number_registry::get().subscribe(shared_from_this()); return kstd::success(); } @@ -69,7 +77,7 @@ namespace kernel::filesystem::devfs return kstd::failure(vfs_errc::invalid_inode); } - auto found = m_inodes.find(kstd::string{name}); + auto found = std::ranges::find_if(m_inodes, [&](auto const & entry) { return entry.first == name; }); if (found != m_inodes.end()) { return found->second; @@ -85,17 +93,17 @@ namespace kernel::filesystem::devfs return kstd::failure(vfs_errc::read_only_file_system); } - auto filesystem::build_device_inode_table() -> void + auto filesystem::on_device_numbered(device_number_registry::entry const & numbered) -> void { - // TODO: implement clear on flat_map - m_inodes = kstd::flat_map<kstd::string, kstd::shared_ptr<device_inode>>{}; - - for (auto const & entry : device_number_registry::get().all()) + if (auto device = numbered.device.lock()) { - if (auto device = entry.device.lock()) - { - m_inodes.emplace(entry.name, kstd::make_shared<device_inode>(device)); - } + m_inodes.emplace_back(numbered.name, kstd::make_shared<device_inode>(device)); } } + + auto filesystem::on_device_unnumbered(device_number_registry::entry const & numbered) -> void + { + erase_if(m_inodes, [&](auto const & entry) { return entry.first == numbered.name; }); + } + } // namespace kernel::filesystem::devfs
\ No newline at end of file diff --git a/kernel/kernel/filesystem/devfs/filesystem.hpp b/kernel/kernel/filesystem/devfs/filesystem.hpp index abc4975a..8d2199e3 100644 --- a/kernel/kernel/filesystem/devfs/filesystem.hpp +++ b/kernel/kernel/filesystem/devfs/filesystem.hpp @@ -2,6 +2,7 @@ #define TEACH_OS_KERNEL_FILESYSTEM_DEVFS_FILESYSTEM_HPP #include <kernel/filesystem/device_inode.hpp> +#include <kernel/filesystem/device_number_registry.hpp> #include <kernel/filesystem/filesystem.hpp> #include <kernel/filesystem/inode.hpp> #include <kernel/filesystem/vfs_types.hpp> @@ -17,6 +18,7 @@ #include <optional> #include <string_view> +#include <utility> namespace kernel::filesystem::devfs { @@ -27,7 +29,9 @@ namespace kernel::filesystem::devfs //! applications to interact with devices using standard file operations. The devfs filesystem dynamically creates //! inodes for devices registered in the system, enabling seamless access to device functionality through the //! filesystem interface. - struct filesystem : kernel::filesystem::filesystem + struct filesystem : kernel::filesystem::filesystem, + kstd::enable_shared_from_this<filesystem>, + device_number_registry_observer { //! @copydoc kernel::filesystem::filesystem::mount auto mount(kstd::shared_ptr<kernel::filesystem::inode> const & backing_inode) -> kstd::result<void> override; @@ -44,9 +48,11 @@ namespace kernel::filesystem::devfs -> kstd::result<kstd::shared_ptr<kernel::filesystem::inode>> override; private: - auto build_device_inode_table() -> void; + auto on_device_numbered(device_number_registry::entry const & numbered) -> void override; + auto on_device_unnumbered(device_number_registry::entry const & numbered) -> void override; - kstd::flat_map<kstd::string, kstd::shared_ptr<device_inode>> m_inodes{}; + // TODO: change to flat_map again once flat_map supports erase. + kstd::vector<std::pair<kstd::string, kstd::shared_ptr<device_inode>>> m_inodes{}; }; } // namespace kernel::filesystem::devfs diff --git a/kernel/kernel/filesystem/devfs/filesystem.tests.cpp b/kernel/kernel/filesystem/devfs/filesystem.tests.cpp index 93805440..29a33231 100644 --- a/kernel/kernel/filesystem/devfs/filesystem.tests.cpp +++ b/kernel/kernel/filesystem/devfs/filesystem.tests.cpp @@ -4,6 +4,8 @@ #include <kernel/filesystem/vfs_types.hpp> #include <kernel/test_support/filesystem/storage_boot_module_fixture.hpp> +#include <kstd/memory.hpp> + #include <catch2/catch_test_macros.hpp> SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, @@ -13,50 +15,51 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, { setup_modules(1); - auto fs = kernel::filesystem::devfs::filesystem{}; - auto result = fs.mount(nullptr); + auto fs = kstd::make_shared<kernel::filesystem::devfs::filesystem>(); + auto result = fs->mount(nullptr); THEN("mount succeeds") { REQUIRE(result); - REQUIRE(fs.root_inode()); + REQUIRE(fs->root_inode()); } THEN("lookup on root finds ram0 device inode") { - auto inode = fs.lookup(fs.root_inode(), "ram0"); + auto inode = fs->lookup(fs->root_inode(), "ram0"); REQUIRE(inode); REQUIRE(inode.value()->is_device()); } THEN("lookup of an unknown device returns error") { - auto inode = fs.lookup(fs.root_inode(), "ram99"); + auto inode = fs->lookup(fs->root_inode(), "ram99"); REQUIRE(!inode); } THEN("lookup with wrong parent returns error") { - auto other_fs = kernel::filesystem::devfs::filesystem{}; - CHECK(other_fs.mount(nullptr)); + auto other_fs = kstd::make_shared<kernel::filesystem::devfs::filesystem>(); + CHECK(other_fs->mount(nullptr)); - auto inode = fs.lookup(other_fs.root_inode(), "ram0"); + auto inode = fs->lookup(other_fs->root_inode(), "ram0"); REQUIRE(!inode); } THEN("lookup with a non-directory parent returns error") { - auto non_directory_inode = fs.lookup(fs.root_inode(), "ram0"); + auto non_directory_inode = fs->lookup(fs->root_inode(), "ram0"); REQUIRE(non_directory_inode); REQUIRE_FALSE(non_directory_inode.value()->is_directory()); - auto result = fs.lookup(*non_directory_inode, "anything"); + auto result = fs->lookup(*non_directory_inode, "anything"); REQUIRE(!result); } THEN("create_inode always returns an error") { - auto result = fs.create_inode(fs.root_inode(), "new_device", kernel::filesystem::vfs_types::inode_type::regular); + auto result = + fs->create_inode(fs->root_inode(), "new_device", kernel::filesystem::vfs_types::inode_type::regular); REQUIRE(!result); } } @@ -65,15 +68,15 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, { setup_modules(3, 2048); - auto fs = kernel::filesystem::devfs::filesystem{}; - auto result = fs.mount(nullptr); + auto fs = kstd::make_shared<kernel::filesystem::devfs::filesystem>(); + auto result = fs->mount(nullptr); REQUIRE(result); THEN("lookup finds all generated RAM devices") { - REQUIRE(fs.lookup(fs.root_inode(), "ram0")); - REQUIRE(fs.lookup(fs.root_inode(), "ram1")); - REQUIRE(fs.lookup(fs.root_inode(), "ram2")); + REQUIRE(fs->lookup(fs->root_inode(), "ram0")); + REQUIRE(fs->lookup(fs->root_inode(), "ram1")); + REQUIRE(fs->lookup(fs->root_inode(), "ram2")); } } } |
