aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-08-23 18:10:10 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-08-26 11:16:17 +0200
commit84aac7e26dae2b4364d2f1145d4b2b40f1e37585 (patch)
tree92fbe61467f3c06234acb654c7033d3f4b977d53 /kernel
parentb253637e5eed149f6e8ad7465cf97dda8bf8483a (diff)
downloadkernel-84aac7e26dae2b4364d2f1145d4b2b40f1e37585.tar.xz
kernel-84aac7e26dae2b4364d2f1145d4b2b40f1e37585.zip
kernel/fs: rework filesystem probing
Diffstat (limited to 'kernel')
-rw-r--r--kernel/CMakeLists.txt3
-rw-r--r--kernel/kernel/filesystem/devfs/filesystem.cpp26
-rw-r--r--kernel/kernel/filesystem/devfs/filesystem.hpp6
-rw-r--r--kernel/kernel/filesystem/driver_registry.cpp125
-rw-r--r--kernel/kernel/filesystem/driver_registry.hpp73
-rw-r--r--kernel/kernel/filesystem/ext2/filesystem.cpp84
-rw-r--r--kernel/kernel/filesystem/ext2/filesystem.hpp2
-rw-r--r--kernel/kernel/filesystem/filesystem.cpp32
-rw-r--r--kernel/kernel/filesystem/filesystem.hpp9
-rw-r--r--kernel/kernel/filesystem/rootfs/filesystem.cpp29
-rw-r--r--kernel/kernel/filesystem/rootfs/filesystem.hpp3
-rw-r--r--kernel/kernel/filesystem/type.hpp48
-rw-r--r--kernel/kernel/filesystem/type_registry.cpp94
-rw-r--r--kernel/kernel/filesystem/type_registry.hpp59
-rw-r--r--kernel/kernel/filesystem/type_registry.tests.cpp81
-rw-r--r--kernel/kernel/filesystem/vfs.cpp63
-rw-r--r--kernel/kernel/main.cpp4
-rw-r--r--kernel/kernel/test_support/filesystem/driver_registry.hpp10
-rw-r--r--kernel/kernel/test_support/filesystem/filesystem.cpp6
-rw-r--r--kernel/kernel/test_support/filesystem/filesystem.hpp3
-rw-r--r--kernel/kernel/test_support/filesystem/storage_boot_module_fixture.cpp2
-rw-r--r--kernel/kernel/test_support/filesystem/type_registry.hpp10
-rw-r--r--kernel/kernel/test_support/state_reset_listener.cpp9
23 files changed, 345 insertions, 436 deletions
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 <kernel/filesystem/devfs/inode.hpp>
#include <kernel/filesystem/device_inode.hpp>
#include <kernel/filesystem/device_number_registry.hpp>
+#include <kernel/filesystem/driver_registry.hpp>
#include <kernel/filesystem/error.hpp>
#include <kernel/filesystem/filesystem.hpp>
#include <kernel/filesystem/inode.hpp>
-#include <kernel/filesystem/type.hpp>
#include <kapi/filesystem.hpp>
@@ -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<std::uint32_t> 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<filesystem>();
@@ -45,10 +35,20 @@ namespace kernel::filesystem::devfs
};
[[gnu::used]]
- constexpr auto registration = type_registration<type>{};
+ constexpr auto registration = driver_module<descriptor>{};
static_assert(sizeof(kernel::filesystem::filesystem) == sizeof(devfs::filesystem));
+ auto filesystem::probe(inode_ptr const & inode) const -> kstd::result<std::uint32_t>
+ {
+ if (inode)
+ {
+ return kstd::failure(vfs_errc::invalid_argument);
+ }
+
+ return 0;
+ }
+
auto filesystem::mount(inode_ptr const &) -> kstd::result<mount_result>
{
auto root = kstd::make_shared<inode>();
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 <kernel/filesystem/device_inode.hpp>
#include <kernel/filesystem/device_number_registry.hpp>
+#include <kernel/filesystem/error.hpp>
#include <kernel/filesystem/filesystem.hpp>
#include <kernel/filesystem/inode.hpp>
@@ -13,6 +14,7 @@
#include <kstd/string.hpp>
#include <kstd/system_error.hpp>
+#include <cstdint>
#include <optional>
#include <string_view>
@@ -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<std::uint32_t> override;
+
auto mount(inode_ptr const & backing_inode) -> kstd::result<mount_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 <kernel/filesystem/driver_registry.hpp>
+
+#include <kernel/filesystem/error.hpp>
+#include <kernel/filesystem/filesystem.hpp>
+#include <kernel/filesystem/inode.hpp>
+
+#include <kapi/system.hpp>
+
+#include <kstd/memory.hpp>
+#include <kstd/print.hpp>
+#include <kstd/result.hpp>
+#include <kstd/vector.hpp>
+
+#include <algorithm>
+#include <cstdint>
+#include <functional>
+#include <optional>
+#include <ranges>
+#include <span>
+#include <string_view>
+#include <utility>
+
+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<driver_descriptor const> const __start_filesystem_drivers;
+ extern kstd::observer_ptr<driver_descriptor const> const __stop_filesystem_drivers;
+ // NOLINTEND(readability-identifier-naming)
+ }
+
+ namespace
+ {
+ auto constinit instance = std::optional<driver_registry>{};
+ }
+
+ 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<kstd::shared_ptr<filesystem>>
+ {
+ 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<filesystem> descriptor) -> bool
+ {
+ auto result = m_drivers.emplace(name, descriptor);
+ return result.second;
+ }
+
+ auto driver_registry::match(kstd::shared_ptr<inode> const & inode) const -> kstd::result<kstd::shared_ptr<filesystem>>
+ {
+ struct candidate
+ {
+ std::uint32_t priority;
+ kstd::shared_ptr<filesystem> driver;
+ };
+
+ auto candidates = kstd::vector<candidate>{};
+
+ 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 <kernel/filesystem/filesystem.hpp>
+#include <kernel/filesystem/inode.hpp>
+
+#include <kstd/flat_map.hpp>
+#include <kstd/memory.hpp>
+#include <kstd/result.hpp>
+#include <kstd/string.hpp>
+#include <kstd/vector.hpp>
+
+#include <concepts>
+#include <optional>
+#include <string_view>
+
+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<filesystem> = 0;
+ };
+
+ template<std::derived_from<driver_descriptor> Type>
+ struct driver_module
+ {
+ constexpr auto static instance = Type{};
+ [[using gnu: section("filesystem_drivers"), used, visibility("hidden")]] constexpr auto static pointer{
+ kstd::make_observer<driver_descriptor const>(&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<filesystem> driver) -> bool;
+
+ //! Find a registered filesystem driver
+ //!
+ //! @param name The name of the filesystem
+ [[nodiscard]] auto find(std::string_view name) const -> std::optional<kstd::shared_ptr<filesystem>>;
+
+ //! 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<inode> const & inode) const -> kstd::result<kstd::shared_ptr<filesystem>>;
+
+ private:
+ //! A map from filesystem names to filesystem drivers.
+ kstd::flat_map<std::string_view, kstd::shared_ptr<filesystem>> 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 <kernel/filesystem/ext2/filesystem.hpp>
+#include <kernel/filesystem/driver_registry.hpp>
#include <kernel/filesystem/error.hpp>
#include <kernel/filesystem/ext2/block_group_descriptor.hpp>
#include <kernel/filesystem/ext2/error.hpp>
@@ -9,7 +10,6 @@
#include <kernel/filesystem/ext2/superblock.hpp>
#include <kernel/filesystem/filesystem.hpp>
#include <kernel/filesystem/inode.hpp>
-#include <kernel/filesystem/type.hpp>
#include <kapi/filesystem.hpp>
#include <kapi/system.hpp>
@@ -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<filesystem>();
+ }
+ };
+
+ [[gnu::used]]
+ constexpr auto registration = driver_module<descriptor>{};
+
+ static_assert(sizeof(kernel::filesystem::filesystem) == sizeof(kernel::filesystem::ext2::filesystem));
+
namespace
{
[[nodiscard]] auto bitmap_is_set(kstd::vector<uint8_t> 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<indirect_level, 3>
{
- [[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<std::uint32_t>
+ {
+ 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<std::uint32_t> 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<filesystem>();
+ return kstd::failure(ext2_errc::unsupported_features_present);
}
- };
-
- [[gnu::used]]
- constexpr auto registration = type_registration<type>{};
-
- static_assert(sizeof(kernel::filesystem::filesystem) == sizeof(kernel::filesystem::ext2::filesystem));
- auto filesystem::indirect_levels(mount_state const & state) const -> std::array<indirect_level, 3>
- {
- 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<mount_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<std::uint32_t> override;
+
auto mount(inode_ptr const & backing_inode) -> kstd::result<mount_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 <kernel/filesystem/filesystem.hpp>
-
-#include <kernel/filesystem/error.hpp>
-#include <kernel/filesystem/inode.hpp>
-#include <kernel/filesystem/type_registry.hpp>
-
-#include <kstd/memory.hpp>
-#include <kstd/result.hpp>
-#include <kstd/system_error.hpp>
-
-namespace kernel::filesystem
-{
-
- auto filesystem::probe(kstd::shared_ptr<inode> const & backing_inode) -> kstd::result<kstd::shared_ptr<filesystem>>
- {
- 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 <kstd/system_error.hpp>
#include <kstd/vector.hpp>
+#include <cstdint>
#include <optional>
#include <string_view>
#include <utility>
@@ -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<filesystem_ptr>;
+ //! @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<std::uint32_t> = 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 <kernel/filesystem/rootfs/filesystem.hpp>
+#include <kernel/filesystem/driver_registry.hpp>
#include <kernel/filesystem/error.hpp>
#include <kernel/filesystem/filesystem.hpp>
#include <kernel/filesystem/rootfs/inode.hpp>
-#include <kernel/filesystem/type.hpp>
#include <kapi/filesystem.hpp>
@@ -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<std::uint32_t> 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<filesystem>();
@@ -42,7 +31,19 @@ namespace kernel::filesystem::rootfs
};
[[gnu::used]]
- constexpr auto registration = type_registration<type>{};
+ constexpr auto registration = driver_module<descriptor>{};
+
+ static_assert(sizeof(kernel::filesystem::filesystem) == sizeof(rootfs::filesystem));
+
+ auto filesystem::probe(inode_ptr const & inode) const -> kstd::result<std::uint32_t>
+ {
+ if (inode)
+ {
+ return kstd::failure(vfs_errc::invalid_argument);
+ }
+
+ return 0;
+ }
auto filesystem::mount(inode_ptr const &) -> kstd::result<mount_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 <kstd/system_error.hpp>
#include <kstd/vector.hpp>
+#include <cstdint>
#include <optional>
#include <string_view>
@@ -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<std::uint32_t> override;
+
//! @copydoc kernel::filesystem::filesystem::mount
auto mount(inode_ptr const & backing_inode) -> kstd::result<mount_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 <kernel/filesystem/filesystem.hpp>
-#include <kernel/filesystem/inode.hpp>
-
-#include <kstd/memory.hpp>
-#include <kstd/result.hpp>
-
-#include <cstdint>
-#include <string_view>
-
-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<inode> const & backing_inode) const noexcept
- -> kstd::result<std::uint32_t> = 0;
-
- //! Create a new instance of the filesystem represented by this descriptor.
- [[nodiscard]] virtual auto make_instance() const -> kstd::shared_ptr<filesystem> = 0;
- };
-
- template<typename Type>
- struct type_registration
- {
- constexpr auto static instance = Type{};
- [[using gnu: section("fs_types"), used, visibility("hidden")]] constexpr auto static pointer{
- kstd::make_observer<type const>(&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 <kernel/filesystem/type_registry.hpp>
-
-#include <kapi/system.hpp>
-
-#include <kstd/memory.hpp>
-#include <kstd/print.hpp>
-#include <kstd/vector.hpp>
-
-#include <algorithm>
-#include <cstddef>
-#include <optional>
-#include <ranges>
-#include <span>
-
-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<type_registry>{};
- }
-
- 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<pointer>
- {
- 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<pointer>
- {
- 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 <kernel/filesystem/type.hpp>
-
-#include <kstd/flat_map.hpp>
-#include <kstd/memory.hpp>
-#include <kstd/string.hpp>
-#include <kstd/vector.hpp>
-
-#include <cstddef>
-#include <optional>
-#include <string_view>
-
-namespace kernel::filesystem
-{
-
- struct type_registry
- {
- using value_type = type;
- using pointer = kstd::observer_ptr<value_type const>;
-
- 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<pointer>;
-
- //! Get all currently registered type descriptors.
- //!
- //! @return A span containing all currently registered filesystem type descriptors.
- [[nodiscard]] auto all() const noexcept -> kstd::vector<pointer>;
-
- //! 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<std::string_view, pointer> 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 <kernel/filesystem/type_registry.hpp>
-
-#include <kernel/filesystem/filesystem.hpp>
-#include <kernel/filesystem/inode.hpp>
-#include <kernel/filesystem/type.hpp>
-
-#include <kstd/memory.hpp>
-#include <kstd/result.hpp>
-
-#include <catch2/catch_test_macros.hpp>
-
-#include <cstdint>
-#include <iterator>
-#include <string_view>
-
-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<kernel::filesystem::inode> const &) const noexcept
- -> kstd::result<std::uint32_t> override
- {
- return false;
- }
-
- [[nodiscard]] auto make_instance() const -> kstd::shared_ptr<kernel::filesystem::filesystem> 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 <kernel/filesystem/dentry.hpp>
#include <kernel/filesystem/device_inode.hpp>
#include <kernel/filesystem/device_number_registry.hpp>
+#include <kernel/filesystem/driver_registry.hpp>
#include <kernel/filesystem/error.hpp>
#include <kernel/filesystem/file_type.hpp>
#include <kernel/filesystem/filesystem.hpp>
@@ -11,12 +12,12 @@
#include <kernel/filesystem/mount.hpp>
#include <kernel/filesystem/mount_table.hpp>
#include <kernel/filesystem/path.hpp>
-#include <kernel/filesystem/type_registry.hpp>
#include <kapi/filesystem.hpp>
#include <kapi/system.hpp>
#include <kstd/memory.hpp>
+#include <kstd/print.hpp>
#include <kstd/result.hpp>
#include <kstd/system_error.hpp>
#include <kstd/units.hpp>
@@ -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 <kernel/devices/init.hpp>
#include <kernel/devices/storage.hpp>
#include <kernel/drivers/init.hpp>
@@ -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 <kstd/result.hpp>
#include <kstd/system_error.hpp>
+#include <cstdint>
#include <optional>
#include <string_view>
#include <utility>
namespace kernel::tests::filesystem
{
+ auto filesystem::probe(inode_ptr const &) const -> kstd::result<std::uint32_t>
+ {
+ return 0;
+ }
+
auto filesystem::mount(inode_ptr const &) -> kstd::result<mount_result>
{
return std::pair{kstd::make_shared<inode>(), 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 <kstd/result.hpp>
#include <kstd/system_error.hpp>
+#include <cstdint>
#include <optional>
#include <string_view>
@@ -19,6 +20,8 @@ namespace kernel::tests::filesystem
{
filesystem() = default;
+ [[nodiscard]] auto probe(inode_ptr const & inode) const -> kstd::result<std::uint32_t> override;
+
auto mount(kstd::shared_ptr<kernel::filesystem::inode> const & backing_inode)
-> kstd::result<mount_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 <kernel/bus/boot_modules.hpp>
#include <kernel/devices/storage.hpp>
-#include <kernel/filesystem/type.hpp>
-#include <kernel/filesystem/type_registry.hpp>
#include <kapi/boot_modules.hpp>
#include <kapi/boot_modules/device.hpp>
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 <kernel/devices/storage.hpp>
#include <kernel/drivers/init.hpp>
+#include <kernel/filesystem/driver_registry.hpp>
#include <kernel/filesystem/open_file_table.hpp>
-#include <kernel/filesystem/type_registry.hpp>
#include <kernel/filesystem/vfs.hpp>
#include <kernel/test_support/cio.hpp>
#include <kernel/test_support/cpu.hpp>
#include <kernel/test_support/filesystem/device_number_registry.hpp>
+#include <kernel/test_support/filesystem/driver_registry.hpp>
#include <kernel/test_support/filesystem/open_file_table.hpp>
-#include <kernel/test_support/filesystem/type_registry.hpp>
#include <kernel/test_support/filesystem/vfs.hpp>
#include <kernel/test_support/memory.hpp>
@@ -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();