diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-07-16 17:30:17 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-07-16 17:30:17 +0200 |
| commit | 604c2a843d95921e0429ebbdd5849174e47a9547 (patch) | |
| tree | 79adbeeb843926c2a60bbc8b645cf073c8a3f1f1 /kernel | |
| parent | a6166befa7421be233ece97e184139870bbc0af7 (diff) | |
| download | kernel-604c2a843d95921e0429ebbdd5849174e47a9547.tar.xz kernel-604c2a843d95921e0429ebbdd5849174e47a9547.zip | |
kernel: begin block device re-architecture work
Diffstat (limited to 'kernel')
40 files changed, 616 insertions, 519 deletions
diff --git a/kernel/kapi/devices/device.cpp b/kernel/kapi/devices/device.cpp index d8cae29c..6ac92e79 100644 --- a/kernel/kapi/devices/device.cpp +++ b/kernel/kapi/devices/device.cpp @@ -31,11 +31,6 @@ namespace kapi::devices return m_name; } - [[nodiscard]] auto device::is_block_device() const -> bool - { - return false; - } - auto device::set_parent(kstd::observer_ptr<bus> parent) -> void { m_parent = parent; diff --git a/kernel/kapi/filesystem.cpp b/kernel/kapi/filesystem.cpp index 982d5df0..b2f94747 100644 --- a/kernel/kapi/filesystem.cpp +++ b/kernel/kapi/filesystem.cpp @@ -7,6 +7,7 @@ #include <kstd/memory.hpp> #include <kstd/result.hpp> #include <kstd/system_error.hpp> +#include <kstd/units.hpp> #include <cstddef> #include <expected> @@ -42,17 +43,18 @@ namespace kapi::filesystem .and_then([=]() { return kernel::filesystem::open_file_table::get().remove_file(file_descriptor); }); } - auto read(size_t file_descriptor, std::span<std::byte> buffer) -> std::expected<std::size_t, kstd::error_code> + auto read(size_t file_descriptor, std::span<std::byte> buffer) -> std::expected<kstd::units::bytes, kstd::error_code> { return kernel::filesystem::open_file_table::get().file(file_descriptor).and_then([=](auto descriptor) { - return descriptor->read(buffer.data(), buffer.size()); + return descriptor->read(buffer.data(), kstd::units::bytes{buffer.size()}); }); } - auto write(size_t file_descriptor, std::span<std::byte const> buffer) -> std::expected<std::size_t, kstd::error_code> + auto write(size_t file_descriptor, std::span<std::byte const> buffer) + -> std::expected<kstd::units::bytes, kstd::error_code> { return kernel::filesystem::open_file_table::get().file(file_descriptor).and_then([=](auto descriptor) { - return descriptor->write(buffer.data(), buffer.size()); + return descriptor->write(buffer.data(), kstd::units::bytes{buffer.size()}); }); } diff --git a/kernel/kapi/filesystem.tests.cpp b/kernel/kapi/filesystem.tests.cpp index ffd8d7f6..90609a6d 100644 --- a/kernel/kapi/filesystem.tests.cpp +++ b/kernel/kapi/filesystem.tests.cpp @@ -13,6 +13,8 @@ #include <string_view> #include <vector> +using namespace kstd::units_literals; + // NOLINTBEGIN (readability-magic-numbers) SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kapi filesystem with real images", @@ -36,7 +38,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap auto bytes_read = kapi::filesystem::read(fd, buffer); auto buffer_as_str = bytes_read.transform( - [&](auto length) { return std::string_view{std::bit_cast<char *>(buffer.data()), length}; }); + [&](auto length) { return std::string_view{std::bit_cast<char *>(buffer.data()), length.value}; }); REQUIRE(buffer_as_str == "info_1"); @@ -51,7 +53,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap auto write_buffer = std::vector<std::byte>{std::byte{'H'}, std::byte{'e'}}; auto const bytes_written = kapi::filesystem::write(*write_fd, write_buffer); - REQUIRE(bytes_written == 2); + REQUIRE(bytes_written == 2_B); auto read_fd = kapi::filesystem::open("/information/info_1.txt"); REQUIRE(read_fd); @@ -59,7 +61,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap auto read_buffer = std::vector<std::byte>(6); auto const bytes_read = kapi::filesystem::read(*read_fd, read_buffer); auto buffer_as_str = bytes_read.transform( - [&](auto length) { return std::string_view{std::bit_cast<char *>(read_buffer.data()), length}; }); + [&](auto length) { return std::string_view{std::bit_cast<char *>(read_buffer.data()), length.value}; }); REQUIRE(buffer_as_str == "Hefo_1"); @@ -74,7 +76,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap auto buffer = std::vector<std::byte>(6); auto bytes_read = kapi::filesystem::read(fd, buffer); auto buffer_as_str = bytes_read.transform( - [&](auto length) { return std::string_view{std::bit_cast<char *>(buffer.data()), length}; }); + [&](auto length) { return std::string_view{std::bit_cast<char *>(buffer.data()), length.value}; }); REQUIRE(buffer_as_str == "info_1"); @@ -88,7 +90,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap auto buffer = std::vector<std::byte>(6); auto bytes_read = kapi::filesystem::read(fd, buffer); auto buffer_as_str = bytes_read.transform( - [&](auto length) { return std::string_view{std::bit_cast<char *>(buffer.data()), length}; }); + [&](auto length) { return std::string_view{std::bit_cast<char *>(buffer.data()), length.value}; }); REQUIRE(buffer_as_str == "info_1"); @@ -104,7 +106,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap auto buffer = std::vector<std::byte>(7); auto bytes_read = kapi::filesystem::read(fd, buffer); auto buffer_as_str = bytes_read.transform( - [&](auto length) { return std::string_view{std::bit_cast<char *>(buffer.data()), length}; }); + [&](auto length) { return std::string_view{std::bit_cast<char *>(buffer.data()), length.value}; }); REQUIRE(buffer_as_str == "sheep_1"); @@ -120,7 +122,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap auto buffer = std::vector<std::byte>(8); auto bytes_read = kapi::filesystem::read(fd, buffer); auto buffer_as_str = bytes_read.transform( - [&](auto length) { return std::string_view{std::bit_cast<char *>(buffer.data()), length}; }); + [&](auto length) { return std::string_view{std::bit_cast<char *>(buffer.data()), length.value}; }); REQUIRE(buffer_as_str == "monkey_1"); diff --git a/kernel/kernel/devices/block_device.cpp b/kernel/kernel/devices/block_device.cpp index a3531121..4d85a520 100644 --- a/kernel/kernel/devices/block_device.cpp +++ b/kernel/kernel/devices/block_device.cpp @@ -1,19 +1,23 @@ #include <kernel/devices/block_device.hpp> +#include <kapi/devices.hpp> #include <kapi/devices/device.hpp> #include <kapi/system.hpp> #include <kstd/string.hpp> +#include <kstd/units.hpp> #include <cstddef> +using namespace kstd::units_literals; + namespace kernel::devices { - block_device::block_device(size_t major, size_t minor, kstd::string const & name, size_t block_size) + block_device::block_device(size_t major, size_t minor, kstd::string const & name, kstd::units::bytes block_size) : kapi::devices::device(major, minor, name) , m_block_size(block_size) { - if (m_block_size == 0) + if (m_block_size == 0_B) { kapi::system::panic("[DEVICES] block_device constructed with zero block size."); } @@ -21,22 +25,32 @@ namespace kernel::devices auto block_device::calculate_transfer(size_t block_index) const -> transfer_info { - size_t const offset = block_index * m_block_size; - size_t const limit = size(); + auto const offset = block_index * m_block_size; + auto const limit = size(); - size_t const available = (offset < limit) ? (limit - offset) : 0; - size_t const to_transfer = (available < m_block_size) ? available : m_block_size; + auto const available = (offset < limit) ? (limit - offset) : 0_B; + auto const to_transfer = (available < m_block_size) ? available : m_block_size; return {offset, to_transfer, m_block_size - to_transfer}; } - auto block_device::block_size() const -> size_t + auto block_device::block_size() const -> kstd::units::bytes { - return m_block_size; + return kstd::units::bytes{m_block_size}; } - auto block_device::capacity() const -> size_t + auto block_device::capacity() const -> kstd::units::bytes { return size(); } + + auto block_device::query_interface(kapi::devices::interface interface) -> void * + { + if (interface == kapi::devices::block_device::id) + { + return static_cast<kapi::devices::block_device *>(this); + } + + return kapi::devices::device::query_interface(interface); + } } // namespace kernel::devices
\ No newline at end of file diff --git a/kernel/kernel/devices/block_device.hpp b/kernel/kernel/devices/block_device.hpp index 31599502..2b3b844c 100644 --- a/kernel/kernel/devices/block_device.hpp +++ b/kernel/kernel/devices/block_device.hpp @@ -1,9 +1,11 @@ #ifndef TEACH_OS_KERNEL_DEVICES_BLOCK_DEVICE_HPP #define TEACH_OS_KERNEL_DEVICES_BLOCK_DEVICE_HPP -#include <kapi/devices/device.hpp> +#include <kapi/devices.hpp> +#include <kstd/result.hpp> #include <kstd/string.hpp> +#include <kstd/units.hpp> #include <cstddef> @@ -12,7 +14,7 @@ namespace kernel::devices /** * @brief Base interface for block-addressable devices. */ - struct block_device : kapi::devices::device + struct block_device : kapi::devices::device, kapi::devices::block_device { /** * @brief Create a block device descriptor. @@ -21,50 +23,19 @@ namespace kernel::devices * @param name Device name. * @param block_size Size of one logical block in bytes. */ - block_device(size_t major, size_t minor, kstd::string const & name, size_t block_size); - - /** - * @brief Read data from the block at @p block_index into @p buffer. - * @param block_index Zero-based block index. - * @param buffer Destination buffer. - * @warning Panics if @p buffer is null. - * @note Reads up to one logical block (see constructor @p block_size). Implementations may perform a partial - * transfer for the final block when fewer than @p block_size bytes remain. - */ - virtual auto read_block(size_t block_index, void * buffer) const -> void = 0; - - /** - * @brief Write data to the block at @p block_index. - * @param block_index Zero-based block index. - * @param buffer Source buffer, must not be null. - * @warning Panics if @p buffer is null. - * @note Writes up to one logical block (see constructor @p block_size). - * Implementations may perform a partial transfer for the final block when - * fewer than @p block_size bytes remain. - */ - virtual auto write_block(size_t block_index, void const * buffer) -> void = 0; + block_device(size_t major, size_t minor, kstd::string const & name, kstd::units::bytes block_size); /** * @brief Return logical block size in bytes. * @return One logical block size in bytes. */ - [[nodiscard]] auto block_size() const -> size_t; + [[nodiscard]] auto block_size() const -> kstd::units::bytes override; /** * @brief Return device capacity in bytes. * @return Total number of addressable bytes. */ - [[nodiscard]] auto capacity() const -> size_t; - - /** - * @brief Override to identify block devices. - * @return true if this device is a block device, false otherwise. - */ - - [[nodiscard]] auto is_block_device() const -> bool override - { - return true; - } + [[nodiscard]] auto capacity() const -> kstd::units::bytes override; protected: /** @@ -72,16 +43,16 @@ namespace kernel::devices */ struct transfer_info { - size_t offset; - size_t to_transfer; - size_t remainder; + kstd::units::bytes offset; + kstd::units::bytes to_transfer; + kstd::units::bytes remainder; }; /** * @brief Return total device size in bytes. * @return Total number of addressable bytes. */ - [[nodiscard]] virtual auto size() const -> size_t = 0; + [[nodiscard]] virtual auto size() const -> kstd::units::bytes = 0; /** * @brief Compute transfer information for @p block_index. @@ -90,7 +61,10 @@ namespace kernel::devices */ [[nodiscard]] auto calculate_transfer(size_t block_index) const -> transfer_info; - size_t m_block_size; + [[nodiscard]] auto query_interface(kapi::devices::interface interface) -> void * override; + + private: + kstd::units::bytes m_block_size; }; } // namespace kernel::devices diff --git a/kernel/kernel/devices/block_device.tests.cpp b/kernel/kernel/devices/block_device.tests.cpp index 98722638..23af74ef 100644 --- a/kernel/kernel/devices/block_device.tests.cpp +++ b/kernel/kernel/devices/block_device.tests.cpp @@ -5,20 +5,21 @@ #include <kstd/memory.hpp> #include <kstd/print.hpp> #include <kstd/string.hpp> +#include <kstd/units.hpp> #include <kstd/vector.hpp> #include <catch2/catch_test_macros.hpp> -#include <cstddef> +using namespace kstd::units_literals; SCENARIO("Block device construction", "[devices][block_device]") { GIVEN("parameters for a block device") { - size_t major = 1; - size_t minor = 0; - kstd::string name = "test_block_device"; - size_t block_size = 512; + auto major = 1uz; + auto minor = 0uz; + auto name = "test_block_device"; + auto block_size = 512_B; WHEN("constructing a block device") { @@ -31,7 +32,7 @@ SCENARIO("Block device construction", "[devices][block_device]") REQUIRE(device->minor() == minor); REQUIRE(device->name() == name); REQUIRE(device->block_size() == block_size); - REQUIRE(device->capacity() == 3 * 512); + REQUIRE(device->capacity() == 3 * 512_B); } } @@ -39,7 +40,7 @@ SCENARIO("Block device construction", "[devices][block_device]") { THEN("the constructor panics") { - REQUIRE_THROWS_AS((kernel::tests::devices::block_device(major, minor, name, 0)), kernel::tests::cpu::halt); + REQUIRE_THROWS_AS((kernel::tests::devices::block_device(major, minor, name, 0_B)), kernel::tests::cpu::halt); } } } diff --git a/kernel/kernel/devices/block_device_utils.cpp b/kernel/kernel/devices/block_device_utils.cpp index 68a0a306..1fefd034 100644 --- a/kernel/kernel/devices/block_device_utils.cpp +++ b/kernel/kernel/devices/block_device_utils.cpp @@ -1,63 +1,72 @@ #include <kernel/devices/block_device_utils.hpp> -#include <kernel/devices/block_device.hpp> - +#include <kapi/devices.hpp> #include <kapi/devices/device.hpp> #include <kapi/system.hpp> #include <kstd/cstring.hpp> #include <kstd/memory.hpp> +#include <kstd/result.hpp> +#include <kstd/units.hpp> #include <kstd/vector.hpp> #include <algorithm> #include <cstddef> +using namespace kstd::units_literals; + namespace kernel::devices::block_device_utils { - using block_op = void (*)(size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, - std::byte * scratch, void * buffer); + using block_op = kstd::result<kstd::units::bytes> (*)(size_t idx, kstd::units::bytes off, kstd::units::bytes len, + kstd::units::bytes done, kapi::devices::block_device * device, + std::byte * scratch, void * buffer); - auto process_blocks(kstd::shared_ptr<kapi::devices::device> const & device, size_t offset, size_t size, void * buffer, - block_op op) -> size_t + auto process_blocks(kstd::shared_ptr<kapi::devices::device> const & device, kstd::units::bytes offset, + kstd::units::bytes size, void * buffer, block_op op) -> kstd::result<kstd::units::bytes> { if (buffer == nullptr) { kapi::system::panic("[FILESYSTEM] device_file::process_blocks called with null buffer."); } - if (size == 0) + if (size == 0_B) { - return 0; + return 0_B; } - if (!device->is_block_device()) + if (!device->is_a<kapi::devices::block_device>()) { kapi::system::panic("[FILESYSTEM] device_file: expected block_device."); } - auto * block_dev = static_cast<devices::block_device *>(device.get()); + auto * block_dev = device->as<kapi::devices::block_device>(); - size_t const block_size = block_dev->block_size(); - size_t const capacity = block_dev->capacity(); + auto const block_size = block_dev->block_size(); + auto const capacity = block_dev->capacity(); if (offset >= capacity) { - return 0; + return 0_B; } - size_t const total_to_process = std::min(size, capacity - offset); + auto const total_to_process = std::min(size, capacity - offset); - kstd::vector<std::byte> scratch_buffer{block_size}; - auto processed = 0uz; + kstd::vector<std::byte> scratch_buffer{block_size.value}; + auto processed = 0_B; while (processed < total_to_process) { - size_t const absolute_offset = offset + processed; - size_t const block_index = absolute_offset / block_size; - size_t const in_block_offset = absolute_offset % block_size; - size_t const chunk_size = std::min(total_to_process - processed, block_size - in_block_offset); - - op(block_index, in_block_offset, chunk_size, processed, block_dev, scratch_buffer.data(), buffer); + auto const absolute_offset = offset + processed; + auto const block_index = absolute_offset / block_size; + auto const in_block_offset = absolute_offset % block_size; + auto const chunk_size = std::min(total_to_process - processed, block_size - in_block_offset); + + if (auto result = + op(block_index, in_block_offset, chunk_size, processed, block_dev, scratch_buffer.data(), buffer); + !result) + { + return result; + } processed += chunk_size; } @@ -65,40 +74,46 @@ namespace kernel::devices::block_device_utils return processed; } - auto read(kstd::shared_ptr<kapi::devices::device> const & device, void * buffer, size_t offset, size_t size) -> size_t + auto read(kstd::shared_ptr<kapi::devices::device> const & device, void * buffer, kstd::units::bytes offset, + kstd::units::bytes size) -> kstd::result<kstd::units::bytes> { return process_blocks(device, offset, size, buffer, - [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, - std::byte * scratch, void * buffer) { + [](size_t idx, kstd::units::bytes off, kstd::units::bytes len, kstd::units::bytes done, + kapi::devices::block_device * device, std::byte * scratch, void * buffer) { auto * out = static_cast<std::byte *>(buffer); - if (off == 0 && len == device->block_size()) + if (off == 0_B && len == device->block_size()) { - device->read_block(idx, out + done); + return device->read_block(idx, out + done); } else { - device->read_block(idx, scratch); - kstd::libc::memcpy(out + done, scratch + off, len); + auto result = device->read_block(idx, scratch); + if (result) + { + kstd::libc::memcpy(out + done, scratch + off, len.value); + } + return result; } }); } - auto write(kstd::shared_ptr<kapi::devices::device> const & device, void const * buffer, size_t offset, size_t size) - -> size_t + auto write(kstd::shared_ptr<kapi::devices::device> const & device, void const * buffer, kstd::units::bytes offset, + kstd::units::bytes size) -> kstd::result<kstd::units::bytes> { return process_blocks(device, offset, size, const_cast<void *>(buffer), - [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, - std::byte * scratch, void * buffer) { + [](size_t idx, kstd::units::bytes off, kstd::units::bytes len, kstd::units::bytes done, + kapi::devices::block_device * device, std::byte * scratch, void * buffer) { auto const * in = static_cast<std::byte const *>(buffer); - if (off == 0 && len == device->block_size()) + if (off == 0_B && len == device->block_size()) { - device->write_block(idx, in + done); + return device->write_block(idx, in + done); } else { - device->read_block(idx, scratch); - kstd::libc::memcpy(scratch + off, in + done, len); - device->write_block(idx, scratch); + return device->read_block(idx, scratch).and_then([&](auto) { + kstd::libc::memcpy(scratch + off, in + done, len.value); + return device->write_block(idx, scratch); + }); } }); } diff --git a/kernel/kernel/devices/block_device_utils.hpp b/kernel/kernel/devices/block_device_utils.hpp index 88e23347..6b626180 100644 --- a/kernel/kernel/devices/block_device_utils.hpp +++ b/kernel/kernel/devices/block_device_utils.hpp @@ -4,8 +4,8 @@ #include <kapi/devices/device.hpp> #include <kstd/memory.hpp> - -#include <cstddef> +#include <kstd/result.hpp> +#include <kstd/units.hpp> namespace kernel::devices::block_device_utils { @@ -25,8 +25,8 @@ namespace kernel::devices::block_device_utils @param size The number of bytes to read. @return The number of bytes actually read, which may be less than the requested size. */ - auto read(kstd::shared_ptr<kapi::devices::device> const & device, void * buffer, size_t offset, size_t size) - -> size_t; + auto read(kstd::shared_ptr<kapi::devices::device> const & device, void * buffer, kstd::units::bytes offset, + kstd::units::bytes size) -> kstd::result<kstd::units::bytes>; /** @brief Writes data from a @p buffer to a @p device, starting at a specific @p offset and for a given @p size. @@ -37,8 +37,8 @@ namespace kernel::devices::block_device_utils @param size The number of bytes to write. @return The number of bytes actually written, which may be less than the requested size. */ - auto write(kstd::shared_ptr<kapi::devices::device> const & device, void const * buffer, size_t offset, size_t size) - -> size_t; + auto write(kstd::shared_ptr<kapi::devices::device> const & device, void const * buffer, kstd::units::bytes offset, + kstd::units::bytes size) -> kstd::result<kstd::units::bytes>; } // namespace kernel::devices::block_device_utils #endif
\ No newline at end of file diff --git a/kernel/kernel/devices/block_device_utils.tests.cpp b/kernel/kernel/devices/block_device_utils.tests.cpp index c8c4acfb..40c52948 100644 --- a/kernel/kernel/devices/block_device_utils.tests.cpp +++ b/kernel/kernel/devices/block_device_utils.tests.cpp @@ -6,6 +6,7 @@ #include <kstd/memory.hpp> #include <kstd/print.hpp> +#include <kstd/units.hpp> #include <kstd/vector.hpp> #include <catch2/catch_test_macros.hpp> @@ -13,28 +14,31 @@ #include <cstddef> #include <cstdint> +using namespace kstd::units_literals; + SCENARIO("reading from a block device with block_device_utils", "[devices][block_device_utils]") { GIVEN("a block device with known data") { - auto const block_size = 512; + auto const block_size = 512_B; auto device = kstd::make_shared<kernel::tests::devices::block_device>(0, 0, "test_block_device", block_size); - kstd::vector<uint8_t> block_data(block_size); + kstd::vector<uint8_t> block_data(block_size.value); for (size_t i = 0; i < block_data.size(); ++i) { block_data[i] = static_cast<uint8_t>(i % 256); } - device->write_block(0, block_data.data()); - device->write_block(1, block_data.data()); + CHECK(device->write_block(0, block_data.data())); + CHECK(device->write_block(1, block_data.data())); WHEN("reading from the block device using block_device_utils") { - kstd::vector<uint8_t> read_buffer(block_size); - auto bytes_read = kernel::devices::block_device_utils::read(device, read_buffer.data(), 0, read_buffer.size()); + kstd::vector<uint8_t> read_buffer(block_size.value); + auto bytes_read = kernel::devices::block_device_utils::read(device, read_buffer.data(), 0_B, + kstd::units::bytes{read_buffer.size()}); THEN("the correct number of bytes is read") { - REQUIRE(bytes_read == read_buffer.size()); + REQUIRE(bytes_read == kstd::units::bytes{read_buffer.size()}); } THEN("the data read matches the data written to the block device") @@ -46,16 +50,17 @@ SCENARIO("reading from a block device with block_device_utils", "[devices][block WHEN("reading over block boundaries") { kstd::vector<uint8_t> read_buffer(1024); - auto bytes_read = kernel::devices::block_device_utils::read(device, read_buffer.data(), 256, read_buffer.size()); + auto bytes_read = kernel::devices::block_device_utils::read(device, read_buffer.data(), 256_B, + kstd::units::bytes{read_buffer.size()}); THEN("the correct number of bytes is read") { - REQUIRE(bytes_read == 1.5 * block_size); + REQUIRE(bytes_read == kstd::units::bytes{static_cast<std::size_t>(1.5 * block_size.value)}); } THEN("the data read matches the expected data across block boundaries") { - for (size_t i = 0; i < bytes_read; ++i) + for (size_t i = 0; i < bytes_read.value().value; ++i) { uint8_t expected_value = static_cast<uint8_t>((256 + i) % 256); REQUIRE(read_buffer[i] == expected_value); @@ -65,23 +70,24 @@ SCENARIO("reading from a block device with block_device_utils", "[devices][block WHEN("reading beyond the device capacity") { - kstd::vector<uint8_t> read_buffer(block_size); - auto bytes_read = kernel::devices::block_device_utils::read(device, read_buffer.data(), 1024, read_buffer.size()); + kstd::vector<uint8_t> read_buffer(block_size.value); + auto bytes_read = kernel::devices::block_device_utils::read(device, read_buffer.data(), 1024_B, + kstd::units::bytes{read_buffer.size()}); THEN("no bytes are read") { - REQUIRE(bytes_read == 0); + REQUIRE(bytes_read == 0_B); } } WHEN("reading nothing") { - kstd::vector<uint8_t> read_buffer(block_size); - auto bytes_read = kernel::devices::block_device_utils::read(device, read_buffer.data(), 0, 0); + kstd::vector<uint8_t> read_buffer(block_size.value); + auto bytes_read = kernel::devices::block_device_utils::read(device, read_buffer.data(), 0_B, 0_B); THEN("no bytes are read") { - REQUIRE(bytes_read == 0); + REQUIRE(bytes_read == 0_B); } } @@ -89,7 +95,8 @@ SCENARIO("reading from a block device with block_device_utils", "[devices][block { THEN("the system panics") { - REQUIRE_THROWS_AS(kernel::devices::block_device_utils::read(device, nullptr, 0, 512), kernel::tests::cpu::halt); + REQUIRE_THROWS_AS(kernel::devices::block_device_utils::read(device, nullptr, 0_B, 512_B), + kernel::tests::cpu::halt); } } } @@ -99,56 +106,56 @@ SCENARIO("writing to a block device using block_device_utils", "[devices][block_ { GIVEN("a block device") { - auto const block_size = 512; + auto const block_size = 512_B; auto device = kstd::make_shared<kernel::tests::devices::block_device>(0, 0, "test_block_device", block_size, 2 * block_size); WHEN("writing to the block device using block_device_utils") { - kstd::vector<uint8_t> write_buffer(block_size); + kstd::vector<uint8_t> write_buffer(block_size.value); for (size_t i = 0; i < write_buffer.size(); ++i) { write_buffer[i] = static_cast<uint8_t>(i % 256); } - auto bytes_written = - kernel::devices::block_device_utils::write(device, write_buffer.data(), 0, write_buffer.size()); + auto bytes_written = kernel::devices::block_device_utils::write(device, write_buffer.data(), 0_B, + kstd::units::bytes{write_buffer.size()}); THEN("the correct number of bytes is written") { - REQUIRE(bytes_written == write_buffer.size()); + REQUIRE(bytes_written == kstd::units::bytes{write_buffer.size()}); } THEN("the data written matches the data read back from the block device") { - kstd::vector<uint8_t> read_buffer(block_size); - device->read_block(0, read_buffer.data()); + kstd::vector<uint8_t> read_buffer(block_size.value); + CHECK(device->read_block(0, read_buffer.data())); REQUIRE(read_buffer == write_buffer); } } WHEN("writing over block boundaries") { - kstd::vector<uint8_t> write_buffer(2 * block_size); + kstd::vector<uint8_t> write_buffer(2 * block_size.value); for (size_t i = 0; i < write_buffer.size(); ++i) { write_buffer[i] = static_cast<uint8_t>(i % 256); } - auto bytes_written = - kernel::devices::block_device_utils::write(device, write_buffer.data(), 256, write_buffer.size()); + auto bytes_written = kernel::devices::block_device_utils::write(device, write_buffer.data(), 256_B, + kstd::units::bytes{write_buffer.size()}); THEN("the correct number of bytes is written") { - REQUIRE(bytes_written == 1.5 * block_size); + REQUIRE(bytes_written == kstd::units::bytes{static_cast<std::size_t>(1.5 * block_size.value)}); } THEN("the data written matches the data read back from the block device across block boundaries") { - kstd::vector<uint8_t> read_buffer(2 * block_size); - auto bytes_read = kernel::devices::block_device_utils::read(device, read_buffer.data(), 256, 2 * block_size); + kstd::vector<uint8_t> read_buffer(2 * block_size.value); + auto bytes_read = kernel::devices::block_device_utils::read(device, read_buffer.data(), 256_B, 2 * block_size); - for (size_t i = 0; i < bytes_read; ++i) + for (size_t i = 0; i < bytes_read.value().value; ++i) { REQUIRE(read_buffer[i] == write_buffer[i]); } @@ -157,24 +164,24 @@ SCENARIO("writing to a block device using block_device_utils", "[devices][block_ WHEN("writing beyond the device capacity") { - kstd::vector<uint8_t> write_buffer(block_size); - auto bytes_written = - kernel::devices::block_device_utils::write(device, write_buffer.data(), 1024, write_buffer.size()); + kstd::vector<uint8_t> write_buffer(block_size.value); + auto bytes_written = kernel::devices::block_device_utils::write(device, write_buffer.data(), 1024_B, + kstd::units::bytes{write_buffer.size()}); THEN("no bytes are written") { - REQUIRE(bytes_written == 0); + REQUIRE(bytes_written == 0_B); } } WHEN("writing nothing") { - kstd::vector<uint8_t> write_buffer(block_size); - auto bytes_written = kernel::devices::block_device_utils::write(device, write_buffer.data(), 0, 0); + kstd::vector<uint8_t> write_buffer(block_size.value); + auto bytes_written = kernel::devices::block_device_utils::write(device, write_buffer.data(), 0_B, 0_B); THEN("no bytes are written") { - REQUIRE(bytes_written == 0); + REQUIRE(bytes_written == 0_B); } } @@ -182,7 +189,7 @@ SCENARIO("writing to a block device using block_device_utils", "[devices][block_ { THEN("the system panics") { - REQUIRE_THROWS_AS(kernel::devices::block_device_utils::write(device, nullptr, 0, block_size), + REQUIRE_THROWS_AS(kernel::devices::block_device_utils::write(device, nullptr, 0_B, block_size), kernel::tests::cpu::halt); } } @@ -200,7 +207,8 @@ SCENARIO("block_device_utils with a non-block device", "[devices][block_device_u kstd::vector<uint8_t> read_buffer(512); THEN("the system panics") { - REQUIRE_THROWS_AS(kernel::devices::block_device_utils::read(device, read_buffer.data(), 0, read_buffer.size()), + REQUIRE_THROWS_AS(kernel::devices::block_device_utils::read(device, read_buffer.data(), 0_B, + kstd::units::bytes{read_buffer.size()}), kernel::tests::cpu::halt); } } @@ -210,9 +218,9 @@ SCENARIO("block_device_utils with a non-block device", "[devices][block_device_u kstd::vector<uint8_t> write_buffer(512); THEN("the system panics") { - REQUIRE_THROWS_AS( - kernel::devices::block_device_utils::write(device, write_buffer.data(), 0, write_buffer.size()), - kernel::tests::cpu::halt); + REQUIRE_THROWS_AS(kernel::devices::block_device_utils::write(device, write_buffer.data(), 0_B, + kstd::units::bytes{write_buffer.size()}), + kernel::tests::cpu::halt); } } } diff --git a/kernel/kernel/devices/storage/ram_disk/device.cpp b/kernel/kernel/devices/storage/ram_disk/device.cpp index eff6114d..1e2f2597 100644 --- a/kernel/kernel/devices/storage/ram_disk/device.cpp +++ b/kernel/kernel/devices/storage/ram_disk/device.cpp @@ -7,14 +7,18 @@ #include <kstd/cstring.hpp> #include <kstd/format.hpp> +#include <kstd/result.hpp> +#include <kstd/units.hpp> #include <cstddef> +using namespace kstd::units_literals; + namespace kernel::devices::storage::ram_disk { namespace { - constexpr size_t ram_disk_block_size = 512uz; + constexpr auto ram_disk_block_size = 512_B; } // namespace device::device(kapi::boot_modules::boot_module const & module, size_t major, size_t minor, std::size_t device_index) @@ -27,7 +31,7 @@ namespace kernel::devices::storage::ram_disk return m_boot_module.start_address.raw() != 0 && m_boot_module.size > 0; } - auto device::read_block(size_t block_index, void * buffer) const -> void + auto device::read_block(size_t block_index, void * buffer) const -> kstd::result<kstd::units::bytes> { if (buffer == nullptr) { @@ -36,19 +40,21 @@ namespace kernel::devices::storage::ram_disk auto const info = calculate_transfer(block_index); - if (info.to_transfer > 0) + if (info.to_transfer > 0_B) { auto const src = static_cast<std::byte const *>(m_boot_module.start_address) + info.offset; - kstd::libc::memcpy(buffer, src, info.to_transfer); + kstd::libc::memcpy(buffer, src, info.to_transfer.value); } - if (info.remainder > 0) + if (info.remainder > 0_B) { - kstd::libc::memset(static_cast<std::byte *>(buffer) + info.to_transfer, 0, info.remainder); + kstd::libc::memset(static_cast<std::byte *>(buffer) + info.to_transfer, 0, info.remainder.value); } + + return info.to_transfer; } - auto device::write_block(size_t block_index, void const * buffer) -> void + auto device::write_block(size_t block_index, void const * buffer) -> kstd::result<kstd::units::bytes> { if (buffer == nullptr) { @@ -57,15 +63,17 @@ namespace kernel::devices::storage::ram_disk auto const info = calculate_transfer(block_index); - if (info.to_transfer > 0) + if (info.to_transfer > 0_B) { auto const dest = static_cast<std::byte *>(m_boot_module.start_address) + info.offset; - kstd::libc::memcpy(dest, buffer, info.to_transfer); + kstd::libc::memcpy(dest, buffer, info.to_transfer.value); } + + return info.to_transfer; } - auto device::size() const -> size_t + auto device::size() const -> kstd::units::bytes { - return m_boot_module.size; + return kstd::units::bytes{m_boot_module.size}; } } // namespace kernel::devices::storage::ram_disk
\ No newline at end of file diff --git a/kernel/kernel/devices/storage/ram_disk/device.hpp b/kernel/kernel/devices/storage/ram_disk/device.hpp index cd62a1ec..f4c83187 100644 --- a/kernel/kernel/devices/storage/ram_disk/device.hpp +++ b/kernel/kernel/devices/storage/ram_disk/device.hpp @@ -5,6 +5,9 @@ #include <kapi/boot_module/boot_module.hpp> +#include <kstd/result.hpp> +#include <kstd/units.hpp> + #include <cstddef> namespace kernel::devices::storage::ram_disk @@ -35,7 +38,7 @@ namespace kernel::devices::storage::ram_disk * @note If the request reaches the module end, only available bytes are copied and the rest of the * logical block is filled with zeros. */ - auto read_block(size_t block_index, void * buffer) const -> void override; + auto read_block(size_t block_index, void * buffer) const -> kstd::result<kstd::units::bytes> override; /** * @brief Write one logical block from @p buffer. @@ -43,13 +46,13 @@ namespace kernel::devices::storage::ram_disk * @param buffer Source buffer, must not be null. * @note If the request reaches the module end, only the bytes in the module range are written. */ - auto write_block(size_t block_index, void const * buffer) -> void override; + auto write_block(size_t block_index, void const * buffer) -> kstd::result<kstd::units::bytes> override; private: /** * @brief Return module size in bytes. */ - [[nodiscard]] auto size() const -> size_t override; + [[nodiscard]] auto size() const -> kstd::units::bytes override; kapi::boot_modules::boot_module m_boot_module{}; }; diff --git a/kernel/kernel/devices/storage/ram_disk/device.tests.cpp b/kernel/kernel/devices/storage/ram_disk/device.tests.cpp index 988c2d38..a10dc84e 100644 --- a/kernel/kernel/devices/storage/ram_disk/device.tests.cpp +++ b/kernel/kernel/devices/storage/ram_disk/device.tests.cpp @@ -61,23 +61,24 @@ SCENARIO("RAM Disk Device Read and Write", "[ram_disk_device]") WHEN("reading a full block from the device") { - auto buffer = std::vector<std::byte>(device.block_size()); - device.read_block(0, buffer.data()); + auto buffer = std::vector<std::byte>(device.block_size().value); + CHECK(device.read_block(0, buffer.data())); THEN("the buffer is filled with the module data") { - REQUIRE_THAT(buffer, Catch::Matchers::RangeEquals(std::views::take(storage, device.block_size()))); + REQUIRE_THAT(buffer, Catch::Matchers::RangeEquals(std::views::take(storage, device.block_size().value))); } } WHEN("reading from a block index beyond the module size") { - auto buffer = std::vector<std::byte>(device.block_size()); - device.read_block(10, buffer.data()); + auto buffer = std::vector<std::byte>(device.block_size().value); + CHECK(device.read_block(10, buffer.data())); THEN("the buffer is filled with zeros") { - REQUIRE_THAT(buffer, Catch::Matchers::RangeEquals(std::vector<std::byte>(device.block_size(), std::byte{0}))); + REQUIRE_THAT(buffer, + Catch::Matchers::RangeEquals(std::vector<std::byte>(device.block_size().value, std::byte{0}))); } } @@ -88,19 +89,19 @@ SCENARIO("RAM Disk Device Read and Write", "[ram_disk_device]") WHEN("writing to a full block") { - auto buffer = std::vector<std::byte>(device.block_size(), std::byte{0x01}); - device.write_block(0, buffer.data()); + auto buffer = std::vector<std::byte>(device.block_size().value, std::byte{0x01}); + CHECK(device.write_block(0, buffer.data())); THEN("the module data is updated") { - REQUIRE_THAT(std::views::take(storage, device.block_size()), Catch::Matchers::RangeEquals(buffer)); + REQUIRE_THAT(std::views::take(storage, device.block_size().value), Catch::Matchers::RangeEquals(buffer)); } } WHEN("writing to a block index beyond the module size") { - auto buffer = std::vector<std::byte>(device.block_size(), std::byte{0x01}); - device.write_block(10, buffer.data()); + auto buffer = std::vector<std::byte>(device.block_size().value, std::byte{0x01}); + CHECK(device.write_block(10, buffer.data())); THEN("the module data is not updated") { diff --git a/kernel/kernel/filesystem/devfs/inode.cpp b/kernel/kernel/filesystem/devfs/inode.cpp index 2e4ee7de..8d0a9b14 100644 --- a/kernel/kernel/filesystem/devfs/inode.cpp +++ b/kernel/kernel/filesystem/devfs/inode.cpp @@ -1,19 +1,20 @@ #include <kernel/filesystem/devfs/inode.hpp> #include <kstd/result.hpp> +#include <kstd/units.hpp> -#include <cstddef> +using namespace kstd::units_literals; namespace kernel::filesystem::devfs { - auto inode::read(void *, size_t, size_t) const -> kstd::result<size_t> + auto inode::read(void *, kstd::units::bytes, kstd::units::bytes) const -> kstd::result<kstd::units::bytes> { - return 0; + return 0_B; } - auto inode::write(void const *, size_t, size_t) -> kstd::result<size_t> + auto inode::write(void const *, kstd::units::bytes, kstd::units::bytes) -> kstd::result<kstd::units::bytes> { - return 0; + return 0_B; } auto inode::is_directory() const -> bool diff --git a/kernel/kernel/filesystem/devfs/inode.hpp b/kernel/kernel/filesystem/devfs/inode.hpp index 3472079f..1e6d4e05 100644 --- a/kernel/kernel/filesystem/devfs/inode.hpp +++ b/kernel/kernel/filesystem/devfs/inode.hpp @@ -4,8 +4,7 @@ #include <kernel/filesystem/inode.hpp> #include <kstd/result.hpp> - -#include <cstddef> +#include <kstd/units.hpp> namespace kernel::filesystem::devfs { @@ -22,7 +21,8 @@ namespace kernel::filesystem::devfs @param size Number of bytes requested. @return Number of bytes read (always 0 because this inode does not expose file data). */ - auto read(void * buffer, size_t offset, size_t size) const -> kstd::result<size_t> override; + auto read(void * buffer, kstd::units::bytes offset, kstd::units::bytes size) const + -> kstd::result<kstd::units::bytes> override; /** @brief Writes to the devfs directory inode. @@ -31,7 +31,8 @@ namespace kernel::filesystem::devfs @param size Number of bytes requested. @return Number of bytes written (always 0 because writes are not supported for this inode). */ - auto write(void const * buffer, size_t offset, size_t size) -> kstd::result<size_t> override; + auto write(void const * buffer, kstd::units::bytes offset, kstd::units::bytes size) + -> kstd::result<kstd::units::bytes> override; /** @brief Check if this inode represents a directory. diff --git a/kernel/kernel/filesystem/devfs/inode.tests.cpp b/kernel/kernel/filesystem/devfs/inode.tests.cpp index ecf9a79b..9445be7d 100644 --- a/kernel/kernel/filesystem/devfs/inode.tests.cpp +++ b/kernel/kernel/filesystem/devfs/inode.tests.cpp @@ -2,12 +2,15 @@ #include <kstd/memory.hpp> #include <kstd/print.hpp> +#include <kstd/units.hpp> #include <kstd/vector.hpp> #include <catch2/catch_test_macros.hpp> #include <cstdint> +using namespace kstd::units_literals; + SCENARIO("Devfs inode creation", "[filesystem][devfs][inode]") { GIVEN("a devfs inode") @@ -33,22 +36,22 @@ SCENARIO("Devfs inode read/write", "[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()); + auto bytes_read = inode.read(buffer.data(), 0_B, kstd::units::bytes{buffer.size()}); THEN("no bytes are read") { - REQUIRE(bytes_read == 0); + REQUIRE(bytes_read == 0_B); } } WHEN("attempting to write to the devfs inode") { kstd::vector<uint8_t> buffer(512); - auto bytes_written = inode.write(buffer.data(), 0, buffer.size()); + auto bytes_written = inode.write(buffer.data(), 0_B, kstd::units::bytes{buffer.size()}); THEN("no bytes are written") { - REQUIRE(bytes_written == 0); + REQUIRE(bytes_written == 0_B); } } } diff --git a/kernel/kernel/filesystem/device_inode.cpp b/kernel/kernel/filesystem/device_inode.cpp index 644e3df7..7019377b 100644 --- a/kernel/kernel/filesystem/device_inode.cpp +++ b/kernel/kernel/filesystem/device_inode.cpp @@ -2,13 +2,13 @@ #include <kernel/devices/block_device_utils.hpp> +#include <kapi/devices.hpp> #include <kapi/devices/device.hpp> #include <kapi/system.hpp> #include <kstd/memory.hpp> #include <kstd/result.hpp> - -#include <cstddef> +#include <kstd/units.hpp> namespace kernel::filesystem { @@ -21,9 +21,10 @@ namespace kernel::filesystem } } - auto device_inode::read(void * buffer, size_t offset, size_t size) const -> kstd::result<size_t> + auto device_inode::read(void * buffer, kstd::units::bytes offset, kstd::units::bytes size) const + -> kstd::result<kstd::units::bytes> { - if (m_device->is_block_device()) + if (m_device->is_a<kapi::devices::block_device>()) { return devices::block_device_utils::read(m_device, buffer, offset, size); } @@ -33,9 +34,10 @@ namespace kernel::filesystem } } - auto device_inode::write(void const * buffer, size_t offset, size_t size) -> kstd::result<size_t> + auto device_inode::write(void const * buffer, kstd::units::bytes offset, kstd::units::bytes size) + -> kstd::result<kstd::units::bytes> { - if (m_device->is_block_device()) + if (m_device->is_a<kapi::devices::block_device>()) { return devices::block_device_utils::write(m_device, buffer, offset, size); } diff --git a/kernel/kernel/filesystem/device_inode.hpp b/kernel/kernel/filesystem/device_inode.hpp index 5b22366a..23b9863d 100644 --- a/kernel/kernel/filesystem/device_inode.hpp +++ b/kernel/kernel/filesystem/device_inode.hpp @@ -7,8 +7,7 @@ #include <kstd/memory.hpp> #include <kstd/result.hpp> - -#include <cstddef> +#include <kstd/units.hpp> namespace kernel::filesystem { @@ -33,7 +32,8 @@ namespace kernel::filesystem @param size The number of bytes to read. @return The number of bytes read. */ - auto read(void * buffer, size_t offset, size_t size) const -> kstd::result<size_t> override; + auto read(void * buffer, kstd::units::bytes offset, kstd::units::bytes size) const + -> kstd::result<kstd::units::bytes> override; /** @brief Write data to the device inode (and in the background from the associated device) from a @p buffer, starting @@ -43,7 +43,8 @@ namespace kernel::filesystem @param size The number of bytes to write. @return The number of bytes written. */ - auto write(void const * buffer, size_t offset, size_t size) -> kstd::result<size_t> override; + auto write(void const * buffer, kstd::units::bytes offset, kstd::units::bytes size) + -> kstd::result<kstd::units::bytes> override; /** @brief Get the associated device. diff --git a/kernel/kernel/filesystem/device_inode.tests.cpp b/kernel/kernel/filesystem/device_inode.tests.cpp index d78d4a07..2a0b22db 100644 --- a/kernel/kernel/filesystem/device_inode.tests.cpp +++ b/kernel/kernel/filesystem/device_inode.tests.cpp @@ -6,6 +6,7 @@ #include <kstd/memory.hpp> #include <kstd/print.hpp> +#include <kstd/units.hpp> #include <kstd/vector.hpp> #include <catch2/catch_test_macros.hpp> @@ -13,11 +14,13 @@ #include <cstddef> #include <cstdint> +using namespace kstd::units_literals; + SCENARIO("Device inode construction", "[filesystem][device_inode]") { GIVEN("a block device") { - auto device = kstd::make_shared<kernel::tests::devices::block_device>(0, 0, "test_block_device", 512, 3 * 512); + auto device = kstd::make_shared<kernel::tests::devices::block_device>(0, 0, "test_block_device", 512_B, 3 * 512_B); WHEN("constructing a device inode with the block device") { @@ -51,7 +54,7 @@ SCENARIO("Device inode read/write", "[filesystem][device_inode]") { GIVEN("a block device and a device inode for that device") { - auto device = kstd::make_shared<kernel::tests::devices::block_device>(0, 0, "test_block_device", 512, 3 * 512); + auto device = kstd::make_shared<kernel::tests::devices::block_device>(0, 0, "test_block_device", 512_B, 3 * 512_B); auto inode = kernel::filesystem::device_inode{device}; WHEN("writing to the device inode") @@ -62,19 +65,19 @@ SCENARIO("Device inode read/write", "[filesystem][device_inode]") write_buffer[i] = static_cast<uint8_t>(i % 256); } - auto bytes_written = inode.write(write_buffer.data(), 256, write_buffer.size()); + auto bytes_written = inode.write(write_buffer.data(), 256_B, kstd::units::bytes{write_buffer.size()}); THEN("the correct number of bytes is written") { - REQUIRE(bytes_written == 1024); + REQUIRE(bytes_written == 1024_B); } THEN("the data written matches the data read back from the device inode") { kstd::vector<uint8_t> read_buffer(1024); - auto bytes_read = inode.read(read_buffer.data(), 256, read_buffer.size()); + auto bytes_read = inode.read(read_buffer.data(), 256_B, kstd::units::bytes{read_buffer.size()}); - REQUIRE(bytes_read == write_buffer.size()); + REQUIRE(bytes_read.value().value == write_buffer.size()); REQUIRE(read_buffer == write_buffer); } } @@ -93,7 +96,8 @@ SCENARIO("Device inode read/write with a non-block device", "[filesystem][device kstd::vector<uint8_t> read_buffer(512); THEN("the system panics") { - REQUIRE_THROWS_AS(inode.read(read_buffer.data(), 0, read_buffer.size()), kernel::tests::cpu::halt); + REQUIRE_THROWS_AS(inode.read(read_buffer.data(), 0_B, kstd::units::bytes{read_buffer.size()}), + kernel::tests::cpu::halt); } } @@ -102,7 +106,8 @@ SCENARIO("Device inode read/write with a non-block device", "[filesystem][device kstd::vector<uint8_t> write_buffer(512); THEN("the system panics") { - REQUIRE_THROWS_AS(inode.write(write_buffer.data(), 0, write_buffer.size()), kernel::tests::cpu::halt); + REQUIRE_THROWS_AS(inode.write(write_buffer.data(), 0_B, kstd::units::bytes{write_buffer.size()}), + kernel::tests::cpu::halt); } } } diff --git a/kernel/kernel/filesystem/ext2/filesystem.cpp b/kernel/kernel/filesystem/ext2/filesystem.cpp index 091b1399..89dac095 100644 --- a/kernel/kernel/filesystem/ext2/filesystem.cpp +++ b/kernel/kernel/filesystem/ext2/filesystem.cpp @@ -17,6 +17,7 @@ #include <kstd/memory.hpp> #include <kstd/result.hpp> #include <kstd/system_error.hpp> +#include <kstd/units.hpp> #include <kstd/vector.hpp> #include <array> @@ -26,6 +27,8 @@ #include <string_view> #include <tuple> +using namespace kstd::units_literals; + namespace kernel::filesystem::ext2 { namespace @@ -79,7 +82,8 @@ namespace kernel::filesystem::ext2 { std::ignore = kernel::filesystem::filesystem::mount(backing_inode); - if (auto read_result = m_backing_inode->read(&m_superblock, constants::superblock_offset, sizeof(m_superblock)); + if (auto read_result = + m_backing_inode->read(&m_superblock, constants::superblock_offset, kstd::object_size(m_superblock)); !read_result) { return kstd::failure(read_result.error()); @@ -97,7 +101,7 @@ namespace kernel::filesystem::ext2 if (auto read_result = m_backing_inode->read(m_block_group_descriptors.data(), block_group_descriptor_table_offset(), - num_block_groups * sizeof(block_group_descriptor)); + num_block_groups * kstd::type_size<block_group_descriptor>); !read_result) { return kstd::failure(read_result.error()); @@ -131,7 +135,7 @@ namespace kernel::filesystem::ext2 auto * ext2_parent = static_cast<inode *>(parent.get()); auto const & inode_data = ext2_parent->data(); - kstd::vector<uint8_t> buffer(block_size()); + kstd::vector<uint8_t> buffer(block_size().value); for (uint32_t i = 0; i < inode_block_count(inode_data); ++i) { @@ -147,7 +151,7 @@ namespace kernel::filesystem::ext2 } auto const * entry = reinterpret_cast<linked_directory_entry const *>(buffer.data()); - auto bytes_read = 0uz; + auto bytes_read = 0_B; while (bytes_read < block_size() && entry->inode != 0) { @@ -157,7 +161,7 @@ namespace kernel::filesystem::ext2 return read_inode(entry->inode); } - bytes_read += entry->rec_len; + bytes_read += kstd::units::bytes{entry->rec_len}; entry = reinterpret_cast<linked_directory_entry const *>(buffer.data() + bytes_read); } } @@ -240,7 +244,7 @@ namespace kernel::filesystem::ext2 return kstd::failure(global_block.error()); } - kstd::vector<uint8_t> buffer(block_size()); + kstd::vector<uint8_t> buffer(block_size().value); if (auto read_result = read_block(*global_block, buffer.data()); !read_result) { return kstd::failure(read_result.error()); @@ -248,27 +252,27 @@ namespace kernel::filesystem::ext2 // TODO handle "gaps" in directory entries (e.g., after deletions) in the current implementation, we only // add new entries at the end of the last block, but we could also reuse space from deleted entries - auto offset = 0uz; + auto offset = 0_B; while (true) { auto const * entry = reinterpret_cast<linked_directory_entry const *>(buffer.data() + offset); - if (offset + entry->rec_len >= block_size()) + if (offset + kstd::units::bytes{entry->rec_len} >= block_size()) { break; } - offset += entry->rec_len; + offset += kstd::units::bytes{entry->rec_len}; } auto const file_type = map_inode_mode_to_file_type(mode); auto const name_len = static_cast<uint8_t>(name.size()); - auto const needed_rec_len = static_cast<uint16_t>((8u + name_len + 3u) & ~3u); + auto const needed_rec_len = static_cast<kstd::units::bytes>((8u + name_len + 3u) & ~3u); auto * last_entry = reinterpret_cast<linked_directory_entry *>(buffer.data() + offset); - auto const last_entry_actual_len = static_cast<uint16_t>((8u + last_entry->name_len + 3u) & ~3u); + auto const last_entry_actual_len = static_cast<kstd::units::bytes>((8u + last_entry->name_len + 3u) & ~3u); - if (last_entry->rec_len - last_entry_actual_len >= needed_rec_len) + if (kstd::units::bytes{last_entry->rec_len} - last_entry_actual_len >= needed_rec_len) { - last_entry->rec_len = last_entry_actual_len; + last_entry->rec_len = last_entry_actual_len.value; write_directory_entry_to_buffer(buffer.data(), offset + last_entry_actual_len, child_inode_number, name, file_type); return global_block.and_then([&](auto block_number) { return write_block(block_number, buffer.data()); }) @@ -288,8 +292,8 @@ namespace kernel::filesystem::ext2 return kstd::failure(new_global_block.error()); } - kstd::libc::memset(buffer.data(), 0, block_size()); - write_directory_entry_to_buffer(buffer.data(), 0, child_inode_number, name, file_type); + kstd::libc::memset(buffer.data(), 0, block_size().value); + write_directory_entry_to_buffer(buffer.data(), 0_B, child_inode_number, name, file_type); if (auto update_result = new_global_block.and_then([&](auto block_number) { return write_block(block_number, buffer.data()); }); !update_result) @@ -298,7 +302,7 @@ namespace kernel::filesystem::ext2 } } - ext2_parent->data_mutable().size = inode_block_count(ext2_parent->data()) * block_size(); + ext2_parent->data_mutable().size = (inode_block_count(ext2_parent->data()) * block_size()).value; return write_inode(ext2_parent->number(), ext2_parent->data()); } @@ -316,11 +320,11 @@ namespace kernel::filesystem::ext2 return kstd::failure(global_block.error()); } - kstd::vector<uint8_t> buffer(block_size(), 0); - write_directory_entry_to_buffer(buffer.data(), 0, new_inode->number(), ".", 2); - auto const dot_actual_len = static_cast<uint16_t>((8u + 1 + 3u) & ~3u); + kstd::vector<uint8_t> buffer(block_size().value, 0); + write_directory_entry_to_buffer(buffer.data(), 0_B, new_inode->number(), ".", 2); + auto const dot_actual_len = static_cast<kstd::units::bytes>((8u + 1 + 3u) & ~3u); auto * entry = reinterpret_cast<linked_directory_entry *>(buffer.data()); - entry->rec_len = dot_actual_len; + entry->rec_len = dot_actual_len.value; write_directory_entry_to_buffer(buffer.data(), dot_actual_len, parent_inode->number(), "..", 2); @@ -334,8 +338,9 @@ namespace kernel::filesystem::ext2 .transform([](auto) {}); } - auto filesystem::write_directory_entry_to_buffer(uint8_t * block_buffer, size_t offset, uint32_t child_inode_number, - std::string_view name, uint8_t file_type) -> void + auto filesystem::write_directory_entry_to_buffer(uint8_t * block_buffer, kstd::units::bytes offset, + uint32_t child_inode_number, std::string_view name, + uint8_t file_type) -> void { auto const name_len = static_cast<uint8_t>(name.size()); auto * entry = reinterpret_cast<linked_directory_entry *>(block_buffer + offset); @@ -352,7 +357,8 @@ namespace kernel::filesystem::ext2 { auto new_inode_data = inode_data{}; - if (auto read_result = m_backing_inode->read(&new_inode_data, *inode_offset, sizeof(inode_data)); !read_result) + if (auto read_result = m_backing_inode->read(&new_inode_data, *inode_offset, kstd::type_size<inode_data>); + !read_result) { return kstd::failure(read_result.error()); } @@ -371,7 +377,7 @@ namespace kernel::filesystem::ext2 { if (auto inode_offset = calculate_inode_offset(inode_number)) { - return m_backing_inode->write(&data, *inode_offset, sizeof(inode_data)).transform([](auto) {}); + return m_backing_inode->write(&data, *inode_offset, kstd::type_size<inode_data>).transform([](auto) {}); } else { @@ -379,7 +385,7 @@ namespace kernel::filesystem::ext2 } } - auto filesystem::calculate_inode_offset(uint32_t inode_number) const -> kstd::result<size_t> + auto filesystem::calculate_inode_offset(uint32_t inode_number) const -> kstd::result<kstd::units::bytes> { auto const inodes_per_group = m_superblock.inodes_per_group; auto const block_group_index = (inode_number - 1) / inodes_per_group; @@ -392,7 +398,7 @@ namespace kernel::filesystem::ext2 auto const & block_group_descriptor = m_block_group_descriptors.at(block_group_index); auto const inode_table_start_block = block_group_descriptor.inode_table; - auto const inode_table_offset = static_cast<size_t>(inode_table_start_block) * block_size(); + auto const inode_table_offset = inode_table_start_block * block_size(); auto const inode_offset = inode_table_offset + inode_index_within_group * inode_size(); return inode_offset; @@ -416,7 +422,7 @@ namespace kernel::filesystem::ext2 continue; } - kstd::vector<uint8_t> block_bitmap(block_size(), 0); + kstd::vector<uint8_t> block_bitmap(block_size().value, 0); if (auto read_result = read_block(block_group_descriptor.block_bitmap, block_bitmap.data()); !read_result) { return kstd::failure(read_result.error()); @@ -445,10 +451,11 @@ namespace kernel::filesystem::ext2 } // TODO update all block group descriptors - if (auto write_result = m_backing_inode->write( - &block_group_descriptor, - block_group_descriptor_table_offset() + block_group_descriptor_index * sizeof(block_group_descriptor), - sizeof(block_group_descriptor)); + if (auto write_result = + m_backing_inode->write(&block_group_descriptor, + block_group_descriptor_table_offset() + + block_group_descriptor_index * kstd::object_size(block_group_descriptor), + kstd::object_size(block_group_descriptor)); !write_result) { return kstd::failure(write_result.error()); @@ -457,7 +464,8 @@ namespace kernel::filesystem::ext2 } // TODO update all superblocks - if (auto write_result = m_backing_inode->write(&m_superblock, constants::superblock_offset, sizeof(m_superblock)); + if (auto write_result = + m_backing_inode->write(&m_superblock, constants::superblock_offset, kstd::object_size(m_superblock)); !write_result) { return kstd::failure(write_result.error()); @@ -487,7 +495,7 @@ namespace kernel::filesystem::ext2 continue; } - kstd::vector<uint8_t> inode_bitmap(block_size(), 0); + kstd::vector<uint8_t> inode_bitmap(block_size().value, 0); if (auto read_result = read_block(block_group_descriptor.inode_bitmap, inode_bitmap.data()); !read_result) { return kstd::failure(read_result.error()); @@ -586,8 +594,8 @@ namespace kernel::filesystem::ext2 uint32_t block_number_buffer = 0; auto const block_start_offset = block_number * block_size(); - auto const number_start_address = block_start_offset + index * sizeof(uint32_t); - if (auto read_result = m_backing_inode->read(&block_number_buffer, number_start_address, sizeof(uint32_t)); + auto const number_start_address = block_start_offset + index * kstd::type_size<uint32_t>; + if (auto read_result = m_backing_inode->read(&block_number_buffer, number_start_address, kstd::type_size<uint32_t>); !read_result) { return kstd::failure(read_result.error()); @@ -615,7 +623,7 @@ namespace kernel::filesystem::ext2 } auto block_number = data.block[level.slot_index]; - auto parent_byte_offset = 0uz; + auto parent_byte_offset = 0_B; bool is_root = true; for (auto stride = level.capacity / block_numbers_per_block();; stride /= block_numbers_per_block()) @@ -639,7 +647,8 @@ namespace kernel::filesystem::ext2 } else { - if (auto write_result = m_backing_inode->write(&block_number, parent_byte_offset, sizeof(uint32_t)); + if (auto write_result = + m_backing_inode->write(&block_number, parent_byte_offset, kstd::type_size<uint32_t>); !write_result) { return kstd::failure(write_result.error()); @@ -647,11 +656,11 @@ namespace kernel::filesystem::ext2 } } - auto const byte_offset = block_number * block_size() + idx * sizeof(uint32_t); + auto const byte_offset = block_number * block_size() + idx * kstd::type_size<uint32_t>; if (stride == 1) { - if (auto write_result = m_backing_inode->write(&global_block_number, byte_offset, sizeof(uint32_t)); + if (auto write_result = m_backing_inode->write(&global_block_number, byte_offset, kstd::type_size<uint32_t>); !write_result) { return kstd::failure(write_result.error()); @@ -675,13 +684,13 @@ namespace kernel::filesystem::ext2 return kstd::success(); } - auto filesystem::read_block(uint32_t block_number, void * buffer) const -> kstd::result<size_t> + auto filesystem::read_block(uint32_t block_number, void * buffer) const -> kstd::result<kstd::units::bytes> { auto const block_offset = static_cast<size_t>(block_number) * block_size(); return m_backing_inode->read(buffer, block_offset, block_size()); } - auto filesystem::write_block(uint32_t block_number, void const * buffer) -> kstd::result<size_t> + auto filesystem::write_block(uint32_t block_number, void const * buffer) -> kstd::result<kstd::units::bytes> { auto const block_offset = static_cast<size_t>(block_number) * block_size(); return m_backing_inode->write(buffer, block_offset, block_size()); @@ -693,15 +702,16 @@ namespace kernel::filesystem::ext2 // TODO update all block group descriptors return m_backing_inode ->write(&block_group_descriptor, - block_group_descriptor_table_offset() + block_group_descriptor_index * sizeof(block_group_descriptor), - sizeof(block_group_descriptor)) + block_group_descriptor_table_offset() + + block_group_descriptor_index * kstd::object_size(block_group_descriptor), + kstd::object_size(block_group_descriptor)) .transform([](auto) {}); } auto filesystem::write_superblock() const -> kstd::result<void> { // TODO update all superblocks - return m_backing_inode->write(&m_superblock, constants::superblock_offset, sizeof(m_superblock)) + return m_backing_inode->write(&m_superblock, constants::superblock_offset, kstd::object_size(m_superblock)) .transform([](auto) {}); } @@ -738,7 +748,7 @@ namespace kernel::filesystem::ext2 auto filesystem::block_numbers_per_block() const -> size_t { - return block_size() / sizeof(uint32_t); + return block_size() / kstd::type_size<uint32_t>; } auto filesystem::block_numbers_per_singly_indirect_block() const -> size_t @@ -756,9 +766,9 @@ namespace kernel::filesystem::ext2 return block_numbers_per_doubly_indirect_block() * block_numbers_per_block(); } - auto filesystem::block_size() const -> size_t + auto filesystem::block_size() const -> kstd::units::bytes { - return constants::base_block_size << m_superblock.log_block_size; + return kstd::units::bytes{constants::base_block_size.value << m_superblock.log_block_size}; } auto filesystem::revision_level() const -> uint32_t @@ -766,9 +776,9 @@ namespace kernel::filesystem::ext2 return m_superblock.rev_level; } - auto filesystem::inode_size() const -> uint16_t + auto filesystem::inode_size() const -> kstd::units::bytes { - return revision_level() == constants::good_old_revision ? 128 : m_superblock.inode_size; + return kstd::units::bytes(revision_level() == constants::good_old_revision ? 128 : m_superblock.inode_size); } auto filesystem::inode_block_count(inode_data const & data) const -> uint32_t @@ -781,9 +791,9 @@ namespace kernel::filesystem::ext2 data.blocks += delta * (2 << m_superblock.log_block_size); } - auto filesystem::block_group_descriptor_table_offset() const -> size_t + auto filesystem::block_group_descriptor_table_offset() const -> kstd::units::bytes { - return block_size() == 1024 ? 2 * block_size() : block_size(); + return block_size() == 1024_B ? 2 * block_size() : block_size(); } } // namespace kernel::filesystem::ext2 diff --git a/kernel/kernel/filesystem/ext2/filesystem.hpp b/kernel/kernel/filesystem/ext2/filesystem.hpp index e5192ec0..23e56143 100644 --- a/kernel/kernel/filesystem/ext2/filesystem.hpp +++ b/kernel/kernel/filesystem/ext2/filesystem.hpp @@ -11,6 +11,7 @@ #include <kstd/memory.hpp> #include <kstd/result.hpp> #include <kstd/system_error.hpp> +#include <kstd/units.hpp> #include <kstd/vector.hpp> #include <array> @@ -25,8 +26,8 @@ namespace kernel::filesystem::ext2 */ namespace constants { - constexpr size_t inline base_block_size = 1024; - constexpr size_t inline superblock_offset = base_block_size; + constexpr kstd::units::bytes inline base_block_size = kstd::units::bytes{1024}; + constexpr kstd::units::bytes inline superblock_offset = base_block_size; constexpr uint16_t inline magic_number = 0xEF53; constexpr uint32_t inline good_old_revision = 0; @@ -82,7 +83,7 @@ namespace kernel::filesystem::ext2 @brief Gets the size of a block in the filesystem. @return The size of a block in bytes. */ - [[nodiscard]] auto block_size() const -> size_t; + [[nodiscard]] auto block_size() const -> kstd::units::bytes; /** @brief Gets the revision level of the filesystem. @@ -96,7 +97,7 @@ namespace kernel::filesystem::ext2 @param buffer The buffer to read the block data into. @return The number of bytes read. */ - auto read_block(uint32_t block_number, void * buffer) const -> kstd::result<size_t>; + auto read_block(uint32_t block_number, void * buffer) const -> kstd::result<kstd::units::bytes>; /** @brief Writes a block of data from the provided buffer to the backing device. @@ -104,7 +105,7 @@ namespace kernel::filesystem::ext2 @param buffer The buffer containing the data to write. @return The number of bytes written. */ - auto write_block(uint32_t block_number, void const * buffer) -> kstd::result<size_t>; + auto write_block(uint32_t block_number, void const * buffer) -> kstd::result<kstd::units::bytes>; /** @brief Allocates a specified number of blocks. @@ -117,7 +118,7 @@ namespace kernel::filesystem::ext2 @brief Gets the size of an inode in the filesystem. @return The size of an inode in bytes. */ - [[nodiscard]] auto inode_size() const -> uint16_t; + [[nodiscard]] auto inode_size() const -> kstd::units::bytes; /** @brief Gets the number of blocks allocated to an inode. @@ -172,14 +173,14 @@ namespace kernel::filesystem::ext2 -> kstd::result<void>; auto init_directory(kstd::shared_ptr<kernel::filesystem::ext2::inode> const & new_inode, kernel::filesystem::ext2::inode * parent_inode) -> kstd::result<void>; - auto write_directory_entry_to_buffer(uint8_t * block_buffer, size_t offset, uint32_t child_inode_number, + auto write_directory_entry_to_buffer(uint8_t * block_buffer, kstd::units::bytes offset, uint32_t child_inode_number, std::string_view name, uint8_t file_type) -> void; - [[nodiscard]] auto calculate_inode_offset(uint32_t inode_number) const -> kstd::result<size_t>; + [[nodiscard]] auto calculate_inode_offset(uint32_t inode_number) const -> kstd::result<kstd::units::bytes>; [[nodiscard]] auto read_inode(uint32_t inode_number) const -> kstd::result<kstd::shared_ptr<inode>>; [[nodiscard]] auto read_block_number_at_index(uint32_t block_number, size_t index) const -> kstd::result<uint32_t>; - [[nodiscard]] auto block_group_descriptor_table_offset() const -> size_t; + [[nodiscard]] auto block_group_descriptor_table_offset() const -> kstd::units::bytes; [[nodiscard]] auto block_numbers_per_block() const -> size_t; [[nodiscard]] auto block_numbers_per_singly_indirect_block() const -> size_t; diff --git a/kernel/kernel/filesystem/ext2/filesystem.tests.cpp b/kernel/kernel/filesystem/ext2/filesystem.tests.cpp index 8aecc847..9013ea22 100644 --- a/kernel/kernel/filesystem/ext2/filesystem.tests.cpp +++ b/kernel/kernel/filesystem/ext2/filesystem.tests.cpp @@ -14,6 +14,7 @@ #include <kernel/test_support/filesystem/storage_boot_module_fixture.hpp> #include <kstd/memory.hpp> +#include <kstd/units.hpp> #include <kstd/vector.hpp> #include <catch2/catch_test_macros.hpp> @@ -26,6 +27,10 @@ #include <string_view> #include <vector> +using namespace kstd::units_literals; + +// NOLINTBEGIN(readability-magic-numbers) + SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 filesystem mount and lookup with real image", "[filesystem][ext2][filesystem][img]") { @@ -144,12 +149,12 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, auto buffer = std::vector<std::byte>{std::byte{'H'}, std::byte{'e'}, std::byte{'l'}, std::byte{'l'}, std::byte{'o'}, std::byte{' '}, std::byte{'W'}, std::byte{'o'}, std::byte{'r'}, std::byte{'l'}, std::byte{'d'}, std::byte{'!'}}; - auto bytes_written = new_inode.value()->write(buffer.data(), 0, buffer.size()); - REQUIRE(bytes_written == buffer.size()); + auto bytes_written = new_inode.value()->write(buffer.data(), 0_B, kstd::units::bytes{buffer.size()}); + REQUIRE(bytes_written == kstd::units::bytes{buffer.size()}); auto read_buffer = std::vector<std::byte>(5, std::byte{0xAA}); - auto bytes_read = new_inode.value()->read(read_buffer.data(), 0, read_buffer.size()); - REQUIRE(bytes_read == read_buffer.size()); + auto bytes_read = new_inode.value()->read(read_buffer.data(), 0_B, kstd::units::bytes{read_buffer.size()}); + REQUIRE(bytes_read == kstd::units::bytes{read_buffer.size()}); std::string_view result{reinterpret_cast<char *>(read_buffer.data()), static_cast<size_t>(*bytes_read)}; REQUIRE(result == "Hello"); @@ -166,7 +171,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, SCENARIO("Ext2 filesystem rejects invalid magic", "[filesystem][ext2][filesystem]") { - auto const block_size = 1024; + auto const block_size = 1024_B; GIVEN("a block device that does not contain an ext2 superblock") { auto device = kstd::make_shared<kernel::tests::devices::block_device>(0, 0, "mock", block_size, 2 * block_size); @@ -185,7 +190,7 @@ SCENARIO("Ext2 filesystem rejects invalid magic", "[filesystem][ext2][filesystem SCENARIO("Ext2 block mapping includes direct and all indirect levels", "[filesystem][ext2][filesystem]") { - auto const block_size = 1024; + auto const block_size = 1024_B; GIVEN("a minimally valid ext2 layout with configured indirect block tables") { @@ -214,7 +219,7 @@ SCENARIO("Ext2 block mapping includes direct and all indirect levels", "[filesys kernel::tests::filesystem::ext2::write_u32(*device, 51 * block_size, 52); kernel::tests::filesystem::ext2::write_u32(*device, 52 * block_size, 53); - auto const numbers_per_block = static_cast<uint32_t>(block_size / sizeof(uint32_t)); + auto const numbers_per_block = static_cast<uint32_t>(block_size / kstd::type_size<uint32_t>); auto const singly_start = static_cast<uint32_t>(kernel::filesystem::ext2::constants::direct_block_count); auto const doubly_start = singly_start + numbers_per_block; auto const triply_start = doubly_start + numbers_per_block * numbers_per_block; @@ -237,7 +242,7 @@ SCENARIO("Ext2 block mapping includes direct and all indirect levels", "[filesys SCENARIO("Ext2 block writing includes direct and all indirect levels", "[filesystem][ext2][filesystem]") { - auto const block_size = 1024; + auto const block_size = 1024_B; GIVEN("a mounted ext2 filesystem with free blocks available for indirect table allocation") { @@ -259,7 +264,7 @@ SCENARIO("Ext2 block writing includes direct and all indirect levels", "[filesys block_group_descriptor.inode_table = 5; block_group_descriptor.free_blocks_count = 128; - auto block_bitmap = std::vector<std::byte>(block_size, std::byte{0x00}); + auto block_bitmap = std::vector<std::byte>(block_size.value, std::byte{0x00}); block_bitmap[0] = std::byte{0b1111'1111}; block_bitmap[1] = std::byte{0b1111'1111}; @@ -271,7 +276,7 @@ SCENARIO("Ext2 block writing includes direct and all indirect levels", "[filesys auto fs = kernel::filesystem::ext2::filesystem{}; REQUIRE(fs.mount(dev_inode)); - auto read_u32 = [&](size_t offset) -> uint32_t { + auto read_u32 = [&](kstd::units::bytes offset) -> uint32_t { auto value = uint32_t{0}; std::memcpy(&value, device->data.data() + offset, sizeof(value)); return value; @@ -279,7 +284,7 @@ SCENARIO("Ext2 block writing includes direct and all indirect levels", "[filesys auto inode_data = kernel::filesystem::ext2::inode_data{}; - auto const numbers_per_block = static_cast<uint32_t>(block_size / sizeof(uint32_t)); + auto const numbers_per_block = static_cast<uint32_t>(block_size / kstd::type_size<uint32_t>); auto const singly_start = static_cast<uint32_t>(kernel::filesystem::ext2::constants::direct_block_count); auto const doubly_start = singly_start + numbers_per_block; auto const triply_start = doubly_start + numbers_per_block * numbers_per_block; @@ -296,12 +301,13 @@ SCENARIO("Ext2 block writing includes direct and all indirect levels", "[filesys REQUIRE(fs.write_global_block_number_to_inode_block_index(singly_start, inode_data, singly_global_block_number)); REQUIRE(inode_data.block[12] == 16); - REQUIRE(read_u32(static_cast<size_t>(inode_data.block[12]) * block_size) == singly_global_block_number); + REQUIRE(read_u32(static_cast<kstd::units::bytes>(inode_data.block[12]) * block_size.value) == + singly_global_block_number); REQUIRE(fs.write_global_block_number_to_inode_block_index(singly_start + 1, inode_data, singly_global_block_number + 1)); - REQUIRE(read_u32(static_cast<size_t>(inode_data.block[12]) * block_size + 1 * sizeof(uint32_t)) == - singly_global_block_number + 1); + REQUIRE(read_u32(static_cast<kstd::units::bytes>(inode_data.block[12]) * block_size.value + + 1 * kstd::type_size<uint32_t>) == singly_global_block_number + 1); REQUIRE(fs.write_global_block_number_to_inode_block_index(doubly_start, inode_data, doubly_global_block_number)); REQUIRE(inode_data.block[13] == 17); @@ -324,3 +330,5 @@ SCENARIO("Ext2 block writing includes direct and all indirect levels", "[filesys } } } + +// NOLINTEND(readability-magic-numbers)
\ No newline at end of file diff --git a/kernel/kernel/filesystem/ext2/inode.cpp b/kernel/kernel/filesystem/ext2/inode.cpp index 8af168b9..f42e2c0c 100644 --- a/kernel/kernel/filesystem/ext2/inode.cpp +++ b/kernel/kernel/filesystem/ext2/inode.cpp @@ -7,11 +7,14 @@ #include <kstd/cstring.hpp> #include <kstd/result.hpp> +#include <kstd/units.hpp> #include <algorithm> #include <cstddef> #include <cstdint> +using namespace kstd::units_literals; + namespace kernel::filesystem::ext2 { inode::inode(filesystem * fs, uint32_t inode_number, inode_data const & data) @@ -25,22 +28,23 @@ namespace kernel::filesystem::ext2 } } - auto inode::read(void * buffer, size_t offset, size_t size) const -> kstd::result<size_t> + auto inode::read(void * buffer, kstd::units::bytes offset, kstd::units::bytes size) const + -> kstd::result<kstd::units::bytes> { auto const max_readable = this->size() - offset; auto const requested_size = std::min(size, max_readable); - if (is_symbolic_link() && this->size() <= sizeof(m_data.block)) + if (is_symbolic_link() && this->size() <= kstd::units::bytes{sizeof(m_data.block)}) { auto inline_target = reinterpret_cast<uint8_t const *>(m_data.block.data()); - kstd::libc::memcpy(static_cast<uint8_t *>(buffer), inline_target + offset, requested_size); + kstd::libc::memcpy(static_cast<uint8_t *>(buffer), inline_target + offset, requested_size.value); return requested_size; } auto block_index = offset / m_filesystem->block_size(); auto in_block_offset = offset % m_filesystem->block_size(); - auto bytes_read = 0uz; + auto bytes_read = 0_B; while (bytes_read < requested_size) { @@ -53,7 +57,7 @@ namespace kernel::filesystem::ext2 auto const bytes_to_read = std::min(requested_size - bytes_read, m_filesystem->block_size() - in_block_offset); if (block_number == 0) { - kstd::libc::memset(static_cast<uint8_t *>(buffer) + bytes_read, 0, bytes_to_read); + kstd::libc::memset(static_cast<uint8_t *>(buffer) + bytes_read, 0, bytes_to_read.value); bytes_read += bytes_to_read; } else @@ -71,13 +75,14 @@ namespace kernel::filesystem::ext2 } block_index++; - in_block_offset = 0; // After the first block, we always start at the beginning of the block + in_block_offset = 0_B; // After the first block, we always start at the beginning of the block } return bytes_read; } - auto inode::write(void const * buffer, size_t offset, size_t size) -> kstd::result<size_t> + auto inode::write(void const * buffer, kstd::units::bytes offset, kstd::units::bytes size) + -> kstd::result<kstd::units::bytes> { if (!is_regular()) { @@ -95,7 +100,7 @@ namespace kernel::filesystem::ext2 if (new_inode_size > max_new_inode_size_without_new_blocks) { auto const additional_blocks_needed = - (new_inode_size - max_new_inode_size_without_new_blocks + m_filesystem->block_size() - 1) / + (new_inode_size - max_new_inode_size_without_new_blocks + m_filesystem->block_size() - 1_B) / m_filesystem->block_size(); if (!append_blocks(additional_blocks_needed)) @@ -108,7 +113,7 @@ namespace kernel::filesystem::ext2 auto block_index = offset / m_filesystem->block_size(); auto in_block_offset = offset % m_filesystem->block_size(); - auto bytes_written = 0uz; + auto bytes_written = 0_B; while (bytes_written < size) { @@ -134,7 +139,7 @@ namespace kernel::filesystem::ext2 bytes_written += write_result.value(); block_index++; - in_block_offset = 0; + in_block_offset = 0_B; } set_size(std::max(this->size(), offset + bytes_written)); @@ -196,7 +201,7 @@ namespace kernel::filesystem::ext2 return (m_data.mode & constants::mode_mask) == constants::mode_symbolic_link; } - auto inode::size() const -> uint64_t + auto inode::size() const -> kstd::units::bytes { uint64_t size = m_data.size; @@ -205,16 +210,16 @@ namespace kernel::filesystem::ext2 size |= static_cast<uint64_t>(m_data.dir_acl) << 32; } - return size; + return kstd::units::bytes{size}; } - auto inode::set_size(uint64_t new_size) -> void + auto inode::set_size(kstd::units::bytes new_size) -> void { if (m_filesystem->revision_level() > constants::good_old_revision && is_regular()) { - m_data.dir_acl = static_cast<uint32_t>(new_size >> 32); + m_data.dir_acl = static_cast<uint32_t>(new_size.value >> 32); } - m_data.size = static_cast<uint32_t>(new_size); + m_data.size = static_cast<uint32_t>(new_size.value); } [[nodiscard]] auto inode::number() const -> uint32_t diff --git a/kernel/kernel/filesystem/ext2/inode.hpp b/kernel/kernel/filesystem/ext2/inode.hpp index 61542ef8..1d364a54 100644 --- a/kernel/kernel/filesystem/ext2/inode.hpp +++ b/kernel/kernel/filesystem/ext2/inode.hpp @@ -5,6 +5,7 @@ #include <kstd/memory.hpp> #include <kstd/result.hpp> +#include <kstd/units.hpp> #include <array> #include <cstddef> @@ -56,7 +57,8 @@ namespace kernel::filesystem::ext2 @param size Number of bytes requested. @return Number of bytes read. */ - auto read(void * buffer, size_t offset, size_t size) const -> kstd::result<size_t> override; + auto read(void * buffer, kstd::units::bytes offset, kstd::units::bytes size) const + -> kstd::result<kstd::units::bytes> override; /** @brief Writes to the ext2 inode into a @p buffer, starting at the specified @p offset and for a given @p size. @@ -65,7 +67,8 @@ namespace kernel::filesystem::ext2 @param size Number of bytes requested. @return Number of bytes written. */ - auto write(void const * buffer, size_t offset, size_t size) -> kstd::result<size_t> override; + auto write(void const * buffer, kstd::units::bytes offset, kstd::units::bytes size) + -> kstd::result<kstd::units::bytes> override; /** @brief Appends the specified number of blocks to the inode. @@ -108,13 +111,13 @@ namespace kernel::filesystem::ext2 @brief Get the size of the file represented by this inode. @return The size of the file in bytes. */ - [[nodiscard]] auto size() const -> uint64_t; + [[nodiscard]] auto size() const -> kstd::units::bytes; /** @brief Set the size of the file represented by this inode. @param new_size The new size of the file in bytes. */ - auto set_size(uint64_t new_size) -> void; + auto set_size(kstd::units::bytes new_size) -> void; /** @brief Get the inode number of this inode. diff --git a/kernel/kernel/filesystem/ext2/inode.tests.cpp b/kernel/kernel/filesystem/ext2/inode.tests.cpp index 7e293d14..e3c06407 100644 --- a/kernel/kernel/filesystem/ext2/inode.tests.cpp +++ b/kernel/kernel/filesystem/ext2/inode.tests.cpp @@ -12,6 +12,7 @@ #include <kernel/test_support/filesystem/storage_boot_module_fixture.hpp> #include <kstd/memory.hpp> +#include <kstd/units.hpp> #include <kstd/vector.hpp> #include <catch2/catch_test_macros.hpp> @@ -23,6 +24,8 @@ #include <string_view> #include <vector> +using namespace kstd::units_literals; + // NOLINTBEGIN(readability-magic-numbers) SCENARIO("Ext2 inode initialization and properties", "[filesystem][ext2][inode]") @@ -113,20 +116,20 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 in THEN("reading from offset zero returns expected file prefix") { auto buffer = kstd::vector<std::byte>(6); - auto const bytes_read = file.value()->read(buffer.data(), 0, buffer.size()); + auto const bytes_read = file.value()->read(buffer.data(), 0_B, kstd::units::bytes{buffer.size()}); - REQUIRE(bytes_read == 6); + REQUIRE(bytes_read == 6_B); - auto const text = std::string_view{reinterpret_cast<char const *>(buffer.data()), *bytes_read}; + auto const text = std::string_view{reinterpret_cast<char const *>(buffer.data()), bytes_read->value}; REQUIRE(text == "info_1"); } THEN("reading with an offset returns the expected byte") { auto buffer = kstd::vector<std::byte>(1); - auto const bytes_read = file.value()->read(buffer.data(), 5, buffer.size()); + auto const bytes_read = file.value()->read(buffer.data(), 5_B, kstd::units::bytes{buffer.size()}); - REQUIRE(bytes_read == 1); + REQUIRE(bytes_read == 1_B); REQUIRE(static_cast<char>(buffer[0]) == '1'); } } @@ -134,7 +137,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 in SCENARIO("Ext2 inode handles zeros in block mappings as file holes", "[filesystem][ext2][inode]") { - auto const block_size = 1024uz; + auto const block_size = 1024_B; GIVEN("an ext2 inode with only direct mapped data blocks") { auto device = kstd::make_shared<kernel::tests::devices::block_device>(0, 0, "mock", block_size, 64 * block_size); @@ -150,10 +153,10 @@ SCENARIO("Ext2 inode handles zeros in block mappings as file holes", "[filesyste data.block[0] = 30; data.block[1] = 0; data.block[2] = 31; - data.size = block_size * 3; + data.size = block_size.value * 3; - kernel::tests::filesystem::ext2::write_bytes(*device, 30 * block_size, "Hello", 5); - kernel::tests::filesystem::ext2::write_bytes(*device, 31 * block_size, "World!", 6); + kernel::tests::filesystem::ext2::write_bytes(*device, 30 * block_size, "Hello", 5_B); + kernel::tests::filesystem::ext2::write_bytes(*device, 31 * block_size, "World!", 6_B); auto inode = kernel::filesystem::ext2::inode{&fs, 42, data}; @@ -161,14 +164,15 @@ SCENARIO("Ext2 inode handles zeros in block mappings as file holes", "[filesyste THEN("correct number of bytes are read and holes are returned as zeros") { - auto const bytes_read = inode.read(buffer.data(), 0, buffer.size()); - REQUIRE(bytes_read == data.size); + auto const bytes_read = inode.read(buffer.data(), 0_B, kstd::units::bytes{buffer.size()}); + REQUIRE(bytes_read == kstd::units::bytes{data.size}); - auto const text = std::string_view{reinterpret_cast<char const *>(buffer.data()), *bytes_read}; + auto const text = std::string_view{reinterpret_cast<char const *>(buffer.data()), bytes_read->value}; REQUIRE(text.substr(0, 5) == "Hello"); - REQUIRE(std::ranges::all_of(text.substr(5, block_size - 5), [](char c) { return c == '\0'; })); - REQUIRE(text.substr(2 * block_size, 6) == "World!"); - REQUIRE(std::ranges::all_of(text.substr(2 * block_size + 6, 3 * block_size), [](char c) { return c == '\0'; })); + REQUIRE(std::ranges::all_of(text.substr(5, block_size.value - 5), [](char c) { return c == '\0'; })); + REQUIRE(text.substr(2 * block_size.value, 6) == "World!"); + REQUIRE(std::ranges::all_of(text.substr(2 * block_size.value + 6, 3 * block_size.value), + [](char c) { return c == '\0'; })); } } @@ -186,15 +190,15 @@ SCENARIO("Ext2 inode handles zeros in block mappings as file holes", "[filesyste auto data = kernel::filesystem::ext2::inode_data{}; data.block[0] = 30; data.block[12] = 31; - data.size = block_size * 15; + data.size = block_size.value * 15; kernel::tests::filesystem::ext2::write_u32(*device, 31 * block_size, 50); - kernel::tests::filesystem::ext2::write_u32(*device, 31 * block_size + 4, 0); - kernel::tests::filesystem::ext2::write_u32(*device, 31 * block_size + 8, 51); + kernel::tests::filesystem::ext2::write_u32(*device, 31 * block_size + 4_B, 0); + kernel::tests::filesystem::ext2::write_u32(*device, 31 * block_size + 8_B, 51); - kernel::tests::filesystem::ext2::write_bytes(*device, 30 * block_size, "Hello", 5); - kernel::tests::filesystem::ext2::write_bytes(*device, 50 * block_size, "Blub", 4); - kernel::tests::filesystem::ext2::write_bytes(*device, 51 * block_size, "World!", 6); + kernel::tests::filesystem::ext2::write_bytes(*device, 30 * block_size, "Hello", 5_B); + kernel::tests::filesystem::ext2::write_bytes(*device, 50 * block_size, "Blub", 4_B); + kernel::tests::filesystem::ext2::write_bytes(*device, 51 * block_size, "World!", 6_B); auto inode = kernel::filesystem::ext2::inode{&fs, 42, data}; @@ -202,18 +206,18 @@ SCENARIO("Ext2 inode handles zeros in block mappings as file holes", "[filesyste THEN("correct number of bytes are read and holes are returned as zeros") { - auto const bytes_read = inode.read(buffer.data(), 0, buffer.size()); - REQUIRE(bytes_read == data.size); + auto const bytes_read = inode.read(buffer.data(), 0_B, kstd::units::bytes{buffer.size()}); + REQUIRE(bytes_read == kstd::units::bytes{data.size}); - auto const text = std::string_view{reinterpret_cast<char const *>(buffer.data()), *bytes_read}; + auto const text = std::string_view{reinterpret_cast<char const *>(buffer.data()), bytes_read->value}; REQUIRE(text.substr(0, 5) == "Hello"); - REQUIRE(std::ranges::all_of(text.substr(5, 12 * block_size - 5), [](char c) { return c == '\0'; })); - REQUIRE(text.substr(12 * block_size, 4) == "Blub"); - REQUIRE( - std::ranges::all_of(text.substr(12 * block_size + 4, 2 * block_size - 4), [](char c) { return c == '\0'; })); - REQUIRE(text.substr(14 * block_size, 6) == "World!"); - REQUIRE( - std::ranges::all_of(text.substr(14 * block_size + 6, 1 * block_size - 6), [](char c) { return c == '\0'; })); + REQUIRE(std::ranges::all_of(text.substr(5, 12 * block_size.value - 5), [](char c) { return c == '\0'; })); + REQUIRE(text.substr(12 * block_size.value, 4) == "Blub"); + REQUIRE(std::ranges::all_of(text.substr(12 * block_size.value + 4, 2 * block_size.value - 4), + [](char c) { return c == '\0'; })); + REQUIRE(text.substr(14 * block_size.value, 6) == "World!"); + REQUIRE(std::ranges::all_of(text.substr(14 * block_size.value + 6, 1 * block_size.value - 6), + [](char c) { return c == '\0'; })); } } @@ -230,16 +234,16 @@ SCENARIO("Ext2 inode handles zeros in block mappings as file holes", "[filesyste auto data = kernel::filesystem::ext2::inode_data{}; data.block[12] = 0; - data.size = block_size * 15; + data.size = block_size.value * 15; auto inode = kernel::filesystem::ext2::inode{&fs, 42, data}; - auto buffer = kstd::vector<std::byte>(block_size * 15, std::byte{0xAB}); + auto buffer = kstd::vector<std::byte>(block_size.value * 15, std::byte{0xAB}); THEN("all direct blocks are zero when singly indirect block pointer is zero") { - auto const bytes_read = inode.read(buffer.data(), 0, buffer.size()); - REQUIRE(bytes_read == buffer.size()); + auto const bytes_read = inode.read(buffer.data(), 0_B, kstd::units::bytes{buffer.size()}); + REQUIRE(bytes_read == kstd::units::bytes{buffer.size()}); REQUIRE(std::ranges::all_of(buffer, [](std::byte c) { return c == std::byte{0x00}; })); } } @@ -247,7 +251,7 @@ SCENARIO("Ext2 inode handles zeros in block mappings as file holes", "[filesyste SCENARIO("Ext2 inode read across block boundaries", "[filesystem][ext2][inode]") { - auto const block_size = 1024uz; + auto const block_size = 1024_B; GIVEN("an ext2 inode with two direct blocks and a block size of 1024 bytes") { auto device = kstd::make_shared<kernel::tests::devices::block_device>(0, 0, "mock", block_size, 64 * block_size); @@ -260,21 +264,21 @@ SCENARIO("Ext2 inode read across block boundaries", "[filesystem][ext2][inode]") REQUIRE(fs.mount(dev_inode)); auto inode_data = kernel::filesystem::ext2::inode_data{}; - inode_data.size = block_size * 2; + inode_data.size = block_size.value * 2; inode_data.block[0] = 20; - kernel::tests::filesystem::ext2::write_bytes(*device, 21 * block_size - 6, "Hello ", 6); + kernel::tests::filesystem::ext2::write_bytes(*device, 21 * block_size - 6_B, "Hello ", 6_B); inode_data.block[1] = 21; - kernel::tests::filesystem::ext2::write_bytes(*device, 21 * block_size, "World!", 6); + kernel::tests::filesystem::ext2::write_bytes(*device, 21 * block_size, "World!", 6_B); auto inode = kernel::filesystem::ext2::inode{&fs, 42, inode_data}; auto buffer = kstd::vector<std::byte>(12, std::byte{0x00}); THEN("reading across the block boundary returns the combined content") { - auto const bytes_read = inode.read(buffer.data(), block_size - 6, buffer.size()); - REQUIRE(bytes_read == 12); + auto const bytes_read = inode.read(buffer.data(), block_size - 6_B, kstd::units::bytes{buffer.size()}); + REQUIRE(bytes_read == kstd::units::bytes{12}); - auto const text = std::string_view{reinterpret_cast<char const *>(buffer.data()), *bytes_read}; + auto const text = std::string_view{reinterpret_cast<char const *>(buffer.data()), bytes_read->value}; REQUIRE(text == "Hello World!"); } } @@ -309,18 +313,18 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 in std::byte{'o'}, std::byte{' '}, std::byte{'W'}, std::byte{'o'}, std::byte{'r'}, std::byte{'l'}, std::byte{'d'}, std::byte{'!'}}; - auto const bytes_written = file.value()->write(write_buffer.data(), 0, write_buffer.size()); - REQUIRE(bytes_written == 12); + auto const bytes_written = file.value()->write(write_buffer.data(), 0_B, kstd::units::bytes{write_buffer.size()}); + REQUIRE(bytes_written == kstd::units::bytes{12}); auto read_buffer = kstd::vector<std::byte>(42, std::byte{0x00}); - auto const bytes_read = file.value()->read(read_buffer.data(), 0, read_buffer.size()); - REQUIRE(bytes_read == 12); + auto const bytes_read = file.value()->read(read_buffer.data(), 0_B, kstd::units::bytes{read_buffer.size()}); + REQUIRE(bytes_read == kstd::units::bytes{12}); - auto const text = std::string_view{reinterpret_cast<char const *>(read_buffer.data()), *bytes_read}; + auto const text = std::string_view{reinterpret_cast<char const *>(read_buffer.data()), bytes_read->value}; REQUIRE(text == "Hello World!"); auto inode_data = static_cast<kernel::filesystem::ext2::inode *>(file.value().get())->data(); - REQUIRE(inode_data.size == bytes_read); + REQUIRE(inode_data.size == bytes_read->value); } THEN("writing allocates new blocks and updates the inode size") @@ -330,13 +334,13 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 in auto const block_size = fs.block_size(); auto const expected_allocated_blocks = 32 * fs.inode_block_count(inode_data); - auto write_buffer = kstd::vector<std::byte>(block_size * expected_allocated_blocks, std::byte{'A'}); + auto write_buffer = kstd::vector<std::byte>(block_size.value * expected_allocated_blocks, std::byte{'A'}); - auto const bytes_written = file.value()->write(write_buffer.data(), 0, write_buffer.size()); + auto const bytes_written = file.value()->write(write_buffer.data(), 0_B, kstd::units::bytes{write_buffer.size()}); REQUIRE(bytes_written == block_size * expected_allocated_blocks); - auto read_buffer = kstd::vector<std::byte>(block_size * expected_allocated_blocks, std::byte{0x00}); - auto const bytes_read = file.value()->read(read_buffer.data(), 0, read_buffer.size()); + auto read_buffer = kstd::vector<std::byte>(block_size.value * expected_allocated_blocks, std::byte{0x00}); + auto const bytes_read = file.value()->read(read_buffer.data(), 0_B, kstd::units::bytes{read_buffer.size()}); REQUIRE(bytes_read == block_size * expected_allocated_blocks); REQUIRE(std::ranges::all_of(read_buffer, [](std::byte c) { return c == std::byte{'A'}; })); @@ -348,7 +352,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 in THEN("writing to a an inode of type directory panics") { auto write_buffer = kstd::vector<std::byte>(12, std::byte{0xAA}); - REQUIRE_THROWS_AS(information.value()->write(write_buffer.data(), 0, write_buffer.size()), + REQUIRE_THROWS_AS(information.value()->write(write_buffer.data(), 0_B, kstd::units::bytes{write_buffer.size()}), kernel::tests::cpu::halt); } } @@ -356,7 +360,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 in SCENARIO("Ext2 inode write across block boundaries", "[filesystem][ext2][inode]") { - auto const block_size = 1024uz; + auto const block_size = 1024_B; auto device = kstd::make_shared<kernel::tests::devices::block_device>(0, 0, "mock", block_size, 128 * block_size); REQUIRE(device != nullptr); @@ -380,7 +384,7 @@ SCENARIO("Ext2 inode write across block boundaries", "[filesystem][ext2][inode]" auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(device); - auto block_bitmap = std::vector<std::byte>(block_size, std::byte{0x00}); + auto block_bitmap = std::vector<std::byte>(block_size.value, std::byte{0x00}); block_bitmap[0] = std::byte{0b1111'1111}; block_bitmap[1] = std::byte{0b1111'1111}; block_bitmap[2] = std::byte{0b0011'0000}; @@ -392,7 +396,7 @@ SCENARIO("Ext2 inode write across block boundaries", "[filesystem][ext2][inode]" auto inode_data = kernel::filesystem::ext2::inode_data{}; inode_data.size = 5; - inode_data.blocks = 2 * block_size / 512; + inode_data.blocks = 2 * block_size.value / 512; inode_data.block[0] = 20; inode_data.block[1] = 21; inode_data.mode = kernel::filesystem::ext2::constants::mode_regular; @@ -401,7 +405,7 @@ SCENARIO("Ext2 inode write across block boundaries", "[filesystem][ext2][inode]" auto const inode_data_offset = block_group_descriptor.inode_table * block_size + (inode_number - 1) * fs.inode_size(); auto inode = kernel::filesystem::ext2::inode{&fs, inode_number, inode_data}; - REQUIRE(dev_inode->write(&inode, inode_data_offset, sizeof(kernel::filesystem::ext2::inode_data))); + REQUIRE(dev_inode->write(&inode, inode_data_offset, kstd::type_size<kernel::filesystem::ext2::inode_data>)); auto const buffer = kstd::vector<std::byte>{std::byte{'H'}, std::byte{'e'}, std::byte{'l'}, std::byte{'l'}, std::byte{'o'}, std::byte{' '}, std::byte{'W'}, std::byte{'o'}, @@ -411,26 +415,26 @@ SCENARIO("Ext2 inode write across block boundaries", "[filesystem][ext2][inode]" { auto do_read_inode = [&]() { auto inode_data = kernel::filesystem::ext2::inode_data{}; - REQUIRE(dev_inode->read(&inode_data, inode_data_offset, sizeof(kernel::filesystem::ext2::inode_data))); + REQUIRE(dev_inode->read(&inode_data, inode_data_offset, kstd::type_size<kernel::filesystem::ext2::inode_data>)); auto read_inode = kernel::filesystem::ext2::inode{&fs, inode_number, inode_data}; return read_inode; }; THEN("writing in the current size does not update the size and does not allocate new blocks") { - auto const expected_bytes_written = 3; - auto const bytes_written = inode.write(buffer.data(), 0, expected_bytes_written); + auto const expected_bytes_written = 3_B; + auto const bytes_written = inode.write(buffer.data(), 0_B, expected_bytes_written); REQUIRE(bytes_written == expected_bytes_written); auto const text = std::string_view{reinterpret_cast<char const *>(device->data.data() + 20 * block_size), 3}; REQUIRE(text == "Hel"); - auto read_block_bitmap = std::vector<std::byte>(block_size, std::byte{0x00}); + auto read_block_bitmap = std::vector<std::byte>(block_size.value, std::byte{0x00}); REQUIRE(dev_inode->read(read_block_bitmap.data(), block_group_descriptor.block_bitmap * block_size, block_size)); REQUIRE(block_bitmap == read_block_bitmap); auto read_inode = do_read_inode(); - REQUIRE(inode_data.size == read_inode.size()); + REQUIRE(inode_data.size == read_inode.size().value); REQUIRE(inode_data.blocks == read_inode.data().blocks); auto const current_blocks = inode_data.block; @@ -441,20 +445,20 @@ SCENARIO("Ext2 inode write across block boundaries", "[filesystem][ext2][inode]" THEN("writing over the current size (within an existing block) updates the size but does not allocate additional " "blocks") { - auto const offset = block_size - 4; - auto const bytes_written = inode.write(buffer.data(), offset, buffer.size()); - REQUIRE(bytes_written == buffer.size()); + auto const offset = block_size - 4_B; + auto const bytes_written = inode.write(buffer.data(), offset, kstd::units::bytes{buffer.size()}); + REQUIRE(bytes_written == kstd::units::bytes{buffer.size()}); - auto const text = - std::string_view{reinterpret_cast<char const *>(device->data.data() + 21 * block_size - 4), *bytes_written}; + auto const text = std::string_view{ + reinterpret_cast<char const *>(device->data.data() + 21 * block_size.value - 4), bytes_written->value}; REQUIRE(text == "Hello World!"); - auto read_block_bitmap = std::vector<std::byte>(block_size, std::byte{0x00}); + auto read_block_bitmap = std::vector<std::byte>(block_size.value, std::byte{0x00}); REQUIRE(dev_inode->read(read_block_bitmap.data(), block_group_descriptor.block_bitmap * block_size, block_size)); REQUIRE(block_bitmap == read_block_bitmap); auto read_inode = do_read_inode(); - REQUIRE(offset + buffer.size() == read_inode.size()); + REQUIRE(offset + kstd::units::bytes{buffer.size()} == read_inode.size()); REQUIRE(inode_data.blocks == read_inode.data().blocks); auto const current_blocks = inode_data.block; @@ -464,16 +468,16 @@ SCENARIO("Ext2 inode write across block boundaries", "[filesystem][ext2][inode]" THEN("writing over the current size and over allocated blocks updates size and allocates a new block") { - auto const offset = block_size * 2 - 4; - auto const bytes_written = inode.write(buffer.data(), offset, buffer.size()); - REQUIRE(bytes_written == buffer.size()); + auto const offset = block_size * 2 - 4_B; + auto const bytes_written = inode.write(buffer.data(), offset, kstd::units::bytes{buffer.size()}); + REQUIRE(bytes_written == kstd::units::bytes{buffer.size()}); auto read_buffer = std::vector<std::byte>(buffer.size(), std::byte{0x00}); - auto const bytes_read = inode.read(read_buffer.data(), offset, buffer.size()); - auto const text = std::string_view{reinterpret_cast<char const *>(read_buffer.data()), *bytes_read}; + auto const bytes_read = inode.read(read_buffer.data(), offset, kstd::units::bytes{buffer.size()}); + auto const text = std::string_view{reinterpret_cast<char const *>(read_buffer.data()), bytes_read->value}; REQUIRE(text == "Hello World!"); - auto read_block_bitmap = std::vector<std::byte>(block_size, std::byte{0x00}); + auto read_block_bitmap = std::vector<std::byte>(block_size.value, std::byte{0x00}); REQUIRE(dev_inode->read(read_block_bitmap.data(), block_group_descriptor.block_bitmap * block_size, block_size)); auto expected_block_bitmap = block_bitmap; @@ -481,7 +485,7 @@ SCENARIO("Ext2 inode write across block boundaries", "[filesystem][ext2][inode]" REQUIRE(expected_block_bitmap == read_block_bitmap); auto read_inode = do_read_inode(); - REQUIRE(offset + buffer.size() == read_inode.size()); + REQUIRE(offset + kstd::units::bytes{buffer.size()} == read_inode.size()); REQUIRE(inode_data.blocks + 2 == read_inode.data().blocks); auto expected_blocks = inode_data.block; @@ -493,7 +497,8 @@ SCENARIO("Ext2 inode write across block boundaries", "[filesystem][ext2][inode]" THEN("writing over the current size and over the number of free blocks") { auto const offset = 65 * block_size; - REQUIRE_THROWS_AS(inode.write(buffer.data(), offset, buffer.size()), kernel::tests::cpu::halt); + REQUIRE_THROWS_AS(inode.write(buffer.data(), offset, kstd::units::bytes{buffer.size()}), + kernel::tests::cpu::halt); } } } @@ -501,7 +506,7 @@ SCENARIO("Ext2 inode write across block boundaries", "[filesystem][ext2][inode]" SCENARIO("Ext2 inode get_size() and set_size() handles size correctly depending on revision level", "[filesystem][ext2][inode]") { - auto const block_size = 1024uz; + auto const block_size = 1024_B; auto superblock = kernel::filesystem::ext2::superblock{}; superblock.magic = kernel::filesystem::ext2::constants::magic_number; @@ -528,7 +533,7 @@ SCENARIO("Ext2 inode get_size() and set_size() handles size correctly depending data.size = 256; data.dir_acl = 32; - auto const verify_size_and_set_size = [&](uint16_t mode, uint64_t expected_initial_size, + auto const verify_size_and_set_size = [&](uint16_t mode, kstd::units::bytes expected_initial_size, uint32_t expected_dir_acl_after_set_size) { data.mode = mode; @@ -536,21 +541,21 @@ SCENARIO("Ext2 inode get_size() and set_size() handles size correctly depending REQUIRE(inode.size() == expected_initial_size); - inode.set_size(12); + inode.set_size(12_B); - REQUIRE(inode.size() == 12); + REQUIRE(inode.size() == 12_B); REQUIRE(inode.data().size == 12); REQUIRE(inode.data().dir_acl == expected_dir_acl_after_set_size); }; THEN("the inode size is 256 if mode = regular") { - verify_size_and_set_size(kernel::filesystem::ext2::constants::mode_regular, 256, 32); + verify_size_and_set_size(kernel::filesystem::ext2::constants::mode_regular, 256_B, 32); } THEN("the inode size is 256 if mode = directory") { - verify_size_and_set_size(kernel::filesystem::ext2::constants::mode_directory, 256, 32); + verify_size_and_set_size(kernel::filesystem::ext2::constants::mode_directory, 256_B, 32); } } @@ -571,7 +576,7 @@ SCENARIO("Ext2 inode get_size() and set_size() handles size correctly depending data.size = 256; data.dir_acl = 32; - auto const verify_size_and_set_size = [&](uint16_t mode, uint64_t expected_initial_size, + auto const verify_size_and_set_size = [&](uint16_t mode, kstd::units::bytes expected_initial_size, uint32_t expected_dir_acl_after_set_size) { data.mode = mode; @@ -579,21 +584,21 @@ SCENARIO("Ext2 inode get_size() and set_size() handles size correctly depending REQUIRE(inode.size() == expected_initial_size); - inode.set_size(12); + inode.set_size(12_B); - REQUIRE(inode.size() == 12); + REQUIRE(inode.size() == 12_B); REQUIRE(inode.data().size == 12); REQUIRE(inode.data().dir_acl == expected_dir_acl_after_set_size); }; THEN("the inode size is 256 if mode = regular") { - verify_size_and_set_size(kernel::filesystem::ext2::constants::mode_regular, 0x0000'0020'0000'0100, 0); + verify_size_and_set_size(kernel::filesystem::ext2::constants::mode_regular, 0x0000'0020'0000'0100_B, 0); } THEN("the inode size is 256 if mode = directory") { - verify_size_and_set_size(kernel::filesystem::ext2::constants::mode_directory, 256, 32); + verify_size_and_set_size(kernel::filesystem::ext2::constants::mode_directory, 256_B, 32); } } } diff --git a/kernel/kernel/filesystem/inode.hpp b/kernel/kernel/filesystem/inode.hpp index cfddebf6..67487a8b 100644 --- a/kernel/kernel/filesystem/inode.hpp +++ b/kernel/kernel/filesystem/inode.hpp @@ -2,8 +2,7 @@ #define TEACH_OS_KERNEL_FILESYSTEM_INODE_HPP #include <kstd/result.hpp> - -#include <cstddef> +#include <kstd/units.hpp> namespace kernel::filesystem { @@ -30,7 +29,8 @@ namespace kernel::filesystem @param size Number of bytes requested. @return Number of bytes read. */ - virtual auto read(void * buffer, size_t offset, size_t size) const -> kstd::result<size_t> = 0; + virtual auto read(void * buffer, kstd::units::bytes offset, kstd::units::bytes size) const + -> kstd::result<kstd::units::bytes> = 0; /** @brief Writes to the inode into a @p buffer, starting at the specified @p offset and for a given @p size. This @@ -40,7 +40,8 @@ namespace kernel::filesystem @param size Number of bytes to write. @return Number of bytes written. */ - virtual auto write(void const * buffer, size_t offset, size_t size) -> kstd::result<size_t> = 0; + virtual auto write(void const * buffer, kstd::units::bytes offset, kstd::units::bytes size) + -> kstd::result<kstd::units::bytes> = 0; /** @brief Returns whether the inode is a directory. diff --git a/kernel/kernel/filesystem/open_file_descriptor.cpp b/kernel/kernel/filesystem/open_file_descriptor.cpp index ecf3e725..6277d0b6 100644 --- a/kernel/kernel/filesystem/open_file_descriptor.cpp +++ b/kernel/kernel/filesystem/open_file_descriptor.cpp @@ -5,6 +5,7 @@ #include <kstd/memory.hpp> #include <kstd/os/error.hpp> #include <kstd/result.hpp> +#include <kstd/units.hpp> #include <cstddef> @@ -20,7 +21,7 @@ namespace kernel::filesystem } } - auto open_file_descriptor::read(void * buffer, size_t size) -> kstd::result<size_t> + auto open_file_descriptor::read(void * buffer, kstd::units::bytes size) -> kstd::result<kstd::units::bytes> { if (auto result = m_dentry->get_inode()->read(buffer, m_offset, size); !result) { @@ -34,7 +35,7 @@ namespace kernel::filesystem } } - auto open_file_descriptor::write(void const * buffer, size_t size) -> kstd::result<size_t> + auto open_file_descriptor::write(void const * buffer, kstd::units::bytes size) -> kstd::result<kstd::units::bytes> { if (auto result = m_dentry->get_inode()->write(buffer, m_offset, size); !result) { @@ -48,7 +49,7 @@ namespace kernel::filesystem } } - auto open_file_descriptor::offset() const -> size_t + auto open_file_descriptor::offset() const -> kstd::units::bytes { return m_offset; } diff --git a/kernel/kernel/filesystem/open_file_descriptor.hpp b/kernel/kernel/filesystem/open_file_descriptor.hpp index f6899a31..1ecc09a9 100644 --- a/kernel/kernel/filesystem/open_file_descriptor.hpp +++ b/kernel/kernel/filesystem/open_file_descriptor.hpp @@ -5,8 +5,7 @@ #include <kstd/memory.hpp> #include <kstd/result.hpp> - -#include <cstddef> +#include <kstd/units.hpp> namespace kernel::filesystem { @@ -35,7 +34,7 @@ namespace kernel::filesystem @param size The number of bytes to read. @return The number of bytes read. */ - auto read(void * buffer, size_t size) -> kstd::result<size_t>; + auto read(void * buffer, kstd::units::bytes size) -> kstd::result<kstd::units::bytes>; /** @brief Writes data to the open file descriptor from a @p buffer, starting at the current file offset and for a @@ -45,13 +44,13 @@ namespace kernel::filesystem @param size The number of bytes to write. @return The number of bytes written. */ - auto write(void const * buffer, size_t size) -> kstd::result<size_t>; + auto write(void const * buffer, kstd::units::bytes size) -> kstd::result<kstd::units::bytes>; /** @brief Returns the current file offset for this open file descriptor. @return The current file offset in bytes. */ - [[nodiscard]] auto offset() const -> size_t; + [[nodiscard]] auto offset() const -> kstd::units::bytes; /** @brief Return a reference to the dentry associated with this open file descriptor. @@ -61,7 +60,7 @@ namespace kernel::filesystem private: kstd::shared_ptr<dentry> m_dentry; - size_t m_offset; + kstd::units::bytes m_offset; }; } // namespace kernel::filesystem diff --git a/kernel/kernel/filesystem/open_file_descriptor.tests.cpp b/kernel/kernel/filesystem/open_file_descriptor.tests.cpp index 67883efd..6653ed86 100644 --- a/kernel/kernel/filesystem/open_file_descriptor.tests.cpp +++ b/kernel/kernel/filesystem/open_file_descriptor.tests.cpp @@ -8,6 +8,7 @@ #include <kstd/memory.hpp> #include <kstd/print.hpp> +#include <kstd/units.hpp> #include <kstd/vector.hpp> #include <catch2/catch_test_macros.hpp> @@ -16,6 +17,8 @@ #include <filesystem> #include <string_view> +using namespace kstd::units_literals; + SCENARIO("Open file descriptor construction", "[filesystem][open_file_descriptor]") { GIVEN("a dentry and an open file descriptor for that dentry") @@ -26,7 +29,7 @@ SCENARIO("Open file descriptor construction", "[filesystem][open_file_descriptor THEN("the initial offset is zero") { - REQUIRE(file_descriptor.offset() == 0); + REQUIRE(file_descriptor.offset() == 0_B); } } } @@ -41,30 +44,30 @@ SCENARIO("Open file descriptor read/write offset management", "[filesystem][open THEN("the offset is updated correctly after reads") { - REQUIRE(file_descriptor.read(nullptr, 100) == 100); - REQUIRE(file_descriptor.offset() == 100); - REQUIRE(file_descriptor.read(nullptr, 50) == 50); - REQUIRE(file_descriptor.offset() == 150); + REQUIRE(file_descriptor.read(nullptr, 100_B) == 100_B); + REQUIRE(file_descriptor.offset() == 100_B); + REQUIRE(file_descriptor.read(nullptr, 50_B) == 50_B); + REQUIRE(file_descriptor.offset() == 150_B); } THEN("the offset is updated correctly after writes") { - REQUIRE(file_descriptor.write(nullptr, 200) == 200); - REQUIRE(file_descriptor.offset() == 200); - REQUIRE(file_descriptor.write(nullptr, 25) == 25); - REQUIRE(file_descriptor.offset() == 225); + REQUIRE(file_descriptor.write(nullptr, 200_B) == 200_B); + REQUIRE(file_descriptor.offset() == 200_B); + REQUIRE(file_descriptor.write(nullptr, 25_B) == 25_B); + REQUIRE(file_descriptor.offset() == 225_B); } THEN("reads and writes both update the same offset") { - REQUIRE(file_descriptor.read(nullptr, 10) == 10); - REQUIRE(file_descriptor.offset() == 10); - REQUIRE(file_descriptor.write(nullptr, 20) == 20); - REQUIRE(file_descriptor.offset() == 30); - REQUIRE(file_descriptor.read(nullptr, 5) == 5); - REQUIRE(file_descriptor.offset() == 35); - REQUIRE(file_descriptor.write(nullptr, 15) == 15); - REQUIRE(file_descriptor.offset() == 50); + REQUIRE(file_descriptor.read(nullptr, 10_B) == 10_B); + REQUIRE(file_descriptor.offset() == 10_B); + REQUIRE(file_descriptor.write(nullptr, 20_B) == 20_B); + REQUIRE(file_descriptor.offset() == 30_B); + REQUIRE(file_descriptor.read(nullptr, 5_B) == 5_B); + REQUIRE(file_descriptor.offset() == 35_B); + REQUIRE(file_descriptor.write(nullptr, 15_B) == 15_B); + REQUIRE(file_descriptor.offset() == 50_B); } } } @@ -87,47 +90,49 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Ope THEN("the file can be read and the offset is updated") { kstd::vector<std::byte> buffer(32); - auto bytes_read = ofd->read(buffer.data(), buffer.size()); - REQUIRE(bytes_read == 7); - REQUIRE(ofd->offset() == 7); + auto bytes_read = ofd->read(buffer.data(), kstd::units::bytes{buffer.size()}); + REQUIRE(bytes_read == 7_B); + REQUIRE(ofd->offset() == 7_B); - std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), *bytes_read}; + std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), bytes_read->value}; REQUIRE(buffer_as_str == "info_1\n"); } THEN("the file can be read multiple times and the offset is updated") { kstd::vector<std::byte> buffer(4); - auto bytes_read_1 = ofd->read(buffer.data(), buffer.size() / 2); - REQUIRE(bytes_read_1 == buffer.size() / 2); - REQUIRE(ofd->offset() == buffer.size() / 2); + auto bytes_read_1 = ofd->read(buffer.data(), kstd::units::bytes{buffer.size() / 2}); + REQUIRE(bytes_read_1 == kstd::units::bytes{buffer.size() / 2}); + REQUIRE(ofd->offset() == kstd::units::bytes{buffer.size() / 2}); - auto bytes_read_2 = ofd->read(buffer.data() + buffer.size() / 2, buffer.size() / 2); - REQUIRE(bytes_read_2 == buffer.size() / 2); - REQUIRE(ofd->offset() == buffer.size()); + auto bytes_read_2 = ofd->read(buffer.data() + buffer.size() / 2, kstd::units::bytes{buffer.size() / 2}); + REQUIRE(bytes_read_2 == kstd::units::bytes{buffer.size() / 2}); + REQUIRE(ofd->offset() == kstd::units::bytes{buffer.size()}); - std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), *bytes_read_1 + *bytes_read_2}; + std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), + bytes_read_1->value + bytes_read_2->value}; REQUIRE(buffer_as_str == "info"); } THEN("the file can be written to and the offset is updated") { auto write_buffer = kstd::vector<std::byte>(12, std::byte{0xAA}); - auto const bytes_written = ofd->write(write_buffer.data(), write_buffer.size()); - REQUIRE(bytes_written == 12); - REQUIRE(ofd->offset() == 12); + auto const bytes_written = ofd->write(write_buffer.data(), kstd::units::bytes{write_buffer.size()}); + REQUIRE(bytes_written == 12_B); + REQUIRE(ofd->offset() == 12_B); } THEN("the file can be written to multiple times and the offset is updated") { auto write_buffer = kstd::vector<std::byte>(8, std::byte{0xAA}); - auto const bytes_written_1 = ofd->write(write_buffer.data(), write_buffer.size() / 2); - REQUIRE(bytes_written_1 == write_buffer.size() / 2); - REQUIRE(ofd->offset() == write_buffer.size() / 2); - - auto const bytes_written_2 = ofd->write(write_buffer.data() + write_buffer.size() / 2, write_buffer.size() / 2); - REQUIRE(bytes_written_2 == write_buffer.size() / 2); - REQUIRE(ofd->offset() == write_buffer.size()); + auto const bytes_written_1 = ofd->write(write_buffer.data(), kstd::units::bytes{write_buffer.size() / 2}); + REQUIRE(bytes_written_1 == kstd::units::bytes{write_buffer.size() / 2}); + REQUIRE(ofd->offset() == kstd::units::bytes{write_buffer.size() / 2}); + + auto const bytes_written_2 = + ofd->write(write_buffer.data() + write_buffer.size() / 2, kstd::units::bytes{write_buffer.size() / 2}); + REQUIRE(bytes_written_2 == kstd::units::bytes{write_buffer.size() / 2}); + REQUIRE(ofd->offset() == kstd::units::bytes{write_buffer.size()}); } } } diff --git a/kernel/kernel/filesystem/rootfs/inode.cpp b/kernel/kernel/filesystem/rootfs/inode.cpp index e3e9d641..43aee16e 100644 --- a/kernel/kernel/filesystem/rootfs/inode.cpp +++ b/kernel/kernel/filesystem/rootfs/inode.cpp @@ -3,19 +3,18 @@ #include <kernel/filesystem/rootfs/inode.hpp> #include <kstd/result.hpp> - -#include <cstddef> +#include <kstd/units.hpp> namespace kernel::filesystem::rootfs { - auto inode::read(void *, size_t, size_t) const -> kstd::result<size_t> + auto inode::read(void *, kstd::units::bytes, kstd::units::bytes) const -> kstd::result<kstd::units::bytes> { - return 0; + return kstd::units::bytes{}; } - auto inode::write(void const *, size_t, size_t) -> kstd::result<size_t> + auto inode::write(void const *, kstd::units::bytes, kstd::units::bytes) -> kstd::result<kstd::units::bytes> { - return 0; + return kstd::units::bytes{}; } auto inode::is_directory() const -> bool diff --git a/kernel/kernel/filesystem/rootfs/inode.hpp b/kernel/kernel/filesystem/rootfs/inode.hpp index 777f13f9..a61e83f1 100644 --- a/kernel/kernel/filesystem/rootfs/inode.hpp +++ b/kernel/kernel/filesystem/rootfs/inode.hpp @@ -6,10 +6,9 @@ #include <kstd/memory.hpp> #include <kstd/result.hpp> #include <kstd/string.hpp> +#include <kstd/units.hpp> #include <kstd/vector.hpp> -#include <cstddef> - namespace kernel::filesystem::rootfs { /** @@ -24,7 +23,8 @@ namespace kernel::filesystem::rootfs @param size Number of bytes requested. @return Number of bytes read (always 0 because this inode does not expose file data). */ - auto read(void * buffer, size_t offset, size_t size) const -> kstd::result<size_t> override; + auto read(void * buffer, kstd::units::bytes offset, kstd::units::bytes size) const + -> kstd::result<kstd::units::bytes> override; /** @brief Writes to the rootfs directory inode. @@ -33,7 +33,8 @@ namespace kernel::filesystem::rootfs @param size Number of bytes requested. @return Number of bytes written (always 0 because writes are not supported for this inode). */ - auto write(void const * buffer, size_t offset, size_t size) -> kstd::result<size_t> override; + auto write(void const * buffer, kstd::units::bytes offset, kstd::units::bytes size) + -> kstd::result<kstd::units::bytes> override; /** @brief Check if this inode represents a directory. diff --git a/kernel/kernel/filesystem/rootfs/inode.tests.cpp b/kernel/kernel/filesystem/rootfs/inode.tests.cpp index 0b48ca71..9819743d 100644 --- a/kernel/kernel/filesystem/rootfs/inode.tests.cpp +++ b/kernel/kernel/filesystem/rootfs/inode.tests.cpp @@ -2,10 +2,13 @@ #include <kstd/memory.hpp> #include <kstd/print.hpp> +#include <kstd/units.hpp> #include <kstd/vector.hpp> #include <catch2/catch_test_macros.hpp> +using namespace kstd::units_literals; + SCENARIO("Rootfs inode read/write", "[filesystem][rootfs][inode]") { GIVEN("a rootfs inode") @@ -15,22 +18,22 @@ SCENARIO("Rootfs inode read/write", "[filesystem][rootfs][inode]") WHEN("reading from the inode") { kstd::vector<char> buffer(10); - auto bytes_read = inode.read(buffer.data(), 0, buffer.size()); + auto bytes_read = inode.read(buffer.data(), 0_B, kstd::units::bytes{buffer.size()}); THEN("no bytes are read") { - REQUIRE(bytes_read == 0); + REQUIRE(bytes_read == 0_B); } } WHEN("writing to the inode") { kstd::vector<char> buffer(10, 'x'); - auto bytes_written = inode.write(buffer.data(), 0, buffer.size()); + auto bytes_written = inode.write(buffer.data(), 0_B, kstd::units::bytes{buffer.size()}); THEN("no bytes are written") { - REQUIRE(bytes_written == 0); + REQUIRE(bytes_written == 0_B); } } } diff --git a/kernel/kernel/filesystem/vfs.cpp b/kernel/kernel/filesystem/vfs.cpp index 9a78b6f8..66faf15a 100644 --- a/kernel/kernel/filesystem/vfs.cpp +++ b/kernel/kernel/filesystem/vfs.cpp @@ -16,6 +16,7 @@ #include <kstd/memory.hpp> #include <kstd/result.hpp> #include <kstd/system_error.hpp> +#include <kstd/units.hpp> #include <kstd/vector.hpp> #include <algorithm> @@ -26,6 +27,8 @@ #include <string_view> #include <utility> +using namespace kstd::units_literals; + namespace { constinit auto static active_vfs = std::optional<kernel::filesystem::vfs>{}; @@ -337,13 +340,14 @@ namespace kernel::filesystem } kstd::vector<uint8_t> buffer(constants::symlink_max_path_length); - auto const bytes_read = next_dentry->get_inode()->read(buffer.data(), 0, buffer.size()); + auto const bytes_read = next_dentry->get_inode()->read(buffer.data(), 0_B, kstd::units::bytes{buffer.size()}); if (!bytes_read) { return kstd::failure(bytes_read.error()); } - auto const symbolic_link_path = std::string_view{reinterpret_cast<char const *>(buffer.data()), *bytes_read}; + auto const symbolic_link_path = + std::string_view{reinterpret_cast<char const *>(buffer.data()), bytes_read->value}; auto symbolic_link_parts = path::split(symbolic_link_path); kstd::vector symbolic_link_parts_vector(symbolic_link_parts.begin(), symbolic_link_parts.end()); diff --git a/kernel/kernel/filesystem/vfs.tests.cpp b/kernel/kernel/filesystem/vfs.tests.cpp index c70c13c8..5e73db4a 100644 --- a/kernel/kernel/filesystem/vfs.tests.cpp +++ b/kernel/kernel/filesystem/vfs.tests.cpp @@ -396,8 +396,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto sheep_1_ofd = kstd::make_shared<kernel::filesystem::open_file_descriptor>(dentry.value()); kstd::vector<std::byte> buffer(7); - auto bytes_read = sheep_1_ofd->read(buffer.data(), buffer.size()); - std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), *bytes_read}; + auto bytes_read = sheep_1_ofd->read(buffer.data(), kstd::units::bytes{buffer.size()}); + std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), bytes_read->value}; REQUIRE(buffer_as_str == "sheep_1"); REQUIRE(vfs.close(dentry.value()->absolute_path())); @@ -423,13 +423,13 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto goat_1_ofd = kstd::make_shared<kernel::filesystem::open_file_descriptor>(goat_1.value()); kstd::vector<std::byte> sheep_buffer(7); - auto bytes_read = sheep_1_ofd->read(sheep_buffer.data(), sheep_buffer.size()); - std::string_view buffer_as_str{reinterpret_cast<char *>(sheep_buffer.data()), *bytes_read}; + auto bytes_read = sheep_1_ofd->read(sheep_buffer.data(), kstd::units::bytes{sheep_buffer.size()}); + std::string_view buffer_as_str{reinterpret_cast<char *>(sheep_buffer.data()), bytes_read->value}; REQUIRE(buffer_as_str == "sheep_1"); kstd::vector<std::byte> goat_buffer(6); - bytes_read = goat_1_ofd->read(goat_buffer.data(), goat_buffer.size()); - buffer_as_str = std::string_view{reinterpret_cast<char *>(goat_buffer.data()), *bytes_read}; + bytes_read = goat_1_ofd->read(goat_buffer.data(), kstd::units::bytes{goat_buffer.size()}); + buffer_as_str = std::string_view{reinterpret_cast<char *>(goat_buffer.data()), bytes_read->value}; REQUIRE(buffer_as_str == "goat_1"); REQUIRE(vfs.close(sheep_1.value()->absolute_path())); diff --git a/kernel/kernel/main.cpp b/kernel/kernel/main.cpp index 525e25c4..366fcc26 100644 --- a/kernel/kernel/main.cpp +++ b/kernel/kernel/main.cpp @@ -40,7 +40,7 @@ auto run_demo() -> void // 2) read from the file kstd::vector<std::byte> buffer_1{10}; - auto bytes_read = *kapi::filesystem::read(fd_1.value(), buffer_1); + auto bytes_read = kapi::filesystem::read(fd_1.value(), buffer_1)->value; auto buffer_as_str = std::string_view{reinterpret_cast<char *>(buffer_1.data()), bytes_read}; kstd::println("--> read {} bytes from /entrance/tickets.txt: {}", bytes_read, buffer_as_str); kstd::println(""); @@ -79,7 +79,7 @@ auto run_demo() -> void // 6) read from the new file kstd::vector<std::byte> buffer_2{10}; - bytes_read = *kapi::filesystem::read(fd_2.value(), buffer_2); + bytes_read = kapi::filesystem::read(fd_2.value(), buffer_2)->value; buffer_as_str = std::string_view{reinterpret_cast<char *>(buffer_2.data()), static_cast<size_t>(bytes_read)}; kstd::println("--> read {} bytes from /entrance/information/info_1.txt: {} ", bytes_read, buffer_as_str); @@ -97,13 +97,13 @@ auto run_demo() -> void // 8) read from the device file kstd::vector<std::byte> buffer_3{2}; - bytes_read = *kapi::filesystem::read(fd_3.value(), buffer_3); + bytes_read = kapi::filesystem::read(fd_3.value(), buffer_3)->value; kstd::println("--> read {} bytes from /dev/ram2: {::#04x} ", bytes_read, buffer_3); // 9) write to the device file auto const default_buffer_value = std::byte{0xAA}; kstd::vector<std::byte> write_buffer{default_buffer_value, default_buffer_value}; - auto bytes_written = *kapi::filesystem::write(fd_3.value(), write_buffer); + auto bytes_written = kapi::filesystem::write(fd_3.value(), write_buffer)->value; kstd::println("--> written {} bytes to /dev/ram2: {::#04x}", bytes_written, write_buffer); // 10) do memory dump to show that the write to the device file had an effect @@ -135,7 +135,7 @@ auto run_demo() -> void kstd::vector<std::byte> test_write_buffer{ std::byte{'H'}, std::byte{'e'}, std::byte{'l'}, std::byte{'l'}, std::byte{'o'}, std::byte{' '}, std::byte{'T'}, std::byte{'e'}, std::byte{'a'}, std::byte{'c'}, std::byte{'h'}, std::byte{'O'}, std::byte{'S'}}; - bytes_written = *kapi::filesystem::write(*fd_4, test_write_buffer); + bytes_written = kapi::filesystem::write(*fd_4, test_write_buffer)->value; kstd::println("--> written {} bytes to /test_files/test_file.txt: {::#04x}", bytes_written, test_write_buffer); // 14) dmp the module after create new directory and file diff --git a/kernel/kernel/test_support/devices/block_device.cpp b/kernel/kernel/test_support/devices/block_device.cpp index 2dda5dec..cb80370b 100644 --- a/kernel/kernel/test_support/devices/block_device.cpp +++ b/kernel/kernel/test_support/devices/block_device.cpp @@ -2,7 +2,9 @@ #include <kernel/devices/block_device.hpp> +#include <kstd/result.hpp> #include <kstd/string.hpp> +#include <kstd/units.hpp> #include <kstd/vector.hpp> #include <algorithm> @@ -11,13 +13,15 @@ #include <cstring> #include <string.h> +using namespace kstd::units_literals; + namespace kernel::tests::devices { - block_device::block_device(size_t major, size_t minor, kstd::string const & name, size_t block_size, - size_t initial_size) + block_device::block_device(size_t major, size_t minor, kstd::string const & name, kstd::units::bytes block_size, + kstd::units::bytes initial_size) : kernel::devices::block_device(major, minor, name, block_size) { - data.resize(initial_size, 0); + data.resize(initial_size.value, 0); } auto block_device::init() -> bool @@ -25,37 +29,41 @@ namespace kernel::tests::devices return true; } - auto block_device::read_block(size_t block_index, void * buffer) const -> void + auto block_device::read_block(size_t block_index, void * buffer) const -> kstd::result<kstd::units::bytes> { auto const offset = block_index * block_size(); - if (offset >= data.size()) + if (offset.value >= data.size()) { - kstd::libc::memset(buffer, 0, block_size()); - return; + kstd::libc::memset(buffer, 0, block_size().value); + return 0_B; } - auto const bytes_to_read = std::min(block_size(), data.size() - offset); - kstd::libc::memcpy(buffer, data.data() + offset, bytes_to_read); + auto const bytes_to_read = std::min(block_size(), kstd::units::bytes{data.size()} - offset); + kstd::libc::memcpy(buffer, data.data() + offset, bytes_to_read.value); if (bytes_to_read < block_size()) { - kstd::libc::memset(static_cast<uint8_t *>(buffer) + bytes_to_read, 0, block_size() - bytes_to_read); + kstd::libc::memset(static_cast<uint8_t *>(buffer) + bytes_to_read, 0, + static_cast<std::size_t>(block_size() - bytes_to_read)); } + + return bytes_to_read; } - auto block_device::write_block(size_t block_index, void const * buffer) -> void + auto block_device::write_block(size_t block_index, void const * buffer) -> kstd::result<kstd::units::bytes> { auto const offset = block_index * block_size(); auto const write_end = offset + block_size(); - if (write_end > data.size()) + if (write_end.value > data.size()) { - data.resize(write_end, 0); + data.resize(write_end.value, 0); } - kstd::libc::memcpy(data.data() + offset, static_cast<uint8_t const *>(buffer), block_size()); + kstd::libc::memcpy(data.data() + offset, static_cast<uint8_t const *>(buffer), block_size().value); + return block_size(); } - auto block_device::size() const -> size_t + auto block_device::size() const -> kstd::units::bytes { - return data.size(); + return kstd::units::bytes{data.size()}; } } // namespace kernel::tests::devices
\ No newline at end of file diff --git a/kernel/kernel/test_support/devices/block_device.hpp b/kernel/kernel/test_support/devices/block_device.hpp index d83dddd1..147c117c 100644 --- a/kernel/kernel/test_support/devices/block_device.hpp +++ b/kernel/kernel/test_support/devices/block_device.hpp @@ -3,7 +3,9 @@ #include <kernel/devices/block_device.hpp> +#include <kstd/result.hpp> #include <kstd/string.hpp> +#include <kstd/units.hpp> #include <kstd/vector.hpp> #include <cstddef> @@ -14,14 +16,15 @@ namespace kernel::tests::devices struct block_device : kernel::devices::block_device { - block_device(size_t major, size_t minor, kstd::string const & name, size_t block_size, size_t initial_size = 0); + block_device(size_t major, size_t minor, kstd::string const & name, kstd::units::bytes block_size, + kstd::units::bytes initial_size = {}); auto init() -> bool override; - auto read_block(size_t block_index, void * buffer) const -> void override; - auto write_block(size_t block_index, void const * buffer) -> void override; + auto read_block(size_t block_index, void * buffer) const -> kstd::result<kstd::units::bytes> override; + auto write_block(size_t block_index, void const * buffer) -> kstd::result<kstd::units::bytes> override; - [[nodiscard]] auto size() const -> size_t override; + [[nodiscard]] auto size() const -> kstd::units::bytes override; kstd::vector<uint8_t> data{}; }; diff --git a/kernel/kernel/test_support/filesystem/ext2.cpp b/kernel/kernel/test_support/filesystem/ext2.cpp index 3a7449ed..ff01cbb2 100644 --- a/kernel/kernel/test_support/filesystem/ext2.cpp +++ b/kernel/kernel/test_support/filesystem/ext2.cpp @@ -6,9 +6,12 @@ #include <kernel/filesystem/ext2/superblock.hpp> #include <kernel/test_support/devices/block_device.hpp> +#include <kstd/units.hpp> + #include <cstdint> #include <cstring> -#include <vector> + +using namespace kstd::units_literals; namespace kernel::tests::filesystem::ext2 { @@ -17,21 +20,21 @@ namespace kernel::tests::filesystem::ext2 constexpr uint32_t root_directory_data_block = 20; } // namespace - auto write_bytes(kernel::tests::devices::block_device & device, size_t offset, void const * source, size_t size) - -> void + auto write_bytes(kernel::tests::devices::block_device & device, kstd::units::bytes offset, void const * source, + kstd::units::bytes size) -> void { auto const required_size = offset + size; - if (device.data.size() < required_size) + if (kstd::units::bytes{device.data.size()} < required_size) { - device.data.resize(required_size, 0); + device.data.resize(required_size.value, 0); } - std::memcpy(device.data.data() + offset, source, size); + std::memcpy(device.data.data() + offset, source, size.value); } - auto write_u32(kernel::tests::devices::block_device & device, size_t offset, uint32_t value) -> void + auto write_u32(kernel::tests::devices::block_device & device, kstd::units::bytes offset, uint32_t value) -> void { - write_bytes(device, offset, &value, sizeof(value)); + write_bytes(device, offset, &value, kstd::object_size(value)); } auto setup_mock_ext2_layout(kernel::tests::devices::block_device & device) -> void @@ -60,8 +63,9 @@ namespace kernel::tests::filesystem::ext2 kernel::filesystem::ext2::superblock const & superblock, kernel::filesystem::ext2::block_group_descriptor const & group_descriptor) -> void { - write_bytes(device, kernel::filesystem::ext2::constants::superblock_offset, &superblock, sizeof(superblock)); - write_bytes(device, 2048, &group_descriptor, sizeof(group_descriptor)); + write_bytes(device, kernel::filesystem::ext2::constants::superblock_offset, &superblock, + kstd::object_size(superblock)); + write_bytes(device, 2048_B, &group_descriptor, kstd::object_size(group_descriptor)); auto root_inode_data = kernel::filesystem::ext2::inode_data{}; root_inode_data.mode = kernel::filesystem::ext2::constants::mode_directory; @@ -70,7 +74,7 @@ namespace kernel::tests::filesystem::ext2 auto const root_inode_offset = static_cast<size_t>(group_descriptor.inode_table) * kernel::filesystem::ext2::constants::base_block_size + - (kernel::filesystem::ext2::constants::root_inode_number - 1) * superblock.inode_size; - write_bytes(device, root_inode_offset, &root_inode_data, sizeof(root_inode_data)); + (kernel::filesystem::ext2::constants::root_inode_number - 1) * kstd::units::bytes{superblock.inode_size}; + write_bytes(device, root_inode_offset, &root_inode_data, kstd::object_size(root_inode_data)); } } // namespace kernel::tests::filesystem::ext2
\ No newline at end of file diff --git a/kernel/kernel/test_support/filesystem/ext2.hpp b/kernel/kernel/test_support/filesystem/ext2.hpp index 3dd80ea3..a8f73ab5 100644 --- a/kernel/kernel/test_support/filesystem/ext2.hpp +++ b/kernel/kernel/test_support/filesystem/ext2.hpp @@ -5,14 +5,15 @@ #include <kernel/filesystem/ext2/superblock.hpp> #include <kernel/test_support/devices/block_device.hpp> -#include <cstddef> +#include <kstd/units.hpp> + #include <cstdint> namespace kernel::tests::filesystem::ext2 { - auto write_bytes(kernel::tests::devices::block_device & device, size_t offset, void const * source, size_t size) - -> void; - auto write_u32(kernel::tests::devices::block_device & device, size_t offset, uint32_t value) -> void; + auto write_bytes(kernel::tests::devices::block_device & device, kstd::units::bytes offset, void const * source, + kstd::units::bytes size) -> void; + auto write_u32(kernel::tests::devices::block_device & device, kstd::units::bytes offset, uint32_t value) -> void; auto setup_mock_ext2_layout(kernel::tests::devices::block_device & device) -> void; auto setup_mock_ext2_layout(kernel::tests::devices::block_device & device, kernel::filesystem::ext2::superblock const & superblock) -> void; diff --git a/kernel/kernel/test_support/filesystem/inode.cpp b/kernel/kernel/test_support/filesystem/inode.cpp index fd8e4d69..1d090589 100644 --- a/kernel/kernel/test_support/filesystem/inode.cpp +++ b/kernel/kernel/test_support/filesystem/inode.cpp @@ -3,17 +3,16 @@ #include <kernel/filesystem/inode.hpp> #include <kstd/result.hpp> - -#include <cstddef> +#include <kstd/units.hpp> namespace kernel::tests::filesystem { - auto inode::read(void *, size_t, size_t size) const -> kstd::result<size_t> + auto inode::read(void *, kstd::units::bytes, kstd::units::bytes size) const -> kstd::result<kstd::units::bytes> { return size; } - auto inode::write(void const *, size_t, size_t size) -> kstd::result<size_t> + auto inode::write(void const *, kstd::units::bytes, kstd::units::bytes size) -> kstd::result<kstd::units::bytes> { return size; } diff --git a/kernel/kernel/test_support/filesystem/inode.hpp b/kernel/kernel/test_support/filesystem/inode.hpp index da2e3e21..d2fbf19d 100644 --- a/kernel/kernel/test_support/filesystem/inode.hpp +++ b/kernel/kernel/test_support/filesystem/inode.hpp @@ -4,15 +4,16 @@ #include <kernel/filesystem/inode.hpp> #include <kstd/result.hpp> - -#include <cstddef> +#include <kstd/units.hpp> namespace kernel::tests::filesystem { struct inode : kernel::filesystem::inode { - auto read(void * buffer, size_t offset, size_t size) const -> kstd::result<size_t> override; - auto write(void const * buffer, size_t offset, size_t size) -> kstd::result<size_t> override; + auto read(void * buffer, kstd::units::bytes offset, kstd::units::bytes size) const + -> kstd::result<kstd::units::bytes> override; + auto write(void const * buffer, kstd::units::bytes offset, kstd::units::bytes size) + -> kstd::result<kstd::units::bytes> override; [[nodiscard]] auto is_regular() const -> bool override; }; |
