aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-07-13 13:50:11 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-07-13 13:50:11 +0200
commit74e471800380573af6d63b2ad1ba95cfecbce246 (patch)
tree79bb49c766c27fc5be98195ba2ab25afb75ddc0c /kernel
parent34ffa4de405d053ef4b53d58e1437f2e82d152b1 (diff)
downloadkernel-74e471800380573af6d63b2ad1ba95cfecbce246.tar.xz
kernel-74e471800380573af6d63b2ad1ba95cfecbce246.zip
kernel: initial fs driver system_error integration
Diffstat (limited to 'kernel')
-rw-r--r--kernel/kernel/filesystem/devfs/filesystem.cpp20
-rw-r--r--kernel/kernel/filesystem/devfs/filesystem.hpp7
-rw-r--r--kernel/kernel/filesystem/devfs/filesystem.tests.cpp36
-rw-r--r--kernel/kernel/filesystem/ext2/error.hpp96
-rw-r--r--kernel/kernel/filesystem/ext2/filesystem.cpp50
-rw-r--r--kernel/kernel/filesystem/ext2/filesystem.hpp17
-rw-r--r--kernel/kernel/filesystem/ext2/filesystem.tests.cpp34
-rw-r--r--kernel/kernel/filesystem/ext2/inode.cpp4
-rw-r--r--kernel/kernel/filesystem/ext2/inode.tests.cpp26
-rw-r--r--kernel/kernel/filesystem/filesystem.cpp13
-rw-r--r--kernel/kernel/filesystem/filesystem.hpp24
-rw-r--r--kernel/kernel/filesystem/rootfs/filesystem.cpp10
-rw-r--r--kernel/kernel/filesystem/rootfs/filesystem.hpp7
-rw-r--r--kernel/kernel/filesystem/rootfs/filesystem.tests.cpp14
-rw-r--r--kernel/kernel/filesystem/vfs.cpp16
-rw-r--r--kernel/kernel/test_support/filesystem/filesystem.cpp4
-rw-r--r--kernel/kernel/test_support/filesystem/filesystem.hpp4
17 files changed, 258 insertions, 124 deletions
diff --git a/kernel/kernel/filesystem/devfs/filesystem.cpp b/kernel/kernel/filesystem/devfs/filesystem.cpp
index 3b1da25c..226102ba 100644
--- a/kernel/kernel/filesystem/devfs/filesystem.cpp
+++ b/kernel/kernel/filesystem/devfs/filesystem.cpp
@@ -4,14 +4,17 @@
#include <kernel/devices/storage/management.hpp>
#include <kernel/filesystem/devfs/inode.hpp>
#include <kernel/filesystem/device_inode.hpp>
+#include <kernel/filesystem/error.hpp>
#include <kernel/filesystem/inode.hpp>
#include <kernel/filesystem/type.hpp>
#include <kapi/devices/device.hpp>
#include <kstd/memory.hpp>
+#include <kstd/system_error.hpp>
#include <algorithm>
+#include <expected>
#include <string_view>
namespace kernel::filesystem::devfs
@@ -37,25 +40,25 @@ namespace kernel::filesystem::devfs
[[gnu::used]]
constexpr auto registration = type_registration<type>{};
- auto filesystem::mount(kstd::shared_ptr<kernel::filesystem::inode> const &) -> operation_result
+ auto filesystem::mount(kstd::shared_ptr<kernel::filesystem::inode> const &) -> std::expected<void, kstd::error_code>
{
m_root_inode = kstd::make_shared<inode>();
build_device_inode_table();
- return operation_result::success;
+ return {};
}
auto filesystem::lookup(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name) const
- -> kstd::shared_ptr<kernel::filesystem::inode>
+ -> std::expected<kstd::shared_ptr<kernel::filesystem::inode>, kstd::error_code>
{
if (!parent || !parent->is_directory())
{
- return nullptr;
+ return std::unexpected{make_error_code(kstd::errc::invalid_argument)};
}
if (parent.get() != m_root_inode.get())
{
- return nullptr;
+ return std::unexpected{make_error_code(kstd::errc::invalid_argument)};
}
auto it = std::ranges::find_if(m_inodes, [&](auto const & dev_node) {
@@ -65,7 +68,12 @@ namespace kernel::filesystem::devfs
}
return false;
});
- return (it != m_inodes.end()) ? *it : nullptr;
+ if (it != m_inodes.end())
+ {
+ return *it;
+ }
+
+ return std::unexpected{make_error_code(vfs_errc::non_existent_path)};
}
auto filesystem::build_device_inode_table() -> void
diff --git a/kernel/kernel/filesystem/devfs/filesystem.hpp b/kernel/kernel/filesystem/devfs/filesystem.hpp
index 083d248c..e96790b8 100644
--- a/kernel/kernel/filesystem/devfs/filesystem.hpp
+++ b/kernel/kernel/filesystem/devfs/filesystem.hpp
@@ -6,8 +6,10 @@
#include <kernel/filesystem/inode.hpp>
#include <kstd/memory.hpp>
+#include <kstd/system_error.hpp>
#include <kstd/vector.hpp>
+#include <expected>
#include <string_view>
namespace kernel::filesystem::devfs
@@ -25,7 +27,8 @@ namespace kernel::filesystem::devfs
@param backing_inode Backing inode passed by the vfs (not required by devfs).
@return The result of the mount operation.
*/
- auto mount(kstd::shared_ptr<kernel::filesystem::inode> const & backing_inode) -> operation_result override;
+ auto mount(kstd::shared_ptr<kernel::filesystem::inode> const & backing_inode)
+ -> std::expected<void, kstd::error_code> override;
/**
@brief Looks up an inode by @p name within a @p parent directory.
@@ -34,7 +37,7 @@ namespace kernel::filesystem::devfs
@return A pointer to the found inode, or a null pointer if not found.
*/
[[nodiscard]] auto lookup(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name) const
- -> kstd::shared_ptr<kernel::filesystem::inode> override;
+ -> std::expected<kstd::shared_ptr<kernel::filesystem::inode>, kstd::error_code> override;
private:
auto build_device_inode_table() -> void;
diff --git a/kernel/kernel/filesystem/devfs/filesystem.tests.cpp b/kernel/kernel/filesystem/devfs/filesystem.tests.cpp
index 36cb4117..d5028231 100644
--- a/kernel/kernel/filesystem/devfs/filesystem.tests.cpp
+++ b/kernel/kernel/filesystem/devfs/filesystem.tests.cpp
@@ -17,40 +17,40 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture,
THEN("mount succeeds")
{
- REQUIRE(result == kernel::filesystem::filesystem::operation_result::success);
- REQUIRE(fs.root_inode() != nullptr);
+ REQUIRE(result);
+ REQUIRE(fs.root_inode());
}
THEN("lookup on root finds ram0 device inode")
{
auto inode = fs.lookup(fs.root_inode(), "ram0");
- REQUIRE(inode != nullptr);
- REQUIRE(inode->is_device());
+ REQUIRE(inode);
+ REQUIRE(inode.value()->is_device());
}
- THEN("lookup of an unknown device returns null")
+ THEN("lookup of an unknown device returns error")
{
auto inode = fs.lookup(fs.root_inode(), "ram99");
- REQUIRE(inode == nullptr);
+ REQUIRE(!inode);
}
- THEN("lookup with wrong parent returns null")
+ THEN("lookup with wrong parent returns error")
{
auto other_fs = kernel::filesystem::devfs::filesystem{};
- other_fs.mount(nullptr);
+ CHECK(other_fs.mount(nullptr));
auto inode = fs.lookup(other_fs.root_inode(), "ram0");
- REQUIRE(inode == nullptr);
+ REQUIRE(!inode);
}
- THEN("lookup with a non-directory parent returns null")
+ THEN("lookup with a non-directory parent returns error")
{
auto non_directory_inode = fs.lookup(fs.root_inode(), "ram0");
- REQUIRE(non_directory_inode != nullptr);
- REQUIRE_FALSE(non_directory_inode->is_directory());
+ REQUIRE(non_directory_inode);
+ REQUIRE_FALSE(non_directory_inode.value()->is_directory());
- auto result = fs.lookup(non_directory_inode, "anything");
- REQUIRE(result == nullptr);
+ auto result = fs.lookup(*non_directory_inode, "anything");
+ REQUIRE(!result);
}
}
@@ -60,13 +60,13 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture,
auto fs = kernel::filesystem::devfs::filesystem{};
auto result = fs.mount(nullptr);
- REQUIRE(result == kernel::filesystem::filesystem::operation_result::success);
+ REQUIRE(result);
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);
+ REQUIRE(fs.lookup(fs.root_inode(), "ram0"));
+ REQUIRE(fs.lookup(fs.root_inode(), "ram16"));
+ REQUIRE(fs.lookup(fs.root_inode(), "ram32"));
}
}
}
diff --git a/kernel/kernel/filesystem/ext2/error.hpp b/kernel/kernel/filesystem/ext2/error.hpp
new file mode 100644
index 00000000..e42b714b
--- /dev/null
+++ b/kernel/kernel/filesystem/ext2/error.hpp
@@ -0,0 +1,96 @@
+#ifndef TEACHOS_KERNEL_FILESYSTEM_EXT2_ERROR_HPP
+#define TEACHOS_KERNEL_FILESYSTEM_EXT2_ERROR_HPP
+
+#include <kernel/filesystem/error.hpp>
+
+#include <kstd/system_error.hpp>
+
+#include <string_view>
+#include <type_traits>
+
+namespace kernel::filesystem::ext2
+{
+
+ enum struct ext2_errc : int
+ {
+ invalid_magic_number = 1,
+ invalid_root_inode,
+ invalid_block_group_index,
+ invalid_block_index,
+ invalid_block_number,
+ };
+
+ namespace detail
+ {
+ struct ext2_category_t final : kstd::error_category
+ {
+ [[nodiscard]] constexpr auto name() const noexcept -> std::string_view override
+ {
+ return "ext2";
+ }
+
+ [[nodiscard]] constexpr auto message(int value) const noexcept -> std::string_view override
+ {
+ switch (static_cast<ext2_errc>(value))
+ {
+ case ext2_errc::invalid_magic_number:
+ return "invalid filesystem magic";
+ case ext2_errc::invalid_root_inode:
+ return "invalid root inode";
+ case ext2_errc::invalid_block_group_index:
+ return "block group index out of bounds";
+ case ext2_errc::invalid_block_index:
+ return "block index out of bounds";
+ case ext2_errc::invalid_block_number:
+ return "block index out of bounds";
+ default:
+ return "unknown ext2 error";
+ };
+ }
+
+ [[nodiscard]] constexpr auto equivalent(int code, kstd::error_condition const & condition) const noexcept
+ -> bool override
+ {
+ switch (static_cast<ext2_errc>(code))
+ {
+ case ext2_errc::invalid_magic_number:
+ case ext2_errc::invalid_root_inode:
+ case ext2_errc::invalid_block_group_index:
+ case ext2_errc::invalid_block_index:
+ case ext2_errc::invalid_block_number:
+ if (condition.category() == kernel::filesystem::vfs_category())
+ {
+ return condition.value() == static_cast<int>(kernel::filesystem::vfs_errc::invalid_filesystem);
+ }
+ else if (condition.category() == kstd::generic_category())
+ {
+ return condition.value() == static_cast<int>(kstd::errc::io_error);
+ }
+ }
+
+ return kstd::error_category::equivalent(code, condition);
+ }
+ } constexpr inline ext2_category_instance{};
+ } // namespace detail
+
+ [[nodiscard]] constexpr auto inline ext2_category() noexcept -> kstd::error_category const &
+ {
+ return detail::ext2_category_instance;
+ }
+
+ [[nodiscard]] constexpr auto inline make_error_code(ext2_errc error) noexcept -> kstd::error_code
+ {
+ return {static_cast<int>(error), ext2_category()};
+ }
+
+} // namespace kernel::filesystem::ext2
+
+namespace kstd
+{
+ template<>
+ struct is_error_code_enum<kernel::filesystem::ext2::ext2_errc> : std::true_type
+ {
+ };
+} // namespace kstd
+
+#endif
diff --git a/kernel/kernel/filesystem/ext2/filesystem.cpp b/kernel/kernel/filesystem/ext2/filesystem.cpp
index 82c6441d..fd77a0a2 100644
--- a/kernel/kernel/filesystem/ext2/filesystem.cpp
+++ b/kernel/kernel/filesystem/ext2/filesystem.cpp
@@ -1,6 +1,8 @@
#include <kernel/filesystem/ext2/filesystem.hpp>
+#include <kernel/filesystem/error.hpp>
#include <kernel/filesystem/ext2/block_group_descriptor.hpp>
+#include <kernel/filesystem/ext2/error.hpp>
#include <kernel/filesystem/ext2/inode.hpp>
#include <kernel/filesystem/ext2/linked_directory_entry.hpp>
#include <kernel/filesystem/ext2/superblock.hpp>
@@ -9,13 +11,15 @@
#include <kernel/filesystem/type.hpp>
#include <kstd/memory.hpp>
-#include <kstd/unikstd.h>
+#include <kstd/system_error.hpp>
#include <kstd/vector.hpp>
#include <array>
#include <cstddef>
#include <cstdint>
+#include <expected>
#include <string_view>
+#include <tuple>
namespace kernel::filesystem::ext2
{
@@ -41,15 +45,16 @@ namespace kernel::filesystem::ext2
[[gnu::used]]
constexpr auto registration = type_registration<type>{};
- auto filesystem::mount(kstd::shared_ptr<kernel::filesystem::inode> const & backing_inode) -> operation_result
+ auto filesystem::mount(kstd::shared_ptr<kernel::filesystem::inode> const & backing_inode)
+ -> std::expected<void, kstd::error_code>
{
- kernel::filesystem::filesystem::mount(backing_inode);
+ std::ignore = kernel::filesystem::filesystem::mount(backing_inode);
m_backing_inode->read(&m_superblock, constants::superblock_offset, sizeof(m_superblock));
if (m_superblock.magic != constants::magic_number)
{
- return operation_result::invalid_magic_number;
+ return std::unexpected{make_error_code(ext2_errc::invalid_magic_number)};
}
auto const blocks_per_group = m_superblock.blocks_per_group;
@@ -60,36 +65,41 @@ namespace kernel::filesystem::ext2
m_backing_inode->read(m_block_group_descriptors.data(), block_group_descriptor_table_offset(),
num_block_groups * sizeof(block_group_descriptor));
- m_root_inode = read_inode(constants::root_inode_number);
+ if (auto root_inode = read_inode(constants::root_inode_number))
+ {
+ m_root_inode = root_inode.value();
+ }
if (!m_root_inode || !m_root_inode->is_directory())
{
- return operation_result::invalid_root_inode;
+ return std::unexpected{make_error_code(ext2_errc::invalid_root_inode)};
}
- return operation_result::success;
+
+ return {};
}
auto filesystem::lookup(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name) const
- -> kstd::shared_ptr<kernel::filesystem::inode>
+ -> std::expected<kstd::shared_ptr<kernel::filesystem::inode>, kstd::error_code>
{
if (!parent || !parent->is_directory())
{
- return nullptr;
+ return std::unexpected{make_error_code(kstd::errc::invalid_argument)};
}
auto * ext2_parent = static_cast<inode *>(parent.get());
- if (!ext2_parent)
- {
- return nullptr;
- }
-
auto const & inode_data = ext2_parent->data();
kstd::vector<uint8_t> buffer(block_size());
for (uint32_t i = 0; i < inode_block_count(inode_data); ++i)
{
auto const global_block_number = map_inode_block_index_to_global_block_number(i, inode_data);
- auto const block_offset = global_block_number * block_size();
+
+ if (!global_block_number)
+ {
+ return std::unexpected{make_error_code(ext2_errc::invalid_block_number)};
+ }
+
+ auto const block_offset = global_block_number.value() * block_size();
m_backing_inode->read(buffer.data(), block_offset, block_size());
auto const * entry = reinterpret_cast<linked_directory_entry const *>(buffer.data());
@@ -108,10 +118,10 @@ namespace kernel::filesystem::ext2
}
}
- return nullptr;
+ return std::unexpected{make_error_code(vfs_errc::non_existent_path)};
}
- auto filesystem::read_inode(uint32_t inode_number) const -> kstd::shared_ptr<inode>
+ auto filesystem::read_inode(uint32_t inode_number) const -> std::expected<kstd::shared_ptr<inode>, kstd::error_code>
{
auto const inodes_per_group = m_superblock.inodes_per_group;
auto const block_group_index = (inode_number - 1) / inodes_per_group;
@@ -119,7 +129,7 @@ namespace kernel::filesystem::ext2
if (block_group_index >= m_block_group_descriptors.size())
{
- return nullptr;
+ return std::unexpected{make_error_code(ext2_errc::invalid_block_group_index)};
}
auto const & block_group_descriptor = m_block_group_descriptors.at(block_group_index);
@@ -143,7 +153,7 @@ namespace kernel::filesystem::ext2
}
auto filesystem::map_inode_block_index_to_global_block_number(size_t inode_block_index, inode_data data) const
- -> kstd::ssize_t
+ -> std::expected<std::size_t, kstd::error_code>
{
if (inode_block_index < constants::direct_block_count)
{
@@ -186,7 +196,7 @@ namespace kernel::filesystem::ext2
return block_number;
}
- return -1;
+ return std::unexpected{make_error_code(ext2_errc::invalid_block_index)};
}
auto filesystem::read_block_number_at_index(uint32_t block_number, size_t index) const -> uint32_t
diff --git a/kernel/kernel/filesystem/ext2/filesystem.hpp b/kernel/kernel/filesystem/ext2/filesystem.hpp
index fc2ba7df..da7ae64e 100644
--- a/kernel/kernel/filesystem/ext2/filesystem.hpp
+++ b/kernel/kernel/filesystem/ext2/filesystem.hpp
@@ -8,12 +8,13 @@
#include <kernel/filesystem/inode.hpp>
#include <kstd/memory.hpp>
-#include <kstd/unikstd.h>
+#include <kstd/system_error.hpp>
#include <kstd/vector.hpp>
#include <array>
#include <cstddef>
#include <cstdint>
+#include <expected>
#include <string_view>
namespace kernel::filesystem::ext2
@@ -47,14 +48,15 @@ namespace kernel::filesystem::ext2
@brief A filesystem implementation for the ext2 filesystem format. This class provides methods for mounting an ext2
filesystem, and looking up inodes.
*/
- struct filesystem : kernel::filesystem::filesystem
+ struct filesystem final : kernel::filesystem::filesystem
{
/**
@brief Initializes the ext2 filesystem with the given @p backing_inode.
@param backing_inode The backing inode to mount.
@return The result of the mount operation.
*/
- auto mount(kstd::shared_ptr<kernel::filesystem::inode> const & backing_inode) -> operation_result override;
+ auto mount(kstd::shared_ptr<kernel::filesystem::inode> const & backing_inode)
+ -> std::expected<void, kstd::error_code> override;
/**
@brief Looks up an inode by @p name within a @p parent directory.
@@ -63,7 +65,7 @@ namespace kernel::filesystem::ext2
@return A pointer to the found inode, or a null pointer if not found.
*/
[[nodiscard]] auto lookup(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name) const
- -> kstd::shared_ptr<kernel::filesystem::inode> override;
+ -> std::expected<kstd::shared_ptr<kernel::filesystem::inode>, kstd::error_code> override;
/**
@brief Gets the size of a block in the filesystem.
@@ -81,10 +83,10 @@ namespace kernel::filesystem::ext2
@brief Maps an inode block index to a global block number.
@param inode_block_index The index of the block within the inode.
@param data The inode data.
- @return The global block number.
+ @return The global block number on success, an error otherwise.
*/
[[nodiscard]] auto map_inode_block_index_to_global_block_number(size_t inode_block_index, inode_data data) const
- -> kstd::ssize_t;
+ -> std::expected<std::size_t, kstd::error_code>;
private:
struct indirect_level
@@ -95,7 +97,8 @@ namespace kernel::filesystem::ext2
[[nodiscard]] auto indirect_levels() const -> std::array<indirect_level, 3>;
- [[nodiscard]] auto read_inode(uint32_t inode_number) const -> kstd::shared_ptr<kernel::filesystem::ext2::inode>;
+ [[nodiscard]] auto read_inode(uint32_t inode_number) const
+ -> std::expected<kstd::shared_ptr<inode>, kstd::error_code>;
[[nodiscard]] auto read_block_number_at_index(uint32_t block_number, size_t index) const -> uint32_t;
[[nodiscard]] auto inode_size() const -> uint16_t;
diff --git a/kernel/kernel/filesystem/ext2/filesystem.tests.cpp b/kernel/kernel/filesystem/ext2/filesystem.tests.cpp
index ed3ac1ac..9a677981 100644
--- a/kernel/kernel/filesystem/ext2/filesystem.tests.cpp
+++ b/kernel/kernel/filesystem/ext2/filesystem.tests.cpp
@@ -2,6 +2,7 @@
#include <kernel/devices/storage/management.hpp>
#include <kernel/filesystem/device_inode.hpp>
+#include <kernel/filesystem/ext2/error.hpp>
#include <kernel/filesystem/ext2/inode.hpp>
#include <kernel/filesystem/filesystem.hpp>
#include <kernel/test_support/devices/block_device.hpp>
@@ -33,7 +34,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture,
auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(boot_device);
auto fs = kernel::filesystem::ext2::filesystem{};
- REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success);
+ REQUIRE(fs.mount(dev_inode));
THEN("the root inode is available and is a directory")
{
@@ -44,25 +45,25 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture,
THEN("lookup resolves known entries from the image")
{
auto information = fs.lookup(fs.root_inode(), "information");
- REQUIRE(information != nullptr);
- REQUIRE(information->is_directory());
+ REQUIRE(information);
+ REQUIRE(information.value()->is_directory());
- auto info_1 = fs.lookup(information, "info_1.txt");
- REQUIRE(info_1 != nullptr);
- REQUIRE(info_1->is_regular());
+ auto info_1 = fs.lookup(*information, "info_1.txt");
+ REQUIRE(info_1);
+ REQUIRE(info_1.value()->is_regular());
}
THEN("lookup returns null for invalid inputs")
{
- REQUIRE(fs.lookup(nullptr, "information") == nullptr);
+ REQUIRE(!fs.lookup(nullptr, "information"));
auto information = fs.lookup(fs.root_inode(), "information");
- REQUIRE(information != nullptr);
- auto info_1 = fs.lookup(information, "info_1.txt");
- REQUIRE(info_1 != nullptr);
+ REQUIRE(information);
+ auto info_1 = fs.lookup(*information, "info_1.txt");
+ REQUIRE(info_1);
- REQUIRE(fs.lookup(info_1, "anything") == nullptr);
- REQUIRE(fs.lookup(fs.root_inode(), "does_not_exist") == nullptr);
+ REQUIRE(!fs.lookup(*info_1, "anything"));
+ REQUIRE(!fs.lookup(fs.root_inode(), "does_not_exist"));
}
}
}
@@ -81,7 +82,8 @@ SCENARIO("Ext2 filesystem rejects invalid magic", "[filesystem][ext2][filesystem
THEN("mount fails with invalid_magic_number")
{
- REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::invalid_magic_number);
+ REQUIRE(fs.mount(dev_inode).error() ==
+ make_error_code(kernel::filesystem::ext2::ext2_errc::invalid_magic_number));
}
}
}
@@ -100,7 +102,7 @@ SCENARIO("Ext2 block mapping includes direct and all indirect levels", "[filesys
auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(device);
auto fs = kernel::filesystem::ext2::filesystem{};
- REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success);
+ REQUIRE(fs.mount(dev_inode));
auto inode_data = kernel::filesystem::ext2::inode_data{};
inode_data.block[0] = 7;
@@ -130,10 +132,10 @@ SCENARIO("Ext2 block mapping includes direct and all indirect levels", "[filesys
REQUIRE(fs.map_inode_block_index_to_global_block_number(triply_start, inode_data) == 53);
}
- THEN("mapping returns zero for out-of-range indexes")
+ THEN("mapping returns error for out-of-range indexes")
{
auto const beyond_triply = triply_start + numbers_per_block * numbers_per_block * numbers_per_block;
- REQUIRE(fs.map_inode_block_index_to_global_block_number(beyond_triply, inode_data) == -1);
+ REQUIRE(!fs.map_inode_block_index_to_global_block_number(beyond_triply, inode_data));
}
}
}
diff --git a/kernel/kernel/filesystem/ext2/inode.cpp b/kernel/kernel/filesystem/ext2/inode.cpp
index 11f55cb6..23344a7b 100644
--- a/kernel/kernel/filesystem/ext2/inode.cpp
+++ b/kernel/kernel/filesystem/ext2/inode.cpp
@@ -43,7 +43,7 @@ namespace kernel::filesystem::ext2
while (bytes_read < requested_size)
{
auto const block_number = m_filesystem->map_inode_block_index_to_global_block_number(block_index, m_data);
- if (block_number == -1)
+ if (!block_number)
{
break;
}
@@ -56,7 +56,7 @@ namespace kernel::filesystem::ext2
}
else
{
- auto const block_start_offset = block_number * m_filesystem->block_size();
+ auto const block_start_offset = block_number.value() * m_filesystem->block_size();
auto const read_offset = block_start_offset + in_block_offset;
bytes_read += m_filesystem->backing_inode()->read(static_cast<uint8_t *>(buffer) + bytes_read, read_offset,
diff --git a/kernel/kernel/filesystem/ext2/inode.tests.cpp b/kernel/kernel/filesystem/ext2/inode.tests.cpp
index aa21f6ed..325ba956 100644
--- a/kernel/kernel/filesystem/ext2/inode.tests.cpp
+++ b/kernel/kernel/filesystem/ext2/inode.tests.cpp
@@ -97,18 +97,18 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 in
auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(boot_device);
auto fs = kernel::filesystem::ext2::filesystem{};
- REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success);
+ REQUIRE(fs.mount(dev_inode));
auto information = fs.lookup(fs.root_inode(), "information");
- REQUIRE(information != nullptr);
- auto file = fs.lookup(information, "info_1.txt");
- REQUIRE(file != nullptr);
- REQUIRE(file->is_regular());
+ REQUIRE(information);
+ auto file = fs.lookup(*information, "info_1.txt");
+ REQUIRE(file);
+ REQUIRE(file.value()->is_regular());
THEN("reading from offset zero returns expected file prefix")
{
auto buffer = kstd::vector<std::byte>(6);
- auto const bytes_read = file->read(buffer.data(), 0, buffer.size());
+ auto const bytes_read = file.value()->read(buffer.data(), 0, buffer.size());
REQUIRE(bytes_read == 6);
@@ -119,7 +119,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 in
THEN("reading with an offset returns the expected byte")
{
auto buffer = kstd::vector<std::byte>(1);
- auto const bytes_read = file->read(buffer.data(), 5, buffer.size());
+ auto const bytes_read = file.value()->read(buffer.data(), 5, buffer.size());
REQUIRE(bytes_read == 1);
REQUIRE(static_cast<char>(buffer[0]) == '1');
@@ -139,7 +139,7 @@ SCENARIO("Ext2 inode handles zeros in block mappings as file holes", "[filesyste
auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(device);
auto fs = kernel::filesystem::ext2::filesystem{};
- REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success);
+ REQUIRE(fs.mount(dev_inode));
auto data = kernel::filesystem::ext2::inode_data{};
data.block[0] = 30;
@@ -176,7 +176,7 @@ SCENARIO("Ext2 inode handles zeros in block mappings as file holes", "[filesyste
auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(device);
auto fs = kernel::filesystem::ext2::filesystem{};
- REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success);
+ REQUIRE(fs.mount(dev_inode));
auto data = kernel::filesystem::ext2::inode_data{};
data.block[0] = 30;
@@ -221,7 +221,7 @@ SCENARIO("Ext2 inode handles zeros in block mappings as file holes", "[filesyste
auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(device);
auto fs = kernel::filesystem::ext2::filesystem{};
- REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success);
+ REQUIRE(fs.mount(dev_inode));
auto data = kernel::filesystem::ext2::inode_data{};
data.block[12] = 0;
@@ -252,7 +252,7 @@ SCENARIO("Ext2 inode read across block boundaries", "[filesystem][ext2][inode]")
auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(device);
auto fs = kernel::filesystem::ext2::filesystem{};
- REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success);
+ REQUIRE(fs.mount(dev_inode));
auto inode_data = kernel::filesystem::ext2::inode_data{};
inode_data.size = block_size * 2;
@@ -313,7 +313,7 @@ SCENARIO("Ext2 inode get_size() correctly returns size depending on revision lev
auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(device);
auto fs = kernel::filesystem::ext2::filesystem{};
- REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success);
+ REQUIRE(fs.mount(dev_inode));
auto data = kernel::filesystem::ext2::inode_data{};
data.size = 256;
@@ -349,7 +349,7 @@ SCENARIO("Ext2 inode get_size() correctly returns size depending on revision lev
auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(device);
auto fs = kernel::filesystem::ext2::filesystem{};
- REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success);
+ REQUIRE(fs.mount(dev_inode));
auto data = kernel::filesystem::ext2::inode_data{};
data.size = 256;
diff --git a/kernel/kernel/filesystem/filesystem.cpp b/kernel/kernel/filesystem/filesystem.cpp
index f0b7fd28..cb60734f 100644
--- a/kernel/kernel/filesystem/filesystem.cpp
+++ b/kernel/kernel/filesystem/filesystem.cpp
@@ -6,8 +6,10 @@
#include <kapi/system.hpp>
#include <kstd/memory.hpp>
+#include <kstd/system_error.hpp>
#include <array>
+#include <expected>
namespace kernel::filesystem
{
@@ -18,7 +20,8 @@ namespace kernel::filesystem
};
} // namespace
- auto filesystem::probe_and_mount(kstd::shared_ptr<inode> const & backing_inode) -> kstd::shared_ptr<filesystem>
+ auto filesystem::probe_and_mount(kstd::shared_ptr<inode> const & backing_inode)
+ -> std::expected<kstd::shared_ptr<filesystem>, kstd::error_code>
{
if (!backing_inode)
{
@@ -28,16 +31,16 @@ namespace kernel::filesystem
for (auto & factory : filesystem_factories)
{
auto fs = factory();
- if (fs->mount(backing_inode) == operation_result::success)
+ if (fs->mount(backing_inode))
{
return fs;
}
}
- return nullptr;
+ return std::unexpected{make_error_code(kstd::errc::not_supported)};
}
- auto filesystem::mount(kstd::shared_ptr<inode> const & backing_inode) -> operation_result
+ auto filesystem::mount(kstd::shared_ptr<inode> const & backing_inode) -> std::expected<void, kstd::error_code>
{
if (!backing_inode)
{
@@ -45,7 +48,7 @@ namespace kernel::filesystem
}
m_backing_inode = backing_inode;
- return operation_result::success;
+ return {};
}
auto filesystem::root_inode() const -> kstd::shared_ptr<inode> const &
diff --git a/kernel/kernel/filesystem/filesystem.hpp b/kernel/kernel/filesystem/filesystem.hpp
index b818d992..f9521d1f 100644
--- a/kernel/kernel/filesystem/filesystem.hpp
+++ b/kernel/kernel/filesystem/filesystem.hpp
@@ -4,8 +4,10 @@
#include <kernel/filesystem/inode.hpp>
#include <kstd/memory.hpp>
+#include <kstd/system_error.hpp>
#include <kstd/vector.hpp>
+#include <expected>
#include <string_view>
namespace kernel::filesystem
@@ -16,14 +18,6 @@ namespace kernel::filesystem
*/
struct filesystem
{
- enum class operation_result : int
- {
- success = 0,
- invalid_magic_number = -1,
- invalid_root_inode = -2,
- unmount_failed = -3
- };
-
/**
@brief Virtual destructor for the filesystem.
*/
@@ -34,19 +28,19 @@ namespace kernel::filesystem
and returns a pointer to the mounted filesystem instance. This method iterates through known filesystem types and
attempts to initialize it with the backing inode until the mount was successful or all types have been tried.
@param backing_inode The inode to probe and mount.
- @return A pointer to the mounted filesystem instance if successful, or a null pointer if no recognizable filesystem
- is found on the backing inode.
+ @return A pointer to the mounted filesystem instance if successful, an error otherwise.
@warning Panics if @p backing_inode is null.
*/
- auto static probe_and_mount(kstd::shared_ptr<inode> const & backing_inode) -> kstd::shared_ptr<filesystem>;
+ auto static probe_and_mount(kstd::shared_ptr<inode> const & backing_inode)
+ -> std::expected<kstd::shared_ptr<filesystem>, kstd::error_code>;
/**
@brief Initializes the filesystem with the given @p backing_inode.
@param backing_inode The inode to use as the backing inode for the filesystem. (This is typically the inode
representing the block device or another inode which contains the filesystem data.)
- @return The result of the mount operation.
+ @return Nothing on success, and error otherwise.
*/
- virtual auto mount(kstd::shared_ptr<inode> const & backing_inode) -> operation_result;
+ virtual auto mount(kstd::shared_ptr<inode> const & backing_inode) -> std::expected<void, kstd::error_code>;
/**
@brief Looks up a child inode within the given @p parent inode with the specified @p name. This method must be
@@ -54,10 +48,10 @@ namespace kernel::filesystem
finding the requested inode.
@param parent The parent inode.
@param name The name of the child inode to look up.
- @return A pointer to the requested child inode, or a null pointer if not found.
+ @return A pointer to the requested child inode, an error otherwise.
*/
[[nodiscard]] virtual auto lookup(kstd::shared_ptr<inode> const & parent, std::string_view name) const
- -> kstd::shared_ptr<inode> = 0;
+ -> std::expected<kstd::shared_ptr<inode>, kstd::error_code> = 0;
/**
@brief Returns a reference to the root inode of the filesystem.
diff --git a/kernel/kernel/filesystem/rootfs/filesystem.cpp b/kernel/kernel/filesystem/rootfs/filesystem.cpp
index 52c2cec2..06b6d5c9 100644
--- a/kernel/kernel/filesystem/rootfs/filesystem.cpp
+++ b/kernel/kernel/filesystem/rootfs/filesystem.cpp
@@ -6,7 +6,9 @@
#include <kernel/filesystem/type.hpp>
#include <kstd/memory.hpp>
+#include <kstd/system_error.hpp>
+#include <expected>
#include <string_view>
namespace kernel::filesystem::rootfs
@@ -33,15 +35,15 @@ namespace kernel::filesystem::rootfs
[[gnu::used]]
constexpr auto registration = type_registration<type>{};
- auto filesystem::mount(kstd::shared_ptr<kernel::filesystem::inode> const &) -> operation_result
+ auto filesystem::mount(kstd::shared_ptr<kernel::filesystem::inode> const &) -> std::expected<void, kstd::error_code>
{
m_root_inode = kstd::make_shared<inode>();
- return operation_result::success;
+ return {};
}
auto filesystem::lookup(kstd::shared_ptr<kernel::filesystem::inode> const &, std::string_view) const
- -> kstd::shared_ptr<kernel::filesystem::inode>
+ -> std::expected<kstd::shared_ptr<kernel::filesystem::inode>, kstd::error_code>
{
- return nullptr;
+ return std::unexpected{make_error_code(kstd::errc::no_such_file_or_directory)};
}
} // namespace kernel::filesystem::rootfs
diff --git a/kernel/kernel/filesystem/rootfs/filesystem.hpp b/kernel/kernel/filesystem/rootfs/filesystem.hpp
index 5d59486d..e05cc808 100644
--- a/kernel/kernel/filesystem/rootfs/filesystem.hpp
+++ b/kernel/kernel/filesystem/rootfs/filesystem.hpp
@@ -6,8 +6,10 @@
#include <kstd/memory.hpp>
#include <kstd/string.hpp>
+#include <kstd/system_error.hpp>
#include <kstd/vector.hpp>
+#include <expected>
#include <string_view>
namespace kernel::filesystem::rootfs
@@ -25,7 +27,8 @@ namespace kernel::filesystem::rootfs
@param backing_inode The backing inode to mount (not required by rootfs).
@return The result of the mount operation.
*/
- auto mount(kstd::shared_ptr<kernel::filesystem::inode> const & backing_inode) -> operation_result override;
+ auto mount(kstd::shared_ptr<kernel::filesystem::inode> const & backing_inode)
+ -> std::expected<void, kstd::error_code> override;
/**
@brief Looks up an inode by @p name within a @p parent directory.
@@ -34,7 +37,7 @@ namespace kernel::filesystem::rootfs
@return Always returns nullptr.
*/
[[nodiscard]] auto lookup(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name) const
- -> kstd::shared_ptr<kernel::filesystem::inode> override;
+ -> std::expected<kstd::shared_ptr<kernel::filesystem::inode>, kstd::error_code> override;
};
} // namespace kernel::filesystem::rootfs
diff --git a/kernel/kernel/filesystem/rootfs/filesystem.tests.cpp b/kernel/kernel/filesystem/rootfs/filesystem.tests.cpp
index 8f16077a..347502ca 100644
--- a/kernel/kernel/filesystem/rootfs/filesystem.tests.cpp
+++ b/kernel/kernel/filesystem/rootfs/filesystem.tests.cpp
@@ -17,22 +17,22 @@ SCENARIO("Rootfs filesystem mount and lookup", "[filesystem][rootfs][filesystem]
THEN("the filesystem can be mounted successfully")
{
- REQUIRE(result == kernel::filesystem::filesystem::operation_result::success);
- REQUIRE(fs.root_inode() != nullptr);
+ REQUIRE(result);
+ REQUIRE(fs.root_inode());
}
- THEN("looking up a non-existent directory returns null")
+ THEN("looking up a non-existent directory returns an error")
{
auto non_existent_inode_1 = fs.lookup(fs.root_inode(), "");
- REQUIRE(non_existent_inode_1 == nullptr);
+ REQUIRE(!non_existent_inode_1);
auto non_existent_inode_2 = fs.lookup(fs.root_inode(), "nonexistent");
- REQUIRE(non_existent_inode_2 == nullptr);
+ REQUIRE(!non_existent_inode_2);
}
- THEN("looking up with a null parent inode returns null")
+ THEN("looking up with a null parent inode returns an error")
{
auto result = fs.lookup(nullptr, "dev");
- REQUIRE(result == nullptr);
+ REQUIRE(!result);
}
}
}
diff --git a/kernel/kernel/filesystem/vfs.cpp b/kernel/kernel/filesystem/vfs.cpp
index 55c83ca9..7de2b79f 100644
--- a/kernel/kernel/filesystem/vfs.cpp
+++ b/kernel/kernel/filesystem/vfs.cpp
@@ -45,7 +45,10 @@ namespace kernel::filesystem
{
// mount rootfs at /
auto root_fs = kstd::make_shared<rootfs::filesystem>();
- root_fs->mount(nullptr);
+ if (auto result = root_fs->mount(nullptr); !result)
+ {
+ kapi::system::panic("[FILESYSTEM] failed to mount root FS", result.error());
+ }
auto root_fs_root_dentry = kstd::make_shared<dentry>(nullptr, root_fs->root_inode(), "/");
auto root_mount = kstd::make_shared<mount>(nullptr, root_fs_root_dentry, root_fs, nullptr, nullptr);
@@ -53,7 +56,10 @@ namespace kernel::filesystem
// mount devfs at /dev (inside rootfs, temporary, will be shadowed)
auto device_fs = kstd::make_shared<devfs::filesystem>();
- device_fs->mount(nullptr);
+ if (auto result = device_fs->mount(nullptr); !result)
+ {
+ kapi::system::panic("[FILESYSTEM] failed to mount device FS", result.error());
+ }
graft_persistent_device_fs(device_fs);
// mount boot fs at / (shadows rootfs), re-graft devfs
@@ -65,7 +71,7 @@ namespace kernel::filesystem
{
if (auto root_dentry = resolve_path("/"))
{
- do_mount_internal(*root_dentry, root_mount, boot_root_fs, boot_device_mount_context);
+ do_mount_internal(*root_dentry, root_mount, *boot_root_fs, boot_device_mount_context);
graft_persistent_device_fs(device_fs);
}
}
@@ -120,7 +126,7 @@ namespace kernel::filesystem
{
if (auto fs = kernel::filesystem::filesystem::probe_and_mount(source_dentry->get_inode()))
{
- do_mount_internal(mount_point_dentry, mount_context, fs, source_mount_context);
+ do_mount_internal(mount_point_dentry, mount_context, *fs, source_mount_context);
return {};
}
return std::unexpected{make_error_code(vfs_errc::invalid_filesystem)};
@@ -240,7 +246,7 @@ namespace kernel::filesystem
return std::unexpected{make_error_code(vfs_errc::non_existent_path)};
}
- next_dentry = kstd::make_shared<dentry>(current_dentry, found_inode, part);
+ next_dentry = kstd::make_shared<dentry>(current_dentry, *found_inode, part);
current_dentry->add_child(next_dentry);
}
else if (next_dentry->has_flag(dentry::dentry_flags::is_mount_point))
diff --git a/kernel/kernel/test_support/filesystem/filesystem.cpp b/kernel/kernel/test_support/filesystem/filesystem.cpp
index a4ea30bb..38cea2f1 100644
--- a/kernel/kernel/test_support/filesystem/filesystem.cpp
+++ b/kernel/kernel/test_support/filesystem/filesystem.cpp
@@ -4,13 +4,15 @@
#include <kernel/test_support/filesystem/inode.hpp>
#include <kstd/memory.hpp>
+#include <kstd/system_error.hpp>
+#include <expected>
#include <string_view>
namespace kernel::tests::filesystem
{
auto filesystem::lookup(kstd::shared_ptr<kernel::filesystem::inode> const &, std::string_view) const
- -> kstd::shared_ptr<kernel::filesystem::inode>
+ -> std::expected<kstd::shared_ptr<kernel::filesystem::inode>, kstd::error_code>
{
return kstd::make_shared<inode>();
}
diff --git a/kernel/kernel/test_support/filesystem/filesystem.hpp b/kernel/kernel/test_support/filesystem/filesystem.hpp
index 5809bb5e..e6e0f416 100644
--- a/kernel/kernel/test_support/filesystem/filesystem.hpp
+++ b/kernel/kernel/test_support/filesystem/filesystem.hpp
@@ -5,7 +5,9 @@
#include <kernel/filesystem/inode.hpp>
#include <kstd/memory.hpp>
+#include <kstd/system_error.hpp>
+#include <expected>
#include <string_view>
namespace kernel::tests::filesystem
@@ -15,7 +17,7 @@ namespace kernel::tests::filesystem
filesystem() = default;
[[nodiscard]] auto lookup(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name) const
- -> kstd::shared_ptr<kernel::filesystem::inode> override;
+ -> std::expected<kstd::shared_ptr<kernel::filesystem::inode>, kstd::error_code> override;
};
} // namespace kernel::tests::filesystem