From 84aac7e26dae2b4364d2f1145d4b2b40f1e37585 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Sun, 23 Aug 2026 18:10:10 +0200 Subject: kernel/fs: rework filesystem probing --- arch/x86_64/scripts/kernel.ld | 6 +- kernel/CMakeLists.txt | 3 +- kernel/kernel/filesystem/devfs/filesystem.cpp | 26 ++--- kernel/kernel/filesystem/devfs/filesystem.hpp | 6 +- kernel/kernel/filesystem/driver_registry.cpp | 125 +++++++++++++++++++++ kernel/kernel/filesystem/driver_registry.hpp | 73 ++++++++++++ kernel/kernel/filesystem/ext2/filesystem.cpp | 84 +++++++------- kernel/kernel/filesystem/ext2/filesystem.hpp | 2 + kernel/kernel/filesystem/filesystem.cpp | 32 ------ kernel/kernel/filesystem/filesystem.hpp | 9 +- kernel/kernel/filesystem/rootfs/filesystem.cpp | 29 ++--- kernel/kernel/filesystem/rootfs/filesystem.hpp | 3 + kernel/kernel/filesystem/type.hpp | 48 -------- kernel/kernel/filesystem/type_registry.cpp | 94 ---------------- kernel/kernel/filesystem/type_registry.hpp | 59 ---------- kernel/kernel/filesystem/type_registry.tests.cpp | 81 ------------- kernel/kernel/filesystem/vfs.cpp | 63 ++++++----- kernel/kernel/main.cpp | 4 +- .../test_support/filesystem/driver_registry.hpp | 10 ++ .../kernel/test_support/filesystem/filesystem.cpp | 6 + .../kernel/test_support/filesystem/filesystem.hpp | 3 + .../filesystem/storage_boot_module_fixture.cpp | 2 - .../test_support/filesystem/type_registry.hpp | 10 -- .../kernel/test_support/state_reset_listener.cpp | 9 +- 24 files changed, 348 insertions(+), 439 deletions(-) create mode 100644 kernel/kernel/filesystem/driver_registry.cpp create mode 100644 kernel/kernel/filesystem/driver_registry.hpp delete mode 100644 kernel/kernel/filesystem/filesystem.cpp delete mode 100644 kernel/kernel/filesystem/type.hpp delete mode 100644 kernel/kernel/filesystem/type_registry.cpp delete mode 100644 kernel/kernel/filesystem/type_registry.hpp delete mode 100644 kernel/kernel/filesystem/type_registry.tests.cpp create mode 100644 kernel/kernel/test_support/filesystem/driver_registry.hpp delete mode 100644 kernel/kernel/test_support/filesystem/type_registry.hpp diff --git a/arch/x86_64/scripts/kernel.ld b/arch/x86_64/scripts/kernel.ld index f621c3f1..e6ae3425 100644 --- a/arch/x86_64/scripts/kernel.ld +++ b/arch/x86_64/scripts/kernel.ld @@ -76,9 +76,9 @@ SECTIONS . = ALIGN(8); /* Filesystem driver factories */ - PROVIDE(__start_fs_types = .); - KEEP(*(fs_types)); - PROVIDE(__stop_fs_types = .); + PROVIDE(__start_filesystem_drivers = .); + KEEP(*(filesystem_drivers)); + PROVIDE(__stop_filesystem_drivers = .); /* Kernel driver factories */ PROVIDE(__start_kernel_drivers = .); diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index c7cf9498..2cca2dda 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -60,14 +60,13 @@ target_sources("kernel_lib" PRIVATE "kernel/filesystem/dentry.cpp" "kernel/filesystem/device_inode.cpp" "kernel/filesystem/device_number_registry.cpp" + "kernel/filesystem/driver_registry.cpp" "kernel/filesystem/error.cpp" - "kernel/filesystem/filesystem.cpp" "kernel/filesystem/inode.cpp" "kernel/filesystem/mount_table.cpp" "kernel/filesystem/mount.cpp" "kernel/filesystem/open_file_descriptor.cpp" "kernel/filesystem/open_file_table.cpp" - "kernel/filesystem/type_registry.cpp" "kernel/filesystem/vfs.cpp" # DevFS Filesystem diff --git a/kernel/kernel/filesystem/devfs/filesystem.cpp b/kernel/kernel/filesystem/devfs/filesystem.cpp index 0e3f3164..a7c8e50c 100644 --- a/kernel/kernel/filesystem/devfs/filesystem.cpp +++ b/kernel/kernel/filesystem/devfs/filesystem.cpp @@ -3,10 +3,10 @@ #include #include #include +#include #include #include #include -#include #include @@ -21,23 +21,13 @@ namespace kernel::filesystem::devfs { - struct type final : kernel::filesystem::type + struct descriptor final : kernel::filesystem::driver_descriptor { [[nodiscard]] auto name() const noexcept -> std::string_view override { return "devfs"; } - [[nodiscard]] auto probe(filesystem::inode_ptr const & backing_inode) const noexcept - -> kstd::result override - { - if (backing_inode) - { - return kstd::failure(vfs_errc::invalid_argument); - } - return 0; - } - [[nodiscard]] auto make_instance() const -> filesystem::filesystem_ptr override { return kstd::make_shared(); @@ -45,10 +35,20 @@ namespace kernel::filesystem::devfs }; [[gnu::used]] - constexpr auto registration = type_registration{}; + constexpr auto registration = driver_module{}; static_assert(sizeof(kernel::filesystem::filesystem) == sizeof(devfs::filesystem)); + auto filesystem::probe(inode_ptr const & inode) const -> kstd::result + { + if (inode) + { + return kstd::failure(vfs_errc::invalid_argument); + } + + return 0; + } + auto filesystem::mount(inode_ptr const &) -> kstd::result { auto root = kstd::make_shared(); diff --git a/kernel/kernel/filesystem/devfs/filesystem.hpp b/kernel/kernel/filesystem/devfs/filesystem.hpp index 56744477..aa33c58b 100644 --- a/kernel/kernel/filesystem/devfs/filesystem.hpp +++ b/kernel/kernel/filesystem/devfs/filesystem.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -13,6 +14,7 @@ #include #include +#include #include #include @@ -25,8 +27,10 @@ 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 final : kernel::filesystem::filesystem { + [[nodiscard]] auto probe(inode_ptr const & inode) const -> kstd::result override; + auto mount(inode_ptr const & backing_inode) -> kstd::result override; [[nodiscard]] auto lookup(inode_ptr const & parent, std::string_view name, driver_data_ptr driver_data) const diff --git a/kernel/kernel/filesystem/driver_registry.cpp b/kernel/kernel/filesystem/driver_registry.cpp new file mode 100644 index 00000000..22bc306d --- /dev/null +++ b/kernel/kernel/filesystem/driver_registry.cpp @@ -0,0 +1,125 @@ +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace kernel::filesystem +{ + + extern "C" + { + // We need to suppress clang-tidy linting warnings here, since these symbols are generated by the linker and we + // cannot choose their names, unless we wanted to extend the linker script needlessly. + // NOLINTBEGIN(readability-identifier-naming) + extern kstd::observer_ptr const __start_filesystem_drivers; + extern kstd::observer_ptr const __stop_filesystem_drivers; + // NOLINTEND(readability-identifier-naming) + } + + namespace + { + auto constinit instance = std::optional{}; + } + + auto driver_registry::init() -> void + { + if (instance) + { + kapi::system::panic("[OS:FS] The filesystem driver registry was already initialized!"); + } + + instance.emplace(); + + auto instances = + std::span{&__start_filesystem_drivers, &__stop_filesystem_drivers} | + std::views::filter([](auto descriptor) { return descriptor != nullptr; }) | + std::views::transform([](auto descriptor) { return std::pair{descriptor, descriptor->make_instance()}; }) | + std::views::filter([](auto entry) { return entry.second != nullptr; }); + + std::ranges::for_each(instances, [](auto entry) { + auto [descriptor, driver] = entry; + kstd::println("[OS:FS] Registering filesystem driver '{}'", descriptor->name()); + instance->add(descriptor->name(), driver); + }); + } + + auto driver_registry::get() -> driver_registry & + { + if (!instance) + { + kapi::system::panic("[OS:FS] The filesystem driver registry has not been initialized!"); + } + + return *instance; + } + + auto driver_registry::find(std::string_view name) const -> std::optional> + { + if (auto it = m_drivers.find(name); it != m_drivers.end()) + { + return it->second; + } + return std::nullopt; + } + + auto driver_registry::add(std::string_view name, kstd::shared_ptr descriptor) -> bool + { + auto result = m_drivers.emplace(name, descriptor); + return result.second; + } + + auto driver_registry::match(kstd::shared_ptr const & inode) const -> kstd::result> + { + struct candidate + { + std::uint32_t priority; + kstd::shared_ptr driver; + }; + + auto candidates = kstd::vector{}; + + for (auto const & entry : m_drivers) + { + auto const & [name, driver] = entry; + auto priority = driver->probe(inode); + if (priority) + { + candidates.push_back({*priority, driver}); + } + } + + std::ranges::stable_sort(candidates, std::ranges::greater{}, &candidate::priority); + + if (candidates.empty()) + { + return kstd::failure(vfs_errc::unsupported_filesystem); + } + + return candidates.front().driver; + } +} // namespace kernel::filesystem + +namespace kernel::tests::filesystem::driver_registry +{ + auto deinit() -> void + { + kernel::filesystem::instance.reset(); + } +} // namespace kernel::tests::filesystem::driver_registry \ No newline at end of file diff --git a/kernel/kernel/filesystem/driver_registry.hpp b/kernel/kernel/filesystem/driver_registry.hpp new file mode 100644 index 00000000..1a6cd47e --- /dev/null +++ b/kernel/kernel/filesystem/driver_registry.hpp @@ -0,0 +1,73 @@ +#ifndef TEACHOS_KERNEL_DRIVER_REGISTRY_HPP +#define TEACHOS_KERNEL_DRIVER_REGISTRY_HPP + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace kernel::filesystem +{ + + struct driver_descriptor + { + virtual ~driver_descriptor() = default; + + //! Get the name of the driver. + [[nodiscard]] virtual auto name() const noexcept -> std::string_view = 0; + + //! Create a new instance of the driver represented by this descriptor. + [[nodiscard]] virtual auto make_instance() const -> kstd::shared_ptr = 0; + }; + + template Type> + struct driver_module + { + constexpr auto static instance = Type{}; + [[using gnu: section("filesystem_drivers"), used, visibility("hidden")]] constexpr auto static pointer{ + kstd::make_observer(&instance), + }; + }; + + struct driver_registry + { + constexpr driver_registry() noexcept = default; + + auto static init() -> void; + + auto static get() -> driver_registry &; + + //! Register a new filesystem. + //! + //! @param name The name of the filesystem. + //! @param driver The filesystem driver to register. + //! @return @c true iff. the driver was successfully added, @c false if not. + auto add(std::string_view name, kstd::shared_ptr driver) -> bool; + + //! Find a registered filesystem driver + //! + //! @param name The name of the filesystem + [[nodiscard]] auto find(std::string_view name) const -> std::optional>; + + //! Match all currently registered filesystem drivers against a given inode. + //! + //! @param inode The inode to match on, if any. + //! @return a match priority if th + [[nodiscard]] auto match(kstd::shared_ptr const & inode) const -> kstd::result>; + + private: + //! A map from filesystem names to filesystem drivers. + kstd::flat_map> m_drivers{}; + }; + +} // namespace kernel::filesystem + +#endif diff --git a/kernel/kernel/filesystem/ext2/filesystem.cpp b/kernel/kernel/filesystem/ext2/filesystem.cpp index ef81f6ac..579094e0 100644 --- a/kernel/kernel/filesystem/ext2/filesystem.cpp +++ b/kernel/kernel/filesystem/ext2/filesystem.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -9,7 +10,6 @@ #include #include #include -#include #include #include @@ -34,6 +34,25 @@ using namespace kstd::units_literals; namespace kernel::filesystem::ext2 { + + struct descriptor final : kernel::filesystem::driver_descriptor + { + [[nodiscard]] auto name() const noexcept -> std::string_view override + { + return "ext2"; + } + + [[nodiscard]] auto make_instance() const -> filesystem::filesystem_ptr override + { + return kstd::make_shared(); + } + }; + + [[gnu::used]] + constexpr auto registration = driver_module{}; + + static_assert(sizeof(kernel::filesystem::filesystem) == sizeof(kernel::filesystem::ext2::filesystem)); + namespace { [[nodiscard]] auto bitmap_is_set(kstd::vector const & bitmap, size_t index) -> bool @@ -55,57 +74,38 @@ namespace kernel::filesystem::ext2 read_only_compatible_features::large_file_support; } // namespace - struct type final : kernel::filesystem::type + auto filesystem::indirect_levels(mount_state const & state) const -> std::array { - [[nodiscard]] auto name() const noexcept -> std::string_view override + return { + {{constants::singly_indirect_block_index, block_numbers_per_singly_indirect_block(state)}, + {constants::doubly_indirect_block_index, block_numbers_per_doubly_indirect_block(state)}, + {constants::triply_indirect_block_index, block_numbers_per_triply_indirect_block(state)}} + }; + } + + auto filesystem::probe(inode_ptr const & backing_inode) const -> kstd::result + { + auto superblock = ext2::superblock{}; + auto bytes = std::as_writable_bytes(std::span{&superblock, 1}); + auto read_result = backing_inode->read(bytes, constants::superblock_offset); + + if (!read_result) { - return "ext2"; + return kstd::failure(read_result.error()); } - [[nodiscard]] auto probe(filesystem::inode_ptr const & backing_inode) const noexcept - -> kstd::result override + if (superblock.magic != constants::magic_number) { - auto superblock = ext2::superblock{}; - auto bytes = std::as_writable_bytes(std::span{&superblock, 1}); - auto read_result = backing_inode->read(bytes, constants::superblock_offset); - - if (!read_result) - { - return kstd::failure(read_result.error()); - } - - if (superblock.magic != constants::magic_number) - { - return kstd::failure(ext2_errc::invalid_magic_number); - } - - if (superblock.feature_incompat & std::to_underlying(~supported_incompatible_features) || - superblock.feature_ro_compat & std::to_underlying(~supported_ro_compatible_features)) - { - return kstd::failure(ext2_errc::unsupported_features_present); - } - - return 0; + return kstd::failure(ext2_errc::invalid_magic_number); } - [[nodiscard]] auto make_instance() const -> filesystem::filesystem_ptr override + if (superblock.feature_incompat & std::to_underlying(~supported_incompatible_features) || + superblock.feature_ro_compat & std::to_underlying(~supported_ro_compatible_features)) { - return kstd::make_shared(); + return kstd::failure(ext2_errc::unsupported_features_present); } - }; - - [[gnu::used]] - constexpr auto registration = type_registration{}; - - static_assert(sizeof(kernel::filesystem::filesystem) == sizeof(kernel::filesystem::ext2::filesystem)); - auto filesystem::indirect_levels(mount_state const & state) const -> std::array - { - return { - {{constants::singly_indirect_block_index, block_numbers_per_singly_indirect_block(state)}, - {constants::doubly_indirect_block_index, block_numbers_per_doubly_indirect_block(state)}, - {constants::triply_indirect_block_index, block_numbers_per_triply_indirect_block(state)}} - }; + return 0; } auto filesystem::mount(inode_ptr const & backing_inode) -> kstd::result diff --git a/kernel/kernel/filesystem/ext2/filesystem.hpp b/kernel/kernel/filesystem/ext2/filesystem.hpp index 9ee737a7..4b5604e5 100644 --- a/kernel/kernel/filesystem/ext2/filesystem.hpp +++ b/kernel/kernel/filesystem/ext2/filesystem.hpp @@ -76,6 +76,8 @@ namespace kernel::filesystem::ext2 //! The Second Extended Filesystem (ext2) struct filesystem final : kernel::filesystem::filesystem { + [[nodiscard]] auto probe(inode_ptr const & backing_inode) const -> kstd::result override; + auto mount(inode_ptr const & backing_inode) -> kstd::result override; [[nodiscard]] auto lookup(inode_ptr const & parent, std::string_view name, driver_data_ptr driver_data) const diff --git a/kernel/kernel/filesystem/filesystem.cpp b/kernel/kernel/filesystem/filesystem.cpp deleted file mode 100644 index d2e3adde..00000000 --- a/kernel/kernel/filesystem/filesystem.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#include -#include -#include - -#include -#include -#include - -namespace kernel::filesystem -{ - - auto filesystem::probe(kstd::shared_ptr const & backing_inode) -> kstd::result> - { - for (auto & type : type_registry::get().all()) - { - if (!type || !type->probe(backing_inode)) - { - continue; - } - - if (auto fs = type->make_instance()) - { - return fs; - } - } - - return kstd::failure(vfs_errc::unsupported_filesystem); - } - -} // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/kernel/filesystem/filesystem.hpp b/kernel/kernel/filesystem/filesystem.hpp index 2e713c89..f9fb2859 100644 --- a/kernel/kernel/filesystem/filesystem.hpp +++ b/kernel/kernel/filesystem/filesystem.hpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -30,11 +31,11 @@ namespace kernel::filesystem //! Virtual destructor enabling polymorphic destruction. virtual ~filesystem() = default; - //! Probes the given inode to determine if it contains a recognizable filesystem. + //! Check if the data represented by the given inode is recognized as this filesystem. //! - //! @param backing_inode The inode to probe and mount, if any. - //! @return A pointer to the instantiated filesystem and the root of it on success, an error otherwise. - auto static probe(inode_ptr const & backing_inode) -> kstd::result; + //! @param inode The inode to probe, if any. + //! @return the priority (higher is better) of the match on success, an error otherwise. + [[nodiscard]] virtual auto probe(inode_ptr const & inode) const -> kstd::result = 0; //! Initializes the filesystem with the given inode. //! diff --git a/kernel/kernel/filesystem/rootfs/filesystem.cpp b/kernel/kernel/filesystem/rootfs/filesystem.cpp index 994ebaca..a14addba 100644 --- a/kernel/kernel/filesystem/rootfs/filesystem.cpp +++ b/kernel/kernel/filesystem/rootfs/filesystem.cpp @@ -1,9 +1,9 @@ #include +#include #include #include #include -#include #include @@ -17,24 +17,13 @@ namespace kernel::filesystem::rootfs { - struct type final : kernel::filesystem::type + struct descriptor final : kernel::filesystem::driver_descriptor { [[nodiscard]] auto name() const noexcept -> std::string_view override { return "rootfs"; } - [[nodiscard]] auto probe(filesystem::inode_ptr const & backing_inode) const noexcept - -> kstd::result override - { - if (backing_inode) - { - return kstd::failure(vfs_errc::invalid_argument); - } - - return 0; - } - [[nodiscard]] auto make_instance() const -> filesystem::filesystem_ptr override { return kstd::make_shared(); @@ -42,7 +31,19 @@ namespace kernel::filesystem::rootfs }; [[gnu::used]] - constexpr auto registration = type_registration{}; + constexpr auto registration = driver_module{}; + + static_assert(sizeof(kernel::filesystem::filesystem) == sizeof(rootfs::filesystem)); + + auto filesystem::probe(inode_ptr const & inode) const -> kstd::result + { + if (inode) + { + return kstd::failure(vfs_errc::invalid_argument); + } + + return 0; + } auto filesystem::mount(inode_ptr const &) -> kstd::result { diff --git a/kernel/kernel/filesystem/rootfs/filesystem.hpp b/kernel/kernel/filesystem/rootfs/filesystem.hpp index edef76d4..0195b250 100644 --- a/kernel/kernel/filesystem/rootfs/filesystem.hpp +++ b/kernel/kernel/filesystem/rootfs/filesystem.hpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -24,6 +25,8 @@ namespace kernel::filesystem::rootfs //! hierarchy. It is responsible for providing a stable and consistent interface to the root directory. struct filesystem : kernel::filesystem::filesystem { + [[nodiscard]] auto probe(inode_ptr const & inode) const -> kstd::result override; + //! @copydoc kernel::filesystem::filesystem::mount auto mount(inode_ptr const & backing_inode) -> kstd::result override; diff --git a/kernel/kernel/filesystem/type.hpp b/kernel/kernel/filesystem/type.hpp deleted file mode 100644 index c2f2595b..00000000 --- a/kernel/kernel/filesystem/type.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef TEACHOS_KERNEL_FILESYSTEM_TYPE_HPP -#define TEACHOS_KERNEL_FILESYSTEM_TYPE_HPP - -#include -#include - -#include -#include - -#include -#include - -namespace kernel::filesystem -{ - - //! A type descriptor for a filesystem driver. - //! - //! Each filesystem must expose an instance of a class derived from this type in order to be registered with the vfs - //! filesystem registry. - struct type - { - virtual ~type() = default; - - //! Get the name of the filesystem represented by this descriptor. - [[nodiscard]] virtual auto name() const noexcept -> std::string_view = 0; - - //! Check if the filesystem is applicable. - //! - //! @return the priority of this filesystem for the given inode. - [[nodiscard]] virtual auto probe(kstd::shared_ptr const & backing_inode) const noexcept - -> kstd::result = 0; - - //! Create a new instance of the filesystem represented by this descriptor. - [[nodiscard]] virtual auto make_instance() const -> kstd::shared_ptr = 0; - }; - - template - struct type_registration - { - constexpr auto static instance = Type{}; - [[using gnu: section("fs_types"), used, visibility("hidden")]] constexpr auto static pointer{ - kstd::make_observer(&instance), - }; - }; - -} // namespace kernel::filesystem - -#endif diff --git a/kernel/kernel/filesystem/type_registry.cpp b/kernel/kernel/filesystem/type_registry.cpp deleted file mode 100644 index 05fb116a..00000000 --- a/kernel/kernel/filesystem/type_registry.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace kernel::filesystem -{ - - extern "C" - { - // We need to suppress clang-tidy linting warnings here, since these symbols are generated by the linker and we - // cannot choose their names, unless we wanted to extend the linker script needlessly. - // NOLINTBEGIN(readability-identifier-naming) - extern type_registry::pointer const __start_fs_types; - extern type_registry::pointer const __stop_fs_types; - // NOLINTEND(readability-identifier-naming) - } - - namespace - { - auto constinit instance = std::optional{}; - } - - auto type_registry::init() -> void - { - if (instance) - { - kapi::system::panic("[FILESYSTEM] tried to initialize type registry more than once!"); - } - - instance.emplace(); - - auto type_descriptors = std::span{&__start_fs_types, &__stop_fs_types} | // - std::views::filter([](auto p) { return p != nullptr; }); - - std::ranges::for_each(type_descriptors, [](auto descriptor) { - kstd::println("[FILESYSTEM] registering '{}'", descriptor->name()); - instance->add(descriptor); - }); - } - - auto type_registry::get() -> type_registry & - { - if (!instance) - { - kapi::system::panic("[FILESYSTEM] type registry has not been initialized!"); - } - - return *instance; - } - - auto type_registry::find(std::string_view name) const -> std::optional - { - if (auto it = m_descriptors.find(name); it != m_descriptors.end()) - { - return it->second; - } - return std::nullopt; - } - - auto type_registry::add(pointer descriptor) -> bool - { - auto result = m_descriptors.emplace(descriptor->name(), descriptor); - return result.second; - } - - auto type_registry::all() const noexcept -> kstd::vector - { - return m_descriptors.values(); - } - - auto type_registry::size() const noexcept -> std::size_t - { - return m_descriptors.size(); - } - -} // namespace kernel::filesystem - -namespace kernel::tests::filesystem::type_registry -{ - auto deinit() -> void - { - kernel::filesystem::instance.reset(); - } -} // namespace kernel::tests::filesystem::type_registry \ No newline at end of file diff --git a/kernel/kernel/filesystem/type_registry.hpp b/kernel/kernel/filesystem/type_registry.hpp deleted file mode 100644 index 11669ab3..00000000 --- a/kernel/kernel/filesystem/type_registry.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef TEACHOS_KERNEL_TYPE_REGISTRY_HPP -#define TEACHOS_KERNEL_TYPE_REGISTRY_HPP - -#include - -#include -#include -#include -#include - -#include -#include -#include - -namespace kernel::filesystem -{ - - struct type_registry - { - using value_type = type; - using pointer = kstd::observer_ptr; - - auto static init() -> void; - auto static get() -> type_registry &; - - constexpr type_registry() noexcept = default; - - //! Add a type descriptor to this registry. - //! - //! This function will register the given descriptor with this registry, given that no descriptor for a filesystem - //! with the same name exists in this registry already. - //! - //! @param descriptor The filesystem type descriptor to add to the registry. - //! @return @p true iff. the descriptor was successfully added, @p false if not. - auto add(pointer descriptor) -> bool; - - //! Find a registered type descriptor by name - //! - //! @param name The name of the filesystem - [[nodiscard]] auto find(std::string_view name) const -> std::optional; - - //! Get all currently registered type descriptors. - //! - //! @return A span containing all currently registered filesystem type descriptors. - [[nodiscard]] auto all() const noexcept -> kstd::vector; - - //! Get the number of registered filesystem types. - //! - //! @return The number of filesystem descriptors currently registered with this registry. - [[nodiscard]] auto size() const noexcept -> std::size_t; - - private: - //! A map from filesystem names (identifiers) to filesystem type descriptors. - kstd::flat_map m_descriptors{}; - }; - -} // namespace kernel::filesystem - -#endif diff --git a/kernel/kernel/filesystem/type_registry.tests.cpp b/kernel/kernel/filesystem/type_registry.tests.cpp deleted file mode 100644 index b38c16f8..00000000 --- a/kernel/kernel/filesystem/type_registry.tests.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include - -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include - -struct test_type final : kernel::filesystem::type -{ - [[nodiscard]] auto name() const noexcept -> std::string_view override - { - return "bht_testfs"; - } - - [[nodiscard]] auto probe(kstd::shared_ptr const &) const noexcept - -> kstd::result override - { - return false; - } - - [[nodiscard]] auto make_instance() const -> kstd::shared_ptr override - { - return nullptr; - } -}; - -SCENARIO("Filesystem type registry initialization and construction", "[filesystem]") -{ - GIVEN("A default constructed type_registry") - { - auto instance = kernel::filesystem::type_registry{}; - - WHEN("getting the span of filesystem descriptors") - { - auto descriptors = instance.all(); - - THEN("the span is empty") - { - REQUIRE(descriptors.empty()); - } - } - } -} - -SCENARIO("Filesystem type registry modifiers", "[filesystem]") -{ - GIVEN("A default constructed type_registry") - { - auto instance = kernel::filesystem::type_registry{}; - - WHEN("adding a type descriptor") - { - auto descriptor = test_type{}; - - instance.add(kstd::make_observer(&descriptor)); - - THEN("the size of the registry is one") - { - REQUIRE(instance.size() == 1); - } - - THEN("the span is not empty") - { - REQUIRE_FALSE(instance.all().empty()); - } - - THEN("the span's size is equal to the registry size") - { - REQUIRE(std::size(instance.all()) == std::size(instance)); - } - } - } -} diff --git a/kernel/kernel/filesystem/vfs.cpp b/kernel/kernel/filesystem/vfs.cpp index 43da7130..d8bcb6b6 100644 --- a/kernel/kernel/filesystem/vfs.cpp +++ b/kernel/kernel/filesystem/vfs.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -11,12 +12,12 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -53,14 +54,13 @@ namespace kernel::filesystem vfs::vfs() { // mount rootfs at / - auto root_fs_descriptor = type_registry::get().find("rootfs"); - if (!root_fs_descriptor) + auto rootfs = driver_registry::get().find("rootfs"); + if (!rootfs) { kapi::system::panic("[OS:FS] rootfs driver is missing!"); } - auto root_fs = (*root_fs_descriptor)->make_instance(); - auto root_mount_result = root_fs->mount(nullptr); + auto root_mount_result = (*rootfs)->mount(nullptr); if (!root_mount_result) { kapi::system::panic("[FILESYSTEM] failed to mount root FS", root_mount_result.error()); @@ -68,45 +68,53 @@ namespace kernel::filesystem auto [root_inode, root_state] = *root_mount_result; - auto root_mount = mount::attach(nullptr, root_fs, root_inode, root_state, nullptr, nullptr); + auto root_mount = mount::attach(nullptr, *rootfs, root_inode, root_state, nullptr, nullptr); m_mount_table.add_mount(root_mount); // mount devfs at /dev (inside rootfs, temporary, will be shadowed) - auto device_fs_descriptor = type_registry::get().find("devfs"); - if (!device_fs_descriptor) + auto devfs = driver_registry::get().find("devfs"); + if (!devfs) { kapi::system::panic("[OS:FS] devfs driver is missing!"); } - auto device_fs = (*device_fs_descriptor)->make_instance(); - auto device_fs_mount_result = device_fs->mount(nullptr); + auto device_fs_mount_result = (*devfs)->mount(nullptr); if (!device_fs_mount_result) { kapi::system::panic("[FILESYSTEM] failed to mount device FS", device_fs_mount_result.error()); } auto [device_fs_root, device_fs_data] = *device_fs_mount_result; - graft_persistent_device_fs(device_fs, device_fs_root, device_fs_data); + graft_persistent_device_fs(*devfs, device_fs_root, device_fs_data); // 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) { - if (auto result = kernel::filesystem::filesystem::probe(boot_device_dentry->inode())) + auto driver = driver_registry::get().match(boot_device_dentry->inode()); + if (!driver) { - if (auto root_dentry = resolve_path("/")) - { - auto mount = - mount::create(*root_dentry, *result, root_mount, 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); - graft_persistent_device_fs(device_fs, device_fs_root, device_fs_data); - } + kstd::println(kstd::print_sink::stderr, "[OS:FS] Missing driver for root disk!"); + return; + } + + auto root_dentry = resolve_path("/"); + if (!root_dentry) + { + kapi::system::panic("[OS:FS] No root directory found!"); + } + + auto mount = + mount::create(*root_dentry, *driver, root_mount, 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); + + graft_persistent_device_fs(*devfs, device_fs_root, device_fs_data); } } @@ -188,13 +196,14 @@ namespace kernel::filesystem } auto [source_dentry, source_mount_context] = *resolved_source; - auto fs = kernel::filesystem::filesystem::probe(source_dentry->inode()); - if (!fs) + auto driver = driver_registry::get().match(source_dentry->inode()); + if (!driver) { - return kstd::failure(fs.error()); + return kstd::failure(driver.error()); } - auto mount = mount::create(mount_point_dentry, *fs, mount_context, source_mount_context, source_dentry->inode()); + auto mount = + mount::create(mount_point_dentry, *driver, mount_context, source_mount_context, source_dentry->inode()); if (!mount) { return kstd::failure(mount.error()); diff --git a/kernel/kernel/main.cpp b/kernel/kernel/main.cpp index db47f167..f8322b31 100644 --- a/kernel/kernel/main.cpp +++ b/kernel/kernel/main.cpp @@ -1,4 +1,4 @@ -#include "kernel/filesystem/type_registry.hpp" +#include "kernel/filesystem/driver_registry.hpp" #include #include #include @@ -248,7 +248,7 @@ auto main() -> int kernel::filesystem::open_file_table::init(); kstd::println("[OS] Global open file table initialized."); - kernel::filesystem::type_registry::init(); + kernel::filesystem::driver_registry::init(); kstd::println("[OS] Builtin filesystems registered."); kernel::filesystem::vfs::init(); diff --git a/kernel/kernel/test_support/filesystem/driver_registry.hpp b/kernel/kernel/test_support/filesystem/driver_registry.hpp new file mode 100644 index 00000000..b91acd57 --- /dev/null +++ b/kernel/kernel/test_support/filesystem/driver_registry.hpp @@ -0,0 +1,10 @@ +#ifndef TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_DRIVER_REGISTRY_HPP +#define TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_DRIVER_REGISTRY_HPP + +namespace kernel::tests::filesystem::driver_registry +{ + //! Deinitialize the FS type registry singleton. + auto deinit() -> void; +} // namespace kernel::tests::filesystem::driver_registry + +#endif \ No newline at end of file diff --git a/kernel/kernel/test_support/filesystem/filesystem.cpp b/kernel/kernel/test_support/filesystem/filesystem.cpp index 105746e8..0d4610ab 100644 --- a/kernel/kernel/test_support/filesystem/filesystem.cpp +++ b/kernel/kernel/test_support/filesystem/filesystem.cpp @@ -9,12 +9,18 @@ #include #include +#include #include #include #include namespace kernel::tests::filesystem { + auto filesystem::probe(inode_ptr const &) const -> kstd::result + { + return 0; + } + auto filesystem::mount(inode_ptr const &) -> kstd::result { return std::pair{kstd::make_shared(), nullptr}; diff --git a/kernel/kernel/test_support/filesystem/filesystem.hpp b/kernel/kernel/test_support/filesystem/filesystem.hpp index 52111a5a..3df2cccb 100644 --- a/kernel/kernel/test_support/filesystem/filesystem.hpp +++ b/kernel/kernel/test_support/filesystem/filesystem.hpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -19,6 +20,8 @@ namespace kernel::tests::filesystem { filesystem() = default; + [[nodiscard]] auto probe(inode_ptr const & inode) const -> kstd::result override; + auto mount(kstd::shared_ptr const & backing_inode) -> kstd::result override; diff --git a/kernel/kernel/test_support/filesystem/storage_boot_module_fixture.cpp b/kernel/kernel/test_support/filesystem/storage_boot_module_fixture.cpp index 3df23751..b9228c69 100644 --- a/kernel/kernel/test_support/filesystem/storage_boot_module_fixture.cpp +++ b/kernel/kernel/test_support/filesystem/storage_boot_module_fixture.cpp @@ -2,8 +2,6 @@ #include #include -#include -#include #include #include diff --git a/kernel/kernel/test_support/filesystem/type_registry.hpp b/kernel/kernel/test_support/filesystem/type_registry.hpp deleted file mode 100644 index 8d5b6029..00000000 --- a/kernel/kernel/test_support/filesystem/type_registry.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_TYPE_REGISTRY_HPP -#define TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_TYPE_REGISTRY_HPP - -namespace kernel::tests::filesystem::type_registry -{ - //! Deinitialize the FS type registry singleton. - auto deinit() -> void; -} // namespace kernel::tests::filesystem::type_registry - -#endif \ No newline at end of file diff --git a/kernel/kernel/test_support/state_reset_listener.cpp b/kernel/kernel/test_support/state_reset_listener.cpp index e900b31c..948f2f7e 100644 --- a/kernel/kernel/test_support/state_reset_listener.cpp +++ b/kernel/kernel/test_support/state_reset_listener.cpp @@ -1,13 +1,13 @@ #include #include +#include #include -#include #include #include #include #include +#include #include -#include #include #include @@ -42,15 +42,14 @@ struct state_reset_listener : Catch::EventListenerBase std::ignore = kernel::devices::storage::init(); kernel::filesystem::open_file_table::init(); - kernel::filesystem::type_registry::init(); + kernel::filesystem::driver_registry::init(); } void testCaseEnded(Catch::TestCaseStats const &) override { - kernel::tests::filesystem::type_registry::deinit(); + kernel::tests::filesystem::driver_registry::deinit(); kernel::tests::filesystem::device_number_registry::deinit(); kernel::tests::filesystem::vfs::deinit(); - kernel::tests::filesystem::type_registry::deinit(); kernel::tests::filesystem::open_file_table::deinit(); kapi::test_support::devices::deinit(); -- cgit v1.2.3