diff options
| author | Lukas Oesch <lukas.oesch@ost.ch> | 2026-06-10 10:40:46 +0200 |
|---|---|---|
| committer | Lukas Oesch <lukas.oesch@ost.ch> | 2026-06-10 10:40:46 +0200 |
| commit | 33abd5cf264cb9e34121082105b0bc17b3cf7a36 (patch) | |
| tree | 36b15d53fea04f4f9d9af817100f7ad013bd9b5c /kernel/src/filesystem/devfs | |
| parent | d01caf1c4aef3c89c68b9d1cc9fe56445f0860b5 (diff) | |
| parent | 7e27130c342b7299a1d2188a7192a7f17b5ac2ad (diff) | |
| download | kernel-33abd5cf264cb9e34121082105b0bc17b3cf7a36.tar.xz kernel-33abd5cf264cb9e34121082105b0bc17b3cf7a36.zip | |
Merge of BA-FS26 branch into develop
See merge request teachos/kernel!49
Diffstat (limited to 'kernel/src/filesystem/devfs')
| -rw-r--r-- | kernel/src/filesystem/devfs/filesystem.cpp | 81 | ||||
| -rw-r--r-- | kernel/src/filesystem/devfs/filesystem.tests.cpp | 72 | ||||
| -rw-r--r-- | kernel/src/filesystem/devfs/inode.cpp | 21 | ||||
| -rw-r--r-- | kernel/src/filesystem/devfs/inode.tests.cpp | 55 |
4 files changed, 229 insertions, 0 deletions
diff --git a/kernel/src/filesystem/devfs/filesystem.cpp b/kernel/src/filesystem/devfs/filesystem.cpp new file mode 100644 index 0000000..ce887ff --- /dev/null +++ b/kernel/src/filesystem/devfs/filesystem.cpp @@ -0,0 +1,81 @@ +#include <kernel/filesystem/devfs/filesystem.hpp> + +#include "kernel/filesystem/filesystem.hpp" +#include <kernel/devices/storage/management.hpp> +#include <kernel/filesystem/devfs/inode.hpp> +#include <kernel/filesystem/device_inode.hpp> +#include <kernel/filesystem/inode.hpp> +#include <kernel/filesystem/type.hpp> + +#include <kapi/devices/device.hpp> + +#include <kstd/memory> + +#include <algorithm> +#include <string_view> + +namespace kernel::filesystem::devfs +{ + struct type final : kernel::filesystem::type + { + [[nodiscard]] auto name() const noexcept -> std::string_view override + { + return "devfs"; + } + + [[nodiscard]] auto requires_device() const noexcept -> bool override + { + return false; + } + + [[nodiscard]] auto make_instance() const -> kstd::shared_ptr<kernel::filesystem::filesystem> override + { + return kstd::make_shared<filesystem>(); + } + }; + + [[gnu::used]] + constexpr auto registration = type_registration<type>{}; + + auto filesystem::mount(kstd::shared_ptr<kernel::filesystem::inode> const &) -> operation_result + { + m_root_inode = kstd::make_shared<inode>(); + build_device_inode_table(); + + return operation_result::success; + } + + auto filesystem::lookup(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name) const + -> kstd::shared_ptr<kernel::filesystem::inode> + { + if (!parent || !parent->is_directory()) + { + return nullptr; + } + + if (parent.get() != m_root_inode.get()) + { + return nullptr; + } + + auto it = std::ranges::find_if(m_inodes, [&](auto const & dev_node) { + if (auto device_inode_ptr = static_cast<device_inode *>(dev_node.get())) + { + return device_inode_ptr->device()->name() == name; + } + return false; + }); + return (it != m_inodes.end()) ? *it : nullptr; + } + + auto filesystem::build_device_inode_table() -> void + { + m_inodes.clear(); + + auto storage_mgmt = devices::storage::management::get(); + std::ranges::for_each(storage_mgmt.all_controllers(), [&](auto const & controller) { + std::ranges::for_each(controller->all_devices(), + [&](auto const & device) { m_inodes.push_back(kstd::make_shared<device_inode>(device)); }); + }); + } +} // namespace kernel::filesystem::devfs
\ No newline at end of file diff --git a/kernel/src/filesystem/devfs/filesystem.tests.cpp b/kernel/src/filesystem/devfs/filesystem.tests.cpp new file mode 100644 index 0000000..36cb411 --- /dev/null +++ b/kernel/src/filesystem/devfs/filesystem.tests.cpp @@ -0,0 +1,72 @@ +#include <kernel/filesystem/devfs/filesystem.hpp> + +#include <kernel/filesystem/filesystem.hpp> +#include <kernel/test_support/filesystem/storage_boot_module_fixture.hpp> + +#include <catch2/catch_test_macros.hpp> + +SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, + "Devfs filesystem lookup uses storage management devices", "[filesystem][devfs][filesystem]") +{ + GIVEN("a boot module registry with one module") + { + setup_modules(1); + + auto fs = kernel::filesystem::devfs::filesystem{}; + auto result = fs.mount(nullptr); + + THEN("mount succeeds") + { + REQUIRE(result == kernel::filesystem::filesystem::operation_result::success); + REQUIRE(fs.root_inode() != nullptr); + } + + THEN("lookup on root finds ram0 device inode") + { + auto inode = fs.lookup(fs.root_inode(), "ram0"); + REQUIRE(inode != nullptr); + REQUIRE(inode->is_device()); + } + + THEN("lookup of an unknown device returns null") + { + auto inode = fs.lookup(fs.root_inode(), "ram99"); + REQUIRE(inode == nullptr); + } + + THEN("lookup with wrong parent returns null") + { + auto other_fs = kernel::filesystem::devfs::filesystem{}; + other_fs.mount(nullptr); + + auto inode = fs.lookup(other_fs.root_inode(), "ram0"); + REQUIRE(inode == nullptr); + } + + THEN("lookup with a non-directory parent returns null") + { + auto non_directory_inode = fs.lookup(fs.root_inode(), "ram0"); + REQUIRE(non_directory_inode != nullptr); + REQUIRE_FALSE(non_directory_inode->is_directory()); + + auto result = fs.lookup(non_directory_inode, "anything"); + REQUIRE(result == nullptr); + } + } + + GIVEN("a boot module registry with three modules") + { + setup_modules(3, 2048); + + auto fs = kernel::filesystem::devfs::filesystem{}; + auto result = fs.mount(nullptr); + REQUIRE(result == kernel::filesystem::filesystem::operation_result::success); + + THEN("lookup finds all generated RAM devices") + { + REQUIRE(fs.lookup(fs.root_inode(), "ram0") != nullptr); + REQUIRE(fs.lookup(fs.root_inode(), "ram16") != nullptr); + REQUIRE(fs.lookup(fs.root_inode(), "ram32") != nullptr); + } + } +} diff --git a/kernel/src/filesystem/devfs/inode.cpp b/kernel/src/filesystem/devfs/inode.cpp new file mode 100644 index 0000000..7bbfbbe --- /dev/null +++ b/kernel/src/filesystem/devfs/inode.cpp @@ -0,0 +1,21 @@ +#include <kernel/filesystem/devfs/inode.hpp> + +#include <cstddef> + +namespace kernel::filesystem::devfs +{ + auto inode::read(void *, size_t, size_t) const -> size_t + { + return 0; + } + + auto inode::write(void const *, size_t, size_t) -> size_t + { + return 0; + } + + auto inode::is_directory() const -> bool + { + return true; + } +} // namespace kernel::filesystem::devfs
\ No newline at end of file diff --git a/kernel/src/filesystem/devfs/inode.tests.cpp b/kernel/src/filesystem/devfs/inode.tests.cpp new file mode 100644 index 0000000..ae26e74 --- /dev/null +++ b/kernel/src/filesystem/devfs/inode.tests.cpp @@ -0,0 +1,55 @@ +#include <kernel/filesystem/devfs/inode.hpp> + +#include <kstd/memory> +#include <kstd/print> +#include <kstd/vector> + +#include <catch2/catch_test_macros.hpp> + +#include <cstdint> + +SCENARIO("Devfs inode creation", "[filesystem][devfs][inode]") +{ + GIVEN("a devfs inode") + { + auto inode = kernel::filesystem::devfs::inode{}; + + THEN("the inode has the correct kind") + { + REQUIRE(inode.is_directory()); + REQUIRE_FALSE(inode.is_device()); + REQUIRE_FALSE(inode.is_regular()); + REQUIRE_FALSE(inode.is_symbolic_link()); + } + } +} + +SCENARIO("Devfs inode read/write", "[filesystem][devfs][inode]") +{ + GIVEN("a devfs inode") + { + auto inode = kernel::filesystem::devfs::inode{}; + + WHEN("attempting to read from the devfs inode") + { + kstd::vector<uint8_t> buffer(512); + auto bytes_read = inode.read(buffer.data(), 0, buffer.size()); + + THEN("no bytes are read") + { + REQUIRE(bytes_read == 0); + } + } + + WHEN("attempting to write to the devfs inode") + { + kstd::vector<uint8_t> buffer(512); + auto bytes_written = inode.write(buffer.data(), 0, buffer.size()); + + THEN("no bytes are written") + { + REQUIRE(bytes_written == 0); + } + } + } +} |
