From 035c8d6e38fd901e6769a81f67b8d9e1e3fcea20 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 26 Feb 2026 11:24:27 +0100 Subject: implemented boot_modules and boot_module_registry, init boot_modules in kernel main --- kernel/src/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 01bcbb0..117a1d8 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,3 +1,4 @@ +#include "kapi/boot_modules.hpp" #include "kapi/cio.hpp" #include "kapi/memory.hpp" #include "kapi/system.hpp" @@ -16,5 +17,8 @@ auto main() -> int kstd::println("[OS] Memory subsystem initialized."); kapi::system::memory_initialized(); + kapi::boot_modules::init(); + kstd::println("[OS] Boot module registry initialized."); + kapi::system::panic("Returning from kernel main!"); } -- cgit v1.2.3 From dd60285848be17083d7ef77fa0ed8896b6e087b7 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Sat, 28 Feb 2026 17:33:42 +0100 Subject: Initialize storage management from kernel main --- kernel/src/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 117a1d8..0336fef 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -3,6 +3,8 @@ #include "kapi/memory.hpp" #include "kapi/system.hpp" +#include "devices/storage/StorageManagement.hpp" + #include "kernel/memory.hpp" #include @@ -20,5 +22,8 @@ auto main() -> int kapi::boot_modules::init(); kstd::println("[OS] Boot module registry initialized."); + devices::storage::storage_management::init(); + kstd::println("[OS] Storage management initialized."); + kapi::system::panic("Returning from kernel main!"); } -- cgit v1.2.3 From 5268bf6622463c3d233683fe56ae9977baf8eeaa Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 3 Mar 2026 16:57:02 +0100 Subject: rename files to snake_case (temp_device part1 -> renamed to device later, due to capital-/lower-letter problem) --- kernel/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 0336fef..07aa8ae 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -3,7 +3,7 @@ #include "kapi/memory.hpp" #include "kapi/system.hpp" -#include "devices/storage/StorageManagement.hpp" +#include "devices/storage/storage_management.hpp" #include "kernel/memory.hpp" -- cgit v1.2.3 From 2f4001cdb1f528d8a0d255d81ac3a8b9aa522fac Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 7 Mar 2026 13:55:40 +0100 Subject: implement first draft of a file_descriptor_table and open_file_description --- kernel/src/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 07aa8ae..4b74bd4 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -4,6 +4,7 @@ #include "kapi/system.hpp" #include "devices/storage/storage_management.hpp" +#include "filesystem/file_descriptor_table.hpp" #include "kernel/memory.hpp" @@ -25,5 +26,8 @@ auto main() -> int devices::storage::storage_management::init(); kstd::println("[OS] Storage management initialized."); + filesystem::file_descriptor_table::init(); + kstd::println("[OS] Global file descriptor table initialized."); + kapi::system::panic("Returning from kernel main!"); } -- cgit v1.2.3 From 1453fbedde547d9e69cdad659df667f43a8dc750 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Sun, 15 Mar 2026 14:31:41 +0100 Subject: Create basic VFS structure --- kernel/src/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 4b74bd4..07fb81b 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -5,6 +5,7 @@ #include "devices/storage/storage_management.hpp" #include "filesystem/file_descriptor_table.hpp" +#include "filesystem/vfs.hpp" #include "kernel/memory.hpp" @@ -29,5 +30,8 @@ auto main() -> int filesystem::file_descriptor_table::init(); kstd::println("[OS] Global file descriptor table initialized."); + filesystem::vfs::init(); + kstd::println("[OS] Virtual filesystem initialized."); + kapi::system::panic("Returning from kernel main!"); } -- cgit v1.2.3 From e87963115bcdc0f0534bc2194bf3f7e3d3f3e2b6 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sun, 15 Mar 2026 15:35:04 +0100 Subject: move test code into separate function --- kernel/src/main.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 07fb81b..011821a 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -4,21 +4,92 @@ #include "kapi/system.hpp" #include "devices/storage/storage_management.hpp" +#include "filesystem/device_file.hpp" #include "filesystem/file_descriptor_table.hpp" +#include "filesystem/open_file_description.hpp" #include "filesystem/vfs.hpp" #include "kernel/memory.hpp" +#include #include +#include +#include +#include + +auto run_test_code() -> void +{ + // setup + auto fd_table = filesystem::file_descriptor_table::get(); + auto storage_mgmt = devices::storage::storage_management::get(); + auto device = storage_mgmt.device_by_major_minor(1, 0); + + filesystem::device_file dev_file(device); + filesystem::open_file_description ofd(&dev_file); + auto fd_index = fd_table.add_file(ofd); + + // use: read two bytes and write two again + auto fd = fd_table.get_file(fd_index); + if (!fd) + { + kstd::os::panic("test code failed"); + } + + std::array buffer{}; + auto number_of_read_bytes = fd->read(buffer.data(), buffer.size()); + + for (size_t i = 0; i < number_of_read_bytes; ++i) + { + kstd::print("{:02x} ", static_cast(buffer[i])); + + if ((i + 1) % 16 == 0) + { + kstd::println(""); + } + } + kstd::println("---"); + + // write half of the file new + std::array write_buffer{std::byte{0xBB}, std::byte{0xAA}}; + auto written_bytes = fd->write(write_buffer.data(), write_buffer.size()); + + kstd::println("written bytes: {}", written_bytes); + + fd_table.remove_file(fd_index); + + // use: read four bytes again -> two old bytes two new bytes + filesystem::open_file_description ofd1(&dev_file); + fd_index = fd_table.add_file(ofd1); + auto fd1 = fd_table.get_file(fd_index); + + if (!fd1) + { + kstd::os::panic("test code failed"); + } + + std::array buffer1{}; + number_of_read_bytes = fd1->read(buffer1.data(), buffer1.size()); + + for (size_t i = 0; i < number_of_read_bytes; ++i) + { + kstd::print("{:02x} ", static_cast(buffer1[i])); + + if ((i + 1) % 16 == 0) + { + kstd::println(""); + } + } + kstd::println("---"); +} + auto main() -> int { kapi::cio::init(); kstd::println("[OS] IO subsystem initialized."); kapi::memory::init(); - kernel::memory::init_heap(kapi::memory::heap_base); - kstd::println("[OS] Memory subsystem initialized."); + kernel::memory::init_heap(kapi::memory::heap_base); kstd::println("[OS] Memory subsystem initialized."); kapi::system::memory_initialized(); kapi::boot_modules::init(); @@ -33,5 +104,7 @@ auto main() -> int filesystem::vfs::init(); kstd::println("[OS] Virtual filesystem initialized."); + run_test_code(); + kapi::system::panic("Returning from kernel main!"); } -- cgit v1.2.3 From 5801be615a50bf465a9663b7f75cafbcf0870f5c Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 17 Mar 2026 11:49:13 +0100 Subject: use kstd::vector instead of std::array and replace plain-pointers with kstd::shared_ptr --- kernel/src/main.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 011821a..cf3afdf 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -8,13 +8,13 @@ #include "filesystem/file_descriptor_table.hpp" #include "filesystem/open_file_description.hpp" #include "filesystem/vfs.hpp" - #include "kernel/memory.hpp" +#include #include #include +#include -#include #include #include @@ -25,8 +25,8 @@ auto run_test_code() -> void auto storage_mgmt = devices::storage::storage_management::get(); auto device = storage_mgmt.device_by_major_minor(1, 0); - filesystem::device_file dev_file(device); - filesystem::open_file_description ofd(&dev_file); + auto dev_file = kstd::make_shared(device); + filesystem::open_file_description ofd(dev_file); auto fd_index = fd_table.add_file(ofd); // use: read two bytes and write two again @@ -36,7 +36,7 @@ auto run_test_code() -> void kstd::os::panic("test code failed"); } - std::array buffer{}; + kstd::vector buffer{2}; auto number_of_read_bytes = fd->read(buffer.data(), buffer.size()); for (size_t i = 0; i < number_of_read_bytes; ++i) @@ -51,7 +51,7 @@ auto run_test_code() -> void kstd::println("---"); // write half of the file new - std::array write_buffer{std::byte{0xBB}, std::byte{0xAA}}; + kstd::vector write_buffer{std::byte{0xBB}, std::byte{0xAA}}; auto written_bytes = fd->write(write_buffer.data(), write_buffer.size()); kstd::println("written bytes: {}", written_bytes); @@ -59,7 +59,7 @@ auto run_test_code() -> void fd_table.remove_file(fd_index); // use: read four bytes again -> two old bytes two new bytes - filesystem::open_file_description ofd1(&dev_file); + filesystem::open_file_description ofd1(dev_file); fd_index = fd_table.add_file(ofd1); auto fd1 = fd_table.get_file(fd_index); @@ -68,7 +68,7 @@ auto run_test_code() -> void kstd::os::panic("test code failed"); } - std::array buffer1{}; + kstd::vector buffer1{4}; number_of_read_bytes = fd1->read(buffer1.data(), buffer1.size()); for (size_t i = 0; i < number_of_read_bytes; ++i) @@ -89,7 +89,8 @@ auto main() -> int kstd::println("[OS] IO subsystem initialized."); kapi::memory::init(); - kernel::memory::init_heap(kapi::memory::heap_base); kstd::println("[OS] Memory subsystem initialized."); + kernel::memory::init_heap(kapi::memory::heap_base); + kstd::println("[OS] Memory subsystem initialized."); kapi::system::memory_initialized(); kapi::boot_modules::init(); -- cgit v1.2.3 From 3ace886a9e9f044cd48de51f0a15aceb02bfa9b2 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Tue, 17 Mar 2026 19:36:20 +0100 Subject: Clean up project folder structure --- kernel/src/devices/block_device.cpp | 42 +++++++ kernel/src/devices/device.cpp | 28 +++++ .../storage/ram_disk/ram_disk_controller.cpp | 28 +++++ .../devices/storage/ram_disk/ram_disk_device.cpp | 77 +++++++++++++ kernel/src/devices/storage/storage_controller.cpp | 44 ++++++++ kernel/src/devices/storage/storage_management.cpp | 85 ++++++++++++++ kernel/src/filesystem/custody.cpp | 30 +++++ kernel/src/filesystem/device_file.cpp | 124 +++++++++++++++++++++ kernel/src/filesystem/ext2/ext2_filesystem.cpp | 33 ++++++ kernel/src/filesystem/file_descriptor_table.cpp | 82 ++++++++++++++ kernel/src/filesystem/filesystem.cpp | 11 ++ kernel/src/filesystem/inode.cpp | 108 ++++++++++++++++++ kernel/src/filesystem/inode_file.cpp | 35 ++++++ kernel/src/filesystem/mount.cpp | 32 ++++++ kernel/src/filesystem/open_file_description.cpp | 35 ++++++ kernel/src/filesystem/vfs.cpp | 123 ++++++++++++++++++++ kernel/src/main.cpp | 10 +- 17 files changed, 922 insertions(+), 5 deletions(-) create mode 100644 kernel/src/devices/block_device.cpp create mode 100644 kernel/src/devices/device.cpp create mode 100644 kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp create mode 100644 kernel/src/devices/storage/ram_disk/ram_disk_device.cpp create mode 100644 kernel/src/devices/storage/storage_controller.cpp create mode 100644 kernel/src/devices/storage/storage_management.cpp create mode 100644 kernel/src/filesystem/custody.cpp create mode 100644 kernel/src/filesystem/device_file.cpp create mode 100644 kernel/src/filesystem/ext2/ext2_filesystem.cpp create mode 100644 kernel/src/filesystem/file_descriptor_table.cpp create mode 100644 kernel/src/filesystem/filesystem.cpp create mode 100644 kernel/src/filesystem/inode.cpp create mode 100644 kernel/src/filesystem/inode_file.cpp create mode 100644 kernel/src/filesystem/mount.cpp create mode 100644 kernel/src/filesystem/open_file_description.cpp create mode 100644 kernel/src/filesystem/vfs.cpp (limited to 'kernel/src') diff --git a/kernel/src/devices/block_device.cpp b/kernel/src/devices/block_device.cpp new file mode 100644 index 0000000..d12251b --- /dev/null +++ b/kernel/src/devices/block_device.cpp @@ -0,0 +1,42 @@ +#include "kernel/devices/block_device.hpp" + +#include "kapi/system.hpp" + +#include "kernel/devices/device.hpp" + +#include +#include + +namespace devices +{ + block_device::block_device(size_t major, size_t minor, std::string_view name, size_t block_size) + : device(major, minor, name) + , m_block_size(block_size) + { + if (m_block_size == 0) + { + kapi::system::panic("[DEVICES] block_device constructed with zero block size."); + } + } + + 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(); + + size_t const available = (offset < limit) ? (limit - offset) : 0; + size_t 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 + { + return m_block_size; + } + + auto block_device::capacity() const -> size_t + { + return size(); + } +} // namespace devices \ No newline at end of file diff --git a/kernel/src/devices/device.cpp b/kernel/src/devices/device.cpp new file mode 100644 index 0000000..29498fa --- /dev/null +++ b/kernel/src/devices/device.cpp @@ -0,0 +1,28 @@ +#include "kernel/devices/device.hpp" + +#include +#include + +namespace devices +{ + device::device(size_t major, size_t minor, std::string_view name) + : m_major(major) + , m_minor(minor) + , m_name(name) + {} + + auto device::major() const -> size_t + { + return m_major; + } + + auto device::minor() const -> size_t + { + return m_minor; + } + + auto device::name() const -> std::string_view + { + return m_name; + } +} // namespace devices \ No newline at end of file diff --git a/kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp b/kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp new file mode 100644 index 0000000..efb6256 --- /dev/null +++ b/kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp @@ -0,0 +1,28 @@ +#include "kernel/devices/storage/ram_disk/ram_disk_controller.hpp" + +#include "kapi/boot_module/boot_module_registry.hpp" + +#include "kernel/devices/storage/ram_disk/ram_disk_device.hpp" + +#include +#include + +#include +#include + +namespace devices::storage::ram_disk +{ + ram_disk_controller::ram_disk_controller(kapi::boot_modules::boot_module_registry const * registry) + : m_boot_module_registry(registry) + {} + + auto ram_disk_controller::probe() -> void + { + size_t current_device_index = 0; + + std::ranges::for_each(*m_boot_module_registry, [this, ¤t_device_index](auto const & module) { + auto const minor = current_device_index++ * m_minors_per_device; + m_devices.push_back(kstd::make_shared(module, m_major, minor)); + }); + } +} // namespace devices::storage::ram_disk \ No newline at end of file diff --git a/kernel/src/devices/storage/ram_disk/ram_disk_device.cpp b/kernel/src/devices/storage/ram_disk/ram_disk_device.cpp new file mode 100644 index 0000000..650a151 --- /dev/null +++ b/kernel/src/devices/storage/ram_disk/ram_disk_device.cpp @@ -0,0 +1,77 @@ +#include "kernel/devices/storage/ram_disk/ram_disk_device.hpp" + +#include "kapi/boot_module/boot_module.hpp" +#include "kapi/system.hpp" + +#include "kernel/devices/block_device.hpp" + +#include + +#include +#include +#include + +namespace devices::storage::ram_disk +{ + namespace + { + constexpr size_t RAM_DISK_BLOCK_SIZE = 512uz; + + // TODO BA-FS26 @Felix + // TODO BA-FS26 currently only names for 9 minor devices + constinit std::array name = {'r', 'a', 'm', '0', '\0'}; + + auto determine_device_name(size_t minor) -> std::string_view + { + name[3] = '0' + minor; + return std::string_view{name}; + } + } // namespace + + ram_disk_device::ram_disk_device(kapi::boot_modules::boot_module const & module, size_t major, size_t minor) + : block_device(major, minor, determine_device_name(minor), RAM_DISK_BLOCK_SIZE) + , m_boot_module(module) + {} + + auto ram_disk_device::read_block(size_t block_index, void * buffer) const -> void + { + if (buffer == nullptr) + { + kapi::system::panic("[RAM DISK DEVICE] read_block called with null buffer."); + } + + auto const info = calculate_transfer(block_index); + + if (info.to_transfer > 0) + { + auto const src = static_cast(m_boot_module.start_address) + info.offset; + kstd::libc::memcpy(buffer, src, info.to_transfer); + } + + if (info.remainder > 0) + { + kstd::libc::memset(static_cast(buffer) + info.to_transfer, 0, info.remainder); + } + } + + auto ram_disk_device::write_block(size_t block_index, void const * buffer) -> void + { + if (buffer == nullptr) + { + kapi::system::panic("[RAM DISK DEVICE] write_block called with null buffer."); + } + + auto const info = calculate_transfer(block_index); + + if (info.to_transfer > 0) + { + auto const dest = static_cast(m_boot_module.start_address) + info.offset; + kstd::libc::memcpy(dest, buffer, info.to_transfer); + } + } + + auto ram_disk_device::size() const -> size_t + { + return m_boot_module.size; + } +} // namespace devices::storage::ram_disk \ No newline at end of file diff --git a/kernel/src/devices/storage/storage_controller.cpp b/kernel/src/devices/storage/storage_controller.cpp new file mode 100644 index 0000000..e415436 --- /dev/null +++ b/kernel/src/devices/storage/storage_controller.cpp @@ -0,0 +1,44 @@ +#include "kernel/devices/storage/storage_controller.hpp" + +#include "kernel/devices/device.hpp" + +#include +#include + +#include +#include + +namespace devices::storage +{ + auto storage_controller::set_ids(size_t major, size_t minors_per_dev) -> void + { + m_major = major; + m_minors_per_device = minors_per_dev; + } + + auto storage_controller::major() const -> size_t + { + return m_major; + } + + auto storage_controller::device_by_minor(size_t minor) const -> kstd::shared_ptr + { + auto it = std::ranges::find_if(m_devices, [minor](auto const & device) { return device->minor() == minor; }); + + if (it != m_devices.end()) + { + return *it; + } + return nullptr; + } + + auto storage_controller::devices_count() const -> size_t + { + return m_devices.size(); + } + + auto storage_controller::all_devices() const -> kstd::vector> const & + { + return m_devices; + } +} // namespace devices::storage \ No newline at end of file diff --git a/kernel/src/devices/storage/storage_management.cpp b/kernel/src/devices/storage/storage_management.cpp new file mode 100644 index 0000000..56216b0 --- /dev/null +++ b/kernel/src/devices/storage/storage_management.cpp @@ -0,0 +1,85 @@ +#include "kernel/devices/storage/storage_management.hpp" + +#include "kapi/boot_modules.hpp" +#include "kapi/system.hpp" + +#include "kernel/devices/device.hpp" +#include "kernel/devices/storage/ram_disk/ram_disk_controller.hpp" +#include "kernel/devices/storage/storage_controller.hpp" + +#include +#include + +#include +#include +#include + +namespace devices::storage +{ + namespace + { + constexpr size_t static MINORS_PER_DEVICE = 16; + constexpr size_t static START_MAJOR = 1; + constinit size_t static next_free_major = START_MAJOR; + + constinit auto static active_storage_management = std::optional{}; + } // namespace + + auto storage_management::init() -> void + { + if (active_storage_management) + { + kapi::system::panic("[DEVICES] Storage management has already been initialized."); + } + active_storage_management.emplace(storage_management{}); + + auto current_ram_disk_controller = + kstd::make_shared(&kapi::boot_modules::get_boot_module_registry()); + active_storage_management->add_controller(current_ram_disk_controller); + + std::ranges::for_each(active_storage_management->m_controllers, [](auto controller) { controller->probe(); }); + } + + auto storage_management::get() -> storage_management & + { + if (!active_storage_management) + { + kapi::system::panic("[DEVICES] Storage management has not been initialized."); + } + + return *active_storage_management; + } + + auto storage_management::add_controller(kstd::shared_ptr const & controller) -> void + { + controller->set_ids(next_free_major++, MINORS_PER_DEVICE); + m_controllers.push_back(controller); + } + + auto storage_management::all_controllers() const -> kstd::vector> const & + { + return m_controllers; + } + + auto storage_management::device_by_major_minor(size_t major, size_t minor) -> kstd::shared_ptr + { + kstd::shared_ptr found = nullptr; + + std::ranges::find_if(m_controllers, [&](auto const & controller) { + if (controller != nullptr && controller->major() == major) + { + found = controller->device_by_minor(minor); + return found != nullptr; + } + return false; + }); + + return found; + } + + auto storage_management::determine_boot_device() -> kstd::shared_ptr + { + return device_by_major_minor(START_MAJOR, 0); + } + +} // namespace devices::storage \ No newline at end of file diff --git a/kernel/src/filesystem/custody.cpp b/kernel/src/filesystem/custody.cpp new file mode 100644 index 0000000..a4dd12c --- /dev/null +++ b/kernel/src/filesystem/custody.cpp @@ -0,0 +1,30 @@ +#include "kernel/filesystem/custody.hpp" + +#include "kapi/system.hpp" + +#include "kernel/filesystem/inode.hpp" + +#include + +namespace filesystem +{ + custody::custody(kstd::shared_ptr const & parent, kstd::shared_ptr const & node) + : m_parent(parent) + , m_inode(node) + { + if (!m_inode) + { + kapi::system::panic("[FILESYSTEM] custody constructed with null inode."); + } + } + + auto custody::get_inode() const -> kstd::shared_ptr const & + { + return m_inode; + } + + auto custody::get_parent() const -> kstd::shared_ptr const & + { + return m_parent; + } +} // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/device_file.cpp b/kernel/src/filesystem/device_file.cpp new file mode 100644 index 0000000..c6db5af --- /dev/null +++ b/kernel/src/filesystem/device_file.cpp @@ -0,0 +1,124 @@ +#include "kernel/filesystem/device_file.hpp" + +#include "kapi/system.hpp" + +#include "kernel/devices/block_device.hpp" +#include "kernel/devices/device.hpp" + +#include +#include +#include + +#include +#include + +namespace filesystem +{ + device_file::device_file(kstd::shared_ptr const & device) + : m_device(device) + { + if (!m_device) + { + kapi::system::panic("[FILESYSTEM] device_file constructed with null device."); + } + } + + auto device_file::open() -> void + { + // Hook point for permission checks or lazy metadata loading. + } + + auto device_file::read(void * buffer, size_t offset, size_t size) const -> size_t + { + if (m_device->is_block_device()) + { + return process_blocks(offset, size, buffer, + [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, + std::byte * scratch, void * buffer) { + auto * out = static_cast(buffer); + if (off == 0 && len == device->block_size()) + { + device->read_block(idx, out + done); + } + else + { + device->read_block(idx, scratch); + kstd::libc::memcpy(out + done, scratch + off, len); + } + }); + } + else + { + kapi::system::panic("[FILESYSTEM] device_file::read called on non-block device."); + } + } + + auto device_file::write(void const * buffer, size_t offset, size_t size) -> size_t + { + if (m_device->is_block_device()) + { + return process_blocks(offset, size, const_cast(buffer), + [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, + std::byte * scratch, void * buffer) { + auto const * in = static_cast(buffer); + if (off == 0 && len == device->block_size()) + { + 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); + } + }); + } + else + { + kapi::system::panic("[FILESYSTEM] device_file::write called on non-block device."); + } + } + + auto device_file::process_blocks(size_t offset, size_t size, void * buffer, block_op op) const -> size_t + { + if (buffer == nullptr) + { + kapi::system::panic("[FILESYSTEM] device_file::write called with null buffer."); + } + + if (size == 0) + { + return 0; + } + + auto * block_dev = static_cast(m_device.get()); + if (block_dev == nullptr) + { + kapi::system::panic("[FILESYSTEM] device_file: expected block_device."); + } + + size_t const block_size = block_dev->block_size(); + size_t const capacity = block_dev->capacity(); + + if (offset >= capacity) + return 0; + size_t const total_to_process = std::min(size, capacity - offset); + + kstd::vector scratch_buffer{block_size}; + auto processed = 0uz; + + 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); + + processed += chunk_size; + } + + return processed; + } +} // namespace filesystem diff --git a/kernel/src/filesystem/ext2/ext2_filesystem.cpp b/kernel/src/filesystem/ext2/ext2_filesystem.cpp new file mode 100644 index 0000000..408b292 --- /dev/null +++ b/kernel/src/filesystem/ext2/ext2_filesystem.cpp @@ -0,0 +1,33 @@ +#include "kernel/filesystem/ext2/ext2_filesystem.hpp" + +#include "kernel/devices/device.hpp" +#include "kernel/filesystem/inode.hpp" +#include "kernel/filesystem/inode_metadata.hpp" + +#include + +#include + +namespace filesystem::ext2 +{ + auto ext2_filesystem::mount(kstd::shared_ptr const & device) -> int + { + if (!device) + { + return -1; // TODO BA-FS26 panic or errorcode? + } + + m_device = device; + // TODO BA-FS26 load proper root inode from ext2 metadata + m_root_inode = inode{inode_kind::directory}; + + // TODO BA-FS26 implement + return 0; + } + + auto ext2_filesystem::lookup(inode const & /*parent*/, std::string_view /*name*/) -> inode * + { + // TODO BA-FS26 implement ext2 directory traversal and inode loading + return nullptr; + } +} // namespace filesystem::ext2 diff --git a/kernel/src/filesystem/file_descriptor_table.cpp b/kernel/src/filesystem/file_descriptor_table.cpp new file mode 100644 index 0000000..814322e --- /dev/null +++ b/kernel/src/filesystem/file_descriptor_table.cpp @@ -0,0 +1,82 @@ +#include "kernel/filesystem/file_descriptor_table.hpp" + +#include "kapi/system.hpp" + +#include "kernel/filesystem/open_file_description.hpp" + +#include +#include +#include + +namespace filesystem +{ + namespace + { + constinit auto static global_file_descriptor_table = std::optional{}; + } // namespace + + auto file_descriptor_table::init() -> void + { + if (global_file_descriptor_table) + { + kapi::system::panic("[FILESYSTEM] File descriptor table has already been initialized."); + } + + global_file_descriptor_table.emplace(file_descriptor_table{}); + } + + auto file_descriptor_table::get() -> file_descriptor_table & + { + if (!global_file_descriptor_table) + { + kapi::system::panic("[FILESYSTEM] File descriptor table has not been initialized."); + } + + return *global_file_descriptor_table; + } + + auto file_descriptor_table::add_file(open_file_description & file_description) -> int + { + auto it = std::ranges::find_if(m_open_files, [](auto & open_file) { return !open_file.has_value(); }); + if (it != m_open_files.end()) + { + *it = file_description; + return static_cast(it - m_open_files.begin()); + } + + m_open_files.push_back(file_description); + return static_cast(m_open_files.size() - 1); + } + + auto file_descriptor_table::get_file(int fd) const -> std::optional + { + if (fd < 0) + { + return std::nullopt; + } + + auto const index = static_cast(fd); + if (index >= m_open_files.size() || !m_open_files.at(fd).has_value()) + { + return std::nullopt; + } + + return m_open_files.at(fd); + } + + auto file_descriptor_table::remove_file(int fd) -> void + { + if (fd < 0) + { + return; + } + + auto const index = static_cast(fd); + if (index >= m_open_files.size()) + { + return; + } + + m_open_files.at(fd).reset(); + } +} // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp new file mode 100644 index 0000000..86b7940 --- /dev/null +++ b/kernel/src/filesystem/filesystem.cpp @@ -0,0 +1,11 @@ +#include "kernel/filesystem/filesystem.hpp" + +#include "kernel/filesystem/inode.hpp" + +namespace filesystem +{ + auto filesystem::root_inode() const -> inode const & + { + return m_root_inode; + } +} // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/inode.cpp b/kernel/src/filesystem/inode.cpp new file mode 100644 index 0000000..af73662 --- /dev/null +++ b/kernel/src/filesystem/inode.cpp @@ -0,0 +1,108 @@ +#include "kernel/filesystem/inode.hpp" + +#include "kapi/system.hpp" + +#include "kernel/devices/device.hpp" +#include "kernel/filesystem/inode_metadata.hpp" + +#include + +#include + +namespace filesystem +{ + inode::inode(inode_kind kind) + : m_kind(kind) + {} + + inode::inode(kstd::shared_ptr const & device) + : m_kind(inode_kind::device) + , m_device(device) + { + if (!m_device) + { + kapi::system::panic("[FILESYSTEM] inode constructed with null device."); + } + } + + auto inode::metadata() const -> inode_metadata + { + auto meta = inode_metadata{}; + meta.kind = m_kind; + + if (is_device()) + { + meta.major = m_device->major(); + meta.minor = m_device->minor(); + } + + return meta; + } + + auto inode::is_directory() const -> bool + { + return m_kind == inode_kind::directory; + } + + auto inode::is_regular() const -> bool + { + return m_kind == inode_kind::regular; + } + + auto inode::is_device() const -> bool + { + return m_kind == inode_kind::device; + } + + auto inode::is_block_device() const -> bool + { + return is_device() && m_device->is_block_device(); + } + + auto inode::major_device() const -> size_t + { + if (!is_device()) + { + kapi::system::panic("[FILESYSTEM] inode::major_device called on non-device inode."); + } + + return m_device->major(); + } + + auto inode::minor_device() const -> size_t + { + if (!is_device()) + { + kapi::system::panic("[FILESYSTEM] inode::minor_device called on non-device inode."); + } + + return m_device->minor(); + } + + auto inode::backing_device() const -> kstd::shared_ptr const & + { + return m_device; + } + + auto inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t + { + if (is_device()) + { + kapi::system::panic("[FILESYSTEM] inode::read called on device inode. Open it as a device file first."); + } + + // TODO BA-FS26 + return 0; + } + + auto inode::write(void const *, size_t, size_t) -> size_t + { + if (is_device()) + { + kapi::system::panic("[FILESYSTEM] inode::write called on device inode. Open it as a device file first."); + } + + kapi::system::panic("[FILESYSTEM] inode::write is not implemented yet"); + return 0; + } +} // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/inode_file.cpp b/kernel/src/filesystem/inode_file.cpp new file mode 100644 index 0000000..7abac7b --- /dev/null +++ b/kernel/src/filesystem/inode_file.cpp @@ -0,0 +1,35 @@ +#include "kernel/filesystem/inode_file.hpp" + +#include "kapi/system.hpp" + +#include "kernel/filesystem/inode.hpp" + +#include + +#include + +namespace filesystem +{ + inode_file::inode_file(kstd::shared_ptr const & inode) + : m_inode(inode) + { + if (!m_inode) + { + kapi::system::panic("[FILESYSTEM] inode_file constructed with null inode"); + } + } + + auto inode_file::open() -> void + { + // Hook point for permission checks or lazy metadata loading. + } + + auto inode_file::read(void * buffer, size_t offset, size_t size) const -> size_t + { + return m_inode->read(buffer, offset, size); + } + auto inode_file::write(void const * buffer, size_t offset, size_t size) -> size_t + { + return m_inode->write(buffer, offset, size); + } +} // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp new file mode 100644 index 0000000..a2c501f --- /dev/null +++ b/kernel/src/filesystem/mount.cpp @@ -0,0 +1,32 @@ +#include "kernel/filesystem/mount.hpp" + +#include "kapi/system.hpp" + +#include "kernel/filesystem/filesystem.hpp" + +#include + +#include + +namespace filesystem +{ + mount::mount(std::string_view const & path, kstd::shared_ptr const & fs) + : m_path(path) + , m_filesystem(fs) + { + if (!m_filesystem) + { + kapi::system::panic("[FILESYSTEM] mount initialized with null filesystem."); + } + } + + auto mount::path() const -> std::string_view + { + return m_path; + } + + auto mount::get_filesystem() const -> kstd::shared_ptr const & + { + return m_filesystem; + } +} // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/open_file_description.cpp b/kernel/src/filesystem/open_file_description.cpp new file mode 100644 index 0000000..ff4d678 --- /dev/null +++ b/kernel/src/filesystem/open_file_description.cpp @@ -0,0 +1,35 @@ +#include "kernel/filesystem/open_file_description.hpp" + +#include "kernel/filesystem/file.hpp" + +#include +#include + +#include + +namespace filesystem +{ + open_file_description::open_file_description(kstd::shared_ptr const & file) + : m_file(file) + , m_offset(0) + { + if (!file) + { + kstd::os::panic("[FILESYSTEM] open_file_description constructed with null file."); + } + } + + auto open_file_description::read(void * buffer, size_t size) -> size_t + { + auto read_bytes = m_file->read(buffer, m_offset, size); + m_offset += read_bytes; + return read_bytes; + } + + auto open_file_description::write(void const * buffer, size_t size) -> size_t + { + auto written_bytes = m_file->write(buffer, m_offset, size); + m_offset += written_bytes; + return written_bytes; + } +} // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp new file mode 100644 index 0000000..8d2ed0a --- /dev/null +++ b/kernel/src/filesystem/vfs.cpp @@ -0,0 +1,123 @@ +#include "kernel/filesystem/vfs.hpp" + +#include "kapi/system.hpp" + +#include "kernel/devices/storage/storage_management.hpp" +#include "kernel/filesystem/custody.hpp" +#include "kernel/devices/device.hpp" +#include "kernel/filesystem/device_file.hpp" +#include "kernel/filesystem/ext2/ext2_filesystem.hpp" +#include "kernel/filesystem/inode.hpp" +#include "kernel/filesystem/inode_file.hpp" +#include "kernel/filesystem/mount.hpp" +#include "kernel/filesystem/open_file_description.hpp" + +#include +#include + +#include +#include +#include + +namespace filesystem +{ + namespace + { + constinit auto static active_vfs = std::optional{}; + } // namespace + + auto vfs::init() -> void + { + if (active_vfs) + { + kapi::system::panic("[FILESYSTEM] vfs has already been initialized."); + } + + active_vfs.emplace(vfs{}); + + auto storage_mgmt = devices::storage::storage_management::get(); + if (auto boot_device = storage_mgmt.determine_boot_device()) + { + active_vfs->m_root_fs = kstd::make_shared(); + if (active_vfs->m_root_fs->mount(boot_device) != 0) + { + kapi::system::panic("[FILESYSTEM] Failed to mount root filesystem."); + } + + active_vfs->m_root_mount = mount{"/", active_vfs->m_root_fs}; + + std::ranges::for_each(storage_mgmt.all_controllers(), [&](auto controller) { + std::ranges::for_each(controller->all_devices(), [&](auto device) { active_vfs->make_device_node(device); }); + }); + } + else + { + // TODO BA-FS26 ?? what when no boot_device == no modules loaded?? + } + } + + auto vfs::get() -> vfs & + { + if (!active_vfs) + { + kapi::system::panic("[FILESYSTEM] vfs has not been initialized."); + } + + return *active_vfs; + } + + auto vfs::open(std::string_view path) -> std::optional + { + if (auto custody = resolve_path(path)) + { + auto node = custody->get_inode(); + if (node->is_device()) + { + auto current_device_file = kstd::make_shared(node->backing_device()); + current_device_file->open(); + return open_file_description{current_device_file}; + } + + auto current_inode_file = kstd::make_shared(node); + current_inode_file->open(); + return open_file_description{current_inode_file}; + } + + return std::nullopt; + } + + auto vfs::make_device_node(kstd::shared_ptr const & device) -> void + { + if (!device) + { + kapi::system::panic("[FILESYSTEM] make_device_node called with null device."); + } + + m_device_nodes.push_back(device_node_entry{device->name(), kstd::make_shared(device)}); + } + + auto vfs::resolve_path(std::string_view path) -> std::optional + { + // TODO BA-FS26 implement real path resolution with mounts and directories etc. + // For now, just support device nodes at /dev/. + + constexpr auto device_prefix = std::string_view{"/dev/"}; + if (path.starts_with(device_prefix)) + { + auto const device_name = path.substr(device_prefix.size()); + auto entry = std::ranges::find_if(m_device_nodes, [&](auto const & device_entry) { + return device_entry.has_value() && device_entry->name == device_name; + }); + + if (entry != m_device_nodes.end()) + { + return custody{nullptr, entry->value().node}; + } + + return std::nullopt; + } + + return std::nullopt; + } + +} // namespace filesystem \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index cf3afdf..6ced18c 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -3,11 +3,11 @@ #include "kapi/memory.hpp" #include "kapi/system.hpp" -#include "devices/storage/storage_management.hpp" -#include "filesystem/device_file.hpp" -#include "filesystem/file_descriptor_table.hpp" -#include "filesystem/open_file_description.hpp" -#include "filesystem/vfs.hpp" +#include "kernel/devices/storage/storage_management.hpp" +#include "kernel/filesystem/device_file.hpp" +#include "kernel/filesystem/file_descriptor_table.hpp" +#include "kernel/filesystem/open_file_description.hpp" +#include "kernel/filesystem/vfs.hpp" #include "kernel/memory.hpp" #include -- cgit v1.2.3 From fde097681f96e2c6f23ecd71a5c0037acb3ac79e Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Tue, 17 Mar 2026 19:47:53 +0100 Subject: Fix include order --- kernel/src/filesystem/vfs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 8d2ed0a..2123fc7 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -2,9 +2,9 @@ #include "kapi/system.hpp" +#include "kernel/devices/device.hpp" #include "kernel/devices/storage/storage_management.hpp" #include "kernel/filesystem/custody.hpp" -#include "kernel/devices/device.hpp" #include "kernel/filesystem/device_file.hpp" #include "kernel/filesystem/ext2/ext2_filesystem.hpp" #include "kernel/filesystem/inode.hpp" -- cgit v1.2.3 From 8c502bc3423a6b3597ffbebb06a3fa3e17a6e4b0 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 18 Mar 2026 09:21:11 +0100 Subject: fix clang-tidy warnings --- kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp | 1 - kernel/src/filesystem/vfs.cpp | 1 - kernel/src/main.cpp | 4 +++- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp b/kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp index efb6256..f3e9f70 100644 --- a/kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp +++ b/kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp @@ -5,7 +5,6 @@ #include "kernel/devices/storage/ram_disk/ram_disk_device.hpp" #include -#include #include #include diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 2123fc7..4e0b6bf 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -12,7 +12,6 @@ #include "kernel/filesystem/mount.hpp" #include "kernel/filesystem/open_file_description.hpp" -#include #include #include diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 6ced18c..eb59402 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -51,7 +51,9 @@ auto run_test_code() -> void kstd::println("---"); // write half of the file new - kstd::vector write_buffer{std::byte{0xBB}, std::byte{0xAA}}; + auto const value1 = std::byte{0xAA}; + auto const value2 = std::byte{0xBB}; + kstd::vector write_buffer{value1, value2}; auto written_bytes = fd->write(write_buffer.data(), write_buffer.size()); kstd::println("written bytes: {}", written_bytes); -- cgit v1.2.3 From e7ccb96aecae7b231fb05818d7e45a767aebc31d Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 18 Mar 2026 17:18:37 +0100 Subject: kstd: introduce strong type for memory amounts --- kernel/src/memory.cpp | 5 ++--- kernel/src/memory/block_list_allocator.cpp | 28 ++++++++++++++++------------ kernel/src/memory/operators.cpp | 13 ++++++++----- 3 files changed, 26 insertions(+), 20 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/memory.cpp b/kernel/src/memory.cpp index 0f614f0..4a8e203 100644 --- a/kernel/src/memory.cpp +++ b/kernel/src/memory.cpp @@ -7,10 +7,9 @@ #include "kernel/memory/heap_allocator.hpp" #include +#include #include -#include -#include #include namespace kernel::memory @@ -22,7 +21,7 @@ namespace kernel::memory { null_allocator static instance; - [[nodiscard]] auto allocate(std::size_t, std::align_val_t) noexcept -> void * override + [[nodiscard]] auto allocate(kstd::units::bytes, kstd::units::bytes) noexcept -> void * override { kstd::print(kstd::print_sink::stderr, "Tried to allocate memory without an active heap!"); return nullptr; diff --git a/kernel/src/memory/block_list_allocator.cpp b/kernel/src/memory/block_list_allocator.cpp index 5d870d8..fbc5945 100644 --- a/kernel/src/memory/block_list_allocator.cpp +++ b/kernel/src/memory/block_list_allocator.cpp @@ -6,19 +6,21 @@ #include "kernel/memory/heap_allocator.hpp" #include +#include #include #include #include #include -#include + +using namespace kstd::units_literals; namespace kernel::memory { namespace { - [[nodiscard]] constexpr auto align_up(std::byte * pointer, std::align_val_t alignment) noexcept -> std::byte * + [[nodiscard]] constexpr auto align_up(std::byte * pointer, kstd::units::bytes alignment) noexcept -> std::byte * { auto const remainder = std::bit_cast(pointer) % static_cast(alignment); return remainder == 0 ? pointer : pointer + static_cast(alignment) - remainder; @@ -33,7 +35,7 @@ namespace kernel::memory , m_lock{} {} - auto block_list_allocator::allocate(std::size_t size, std::align_val_t alignment) noexcept -> void * + auto block_list_allocator::allocate(kstd::units::bytes size, kstd::units::bytes alignment) noexcept -> void * { kstd::lock_guard guard{m_lock}; @@ -47,13 +49,13 @@ namespace kernel::memory auto const raw_block = reinterpret_cast(current); auto const unaligned_payload = raw_block + allocated_metadata_size; auto const aligned_payload = align_up(unaligned_payload, alignment); - auto const required_padding = static_cast(aligned_payload - unaligned_payload); + auto const required_padding = static_cast(aligned_payload - unaligned_payload); auto const total_required_size = required_padding + allocated_metadata_size + size; if (current->usable_size >= total_required_size) { auto const payload_header = aligned_payload - sizeof(block_header *) - sizeof(block_header); - auto const front_padding = static_cast(payload_header - raw_block); + auto const front_padding = static_cast(payload_header - raw_block); auto payload_block = current; @@ -72,9 +74,10 @@ namespace kernel::memory payload_block->prev = current; } - auto const payload_size = - aligned_payload - reinterpret_cast(payload_block) - allocated_metadata_size + size; - split(payload_block, payload_size, 0uz); + auto const header_size = + static_cast(aligned_payload - reinterpret_cast(payload_block)); + auto const payload_size = header_size - allocated_metadata_size + size; + split(payload_block, payload_size, 0_B); payload_block->free = false; @@ -87,7 +90,7 @@ namespace kernel::memory current = current->next; } - auto const search_size = size + static_cast(alignment); + auto const search_size = size + alignment; if (attempt == 0uz && !expand(search_size)) { return nullptr; @@ -114,10 +117,10 @@ namespace kernel::memory coalesce(block); } - auto block_list_allocator::expand(std::size_t size) noexcept -> bool + auto block_list_allocator::expand(kstd::units::bytes size) noexcept -> bool { auto const total_required_size = size + allocated_metadata_size; - auto const frames_needed = (total_required_size + kapi::memory::frame::size - 1) / kapi::memory::frame::size; + auto const frames_needed = (total_required_size + kapi::memory::frame::size - 1_B) / kapi::memory::frame::size; auto const flags = kapi::memory::page_mapper::flags::writable | kapi::memory::page_mapper::flags::supervisor_only | kapi::memory::page_mapper::flags::global; @@ -187,7 +190,8 @@ namespace kernel::memory } } - auto block_list_allocator::split(block_header * block, std::size_t size, std::size_t padding) noexcept -> void + auto block_list_allocator::split(block_header * block, kstd::units::bytes size, kstd::units::bytes padding) noexcept + -> void { auto const new_block_size = size + padding; diff --git a/kernel/src/memory/operators.cpp b/kernel/src/memory/operators.cpp index 57e31e6..c786b53 100644 --- a/kernel/src/memory/operators.cpp +++ b/kernel/src/memory/operators.cpp @@ -2,13 +2,16 @@ #include "kernel/memory.hpp" +#include + #include #include [[nodiscard]] auto operator new(std::size_t size, std::align_val_t alignment, std::nothrow_t const &) noexcept -> void * { auto & allocator = kernel::memory::get_heap_allocator(); - return allocator.allocate(size, alignment); + return allocator.allocate(static_cast(size), + static_cast(static_cast(alignment))); } [[nodiscard]] auto operator new(std::size_t size, std::align_val_t alignment) -> void * @@ -83,9 +86,9 @@ auto operator delete[](void * pointer) noexcept -> void ::operator delete(pointer); } -auto operator delete[](void * pointer, std::size_t) noexcept -> void +auto operator delete[](void * pointer, std::size_t size) noexcept -> void { - ::operator delete(pointer); + ::operator delete(pointer, size); } auto operator delete[](void * pointer, std::align_val_t) noexcept -> void @@ -93,7 +96,7 @@ auto operator delete[](void * pointer, std::align_val_t) noexcept -> void ::operator delete(pointer); } -auto operator delete[](void * pointer, std::size_t, std::align_val_t) noexcept -> void +auto operator delete[](void * pointer, std::size_t size, std::align_val_t) noexcept -> void { - ::operator delete(pointer); + ::operator delete(pointer, size); } -- cgit v1.2.3 From 584304d99b6bb43cef8aab9c6bfe22d24a5bf5a0 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 19 Mar 2026 13:31:54 +0100 Subject: kernel/memory: fix sized operator delete --- kernel/src/memory/operators.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/memory/operators.cpp b/kernel/src/memory/operators.cpp index c786b53..25b5f24 100644 --- a/kernel/src/memory/operators.cpp +++ b/kernel/src/memory/operators.cpp @@ -76,9 +76,9 @@ auto operator delete(void * pointer, std::align_val_t) noexcept -> void ::operator delete(pointer); } -auto operator delete(void * pointer, std::size_t, std::align_val_t) noexcept -> void +auto operator delete(void * pointer, std::size_t size, std::align_val_t) noexcept -> void { - ::operator delete(pointer); + ::operator delete(pointer, size); } auto operator delete[](void * pointer) noexcept -> void -- cgit v1.2.3 From 98b6633ea8e961f8668259dbd4970330494408d5 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 19 Mar 2026 21:32:38 +0100 Subject: prepare files for new inode structure --- kernel/src/filesystem/device_inode.cpp | 6 ++++++ kernel/src/filesystem/ext2/ext2_inode.cpp | 6 ++++++ 2 files changed, 12 insertions(+) create mode 100644 kernel/src/filesystem/device_inode.cpp create mode 100644 kernel/src/filesystem/ext2/ext2_inode.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/device_inode.cpp b/kernel/src/filesystem/device_inode.cpp new file mode 100644 index 0000000..b9018b1 --- /dev/null +++ b/kernel/src/filesystem/device_inode.cpp @@ -0,0 +1,6 @@ +#include "kernel/filesystem/device_inode.hpp" + +namespace filesystem +{ + // TODO BA-FS26: Implement device inode +} \ No newline at end of file diff --git a/kernel/src/filesystem/ext2/ext2_inode.cpp b/kernel/src/filesystem/ext2/ext2_inode.cpp new file mode 100644 index 0000000..ec68ee9 --- /dev/null +++ b/kernel/src/filesystem/ext2/ext2_inode.cpp @@ -0,0 +1,6 @@ +#include "kernel/filesystem/ext2/ext2_inode.hpp" + +namespace filesystem::ext2 +{ + // TODO BA-FS26: Implement ext2 inode +} \ No newline at end of file -- cgit v1.2.3 From 8d3471f1d160d301f9d990455bd8c63450df1cf3 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 19 Mar 2026 21:59:31 +0100 Subject: remove inode metadata --- kernel/src/filesystem/device_inode.cpp | 50 ++++++++++++++- kernel/src/filesystem/ext2/ext2_filesystem.cpp | 3 +- kernel/src/filesystem/filesystem.cpp | 4 +- kernel/src/filesystem/inode.cpp | 85 -------------------------- kernel/src/filesystem/vfs.cpp | 6 +- 5 files changed, 56 insertions(+), 92 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/device_inode.cpp b/kernel/src/filesystem/device_inode.cpp index b9018b1..18e3b24 100644 --- a/kernel/src/filesystem/device_inode.cpp +++ b/kernel/src/filesystem/device_inode.cpp @@ -1,6 +1,52 @@ #include "kernel/filesystem/device_inode.hpp" +#include "kapi/system.hpp" + +#include "kernel/devices/device.hpp" +#include "kernel/filesystem/inode.hpp" + +#include + +#include + namespace filesystem { - // TODO BA-FS26: Implement device inode -} \ No newline at end of file + device_inode::device_inode(kstd::shared_ptr const & device) + : inode(inode_kind::device) + , m_device(device) + { + if (!device) + { + kapi::system::panic("[FILESYSTEM] device_inode constructed with null device."); + } + } + + auto device_inode::backing_device() const -> kstd::shared_ptr const & + { + return m_device; + } + + auto device_inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t + { + if (!m_device) + { + kapi::system::panic("[FILESYSTEM] device_inode has null device."); + } + + // TODO BA-FS26 use device file? + // return m_device->read(buffer, offset, size); + return 0; + } + + auto device_inode::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t + { + if (!m_device) + { + kapi::system::panic("[FILESYSTEM] device_inode has null device."); + } + + // TODO BA-FS26 use device file? + // return m_device->write(buffer, offset, size); + return 0; + } +} // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/ext2/ext2_filesystem.cpp b/kernel/src/filesystem/ext2/ext2_filesystem.cpp index 408b292..87845d5 100644 --- a/kernel/src/filesystem/ext2/ext2_filesystem.cpp +++ b/kernel/src/filesystem/ext2/ext2_filesystem.cpp @@ -2,7 +2,6 @@ #include "kernel/devices/device.hpp" #include "kernel/filesystem/inode.hpp" -#include "kernel/filesystem/inode_metadata.hpp" #include @@ -19,7 +18,7 @@ namespace filesystem::ext2 m_device = device; // TODO BA-FS26 load proper root inode from ext2 metadata - m_root_inode = inode{inode_kind::directory}; + // m_root_inode = inode{inode_kind::directory}; // TODO BA-FS26 implement return 0; diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index 86b7940..50b5587 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -2,9 +2,11 @@ #include "kernel/filesystem/inode.hpp" +#include + namespace filesystem { - auto filesystem::root_inode() const -> inode const & + auto filesystem::root_inode() const -> kstd::shared_ptr const & { return m_root_inode; } diff --git a/kernel/src/filesystem/inode.cpp b/kernel/src/filesystem/inode.cpp index af73662..de3282f 100644 --- a/kernel/src/filesystem/inode.cpp +++ b/kernel/src/filesystem/inode.cpp @@ -1,44 +1,11 @@ #include "kernel/filesystem/inode.hpp" -#include "kapi/system.hpp" - -#include "kernel/devices/device.hpp" -#include "kernel/filesystem/inode_metadata.hpp" - -#include - -#include - namespace filesystem { inode::inode(inode_kind kind) : m_kind(kind) {} - inode::inode(kstd::shared_ptr const & device) - : m_kind(inode_kind::device) - , m_device(device) - { - if (!m_device) - { - kapi::system::panic("[FILESYSTEM] inode constructed with null device."); - } - } - - auto inode::metadata() const -> inode_metadata - { - auto meta = inode_metadata{}; - meta.kind = m_kind; - - if (is_device()) - { - meta.major = m_device->major(); - meta.minor = m_device->minor(); - } - - return meta; - } - auto inode::is_directory() const -> bool { return m_kind == inode_kind::directory; @@ -53,56 +20,4 @@ namespace filesystem { return m_kind == inode_kind::device; } - - auto inode::is_block_device() const -> bool - { - return is_device() && m_device->is_block_device(); - } - - auto inode::major_device() const -> size_t - { - if (!is_device()) - { - kapi::system::panic("[FILESYSTEM] inode::major_device called on non-device inode."); - } - - return m_device->major(); - } - - auto inode::minor_device() const -> size_t - { - if (!is_device()) - { - kapi::system::panic("[FILESYSTEM] inode::minor_device called on non-device inode."); - } - - return m_device->minor(); - } - - auto inode::backing_device() const -> kstd::shared_ptr const & - { - return m_device; - } - - auto inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t - { - if (is_device()) - { - kapi::system::panic("[FILESYSTEM] inode::read called on device inode. Open it as a device file first."); - } - - // TODO BA-FS26 - return 0; - } - - auto inode::write(void const *, size_t, size_t) -> size_t - { - if (is_device()) - { - kapi::system::panic("[FILESYSTEM] inode::write called on device inode. Open it as a device file first."); - } - - kapi::system::panic("[FILESYSTEM] inode::write is not implemented yet"); - return 0; - } } // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 4e0b6bf..188da6d 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -6,6 +6,7 @@ #include "kernel/devices/storage/storage_management.hpp" #include "kernel/filesystem/custody.hpp" #include "kernel/filesystem/device_file.hpp" +#include "kernel/filesystem/device_inode.hpp" #include "kernel/filesystem/ext2/ext2_filesystem.hpp" #include "kernel/filesystem/inode.hpp" #include "kernel/filesystem/inode_file.hpp" @@ -72,7 +73,8 @@ namespace filesystem auto node = custody->get_inode(); if (node->is_device()) { - auto current_device_file = kstd::make_shared(node->backing_device()); + auto device_node = static_cast(node.get()); + auto current_device_file = kstd::make_shared(device_node->backing_device()); current_device_file->open(); return open_file_description{current_device_file}; } @@ -92,7 +94,7 @@ namespace filesystem kapi::system::panic("[FILESYSTEM] make_device_node called with null device."); } - m_device_nodes.push_back(device_node_entry{device->name(), kstd::make_shared(device)}); + m_device_nodes.push_back(device_node_entry{device->name(), kstd::make_shared(device)}); } auto vfs::resolve_path(std::string_view path) -> std::optional -- cgit v1.2.3 From 09e3d0cb2272e7eabd79a320c17c58124515d427 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 19 Mar 2026 22:58:31 +0100 Subject: first try to simplify the architecture (remove redundant inode_file and open() methods), add ext2_file placeholder struct --- kernel/src/filesystem/device_file.cpp | 5 ----- kernel/src/filesystem/device_inode.cpp | 32 ++++------------------------ kernel/src/filesystem/ext2/ext2_file.cpp | 20 ++++++++++++++++++ kernel/src/filesystem/ext2/ext2_inode.cpp | 17 +++++++++++++-- kernel/src/filesystem/inode_file.cpp | 35 ------------------------------- kernel/src/filesystem/vfs.cpp | 14 ++++--------- 6 files changed, 43 insertions(+), 80 deletions(-) create mode 100644 kernel/src/filesystem/ext2/ext2_file.cpp delete mode 100644 kernel/src/filesystem/inode_file.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/device_file.cpp b/kernel/src/filesystem/device_file.cpp index c6db5af..48ed20d 100644 --- a/kernel/src/filesystem/device_file.cpp +++ b/kernel/src/filesystem/device_file.cpp @@ -23,11 +23,6 @@ namespace filesystem } } - auto device_file::open() -> void - { - // Hook point for permission checks or lazy metadata loading. - } - auto device_file::read(void * buffer, size_t offset, size_t size) const -> size_t { if (m_device->is_block_device()) diff --git a/kernel/src/filesystem/device_inode.cpp b/kernel/src/filesystem/device_inode.cpp index 18e3b24..592637d 100644 --- a/kernel/src/filesystem/device_inode.cpp +++ b/kernel/src/filesystem/device_inode.cpp @@ -3,12 +3,12 @@ #include "kapi/system.hpp" #include "kernel/devices/device.hpp" +#include "kernel/filesystem/device_file.hpp" +#include "kernel/filesystem/file.hpp" #include "kernel/filesystem/inode.hpp" #include -#include - namespace filesystem { device_inode::device_inode(kstd::shared_ptr const & device) @@ -21,32 +21,8 @@ namespace filesystem } } - auto device_inode::backing_device() const -> kstd::shared_ptr const & - { - return m_device; - } - - auto device_inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t + auto device_inode::open_file() const -> kstd::shared_ptr { - if (!m_device) - { - kapi::system::panic("[FILESYSTEM] device_inode has null device."); - } - - // TODO BA-FS26 use device file? - // return m_device->read(buffer, offset, size); - return 0; - } - - auto device_inode::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t - { - if (!m_device) - { - kapi::system::panic("[FILESYSTEM] device_inode has null device."); - } - - // TODO BA-FS26 use device file? - // return m_device->write(buffer, offset, size); - return 0; + return kstd::make_shared(m_device); } } // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/ext2/ext2_file.cpp b/kernel/src/filesystem/ext2/ext2_file.cpp new file mode 100644 index 0000000..7217c77 --- /dev/null +++ b/kernel/src/filesystem/ext2/ext2_file.cpp @@ -0,0 +1,20 @@ +#include "kernel/filesystem/ext2/ext2_file.hpp" + +#include "kapi/system.hpp" + +#include + +namespace filesystem::ext2 +{ + auto ext2_file::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t + { + kapi::system::panic("[FILESYSTEM] ext2_file::read is not implemented yet."); + return 0; + } + + auto ext2_file::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t + { + kapi::system::panic("[FILESYSTEM] ext2_file::write is not implemented yet."); + return 0; + } +} // namespace filesystem::ext2 diff --git a/kernel/src/filesystem/ext2/ext2_inode.cpp b/kernel/src/filesystem/ext2/ext2_inode.cpp index ec68ee9..1522387 100644 --- a/kernel/src/filesystem/ext2/ext2_inode.cpp +++ b/kernel/src/filesystem/ext2/ext2_inode.cpp @@ -1,6 +1,19 @@ #include "kernel/filesystem/ext2/ext2_inode.hpp" +#include "kernel/filesystem/ext2/ext2_file.hpp" +#include "kernel/filesystem/file.hpp" +#include "kernel/filesystem/inode.hpp" + +#include + namespace filesystem::ext2 { - // TODO BA-FS26: Implement ext2 inode -} \ No newline at end of file + ext2_inode::ext2_inode() + : inode(inode_kind::regular) + {} + + auto ext2_inode::open_file() const -> kstd::shared_ptr + { + return kstd::make_shared(); + } +} // namespace filesystem::ext2 \ No newline at end of file diff --git a/kernel/src/filesystem/inode_file.cpp b/kernel/src/filesystem/inode_file.cpp deleted file mode 100644 index 7abac7b..0000000 --- a/kernel/src/filesystem/inode_file.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "kernel/filesystem/inode_file.hpp" - -#include "kapi/system.hpp" - -#include "kernel/filesystem/inode.hpp" - -#include - -#include - -namespace filesystem -{ - inode_file::inode_file(kstd::shared_ptr const & inode) - : m_inode(inode) - { - if (!m_inode) - { - kapi::system::panic("[FILESYSTEM] inode_file constructed with null inode"); - } - } - - auto inode_file::open() -> void - { - // Hook point for permission checks or lazy metadata loading. - } - - auto inode_file::read(void * buffer, size_t offset, size_t size) const -> size_t - { - return m_inode->read(buffer, offset, size); - } - auto inode_file::write(void const * buffer, size_t offset, size_t size) -> size_t - { - return m_inode->write(buffer, offset, size); - } -} // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 188da6d..4b0c7d7 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -5,11 +5,8 @@ #include "kernel/devices/device.hpp" #include "kernel/devices/storage/storage_management.hpp" #include "kernel/filesystem/custody.hpp" -#include "kernel/filesystem/device_file.hpp" #include "kernel/filesystem/device_inode.hpp" #include "kernel/filesystem/ext2/ext2_filesystem.hpp" -#include "kernel/filesystem/inode.hpp" -#include "kernel/filesystem/inode_file.hpp" #include "kernel/filesystem/mount.hpp" #include "kernel/filesystem/open_file_description.hpp" @@ -71,16 +68,13 @@ namespace filesystem if (auto custody = resolve_path(path)) { auto node = custody->get_inode(); - if (node->is_device()) + + auto current_inode_file = node->open_file(); + if (!current_inode_file) { - auto device_node = static_cast(node.get()); - auto current_device_file = kstd::make_shared(device_node->backing_device()); - current_device_file->open(); - return open_file_description{current_device_file}; + kapi::system::panic("[FILESYSTEM] inode::open_file returned null file."); } - auto current_inode_file = kstd::make_shared(node); - current_inode_file->open(); return open_file_description{current_inode_file}; } -- cgit v1.2.3 From f669454966c9fa8cbdbbefb1d9cfdd61026849f9 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 20 Mar 2026 21:47:58 +0100 Subject: improve architecture again -> use same architecture for devices and ext2_files --- kernel/src/filesystem/ext2/ext2_inode.cpp | 8 +++++--- kernel/src/filesystem/inode_file.cpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 kernel/src/filesystem/inode_file.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/ext2_inode.cpp b/kernel/src/filesystem/ext2/ext2_inode.cpp index 1522387..8131f43 100644 --- a/kernel/src/filesystem/ext2/ext2_inode.cpp +++ b/kernel/src/filesystem/ext2/ext2_inode.cpp @@ -1,19 +1,21 @@ #include "kernel/filesystem/ext2/ext2_inode.hpp" -#include "kernel/filesystem/ext2/ext2_file.hpp" +#include "kernel/filesystem/disk_file.hpp" #include "kernel/filesystem/file.hpp" #include "kernel/filesystem/inode.hpp" +#include "kernel/filesystem/inode_file.hpp" #include namespace filesystem::ext2 { - ext2_inode::ext2_inode() + ext2_inode::ext2_inode(kstd::shared_ptr const & disk_file) : inode(inode_kind::regular) + , m_disk_file(disk_file) {} auto ext2_inode::open_file() const -> kstd::shared_ptr { - return kstd::make_shared(); + return kstd::make_shared(m_disk_file); } } // namespace filesystem::ext2 \ No newline at end of file diff --git a/kernel/src/filesystem/inode_file.cpp b/kernel/src/filesystem/inode_file.cpp new file mode 100644 index 0000000..9c351da --- /dev/null +++ b/kernel/src/filesystem/inode_file.cpp @@ -0,0 +1,31 @@ +#include "kernel/filesystem/inode_file.hpp" + +#include "kapi/system.hpp" + +#include "kernel/filesystem/disk_file.hpp" + +#include + +#include + +namespace filesystem +{ + inode_file::inode_file(kstd::shared_ptr const & disk_file) + : m_disk_file(disk_file) + { + if (!m_disk_file) + { + kapi::system::panic("[FILESYSTEM] inode_file constructed with null disk_file."); + } + } + + auto inode_file::read(void * buffer, size_t offset, size_t size) const -> size_t + { + return m_disk_file->read(buffer, offset, size); + } + + auto inode_file::write(void const * buffer, size_t offset, size_t size) -> size_t + { + return m_disk_file->write(buffer, offset, size); + } +} // namespace filesystem \ No newline at end of file -- cgit v1.2.3 From 91feb8a2a70af1915c8cfa4ee7d95b6e276f5c02 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 20 Mar 2026 21:51:51 +0100 Subject: small refactoring --- kernel/src/filesystem/vfs.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 4b0c7d7..1bc9ae6 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -69,13 +69,12 @@ namespace filesystem { auto node = custody->get_inode(); - auto current_inode_file = node->open_file(); - if (!current_inode_file) + if (auto current_inode_file = node->open_file();) { - kapi::system::panic("[FILESYSTEM] inode::open_file returned null file."); + return open_file_description{current_inode_file}; } - return open_file_description{current_inode_file}; + kapi::system::panic("[FILESYSTEM] inode::open_file returned null file."); } return std::nullopt; -- cgit v1.2.3 From b02b90f21de5954aef34eb37a17775f194b8de39 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 20 Mar 2026 22:11:33 +0100 Subject: prepare test code for a further test function --- kernel/src/main.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index eb59402..e719164 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -18,7 +18,7 @@ #include #include -auto run_test_code() -> void +auto test_file_description_manually() -> void { // setup auto fd_table = filesystem::file_descriptor_table::get(); @@ -85,6 +85,17 @@ auto run_test_code() -> void kstd::println("---"); } +auto test_device_with_vfs() -> void +{ + // TODO BA-FS26 +} + +auto run_test_code() -> void +{ + test_file_description_manually(); + test_device_with_vfs(); +} + auto main() -> int { kapi::cio::init(); -- cgit v1.2.3 From a396b71827a24f9d6c8010fd85b9afd9d86b6e2a Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 20 Mar 2026 22:13:36 +0100 Subject: implement first draft of a do_mount function --- kernel/src/filesystem/vfs.cpp | 49 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 1bc9ae6..febb844 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -36,13 +36,12 @@ namespace filesystem if (auto boot_device = storage_mgmt.determine_boot_device()) { active_vfs->m_root_fs = kstd::make_shared(); - if (active_vfs->m_root_fs->mount(boot_device) != 0) + if (active_vfs->do_mount("/", active_vfs->m_root_fs) != 0) { kapi::system::panic("[FILESYSTEM] Failed to mount root filesystem."); } - active_vfs->m_root_mount = mount{"/", active_vfs->m_root_fs}; - + // TODO BA-FS26 use do_mount when tempdevfs is implemented -> just call /dev/ with all devices in devtempfs std::ranges::for_each(storage_mgmt.all_controllers(), [&](auto controller) { std::ranges::for_each(controller->all_devices(), [&](auto device) { active_vfs->make_device_node(device); }); }); @@ -69,8 +68,9 @@ namespace filesystem { auto node = custody->get_inode(); - if (auto current_inode_file = node->open_file();) + if (auto current_inode_file = node->open_file()) { + // TODO BA-FS26 return shared_ptr? return open_file_description{current_inode_file}; } @@ -80,6 +80,45 @@ namespace filesystem return std::nullopt; } + auto vfs::do_mount(std::string_view path, kstd::shared_ptr const & filesystem) -> int + { + if (!filesystem) + { + return -1; // TODO BA-FS26 panic or errorcode? + } + + if (path.empty() || path.front() != '/') + { + return -1; // TODO BA-FS26 panic or errorcode? + } + + // TODO BA-FS26 better path validation + if ((path.size() > 1 && path.back() == '/') || path.find("//") != std::string_view::npos) + { + return -1; // TODO BA-FS26 panic or errorcode? + } + + if (path == "/") + { + m_root_fs = filesystem; + m_root_mount = mount{"/", filesystem}; + return 0; + } + + auto existing_mount = + std::ranges::find_if(m_mounts, [&](auto const & existing) { return existing.path() == path; }); + if (existing_mount != m_mounts.end()) + { + *existing_mount = mount{path, filesystem}; + } + else + { + m_mounts.push_back(mount{path, filesystem}); + } + + return 0; + } + auto vfs::make_device_node(kstd::shared_ptr const & device) -> void { if (!device) @@ -94,6 +133,8 @@ namespace filesystem { // TODO BA-FS26 implement real path resolution with mounts and directories etc. // For now, just support device nodes at /dev/. + // TODO BA-FS26 better path validation + // TODO BA-FS26 implement a path parser (maybe in libs?) and use it here and in do_mount constexpr auto device_prefix = std::string_view{"/dev/"}; if (path.starts_with(device_prefix)) -- cgit v1.2.3 From be44d4b778bb7c3a947af4cae610ecc3b8851672 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 20 Mar 2026 22:27:26 +0100 Subject: use kstd::shared_ptr instead of std::optional for open_file_descriptions --- kernel/src/filesystem/file_descriptor_table.cpp | 24 ++++++++++++++++-------- kernel/src/filesystem/vfs.cpp | 8 ++++---- kernel/src/main.cpp | 4 ++-- 3 files changed, 22 insertions(+), 14 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/file_descriptor_table.cpp b/kernel/src/filesystem/file_descriptor_table.cpp index 814322e..6eb3845 100644 --- a/kernel/src/filesystem/file_descriptor_table.cpp +++ b/kernel/src/filesystem/file_descriptor_table.cpp @@ -4,6 +4,8 @@ #include "kernel/filesystem/open_file_description.hpp" +#include + #include #include #include @@ -35,9 +37,15 @@ namespace filesystem return *global_file_descriptor_table; } - auto file_descriptor_table::add_file(open_file_description & file_description) -> int + auto file_descriptor_table::add_file(kstd::shared_ptr const & file_description) -> int { - auto it = std::ranges::find_if(m_open_files, [](auto & open_file) { return !open_file.has_value(); }); + if (!file_description) + { + // TODO BA-FS26 panic or errorcode? + return -1; + } + + auto it = std::ranges::find_if(m_open_files, [](auto const & open_file) { return open_file == nullptr; }); if (it != m_open_files.end()) { *it = file_description; @@ -48,20 +56,20 @@ namespace filesystem return static_cast(m_open_files.size() - 1); } - auto file_descriptor_table::get_file(int fd) const -> std::optional + auto file_descriptor_table::get_file(int fd) const -> kstd::shared_ptr { if (fd < 0) { - return std::nullopt; + return nullptr; } auto const index = static_cast(fd); - if (index >= m_open_files.size() || !m_open_files.at(fd).has_value()) + if (index >= m_open_files.size()) { - return std::nullopt; + return nullptr; } - return m_open_files.at(fd); + return m_open_files.at(index); } auto file_descriptor_table::remove_file(int fd) -> void @@ -77,6 +85,6 @@ namespace filesystem return; } - m_open_files.at(fd).reset(); + m_open_files.at(index) = nullptr; } } // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index febb844..a3e554e 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -7,6 +7,7 @@ #include "kernel/filesystem/custody.hpp" #include "kernel/filesystem/device_inode.hpp" #include "kernel/filesystem/ext2/ext2_filesystem.hpp" +#include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/mount.hpp" #include "kernel/filesystem/open_file_description.hpp" @@ -62,7 +63,7 @@ namespace filesystem return *active_vfs; } - auto vfs::open(std::string_view path) -> std::optional + auto vfs::open(std::string_view path) -> kstd::shared_ptr { if (auto custody = resolve_path(path)) { @@ -70,14 +71,13 @@ namespace filesystem if (auto current_inode_file = node->open_file()) { - // TODO BA-FS26 return shared_ptr? - return open_file_description{current_inode_file}; + return kstd::make_shared(current_inode_file); } kapi::system::panic("[FILESYSTEM] inode::open_file returned null file."); } - return std::nullopt; + return nullptr; } auto vfs::do_mount(std::string_view path, kstd::shared_ptr const & filesystem) -> int diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index e719164..31133a5 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -26,7 +26,7 @@ auto test_file_description_manually() -> void auto device = storage_mgmt.device_by_major_minor(1, 0); auto dev_file = kstd::make_shared(device); - filesystem::open_file_description ofd(dev_file); + auto ofd = kstd::make_shared(dev_file); auto fd_index = fd_table.add_file(ofd); // use: read two bytes and write two again @@ -61,7 +61,7 @@ auto test_file_description_manually() -> void fd_table.remove_file(fd_index); // use: read four bytes again -> two old bytes two new bytes - filesystem::open_file_description ofd1(dev_file); + auto ofd1 = kstd::make_shared(dev_file); fd_index = fd_table.add_file(ofd1); auto fd1 = fd_table.get_file(fd_index); -- cgit v1.2.3 From 90452b752688110db2edc8d5dccdf0d6e0face5f Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 20 Mar 2026 23:17:11 +0100 Subject: fix build --- kernel/src/filesystem/vfs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index a3e554e..ee5fd9b 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -93,7 +93,7 @@ namespace filesystem } // TODO BA-FS26 better path validation - if ((path.size() > 1 && path.back() == '/') || path.find("//") != std::string_view::npos) + if ((path.size() > 1 && path.back() == '/')) { return -1; // TODO BA-FS26 panic or errorcode? } -- cgit v1.2.3 From ba63fbfc2bb43a6f0f05b6b49fd51fd6c89a0861 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 21 Mar 2026 00:28:17 +0100 Subject: refactor file and inode architecture again --- kernel/src/filesystem/device_file.cpp | 25 +++++++++++++++++-------- kernel/src/filesystem/device_inode.cpp | 14 ++++++++++++-- kernel/src/filesystem/ext2/ext2_inode.cpp | 15 ++++++++++----- kernel/src/filesystem/file.cpp | 20 ++++++++++++++++++++ kernel/src/filesystem/inode_file.cpp | 21 ++++++++++++--------- kernel/src/filesystem/vfs.cpp | 5 +++-- kernel/src/main.cpp | 5 ++++- 7 files changed, 78 insertions(+), 27 deletions(-) create mode 100644 kernel/src/filesystem/file.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/device_file.cpp b/kernel/src/filesystem/device_file.cpp index 48ed20d..26c7511 100644 --- a/kernel/src/filesystem/device_file.cpp +++ b/kernel/src/filesystem/device_file.cpp @@ -4,6 +4,9 @@ #include "kernel/devices/block_device.hpp" #include "kernel/devices/device.hpp" +#include "kernel/filesystem/device_inode.hpp" +#include "kernel/filesystem/file.hpp" +#include "kernel/filesystem/inode.hpp" #include #include @@ -14,18 +17,18 @@ namespace filesystem { - device_file::device_file(kstd::shared_ptr const & device) - : m_device(device) + device_file::device_file(kstd::shared_ptr const & inode) + : file(inode) { - if (!m_device) + if (!m_inode->is_device()) { - kapi::system::panic("[FILESYSTEM] device_file constructed with null device."); + kapi::system::panic("[FILESYSTEM] device_file constructed with non-device inode."); } } auto device_file::read(void * buffer, size_t offset, size_t size) const -> size_t { - if (m_device->is_block_device()) + if (device()->is_block_device()) { return process_blocks(offset, size, buffer, [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, @@ -50,7 +53,7 @@ namespace filesystem auto device_file::write(void const * buffer, size_t offset, size_t size) -> size_t { - if (m_device->is_block_device()) + if (device()->is_block_device()) { return process_blocks(offset, size, const_cast(buffer), [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, @@ -78,7 +81,7 @@ namespace filesystem { if (buffer == nullptr) { - kapi::system::panic("[FILESYSTEM] device_file::write called with null buffer."); + kapi::system::panic("[FILESYSTEM] device_file::process_blocks called with null buffer."); } if (size == 0) @@ -86,7 +89,7 @@ namespace filesystem return 0; } - auto * block_dev = static_cast(m_device.get()); + auto * block_dev = static_cast(device().get()); if (block_dev == nullptr) { kapi::system::panic("[FILESYSTEM] device_file: expected block_device."); @@ -116,4 +119,10 @@ namespace filesystem return processed; } + + auto device_file::device() const -> kstd::shared_ptr const & + { + auto inode = static_cast(m_inode.get()); + return inode->device(); + } } // namespace filesystem diff --git a/kernel/src/filesystem/device_inode.cpp b/kernel/src/filesystem/device_inode.cpp index 592637d..65dd9a3 100644 --- a/kernel/src/filesystem/device_inode.cpp +++ b/kernel/src/filesystem/device_inode.cpp @@ -21,8 +21,18 @@ namespace filesystem } } - auto device_inode::open_file() const -> kstd::shared_ptr + auto device_inode::open_file(kstd::shared_ptr const & self) const -> kstd::shared_ptr { - return kstd::make_shared(m_device); + if (!self) + { + kapi::system::panic("[FILESYSTEM] device_inode::open_file called with null inode."); + } + + return kstd::make_shared(self); + } + + auto device_inode::device() const -> kstd::shared_ptr const & + { + return m_device; } } // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/ext2/ext2_inode.cpp b/kernel/src/filesystem/ext2/ext2_inode.cpp index 8131f43..0a1994b 100644 --- a/kernel/src/filesystem/ext2/ext2_inode.cpp +++ b/kernel/src/filesystem/ext2/ext2_inode.cpp @@ -1,6 +1,7 @@ #include "kernel/filesystem/ext2/ext2_inode.hpp" -#include "kernel/filesystem/disk_file.hpp" +#include "kapi/system.hpp" + #include "kernel/filesystem/file.hpp" #include "kernel/filesystem/inode.hpp" #include "kernel/filesystem/inode_file.hpp" @@ -9,13 +10,17 @@ namespace filesystem::ext2 { - ext2_inode::ext2_inode(kstd::shared_ptr const & disk_file) + ext2_inode::ext2_inode() : inode(inode_kind::regular) - , m_disk_file(disk_file) {} - auto ext2_inode::open_file() const -> kstd::shared_ptr + auto ext2_inode::open_file(kstd::shared_ptr const & self) const -> kstd::shared_ptr { - return kstd::make_shared(m_disk_file); + if (!self) + { + kapi::system::panic("[FILESYSTEM] ext2_inode::open_file called with null inode."); + } + + return kstd::make_shared(self); } } // namespace filesystem::ext2 \ No newline at end of file diff --git a/kernel/src/filesystem/file.cpp b/kernel/src/filesystem/file.cpp new file mode 100644 index 0000000..a147863 --- /dev/null +++ b/kernel/src/filesystem/file.cpp @@ -0,0 +1,20 @@ +#include "kernel/filesystem/file.hpp" + +#include "kapi/system.hpp" + +#include "kernel/filesystem/inode.hpp" + +#include + +namespace filesystem +{ + + file::file(kstd::shared_ptr const & inode) + : m_inode(inode) + { + if (!m_inode) + { + kapi::system::panic("[FILESYSTEM] file constructed with null inode."); + } + } +} // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/inode_file.cpp b/kernel/src/filesystem/inode_file.cpp index 9c351da..8b2fcba 100644 --- a/kernel/src/filesystem/inode_file.cpp +++ b/kernel/src/filesystem/inode_file.cpp @@ -2,7 +2,8 @@ #include "kapi/system.hpp" -#include "kernel/filesystem/disk_file.hpp" +#include "kernel/filesystem/file.hpp" +#include "kernel/filesystem/inode.hpp" #include @@ -10,22 +11,24 @@ namespace filesystem { - inode_file::inode_file(kstd::shared_ptr const & disk_file) - : m_disk_file(disk_file) + inode_file::inode_file(kstd::shared_ptr const & inode) + : file(inode) { - if (!m_disk_file) + if (m_inode->is_device()) { - kapi::system::panic("[FILESYSTEM] inode_file constructed with null disk_file."); + kapi::system::panic("[FILESYSTEM] inode_file constructed with device inode."); } } - auto inode_file::read(void * buffer, size_t offset, size_t size) const -> size_t + auto inode_file::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t { - return m_disk_file->read(buffer, offset, size); + // TODO BA-FS26 + return 0; } - auto inode_file::write(void const * buffer, size_t offset, size_t size) -> size_t + auto inode_file::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t { - return m_disk_file->write(buffer, offset, size); + // TODO BA-FS26 + return 0; } } // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index ee5fd9b..5330b82 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -34,6 +34,7 @@ namespace filesystem active_vfs.emplace(vfs{}); auto storage_mgmt = devices::storage::storage_management::get(); + // TODO BA-FS26 fix mounting boot_device if (auto boot_device = storage_mgmt.determine_boot_device()) { active_vfs->m_root_fs = kstd::make_shared(); @@ -69,9 +70,9 @@ namespace filesystem { auto node = custody->get_inode(); - if (auto current_inode_file = node->open_file()) + if (auto opened_file = node->open_file(node)) { - return kstd::make_shared(current_inode_file); + return kstd::make_shared(opened_file); } kapi::system::panic("[FILESYSTEM] inode::open_file returned null file."); diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 31133a5..8d7308b 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -5,6 +5,7 @@ #include "kernel/devices/storage/storage_management.hpp" #include "kernel/filesystem/device_file.hpp" +#include "kernel/filesystem/device_inode.hpp" #include "kernel/filesystem/file_descriptor_table.hpp" #include "kernel/filesystem/open_file_description.hpp" #include "kernel/filesystem/vfs.hpp" @@ -25,7 +26,9 @@ auto test_file_description_manually() -> void auto storage_mgmt = devices::storage::storage_management::get(); auto device = storage_mgmt.device_by_major_minor(1, 0); - auto dev_file = kstd::make_shared(device); + auto dev_node = kstd::make_shared(device); + + auto dev_file = kstd::make_shared(dev_node); auto ofd = kstd::make_shared(dev_file); auto fd_index = fd_table.add_file(ofd); -- cgit v1.2.3 From ffb2accb09a013d8da16acd824c846bc1acfd8e4 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 21 Mar 2026 10:52:46 +0100 Subject: use enable_shared_from_this instead of self invocation method --- kernel/src/filesystem/device_inode.cpp | 9 ++------- kernel/src/filesystem/ext2/ext2_inode.cpp | 11 ++--------- kernel/src/filesystem/vfs.cpp | 2 +- 3 files changed, 5 insertions(+), 17 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/device_inode.cpp b/kernel/src/filesystem/device_inode.cpp index 65dd9a3..b9ccd6d 100644 --- a/kernel/src/filesystem/device_inode.cpp +++ b/kernel/src/filesystem/device_inode.cpp @@ -21,14 +21,9 @@ namespace filesystem } } - auto device_inode::open_file(kstd::shared_ptr const & self) const -> kstd::shared_ptr + auto device_inode::open_file() -> kstd::shared_ptr { - if (!self) - { - kapi::system::panic("[FILESYSTEM] device_inode::open_file called with null inode."); - } - - return kstd::make_shared(self); + return kstd::make_shared(shared_from_this()); } auto device_inode::device() const -> kstd::shared_ptr const & diff --git a/kernel/src/filesystem/ext2/ext2_inode.cpp b/kernel/src/filesystem/ext2/ext2_inode.cpp index 0a1994b..0760cb1 100644 --- a/kernel/src/filesystem/ext2/ext2_inode.cpp +++ b/kernel/src/filesystem/ext2/ext2_inode.cpp @@ -1,7 +1,5 @@ #include "kernel/filesystem/ext2/ext2_inode.hpp" -#include "kapi/system.hpp" - #include "kernel/filesystem/file.hpp" #include "kernel/filesystem/inode.hpp" #include "kernel/filesystem/inode_file.hpp" @@ -14,13 +12,8 @@ namespace filesystem::ext2 : inode(inode_kind::regular) {} - auto ext2_inode::open_file(kstd::shared_ptr const & self) const -> kstd::shared_ptr + auto ext2_inode::open_file() -> kstd::shared_ptr { - if (!self) - { - kapi::system::panic("[FILESYSTEM] ext2_inode::open_file called with null inode."); - } - - return kstd::make_shared(self); + return kstd::make_shared(shared_from_this()); } } // namespace filesystem::ext2 \ No newline at end of file diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 5330b82..2316de0 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -70,7 +70,7 @@ namespace filesystem { auto node = custody->get_inode(); - if (auto opened_file = node->open_file(node)) + if (auto opened_file = node->open_file()) { return kstd::make_shared(opened_file); } -- cgit v1.2.3 From 6c172389b562a08a6540574d6fbdf6a5bdce37b8 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 21 Mar 2026 16:22:23 +0100 Subject: simplify architecture again --- kernel/src/filesystem/device_file.cpp | 128 ------------------------ kernel/src/filesystem/device_inode.cpp | 100 ++++++++++++++++-- kernel/src/filesystem/ext2/ext2_inode.cpp | 15 ++- kernel/src/filesystem/file.cpp | 20 ---- kernel/src/filesystem/inode_file.cpp | 34 ------- kernel/src/filesystem/open_file_description.cpp | 14 +-- kernel/src/filesystem/vfs.cpp | 6 +- kernel/src/main.cpp | 9 +- 8 files changed, 118 insertions(+), 208 deletions(-) delete mode 100644 kernel/src/filesystem/device_file.cpp delete mode 100644 kernel/src/filesystem/file.cpp delete mode 100644 kernel/src/filesystem/inode_file.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/device_file.cpp b/kernel/src/filesystem/device_file.cpp deleted file mode 100644 index 26c7511..0000000 --- a/kernel/src/filesystem/device_file.cpp +++ /dev/null @@ -1,128 +0,0 @@ -#include "kernel/filesystem/device_file.hpp" - -#include "kapi/system.hpp" - -#include "kernel/devices/block_device.hpp" -#include "kernel/devices/device.hpp" -#include "kernel/filesystem/device_inode.hpp" -#include "kernel/filesystem/file.hpp" -#include "kernel/filesystem/inode.hpp" - -#include -#include -#include - -#include -#include - -namespace filesystem -{ - device_file::device_file(kstd::shared_ptr const & inode) - : file(inode) - { - if (!m_inode->is_device()) - { - kapi::system::panic("[FILESYSTEM] device_file constructed with non-device inode."); - } - } - - auto device_file::read(void * buffer, size_t offset, size_t size) const -> size_t - { - if (device()->is_block_device()) - { - return process_blocks(offset, size, buffer, - [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, - std::byte * scratch, void * buffer) { - auto * out = static_cast(buffer); - if (off == 0 && len == device->block_size()) - { - device->read_block(idx, out + done); - } - else - { - device->read_block(idx, scratch); - kstd::libc::memcpy(out + done, scratch + off, len); - } - }); - } - else - { - kapi::system::panic("[FILESYSTEM] device_file::read called on non-block device."); - } - } - - auto device_file::write(void const * buffer, size_t offset, size_t size) -> size_t - { - if (device()->is_block_device()) - { - return process_blocks(offset, size, const_cast(buffer), - [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, - std::byte * scratch, void * buffer) { - auto const * in = static_cast(buffer); - if (off == 0 && len == device->block_size()) - { - 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); - } - }); - } - else - { - kapi::system::panic("[FILESYSTEM] device_file::write called on non-block device."); - } - } - - auto device_file::process_blocks(size_t offset, size_t size, void * buffer, block_op op) const -> size_t - { - if (buffer == nullptr) - { - kapi::system::panic("[FILESYSTEM] device_file::process_blocks called with null buffer."); - } - - if (size == 0) - { - return 0; - } - - auto * block_dev = static_cast(device().get()); - if (block_dev == nullptr) - { - kapi::system::panic("[FILESYSTEM] device_file: expected block_device."); - } - - size_t const block_size = block_dev->block_size(); - size_t const capacity = block_dev->capacity(); - - if (offset >= capacity) - return 0; - size_t const total_to_process = std::min(size, capacity - offset); - - kstd::vector scratch_buffer{block_size}; - auto processed = 0uz; - - 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); - - processed += chunk_size; - } - - return processed; - } - - auto device_file::device() const -> kstd::shared_ptr const & - { - auto inode = static_cast(m_inode.get()); - return inode->device(); - } -} // namespace filesystem diff --git a/kernel/src/filesystem/device_inode.cpp b/kernel/src/filesystem/device_inode.cpp index b9ccd6d..812b43a 100644 --- a/kernel/src/filesystem/device_inode.cpp +++ b/kernel/src/filesystem/device_inode.cpp @@ -2,12 +2,16 @@ #include "kapi/system.hpp" +#include "kernel/devices/block_device.hpp" #include "kernel/devices/device.hpp" -#include "kernel/filesystem/device_file.hpp" -#include "kernel/filesystem/file.hpp" #include "kernel/filesystem/inode.hpp" +#include #include +#include + +#include +#include namespace filesystem { @@ -21,13 +25,97 @@ namespace filesystem } } - auto device_inode::open_file() -> kstd::shared_ptr + auto device_inode::read(void * buffer, size_t offset, size_t size) const -> size_t { - return kstd::make_shared(shared_from_this()); + if (m_device->is_block_device()) + { + return process_blocks(offset, size, buffer, + [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, + std::byte * scratch, void * buffer) { + auto * out = static_cast(buffer); + if (off == 0 && len == device->block_size()) + { + device->read_block(idx, out + done); + } + else + { + device->read_block(idx, scratch); + kstd::libc::memcpy(out + done, scratch + off, len); + } + }); + } + else + { + kapi::system::panic("[FILESYSTEM] device_file::read called on non-block device."); + } } - auto device_inode::device() const -> kstd::shared_ptr const & + auto device_inode::write(void const * buffer, size_t offset, size_t size) -> size_t { - return m_device; + if (m_device->is_block_device()) + { + return process_blocks(offset, size, const_cast(buffer), + [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, + std::byte * scratch, void * buffer) { + auto const * in = static_cast(buffer); + if (off == 0 && len == device->block_size()) + { + 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); + } + }); + } + else + { + kapi::system::panic("[FILESYSTEM] device_file::write called on non-block device."); + } + } + + auto device_inode::process_blocks(size_t offset, size_t size, void * buffer, block_op op) const -> size_t + { + if (buffer == nullptr) + { + kapi::system::panic("[FILESYSTEM] device_file::process_blocks called with null buffer."); + } + + if (size == 0) + { + return 0; + } + + auto * block_dev = static_cast(m_device.get()); + if (block_dev == nullptr) + { + kapi::system::panic("[FILESYSTEM] device_file: expected block_device."); + } + + size_t const block_size = block_dev->block_size(); + size_t const capacity = block_dev->capacity(); + + if (offset >= capacity) + return 0; + size_t const total_to_process = std::min(size, capacity - offset); + + kstd::vector scratch_buffer{block_size}; + auto processed = 0uz; + + 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); + + processed += chunk_size; + } + + return processed; } } // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/ext2/ext2_inode.cpp b/kernel/src/filesystem/ext2/ext2_inode.cpp index 0760cb1..3cc0fb2 100644 --- a/kernel/src/filesystem/ext2/ext2_inode.cpp +++ b/kernel/src/filesystem/ext2/ext2_inode.cpp @@ -1,10 +1,8 @@ #include "kernel/filesystem/ext2/ext2_inode.hpp" -#include "kernel/filesystem/file.hpp" #include "kernel/filesystem/inode.hpp" -#include "kernel/filesystem/inode_file.hpp" -#include +#include namespace filesystem::ext2 { @@ -12,8 +10,15 @@ namespace filesystem::ext2 : inode(inode_kind::regular) {} - auto ext2_inode::open_file() -> kstd::shared_ptr + auto ext2_inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t { - return kstd::make_shared(shared_from_this()); + // TODO BA-FS26 implement + return 0; + } + + auto ext2_inode::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t + { + // TODO BA-FS26 implement + return 0; } } // namespace filesystem::ext2 \ No newline at end of file diff --git a/kernel/src/filesystem/file.cpp b/kernel/src/filesystem/file.cpp deleted file mode 100644 index a147863..0000000 --- a/kernel/src/filesystem/file.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "kernel/filesystem/file.hpp" - -#include "kapi/system.hpp" - -#include "kernel/filesystem/inode.hpp" - -#include - -namespace filesystem -{ - - file::file(kstd::shared_ptr const & inode) - : m_inode(inode) - { - if (!m_inode) - { - kapi::system::panic("[FILESYSTEM] file constructed with null inode."); - } - } -} // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/inode_file.cpp b/kernel/src/filesystem/inode_file.cpp deleted file mode 100644 index 8b2fcba..0000000 --- a/kernel/src/filesystem/inode_file.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "kernel/filesystem/inode_file.hpp" - -#include "kapi/system.hpp" - -#include "kernel/filesystem/file.hpp" -#include "kernel/filesystem/inode.hpp" - -#include - -#include - -namespace filesystem -{ - inode_file::inode_file(kstd::shared_ptr const & inode) - : file(inode) - { - if (m_inode->is_device()) - { - kapi::system::panic("[FILESYSTEM] inode_file constructed with device inode."); - } - } - - auto inode_file::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t - { - // TODO BA-FS26 - return 0; - } - - auto inode_file::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t - { - // TODO BA-FS26 - return 0; - } -} // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/open_file_description.cpp b/kernel/src/filesystem/open_file_description.cpp index ff4d678..93c38ac 100644 --- a/kernel/src/filesystem/open_file_description.cpp +++ b/kernel/src/filesystem/open_file_description.cpp @@ -1,6 +1,6 @@ #include "kernel/filesystem/open_file_description.hpp" -#include "kernel/filesystem/file.hpp" +#include "kernel/filesystem/inode.hpp" #include #include @@ -9,26 +9,26 @@ namespace filesystem { - open_file_description::open_file_description(kstd::shared_ptr const & file) - : m_file(file) + open_file_description::open_file_description(kstd::shared_ptr const & inode) + : m_inode(inode) , m_offset(0) { - if (!file) + if (!inode) { - kstd::os::panic("[FILESYSTEM] open_file_description constructed with null file."); + kstd::os::panic("[FILESYSTEM] open_file_description constructed with null inode."); } } auto open_file_description::read(void * buffer, size_t size) -> size_t { - auto read_bytes = m_file->read(buffer, m_offset, size); + auto read_bytes = m_inode->read(buffer, m_offset, size); m_offset += read_bytes; return read_bytes; } auto open_file_description::write(void const * buffer, size_t size) -> size_t { - auto written_bytes = m_file->write(buffer, m_offset, size); + auto written_bytes = m_inode->write(buffer, m_offset, size); m_offset += written_bytes; return written_bytes; } diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 2316de0..86991ea 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -68,11 +68,9 @@ namespace filesystem { if (auto custody = resolve_path(path)) { - auto node = custody->get_inode(); - - if (auto opened_file = node->open_file()) + if (auto node = custody->get_inode()) { - return kstd::make_shared(opened_file); + return kstd::make_shared(node); } kapi::system::panic("[FILESYSTEM] inode::open_file returned null file."); diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 8d7308b..eb699bd 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -4,7 +4,6 @@ #include "kapi/system.hpp" #include "kernel/devices/storage/storage_management.hpp" -#include "kernel/filesystem/device_file.hpp" #include "kernel/filesystem/device_inode.hpp" #include "kernel/filesystem/file_descriptor_table.hpp" #include "kernel/filesystem/open_file_description.hpp" @@ -28,8 +27,7 @@ auto test_file_description_manually() -> void auto dev_node = kstd::make_shared(device); - auto dev_file = kstd::make_shared(dev_node); - auto ofd = kstd::make_shared(dev_file); + auto ofd = kstd::make_shared(dev_node); auto fd_index = fd_table.add_file(ofd); // use: read two bytes and write two again @@ -64,7 +62,7 @@ auto test_file_description_manually() -> void fd_table.remove_file(fd_index); // use: read four bytes again -> two old bytes two new bytes - auto ofd1 = kstd::make_shared(dev_file); + auto ofd1 = kstd::make_shared(dev_node); fd_index = fd_table.add_file(ofd1); auto fd1 = fd_table.get_file(fd_index); @@ -91,6 +89,9 @@ auto test_file_description_manually() -> void auto test_device_with_vfs() -> void { // TODO BA-FS26 + + auto vfs = filesystem::vfs::get(); + vfs.open("/"); } auto run_test_code() -> void -- cgit v1.2.3 From 9d23a9fb6ae774bf3b1345d0b7adcb88f9627dc0 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 21 Mar 2026 16:35:01 +0100 Subject: refactoring, node cannot be null --- kernel/src/filesystem/vfs.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 86991ea..c448618 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -68,12 +68,7 @@ namespace filesystem { if (auto custody = resolve_path(path)) { - if (auto node = custody->get_inode()) - { - return kstd::make_shared(node); - } - - kapi::system::panic("[FILESYSTEM] inode::open_file returned null file."); + return kstd::make_shared(custody->get_inode()); } return nullptr; -- cgit v1.2.3 From ac3510bb9f696869f059ecd4ece2c6970fa63b6c Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 21 Mar 2026 23:57:49 +0100 Subject: implement device names with kstd::string --- kernel/src/devices/block_device.cpp | 5 +++-- kernel/src/devices/device.cpp | 7 ++++--- kernel/src/devices/storage/ram_disk/ram_disk_device.cpp | 15 ++------------- kernel/src/filesystem/vfs.cpp | 2 +- kernel/src/main.cpp | 13 +++++++++++++ 5 files changed, 23 insertions(+), 19 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/devices/block_device.cpp b/kernel/src/devices/block_device.cpp index d12251b..3402814 100644 --- a/kernel/src/devices/block_device.cpp +++ b/kernel/src/devices/block_device.cpp @@ -4,12 +4,13 @@ #include "kernel/devices/device.hpp" +#include + #include -#include namespace devices { - block_device::block_device(size_t major, size_t minor, std::string_view name, size_t block_size) + block_device::block_device(size_t major, size_t minor, kstd::string const & name, size_t block_size) : device(major, minor, name) , m_block_size(block_size) { diff --git a/kernel/src/devices/device.cpp b/kernel/src/devices/device.cpp index 29498fa..287f14b 100644 --- a/kernel/src/devices/device.cpp +++ b/kernel/src/devices/device.cpp @@ -1,11 +1,12 @@ #include "kernel/devices/device.hpp" +#include + #include -#include namespace devices { - device::device(size_t major, size_t minor, std::string_view name) + device::device(size_t major, size_t minor, kstd::string const & name) : m_major(major) , m_minor(minor) , m_name(name) @@ -21,7 +22,7 @@ namespace devices return m_minor; } - auto device::name() const -> std::string_view + auto device::name() const -> kstd::string const & { return m_name; } diff --git a/kernel/src/devices/storage/ram_disk/ram_disk_device.cpp b/kernel/src/devices/storage/ram_disk/ram_disk_device.cpp index 650a151..bf329cb 100644 --- a/kernel/src/devices/storage/ram_disk/ram_disk_device.cpp +++ b/kernel/src/devices/storage/ram_disk/ram_disk_device.cpp @@ -6,30 +6,19 @@ #include "kernel/devices/block_device.hpp" #include +#include -#include #include -#include namespace devices::storage::ram_disk { namespace { constexpr size_t RAM_DISK_BLOCK_SIZE = 512uz; - - // TODO BA-FS26 @Felix - // TODO BA-FS26 currently only names for 9 minor devices - constinit std::array name = {'r', 'a', 'm', '0', '\0'}; - - auto determine_device_name(size_t minor) -> std::string_view - { - name[3] = '0' + minor; - return std::string_view{name}; - } } // namespace ram_disk_device::ram_disk_device(kapi::boot_modules::boot_module const & module, size_t major, size_t minor) - : block_device(major, minor, determine_device_name(minor), RAM_DISK_BLOCK_SIZE) + : block_device(major, minor, "ram" + kstd::to_string(minor), RAM_DISK_BLOCK_SIZE) , m_boot_module(module) {} diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index c448618..1bd6fb5 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -120,7 +120,7 @@ namespace filesystem kapi::system::panic("[FILESYSTEM] make_device_node called with null device."); } - m_device_nodes.push_back(device_node_entry{device->name(), kstd::make_shared(device)}); + m_device_nodes.push_back(device_node_entry{device->name().view(), kstd::make_shared(device)}); } auto vfs::resolve_path(std::string_view path) -> std::optional diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index eb699bd..1043c81 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -10,14 +10,26 @@ #include "kernel/filesystem/vfs.hpp" #include "kernel/memory.hpp" +#include #include #include #include +#include #include +#include #include #include +auto test_device_names() -> void +{ + auto storage_mgmt = devices::storage::storage_management::get(); + std::ranges::for_each(storage_mgmt.all_controllers(), [](auto const & controller) { + std::ranges::for_each(controller->all_devices(), + [](auto const & device) { kstd::println("{}", device->name().view()); }); + }); +} + auto test_file_description_manually() -> void { // setup @@ -96,6 +108,7 @@ auto test_device_with_vfs() -> void auto run_test_code() -> void { + test_device_names(); test_file_description_manually(); test_device_with_vfs(); } -- cgit v1.2.3 From fde90dcc551b35ea03fef1231fafac9faea2c5b5 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sun, 22 Mar 2026 09:31:03 +0100 Subject: add tests, use better println for vectors --- kernel/src/main.cpp | 57 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 24 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 1043c81..3ba240d 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -19,7 +19,6 @@ #include #include -#include auto test_device_names() -> void { @@ -51,17 +50,8 @@ auto test_file_description_manually() -> void kstd::vector buffer{2}; auto number_of_read_bytes = fd->read(buffer.data(), buffer.size()); - - for (size_t i = 0; i < number_of_read_bytes; ++i) - { - kstd::print("{:02x} ", static_cast(buffer[i])); - - if ((i + 1) % 16 == 0) - { - kstd::println(""); - } - } - kstd::println("---"); + kstd::println("read bytes: {}", number_of_read_bytes); + kstd::println("buffer: {::#04x}", buffer); // write half of the file new auto const value1 = std::byte{0xAA}; @@ -85,17 +75,8 @@ auto test_file_description_manually() -> void kstd::vector buffer1{4}; number_of_read_bytes = fd1->read(buffer1.data(), buffer1.size()); - - for (size_t i = 0; i < number_of_read_bytes; ++i) - { - kstd::print("{:02x} ", static_cast(buffer1[i])); - - if ((i + 1) % 16 == 0) - { - kstd::println(""); - } - } - kstd::println("---"); + kstd::println("read bytes: {}", number_of_read_bytes); + kstd::println("buffer: {::#04x}", buffer1); } auto test_device_with_vfs() -> void @@ -103,14 +84,41 @@ auto test_device_with_vfs() -> void // TODO BA-FS26 auto vfs = filesystem::vfs::get(); - vfs.open("/"); + auto ofd = vfs.open("/dev/ram0"); + if (!ofd) + { + kstd::os::panic("test code failed"); + } + + auto fd_table = filesystem::file_descriptor_table::get(); + auto fd = fd_table.add_file(ofd); + kstd::vector buffer{2}; + auto file = fd_table.get_file(fd); + if (!file) + { + kstd::os::panic("test code failed"); + } + + auto number_of_read_bytes = file->read(buffer.data(), buffer.size()); + kstd::println("read bytes: {}", number_of_read_bytes); + kstd::println("buffer: {::#04x}", buffer); } auto run_test_code() -> void { + kstd::println("[TEST] Running test code..."); + + kstd::println("[TEST] device names"); test_device_names(); + kstd::println("---------------------------------"); + + kstd::println("[TEST] file description manually"); test_file_description_manually(); + kstd::println("---------------------------------"); + + kstd::println("[TEST] device with VFS"); test_device_with_vfs(); + kstd::println("---------------------------------"); } auto main() -> int @@ -136,6 +144,7 @@ auto main() -> int kstd::println("[OS] Virtual filesystem initialized."); run_test_code(); + kstd::println("[TEST] All tests completed."); kapi::system::panic("Returning from kernel main!"); } -- cgit v1.2.3 From f90cbdaa91b1b7a4752db3f159ce2524696cff9f Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Mon, 23 Mar 2026 09:03:27 +0100 Subject: Rename custody to dentry and add children --- kernel/src/filesystem/custody.cpp | 30 ------------------------------ kernel/src/filesystem/dentry.cpp | 30 ++++++++++++++++++++++++++++++ kernel/src/filesystem/vfs.cpp | 16 ++++++++-------- 3 files changed, 38 insertions(+), 38 deletions(-) delete mode 100644 kernel/src/filesystem/custody.cpp create mode 100644 kernel/src/filesystem/dentry.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/custody.cpp b/kernel/src/filesystem/custody.cpp deleted file mode 100644 index a4dd12c..0000000 --- a/kernel/src/filesystem/custody.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "kernel/filesystem/custody.hpp" - -#include "kapi/system.hpp" - -#include "kernel/filesystem/inode.hpp" - -#include - -namespace filesystem -{ - custody::custody(kstd::shared_ptr const & parent, kstd::shared_ptr const & node) - : m_parent(parent) - , m_inode(node) - { - if (!m_inode) - { - kapi::system::panic("[FILESYSTEM] custody constructed with null inode."); - } - } - - auto custody::get_inode() const -> kstd::shared_ptr const & - { - return m_inode; - } - - auto custody::get_parent() const -> kstd::shared_ptr const & - { - return m_parent; - } -} // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp new file mode 100644 index 0000000..08f0b25 --- /dev/null +++ b/kernel/src/filesystem/dentry.cpp @@ -0,0 +1,30 @@ +#include "kernel/filesystem/dentry.hpp" + +#include "kapi/system.hpp" + +#include "kernel/filesystem/inode.hpp" + +#include + +namespace filesystem +{ + dentry::dentry(kstd::shared_ptr const & parent, kstd::shared_ptr const & node) + : m_parent(parent) + , m_inode(node) + { + if (!m_inode) + { + kapi::system::panic("[FILESYSTEM] dentry constructed with null inode."); + } + } + + auto dentry::get_inode() const -> kstd::shared_ptr const & + { + return m_inode; + } + + auto dentry::get_parent() const -> kstd::shared_ptr const & + { + return m_parent; + } +} // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 1bd6fb5..a111f23 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -4,7 +4,7 @@ #include "kernel/devices/device.hpp" #include "kernel/devices/storage/storage_management.hpp" -#include "kernel/filesystem/custody.hpp" +#include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/device_inode.hpp" #include "kernel/filesystem/ext2/ext2_filesystem.hpp" #include "kernel/filesystem/filesystem.hpp" @@ -66,9 +66,9 @@ namespace filesystem auto vfs::open(std::string_view path) -> kstd::shared_ptr { - if (auto custody = resolve_path(path)) + if (auto dentry = resolve_path(path)) { - return kstd::make_shared(custody->get_inode()); + return kstd::make_shared(dentry->get_inode()); } return nullptr; @@ -100,14 +100,14 @@ namespace filesystem } auto existing_mount = - std::ranges::find_if(m_mounts, [&](auto const & existing) { return existing.path() == path; }); - if (existing_mount != m_mounts.end()) + std::ranges::find_if(m_mount_table, [&](auto const & existing) { return existing.path() == path; }); + if (existing_mount != m_mount_table.end()) { *existing_mount = mount{path, filesystem}; } else { - m_mounts.push_back(mount{path, filesystem}); + m_mount_table.push_back(mount{path, filesystem}); } return 0; @@ -123,7 +123,7 @@ namespace filesystem m_device_nodes.push_back(device_node_entry{device->name().view(), kstd::make_shared(device)}); } - auto vfs::resolve_path(std::string_view path) -> std::optional + auto vfs::resolve_path(std::string_view path) -> std::optional { // TODO BA-FS26 implement real path resolution with mounts and directories etc. // For now, just support device nodes at /dev/. @@ -140,7 +140,7 @@ namespace filesystem if (entry != m_device_nodes.end()) { - return custody{nullptr, entry->value().node}; + return dentry{nullptr, entry->value().node}; } return std::nullopt; -- cgit v1.2.3 From d70e2df0885a844d47b6498bf2c710fb9730b364 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Mon, 23 Mar 2026 09:49:10 +0100 Subject: Add dentry structure --- kernel/src/filesystem/dentry.cpp | 17 +++++++++++++++++ kernel/src/filesystem/vfs.cpp | 21 +++++++++++---------- 2 files changed, 28 insertions(+), 10 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index 08f0b25..e498b52 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -6,6 +6,8 @@ #include +#include + namespace filesystem { dentry::dentry(kstd::shared_ptr const & parent, kstd::shared_ptr const & node) @@ -27,4 +29,19 @@ namespace filesystem { return m_parent; } + + auto dentry::set_flag(dentry_flags flag) -> void + { + m_flags |= static_cast(flag); + } + + auto dentry::unset_flag(dentry_flags flag) -> void + { + m_flags &= ~static_cast(flag); + } + + auto dentry::has_flag(dentry_flags flag) const -> bool + { + return (m_flags & static_cast(flag)) != 0; + } } // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index a111f23..2c4a4d5 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -38,10 +38,11 @@ namespace filesystem if (auto boot_device = storage_mgmt.determine_boot_device()) { active_vfs->m_root_fs = kstd::make_shared(); - if (active_vfs->do_mount("/", active_vfs->m_root_fs) != 0) - { - kapi::system::panic("[FILESYSTEM] Failed to mount root filesystem."); - } + active_vfs->m_root_dentry = kstd::make_shared(nullptr, active_vfs->m_root_fs->root_inode()); + // if (active_vfs->do_mount("/", active_vfs->m_root_fs) != 0) + // { + // kapi::system::panic("[FILESYSTEM] Failed to mount root filesystem."); + // } // TODO BA-FS26 use do_mount when tempdevfs is implemented -> just call /dev/ with all devices in devtempfs std::ranges::for_each(storage_mgmt.all_controllers(), [&](auto controller) { @@ -92,12 +93,12 @@ namespace filesystem return -1; // TODO BA-FS26 panic or errorcode? } - if (path == "/") - { - m_root_fs = filesystem; - m_root_mount = mount{"/", filesystem}; - return 0; - } + // if (path == "/") + // { + // m_root_fs = filesystem; + // m_root_mount = mount{"/", filesystem}; + // return 0; + // } auto existing_mount = std::ranges::find_if(m_mount_table, [&](auto const & existing) { return existing.path() == path; }); -- cgit v1.2.3 From bcb4f8a76dea2443c1597716e27b7c2d268bfc44 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Mon, 23 Mar 2026 09:49:32 +0100 Subject: Refactor filesystem --- kernel/src/filesystem/ext2/ext2_filesystem.cpp | 8 ++------ kernel/src/filesystem/filesystem.cpp | 11 +++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/ext2_filesystem.cpp b/kernel/src/filesystem/ext2/ext2_filesystem.cpp index 87845d5..ea692ee 100644 --- a/kernel/src/filesystem/ext2/ext2_filesystem.cpp +++ b/kernel/src/filesystem/ext2/ext2_filesystem.cpp @@ -1,6 +1,7 @@ #include "kernel/filesystem/ext2/ext2_filesystem.hpp" #include "kernel/devices/device.hpp" +#include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" #include @@ -11,12 +12,7 @@ namespace filesystem::ext2 { auto ext2_filesystem::mount(kstd::shared_ptr const & device) -> int { - if (!device) - { - return -1; // TODO BA-FS26 panic or errorcode? - } - - m_device = device; + filesystem::mount(device); // TODO BA-FS26 error handling? // TODO BA-FS26 load proper root inode from ext2 metadata // m_root_inode = inode{inode_kind::directory}; diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index 50b5587..0e33d95 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -1,11 +1,22 @@ #include "kernel/filesystem/filesystem.hpp" +#include "kernel/devices/device.hpp" #include "kernel/filesystem/inode.hpp" #include namespace filesystem { + auto filesystem::mount(kstd::shared_ptr const & device) -> int + { + if (!device) + { + return -1; // TODO BA-FS26 panic or errorcode? + } + m_device = device; + return 0; + } + auto filesystem::root_inode() const -> kstd::shared_ptr const & { return m_root_inode; -- cgit v1.2.3 From fdcf1c7d2b47d418916e311cea8b87affaf63f90 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Mon, 23 Mar 2026 20:12:29 +0100 Subject: Small refactoring use shared pointer --- kernel/src/filesystem/ext2/ext2_filesystem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/ext2_filesystem.cpp b/kernel/src/filesystem/ext2/ext2_filesystem.cpp index ea692ee..536e328 100644 --- a/kernel/src/filesystem/ext2/ext2_filesystem.cpp +++ b/kernel/src/filesystem/ext2/ext2_filesystem.cpp @@ -20,7 +20,8 @@ namespace filesystem::ext2 return 0; } - auto ext2_filesystem::lookup(inode const & /*parent*/, std::string_view /*name*/) -> inode * + auto ext2_filesystem::lookup(kstd::shared_ptr const & /*parent*/, std::string_view /*name*/) + -> kstd::shared_ptr { // TODO BA-FS26 implement ext2 directory traversal and inode loading return nullptr; -- cgit v1.2.3 From 7173e5ba354dccc4b5d5fea119b946f28bc5b08f Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Mon, 23 Mar 2026 20:22:43 +0100 Subject: Refactor move init logic into member function --- kernel/src/filesystem/vfs.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 2c4a4d5..ece3080 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -32,21 +32,28 @@ namespace filesystem } active_vfs.emplace(vfs{}); + active_vfs->init_internal(); + } + auto vfs::init_internal() -> void + { auto storage_mgmt = devices::storage::storage_management::get(); // TODO BA-FS26 fix mounting boot_device if (auto boot_device = storage_mgmt.determine_boot_device()) { - active_vfs->m_root_fs = kstd::make_shared(); - active_vfs->m_root_dentry = kstd::make_shared(nullptr, active_vfs->m_root_fs->root_inode()); - // if (active_vfs->do_mount("/", active_vfs->m_root_fs) != 0) + m_root_fs = kstd::make_shared(); + + m_root_fs->mount(boot_device); + + m_root_dentry = kstd::make_shared(nullptr, m_root_fs->root_inode()); + // if (do_mount("/", m_root_fs) != 0) // { // kapi::system::panic("[FILESYSTEM] Failed to mount root filesystem."); // } // TODO BA-FS26 use do_mount when tempdevfs is implemented -> just call /dev/ with all devices in devtempfs std::ranges::for_each(storage_mgmt.all_controllers(), [&](auto controller) { - std::ranges::for_each(controller->all_devices(), [&](auto device) { active_vfs->make_device_node(device); }); + std::ranges::for_each(controller->all_devices(), [&](auto device) { make_device_node(device); }); }); } else -- cgit v1.2.3 From fbb4eefce7bf825b0406f6fa63de318153a3b95a Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Mon, 23 Mar 2026 21:41:37 +0100 Subject: Implement resolve_path --- kernel/src/filesystem/dentry.cpp | 18 ++++++++++++++-- kernel/src/filesystem/vfs.cpp | 46 +++++++++++++++++++++++++++++++++++----- 2 files changed, 57 insertions(+), 7 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index e498b52..76949f2 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -6,12 +6,15 @@ #include +#include #include +#include namespace filesystem { - dentry::dentry(kstd::shared_ptr const & parent, kstd::shared_ptr const & node) - : m_parent(parent) + dentry::dentry(kstd::shared_ptr const & parent, kstd::shared_ptr const & node, std::string_view name) + : m_name(name) + , m_parent(parent) , m_inode(node) { if (!m_inode) @@ -30,6 +33,17 @@ namespace filesystem return m_parent; } + auto dentry::add_child(kstd::shared_ptr const & child) -> void + { + m_children.push_back(child); + } + + auto dentry::find_child(std::string_view name) const -> kstd::shared_ptr + { + auto it = std::ranges::find_if(m_children, [&](auto const & child) { return child->m_name == name; }); + return (it != m_children.end()) ? *it : nullptr; + } + auto dentry::set_flag(dentry_flags flag) -> void { m_flags |= static_cast(flag); diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index ece3080..0e8a76d 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -15,6 +15,7 @@ #include #include +#include #include namespace filesystem @@ -42,7 +43,6 @@ namespace filesystem if (auto boot_device = storage_mgmt.determine_boot_device()) { m_root_fs = kstd::make_shared(); - m_root_fs->mount(boot_device); m_root_dentry = kstd::make_shared(nullptr, m_root_fs->root_inode()); @@ -131,7 +131,7 @@ namespace filesystem m_device_nodes.push_back(device_node_entry{device->name().view(), kstd::make_shared(device)}); } - auto vfs::resolve_path(std::string_view path) -> std::optional + auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr { // TODO BA-FS26 implement real path resolution with mounts and directories etc. // For now, just support device nodes at /dev/. @@ -148,13 +148,49 @@ namespace filesystem if (entry != m_device_nodes.end()) { - return dentry{nullptr, entry->value().node}; + return kstd::make_shared(nullptr, entry->value().node); } - return std::nullopt; + return nullptr; } + else if (!path.empty() && path.front() == '/') + { + auto path_parts = + std::views::split(path, '/') | std::views::filter([](auto const & part) { return !part.empty(); }); + auto parent = m_root_dentry; - return std::nullopt; + for (auto const & part : path_parts) + { + if (auto child = parent->find_child(std::string_view{part})) + { + parent = child; + } + else if (auto found_inode = m_root_fs->lookup(parent->get_inode(), std::string_view{part})) + { + auto next_dentry = kstd::make_shared(parent, found_inode, std::string_view{part}); + parent->add_child(next_dentry); + parent = next_dentry; + } + else + { + return nullptr; + } + } + // | std::views::transform([this](auto const & part) { + // // TODO BA-FS26 implement real path resolution with mounts and directories etc. + // // For now, just return null for any non-device-node path. + // return std::optional>{}; + // }) + // | std::views::filter([](auto const & opt) { return opt.has_value(); }) + // | std::views::transform([](auto const & opt) { return opt.value(); }) + // | std::ranges::find_if(m_mount_table, [&](auto const & mount) { + // // TODO BA-FS26 implement real path resolution with mounts and directories etc. + // // For now, just check if the first path component matches a mount point. + // return part == mount.path(); + // }); + } + + return nullptr; } } // namespace filesystem \ No newline at end of file -- cgit v1.2.3 From b3cb1d0f8864bf54362f1da2b7a65ca693778cff Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Mon, 23 Mar 2026 22:18:54 +0100 Subject: Add test for resolve_path --- kernel/src/filesystem/ext2/ext2_filesystem.cpp | 5 ++++- kernel/src/main.cpp | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/ext2_filesystem.cpp b/kernel/src/filesystem/ext2/ext2_filesystem.cpp index 536e328..3f5774c 100644 --- a/kernel/src/filesystem/ext2/ext2_filesystem.cpp +++ b/kernel/src/filesystem/ext2/ext2_filesystem.cpp @@ -1,6 +1,7 @@ #include "kernel/filesystem/ext2/ext2_filesystem.hpp" #include "kernel/devices/device.hpp" +#include "kernel/filesystem/ext2/ext2_inode.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" @@ -17,6 +18,7 @@ namespace filesystem::ext2 // m_root_inode = inode{inode_kind::directory}; // TODO BA-FS26 implement + m_root_inode = kstd::make_shared(); return 0; } @@ -24,6 +26,7 @@ namespace filesystem::ext2 -> kstd::shared_ptr { // TODO BA-FS26 implement ext2 directory traversal and inode loading - return nullptr; + // return nullptr; + return kstd::make_shared(); } } // namespace filesystem::ext2 diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 3ba240d..a575be2 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -104,6 +104,16 @@ auto test_device_with_vfs() -> void kstd::println("buffer: {::#04x}", buffer); } +auto test_file_lookup() -> void +{ + // TODO BA-FS26 implement a more complete test with multiple files and directories and mounts etc. + + auto vfs = filesystem::vfs::get(); + vfs.open("/a/b/c"); + vfs.open("/a/d/e"); + vfs.open("x/y/z"); +} + auto run_test_code() -> void { kstd::println("[TEST] Running test code..."); @@ -119,6 +129,10 @@ auto run_test_code() -> void kstd::println("[TEST] device with VFS"); test_device_with_vfs(); kstd::println("---------------------------------"); + + kstd::println("[TEST] file lookup"); + test_file_lookup(); + kstd::println("---------------------------------"); } auto main() -> int -- cgit v1.2.3 From 444810121f9c89285da1ec118828640f0445b2a7 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Tue, 24 Mar 2026 16:50:27 +0100 Subject: Add mount_table --- kernel/src/filesystem/mount_table.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 kernel/src/filesystem/mount_table.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp new file mode 100644 index 0000000..0e9a53d --- /dev/null +++ b/kernel/src/filesystem/mount_table.cpp @@ -0,0 +1,29 @@ +#include "kernel/filesystem/mount_table.hpp" + +#include "kapi/system.hpp" + +#include "kernel/filesystem/dentry.hpp" +#include "kernel/filesystem/mount.hpp" + +#include + +#include + +namespace filesystem +{ + void mount_table::add_mount(kstd::shared_ptr mount) + { + m_mounts.push_back(mount); + } + + auto mount_table::find_mount_by_dentry(kstd::shared_ptr const & dentry) -> kstd::shared_ptr + { + auto found = + std::ranges::find_if(m_mounts, [&](auto const & mount) { return mount->get_dentry().get() == dentry.get(); }); + if (found != m_mounts.end()) + { + return *found; + } + kapi::system::panic("[FILESYSTEM] dentry has mount flag set but no corresponding mount found."); + } +} // namespace filesystem \ No newline at end of file -- cgit v1.2.3 From b742349ba039d1a864462332bb7ae5a071afdec1 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Tue, 24 Mar 2026 16:53:21 +0100 Subject: Refactor mount_table entry (mount) to use dentry as key instead of path --- kernel/src/filesystem/mount.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index a2c501f..b65f331 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -2,6 +2,7 @@ #include "kapi/system.hpp" +#include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/filesystem.hpp" #include @@ -10,8 +11,8 @@ namespace filesystem { - mount::mount(std::string_view const & path, kstd::shared_ptr const & fs) - : m_path(path) + mount::mount(kstd::shared_ptr const & mount_dentry, kstd::shared_ptr const & fs) + : m_dentry(mount_dentry) , m_filesystem(fs) { if (!m_filesystem) @@ -20,9 +21,9 @@ namespace filesystem } } - auto mount::path() const -> std::string_view + auto mount::get_dentry() const -> kstd::shared_ptr { - return m_path; + return m_dentry; } auto mount::get_filesystem() const -> kstd::shared_ptr const & -- cgit v1.2.3 From 70229b88ad195a6e945b4cc75e1248685cda0951 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Tue, 24 Mar 2026 17:05:57 +0100 Subject: Add root_dentry to filesystem --- kernel/src/filesystem/filesystem.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index 0e33d95..8ebe58f 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -1,6 +1,7 @@ #include "kernel/filesystem/filesystem.hpp" #include "kernel/devices/device.hpp" +#include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/inode.hpp" #include @@ -21,4 +22,14 @@ namespace filesystem { return m_root_inode; } + + auto filesystem::root_dentry() const -> kstd::shared_ptr const & + { + return m_root_dentry; + } + + auto filesystem::set_root_dentry(kstd::shared_ptr dentry) -> void + { + m_root_dentry = dentry; + } } // namespace filesystem \ No newline at end of file -- cgit v1.2.3 From a2ac8770937a28d0d4c674e25c9b3c77802a5c9e Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Tue, 24 Mar 2026 17:22:55 +0100 Subject: Refactor mounting of new filesystems and path resolving in vfs --- kernel/src/filesystem/vfs.cpp | 53 ++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 23 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 0e8a76d..c77736a 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -82,9 +82,9 @@ namespace filesystem return nullptr; } - auto vfs::do_mount(std::string_view path, kstd::shared_ptr const & filesystem) -> int + auto vfs::do_mount(std::string_view path, kstd::shared_ptr const & new_filesystem) -> int { - if (!filesystem) + if (!new_filesystem) { return -1; // TODO BA-FS26 panic or errorcode? } @@ -100,24 +100,21 @@ namespace filesystem return -1; // TODO BA-FS26 panic or errorcode? } - // if (path == "/") - // { - // m_root_fs = filesystem; - // m_root_mount = mount{"/", filesystem}; - // return 0; - // } + auto mount_dentry = resolve_path(path); - auto existing_mount = - std::ranges::find_if(m_mount_table, [&](auto const & existing) { return existing.path() == path; }); - if (existing_mount != m_mount_table.end()) + if (!mount_dentry) { - *existing_mount = mount{path, filesystem}; - } - else - { - m_mount_table.push_back(mount{path, filesystem}); + return -1; // mount point path doesn't exist } + // TODO BA-FS26 check if mount point is already mounted and handle it (unmount old fs, fail, etc.) + + mount_dentry->set_flag(dentry::dentry_flags::dcache_mounted); + m_mount_table.add_mount(kstd::make_shared(mount_dentry, new_filesystem)); + + new_filesystem->set_root_dentry( + kstd::make_shared(mount_dentry->get_parent(), new_filesystem->root_inode())); + return 0; } @@ -157,19 +154,29 @@ namespace filesystem { auto path_parts = std::views::split(path, '/') | std::views::filter([](auto const & part) { return !part.empty(); }); - auto parent = m_root_dentry; + auto current_parent = m_root_dentry; + auto current_fs = m_root_fs; for (auto const & part : path_parts) { - if (auto child = parent->find_child(std::string_view{part})) + if (auto child = current_parent->find_child(std::string_view{part})) { - parent = child; + if (child->has_flag(dentry::dentry_flags::dcache_mounted)) // found dentry is a mounted fs + { + auto found_mount = m_mount_table.find_mount_by_dentry(child); + current_fs = found_mount->get_filesystem(); + current_parent = current_fs->root_dentry(); + } + else + { // found dentry is NOT a mounted fs -> continue path resolution in current fs + current_parent = child; + } } - else if (auto found_inode = m_root_fs->lookup(parent->get_inode(), std::string_view{part})) + else if (auto found_inode = m_root_fs->lookup(current_parent->get_inode(), std::string_view{part})) { - auto next_dentry = kstd::make_shared(parent, found_inode, std::string_view{part}); - parent->add_child(next_dentry); - parent = next_dentry; + auto next_dentry = kstd::make_shared(current_parent, found_inode, std::string_view{part}); + current_parent->add_child(next_dentry); + current_parent = next_dentry; } else { -- cgit v1.2.3 From 7351349f296f100f10db62b5a834a971fbe51473 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 24 Mar 2026 18:52:41 +0100 Subject: small refactoring --- kernel/src/filesystem/mount_table.cpp | 6 +++--- kernel/src/filesystem/vfs.cpp | 36 ++++++++++------------------------- 2 files changed, 13 insertions(+), 29 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index 0e9a53d..b4a906b 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -18,11 +18,11 @@ namespace filesystem auto mount_table::find_mount_by_dentry(kstd::shared_ptr const & dentry) -> kstd::shared_ptr { - auto found = + auto it = std::ranges::find_if(m_mounts, [&](auto const & mount) { return mount->get_dentry().get() == dentry.get(); }); - if (found != m_mounts.end()) + if (it != m_mounts.end()) { - return *found; + return *it; } kapi::system::panic("[FILESYSTEM] dentry has mount flag set but no corresponding mount found."); } diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index c77736a..78dec77 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -39,7 +39,6 @@ namespace filesystem auto vfs::init_internal() -> void { auto storage_mgmt = devices::storage::storage_management::get(); - // TODO BA-FS26 fix mounting boot_device if (auto boot_device = storage_mgmt.determine_boot_device()) { m_root_fs = kstd::make_shared(); @@ -82,9 +81,9 @@ namespace filesystem return nullptr; } - auto vfs::do_mount(std::string_view path, kstd::shared_ptr const & new_filesystem) -> int + auto vfs::do_mount(std::string_view path, kstd::shared_ptr const & filesystem) -> int { - if (!new_filesystem) + if (!filesystem) { return -1; // TODO BA-FS26 panic or errorcode? } @@ -100,22 +99,19 @@ namespace filesystem return -1; // TODO BA-FS26 panic or errorcode? } - auto mount_dentry = resolve_path(path); - - if (!mount_dentry) + if (auto mount_dentry = resolve_path(path)) { - return -1; // mount point path doesn't exist - } + // TODO BA-FS26 check if mount point is already mounted and handle it (unmount old fs, fail, etc.) - // TODO BA-FS26 check if mount point is already mounted and handle it (unmount old fs, fail, etc.) + mount_dentry->set_flag(dentry::dentry_flags::dcache_mounted); + m_mount_table.add_mount(kstd::make_shared(mount_dentry, filesystem)); - mount_dentry->set_flag(dentry::dentry_flags::dcache_mounted); - m_mount_table.add_mount(kstd::make_shared(mount_dentry, new_filesystem)); + filesystem->set_root_dentry(kstd::make_shared(mount_dentry->get_parent(), filesystem->root_inode())); - new_filesystem->set_root_dentry( - kstd::make_shared(mount_dentry->get_parent(), new_filesystem->root_inode())); + return 0; + } - return 0; + return -1; } auto vfs::make_device_node(kstd::shared_ptr const & device) -> void @@ -183,18 +179,6 @@ namespace filesystem return nullptr; } } - // | std::views::transform([this](auto const & part) { - // // TODO BA-FS26 implement real path resolution with mounts and directories etc. - // // For now, just return null for any non-device-node path. - // return std::optional>{}; - // }) - // | std::views::filter([](auto const & opt) { return opt.has_value(); }) - // | std::views::transform([](auto const & opt) { return opt.value(); }) - // | std::ranges::find_if(m_mount_table, [&](auto const & mount) { - // // TODO BA-FS26 implement real path resolution with mounts and directories etc. - // // For now, just check if the first path component matches a mount point. - // return part == mount.path(); - // }); } return nullptr; -- cgit v1.2.3 From 2eb086d516f20a0b5cef9881a3459adb389c6ee8 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 24 Mar 2026 19:06:50 +0100 Subject: implement == and <=> operator in shared_ptr --- kernel/src/filesystem/mount_table.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index b4a906b..3176d6d 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -18,8 +18,7 @@ namespace filesystem auto mount_table::find_mount_by_dentry(kstd::shared_ptr const & dentry) -> kstd::shared_ptr { - auto it = - std::ranges::find_if(m_mounts, [&](auto const & mount) { return mount->get_dentry().get() == dentry.get(); }); + auto it = std::ranges::find_if(m_mounts, [&](auto const & mount) { return mount->get_dentry() == dentry; }); if (it != m_mounts.end()) { return *it; -- cgit v1.2.3 From 76de81de1e12694bf6bec1edd3e3409092a92d09 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 24 Mar 2026 20:41:32 +0100 Subject: refactoring, add root_mount into the root_table --- kernel/src/filesystem/mount_table.cpp | 7 +++++ kernel/src/filesystem/vfs.cpp | 53 ++++++++++++++++++++--------------- kernel/src/main.cpp | 1 - 3 files changed, 38 insertions(+), 23 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index 3176d6d..debb9ab 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -16,6 +16,13 @@ namespace filesystem m_mounts.push_back(mount); } + auto mount_table::get_root_mount() const -> kstd::shared_ptr + { + auto it = + std::ranges::find_if(m_mounts, [](auto const & mount) { return mount->get_dentry()->get_parent() == nullptr; }); + return it != m_mounts.end() ? *it : nullptr; + } + auto mount_table::find_mount_by_dentry(kstd::shared_ptr const & dentry) -> kstd::shared_ptr { auto it = std::ranges::find_if(m_mounts, [&](auto const & mount) { return mount->get_dentry() == dentry; }); diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 78dec77..c8e5bc5 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -41,14 +41,13 @@ namespace filesystem auto storage_mgmt = devices::storage::storage_management::get(); if (auto boot_device = storage_mgmt.determine_boot_device()) { - m_root_fs = kstd::make_shared(); - m_root_fs->mount(boot_device); + auto root_fs = kstd::make_shared(); + root_fs->mount(boot_device); - m_root_dentry = kstd::make_shared(nullptr, m_root_fs->root_inode()); - // if (do_mount("/", m_root_fs) != 0) - // { - // kapi::system::panic("[FILESYSTEM] Failed to mount root filesystem."); - // } + auto root_dentry = kstd::make_shared(nullptr, root_fs->root_inode(), "/"); + root_fs->set_root_dentry(root_dentry); + + m_mount_table.add_mount(kstd::make_shared(nullptr, root_fs)); // TODO BA-FS26 use do_mount when tempdevfs is implemented -> just call /dev/ with all devices in devtempfs std::ranges::for_each(storage_mgmt.all_controllers(), [&](auto controller) { @@ -148,37 +147,47 @@ namespace filesystem } else if (!path.empty() && path.front() == '/') { + auto root_mount = m_mount_table.get_root_mount(); + if (!root_mount) + { + kapi::system::panic("[FILESYSTEM] no root mount found."); + } + + auto current_dentry = root_mount->get_dentry(); + auto current_fs = root_mount->get_filesystem(); + auto path_parts = std::views::split(path, '/') | std::views::filter([](auto const & part) { return !part.empty(); }); - auto current_parent = m_root_dentry; - auto current_fs = m_root_fs; - for (auto const & part : path_parts) { - if (auto child = current_parent->find_child(std::string_view{part})) + auto next_dentry = current_dentry->find_child(std::string_view{part}); + + if (!next_dentry) { - if (child->has_flag(dentry::dentry_flags::dcache_mounted)) // found dentry is a mounted fs + if (auto found_inode = current_fs->lookup(current_dentry->get_inode(), std::string_view{part})) { - auto found_mount = m_mount_table.find_mount_by_dentry(child); - current_fs = found_mount->get_filesystem(); - current_parent = current_fs->root_dentry(); + next_dentry = kstd::make_shared(current_dentry, found_inode, std::string_view{part}); + current_dentry->add_child(next_dentry); } else - { // found dentry is NOT a mounted fs -> continue path resolution in current fs - current_parent = child; + { + return nullptr; } } - else if (auto found_inode = m_root_fs->lookup(current_parent->get_inode(), std::string_view{part})) + + if (next_dentry->has_flag(dentry::dentry_flags::dcache_mounted)) { - auto next_dentry = kstd::make_shared(current_parent, found_inode, std::string_view{part}); - current_parent->add_child(next_dentry); - current_parent = next_dentry; + auto found_mount = m_mount_table.find_mount_by_dentry(next_dentry); + current_fs = found_mount->get_filesystem(); + current_dentry = current_fs->root_dentry(); } else { - return nullptr; + current_dentry = next_dentry; } } + + return current_dentry; } return nullptr; diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index a575be2..9571a0d 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 84d4476650b31dbfc52becf2ff65ddce9d31c9ec Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 24 Mar 2026 23:54:28 +0100 Subject: implement a rootfs to handle / mounts correctly --- kernel/src/filesystem/filesystem.cpp | 11 ------ kernel/src/filesystem/mount.cpp | 15 ++++++-- kernel/src/filesystem/mount_table.cpp | 14 ++----- kernel/src/filesystem/rootfs/rootfs_filesystem.cpp | 24 ++++++++++++ kernel/src/filesystem/rootfs/rootfs_inode.cpp | 22 +++++++++++ kernel/src/filesystem/vfs.cpp | 43 +++++++++++++++------- kernel/src/main.cpp | 10 +++++ 7 files changed, 100 insertions(+), 39 deletions(-) create mode 100644 kernel/src/filesystem/rootfs/rootfs_filesystem.cpp create mode 100644 kernel/src/filesystem/rootfs/rootfs_inode.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index 8ebe58f..0e33d95 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -1,7 +1,6 @@ #include "kernel/filesystem/filesystem.hpp" #include "kernel/devices/device.hpp" -#include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/inode.hpp" #include @@ -22,14 +21,4 @@ namespace filesystem { return m_root_inode; } - - auto filesystem::root_dentry() const -> kstd::shared_ptr const & - { - return m_root_dentry; - } - - auto filesystem::set_root_dentry(kstd::shared_ptr dentry) -> void - { - m_root_dentry = dentry; - } } // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index b65f331..d9937dc 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -11,8 +11,10 @@ namespace filesystem { - mount::mount(kstd::shared_ptr const & mount_dentry, kstd::shared_ptr const & fs) - : m_dentry(mount_dentry) + mount::mount(kstd::shared_ptr const & mount_dentry, kstd::shared_ptr const & root_dentry, + kstd::shared_ptr const & fs) + : m_mount_dentry(mount_dentry) + , m_root_dentry(root_dentry) , m_filesystem(fs) { if (!m_filesystem) @@ -21,13 +23,18 @@ namespace filesystem } } - auto mount::get_dentry() const -> kstd::shared_ptr + auto mount::get_mount_dentry() const -> kstd::shared_ptr { - return m_dentry; + return m_mount_dentry; } auto mount::get_filesystem() const -> kstd::shared_ptr const & { return m_filesystem; } + + auto mount::root_dentry() const -> kstd::shared_ptr const & + { + return m_root_dentry; + } } // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index debb9ab..681c2b9 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -1,7 +1,5 @@ #include "kernel/filesystem/mount_table.hpp" -#include "kapi/system.hpp" - #include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/mount.hpp" @@ -18,18 +16,14 @@ namespace filesystem auto mount_table::get_root_mount() const -> kstd::shared_ptr { - auto it = - std::ranges::find_if(m_mounts, [](auto const & mount) { return mount->get_dentry()->get_parent() == nullptr; }); + auto it = std::ranges::find_if(m_mounts, [](auto const & mount) { return mount->get_mount_dentry() == nullptr; }); return it != m_mounts.end() ? *it : nullptr; } auto mount_table::find_mount_by_dentry(kstd::shared_ptr const & dentry) -> kstd::shared_ptr { - auto it = std::ranges::find_if(m_mounts, [&](auto const & mount) { return mount->get_dentry() == dentry; }); - if (it != m_mounts.end()) - { - return *it; - } - kapi::system::panic("[FILESYSTEM] dentry has mount flag set but no corresponding mount found."); + auto it = std::ranges::find_if(m_mounts, [&](auto const & mnt) { return mnt->get_mount_dentry() == dentry; }); + + return it != m_mounts.end() ? *it : nullptr; } } // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp b/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp new file mode 100644 index 0000000..22b1962 --- /dev/null +++ b/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp @@ -0,0 +1,24 @@ +#include "kernel/filesystem/rootfs/rootfs_filesystem.hpp" + +#include "kernel/devices/device.hpp" +#include "kernel/filesystem/inode.hpp" +#include "kernel/filesystem/rootfs/rootfs_inode.hpp" + +#include + +#include + +namespace filesystem::rootfs +{ + auto rootfs_filesystem::mount(kstd::shared_ptr const & /*device*/) -> int + { + m_root_inode = kstd::make_shared(); + return 0; + } + + auto rootfs_filesystem::lookup(kstd::shared_ptr const & /*parent*/, std::string_view /*name*/) + -> kstd::shared_ptr + { + return nullptr; + } +} // namespace filesystem::rootfs diff --git a/kernel/src/filesystem/rootfs/rootfs_inode.cpp b/kernel/src/filesystem/rootfs/rootfs_inode.cpp new file mode 100644 index 0000000..ed057f7 --- /dev/null +++ b/kernel/src/filesystem/rootfs/rootfs_inode.cpp @@ -0,0 +1,22 @@ +#include "kernel/filesystem/rootfs/rootfs_inode.hpp" + +#include "kernel/filesystem/inode.hpp" + +#include + +namespace filesystem::rootfs +{ + rootfs_inode::rootfs_inode() + : inode(inode_kind::directory) + {} + + auto rootfs_inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t + { + return 0; + } + + auto rootfs_inode::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t + { + return 0; + } +} // namespace filesystem::rootfs diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index c8e5bc5..1c4dd8b 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -10,6 +10,7 @@ #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/mount.hpp" #include "kernel/filesystem/open_file_description.hpp" +#include "kernel/filesystem/rootfs/rootfs_filesystem.hpp" #include @@ -38,16 +39,20 @@ namespace filesystem auto vfs::init_internal() -> void { + auto virtual_fs = kstd::make_shared(); + virtual_fs->mount(nullptr); + + auto virtual_root_dentry = kstd::make_shared(nullptr, virtual_fs->root_inode(), "/"); + m_mount_table.add_mount(kstd::make_shared(nullptr, virtual_root_dentry, virtual_fs)); + auto storage_mgmt = devices::storage::storage_management::get(); if (auto boot_device = storage_mgmt.determine_boot_device()) { - auto root_fs = kstd::make_shared(); - root_fs->mount(boot_device); + // TODO BA-FS26 detect fs type from boot device and load corresponding fs, for now just assume ext2 + auto boot_root_fs = kstd::make_shared(); + boot_root_fs->mount(boot_device); - auto root_dentry = kstd::make_shared(nullptr, root_fs->root_inode(), "/"); - root_fs->set_root_dentry(root_dentry); - - m_mount_table.add_mount(kstd::make_shared(nullptr, root_fs)); + do_mount("/", boot_root_fs); // TODO BA-FS26 use do_mount when tempdevfs is implemented -> just call /dev/ with all devices in devtempfs std::ranges::for_each(storage_mgmt.all_controllers(), [&](auto controller) { @@ -102,10 +107,10 @@ namespace filesystem { // TODO BA-FS26 check if mount point is already mounted and handle it (unmount old fs, fail, etc.) + auto new_fs_root = kstd::make_shared(mount_dentry, filesystem->root_inode()); + auto new_mount = kstd::make_shared(mount_dentry, new_fs_root, filesystem); + m_mount_table.add_mount(new_mount); mount_dentry->set_flag(dentry::dentry_flags::dcache_mounted); - m_mount_table.add_mount(kstd::make_shared(mount_dentry, filesystem)); - - filesystem->set_root_dentry(kstd::make_shared(mount_dentry->get_parent(), filesystem->root_inode())); return 0; } @@ -153,20 +158,30 @@ namespace filesystem kapi::system::panic("[FILESYSTEM] no root mount found."); } - auto current_dentry = root_mount->get_dentry(); + auto current_dentry = root_mount->root_dentry(); auto current_fs = root_mount->get_filesystem(); + while (current_dentry->has_flag(dentry::dentry_flags::dcache_mounted)) + { + auto mnt = m_mount_table.find_mount_by_dentry(current_dentry); + if (!mnt) + kapi::system::panic("[FILESYSTEM] dcache_mounted set but no covering mount found."); + current_dentry = mnt->root_dentry(); + current_fs = mnt->get_filesystem(); + } + auto path_parts = std::views::split(path, '/') | std::views::filter([](auto const & part) { return !part.empty(); }); for (auto const & part : path_parts) { - auto next_dentry = current_dentry->find_child(std::string_view{part}); + std::string_view part_view{part}; + auto next_dentry = current_dentry->find_child(part_view); if (!next_dentry) { - if (auto found_inode = current_fs->lookup(current_dentry->get_inode(), std::string_view{part})) + if (auto found_inode = current_fs->lookup(current_dentry->get_inode(), part_view)) { - next_dentry = kstd::make_shared(current_dentry, found_inode, std::string_view{part}); + next_dentry = kstd::make_shared(current_dentry, found_inode, part_view); current_dentry->add_child(next_dentry); } else @@ -179,7 +194,7 @@ namespace filesystem { auto found_mount = m_mount_table.find_mount_by_dentry(next_dentry); current_fs = found_mount->get_filesystem(); - current_dentry = current_fs->root_dentry(); + current_dentry = found_mount->root_dentry(); } else { diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 9571a0d..19a0992 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -5,6 +5,7 @@ #include "kernel/devices/storage/storage_management.hpp" #include "kernel/filesystem/device_inode.hpp" +#include "kernel/filesystem/ext2/ext2_filesystem.hpp" #include "kernel/filesystem/file_descriptor_table.hpp" #include "kernel/filesystem/open_file_description.hpp" #include "kernel/filesystem/vfs.hpp" @@ -108,8 +109,17 @@ auto test_file_lookup() -> void // TODO BA-FS26 implement a more complete test with multiple files and directories and mounts etc. auto vfs = filesystem::vfs::get(); + auto storage_mgmt = devices::storage::storage_management::get(); + vfs.open("/a/b/c"); vfs.open("/a/d/e"); + + auto new_filesystem = kstd::make_shared(); + auto device = storage_mgmt.device_by_major_minor(1, 16); + new_filesystem->mount(device); + vfs.do_mount("/a/b", new_filesystem); + vfs.open("/a/b/c"); + vfs.open("x/y/z"); } -- cgit v1.2.3 From 74351bbcd440189bafa79c806dd3ae8255f42c11 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 25 Mar 2026 07:47:24 +0100 Subject: currently do not support stacked mounts --- kernel/src/filesystem/vfs.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 1c4dd8b..483bae5 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -161,7 +161,8 @@ namespace filesystem auto current_dentry = root_mount->root_dentry(); auto current_fs = root_mount->get_filesystem(); - while (current_dentry->has_flag(dentry::dentry_flags::dcache_mounted)) + // TODO BA-FS26 use while to allow stacked mounts? + if (current_dentry->has_flag(dentry::dentry_flags::dcache_mounted)) { auto mnt = m_mount_table.find_mount_by_dentry(current_dentry); if (!mnt) @@ -190,6 +191,7 @@ namespace filesystem } } + // TODO BA-FS26 use while to allow stacked mounts? if (next_dentry->has_flag(dentry::dentry_flags::dcache_mounted)) { auto found_mount = m_mount_table.find_mount_by_dentry(next_dentry); -- cgit v1.2.3 From 31ac3e6ffff00b7ac3b3dbb3db38c44409251b34 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 26 Mar 2026 20:09:37 +0100 Subject: first draft of an devfs implementation --- kernel/src/filesystem/devfs/devfs_filesystem.cpp | 57 ++++++++++++++++++++++++ kernel/src/filesystem/devfs/devfs_root_inode.cpp | 22 +++++++++ kernel/src/filesystem/device_inode.cpp | 5 +++ kernel/src/filesystem/vfs.cpp | 50 ++++++--------------- 4 files changed, 98 insertions(+), 36 deletions(-) create mode 100644 kernel/src/filesystem/devfs/devfs_filesystem.cpp create mode 100644 kernel/src/filesystem/devfs/devfs_root_inode.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/devfs/devfs_filesystem.cpp b/kernel/src/filesystem/devfs/devfs_filesystem.cpp new file mode 100644 index 0000000..cfd2d88 --- /dev/null +++ b/kernel/src/filesystem/devfs/devfs_filesystem.cpp @@ -0,0 +1,57 @@ +#include "kernel/filesystem/devfs/devfs_filesystem.hpp" + +#include "kernel/devices/device.hpp" +#include "kernel/devices/storage/storage_management.hpp" +#include "kernel/filesystem/devfs/devfs_root_inode.hpp" +#include "kernel/filesystem/device_inode.hpp" +#include "kernel/filesystem/inode.hpp" + +#include + +#include +#include + +namespace filesystem::devfs +{ + auto devfs_filesystem::mount(kstd::shared_ptr const & /*device*/) -> int + { + m_root_inode = kstd::make_shared(); + build_device_inode_table(); + return 0; + } + + auto devfs_filesystem::lookup(kstd::shared_ptr const & parent, std::string_view name) + -> kstd::shared_ptr + { + if (!parent || !parent->is_directory()) + { + return nullptr; + } + + if (parent.get() != m_root_inode.get()) + { + return nullptr; + } + + auto it = std::ranges::find_if(m_inodes, [&](auto const & dev_node) { + auto device_inode_ptr = static_cast(dev_node.get()); + if (!device_inode_ptr) + { + return false; + } + return device_inode_ptr->device()->name() == name; + }); + return (it != m_inodes.end()) ? *it : nullptr; + } + + auto devfs_filesystem::build_device_inode_table() -> void + { + m_inodes.clear(); + + auto storage_mgmt = devices::storage::storage_management::get(); + std::ranges::for_each(storage_mgmt.all_controllers(), [&](auto const & controller) { + std::ranges::for_each(controller->all_devices(), + [&](auto const & device) { m_inodes.push_back(kstd::make_shared(device)); }); + }); + } +} // namespace filesystem::devfs \ No newline at end of file diff --git a/kernel/src/filesystem/devfs/devfs_root_inode.cpp b/kernel/src/filesystem/devfs/devfs_root_inode.cpp new file mode 100644 index 0000000..53441b0 --- /dev/null +++ b/kernel/src/filesystem/devfs/devfs_root_inode.cpp @@ -0,0 +1,22 @@ +#include "kernel/filesystem/devfs/devfs_root_inode.hpp" + +#include "kernel/filesystem/inode.hpp" + +#include + +namespace filesystem::devfs +{ + devfs_root_inode::devfs_root_inode() + : inode(inode_kind::directory) + {} + + auto devfs_root_inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t + { + return 0; + } + + auto devfs_root_inode::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t + { + return 0; + } +} // namespace filesystem::devfs \ No newline at end of file diff --git a/kernel/src/filesystem/device_inode.cpp b/kernel/src/filesystem/device_inode.cpp index 812b43a..64cd6e9 100644 --- a/kernel/src/filesystem/device_inode.cpp +++ b/kernel/src/filesystem/device_inode.cpp @@ -76,6 +76,11 @@ namespace filesystem } } + auto device_inode::device() const -> kstd::shared_ptr const & + { + return m_device; + } + auto device_inode::process_blocks(size_t offset, size_t size, void * buffer, block_op op) const -> size_t { if (buffer == nullptr) diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 483bae5..368d994 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -2,10 +2,9 @@ #include "kapi/system.hpp" -#include "kernel/devices/device.hpp" #include "kernel/devices/storage/storage_management.hpp" #include "kernel/filesystem/dentry.hpp" -#include "kernel/filesystem/device_inode.hpp" +#include "kernel/filesystem/devfs/devfs_filesystem.hpp" #include "kernel/filesystem/ext2/ext2_filesystem.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/mount.hpp" @@ -14,7 +13,6 @@ #include -#include #include #include #include @@ -52,12 +50,18 @@ namespace filesystem auto boot_root_fs = kstd::make_shared(); boot_root_fs->mount(boot_device); - do_mount("/", boot_root_fs); + if (do_mount("/", boot_root_fs) != 0) + { + kapi::system::panic("[FILESYSTEM] failed to mount root filesystem."); + } + + auto device_fs = kstd::make_shared(); + device_fs->mount(nullptr); - // TODO BA-FS26 use do_mount when tempdevfs is implemented -> just call /dev/ with all devices in devtempfs - std::ranges::for_each(storage_mgmt.all_controllers(), [&](auto controller) { - std::ranges::for_each(controller->all_devices(), [&](auto device) { make_device_node(device); }); - }); + if (do_mount("/dev", device_fs) != 0) + { + kapi::system::panic("[FILESYSTEM] failed to mount devfs at /dev."); + } } else { @@ -118,39 +122,13 @@ namespace filesystem return -1; } - auto vfs::make_device_node(kstd::shared_ptr const & device) -> void - { - if (!device) - { - kapi::system::panic("[FILESYSTEM] make_device_node called with null device."); - } - - m_device_nodes.push_back(device_node_entry{device->name().view(), kstd::make_shared(device)}); - } - auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr { - // TODO BA-FS26 implement real path resolution with mounts and directories etc. - // For now, just support device nodes at /dev/. + // TODO BA-FS26 implement full path resolution semantics. // TODO BA-FS26 better path validation // TODO BA-FS26 implement a path parser (maybe in libs?) and use it here and in do_mount - constexpr auto device_prefix = std::string_view{"/dev/"}; - if (path.starts_with(device_prefix)) - { - auto const device_name = path.substr(device_prefix.size()); - auto entry = std::ranges::find_if(m_device_nodes, [&](auto const & device_entry) { - return device_entry.has_value() && device_entry->name == device_name; - }); - - if (entry != m_device_nodes.end()) - { - return kstd::make_shared(nullptr, entry->value().node); - } - - return nullptr; - } - else if (!path.empty() && path.front() == '/') + if (!path.empty() && path.front() == '/') { auto root_mount = m_mount_table.get_root_mount(); if (!root_mount) -- cgit v1.2.3 From e97b668f82ad1a51e1e9352073a3ae51cedfdd34 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 26 Mar 2026 20:27:23 +0100 Subject: mount /dev in the rootfs --- kernel/src/filesystem/rootfs/rootfs_filesystem.cpp | 9 +++++++-- kernel/src/filesystem/rootfs/rootfs_inode.cpp | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp b/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp index 22b1962..e819fc7 100644 --- a/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp +++ b/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp @@ -12,13 +12,18 @@ namespace filesystem::rootfs { auto rootfs_filesystem::mount(kstd::shared_ptr const & /*device*/) -> int { - m_root_inode = kstd::make_shared(); + auto rfs_inode = kstd::make_shared(); + rfs_inode->add_child("dev"); + m_root_inode = rfs_inode; + return 0; } - auto rootfs_filesystem::lookup(kstd::shared_ptr const & /*parent*/, std::string_view /*name*/) + auto rootfs_filesystem::lookup(kstd::shared_ptr const & parent, std::string_view name) -> kstd::shared_ptr { + if (auto * rfs_inode = static_cast(parent.get())) + return rfs_inode->lookup_child(name); return nullptr; } } // namespace filesystem::rootfs diff --git a/kernel/src/filesystem/rootfs/rootfs_inode.cpp b/kernel/src/filesystem/rootfs/rootfs_inode.cpp index ed057f7..9bbfbce 100644 --- a/kernel/src/filesystem/rootfs/rootfs_inode.cpp +++ b/kernel/src/filesystem/rootfs/rootfs_inode.cpp @@ -2,7 +2,13 @@ #include "kernel/filesystem/inode.hpp" +#include +#include + +#include #include +#include +#include namespace filesystem::rootfs { @@ -19,4 +25,15 @@ namespace filesystem::rootfs { return 0; } + + auto rootfs_inode::add_child(std::string_view name) -> void + { + m_children.push_back(std::make_pair(kstd::string{name}, kstd::make_shared())); + } + + auto rootfs_inode::lookup_child(std::string_view name) -> kstd::shared_ptr + { + auto it = std::ranges::find_if(m_children, [&](auto const & pair) { return pair.first == name; }); + return (it != m_children.end()) ? it->second : nullptr; + } } // namespace filesystem::rootfs -- cgit v1.2.3 From 372148a1379d7f14cbe641272f8f28766925f3aa Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 26 Mar 2026 21:13:59 +0100 Subject: mock filesystem correctly for tests with /dev --- kernel/src/filesystem/ext2/ext2_filesystem.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/ext2_filesystem.cpp b/kernel/src/filesystem/ext2/ext2_filesystem.cpp index 3f5774c..373c6a2 100644 --- a/kernel/src/filesystem/ext2/ext2_filesystem.cpp +++ b/kernel/src/filesystem/ext2/ext2_filesystem.cpp @@ -22,11 +22,16 @@ namespace filesystem::ext2 return 0; } - auto ext2_filesystem::lookup(kstd::shared_ptr const & /*parent*/, std::string_view /*name*/) + auto ext2_filesystem::lookup(kstd::shared_ptr const & /*parent*/, std::string_view name) -> kstd::shared_ptr { // TODO BA-FS26 implement ext2 directory traversal and inode loading - // return nullptr; + if (name == "dev") + { + // TODO BA-FS26 just for testing + return nullptr; + } + return kstd::make_shared(); } } // namespace filesystem::ext2 -- cgit v1.2.3 From c3e80174faa2db9e6674af995aaa95b59ec53fec Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 26 Mar 2026 21:15:40 +0100 Subject: fix resolve_path -> first traverse rootfs before jumping into the mounted root filesystem --- kernel/src/filesystem/vfs.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 368d994..40c97f8 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -139,16 +139,6 @@ namespace filesystem auto current_dentry = root_mount->root_dentry(); auto current_fs = root_mount->get_filesystem(); - // TODO BA-FS26 use while to allow stacked mounts? - if (current_dentry->has_flag(dentry::dentry_flags::dcache_mounted)) - { - auto mnt = m_mount_table.find_mount_by_dentry(current_dentry); - if (!mnt) - kapi::system::panic("[FILESYSTEM] dcache_mounted set but no covering mount found."); - current_dentry = mnt->root_dentry(); - current_fs = mnt->get_filesystem(); - } - auto path_parts = std::views::split(path, '/') | std::views::filter([](auto const & part) { return !part.empty(); }); for (auto const & part : path_parts) @@ -173,6 +163,8 @@ namespace filesystem if (next_dentry->has_flag(dentry::dentry_flags::dcache_mounted)) { auto found_mount = m_mount_table.find_mount_by_dentry(next_dentry); + if (!found_mount) + kapi::system::panic("[FILESYSTEM] dcache_mounted set but no covering mount found."); current_fs = found_mount->get_filesystem(); current_dentry = found_mount->root_dentry(); } -- cgit v1.2.3 From cb60cdebdc36dd2358fe1ce06eec197e213af491 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 24 Mar 2026 17:35:54 +0100 Subject: kapi/cpu: introduce CPU API --- kernel/src/cpu.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ kernel/src/main.cpp | 5 +++++ 2 files changed, 51 insertions(+) create mode 100644 kernel/src/cpu.cpp (limited to 'kernel/src') diff --git a/kernel/src/cpu.cpp b/kernel/src/cpu.cpp new file mode 100644 index 0000000..fc460c9 --- /dev/null +++ b/kernel/src/cpu.cpp @@ -0,0 +1,46 @@ +#include "kernel/cpu.hpp" + +#include "kapi/cpu.hpp" +#include "kapi/system.hpp" + +#include + +namespace kernel::cpu +{ + + namespace + { + struct exception_handler : kapi::cpu::exception_handler + { + auto handle(kapi::cpu::exception const & context) -> bool override + { + switch (context.type) + { + case kapi::cpu::exception::type::page_fault: + return handle_page_fault(context); + default: + return false; + } + } + + private: + auto handle_page_fault(kapi::cpu::exception const & context) -> bool + { + kstd::println(kstd::print_sink::stderr, "[OS:CPU] PAGE FAULT!"); + kstd::println(kstd::print_sink::stderr, "\tFault address: {:#018x}", context.access_address); + kstd::println(kstd::print_sink::stderr, "\tPresent: {}", context.is_present); + kstd::println(kstd::print_sink::stderr, "\tWrite: {}", context.is_write_access); + kstd::println(kstd::print_sink::stderr, "\tUser: {}", context.is_user_mode); + kstd::println(kstd::print_sink::stderr, "\tRIP: {:#018x}", context.instruction_pointer); + + kapi::system::panic("Halting the system due to an unrecoverable page fault."); + } + } static constinit handler; + } // namespace + + auto init() -> void + { + kapi::cpu::set_exception_handler(handler); + } + +} // namespace kernel::cpu \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index eb59402..0416ee9 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,8 +1,10 @@ #include "kapi/boot_modules.hpp" #include "kapi/cio.hpp" +#include "kapi/cpu.hpp" #include "kapi/memory.hpp" #include "kapi/system.hpp" +#include "kernel/cpu.hpp" #include "kernel/devices/storage/storage_management.hpp" #include "kernel/filesystem/device_file.hpp" #include "kernel/filesystem/file_descriptor_table.hpp" @@ -90,6 +92,9 @@ auto main() -> int kapi::cio::init(); kstd::println("[OS] IO subsystem initialized."); + kapi::cpu::init(); + kernel::cpu::init(); + kapi::memory::init(); kernel::memory::init_heap(kapi::memory::heap_base); kstd::println("[OS] Memory subsystem initialized."); -- cgit v1.2.3 From 42895684b631380c8aca94f82209297ac0c0e5f2 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 24 Mar 2026 17:44:21 +0100 Subject: kapi: extract interrupt enablement --- kernel/src/main.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 0416ee9..6bd168c 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -94,6 +94,7 @@ auto main() -> int kapi::cpu::init(); kernel::cpu::init(); + kapi::cpu::enable_interrupts(); kapi::memory::init(); kernel::memory::init_heap(kapi::memory::heap_base); -- cgit v1.2.3 From fd1c5a50bb35f772b8e37125188640447d4b3b2a Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 25 Mar 2026 13:24:03 +0100 Subject: kapi/cpu: enable formatting of exception types --- kernel/src/cpu.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/cpu.cpp b/kernel/src/cpu.cpp index fc460c9..11b6551 100644 --- a/kernel/src/cpu.cpp +++ b/kernel/src/cpu.cpp @@ -14,6 +14,7 @@ namespace kernel::cpu { auto handle(kapi::cpu::exception const & context) -> bool override { + kstd::println(kstd::print_sink::stderr, "[OS:CPU] {} @ {:#018x}", context.type, context.instruction_pointer); switch (context.type) { case kapi::cpu::exception::type::page_fault: @@ -26,12 +27,10 @@ namespace kernel::cpu private: auto handle_page_fault(kapi::cpu::exception const & context) -> bool { - kstd::println(kstd::print_sink::stderr, "[OS:CPU] PAGE FAULT!"); kstd::println(kstd::print_sink::stderr, "\tFault address: {:#018x}", context.access_address); kstd::println(kstd::print_sink::stderr, "\tPresent: {}", context.is_present); kstd::println(kstd::print_sink::stderr, "\tWrite: {}", context.is_write_access); kstd::println(kstd::print_sink::stderr, "\tUser: {}", context.is_user_mode); - kstd::println(kstd::print_sink::stderr, "\tRIP: {:#018x}", context.instruction_pointer); kapi::system::panic("Halting the system due to an unrecoverable page fault."); } -- cgit v1.2.3 From 8d06763f47e7b7c93af2a55f6bd2dbc4aa9abfa2 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 26 Mar 2026 16:10:50 +0100 Subject: kapi/cpu: simplify exception handling --- kernel/src/cpu.cpp | 45 --------------------------------------------- kernel/src/main.cpp | 2 -- 2 files changed, 47 deletions(-) delete mode 100644 kernel/src/cpu.cpp (limited to 'kernel/src') diff --git a/kernel/src/cpu.cpp b/kernel/src/cpu.cpp deleted file mode 100644 index 11b6551..0000000 --- a/kernel/src/cpu.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "kernel/cpu.hpp" - -#include "kapi/cpu.hpp" -#include "kapi/system.hpp" - -#include - -namespace kernel::cpu -{ - - namespace - { - struct exception_handler : kapi::cpu::exception_handler - { - auto handle(kapi::cpu::exception const & context) -> bool override - { - kstd::println(kstd::print_sink::stderr, "[OS:CPU] {} @ {:#018x}", context.type, context.instruction_pointer); - switch (context.type) - { - case kapi::cpu::exception::type::page_fault: - return handle_page_fault(context); - default: - return false; - } - } - - private: - auto handle_page_fault(kapi::cpu::exception const & context) -> bool - { - kstd::println(kstd::print_sink::stderr, "\tFault address: {:#018x}", context.access_address); - kstd::println(kstd::print_sink::stderr, "\tPresent: {}", context.is_present); - kstd::println(kstd::print_sink::stderr, "\tWrite: {}", context.is_write_access); - kstd::println(kstd::print_sink::stderr, "\tUser: {}", context.is_user_mode); - - kapi::system::panic("Halting the system due to an unrecoverable page fault."); - } - } static constinit handler; - } // namespace - - auto init() -> void - { - kapi::cpu::set_exception_handler(handler); - } - -} // namespace kernel::cpu \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 6bd168c..45a4aae 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -4,7 +4,6 @@ #include "kapi/memory.hpp" #include "kapi/system.hpp" -#include "kernel/cpu.hpp" #include "kernel/devices/storage/storage_management.hpp" #include "kernel/filesystem/device_file.hpp" #include "kernel/filesystem/file_descriptor_table.hpp" @@ -93,7 +92,6 @@ auto main() -> int kstd::println("[OS] IO subsystem initialized."); kapi::cpu::init(); - kernel::cpu::init(); kapi::cpu::enable_interrupts(); kapi::memory::init(); -- cgit v1.2.3 From 00a77644192642e06462c11479a5c0e9bd859e9a Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 26 Mar 2026 16:35:32 +0100 Subject: kapi: extract interrupts API --- kernel/src/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 45a4aae..6434045 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,6 +1,7 @@ #include "kapi/boot_modules.hpp" #include "kapi/cio.hpp" #include "kapi/cpu.hpp" +#include "kapi/interrupts.hpp" #include "kapi/memory.hpp" #include "kapi/system.hpp" @@ -92,7 +93,7 @@ auto main() -> int kstd::println("[OS] IO subsystem initialized."); kapi::cpu::init(); - kapi::cpu::enable_interrupts(); + kapi::interrupts::enable(); kapi::memory::init(); kernel::memory::init_heap(kapi::memory::heap_base); -- cgit v1.2.3 From a6f93bf8df0dbfa7d19aa1168bfc8b052e41c42f Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 28 Mar 2026 17:28:32 +0100 Subject: fix vfs mount with /dev & /a and rootfs & devfs --- kernel/src/filesystem/devfs/devfs_filesystem.cpp | 3 +- kernel/src/filesystem/mount.cpp | 11 +- kernel/src/filesystem/mount_table.cpp | 29 +++-- kernel/src/filesystem/rootfs/rootfs_filesystem.cpp | 2 +- kernel/src/filesystem/vfs.cpp | 122 +++++++++------------ 5 files changed, 82 insertions(+), 85 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/devfs/devfs_filesystem.cpp b/kernel/src/filesystem/devfs/devfs_filesystem.cpp index cfd2d88..c4cd81a 100644 --- a/kernel/src/filesystem/devfs/devfs_filesystem.cpp +++ b/kernel/src/filesystem/devfs/devfs_filesystem.cpp @@ -13,10 +13,11 @@ namespace filesystem::devfs { - auto devfs_filesystem::mount(kstd::shared_ptr const & /*device*/) -> int + auto devfs_filesystem::mount(kstd::shared_ptr const &) -> int { m_root_inode = kstd::make_shared(); build_device_inode_table(); + return 0; } diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index d9937dc..afc07fa 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -6,14 +6,16 @@ #include "kernel/filesystem/filesystem.hpp" #include +#include #include namespace filesystem { mount::mount(kstd::shared_ptr const & mount_dentry, kstd::shared_ptr const & root_dentry, - kstd::shared_ptr const & fs) - : m_mount_dentry(mount_dentry) + kstd::shared_ptr const & fs, std::string_view mount_path) + : m_mount_path(mount_path) + , m_mount_dentry(mount_dentry) , m_root_dentry(root_dentry) , m_filesystem(fs) { @@ -37,4 +39,9 @@ namespace filesystem { return m_root_dentry; } + + auto mount::get_mount_path() const -> std::string_view + { + return m_mount_path.view(); + } } // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index 681c2b9..b9e57d4 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -1,11 +1,11 @@ #include "kernel/filesystem/mount_table.hpp" -#include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/mount.hpp" #include -#include +#include +#include namespace filesystem { @@ -14,16 +14,25 @@ namespace filesystem m_mounts.push_back(mount); } - auto mount_table::get_root_mount() const -> kstd::shared_ptr + auto mount_table::find_longest_prefix_mount(std::string_view path) const -> kstd::shared_ptr { - auto it = std::ranges::find_if(m_mounts, [](auto const & mount) { return mount->get_mount_dentry() == nullptr; }); - return it != m_mounts.end() ? *it : nullptr; - } + kstd::shared_ptr mount_with_longest_prefix = nullptr; + std::size_t best_len = 0; - auto mount_table::find_mount_by_dentry(kstd::shared_ptr const & dentry) -> kstd::shared_ptr - { - auto it = std::ranges::find_if(m_mounts, [&](auto const & mnt) { return mnt->get_mount_dentry() == dentry; }); + for (auto const & mount : m_mounts) + { + auto mp = mount->get_mount_path(); + + // /a/b/c should match /a/b but not /a/bb or /a/b/c/d, / should match everything + bool is_prefix = path.starts_with(mp) && (mp == "/" || path.size() == mp.size() || path[mp.size()] == '/'); + + if (is_prefix && mp.size() >= best_len) + { + mount_with_longest_prefix = mount; + best_len = mp.size(); + } + } - return it != m_mounts.end() ? *it : nullptr; + return mount_with_longest_prefix; } } // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp b/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp index e819fc7..22502aa 100644 --- a/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp +++ b/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp @@ -10,7 +10,7 @@ namespace filesystem::rootfs { - auto rootfs_filesystem::mount(kstd::shared_ptr const & /*device*/) -> int + auto rootfs_filesystem::mount(kstd::shared_ptr const &) -> int { auto rfs_inode = kstd::make_shared(); rfs_inode->add_child("dev"); diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 40c97f8..da7fa05 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -37,11 +37,11 @@ namespace filesystem auto vfs::init_internal() -> void { - auto virtual_fs = kstd::make_shared(); - virtual_fs->mount(nullptr); + auto root_fs = kstd::make_shared(); + root_fs->mount(nullptr); - auto virtual_root_dentry = kstd::make_shared(nullptr, virtual_fs->root_inode(), "/"); - m_mount_table.add_mount(kstd::make_shared(nullptr, virtual_root_dentry, virtual_fs)); + auto root_fs_root_dentry = kstd::make_shared(nullptr, root_fs->root_inode()); + m_mount_table.add_mount(kstd::make_shared(nullptr, root_fs_root_dentry, root_fs, "")); auto storage_mgmt = devices::storage::storage_management::get(); if (auto boot_device = storage_mgmt.determine_boot_device()) @@ -49,24 +49,12 @@ namespace filesystem // TODO BA-FS26 detect fs type from boot device and load corresponding fs, for now just assume ext2 auto boot_root_fs = kstd::make_shared(); boot_root_fs->mount(boot_device); - - if (do_mount("/", boot_root_fs) != 0) - { - kapi::system::panic("[FILESYSTEM] failed to mount root filesystem."); - } - - auto device_fs = kstd::make_shared(); - device_fs->mount(nullptr); - - if (do_mount("/dev", device_fs) != 0) - { - kapi::system::panic("[FILESYSTEM] failed to mount devfs at /dev."); - } - } - else - { - // TODO BA-FS26 ?? what when no boot_device == no modules loaded?? + do_mount_internal("/", root_fs_root_dentry, boot_root_fs); } + + auto device_fs = kstd::make_shared(); + device_fs->mount(nullptr); + do_mount_internal("/dev", root_fs_root_dentry, device_fs); } auto vfs::get() -> vfs & @@ -107,77 +95,69 @@ namespace filesystem return -1; // TODO BA-FS26 panic or errorcode? } - if (auto mount_dentry = resolve_path(path)) + if (auto mount_point_dentry = resolve_path(path)) { - // TODO BA-FS26 check if mount point is already mounted and handle it (unmount old fs, fail, etc.) - - auto new_fs_root = kstd::make_shared(mount_dentry, filesystem->root_inode()); - auto new_mount = kstd::make_shared(mount_dentry, new_fs_root, filesystem); - m_mount_table.add_mount(new_mount); - mount_dentry->set_flag(dentry::dentry_flags::dcache_mounted); - + do_mount_internal(path, mount_point_dentry, filesystem); return 0; } return -1; } + auto vfs::do_mount_internal(std::string_view path, kstd::shared_ptr const & mount_point_dentry, + kstd::shared_ptr const & fs) -> void + { + // TODO BA-FS26 check if mount point is already mounted and handle it (unmount old fs, fail, etc.) + auto new_fs_root = kstd::make_shared(mount_point_dentry, fs->root_inode()); + auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, path); + m_mount_table.add_mount(new_mount); + } + auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr { // TODO BA-FS26 implement full path resolution semantics. // TODO BA-FS26 better path validation // TODO BA-FS26 implement a path parser (maybe in libs?) and use it here and in do_mount - if (!path.empty() && path.front() == '/') + if (path.empty() || path.front() != '/') + return nullptr; + + // TODO BA-FS26 longest match in mount_table -> jump into final fs directly + // TODO BA-FS26 performance optimization first check mounted_flag O(1) then check mount_table O(n) + + auto best_mount = m_mount_table.find_longest_prefix_mount(path); + if (!best_mount) { - auto root_mount = m_mount_table.get_root_mount(); - if (!root_mount) - { - kapi::system::panic("[FILESYSTEM] no root mount found."); - } + kapi::system::panic("[FILESYSTEM] no root mount found."); + } - auto current_dentry = root_mount->root_dentry(); - auto current_fs = root_mount->get_filesystem(); + auto current_dentry = best_mount->root_dentry(); + auto current_fs = best_mount->get_filesystem(); - auto path_parts = - std::views::split(path, '/') | std::views::filter([](auto const & part) { return !part.empty(); }); - for (auto const & part : path_parts) + std::string_view remaining = path.substr(best_mount->get_mount_path().size()); + + auto path_parts = + std::views::split(remaining, '/') | std::views::filter([](auto const & part) { return !part.empty(); }); + + for (auto const & part : path_parts) + { + std::string_view part_view{part}; + + auto next_dentry = current_dentry->find_child(part_view); + if (!next_dentry) { - std::string_view part_view{part}; - auto next_dentry = current_dentry->find_child(part_view); - - if (!next_dentry) - { - if (auto found_inode = current_fs->lookup(current_dentry->get_inode(), part_view)) - { - next_dentry = kstd::make_shared(current_dentry, found_inode, part_view); - current_dentry->add_child(next_dentry); - } - else - { - return nullptr; - } - } - - // TODO BA-FS26 use while to allow stacked mounts? - if (next_dentry->has_flag(dentry::dentry_flags::dcache_mounted)) - { - auto found_mount = m_mount_table.find_mount_by_dentry(next_dentry); - if (!found_mount) - kapi::system::panic("[FILESYSTEM] dcache_mounted set but no covering mount found."); - current_fs = found_mount->get_filesystem(); - current_dentry = found_mount->root_dentry(); - } - else - { - current_dentry = next_dentry; - } + auto found_inode = current_fs->lookup(current_dentry->get_inode(), part_view); + if (!found_inode) + return nullptr; + + next_dentry = kstd::make_shared(current_dentry, found_inode, part_view); + current_dentry->add_child(next_dentry); } - return current_dentry; + current_dentry = next_dentry; } - return nullptr; + return current_dentry; } } // namespace filesystem \ No newline at end of file -- cgit v1.2.3 From 09300635a916b67c027f8b6c1823db944f578669 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 28 Mar 2026 17:34:08 +0100 Subject: improve open and mount tests --- kernel/src/main.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 19a0992..4510240 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -111,16 +111,32 @@ auto test_file_lookup() -> void auto vfs = filesystem::vfs::get(); auto storage_mgmt = devices::storage::storage_management::get(); - vfs.open("/a/b/c"); - vfs.open("/a/d/e"); + auto ofd1 = vfs.open("/a/b/c"); + auto ofd2 = vfs.open("/dev/ram0"); + auto ofd3 = vfs.open("/a/d/e"); + if (!ofd1 || !ofd2 || !ofd3) + { + kstd::os::panic("test code failed"); + } + + if (auto ofd4 = vfs.open("/dev/xxx")) + { + kstd::os::panic("test code failed"); + } auto new_filesystem = kstd::make_shared(); auto device = storage_mgmt.device_by_major_minor(1, 16); new_filesystem->mount(device); - vfs.do_mount("/a/b", new_filesystem); - vfs.open("/a/b/c"); + if (vfs.do_mount("/a/b", new_filesystem) != 0) + { + kstd::os::panic("test code failed"); + } + auto ofd5 = vfs.open("/a/b/c"); - vfs.open("x/y/z"); + if (auto ofd6 = vfs.open("x/y/z")) + { + kstd::os::panic("test code failed"); + } } auto run_test_code() -> void -- cgit v1.2.3 From fe964c2c9d3fb29223060f99c07ae1ce4e69daae Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 28 Mar 2026 19:14:02 +0100 Subject: set flag (currently not needed) --- kernel/src/filesystem/vfs.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index da7fa05..7a90531 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -111,6 +111,7 @@ namespace filesystem auto new_fs_root = kstd::make_shared(mount_point_dentry, fs->root_inode()); auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, path); m_mount_table.add_mount(new_mount); + mount_point_dentry->set_flag(dentry::dentry_flags::dcache_mounted); } auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr -- cgit v1.2.3 From 8a9bf5a90b7f46d5c615b55a3fc418b419db4926 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 28 Mar 2026 19:14:26 +0100 Subject: improve test --- kernel/src/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 4510240..98c88f2 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -132,6 +132,10 @@ auto test_file_lookup() -> void kstd::os::panic("test code failed"); } auto ofd5 = vfs.open("/a/b/c"); + if (!ofd5) + { + kstd::os::panic("test code failed"); + } if (auto ofd6 = vfs.open("x/y/z")) { -- cgit v1.2.3 From 8c0488fb8df8742740eb8464a7ad51d71a24e416 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sun, 29 Mar 2026 13:29:23 +0200 Subject: remove redundant ext2_file class --- kernel/src/filesystem/ext2/ext2_file.cpp | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 kernel/src/filesystem/ext2/ext2_file.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/ext2_file.cpp b/kernel/src/filesystem/ext2/ext2_file.cpp deleted file mode 100644 index 7217c77..0000000 --- a/kernel/src/filesystem/ext2/ext2_file.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "kernel/filesystem/ext2/ext2_file.hpp" - -#include "kapi/system.hpp" - -#include - -namespace filesystem::ext2 -{ - auto ext2_file::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t - { - kapi::system::panic("[FILESYSTEM] ext2_file::read is not implemented yet."); - return 0; - } - - auto ext2_file::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t - { - kapi::system::panic("[FILESYSTEM] ext2_file::write is not implemented yet."); - return 0; - } -} // namespace filesystem::ext2 -- cgit v1.2.3 From 9c602f2cf8fd87f55adc31c085e469e72b7cbbfa Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Sun, 29 Mar 2026 20:49:03 +0200 Subject: Move block device offset and size-to-blocks calculation to block_device_utils --- kernel/src/devices/block_device_utils.cpp | 103 +++++++++++++++++++++++++ kernel/src/filesystem/device_inode.cpp | 76 +----------------- kernel/src/filesystem/ext2/ext2_filesystem.cpp | 2 + 3 files changed, 108 insertions(+), 73 deletions(-) create mode 100644 kernel/src/devices/block_device_utils.cpp (limited to 'kernel/src') diff --git a/kernel/src/devices/block_device_utils.cpp b/kernel/src/devices/block_device_utils.cpp new file mode 100644 index 0000000..9d3af1b --- /dev/null +++ b/kernel/src/devices/block_device_utils.cpp @@ -0,0 +1,103 @@ +#include "kernel/devices/block_device_utils.hpp" + +#include "kapi/system.hpp" + +#include "kernel/devices/block_device.hpp" +#include "kernel/devices/device.hpp" + +#include +#include +#include + +#include +#include + +namespace 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); + + auto process_blocks(kstd::shared_ptr const & device, size_t offset, size_t size, void * buffer, + block_op op) -> size_t + { + if (buffer == nullptr) + { + kapi::system::panic("[FILESYSTEM] device_file::process_blocks called with null buffer."); + } + + if (size == 0) + { + return 0; + } + + auto * block_dev = static_cast(device.get()); + if (block_dev == nullptr) + { + kapi::system::panic("[FILESYSTEM] device_file: expected block_device."); + } + + size_t const block_size = block_dev->block_size(); + size_t const capacity = block_dev->capacity(); + + if (offset >= capacity) + return 0; + size_t const total_to_process = std::min(size, capacity - offset); + + kstd::vector scratch_buffer{block_size}; + auto processed = 0uz; + + 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); + + processed += chunk_size; + } + + return processed; + } + + auto read(kstd::shared_ptr const & device, void * buffer, size_t offset, size_t size) -> size_t + { + 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) { + auto * out = static_cast(buffer); + if (off == 0 && len == device->block_size()) + { + device->read_block(idx, out + done); + } + else + { + device->read_block(idx, scratch); + kstd::libc::memcpy(out + done, scratch + off, len); + } + }); + } + + auto write(kstd::shared_ptr const & device, void const * buffer, size_t offset, size_t size) + -> size_t + { + return process_blocks(device, offset, size, const_cast(buffer), + [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, + std::byte * scratch, void * buffer) { + auto const * in = static_cast(buffer); + if (off == 0 && len == device->block_size()) + { + 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); + } + }); + } + +} // namespace devices::block_device_utils \ No newline at end of file diff --git a/kernel/src/filesystem/device_inode.cpp b/kernel/src/filesystem/device_inode.cpp index 64cd6e9..da062fc 100644 --- a/kernel/src/filesystem/device_inode.cpp +++ b/kernel/src/filesystem/device_inode.cpp @@ -2,7 +2,7 @@ #include "kapi/system.hpp" -#include "kernel/devices/block_device.hpp" +#include "kernel/devices/block_device_utils.hpp" #include "kernel/devices/device.hpp" #include "kernel/filesystem/inode.hpp" @@ -10,7 +10,6 @@ #include #include -#include #include namespace filesystem @@ -29,20 +28,7 @@ namespace filesystem { if (m_device->is_block_device()) { - return process_blocks(offset, size, buffer, - [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, - std::byte * scratch, void * buffer) { - auto * out = static_cast(buffer); - if (off == 0 && len == device->block_size()) - { - device->read_block(idx, out + done); - } - else - { - device->read_block(idx, scratch); - kstd::libc::memcpy(out + done, scratch + off, len); - } - }); + return devices::block_device_utils::read(m_device, buffer, offset, size); } else { @@ -54,21 +40,7 @@ namespace filesystem { if (m_device->is_block_device()) { - return process_blocks(offset, size, const_cast(buffer), - [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, - std::byte * scratch, void * buffer) { - auto const * in = static_cast(buffer); - if (off == 0 && len == device->block_size()) - { - 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 devices::block_device_utils::write(m_device, buffer, offset, size); } else { @@ -81,46 +53,4 @@ namespace filesystem return m_device; } - auto device_inode::process_blocks(size_t offset, size_t size, void * buffer, block_op op) const -> size_t - { - if (buffer == nullptr) - { - kapi::system::panic("[FILESYSTEM] device_file::process_blocks called with null buffer."); - } - - if (size == 0) - { - return 0; - } - - auto * block_dev = static_cast(m_device.get()); - if (block_dev == nullptr) - { - kapi::system::panic("[FILESYSTEM] device_file: expected block_device."); - } - - size_t const block_size = block_dev->block_size(); - size_t const capacity = block_dev->capacity(); - - if (offset >= capacity) - return 0; - size_t const total_to_process = std::min(size, capacity - offset); - - kstd::vector scratch_buffer{block_size}; - auto processed = 0uz; - - 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); - - processed += chunk_size; - } - - return processed; - } } // namespace filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/ext2/ext2_filesystem.cpp b/kernel/src/filesystem/ext2/ext2_filesystem.cpp index 373c6a2..19f1014 100644 --- a/kernel/src/filesystem/ext2/ext2_filesystem.cpp +++ b/kernel/src/filesystem/ext2/ext2_filesystem.cpp @@ -1,5 +1,6 @@ #include "kernel/filesystem/ext2/ext2_filesystem.hpp" +#include "kernel/devices/block_device_utils.hpp" #include "kernel/devices/device.hpp" #include "kernel/filesystem/ext2/ext2_inode.hpp" #include "kernel/filesystem/filesystem.hpp" @@ -19,6 +20,7 @@ namespace filesystem::ext2 // TODO BA-FS26 implement m_root_inode = kstd::make_shared(); + // devices::block_device_utils::read(device, nullptr, 0, 0); // TODO BA-FS26 just for testing return 0; } -- cgit v1.2.3 From ea578b348f63939bb07bd669ad86d3fe1b6d5f65 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Sun, 29 Mar 2026 21:30:32 +0200 Subject: Save WIP add some definitions and helper functions --- kernel/src/filesystem/ext2/ext2_filesystem.cpp | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/ext2_filesystem.cpp b/kernel/src/filesystem/ext2/ext2_filesystem.cpp index 19f1014..e176ade 100644 --- a/kernel/src/filesystem/ext2/ext2_filesystem.cpp +++ b/kernel/src/filesystem/ext2/ext2_filesystem.cpp @@ -3,15 +3,48 @@ #include "kernel/devices/block_device_utils.hpp" #include "kernel/devices/device.hpp" #include "kernel/filesystem/ext2/ext2_inode.hpp" +#include "kernel/filesystem/ext2/ext2_superblock.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" #include +#include +#include #include namespace filesystem::ext2 { + namespace + { + constexpr size_t SUPERBLOCK_OFFSET = 1024; + constexpr uint16_t EXT2_MAGIC = 0xEF53; + + // Mode bits + constexpr uint16_t S_IFMT = 0xF000; + constexpr uint16_t S_IFREG = 0x8000; + constexpr uint16_t S_IFDIR = 0x4000; + + auto S_ISREG(uint16_t mode) -> bool + { + return (mode & S_IFMT) == S_IFREG; + } + auto S_ISDIR(uint16_t mode) -> bool + { + return (mode & S_IFMT) == S_IFDIR; + } + + auto get_block_size(ext2_superblock const & superblock) -> size_t + { + return 1024U << superblock.log_block_size; + } + + auto get_inode_size(ext2_superblock const & superblock) -> size_t + { + return superblock.rev_level == 0 ? 128 : superblock.inode_size; + } + } // namespace + auto ext2_filesystem::mount(kstd::shared_ptr const & device) -> int { filesystem::mount(device); // TODO BA-FS26 error handling? -- cgit v1.2.3 From 7ad07a735759dc93b668ec92896f57c0c0df0025 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Mon, 30 Mar 2026 19:26:48 +0200 Subject: Fix linter warnings --- kernel/src/filesystem/ext2/ext2_filesystem.cpp | 44 +++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/ext2_filesystem.cpp b/kernel/src/filesystem/ext2/ext2_filesystem.cpp index e176ade..ea6fe0d 100644 --- a/kernel/src/filesystem/ext2/ext2_filesystem.cpp +++ b/kernel/src/filesystem/ext2/ext2_filesystem.cpp @@ -17,32 +17,32 @@ namespace filesystem::ext2 { namespace { - constexpr size_t SUPERBLOCK_OFFSET = 1024; - constexpr uint16_t EXT2_MAGIC = 0xEF53; + // constexpr size_t SUPERBLOCK_OFFSET = 1024; + // constexpr uint16_t EXT2_MAGIC = 0xEF53; - // Mode bits - constexpr uint16_t S_IFMT = 0xF000; - constexpr uint16_t S_IFREG = 0x8000; - constexpr uint16_t S_IFDIR = 0x4000; + // // Mode bits + // constexpr uint16_t S_IFMT = 0xF000; + // constexpr uint16_t S_IFREG = 0x8000; + // constexpr uint16_t S_IFDIR = 0x4000; - auto S_ISREG(uint16_t mode) -> bool - { - return (mode & S_IFMT) == S_IFREG; - } - auto S_ISDIR(uint16_t mode) -> bool - { - return (mode & S_IFMT) == S_IFDIR; - } + // auto S_ISREG(uint16_t mode) -> bool + // { + // return (mode & S_IFMT) == S_IFREG; + // } + // auto S_ISDIR(uint16_t mode) -> bool + // { + // return (mode & S_IFMT) == S_IFDIR; + // } - auto get_block_size(ext2_superblock const & superblock) -> size_t - { - return 1024U << superblock.log_block_size; - } + // auto get_block_size(ext2_superblock const & superblock) -> size_t + // { + // return 1024U << superblock.log_block_size; + // } - auto get_inode_size(ext2_superblock const & superblock) -> size_t - { - return superblock.rev_level == 0 ? 128 : superblock.inode_size; - } + // auto get_inode_size(ext2_superblock const & superblock) -> size_t + // { + // return superblock.rev_level == 0 ? 128 : superblock.inode_size; + // } } // namespace auto ext2_filesystem::mount(kstd::shared_ptr const & device) -> int -- cgit v1.2.3 From 5603c7ec2b07dbc772fe2c20a9e9e176c5465c57 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Mon, 30 Mar 2026 21:22:22 +0200 Subject: Move everything in kernel into kernel namespace --- kernel/src/devices/block_device.cpp | 4 ++-- kernel/src/devices/block_device_utils.cpp | 4 ++-- kernel/src/devices/device.cpp | 4 ++-- .../storage/ram_disk/ram_disk_controller.cpp | 4 ++-- .../devices/storage/ram_disk/ram_disk_device.cpp | 4 ++-- kernel/src/devices/storage/storage_controller.cpp | 4 ++-- kernel/src/devices/storage/storage_management.cpp | 4 ++-- kernel/src/filesystem/dentry.cpp | 4 ++-- kernel/src/filesystem/devfs/devfs_filesystem.cpp | 4 ++-- kernel/src/filesystem/devfs/devfs_root_inode.cpp | 4 ++-- kernel/src/filesystem/device_inode.cpp | 4 ++-- kernel/src/filesystem/ext2/ext2_filesystem.cpp | 4 ++-- kernel/src/filesystem/ext2/ext2_inode.cpp | 4 ++-- kernel/src/filesystem/file_descriptor_table.cpp | 4 ++-- kernel/src/filesystem/filesystem.cpp | 4 ++-- kernel/src/filesystem/inode.cpp | 4 ++-- kernel/src/filesystem/mount.cpp | 4 ++-- kernel/src/filesystem/mount_table.cpp | 4 ++-- kernel/src/filesystem/open_file_description.cpp | 4 ++-- kernel/src/filesystem/rootfs/rootfs_filesystem.cpp | 4 ++-- kernel/src/filesystem/rootfs/rootfs_inode.cpp | 4 ++-- kernel/src/filesystem/vfs.cpp | 4 ++-- kernel/src/main.cpp | 28 +++++++++++----------- 23 files changed, 58 insertions(+), 58 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/devices/block_device.cpp b/kernel/src/devices/block_device.cpp index 3402814..cfe2eb2 100644 --- a/kernel/src/devices/block_device.cpp +++ b/kernel/src/devices/block_device.cpp @@ -8,7 +8,7 @@ #include -namespace devices +namespace kernel::devices { block_device::block_device(size_t major, size_t minor, kstd::string const & name, size_t block_size) : device(major, minor, name) @@ -40,4 +40,4 @@ namespace devices { return size(); } -} // namespace devices \ No newline at end of file +} // namespace kernel::devices \ No newline at end of file diff --git a/kernel/src/devices/block_device_utils.cpp b/kernel/src/devices/block_device_utils.cpp index 9d3af1b..5469087 100644 --- a/kernel/src/devices/block_device_utils.cpp +++ b/kernel/src/devices/block_device_utils.cpp @@ -12,7 +12,7 @@ #include #include -namespace devices::block_device_utils +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, @@ -100,4 +100,4 @@ namespace devices::block_device_utils }); } -} // namespace devices::block_device_utils \ No newline at end of file +} // namespace kernel::devices::block_device_utils \ No newline at end of file diff --git a/kernel/src/devices/device.cpp b/kernel/src/devices/device.cpp index 287f14b..1e7589e 100644 --- a/kernel/src/devices/device.cpp +++ b/kernel/src/devices/device.cpp @@ -4,7 +4,7 @@ #include -namespace devices +namespace kernel::devices { device::device(size_t major, size_t minor, kstd::string const & name) : m_major(major) @@ -26,4 +26,4 @@ namespace devices { return m_name; } -} // namespace devices \ No newline at end of file +} // namespace kernel::devices \ No newline at end of file diff --git a/kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp b/kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp index f3e9f70..26eb10b 100644 --- a/kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp +++ b/kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp @@ -9,7 +9,7 @@ #include #include -namespace devices::storage::ram_disk +namespace kernel::devices::storage::ram_disk { ram_disk_controller::ram_disk_controller(kapi::boot_modules::boot_module_registry const * registry) : m_boot_module_registry(registry) @@ -24,4 +24,4 @@ namespace devices::storage::ram_disk m_devices.push_back(kstd::make_shared(module, m_major, minor)); }); } -} // namespace devices::storage::ram_disk \ No newline at end of file +} // namespace kernel::devices::storage::ram_disk \ No newline at end of file diff --git a/kernel/src/devices/storage/ram_disk/ram_disk_device.cpp b/kernel/src/devices/storage/ram_disk/ram_disk_device.cpp index bf329cb..72e8025 100644 --- a/kernel/src/devices/storage/ram_disk/ram_disk_device.cpp +++ b/kernel/src/devices/storage/ram_disk/ram_disk_device.cpp @@ -10,7 +10,7 @@ #include -namespace devices::storage::ram_disk +namespace kernel::devices::storage::ram_disk { namespace { @@ -63,4 +63,4 @@ namespace devices::storage::ram_disk { return m_boot_module.size; } -} // namespace devices::storage::ram_disk \ No newline at end of file +} // namespace kernel::devices::storage::ram_disk \ No newline at end of file diff --git a/kernel/src/devices/storage/storage_controller.cpp b/kernel/src/devices/storage/storage_controller.cpp index e415436..3d13b66 100644 --- a/kernel/src/devices/storage/storage_controller.cpp +++ b/kernel/src/devices/storage/storage_controller.cpp @@ -8,7 +8,7 @@ #include #include -namespace devices::storage +namespace kernel::devices::storage { auto storage_controller::set_ids(size_t major, size_t minors_per_dev) -> void { @@ -41,4 +41,4 @@ namespace devices::storage { return m_devices; } -} // namespace devices::storage \ No newline at end of file +} // namespace kernel::devices::storage \ No newline at end of file diff --git a/kernel/src/devices/storage/storage_management.cpp b/kernel/src/devices/storage/storage_management.cpp index 56216b0..2bc57c4 100644 --- a/kernel/src/devices/storage/storage_management.cpp +++ b/kernel/src/devices/storage/storage_management.cpp @@ -14,7 +14,7 @@ #include #include -namespace devices::storage +namespace kernel::devices::storage { namespace { @@ -82,4 +82,4 @@ namespace devices::storage return device_by_major_minor(START_MAJOR, 0); } -} // namespace devices::storage \ No newline at end of file +} // namespace kernel::devices::storage \ No newline at end of file diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index 76949f2..2f99e91 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -10,7 +10,7 @@ #include #include -namespace filesystem +namespace kernel::filesystem { dentry::dentry(kstd::shared_ptr const & parent, kstd::shared_ptr const & node, std::string_view name) : m_name(name) @@ -58,4 +58,4 @@ namespace filesystem { return (m_flags & static_cast(flag)) != 0; } -} // namespace filesystem \ No newline at end of file +} // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/devfs/devfs_filesystem.cpp b/kernel/src/filesystem/devfs/devfs_filesystem.cpp index c4cd81a..df977b8 100644 --- a/kernel/src/filesystem/devfs/devfs_filesystem.cpp +++ b/kernel/src/filesystem/devfs/devfs_filesystem.cpp @@ -11,7 +11,7 @@ #include #include -namespace filesystem::devfs +namespace kernel::filesystem::devfs { auto devfs_filesystem::mount(kstd::shared_ptr const &) -> int { @@ -55,4 +55,4 @@ namespace filesystem::devfs [&](auto const & device) { m_inodes.push_back(kstd::make_shared(device)); }); }); } -} // namespace filesystem::devfs \ No newline at end of file +} // namespace kernel::filesystem::devfs \ No newline at end of file diff --git a/kernel/src/filesystem/devfs/devfs_root_inode.cpp b/kernel/src/filesystem/devfs/devfs_root_inode.cpp index 53441b0..a7308dc 100644 --- a/kernel/src/filesystem/devfs/devfs_root_inode.cpp +++ b/kernel/src/filesystem/devfs/devfs_root_inode.cpp @@ -4,7 +4,7 @@ #include -namespace filesystem::devfs +namespace kernel::filesystem::devfs { devfs_root_inode::devfs_root_inode() : inode(inode_kind::directory) @@ -19,4 +19,4 @@ namespace filesystem::devfs { return 0; } -} // namespace filesystem::devfs \ No newline at end of file +} // namespace kernel::filesystem::devfs \ No newline at end of file diff --git a/kernel/src/filesystem/device_inode.cpp b/kernel/src/filesystem/device_inode.cpp index da062fc..d574d8f 100644 --- a/kernel/src/filesystem/device_inode.cpp +++ b/kernel/src/filesystem/device_inode.cpp @@ -12,7 +12,7 @@ #include -namespace filesystem +namespace kernel::filesystem { device_inode::device_inode(kstd::shared_ptr const & device) : inode(inode_kind::device) @@ -53,4 +53,4 @@ namespace filesystem return m_device; } -} // namespace filesystem \ No newline at end of file +} // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/ext2/ext2_filesystem.cpp b/kernel/src/filesystem/ext2/ext2_filesystem.cpp index ea6fe0d..036b80e 100644 --- a/kernel/src/filesystem/ext2/ext2_filesystem.cpp +++ b/kernel/src/filesystem/ext2/ext2_filesystem.cpp @@ -13,7 +13,7 @@ #include #include -namespace filesystem::ext2 +namespace kernel::filesystem::ext2 { namespace { @@ -69,4 +69,4 @@ namespace filesystem::ext2 return kstd::make_shared(); } -} // namespace filesystem::ext2 +} // namespace kernel::filesystem::ext2 diff --git a/kernel/src/filesystem/ext2/ext2_inode.cpp b/kernel/src/filesystem/ext2/ext2_inode.cpp index 3cc0fb2..142502e 100644 --- a/kernel/src/filesystem/ext2/ext2_inode.cpp +++ b/kernel/src/filesystem/ext2/ext2_inode.cpp @@ -4,7 +4,7 @@ #include -namespace filesystem::ext2 +namespace kernel::filesystem::ext2 { ext2_inode::ext2_inode() : inode(inode_kind::regular) @@ -21,4 +21,4 @@ namespace filesystem::ext2 // TODO BA-FS26 implement return 0; } -} // namespace filesystem::ext2 \ No newline at end of file +} // namespace kernel::filesystem::ext2 \ No newline at end of file diff --git a/kernel/src/filesystem/file_descriptor_table.cpp b/kernel/src/filesystem/file_descriptor_table.cpp index 6eb3845..287aea2 100644 --- a/kernel/src/filesystem/file_descriptor_table.cpp +++ b/kernel/src/filesystem/file_descriptor_table.cpp @@ -10,7 +10,7 @@ #include #include -namespace filesystem +namespace kernel::filesystem { namespace { @@ -87,4 +87,4 @@ namespace filesystem m_open_files.at(index) = nullptr; } -} // namespace filesystem \ No newline at end of file +} // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index 0e33d95..c891d00 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -5,7 +5,7 @@ #include -namespace filesystem +namespace kernel::filesystem { auto filesystem::mount(kstd::shared_ptr const & device) -> int { @@ -21,4 +21,4 @@ namespace filesystem { return m_root_inode; } -} // namespace filesystem \ No newline at end of file +} // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/inode.cpp b/kernel/src/filesystem/inode.cpp index de3282f..1cbead8 100644 --- a/kernel/src/filesystem/inode.cpp +++ b/kernel/src/filesystem/inode.cpp @@ -1,6 +1,6 @@ #include "kernel/filesystem/inode.hpp" -namespace filesystem +namespace kernel::filesystem { inode::inode(inode_kind kind) : m_kind(kind) @@ -20,4 +20,4 @@ namespace filesystem { return m_kind == inode_kind::device; } -} // namespace filesystem \ No newline at end of file +} // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index afc07fa..f9e709c 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -10,7 +10,7 @@ #include -namespace filesystem +namespace kernel::filesystem { mount::mount(kstd::shared_ptr const & mount_dentry, kstd::shared_ptr const & root_dentry, kstd::shared_ptr const & fs, std::string_view mount_path) @@ -44,4 +44,4 @@ namespace filesystem { return m_mount_path.view(); } -} // namespace filesystem \ No newline at end of file +} // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index b9e57d4..737434e 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -7,7 +7,7 @@ #include #include -namespace filesystem +namespace kernel::filesystem { void mount_table::add_mount(kstd::shared_ptr mount) { @@ -35,4 +35,4 @@ namespace filesystem return mount_with_longest_prefix; } -} // namespace filesystem \ No newline at end of file +} // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/open_file_description.cpp b/kernel/src/filesystem/open_file_description.cpp index 93c38ac..8c04225 100644 --- a/kernel/src/filesystem/open_file_description.cpp +++ b/kernel/src/filesystem/open_file_description.cpp @@ -7,7 +7,7 @@ #include -namespace filesystem +namespace kernel::filesystem { open_file_description::open_file_description(kstd::shared_ptr const & inode) : m_inode(inode) @@ -32,4 +32,4 @@ namespace filesystem m_offset += written_bytes; return written_bytes; } -} // namespace filesystem \ No newline at end of file +} // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp b/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp index 22502aa..804e211 100644 --- a/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp +++ b/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp @@ -8,7 +8,7 @@ #include -namespace filesystem::rootfs +namespace kernel::filesystem::rootfs { auto rootfs_filesystem::mount(kstd::shared_ptr const &) -> int { @@ -26,4 +26,4 @@ namespace filesystem::rootfs return rfs_inode->lookup_child(name); return nullptr; } -} // namespace filesystem::rootfs +} // namespace kernel::filesystem::rootfs diff --git a/kernel/src/filesystem/rootfs/rootfs_inode.cpp b/kernel/src/filesystem/rootfs/rootfs_inode.cpp index 9bbfbce..f44f06c 100644 --- a/kernel/src/filesystem/rootfs/rootfs_inode.cpp +++ b/kernel/src/filesystem/rootfs/rootfs_inode.cpp @@ -10,7 +10,7 @@ #include #include -namespace filesystem::rootfs +namespace kernel::filesystem::rootfs { rootfs_inode::rootfs_inode() : inode(inode_kind::directory) @@ -36,4 +36,4 @@ namespace filesystem::rootfs auto it = std::ranges::find_if(m_children, [&](auto const & pair) { return pair.first == name; }); return (it != m_children.end()) ? it->second : nullptr; } -} // namespace filesystem::rootfs +} // namespace kernel::filesystem::rootfs diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 7a90531..2dbdb12 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -17,7 +17,7 @@ #include #include -namespace filesystem +namespace kernel::filesystem { namespace { @@ -161,4 +161,4 @@ namespace filesystem return current_dentry; } -} // namespace filesystem \ No newline at end of file +} // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index bb6d57d..2dd9fd9 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -24,7 +24,7 @@ auto test_device_names() -> void { - auto storage_mgmt = devices::storage::storage_management::get(); + auto storage_mgmt = kernel::devices::storage::storage_management::get(); std::ranges::for_each(storage_mgmt.all_controllers(), [](auto const & controller) { std::ranges::for_each(controller->all_devices(), [](auto const & device) { kstd::println("{}", device->name().view()); }); @@ -34,13 +34,13 @@ auto test_device_names() -> void auto test_file_description_manually() -> void { // setup - auto fd_table = filesystem::file_descriptor_table::get(); - auto storage_mgmt = devices::storage::storage_management::get(); + auto fd_table = kernel::filesystem::file_descriptor_table::get(); + auto storage_mgmt = kernel::devices::storage::storage_management::get(); auto device = storage_mgmt.device_by_major_minor(1, 0); - auto dev_node = kstd::make_shared(device); + auto dev_node = kstd::make_shared(device); - auto ofd = kstd::make_shared(dev_node); + auto ofd = kstd::make_shared(dev_node); auto fd_index = fd_table.add_file(ofd); // use: read two bytes and write two again @@ -66,7 +66,7 @@ auto test_file_description_manually() -> void fd_table.remove_file(fd_index); // use: read four bytes again -> two old bytes two new bytes - auto ofd1 = kstd::make_shared(dev_node); + auto ofd1 = kstd::make_shared(dev_node); fd_index = fd_table.add_file(ofd1); auto fd1 = fd_table.get_file(fd_index); @@ -85,14 +85,14 @@ auto test_device_with_vfs() -> void { // TODO BA-FS26 - auto vfs = filesystem::vfs::get(); + auto vfs = kernel::filesystem::vfs::get(); auto ofd = vfs.open("/dev/ram0"); if (!ofd) { kstd::os::panic("test code failed"); } - auto fd_table = filesystem::file_descriptor_table::get(); + auto fd_table = kernel::filesystem::file_descriptor_table::get(); auto fd = fd_table.add_file(ofd); kstd::vector buffer{2}; auto file = fd_table.get_file(fd); @@ -110,8 +110,8 @@ auto test_file_lookup() -> void { // TODO BA-FS26 implement a more complete test with multiple files and directories and mounts etc. - auto vfs = filesystem::vfs::get(); - auto storage_mgmt = devices::storage::storage_management::get(); + auto vfs = kernel::filesystem::vfs::get(); + auto storage_mgmt = kernel::devices::storage::storage_management::get(); auto ofd1 = vfs.open("/a/b/c"); auto ofd2 = vfs.open("/dev/ram0"); @@ -126,7 +126,7 @@ auto test_file_lookup() -> void kstd::os::panic("test code failed"); } - auto new_filesystem = kstd::make_shared(); + auto new_filesystem = kstd::make_shared(); auto device = storage_mgmt.device_by_major_minor(1, 16); new_filesystem->mount(device); if (vfs.do_mount("/a/b", new_filesystem) != 0) @@ -182,13 +182,13 @@ auto main() -> int kapi::boot_modules::init(); kstd::println("[OS] Boot module registry initialized."); - devices::storage::storage_management::init(); + kernel::devices::storage::storage_management::init(); kstd::println("[OS] Storage management initialized."); - filesystem::file_descriptor_table::init(); + kernel::filesystem::file_descriptor_table::init(); kstd::println("[OS] Global file descriptor table initialized."); - filesystem::vfs::init(); + kernel::filesystem::vfs::init(); kstd::println("[OS] Virtual filesystem initialized."); run_test_code(); -- cgit v1.2.3 From 55e37a219fc953d1675bc2edb8573c6d47df7647 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Mon, 30 Mar 2026 21:23:02 +0200 Subject: Rename ext2 filesystem files --- kernel/src/filesystem/ext2/ext2_filesystem.cpp | 72 -------------------------- kernel/src/filesystem/ext2/ext2_inode.cpp | 24 --------- kernel/src/filesystem/ext2/filesystem.cpp | 72 ++++++++++++++++++++++++++ kernel/src/filesystem/ext2/inode.cpp | 24 +++++++++ kernel/src/filesystem/vfs.cpp | 4 +- kernel/src/main.cpp | 4 +- 6 files changed, 100 insertions(+), 100 deletions(-) delete mode 100644 kernel/src/filesystem/ext2/ext2_filesystem.cpp delete mode 100644 kernel/src/filesystem/ext2/ext2_inode.cpp create mode 100644 kernel/src/filesystem/ext2/filesystem.cpp create mode 100644 kernel/src/filesystem/ext2/inode.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/ext2_filesystem.cpp b/kernel/src/filesystem/ext2/ext2_filesystem.cpp deleted file mode 100644 index 036b80e..0000000 --- a/kernel/src/filesystem/ext2/ext2_filesystem.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "kernel/filesystem/ext2/ext2_filesystem.hpp" - -#include "kernel/devices/block_device_utils.hpp" -#include "kernel/devices/device.hpp" -#include "kernel/filesystem/ext2/ext2_inode.hpp" -#include "kernel/filesystem/ext2/ext2_superblock.hpp" -#include "kernel/filesystem/filesystem.hpp" -#include "kernel/filesystem/inode.hpp" - -#include - -#include -#include -#include - -namespace kernel::filesystem::ext2 -{ - namespace - { - // constexpr size_t SUPERBLOCK_OFFSET = 1024; - // constexpr uint16_t EXT2_MAGIC = 0xEF53; - - // // Mode bits - // constexpr uint16_t S_IFMT = 0xF000; - // constexpr uint16_t S_IFREG = 0x8000; - // constexpr uint16_t S_IFDIR = 0x4000; - - // auto S_ISREG(uint16_t mode) -> bool - // { - // return (mode & S_IFMT) == S_IFREG; - // } - // auto S_ISDIR(uint16_t mode) -> bool - // { - // return (mode & S_IFMT) == S_IFDIR; - // } - - // auto get_block_size(ext2_superblock const & superblock) -> size_t - // { - // return 1024U << superblock.log_block_size; - // } - - // auto get_inode_size(ext2_superblock const & superblock) -> size_t - // { - // return superblock.rev_level == 0 ? 128 : superblock.inode_size; - // } - } // namespace - - auto ext2_filesystem::mount(kstd::shared_ptr const & device) -> int - { - filesystem::mount(device); // TODO BA-FS26 error handling? - // TODO BA-FS26 load proper root inode from ext2 metadata - // m_root_inode = inode{inode_kind::directory}; - - // TODO BA-FS26 implement - m_root_inode = kstd::make_shared(); - // devices::block_device_utils::read(device, nullptr, 0, 0); // TODO BA-FS26 just for testing - return 0; - } - - auto ext2_filesystem::lookup(kstd::shared_ptr const & /*parent*/, std::string_view name) - -> kstd::shared_ptr - { - // TODO BA-FS26 implement ext2 directory traversal and inode loading - if (name == "dev") - { - // TODO BA-FS26 just for testing - return nullptr; - } - - return kstd::make_shared(); - } -} // namespace kernel::filesystem::ext2 diff --git a/kernel/src/filesystem/ext2/ext2_inode.cpp b/kernel/src/filesystem/ext2/ext2_inode.cpp deleted file mode 100644 index 142502e..0000000 --- a/kernel/src/filesystem/ext2/ext2_inode.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "kernel/filesystem/ext2/ext2_inode.hpp" - -#include "kernel/filesystem/inode.hpp" - -#include - -namespace kernel::filesystem::ext2 -{ - ext2_inode::ext2_inode() - : inode(inode_kind::regular) - {} - - auto ext2_inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t - { - // TODO BA-FS26 implement - return 0; - } - - auto ext2_inode::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t - { - // TODO BA-FS26 implement - return 0; - } -} // namespace kernel::filesystem::ext2 \ No newline at end of file diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp new file mode 100644 index 0000000..d951158 --- /dev/null +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -0,0 +1,72 @@ +#include "kernel/filesystem/ext2/filesystem.hpp" + +#include "kernel/devices/block_device_utils.hpp" +#include "kernel/devices/device.hpp" +#include "kernel/filesystem/ext2/inode.hpp" +#include "kernel/filesystem/ext2/superblock.hpp" +#include "kernel/filesystem/filesystem.hpp" +#include "kernel/filesystem/inode.hpp" + +#include + +#include +#include +#include + +namespace kernel::filesystem::ext2 +{ + namespace + { + // constexpr size_t SUPERBLOCK_OFFSET = 1024; + // constexpr uint16_t EXT2_MAGIC = 0xEF53; + + // // Mode bits + // constexpr uint16_t S_IFMT = 0xF000; + // constexpr uint16_t S_IFREG = 0x8000; + // constexpr uint16_t S_IFDIR = 0x4000; + + // auto S_ISREG(uint16_t mode) -> bool + // { + // return (mode & S_IFMT) == S_IFREG; + // } + // auto S_ISDIR(uint16_t mode) -> bool + // { + // return (mode & S_IFMT) == S_IFDIR; + // } + + // auto get_block_size(superblock const & superblock) -> size_t + // { + // return 1024U << superblock.log_block_size; + // } + + // auto get_inode_size(superblock const & superblock) -> size_t + // { + // return superblock.rev_level == 0 ? 128 : superblock.inode_size; + // } + } // namespace + + auto filesystem::mount(kstd::shared_ptr const & device) -> int + { + kernel::filesystem::filesystem::mount(device); // TODO BA-FS26 error handling? + // TODO BA-FS26 load proper root inode from ext2 metadata + // m_root_inode = inode{inode_kind::directory}; + + // TODO BA-FS26 implement + m_root_inode = kstd::make_shared(); + // devices::block_device_utils::read(device, nullptr, 0, 0); // TODO BA-FS26 just for testing + return 0; + } + + auto filesystem::lookup(kstd::shared_ptr const & /*parent*/, std::string_view name) + -> kstd::shared_ptr + { + // TODO BA-FS26 implement ext2 directory traversal and inode loading + if (name == "dev") + { + // TODO BA-FS26 just for testing + return nullptr; + } + + return kstd::make_shared(); + } +} // namespace kernel::filesystem::ext2 diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp new file mode 100644 index 0000000..b75969a --- /dev/null +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -0,0 +1,24 @@ +#include "kernel/filesystem/ext2/inode.hpp" + +#include "kernel/filesystem/inode.hpp" + +#include + +namespace kernel::filesystem::ext2 +{ + inode::inode() + : kernel::filesystem::inode(inode_kind::regular) + {} + + auto inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t + { + // TODO BA-FS26 implement + return 0; + } + + auto inode::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t + { + // TODO BA-FS26 implement + return 0; + } +} // namespace kernel::filesystem::ext2 \ No newline at end of file diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 2dbdb12..69740c3 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -5,7 +5,7 @@ #include "kernel/devices/storage/storage_management.hpp" #include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/devfs/devfs_filesystem.hpp" -#include "kernel/filesystem/ext2/ext2_filesystem.hpp" +#include "kernel/filesystem/ext2/filesystem.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/mount.hpp" #include "kernel/filesystem/open_file_description.hpp" @@ -47,7 +47,7 @@ namespace kernel::filesystem if (auto boot_device = storage_mgmt.determine_boot_device()) { // TODO BA-FS26 detect fs type from boot device and load corresponding fs, for now just assume ext2 - auto boot_root_fs = kstd::make_shared(); + auto boot_root_fs = kstd::make_shared(); boot_root_fs->mount(boot_device); do_mount_internal("/", root_fs_root_dentry, boot_root_fs); } diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 2dd9fd9..ff73985 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -7,7 +7,7 @@ #include "kernel/devices/storage/storage_management.hpp" #include "kernel/filesystem/device_inode.hpp" -#include "kernel/filesystem/ext2/ext2_filesystem.hpp" +#include "kernel/filesystem/ext2/filesystem.hpp" #include "kernel/filesystem/file_descriptor_table.hpp" #include "kernel/filesystem/open_file_description.hpp" #include "kernel/filesystem/vfs.hpp" @@ -126,7 +126,7 @@ auto test_file_lookup() -> void kstd::os::panic("test code failed"); } - auto new_filesystem = kstd::make_shared(); + auto new_filesystem = kstd::make_shared(); auto device = storage_mgmt.device_by_major_minor(1, 16); new_filesystem->mount(device); if (vfs.do_mount("/a/b", new_filesystem) != 0) -- cgit v1.2.3 From 0b5084780e4a89dcaccbda5823495c9cdd62b006 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Mon, 30 Mar 2026 20:52:25 +0200 Subject: Rename devfs filesystem files --- kernel/src/filesystem/devfs/devfs_filesystem.cpp | 58 ------------------------ kernel/src/filesystem/devfs/devfs_root_inode.cpp | 22 --------- kernel/src/filesystem/devfs/filesystem.cpp | 58 ++++++++++++++++++++++++ kernel/src/filesystem/devfs/inode.cpp | 22 +++++++++ kernel/src/filesystem/vfs.cpp | 4 +- 5 files changed, 82 insertions(+), 82 deletions(-) delete mode 100644 kernel/src/filesystem/devfs/devfs_filesystem.cpp delete mode 100644 kernel/src/filesystem/devfs/devfs_root_inode.cpp create mode 100644 kernel/src/filesystem/devfs/filesystem.cpp create mode 100644 kernel/src/filesystem/devfs/inode.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/devfs/devfs_filesystem.cpp b/kernel/src/filesystem/devfs/devfs_filesystem.cpp deleted file mode 100644 index df977b8..0000000 --- a/kernel/src/filesystem/devfs/devfs_filesystem.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "kernel/filesystem/devfs/devfs_filesystem.hpp" - -#include "kernel/devices/device.hpp" -#include "kernel/devices/storage/storage_management.hpp" -#include "kernel/filesystem/devfs/devfs_root_inode.hpp" -#include "kernel/filesystem/device_inode.hpp" -#include "kernel/filesystem/inode.hpp" - -#include - -#include -#include - -namespace kernel::filesystem::devfs -{ - auto devfs_filesystem::mount(kstd::shared_ptr const &) -> int - { - m_root_inode = kstd::make_shared(); - build_device_inode_table(); - - return 0; - } - - auto devfs_filesystem::lookup(kstd::shared_ptr const & parent, std::string_view name) - -> kstd::shared_ptr - { - if (!parent || !parent->is_directory()) - { - return nullptr; - } - - if (parent.get() != m_root_inode.get()) - { - return nullptr; - } - - auto it = std::ranges::find_if(m_inodes, [&](auto const & dev_node) { - auto device_inode_ptr = static_cast(dev_node.get()); - if (!device_inode_ptr) - { - return false; - } - return device_inode_ptr->device()->name() == name; - }); - return (it != m_inodes.end()) ? *it : nullptr; - } - - auto devfs_filesystem::build_device_inode_table() -> void - { - m_inodes.clear(); - - auto storage_mgmt = devices::storage::storage_management::get(); - std::ranges::for_each(storage_mgmt.all_controllers(), [&](auto const & controller) { - std::ranges::for_each(controller->all_devices(), - [&](auto const & device) { m_inodes.push_back(kstd::make_shared(device)); }); - }); - } -} // namespace kernel::filesystem::devfs \ No newline at end of file diff --git a/kernel/src/filesystem/devfs/devfs_root_inode.cpp b/kernel/src/filesystem/devfs/devfs_root_inode.cpp deleted file mode 100644 index a7308dc..0000000 --- a/kernel/src/filesystem/devfs/devfs_root_inode.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "kernel/filesystem/devfs/devfs_root_inode.hpp" - -#include "kernel/filesystem/inode.hpp" - -#include - -namespace kernel::filesystem::devfs -{ - devfs_root_inode::devfs_root_inode() - : inode(inode_kind::directory) - {} - - auto devfs_root_inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t - { - return 0; - } - - auto devfs_root_inode::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t - { - return 0; - } -} // namespace kernel::filesystem::devfs \ No newline at end of file diff --git a/kernel/src/filesystem/devfs/filesystem.cpp b/kernel/src/filesystem/devfs/filesystem.cpp new file mode 100644 index 0000000..e7d0e13 --- /dev/null +++ b/kernel/src/filesystem/devfs/filesystem.cpp @@ -0,0 +1,58 @@ +#include "kernel/filesystem/devfs/filesystem.hpp" + +#include "kernel/devices/device.hpp" +#include "kernel/devices/storage/storage_management.hpp" +#include "kernel/filesystem/devfs/inode.hpp" +#include "kernel/filesystem/device_inode.hpp" +#include "kernel/filesystem/inode.hpp" + +#include + +#include +#include + +namespace kernel::filesystem::devfs +{ + auto filesystem::mount(kstd::shared_ptr const &) -> int + { + m_root_inode = kstd::make_shared(); + build_device_inode_table(); + + return 0; + } + + auto filesystem::lookup(kstd::shared_ptr const & parent, std::string_view name) + -> kstd::shared_ptr + { + if (!parent || !parent->is_directory()) + { + return nullptr; + } + + if (parent.get() != m_root_inode.get()) + { + return nullptr; + } + + auto it = std::ranges::find_if(m_inodes, [&](auto const & dev_node) { + auto device_inode_ptr = static_cast(dev_node.get()); + if (!device_inode_ptr) + { + return false; + } + return device_inode_ptr->device()->name() == name; + }); + return (it != m_inodes.end()) ? *it : nullptr; + } + + auto filesystem::build_device_inode_table() -> void + { + m_inodes.clear(); + + auto storage_mgmt = devices::storage::storage_management::get(); + std::ranges::for_each(storage_mgmt.all_controllers(), [&](auto const & controller) { + std::ranges::for_each(controller->all_devices(), + [&](auto const & device) { m_inodes.push_back(kstd::make_shared(device)); }); + }); + } +} // namespace kernel::filesystem::devfs \ No newline at end of file diff --git a/kernel/src/filesystem/devfs/inode.cpp b/kernel/src/filesystem/devfs/inode.cpp new file mode 100644 index 0000000..52cf6fa --- /dev/null +++ b/kernel/src/filesystem/devfs/inode.cpp @@ -0,0 +1,22 @@ +#include "kernel/filesystem/devfs/inode.hpp" + +#include "kernel/filesystem/inode.hpp" + +#include + +namespace kernel::filesystem::devfs +{ + inode::inode() + : kernel::filesystem::inode(inode_kind::directory) + {} + + auto inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t + { + return 0; + } + + auto inode::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t + { + return 0; + } +} // namespace kernel::filesystem::devfs \ No newline at end of file diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 69740c3..fdad36c 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -4,7 +4,7 @@ #include "kernel/devices/storage/storage_management.hpp" #include "kernel/filesystem/dentry.hpp" -#include "kernel/filesystem/devfs/devfs_filesystem.hpp" +#include "kernel/filesystem/devfs/filesystem.hpp" #include "kernel/filesystem/ext2/filesystem.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/mount.hpp" @@ -52,7 +52,7 @@ namespace kernel::filesystem do_mount_internal("/", root_fs_root_dentry, boot_root_fs); } - auto device_fs = kstd::make_shared(); + auto device_fs = kstd::make_shared(); device_fs->mount(nullptr); do_mount_internal("/dev", root_fs_root_dentry, device_fs); } -- cgit v1.2.3 From 81ab0ba35d724dd465ed870e87047b3bf74cea13 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Mon, 30 Mar 2026 21:01:18 +0200 Subject: Rename rootfs filesystem files --- kernel/src/filesystem/rootfs/filesystem.cpp | 29 ++++++++++++++++ kernel/src/filesystem/rootfs/inode.cpp | 39 ++++++++++++++++++++++ kernel/src/filesystem/rootfs/rootfs_filesystem.cpp | 29 ---------------- kernel/src/filesystem/rootfs/rootfs_inode.cpp | 39 ---------------------- kernel/src/filesystem/vfs.cpp | 4 +-- 5 files changed, 70 insertions(+), 70 deletions(-) create mode 100644 kernel/src/filesystem/rootfs/filesystem.cpp create mode 100644 kernel/src/filesystem/rootfs/inode.cpp delete mode 100644 kernel/src/filesystem/rootfs/rootfs_filesystem.cpp delete mode 100644 kernel/src/filesystem/rootfs/rootfs_inode.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/rootfs/filesystem.cpp b/kernel/src/filesystem/rootfs/filesystem.cpp new file mode 100644 index 0000000..0133612 --- /dev/null +++ b/kernel/src/filesystem/rootfs/filesystem.cpp @@ -0,0 +1,29 @@ +#include "kernel/filesystem/rootfs/filesystem.hpp" + +#include "kernel/devices/device.hpp" +#include "kernel/filesystem/inode.hpp" +#include "kernel/filesystem/rootfs/inode.hpp" + +#include + +#include + +namespace kernel::filesystem::rootfs +{ + auto filesystem::mount(kstd::shared_ptr const &) -> int + { + auto rfs_inode = kstd::make_shared(); + rfs_inode->add_child("dev"); + m_root_inode = rfs_inode; + + return 0; + } + + auto filesystem::lookup(kstd::shared_ptr const & parent, std::string_view name) + -> kstd::shared_ptr + { + if (auto * rfs_inode = static_cast(parent.get())) + return rfs_inode->lookup_child(name); + return nullptr; + } +} // namespace kernel::filesystem::rootfs diff --git a/kernel/src/filesystem/rootfs/inode.cpp b/kernel/src/filesystem/rootfs/inode.cpp new file mode 100644 index 0000000..3ca9c02 --- /dev/null +++ b/kernel/src/filesystem/rootfs/inode.cpp @@ -0,0 +1,39 @@ +#include "kernel/filesystem/inode.hpp" + +#include "kernel/filesystem/rootfs/inode.hpp" + +#include +#include + +#include +#include +#include +#include + +namespace kernel::filesystem::rootfs +{ + inode::inode() + : kernel::filesystem::inode(inode_kind::directory) + {} + + auto inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t + { + return 0; + } + + auto inode::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t + { + return 0; + } + + auto inode::add_child(std::string_view name) -> void + { + m_children.push_back(std::make_pair(kstd::string{name}, kstd::make_shared())); + } + + auto inode::lookup_child(std::string_view name) -> kstd::shared_ptr + { + auto it = std::ranges::find_if(m_children, [&](auto const & pair) { return pair.first == name; }); + return (it != m_children.end()) ? it->second : nullptr; + } +} // namespace kernel::filesystem::rootfs diff --git a/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp b/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp deleted file mode 100644 index 804e211..0000000 --- a/kernel/src/filesystem/rootfs/rootfs_filesystem.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "kernel/filesystem/rootfs/rootfs_filesystem.hpp" - -#include "kernel/devices/device.hpp" -#include "kernel/filesystem/inode.hpp" -#include "kernel/filesystem/rootfs/rootfs_inode.hpp" - -#include - -#include - -namespace kernel::filesystem::rootfs -{ - auto rootfs_filesystem::mount(kstd::shared_ptr const &) -> int - { - auto rfs_inode = kstd::make_shared(); - rfs_inode->add_child("dev"); - m_root_inode = rfs_inode; - - return 0; - } - - auto rootfs_filesystem::lookup(kstd::shared_ptr const & parent, std::string_view name) - -> kstd::shared_ptr - { - if (auto * rfs_inode = static_cast(parent.get())) - return rfs_inode->lookup_child(name); - return nullptr; - } -} // namespace kernel::filesystem::rootfs diff --git a/kernel/src/filesystem/rootfs/rootfs_inode.cpp b/kernel/src/filesystem/rootfs/rootfs_inode.cpp deleted file mode 100644 index f44f06c..0000000 --- a/kernel/src/filesystem/rootfs/rootfs_inode.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "kernel/filesystem/rootfs/rootfs_inode.hpp" - -#include "kernel/filesystem/inode.hpp" - -#include -#include - -#include -#include -#include -#include - -namespace kernel::filesystem::rootfs -{ - rootfs_inode::rootfs_inode() - : inode(inode_kind::directory) - {} - - auto rootfs_inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t - { - return 0; - } - - auto rootfs_inode::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t - { - return 0; - } - - auto rootfs_inode::add_child(std::string_view name) -> void - { - m_children.push_back(std::make_pair(kstd::string{name}, kstd::make_shared())); - } - - auto rootfs_inode::lookup_child(std::string_view name) -> kstd::shared_ptr - { - auto it = std::ranges::find_if(m_children, [&](auto const & pair) { return pair.first == name; }); - return (it != m_children.end()) ? it->second : nullptr; - } -} // namespace kernel::filesystem::rootfs diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index fdad36c..bee68e6 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -9,7 +9,7 @@ #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/mount.hpp" #include "kernel/filesystem/open_file_description.hpp" -#include "kernel/filesystem/rootfs/rootfs_filesystem.hpp" +#include "kernel/filesystem/rootfs/filesystem.hpp" #include @@ -37,7 +37,7 @@ namespace kernel::filesystem auto vfs::init_internal() -> void { - auto root_fs = kstd::make_shared(); + auto root_fs = kstd::make_shared(); root_fs->mount(nullptr); auto root_fs_root_dentry = kstd::make_shared(nullptr, root_fs->root_inode()); -- cgit v1.2.3 From 846135ba5cdfa545124b97c74182f5eada9a403a Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Mon, 30 Mar 2026 21:20:25 +0200 Subject: Rename ram_disk and storage files --- kernel/src/devices/storage/controller.cpp | 44 +++++++++++ kernel/src/devices/storage/management.cpp | 85 ++++++++++++++++++++++ kernel/src/devices/storage/ram_disk/controller.cpp | 27 +++++++ kernel/src/devices/storage/ram_disk/device.cpp | 65 +++++++++++++++++ .../storage/ram_disk/ram_disk_controller.cpp | 27 ------- .../devices/storage/ram_disk/ram_disk_device.cpp | 66 ----------------- kernel/src/devices/storage/storage_controller.cpp | 44 ----------- kernel/src/devices/storage/storage_management.cpp | 85 ---------------------- kernel/src/filesystem/devfs/filesystem.cpp | 4 +- kernel/src/filesystem/vfs.cpp | 4 +- kernel/src/main.cpp | 10 +-- 11 files changed, 230 insertions(+), 231 deletions(-) create mode 100644 kernel/src/devices/storage/controller.cpp create mode 100644 kernel/src/devices/storage/management.cpp create mode 100644 kernel/src/devices/storage/ram_disk/controller.cpp create mode 100644 kernel/src/devices/storage/ram_disk/device.cpp delete mode 100644 kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp delete mode 100644 kernel/src/devices/storage/ram_disk/ram_disk_device.cpp delete mode 100644 kernel/src/devices/storage/storage_controller.cpp delete mode 100644 kernel/src/devices/storage/storage_management.cpp (limited to 'kernel/src') diff --git a/kernel/src/devices/storage/controller.cpp b/kernel/src/devices/storage/controller.cpp new file mode 100644 index 0000000..46c45e4 --- /dev/null +++ b/kernel/src/devices/storage/controller.cpp @@ -0,0 +1,44 @@ +#include "kernel/devices/storage/controller.hpp" + +#include "kernel/devices/device.hpp" + +#include +#include + +#include +#include + +namespace kernel::devices::storage +{ + auto controller::set_ids(size_t major, size_t minors_per_dev) -> void + { + m_major = major; + m_minors_per_device = minors_per_dev; + } + + auto controller::major() const -> size_t + { + return m_major; + } + + auto controller::device_by_minor(size_t minor) const -> kstd::shared_ptr + { + auto it = std::ranges::find_if(m_devices, [minor](auto const & device) { return device->minor() == minor; }); + + if (it != m_devices.end()) + { + return *it; + } + return nullptr; + } + + auto controller::devices_count() const -> size_t + { + return m_devices.size(); + } + + auto controller::all_devices() const -> kstd::vector> const & + { + return m_devices; + } +} // namespace kernel::devices::storage \ No newline at end of file diff --git a/kernel/src/devices/storage/management.cpp b/kernel/src/devices/storage/management.cpp new file mode 100644 index 0000000..62c0ce4 --- /dev/null +++ b/kernel/src/devices/storage/management.cpp @@ -0,0 +1,85 @@ +#include "kernel/devices/storage/management.hpp" + +#include "kapi/boot_modules.hpp" +#include "kapi/system.hpp" + +#include "kernel/devices/device.hpp" +#include "kernel/devices/storage/controller.hpp" +#include "kernel/devices/storage/ram_disk/controller.hpp" + +#include +#include + +#include +#include +#include + +namespace kernel::devices::storage +{ + namespace + { + constexpr size_t static MINORS_PER_DEVICE = 16; + constexpr size_t static START_MAJOR = 1; + constinit size_t static next_free_major = START_MAJOR; + + constinit auto static active_storage_management = std::optional{}; + } // namespace + + auto management::init() -> void + { + if (active_storage_management) + { + kapi::system::panic("[DEVICES] Storage management has already been initialized."); + } + active_storage_management.emplace(management{}); + + auto current_ram_disk_controller = + kstd::make_shared(&kapi::boot_modules::get_boot_module_registry()); + active_storage_management->add_controller(current_ram_disk_controller); + + std::ranges::for_each(active_storage_management->m_controllers, [](auto controller) { controller->probe(); }); + } + + auto management::get() -> management & + { + if (!active_storage_management) + { + kapi::system::panic("[DEVICES] Storage management has not been initialized."); + } + + return *active_storage_management; + } + + auto management::add_controller(kstd::shared_ptr const & controller) -> void + { + controller->set_ids(next_free_major++, MINORS_PER_DEVICE); + m_controllers.push_back(controller); + } + + auto management::all_controllers() const -> kstd::vector> const & + { + return m_controllers; + } + + auto management::device_by_major_minor(size_t major, size_t minor) -> kstd::shared_ptr + { + kstd::shared_ptr found = nullptr; + + std::ranges::find_if(m_controllers, [&](auto const & controller) { + if (controller != nullptr && controller->major() == major) + { + found = controller->device_by_minor(minor); + return found != nullptr; + } + return false; + }); + + return found; + } + + auto management::determine_boot_device() -> kstd::shared_ptr + { + return device_by_major_minor(START_MAJOR, 0); + } + +} // namespace kernel::devices::storage \ No newline at end of file diff --git a/kernel/src/devices/storage/ram_disk/controller.cpp b/kernel/src/devices/storage/ram_disk/controller.cpp new file mode 100644 index 0000000..040e61f --- /dev/null +++ b/kernel/src/devices/storage/ram_disk/controller.cpp @@ -0,0 +1,27 @@ +#include "kernel/devices/storage/ram_disk/controller.hpp" + +#include "kapi/boot_module/boot_module_registry.hpp" + +#include "kernel/devices/storage/ram_disk/device.hpp" + +#include + +#include +#include + +namespace kernel::devices::storage::ram_disk +{ + controller::controller(kapi::boot_modules::boot_module_registry const * registry) + : m_boot_module_registry(registry) + {} + + auto controller::probe() -> void + { + size_t current_device_index = 0; + + std::ranges::for_each(*m_boot_module_registry, [this, ¤t_device_index](auto const & module) { + auto const minor = current_device_index++ * m_minors_per_device; + m_devices.push_back(kstd::make_shared(module, m_major, minor)); + }); + } +} // namespace kernel::devices::storage::ram_disk \ No newline at end of file diff --git a/kernel/src/devices/storage/ram_disk/device.cpp b/kernel/src/devices/storage/ram_disk/device.cpp new file mode 100644 index 0000000..5116c93 --- /dev/null +++ b/kernel/src/devices/storage/ram_disk/device.cpp @@ -0,0 +1,65 @@ +#include "kapi/boot_module/boot_module.hpp" +#include "kapi/system.hpp" + +#include "kernel/devices/block_device.hpp" +#include "kernel/devices/storage/ram_disk/device.hpp" + +#include +#include + +#include + +namespace kernel::devices::storage::ram_disk +{ + namespace + { + constexpr size_t RAM_DISK_BLOCK_SIZE = 512uz; + } // namespace + + device::device(kapi::boot_modules::boot_module const & module, size_t major, size_t minor) + : block_device(major, minor, "ram" + kstd::to_string(minor), RAM_DISK_BLOCK_SIZE) + , m_boot_module(module) + {} + + auto device::read_block(size_t block_index, void * buffer) const -> void + { + if (buffer == nullptr) + { + kapi::system::panic("[RAM DISK DEVICE] read_block called with null buffer."); + } + + auto const info = calculate_transfer(block_index); + + if (info.to_transfer > 0) + { + auto const src = static_cast(m_boot_module.start_address) + info.offset; + kstd::libc::memcpy(buffer, src, info.to_transfer); + } + + if (info.remainder > 0) + { + kstd::libc::memset(static_cast(buffer) + info.to_transfer, 0, info.remainder); + } + } + + auto device::write_block(size_t block_index, void const * buffer) -> void + { + if (buffer == nullptr) + { + kapi::system::panic("[RAM DISK DEVICE] write_block called with null buffer."); + } + + auto const info = calculate_transfer(block_index); + + if (info.to_transfer > 0) + { + auto const dest = static_cast(m_boot_module.start_address) + info.offset; + kstd::libc::memcpy(dest, buffer, info.to_transfer); + } + } + + auto device::size() const -> size_t + { + return m_boot_module.size; + } +} // namespace kernel::devices::storage::ram_disk \ No newline at end of file diff --git a/kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp b/kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp deleted file mode 100644 index 26eb10b..0000000 --- a/kernel/src/devices/storage/ram_disk/ram_disk_controller.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "kernel/devices/storage/ram_disk/ram_disk_controller.hpp" - -#include "kapi/boot_module/boot_module_registry.hpp" - -#include "kernel/devices/storage/ram_disk/ram_disk_device.hpp" - -#include - -#include -#include - -namespace kernel::devices::storage::ram_disk -{ - ram_disk_controller::ram_disk_controller(kapi::boot_modules::boot_module_registry const * registry) - : m_boot_module_registry(registry) - {} - - auto ram_disk_controller::probe() -> void - { - size_t current_device_index = 0; - - std::ranges::for_each(*m_boot_module_registry, [this, ¤t_device_index](auto const & module) { - auto const minor = current_device_index++ * m_minors_per_device; - m_devices.push_back(kstd::make_shared(module, m_major, minor)); - }); - } -} // namespace kernel::devices::storage::ram_disk \ No newline at end of file diff --git a/kernel/src/devices/storage/ram_disk/ram_disk_device.cpp b/kernel/src/devices/storage/ram_disk/ram_disk_device.cpp deleted file mode 100644 index 72e8025..0000000 --- a/kernel/src/devices/storage/ram_disk/ram_disk_device.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "kernel/devices/storage/ram_disk/ram_disk_device.hpp" - -#include "kapi/boot_module/boot_module.hpp" -#include "kapi/system.hpp" - -#include "kernel/devices/block_device.hpp" - -#include -#include - -#include - -namespace kernel::devices::storage::ram_disk -{ - namespace - { - constexpr size_t RAM_DISK_BLOCK_SIZE = 512uz; - } // namespace - - ram_disk_device::ram_disk_device(kapi::boot_modules::boot_module const & module, size_t major, size_t minor) - : block_device(major, minor, "ram" + kstd::to_string(minor), RAM_DISK_BLOCK_SIZE) - , m_boot_module(module) - {} - - auto ram_disk_device::read_block(size_t block_index, void * buffer) const -> void - { - if (buffer == nullptr) - { - kapi::system::panic("[RAM DISK DEVICE] read_block called with null buffer."); - } - - auto const info = calculate_transfer(block_index); - - if (info.to_transfer > 0) - { - auto const src = static_cast(m_boot_module.start_address) + info.offset; - kstd::libc::memcpy(buffer, src, info.to_transfer); - } - - if (info.remainder > 0) - { - kstd::libc::memset(static_cast(buffer) + info.to_transfer, 0, info.remainder); - } - } - - auto ram_disk_device::write_block(size_t block_index, void const * buffer) -> void - { - if (buffer == nullptr) - { - kapi::system::panic("[RAM DISK DEVICE] write_block called with null buffer."); - } - - auto const info = calculate_transfer(block_index); - - if (info.to_transfer > 0) - { - auto const dest = static_cast(m_boot_module.start_address) + info.offset; - kstd::libc::memcpy(dest, buffer, info.to_transfer); - } - } - - auto ram_disk_device::size() const -> size_t - { - return m_boot_module.size; - } -} // namespace kernel::devices::storage::ram_disk \ No newline at end of file diff --git a/kernel/src/devices/storage/storage_controller.cpp b/kernel/src/devices/storage/storage_controller.cpp deleted file mode 100644 index 3d13b66..0000000 --- a/kernel/src/devices/storage/storage_controller.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "kernel/devices/storage/storage_controller.hpp" - -#include "kernel/devices/device.hpp" - -#include -#include - -#include -#include - -namespace kernel::devices::storage -{ - auto storage_controller::set_ids(size_t major, size_t minors_per_dev) -> void - { - m_major = major; - m_minors_per_device = minors_per_dev; - } - - auto storage_controller::major() const -> size_t - { - return m_major; - } - - auto storage_controller::device_by_minor(size_t minor) const -> kstd::shared_ptr - { - auto it = std::ranges::find_if(m_devices, [minor](auto const & device) { return device->minor() == minor; }); - - if (it != m_devices.end()) - { - return *it; - } - return nullptr; - } - - auto storage_controller::devices_count() const -> size_t - { - return m_devices.size(); - } - - auto storage_controller::all_devices() const -> kstd::vector> const & - { - return m_devices; - } -} // namespace kernel::devices::storage \ No newline at end of file diff --git a/kernel/src/devices/storage/storage_management.cpp b/kernel/src/devices/storage/storage_management.cpp deleted file mode 100644 index 2bc57c4..0000000 --- a/kernel/src/devices/storage/storage_management.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "kernel/devices/storage/storage_management.hpp" - -#include "kapi/boot_modules.hpp" -#include "kapi/system.hpp" - -#include "kernel/devices/device.hpp" -#include "kernel/devices/storage/ram_disk/ram_disk_controller.hpp" -#include "kernel/devices/storage/storage_controller.hpp" - -#include -#include - -#include -#include -#include - -namespace kernel::devices::storage -{ - namespace - { - constexpr size_t static MINORS_PER_DEVICE = 16; - constexpr size_t static START_MAJOR = 1; - constinit size_t static next_free_major = START_MAJOR; - - constinit auto static active_storage_management = std::optional{}; - } // namespace - - auto storage_management::init() -> void - { - if (active_storage_management) - { - kapi::system::panic("[DEVICES] Storage management has already been initialized."); - } - active_storage_management.emplace(storage_management{}); - - auto current_ram_disk_controller = - kstd::make_shared(&kapi::boot_modules::get_boot_module_registry()); - active_storage_management->add_controller(current_ram_disk_controller); - - std::ranges::for_each(active_storage_management->m_controllers, [](auto controller) { controller->probe(); }); - } - - auto storage_management::get() -> storage_management & - { - if (!active_storage_management) - { - kapi::system::panic("[DEVICES] Storage management has not been initialized."); - } - - return *active_storage_management; - } - - auto storage_management::add_controller(kstd::shared_ptr const & controller) -> void - { - controller->set_ids(next_free_major++, MINORS_PER_DEVICE); - m_controllers.push_back(controller); - } - - auto storage_management::all_controllers() const -> kstd::vector> const & - { - return m_controllers; - } - - auto storage_management::device_by_major_minor(size_t major, size_t minor) -> kstd::shared_ptr - { - kstd::shared_ptr found = nullptr; - - std::ranges::find_if(m_controllers, [&](auto const & controller) { - if (controller != nullptr && controller->major() == major) - { - found = controller->device_by_minor(minor); - return found != nullptr; - } - return false; - }); - - return found; - } - - auto storage_management::determine_boot_device() -> kstd::shared_ptr - { - return device_by_major_minor(START_MAJOR, 0); - } - -} // namespace kernel::devices::storage \ No newline at end of file diff --git a/kernel/src/filesystem/devfs/filesystem.cpp b/kernel/src/filesystem/devfs/filesystem.cpp index e7d0e13..94c9b05 100644 --- a/kernel/src/filesystem/devfs/filesystem.cpp +++ b/kernel/src/filesystem/devfs/filesystem.cpp @@ -1,7 +1,7 @@ #include "kernel/filesystem/devfs/filesystem.hpp" #include "kernel/devices/device.hpp" -#include "kernel/devices/storage/storage_management.hpp" +#include "kernel/devices/storage/management.hpp" #include "kernel/filesystem/devfs/inode.hpp" #include "kernel/filesystem/device_inode.hpp" #include "kernel/filesystem/inode.hpp" @@ -49,7 +49,7 @@ namespace kernel::filesystem::devfs { m_inodes.clear(); - auto storage_mgmt = devices::storage::storage_management::get(); + auto storage_mgmt = devices::storage::management::get(); std::ranges::for_each(storage_mgmt.all_controllers(), [&](auto const & controller) { std::ranges::for_each(controller->all_devices(), [&](auto const & device) { m_inodes.push_back(kstd::make_shared(device)); }); diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index bee68e6..06214d2 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -2,7 +2,7 @@ #include "kapi/system.hpp" -#include "kernel/devices/storage/storage_management.hpp" +#include "kernel/devices/storage/management.hpp" #include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/devfs/filesystem.hpp" #include "kernel/filesystem/ext2/filesystem.hpp" @@ -43,7 +43,7 @@ namespace kernel::filesystem auto root_fs_root_dentry = kstd::make_shared(nullptr, root_fs->root_inode()); m_mount_table.add_mount(kstd::make_shared(nullptr, root_fs_root_dentry, root_fs, "")); - auto storage_mgmt = devices::storage::storage_management::get(); + auto storage_mgmt = devices::storage::management::get(); if (auto boot_device = storage_mgmt.determine_boot_device()) { // TODO BA-FS26 detect fs type from boot device and load corresponding fs, for now just assume ext2 diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index ff73985..37b4c5b 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -5,7 +5,7 @@ #include "kapi/memory.hpp" #include "kapi/system.hpp" -#include "kernel/devices/storage/storage_management.hpp" +#include "kernel/devices/storage/management.hpp" #include "kernel/filesystem/device_inode.hpp" #include "kernel/filesystem/ext2/filesystem.hpp" #include "kernel/filesystem/file_descriptor_table.hpp" @@ -24,7 +24,7 @@ auto test_device_names() -> void { - auto storage_mgmt = kernel::devices::storage::storage_management::get(); + auto storage_mgmt = kernel::devices::storage::management::get(); std::ranges::for_each(storage_mgmt.all_controllers(), [](auto const & controller) { std::ranges::for_each(controller->all_devices(), [](auto const & device) { kstd::println("{}", device->name().view()); }); @@ -35,7 +35,7 @@ auto test_file_description_manually() -> void { // setup auto fd_table = kernel::filesystem::file_descriptor_table::get(); - auto storage_mgmt = kernel::devices::storage::storage_management::get(); + auto storage_mgmt = kernel::devices::storage::management::get(); auto device = storage_mgmt.device_by_major_minor(1, 0); auto dev_node = kstd::make_shared(device); @@ -111,7 +111,7 @@ auto test_file_lookup() -> void // TODO BA-FS26 implement a more complete test with multiple files and directories and mounts etc. auto vfs = kernel::filesystem::vfs::get(); - auto storage_mgmt = kernel::devices::storage::storage_management::get(); + auto storage_mgmt = kernel::devices::storage::management::get(); auto ofd1 = vfs.open("/a/b/c"); auto ofd2 = vfs.open("/dev/ram0"); @@ -182,7 +182,7 @@ auto main() -> int kapi::boot_modules::init(); kstd::println("[OS] Boot module registry initialized."); - kernel::devices::storage::storage_management::init(); + kernel::devices::storage::management::init(); kstd::println("[OS] Storage management initialized."); kernel::filesystem::file_descriptor_table::init(); -- cgit v1.2.3 From 9e85f9d1f34d08213a918d9c1b0845c179e323af Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 31 Mar 2026 08:56:17 +0200 Subject: move device into kapi --- kernel/src/devices/block_device.cpp | 4 ++-- kernel/src/devices/block_device_utils.cpp | 8 +++---- kernel/src/devices/device.cpp | 29 -------------------------- kernel/src/devices/storage/controller.cpp | 6 +++--- kernel/src/devices/storage/management.cpp | 8 +++---- kernel/src/devices/storage/ram_disk/device.cpp | 8 ++++++- kernel/src/filesystem/devfs/filesystem.cpp | 4 ++-- kernel/src/filesystem/device_inode.cpp | 6 +++--- kernel/src/filesystem/ext2/filesystem.cpp | 4 ++-- kernel/src/filesystem/filesystem.cpp | 4 ++-- kernel/src/filesystem/rootfs/filesystem.cpp | 4 ++-- 11 files changed, 31 insertions(+), 54 deletions(-) delete mode 100644 kernel/src/devices/device.cpp (limited to 'kernel/src') diff --git a/kernel/src/devices/block_device.cpp b/kernel/src/devices/block_device.cpp index cfe2eb2..c006198 100644 --- a/kernel/src/devices/block_device.cpp +++ b/kernel/src/devices/block_device.cpp @@ -2,7 +2,7 @@ #include "kapi/system.hpp" -#include "kernel/devices/device.hpp" +#include "kapi/devices/device.hpp" #include @@ -11,7 +11,7 @@ namespace kernel::devices { block_device::block_device(size_t major, size_t minor, kstd::string const & name, size_t block_size) - : device(major, minor, name) + : kapi::devices::device(major, minor, name) , m_block_size(block_size) { if (m_block_size == 0) diff --git a/kernel/src/devices/block_device_utils.cpp b/kernel/src/devices/block_device_utils.cpp index 5469087..6fe89fe 100644 --- a/kernel/src/devices/block_device_utils.cpp +++ b/kernel/src/devices/block_device_utils.cpp @@ -3,7 +3,7 @@ #include "kapi/system.hpp" #include "kernel/devices/block_device.hpp" -#include "kernel/devices/device.hpp" +#include "kapi/devices/device.hpp" #include #include @@ -18,7 +18,7 @@ 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); - auto process_blocks(kstd::shared_ptr const & device, size_t offset, size_t size, void * buffer, + auto process_blocks(kstd::shared_ptr const & device, size_t offset, size_t size, void * buffer, block_op op) -> size_t { if (buffer == nullptr) @@ -62,7 +62,7 @@ namespace kernel::devices::block_device_utils return processed; } - auto read(kstd::shared_ptr const & device, void * buffer, size_t offset, size_t size) -> size_t + auto read(kstd::shared_ptr const & device, void * buffer, size_t offset, size_t size) -> size_t { return process_blocks(device, offset, size, buffer, [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, @@ -80,7 +80,7 @@ namespace kernel::devices::block_device_utils }); } - auto write(kstd::shared_ptr const & device, void const * buffer, size_t offset, size_t size) + auto write(kstd::shared_ptr const & device, void const * buffer, size_t offset, size_t size) -> size_t { return process_blocks(device, offset, size, const_cast(buffer), diff --git a/kernel/src/devices/device.cpp b/kernel/src/devices/device.cpp deleted file mode 100644 index 1e7589e..0000000 --- a/kernel/src/devices/device.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "kernel/devices/device.hpp" - -#include - -#include - -namespace kernel::devices -{ - device::device(size_t major, size_t minor, kstd::string const & name) - : m_major(major) - , m_minor(minor) - , m_name(name) - {} - - auto device::major() const -> size_t - { - return m_major; - } - - auto device::minor() const -> size_t - { - return m_minor; - } - - auto device::name() const -> kstd::string const & - { - return m_name; - } -} // namespace kernel::devices \ No newline at end of file diff --git a/kernel/src/devices/storage/controller.cpp b/kernel/src/devices/storage/controller.cpp index 46c45e4..1bef670 100644 --- a/kernel/src/devices/storage/controller.cpp +++ b/kernel/src/devices/storage/controller.cpp @@ -1,6 +1,6 @@ #include "kernel/devices/storage/controller.hpp" -#include "kernel/devices/device.hpp" +#include "kapi/devices/device.hpp" #include #include @@ -21,7 +21,7 @@ namespace kernel::devices::storage return m_major; } - auto controller::device_by_minor(size_t minor) const -> kstd::shared_ptr + auto controller::device_by_minor(size_t minor) const -> kstd::shared_ptr { auto it = std::ranges::find_if(m_devices, [minor](auto const & device) { return device->minor() == minor; }); @@ -37,7 +37,7 @@ namespace kernel::devices::storage return m_devices.size(); } - auto controller::all_devices() const -> kstd::vector> const & + auto controller::all_devices() const -> kstd::vector> const & { return m_devices; } diff --git a/kernel/src/devices/storage/management.cpp b/kernel/src/devices/storage/management.cpp index 62c0ce4..d440bf0 100644 --- a/kernel/src/devices/storage/management.cpp +++ b/kernel/src/devices/storage/management.cpp @@ -3,7 +3,7 @@ #include "kapi/boot_modules.hpp" #include "kapi/system.hpp" -#include "kernel/devices/device.hpp" +#include "kapi/devices/device.hpp" #include "kernel/devices/storage/controller.hpp" #include "kernel/devices/storage/ram_disk/controller.hpp" @@ -61,9 +61,9 @@ namespace kernel::devices::storage return m_controllers; } - auto management::device_by_major_minor(size_t major, size_t minor) -> kstd::shared_ptr + auto management::device_by_major_minor(size_t major, size_t minor) -> kstd::shared_ptr { - kstd::shared_ptr found = nullptr; + kstd::shared_ptr found = nullptr; std::ranges::find_if(m_controllers, [&](auto const & controller) { if (controller != nullptr && controller->major() == major) @@ -77,7 +77,7 @@ namespace kernel::devices::storage return found; } - auto management::determine_boot_device() -> kstd::shared_ptr + auto management::determine_boot_device() -> kstd::shared_ptr { return device_by_major_minor(START_MAJOR, 0); } diff --git a/kernel/src/devices/storage/ram_disk/device.cpp b/kernel/src/devices/storage/ram_disk/device.cpp index 5116c93..8fc3b2a 100644 --- a/kernel/src/devices/storage/ram_disk/device.cpp +++ b/kernel/src/devices/storage/ram_disk/device.cpp @@ -1,8 +1,9 @@ +#include "kernel/devices/storage/ram_disk/device.hpp" + #include "kapi/boot_module/boot_module.hpp" #include "kapi/system.hpp" #include "kernel/devices/block_device.hpp" -#include "kernel/devices/storage/ram_disk/device.hpp" #include #include @@ -21,6 +22,11 @@ namespace kernel::devices::storage::ram_disk , m_boot_module(module) {} + auto device::init() -> bool + { + 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 { if (buffer == nullptr) diff --git a/kernel/src/filesystem/devfs/filesystem.cpp b/kernel/src/filesystem/devfs/filesystem.cpp index 94c9b05..9043ac5 100644 --- a/kernel/src/filesystem/devfs/filesystem.cpp +++ b/kernel/src/filesystem/devfs/filesystem.cpp @@ -1,6 +1,6 @@ #include "kernel/filesystem/devfs/filesystem.hpp" -#include "kernel/devices/device.hpp" +#include "kapi/devices/device.hpp" #include "kernel/devices/storage/management.hpp" #include "kernel/filesystem/devfs/inode.hpp" #include "kernel/filesystem/device_inode.hpp" @@ -13,7 +13,7 @@ namespace kernel::filesystem::devfs { - auto filesystem::mount(kstd::shared_ptr const &) -> int + auto filesystem::mount(kstd::shared_ptr const &) -> int { m_root_inode = kstd::make_shared(); build_device_inode_table(); diff --git a/kernel/src/filesystem/device_inode.cpp b/kernel/src/filesystem/device_inode.cpp index d574d8f..af8cecc 100644 --- a/kernel/src/filesystem/device_inode.cpp +++ b/kernel/src/filesystem/device_inode.cpp @@ -3,7 +3,7 @@ #include "kapi/system.hpp" #include "kernel/devices/block_device_utils.hpp" -#include "kernel/devices/device.hpp" +#include "kapi/devices/device.hpp" #include "kernel/filesystem/inode.hpp" #include @@ -14,7 +14,7 @@ namespace kernel::filesystem { - device_inode::device_inode(kstd::shared_ptr const & device) + device_inode::device_inode(kstd::shared_ptr const & device) : inode(inode_kind::device) , m_device(device) { @@ -48,7 +48,7 @@ namespace kernel::filesystem } } - auto device_inode::device() const -> kstd::shared_ptr const & + auto device_inode::device() const -> kstd::shared_ptr const & { return m_device; } diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index d951158..eb9edc4 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -1,7 +1,7 @@ #include "kernel/filesystem/ext2/filesystem.hpp" #include "kernel/devices/block_device_utils.hpp" -#include "kernel/devices/device.hpp" +#include "kapi/devices/device.hpp" #include "kernel/filesystem/ext2/inode.hpp" #include "kernel/filesystem/ext2/superblock.hpp" #include "kernel/filesystem/filesystem.hpp" @@ -45,7 +45,7 @@ namespace kernel::filesystem::ext2 // } } // namespace - auto filesystem::mount(kstd::shared_ptr const & device) -> int + auto filesystem::mount(kstd::shared_ptr const & device) -> int { kernel::filesystem::filesystem::mount(device); // TODO BA-FS26 error handling? // TODO BA-FS26 load proper root inode from ext2 metadata diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index c891d00..0ac9cf8 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -1,13 +1,13 @@ #include "kernel/filesystem/filesystem.hpp" -#include "kernel/devices/device.hpp" +#include "kapi/devices/device.hpp" #include "kernel/filesystem/inode.hpp" #include namespace kernel::filesystem { - auto filesystem::mount(kstd::shared_ptr const & device) -> int + auto filesystem::mount(kstd::shared_ptr const & device) -> int { if (!device) { diff --git a/kernel/src/filesystem/rootfs/filesystem.cpp b/kernel/src/filesystem/rootfs/filesystem.cpp index 0133612..37bf588 100644 --- a/kernel/src/filesystem/rootfs/filesystem.cpp +++ b/kernel/src/filesystem/rootfs/filesystem.cpp @@ -1,6 +1,6 @@ #include "kernel/filesystem/rootfs/filesystem.hpp" -#include "kernel/devices/device.hpp" +#include "kapi/devices/device.hpp" #include "kernel/filesystem/inode.hpp" #include "kernel/filesystem/rootfs/inode.hpp" @@ -10,7 +10,7 @@ namespace kernel::filesystem::rootfs { - auto filesystem::mount(kstd::shared_ptr const &) -> int + auto filesystem::mount(kstd::shared_ptr const &) -> int { auto rfs_inode = kstd::make_shared(); rfs_inode->add_child("dev"); -- cgit v1.2.3 From 1f652b8b5ca5dbea588975466801cb1479f3dda8 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 1 Apr 2026 12:15:25 +0200 Subject: kernel/tests: dissolve tests into source tree --- kernel/src/main.tests.cpp | 38 ++++++++++++ kernel/src/test_support/kapi/cio.cpp | 38 ++++++++++++ kernel/src/test_support/kapi/cpu.cpp | 29 ++++++++++ kernel/src/test_support/kapi/interrupts.cpp | 11 ++++ kernel/src/test_support/kapi/memory.cpp | 86 ++++++++++++++++++++++++++++ kernel/src/test_support/log_buffer.cpp | 39 +++++++++++++ kernel/src/test_support/simulated_memory.cpp | 33 +++++++++++ 7 files changed, 274 insertions(+) create mode 100644 kernel/src/main.tests.cpp create mode 100644 kernel/src/test_support/kapi/cio.cpp create mode 100644 kernel/src/test_support/kapi/cpu.cpp create mode 100644 kernel/src/test_support/kapi/interrupts.cpp create mode 100644 kernel/src/test_support/kapi/memory.cpp create mode 100644 kernel/src/test_support/log_buffer.cpp create mode 100644 kernel/src/test_support/simulated_memory.cpp (limited to 'kernel/src') diff --git a/kernel/src/main.tests.cpp b/kernel/src/main.tests.cpp new file mode 100644 index 0000000..b3ae142 --- /dev/null +++ b/kernel/src/main.tests.cpp @@ -0,0 +1,38 @@ +#include "kapi/interrupts.hpp" +#include "kapi/memory.hpp" +#include +#include + +#include + +auto main(int argc, char ** argv) -> int +{ + auto session = Catch::Session{}; + + if (auto result = session.applyCommandLine(argc, argv); result != 0) + { + return result; + } + + auto const & config = session.configData(); + auto skip_init = config.listTests || // + config.listTags || // + config.listReporters || // + config.listListeners || // + config.showHelp; + + if (!skip_init) + { + kapi::cio::init(); + kapi::cpu::init(); + kapi::interrupts::enable(); + + kapi::memory::init(); + // note: no kernel heap is created, since we are in the test environment. Nonetheless, we still initialize the + // memory subsystem, so that components that rely on it can be tested. No component must ever rely on the heap + // allocator directly, rather they have to go through the new and delete. However, some components may use the frame + // allocator and page mapper in order to perform their tasks. + } + + return session.run(); +} diff --git a/kernel/src/test_support/kapi/cio.cpp b/kernel/src/test_support/kapi/cio.cpp new file mode 100644 index 0000000..6359fa8 --- /dev/null +++ b/kernel/src/test_support/kapi/cio.cpp @@ -0,0 +1,38 @@ +#include + +#include "kernel/tests/log_buffer.hpp" + +#include +#include +#include + +namespace kapi::cio +{ + + namespace + { + + class test_output_device : public output_device + { + public: + test_output_device() = default; + + auto write(output_stream stream, std::string_view text) -> void override + { + auto & standard_stream = stream == output_stream::stdout ? std::cout : std::cerr; + standard_stream << text; + if (text != "\n") + { + kernel::tests::log_buffer::append(std::string{text}); + } + } + } device{}; + + } // namespace + + auto init() -> void + { + set_output_device(device); + } + +} // namespace kapi::cio \ No newline at end of file diff --git a/kernel/src/test_support/kapi/cpu.cpp b/kernel/src/test_support/kapi/cpu.cpp new file mode 100644 index 0000000..3ecaadc --- /dev/null +++ b/kernel/src/test_support/kapi/cpu.cpp @@ -0,0 +1,29 @@ +#include "kernel/tests/cpu.hpp" + +#include + +#include +#include + +namespace kapi::cpu +{ + + auto init() -> void + { + auto static initialized = std::atomic_flag{}; + if (initialized.test_and_set()) + { + throw std::logic_error("kapi::cpu::init() called more than once"); + } + + // TODO: make sure that simulated interrupt can run. + + return; + } + + auto halt() -> void + { + throw kernel::tests::cpu::halt{}; + } + +} // namespace kapi::cpu \ No newline at end of file diff --git a/kernel/src/test_support/kapi/interrupts.cpp b/kernel/src/test_support/kapi/interrupts.cpp new file mode 100644 index 0000000..0077266 --- /dev/null +++ b/kernel/src/test_support/kapi/interrupts.cpp @@ -0,0 +1,11 @@ +#include + +namespace kapi::interrupts +{ + + auto enable() -> void + { + // TODO: enable simulated interrupts. + } + +} // namespace kapi::interrupts \ No newline at end of file diff --git a/kernel/src/test_support/kapi/memory.cpp b/kernel/src/test_support/kapi/memory.cpp new file mode 100644 index 0000000..6de2f60 --- /dev/null +++ b/kernel/src/test_support/kapi/memory.cpp @@ -0,0 +1,86 @@ +#include "kapi/memory.hpp" + +#include + +#include "kernel/tests/simulated_memory.hpp" + +#include +#include + +#include +#include +#include +#include + +namespace kapi::memory +{ + + namespace + { + //! The size of the simulated RAM. + constexpr auto simulate_memory_size = kstd::units::MiB(32); + + struct test_boostrap_frame_allocator : frame_allocator + { + auto mark_used(frame) -> void override {} + + auto allocate_many(std::size_t count) noexcept -> std::optional> override + { + auto start = next_free_frame; + next_free_frame += count; + return std::pair{frame{start}, count}; + } + + auto release_many(std::pair) -> void override {} + + std::size_t next_free_frame{}; + } boostrap_allocator; + + struct test_page_mapper : page_mapper + { + auto map(page page, frame frame, flags flags) -> std::byte * override + { + kstd::println("mapping page {} onto frame {} with flags {}", page.number(), frame.number(), + static_cast(flags)); + + if ((page.start_address() & pmm_metadata_base.raw()) == pmm_metadata_base.raw()) + { + auto offset = page.start_address() & ~pmm_metadata_base.raw(); + return kernel::tests::simulated_memory::pmm_metadata_base() + offset; + } + + return nullptr; + } + + auto unmap(page page) -> void override + { + kstd::println("unmapping page {}", page.number()); + } + + auto try_unmap(page page) noexcept -> bool override + { + kstd::println("trying to unmap page {}", page.number()); + return false; + } + } test_mapper; + + auto handoff_to_kernel_pmm(frame_allocator & new_allocator) -> void + { + for (auto i = 0uz; i < boostrap_allocator.next_free_frame; ++i) + { + new_allocator.mark_used(frame{i}); + } + } + + } // namespace + + auto init() -> void + { + kernel::tests::simulated_memory::init(simulate_memory_size); + set_frame_allocator(boostrap_allocator); + set_page_mapper(test_mapper); + + init_pmm(simulate_memory_size / frame::size, handoff_to_kernel_pmm); + } + +} // namespace kapi::memory \ No newline at end of file diff --git a/kernel/src/test_support/log_buffer.cpp b/kernel/src/test_support/log_buffer.cpp new file mode 100644 index 0000000..9e30afb --- /dev/null +++ b/kernel/src/test_support/log_buffer.cpp @@ -0,0 +1,39 @@ +#include "kernel/tests/log_buffer.hpp" + +#include +#include +#include + +namespace kernel::tests::log_buffer +{ + + namespace + { + std::vector recorded_messages{}; + } + + auto append(std::string const & message) -> void + { + recorded_messages.push_back(message); + } + + auto clear() -> void + { + recorded_messages.clear(); + } + + auto flat_messages() -> std::string + { + return std::ranges::fold_left(recorded_messages, std::string{}, + [](std::string accumulator, std::string const & message) { + accumulator += message; + return accumulator; + }); + } + + auto messages() -> std::vector const & + { + return recorded_messages; + } + +} // namespace kernel::tests::log_buffer diff --git a/kernel/src/test_support/simulated_memory.cpp b/kernel/src/test_support/simulated_memory.cpp new file mode 100644 index 0000000..9a9b354 --- /dev/null +++ b/kernel/src/test_support/simulated_memory.cpp @@ -0,0 +1,33 @@ +#include "kernel/tests/simulated_memory.hpp" + +#include + +#include +#include + +namespace kernel::tests::simulated_memory +{ + + namespace + { + auto constinit ram_storage = std::vector{}; + auto constinit pmm_storage = std::vector{}; + } // namespace + + auto init(kstd::units::bytes size) -> void + { + ram_storage.resize(size / kstd::units::bytes{1}); + pmm_storage.resize(size / kstd::units::bytes{1}); + } + + auto pmm_metadata_base() -> std::byte * + { + return pmm_storage.data(); + } + + auto ram_base() -> std::byte * + { + return ram_storage.data(); + } + +} // namespace kernel::tests::simulated_memory \ No newline at end of file -- cgit v1.2.3 From 790ffa870dee2c14cd45f669c0eb3e95c15fd1b6 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 1 Apr 2026 13:31:20 +0200 Subject: kernel: add bitmap_allocator tests --- kernel/src/memory/bitmap_allocator.cpp | 20 +- kernel/src/memory/bitmap_allocator.tests.cpp | 289 +++++++++++++++++++++++++++ kernel/src/test_support/kapi/memory.cpp | 8 +- 3 files changed, 306 insertions(+), 11 deletions(-) create mode 100644 kernel/src/memory/bitmap_allocator.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/memory/bitmap_allocator.cpp b/kernel/src/memory/bitmap_allocator.cpp index c010f77..caaf5a4 100644 --- a/kernel/src/memory/bitmap_allocator.cpp +++ b/kernel/src/memory/bitmap_allocator.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -17,7 +18,9 @@ namespace kernel::memory , m_frame_count{frame_count} , m_last_index{} { - std::ranges::fill(m_bitmap, ~0uz); + constexpr auto bits_per_word = 64uz; + auto to_fill = (frame_count + bits_per_word - 1) / bits_per_word; + std::ranges::fill(std::views::take(m_bitmap, to_fill), ~0uz); } auto bitmap_frame_allocator::allocate_many(std::size_t count) noexcept @@ -78,22 +81,25 @@ namespace kernel::memory auto bitmap_frame_allocator::test(std::size_t index) const noexcept -> bool { - auto entry_entry = index / 64; - auto entry_offset = index % 64; + constexpr auto bits_per_word = 64uz; + auto entry_entry = index / bits_per_word; + auto entry_offset = index % bits_per_word; return (m_bitmap[entry_entry] & (1uz << entry_offset)); } auto bitmap_frame_allocator::set(std::size_t index) noexcept -> void { - auto entry_entry = index / 64; - auto entry_offset = index % 64; + constexpr auto bits_per_word = 64uz; + auto entry_entry = index / bits_per_word; + auto entry_offset = index % bits_per_word; m_bitmap[entry_entry] |= (1uz << entry_offset); } auto bitmap_frame_allocator::clear(std::size_t index) noexcept -> void { - auto entry_entry = index / 64; - auto entry_offset = index % 64; + constexpr auto bits_per_word = 64uz; + auto entry_entry = index / bits_per_word; + auto entry_offset = index % bits_per_word; m_bitmap[entry_entry] &= ~(1uz << entry_offset); } diff --git a/kernel/src/memory/bitmap_allocator.tests.cpp b/kernel/src/memory/bitmap_allocator.tests.cpp new file mode 100644 index 0000000..56ec0a4 --- /dev/null +++ b/kernel/src/memory/bitmap_allocator.tests.cpp @@ -0,0 +1,289 @@ +#include "kernel/memory/bitmap_allocator.hpp" + +#include "kapi/memory.hpp" + +#include "catch2/matchers/catch_matchers.hpp" +#include "catch2/matchers/catch_matchers_range_equals.hpp" + +#include + +#include +#include +#include +#include +#include + +constexpr auto all_bits_set = std::numeric_limits::max(); +constexpr auto available_frames = 1024uz; + +SCENARIO("Bitmap allocator construction and initialization", "[memory][bitmap_allocator]") +{ + GIVEN("A storage region") + { + auto storage = std::vector(available_frames / 64, 0uz); + + WHEN("constructing the allocator with 0 frames") + { + auto allocator = kernel::memory::bitmap_frame_allocator{std::span(storage), 0}; + + THEN("the storage region is not modified") + { + REQUIRE_THAT(storage, Catch::Matchers::RangeEquals(std::vector(16, 0uz))); + } + } + + WHEN("constructing with 1 frame") + { + auto allocator = kernel::memory::bitmap_frame_allocator{std::span(storage), 1}; + + THEN("the first word of the storage region is set to all ones") + { + REQUIRE_THAT(std::views::take(storage, 1), Catch::Matchers::RangeEquals(std::vector(1, all_bits_set))); + } + + THEN("the rest of the storage region is not modified") + { + REQUIRE_THAT(std::views::drop(storage, 1), Catch::Matchers::RangeEquals(std::vector(15, 0uz))); + } + } + + WHEN("constructing with 64 frames") + { + auto allocator = kernel::memory::bitmap_frame_allocator{std::span(storage), 64}; + + THEN("the first word of the storage region is set to all ones") + { + REQUIRE_THAT(std::views::take(storage, 1), Catch::Matchers::RangeEquals(std::vector(1, all_bits_set))); + } + + THEN("the rest of the storage region is not modified") + { + REQUIRE_THAT(std::views::drop(storage, 1), Catch::Matchers::RangeEquals(std::vector(15, 0uz))); + } + } + + WHEN("constructing with all available frames") + { + auto allocator = kernel::memory::bitmap_frame_allocator{std::span(storage), available_frames}; + + THEN("the storage region is filled with all ones") + { + REQUIRE_THAT(storage, Catch::Matchers::RangeEquals(std::vector(16, all_bits_set))); + } + } + + WHEN("constructing with half the available frames") + { + auto allocator = kernel::memory::bitmap_frame_allocator{std::span(storage), available_frames / 2}; + + THEN("the first half of the storage region is filled with all ones") + { + REQUIRE_THAT(std::views::take(storage, (available_frames / 2) / 64), + Catch::Matchers::RangeEquals(std::vector((available_frames / 2) / 64, all_bits_set))); + } + + THEN("the second half of the storage region is filled with all zeros") + { + REQUIRE_THAT(std::views::drop(storage, (available_frames / 2) / 64), + Catch::Matchers::RangeEquals(std::vector((available_frames / 2) / 64, 0uz))); + } + } + } +} + +SCENARIO("Bitmap allocator frame allocation", "[memory][bitmap_allocator]") +{ + GIVEN("A storage region") + { + auto storage = std::vector(available_frames / 64, 0uz); + + AND_GIVEN("an allocator constructed with all available frames but no free ones") + { + auto allocator = kernel::memory::bitmap_frame_allocator{std::span(storage), available_frames}; + + WHEN("allocating 1 frame") + { + auto result = allocator.allocate_many(1); + + THEN("the result is empty") + { + REQUIRE_FALSE(result.has_value()); + } + } + } + + AND_GIVEN("an allocator constructed with all available frames but only one free one") + { + auto allocator = kernel::memory::bitmap_frame_allocator{std::span(storage), available_frames}; + allocator.release_many({kapi::memory::frame{0}, 1}); + + WHEN("allocating 1 frame") + { + auto result = allocator.allocate_many(1); + + THEN("the result is not empty") + { + REQUIRE(result.has_value()); + } + + THEN("the result contains 1 frame") + { + REQUIRE(result->second == 1); + } + } + + WHEN("allocating more frames than are free") + { + auto result = allocator.allocate_many(2); + + THEN("the result is empty") + { + REQUIRE_FALSE(result.has_value()); + } + + AND_WHEN("allocating a single frame") + { + auto result = allocator.allocate_many(1); + + THEN("the result is not empty") + { + REQUIRE(result.has_value()); + } + } + + WHEN("allocating 0 frames") + { + auto result = allocator.allocate_many(0); + + THEN("the result is empty") + { + REQUIRE_FALSE(result.has_value()); + } + } + } + } + + AND_GIVEN("an allocator with many single frame holes") + { + auto allocator = kernel::memory::bitmap_frame_allocator{std::span(storage), available_frames}; + for (auto i = 0uz; i < available_frames; i += 2) + { + allocator.release_many({kapi::memory::frame{i}, 1}); + } + + WHEN("allocating 1 frame") + { + auto result = allocator.allocate_many(1); + + THEN("the result is not empty") + { + REQUIRE(result.has_value()); + } + + THEN("the result contains 1 frame") + { + REQUIRE(result->second == 1); + } + } + + WHEN("allocating 2 frames") + { + auto result = allocator.allocate_many(2); + + THEN("the result is empty") + { + REQUIRE_FALSE(result.has_value()); + } + } + } + + AND_GIVEN("and allocator with all frames marked as free") + { + auto allocator = kernel::memory::bitmap_frame_allocator{std::span(storage), available_frames}; + allocator.release_many({kapi::memory::frame{0}, available_frames}); + + WHEN("allocating 1 frame") + { + auto result = allocator.allocate_many(1); + + THEN("the result is not empty") + { + REQUIRE(result.has_value()); + } + + THEN("the result contains 1 frame") + { + REQUIRE(result->second == 1); + } + } + + WHEN("allocating multiple frames") + { + auto result = allocator.allocate_many(20); + + THEN("the result is not empty") + { + REQUIRE(result.has_value()); + } + + THEN("the result contains 20 frames") + { + REQUIRE(result->second == 20); + } + } + + WHEN("marking all frames as used") + { + for (auto i = 0uz; i < available_frames; i++) + { + allocator.mark_used(kapi::memory::frame{i}); + } + + THEN("the allocator has no free frames") + { + REQUIRE_FALSE(allocator.allocate_many(1).has_value()); + } + } + } + + AND_GIVEN("an allocator with a contiguous block of free frames") + { + auto allocator = kernel::memory::bitmap_frame_allocator{std::span(storage), available_frames}; + allocator.release_many({kapi::memory::frame{0}, available_frames}); + for (auto i = 0uz; i < available_frames / 2; i++) + { + allocator.mark_used(kapi::memory::frame{i}); + } + + WHEN("allocating a single frame") + { + auto result = allocator.allocate_many(1); + + THEN("the result is not empty") + { + REQUIRE(result.has_value()); + } + + THEN("the result contains 1 frame") + { + REQUIRE(result->second == 1); + } + } + + WHEN("allocating multiple frames") + { + auto result = allocator.allocate_many(20); + + THEN("the result is not empty") + { + REQUIRE(result.has_value()); + } + + THEN("the result contains 20 frames") + { + REQUIRE(result->second == 20); + } + } + } + } +} \ No newline at end of file diff --git a/kernel/src/test_support/kapi/memory.cpp b/kernel/src/test_support/kapi/memory.cpp index 6de2f60..556962c 100644 --- a/kernel/src/test_support/kapi/memory.cpp +++ b/kernel/src/test_support/kapi/memory.cpp @@ -19,6 +19,7 @@ namespace kapi::memory { //! The size of the simulated RAM. constexpr auto simulate_memory_size = kstd::units::MiB(32); + constexpr auto number_of_simulated_frames = simulate_memory_size / frame::size; struct test_boostrap_frame_allocator : frame_allocator { @@ -66,10 +67,9 @@ namespace kapi::memory auto handoff_to_kernel_pmm(frame_allocator & new_allocator) -> void { - for (auto i = 0uz; i < boostrap_allocator.next_free_frame; ++i) - { - new_allocator.mark_used(frame{i}); - } + auto first_free_frame = boostrap_allocator.next_free_frame; + auto number_of_free_frames = number_of_simulated_frames - first_free_frame; + new_allocator.release_many({frame{first_free_frame}, number_of_free_frames}); } } // namespace -- cgit v1.2.3 From 7fc60f9350ebf86e2e13d09af159635ee8a1d086 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 1 Apr 2026 14:25:04 +0200 Subject: kernel: add ram disk device tests --- .../src/devices/storage/ram_disk/device.tests.cpp | 117 +++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 kernel/src/devices/storage/ram_disk/device.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/devices/storage/ram_disk/device.tests.cpp b/kernel/src/devices/storage/ram_disk/device.tests.cpp new file mode 100644 index 0000000..eacdb04 --- /dev/null +++ b/kernel/src/devices/storage/ram_disk/device.tests.cpp @@ -0,0 +1,117 @@ +#include "kernel/devices/storage/ram_disk/device.hpp" + +#include "kapi/boot_module/boot_module.hpp" +#include "kapi/memory.hpp" + +#include "catch2/matchers/catch_matchers.hpp" +#include "catch2/matchers/catch_matchers_range_equals.hpp" + +#include + +#include +#include +#include +#include + +SCENARIO("RAM Disk Device Construction and Initialization", "[ram_disk_device]") +{ + GIVEN("an empty boot module") + { + kapi::boot_modules::boot_module boot_module{}; + boot_module.start_address = kapi::memory::linear_address{nullptr}; + boot_module.size = 0; + + WHEN("constructing the device") + { + kernel::devices::storage::ram_disk::device device{boot_module, 0, 0}; + + THEN("init return false") + { + REQUIRE_FALSE(device.init()); + } + } + } + + GIVEN("a boot module with a valid start address and size") + { + kapi::boot_modules::boot_module boot_module{}; + boot_module.start_address = kapi::memory::linear_address{reinterpret_cast(0x1000)}; + boot_module.size = 512; + + WHEN("constructing the device") + { + kernel::devices::storage::ram_disk::device device{boot_module, 0, 0}; + + THEN("init return true") + { + REQUIRE(device.init()); + } + } + } +} + +SCENARIO("RAM Disk Device Read and Write", "[ram_disk_device]") +{ + GIVEN("a device initialized with a valid boot module") + { + auto storage = std::vector{4096, std::byte{0xff}}; + auto module = + kapi::boot_modules::boot_module{"test_module", kapi::memory::linear_address{storage.data()}, storage.size()}; + auto device = kernel::devices::storage::ram_disk::device{module, 0, 0}; + REQUIRE(device.init()); + + WHEN("reading a full block from the device") + { + auto buffer = std::vector(device.block_size()); + 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()))); + } + } + + WHEN("reading from a block index beyond the module size") + { + auto buffer = std::vector(device.block_size()); + device.read_block(10, buffer.data()); + + THEN("the buffer is filled with zeros") + { + REQUIRE_THAT(buffer, Catch::Matchers::RangeEquals(std::vector(device.block_size(), std::byte{0}))); + } + } + + WHEN("reading into a null buffer") + { + REQUIRE_THROWS_AS(device.read_block(0, nullptr), std::runtime_error); + } + + WHEN("writing to a full block") + { + auto buffer = std::vector(device.block_size(), std::byte{0x01}); + 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)); + } + } + + WHEN("writing to a block index beyond the module size") + { + auto buffer = std::vector(device.block_size(), std::byte{0x01}); + device.write_block(10, buffer.data()); + + THEN("the module data is not updated") + { + REQUIRE_THAT(storage, Catch::Matchers::RangeEquals(std::vector{4096, std::byte{0xff}})); + } + } + + WHEN("writing from a null buffer") + { + REQUIRE_THROWS_AS(device.write_block(0, nullptr), std::runtime_error); + } + } +} \ No newline at end of file -- cgit v1.2.3 From eaec1833e978d2443ffdfc226fff60d0b5571cb6 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 1 Apr 2026 16:27:51 +0200 Subject: kernel/tests: move initialization to a listener --- kernel/src/main.tests.cpp | 38 ------------------ kernel/src/test_support/kapi/cio.cpp | 5 +++ kernel/src/test_support/kapi/cpu.cpp | 18 +++++++-- kernel/src/test_support/kapi/memory.cpp | 14 +++++-- kernel/src/test_support/simulated_memory.cpp | 6 +++ kernel/src/test_support/state_reset_listener.cpp | 50 ++++++++++++++++++++++++ 6 files changed, 86 insertions(+), 45 deletions(-) delete mode 100644 kernel/src/main.tests.cpp create mode 100644 kernel/src/test_support/state_reset_listener.cpp (limited to 'kernel/src') diff --git a/kernel/src/main.tests.cpp b/kernel/src/main.tests.cpp deleted file mode 100644 index b3ae142..0000000 --- a/kernel/src/main.tests.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "kapi/interrupts.hpp" -#include "kapi/memory.hpp" -#include -#include - -#include - -auto main(int argc, char ** argv) -> int -{ - auto session = Catch::Session{}; - - if (auto result = session.applyCommandLine(argc, argv); result != 0) - { - return result; - } - - auto const & config = session.configData(); - auto skip_init = config.listTests || // - config.listTags || // - config.listReporters || // - config.listListeners || // - config.showHelp; - - if (!skip_init) - { - kapi::cio::init(); - kapi::cpu::init(); - kapi::interrupts::enable(); - - kapi::memory::init(); - // note: no kernel heap is created, since we are in the test environment. Nonetheless, we still initialize the - // memory subsystem, so that components that rely on it can be tested. No component must ever rely on the heap - // allocator directly, rather they have to go through the new and delete. However, some components may use the frame - // allocator and page mapper in order to perform their tasks. - } - - return session.run(); -} diff --git a/kernel/src/test_support/kapi/cio.cpp b/kernel/src/test_support/kapi/cio.cpp index 6359fa8..0dd4b8c 100644 --- a/kernel/src/test_support/kapi/cio.cpp +++ b/kernel/src/test_support/kapi/cio.cpp @@ -35,4 +35,9 @@ namespace kapi::cio set_output_device(device); } + auto reset() -> void + { + kernel::tests::log_buffer::clear(); + } + } // namespace kapi::cio \ No newline at end of file diff --git a/kernel/src/test_support/kapi/cpu.cpp b/kernel/src/test_support/kapi/cpu.cpp index 3ecaadc..9b2f0b9 100644 --- a/kernel/src/test_support/kapi/cpu.cpp +++ b/kernel/src/test_support/kapi/cpu.cpp @@ -8,17 +8,29 @@ namespace kapi::cpu { - auto init() -> void + namespace { auto static initialized = std::atomic_flag{}; + } + + auto reset() -> void + { + if (!initialized.test()) + { + throw std::logic_error{"kapi::cpu::reset() called before kapi::cpu::init()"}; + } + + initialized.clear(); + } + + auto init() -> void + { if (initialized.test_and_set()) { throw std::logic_error("kapi::cpu::init() called more than once"); } // TODO: make sure that simulated interrupt can run. - - return; } auto halt() -> void diff --git a/kernel/src/test_support/kapi/memory.cpp b/kernel/src/test_support/kapi/memory.cpp index 556962c..4f261ac 100644 --- a/kernel/src/test_support/kapi/memory.cpp +++ b/kernel/src/test_support/kapi/memory.cpp @@ -21,7 +21,7 @@ namespace kapi::memory constexpr auto simulate_memory_size = kstd::units::MiB(32); constexpr auto number_of_simulated_frames = simulate_memory_size / frame::size; - struct test_boostrap_frame_allocator : frame_allocator + struct test_bootstrap_frame_allocator : frame_allocator { auto mark_used(frame) -> void override {} @@ -35,7 +35,7 @@ namespace kapi::memory auto release_many(std::pair) -> void override {} std::size_t next_free_frame{}; - } boostrap_allocator; + } bootstrap_allocator; struct test_page_mapper : page_mapper { @@ -67,7 +67,7 @@ namespace kapi::memory auto handoff_to_kernel_pmm(frame_allocator & new_allocator) -> void { - auto first_free_frame = boostrap_allocator.next_free_frame; + auto first_free_frame = bootstrap_allocator.next_free_frame; auto number_of_free_frames = number_of_simulated_frames - first_free_frame; new_allocator.release_many({frame{first_free_frame}, number_of_free_frames}); } @@ -77,10 +77,16 @@ namespace kapi::memory auto init() -> void { kernel::tests::simulated_memory::init(simulate_memory_size); - set_frame_allocator(boostrap_allocator); + set_frame_allocator(bootstrap_allocator); set_page_mapper(test_mapper); init_pmm(simulate_memory_size / frame::size, handoff_to_kernel_pmm); } + auto reset() -> void + { + kernel::tests::simulated_memory::reset(); + bootstrap_allocator.next_free_frame = 0; + } + } // namespace kapi::memory \ No newline at end of file diff --git a/kernel/src/test_support/simulated_memory.cpp b/kernel/src/test_support/simulated_memory.cpp index 9a9b354..49e172f 100644 --- a/kernel/src/test_support/simulated_memory.cpp +++ b/kernel/src/test_support/simulated_memory.cpp @@ -20,6 +20,12 @@ namespace kernel::tests::simulated_memory pmm_storage.resize(size / kstd::units::bytes{1}); } + auto reset() -> void + { + ram_storage.clear(); + pmm_storage.clear(); + } + auto pmm_metadata_base() -> std::byte * { return pmm_storage.data(); diff --git a/kernel/src/test_support/state_reset_listener.cpp b/kernel/src/test_support/state_reset_listener.cpp new file mode 100644 index 0000000..e201a10 --- /dev/null +++ b/kernel/src/test_support/state_reset_listener.cpp @@ -0,0 +1,50 @@ +#include "kapi/cio.hpp" +#include "kapi/cpu.hpp" +#include "kapi/memory.hpp" + +#include +#include +#include +#include + +namespace kapi +{ + namespace cio + { + auto reset() -> void; + } + + namespace cpu + { + auto reset() -> void; + } + + namespace memory + { + auto reset() -> void; + } +} // namespace kapi + +struct state_reset_listener : Catch::EventListenerBase +{ + using EventListenerBase::EventListenerBase; + + void testCaseStarting(Catch::TestCaseInfo const &) override + { + kapi::cio::init(); + kapi::cpu::init(); + kapi::memory::init(); + } + + void testCaseEnded(Catch::TestCaseStats const &) override + { + kapi::memory::reset(); + kapi::cpu::reset(); + kapi::cio::reset(); + } +}; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +CATCH_REGISTER_LISTENER(state_reset_listener); +#pragma GCC diagnostic pop \ No newline at end of file -- cgit v1.2.3 From 1a22d810ff2772d6b4dba5b1eb27d21285668c6f Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 1 Apr 2026 16:32:43 +0200 Subject: kernel/tests: improve memory cleanup --- kernel/src/test_support/kapi/memory.cpp | 35 +++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/test_support/kapi/memory.cpp b/kernel/src/test_support/kapi/memory.cpp index 4f261ac..652a3d3 100644 --- a/kernel/src/test_support/kapi/memory.cpp +++ b/kernel/src/test_support/kapi/memory.cpp @@ -35,7 +35,9 @@ namespace kapi::memory auto release_many(std::pair) -> void override {} std::size_t next_free_frame{}; - } bootstrap_allocator; + }; + + auto constinit bootstrap_allocator = std::optional{}; struct test_page_mapper : page_mapper { @@ -63,22 +65,31 @@ namespace kapi::memory kstd::println("trying to unmap page {}", page.number()); return false; } - } test_mapper; + }; + + auto constinit test_mapper = std::optional{}; auto handoff_to_kernel_pmm(frame_allocator & new_allocator) -> void { - auto first_free_frame = bootstrap_allocator.next_free_frame; + auto first_free_frame = bootstrap_allocator->next_free_frame; auto number_of_free_frames = number_of_simulated_frames - first_free_frame; new_allocator.release_many({frame{first_free_frame}, number_of_free_frames}); } + auto constinit previous_frame_allocator = std::optional{}; + auto constinit previous_page_mapper = std::optional{}; + } // namespace auto init() -> void { kernel::tests::simulated_memory::init(simulate_memory_size); - set_frame_allocator(bootstrap_allocator); - set_page_mapper(test_mapper); + + bootstrap_allocator.emplace(); + test_mapper.emplace(); + + previous_frame_allocator = set_frame_allocator(*bootstrap_allocator); + previous_page_mapper = set_page_mapper(*test_mapper); init_pmm(simulate_memory_size / frame::size, handoff_to_kernel_pmm); } @@ -86,7 +97,19 @@ namespace kapi::memory auto reset() -> void { kernel::tests::simulated_memory::reset(); - bootstrap_allocator.next_free_frame = 0; + + if (previous_frame_allocator && *previous_frame_allocator) + { + set_frame_allocator(**previous_frame_allocator); + } + + if (previous_page_mapper && *previous_page_mapper) + { + set_page_mapper(**previous_page_mapper); + } + + bootstrap_allocator.reset(); + test_mapper.reset(); } } // namespace kapi::memory \ No newline at end of file -- cgit v1.2.3 From b078f2bf4726b5c62584cebd84107ac1028bb083 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 1 Apr 2026 17:26:13 +0200 Subject: kernel/tests: clean up fake memory implementation --- kernel/src/test_support/kapi/memory.cpp | 92 ++++++---------------------- kernel/src/test_support/page_mapper.cpp | 57 +++++++++++++++++ kernel/src/test_support/simulated_memory.cpp | 31 ++++------ 3 files changed, 88 insertions(+), 92 deletions(-) create mode 100644 kernel/src/test_support/page_mapper.cpp (limited to 'kernel/src') diff --git a/kernel/src/test_support/kapi/memory.cpp b/kernel/src/test_support/kapi/memory.cpp index 652a3d3..7b7a81e 100644 --- a/kernel/src/test_support/kapi/memory.cpp +++ b/kernel/src/test_support/kapi/memory.cpp @@ -2,15 +2,12 @@ #include -#include "kernel/tests/simulated_memory.hpp" +#include "kernel/tests/bump_frame_allocator.hpp" +#include "kernel/tests/page_mapper.hpp" -#include #include -#include -#include #include -#include namespace kapi::memory { @@ -18,97 +15,48 @@ namespace kapi::memory namespace { //! The size of the simulated RAM. - constexpr auto simulate_memory_size = kstd::units::MiB(32); - constexpr auto number_of_simulated_frames = simulate_memory_size / frame::size; + constexpr auto memory_size = kstd::units::MiB(32); + constexpr auto number_of_frames = memory_size / frame::size; - struct test_bootstrap_frame_allocator : frame_allocator - { - auto mark_used(frame) -> void override {} - - auto allocate_many(std::size_t count) noexcept -> std::optional> override - { - auto start = next_free_frame; - next_free_frame += count; - return std::pair{frame{start}, count}; - } - - auto release_many(std::pair) -> void override {} + auto constinit bump_allocator = std::optional{}; + auto constinit test_mapper = std::optional{}; - std::size_t next_free_frame{}; - }; - - auto constinit bootstrap_allocator = std::optional{}; - - struct test_page_mapper : page_mapper - { - auto map(page page, frame frame, flags flags) -> std::byte * override - { - kstd::println("mapping page {} onto frame {} with flags {}", page.number(), frame.number(), - static_cast(flags)); - - if ((page.start_address() & pmm_metadata_base.raw()) == pmm_metadata_base.raw()) - { - auto offset = page.start_address() & ~pmm_metadata_base.raw(); - return kernel::tests::simulated_memory::pmm_metadata_base() + offset; - } - - return nullptr; - } - - auto unmap(page page) -> void override - { - kstd::println("unmapping page {}", page.number()); - } - - auto try_unmap(page page) noexcept -> bool override - { - kstd::println("trying to unmap page {}", page.number()); - return false; - } - }; - - auto constinit test_mapper = std::optional{}; + auto constinit old_allocator = std::optional{}; + auto constinit old_mapper = std::optional{}; auto handoff_to_kernel_pmm(frame_allocator & new_allocator) -> void { - auto first_free_frame = bootstrap_allocator->next_free_frame; - auto number_of_free_frames = number_of_simulated_frames - first_free_frame; + auto first_free_frame = bump_allocator->next_free_frame; + auto number_of_free_frames = number_of_frames - first_free_frame; new_allocator.release_many({frame{first_free_frame}, number_of_free_frames}); } - auto constinit previous_frame_allocator = std::optional{}; - auto constinit previous_page_mapper = std::optional{}; - } // namespace auto init() -> void { - kernel::tests::simulated_memory::init(simulate_memory_size); + bump_allocator.emplace(); + test_mapper.emplace(memory_size); - bootstrap_allocator.emplace(); - test_mapper.emplace(); + old_allocator = set_frame_allocator(*bump_allocator); + old_mapper = set_page_mapper(*test_mapper); - previous_frame_allocator = set_frame_allocator(*bootstrap_allocator); - previous_page_mapper = set_page_mapper(*test_mapper); - - init_pmm(simulate_memory_size / frame::size, handoff_to_kernel_pmm); + init_pmm(memory_size / frame::size, handoff_to_kernel_pmm); } auto reset() -> void { - kernel::tests::simulated_memory::reset(); - - if (previous_frame_allocator && *previous_frame_allocator) + if (old_allocator && *old_allocator) { - set_frame_allocator(**previous_frame_allocator); + set_frame_allocator(**old_allocator); } - if (previous_page_mapper && *previous_page_mapper) + if (old_mapper && *old_mapper) { - set_page_mapper(**previous_page_mapper); + set_page_mapper(**old_mapper); } - bootstrap_allocator.reset(); + bump_allocator.reset(); test_mapper.reset(); } diff --git a/kernel/src/test_support/page_mapper.cpp b/kernel/src/test_support/page_mapper.cpp new file mode 100644 index 0000000..a026ec3 --- /dev/null +++ b/kernel/src/test_support/page_mapper.cpp @@ -0,0 +1,57 @@ +#include "kernel/tests/page_mapper.hpp" + +#include "kapi/memory.hpp" + +#include + +#include +#include +#include + +namespace kernel::tests +{ + + page_mapper::page_mapper(kstd::units::bytes memory_size) + : memory{memory_size} + {} + + auto page_mapper::map(kapi::memory::page page, kapi::memory::frame frame, flags) -> std::byte * + { + page_mappings.insert({page.number(), frame}); + + auto page_address = page.start_address(); + + if (page_address >= kapi::memory::mmio_base) + { + throw std::invalid_argument{"MMIO mapping not yet supported in testing!"}; + } + else if (page_address >= kapi::memory::higher_half_direct_map_base) + { + auto offset = frame.number() * kapi::memory::frame::size; + return memory.ram_base() + offset; + } + + return nullptr; + } + + auto page_mapper::unmap(kapi::memory::page page) -> void + { + if (!try_unmap(page)) + { + auto error = std::format("Page {} was never mapped!", page.number()); + throw std::invalid_argument{error}; + } + } + + auto page_mapper::try_unmap(kapi::memory::page page) noexcept -> bool + { + if (page_mappings.contains(page.number())) + { + page_mappings.erase(page.number()); + return true; + } + + return false; + } + +} // namespace kernel::tests \ No newline at end of file diff --git a/kernel/src/test_support/simulated_memory.cpp b/kernel/src/test_support/simulated_memory.cpp index 49e172f..d23350b 100644 --- a/kernel/src/test_support/simulated_memory.cpp +++ b/kernel/src/test_support/simulated_memory.cpp @@ -5,35 +5,26 @@ #include #include -namespace kernel::tests::simulated_memory +namespace kernel::tests { - namespace - { - auto constinit ram_storage = std::vector{}; - auto constinit pmm_storage = std::vector{}; - } // namespace - - auto init(kstd::units::bytes size) -> void - { - ram_storage.resize(size / kstd::units::bytes{1}); - pmm_storage.resize(size / kstd::units::bytes{1}); - } + simulated_memory::simulated_memory(kstd::units::bytes size) + : m_memory{size / kstd::units::bytes{1}} + {} - auto reset() -> void + auto simulated_memory::ram_base() noexcept -> std::byte * { - ram_storage.clear(); - pmm_storage.clear(); + return m_memory.data(); } - auto pmm_metadata_base() -> std::byte * + auto simulated_memory::ram_base() const noexcept -> std::byte const * { - return pmm_storage.data(); + return m_memory.data(); } - auto ram_base() -> std::byte * + auto simulated_memory::clear() -> void { - return ram_storage.data(); + m_memory.clear(); } -} // namespace kernel::tests::simulated_memory \ No newline at end of file +} // namespace kernel::tests \ No newline at end of file -- cgit v1.2.3 From 825d8bafef152a52cd76851764913fb12cdc685d Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 1 Apr 2026 17:29:25 +0200 Subject: kernel/test: rename test include to test_support --- kernel/src/test_support/kapi/cio.cpp | 2 +- kernel/src/test_support/kapi/cpu.cpp | 2 +- kernel/src/test_support/kapi/memory.cpp | 4 ++-- kernel/src/test_support/log_buffer.cpp | 2 +- kernel/src/test_support/page_mapper.cpp | 2 +- kernel/src/test_support/simulated_memory.cpp | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/test_support/kapi/cio.cpp b/kernel/src/test_support/kapi/cio.cpp index 0dd4b8c..35452d4 100644 --- a/kernel/src/test_support/kapi/cio.cpp +++ b/kernel/src/test_support/kapi/cio.cpp @@ -1,6 +1,6 @@ #include -#include "kernel/tests/log_buffer.hpp" +#include "kernel/test_support/log_buffer.hpp" #include #include diff --git a/kernel/src/test_support/kapi/cpu.cpp b/kernel/src/test_support/kapi/cpu.cpp index 9b2f0b9..6592d15 100644 --- a/kernel/src/test_support/kapi/cpu.cpp +++ b/kernel/src/test_support/kapi/cpu.cpp @@ -1,4 +1,4 @@ -#include "kernel/tests/cpu.hpp" +#include "kernel/test_support/cpu.hpp" #include diff --git a/kernel/src/test_support/kapi/memory.cpp b/kernel/src/test_support/kapi/memory.cpp index 7b7a81e..3a2c2ba 100644 --- a/kernel/src/test_support/kapi/memory.cpp +++ b/kernel/src/test_support/kapi/memory.cpp @@ -2,8 +2,8 @@ #include -#include "kernel/tests/bump_frame_allocator.hpp" -#include "kernel/tests/page_mapper.hpp" +#include "kernel/test_support/bump_frame_allocator.hpp" +#include "kernel/test_support/page_mapper.hpp" #include diff --git a/kernel/src/test_support/log_buffer.cpp b/kernel/src/test_support/log_buffer.cpp index 9e30afb..36ed15e 100644 --- a/kernel/src/test_support/log_buffer.cpp +++ b/kernel/src/test_support/log_buffer.cpp @@ -1,4 +1,4 @@ -#include "kernel/tests/log_buffer.hpp" +#include "kernel/test_support/log_buffer.hpp" #include #include diff --git a/kernel/src/test_support/page_mapper.cpp b/kernel/src/test_support/page_mapper.cpp index a026ec3..5a1b747 100644 --- a/kernel/src/test_support/page_mapper.cpp +++ b/kernel/src/test_support/page_mapper.cpp @@ -1,4 +1,4 @@ -#include "kernel/tests/page_mapper.hpp" +#include "kernel/test_support/page_mapper.hpp" #include "kapi/memory.hpp" diff --git a/kernel/src/test_support/simulated_memory.cpp b/kernel/src/test_support/simulated_memory.cpp index d23350b..7264a35 100644 --- a/kernel/src/test_support/simulated_memory.cpp +++ b/kernel/src/test_support/simulated_memory.cpp @@ -1,4 +1,4 @@ -#include "kernel/tests/simulated_memory.hpp" +#include "kernel/test_support/simulated_memory.hpp" #include -- cgit v1.2.3 From dc64b1cba4677b40c9dda31ecd5109507837b817 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 1 Apr 2026 20:59:55 +0200 Subject: kernel/tests: don't rely on vector for fake memory --- kernel/src/test_support/page_mapper.cpp | 20 +++++++- kernel/src/test_support/simulated_memory.cpp | 77 +++++++++++++++++++++++++--- 2 files changed, 88 insertions(+), 9 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/test_support/page_mapper.cpp b/kernel/src/test_support/page_mapper.cpp index 5a1b747..805998b 100644 --- a/kernel/src/test_support/page_mapper.cpp +++ b/kernel/src/test_support/page_mapper.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace kernel::tests { @@ -20,10 +21,25 @@ namespace kernel::tests page_mappings.insert({page.number(), frame}); auto page_address = page.start_address(); + auto sandbox_start = memory.heap_base(); + auto sandbox_end = sandbox_start + memory.heap_size(); - if (page_address >= kapi::memory::mmio_base) + if (page_address >= sandbox_start && page_address < sandbox_end) { - throw std::invalid_argument{"MMIO mapping not yet supported in testing!"}; + auto virtual_target = static_cast(page_address); + auto physical_offset = frame.number() * kapi::memory::frame::size; + auto mapped_ptr = mmap(virtual_target, kapi::memory::page::size.value, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_FIXED, memory.memory_descriptor(), physical_offset.value); + if (mapped_ptr == MAP_FAILED) + { + throw std::runtime_error("Failed to map page"); + } + + return static_cast(mapped_ptr); + } + else if (page_address >= kapi::memory::mmio_base) + { + throw std::runtime_error("MMIO mapping not yet supported in testing!"); } else if (page_address >= kapi::memory::higher_half_direct_map_base) { diff --git a/kernel/src/test_support/simulated_memory.cpp b/kernel/src/test_support/simulated_memory.cpp index 7264a35..fa3d36c 100644 --- a/kernel/src/test_support/simulated_memory.cpp +++ b/kernel/src/test_support/simulated_memory.cpp @@ -1,30 +1,93 @@ #include "kernel/test_support/simulated_memory.hpp" +#include "kapi/memory.hpp" + #include #include -#include +#include +#include +#include +#include +#include + +using namespace kstd::units_literals; namespace kernel::tests { + namespace + { + constexpr auto virtual_size = 1_GiB; + } simulated_memory::simulated_memory(kstd::units::bytes size) - : m_memory{size / kstd::units::bytes{1}} - {} + : m_memory_descriptor{memfd_create("teachos_simulated_memory", 0)} + , m_size{size} + { + if (m_memory_descriptor < 0) + { + throw std::runtime_error("Failed to create simulated memory"); + } + + if (ftruncate(m_memory_descriptor, static_cast(m_size.value)) < 0) + { + throw std::runtime_error("Failed to resize simulated memory"); + } + + auto mapped_pointer = mmap(nullptr, m_size.value, PROT_READ | PROT_WRITE, MAP_SHARED, m_memory_descriptor, 0); + if (mapped_pointer == MAP_FAILED) + { + throw std::runtime_error("Failed to map simulated memory"); + } + + m_physical_base = static_cast(mapped_pointer); + + auto virtual_pointer = mmap(nullptr, virtual_size.value, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (virtual_pointer == MAP_FAILED) + { + throw std::runtime_error("Failed to map simulated memory"); + } + + m_virtual_base = static_cast(virtual_pointer); + + clear(); + } + + simulated_memory::~simulated_memory() + { + munmap(m_physical_base, m_size.value); + munmap(m_virtual_base, virtual_size.value); + close(m_memory_descriptor); + } + + auto simulated_memory::clear() -> void + { + std::memset(m_physical_base, 0, m_size.value); + } auto simulated_memory::ram_base() noexcept -> std::byte * { - return m_memory.data(); + return m_physical_base; } auto simulated_memory::ram_base() const noexcept -> std::byte const * { - return m_memory.data(); + return m_physical_base; } - auto simulated_memory::clear() -> void + auto simulated_memory::heap_base() const noexcept -> kapi::memory::linear_address + { + return kapi::memory::linear_address{m_virtual_base}; + } + + auto simulated_memory::heap_size() const noexcept -> kstd::units::bytes + { + return virtual_size; + } + + auto simulated_memory::memory_descriptor() const noexcept -> int { - m_memory.clear(); + return m_memory_descriptor; } } // namespace kernel::tests \ No newline at end of file -- cgit v1.2.3 From f8456a8709b6894166865eb4ca067604f480eb7f Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 1 Apr 2026 21:16:10 +0200 Subject: kernel/tests: add basic heap allocator tests --- kernel/src/memory/block_list_allocator.tests.cpp | 80 ++++++++++++++++++++++++ kernel/src/test_support/kapi/memory.cpp | 44 +++++++------ 2 files changed, 106 insertions(+), 18 deletions(-) create mode 100644 kernel/src/memory/block_list_allocator.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/memory/block_list_allocator.tests.cpp b/kernel/src/memory/block_list_allocator.tests.cpp new file mode 100644 index 0000000..5f6f382 --- /dev/null +++ b/kernel/src/memory/block_list_allocator.tests.cpp @@ -0,0 +1,80 @@ +#include "kernel/memory/block_list_allocator.hpp" + +#include "kernel/test_support/memory.hpp" + +#include + +#include + +#include + +using namespace kstd::units_literals; + +SCENARIO("Block List Allocator Operations", "[memory][allocator]") +{ + GIVEN("A newly initialized block list allocator mapped via the test sandbox") + { + auto sandbox_base = kernel::tests::memory::heap_base(); + kernel::memory::block_list_allocator allocator{sandbox_base}; + + WHEN("a basic allocation request is made") + { + void * ptr = allocator.allocate(128_B, 8_B); + + THEN("a valid, non-null pointer is returned") + { + REQUIRE(ptr != nullptr); + } + + AND_THEN("the returned memory is writeable without causing segmentation faults") + { + auto byte_ptr = static_cast(ptr); + byte_ptr[0] = std::byte{0xDE}; + byte_ptr[127] = std::byte{0xAD}; + REQUIRE(byte_ptr[0] == std::byte{0xDE}); + REQUIRE(byte_ptr[127] == std::byte{0xAD}); + } + + allocator.deallocate(ptr); + } + + WHEN("multiple allocations are made sequentially") + { + void * ptr1 = allocator.allocate(64_B, 8_B); + void * ptr2 = allocator.allocate(64_B, 8_B); + void * ptr3 = allocator.allocate(1_KiB, 16_B); + + THEN("they return distinct, non-overlapping memory blocks") + { + REQUIRE(ptr1 != nullptr); + REQUIRE(ptr2 != nullptr); + REQUIRE(ptr3 != nullptr); + REQUIRE(ptr1 != ptr2); + REQUIRE(ptr2 != ptr3); + REQUIRE(ptr1 != ptr3); + } + + allocator.deallocate(ptr1); + allocator.deallocate(ptr2); + allocator.deallocate(ptr3); + } + + WHEN("a block is allocated and then completely freed") + { + void * original_ptr = allocator.allocate(512_B, 16_B); + allocator.deallocate(original_ptr); + + AND_WHEN("a new allocation of equal or smaller size is requested") + { + void * new_ptr = allocator.allocate(128_B, 16_B); + + THEN("the allocator actively reuses the coalesced space") + { + REQUIRE(new_ptr == original_ptr); + } + + allocator.deallocate(new_ptr); + } + } + } +} diff --git a/kernel/src/test_support/kapi/memory.cpp b/kernel/src/test_support/kapi/memory.cpp index 3a2c2ba..f244b7f 100644 --- a/kernel/src/test_support/kapi/memory.cpp +++ b/kernel/src/test_support/kapi/memory.cpp @@ -9,29 +9,29 @@ #include -namespace kapi::memory +namespace { + //! The size of the simulated RAM. + constexpr auto memory_size = kstd::units::MiB(32); + constexpr auto number_of_frames = memory_size / kapi::memory::frame::size; - namespace - { - //! The size of the simulated RAM. - constexpr auto memory_size = kstd::units::MiB(32); - constexpr auto number_of_frames = memory_size / frame::size; + auto constinit bump_allocator = std::optional{}; + auto constinit test_mapper = std::optional{}; - auto constinit bump_allocator = std::optional{}; - auto constinit test_mapper = std::optional{}; + auto constinit old_allocator = std::optional{}; + auto constinit old_mapper = std::optional{}; - auto constinit old_allocator = std::optional{}; - auto constinit old_mapper = std::optional{}; + auto handoff_to_kernel_pmm(kapi::memory::frame_allocator & new_allocator) -> void + { + auto first_free_frame = bump_allocator->next_free_frame; + auto number_of_free_frames = number_of_frames - first_free_frame; + new_allocator.release_many({kapi::memory::frame{first_free_frame}, number_of_free_frames}); + } - auto handoff_to_kernel_pmm(frame_allocator & new_allocator) -> void - { - auto first_free_frame = bump_allocator->next_free_frame; - auto number_of_free_frames = number_of_frames - first_free_frame; - new_allocator.release_many({frame{first_free_frame}, number_of_free_frames}); - } +} // namespace - } // namespace +namespace kapi::memory +{ auto init() -> void { @@ -60,4 +60,12 @@ namespace kapi::memory test_mapper.reset(); } -} // namespace kapi::memory \ No newline at end of file +} // namespace kapi::memory + +namespace kernel::tests::memory +{ + auto heap_base() -> kapi::memory::linear_address + { + return test_mapper->memory.heap_base(); + } +} // namespace kernel::tests::memory \ No newline at end of file -- cgit v1.2.3 From 3eb680cf5bcef626505cac82820996d8db4170d7 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 1 Apr 2026 22:52:22 +0200 Subject: kernel/tests: prevent double mapping of pages --- kernel/src/memory/block_list_allocator.tests.cpp | 13 +++++++++++++ kernel/src/test_support/page_mapper.cpp | 7 ++++++- 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/memory/block_list_allocator.tests.cpp b/kernel/src/memory/block_list_allocator.tests.cpp index 5f6f382..8ca426d 100644 --- a/kernel/src/memory/block_list_allocator.tests.cpp +++ b/kernel/src/memory/block_list_allocator.tests.cpp @@ -1,5 +1,7 @@ #include "kernel/memory/block_list_allocator.hpp" +#include "kapi/memory.hpp" + #include "kernel/test_support/memory.hpp" #include @@ -10,10 +12,21 @@ using namespace kstd::units_literals; +namespace kapi +{ + namespace memory + { + auto reset() -> void; + } +} // namespace kapi + SCENARIO("Block List Allocator Operations", "[memory][allocator]") { GIVEN("A newly initialized block list allocator mapped via the test sandbox") { + kapi::memory::reset(); + kapi::memory::init(); + auto sandbox_base = kernel::tests::memory::heap_base(); kernel::memory::block_list_allocator allocator{sandbox_base}; diff --git a/kernel/src/test_support/page_mapper.cpp b/kernel/src/test_support/page_mapper.cpp index 805998b..abdcae5 100644 --- a/kernel/src/test_support/page_mapper.cpp +++ b/kernel/src/test_support/page_mapper.cpp @@ -18,7 +18,12 @@ namespace kernel::tests auto page_mapper::map(kapi::memory::page page, kapi::memory::frame frame, flags) -> std::byte * { - page_mappings.insert({page.number(), frame}); + auto result = page_mappings.insert({page.number(), frame}); + if (!result.second) + { + auto error = std::format("Page {} was already mapped!", page.number()); + throw std::invalid_argument{error}; + } auto page_address = page.start_address(); auto sandbox_start = memory.heap_base(); -- cgit v1.2.3 From f7ff847498d629c05bb206b41a172f6735e2afe6 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 2 Apr 2026 09:51:44 +0200 Subject: kernel/tests: clean up implementation structure --- kernel/src/memory/block_list_allocator.tests.cpp | 12 +--- kernel/src/test_support/kapi/cio.cpp | 63 +++++++++++-------- kernel/src/test_support/kapi/cpu.cpp | 37 +++++++----- kernel/src/test_support/kapi/memory.cpp | 25 ++++---- kernel/src/test_support/log_buffer.cpp | 32 ++++------ kernel/src/test_support/output_device.cpp | 28 +++++++++ kernel/src/test_support/page_mapper.cpp | 22 +++---- kernel/src/test_support/simulated_memory.cpp | 77 +++++++++++++++--------- kernel/src/test_support/state_reset_listener.cpp | 28 +++------ 9 files changed, 176 insertions(+), 148 deletions(-) create mode 100644 kernel/src/test_support/output_device.cpp (limited to 'kernel/src') diff --git a/kernel/src/memory/block_list_allocator.tests.cpp b/kernel/src/memory/block_list_allocator.tests.cpp index 8ca426d..0571441 100644 --- a/kernel/src/memory/block_list_allocator.tests.cpp +++ b/kernel/src/memory/block_list_allocator.tests.cpp @@ -12,22 +12,14 @@ using namespace kstd::units_literals; -namespace kapi -{ - namespace memory - { - auto reset() -> void; - } -} // namespace kapi - SCENARIO("Block List Allocator Operations", "[memory][allocator]") { GIVEN("A newly initialized block list allocator mapped via the test sandbox") { - kapi::memory::reset(); + kernel::tests::memory::deinit(); kapi::memory::init(); - auto sandbox_base = kernel::tests::memory::heap_base(); + auto sandbox_base = kernel::tests::memory::virtual_base(); kernel::memory::block_list_allocator allocator{sandbox_base}; WHEN("a basic allocation request is made") diff --git a/kernel/src/test_support/kapi/cio.cpp b/kernel/src/test_support/kapi/cio.cpp index 35452d4..4a1cd1f 100644 --- a/kernel/src/test_support/kapi/cio.cpp +++ b/kernel/src/test_support/kapi/cio.cpp @@ -1,43 +1,54 @@ +#include "kernel/test_support/cio.hpp" + #include #include "kernel/test_support/log_buffer.hpp" -#include -#include -#include +#include +#include +#include + +namespace +{ + + auto constinit is_initialized = std::atomic_flag{}; + auto constinit device = std::optional{}; + +} // namespace namespace kapi::cio { - namespace + auto init() -> void { - - class test_output_device : public output_device + if (is_initialized.test_and_set()) { - public: - test_output_device() = default; - - auto write(output_stream stream, std::string_view text) -> void override - { - auto & standard_stream = stream == output_stream::stdout ? std::cout : std::cerr; - standard_stream << text; - if (text != "\n") - { - kernel::tests::log_buffer::append(std::string{text}); - } - } - } device{}; - - } // namespace + throw std::logic_error("kapi::cio::init() called more than once"); + } - auto init() -> void + device.emplace(); + set_output_device(*device); + } + +} // namespace kapi::cio + +namespace kernel::tests::cio +{ + + auto deinit() -> void { - set_output_device(device); + if (!is_initialized.test()) + { + throw std::logic_error("kapi::cio::deinit() called before kapi::cio::init()"); + } + + device.reset(); + is_initialized.clear(); } - auto reset() -> void + auto log_buffer() -> kernel::tests::log_buffer & { - kernel::tests::log_buffer::clear(); + return device->log_buffer(); } -} // namespace kapi::cio \ No newline at end of file +} // namespace kernel::tests::cio \ No newline at end of file diff --git a/kernel/src/test_support/kapi/cpu.cpp b/kernel/src/test_support/kapi/cpu.cpp index 6592d15..96dd10a 100644 --- a/kernel/src/test_support/kapi/cpu.cpp +++ b/kernel/src/test_support/kapi/cpu.cpp @@ -5,23 +5,13 @@ #include #include -namespace kapi::cpu +namespace { + auto static initialized = std::atomic_flag{}; +} - namespace - { - auto static initialized = std::atomic_flag{}; - } - - auto reset() -> void - { - if (!initialized.test()) - { - throw std::logic_error{"kapi::cpu::reset() called before kapi::cpu::init()"}; - } - - initialized.clear(); - } +namespace kapi::cpu +{ auto init() -> void { @@ -38,4 +28,19 @@ namespace kapi::cpu throw kernel::tests::cpu::halt{}; } -} // namespace kapi::cpu \ No newline at end of file +} // namespace kapi::cpu + +namespace kernel::tests::cpu +{ + + auto deinit() -> void + { + if (!initialized.test()) + { + throw std::logic_error{"kapi::cpu::reset() called before kapi::cpu::init()"}; + } + + initialized.clear(); + } + +} // namespace kernel::tests::cpu \ No newline at end of file diff --git a/kernel/src/test_support/kapi/memory.cpp b/kernel/src/test_support/kapi/memory.cpp index f244b7f..e926ba6 100644 --- a/kernel/src/test_support/kapi/memory.cpp +++ b/kernel/src/test_support/kapi/memory.cpp @@ -12,8 +12,10 @@ namespace { //! The size of the simulated RAM. - constexpr auto memory_size = kstd::units::MiB(32); - constexpr auto number_of_frames = memory_size / kapi::memory::frame::size; + constexpr auto physical_size = kstd::units::MiB(32); + constexpr auto virtual_size = kstd::units::GiB(1); + + constexpr auto number_of_frames = physical_size / kapi::memory::frame::size; auto constinit bump_allocator = std::optional{}; auto constinit test_mapper = std::optional{}; @@ -36,15 +38,19 @@ namespace kapi::memory auto init() -> void { bump_allocator.emplace(); - test_mapper.emplace(memory_size); + test_mapper.emplace(physical_size, virtual_size); old_allocator = set_frame_allocator(*bump_allocator); old_mapper = set_page_mapper(*test_mapper); - init_pmm(memory_size / frame::size, handoff_to_kernel_pmm); + init_pmm(physical_size / frame::size, handoff_to_kernel_pmm); } +} // namespace kapi::memory + +namespace kernel::tests::memory +{ - auto reset() -> void + auto deinit() -> void { if (old_allocator && *old_allocator) { @@ -60,12 +66,9 @@ namespace kapi::memory test_mapper.reset(); } -} // namespace kapi::memory - -namespace kernel::tests::memory -{ - auto heap_base() -> kapi::memory::linear_address + auto virtual_base() -> kapi::memory::linear_address { - return test_mapper->memory.heap_base(); + return test_mapper->memory.virtual_base(); } + } // namespace kernel::tests::memory \ No newline at end of file diff --git a/kernel/src/test_support/log_buffer.cpp b/kernel/src/test_support/log_buffer.cpp index 36ed15e..9cff596 100644 --- a/kernel/src/test_support/log_buffer.cpp +++ b/kernel/src/test_support/log_buffer.cpp @@ -4,36 +4,30 @@ #include #include -namespace kernel::tests::log_buffer +namespace kernel::tests { - namespace + auto log_buffer::append(std::string const & message) -> void { - std::vector recorded_messages{}; + m_messages.push_back(message); } - auto append(std::string const & message) -> void + auto log_buffer::clear() -> void { - recorded_messages.push_back(message); + m_messages.clear(); } - auto clear() -> void + auto log_buffer::flat_messages() -> std::string { - recorded_messages.clear(); + return std::ranges::fold_left(m_messages, std::string{}, [](std::string accumulator, std::string const & message) { + accumulator += message; + return accumulator; + }); } - auto flat_messages() -> std::string + auto log_buffer::messages() -> std::vector const & { - return std::ranges::fold_left(recorded_messages, std::string{}, - [](std::string accumulator, std::string const & message) { - accumulator += message; - return accumulator; - }); + return m_messages; } - auto messages() -> std::vector const & - { - return recorded_messages; - } - -} // namespace kernel::tests::log_buffer +} // namespace kernel::tests diff --git a/kernel/src/test_support/output_device.cpp b/kernel/src/test_support/output_device.cpp new file mode 100644 index 0000000..83dcbcc --- /dev/null +++ b/kernel/src/test_support/output_device.cpp @@ -0,0 +1,28 @@ +#include "kapi/cio.hpp" + +#include "kernel/test_support/cio.hpp" +#include "kernel/test_support/log_buffer.hpp" + +#include +#include +#include + +namespace kernel::tests::cio +{ + + auto output_device::write(kapi::cio::output_stream stream, std::string_view text) -> void + { + auto & standard_stream = stream == kapi::cio::output_stream::stdout ? std::cout : std::cerr; + standard_stream << text; + if (text != "\n") + { + m_log_buffer.append(std::string{text}); + } + } + + auto output_device::log_buffer() noexcept -> kernel::tests::log_buffer & + { + return m_log_buffer; + } + +} // namespace kernel::tests::cio \ No newline at end of file diff --git a/kernel/src/test_support/page_mapper.cpp b/kernel/src/test_support/page_mapper.cpp index abdcae5..9236deb 100644 --- a/kernel/src/test_support/page_mapper.cpp +++ b/kernel/src/test_support/page_mapper.cpp @@ -7,13 +7,12 @@ #include #include #include -#include namespace kernel::tests { - page_mapper::page_mapper(kstd::units::bytes memory_size) - : memory{memory_size} + page_mapper::page_mapper(kstd::units::bytes physical_size, kstd::units::bytes virtual_size) + : memory{physical_size, virtual_size} {} auto page_mapper::map(kapi::memory::page page, kapi::memory::frame frame, flags) -> std::byte * @@ -26,21 +25,14 @@ namespace kernel::tests } auto page_address = page.start_address(); - auto sandbox_start = memory.heap_base(); - auto sandbox_end = sandbox_start + memory.heap_size(); + auto virtual_base = memory.virtual_base(); + auto virtual_end = virtual_base + memory.virtual_size(); - if (page_address >= sandbox_start && page_address < sandbox_end) + if (page_address >= virtual_base && page_address < virtual_end) { auto virtual_target = static_cast(page_address); auto physical_offset = frame.number() * kapi::memory::frame::size; - auto mapped_ptr = mmap(virtual_target, kapi::memory::page::size.value, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_FIXED, memory.memory_descriptor(), physical_offset.value); - if (mapped_ptr == MAP_FAILED) - { - throw std::runtime_error("Failed to map page"); - } - - return static_cast(mapped_ptr); + return memory.map(kapi::memory::page::size, virtual_target, physical_offset.value); } else if (page_address >= kapi::memory::mmio_base) { @@ -49,7 +41,7 @@ namespace kernel::tests else if (page_address >= kapi::memory::higher_half_direct_map_base) { auto offset = frame.number() * kapi::memory::frame::size; - return memory.ram_base() + offset; + return memory.physical_base() + offset; } return nullptr; diff --git a/kernel/src/test_support/simulated_memory.cpp b/kernel/src/test_support/simulated_memory.cpp index fa3d36c..0648df2 100644 --- a/kernel/src/test_support/simulated_memory.cpp +++ b/kernel/src/test_support/simulated_memory.cpp @@ -4,50 +4,50 @@ #include +#include #include #include +#include #include #include #include #include -using namespace kstd::units_literals; - namespace kernel::tests { - namespace - { - constexpr auto virtual_size = 1_GiB; - } - simulated_memory::simulated_memory(kstd::units::bytes size) - : m_memory_descriptor{memfd_create("teachos_simulated_memory", 0)} - , m_size{size} + simulated_memory::simulated_memory(kstd::units::bytes physical_size, kstd::units::bytes virtual_size) + : m_descriptor{memfd_create("teachos_simulated_memory", 0)} + , m_physical_size{physical_size} + , m_virtual_size{virtual_size} { - if (m_memory_descriptor < 0) + if (m_descriptor < 0) { - throw std::runtime_error("Failed to create simulated memory"); + auto error = std::format("Failed to allocate backing memory: {}", strerror(errno)); + throw std::runtime_error(error); } - if (ftruncate(m_memory_descriptor, static_cast(m_size.value)) < 0) + if (ftruncate(m_descriptor, static_cast(m_physical_size.value)) < 0) { - throw std::runtime_error("Failed to resize simulated memory"); + auto error = std::format("Failed to reserve backing memory: {}", strerror(errno)); + throw std::runtime_error(error); } - auto mapped_pointer = mmap(nullptr, m_size.value, PROT_READ | PROT_WRITE, MAP_SHARED, m_memory_descriptor, 0); - if (mapped_pointer == MAP_FAILED) + auto physical_storage = mmap(nullptr, m_physical_size.value, PROT_READ | PROT_WRITE, MAP_SHARED, m_descriptor, 0); + if (physical_storage == MAP_FAILED) { - throw std::runtime_error("Failed to map simulated memory"); + auto error = std::format("Failed to map backing memory: {}", strerror(errno)); + throw std::runtime_error(error); } - m_physical_base = static_cast(mapped_pointer); - auto virtual_pointer = mmap(nullptr, virtual_size.value, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (virtual_pointer == MAP_FAILED) { - throw std::runtime_error("Failed to map simulated memory"); + auto error = std::format("Failed to reserve virtual memory: {}", strerror(errno)); + throw std::runtime_error(error); } + m_physical_base = static_cast(physical_storage); m_virtual_base = static_cast(virtual_pointer); clear(); @@ -55,39 +55,56 @@ namespace kernel::tests simulated_memory::~simulated_memory() { - munmap(m_physical_base, m_size.value); - munmap(m_virtual_base, virtual_size.value); - close(m_memory_descriptor); + munmap(m_virtual_base, m_virtual_size.value); + munmap(m_physical_base, m_physical_size.value); + close(m_descriptor); } auto simulated_memory::clear() -> void { - std::memset(m_physical_base, 0, m_size.value); + std::memset(m_physical_base, 0, m_physical_size.value); } - auto simulated_memory::ram_base() noexcept -> std::byte * + auto simulated_memory::physical_base() noexcept -> std::byte * { return m_physical_base; } - auto simulated_memory::ram_base() const noexcept -> std::byte const * + auto simulated_memory::physical_base() const noexcept -> std::byte const * { return m_physical_base; } - auto simulated_memory::heap_base() const noexcept -> kapi::memory::linear_address + auto simulated_memory::physical_size() const noexcept -> kstd::units::bytes + { + return m_physical_size; + } + + auto simulated_memory::virtual_base() const noexcept -> kapi::memory::linear_address { return kapi::memory::linear_address{m_virtual_base}; } - auto simulated_memory::heap_size() const noexcept -> kstd::units::bytes + auto simulated_memory::virtual_size() const noexcept -> kstd::units::bytes { - return virtual_size; + return m_virtual_size; } - auto simulated_memory::memory_descriptor() const noexcept -> int + auto simulated_memory::descriptor() const noexcept -> int { - return m_memory_descriptor; + return m_descriptor; + } + + auto simulated_memory::map(kstd::units::bytes size, std::byte * to, off_t offset) -> std::byte * + { + auto mapped_ptr = mmap(to, size.value, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, m_descriptor, offset); + if (mapped_ptr == MAP_FAILED) + { + auto error = std::format("Failed to map page: {}", strerror(errno)); + throw std::runtime_error(error); + } + + return static_cast(mapped_ptr); } } // namespace kernel::tests \ No newline at end of file diff --git a/kernel/src/test_support/state_reset_listener.cpp b/kernel/src/test_support/state_reset_listener.cpp index e201a10..8c95cc8 100644 --- a/kernel/src/test_support/state_reset_listener.cpp +++ b/kernel/src/test_support/state_reset_listener.cpp @@ -2,29 +2,15 @@ #include "kapi/cpu.hpp" #include "kapi/memory.hpp" +#include "kernel/test_support/cio.hpp" +#include "kernel/test_support/cpu.hpp" +#include "kernel/test_support/memory.hpp" + #include #include #include #include -namespace kapi -{ - namespace cio - { - auto reset() -> void; - } - - namespace cpu - { - auto reset() -> void; - } - - namespace memory - { - auto reset() -> void; - } -} // namespace kapi - struct state_reset_listener : Catch::EventListenerBase { using EventListenerBase::EventListenerBase; @@ -38,9 +24,9 @@ struct state_reset_listener : Catch::EventListenerBase void testCaseEnded(Catch::TestCaseStats const &) override { - kapi::memory::reset(); - kapi::cpu::reset(); - kapi::cio::reset(); + kernel::tests::memory::deinit(); + kernel::tests::cpu::deinit(); + kernel::tests::cio::deinit(); } }; -- cgit v1.2.3 From 39d2696ee75db377c7e31fda1e29e4a7d3cfb378 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 2 Apr 2026 10:15:18 +0200 Subject: kernel/tests: improve documentation --- kernel/src/test_support/simulated_memory.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/test_support/simulated_memory.cpp b/kernel/src/test_support/simulated_memory.cpp index 0648df2..03dac1d 100644 --- a/kernel/src/test_support/simulated_memory.cpp +++ b/kernel/src/test_support/simulated_memory.cpp @@ -90,11 +90,6 @@ namespace kernel::tests return m_virtual_size; } - auto simulated_memory::descriptor() const noexcept -> int - { - return m_descriptor; - } - auto simulated_memory::map(kstd::units::bytes size, std::byte * to, off_t offset) -> std::byte * { auto mapped_ptr = mmap(to, size.value, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, m_descriptor, offset); -- cgit v1.2.3 From d0c532af74d8d486d734904fd330d5dae7f49754 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 2 Apr 2026 13:36:01 +0200 Subject: kapi: add basic device subsystem --- kernel/src/devices/root_bus.cpp | 55 +++++++++++++++++++++++++++++++++++++++++ kernel/src/main.cpp | 4 +++ 2 files changed, 59 insertions(+) create mode 100644 kernel/src/devices/root_bus.cpp (limited to 'kernel/src') diff --git a/kernel/src/devices/root_bus.cpp b/kernel/src/devices/root_bus.cpp new file mode 100644 index 0000000..a7f3c1a --- /dev/null +++ b/kernel/src/devices/root_bus.cpp @@ -0,0 +1,55 @@ +#include "kernel/devices/root_bus.hpp" + +#include "kapi/devices.hpp" +#include "kapi/devices/bus.hpp" +#include "kapi/devices/device.hpp" +#include "kapi/system.hpp" + +#include +#include +#include + +#include +#include + +namespace kernel::devices +{ + + root_bus::root_bus() + : kapi::devices::bus{kapi::devices::allocate_major_number(), 0, "system"} + {} + + auto root_bus::add_child(kstd::unique_ptr child) -> void + { + auto observer = m_observers.emplace_back(child.get()); + m_children.push_back(std::move(child)); + + if (m_initialized) + { + kstd::println("Initializing child device '{}'", observer->name()); + if (!observer->init()) + { + kapi::system::panic("[kernel:devices] Failed to initialize child device"); + } + } + } + + auto root_bus::children() const -> kstd::vector> const & + { + return m_observers; + } + + auto root_bus::init() -> bool + { + if (m_initialized) + { + kapi::system::panic("[kernel:devices] Root bus already initialized!"); + } + + return std::ranges::fold_left(m_children, true, [](bool acc, auto & child) -> bool { + kstd::println("[kernel:devices] Initializing child device '{}'", child->name()); + return acc && child->init(); + }); + } + +} // namespace kernel::devices \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 37b4c5b..9d6028d 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,6 +1,7 @@ #include "kapi/boot_modules.hpp" #include "kapi/cio.hpp" #include "kapi/cpu.hpp" +#include "kapi/devices.hpp" #include "kapi/interrupts.hpp" #include "kapi/memory.hpp" #include "kapi/system.hpp" @@ -179,6 +180,9 @@ auto main() -> int kstd::println("[OS] Memory subsystem initialized."); kapi::system::memory_initialized(); + kapi::devices::init(); + kstd::println("[OS] System root bus initialized."); + kapi::boot_modules::init(); kstd::println("[OS] Boot module registry initialized."); -- cgit v1.2.3 From b84c4c9d8c90f3d3fd5a60de282278912fad2f04 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 2 Apr 2026 13:59:27 +0200 Subject: x86_64/devices: implement ISA bus stub --- kernel/src/devices/root_bus.cpp | 4 ++-- kernel/src/main.cpp | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/devices/root_bus.cpp b/kernel/src/devices/root_bus.cpp index a7f3c1a..75b5b80 100644 --- a/kernel/src/devices/root_bus.cpp +++ b/kernel/src/devices/root_bus.cpp @@ -24,7 +24,7 @@ namespace kernel::devices auto observer = m_observers.emplace_back(child.get()); m_children.push_back(std::move(child)); - if (m_initialized) + if (m_initialized.test()) { kstd::println("Initializing child device '{}'", observer->name()); if (!observer->init()) @@ -41,7 +41,7 @@ namespace kernel::devices auto root_bus::init() -> bool { - if (m_initialized) + if (m_initialized.test_and_set()) { kapi::system::panic("[kernel:devices] Root bus already initialized!"); } diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 9d6028d..eaaf87f 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -183,6 +183,9 @@ auto main() -> int kapi::devices::init(); kstd::println("[OS] System root bus initialized."); + kapi::devices::init_platform_devices(); + kstd::println("[OS] Platform devices initialized."); + kapi::boot_modules::init(); kstd::println("[OS] Boot module registry initialized."); -- cgit v1.2.3 From 66ffd2ad8c793c4eea1527848fe4772e42595718 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 2 Apr 2026 14:24:52 +0200 Subject: kapi: extract common bus code --- kernel/src/devices/root_bus.cpp | 43 ----------------------------------------- 1 file changed, 43 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/devices/root_bus.cpp b/kernel/src/devices/root_bus.cpp index 75b5b80..d3ba23f 100644 --- a/kernel/src/devices/root_bus.cpp +++ b/kernel/src/devices/root_bus.cpp @@ -1,16 +1,6 @@ #include "kernel/devices/root_bus.hpp" #include "kapi/devices.hpp" -#include "kapi/devices/bus.hpp" -#include "kapi/devices/device.hpp" -#include "kapi/system.hpp" - -#include -#include -#include - -#include -#include namespace kernel::devices { @@ -19,37 +9,4 @@ namespace kernel::devices : kapi::devices::bus{kapi::devices::allocate_major_number(), 0, "system"} {} - auto root_bus::add_child(kstd::unique_ptr child) -> void - { - auto observer = m_observers.emplace_back(child.get()); - m_children.push_back(std::move(child)); - - if (m_initialized.test()) - { - kstd::println("Initializing child device '{}'", observer->name()); - if (!observer->init()) - { - kapi::system::panic("[kernel:devices] Failed to initialize child device"); - } - } - } - - auto root_bus::children() const -> kstd::vector> const & - { - return m_observers; - } - - auto root_bus::init() -> bool - { - if (m_initialized.test_and_set()) - { - kapi::system::panic("[kernel:devices] Root bus already initialized!"); - } - - return std::ranges::fold_left(m_children, true, [](bool acc, auto & child) -> bool { - kstd::println("[kernel:devices] Initializing child device '{}'", child->name()); - return acc && child->init(); - }); - } - } // namespace kernel::devices \ No newline at end of file -- cgit v1.2.3 From ab4c59912c526d515e6e72188c08a7f92e5573e8 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 2 Apr 2026 15:07:54 +0200 Subject: x86_64: implement legacy PIT driver --- kernel/src/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index eaaf87f..2eaa2d8 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -173,7 +173,6 @@ auto main() -> int kstd::println("[OS] IO subsystem initialized."); kapi::cpu::init(); - kapi::interrupts::enable(); kapi::memory::init(); kernel::memory::init_heap(kapi::memory::heap_base); @@ -186,6 +185,9 @@ auto main() -> int kapi::devices::init_platform_devices(); kstd::println("[OS] Platform devices initialized."); + kapi::interrupts::enable(); + kstd::println("[OS] Interrupts enabled."); + kapi::boot_modules::init(); kstd::println("[OS] Boot module registry initialized."); -- cgit v1.2.3 From 21489576381d827871e7cdf060929c5d7f3d4e9f Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 2 Apr 2026 15:49:14 +0200 Subject: devices: don't automatically allocate major numbers in ctors --- kernel/src/devices/root_bus.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/devices/root_bus.cpp b/kernel/src/devices/root_bus.cpp index d3ba23f..43a35bf 100644 --- a/kernel/src/devices/root_bus.cpp +++ b/kernel/src/devices/root_bus.cpp @@ -6,7 +6,7 @@ namespace kernel::devices { root_bus::root_bus() - : kapi::devices::bus{kapi::devices::allocate_major_number(), 0, "system"} + : kapi::devices::bus{0, 0, "system"} {} } // namespace kernel::devices \ No newline at end of file -- cgit v1.2.3 From 3dcd14a0570fef3bcc68d7df42fe3ff4cd496f93 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 6 Apr 2026 14:47:37 +0200 Subject: kapi: hook ACPI initialization up to boot process --- kernel/src/acpi/manager.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 kernel/src/acpi/manager.cpp (limited to 'kernel/src') diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp new file mode 100644 index 0000000..6a17920 --- /dev/null +++ b/kernel/src/acpi/manager.cpp @@ -0,0 +1,54 @@ +#include "kernel/acpi/manager.hpp" + +#include "kapi/acpi.hpp" +#include "kapi/memory.hpp" +#include "kapi/system.hpp" + +#include + +namespace kernel::acpi +{ + + manager::manager(kapi::acpi::root_system_description_pointer const & sdp) + : m_sdp{&sdp} + { + if (m_sdp->signature() != "RSD PTR ") + { + kapi::system::panic("[OS:ACPI] Invalid RSDP signature!"); + } + + if (m_sdp->revision() >= 2) + { + auto const xsdp = static_cast(m_sdp); + if (!xsdp->validate()) + { + kapi::system::panic("[OS:ACPI] Invalid XSDP signature!"); + } + auto physical_extended_table_address = xsdp->table_address(); + auto linear_extended_table_address = kapi::memory::hhdm_to_linear(physical_extended_table_address); + m_rsdt = static_cast(linear_extended_table_address); + m_extended = true; + } + else + { + if (!m_sdp->validate()) + { + kapi::system::panic("[OS:ACPI] Invalid RSDP checksum!"); + } + auto physical_root_table_address = m_sdp->table_address(); + auto linear_root_table_address = kapi::memory::hhdm_to_linear(physical_root_table_address); + m_rsdt = static_cast(linear_root_table_address); + } + } + + auto manager::load_tables() -> bool + { + if (!kapi::acpi::validate_checksum({reinterpret_cast(m_rsdt), m_rsdt->length})) + { + kapi::system::panic("[OS:ACPI] Invalid RSDT checksum!"); + } + + return false; + } + +} // namespace kernel::acpi -- cgit v1.2.3 From 4d938cd31a35cd4322fe914edd568faa5391c9c2 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 6 Apr 2026 15:10:04 +0200 Subject: kernel/acpi: implement basic table discovery --- kernel/src/acpi/manager.cpp | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp index 6a17920..180d458 100644 --- a/kernel/src/acpi/manager.cpp +++ b/kernel/src/acpi/manager.cpp @@ -4,7 +4,10 @@ #include "kapi/memory.hpp" #include "kapi/system.hpp" +#include + #include +#include namespace kernel::acpi { @@ -43,12 +46,47 @@ namespace kernel::acpi auto manager::load_tables() -> bool { - if (!kapi::acpi::validate_checksum({reinterpret_cast(m_rsdt), m_rsdt->length})) + if (!kapi::acpi::validate_checksum({reinterpret_cast(m_rsdt), m_rsdt->length().value})) { kapi::system::panic("[OS:ACPI] Invalid RSDT checksum!"); } - return false; + auto entry_size = m_extended ? sizeof(std::uint64_t) : sizeof(std::uint32_t); + auto entry_count = (m_rsdt->length().value - sizeof(kapi::acpi::system_description_table_header)) / entry_size; + auto entries_base = + reinterpret_cast(m_rsdt) + sizeof(kapi::acpi::system_description_table_header); + + for (std::size_t i = 0; i < entry_count; ++i) + { + auto physical_table_address = kapi::memory::physical_address{}; + + if (m_extended) + { + auto entry = reinterpret_cast(entries_base + (i * entry_size)); + physical_table_address = kapi::memory::physical_address{*entry}; + } + else + { + auto entry = reinterpret_cast(entries_base + (i * entry_size)); + physical_table_address = kapi::memory::physical_address{*entry}; + } + + auto linear_table_address = kapi::memory::hhdm_to_linear(physical_table_address); + auto table = static_cast(linear_table_address); + + if (!kapi::acpi::validate_checksum({reinterpret_cast(table), table->length().value})) + { + kstd::println(kstd::print_sink::stderr, "[OS:ACPI] Invalid table checksum!"); + } + else + { + kstd::println("[OS:ACPI] Found table: {}@{:#x}/{:#x} OEM: {} Rev: {}", table->signature(), linear_table_address, + physical_table_address, table->oem_id(), table->creator_revision()); + m_tables.emplace(table->signature(), table); + } + } + + return !m_tables.empty(); } } // namespace kernel::acpi -- cgit v1.2.3 From f456f1674d48932846eb7b5ec1df630ad67e7e3d Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 6 Apr 2026 17:24:36 +0200 Subject: kernel/acpi: discover local interrupt controllers --- kernel/src/acpi/manager.cpp | 15 ++++++- kernel/src/devices/cpu.cpp | 97 +++++++++++++++++++++++++++++++++++++++++++++ kernel/src/main.cpp | 10 +++++ 3 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 kernel/src/devices/cpu.cpp (limited to 'kernel/src') diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp index 180d458..300b85e 100644 --- a/kernel/src/acpi/manager.cpp +++ b/kernel/src/acpi/manager.cpp @@ -4,10 +4,12 @@ #include "kapi/memory.hpp" #include "kapi/system.hpp" +#include #include #include #include +#include namespace kernel::acpi { @@ -80,8 +82,7 @@ namespace kernel::acpi } else { - kstd::println("[OS:ACPI] Found table: {}@{:#x}/{:#x} OEM: {} Rev: {}", table->signature(), linear_table_address, - physical_table_address, table->oem_id(), table->creator_revision()); + kstd::println("[OS:ACPI] Found '{}' ACPI table", table->signature()); m_tables.emplace(table->signature(), table); } } @@ -89,4 +90,14 @@ namespace kernel::acpi return !m_tables.empty(); } + auto manager::get_table(std::string_view signature) + -> kstd::observer_ptr + { + if (m_tables.contains(signature)) + { + return kstd::make_observer(m_tables.at(signature)); + } + return nullptr; + } + } // namespace kernel::acpi diff --git a/kernel/src/devices/cpu.cpp b/kernel/src/devices/cpu.cpp new file mode 100644 index 0000000..7147368 --- /dev/null +++ b/kernel/src/devices/cpu.cpp @@ -0,0 +1,97 @@ +#include "kernel/devices/cpu.hpp" + +#include "kapi/acpi.hpp" +#include "kapi/devices.hpp" + +#include +#include + +#include +#include +#include + +namespace kernel::devices +{ + + namespace + { + + auto process_madt(kstd::observer_ptr madt, kapi::devices::bus & cpu) -> void + { + auto static const core_major = kapi::devices::allocate_major_number(); + auto static const lapic_major = kapi::devices::allocate_major_number(); + + auto lapic_address = madt->local_interrupt_controller_address(); + + auto const * current = reinterpret_cast(madt.get()) + sizeof(kapi::acpi::madt_header); + auto const * end = reinterpret_cast(madt.get()) + madt->length(); + + auto bsp_found = false; + auto core_index = 0; + + while (current < end) + { + auto const * sub_table = reinterpret_cast(current); + if (sub_table->type() == 0) + { + auto const * local_apic = reinterpret_cast(sub_table); + if (local_apic->flags() & 0b11) + { + auto is_bsp = !bsp_found; + bsp_found = true; + + auto apic_id = local_apic->apic_id(); + auto core = kstd::make_unique(core_major, core_index, apic_id, is_bsp); + auto lapic = kapi::acpi::create_local_interrupt_controller(lapic_major, core_index, apic_id, lapic_address); + + core->add_child(std::move(lapic)); + cpu.add_child(std::move(core)); + + ++core_index; + } + } + + current += sub_table->length(); + } + + kstd::println("[OS:DEV] Discovered {} CPU cores", core_index); + } + + } // namespace + + cpu::core::core(std::size_t major_number, std::size_t minor_number, std::uint64_t hardware_id, bool is_bsp) + : kapi::devices::bus{major_number, minor_number, "cpu_core"} + , m_hardware_id{hardware_id} + , m_is_bsp{is_bsp} + {} + + auto cpu::core::hardware_id() const -> std::uint64_t + { + return m_hardware_id; + } + + auto cpu::core::is_bsp() const -> bool + { + return m_is_bsp; + } + + cpu::cpu(std::size_t major_number) + : kapi::devices::bus{major_number, 0, "cpu"} + {} + + auto cpu::probe() -> bool + { + auto madt = kapi::acpi::get_table("APIC"); + if (!madt) + { + kstd::println("[OS:DEV] Failed to find ACPI APIC table"); + return false; + } + + auto madt_header = static_cast(madt.get()); + process_madt(kstd::make_observer(madt_header), *this); + + return true; + } + +} // namespace kernel::devices \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 2eaa2d8..e704955 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,3 +1,4 @@ +#include "kapi/acpi.hpp" #include "kapi/boot_modules.hpp" #include "kapi/cio.hpp" #include "kapi/cpu.hpp" @@ -179,6 +180,15 @@ auto main() -> int kstd::println("[OS] Memory subsystem initialized."); kapi::system::memory_initialized(); + auto acpi_root_pointer = kapi::acpi::get_root_pointer(); + if (acpi_root_pointer && acpi_root_pointer->validate()) + { + if (kapi::acpi::init(*acpi_root_pointer)) + { + kstd::println("[OS] ACPI subsystem initialized."); + } + } + kapi::devices::init(); kstd::println("[OS] System root bus initialized."); -- cgit v1.2.3 From f50815110789a0f8f6e5ca66ffd49b26578791a9 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 6 Apr 2026 18:43:28 +0200 Subject: kernel: generalize CPU discovery --- kernel/src/devices/cpu.cpp | 58 +++------------------------------------------- 1 file changed, 3 insertions(+), 55 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/devices/cpu.cpp b/kernel/src/devices/cpu.cpp index 7147368..eb10d74 100644 --- a/kernel/src/devices/cpu.cpp +++ b/kernel/src/devices/cpu.cpp @@ -1,64 +1,16 @@ #include "kernel/devices/cpu.hpp" -#include "kapi/acpi.hpp" #include "kapi/devices.hpp" +#include "kapi/platform.hpp" -#include #include #include #include -#include namespace kernel::devices { - namespace - { - - auto process_madt(kstd::observer_ptr madt, kapi::devices::bus & cpu) -> void - { - auto static const core_major = kapi::devices::allocate_major_number(); - auto static const lapic_major = kapi::devices::allocate_major_number(); - - auto lapic_address = madt->local_interrupt_controller_address(); - - auto const * current = reinterpret_cast(madt.get()) + sizeof(kapi::acpi::madt_header); - auto const * end = reinterpret_cast(madt.get()) + madt->length(); - - auto bsp_found = false; - auto core_index = 0; - - while (current < end) - { - auto const * sub_table = reinterpret_cast(current); - if (sub_table->type() == 0) - { - auto const * local_apic = reinterpret_cast(sub_table); - if (local_apic->flags() & 0b11) - { - auto is_bsp = !bsp_found; - bsp_found = true; - - auto apic_id = local_apic->apic_id(); - auto core = kstd::make_unique(core_major, core_index, apic_id, is_bsp); - auto lapic = kapi::acpi::create_local_interrupt_controller(lapic_major, core_index, apic_id, lapic_address); - - core->add_child(std::move(lapic)); - cpu.add_child(std::move(core)); - - ++core_index; - } - } - - current += sub_table->length(); - } - - kstd::println("[OS:DEV] Discovered {} CPU cores", core_index); - } - - } // namespace - cpu::core::core(std::size_t major_number, std::size_t minor_number, std::uint64_t hardware_id, bool is_bsp) : kapi::devices::bus{major_number, minor_number, "cpu_core"} , m_hardware_id{hardware_id} @@ -81,16 +33,12 @@ namespace kernel::devices auto cpu::probe() -> bool { - auto madt = kapi::acpi::get_table("APIC"); - if (!madt) + if (!kapi::platform::discover_cpu_topology(*this)) { - kstd::println("[OS:DEV] Failed to find ACPI APIC table"); + kstd::println("[OS:DEV] Failed to discover CPU topology"); return false; } - auto madt_header = static_cast(madt.get()); - process_madt(kstd::make_observer(madt_header), *this); - return true; } -- cgit v1.2.3 From 8ad4fad2440c20aa19e26ade8cdb881cab7734e2 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 6 Apr 2026 19:09:34 +0200 Subject: kernel/tests: fix link issue --- kernel/src/test_support/kapi/platform.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 kernel/src/test_support/kapi/platform.cpp (limited to 'kernel/src') diff --git a/kernel/src/test_support/kapi/platform.cpp b/kernel/src/test_support/kapi/platform.cpp new file mode 100644 index 0000000..497c992 --- /dev/null +++ b/kernel/src/test_support/kapi/platform.cpp @@ -0,0 +1,14 @@ +#include "kapi/platform.hpp" + +#include "kapi/devices.hpp" + +namespace kapi::platform +{ + + auto discover_cpu_topology(devices::bus &) -> bool + { + // TODO: implement more meaningful simulated CPU topology discovery + return true; + } + +} // namespace kapi::platform \ No newline at end of file -- cgit v1.2.3 From 878852c94c4d56f303366cec177b3edef9b3b9c5 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 8 Apr 2026 13:54:52 +0200 Subject: kapi: add basic support for MMIO mapping --- kernel/src/memory/mmio_allocator.cpp | 107 +++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 kernel/src/memory/mmio_allocator.cpp (limited to 'kernel/src') diff --git a/kernel/src/memory/mmio_allocator.cpp b/kernel/src/memory/mmio_allocator.cpp new file mode 100644 index 0000000..f77f14f --- /dev/null +++ b/kernel/src/memory/mmio_allocator.cpp @@ -0,0 +1,107 @@ +#include "kernel/memory/mmio_allocator.hpp" + +#include "kapi/memory.hpp" +#include "kapi/system.hpp" + +#include + +#include +#include +#include + +namespace kernel::memory +{ + + mmio_allocator::mmio_allocator(kapi::memory::linear_address base, std::size_t pages) + : m_head{make_node(base, pages, nullptr, nullptr, true)} + {} + + auto mmio_allocator::allocate(std::size_t count) -> kapi::memory::linear_address + { + if (count == 0 || !m_head) + { + return {}; + } + + auto current = m_head; + while (current) + { + if (current->page_count > count) + { + auto new_base = current->base + (count * kapi::memory::page::size); + auto split_node = make_node(new_base, current->page_count - count, std::move(current->next), current, true); + + if (current->next) + { + current->next->previous = split_node; + } + current->next = split_node; + current->page_count = count; + } + + current->is_free = false; + return current->base; + } + + kapi::system::panic("[OS:MEM] MMIO alloctor out of memory!"); + return {}; + } + + auto mmio_allocator::release(kapi::memory::linear_address base) -> void + { + auto current = m_head; + + while (current) + { + if (current->base == base && !current->is_free) + { + current->is_free = true; + + if (current->next && current->next->is_free) + { + auto removed = current->next; + current->page_count += removed->page_count; + current->next = removed->next; + if (current->next) + { + current->next->previous = current; + } + destroy_node(removed); + } + + if (current->previous && current->previous->is_free) + { + auto removed = current; + removed->previous->page_count += removed->page_count; + removed->previous->next = removed->next; + if (removed->next) + { + removed->next->previous = removed->previous; + } + destroy_node(removed); + } + return; + } + current = current->next; + } + } + + auto mmio_allocator::make_node(kapi::memory::linear_address base, std::size_t page_count, node * next, + node * previous, bool is_free) -> node * + { + using traits = std::allocator_traits>; + + auto new_node = traits::allocate(m_allocator, 1); + traits::construct(m_allocator, new_node, base, page_count, next, previous, is_free); + return new_node; + } + + auto mmio_allocator::destroy_node(node * instance) -> void + { + using traits = std::allocator_traits>; + + traits::destroy(m_allocator, instance); + traits::deallocate(m_allocator, instance, 1); + } + +} // namespace kernel::memory -- cgit v1.2.3 From 1c52a859d105f6b0f8afb16565b10435fa728882 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 8 Apr 2026 14:15:56 +0200 Subject: kapi: fix mmio initialization --- kernel/src/main.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index e704955..4b61948 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -19,11 +19,14 @@ #include #include #include +#include #include #include #include +using namespace kstd::units_literals; + auto test_device_names() -> void { auto storage_mgmt = kernel::devices::storage::management::get(); @@ -177,8 +180,9 @@ auto main() -> int kapi::memory::init(); kernel::memory::init_heap(kapi::memory::heap_base); - kstd::println("[OS] Memory subsystem initialized."); kapi::system::memory_initialized(); + kapi::memory::init_mmio(kapi::memory::mmio_base, 1_GiB / kapi::memory::page::size); + kstd::println("[OS] Memory subsystem initialized."); auto acpi_root_pointer = kapi::acpi::get_root_pointer(); if (acpi_root_pointer && acpi_root_pointer->validate()) -- cgit v1.2.3 From 77b408b4e18fabb29f4cab5e899e7c8db1bc1204 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 8 Apr 2026 14:16:13 +0200 Subject: kernel: fix mmio allocator --- kernel/src/memory/mmio_allocator.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/memory/mmio_allocator.cpp b/kernel/src/memory/mmio_allocator.cpp index f77f14f..ddbdfc2 100644 --- a/kernel/src/memory/mmio_allocator.cpp +++ b/kernel/src/memory/mmio_allocator.cpp @@ -26,21 +26,25 @@ namespace kernel::memory auto current = m_head; while (current) { - if (current->page_count > count) + if (current->is_free && current->page_count >= count) { - auto new_base = current->base + (count * kapi::memory::page::size); - auto split_node = make_node(new_base, current->page_count - count, std::move(current->next), current, true); - - if (current->next) + if (current->page_count > count) { - current->next->previous = split_node; + auto new_base = current->base + (count * kapi::memory::page::size); + auto split_node = make_node(new_base, current->page_count - count, std::move(current->next), current, true); + + if (current->next) + { + current->next->previous = split_node; + } + current->next = split_node; + current->page_count = count; } - current->next = split_node; - current->page_count = count; - } - current->is_free = false; - return current->base; + current->is_free = false; + return current->base; + } + current = current->next; } kapi::system::panic("[OS:MEM] MMIO alloctor out of memory!"); -- cgit v1.2.3 From 3ad230fab8dc17758559aac3c20ba67a8c619878 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 10 Apr 2026 09:01:59 +0200 Subject: kapi: move platform functions to CPU --- kernel/src/devices/cpu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/devices/cpu.cpp b/kernel/src/devices/cpu.cpp index eb10d74..85f4d47 100644 --- a/kernel/src/devices/cpu.cpp +++ b/kernel/src/devices/cpu.cpp @@ -1,7 +1,7 @@ #include "kernel/devices/cpu.hpp" +#include "kapi/cpu.hpp" #include "kapi/devices.hpp" -#include "kapi/platform.hpp" #include @@ -33,7 +33,7 @@ namespace kernel::devices auto cpu::probe() -> bool { - if (!kapi::platform::discover_cpu_topology(*this)) + if (!kapi::cpu::discover_topology(*this)) { kstd::println("[OS:DEV] Failed to discover CPU topology"); return false; -- cgit v1.2.3 From ed663488a66383e136534a5c43c66ef5868cb2d3 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 10 Apr 2026 09:53:25 +0200 Subject: fixup! kapi: move platform functions to CPU --- kernel/src/test_support/kapi/cpu.cpp | 7 +++++++ kernel/src/test_support/kapi/platform.cpp | 14 -------------- 2 files changed, 7 insertions(+), 14 deletions(-) delete mode 100644 kernel/src/test_support/kapi/platform.cpp (limited to 'kernel/src') diff --git a/kernel/src/test_support/kapi/cpu.cpp b/kernel/src/test_support/kapi/cpu.cpp index 96dd10a..a89bec8 100644 --- a/kernel/src/test_support/kapi/cpu.cpp +++ b/kernel/src/test_support/kapi/cpu.cpp @@ -1,5 +1,6 @@ #include "kernel/test_support/cpu.hpp" +#include "kapi/devices.hpp" #include #include @@ -28,6 +29,12 @@ namespace kapi::cpu throw kernel::tests::cpu::halt{}; } + auto discover_topology(devices::bus &) -> bool + { + // TODO: implement more meaningful simulated CPU topology discovery + return true; + } + } // namespace kapi::cpu namespace kernel::tests::cpu diff --git a/kernel/src/test_support/kapi/platform.cpp b/kernel/src/test_support/kapi/platform.cpp deleted file mode 100644 index 497c992..0000000 --- a/kernel/src/test_support/kapi/platform.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "kapi/platform.hpp" - -#include "kapi/devices.hpp" - -namespace kapi::platform -{ - - auto discover_cpu_topology(devices::bus &) -> bool - { - // TODO: implement more meaningful simulated CPU topology discovery - return true; - } - -} // namespace kapi::platform \ No newline at end of file -- cgit v1.2.3 From dd8dfa3e674d05927e9ed4b7efcb634a634bfdcc Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 10 Apr 2026 10:30:32 +0200 Subject: kapi: move CPU to kapi --- kernel/src/devices/cpu.cpp | 45 ------------------------------------ kernel/src/test_support/kapi/cpu.cpp | 3 +-- 2 files changed, 1 insertion(+), 47 deletions(-) delete mode 100644 kernel/src/devices/cpu.cpp (limited to 'kernel/src') diff --git a/kernel/src/devices/cpu.cpp b/kernel/src/devices/cpu.cpp deleted file mode 100644 index 85f4d47..0000000 --- a/kernel/src/devices/cpu.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "kernel/devices/cpu.hpp" - -#include "kapi/cpu.hpp" -#include "kapi/devices.hpp" - -#include - -#include -#include - -namespace kernel::devices -{ - - cpu::core::core(std::size_t major_number, std::size_t minor_number, std::uint64_t hardware_id, bool is_bsp) - : kapi::devices::bus{major_number, minor_number, "cpu_core"} - , m_hardware_id{hardware_id} - , m_is_bsp{is_bsp} - {} - - auto cpu::core::hardware_id() const -> std::uint64_t - { - return m_hardware_id; - } - - auto cpu::core::is_bsp() const -> bool - { - return m_is_bsp; - } - - cpu::cpu(std::size_t major_number) - : kapi::devices::bus{major_number, 0, "cpu"} - {} - - auto cpu::probe() -> bool - { - if (!kapi::cpu::discover_topology(*this)) - { - kstd::println("[OS:DEV] Failed to discover CPU topology"); - return false; - } - - return true; - } - -} // namespace kernel::devices \ No newline at end of file diff --git a/kernel/src/test_support/kapi/cpu.cpp b/kernel/src/test_support/kapi/cpu.cpp index a89bec8..671097e 100644 --- a/kernel/src/test_support/kapi/cpu.cpp +++ b/kernel/src/test_support/kapi/cpu.cpp @@ -1,6 +1,5 @@ #include "kernel/test_support/cpu.hpp" -#include "kapi/devices.hpp" #include #include @@ -29,7 +28,7 @@ namespace kapi::cpu throw kernel::tests::cpu::halt{}; } - auto discover_topology(devices::bus &) -> bool + auto discover_topology() -> bool { // TODO: implement more meaningful simulated CPU topology discovery return true; -- cgit v1.2.3 From c3f7b747f02a79b34ed914c54ce74be973b17af1 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 10 Apr 2026 17:39:14 +0200 Subject: kapi: extract ACPI functionality to libs --- kernel/src/acpi/manager.cpp | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp index 300b85e..501ce92 100644 --- a/kernel/src/acpi/manager.cpp +++ b/kernel/src/acpi/manager.cpp @@ -1,12 +1,13 @@ #include "kernel/acpi/manager.hpp" -#include "kapi/acpi.hpp" #include "kapi/memory.hpp" #include "kapi/system.hpp" #include #include +#include + #include #include #include @@ -14,7 +15,7 @@ namespace kernel::acpi { - manager::manager(kapi::acpi::root_system_description_pointer const & sdp) + manager::manager(::acpi::rsdp const & sdp) : m_sdp{&sdp} { if (m_sdp->signature() != "RSD PTR ") @@ -24,14 +25,14 @@ namespace kernel::acpi if (m_sdp->revision() >= 2) { - auto const xsdp = static_cast(m_sdp); + auto const xsdp = static_cast<::acpi::xsdp const *>(m_sdp); if (!xsdp->validate()) { kapi::system::panic("[OS:ACPI] Invalid XSDP signature!"); } - auto physical_extended_table_address = xsdp->table_address(); + auto physical_extended_table_address = kapi::memory::physical_address{xsdp->table_address()}; auto linear_extended_table_address = kapi::memory::hhdm_to_linear(physical_extended_table_address); - m_rsdt = static_cast(linear_extended_table_address); + m_rsdt = static_cast<::acpi::sdt const *>(linear_extended_table_address); m_extended = true; } else @@ -40,23 +41,22 @@ namespace kernel::acpi { kapi::system::panic("[OS:ACPI] Invalid RSDP checksum!"); } - auto physical_root_table_address = m_sdp->table_address(); + auto physical_root_table_address = kapi::memory::physical_address{m_sdp->table_address()}; auto linear_root_table_address = kapi::memory::hhdm_to_linear(physical_root_table_address); - m_rsdt = static_cast(linear_root_table_address); + m_rsdt = static_cast<::acpi::sdt const *>(linear_root_table_address); } } auto manager::load_tables() -> bool { - if (!kapi::acpi::validate_checksum({reinterpret_cast(m_rsdt), m_rsdt->length().value})) + if (!::acpi::validate_checksum({reinterpret_cast(m_rsdt), m_rsdt->length().value})) { kapi::system::panic("[OS:ACPI] Invalid RSDT checksum!"); } auto entry_size = m_extended ? sizeof(std::uint64_t) : sizeof(std::uint32_t); - auto entry_count = (m_rsdt->length().value - sizeof(kapi::acpi::system_description_table_header)) / entry_size; - auto entries_base = - reinterpret_cast(m_rsdt) + sizeof(kapi::acpi::system_description_table_header); + auto entry_count = (m_rsdt->length().value - sizeof(::acpi::sdt)) / entry_size; + auto entries_base = reinterpret_cast(m_rsdt) + sizeof(::acpi::sdt); for (std::size_t i = 0; i < entry_count; ++i) { @@ -74,9 +74,9 @@ namespace kernel::acpi } auto linear_table_address = kapi::memory::hhdm_to_linear(physical_table_address); - auto table = static_cast(linear_table_address); + auto table = static_cast<::acpi::sdt const *>(linear_table_address); - if (!kapi::acpi::validate_checksum({reinterpret_cast(table), table->length().value})) + if (!::acpi::validate_checksum({reinterpret_cast(table), table->length().value})) { kstd::println(kstd::print_sink::stderr, "[OS:ACPI] Invalid table checksum!"); } @@ -90,8 +90,7 @@ namespace kernel::acpi return !m_tables.empty(); } - auto manager::get_table(std::string_view signature) - -> kstd::observer_ptr + auto manager::get_table(std::string_view signature) -> kstd::observer_ptr<::acpi::sdt const> { if (m_tables.contains(signature)) { -- cgit v1.2.3 From 21fd1281cf19572e202d583689b99c33ec68da50 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 10 Apr 2026 17:49:40 +0200 Subject: kernel: let arch initialize the ACPI manager --- kernel/src/main.cpp | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 4b61948..b920674 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,4 +1,3 @@ -#include "kapi/acpi.hpp" #include "kapi/boot_modules.hpp" #include "kapi/cio.hpp" #include "kapi/cpu.hpp" @@ -184,15 +183,6 @@ auto main() -> int kapi::memory::init_mmio(kapi::memory::mmio_base, 1_GiB / kapi::memory::page::size); kstd::println("[OS] Memory subsystem initialized."); - auto acpi_root_pointer = kapi::acpi::get_root_pointer(); - if (acpi_root_pointer && acpi_root_pointer->validate()) - { - if (kapi::acpi::init(*acpi_root_pointer)) - { - kstd::println("[OS] ACPI subsystem initialized."); - } - } - kapi::devices::init(); kstd::println("[OS] System root bus initialized."); -- cgit v1.2.3 From 72b40ecf33fb0ef2d4232b80560642296c79399c Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 2 Apr 2026 09:49:17 +0200 Subject: automatically detect the mounted file system type by trial-and-error --- kernel/src/filesystem/filesystem.cpp | 29 +++++++++++++++++++++++++---- kernel/src/filesystem/vfs.cpp | 5 +---- kernel/src/main.cpp | 4 ++-- 3 files changed, 28 insertions(+), 10 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index 0ac9cf8..e0c760f 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -1,20 +1,41 @@ #include "kernel/filesystem/filesystem.hpp" #include "kapi/devices/device.hpp" +#include "kapi/system.hpp" + +#include "kernel/filesystem/ext2/filesystem.hpp" #include "kernel/filesystem/inode.hpp" #include +#include + namespace kernel::filesystem { - auto filesystem::mount(kstd::shared_ptr const & device) -> int + namespace + { + constexpr auto static filesystem_factories = std::array{ + []() { return kstd::make_shared(); }, + }; + } // namespace + + auto filesystem::mount(kstd::shared_ptr const & device) -> kstd::shared_ptr { if (!device) { - return -1; // TODO BA-FS26 panic or errorcode? + kapi::system::panic("[FILESYSTEM] cannot mount filesystem: device is null."); } - m_device = device; - return 0; + + for (auto & factory : filesystem_factories) + { + auto fs = factory(); + if (fs->mount(device) == 0) + { + return fs; + } + } + + kapi::system::panic("[FILESYSTEM] cannot mount filesystem: no suitable filesystem found on device."); } auto filesystem::root_inode() const -> kstd::shared_ptr const & diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 06214d2..66aa91e 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -5,7 +5,6 @@ #include "kernel/devices/storage/management.hpp" #include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/devfs/filesystem.hpp" -#include "kernel/filesystem/ext2/filesystem.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/mount.hpp" #include "kernel/filesystem/open_file_description.hpp" @@ -46,9 +45,7 @@ namespace kernel::filesystem auto storage_mgmt = devices::storage::management::get(); if (auto boot_device = storage_mgmt.determine_boot_device()) { - // TODO BA-FS26 detect fs type from boot device and load corresponding fs, for now just assume ext2 - auto boot_root_fs = kstd::make_shared(); - boot_root_fs->mount(boot_device); + auto boot_root_fs = kernel::filesystem::filesystem::mount(boot_device); do_mount_internal("/", root_fs_root_dentry, boot_root_fs); } diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index b920674..382f12d 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -130,9 +130,9 @@ auto test_file_lookup() -> void kstd::os::panic("test code failed"); } - auto new_filesystem = kstd::make_shared(); auto device = storage_mgmt.device_by_major_minor(1, 16); - new_filesystem->mount(device); + auto new_filesystem = kernel::filesystem::filesystem::mount(device); + if (vfs.do_mount("/a/b", new_filesystem) != 0) { kstd::os::panic("test code failed"); -- cgit v1.2.3 From 93bca4c2a7c1852fc89df6965c835a7dbbdd6512 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 2 Apr 2026 09:50:14 +0200 Subject: read ext2 superblock and check the magic number --- kernel/src/filesystem/ext2/filesystem.cpp | 66 +++++++++++++++++-------------- 1 file changed, 37 insertions(+), 29 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index eb9edc4..a3425b5 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -1,10 +1,10 @@ #include "kernel/filesystem/ext2/filesystem.hpp" -#include "kernel/devices/block_device_utils.hpp" #include "kapi/devices/device.hpp" + +#include "kernel/devices/block_device_utils.hpp" #include "kernel/filesystem/ext2/inode.hpp" #include "kernel/filesystem/ext2/superblock.hpp" -#include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" #include @@ -17,37 +17,35 @@ namespace kernel::filesystem::ext2 { namespace { - // constexpr size_t SUPERBLOCK_OFFSET = 1024; - // constexpr uint16_t EXT2_MAGIC = 0xEF53; - - // // Mode bits - // constexpr uint16_t S_IFMT = 0xF000; - // constexpr uint16_t S_IFREG = 0x8000; - // constexpr uint16_t S_IFDIR = 0x4000; - - // auto S_ISREG(uint16_t mode) -> bool - // { - // return (mode & S_IFMT) == S_IFREG; - // } - // auto S_ISDIR(uint16_t mode) -> bool - // { - // return (mode & S_IFMT) == S_IFDIR; - // } - - // auto get_block_size(superblock const & superblock) -> size_t - // { - // return 1024U << superblock.log_block_size; - // } - - // auto get_inode_size(superblock const & superblock) -> size_t - // { - // return superblock.rev_level == 0 ? 128 : superblock.inode_size; - // } + constexpr size_t SUPERBLOCK_OFFSET = 1024; + constexpr uint16_t EXT2_MAGIC = 0xEF53; + + // Mode bits + constexpr uint16_t S_IFMT = 0xF000; + constexpr uint16_t S_IFREG = 0x8000; + constexpr uint16_t S_IFDIR = 0x4000; + + auto S_ISREG(uint16_t mode) -> bool + { + return (mode & S_IFMT) == S_IFREG; + } + auto S_ISDIR(uint16_t mode) -> bool + { + return (mode & S_IFMT) == S_IFDIR; + } } // namespace auto filesystem::mount(kstd::shared_ptr const & device) -> int { - kernel::filesystem::filesystem::mount(device); // TODO BA-FS26 error handling? + m_device = device; + + kernel::devices::block_device_utils::read(m_device, &m_superblock, SUPERBLOCK_OFFSET, sizeof(m_superblock)); + + if (m_superblock.magic != EXT2_MAGIC) + { + return -1; + } + // TODO BA-FS26 load proper root inode from ext2 metadata // m_root_inode = inode{inode_kind::directory}; @@ -69,4 +67,14 @@ namespace kernel::filesystem::ext2 return kstd::make_shared(); } + + auto filesystem::get_block_size() -> size_t + { + return 1024U << m_superblock.log_block_size; + } + + auto filesystem::get_inode_size() -> size_t + { + return m_superblock.rev_level == 0 ? 128 : m_superblock.inode_size; + } } // namespace kernel::filesystem::ext2 -- cgit v1.2.3 From 1dcf253fdf8169a3b2b71bfac68f2f25951af1a8 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 2 Apr 2026 10:04:04 +0200 Subject: fix build, refactoring --- kernel/src/filesystem/ext2/filesystem.cpp | 27 ++++++++++++++------------- kernel/src/filesystem/filesystem.cpp | 9 ++++++++- kernel/src/filesystem/rootfs/filesystem.cpp | 1 + kernel/src/filesystem/vfs.cpp | 2 +- kernel/src/main.cpp | 4 ++-- 5 files changed, 26 insertions(+), 17 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index a3425b5..0ebb243 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -5,6 +5,7 @@ #include "kernel/devices/block_device_utils.hpp" #include "kernel/filesystem/ext2/inode.hpp" #include "kernel/filesystem/ext2/superblock.hpp" +#include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" #include @@ -21,23 +22,23 @@ namespace kernel::filesystem::ext2 constexpr uint16_t EXT2_MAGIC = 0xEF53; // Mode bits - constexpr uint16_t S_IFMT = 0xF000; - constexpr uint16_t S_IFREG = 0x8000; - constexpr uint16_t S_IFDIR = 0x4000; - - auto S_ISREG(uint16_t mode) -> bool - { - return (mode & S_IFMT) == S_IFREG; - } - auto S_ISDIR(uint16_t mode) -> bool - { - return (mode & S_IFMT) == S_IFDIR; - } + // constexpr uint16_t S_IFMT = 0xF000; + // constexpr uint16_t S_IFREG = 0x8000; + // constexpr uint16_t S_IFDIR = 0x4000; + + // auto S_ISREG(uint16_t mode) -> bool + // { + // return (mode & S_IFMT) == S_IFREG; + // } + // auto S_ISDIR(uint16_t mode) -> bool + // { + // return (mode & S_IFMT) == S_IFDIR; + // } } // namespace auto filesystem::mount(kstd::shared_ptr const & device) -> int { - m_device = device; + kernel::filesystem::filesystem::mount(device); kernel::devices::block_device_utils::read(m_device, &m_superblock, SUPERBLOCK_OFFSET, sizeof(m_superblock)); diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index e0c760f..a06eb80 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -19,7 +19,8 @@ namespace kernel::filesystem }; } // namespace - auto filesystem::mount(kstd::shared_ptr const & device) -> kstd::shared_ptr + auto filesystem::probe_and_mount(kstd::shared_ptr const & device) + -> kstd::shared_ptr { if (!device) { @@ -38,6 +39,12 @@ namespace kernel::filesystem kapi::system::panic("[FILESYSTEM] cannot mount filesystem: no suitable filesystem found on device."); } + auto filesystem::mount(kstd::shared_ptr const & device) -> int + { + m_device = device; + return 0; + } + auto filesystem::root_inode() const -> kstd::shared_ptr const & { return m_root_inode; diff --git a/kernel/src/filesystem/rootfs/filesystem.cpp b/kernel/src/filesystem/rootfs/filesystem.cpp index 37bf588..a7c746e 100644 --- a/kernel/src/filesystem/rootfs/filesystem.cpp +++ b/kernel/src/filesystem/rootfs/filesystem.cpp @@ -1,6 +1,7 @@ #include "kernel/filesystem/rootfs/filesystem.hpp" #include "kapi/devices/device.hpp" + #include "kernel/filesystem/inode.hpp" #include "kernel/filesystem/rootfs/inode.hpp" diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 66aa91e..d611fc9 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -45,7 +45,7 @@ namespace kernel::filesystem auto storage_mgmt = devices::storage::management::get(); if (auto boot_device = storage_mgmt.determine_boot_device()) { - auto boot_root_fs = kernel::filesystem::filesystem::mount(boot_device); + auto boot_root_fs = kernel::filesystem::filesystem::probe_and_mount(boot_device); do_mount_internal("/", root_fs_root_dentry, boot_root_fs); } diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 382f12d..8df6767 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -8,8 +8,8 @@ #include "kernel/devices/storage/management.hpp" #include "kernel/filesystem/device_inode.hpp" -#include "kernel/filesystem/ext2/filesystem.hpp" #include "kernel/filesystem/file_descriptor_table.hpp" +#include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/open_file_description.hpp" #include "kernel/filesystem/vfs.hpp" #include "kernel/memory.hpp" @@ -131,7 +131,7 @@ auto test_file_lookup() -> void } auto device = storage_mgmt.device_by_major_minor(1, 16); - auto new_filesystem = kernel::filesystem::filesystem::mount(device); + auto new_filesystem = kernel::filesystem::filesystem::probe_and_mount(device); if (vfs.do_mount("/a/b", new_filesystem) != 0) { -- cgit v1.2.3 From 16b854e991bb791694268d09eb696c719cdff42f Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 2 Apr 2026 11:09:13 +0200 Subject: read block_group_descriptors --- kernel/src/filesystem/ext2/filesystem.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 0ebb243..96c1589 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -3,12 +3,14 @@ #include "kapi/devices/device.hpp" #include "kernel/devices/block_device_utils.hpp" +#include "kernel/filesystem/ext2/block_group_descriptor.hpp" #include "kernel/filesystem/ext2/inode.hpp" #include "kernel/filesystem/ext2/superblock.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" #include +#include #include #include @@ -47,6 +49,17 @@ namespace kernel::filesystem::ext2 return -1; } + auto const block_size = get_block_size(); + auto const blocks_per_group = m_superblock.blocks_per_group; + auto const num_block_groups = (m_superblock.blocks_count + blocks_per_group - 1) / blocks_per_group; + + m_block_group_descriptors = kstd::vector(num_block_groups); + + auto const block_group_descriptor_table_offset = block_size == 1024 ? 2 * block_size : block_size; + kernel::devices::block_device_utils::read(m_device, m_block_group_descriptors.data(), + block_group_descriptor_table_offset, + num_block_groups * sizeof(block_group_descriptor)); + // TODO BA-FS26 load proper root inode from ext2 metadata // m_root_inode = inode{inode_kind::directory}; -- cgit v1.2.3 From baf63039d5430c0b3b1e6235b561c12f60e97f49 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 2 Apr 2026 15:03:06 +0200 Subject: implement read_inode --- kernel/src/filesystem/ext2/filesystem.cpp | 35 ++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 96c1589..d650e97 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -21,7 +21,9 @@ namespace kernel::filesystem::ext2 namespace { constexpr size_t SUPERBLOCK_OFFSET = 1024; - constexpr uint16_t EXT2_MAGIC = 0xEF53; + constexpr uint16_t MAGIC_NUMBER = 0xEF53; + + constexpr uint32_t ROOT_INODE_NUMBER = 2; // Mode bits // constexpr uint16_t S_IFMT = 0xF000; @@ -44,7 +46,7 @@ namespace kernel::filesystem::ext2 kernel::devices::block_device_utils::read(m_device, &m_superblock, SUPERBLOCK_OFFSET, sizeof(m_superblock)); - if (m_superblock.magic != EXT2_MAGIC) + if (m_superblock.magic != MAGIC_NUMBER) { return -1; } @@ -60,12 +62,7 @@ namespace kernel::filesystem::ext2 block_group_descriptor_table_offset, num_block_groups * sizeof(block_group_descriptor)); - // TODO BA-FS26 load proper root inode from ext2 metadata - // m_root_inode = inode{inode_kind::directory}; - - // TODO BA-FS26 implement - m_root_inode = kstd::make_shared(); - // devices::block_device_utils::read(device, nullptr, 0, 0); // TODO BA-FS26 just for testing + m_root_inode = read_inode(ROOT_INODE_NUMBER); return 0; } @@ -82,6 +79,28 @@ namespace kernel::filesystem::ext2 return kstd::make_shared(); } + auto filesystem::read_inode(uint32_t inode_number) -> kstd::shared_ptr + { + auto const block_size = get_block_size(); + auto const inodes_per_group = m_superblock.inodes_per_group; + auto const block_group_index = (inode_number - 1) / inodes_per_group; + auto const inode_index_within_group = (inode_number - 1) % inodes_per_group; + + if (block_group_index >= m_block_group_descriptors.size()) + { + return nullptr; + } + + 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(inode_table_start_block) * block_size; + auto const inode_offset = inode_table_offset + inode_index_within_group * get_inode_size(); + + auto new_inode = kstd::make_shared(); + kernel::devices::block_device_utils::read(m_device, &new_inode->m_data, inode_offset, sizeof(inode_data)); + return new_inode; + } + auto filesystem::get_block_size() -> size_t { return 1024U << m_superblock.log_block_size; -- cgit v1.2.3 From 794de4a7f8dbea164d857ae9e4525536f338518d Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 2 Apr 2026 16:06:40 +0200 Subject: temporary implementation of inode kind --- kernel/src/filesystem/ext2/filesystem.cpp | 41 ++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 12 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index d650e97..31dc6f2 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -26,18 +26,18 @@ namespace kernel::filesystem::ext2 constexpr uint32_t ROOT_INODE_NUMBER = 2; // Mode bits - // constexpr uint16_t S_IFMT = 0xF000; - // constexpr uint16_t S_IFREG = 0x8000; - // constexpr uint16_t S_IFDIR = 0x4000; - - // auto S_ISREG(uint16_t mode) -> bool - // { - // return (mode & S_IFMT) == S_IFREG; - // } - // auto S_ISDIR(uint16_t mode) -> bool - // { - // return (mode & S_IFMT) == S_IFDIR; - // } + constexpr uint16_t S_IFMT = 0xF000; + constexpr uint16_t S_IFREG = 0x8000; + constexpr uint16_t S_IFDIR = 0x4000; + + auto S_ISREG(uint16_t mode) -> bool + { + return (mode & S_IFMT) == S_IFREG; + } + auto S_ISDIR(uint16_t mode) -> bool + { + return (mode & S_IFMT) == S_IFDIR; + } } // namespace auto filesystem::mount(kstd::shared_ptr const & device) -> int @@ -63,6 +63,7 @@ namespace kernel::filesystem::ext2 num_block_groups * sizeof(block_group_descriptor)); m_root_inode = read_inode(ROOT_INODE_NUMBER); + // TODO BA-FS26 check if root inode is valid and is a directory ?? return 0; } @@ -98,6 +99,22 @@ namespace kernel::filesystem::ext2 auto new_inode = kstd::make_shared(); kernel::devices::block_device_utils::read(m_device, &new_inode->m_data, inode_offset, sizeof(inode_data)); + + // TODO BA-FS26 improve inode_kind really needed? or just map it to the mode bits? + if (S_ISREG(new_inode->m_data.mode)) + { + new_inode->m_kind = inode::inode_kind::regular; + } + else if (S_ISDIR(new_inode->m_data.mode)) + { + new_inode->m_kind = inode::inode_kind::directory; + } + else + { + // TODO BA-FS26 really correct?? + return nullptr; + } + return new_inode; } -- cgit v1.2.3 From 82c8a4c16e3af3d62d7211e741b051da900de79c Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 3 Apr 2026 10:16:36 +0200 Subject: first lookup draft --- kernel/src/filesystem/ext2/filesystem.cpp | 48 ++++++++++++++++++++++++++++++- kernel/src/main.cpp | 2 ++ 2 files changed, 49 insertions(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 31dc6f2..82fcba9 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -5,11 +5,13 @@ #include "kernel/devices/block_device_utils.hpp" #include "kernel/filesystem/ext2/block_group_descriptor.hpp" #include "kernel/filesystem/ext2/inode.hpp" +#include "kernel/filesystem/ext2/linked_directory_entry.hpp" #include "kernel/filesystem/ext2/superblock.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" #include +#include #include #include @@ -24,6 +26,7 @@ namespace kernel::filesystem::ext2 constexpr uint16_t MAGIC_NUMBER = 0xEF53; constexpr uint32_t ROOT_INODE_NUMBER = 2; + constexpr size_t DIRECT_BLOCK_COUNT = 12; // Mode bits constexpr uint16_t S_IFMT = 0xF000; @@ -67,9 +70,52 @@ namespace kernel::filesystem::ext2 return 0; } - auto filesystem::lookup(kstd::shared_ptr const & /*parent*/, std::string_view name) + auto filesystem::lookup(kstd::shared_ptr const & parent, std::string_view name) -> kstd::shared_ptr { + if (!parent || !parent->is_directory()) + { + return nullptr; + } + + auto * ext2_parent = static_cast(parent.get()); + if (!ext2_parent) + { + return nullptr; + } + + auto const block_size = get_block_size(); + auto const & inode_data = ext2_parent->m_data; + kstd::vector buffer(block_size); + + for (size_t i = 0; i < DIRECT_BLOCK_COUNT && inode_data.block[i] != 0; ++i) + { + kernel::devices::block_device_utils::read(m_device, buffer.data(), inode_data.block[i] * block_size, block_size); + + size_t offset = 0; + while (offset < block_size) + { + auto * entry = reinterpret_cast(buffer.data() + offset); + if (entry->inode == 0) + break; + + // Stop if the directory entry is malformed to avoid overruns/loops. + // if (entry->rec_len < sizeof(linked_directory_entry) || offset + entry->rec_len > block_size) + // { + // break; + // } + + std::string_view entry_name(reinterpret_cast(entry->name.data()), entry->name_len); + if (entry_name == name) + { + return read_inode(entry->inode); + } + + offset += entry->rec_len; + } + } + + return nullptr; // TODO BA-FS26 implement ext2 directory traversal and inode loading if (name == "dev") { diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 8df6767..258c28b 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -117,6 +117,8 @@ auto test_file_lookup() -> void auto vfs = kernel::filesystem::vfs::get(); auto storage_mgmt = kernel::devices::storage::management::get(); + auto ofd_hello = vfs.open("/hello.txt"); + auto ofd1 = vfs.open("/a/b/c"); auto ofd2 = vfs.open("/dev/ram0"); auto ofd3 = vfs.open("/a/d/e"); -- cgit v1.2.3 From 7e6137b2725d5cf2b16f55678dcfb99091f03fe9 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 3 Apr 2026 14:30:20 +0200 Subject: implement map_inode_block_index_to_global_block_number and lookup --- kernel/src/filesystem/ext2/filesystem.cpp | 120 ++++++++++++++++++++++++------ 1 file changed, 96 insertions(+), 24 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 82fcba9..a84414f 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -11,6 +11,7 @@ #include "kernel/filesystem/inode.hpp" #include +#include #include #include @@ -26,7 +27,11 @@ namespace kernel::filesystem::ext2 constexpr uint16_t MAGIC_NUMBER = 0xEF53; constexpr uint32_t ROOT_INODE_NUMBER = 2; + constexpr size_t DIRECT_BLOCK_COUNT = 12; + constexpr size_t INDIRECT_BLOCK_INDEX = DIRECT_BLOCK_COUNT; + constexpr size_t DOUBLY_INDIRECT_BLOCK_INDEX = INDIRECT_BLOCK_INDEX + 1; + constexpr size_t TRIPLY_INDIRECT_BLOCK_INDEX = DOUBLY_INDIRECT_BLOCK_INDEX + 1; // Mode bits constexpr uint16_t S_IFMT = 0xF000; @@ -37,6 +42,7 @@ namespace kernel::filesystem::ext2 { return (mode & S_IFMT) == S_IFREG; } + auto S_ISDIR(uint16_t mode) -> bool { return (mode & S_IFMT) == S_IFDIR; @@ -88,42 +94,29 @@ namespace kernel::filesystem::ext2 auto const & inode_data = ext2_parent->m_data; kstd::vector buffer(block_size); - for (size_t i = 0; i < DIRECT_BLOCK_COUNT && inode_data.block[i] != 0; ++i) + for (uint32_t i = 0; i < get_inode_block_count(inode_data); ++i) { - kernel::devices::block_device_utils::read(m_device, buffer.data(), inode_data.block[i] * block_size, block_size); - - size_t offset = 0; - while (offset < block_size) - { - auto * entry = reinterpret_cast(buffer.data() + offset); - if (entry->inode == 0) - break; + auto const global_block_number = map_inode_block_index_to_global_block_number(i, inode_data); + auto const block_offset = global_block_number * block_size; + kernel::devices::block_device_utils::read(m_device, buffer.data(), block_offset, block_size); - // Stop if the directory entry is malformed to avoid overruns/loops. - // if (entry->rec_len < sizeof(linked_directory_entry) || offset + entry->rec_len > block_size) - // { - // break; - // } + auto const * entry = reinterpret_cast(buffer.data()); + auto bytes_read = 0uz; - std::string_view entry_name(reinterpret_cast(entry->name.data()), entry->name_len); + while (bytes_read < block_size && entry->inode != 0) + { + auto const entry_name = std::string_view{entry->name.data(), entry->name_len}; if (entry_name == name) { return read_inode(entry->inode); } - offset += entry->rec_len; + bytes_read += entry->rec_len; + entry = reinterpret_cast(buffer.data() + bytes_read); } } return nullptr; - // TODO BA-FS26 implement ext2 directory traversal and inode loading - if (name == "dev") - { - // TODO BA-FS26 just for testing - return nullptr; - } - - return kstd::make_shared(); } auto filesystem::read_inode(uint32_t inode_number) -> kstd::shared_ptr @@ -164,6 +157,80 @@ namespace kernel::filesystem::ext2 return new_inode; } + auto filesystem::map_inode_block_index_to_global_block_number(uint32_t inode_block_index, inode_data data) -> uint32_t + { + if (inode_block_index < DIRECT_BLOCK_COUNT) + { + return data.block.at(inode_block_index); + } + inode_block_index -= DIRECT_BLOCK_COUNT; + + auto const block_size = get_block_size(); + auto const numbers_per_block = block_size / sizeof(uint32_t); + uint32_t block_number_buffer = 0; + + auto const number_of_singly_indirect_blocks = numbers_per_block; + if (inode_block_index < number_of_singly_indirect_blocks) + { + auto const indirect_block_start_offset = data.block.at(INDIRECT_BLOCK_INDEX) * block_size; + auto const direct_block_number_index = inode_block_index; + auto const direct_block_number_offset = + indirect_block_start_offset + direct_block_number_index * sizeof(uint32_t); + kernel::devices::block_device_utils::read(m_device, &block_number_buffer, direct_block_number_offset, + sizeof(uint32_t)); + return block_number_buffer; + } + inode_block_index -= number_of_singly_indirect_blocks; + + auto const number_of_doubly_indirect_blocks = numbers_per_block * numbers_per_block; + if (inode_block_index < number_of_doubly_indirect_blocks) + { + auto const doubly_indirect_block_start_offset = data.block.at(DOUBLY_INDIRECT_BLOCK_INDEX) * block_size; + auto const indirect_block_number_index = inode_block_index / numbers_per_block; + auto const indirect_block_number_offset = + doubly_indirect_block_start_offset + indirect_block_number_index * sizeof(uint32_t); + kernel::devices::block_device_utils::read(m_device, &block_number_buffer, indirect_block_number_offset, + sizeof(uint32_t)); + + auto const indirect_block_start_offset = block_number_buffer * block_size; + auto const direct_block_number_index = inode_block_index % numbers_per_block; + auto const direct_block_number_offset = + indirect_block_start_offset + direct_block_number_index * sizeof(uint32_t); + kernel::devices::block_device_utils::read(m_device, &block_number_buffer, direct_block_number_offset, + sizeof(uint32_t)); + return block_number_buffer; + } + inode_block_index -= number_of_doubly_indirect_blocks; + + auto const number_of_triply_indirect_blocks = numbers_per_block * numbers_per_block * numbers_per_block; + if (inode_block_index < number_of_triply_indirect_blocks) + { + auto const triply_indirect_block_start_offset = data.block.at(TRIPLY_INDIRECT_BLOCK_INDEX) * block_size; + auto const doubly_indirect_block_number_index = inode_block_index / (numbers_per_block * numbers_per_block); + auto const doubly_indirect_block_number_offset = + triply_indirect_block_start_offset + doubly_indirect_block_number_index * sizeof(uint32_t); + kernel::devices::block_device_utils::read(m_device, &block_number_buffer, doubly_indirect_block_number_offset, + sizeof(uint32_t)); + + auto const doubly_indirect_block_start_offset = block_number_buffer * block_size; + auto const indirect_block_number_index = (inode_block_index / numbers_per_block) % numbers_per_block; + auto const indirect_block_number_offset = + doubly_indirect_block_start_offset + indirect_block_number_index * sizeof(uint32_t); + kernel::devices::block_device_utils::read(m_device, &block_number_buffer, indirect_block_number_offset, + sizeof(uint32_t)); + + auto const indirect_block_start_offset = block_number_buffer * block_size; + auto const direct_block_number_index = inode_block_index % numbers_per_block; + auto const direct_block_number_offset = + indirect_block_start_offset + direct_block_number_index * sizeof(uint32_t); + kernel::devices::block_device_utils::read(m_device, &block_number_buffer, direct_block_number_offset, + sizeof(uint32_t)); + return block_number_buffer; + } + + return 0; // TODO BA-FS26 really correct?? + } + auto filesystem::get_block_size() -> size_t { return 1024U << m_superblock.log_block_size; @@ -173,4 +240,9 @@ namespace kernel::filesystem::ext2 { return m_superblock.rev_level == 0 ? 128 : m_superblock.inode_size; } + + auto filesystem::get_inode_block_count(inode_data const & data) -> uint32_t + { + return data.blocks / (2 << m_superblock.log_block_size); + } } // namespace kernel::filesystem::ext2 -- cgit v1.2.3 From fe8706422605e466427ae2727ddb98ce5cd984f6 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 3 Apr 2026 15:38:16 +0200 Subject: refactoring map_inode_block_index_to_global_block_number --- kernel/src/filesystem/ext2/filesystem.cpp | 101 ++++++++++++++---------------- 1 file changed, 48 insertions(+), 53 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index a84414f..56c0b88 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -29,8 +29,8 @@ namespace kernel::filesystem::ext2 constexpr uint32_t ROOT_INODE_NUMBER = 2; constexpr size_t DIRECT_BLOCK_COUNT = 12; - constexpr size_t INDIRECT_BLOCK_INDEX = DIRECT_BLOCK_COUNT; - constexpr size_t DOUBLY_INDIRECT_BLOCK_INDEX = INDIRECT_BLOCK_INDEX + 1; + constexpr size_t SINGLY_INDIRECT_BLOCK_INDEX = DIRECT_BLOCK_COUNT; + constexpr size_t DOUBLY_INDIRECT_BLOCK_INDEX = SINGLY_INDIRECT_BLOCK_INDEX + 1; constexpr size_t TRIPLY_INDIRECT_BLOCK_INDEX = DOUBLY_INDIRECT_BLOCK_INDEX + 1; // Mode bits @@ -167,70 +167,65 @@ namespace kernel::filesystem::ext2 auto const block_size = get_block_size(); auto const numbers_per_block = block_size / sizeof(uint32_t); - uint32_t block_number_buffer = 0; - auto const number_of_singly_indirect_blocks = numbers_per_block; - if (inode_block_index < number_of_singly_indirect_blocks) + auto const block_numbers_per_singly_indirect_block = numbers_per_block; + auto const block_numbers_per_doubly_indirect_block = numbers_per_block * block_numbers_per_singly_indirect_block; + auto const block_numbers_per_triply_indirect_block = numbers_per_block * block_numbers_per_doubly_indirect_block; + + if (inode_block_index < block_numbers_per_singly_indirect_block) { - auto const indirect_block_start_offset = data.block.at(INDIRECT_BLOCK_INDEX) * block_size; - auto const direct_block_number_index = inode_block_index; - auto const direct_block_number_offset = - indirect_block_start_offset + direct_block_number_index * sizeof(uint32_t); - kernel::devices::block_device_utils::read(m_device, &block_number_buffer, direct_block_number_offset, - sizeof(uint32_t)); - return block_number_buffer; + auto const singly_indirect_block_number = data.block.at(SINGLY_INDIRECT_BLOCK_INDEX); + return read_block_number_at_index(singly_indirect_block_number, inode_block_index); } - inode_block_index -= number_of_singly_indirect_blocks; + inode_block_index -= block_numbers_per_singly_indirect_block; - auto const number_of_doubly_indirect_blocks = numbers_per_block * numbers_per_block; - if (inode_block_index < number_of_doubly_indirect_blocks) + if (inode_block_index < block_numbers_per_doubly_indirect_block) { - auto const doubly_indirect_block_start_offset = data.block.at(DOUBLY_INDIRECT_BLOCK_INDEX) * block_size; - auto const indirect_block_number_index = inode_block_index / numbers_per_block; - auto const indirect_block_number_offset = - doubly_indirect_block_start_offset + indirect_block_number_index * sizeof(uint32_t); - kernel::devices::block_device_utils::read(m_device, &block_number_buffer, indirect_block_number_offset, - sizeof(uint32_t)); - - auto const indirect_block_start_offset = block_number_buffer * block_size; - auto const direct_block_number_index = inode_block_index % numbers_per_block; - auto const direct_block_number_offset = - indirect_block_start_offset + direct_block_number_index * sizeof(uint32_t); - kernel::devices::block_device_utils::read(m_device, &block_number_buffer, direct_block_number_offset, - sizeof(uint32_t)); - return block_number_buffer; + auto const doubly_indirect_block_number = data.block.at(DOUBLY_INDIRECT_BLOCK_INDEX); + auto const singly_indirect_block_index_in_doubly_indirect_block = + inode_block_index / block_numbers_per_singly_indirect_block; + auto const singly_indirect_block_number = read_block_number_at_index( + doubly_indirect_block_number, singly_indirect_block_index_in_doubly_indirect_block); + + auto const block_index_in_singly_indirect_block = inode_block_index % block_numbers_per_singly_indirect_block; + return read_block_number_at_index(singly_indirect_block_number, block_index_in_singly_indirect_block); } - inode_block_index -= number_of_doubly_indirect_blocks; + inode_block_index -= block_numbers_per_doubly_indirect_block; - auto const number_of_triply_indirect_blocks = numbers_per_block * numbers_per_block * numbers_per_block; - if (inode_block_index < number_of_triply_indirect_blocks) + if (inode_block_index < block_numbers_per_triply_indirect_block) { - auto const triply_indirect_block_start_offset = data.block.at(TRIPLY_INDIRECT_BLOCK_INDEX) * block_size; - auto const doubly_indirect_block_number_index = inode_block_index / (numbers_per_block * numbers_per_block); - auto const doubly_indirect_block_number_offset = - triply_indirect_block_start_offset + doubly_indirect_block_number_index * sizeof(uint32_t); - kernel::devices::block_device_utils::read(m_device, &block_number_buffer, doubly_indirect_block_number_offset, - sizeof(uint32_t)); - - auto const doubly_indirect_block_start_offset = block_number_buffer * block_size; - auto const indirect_block_number_index = (inode_block_index / numbers_per_block) % numbers_per_block; - auto const indirect_block_number_offset = - doubly_indirect_block_start_offset + indirect_block_number_index * sizeof(uint32_t); - kernel::devices::block_device_utils::read(m_device, &block_number_buffer, indirect_block_number_offset, - sizeof(uint32_t)); - - auto const indirect_block_start_offset = block_number_buffer * block_size; - auto const direct_block_number_index = inode_block_index % numbers_per_block; - auto const direct_block_number_offset = - indirect_block_start_offset + direct_block_number_index * sizeof(uint32_t); - kernel::devices::block_device_utils::read(m_device, &block_number_buffer, direct_block_number_offset, - sizeof(uint32_t)); - return block_number_buffer; + auto const triply_indirect_block_number = data.block.at(TRIPLY_INDIRECT_BLOCK_INDEX); + auto const doubly_indirect_block_index_in_triply_indirect_block = + inode_block_index / block_numbers_per_doubly_indirect_block; + auto const doubly_indirect_block_number = read_block_number_at_index( + triply_indirect_block_number, doubly_indirect_block_index_in_triply_indirect_block); + + auto const remaining_block_numbers = inode_block_index % block_numbers_per_doubly_indirect_block; + + auto const singly_indirect_block_index_in_doubly_indirect_block = + remaining_block_numbers / block_numbers_per_singly_indirect_block; + auto const singly_indirect_block_number = read_block_number_at_index( + doubly_indirect_block_number, singly_indirect_block_index_in_doubly_indirect_block); + + auto const block_index_in_singly_indirect_block = + remaining_block_numbers % block_numbers_per_singly_indirect_block; + return read_block_number_at_index(singly_indirect_block_number, block_index_in_singly_indirect_block); } return 0; // TODO BA-FS26 really correct?? } + auto filesystem::read_block_number_at_index(uint32_t block_number, uint32_t index) -> uint32_t + { + uint32_t block_number_buffer = 0; + + auto const block_start_offset = block_number * get_block_size(); + auto const number_start_address = block_start_offset + index * sizeof(uint32_t); + kernel::devices::block_device_utils::read(m_device, &block_number_buffer, number_start_address, sizeof(uint32_t)); + + return block_number_buffer; + } + auto filesystem::get_block_size() -> size_t { return 1024U << m_superblock.log_block_size; -- cgit v1.2.3 From 725116d22e850c502e6cb8d42b100da1080dfec0 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 6 Apr 2026 10:35:45 +0200 Subject: Add file system pointer to ext2 inode --- kernel/src/filesystem/ext2/filesystem.cpp | 2 +- kernel/src/filesystem/ext2/inode.cpp | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 56c0b88..514bb59 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -136,7 +136,7 @@ namespace kernel::filesystem::ext2 auto const inode_table_offset = static_cast(inode_table_start_block) * block_size; auto const inode_offset = inode_table_offset + inode_index_within_group * get_inode_size(); - auto new_inode = kstd::make_shared(); + auto new_inode = kstd::make_shared(this); kernel::devices::block_device_utils::read(m_device, &new_inode->m_data, inode_offset, sizeof(inode_data)); // TODO BA-FS26 improve inode_kind really needed? or just map it to the mode bits? diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp index b75969a..4d36e66 100644 --- a/kernel/src/filesystem/ext2/inode.cpp +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -1,14 +1,22 @@ #include "kernel/filesystem/ext2/inode.hpp" +#include "kapi/system.hpp" + #include "kernel/filesystem/inode.hpp" #include namespace kernel::filesystem::ext2 { - inode::inode() + inode::inode(filesystem * fs) : kernel::filesystem::inode(inode_kind::regular) - {} + , m_filesystem(fs) + { + if (!m_filesystem) + { + kapi::system::panic("[EXT2] ext2::inode constructed with filesystem null pointer"); + } + } auto inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t { -- cgit v1.2.3 From 4a2d4fb3ab38a64c4b10832f5a6318b7240829cc Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 6 Apr 2026 11:40:12 +0200 Subject: Implement read data in ext2 inode --- kernel/src/filesystem/ext2/inode.cpp | 33 ++++++++++++++++++++++++++++++--- kernel/src/filesystem/filesystem.cpp | 5 +++++ 2 files changed, 35 insertions(+), 3 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp index 4d36e66..7f4cf69 100644 --- a/kernel/src/filesystem/ext2/inode.cpp +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -2,9 +2,13 @@ #include "kapi/system.hpp" +#include "kernel/devices/block_device_utils.hpp" +#include "kernel/filesystem/ext2/filesystem.hpp" #include "kernel/filesystem/inode.hpp" +#include #include +#include namespace kernel::filesystem::ext2 { @@ -18,10 +22,33 @@ namespace kernel::filesystem::ext2 } } - auto inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t + auto inode::read(void * buffer, size_t offset, size_t size) const -> size_t { - // TODO BA-FS26 implement - return 0; + auto block_index = offset / m_filesystem->get_block_size(); + auto in_block_offset = offset % m_filesystem->get_block_size(); + + auto bytes_read = 0uz; + + while (bytes_read < size) + { + auto const block_number = m_filesystem->map_inode_block_index_to_global_block_number(block_index, m_data); + if (block_number == 0) // TODO BA-FS26 really correct? + { + break; + } + + auto const block_start_offset = block_number * m_filesystem->get_block_size(); + auto const read_offset = block_start_offset + in_block_offset; + auto const bytes_to_read = std::min(size - bytes_read, m_filesystem->get_block_size() - in_block_offset); + + bytes_read += kernel::devices::block_device_utils::read( + m_filesystem->device(), static_cast(buffer) + bytes_read, read_offset, bytes_to_read); + + block_index++; + in_block_offset = 0; // 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*/) -> size_t diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index a06eb80..26c57b6 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -49,4 +49,9 @@ namespace kernel::filesystem { return m_root_inode; } + + auto filesystem::device() const -> kstd::shared_ptr const & + { + return m_device; + } } // namespace kernel::filesystem \ No newline at end of file -- cgit v1.2.3 From bf90441a49d9fa2ab3a1c315679f97289cb33dbe Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 6 Apr 2026 11:41:23 +0200 Subject: Add test for reading file --- kernel/src/main.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 258c28b..186d32e 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -23,6 +23,7 @@ #include #include +#include using namespace kstd::units_literals; @@ -119,6 +120,14 @@ auto test_file_lookup() -> void auto ofd_hello = vfs.open("/hello.txt"); + kstd::vector buffer(64); + auto number_of_read_bytes = ofd_hello->read(buffer.data(), buffer.size()); + kstd::println("read bytes: {}", number_of_read_bytes); + kstd::println("buffer: {::#04x}", buffer); + + std::string_view hello_str{reinterpret_cast(buffer.data()), number_of_read_bytes}; + kstd::println("hello_str: {}", hello_str); + auto ofd1 = vfs.open("/a/b/c"); auto ofd2 = vfs.open("/dev/ram0"); auto ofd3 = vfs.open("/a/d/e"); -- cgit v1.2.3 From 2240b9a36e4a9f6f8291c9271e6aac8f5536dbd7 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 7 Apr 2026 22:13:49 +0200 Subject: refactoring --- kernel/src/filesystem/device_inode.cpp | 4 +--- kernel/src/filesystem/ext2/filesystem.cpp | 2 -- kernel/src/filesystem/vfs.cpp | 1 + kernel/src/main.cpp | 2 -- 4 files changed, 2 insertions(+), 7 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/device_inode.cpp b/kernel/src/filesystem/device_inode.cpp index af8cecc..397a0fd 100644 --- a/kernel/src/filesystem/device_inode.cpp +++ b/kernel/src/filesystem/device_inode.cpp @@ -1,14 +1,12 @@ #include "kernel/filesystem/device_inode.hpp" +#include "kapi/devices/device.hpp" #include "kapi/system.hpp" #include "kernel/devices/block_device_utils.hpp" -#include "kapi/devices/device.hpp" #include "kernel/filesystem/inode.hpp" -#include #include -#include #include diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 514bb59..d7c989c 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -11,8 +11,6 @@ #include "kernel/filesystem/inode.hpp" #include -#include -#include #include #include diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index d611fc9..f9a051a 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -74,6 +74,7 @@ namespace kernel::filesystem return nullptr; } + // TODO BA-FS26 implement unmount auto vfs::do_mount(std::string_view path, kstd::shared_ptr const & filesystem) -> int { if (!filesystem) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 186d32e..a2c531f 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -88,8 +88,6 @@ auto test_file_description_manually() -> void auto test_device_with_vfs() -> void { - // TODO BA-FS26 - auto vfs = kernel::filesystem::vfs::get(); auto ofd = vfs.open("/dev/ram0"); if (!ofd) -- cgit v1.2.3 From dd330e7a05905713acfa87ec109956bfe78f78c4 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 09:31:32 +0200 Subject: add descriptions, some refactoring --- kernel/src/filesystem/ext2/filesystem.cpp | 12 ++++++++++-- kernel/src/filesystem/ext2/inode.cpp | 2 +- kernel/src/filesystem/filesystem.cpp | 3 ++- kernel/src/filesystem/mount.cpp | 2 +- kernel/src/filesystem/mount_table.cpp | 2 +- kernel/src/filesystem/vfs.cpp | 19 +++++++++---------- 6 files changed, 24 insertions(+), 16 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index d7c989c..7ee1072 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -36,6 +36,10 @@ namespace kernel::filesystem::ext2 constexpr uint16_t S_IFREG = 0x8000; constexpr uint16_t S_IFDIR = 0x4000; + // Error codes + constexpr int INVALID_MAGIC_NUMBER = -1; + constexpr int INVALID_ROOT_INODE = -2; + auto S_ISREG(uint16_t mode) -> bool { return (mode & S_IFMT) == S_IFREG; @@ -55,7 +59,7 @@ namespace kernel::filesystem::ext2 if (m_superblock.magic != MAGIC_NUMBER) { - return -1; + return INVALID_MAGIC_NUMBER; } auto const block_size = get_block_size(); @@ -70,7 +74,11 @@ namespace kernel::filesystem::ext2 num_block_groups * sizeof(block_group_descriptor)); m_root_inode = read_inode(ROOT_INODE_NUMBER); - // TODO BA-FS26 check if root inode is valid and is a directory ?? + + if (!m_root_inode || !m_root_inode->is_directory()) + { + return INVALID_ROOT_INODE; + } return 0; } diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp index 7f4cf69..a29bb3b 100644 --- a/kernel/src/filesystem/ext2/inode.cpp +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -53,7 +53,7 @@ namespace kernel::filesystem::ext2 auto inode::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t { - // TODO BA-FS26 implement + kapi::system::panic("[EXT2] inode::write is not implemented yet"); return 0; } } // namespace kernel::filesystem::ext2 \ No newline at end of file diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index 26c57b6..b08b520 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -36,11 +36,12 @@ namespace kernel::filesystem } } - kapi::system::panic("[FILESYSTEM] cannot mount filesystem: no suitable filesystem found on device."); + return nullptr; } auto filesystem::mount(kstd::shared_ptr const & device) -> int { + // TODO BA-FS26 maybe check if device is null and panic here already? m_device = device; return 0; } diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index f9e709c..a6d2f7e 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -25,7 +25,7 @@ namespace kernel::filesystem } } - auto mount::get_mount_dentry() const -> kstd::shared_ptr + auto mount::get_mount_dentry() const -> kstd::shared_ptr const & { return m_mount_dentry; } diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index 737434e..195f48a 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -9,7 +9,7 @@ namespace kernel::filesystem { - void mount_table::add_mount(kstd::shared_ptr mount) + void mount_table::add_mount(kstd::shared_ptr const & mount) { m_mounts.push_back(mount); } diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index f9a051a..2578036 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -21,6 +21,11 @@ namespace kernel::filesystem namespace { constinit auto static active_vfs = std::optional{}; + + // Error codes + constexpr int INVALID_PATH = -1; + constexpr int MOUNT_POINT_NOT_FOUND = -2; + constexpr int FILESYSTEM_NULL = -3; } // namespace auto vfs::init() -> void @@ -79,18 +84,12 @@ namespace kernel::filesystem { if (!filesystem) { - return -1; // TODO BA-FS26 panic or errorcode? - } - - if (path.empty() || path.front() != '/') - { - return -1; // TODO BA-FS26 panic or errorcode? + return FILESYSTEM_NULL; } - // TODO BA-FS26 better path validation - if ((path.size() > 1 && path.back() == '/')) + if (path.empty() || path.front() != '/' || (path.size() > 1 && path.back() == '/')) { - return -1; // TODO BA-FS26 panic or errorcode? + return INVALID_PATH; } if (auto mount_point_dentry = resolve_path(path)) @@ -99,7 +98,7 @@ namespace kernel::filesystem return 0; } - return -1; + return MOUNT_POINT_NOT_FOUND; } auto vfs::do_mount_internal(std::string_view path, kstd::shared_ptr const & mount_point_dentry, -- cgit v1.2.3 From 9c0fb15aa67a4dda6beed3cbdfc4cc510674313f Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 14:13:19 +0200 Subject: add test with multiple correct formatted ext2 file systems increase QEMU memory --- kernel/src/main.cpp | 69 ++++++++++++++++++++++------------------------------- 1 file changed, 29 insertions(+), 40 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index a2c531f..1893b84 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -111,51 +111,40 @@ auto test_device_with_vfs() -> void auto test_file_lookup() -> void { - // TODO BA-FS26 implement a more complete test with multiple files and directories and mounts etc. - auto vfs = kernel::filesystem::vfs::get(); - auto storage_mgmt = kernel::devices::storage::management::get(); - - auto ofd_hello = vfs.open("/hello.txt"); - - kstd::vector buffer(64); - auto number_of_read_bytes = ofd_hello->read(buffer.data(), buffer.size()); - kstd::println("read bytes: {}", number_of_read_bytes); - kstd::println("buffer: {::#04x}", buffer); - - std::string_view hello_str{reinterpret_cast(buffer.data()), number_of_read_bytes}; - kstd::println("hello_str: {}", hello_str); - - auto ofd1 = vfs.open("/a/b/c"); - auto ofd2 = vfs.open("/dev/ram0"); - auto ofd3 = vfs.open("/a/d/e"); - if (!ofd1 || !ofd2 || !ofd3) - { - kstd::os::panic("test code failed"); - } - - if (auto ofd4 = vfs.open("/dev/xxx")) - { - kstd::os::panic("test code failed"); - } + auto read_and_write_file = [&vfs](std::string_view path) { + kstd::println("[TEST] Reading and writing file at path: {}", path); + auto ofd = vfs.open(path); + if (!ofd) + { + kstd::os::panic("test code failed"); + } + + kstd::vector buffer{32}; + auto number_of_read_bytes = ofd->read(buffer.data(), buffer.size()); + kstd::println("read bytes: {}", number_of_read_bytes); + kstd::println("buffer: {::#04x}", buffer); + + std::string_view buffer_as_str{reinterpret_cast(buffer.data()), number_of_read_bytes}; + kstd::println("buffer_as_str: {}", buffer_as_str); + }; + + read_and_write_file("/info.txt"); + read_and_write_file("/enclosures/info.txt"); + read_and_write_file("/enclosures/aquarium/tank_1/fish_4.txt"); + read_and_write_file("/enclosures/elephant_house/elephant_1.txt"); + read_and_write_file( + "/enclosures/aquarium/tank_2/" + "this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_" + "limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_30.txt"); + auto storage_mgmt = kernel::devices::storage::management::get(); auto device = storage_mgmt.device_by_major_minor(1, 16); auto new_filesystem = kernel::filesystem::filesystem::probe_and_mount(device); - if (vfs.do_mount("/a/b", new_filesystem) != 0) - { - kstd::os::panic("test code failed"); - } - auto ofd5 = vfs.open("/a/b/c"); - if (!ofd5) - { - kstd::os::panic("test code failed"); - } - - if (auto ofd6 = vfs.open("x/y/z")) - { - kstd::os::panic("test code failed"); - } + vfs.do_mount("/enclosures/aquarium", new_filesystem); + read_and_write_file("/enclosures/aquarium/closed.txt"); + read_and_write_file("/enclosures/aquarium/information/info_2.txt"); } auto run_test_code() -> void -- cgit v1.2.3 From 2793770dc6eba30b73b4a4993618d2cbe184790e Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 15:21:10 +0200 Subject: implement unmount, improve error codes --- kernel/src/filesystem/devfs/filesystem.cpp | 5 ++- kernel/src/filesystem/ext2/filesystem.cpp | 12 ++--- kernel/src/filesystem/filesystem.cpp | 6 +-- kernel/src/filesystem/mount.cpp | 9 +++- kernel/src/filesystem/mount_table.cpp | 69 ++++++++++++++++++++++++++++- kernel/src/filesystem/rootfs/filesystem.cpp | 4 +- kernel/src/filesystem/vfs.cpp | 45 ++++++++++++------- kernel/src/main.cpp | 3 ++ 8 files changed, 121 insertions(+), 32 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/devfs/filesystem.cpp b/kernel/src/filesystem/devfs/filesystem.cpp index 9043ac5..03b4218 100644 --- a/kernel/src/filesystem/devfs/filesystem.cpp +++ b/kernel/src/filesystem/devfs/filesystem.cpp @@ -1,6 +1,7 @@ #include "kernel/filesystem/devfs/filesystem.hpp" #include "kapi/devices/device.hpp" + #include "kernel/devices/storage/management.hpp" #include "kernel/filesystem/devfs/inode.hpp" #include "kernel/filesystem/device_inode.hpp" @@ -13,12 +14,12 @@ namespace kernel::filesystem::devfs { - auto filesystem::mount(kstd::shared_ptr const &) -> int + auto filesystem::mount(kstd::shared_ptr const &) -> operation_result { m_root_inode = kstd::make_shared(); build_device_inode_table(); - return 0; + return operation_result::success; } auto filesystem::lookup(kstd::shared_ptr const & parent, std::string_view name) diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 7ee1072..6d5960e 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -36,10 +36,6 @@ namespace kernel::filesystem::ext2 constexpr uint16_t S_IFREG = 0x8000; constexpr uint16_t S_IFDIR = 0x4000; - // Error codes - constexpr int INVALID_MAGIC_NUMBER = -1; - constexpr int INVALID_ROOT_INODE = -2; - auto S_ISREG(uint16_t mode) -> bool { return (mode & S_IFMT) == S_IFREG; @@ -51,7 +47,7 @@ namespace kernel::filesystem::ext2 } } // namespace - auto filesystem::mount(kstd::shared_ptr const & device) -> int + auto filesystem::mount(kstd::shared_ptr const & device) -> operation_result { kernel::filesystem::filesystem::mount(device); @@ -59,7 +55,7 @@ namespace kernel::filesystem::ext2 if (m_superblock.magic != MAGIC_NUMBER) { - return INVALID_MAGIC_NUMBER; + return operation_result::invalid_magic_number; } auto const block_size = get_block_size(); @@ -77,9 +73,9 @@ namespace kernel::filesystem::ext2 if (!m_root_inode || !m_root_inode->is_directory()) { - return INVALID_ROOT_INODE; + return operation_result::invalid_root_inode; } - return 0; + return operation_result::success; } auto filesystem::lookup(kstd::shared_ptr const & parent, std::string_view name) diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index b08b520..da2838d 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -30,7 +30,7 @@ namespace kernel::filesystem for (auto & factory : filesystem_factories) { auto fs = factory(); - if (fs->mount(device) == 0) + if (fs->mount(device) == operation_result::success) { return fs; } @@ -39,11 +39,11 @@ namespace kernel::filesystem return nullptr; } - auto filesystem::mount(kstd::shared_ptr const & device) -> int + auto filesystem::mount(kstd::shared_ptr const & device) -> operation_result { // TODO BA-FS26 maybe check if device is null and panic here already? m_device = device; - return 0; + return operation_result::success; } auto filesystem::root_inode() const -> kstd::shared_ptr const & diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index a6d2f7e..d165385 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -13,11 +13,13 @@ namespace kernel::filesystem { mount::mount(kstd::shared_ptr const & mount_dentry, kstd::shared_ptr const & root_dentry, - kstd::shared_ptr const & fs, std::string_view mount_path) + kstd::shared_ptr const & fs, std::string_view mount_path, + kstd::shared_ptr const & parent_mount) : m_mount_path(mount_path) , m_mount_dentry(mount_dentry) , m_root_dentry(root_dentry) , m_filesystem(fs) + , m_parent_mount(parent_mount) { if (!m_filesystem) { @@ -44,4 +46,9 @@ namespace kernel::filesystem { return m_mount_path.view(); } + + auto mount::get_parent_mount() const -> kstd::shared_ptr const & + { + return m_parent_mount; + } } // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index 195f48a..3b1dee3 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -1,17 +1,83 @@ #include "kernel/filesystem/mount_table.hpp" +#include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/mount.hpp" #include +#include +#include #include +#include #include namespace kernel::filesystem { + namespace + { + auto is_descendant_of(kstd::shared_ptr const & candidate, kstd::shared_ptr const & ancestor) -> bool + { + for (auto current = candidate; current; current = current->get_parent_mount()) + { + if (current == ancestor) + { + return true; + } + } + + return false; + } + + auto is_strict_prefix(std::string_view prefix, std::string_view path) -> bool + { + return prefix != "/" && path.starts_with(prefix) && path.size() > prefix.size() && path[prefix.size()] == '/'; + } + + auto is_visible_mount(kstd::shared_ptr const & candidate, + kstd::vector> const & mounts) -> bool + { + return std::ranges::none_of(mounts, [&](auto const & other) { + return other != candidate && is_strict_prefix(other->get_mount_path(), candidate->get_mount_path()) && + !is_descendant_of(candidate, other); + }); + } + } // namespace + + auto mount_table::has_child_mounts(kstd::shared_ptr const & parent_mount) const -> bool + { + return std::ranges::any_of( + m_mounts, [&parent_mount](auto const & mount) { return mount->get_parent_mount() == parent_mount; }); + } + void mount_table::add_mount(kstd::shared_ptr const & mount) { m_mounts.push_back(mount); + if (auto mount_dentry = mount->get_mount_dentry()) + { + mount_dentry->set_flag(dentry::dentry_flags::dcache_mounted); + } + } + + auto mount_table::remove_mount(std::string_view path) -> operation_result + { + auto mount_it = std::ranges::find_if(std::ranges::reverse_view(m_mounts), [&](auto const & mount) { + return mount->get_mount_path() == path && is_visible_mount(mount, m_mounts); + }); + + if (mount_it == std::ranges::reverse_view(m_mounts).end()) + { + return operation_result::mount_not_found; + } + + auto const & mount = *mount_it; + if (has_child_mounts(mount)) + { + return operation_result::has_child_mounts; + } + + mount->get_mount_dentry()->unset_flag(dentry::dentry_flags::dcache_mounted); + m_mounts.erase(std::ranges::find(m_mounts, mount)); + return operation_result::removed; } auto mount_table::find_longest_prefix_mount(std::string_view path) const -> kstd::shared_ptr @@ -25,8 +91,9 @@ namespace kernel::filesystem // /a/b/c should match /a/b but not /a/bb or /a/b/c/d, / should match everything bool is_prefix = path.starts_with(mp) && (mp == "/" || path.size() == mp.size() || path[mp.size()] == '/'); + bool visible = is_visible_mount(mount, m_mounts); - if (is_prefix && mp.size() >= best_len) + if (is_prefix && visible && mp.size() >= best_len) { mount_with_longest_prefix = mount; best_len = mp.size(); diff --git a/kernel/src/filesystem/rootfs/filesystem.cpp b/kernel/src/filesystem/rootfs/filesystem.cpp index a7c746e..dffef99 100644 --- a/kernel/src/filesystem/rootfs/filesystem.cpp +++ b/kernel/src/filesystem/rootfs/filesystem.cpp @@ -11,13 +11,13 @@ namespace kernel::filesystem::rootfs { - auto filesystem::mount(kstd::shared_ptr const &) -> int + auto filesystem::mount(kstd::shared_ptr const &) -> operation_result { auto rfs_inode = kstd::make_shared(); rfs_inode->add_child("dev"); m_root_inode = rfs_inode; - return 0; + return operation_result::success; } auto filesystem::lookup(kstd::shared_ptr const & parent, std::string_view name) diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 2578036..45ae053 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -7,6 +7,7 @@ #include "kernel/filesystem/devfs/filesystem.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/mount.hpp" +#include "kernel/filesystem/mount_table.hpp" #include "kernel/filesystem/open_file_description.hpp" #include "kernel/filesystem/rootfs/filesystem.hpp" @@ -21,11 +22,6 @@ namespace kernel::filesystem namespace { constinit auto static active_vfs = std::optional{}; - - // Error codes - constexpr int INVALID_PATH = -1; - constexpr int MOUNT_POINT_NOT_FOUND = -2; - constexpr int FILESYSTEM_NULL = -3; } // namespace auto vfs::init() -> void @@ -45,7 +41,7 @@ namespace kernel::filesystem root_fs->mount(nullptr); auto root_fs_root_dentry = kstd::make_shared(nullptr, root_fs->root_inode()); - m_mount_table.add_mount(kstd::make_shared(nullptr, root_fs_root_dentry, root_fs, "")); + m_mount_table.add_mount(kstd::make_shared(nullptr, root_fs_root_dentry, root_fs, "", nullptr)); auto storage_mgmt = devices::storage::management::get(); if (auto boot_device = storage_mgmt.determine_boot_device()) @@ -79,36 +75,55 @@ namespace kernel::filesystem return nullptr; } - // TODO BA-FS26 implement unmount - auto vfs::do_mount(std::string_view path, kstd::shared_ptr const & filesystem) -> int + auto vfs::do_mount(std::string_view path, kstd::shared_ptr const & filesystem) -> operation_result { if (!filesystem) { - return FILESYSTEM_NULL; + return operation_result::filesystem_null; } if (path.empty() || path.front() != '/' || (path.size() > 1 && path.back() == '/')) { - return INVALID_PATH; + return operation_result::invalid_path; } if (auto mount_point_dentry = resolve_path(path)) { do_mount_internal(path, mount_point_dentry, filesystem); - return 0; + return operation_result::success; + } + + return operation_result::mount_point_not_found; + } + + auto vfs::unmount(std::string_view path) -> operation_result + { + if (path.empty() || path.front() != '/' || (path.size() > 1 && path.back() == '/')) + { + return operation_result::invalid_path; + } + + auto remove_result = m_mount_table.remove_mount(path); + if (remove_result == mount_table::operation_result::removed) + { + return operation_result::success; + } + + if (remove_result == mount_table::operation_result::has_child_mounts) + { + return operation_result::unmount_failed; } - return MOUNT_POINT_NOT_FOUND; + return operation_result::mount_point_not_found; } auto vfs::do_mount_internal(std::string_view path, kstd::shared_ptr const & mount_point_dentry, kstd::shared_ptr const & fs) -> void { - // TODO BA-FS26 check if mount point is already mounted and handle it (unmount old fs, fail, etc.) + auto parent_mount = m_mount_table.find_longest_prefix_mount(path); auto new_fs_root = kstd::make_shared(mount_point_dentry, fs->root_inode()); - auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, path); + auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, path, parent_mount); m_mount_table.add_mount(new_mount); - mount_point_dentry->set_flag(dentry::dentry_flags::dcache_mounted); } auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 1893b84..1d73e20 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -145,6 +145,9 @@ auto test_file_lookup() -> void vfs.do_mount("/enclosures/aquarium", new_filesystem); read_and_write_file("/enclosures/aquarium/closed.txt"); read_and_write_file("/enclosures/aquarium/information/info_2.txt"); + + vfs.unmount("/enclosures/aquarium"); + read_and_write_file("/enclosures/aquarium/tank_1/fish_4.txt"); } auto run_test_code() -> void -- cgit v1.2.3 From 5865dac062f3291b8081eca39c2835015d2c43c6 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 15:48:32 +0200 Subject: extend tests with another filesystem --- kernel/src/main.cpp | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 1d73e20..79ed703 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -139,15 +139,37 @@ auto test_file_lookup() -> void "limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_30.txt"); auto storage_mgmt = kernel::devices::storage::management::get(); - auto device = storage_mgmt.device_by_major_minor(1, 16); - auto new_filesystem = kernel::filesystem::filesystem::probe_and_mount(device); + auto device_1 = storage_mgmt.device_by_major_minor(1, 16); + auto fs_1 = kernel::filesystem::filesystem::probe_and_mount(device_1); - vfs.do_mount("/enclosures/aquarium", new_filesystem); + vfs.do_mount("/enclosures/aquarium", fs_1); read_and_write_file("/enclosures/aquarium/closed.txt"); read_and_write_file("/enclosures/aquarium/information/info_2.txt"); vfs.unmount("/enclosures/aquarium"); read_and_write_file("/enclosures/aquarium/tank_1/fish_4.txt"); + + auto device_2 = storage_mgmt.device_by_major_minor(1, 32); + auto fs_2 = kernel::filesystem::filesystem::probe_and_mount(device_2); + + vfs.do_mount("/enclosures/elephant_house", fs_2); + read_and_write_file("/enclosures/elephant_house/monkey_house/infrastructure/info.txt"); + + vfs.do_mount("/enclosures/elephant_house/monkey_house", fs_1); + read_and_write_file("/enclosures/elephant_house/monkey_house/information/info_2.txt"); + + auto result = vfs.unmount("/enclosures/elephant_house"); + if (result == kernel::filesystem::vfs::operation_result::unmount_failed) + { + kstd::println("[TEST] Unmount failed as expected due to active child mount."); + } + + vfs.unmount("/enclosures/elephant_house/monkey_house"); + result = vfs.unmount("/enclosures/elephant_house"); + if (result == kernel::filesystem::vfs::operation_result::success) + { + kstd::println("[TEST] Unmount succeeded after unmounting child mount."); + } } auto run_test_code() -> void -- cgit v1.2.3 From e2c08ddb3d79f946399ca5d3bc07b4e6c4de9328 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 16:21:33 +0200 Subject: add dentry tests --- kernel/src/filesystem/dentry.cpp | 9 ++- kernel/src/filesystem/dentry.tests.cpp | 136 +++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 kernel/src/filesystem/dentry.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index 2f99e91..6591011 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -12,10 +12,10 @@ namespace kernel::filesystem { - dentry::dentry(kstd::shared_ptr const & parent, kstd::shared_ptr const & node, std::string_view name) + dentry::dentry(kstd::shared_ptr const & parent, kstd::shared_ptr const & inode, std::string_view name) : m_name(name) , m_parent(parent) - , m_inode(node) + , m_inode(inode) { if (!m_inode) { @@ -33,6 +33,11 @@ namespace kernel::filesystem return m_parent; } + auto dentry::get_name() const -> std::string_view + { + return m_name.view(); + } + auto dentry::add_child(kstd::shared_ptr const & child) -> void { m_children.push_back(child); diff --git a/kernel/src/filesystem/dentry.tests.cpp b/kernel/src/filesystem/dentry.tests.cpp new file mode 100644 index 0000000..f82024a --- /dev/null +++ b/kernel/src/filesystem/dentry.tests.cpp @@ -0,0 +1,136 @@ +#include "kernel/filesystem/dentry.hpp" + +#include "kernel/filesystem/devfs/inode.hpp" +#include "kernel/test_support/cio.hpp" +#include "kernel/test_support/cpu.hpp" + +#include +#include + +#include + +SCENARIO("Dentry construction", "[filesystem][dentry]") +{ + GIVEN("A parent dentry and inode") + { + auto inode = kstd::make_shared(); + auto parent_dentry = kstd::make_shared(nullptr, inode); + + WHEN("constructing a dentry") + { + auto child_dentry = kernel::filesystem::dentry{parent_dentry, inode, "child"}; + + THEN("the dentry has the correct parent, inode, and name") + { + REQUIRE(child_dentry.get_parent() == parent_dentry); + REQUIRE(child_dentry.get_inode() == inode); + REQUIRE(child_dentry.get_name() == "child"); + } + + THEN("no flag is set") + { + REQUIRE_FALSE(child_dentry.has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + } + } + + WHEN("constructing a dentry with an empty name") + { + auto child_dentry = kernel::filesystem::dentry{parent_dentry, inode}; + + THEN("the dentry has the correct parent and inode, and an empty name") + { + REQUIRE(child_dentry.get_parent() == parent_dentry); + REQUIRE(child_dentry.get_inode() == inode); + REQUIRE(child_dentry.get_name().empty()); + } + + THEN("no flag is set") + { + REQUIRE_FALSE(child_dentry.has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + } + } + + WHEN("constructing a dentry with a null parent") + { + auto child_dentry = kernel::filesystem::dentry{nullptr, inode, "child"}; + + THEN("the dentry has a null parent, the correct inode, and the correct name") + { + REQUIRE(child_dentry.get_parent() == nullptr); + REQUIRE(child_dentry.get_inode() == inode); + REQUIRE(child_dentry.get_name() == "child"); + } + + THEN("no flag is set") + { + REQUIRE_FALSE(child_dentry.has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + } + } + + WHEN("constructing a dentry with a null inode") + { + THEN("the system panics") + { + REQUIRE_THROWS_AS((kernel::filesystem::dentry{parent_dentry, nullptr, "child"}), kernel::tests::cpu::halt); + } + } + } +} + +SCENARIO("Dentry child logic", "[filesystem][dentry]") +{ + GIVEN("A parent dentry and inode") + { + auto inode = kstd::make_shared(); + auto parent_dentry = kstd::make_shared(nullptr, inode); + + WHEN("adding child dentries") + { + auto child1 = kstd::make_shared(parent_dentry, inode, "child1"); + auto child2 = kstd::make_shared(parent_dentry, inode, "child2"); + parent_dentry->add_child(child1); + parent_dentry->add_child(child2); + + THEN("the children can be found by name") + { + REQUIRE(parent_dentry->find_child("child1") == child1); + REQUIRE(parent_dentry->find_child("child2") == child2); + } + + THEN("finding a non-existent child returns null") + { + REQUIRE(parent_dentry->find_child("nonexistent") == nullptr); + } + } + } +} + +SCENARIO("Dentry Flag logic", "[filesystem][dentry]") +{ + GIVEN("A dentry") + { + auto inode = kstd::make_shared(); + auto dentry = kernel::filesystem::dentry{nullptr, inode, "test"}; + + WHEN("setting a flag") + { + dentry.set_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted); + + THEN("the flag is set") + { + REQUIRE(dentry.has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + } + } + + WHEN("unsetting a flag") + { + dentry.set_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted); + dentry.unset_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted); + + THEN("the flag is unset") + { + REQUIRE_FALSE(dentry.has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + } + } + } +} -- cgit v1.2.3 From bf90905a5ded3995af5677685bc31228d485e64b Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 18:52:11 +0200 Subject: add test block_device --- kernel/src/test_support/devices/block_device.cpp | 58 ++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 kernel/src/test_support/devices/block_device.cpp (limited to 'kernel/src') diff --git a/kernel/src/test_support/devices/block_device.cpp b/kernel/src/test_support/devices/block_device.cpp new file mode 100644 index 0000000..bce415f --- /dev/null +++ b/kernel/src/test_support/devices/block_device.cpp @@ -0,0 +1,58 @@ +#include "kernel/test_support/devices/block_device.hpp" + +#include "kernel/devices/block_device.hpp" + +#include +#include + +#include +#include +#include +#include +#include + +namespace kernel::tests::devices +{ + block_device::block_device(size_t major, size_t minor, kstd::string const & name, size_t block_size) + : kernel::devices::block_device(major, minor, name, block_size) + {} + + auto block_device::init() -> bool + { + return true; + } + + auto block_device::read_block(size_t block_index, void * buffer) const -> void + { + auto const offset = block_index * block_size(); + if (offset >= data.size()) + { + kstd::libc::memset(buffer, 0, block_size()); + return; + } + + auto const bytes_to_read = std::min(block_size(), data.size() - offset); + kstd::libc::memcpy(buffer, data.data() + offset, bytes_to_read); + if (bytes_to_read < block_size()) + { + kstd::libc::memset(static_cast(buffer) + bytes_to_read, 0, block_size() - bytes_to_read); + } + } + + auto block_device::write_block(size_t block_index, void const * buffer) -> void + { + auto const offset = block_index * block_size(); + auto const write_end = offset + block_size(); + if (write_end > data.size()) + { + data.resize(write_end, 0); + } + + kstd::libc::memcpy(data.data() + offset, static_cast(buffer), block_size()); + } + + auto block_device::size() const -> size_t + { + return data.size(); + } +} // namespace kernel::tests::devices \ No newline at end of file -- cgit v1.2.3 From 63c6299262411fc06afca4f224e00e1b2d25eb25 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 19:01:16 +0200 Subject: clean up includes --- kernel/src/filesystem/dentry.tests.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.tests.cpp b/kernel/src/filesystem/dentry.tests.cpp index f82024a..94aa48d 100644 --- a/kernel/src/filesystem/dentry.tests.cpp +++ b/kernel/src/filesystem/dentry.tests.cpp @@ -1,7 +1,6 @@ #include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/devfs/inode.hpp" -#include "kernel/test_support/cio.hpp" #include "kernel/test_support/cpu.hpp" #include -- cgit v1.2.3 From ad2a744960ef8359a40e25c81f2b5fee0d8952c4 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 19:17:08 +0200 Subject: add block_device_utils tests --- kernel/src/devices/block_device_utils.cpp | 2 +- kernel/src/devices/block_device_utils.tests.cpp | 189 ++++++++++++++++++++++++ 2 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 kernel/src/devices/block_device_utils.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/devices/block_device_utils.cpp b/kernel/src/devices/block_device_utils.cpp index 6fe89fe..a1fd5e3 100644 --- a/kernel/src/devices/block_device_utils.cpp +++ b/kernel/src/devices/block_device_utils.cpp @@ -1,9 +1,9 @@ #include "kernel/devices/block_device_utils.hpp" +#include "kapi/devices/device.hpp" #include "kapi/system.hpp" #include "kernel/devices/block_device.hpp" -#include "kapi/devices/device.hpp" #include #include diff --git a/kernel/src/devices/block_device_utils.tests.cpp b/kernel/src/devices/block_device_utils.tests.cpp new file mode 100644 index 0000000..7ecd202 --- /dev/null +++ b/kernel/src/devices/block_device_utils.tests.cpp @@ -0,0 +1,189 @@ +#include "kernel/devices/block_device_utils.hpp" + +#include "kernel/test_support/cpu.hpp" +#include "kernel/test_support/devices/block_device.hpp" + +#include +#include +#include + +#include + +#include +#include + +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 device = kstd::make_shared(0, 0, "test_block_device", block_size); + kstd::vector block_data(block_size); + for (size_t i = 0; i < block_data.size(); ++i) + { + block_data[i] = static_cast(i % 256); + } + device->write_block(0, block_data.data()); + device->write_block(1, block_data.data()); + + WHEN("reading from the block device using block_device_utils") + { + kstd::vector read_buffer(block_size); + auto bytes_read = kernel::devices::block_device_utils::read(device, read_buffer.data(), 0, read_buffer.size()); + + THEN("the correct number of bytes is read") + { + REQUIRE(bytes_read == read_buffer.size()); + } + + THEN("the data read matches the data written to the block device") + { + REQUIRE(read_buffer == block_data); + } + } + + WHEN("reading over block boundaries") + { + kstd::vector read_buffer(1024); + auto bytes_read = kernel::devices::block_device_utils::read(device, read_buffer.data(), 256, read_buffer.size()); + + THEN("the correct number of bytes is read") + { + REQUIRE(bytes_read == 1.5 * block_size); + } + + THEN("the data read matches the expected data across block boundaries") + { + for (size_t i = 0; i < bytes_read; ++i) + { + uint8_t expected_value = static_cast((256 + i) % 256); + REQUIRE(read_buffer[i] == expected_value); + } + } + } + + WHEN("reading beyond the device capacity") + { + kstd::vector read_buffer(block_size); + auto bytes_read = kernel::devices::block_device_utils::read(device, read_buffer.data(), 1024, read_buffer.size()); + + THEN("no bytes are read") + { + REQUIRE(bytes_read == 0); + } + } + + WHEN("reading nothing") + { + kstd::vector read_buffer(block_size); + auto bytes_read = kernel::devices::block_device_utils::read(device, read_buffer.data(), 0, 0); + + THEN("no bytes are read") + { + REQUIRE(bytes_read == 0); + } + } + + WHEN("reading with a null buffer") + { + THEN("the system panics") + { + REQUIRE_THROWS_AS(kernel::devices::block_device_utils::read(device, nullptr, 0, 512), kernel::tests::cpu::halt); + } + } + } +} + +SCENARIO("writing to a block device using block_device_utils", "[devices][block_device_utils]") +{ + GIVEN("a block device") + { + auto const block_size = 512; + auto device = kstd::make_shared(0, 0, "test_block_device", block_size); + device->data.resize(2 * block_size); + + WHEN("writing to the block device using block_device_utils") + { + kstd::vector write_buffer(block_size); + for (size_t i = 0; i < write_buffer.size(); ++i) + { + write_buffer[i] = static_cast(i % 256); + } + + auto bytes_written = + kernel::devices::block_device_utils::write(device, write_buffer.data(), 0, write_buffer.size()); + + THEN("the correct number of bytes is written") + { + REQUIRE(bytes_written == write_buffer.size()); + } + + THEN("the data written matches the data read back from the block device") + { + kstd::vector read_buffer(block_size); + device->read_block(0, read_buffer.data()); + REQUIRE(read_buffer == write_buffer); + } + } + + WHEN("writing over block boundaries") + { + kstd::vector write_buffer(2 * block_size); + for (size_t i = 0; i < write_buffer.size(); ++i) + { + write_buffer[i] = static_cast(i % 256); + } + + auto bytes_written = + kernel::devices::block_device_utils::write(device, write_buffer.data(), 256, write_buffer.size()); + + THEN("the correct number of bytes is written") + { + REQUIRE(bytes_written == 1.5 * block_size); + } + + THEN("the data written matches the data read back from the block device across block boundaries") + { + kstd::vector read_buffer(2 * block_size); + auto bytes_read = kernel::devices::block_device_utils::read(device, read_buffer.data(), 256, 2 * block_size); + + for (size_t i = 0; i < bytes_read; ++i) + { + REQUIRE(read_buffer[i] == write_buffer[i]); + } + } + } + + WHEN("writing beyond the device capacity") + { + kstd::vector write_buffer(block_size); + auto bytes_written = + kernel::devices::block_device_utils::write(device, write_buffer.data(), 1024, write_buffer.size()); + + THEN("no bytes are written") + { + REQUIRE(bytes_written == 0); + } + } + + WHEN("writing nothing") + { + kstd::vector write_buffer(block_size); + auto bytes_written = kernel::devices::block_device_utils::write(device, write_buffer.data(), 0, 0); + + THEN("no bytes are written") + { + REQUIRE(bytes_written == 0); + } + } + + WHEN("writing with a null buffer") + { + THEN("the system panics") + { + REQUIRE_THROWS_AS(kernel::devices::block_device_utils::write(device, nullptr, 0, block_size), + kernel::tests::cpu::halt); + } + } + } +} \ No newline at end of file -- cgit v1.2.3 From 8e9e9ffd0528ffa554c336871f1a484c15613bfc Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 19:28:54 +0200 Subject: add block_device tests --- kernel/src/devices/block_device.cpp | 3 +- kernel/src/devices/block_device.tests.cpp | 46 ++++++++++++++++++++++++ kernel/src/devices/block_device_utils.tests.cpp | 4 +-- kernel/src/test_support/devices/block_device.cpp | 7 ++-- 4 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 kernel/src/devices/block_device.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/devices/block_device.cpp b/kernel/src/devices/block_device.cpp index c006198..b7cb26e 100644 --- a/kernel/src/devices/block_device.cpp +++ b/kernel/src/devices/block_device.cpp @@ -1,8 +1,7 @@ #include "kernel/devices/block_device.hpp" -#include "kapi/system.hpp" - #include "kapi/devices/device.hpp" +#include "kapi/system.hpp" #include diff --git a/kernel/src/devices/block_device.tests.cpp b/kernel/src/devices/block_device.tests.cpp new file mode 100644 index 0000000..378437e --- /dev/null +++ b/kernel/src/devices/block_device.tests.cpp @@ -0,0 +1,46 @@ +#include "kernel/test_support/devices/block_device.hpp" + +#include "kernel/test_support/cpu.hpp" + +#include +#include +#include +#include + +#include + +#include + +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; + + WHEN("constructing a block device") + { + auto device = + kstd::make_shared(major, minor, name, block_size, 3 * block_size); + + THEN("the block device has the correct properties") + { + REQUIRE(device->major() == major); + REQUIRE(device->minor() == minor); + REQUIRE(device->name() == name); + REQUIRE(device->block_size() == block_size); + REQUIRE(device->capacity() == 3 * 512); + } + } + + WHEN("constructing a block device with zero block size") + { + THEN("the constructor panics") + { + REQUIRE_THROWS_AS((kernel::tests::devices::block_device(major, minor, name, 0)), kernel::tests::cpu::halt); + } + } + } +} diff --git a/kernel/src/devices/block_device_utils.tests.cpp b/kernel/src/devices/block_device_utils.tests.cpp index 7ecd202..5f27a9b 100644 --- a/kernel/src/devices/block_device_utils.tests.cpp +++ b/kernel/src/devices/block_device_utils.tests.cpp @@ -99,8 +99,8 @@ SCENARIO("writing to a block device using block_device_utils", "[devices][block_ GIVEN("a block device") { auto const block_size = 512; - auto device = kstd::make_shared(0, 0, "test_block_device", block_size); - device->data.resize(2 * block_size); + auto device = + kstd::make_shared(0, 0, "test_block_device", block_size, 2 * block_size); WHEN("writing to the block device using block_device_utils") { diff --git a/kernel/src/test_support/devices/block_device.cpp b/kernel/src/test_support/devices/block_device.cpp index bce415f..d1d4101 100644 --- a/kernel/src/test_support/devices/block_device.cpp +++ b/kernel/src/test_support/devices/block_device.cpp @@ -13,9 +13,12 @@ namespace kernel::tests::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, size_t block_size, + size_t initial_size) : kernel::devices::block_device(major, minor, name, block_size) - {} + { + data.resize(initial_size, 0); + } auto block_device::init() -> bool { -- cgit v1.2.3 From 6d72142158970119ee0d36d9149c0e0572dedf5f Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 19:43:15 +0200 Subject: add non block device for tests --- kernel/src/test_support/devices/character_device.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 kernel/src/test_support/devices/character_device.cpp (limited to 'kernel/src') diff --git a/kernel/src/test_support/devices/character_device.cpp b/kernel/src/test_support/devices/character_device.cpp new file mode 100644 index 0000000..9e9227d --- /dev/null +++ b/kernel/src/test_support/devices/character_device.cpp @@ -0,0 +1,20 @@ + +#include "kernel/test_support/devices/character_device.hpp" + +#include "kapi/devices.hpp" + +#include + +#include + +namespace kernel::tests::devices +{ + character_device::character_device(size_t major, size_t minor, kstd::string const & name) + : kapi::devices::device(major, minor, name) + {} + + auto character_device::init() -> bool + { + return true; + } +} // namespace kernel::tests::devices \ No newline at end of file -- cgit v1.2.3 From e599e359f727be29415b63c83f3df620d6e4c53c Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 19:50:38 +0200 Subject: fix is_block_device check, add device_inode and non-block device tests --- kernel/src/devices/block_device_utils.cpp | 5 +- kernel/src/devices/block_device_utils.tests.cpp | 32 ++++++- kernel/src/filesystem/device_inode.tests.cpp | 108 ++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 kernel/src/filesystem/device_inode.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/devices/block_device_utils.cpp b/kernel/src/devices/block_device_utils.cpp index a1fd5e3..59e9b97 100644 --- a/kernel/src/devices/block_device_utils.cpp +++ b/kernel/src/devices/block_device_utils.cpp @@ -31,12 +31,13 @@ namespace kernel::devices::block_device_utils return 0; } - auto * block_dev = static_cast(device.get()); - if (block_dev == nullptr) + if (!device->is_block_device()) { kapi::system::panic("[FILESYSTEM] device_file: expected block_device."); } + auto * block_dev = static_cast(device.get()); + size_t const block_size = block_dev->block_size(); size_t const capacity = block_dev->capacity(); diff --git a/kernel/src/devices/block_device_utils.tests.cpp b/kernel/src/devices/block_device_utils.tests.cpp index 5f27a9b..f78e477 100644 --- a/kernel/src/devices/block_device_utils.tests.cpp +++ b/kernel/src/devices/block_device_utils.tests.cpp @@ -2,6 +2,7 @@ #include "kernel/test_support/cpu.hpp" #include "kernel/test_support/devices/block_device.hpp" +#include "kernel/test_support/devices/character_device.hpp" #include #include @@ -186,4 +187,33 @@ SCENARIO("writing to a block device using block_device_utils", "[devices][block_ } } } -} \ No newline at end of file +} + +SCENARIO("block_device_utils with a non-block device", "[devices][block_device_utils]") +{ + GIVEN("a non-block device") + { + auto device = kstd::make_shared(0, 0, "test_character_device"); + + WHEN("attempting to read from the non-block device using block_device_utils") + { + kstd::vector read_buffer(512); + THEN("the system panics") + { + REQUIRE_THROWS_AS(kernel::devices::block_device_utils::read(device, read_buffer.data(), 0, read_buffer.size()), + kernel::tests::cpu::halt); + } + } + + WHEN("attempting to write to the non-block device using block_device_utils") + { + kstd::vector 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); + } + } + } +} diff --git a/kernel/src/filesystem/device_inode.tests.cpp b/kernel/src/filesystem/device_inode.tests.cpp new file mode 100644 index 0000000..4e31812 --- /dev/null +++ b/kernel/src/filesystem/device_inode.tests.cpp @@ -0,0 +1,108 @@ +#include "kernel/filesystem/device_inode.hpp" + +#include "kernel/test_support/cpu.hpp" +#include "kernel/test_support/devices/block_device.hpp" +#include "kernel/test_support/devices/character_device.hpp" + +#include +#include +#include + +#include + +#include +#include + +SCENARIO("Device inode construction", "[filesystem][device_inode]") +{ + GIVEN("a block device") + { + auto device = kstd::make_shared(0, 0, "test_block_device", 512, 3 * 512); + + WHEN("constructing a device inode with the block device") + { + auto inode = kernel::filesystem::device_inode{device}; + + THEN("the device inode has the correct device") + { + REQUIRE(inode.device() == device); + } + + THEN("the device inode has the correct kind") + { + REQUIRE(inode.is_device()); + REQUIRE_FALSE(inode.is_directory()); + REQUIRE_FALSE(inode.is_regular()); + } + } + + WHEN("constructing a device inode with a null device") + { + THEN("the constructor panics") + { + REQUIRE_THROWS_AS((kernel::filesystem::device_inode{nullptr}), kernel::tests::cpu::halt); + } + } + } +} + +SCENARIO("Device inode read/write", "[filesystem][device_inode]") +{ + GIVEN("a block device and a device inode for that device") + { + auto device = kstd::make_shared(0, 0, "test_block_device", 512, 3 * 512); + auto inode = kernel::filesystem::device_inode{device}; + + WHEN("writing to the device inode") + { + kstd::vector write_buffer(1024); + for (size_t i = 0; i < write_buffer.size(); ++i) + { + write_buffer[i] = static_cast(i % 256); + } + + auto bytes_written = inode.write(write_buffer.data(), 256, write_buffer.size()); + + THEN("the correct number of bytes is written") + { + REQUIRE(bytes_written == 1024); + } + + THEN("the data written matches the data read back from the device inode") + { + kstd::vector read_buffer(1024); + auto bytes_read = inode.read(read_buffer.data(), 256, read_buffer.size()); + + REQUIRE(bytes_read == write_buffer.size()); + REQUIRE(read_buffer == write_buffer); + } + } + } +} + +SCENARIO("Device inode read/write with a non-block device", "[filesystem][device_inode]") +{ + GIVEN("a non-block device and a device inode for that device") + { + auto device = kstd::make_shared(0, 0, "test_character_device"); + auto inode = kernel::filesystem::device_inode{device}; + + WHEN("reading from the device inode") + { + kstd::vector read_buffer(512); + THEN("the system panics") + { + REQUIRE_THROWS_AS(inode.read(read_buffer.data(), 0, read_buffer.size()), kernel::tests::cpu::halt); + } + } + + WHEN("writing to the device inode") + { + kstd::vector write_buffer(512); + THEN("the system panics") + { + REQUIRE_THROWS_AS(inode.write(write_buffer.data(), 0, write_buffer.size()), kernel::tests::cpu::halt); + } + } + } +} -- cgit v1.2.3 From 153d061ddfcc6cb9bff1f691a3fe5415f94a3615 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 20:41:49 +0200 Subject: remove todos --- kernel/src/filesystem/filesystem.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index da2838d..d8b04eb 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -41,7 +41,11 @@ namespace kernel::filesystem auto filesystem::mount(kstd::shared_ptr const & device) -> operation_result { - // TODO BA-FS26 maybe check if device is null and panic here already? + if (!device) + { + kapi::system::panic("[FILESYSTEM] cannot mount filesystem: device is null."); + } + m_device = device; return operation_result::success; } -- cgit v1.2.3 From 597251886a0934315468f5ba4dc595910cbf734c Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 20:42:12 +0200 Subject: use separate test inode --- kernel/src/filesystem/dentry.tests.cpp | 8 ++++---- kernel/src/test_support/filesystem/inode.cpp | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 kernel/src/test_support/filesystem/inode.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.tests.cpp b/kernel/src/filesystem/dentry.tests.cpp index 94aa48d..a6620d3 100644 --- a/kernel/src/filesystem/dentry.tests.cpp +++ b/kernel/src/filesystem/dentry.tests.cpp @@ -1,7 +1,7 @@ #include "kernel/filesystem/dentry.hpp" -#include "kernel/filesystem/devfs/inode.hpp" #include "kernel/test_support/cpu.hpp" +#include "kernel/test_support/filesystem/inode.hpp" #include #include @@ -12,7 +12,7 @@ SCENARIO("Dentry construction", "[filesystem][dentry]") { GIVEN("A parent dentry and inode") { - auto inode = kstd::make_shared(); + auto inode = kstd::make_shared(); auto parent_dentry = kstd::make_shared(nullptr, inode); WHEN("constructing a dentry") @@ -80,7 +80,7 @@ SCENARIO("Dentry child logic", "[filesystem][dentry]") { GIVEN("A parent dentry and inode") { - auto inode = kstd::make_shared(); + auto inode = kstd::make_shared(); auto parent_dentry = kstd::make_shared(nullptr, inode); WHEN("adding child dentries") @@ -108,7 +108,7 @@ SCENARIO("Dentry Flag logic", "[filesystem][dentry]") { GIVEN("A dentry") { - auto inode = kstd::make_shared(); + auto inode = kstd::make_shared(); auto dentry = kernel::filesystem::dentry{nullptr, inode, "test"}; WHEN("setting a flag") diff --git a/kernel/src/test_support/filesystem/inode.cpp b/kernel/src/test_support/filesystem/inode.cpp new file mode 100644 index 0000000..6352d5a --- /dev/null +++ b/kernel/src/test_support/filesystem/inode.cpp @@ -0,0 +1,22 @@ +#include "kernel/test_support/filesystem/inode.hpp" + +#include "kernel/filesystem/inode.hpp" + +#include + +namespace kernel::tests::filesystem +{ + inode::inode() + : kernel::filesystem::inode(inode_kind::regular) + {} + + auto inode::read(void *, size_t, size_t) const -> size_t + { + return 0; + } + + auto inode::write(void const *, size_t, size_t) -> size_t + { + return 0; + } +} // namespace kernel::tests::filesystem \ No newline at end of file -- cgit v1.2.3 From 2500898ec94d5071fddb32432ed8041b8e9de26c Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 20:55:49 +0200 Subject: add test_support filesystem --- kernel/src/test_support/filesystem/filesystem.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 kernel/src/test_support/filesystem/filesystem.cpp (limited to 'kernel/src') diff --git a/kernel/src/test_support/filesystem/filesystem.cpp b/kernel/src/test_support/filesystem/filesystem.cpp new file mode 100644 index 0000000..225d096 --- /dev/null +++ b/kernel/src/test_support/filesystem/filesystem.cpp @@ -0,0 +1,17 @@ +#include "kernel/test_support/filesystem/filesystem.hpp" + +#include "kernel/filesystem/inode.hpp" +#include "kernel/test_support/filesystem/inode.hpp" + +#include + +#include + +namespace kernel::tests::filesystem +{ + auto filesystem::lookup(kstd::shared_ptr const &, std::string_view) + -> kstd::shared_ptr + { + return kstd::make_shared(); + } +} // namespace kernel::tests::filesystem \ No newline at end of file -- cgit v1.2.3 From b36f4ed031bf8da10ccf2b97c9a61d71e672621e Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 20:56:06 +0200 Subject: add mount tests --- kernel/src/filesystem/mount.tests.cpp | 49 +++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 kernel/src/filesystem/mount.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount.tests.cpp b/kernel/src/filesystem/mount.tests.cpp new file mode 100644 index 0000000..4c4393a --- /dev/null +++ b/kernel/src/filesystem/mount.tests.cpp @@ -0,0 +1,49 @@ +#include "kernel/filesystem/mount.hpp" + +#include "kernel/filesystem/dentry.hpp" +#include "kernel/test_support/cpu.hpp" +#include "kernel/test_support/filesystem/filesystem.hpp" +#include "kernel/test_support/filesystem/inode.hpp" + +#include +#include +#include + +#include + +SCENARIO("Mount construction", "[filesystem][mount]") +{ + GIVEN("a filesystem and a root dentry") + { + auto fs = kstd::make_shared(); + auto root_inode = kstd::make_shared(); + auto root_dentry = kstd::make_shared(nullptr, root_inode, "/"); + + WHEN("constructing a mount with the filesystem and root dentry") + { + auto mount = kernel::filesystem::mount{root_dentry, root_dentry, fs, "/", nullptr}; + + THEN("the mount has the correct filesystem, root dentry, mount dentry, and mount path") + { + REQUIRE(mount.get_filesystem() == fs); + REQUIRE(mount.root_dentry() == root_dentry); + REQUIRE(mount.get_mount_dentry() == root_dentry); + REQUIRE(mount.get_mount_path() == "/"); + } + + THEN("the mount has no parent mount") + { + REQUIRE(mount.get_parent_mount() == nullptr); + } + } + + WHEN("constructing a mount with a null filesystem") + { + THEN("the constructor panics") + { + REQUIRE_THROWS_AS((kernel::filesystem::mount{root_dentry, root_dentry, nullptr, "/", nullptr}), + kernel::tests::cpu::halt); + } + } + } +} -- cgit v1.2.3 From f4e210b1e6169df99db621ca624555027047bc50 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 21:08:08 +0200 Subject: add mount_table tests --- kernel/src/filesystem/mount_table.tests.cpp | 164 ++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 kernel/src/filesystem/mount_table.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.tests.cpp b/kernel/src/filesystem/mount_table.tests.cpp new file mode 100644 index 0000000..9f390c6 --- /dev/null +++ b/kernel/src/filesystem/mount_table.tests.cpp @@ -0,0 +1,164 @@ +#include "kernel/filesystem/mount_table.hpp" + +#include "kernel/filesystem/dentry.hpp" +#include "kernel/filesystem/mount.hpp" +#include "kernel/test_support/cpu.hpp" +#include "kernel/test_support/filesystem/filesystem.hpp" +#include "kernel/test_support/filesystem/inode.hpp" + +#include +#include +#include + +#include + +#include + +SCENARIO("Mount table construction", "[filesystem][mount_table]") +{ + GIVEN("an empty mount table") + { + kernel::filesystem::mount_table table; + + THEN("finding any mount returns null") + { + REQUIRE(table.find_longest_prefix_mount("/") == nullptr); + REQUIRE(table.find_longest_prefix_mount("/any/path") == nullptr); + } + + THEN("removing any mount returns mount_not_found") + { + REQUIRE(table.remove_mount("/") == kernel::filesystem::mount_table::operation_result::mount_not_found); + REQUIRE(table.remove_mount("/any/path") == kernel::filesystem::mount_table::operation_result::mount_not_found); + } + } +} + +SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem][mount_table]") +{ + GIVEN("a mount table and some mounts") + { + kernel::filesystem::mount_table table; + + auto fs1 = kstd::make_shared(); + auto root_inode1 = kstd::make_shared(); + auto root_dentry1 = kstd::make_shared(nullptr, root_inode1, "/"); + auto mount1 = kstd::make_shared(root_dentry1, root_dentry1, fs1, "/", nullptr); + + auto fs2 = kstd::make_shared(); + auto root_inode2 = kstd::make_shared(); + auto root_dentry2 = kstd::make_shared(nullptr, root_inode2, "/"); + auto mount2 = kstd::make_shared(root_dentry1, root_dentry2, fs2, "/mnt", nullptr); + + table.add_mount(mount1); + table.add_mount(mount2); + + THEN("dentry flags are set correctly for mounted dentries") + { + REQUIRE(root_dentry1->has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + REQUIRE(root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + } + + THEN("finding mounts by path returns the correct mount") + { + REQUIRE(table.find_longest_prefix_mount("/") == mount1); + REQUIRE(table.find_longest_prefix_mount("/file") == mount1); + REQUIRE(table.find_longest_prefix_mount("/mnt") == mount2); + REQUIRE(table.find_longest_prefix_mount("/mnt/file") == mount2); + REQUIRE(table.find_longest_prefix_mount("/other") == mount1); + } + + THEN("removing a mount that has no child mounts succeeds") + { + REQUIRE(table.remove_mount("/mnt") == kernel::filesystem::mount_table::operation_result::removed); + REQUIRE(!root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + REQUIRE(table.find_longest_prefix_mount("/mnt") == nullptr); + } + + THEN("removing a mount that does not exist returns mount_not_found") + { + REQUIRE(table.remove_mount("/nonexistent") == kernel::filesystem::mount_table::operation_result::mount_not_found); + } + } + + GIVEN("multiple mounts with the same path") + { + kernel::filesystem::mount_table table; + + auto fs1 = kstd::make_shared(); + auto root_inode1 = kstd::make_shared(); + auto root_dentry1 = kstd::make_shared(nullptr, root_inode1, "/"); + auto mount1 = kstd::make_shared(root_dentry1, root_dentry1, fs1, "/", nullptr); + + auto fs2 = kstd::make_shared(); + auto root_inode2 = kstd::make_shared(); + auto root_dentry2 = kstd::make_shared(nullptr, root_inode2, "/"); + auto mount2 = kstd::make_shared(root_dentry1, root_dentry2, fs2, "/", mount1); + + table.add_mount(mount1); + table.add_mount(mount2); + + THEN("finding mounts by path returns the correct mount based on longest prefix") + { + REQUIRE(table.find_longest_prefix_mount("/") == mount2); + REQUIRE(table.find_longest_prefix_mount("/file") == mount2); + REQUIRE(table.find_longest_prefix_mount("/mnt") == mount2); + REQUIRE(table.find_longest_prefix_mount("/mnt/file") == mount2); + REQUIRE(table.find_longest_prefix_mount("/other") == mount2); + } + + THEN("removing the topmost mount with the same path succeeds") + { + REQUIRE(table.remove_mount("/") == kernel::filesystem::mount_table::operation_result::removed); + REQUIRE(!root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + REQUIRE(table.find_longest_prefix_mount("/") == mount1); + } + } + + GIVEN("a mount with child mounts") + { + kernel::filesystem::mount_table table; + + auto fs1 = kstd::make_shared(); + auto root_inode1 = kstd::make_shared(); + auto root_dentry1 = kstd::make_shared(nullptr, root_inode1, "/"); + auto mount1 = kstd::make_shared(root_dentry1, root_dentry1, fs1, "/", nullptr); + + auto fs2 = kstd::make_shared(); + auto root_inode2 = kstd::make_shared(); + auto root_dentry2 = kstd::make_shared(nullptr, root_inode2, "/"); + auto mount2 = kstd::make_shared(root_dentry1, root_dentry2, fs2, "/mnt", mount1); + + auto fs3 = kstd::make_shared(); + auto root_inode3 = kstd::make_shared(); + auto root_dentry3 = kstd::make_shared(nullptr, root_inode3, "/"); + auto mount3 = kstd::make_shared(root_dentry2, root_dentry3, fs3, "/mnt/submnt", mount2); + + table.add_mount(mount1); + table.add_mount(mount2); + table.add_mount(mount3); + + THEN("finding mounts by path returns the correct mount based on longest prefix") + { + REQUIRE(table.find_longest_prefix_mount("/") == mount1); + REQUIRE(table.find_longest_prefix_mount("/file") == mount1); + REQUIRE(table.find_longest_prefix_mount("/mnt") == mount2); + REQUIRE(table.find_longest_prefix_mount("/mnt/file") == mount2); + REQUIRE(table.find_longest_prefix_mount("/mnt/submnt") == mount3); + REQUIRE(table.find_longest_prefix_mount("/other") == mount1); + } + + THEN("removing a mount with child mounts returns has_child_mounts") + { + REQUIRE(table.remove_mount("/") == kernel::filesystem::mount_table::operation_result::has_child_mounts); + REQUIRE(table.remove_mount("/mnt") == kernel::filesystem::mount_table::operation_result::has_child_mounts); + } + + THEN("removing a leaf mount succeeds") + { + REQUIRE(table.remove_mount("/mnt/submnt") == kernel::filesystem::mount_table::operation_result::removed); + REQUIRE(!root_dentry3->has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + REQUIRE(table.find_longest_prefix_mount("/mnt/submnt") == nullptr); + } + } +} -- cgit v1.2.3 From 7a7c0106257665358e68bbbc99b41acc0c87c0ba Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 21:16:14 +0200 Subject: fix mount table tests --- kernel/src/filesystem/mount_table.tests.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.tests.cpp b/kernel/src/filesystem/mount_table.tests.cpp index 9f390c6..439fe97 100644 --- a/kernel/src/filesystem/mount_table.tests.cpp +++ b/kernel/src/filesystem/mount_table.tests.cpp @@ -2,7 +2,6 @@ #include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/mount.hpp" -#include "kernel/test_support/cpu.hpp" #include "kernel/test_support/filesystem/filesystem.hpp" #include "kernel/test_support/filesystem/inode.hpp" @@ -56,7 +55,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("dentry flags are set correctly for mounted dentries") { REQUIRE(root_dentry1->has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); - REQUIRE(root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + REQUIRE(!root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); } THEN("finding mounts by path returns the correct mount") @@ -72,7 +71,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] { REQUIRE(table.remove_mount("/mnt") == kernel::filesystem::mount_table::operation_result::removed); REQUIRE(!root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); - REQUIRE(table.find_longest_prefix_mount("/mnt") == nullptr); + REQUIRE(table.find_longest_prefix_mount("/mnt") == mount1); } THEN("removing a mount that does not exist returns mount_not_found") @@ -158,7 +157,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] { REQUIRE(table.remove_mount("/mnt/submnt") == kernel::filesystem::mount_table::operation_result::removed); REQUIRE(!root_dentry3->has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); - REQUIRE(table.find_longest_prefix_mount("/mnt/submnt") == nullptr); + REQUIRE(table.find_longest_prefix_mount("/mnt/submnt") == mount2); } } } -- cgit v1.2.3 From af048d3e550bc2a7a6526f4c9714871e32bf7cf4 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 21:38:50 +0200 Subject: add open_file_description tests --- kernel/src/filesystem/open_file_description.cpp | 6 +++ .../src/filesystem/open_file_description.tests.cpp | 60 ++++++++++++++++++++++ kernel/src/test_support/filesystem/inode.cpp | 8 +-- 3 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 kernel/src/filesystem/open_file_description.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/open_file_description.cpp b/kernel/src/filesystem/open_file_description.cpp index 8c04225..f049a34 100644 --- a/kernel/src/filesystem/open_file_description.cpp +++ b/kernel/src/filesystem/open_file_description.cpp @@ -32,4 +32,10 @@ namespace kernel::filesystem m_offset += written_bytes; return written_bytes; } + + auto open_file_description::offset() const -> size_t + { + return m_offset; + } + } // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/open_file_description.tests.cpp b/kernel/src/filesystem/open_file_description.tests.cpp new file mode 100644 index 0000000..f045094 --- /dev/null +++ b/kernel/src/filesystem/open_file_description.tests.cpp @@ -0,0 +1,60 @@ +#include "kernel/filesystem/open_file_description.hpp" + +#include "kernel/test_support/filesystem/inode.hpp" + +#include +#include +#include + +#include + +SCENARIO("Open file description construction", "[filesystem][open_file_description]") +{ + GIVEN("an inode and an open file description for that inode") + { + auto inode = kstd::make_shared(); + auto file_description = kernel::filesystem::open_file_description{inode}; + + THEN("the initial offset is zero") + { + REQUIRE(file_description.offset() == 0); + } + } +} + +SCENARIO("Open file description read/write offset management", "[filesystem][open_file_description]") +{ + GIVEN("an inode that tracks read/write calls and an open file description for that inode") + { + auto inode = kstd::make_shared(); + auto file_description = kernel::filesystem::open_file_description{inode}; + + THEN("the offset is updated correctly after reads") + { + REQUIRE(file_description.read(nullptr, 100) == 100); + REQUIRE(file_description.offset() == 100); + REQUIRE(file_description.read(nullptr, 50) == 50); + REQUIRE(file_description.offset() == 150); + } + + THEN("the offset is updated correctly after writes") + { + REQUIRE(file_description.write(nullptr, 200) == 200); + REQUIRE(file_description.offset() == 200); + REQUIRE(file_description.write(nullptr, 25) == 25); + REQUIRE(file_description.offset() == 225); + } + + THEN("reads and writes both update the same offset") + { + REQUIRE(file_description.read(nullptr, 10) == 10); + REQUIRE(file_description.offset() == 10); + REQUIRE(file_description.write(nullptr, 20) == 20); + REQUIRE(file_description.offset() == 30); + REQUIRE(file_description.read(nullptr, 5) == 5); + REQUIRE(file_description.offset() == 35); + REQUIRE(file_description.write(nullptr, 15) == 15); + REQUIRE(file_description.offset() == 50); + } + } +} diff --git a/kernel/src/test_support/filesystem/inode.cpp b/kernel/src/test_support/filesystem/inode.cpp index 6352d5a..5df7bcd 100644 --- a/kernel/src/test_support/filesystem/inode.cpp +++ b/kernel/src/test_support/filesystem/inode.cpp @@ -10,13 +10,13 @@ namespace kernel::tests::filesystem : kernel::filesystem::inode(inode_kind::regular) {} - auto inode::read(void *, size_t, size_t) const -> size_t + auto inode::read(void *, size_t, size_t size) const -> size_t { - return 0; + return size; } - auto inode::write(void const *, size_t, size_t) -> size_t + auto inode::write(void const *, size_t, size_t size) -> size_t { - return 0; + return size; } } // namespace kernel::tests::filesystem \ No newline at end of file -- cgit v1.2.3 From 530a478b3e755ef4585b27422a33bd0de1556ce2 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 22:12:51 +0200 Subject: add file_descriptor_table tests --- kernel/src/filesystem/file_descriptor_table.cpp | 5 + .../src/filesystem/file_descriptor_table.tests.cpp | 155 +++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 kernel/src/filesystem/file_descriptor_table.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/file_descriptor_table.cpp b/kernel/src/filesystem/file_descriptor_table.cpp index 287aea2..a31e2e6 100644 --- a/kernel/src/filesystem/file_descriptor_table.cpp +++ b/kernel/src/filesystem/file_descriptor_table.cpp @@ -37,6 +37,11 @@ namespace kernel::filesystem return *global_file_descriptor_table; } + auto file_descriptor_table::reset() -> void + { + global_file_descriptor_table.reset(); + } + auto file_descriptor_table::add_file(kstd::shared_ptr const & file_description) -> int { if (!file_description) diff --git a/kernel/src/filesystem/file_descriptor_table.tests.cpp b/kernel/src/filesystem/file_descriptor_table.tests.cpp new file mode 100644 index 0000000..c431d01 --- /dev/null +++ b/kernel/src/filesystem/file_descriptor_table.tests.cpp @@ -0,0 +1,155 @@ +#include "kernel/filesystem/file_descriptor_table.hpp" + +#include "kernel/filesystem/open_file_description.hpp" +#include "kernel/test_support/cpu.hpp" +#include "kernel/test_support/filesystem/inode.hpp" + +#include +#include +#include + +#include + +struct file_descriptor_table_RAII +{ + file_descriptor_table_RAII() + { + kernel::filesystem::file_descriptor_table::init(); + } + ~file_descriptor_table_RAII() + { + kernel::filesystem::file_descriptor_table::reset(); + } +}; + +struct file_descriptor_table_reset_only +{ + ~file_descriptor_table_reset_only() + { + kernel::filesystem::file_descriptor_table::reset(); + } +}; + +SCENARIO_METHOD(file_descriptor_table_reset_only, "File descriptor table initialization", + "[filesystem][file_descriptor_table]") +{ + THEN("accessing the file descriptor table before initialization panics") + { + REQUIRE_THROWS_AS(kernel::filesystem::file_descriptor_table::get(), kernel::tests::cpu::halt); + } + + THEN("the file descriptor table can be initialized and accessed") + { + kernel::filesystem::file_descriptor_table::init(); + REQUIRE_NOTHROW(kernel::filesystem::file_descriptor_table::get()); + } + + THEN("initializing the file descriptor table more than once panics") + { + kernel::filesystem::file_descriptor_table::init(); + REQUIRE_THROWS_AS(kernel::filesystem::file_descriptor_table::init(), kernel::tests::cpu::halt); + } +} + +SCENARIO_METHOD(file_descriptor_table_RAII, "File descriptor table add/get file", "[filesystem][file_descriptor_table]") +{ + GIVEN("a file descriptor table and an open file description") + { + auto & table = kernel::filesystem::file_descriptor_table::get(); + auto inode = kstd::make_shared(); + auto file_description_1 = kstd::make_shared(inode); + auto file_description_2 = kstd::make_shared(inode); + + WHEN("adding the open file description to the file descriptor table") + { + auto fd_1 = table.add_file(file_description_1); + auto fd_2 = table.add_file(file_description_2); + auto fd_3 = table.add_file(file_description_2); + + THEN("a valid file descriptor is returned") + { + REQUIRE(fd_1 == 0); + REQUIRE(fd_2 == 1); + REQUIRE(fd_3 == 1); + } + + THEN("the file description can be retrieved using the returned file descriptor") + { + auto retrieved_description = table.get_file(fd_1); + REQUIRE(retrieved_description == file_description_1); + } + } + } + + GIVEN("a invalid open file description") + { + auto & table = kernel::filesystem::file_descriptor_table::get(); + + THEN("adding a null file description returns an error code") + { + auto fd = table.add_file(nullptr); + REQUIRE(fd == -1); + } + + THEN("retrieving a file description with a negative file descriptor returns a null pointer") + { + auto retrieved_description = table.get_file(-1); + REQUIRE(retrieved_description == nullptr); + } + + THEN("retrieving a file description with an out-of-bounds file descriptor returns a null pointer") + { + auto retrieved_description = table.get_file(1000); + REQUIRE(retrieved_description == nullptr); + } + } +} + +SCENARIO_METHOD(file_descriptor_table_RAII, "File descriptor table remove file", "[filesystem][file_descriptor_table]") +{ + GIVEN("a file descriptor table with an open file description") + { + auto & table = kernel::filesystem::file_descriptor_table::get(); + auto inode = kstd::make_shared(); + auto file_description = kstd::make_shared(inode); + auto fd = table.add_file(file_description); + + WHEN("removing the file description using the file descriptor") + { + table.remove_file(fd); + + THEN("the file description can no longer be retrieved using the file descriptor") + { + auto retrieved_description = table.get_file(fd); + REQUIRE(retrieved_description == nullptr); + } + } + + WHEN("removing a file description the other file descriptor keep the same index") + { + auto fd2 = table.add_file(file_description); + table.remove_file(fd); + + THEN("the second file description can still be retrieved using its file descriptor") + { + auto retrieved_description = table.get_file(fd2); + REQUIRE(retrieved_description == file_description); + } + } + } + + GIVEN("an invalid file descriptor") + { + auto & table = kernel::filesystem::file_descriptor_table::get(); + + THEN("removing a file with a negative file descriptor does nothing") + { + REQUIRE_NOTHROW(table.remove_file(-1)); + } + + THEN("removing a file with an out-of-bounds file descriptor does nothing") + { + REQUIRE_NOTHROW(table.remove_file(1000)); + } + } +} \ No newline at end of file -- cgit v1.2.3 From 643cbff68aa0a5e029b9ce46eb69846c8b01dca7 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 22:17:15 +0200 Subject: fix test --- kernel/src/filesystem/file_descriptor_table.tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/file_descriptor_table.tests.cpp b/kernel/src/filesystem/file_descriptor_table.tests.cpp index c431d01..d8c05ca 100644 --- a/kernel/src/filesystem/file_descriptor_table.tests.cpp +++ b/kernel/src/filesystem/file_descriptor_table.tests.cpp @@ -70,7 +70,7 @@ SCENARIO_METHOD(file_descriptor_table_RAII, "File descriptor table add/get file" { REQUIRE(fd_1 == 0); REQUIRE(fd_2 == 1); - REQUIRE(fd_3 == 1); + REQUIRE(fd_3 == 2); } THEN("the file description can be retrieved using the returned file descriptor") -- cgit v1.2.3 From 60118b1df5196c4e416ddd6ad2a40be062f68251 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 22:57:55 +0200 Subject: add devfs and rootfs inode tests --- kernel/src/filesystem/devfs/inode.tests.cpp | 54 ++++++++++++++++++ kernel/src/filesystem/rootfs/inode.tests.cpp | 83 ++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 kernel/src/filesystem/devfs/inode.tests.cpp create mode 100644 kernel/src/filesystem/rootfs/inode.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/devfs/inode.tests.cpp b/kernel/src/filesystem/devfs/inode.tests.cpp new file mode 100644 index 0000000..50e34a7 --- /dev/null +++ b/kernel/src/filesystem/devfs/inode.tests.cpp @@ -0,0 +1,54 @@ +#include "kernel/filesystem/devfs/inode.hpp" + +#include +#include +#include + +#include + +#include + +SCENARIO("Devfs inode creation", "[filesystem][devfs][inode]") +{ + GIVEN("a devfs inode") + { + auto inode = kernel::filesystem::devfs::inode{}; + + THEN("the inode has the correct kind") + { + REQUIRE(inode.is_directory()); + REQUIRE_FALSE(inode.is_device()); + REQUIRE_FALSE(inode.is_regular()); + } + } +} + +SCENARIO("Devfs inode read/write", "[filesystem][devfs][inode]") +{ + GIVEN("a devfs inode") + { + auto inode = kernel::filesystem::devfs::inode{}; + + WHEN("attempting to read from the devfs inode") + { + kstd::vector buffer(512); + auto bytes_read = inode.read(buffer.data(), 0, buffer.size()); + + THEN("no bytes are read") + { + REQUIRE(bytes_read == 0); + } + } + + WHEN("attempting to write to the devfs inode") + { + kstd::vector buffer(512); + auto bytes_written = inode.write(buffer.data(), 0, buffer.size()); + + THEN("no bytes are written") + { + REQUIRE(bytes_written == 0); + } + } + } +} diff --git a/kernel/src/filesystem/rootfs/inode.tests.cpp b/kernel/src/filesystem/rootfs/inode.tests.cpp new file mode 100644 index 0000000..a0c5938 --- /dev/null +++ b/kernel/src/filesystem/rootfs/inode.tests.cpp @@ -0,0 +1,83 @@ +#include "kernel/filesystem/rootfs/inode.hpp" + +#include +#include +#include + +#include + +SCENARIO("Rootfs inode creation", "[filesystem][rootfs][inode]") +{ + GIVEN("a rootfs inode") + { + auto inode = kernel::filesystem::rootfs::inode{}; + + THEN("the inode has the correct kind") + { + REQUIRE(inode.is_directory()); + REQUIRE_FALSE(inode.is_device()); + REQUIRE_FALSE(inode.is_regular()); + } + + THEN("the inode has no children") + { + REQUIRE(inode.lookup_child("child") == nullptr); + } + } +} + +SCENARIO("Rootfs inode child management", "[filesystem][rootfs][inode]") +{ + GIVEN("a rootfs inode") + { + auto inode = kernel::filesystem::rootfs::inode{}; + + WHEN("adding a child inode") + { + inode.add_child("child"); + inode.add_child("another child"); + + THEN("the child can be looked up by name") + { + auto child_inode = inode.lookup_child("child"); + REQUIRE(child_inode != nullptr); + REQUIRE(child_inode->is_directory()); + } + + THEN("looking up a non-existent child returns null") + { + REQUIRE(inode.lookup_child("nonexistent") == nullptr); + } + } + } +} + +SCENARIO("Rootfs inode read/write", "[filesystem][rootfs][inode]") +{ + GIVEN("a rootfs inode") + { + auto inode = kernel::filesystem::rootfs::inode{}; + + WHEN("reading from the inode") + { + kstd::vector buffer(10); + auto bytes_read = inode.read(buffer.data(), 0, buffer.size()); + + THEN("no bytes are read") + { + REQUIRE(bytes_read == 0); + } + } + + WHEN("writing to the inode") + { + kstd::vector buffer(10, 'x'); + auto bytes_written = inode.write(buffer.data(), 0, buffer.size()); + + THEN("no bytes are written") + { + REQUIRE(bytes_written == 0); + } + } + } +} -- cgit v1.2.3 From 9ce8ed3dd3aa5f6e21b53d02bac4f62eb8b3f337 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 23:04:40 +0200 Subject: add rootfs filesystem tests --- kernel/src/filesystem/rootfs/filesystem.tests.cpp | 45 +++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 kernel/src/filesystem/rootfs/filesystem.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/rootfs/filesystem.tests.cpp b/kernel/src/filesystem/rootfs/filesystem.tests.cpp new file mode 100644 index 0000000..b013f78 --- /dev/null +++ b/kernel/src/filesystem/rootfs/filesystem.tests.cpp @@ -0,0 +1,45 @@ +#include "kernel/filesystem/rootfs/filesystem.hpp" + +#include "kernel/filesystem/filesystem.hpp" + +#include +#include +#include + +#include + +SCENARIO("Rootfs filesystem mount and lookup", "[filesystem][rootfs][filesystem]") +{ + GIVEN("a mounted rootfs filesystem") + { + auto fs = kernel::filesystem::rootfs::filesystem{}; + auto result = fs.mount(nullptr); + + THEN("the filesystem can be mounted successfully") + { + REQUIRE(result == kernel::filesystem::filesystem::operation_result::success); + REQUIRE(fs.root_inode() != nullptr); + } + + THEN("looking up the 'dev' directory returns a valid inode") + { + auto dev_inode = fs.lookup(fs.root_inode(), "dev"); + REQUIRE(dev_inode != nullptr); + REQUIRE(dev_inode->is_directory()); + } + + THEN("looking up a non-existent directory returns null") + { + auto non_existent_inode_1 = fs.lookup(fs.root_inode(), ""); + REQUIRE(non_existent_inode_1 == nullptr); + auto non_existent_inode_2 = fs.lookup(fs.root_inode(), "nonexistent"); + REQUIRE(non_existent_inode_2 == nullptr); + } + + THEN("looking up with a null parent inode returns null") + { + auto result = fs.lookup(nullptr, "dev"); + REQUIRE(result == nullptr); + } + } +} -- cgit v1.2.3 From 3c9ad45492d7417c65594fa7fa2fb9a8d5439276 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 9 Apr 2026 08:32:51 +0200 Subject: add deinit functions for singletons in tests --- kernel/src/devices/storage/management.cpp | 28 ++++++++----- kernel/src/filesystem/file_descriptor_table.cpp | 25 ++++++------ .../src/filesystem/file_descriptor_table.tests.cpp | 46 +--------------------- kernel/src/filesystem/vfs.cpp | 24 +++++++---- kernel/src/test_support/state_reset_listener.cpp | 12 ++++++ 5 files changed, 63 insertions(+), 72 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/devices/storage/management.cpp b/kernel/src/devices/storage/management.cpp index d440bf0..14a045a 100644 --- a/kernel/src/devices/storage/management.cpp +++ b/kernel/src/devices/storage/management.cpp @@ -1,9 +1,9 @@ #include "kernel/devices/storage/management.hpp" #include "kapi/boot_modules.hpp" +#include "kapi/devices/device.hpp" #include "kapi/system.hpp" -#include "kapi/devices/device.hpp" #include "kernel/devices/storage/controller.hpp" #include "kernel/devices/storage/ram_disk/controller.hpp" @@ -14,17 +14,17 @@ #include #include -namespace kernel::devices::storage +namespace { - namespace - { - constexpr size_t static MINORS_PER_DEVICE = 16; - constexpr size_t static START_MAJOR = 1; - constinit size_t static next_free_major = START_MAJOR; + constexpr size_t static MINORS_PER_DEVICE = 16; + constexpr size_t static START_MAJOR = 1; + constinit size_t static next_free_major = START_MAJOR; - constinit auto static active_storage_management = std::optional{}; - } // namespace + constinit auto static active_storage_management = std::optional{}; +} // namespace +namespace kernel::devices::storage +{ auto management::init() -> void { if (active_storage_management) @@ -81,5 +81,13 @@ namespace kernel::devices::storage { return device_by_major_minor(START_MAJOR, 0); } +} // namespace kernel::devices::storage -} // namespace kernel::devices::storage \ No newline at end of file +namespace kernel::tests::devices::storage +{ + auto deinit() -> void + { + active_storage_management.reset(); + next_free_major = START_MAJOR; + } +} // namespace kernel::tests::devices::storage diff --git a/kernel/src/filesystem/file_descriptor_table.cpp b/kernel/src/filesystem/file_descriptor_table.cpp index a31e2e6..1c062a1 100644 --- a/kernel/src/filesystem/file_descriptor_table.cpp +++ b/kernel/src/filesystem/file_descriptor_table.cpp @@ -10,13 +10,13 @@ #include #include -namespace kernel::filesystem +namespace { - namespace - { - constinit auto static global_file_descriptor_table = std::optional{}; - } // namespace + constinit auto static global_file_descriptor_table = std::optional{}; +} // namespace +namespace kernel::filesystem +{ auto file_descriptor_table::init() -> void { if (global_file_descriptor_table) @@ -37,11 +37,6 @@ namespace kernel::filesystem return *global_file_descriptor_table; } - auto file_descriptor_table::reset() -> void - { - global_file_descriptor_table.reset(); - } - auto file_descriptor_table::add_file(kstd::shared_ptr const & file_description) -> int { if (!file_description) @@ -92,4 +87,12 @@ namespace kernel::filesystem m_open_files.at(index) = nullptr; } -} // namespace kernel::filesystem \ No newline at end of file +} // namespace kernel::filesystem + +namespace kernel::tests::filesystem::file_descriptor_table +{ + auto deinit() -> void + { + global_file_descriptor_table.reset(); + } +} // namespace kernel::tests::filesystem::file_descriptor_table diff --git a/kernel/src/filesystem/file_descriptor_table.tests.cpp b/kernel/src/filesystem/file_descriptor_table.tests.cpp index d8c05ca..5aeadb2 100644 --- a/kernel/src/filesystem/file_descriptor_table.tests.cpp +++ b/kernel/src/filesystem/file_descriptor_table.tests.cpp @@ -1,7 +1,6 @@ #include "kernel/filesystem/file_descriptor_table.hpp" #include "kernel/filesystem/open_file_description.hpp" -#include "kernel/test_support/cpu.hpp" #include "kernel/test_support/filesystem/inode.hpp" #include @@ -10,48 +9,7 @@ #include -struct file_descriptor_table_RAII -{ - file_descriptor_table_RAII() - { - kernel::filesystem::file_descriptor_table::init(); - } - ~file_descriptor_table_RAII() - { - kernel::filesystem::file_descriptor_table::reset(); - } -}; - -struct file_descriptor_table_reset_only -{ - ~file_descriptor_table_reset_only() - { - kernel::filesystem::file_descriptor_table::reset(); - } -}; - -SCENARIO_METHOD(file_descriptor_table_reset_only, "File descriptor table initialization", - "[filesystem][file_descriptor_table]") -{ - THEN("accessing the file descriptor table before initialization panics") - { - REQUIRE_THROWS_AS(kernel::filesystem::file_descriptor_table::get(), kernel::tests::cpu::halt); - } - - THEN("the file descriptor table can be initialized and accessed") - { - kernel::filesystem::file_descriptor_table::init(); - REQUIRE_NOTHROW(kernel::filesystem::file_descriptor_table::get()); - } - - THEN("initializing the file descriptor table more than once panics") - { - kernel::filesystem::file_descriptor_table::init(); - REQUIRE_THROWS_AS(kernel::filesystem::file_descriptor_table::init(), kernel::tests::cpu::halt); - } -} - -SCENARIO_METHOD(file_descriptor_table_RAII, "File descriptor table add/get file", "[filesystem][file_descriptor_table]") +SCENARIO("File descriptor table add/get file", "[filesystem][file_descriptor_table]") { GIVEN("a file descriptor table and an open file description") { @@ -105,7 +63,7 @@ SCENARIO_METHOD(file_descriptor_table_RAII, "File descriptor table add/get file" } } -SCENARIO_METHOD(file_descriptor_table_RAII, "File descriptor table remove file", "[filesystem][file_descriptor_table]") +SCENARIO("File descriptor table remove file", "[filesystem][file_descriptor_table]") { GIVEN("a file descriptor table with an open file description") { diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 45ae053..67d1af2 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -17,13 +17,13 @@ #include #include -namespace kernel::filesystem +namespace { - namespace - { - constinit auto static active_vfs = std::optional{}; - } // namespace + constinit auto static active_vfs = std::optional{}; +} // namespace +namespace kernel::filesystem +{ auto vfs::init() -> void { if (active_vfs) @@ -47,7 +47,10 @@ namespace kernel::filesystem if (auto boot_device = storage_mgmt.determine_boot_device()) { auto boot_root_fs = kernel::filesystem::filesystem::probe_and_mount(boot_device); - do_mount_internal("/", root_fs_root_dentry, boot_root_fs); + if (boot_root_fs) + { + do_mount_internal("/", root_fs_root_dentry, boot_root_fs); + } } auto device_fs = kstd::make_shared(); @@ -172,5 +175,12 @@ namespace kernel::filesystem return current_dentry; } +} // namespace kernel::filesystem -} // namespace kernel::filesystem \ No newline at end of file +namespace kernel::tests::filesystem::vfs +{ + auto deinit() -> void + { + active_vfs.reset(); + } +} // namespace kernel::tests::filesystem::vfs diff --git a/kernel/src/test_support/state_reset_listener.cpp b/kernel/src/test_support/state_reset_listener.cpp index 8c95cc8..af1091c 100644 --- a/kernel/src/test_support/state_reset_listener.cpp +++ b/kernel/src/test_support/state_reset_listener.cpp @@ -2,8 +2,13 @@ #include "kapi/cpu.hpp" #include "kapi/memory.hpp" +#include "kernel/filesystem/file_descriptor_table.hpp" +#include "kernel/test_support/boot_modules.hpp" #include "kernel/test_support/cio.hpp" #include "kernel/test_support/cpu.hpp" +#include "kernel/test_support/devices/storage/management.hpp" +#include "kernel/test_support/filesystem/file_descriptor_table.hpp" +#include "kernel/test_support/filesystem/vfs.hpp" #include "kernel/test_support/memory.hpp" #include @@ -17,6 +22,8 @@ struct state_reset_listener : Catch::EventListenerBase void testCaseStarting(Catch::TestCaseInfo const &) override { + kernel::filesystem::file_descriptor_table::init(); + kapi::cio::init(); kapi::cpu::init(); kapi::memory::init(); @@ -24,6 +31,11 @@ struct state_reset_listener : Catch::EventListenerBase void testCaseEnded(Catch::TestCaseStats const &) override { + kernel::tests::filesystem::file_descriptor_table::deinit(); + kernel::tests::filesystem::vfs::deinit(); + kernel::tests::devices::storage::deinit(); + kernel::tests::boot_modules::deinit(); + kernel::tests::memory::deinit(); kernel::tests::cpu::deinit(); kernel::tests::cio::deinit(); -- cgit v1.2.3 From 97e83ad1466d5962a1e5f5f83fa4c951bfeafb2c Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 9 Apr 2026 09:13:09 +0200 Subject: add devfs filesystem tests, and storage_boot_module_fixture to mock real boot modules --- kernel/src/devices/storage/management.cpp | 4 +- kernel/src/filesystem/devfs/filesystem.tests.cpp | 63 ++++++++++++++++++++++ .../filesystem/storage_boot_module_fixture.cpp | 43 +++++++++++++++ kernel/src/test_support/state_reset_listener.cpp | 2 +- 4 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 kernel/src/filesystem/devfs/filesystem.tests.cpp create mode 100644 kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp (limited to 'kernel/src') diff --git a/kernel/src/devices/storage/management.cpp b/kernel/src/devices/storage/management.cpp index 14a045a..c9fa0a8 100644 --- a/kernel/src/devices/storage/management.cpp +++ b/kernel/src/devices/storage/management.cpp @@ -83,11 +83,11 @@ namespace kernel::devices::storage } } // namespace kernel::devices::storage -namespace kernel::tests::devices::storage +namespace kernel::tests::devices::storage::management { auto deinit() -> void { active_storage_management.reset(); next_free_major = START_MAJOR; } -} // namespace kernel::tests::devices::storage +} // namespace kernel::tests::devices::storage::management diff --git a/kernel/src/filesystem/devfs/filesystem.tests.cpp b/kernel/src/filesystem/devfs/filesystem.tests.cpp new file mode 100644 index 0000000..1d82bf9 --- /dev/null +++ b/kernel/src/filesystem/devfs/filesystem.tests.cpp @@ -0,0 +1,63 @@ +#include "kernel/filesystem/devfs/filesystem.hpp" + +#include "kernel/filesystem/filesystem.hpp" +#include "kernel/test_support/filesystem/storage_boot_module_fixture.hpp" + +#include + +SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, + "Devfs filesystem lookup uses storage management devices", "[filesystem][devfs][filesystem]") +{ + GIVEN("a boot module registry with one module") + { + setup_modules(1); + + auto fs = kernel::filesystem::devfs::filesystem{}; + auto result = fs.mount(nullptr); + + THEN("mount succeeds") + { + REQUIRE(result == kernel::filesystem::filesystem::operation_result::success); + REQUIRE(fs.root_inode() != nullptr); + } + + THEN("lookup on root finds ram0 device inode") + { + auto inode = fs.lookup(fs.root_inode(), "ram0"); + REQUIRE(inode != nullptr); + REQUIRE(inode->is_device()); + } + + THEN("lookup of an unknown device returns null") + { + auto inode = fs.lookup(fs.root_inode(), "ram99"); + REQUIRE(inode == nullptr); + } + + THEN("lookup with a non-directory parent returns null") + { + auto non_directory_inode = fs.lookup(fs.root_inode(), "ram0"); + REQUIRE(non_directory_inode != nullptr); + REQUIRE(!non_directory_inode->is_directory()); + + auto result = fs.lookup(non_directory_inode, "anything"); + REQUIRE(result == nullptr); + } + } + + GIVEN("a boot module registry with three modules") + { + setup_modules(3, 2048); + + auto fs = kernel::filesystem::devfs::filesystem{}; + auto result = fs.mount(nullptr); + REQUIRE(result == kernel::filesystem::filesystem::operation_result::success); + + THEN("lookup finds all generated RAM devices") + { + REQUIRE(fs.lookup(fs.root_inode(), "ram0") != nullptr); + REQUIRE(fs.lookup(fs.root_inode(), "ram16") != nullptr); + REQUIRE(fs.lookup(fs.root_inode(), "ram32") != nullptr); + } + } +} diff --git a/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp b/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp new file mode 100644 index 0000000..8bbf194 --- /dev/null +++ b/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp @@ -0,0 +1,43 @@ +#include "kernel/test_support/filesystem/storage_boot_module_fixture.hpp" + +#include "kapi/boot_module/boot_module.hpp" +#include "kapi/boot_modules.hpp" +#include "kapi/memory.hpp" + +#include "kernel/devices/storage/management.hpp" +#include "kernel/test_support/boot_modules.hpp" +#include "kernel/test_support/devices/storage/management.hpp" + +#include +#include + +namespace kernel::tests::filesystem +{ + auto storage_boot_module_fixture::setup_modules(std::size_t module_count, std::size_t module_size) -> void + { + kernel::tests::devices::storage::management::deinit(); + kernel::tests::boot_modules::deinit(); + + module_names.clear(); + module_data.clear(); + registry = {}; + + module_names.reserve(module_count); + module_data.reserve(module_count); + + for (std::size_t i = 0; i < module_count; ++i) + { + module_names.push_back("test_mod" + std::to_string(i)); + module_data.emplace_back(module_size, std::byte{static_cast(0x40 + (i % 16))}); + } + + for (std::size_t i = 0; i < module_count; ++i) + { + registry.add_boot_module(kapi::boot_modules::boot_module{ + module_names[i], kapi::memory::linear_address{module_data[i].data()}, module_data[i].size()}); + } + + kapi::boot_modules::set_boot_module_registry(registry); + kernel::devices::storage::management::init(); + } +} // namespace kernel::tests::filesystem \ No newline at end of file diff --git a/kernel/src/test_support/state_reset_listener.cpp b/kernel/src/test_support/state_reset_listener.cpp index af1091c..9120c89 100644 --- a/kernel/src/test_support/state_reset_listener.cpp +++ b/kernel/src/test_support/state_reset_listener.cpp @@ -33,8 +33,8 @@ struct state_reset_listener : Catch::EventListenerBase { kernel::tests::filesystem::file_descriptor_table::deinit(); kernel::tests::filesystem::vfs::deinit(); - kernel::tests::devices::storage::deinit(); kernel::tests::boot_modules::deinit(); + kernel::tests::devices::storage::management::deinit(); kernel::tests::memory::deinit(); kernel::tests::cpu::deinit(); -- cgit v1.2.3 From 186bc5c9a08c5d6e0d306ce8b4fe3d75f4782cd2 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 9 Apr 2026 09:19:40 +0200 Subject: add test for devfs edge case --- kernel/src/filesystem/devfs/filesystem.tests.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/devfs/filesystem.tests.cpp b/kernel/src/filesystem/devfs/filesystem.tests.cpp index 1d82bf9..f8c4764 100644 --- a/kernel/src/filesystem/devfs/filesystem.tests.cpp +++ b/kernel/src/filesystem/devfs/filesystem.tests.cpp @@ -34,6 +34,15 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, REQUIRE(inode == nullptr); } + THEN("lookup with wrong parent returns null") + { + auto other_fs = kernel::filesystem::devfs::filesystem{}; + other_fs.mount(nullptr); + + auto inode = fs.lookup(other_fs.root_inode(), "ram0"); + REQUIRE(inode == nullptr); + } + THEN("lookup with a non-directory parent returns null") { auto non_directory_inode = fs.lookup(fs.root_inode(), "ram0"); -- cgit v1.2.3 From 787671aac288590e40c5cabfc9f82a31f21629fe Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 9 Apr 2026 10:33:38 +0200 Subject: add vfs tests with real ext2 images --- kernel/src/filesystem/vfs.tests.cpp | 166 +++++++++++++++++++++ .../filesystem/storage_boot_module_fixture.cpp | 90 +++++++++-- .../filesystem/storage_boot_module_vfs_fixture.cpp | 32 ++++ .../filesystem/test_assets/ext2_1KB_fs.img | 3 + .../filesystem/test_assets/ext2_2KB_fs.img | 3 + .../filesystem/test_assets/ext2_4KB_fs.img | 3 + 6 files changed, 285 insertions(+), 12 deletions(-) create mode 100644 kernel/src/filesystem/vfs.tests.cpp create mode 100644 kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp create mode 100644 kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img create mode 100644 kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img create mode 100644 kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp new file mode 100644 index 0000000..fec32e1 --- /dev/null +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -0,0 +1,166 @@ +#include "kernel/filesystem/vfs.hpp" + +#include "kernel/devices/storage/management.hpp" +#include "kernel/filesystem/filesystem.hpp" +#include "kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp" + +#include + +#include + +SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS with dummy modules", + "[filesystem][vfs]") +{ + GIVEN("an initialized boot module registry with multiple modules") + { + REQUIRE_NOTHROW(setup_modules_and_init_vfs(5)); + + THEN("vfs initializes and provides /dev mount") + { + auto & vfs = kernel::filesystem::vfs::get(); + auto dev = vfs.open("/dev"); + + REQUIRE(dev != nullptr); + } + + THEN("vfs initializes root filesystem with boot device if boot module is present") + { + auto & vfs = kernel::filesystem::vfs::get(); + auto root_file = vfs.open("/"); + + REQUIRE(root_file != nullptr); + } + } +} + +SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS with file backed image", + "[filesystem][vfs][img]") +{ + auto const image_path_1 = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img"; + auto const image_path_2 = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_2KB_fs.img"; + auto const image_path_3 = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_4KB_fs.img"; + + GIVEN("a real image file") + { + REQUIRE(std::filesystem::exists(image_path_1)); + REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module"}, {image_path_1})); + + THEN("vfs initializes and provides expected mount points") + { + auto & volatilefs = kernel::filesystem::vfs::get(); + auto root = volatilefs.open("/"); + auto dev = volatilefs.open("/dev"); + auto information = volatilefs.open("/information/info_1.txt"); + + REQUIRE(root != nullptr); + REQUIRE(dev != nullptr); + REQUIRE(information != nullptr); + } + } + + GIVEN("three real image files") + { + REQUIRE(std::filesystem::exists(image_path_1)); + REQUIRE(std::filesystem::exists(image_path_2)); + REQUIRE(std::filesystem::exists(image_path_3)); + REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module_1", "test_img_module_2", "test_img_module_3"}, + {image_path_1, image_path_2, image_path_3})); + + auto & vfs = kernel::filesystem::vfs::get(); + auto storage_mgmt = kernel::devices::storage::management::get(); + auto device_1 = storage_mgmt.device_by_major_minor(1, 16); + auto fs_1 = kernel::filesystem::filesystem::probe_and_mount(device_1); + auto device_2 = storage_mgmt.device_by_major_minor(1, 32); + auto fs_2 = kernel::filesystem::filesystem::probe_and_mount(device_2); + + THEN("vfs initializes first module as root") + { + auto & vfs = kernel::filesystem::vfs::get(); + auto info1 = vfs.open("/information/info_1.txt"); + auto info2 = vfs.open("/information/info_2.txt"); + + REQUIRE(info1 != nullptr); + REQUIRE(info2 != nullptr); + } + + THEN("second image can be mounted, data retrieved and unmounted again") + { + REQUIRE(vfs.do_mount("/information", fs_1) == kernel::filesystem::vfs::operation_result::success); + + auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); + REQUIRE(mounted_monkey_1 != nullptr); + + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); + auto unmounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); + REQUIRE(unmounted_monkey_1 == nullptr); + + auto info_1 = vfs.open("/information/info_1.txt"); + REQUIRE(info_1 != nullptr); + } + + THEN("third image can be mounted in a mounted file system, unmount only if no child mount exists") + { + REQUIRE(vfs.do_mount("/information", fs_1) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/information/monkey_house/infrastructure", fs_2) == + kernel::filesystem::vfs::operation_result::success); + + auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); + auto mounted_fish1 = vfs.open("/information/monkey_house/infrastructure/enclosures/aquarium/tank_1/fish_1.txt"); + + REQUIRE(mounted_monkey_1 != nullptr); + REQUIRE(mounted_fish1 != nullptr); + + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); + REQUIRE(vfs.unmount("/information/monkey_house/infrastructure") == + kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); + } + + THEN("images can be stacked mounted and correct file system is unmounted again") + { + REQUIRE(vfs.do_mount("/information", fs_1) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/information", fs_2) == kernel::filesystem::vfs::operation_result::success); + + auto mounted_tickets = vfs.open("/information/entrance/tickets.txt"); + REQUIRE(mounted_tickets != nullptr); + + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); + mounted_tickets = vfs.open("/information/entrance/tickets.txt"); + REQUIRE(mounted_tickets == nullptr); + + auto mounted_monkey = vfs.open("/information/monkey_house/monkey_1.txt"); + REQUIRE(mounted_monkey != nullptr); + } + + THEN("mount with null file system fails") + { + REQUIRE(vfs.do_mount("/information", nullptr) == kernel::filesystem::vfs::operation_result::filesystem_null); + } + + THEN("mount with invalid path fails") + { + REQUIRE(vfs.do_mount("", fs_1) == kernel::filesystem::vfs::operation_result::invalid_path); + REQUIRE(vfs.do_mount("information", fs_1) == kernel::filesystem::vfs::operation_result::invalid_path); + REQUIRE(vfs.do_mount("/information/", fs_1) == kernel::filesystem::vfs::operation_result::invalid_path); + } + + THEN("mount with non-existent mount point fails") + { + REQUIRE(vfs.do_mount("/information/nonexistent", fs_1) == + kernel::filesystem::vfs::operation_result::mount_point_not_found); + } + + THEN("unmount with invalid path fails") + { + REQUIRE(vfs.unmount("") == kernel::filesystem::vfs::operation_result::invalid_path); + REQUIRE(vfs.unmount("information") == kernel::filesystem::vfs::operation_result::invalid_path); + REQUIRE(vfs.unmount("/information/") == kernel::filesystem::vfs::operation_result::invalid_path); + } + + THEN("unmounting non-existent mount point returns expected error code") + { + REQUIRE(vfs.unmount("/information/nonexistent") == + kernel::filesystem::vfs::operation_result::mount_point_not_found); + } + } +} diff --git a/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp b/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp index 8bbf194..a139f63 100644 --- a/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp +++ b/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp @@ -8,36 +8,102 @@ #include "kernel/test_support/boot_modules.hpp" #include "kernel/test_support/devices/storage/management.hpp" +#include +#include + #include -#include +#include +#include +#include +#include namespace kernel::tests::filesystem { - auto storage_boot_module_fixture::setup_modules(std::size_t module_count, std::size_t module_size) -> void + storage_boot_module_fixture::~storage_boot_module_fixture() { kernel::tests::devices::storage::management::deinit(); kernel::tests::boot_modules::deinit(); + } - module_names.clear(); - module_data.clear(); - registry = {}; + auto storage_boot_module_fixture::setup_modules(std::size_t module_count, std::size_t module_size) -> void + { + m_module_names.clear(); + m_module_data.clear(); + m_registry = {}; - module_names.reserve(module_count); - module_data.reserve(module_count); + m_module_names.reserve(module_count); + m_module_data.reserve(module_count); for (std::size_t i = 0; i < module_count; ++i) { - module_names.push_back("test_mod" + std::to_string(i)); - module_data.emplace_back(module_size, std::byte{static_cast(0x40 + (i % 16))}); + m_module_names.push_back("test_mod" + kstd::to_string(i)); + m_module_data.emplace_back(module_size, std::byte{static_cast(0x40 + (i % 16))}); } for (std::size_t i = 0; i < module_count; ++i) { - registry.add_boot_module(kapi::boot_modules::boot_module{ - module_names[i], kapi::memory::linear_address{module_data[i].data()}, module_data[i].size()}); + m_registry.add_boot_module(kapi::boot_modules::boot_module{ + m_module_names[i].view(), kapi::memory::linear_address{m_module_data[i].data()}, m_module_data[i].size()}); + } + + kapi::boot_modules::set_boot_module_registry(m_registry); + kernel::devices::storage::management::init(); + } + + auto storage_boot_module_fixture::setup_modules_from_img(kstd::vector const & module_names, + kstd::vector const & img_paths) + -> void + { + m_module_names.clear(); + m_module_data.clear(); + m_registry = {}; + + if (module_names.size() != img_paths.size()) + { + throw std::invalid_argument{"Module names and image paths vectors must have the same size."}; + } + + for (size_t i = 0; i < module_names.size(); ++i) + { + setup_module_from_img(module_names[i], img_paths[i]); } - kapi::boot_modules::set_boot_module_registry(registry); + kapi::boot_modules::set_boot_module_registry(m_registry); kernel::devices::storage::management::init(); } + + auto storage_boot_module_fixture::setup_module_from_img(kstd::string const & module_name, + std::filesystem::path const & img_path) -> void + { + auto file = std::ifstream{img_path, std::ios::binary | std::ios::ate}; + if (!file) + { + throw std::runtime_error{"Failed to open image file for test boot module: " + img_path.string()}; + } + + auto const end_pos = file.tellg(); + if (end_pos < 0) + { + throw std::runtime_error{"Failed to determine image file size for test boot module: " + img_path.string()}; + } + + auto const size = static_cast(end_pos); + file.seekg(0, std::ios::beg); + + m_module_names.push_back(module_name); + m_module_data.emplace_back(size); + + if (size > 0) + { + file.read(reinterpret_cast(m_module_data.back().data()), static_cast(size)); + if (!file) + { + throw std::runtime_error{"Failed to read image file content for test boot module: " + img_path.string()}; + } + } + + m_registry.add_boot_module(kapi::boot_modules::boot_module{ + m_module_names.back().view(), kapi::memory::linear_address{m_module_data.back().data()}, + m_module_data.back().size()}); + } } // namespace kernel::tests::filesystem \ No newline at end of file diff --git a/kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp b/kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp new file mode 100644 index 0000000..cba7278 --- /dev/null +++ b/kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp @@ -0,0 +1,32 @@ +#include "kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp" + +#include "kernel/filesystem/vfs.hpp" +#include "kernel/test_support/filesystem/vfs.hpp" + +#include +#include + +#include +#include + +namespace kernel::tests::filesystem +{ + storage_boot_module_vfs_fixture::~storage_boot_module_vfs_fixture() + { + kernel::tests::filesystem::vfs::deinit(); + } + + auto storage_boot_module_vfs_fixture::setup_modules_and_init_vfs(std::size_t module_count, std::size_t module_size) + -> void + { + setup_modules(module_count, module_size); + kernel::filesystem::vfs::init(); + } + + auto storage_boot_module_vfs_fixture::setup_modules_from_img_and_init_vfs( + kstd::vector const & module_names, kstd::vector const & img_paths) -> void + { + setup_modules_from_img(module_names, img_paths); + kernel::filesystem::vfs::init(); + } +} // namespace kernel::tests::filesystem \ No newline at end of file diff --git a/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img b/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img new file mode 100644 index 0000000..9f1ee4a --- /dev/null +++ b/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94d3988bc309eb9e81f06042c72bf4c4fb5991cd7fdd597eb00c518a96c792d8 +size 10485760 diff --git a/kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img b/kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img new file mode 100644 index 0000000..1880911 --- /dev/null +++ b/kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a13da5abb9c65c737105b1da0d4344c7cd7604c7952c762c4f4e3d3f96fd42d +size 5242880 diff --git a/kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img b/kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img new file mode 100644 index 0000000..3aaceb8 --- /dev/null +++ b/kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ce6a1aea277906e1af6de223c017ff900b96569f076b4d99fc04eaa1ee986f4 +size 10485760 -- cgit v1.2.3 From a03d4d9acc5115ec3f651b06f94ced9a7c0e192f Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 9 Apr 2026 10:56:25 +0200 Subject: add open_file_description tests with real image --- .../src/filesystem/open_file_description.tests.cpp | 54 ++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/open_file_description.tests.cpp b/kernel/src/filesystem/open_file_description.tests.cpp index f045094..db8eb49 100644 --- a/kernel/src/filesystem/open_file_description.tests.cpp +++ b/kernel/src/filesystem/open_file_description.tests.cpp @@ -1,6 +1,8 @@ #include "kernel/filesystem/open_file_description.hpp" +#include "kernel/filesystem/vfs.hpp" #include "kernel/test_support/filesystem/inode.hpp" +#include "kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp" #include #include @@ -8,6 +10,10 @@ #include +#include +#include +#include + SCENARIO("Open file description construction", "[filesystem][open_file_description]") { GIVEN("an inode and an open file description for that inode") @@ -58,3 +64,51 @@ SCENARIO("Open file description read/write offset management", "[filesystem][ope } } } + +SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, + "Open file description read with real image", "[filesystem][open_file_description][img]") +{ + auto const image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img"; + + GIVEN("an open file description for a file in a real image") + { + REQUIRE(std::filesystem::exists(image_path)); + REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module"}, {image_path})); + + auto & vfs = kernel::filesystem::vfs::get(); + auto ofd = vfs.open("/information/info_1.txt"); + REQUIRE(ofd != nullptr); + + THEN("the file can be read and the offset is updated") + { + kstd::vector buffer(32); + auto bytes_read = ofd->read(buffer.data(), buffer.size()); + REQUIRE(bytes_read == 32); + REQUIRE(ofd->offset() == 32); + + std::string_view buffer_as_str{reinterpret_cast(buffer.data()), static_cast(bytes_read)}; + auto const content_end = buffer_as_str.find('\0'); + REQUIRE(buffer_as_str.substr(0, content_end) == "info_1\n"); + + for (auto i = content_end; i < buffer_as_str.size(); ++i) + { + REQUIRE(buffer_as_str[i] == '\0'); + } + } + + THEN("the file can be read multiple times") + { + kstd::vector 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_2 = ofd->read(buffer.data() + buffer.size() / 2, buffer.size() / 2); + REQUIRE(bytes_read_2 == buffer.size() / 2); + REQUIRE(ofd->offset() == buffer.size()); + + std::string_view buffer_as_str{reinterpret_cast(buffer.data()), bytes_read_1 + bytes_read_2}; + REQUIRE(buffer_as_str == "info"); + } + } +} -- cgit v1.2.3 From 01d5f1b29fa04c69ac9f942a1075354ce5b25da2 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 9 Apr 2026 12:32:50 +0200 Subject: add ext2 inode and filesystem tests --- kernel/src/filesystem/ext2/filesystem.cpp | 38 ++---- kernel/src/filesystem/ext2/filesystem.tests.cpp | 132 ++++++++++++++++++++ kernel/src/filesystem/ext2/inode.tests.cpp | 159 ++++++++++++++++++++++++ kernel/src/test_support/filesystem/ext2.cpp | 62 +++++++++ 4 files changed, 365 insertions(+), 26 deletions(-) create mode 100644 kernel/src/filesystem/ext2/filesystem.tests.cpp create mode 100644 kernel/src/filesystem/ext2/inode.tests.cpp create mode 100644 kernel/src/test_support/filesystem/ext2.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 6d5960e..0ad5c97 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -21,29 +21,14 @@ namespace kernel::filesystem::ext2 { namespace { - constexpr size_t SUPERBLOCK_OFFSET = 1024; - constexpr uint16_t MAGIC_NUMBER = 0xEF53; - - constexpr uint32_t ROOT_INODE_NUMBER = 2; - - constexpr size_t DIRECT_BLOCK_COUNT = 12; - constexpr size_t SINGLY_INDIRECT_BLOCK_INDEX = DIRECT_BLOCK_COUNT; - constexpr size_t DOUBLY_INDIRECT_BLOCK_INDEX = SINGLY_INDIRECT_BLOCK_INDEX + 1; - constexpr size_t TRIPLY_INDIRECT_BLOCK_INDEX = DOUBLY_INDIRECT_BLOCK_INDEX + 1; - - // Mode bits - constexpr uint16_t S_IFMT = 0xF000; - constexpr uint16_t S_IFREG = 0x8000; - constexpr uint16_t S_IFDIR = 0x4000; - auto S_ISREG(uint16_t mode) -> bool { - return (mode & S_IFMT) == S_IFREG; + return (mode & constants::mode_mask) == constants::mode_regular; } auto S_ISDIR(uint16_t mode) -> bool { - return (mode & S_IFMT) == S_IFDIR; + return (mode & constants::mode_mask) == constants::mode_directory; } } // namespace @@ -51,9 +36,10 @@ namespace kernel::filesystem::ext2 { kernel::filesystem::filesystem::mount(device); - kernel::devices::block_device_utils::read(m_device, &m_superblock, SUPERBLOCK_OFFSET, sizeof(m_superblock)); + kernel::devices::block_device_utils::read(m_device, &m_superblock, constants::superblock_offset, + sizeof(m_superblock)); - if (m_superblock.magic != MAGIC_NUMBER) + if (m_superblock.magic != constants::magic_number) { return operation_result::invalid_magic_number; } @@ -69,7 +55,7 @@ namespace kernel::filesystem::ext2 block_group_descriptor_table_offset, num_block_groups * sizeof(block_group_descriptor)); - m_root_inode = read_inode(ROOT_INODE_NUMBER); + m_root_inode = read_inode(constants::root_inode_number); if (!m_root_inode || !m_root_inode->is_directory()) { @@ -161,11 +147,11 @@ namespace kernel::filesystem::ext2 auto filesystem::map_inode_block_index_to_global_block_number(uint32_t inode_block_index, inode_data data) -> uint32_t { - if (inode_block_index < DIRECT_BLOCK_COUNT) + if (inode_block_index < constants::direct_block_count) { return data.block.at(inode_block_index); } - inode_block_index -= DIRECT_BLOCK_COUNT; + inode_block_index -= constants::direct_block_count; auto const block_size = get_block_size(); auto const numbers_per_block = block_size / sizeof(uint32_t); @@ -176,14 +162,14 @@ namespace kernel::filesystem::ext2 if (inode_block_index < block_numbers_per_singly_indirect_block) { - auto const singly_indirect_block_number = data.block.at(SINGLY_INDIRECT_BLOCK_INDEX); + auto const singly_indirect_block_number = data.block.at(constants::singly_indirect_block_index); return read_block_number_at_index(singly_indirect_block_number, inode_block_index); } inode_block_index -= block_numbers_per_singly_indirect_block; if (inode_block_index < block_numbers_per_doubly_indirect_block) { - auto const doubly_indirect_block_number = data.block.at(DOUBLY_INDIRECT_BLOCK_INDEX); + auto const doubly_indirect_block_number = data.block.at(constants::doubly_indirect_block_index); auto const singly_indirect_block_index_in_doubly_indirect_block = inode_block_index / block_numbers_per_singly_indirect_block; auto const singly_indirect_block_number = read_block_number_at_index( @@ -196,7 +182,7 @@ namespace kernel::filesystem::ext2 if (inode_block_index < block_numbers_per_triply_indirect_block) { - auto const triply_indirect_block_number = data.block.at(TRIPLY_INDIRECT_BLOCK_INDEX); + auto const triply_indirect_block_number = data.block.at(constants::triply_indirect_block_index); auto const doubly_indirect_block_index_in_triply_indirect_block = inode_block_index / block_numbers_per_doubly_indirect_block; auto const doubly_indirect_block_number = read_block_number_at_index( @@ -230,7 +216,7 @@ namespace kernel::filesystem::ext2 auto filesystem::get_block_size() -> size_t { - return 1024U << m_superblock.log_block_size; + return constants::base_block_size << m_superblock.log_block_size; } auto filesystem::get_inode_size() -> size_t diff --git a/kernel/src/filesystem/ext2/filesystem.tests.cpp b/kernel/src/filesystem/ext2/filesystem.tests.cpp new file mode 100644 index 0000000..b13ebf3 --- /dev/null +++ b/kernel/src/filesystem/ext2/filesystem.tests.cpp @@ -0,0 +1,132 @@ +#include "kernel/filesystem/ext2/filesystem.hpp" + +#include "kernel/devices/storage/management.hpp" +#include "kernel/filesystem/ext2/inode.hpp" +#include "kernel/filesystem/filesystem.hpp" +#include "kernel/test_support/devices/block_device.hpp" +#include "kernel/test_support/filesystem/ext2.hpp" +#include "kernel/test_support/filesystem/storage_boot_module_fixture.hpp" + +#include +#include + +#include + +#include +#include +#include + +SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, + "Ext2 filesystem mount and lookup with real image", "[filesystem][ext2][filesystem][img]") +{ + auto const image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img"; + + GIVEN("a mounted ext2 filesystem from a real image") + { + REQUIRE(std::filesystem::exists(image_path)); + REQUIRE_NOTHROW(setup_modules_from_img({"test_img_module"}, {image_path})); + + auto boot_device = kernel::devices::storage::management::get().determine_boot_device(); + REQUIRE(boot_device != nullptr); + + auto fs = kernel::filesystem::ext2::filesystem{}; + REQUIRE(fs.mount(boot_device) == kernel::filesystem::filesystem::operation_result::success); + + THEN("the root inode is available and is a directory") + { + REQUIRE(fs.root_inode() != nullptr); + REQUIRE(fs.root_inode()->is_directory()); + } + + THEN("lookup resolves known entries from the image") + { + auto information = fs.lookup(fs.root_inode(), "information"); + REQUIRE(information != nullptr); + REQUIRE(information->is_directory()); + + auto info_1 = fs.lookup(information, "info_1.txt"); + REQUIRE(info_1 != nullptr); + REQUIRE(info_1->is_regular()); + } + + THEN("lookup returns null for invalid inputs") + { + REQUIRE(fs.lookup(nullptr, "information") == nullptr); + + auto information = fs.lookup(fs.root_inode(), "information"); + REQUIRE(information != nullptr); + auto info_1 = fs.lookup(information, "info_1.txt"); + REQUIRE(info_1 != nullptr); + + REQUIRE(fs.lookup(info_1, "anything") == nullptr); + REQUIRE(fs.lookup(fs.root_inode(), "does_not_exist") == nullptr); + } + } +} + +SCENARIO("Ext2 filesystem rejects invalid magic", "[filesystem][ext2][filesystem]") +{ + auto const block_size = 1024; + GIVEN("a block device that does not contain an ext2 superblock") + { + auto device = kstd::make_shared(0, 0, "mock", block_size, 2 * block_size); + REQUIRE(device != nullptr); + + auto fs = kernel::filesystem::ext2::filesystem{}; + + THEN("mount fails with invalid_magic_number") + { + REQUIRE(fs.mount(device) == kernel::filesystem::filesystem::operation_result::invalid_magic_number); + } + } +} + +SCENARIO("Ext2 block mapping includes direct and all indirect levels", "[filesystem][ext2][filesystem]") +{ + auto const block_size = 1024; + + GIVEN("a minimally valid ext2 layout with configured indirect block tables") + { + auto device = kstd::make_shared(0, 0, "mock", block_size, 128 * block_size); + REQUIRE(device != nullptr); + + kernel::tests::filesystem::ext2::setup_mock_ext2_layout(*device); + + auto fs = kernel::filesystem::ext2::filesystem{}; + REQUIRE(fs.mount(device) == kernel::filesystem::filesystem::operation_result::success); + + auto inode_data = kernel::filesystem::ext2::inode_data{}; + inode_data.block[0] = 7; + + inode_data.block[12] = 30; + kernel::tests::filesystem::ext2::write_u32(*device, 30 * block_size, 31); + + inode_data.block[13] = 40; + kernel::tests::filesystem::ext2::write_u32(*device, 40 * block_size, 41); + kernel::tests::filesystem::ext2::write_u32(*device, 41 * block_size, 42); + + inode_data.block[14] = 50; + kernel::tests::filesystem::ext2::write_u32(*device, 50 * block_size, 51); + 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(block_size / sizeof(uint32_t)); + auto const singly_start = static_cast(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; + + THEN("mapping resolves direct, singly, doubly and triply indirect indexes") + { + REQUIRE(fs.map_inode_block_index_to_global_block_number(0, inode_data) == 7); + REQUIRE(fs.map_inode_block_index_to_global_block_number(singly_start, inode_data) == 31); + REQUIRE(fs.map_inode_block_index_to_global_block_number(doubly_start, inode_data) == 42); + REQUIRE(fs.map_inode_block_index_to_global_block_number(triply_start, inode_data) == 53); + } + + THEN("mapping returns zero for out-of-range indexes") + { + auto const beyond_triply = triply_start + numbers_per_block * numbers_per_block * numbers_per_block; + REQUIRE(fs.map_inode_block_index_to_global_block_number(beyond_triply, inode_data) == 0); + } + } +} diff --git a/kernel/src/filesystem/ext2/inode.tests.cpp b/kernel/src/filesystem/ext2/inode.tests.cpp new file mode 100644 index 0000000..795ff10 --- /dev/null +++ b/kernel/src/filesystem/ext2/inode.tests.cpp @@ -0,0 +1,159 @@ +#include "kernel/filesystem/ext2/inode.hpp" + +#include "kernel/devices/storage/management.hpp" +#include "kernel/filesystem/ext2/filesystem.hpp" +#include "kernel/filesystem/filesystem.hpp" +#include "kernel/test_support/cpu.hpp" +#include "kernel/test_support/devices/block_device.hpp" +#include "kernel/test_support/filesystem/ext2.hpp" +#include "kernel/test_support/filesystem/storage_boot_module_fixture.hpp" + +#include +#include + +#include + +#include +#include +#include + +SCENARIO("Ext2 inode initialization and properties", "[filesystem][ext2][inode]") +{ + GIVEN("an ext2 filesystem") + { + auto fs = kernel::filesystem::ext2::filesystem{}; + + THEN("the inode is initialized and has the kind regular") + { + auto inode = kernel::filesystem::ext2::inode{&fs}; + REQUIRE(inode.is_regular()); + REQUIRE(!inode.is_directory()); + REQUIRE(!inode.is_device()); + } + } + + GIVEN("no filesystem (null pointer)") + { + THEN("constructing an inode with a null filesystem pointer panics") + { + REQUIRE_THROWS_AS(kernel::filesystem::ext2::inode{nullptr}, kernel::tests::cpu::halt); + } + } +} + +SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 inode reads from real image", + "[filesystem][ext2][inode][img]") +{ + auto const image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img"; + + GIVEN("a mounted ext2 filesystem and a regular file inode") + { + REQUIRE(std::filesystem::exists(image_path)); + REQUIRE_NOTHROW(setup_modules_from_img({"test_img_module"}, {image_path})); + + auto boot_device = kernel::devices::storage::management::get().determine_boot_device(); + REQUIRE(boot_device != nullptr); + + auto fs = kernel::filesystem::ext2::filesystem{}; + REQUIRE(fs.mount(boot_device) == kernel::filesystem::filesystem::operation_result::success); + + auto information = fs.lookup(fs.root_inode(), "information"); + REQUIRE(information != nullptr); + auto file = fs.lookup(information, "info_1.txt"); + REQUIRE(file != nullptr); + REQUIRE(file->is_regular()); + + THEN("reading from offset zero returns expected file prefix") + { + auto buffer = kstd::vector(6); + auto const bytes_read = file->read(buffer.data(), 0, buffer.size()); + + REQUIRE(bytes_read == 6); + + auto const text = std::string_view{reinterpret_cast(buffer.data()), bytes_read}; + REQUIRE(text == "info_1"); + } + + THEN("reading with an offset returns the expected byte") + { + auto buffer = kstd::vector(1); + auto const bytes_read = file->read(buffer.data(), 5, buffer.size()); + + REQUIRE(bytes_read == 1); + REQUIRE(static_cast(buffer[0]) == '1'); + } + } +} + +SCENARIO("Ext2 inode read stops when block mapping resolves to zero", "[filesystem][ext2][inode]") +{ + auto const block_size = 1024; + GIVEN("an ext2 inode without mapped data blocks") + { + auto device = kstd::make_shared(0, 0, "mock", block_size, 64 * block_size); + REQUIRE(device != nullptr); + kernel::tests::filesystem::ext2::setup_mock_ext2_layout(*device); + + auto fs = kernel::filesystem::ext2::filesystem{}; + REQUIRE(fs.mount(device) == kernel::filesystem::filesystem::operation_result::success); + + auto inode = kernel::filesystem::ext2::inode{&fs}; + inode.m_data.blocks = 2; + inode.m_data.block[0] = 0; + + auto buffer = kstd::vector(32, std::byte{0xAB}); + + THEN("no bytes are read") + { + auto const bytes_read = inode.read(buffer.data(), 0, buffer.size()); + REQUIRE(bytes_read == 0); + } + } +} + +SCENARIO("Ext2 inode read across block boundaries", "[filesystem][ext2][inode]") +{ + auto const block_size = 1024; + GIVEN("an ext2 inode with two direct blocks and a block size of 1024 bytes") + { + auto device = kstd::make_shared(0, 0, "mock", block_size, 64 * block_size); + REQUIRE(device != nullptr); + kernel::tests::filesystem::ext2::setup_mock_ext2_layout(*device); + + auto fs = kernel::filesystem::ext2::filesystem{}; + REQUIRE(fs.mount(device) == kernel::filesystem::filesystem::operation_result::success); + + auto inode = kernel::filesystem::ext2::inode{&fs}; + inode.m_data.blocks = 2; + inode.m_data.block[0] = 20; + kernel::tests::filesystem::ext2::write_bytes(*device, 21 * block_size - 6, "Hello ", 6); + inode.m_data.block[1] = 21; + kernel::tests::filesystem::ext2::write_bytes(*device, 21 * block_size, "World!", 6); + + auto buffer = kstd::vector(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 text = std::string_view{reinterpret_cast(buffer.data()), bytes_read}; + REQUIRE(text == "Hello World!"); + } + } +} + +SCENARIO("Ext2 inode write is not implemented", "[filesystem][ext2][inode]") +{ + GIVEN("an ext2 inode") + { + auto fs = kernel::filesystem::ext2::filesystem{}; + auto inode = kernel::filesystem::ext2::inode{&fs}; + + THEN("writing to the inode panics") + { + auto buffer = kstd::vector(32, std::byte{0x00}); + REQUIRE_THROWS_AS(inode.write(buffer.data(), 0, buffer.size()), kernel::tests::cpu::halt); + } + } +} diff --git a/kernel/src/test_support/filesystem/ext2.cpp b/kernel/src/test_support/filesystem/ext2.cpp new file mode 100644 index 0000000..3627373 --- /dev/null +++ b/kernel/src/test_support/filesystem/ext2.cpp @@ -0,0 +1,62 @@ +#include "kernel/test_support/filesystem/ext2.hpp" + +#include "kernel/filesystem/ext2/block_group_descriptor.hpp" +#include "kernel/filesystem/ext2/filesystem.hpp" +#include "kernel/filesystem/ext2/inode.hpp" +#include "kernel/filesystem/ext2/superblock.hpp" +#include "kernel/test_support/devices/block_device.hpp" + +#include +#include + +namespace kernel::tests::filesystem::ext2 +{ + namespace + { + 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 const required_size = offset + size; + if (device.data.size() < required_size) + { + device.data.resize(required_size, 0); + } + + std::memcpy(device.data.data() + offset, source, size); + } + + auto write_u32(kernel::tests::devices::block_device & device, size_t offset, uint32_t value) -> void + { + write_bytes(device, offset, &value, sizeof(value)); + } + + auto setup_mock_ext2_layout(kernel::tests::devices::block_device & device) -> void + { + auto superblock = kernel::filesystem::ext2::superblock{}; + superblock.magic = kernel::filesystem::ext2::constants::magic_number; + superblock.log_block_size = 0; + superblock.blocks_count = 64; + superblock.blocks_per_group = 64; + superblock.inodes_per_group = 32; + superblock.rev_level = 1; + superblock.inode_size = 128; + write_bytes(device, kernel::filesystem::ext2::constants::superblock_offset, &superblock, sizeof(superblock)); + + auto group_descriptor = kernel::filesystem::ext2::block_group_descriptor{}; + group_descriptor.inode_table = 5; + write_bytes(device, 2048, &group_descriptor, sizeof(group_descriptor)); + + auto root_inode_data = kernel::filesystem::ext2::inode_data{}; + root_inode_data.mode = kernel::filesystem::ext2::constants::mode_directory; + root_inode_data.blocks = 2; + root_inode_data.block[0] = root_directory_data_block; + + auto const root_inode_offset = + static_cast(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)); + } +} // namespace kernel::tests::filesystem::ext2 \ No newline at end of file -- cgit v1.2.3 From 48d01e976cc250c2630c1b599a02cea60b56d32d Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Sun, 12 Apr 2026 19:08:50 +0200 Subject: Rename --- kernel/src/filesystem/vfs.tests.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index fec32e1..f363041 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -47,10 +47,10 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS THEN("vfs initializes and provides expected mount points") { - auto & volatilefs = kernel::filesystem::vfs::get(); - auto root = volatilefs.open("/"); - auto dev = volatilefs.open("/dev"); - auto information = volatilefs.open("/information/info_1.txt"); + auto & vfs = kernel::filesystem::vfs::get(); + auto root = vfs.open("/"); + auto dev = vfs.open("/dev"); + auto information = vfs.open("/information/info_1.txt"); REQUIRE(root != nullptr); REQUIRE(dev != nullptr); -- cgit v1.2.3 From bb01b9f2d29524974881e9a88ffb6c229836ddba Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Sun, 12 Apr 2026 20:45:23 +0200 Subject: Add fs syscall handler --- kernel/src/filesystem/file_descriptor_table.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/file_descriptor_table.cpp b/kernel/src/filesystem/file_descriptor_table.cpp index 1c062a1..7569cea 100644 --- a/kernel/src/filesystem/file_descriptor_table.cpp +++ b/kernel/src/filesystem/file_descriptor_table.cpp @@ -41,7 +41,6 @@ namespace kernel::filesystem { if (!file_description) { - // TODO BA-FS26 panic or errorcode? return -1; } @@ -72,20 +71,21 @@ namespace kernel::filesystem return m_open_files.at(index); } - auto file_descriptor_table::remove_file(int fd) -> void + auto file_descriptor_table::remove_file(int fd) -> int { if (fd < 0) { - return; + return -1; } auto const index = static_cast(fd); if (index >= m_open_files.size()) { - return; + return -1; } m_open_files.at(index) = nullptr; + return 0; } } // namespace kernel::filesystem -- cgit v1.2.3 From 5e183b418b0e65dcdffa02a43702a0d6deb43b04 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 13 Apr 2026 21:17:50 +0200 Subject: Back filesystem by inode and not device --- kernel/src/filesystem/devfs/filesystem.cpp | 2 +- kernel/src/filesystem/ext2/filesystem.cpp | 21 +++++-------- kernel/src/filesystem/ext2/filesystem.tests.cpp | 13 +++++++-- kernel/src/filesystem/ext2/inode.cpp | 7 ++--- kernel/src/filesystem/ext2/inode.tests.cpp | 13 +++++++-- kernel/src/filesystem/filesystem.cpp | 22 +++++++------- kernel/src/filesystem/rootfs/filesystem.cpp | 4 +-- kernel/src/filesystem/vfs.cpp | 39 ++++++++++++------------- kernel/src/filesystem/vfs.tests.cpp | 32 ++++++++++---------- kernel/src/main.cpp | 14 ++------- 10 files changed, 82 insertions(+), 85 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/devfs/filesystem.cpp b/kernel/src/filesystem/devfs/filesystem.cpp index 03b4218..dd60c5d 100644 --- a/kernel/src/filesystem/devfs/filesystem.cpp +++ b/kernel/src/filesystem/devfs/filesystem.cpp @@ -14,7 +14,7 @@ namespace kernel::filesystem::devfs { - auto filesystem::mount(kstd::shared_ptr const &) -> operation_result + auto filesystem::mount(kstd::shared_ptr const &) -> operation_result { m_root_inode = kstd::make_shared(); build_device_inode_table(); diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 0ad5c97..c0f97ed 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -1,8 +1,5 @@ #include "kernel/filesystem/ext2/filesystem.hpp" -#include "kapi/devices/device.hpp" - -#include "kernel/devices/block_device_utils.hpp" #include "kernel/filesystem/ext2/block_group_descriptor.hpp" #include "kernel/filesystem/ext2/inode.hpp" #include "kernel/filesystem/ext2/linked_directory_entry.hpp" @@ -32,12 +29,11 @@ namespace kernel::filesystem::ext2 } } // namespace - auto filesystem::mount(kstd::shared_ptr const & device) -> operation_result + auto filesystem::mount(kstd::shared_ptr const & backing_inode) -> operation_result { - kernel::filesystem::filesystem::mount(device); + kernel::filesystem::filesystem::mount(backing_inode); - kernel::devices::block_device_utils::read(m_device, &m_superblock, constants::superblock_offset, - sizeof(m_superblock)); + m_backing_inode->read(&m_superblock, constants::superblock_offset, sizeof(m_superblock)); if (m_superblock.magic != constants::magic_number) { @@ -51,9 +47,8 @@ namespace kernel::filesystem::ext2 m_block_group_descriptors = kstd::vector(num_block_groups); auto const block_group_descriptor_table_offset = block_size == 1024 ? 2 * block_size : block_size; - kernel::devices::block_device_utils::read(m_device, m_block_group_descriptors.data(), - block_group_descriptor_table_offset, - num_block_groups * sizeof(block_group_descriptor)); + m_backing_inode->read(m_block_group_descriptors.data(), block_group_descriptor_table_offset, + num_block_groups * sizeof(block_group_descriptor)); m_root_inode = read_inode(constants::root_inode_number); @@ -86,7 +81,7 @@ namespace kernel::filesystem::ext2 { auto const global_block_number = map_inode_block_index_to_global_block_number(i, inode_data); auto const block_offset = global_block_number * block_size; - kernel::devices::block_device_utils::read(m_device, buffer.data(), block_offset, block_size); + m_backing_inode->read(buffer.data(), block_offset, block_size); auto const * entry = reinterpret_cast(buffer.data()); auto bytes_read = 0uz; @@ -125,7 +120,7 @@ namespace kernel::filesystem::ext2 auto const inode_offset = inode_table_offset + inode_index_within_group * get_inode_size(); auto new_inode = kstd::make_shared(this); - kernel::devices::block_device_utils::read(m_device, &new_inode->m_data, inode_offset, sizeof(inode_data)); + m_backing_inode->read(&new_inode->m_data, inode_offset, sizeof(inode_data)); // TODO BA-FS26 improve inode_kind really needed? or just map it to the mode bits? if (S_ISREG(new_inode->m_data.mode)) @@ -209,7 +204,7 @@ namespace kernel::filesystem::ext2 auto const block_start_offset = block_number * get_block_size(); auto const number_start_address = block_start_offset + index * sizeof(uint32_t); - kernel::devices::block_device_utils::read(m_device, &block_number_buffer, number_start_address, sizeof(uint32_t)); + m_backing_inode->read(&block_number_buffer, number_start_address, sizeof(uint32_t)); return block_number_buffer; } diff --git a/kernel/src/filesystem/ext2/filesystem.tests.cpp b/kernel/src/filesystem/ext2/filesystem.tests.cpp index b13ebf3..a7b8d5b 100644 --- a/kernel/src/filesystem/ext2/filesystem.tests.cpp +++ b/kernel/src/filesystem/ext2/filesystem.tests.cpp @@ -1,6 +1,7 @@ #include "kernel/filesystem/ext2/filesystem.hpp" #include "kernel/devices/storage/management.hpp" +#include "kernel/filesystem/device_inode.hpp" #include "kernel/filesystem/ext2/inode.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/test_support/devices/block_device.hpp" @@ -29,8 +30,10 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, auto boot_device = kernel::devices::storage::management::get().determine_boot_device(); REQUIRE(boot_device != nullptr); + auto dev_inode = kstd::make_shared(boot_device); + auto fs = kernel::filesystem::ext2::filesystem{}; - REQUIRE(fs.mount(boot_device) == kernel::filesystem::filesystem::operation_result::success); + REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success); THEN("the root inode is available and is a directory") { @@ -72,11 +75,13 @@ SCENARIO("Ext2 filesystem rejects invalid magic", "[filesystem][ext2][filesystem auto device = kstd::make_shared(0, 0, "mock", block_size, 2 * block_size); REQUIRE(device != nullptr); + auto dev_inode = kstd::make_shared(device); + auto fs = kernel::filesystem::ext2::filesystem{}; THEN("mount fails with invalid_magic_number") { - REQUIRE(fs.mount(device) == kernel::filesystem::filesystem::operation_result::invalid_magic_number); + REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::invalid_magic_number); } } } @@ -92,8 +97,10 @@ SCENARIO("Ext2 block mapping includes direct and all indirect levels", "[filesys kernel::tests::filesystem::ext2::setup_mock_ext2_layout(*device); + auto dev_inode = kstd::make_shared(device); + auto fs = kernel::filesystem::ext2::filesystem{}; - REQUIRE(fs.mount(device) == kernel::filesystem::filesystem::operation_result::success); + REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success); auto inode_data = kernel::filesystem::ext2::inode_data{}; inode_data.block[0] = 7; diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp index a29bb3b..bf3f0cf 100644 --- a/kernel/src/filesystem/ext2/inode.cpp +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -2,7 +2,6 @@ #include "kapi/system.hpp" -#include "kernel/devices/block_device_utils.hpp" #include "kernel/filesystem/ext2/filesystem.hpp" #include "kernel/filesystem/inode.hpp" @@ -41,8 +40,8 @@ namespace kernel::filesystem::ext2 auto const read_offset = block_start_offset + in_block_offset; auto const bytes_to_read = std::min(size - bytes_read, m_filesystem->get_block_size() - in_block_offset); - bytes_read += kernel::devices::block_device_utils::read( - m_filesystem->device(), static_cast(buffer) + bytes_read, read_offset, bytes_to_read); + bytes_read += + m_filesystem->backing_inode()->read(static_cast(buffer) + bytes_read, read_offset, bytes_to_read); block_index++; in_block_offset = 0; // After the first block, we always start at the beginning of the block @@ -56,4 +55,4 @@ namespace kernel::filesystem::ext2 kapi::system::panic("[EXT2] inode::write is not implemented yet"); return 0; } -} // namespace kernel::filesystem::ext2 \ No newline at end of file +} // namespace kernel::filesystem::ext2 diff --git a/kernel/src/filesystem/ext2/inode.tests.cpp b/kernel/src/filesystem/ext2/inode.tests.cpp index 795ff10..ae66aff 100644 --- a/kernel/src/filesystem/ext2/inode.tests.cpp +++ b/kernel/src/filesystem/ext2/inode.tests.cpp @@ -1,6 +1,7 @@ #include "kernel/filesystem/ext2/inode.hpp" #include "kernel/devices/storage/management.hpp" +#include "kernel/filesystem/device_inode.hpp" #include "kernel/filesystem/ext2/filesystem.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/test_support/cpu.hpp" @@ -54,8 +55,10 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 in auto boot_device = kernel::devices::storage::management::get().determine_boot_device(); REQUIRE(boot_device != nullptr); + auto dev_inode = kstd::make_shared(boot_device); + auto fs = kernel::filesystem::ext2::filesystem{}; - REQUIRE(fs.mount(boot_device) == kernel::filesystem::filesystem::operation_result::success); + REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success); auto information = fs.lookup(fs.root_inode(), "information"); REQUIRE(information != nullptr); @@ -94,8 +97,10 @@ SCENARIO("Ext2 inode read stops when block mapping resolves to zero", "[filesyst REQUIRE(device != nullptr); kernel::tests::filesystem::ext2::setup_mock_ext2_layout(*device); + auto dev_inode = kstd::make_shared(device); + auto fs = kernel::filesystem::ext2::filesystem{}; - REQUIRE(fs.mount(device) == kernel::filesystem::filesystem::operation_result::success); + REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success); auto inode = kernel::filesystem::ext2::inode{&fs}; inode.m_data.blocks = 2; @@ -120,8 +125,10 @@ SCENARIO("Ext2 inode read across block boundaries", "[filesystem][ext2][inode]") REQUIRE(device != nullptr); kernel::tests::filesystem::ext2::setup_mock_ext2_layout(*device); + auto dev_inode = kstd::make_shared(device); + auto fs = kernel::filesystem::ext2::filesystem{}; - REQUIRE(fs.mount(device) == kernel::filesystem::filesystem::operation_result::success); + REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success); auto inode = kernel::filesystem::ext2::inode{&fs}; inode.m_data.blocks = 2; diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index d8b04eb..99e7456 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -1,6 +1,5 @@ #include "kernel/filesystem/filesystem.hpp" -#include "kapi/devices/device.hpp" #include "kapi/system.hpp" #include "kernel/filesystem/ext2/filesystem.hpp" @@ -19,18 +18,17 @@ namespace kernel::filesystem }; } // namespace - auto filesystem::probe_and_mount(kstd::shared_ptr const & device) - -> kstd::shared_ptr + auto filesystem::probe_and_mount(kstd::shared_ptr const & backing_inode) -> kstd::shared_ptr { - if (!device) + if (!backing_inode) { - kapi::system::panic("[FILESYSTEM] cannot mount filesystem: device is null."); + kapi::system::panic("[FILESYSTEM] cannot mount filesystem: backing inode is null."); } for (auto & factory : filesystem_factories) { auto fs = factory(); - if (fs->mount(device) == operation_result::success) + if (fs->mount(backing_inode) == operation_result::success) { return fs; } @@ -39,14 +37,14 @@ namespace kernel::filesystem return nullptr; } - auto filesystem::mount(kstd::shared_ptr const & device) -> operation_result + auto filesystem::mount(kstd::shared_ptr const & backing_inode) -> operation_result { - if (!device) + if (!backing_inode) { - kapi::system::panic("[FILESYSTEM] cannot mount filesystem: device is null."); + kapi::system::panic("[FILESYSTEM] cannot mount filesystem: backing inode is null."); } - m_device = device; + m_backing_inode = backing_inode; return operation_result::success; } @@ -55,8 +53,8 @@ namespace kernel::filesystem return m_root_inode; } - auto filesystem::device() const -> kstd::shared_ptr const & + auto filesystem::backing_inode() const -> kstd::shared_ptr const & { - return m_device; + return m_backing_inode; } } // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/rootfs/filesystem.cpp b/kernel/src/filesystem/rootfs/filesystem.cpp index dffef99..f718c72 100644 --- a/kernel/src/filesystem/rootfs/filesystem.cpp +++ b/kernel/src/filesystem/rootfs/filesystem.cpp @@ -1,7 +1,5 @@ #include "kernel/filesystem/rootfs/filesystem.hpp" -#include "kapi/devices/device.hpp" - #include "kernel/filesystem/inode.hpp" #include "kernel/filesystem/rootfs/inode.hpp" @@ -11,7 +9,7 @@ namespace kernel::filesystem::rootfs { - auto filesystem::mount(kstd::shared_ptr const &) -> operation_result + auto filesystem::mount(kstd::shared_ptr const &) -> operation_result { auto rfs_inode = kstd::make_shared(); rfs_inode->add_child("dev"); diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 67d1af2..394e926 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -2,7 +2,6 @@ #include "kapi/system.hpp" -#include "kernel/devices/storage/management.hpp" #include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/devfs/filesystem.hpp" #include "kernel/filesystem/filesystem.hpp" @@ -43,19 +42,17 @@ namespace kernel::filesystem auto root_fs_root_dentry = kstd::make_shared(nullptr, root_fs->root_inode()); m_mount_table.add_mount(kstd::make_shared(nullptr, root_fs_root_dentry, root_fs, "", nullptr)); - auto storage_mgmt = devices::storage::management::get(); - if (auto boot_device = storage_mgmt.determine_boot_device()) + auto device_fs = kstd::make_shared(); + device_fs->mount(nullptr); + do_mount_internal("/dev", root_fs_root_dentry, device_fs); + + if (auto boot_device_dentry = resolve_path("/dev/ram0")) // TODO BA-FS26 better boot device detection { - auto boot_root_fs = kernel::filesystem::filesystem::probe_and_mount(boot_device); - if (boot_root_fs) + if (auto boot_root_fs = kernel::filesystem::filesystem::probe_and_mount(boot_device_dentry->get_inode())) { do_mount_internal("/", root_fs_root_dentry, boot_root_fs); } } - - auto device_fs = kstd::make_shared(); - device_fs->mount(nullptr); - do_mount_internal("/dev", root_fs_root_dentry, device_fs); } auto vfs::get() -> vfs & @@ -78,24 +75,26 @@ namespace kernel::filesystem return nullptr; } - auto vfs::do_mount(std::string_view path, kstd::shared_ptr const & filesystem) -> operation_result + auto vfs::do_mount(std::string_view source, std::string_view target) -> operation_result { - if (!filesystem) - { - return operation_result::filesystem_null; - } - - if (path.empty() || path.front() != '/' || (path.size() > 1 && path.back() == '/')) + if (target.empty() || target.front() != '/' || (target.size() > 1 && target.back() == '/')) { return operation_result::invalid_path; } - if (auto mount_point_dentry = resolve_path(path)) + if (auto mount_point_dentry = resolve_path(target)) { - do_mount_internal(path, mount_point_dentry, filesystem); - return operation_result::success; + if (auto source_dentry = resolve_path(source)) + { + if (auto fs = kernel::filesystem::filesystem::probe_and_mount(source_dentry->get_inode())) + { + do_mount_internal(target, mount_point_dentry, fs); + return operation_result::success; + } + return operation_result::invalid_filesystem; + } + return operation_result::non_existent_path; } - return operation_result::mount_point_not_found; } diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index f363041..8c963c6 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -67,11 +67,6 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS {image_path_1, image_path_2, image_path_3})); auto & vfs = kernel::filesystem::vfs::get(); - auto storage_mgmt = kernel::devices::storage::management::get(); - auto device_1 = storage_mgmt.device_by_major_minor(1, 16); - auto fs_1 = kernel::filesystem::filesystem::probe_and_mount(device_1); - auto device_2 = storage_mgmt.device_by_major_minor(1, 32); - auto fs_2 = kernel::filesystem::filesystem::probe_and_mount(device_2); THEN("vfs initializes first module as root") { @@ -85,7 +80,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS THEN("second image can be mounted, data retrieved and unmounted again") { - REQUIRE(vfs.do_mount("/information", fs_1) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); REQUIRE(mounted_monkey_1 != nullptr); @@ -100,8 +95,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS THEN("third image can be mounted in a mounted file system, unmount only if no child mount exists") { - REQUIRE(vfs.do_mount("/information", fs_1) == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.do_mount("/information/monkey_house/infrastructure", fs_2) == + REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/dev/ram32", "/information/monkey_house/infrastructure") == kernel::filesystem::vfs::operation_result::success); auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); @@ -118,8 +113,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS THEN("images can be stacked mounted and correct file system is unmounted again") { - REQUIRE(vfs.do_mount("/information", fs_1) == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.do_mount("/information", fs_2) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/dev/ram32", "/information") == kernel::filesystem::vfs::operation_result::success); auto mounted_tickets = vfs.open("/information/entrance/tickets.txt"); REQUIRE(mounted_tickets != nullptr); @@ -134,19 +129,26 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS THEN("mount with null file system fails") { - REQUIRE(vfs.do_mount("/information", nullptr) == kernel::filesystem::vfs::operation_result::filesystem_null); + REQUIRE(vfs.do_mount("/closed.txt", "/information") == + kernel::filesystem::vfs::operation_result::invalid_filesystem); } THEN("mount with invalid path fails") { - REQUIRE(vfs.do_mount("", fs_1) == kernel::filesystem::vfs::operation_result::invalid_path); - REQUIRE(vfs.do_mount("information", fs_1) == kernel::filesystem::vfs::operation_result::invalid_path); - REQUIRE(vfs.do_mount("/information/", fs_1) == kernel::filesystem::vfs::operation_result::invalid_path); + REQUIRE(vfs.do_mount("/dev/ram16", "") == kernel::filesystem::vfs::operation_result::invalid_path); + REQUIRE(vfs.do_mount("/dev/ram16", "information") == kernel::filesystem::vfs::operation_result::invalid_path); + REQUIRE(vfs.do_mount("/dev/ram16", "/information/") == kernel::filesystem::vfs::operation_result::invalid_path); + } + + THEN("mount with non-existent source path fails") + { + REQUIRE(vfs.do_mount("/dev/nonexistent", "/information") == + kernel::filesystem::vfs::operation_result::non_existent_path); } THEN("mount with non-existent mount point fails") { - REQUIRE(vfs.do_mount("/information/nonexistent", fs_1) == + REQUIRE(vfs.do_mount("/dev/ram16", "/information/nonexistent") == kernel::filesystem::vfs::operation_result::mount_point_not_found); } diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 79ed703..e296bd5 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -9,7 +9,6 @@ #include "kernel/devices/storage/management.hpp" #include "kernel/filesystem/device_inode.hpp" #include "kernel/filesystem/file_descriptor_table.hpp" -#include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/open_file_description.hpp" #include "kernel/filesystem/vfs.hpp" #include "kernel/memory.hpp" @@ -138,24 +137,17 @@ auto test_file_lookup() -> void "this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_" "limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_30.txt"); - auto storage_mgmt = kernel::devices::storage::management::get(); - auto device_1 = storage_mgmt.device_by_major_minor(1, 16); - auto fs_1 = kernel::filesystem::filesystem::probe_and_mount(device_1); - - vfs.do_mount("/enclosures/aquarium", fs_1); + vfs.do_mount("/dev/ram16", "/enclosures/aquarium"); read_and_write_file("/enclosures/aquarium/closed.txt"); read_and_write_file("/enclosures/aquarium/information/info_2.txt"); vfs.unmount("/enclosures/aquarium"); read_and_write_file("/enclosures/aquarium/tank_1/fish_4.txt"); - auto device_2 = storage_mgmt.device_by_major_minor(1, 32); - auto fs_2 = kernel::filesystem::filesystem::probe_and_mount(device_2); - - vfs.do_mount("/enclosures/elephant_house", fs_2); + vfs.do_mount("/dev/ram32", "/enclosures/elephant_house"); read_and_write_file("/enclosures/elephant_house/monkey_house/infrastructure/info.txt"); - vfs.do_mount("/enclosures/elephant_house/monkey_house", fs_1); + vfs.do_mount("/dev/ram16", "/enclosures/elephant_house/monkey_house"); read_and_write_file("/enclosures/elephant_house/monkey_house/information/info_2.txt"); auto result = vfs.unmount("/enclosures/elephant_house"); -- cgit v1.2.3 From 5354654a486296be674ecc7ba5e92ca01cc29107 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 14 Apr 2026 08:44:41 +0200 Subject: add tests to mount filesystems backed by a file --- kernel/src/filesystem/vfs.tests.cpp | 67 +++++++++++++++++++++- .../filesystem/test_assets/ext2_1KB_fs.img | 2 +- 2 files changed, 66 insertions(+), 3 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 8c963c6..12dce84 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -1,12 +1,14 @@ #include "kernel/filesystem/vfs.hpp" -#include "kernel/devices/storage/management.hpp" -#include "kernel/filesystem/filesystem.hpp" #include "kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp" +#include + #include +#include #include +#include SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS with dummy modules", "[filesystem][vfs]") @@ -165,4 +167,65 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS kernel::filesystem::vfs::operation_result::mount_point_not_found); } } + + GIVEN("A real image file containing as filesystem formatted files") + { + REQUIRE(std::filesystem::exists(image_path_1)); + REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module_1"}, {image_path_1})); + + THEN("the file-filesystem in the image can be mounted, files can be read and unmounted again") + { + auto & vfs = kernel::filesystem::vfs::get(); + REQUIRE(vfs.do_mount("/archiv/2024.img", "/information") == kernel::filesystem::vfs::operation_result::success); + + auto sheep_1 = vfs.open("/information/sheep_1.txt"); + REQUIRE(sheep_1 != nullptr); + + kstd::vector buffer(7); + auto bytes_read = sheep_1->read(buffer.data(), buffer.size()); + std::string_view buffer_as_str{reinterpret_cast(buffer.data()), bytes_read}; + REQUIRE(buffer_as_str == "sheep_1"); + + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); + auto unmounted_sheep_1 = vfs.open("/information/sheep_1.txt"); + REQUIRE(unmounted_sheep_1 == nullptr); + } + + THEN("the file-filesystem in the image can be mounted and in this filesystem can another file-filesystem be " + "mounted, files can be read and unmounted again") + { + auto & vfs = kernel::filesystem::vfs::get(); + REQUIRE(vfs.do_mount("/archiv/2024.img", "/information") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/archiv/2025.img", "/information/stable") == + kernel::filesystem::vfs::operation_result::success); + + auto sheep_1 = vfs.open("/information/sheep_1.txt"); + auto goat_1 = vfs.open("/information/stable/petting_zoo/goat_1.txt"); + REQUIRE(sheep_1 != nullptr); + REQUIRE(goat_1 != nullptr); + + kstd::vector sheep_buffer(7); + auto bytes_read = sheep_1->read(sheep_buffer.data(), sheep_buffer.size()); + std::string_view buffer_as_str{reinterpret_cast(sheep_buffer.data()), bytes_read}; + REQUIRE(buffer_as_str == "sheep_1"); + + kstd::vector goat_buffer(6); + bytes_read = goat_1->read(goat_buffer.data(), goat_buffer.size()); + buffer_as_str = std::string_view{reinterpret_cast(goat_buffer.data()), bytes_read}; + REQUIRE(buffer_as_str == "goat_1"); + + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); + + REQUIRE(vfs.unmount("/information/stable") == kernel::filesystem::vfs::operation_result::success); + auto unmounted_goat_1 = vfs.open("/information/stable/petting_zoo/goat_1.txt"); + REQUIRE(unmounted_goat_1 == nullptr); + + auto still_mounted_sheep_1 = vfs.open("/information/sheep_1.txt"); + REQUIRE(still_mounted_sheep_1 != nullptr); + + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); + auto unmounted_sheep_1 = vfs.open("/information/sheep_1.txt"); + REQUIRE(unmounted_sheep_1 == nullptr); + } + } } diff --git a/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img b/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img index 9f1ee4a..5bbb76d 100644 --- a/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img +++ b/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:94d3988bc309eb9e81f06042c72bf4c4fb5991cd7fdd597eb00c518a96c792d8 +oid sha256:c2ef9536a439825520d9e230eedaa9ae327f9763350eddbc0f24bf5b9b5d2bf2 size 10485760 -- cgit v1.2.3 From 69068165f49ca204025410ab02546318997edaa3 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 15 Apr 2026 16:53:36 +0200 Subject: kernel: improve bht speed using memory mapping --- .../filesystem/storage_boot_module_fixture.cpp | 105 +++++++++++++-------- .../filesystem/storage_boot_module_vfs_fixture.cpp | 7 +- 2 files changed, 70 insertions(+), 42 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp b/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp index a139f63..cd8360b 100644 --- a/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp +++ b/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp @@ -8,17 +8,72 @@ #include "kernel/test_support/boot_modules.hpp" #include "kernel/test_support/devices/storage/management.hpp" -#include -#include - #include +#include #include -#include -#include +#include #include +#include +#include +#include +#include +#include +#include namespace kernel::tests::filesystem { + storage_boot_module_fixture::mapped_image::mapped_image(std::filesystem::path path) + : file_descriptor(::open(path.c_str(), O_RDWR)) + { + if (file_descriptor < 0) + { + throw std::runtime_error{"Failed to open image file for test boot module: " + path.string()}; + } + + struct stat statistics{}; + if (::fstat(file_descriptor, &statistics) < 0) + { + throw std::runtime_error{"Failed to get statistics for image file: " + path.string()}; + } + + size = static_cast(statistics.st_size); + + mapping = static_cast(::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, file_descriptor, 0)); + if (mapping == MAP_FAILED) + { + throw std::runtime_error{"Failed to map image file for test boot module: " + path.string()}; + } + } + + storage_boot_module_fixture::mapped_image::~mapped_image() + { + if (mapping != nullptr) + { + ::munmap(mapping, size); + } + if (file_descriptor >= 0) + { + ::close(file_descriptor); + } + } + + storage_boot_module_fixture::mapped_image::mapped_image(mapped_image && other) noexcept + : file_descriptor{std::exchange(other.file_descriptor, -1)} + , mapping{std::exchange(other.mapping, nullptr)} + , size{std::exchange(other.size, 0)} + {} + + auto storage_boot_module_fixture::mapped_image::operator=(mapped_image && other) noexcept -> mapped_image & + { + if (this != &other) + { + file_descriptor = std::exchange(other.file_descriptor, -1); + mapping = std::exchange(other.mapping, nullptr); + size = std::exchange(other.size, 0); + } + return *this; + } + storage_boot_module_fixture::~storage_boot_module_fixture() { kernel::tests::devices::storage::management::deinit(); @@ -36,23 +91,22 @@ namespace kernel::tests::filesystem for (std::size_t i = 0; i < module_count; ++i) { - m_module_names.push_back("test_mod" + kstd::to_string(i)); + m_module_names.push_back(std::format("test_mod{}", i)); m_module_data.emplace_back(module_size, std::byte{static_cast(0x40 + (i % 16))}); } for (std::size_t i = 0; i < module_count; ++i) { m_registry.add_boot_module(kapi::boot_modules::boot_module{ - m_module_names[i].view(), kapi::memory::linear_address{m_module_data[i].data()}, m_module_data[i].size()}); + m_module_names[i].c_str(), kapi::memory::linear_address{m_module_data[i].data()}, m_module_data[i].size()}); } kapi::boot_modules::set_boot_module_registry(m_registry); kernel::devices::storage::management::init(); } - auto storage_boot_module_fixture::setup_modules_from_img(kstd::vector const & module_names, - kstd::vector const & img_paths) - -> void + auto storage_boot_module_fixture::setup_modules_from_img(std::vector const & module_names, + std::vector const & img_paths) -> void { m_module_names.clear(); m_module_data.clear(); @@ -72,38 +126,13 @@ namespace kernel::tests::filesystem kernel::devices::storage::management::init(); } - auto storage_boot_module_fixture::setup_module_from_img(kstd::string const & module_name, + auto storage_boot_module_fixture::setup_module_from_img(std::string const & module_name, std::filesystem::path const & img_path) -> void { - auto file = std::ifstream{img_path, std::ios::binary | std::ios::ate}; - if (!file) - { - throw std::runtime_error{"Failed to open image file for test boot module: " + img_path.string()}; - } - - auto const end_pos = file.tellg(); - if (end_pos < 0) - { - throw std::runtime_error{"Failed to determine image file size for test boot module: " + img_path.string()}; - } - - auto const size = static_cast(end_pos); - file.seekg(0, std::ios::beg); - m_module_names.push_back(module_name); - m_module_data.emplace_back(size); - - if (size > 0) - { - file.read(reinterpret_cast(m_module_data.back().data()), static_cast(size)); - if (!file) - { - throw std::runtime_error{"Failed to read image file content for test boot module: " + img_path.string()}; - } - } + auto & mapped_image = m_mapped_images.emplace_back(img_path); m_registry.add_boot_module(kapi::boot_modules::boot_module{ - m_module_names.back().view(), kapi::memory::linear_address{m_module_data.back().data()}, - m_module_data.back().size()}); + m_module_names.back().c_str(), kapi::memory::linear_address{mapped_image.mapping}, mapped_image.size}); } } // namespace kernel::tests::filesystem \ No newline at end of file diff --git a/kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp b/kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp index cba7278..1a71b57 100644 --- a/kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp +++ b/kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp @@ -3,11 +3,10 @@ #include "kernel/filesystem/vfs.hpp" #include "kernel/test_support/filesystem/vfs.hpp" -#include -#include - #include #include +#include +#include namespace kernel::tests::filesystem { @@ -24,7 +23,7 @@ namespace kernel::tests::filesystem } auto storage_boot_module_vfs_fixture::setup_modules_from_img_and_init_vfs( - kstd::vector const & module_names, kstd::vector const & img_paths) -> void + std::vector const & module_names, std::vector const & img_paths) -> void { setup_modules_from_img(module_names, img_paths); kernel::filesystem::vfs::init(); -- cgit v1.2.3 From 252df23b061b2bf54206da73e41faca600541ccc Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 16 Apr 2026 09:26:52 +0200 Subject: acpi: introduce VLA table --- kernel/src/acpi/manager.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp index 501ce92..41469c2 100644 --- a/kernel/src/acpi/manager.cpp +++ b/kernel/src/acpi/manager.cpp @@ -32,7 +32,7 @@ namespace kernel::acpi } auto physical_extended_table_address = kapi::memory::physical_address{xsdp->table_address()}; auto linear_extended_table_address = kapi::memory::hhdm_to_linear(physical_extended_table_address); - m_rsdt = static_cast<::acpi::sdt const *>(linear_extended_table_address); + m_rsdt = static_cast<::acpi::table_header const *>(linear_extended_table_address); m_extended = true; } else @@ -43,7 +43,7 @@ namespace kernel::acpi } auto physical_root_table_address = kapi::memory::physical_address{m_sdp->table_address()}; auto linear_root_table_address = kapi::memory::hhdm_to_linear(physical_root_table_address); - m_rsdt = static_cast<::acpi::sdt const *>(linear_root_table_address); + m_rsdt = static_cast<::acpi::table_header const *>(linear_root_table_address); } } @@ -55,8 +55,8 @@ namespace kernel::acpi } auto entry_size = m_extended ? sizeof(std::uint64_t) : sizeof(std::uint32_t); - auto entry_count = (m_rsdt->length().value - sizeof(::acpi::sdt)) / entry_size; - auto entries_base = reinterpret_cast(m_rsdt) + sizeof(::acpi::sdt); + auto entry_count = (m_rsdt->length().value - sizeof(::acpi::table_header)) / entry_size; + auto entries_base = reinterpret_cast(m_rsdt) + sizeof(::acpi::table_header); for (std::size_t i = 0; i < entry_count; ++i) { @@ -74,7 +74,7 @@ namespace kernel::acpi } auto linear_table_address = kapi::memory::hhdm_to_linear(physical_table_address); - auto table = static_cast<::acpi::sdt const *>(linear_table_address); + auto table = static_cast<::acpi::table_header const *>(linear_table_address); if (!::acpi::validate_checksum({reinterpret_cast(table), table->length().value})) { @@ -90,7 +90,7 @@ namespace kernel::acpi return !m_tables.empty(); } - auto manager::get_table(std::string_view signature) -> kstd::observer_ptr<::acpi::sdt const> + auto manager::get_table(std::string_view signature) -> kstd::observer_ptr<::acpi::table_header const> { if (m_tables.contains(signature)) { -- cgit v1.2.3 From 28cae58fe117e5fcfc46fd6378e19387cd73b2fe Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 16 Apr 2026 09:40:12 +0200 Subject: acpi: derive basic table from table header --- kernel/src/acpi/manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp index 41469c2..2f2a1bd 100644 --- a/kernel/src/acpi/manager.cpp +++ b/kernel/src/acpi/manager.cpp @@ -43,7 +43,7 @@ namespace kernel::acpi } auto physical_root_table_address = kapi::memory::physical_address{m_sdp->table_address()}; auto linear_root_table_address = kapi::memory::hhdm_to_linear(physical_root_table_address); - m_rsdt = static_cast<::acpi::table_header const *>(linear_root_table_address); + m_rsdt = static_cast<::acpi::rsdt const *>(linear_root_table_address); } } -- cgit v1.2.3 From 776ab2749d5af0a34fd2aa6103a377ddc04d4c53 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 16 Apr 2026 10:03:35 +0200 Subject: acpi: introduce XSDT type --- kernel/src/acpi/manager.cpp | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp index 2f2a1bd..5876799 100644 --- a/kernel/src/acpi/manager.cpp +++ b/kernel/src/acpi/manager.cpp @@ -8,8 +8,10 @@ #include +#include #include #include +#include #include namespace kernel::acpi @@ -32,7 +34,7 @@ namespace kernel::acpi } auto physical_extended_table_address = kapi::memory::physical_address{xsdp->table_address()}; auto linear_extended_table_address = kapi::memory::hhdm_to_linear(physical_extended_table_address); - m_rsdt = static_cast<::acpi::table_header const *>(linear_extended_table_address); + m_rsdt = static_cast<::acpi::xsdt const *>(linear_extended_table_address); m_extended = true; } else @@ -54,29 +56,12 @@ namespace kernel::acpi kapi::system::panic("[OS:ACPI] Invalid RSDT checksum!"); } - auto entry_size = m_extended ? sizeof(std::uint64_t) : sizeof(std::uint32_t); - auto entry_count = (m_rsdt->length().value - sizeof(::acpi::table_header)) / entry_size; - auto entries_base = reinterpret_cast(m_rsdt) + sizeof(::acpi::table_header); + auto check_and_register_table = [&](auto table_address) -> void { + auto physical_table_address = kapi::memory::physical_address{reinterpret_cast(table_address)}; + auto mapped_table = kapi::memory::hhdm_to_linear(physical_table_address); + auto table = static_cast<::acpi::table_header const *>(mapped_table); - for (std::size_t i = 0; i < entry_count; ++i) - { - auto physical_table_address = kapi::memory::physical_address{}; - - if (m_extended) - { - auto entry = reinterpret_cast(entries_base + (i * entry_size)); - physical_table_address = kapi::memory::physical_address{*entry}; - } - else - { - auto entry = reinterpret_cast(entries_base + (i * entry_size)); - physical_table_address = kapi::memory::physical_address{*entry}; - } - - auto linear_table_address = kapi::memory::hhdm_to_linear(physical_table_address); - auto table = static_cast<::acpi::table_header const *>(linear_table_address); - - if (!::acpi::validate_checksum({reinterpret_cast(table), table->length().value})) + if (!::acpi::validate_checksum({static_cast(mapped_table), table->length().value})) { kstd::println(kstd::print_sink::stderr, "[OS:ACPI] Invalid table checksum!"); } @@ -85,6 +70,19 @@ namespace kernel::acpi kstd::println("[OS:ACPI] Found '{}' ACPI table", table->signature()); m_tables.emplace(table->signature(), table); } + }; + + if (m_extended) + { + auto xsdt = static_cast<::acpi::xsdt const *>(m_rsdt); + std::ranges::for_each(*xsdt | std::views::transform([](auto const & entry) { return entry.address(); }), + check_and_register_table); + } + else + { + auto rsdt = static_cast<::acpi::rsdt const *>(m_rsdt); + std::ranges::for_each(*rsdt | std::views::transform([](auto const & entry) { return entry.address(); }), + check_and_register_table); } return !m_tables.empty(); -- cgit v1.2.3 From 44b5f84ac7d563be0e2f518db71c273760aba8a3 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sun, 19 Apr 2026 09:40:09 +0200 Subject: add todo to support sparse files --- kernel/src/filesystem/ext2/inode.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp index bf3f0cf..07a5525 100644 --- a/kernel/src/filesystem/ext2/inode.cpp +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -31,7 +31,9 @@ namespace kernel::filesystem::ext2 while (bytes_read < size) { auto const block_number = m_filesystem->map_inode_block_index_to_global_block_number(block_index, m_data); - if (block_number == 0) // TODO BA-FS26 really correct? + // TODO BA-FS26 really correct? sparse files -> 0 means a full block with zeros --> function + // map_inode_block_index_to_global_block_number should return 0 if not possible to find an block + if (block_number == 0) { break; } -- cgit v1.2.3 From e9837b17eeee5ba69f5067e5bfe3f40aca0a9277 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sun, 19 Apr 2026 09:41:45 +0200 Subject: check that after mount the old file isn't available anymore --- kernel/src/filesystem/vfs.tests.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 12dce84..0a7b6c7 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -178,6 +178,9 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto & vfs = kernel::filesystem::vfs::get(); REQUIRE(vfs.do_mount("/archiv/2024.img", "/information") == kernel::filesystem::vfs::operation_result::success); + auto info_1 = vfs.open("/information/info_1.txt"); + REQUIRE(info_1 == nullptr); + auto sheep_1 = vfs.open("/information/sheep_1.txt"); REQUIRE(sheep_1 != nullptr); -- cgit v1.2.3 From 1356405c9fc6d54cf9da4d5f6fd54c55d51ce66d Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sun, 19 Apr 2026 10:01:52 +0200 Subject: vfs open returns the dentry not the open file description --- kernel/src/filesystem/open_file_description.tests.cpp | 5 +++-- kernel/src/filesystem/vfs.cpp | 10 ++-------- kernel/src/filesystem/vfs.tests.cpp | 16 +++++++++++----- kernel/src/main.cpp | 10 ++++++---- 4 files changed, 22 insertions(+), 19 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/open_file_description.tests.cpp b/kernel/src/filesystem/open_file_description.tests.cpp index db8eb49..ec35546 100644 --- a/kernel/src/filesystem/open_file_description.tests.cpp +++ b/kernel/src/filesystem/open_file_description.tests.cpp @@ -76,8 +76,9 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module"}, {image_path})); auto & vfs = kernel::filesystem::vfs::get(); - auto ofd = vfs.open("/information/info_1.txt"); - REQUIRE(ofd != nullptr); + auto dentry = vfs.open("/information/info_1.txt"); + REQUIRE(dentry != nullptr); + auto ofd = kstd::make_shared(dentry->get_inode()); THEN("the file can be read and the offset is updated") { diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 394e926..84c8047 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -7,7 +7,6 @@ #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/mount.hpp" #include "kernel/filesystem/mount_table.hpp" -#include "kernel/filesystem/open_file_description.hpp" #include "kernel/filesystem/rootfs/filesystem.hpp" #include @@ -65,14 +64,9 @@ namespace kernel::filesystem return *active_vfs; } - auto vfs::open(std::string_view path) -> kstd::shared_ptr + auto vfs::open(std::string_view path) -> kstd::shared_ptr { - if (auto dentry = resolve_path(path)) - { - return kstd::make_shared(dentry->get_inode()); - } - - return nullptr; + return resolve_path(path); } auto vfs::do_mount(std::string_view source, std::string_view target) -> operation_result diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 0a7b6c7..eba157d 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -1,7 +1,9 @@ #include "kernel/filesystem/vfs.hpp" +#include "kernel/filesystem/open_file_description.hpp" #include "kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp" +#include #include #include @@ -181,11 +183,12 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto info_1 = vfs.open("/information/info_1.txt"); REQUIRE(info_1 == nullptr); - auto sheep_1 = vfs.open("/information/sheep_1.txt"); - REQUIRE(sheep_1 != nullptr); + auto dentry = vfs.open("/information/sheep_1.txt"); + REQUIRE(dentry != nullptr); + auto sheep_1_ofd = kstd::make_shared(dentry->get_inode()); kstd::vector buffer(7); - auto bytes_read = sheep_1->read(buffer.data(), buffer.size()); + auto bytes_read = sheep_1_ofd->read(buffer.data(), buffer.size()); std::string_view buffer_as_str{reinterpret_cast(buffer.data()), bytes_read}; REQUIRE(buffer_as_str == "sheep_1"); @@ -207,13 +210,16 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(sheep_1 != nullptr); REQUIRE(goat_1 != nullptr); + auto sheep_1_ofd = kstd::make_shared(sheep_1->get_inode()); + auto goat_1_ofd = kstd::make_shared(goat_1->get_inode()); + kstd::vector sheep_buffer(7); - auto bytes_read = sheep_1->read(sheep_buffer.data(), sheep_buffer.size()); + auto bytes_read = sheep_1_ofd->read(sheep_buffer.data(), sheep_buffer.size()); std::string_view buffer_as_str{reinterpret_cast(sheep_buffer.data()), bytes_read}; REQUIRE(buffer_as_str == "sheep_1"); kstd::vector goat_buffer(6); - bytes_read = goat_1->read(goat_buffer.data(), goat_buffer.size()); + bytes_read = goat_1_ofd->read(goat_buffer.data(), goat_buffer.size()); buffer_as_str = std::string_view{reinterpret_cast(goat_buffer.data()), bytes_read}; REQUIRE(buffer_as_str == "goat_1"); diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index e296bd5..aee3579 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -88,13 +88,14 @@ auto test_file_description_manually() -> void auto test_device_with_vfs() -> void { auto vfs = kernel::filesystem::vfs::get(); - auto ofd = vfs.open("/dev/ram0"); - if (!ofd) + auto dentry = vfs.open("/dev/ram0"); + if (!dentry) { kstd::os::panic("test code failed"); } auto fd_table = kernel::filesystem::file_descriptor_table::get(); + auto ofd = kstd::make_shared(dentry->get_inode()); auto fd = fd_table.add_file(ofd); kstd::vector buffer{2}; auto file = fd_table.get_file(fd); @@ -113,13 +114,14 @@ auto test_file_lookup() -> void auto vfs = kernel::filesystem::vfs::get(); auto read_and_write_file = [&vfs](std::string_view path) { kstd::println("[TEST] Reading and writing file at path: {}", path); - auto ofd = vfs.open(path); - if (!ofd) + auto dentry = vfs.open(path); + if (!dentry) { kstd::os::panic("test code failed"); } kstd::vector buffer{32}; + auto ofd = kstd::make_shared(dentry->get_inode()); auto number_of_read_bytes = ofd->read(buffer.data(), buffer.size()); kstd::println("read bytes: {}", number_of_read_bytes); kstd::println("buffer: {::#04x}", buffer); -- cgit v1.2.3 From 2d8fed40bd0d0f8144783b6b344dc79944291b72 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 23 Apr 2026 13:31:17 +0200 Subject: chore: organize includes --- kernel/src/acpi/manager.cpp | 4 ++-- kernel/src/devices/block_device_utils.cpp | 4 ++-- kernel/src/devices/storage/management.cpp | 6 +++--- kernel/src/devices/storage/ram_disk/controller.cpp | 4 ++-- kernel/src/devices/storage/ram_disk/device.cpp | 4 ++-- kernel/src/devices/storage/ram_disk/device.tests.cpp | 5 ++--- kernel/src/filesystem/dentry.cpp | 4 ++-- kernel/src/filesystem/devfs/filesystem.cpp | 4 ++-- kernel/src/filesystem/device_inode.cpp | 6 +++--- kernel/src/filesystem/ext2/inode.cpp | 4 ++-- kernel/src/filesystem/file_descriptor_table.cpp | 4 ++-- kernel/src/filesystem/filesystem.cpp | 4 ++-- kernel/src/filesystem/mount.cpp | 8 ++++---- kernel/src/filesystem/vfs.cpp | 4 ++-- kernel/src/main.cpp | 14 +++++++------- kernel/src/memory.cpp | 6 +++--- kernel/src/memory/bitmap_allocator.tests.cpp | 1 - kernel/src/memory/block_list_allocator.cpp | 4 ++-- kernel/src/memory/block_list_allocator.tests.cpp | 4 ++-- kernel/src/memory/operators.cpp | 4 ++-- .../filesystem/storage_boot_module_fixture.cpp | 13 +++++++------ kernel/src/test_support/kapi/cio.cpp | 4 ++-- kernel/src/test_support/kapi/memory.cpp | 4 ++-- kernel/src/test_support/output_device.cpp | 4 ++-- kernel/src/test_support/simulated_memory.cpp | 3 ++- kernel/src/test_support/state_reset_listener.cpp | 8 ++++---- 26 files changed, 67 insertions(+), 67 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp index 5876799..f17c9cb 100644 --- a/kernel/src/acpi/manager.cpp +++ b/kernel/src/acpi/manager.cpp @@ -3,11 +3,11 @@ #include "kapi/memory.hpp" #include "kapi/system.hpp" +#include + #include #include -#include - #include #include #include diff --git a/kernel/src/devices/block_device_utils.cpp b/kernel/src/devices/block_device_utils.cpp index 59e9b97..3c77308 100644 --- a/kernel/src/devices/block_device_utils.cpp +++ b/kernel/src/devices/block_device_utils.cpp @@ -1,10 +1,10 @@ #include "kernel/devices/block_device_utils.hpp" +#include "kernel/devices/block_device.hpp" + #include "kapi/devices/device.hpp" #include "kapi/system.hpp" -#include "kernel/devices/block_device.hpp" - #include #include #include diff --git a/kernel/src/devices/storage/management.cpp b/kernel/src/devices/storage/management.cpp index c9fa0a8..8ff1b06 100644 --- a/kernel/src/devices/storage/management.cpp +++ b/kernel/src/devices/storage/management.cpp @@ -1,12 +1,12 @@ #include "kernel/devices/storage/management.hpp" +#include "kernel/devices/storage/controller.hpp" +#include "kernel/devices/storage/ram_disk/controller.hpp" + #include "kapi/boot_modules.hpp" #include "kapi/devices/device.hpp" #include "kapi/system.hpp" -#include "kernel/devices/storage/controller.hpp" -#include "kernel/devices/storage/ram_disk/controller.hpp" - #include #include diff --git a/kernel/src/devices/storage/ram_disk/controller.cpp b/kernel/src/devices/storage/ram_disk/controller.cpp index 040e61f..d230533 100644 --- a/kernel/src/devices/storage/ram_disk/controller.cpp +++ b/kernel/src/devices/storage/ram_disk/controller.cpp @@ -1,9 +1,9 @@ #include "kernel/devices/storage/ram_disk/controller.hpp" -#include "kapi/boot_module/boot_module_registry.hpp" - #include "kernel/devices/storage/ram_disk/device.hpp" +#include "kapi/boot_module/boot_module_registry.hpp" + #include #include diff --git a/kernel/src/devices/storage/ram_disk/device.cpp b/kernel/src/devices/storage/ram_disk/device.cpp index 8fc3b2a..c6a1363 100644 --- a/kernel/src/devices/storage/ram_disk/device.cpp +++ b/kernel/src/devices/storage/ram_disk/device.cpp @@ -1,10 +1,10 @@ #include "kernel/devices/storage/ram_disk/device.hpp" +#include "kernel/devices/block_device.hpp" + #include "kapi/boot_module/boot_module.hpp" #include "kapi/system.hpp" -#include "kernel/devices/block_device.hpp" - #include #include diff --git a/kernel/src/devices/storage/ram_disk/device.tests.cpp b/kernel/src/devices/storage/ram_disk/device.tests.cpp index eacdb04..b475c4b 100644 --- a/kernel/src/devices/storage/ram_disk/device.tests.cpp +++ b/kernel/src/devices/storage/ram_disk/device.tests.cpp @@ -3,10 +3,9 @@ #include "kapi/boot_module/boot_module.hpp" #include "kapi/memory.hpp" -#include "catch2/matchers/catch_matchers.hpp" -#include "catch2/matchers/catch_matchers_range_equals.hpp" - #include +#include +#include #include #include diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index 6591011..af5ceab 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -1,9 +1,9 @@ #include "kernel/filesystem/dentry.hpp" -#include "kapi/system.hpp" - #include "kernel/filesystem/inode.hpp" +#include "kapi/system.hpp" + #include #include diff --git a/kernel/src/filesystem/devfs/filesystem.cpp b/kernel/src/filesystem/devfs/filesystem.cpp index dd60c5d..76b9489 100644 --- a/kernel/src/filesystem/devfs/filesystem.cpp +++ b/kernel/src/filesystem/devfs/filesystem.cpp @@ -1,12 +1,12 @@ #include "kernel/filesystem/devfs/filesystem.hpp" -#include "kapi/devices/device.hpp" - #include "kernel/devices/storage/management.hpp" #include "kernel/filesystem/devfs/inode.hpp" #include "kernel/filesystem/device_inode.hpp" #include "kernel/filesystem/inode.hpp" +#include "kapi/devices/device.hpp" + #include #include diff --git a/kernel/src/filesystem/device_inode.cpp b/kernel/src/filesystem/device_inode.cpp index 397a0fd..5793bfc 100644 --- a/kernel/src/filesystem/device_inode.cpp +++ b/kernel/src/filesystem/device_inode.cpp @@ -1,11 +1,11 @@ #include "kernel/filesystem/device_inode.hpp" -#include "kapi/devices/device.hpp" -#include "kapi/system.hpp" - #include "kernel/devices/block_device_utils.hpp" #include "kernel/filesystem/inode.hpp" +#include "kapi/devices/device.hpp" +#include "kapi/system.hpp" + #include #include diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp index 07a5525..6b42db6 100644 --- a/kernel/src/filesystem/ext2/inode.cpp +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -1,10 +1,10 @@ #include "kernel/filesystem/ext2/inode.hpp" -#include "kapi/system.hpp" - #include "kernel/filesystem/ext2/filesystem.hpp" #include "kernel/filesystem/inode.hpp" +#include "kapi/system.hpp" + #include #include #include diff --git a/kernel/src/filesystem/file_descriptor_table.cpp b/kernel/src/filesystem/file_descriptor_table.cpp index 7569cea..4160429 100644 --- a/kernel/src/filesystem/file_descriptor_table.cpp +++ b/kernel/src/filesystem/file_descriptor_table.cpp @@ -1,9 +1,9 @@ #include "kernel/filesystem/file_descriptor_table.hpp" -#include "kapi/system.hpp" - #include "kernel/filesystem/open_file_description.hpp" +#include "kapi/system.hpp" + #include #include diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index 99e7456..f958660 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -1,10 +1,10 @@ #include "kernel/filesystem/filesystem.hpp" -#include "kapi/system.hpp" - #include "kernel/filesystem/ext2/filesystem.hpp" #include "kernel/filesystem/inode.hpp" +#include "kapi/system.hpp" + #include #include diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index d165385..9c8584b 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -1,10 +1,10 @@ #include "kernel/filesystem/mount.hpp" -#include "kapi/system.hpp" - #include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/filesystem.hpp" +#include "kapi/system.hpp" + #include #include @@ -13,8 +13,8 @@ namespace kernel::filesystem { mount::mount(kstd::shared_ptr const & mount_dentry, kstd::shared_ptr const & root_dentry, - kstd::shared_ptr const & fs, std::string_view mount_path, - kstd::shared_ptr const & parent_mount) + kstd::shared_ptr const & fs, std::string_view mount_path, + kstd::shared_ptr const & parent_mount) : m_mount_path(mount_path) , m_mount_dentry(mount_dentry) , m_root_dentry(root_dentry) diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 84c8047..23ced4c 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -1,7 +1,5 @@ #include "kernel/filesystem/vfs.hpp" -#include "kapi/system.hpp" - #include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/devfs/filesystem.hpp" #include "kernel/filesystem/filesystem.hpp" @@ -9,6 +7,8 @@ #include "kernel/filesystem/mount_table.hpp" #include "kernel/filesystem/rootfs/filesystem.hpp" +#include "kapi/system.hpp" + #include #include diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index aee3579..52cbe2e 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,3 +1,10 @@ +#include "kernel/devices/storage/management.hpp" +#include "kernel/filesystem/device_inode.hpp" +#include "kernel/filesystem/file_descriptor_table.hpp" +#include "kernel/filesystem/open_file_description.hpp" +#include "kernel/filesystem/vfs.hpp" +#include "kernel/memory.hpp" + #include "kapi/boot_modules.hpp" #include "kapi/cio.hpp" #include "kapi/cpu.hpp" @@ -6,13 +13,6 @@ #include "kapi/memory.hpp" #include "kapi/system.hpp" -#include "kernel/devices/storage/management.hpp" -#include "kernel/filesystem/device_inode.hpp" -#include "kernel/filesystem/file_descriptor_table.hpp" -#include "kernel/filesystem/open_file_description.hpp" -#include "kernel/filesystem/vfs.hpp" -#include "kernel/memory.hpp" - #include #include #include diff --git a/kernel/src/memory.cpp b/kernel/src/memory.cpp index 4a8e203..b5f65fa 100644 --- a/kernel/src/memory.cpp +++ b/kernel/src/memory.cpp @@ -1,11 +1,11 @@ #include "kernel/memory.hpp" -#include "kapi/memory.hpp" -#include "kapi/system.hpp" - #include "kernel/memory/block_list_allocator.hpp" #include "kernel/memory/heap_allocator.hpp" +#include "kapi/memory.hpp" +#include "kapi/system.hpp" + #include #include diff --git a/kernel/src/memory/bitmap_allocator.tests.cpp b/kernel/src/memory/bitmap_allocator.tests.cpp index 56ec0a4..eff6d85 100644 --- a/kernel/src/memory/bitmap_allocator.tests.cpp +++ b/kernel/src/memory/bitmap_allocator.tests.cpp @@ -4,7 +4,6 @@ #include "catch2/matchers/catch_matchers.hpp" #include "catch2/matchers/catch_matchers_range_equals.hpp" - #include #include diff --git a/kernel/src/memory/block_list_allocator.cpp b/kernel/src/memory/block_list_allocator.cpp index fbc5945..5c416fa 100644 --- a/kernel/src/memory/block_list_allocator.cpp +++ b/kernel/src/memory/block_list_allocator.cpp @@ -1,10 +1,10 @@ #include "kernel/memory/block_list_allocator.hpp" +#include "kernel/memory/heap_allocator.hpp" + #include "kapi/memory.hpp" #include "kapi/system.hpp" -#include "kernel/memory/heap_allocator.hpp" - #include #include diff --git a/kernel/src/memory/block_list_allocator.tests.cpp b/kernel/src/memory/block_list_allocator.tests.cpp index 0571441..fccdad5 100644 --- a/kernel/src/memory/block_list_allocator.tests.cpp +++ b/kernel/src/memory/block_list_allocator.tests.cpp @@ -1,9 +1,9 @@ #include "kernel/memory/block_list_allocator.hpp" -#include "kapi/memory.hpp" - #include "kernel/test_support/memory.hpp" +#include "kapi/memory.hpp" + #include #include diff --git a/kernel/src/memory/operators.cpp b/kernel/src/memory/operators.cpp index 25b5f24..dd3b4fa 100644 --- a/kernel/src/memory/operators.cpp +++ b/kernel/src/memory/operators.cpp @@ -1,7 +1,7 @@ -#include "kapi/system.hpp" - #include "kernel/memory.hpp" +#include "kapi/system.hpp" + #include #include diff --git a/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp b/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp index cd8360b..7fa2cb8 100644 --- a/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp +++ b/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp @@ -1,25 +1,26 @@ #include "kernel/test_support/filesystem/storage_boot_module_fixture.hpp" -#include "kapi/boot_module/boot_module.hpp" -#include "kapi/boot_modules.hpp" -#include "kapi/memory.hpp" - #include "kernel/devices/storage/management.hpp" #include "kernel/test_support/boot_modules.hpp" #include "kernel/test_support/devices/storage/management.hpp" +#include "kapi/boot_module/boot_module.hpp" +#include "kapi/boot_modules.hpp" +#include "kapi/memory.hpp" + #include #include #include #include #include #include -#include -#include #include #include #include +#include +#include + namespace kernel::tests::filesystem { storage_boot_module_fixture::mapped_image::mapped_image(std::filesystem::path path) diff --git a/kernel/src/test_support/kapi/cio.cpp b/kernel/src/test_support/kapi/cio.cpp index 4a1cd1f..5cdd462 100644 --- a/kernel/src/test_support/kapi/cio.cpp +++ b/kernel/src/test_support/kapi/cio.cpp @@ -1,9 +1,9 @@ #include "kernel/test_support/cio.hpp" -#include - #include "kernel/test_support/log_buffer.hpp" +#include + #include #include #include diff --git a/kernel/src/test_support/kapi/memory.cpp b/kernel/src/test_support/kapi/memory.cpp index e926ba6..3b4a1bd 100644 --- a/kernel/src/test_support/kapi/memory.cpp +++ b/kernel/src/test_support/kapi/memory.cpp @@ -1,10 +1,10 @@ #include "kapi/memory.hpp" -#include - #include "kernel/test_support/bump_frame_allocator.hpp" #include "kernel/test_support/page_mapper.hpp" +#include + #include #include diff --git a/kernel/src/test_support/output_device.cpp b/kernel/src/test_support/output_device.cpp index 83dcbcc..505e385 100644 --- a/kernel/src/test_support/output_device.cpp +++ b/kernel/src/test_support/output_device.cpp @@ -1,8 +1,8 @@ -#include "kapi/cio.hpp" - #include "kernel/test_support/cio.hpp" #include "kernel/test_support/log_buffer.hpp" +#include "kapi/cio.hpp" + #include #include #include diff --git a/kernel/src/test_support/simulated_memory.cpp b/kernel/src/test_support/simulated_memory.cpp index 03dac1d..2a4f15b 100644 --- a/kernel/src/test_support/simulated_memory.cpp +++ b/kernel/src/test_support/simulated_memory.cpp @@ -9,9 +9,10 @@ #include #include #include +#include + #include #include -#include namespace kernel::tests { diff --git a/kernel/src/test_support/state_reset_listener.cpp b/kernel/src/test_support/state_reset_listener.cpp index 9120c89..1967743 100644 --- a/kernel/src/test_support/state_reset_listener.cpp +++ b/kernel/src/test_support/state_reset_listener.cpp @@ -1,7 +1,3 @@ -#include "kapi/cio.hpp" -#include "kapi/cpu.hpp" -#include "kapi/memory.hpp" - #include "kernel/filesystem/file_descriptor_table.hpp" #include "kernel/test_support/boot_modules.hpp" #include "kernel/test_support/cio.hpp" @@ -11,6 +7,10 @@ #include "kernel/test_support/filesystem/vfs.hpp" #include "kernel/test_support/memory.hpp" +#include "kapi/cio.hpp" +#include "kapi/cpu.hpp" +#include "kapi/memory.hpp" + #include #include #include -- cgit v1.2.3 From f6f10575f75ac23d06e1d94f7861611503daa7af Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 23 Apr 2026 14:03:28 +0200 Subject: chore: banish relative includes --- kernel/src/acpi/manager.cpp | 6 ++--- kernel/src/devices/block_device.cpp | 6 ++--- kernel/src/devices/block_device.tests.cpp | 4 ++-- kernel/src/devices/block_device_utils.cpp | 8 +++---- kernel/src/devices/block_device_utils.tests.cpp | 8 +++---- kernel/src/devices/root_bus.cpp | 4 ++-- kernel/src/devices/storage/controller.cpp | 4 ++-- kernel/src/devices/storage/management.cpp | 12 +++++----- kernel/src/devices/storage/ram_disk/controller.cpp | 6 ++--- kernel/src/devices/storage/ram_disk/device.cpp | 8 +++---- .../src/devices/storage/ram_disk/device.tests.cpp | 6 ++--- kernel/src/filesystem/dentry.cpp | 6 ++--- kernel/src/filesystem/dentry.tests.cpp | 6 ++--- kernel/src/filesystem/devfs/filesystem.cpp | 12 +++++----- kernel/src/filesystem/devfs/filesystem.tests.cpp | 6 ++--- kernel/src/filesystem/devfs/inode.cpp | 4 ++-- kernel/src/filesystem/devfs/inode.tests.cpp | 2 +- kernel/src/filesystem/device_inode.cpp | 10 ++++---- kernel/src/filesystem/device_inode.tests.cpp | 8 +++---- kernel/src/filesystem/ext2/filesystem.cpp | 16 ++++++------- kernel/src/filesystem/ext2/filesystem.tests.cpp | 18 +++++++------- kernel/src/filesystem/ext2/inode.cpp | 8 +++---- kernel/src/filesystem/ext2/inode.tests.cpp | 20 ++++++++-------- kernel/src/filesystem/file_descriptor_table.cpp | 6 ++--- .../src/filesystem/file_descriptor_table.tests.cpp | 6 ++--- kernel/src/filesystem/filesystem.cpp | 8 +++---- kernel/src/filesystem/inode.cpp | 2 +- kernel/src/filesystem/mount.cpp | 8 +++---- kernel/src/filesystem/mount.tests.cpp | 10 ++++---- kernel/src/filesystem/mount_table.cpp | 6 ++--- kernel/src/filesystem/mount_table.tests.cpp | 10 ++++---- kernel/src/filesystem/open_file_description.cpp | 4 ++-- .../src/filesystem/open_file_description.tests.cpp | 8 +++---- kernel/src/filesystem/rootfs/filesystem.cpp | 6 ++--- kernel/src/filesystem/rootfs/filesystem.tests.cpp | 4 ++-- kernel/src/filesystem/rootfs/inode.cpp | 4 ++-- kernel/src/filesystem/rootfs/inode.tests.cpp | 2 +- kernel/src/filesystem/vfs.cpp | 16 ++++++------- kernel/src/filesystem/vfs.tests.cpp | 6 ++--- kernel/src/main.cpp | 28 +++++++++++----------- kernel/src/memory.cpp | 10 ++++---- kernel/src/memory/bitmap_allocator.cpp | 4 ++-- kernel/src/memory/bitmap_allocator.tests.cpp | 8 +++---- kernel/src/memory/block_list_allocator.cpp | 8 +++---- kernel/src/memory/block_list_allocator.tests.cpp | 6 ++--- kernel/src/memory/mmio_allocator.cpp | 6 ++--- kernel/src/memory/operators.cpp | 4 ++-- kernel/src/test_support/devices/block_device.cpp | 4 ++-- .../src/test_support/devices/character_device.cpp | 5 ++-- kernel/src/test_support/filesystem/ext2.cpp | 12 +++++----- kernel/src/test_support/filesystem/filesystem.cpp | 6 ++--- kernel/src/test_support/filesystem/inode.cpp | 4 ++-- .../filesystem/storage_boot_module_fixture.cpp | 14 +++++------ .../filesystem/storage_boot_module_vfs_fixture.cpp | 6 ++--- kernel/src/test_support/kapi/cio.cpp | 4 ++-- kernel/src/test_support/kapi/cpu.cpp | 2 +- kernel/src/test_support/kapi/memory.cpp | 6 ++--- kernel/src/test_support/log_buffer.cpp | 2 +- kernel/src/test_support/output_device.cpp | 6 ++--- kernel/src/test_support/page_mapper.cpp | 4 ++-- kernel/src/test_support/simulated_memory.cpp | 4 ++-- kernel/src/test_support/state_reset_listener.cpp | 24 +++++++++---------- 62 files changed, 235 insertions(+), 236 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp index f17c9cb..99c8860 100644 --- a/kernel/src/acpi/manager.cpp +++ b/kernel/src/acpi/manager.cpp @@ -1,7 +1,7 @@ -#include "kernel/acpi/manager.hpp" +#include -#include "kapi/memory.hpp" -#include "kapi/system.hpp" +#include +#include #include diff --git a/kernel/src/devices/block_device.cpp b/kernel/src/devices/block_device.cpp index b7cb26e..13d73ac 100644 --- a/kernel/src/devices/block_device.cpp +++ b/kernel/src/devices/block_device.cpp @@ -1,7 +1,7 @@ -#include "kernel/devices/block_device.hpp" +#include -#include "kapi/devices/device.hpp" -#include "kapi/system.hpp" +#include +#include #include diff --git a/kernel/src/devices/block_device.tests.cpp b/kernel/src/devices/block_device.tests.cpp index 378437e..a2ddd2b 100644 --- a/kernel/src/devices/block_device.tests.cpp +++ b/kernel/src/devices/block_device.tests.cpp @@ -1,6 +1,6 @@ -#include "kernel/test_support/devices/block_device.hpp" +#include -#include "kernel/test_support/cpu.hpp" +#include #include #include diff --git a/kernel/src/devices/block_device_utils.cpp b/kernel/src/devices/block_device_utils.cpp index 3c77308..cb8ecba 100644 --- a/kernel/src/devices/block_device_utils.cpp +++ b/kernel/src/devices/block_device_utils.cpp @@ -1,9 +1,9 @@ -#include "kernel/devices/block_device_utils.hpp" +#include -#include "kernel/devices/block_device.hpp" +#include -#include "kapi/devices/device.hpp" -#include "kapi/system.hpp" +#include +#include #include #include diff --git a/kernel/src/devices/block_device_utils.tests.cpp b/kernel/src/devices/block_device_utils.tests.cpp index f78e477..e2e1e65 100644 --- a/kernel/src/devices/block_device_utils.tests.cpp +++ b/kernel/src/devices/block_device_utils.tests.cpp @@ -1,8 +1,8 @@ -#include "kernel/devices/block_device_utils.hpp" +#include -#include "kernel/test_support/cpu.hpp" -#include "kernel/test_support/devices/block_device.hpp" -#include "kernel/test_support/devices/character_device.hpp" +#include +#include +#include #include #include diff --git a/kernel/src/devices/root_bus.cpp b/kernel/src/devices/root_bus.cpp index 43a35bf..1b754f2 100644 --- a/kernel/src/devices/root_bus.cpp +++ b/kernel/src/devices/root_bus.cpp @@ -1,6 +1,6 @@ -#include "kernel/devices/root_bus.hpp" +#include -#include "kapi/devices.hpp" +#include namespace kernel::devices { diff --git a/kernel/src/devices/storage/controller.cpp b/kernel/src/devices/storage/controller.cpp index 1bef670..171b918 100644 --- a/kernel/src/devices/storage/controller.cpp +++ b/kernel/src/devices/storage/controller.cpp @@ -1,6 +1,6 @@ -#include "kernel/devices/storage/controller.hpp" +#include -#include "kapi/devices/device.hpp" +#include #include #include diff --git a/kernel/src/devices/storage/management.cpp b/kernel/src/devices/storage/management.cpp index 8ff1b06..7361cd5 100644 --- a/kernel/src/devices/storage/management.cpp +++ b/kernel/src/devices/storage/management.cpp @@ -1,11 +1,11 @@ -#include "kernel/devices/storage/management.hpp" +#include -#include "kernel/devices/storage/controller.hpp" -#include "kernel/devices/storage/ram_disk/controller.hpp" +#include +#include -#include "kapi/boot_modules.hpp" -#include "kapi/devices/device.hpp" -#include "kapi/system.hpp" +#include +#include +#include #include #include diff --git a/kernel/src/devices/storage/ram_disk/controller.cpp b/kernel/src/devices/storage/ram_disk/controller.cpp index d230533..30441fa 100644 --- a/kernel/src/devices/storage/ram_disk/controller.cpp +++ b/kernel/src/devices/storage/ram_disk/controller.cpp @@ -1,8 +1,8 @@ -#include "kernel/devices/storage/ram_disk/controller.hpp" +#include -#include "kernel/devices/storage/ram_disk/device.hpp" +#include -#include "kapi/boot_module/boot_module_registry.hpp" +#include #include diff --git a/kernel/src/devices/storage/ram_disk/device.cpp b/kernel/src/devices/storage/ram_disk/device.cpp index c6a1363..21b0000 100644 --- a/kernel/src/devices/storage/ram_disk/device.cpp +++ b/kernel/src/devices/storage/ram_disk/device.cpp @@ -1,9 +1,9 @@ -#include "kernel/devices/storage/ram_disk/device.hpp" +#include -#include "kernel/devices/block_device.hpp" +#include -#include "kapi/boot_module/boot_module.hpp" -#include "kapi/system.hpp" +#include +#include #include #include diff --git a/kernel/src/devices/storage/ram_disk/device.tests.cpp b/kernel/src/devices/storage/ram_disk/device.tests.cpp index b475c4b..d0fab76 100644 --- a/kernel/src/devices/storage/ram_disk/device.tests.cpp +++ b/kernel/src/devices/storage/ram_disk/device.tests.cpp @@ -1,7 +1,7 @@ -#include "kernel/devices/storage/ram_disk/device.hpp" +#include -#include "kapi/boot_module/boot_module.hpp" -#include "kapi/memory.hpp" +#include +#include #include #include diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index af5ceab..572dd82 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -1,8 +1,8 @@ -#include "kernel/filesystem/dentry.hpp" +#include -#include "kernel/filesystem/inode.hpp" +#include -#include "kapi/system.hpp" +#include #include diff --git a/kernel/src/filesystem/dentry.tests.cpp b/kernel/src/filesystem/dentry.tests.cpp index a6620d3..f81c260 100644 --- a/kernel/src/filesystem/dentry.tests.cpp +++ b/kernel/src/filesystem/dentry.tests.cpp @@ -1,7 +1,7 @@ -#include "kernel/filesystem/dentry.hpp" +#include -#include "kernel/test_support/cpu.hpp" -#include "kernel/test_support/filesystem/inode.hpp" +#include +#include #include #include diff --git a/kernel/src/filesystem/devfs/filesystem.cpp b/kernel/src/filesystem/devfs/filesystem.cpp index 76b9489..96e40a8 100644 --- a/kernel/src/filesystem/devfs/filesystem.cpp +++ b/kernel/src/filesystem/devfs/filesystem.cpp @@ -1,11 +1,11 @@ -#include "kernel/filesystem/devfs/filesystem.hpp" +#include -#include "kernel/devices/storage/management.hpp" -#include "kernel/filesystem/devfs/inode.hpp" -#include "kernel/filesystem/device_inode.hpp" -#include "kernel/filesystem/inode.hpp" +#include +#include +#include +#include -#include "kapi/devices/device.hpp" +#include #include diff --git a/kernel/src/filesystem/devfs/filesystem.tests.cpp b/kernel/src/filesystem/devfs/filesystem.tests.cpp index f8c4764..2b6c09b 100644 --- a/kernel/src/filesystem/devfs/filesystem.tests.cpp +++ b/kernel/src/filesystem/devfs/filesystem.tests.cpp @@ -1,7 +1,7 @@ -#include "kernel/filesystem/devfs/filesystem.hpp" +#include -#include "kernel/filesystem/filesystem.hpp" -#include "kernel/test_support/filesystem/storage_boot_module_fixture.hpp" +#include +#include #include diff --git a/kernel/src/filesystem/devfs/inode.cpp b/kernel/src/filesystem/devfs/inode.cpp index 52cf6fa..0ed66ad 100644 --- a/kernel/src/filesystem/devfs/inode.cpp +++ b/kernel/src/filesystem/devfs/inode.cpp @@ -1,6 +1,6 @@ -#include "kernel/filesystem/devfs/inode.hpp" +#include -#include "kernel/filesystem/inode.hpp" +#include #include diff --git a/kernel/src/filesystem/devfs/inode.tests.cpp b/kernel/src/filesystem/devfs/inode.tests.cpp index 50e34a7..030d709 100644 --- a/kernel/src/filesystem/devfs/inode.tests.cpp +++ b/kernel/src/filesystem/devfs/inode.tests.cpp @@ -1,4 +1,4 @@ -#include "kernel/filesystem/devfs/inode.hpp" +#include #include #include diff --git a/kernel/src/filesystem/device_inode.cpp b/kernel/src/filesystem/device_inode.cpp index 5793bfc..3bafe06 100644 --- a/kernel/src/filesystem/device_inode.cpp +++ b/kernel/src/filesystem/device_inode.cpp @@ -1,10 +1,10 @@ -#include "kernel/filesystem/device_inode.hpp" +#include -#include "kernel/devices/block_device_utils.hpp" -#include "kernel/filesystem/inode.hpp" +#include +#include -#include "kapi/devices/device.hpp" -#include "kapi/system.hpp" +#include +#include #include diff --git a/kernel/src/filesystem/device_inode.tests.cpp b/kernel/src/filesystem/device_inode.tests.cpp index 4e31812..8ac4eff 100644 --- a/kernel/src/filesystem/device_inode.tests.cpp +++ b/kernel/src/filesystem/device_inode.tests.cpp @@ -1,8 +1,8 @@ -#include "kernel/filesystem/device_inode.hpp" +#include -#include "kernel/test_support/cpu.hpp" -#include "kernel/test_support/devices/block_device.hpp" -#include "kernel/test_support/devices/character_device.hpp" +#include +#include +#include #include #include diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index c0f97ed..41572ee 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -1,11 +1,11 @@ -#include "kernel/filesystem/ext2/filesystem.hpp" - -#include "kernel/filesystem/ext2/block_group_descriptor.hpp" -#include "kernel/filesystem/ext2/inode.hpp" -#include "kernel/filesystem/ext2/linked_directory_entry.hpp" -#include "kernel/filesystem/ext2/superblock.hpp" -#include "kernel/filesystem/filesystem.hpp" -#include "kernel/filesystem/inode.hpp" +#include + +#include +#include +#include +#include +#include +#include #include #include diff --git a/kernel/src/filesystem/ext2/filesystem.tests.cpp b/kernel/src/filesystem/ext2/filesystem.tests.cpp index a7b8d5b..31c4c29 100644 --- a/kernel/src/filesystem/ext2/filesystem.tests.cpp +++ b/kernel/src/filesystem/ext2/filesystem.tests.cpp @@ -1,12 +1,12 @@ -#include "kernel/filesystem/ext2/filesystem.hpp" - -#include "kernel/devices/storage/management.hpp" -#include "kernel/filesystem/device_inode.hpp" -#include "kernel/filesystem/ext2/inode.hpp" -#include "kernel/filesystem/filesystem.hpp" -#include "kernel/test_support/devices/block_device.hpp" -#include "kernel/test_support/filesystem/ext2.hpp" -#include "kernel/test_support/filesystem/storage_boot_module_fixture.hpp" +#include + +#include +#include +#include +#include +#include +#include +#include #include #include diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp index 6b42db6..c45c41e 100644 --- a/kernel/src/filesystem/ext2/inode.cpp +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -1,9 +1,9 @@ -#include "kernel/filesystem/ext2/inode.hpp" +#include -#include "kernel/filesystem/ext2/filesystem.hpp" -#include "kernel/filesystem/inode.hpp" +#include +#include -#include "kapi/system.hpp" +#include #include #include diff --git a/kernel/src/filesystem/ext2/inode.tests.cpp b/kernel/src/filesystem/ext2/inode.tests.cpp index ae66aff..4d61790 100644 --- a/kernel/src/filesystem/ext2/inode.tests.cpp +++ b/kernel/src/filesystem/ext2/inode.tests.cpp @@ -1,13 +1,13 @@ -#include "kernel/filesystem/ext2/inode.hpp" - -#include "kernel/devices/storage/management.hpp" -#include "kernel/filesystem/device_inode.hpp" -#include "kernel/filesystem/ext2/filesystem.hpp" -#include "kernel/filesystem/filesystem.hpp" -#include "kernel/test_support/cpu.hpp" -#include "kernel/test_support/devices/block_device.hpp" -#include "kernel/test_support/filesystem/ext2.hpp" -#include "kernel/test_support/filesystem/storage_boot_module_fixture.hpp" +#include + +#include +#include +#include +#include +#include +#include +#include +#include #include #include diff --git a/kernel/src/filesystem/file_descriptor_table.cpp b/kernel/src/filesystem/file_descriptor_table.cpp index 4160429..db7692b 100644 --- a/kernel/src/filesystem/file_descriptor_table.cpp +++ b/kernel/src/filesystem/file_descriptor_table.cpp @@ -1,8 +1,8 @@ -#include "kernel/filesystem/file_descriptor_table.hpp" +#include -#include "kernel/filesystem/open_file_description.hpp" +#include -#include "kapi/system.hpp" +#include #include diff --git a/kernel/src/filesystem/file_descriptor_table.tests.cpp b/kernel/src/filesystem/file_descriptor_table.tests.cpp index 5aeadb2..86ed7bf 100644 --- a/kernel/src/filesystem/file_descriptor_table.tests.cpp +++ b/kernel/src/filesystem/file_descriptor_table.tests.cpp @@ -1,7 +1,7 @@ -#include "kernel/filesystem/file_descriptor_table.hpp" +#include -#include "kernel/filesystem/open_file_description.hpp" -#include "kernel/test_support/filesystem/inode.hpp" +#include +#include #include #include diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index f958660..24d0e22 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -1,9 +1,9 @@ -#include "kernel/filesystem/filesystem.hpp" +#include -#include "kernel/filesystem/ext2/filesystem.hpp" -#include "kernel/filesystem/inode.hpp" +#include +#include -#include "kapi/system.hpp" +#include #include diff --git a/kernel/src/filesystem/inode.cpp b/kernel/src/filesystem/inode.cpp index 1cbead8..2f0764c 100644 --- a/kernel/src/filesystem/inode.cpp +++ b/kernel/src/filesystem/inode.cpp @@ -1,4 +1,4 @@ -#include "kernel/filesystem/inode.hpp" +#include namespace kernel::filesystem { diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index 9c8584b..67450b7 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -1,9 +1,9 @@ -#include "kernel/filesystem/mount.hpp" +#include -#include "kernel/filesystem/dentry.hpp" -#include "kernel/filesystem/filesystem.hpp" +#include +#include -#include "kapi/system.hpp" +#include #include #include diff --git a/kernel/src/filesystem/mount.tests.cpp b/kernel/src/filesystem/mount.tests.cpp index 4c4393a..d630464 100644 --- a/kernel/src/filesystem/mount.tests.cpp +++ b/kernel/src/filesystem/mount.tests.cpp @@ -1,9 +1,9 @@ -#include "kernel/filesystem/mount.hpp" +#include -#include "kernel/filesystem/dentry.hpp" -#include "kernel/test_support/cpu.hpp" -#include "kernel/test_support/filesystem/filesystem.hpp" -#include "kernel/test_support/filesystem/inode.hpp" +#include +#include +#include +#include #include #include diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index 3b1dee3..da3c451 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -1,7 +1,7 @@ -#include "kernel/filesystem/mount_table.hpp" +#include -#include "kernel/filesystem/dentry.hpp" -#include "kernel/filesystem/mount.hpp" +#include +#include #include #include diff --git a/kernel/src/filesystem/mount_table.tests.cpp b/kernel/src/filesystem/mount_table.tests.cpp index 439fe97..747ffdf 100644 --- a/kernel/src/filesystem/mount_table.tests.cpp +++ b/kernel/src/filesystem/mount_table.tests.cpp @@ -1,9 +1,9 @@ -#include "kernel/filesystem/mount_table.hpp" +#include -#include "kernel/filesystem/dentry.hpp" -#include "kernel/filesystem/mount.hpp" -#include "kernel/test_support/filesystem/filesystem.hpp" -#include "kernel/test_support/filesystem/inode.hpp" +#include +#include +#include +#include #include #include diff --git a/kernel/src/filesystem/open_file_description.cpp b/kernel/src/filesystem/open_file_description.cpp index f049a34..3033e2b 100644 --- a/kernel/src/filesystem/open_file_description.cpp +++ b/kernel/src/filesystem/open_file_description.cpp @@ -1,6 +1,6 @@ -#include "kernel/filesystem/open_file_description.hpp" +#include -#include "kernel/filesystem/inode.hpp" +#include #include #include diff --git a/kernel/src/filesystem/open_file_description.tests.cpp b/kernel/src/filesystem/open_file_description.tests.cpp index ec35546..ce3c81a 100644 --- a/kernel/src/filesystem/open_file_description.tests.cpp +++ b/kernel/src/filesystem/open_file_description.tests.cpp @@ -1,8 +1,8 @@ -#include "kernel/filesystem/open_file_description.hpp" +#include -#include "kernel/filesystem/vfs.hpp" -#include "kernel/test_support/filesystem/inode.hpp" -#include "kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp" +#include +#include +#include #include #include diff --git a/kernel/src/filesystem/rootfs/filesystem.cpp b/kernel/src/filesystem/rootfs/filesystem.cpp index f718c72..6187c3c 100644 --- a/kernel/src/filesystem/rootfs/filesystem.cpp +++ b/kernel/src/filesystem/rootfs/filesystem.cpp @@ -1,7 +1,7 @@ -#include "kernel/filesystem/rootfs/filesystem.hpp" +#include -#include "kernel/filesystem/inode.hpp" -#include "kernel/filesystem/rootfs/inode.hpp" +#include +#include #include diff --git a/kernel/src/filesystem/rootfs/filesystem.tests.cpp b/kernel/src/filesystem/rootfs/filesystem.tests.cpp index b013f78..81ac9e4 100644 --- a/kernel/src/filesystem/rootfs/filesystem.tests.cpp +++ b/kernel/src/filesystem/rootfs/filesystem.tests.cpp @@ -1,6 +1,6 @@ -#include "kernel/filesystem/rootfs/filesystem.hpp" +#include -#include "kernel/filesystem/filesystem.hpp" +#include #include #include diff --git a/kernel/src/filesystem/rootfs/inode.cpp b/kernel/src/filesystem/rootfs/inode.cpp index 3ca9c02..eeea3fe 100644 --- a/kernel/src/filesystem/rootfs/inode.cpp +++ b/kernel/src/filesystem/rootfs/inode.cpp @@ -1,6 +1,6 @@ -#include "kernel/filesystem/inode.hpp" +#include -#include "kernel/filesystem/rootfs/inode.hpp" +#include #include #include diff --git a/kernel/src/filesystem/rootfs/inode.tests.cpp b/kernel/src/filesystem/rootfs/inode.tests.cpp index a0c5938..879818c 100644 --- a/kernel/src/filesystem/rootfs/inode.tests.cpp +++ b/kernel/src/filesystem/rootfs/inode.tests.cpp @@ -1,4 +1,4 @@ -#include "kernel/filesystem/rootfs/inode.hpp" +#include #include #include diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 23ced4c..5b454f6 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -1,13 +1,13 @@ -#include "kernel/filesystem/vfs.hpp" +#include -#include "kernel/filesystem/dentry.hpp" -#include "kernel/filesystem/devfs/filesystem.hpp" -#include "kernel/filesystem/filesystem.hpp" -#include "kernel/filesystem/mount.hpp" -#include "kernel/filesystem/mount_table.hpp" -#include "kernel/filesystem/rootfs/filesystem.hpp" +#include +#include +#include +#include +#include +#include -#include "kapi/system.hpp" +#include #include diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index eba157d..9cadb4d 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -1,7 +1,7 @@ -#include "kernel/filesystem/vfs.hpp" +#include -#include "kernel/filesystem/open_file_description.hpp" -#include "kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp" +#include +#include #include #include diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 52cbe2e..60b6e6e 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,17 +1,17 @@ -#include "kernel/devices/storage/management.hpp" -#include "kernel/filesystem/device_inode.hpp" -#include "kernel/filesystem/file_descriptor_table.hpp" -#include "kernel/filesystem/open_file_description.hpp" -#include "kernel/filesystem/vfs.hpp" -#include "kernel/memory.hpp" - -#include "kapi/boot_modules.hpp" -#include "kapi/cio.hpp" -#include "kapi/cpu.hpp" -#include "kapi/devices.hpp" -#include "kapi/interrupts.hpp" -#include "kapi/memory.hpp" -#include "kapi/system.hpp" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include #include #include diff --git a/kernel/src/memory.cpp b/kernel/src/memory.cpp index b5f65fa..6a85c0e 100644 --- a/kernel/src/memory.cpp +++ b/kernel/src/memory.cpp @@ -1,10 +1,10 @@ -#include "kernel/memory.hpp" +#include -#include "kernel/memory/block_list_allocator.hpp" -#include "kernel/memory/heap_allocator.hpp" +#include +#include -#include "kapi/memory.hpp" -#include "kapi/system.hpp" +#include +#include #include #include diff --git a/kernel/src/memory/bitmap_allocator.cpp b/kernel/src/memory/bitmap_allocator.cpp index caaf5a4..240e2af 100644 --- a/kernel/src/memory/bitmap_allocator.cpp +++ b/kernel/src/memory/bitmap_allocator.cpp @@ -1,6 +1,6 @@ -#include "kernel/memory/bitmap_allocator.hpp" +#include -#include "kapi/memory.hpp" +#include #include #include diff --git a/kernel/src/memory/bitmap_allocator.tests.cpp b/kernel/src/memory/bitmap_allocator.tests.cpp index eff6d85..05d11a3 100644 --- a/kernel/src/memory/bitmap_allocator.tests.cpp +++ b/kernel/src/memory/bitmap_allocator.tests.cpp @@ -1,10 +1,10 @@ -#include "kernel/memory/bitmap_allocator.hpp" +#include -#include "kapi/memory.hpp" +#include -#include "catch2/matchers/catch_matchers.hpp" -#include "catch2/matchers/catch_matchers_range_equals.hpp" #include +#include +#include #include #include diff --git a/kernel/src/memory/block_list_allocator.cpp b/kernel/src/memory/block_list_allocator.cpp index 5c416fa..6e68ada 100644 --- a/kernel/src/memory/block_list_allocator.cpp +++ b/kernel/src/memory/block_list_allocator.cpp @@ -1,9 +1,9 @@ -#include "kernel/memory/block_list_allocator.hpp" +#include -#include "kernel/memory/heap_allocator.hpp" +#include -#include "kapi/memory.hpp" -#include "kapi/system.hpp" +#include +#include #include #include diff --git a/kernel/src/memory/block_list_allocator.tests.cpp b/kernel/src/memory/block_list_allocator.tests.cpp index fccdad5..c5f84c5 100644 --- a/kernel/src/memory/block_list_allocator.tests.cpp +++ b/kernel/src/memory/block_list_allocator.tests.cpp @@ -1,8 +1,8 @@ -#include "kernel/memory/block_list_allocator.hpp" +#include -#include "kernel/test_support/memory.hpp" +#include -#include "kapi/memory.hpp" +#include #include diff --git a/kernel/src/memory/mmio_allocator.cpp b/kernel/src/memory/mmio_allocator.cpp index ddbdfc2..ba23dbd 100644 --- a/kernel/src/memory/mmio_allocator.cpp +++ b/kernel/src/memory/mmio_allocator.cpp @@ -1,7 +1,7 @@ -#include "kernel/memory/mmio_allocator.hpp" +#include -#include "kapi/memory.hpp" -#include "kapi/system.hpp" +#include +#include #include diff --git a/kernel/src/memory/operators.cpp b/kernel/src/memory/operators.cpp index dd3b4fa..5673d68 100644 --- a/kernel/src/memory/operators.cpp +++ b/kernel/src/memory/operators.cpp @@ -1,6 +1,6 @@ -#include "kernel/memory.hpp" +#include -#include "kapi/system.hpp" +#include #include diff --git a/kernel/src/test_support/devices/block_device.cpp b/kernel/src/test_support/devices/block_device.cpp index d1d4101..9a9e544 100644 --- a/kernel/src/test_support/devices/block_device.cpp +++ b/kernel/src/test_support/devices/block_device.cpp @@ -1,6 +1,6 @@ -#include "kernel/test_support/devices/block_device.hpp" +#include -#include "kernel/devices/block_device.hpp" +#include #include #include diff --git a/kernel/src/test_support/devices/character_device.cpp b/kernel/src/test_support/devices/character_device.cpp index 9e9227d..3806654 100644 --- a/kernel/src/test_support/devices/character_device.cpp +++ b/kernel/src/test_support/devices/character_device.cpp @@ -1,7 +1,6 @@ +#include -#include "kernel/test_support/devices/character_device.hpp" - -#include "kapi/devices.hpp" +#include #include diff --git a/kernel/src/test_support/filesystem/ext2.cpp b/kernel/src/test_support/filesystem/ext2.cpp index 3627373..5a27b63 100644 --- a/kernel/src/test_support/filesystem/ext2.cpp +++ b/kernel/src/test_support/filesystem/ext2.cpp @@ -1,10 +1,10 @@ -#include "kernel/test_support/filesystem/ext2.hpp" +#include -#include "kernel/filesystem/ext2/block_group_descriptor.hpp" -#include "kernel/filesystem/ext2/filesystem.hpp" -#include "kernel/filesystem/ext2/inode.hpp" -#include "kernel/filesystem/ext2/superblock.hpp" -#include "kernel/test_support/devices/block_device.hpp" +#include +#include +#include +#include +#include #include #include diff --git a/kernel/src/test_support/filesystem/filesystem.cpp b/kernel/src/test_support/filesystem/filesystem.cpp index 225d096..12d43e0 100644 --- a/kernel/src/test_support/filesystem/filesystem.cpp +++ b/kernel/src/test_support/filesystem/filesystem.cpp @@ -1,7 +1,7 @@ -#include "kernel/test_support/filesystem/filesystem.hpp" +#include -#include "kernel/filesystem/inode.hpp" -#include "kernel/test_support/filesystem/inode.hpp" +#include +#include #include diff --git a/kernel/src/test_support/filesystem/inode.cpp b/kernel/src/test_support/filesystem/inode.cpp index 5df7bcd..54bd7e0 100644 --- a/kernel/src/test_support/filesystem/inode.cpp +++ b/kernel/src/test_support/filesystem/inode.cpp @@ -1,6 +1,6 @@ -#include "kernel/test_support/filesystem/inode.hpp" +#include -#include "kernel/filesystem/inode.hpp" +#include #include diff --git a/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp b/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp index 7fa2cb8..aabaace 100644 --- a/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp +++ b/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp @@ -1,12 +1,12 @@ -#include "kernel/test_support/filesystem/storage_boot_module_fixture.hpp" +#include -#include "kernel/devices/storage/management.hpp" -#include "kernel/test_support/boot_modules.hpp" -#include "kernel/test_support/devices/storage/management.hpp" +#include +#include +#include -#include "kapi/boot_module/boot_module.hpp" -#include "kapi/boot_modules.hpp" -#include "kapi/memory.hpp" +#include +#include +#include #include #include diff --git a/kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp b/kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp index 1a71b57..02ccfec 100644 --- a/kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp +++ b/kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp @@ -1,7 +1,7 @@ -#include "kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp" +#include -#include "kernel/filesystem/vfs.hpp" -#include "kernel/test_support/filesystem/vfs.hpp" +#include +#include #include #include diff --git a/kernel/src/test_support/kapi/cio.cpp b/kernel/src/test_support/kapi/cio.cpp index 5cdd462..98bc99d 100644 --- a/kernel/src/test_support/kapi/cio.cpp +++ b/kernel/src/test_support/kapi/cio.cpp @@ -1,6 +1,6 @@ -#include "kernel/test_support/cio.hpp" +#include -#include "kernel/test_support/log_buffer.hpp" +#include #include diff --git a/kernel/src/test_support/kapi/cpu.cpp b/kernel/src/test_support/kapi/cpu.cpp index 671097e..5d95633 100644 --- a/kernel/src/test_support/kapi/cpu.cpp +++ b/kernel/src/test_support/kapi/cpu.cpp @@ -1,4 +1,4 @@ -#include "kernel/test_support/cpu.hpp" +#include #include diff --git a/kernel/src/test_support/kapi/memory.cpp b/kernel/src/test_support/kapi/memory.cpp index 3b4a1bd..7fc95cb 100644 --- a/kernel/src/test_support/kapi/memory.cpp +++ b/kernel/src/test_support/kapi/memory.cpp @@ -1,7 +1,7 @@ -#include "kapi/memory.hpp" +#include -#include "kernel/test_support/bump_frame_allocator.hpp" -#include "kernel/test_support/page_mapper.hpp" +#include +#include #include diff --git a/kernel/src/test_support/log_buffer.cpp b/kernel/src/test_support/log_buffer.cpp index 9cff596..04d875b 100644 --- a/kernel/src/test_support/log_buffer.cpp +++ b/kernel/src/test_support/log_buffer.cpp @@ -1,4 +1,4 @@ -#include "kernel/test_support/log_buffer.hpp" +#include #include #include diff --git a/kernel/src/test_support/output_device.cpp b/kernel/src/test_support/output_device.cpp index 505e385..45fb4bc 100644 --- a/kernel/src/test_support/output_device.cpp +++ b/kernel/src/test_support/output_device.cpp @@ -1,7 +1,7 @@ -#include "kernel/test_support/cio.hpp" -#include "kernel/test_support/log_buffer.hpp" +#include +#include -#include "kapi/cio.hpp" +#include #include #include diff --git a/kernel/src/test_support/page_mapper.cpp b/kernel/src/test_support/page_mapper.cpp index 9236deb..3d50ff1 100644 --- a/kernel/src/test_support/page_mapper.cpp +++ b/kernel/src/test_support/page_mapper.cpp @@ -1,6 +1,6 @@ -#include "kernel/test_support/page_mapper.hpp" +#include -#include "kapi/memory.hpp" +#include #include diff --git a/kernel/src/test_support/simulated_memory.cpp b/kernel/src/test_support/simulated_memory.cpp index 2a4f15b..074e6b1 100644 --- a/kernel/src/test_support/simulated_memory.cpp +++ b/kernel/src/test_support/simulated_memory.cpp @@ -1,6 +1,6 @@ -#include "kernel/test_support/simulated_memory.hpp" +#include -#include "kapi/memory.hpp" +#include #include diff --git a/kernel/src/test_support/state_reset_listener.cpp b/kernel/src/test_support/state_reset_listener.cpp index 1967743..1815110 100644 --- a/kernel/src/test_support/state_reset_listener.cpp +++ b/kernel/src/test_support/state_reset_listener.cpp @@ -1,15 +1,15 @@ -#include "kernel/filesystem/file_descriptor_table.hpp" -#include "kernel/test_support/boot_modules.hpp" -#include "kernel/test_support/cio.hpp" -#include "kernel/test_support/cpu.hpp" -#include "kernel/test_support/devices/storage/management.hpp" -#include "kernel/test_support/filesystem/file_descriptor_table.hpp" -#include "kernel/test_support/filesystem/vfs.hpp" -#include "kernel/test_support/memory.hpp" - -#include "kapi/cio.hpp" -#include "kapi/cpu.hpp" -#include "kapi/memory.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include #include -- cgit v1.2.3 From 97afdf08922956627073d929bcb2529306333313 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 25 Apr 2026 23:29:27 +0200 Subject: add demo code --- kernel/src/main.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 60b6e6e..9f4ec1e 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -187,6 +188,64 @@ auto run_test_code() -> void kstd::println("---------------------------------"); } +auto run_demo() -> void +{ + // 1) open a file + auto fd_1 = kapi::filesystem::open("/entrance/tickets.txt"); + if (fd_1 == -1) + { + kstd::os::panic("demo failed"); + } + + // 2) read from the file + kstd::vector buffer_1{10}; + auto bytes_read = kapi::filesystem::read(fd_1, buffer_1.data(), buffer_1.size()); + auto buffer_as_str = std::string_view{reinterpret_cast(buffer_1.data()), static_cast(bytes_read)}; + kstd::println("Read {} bytes from /entrance/tickets.txt: {}", bytes_read, buffer_as_str); + + // 3) show that /entrance/information/info_1.txt is not accessible before mounting + auto fd_before_mount = kapi::filesystem::open("/entrance/information/info_1.txt"); + if (fd_before_mount == -1) + { + kstd::println("/entrance/information/info_1.txt is not accessible before mounting, as expected."); + } + + // 4) mount a new filesystem on top of /entrance + kapi::filesystem::mount("/dev/ram16", "/entrance"); + + // 5) open a file from the new filesystem + auto fd_2 = kapi::filesystem::open("/entrance/information/info_1.txt"); + if (fd_2 == -1) + { + kstd::os::panic("demo failed"); + } + + // 6) read from the new file + kstd::vector buffer_2{10}; + bytes_read = kapi::filesystem::read(fd_2, buffer_2.data(), buffer_2.size()); + buffer_as_str = std::string_view{reinterpret_cast(buffer_2.data()), static_cast(bytes_read)}; + kstd::println("Read {} bytes from /entrance/information/info_1.txt: {}", bytes_read, buffer_as_str); + + // 7) open device as file + auto fd_3 = kapi::filesystem::open("/dev/ram48"); + if (fd_3 == -1) + { + kstd::os::panic("demo failed"); + } + + // 8) read from the device file + kstd::vector buffer_3{2}; + bytes_read = kapi::filesystem::read(fd_3, buffer_3.data(), buffer_3.size()); + kstd::println("Read {} bytes from /dev/ram48: {::#04x}", bytes_read, buffer_3); + + // 9) write to the device file + kstd::vector write_buffer{std::byte{0xAA}, std::byte{0xAA}}; + auto bytes_written = kapi::filesystem::write(fd_3, write_buffer.data(), write_buffer.size()); + kstd::println("Written {} bytes to /dev/ram48: {::#04x}", bytes_written, write_buffer); + + // 10) do memory dump to show that the write to the device file had an effect +} + auto main() -> int { kapi::cio::init(); @@ -221,6 +280,10 @@ auto main() -> int kernel::filesystem::vfs::init(); kstd::println("[OS] Virtual filesystem initialized."); + // TODO BA-FS26 remove demo and test code again? + // run_demo(); + + // TODO BA-FS26 remove demo and test code again? run_test_code(); kstd::println("[TEST] All tests completed."); -- cgit v1.2.3 From 4e2624b63236fa309c9ecf53a694b6ac9babf4e6 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sun, 26 Apr 2026 10:11:24 +0200 Subject: rename open_file_description to open_file_descriptor --- kernel/src/filesystem/file_descriptor_table.cpp | 12 +-- .../src/filesystem/file_descriptor_table.tests.cpp | 62 +++++------ kernel/src/filesystem/open_file_description.cpp | 41 -------- .../src/filesystem/open_file_description.tests.cpp | 115 --------------------- kernel/src/filesystem/open_file_descriptor.cpp | 40 +++++++ .../src/filesystem/open_file_descriptor.tests.cpp | 114 ++++++++++++++++++++ kernel/src/filesystem/vfs.tests.cpp | 8 +- kernel/src/main.cpp | 16 +-- 8 files changed, 203 insertions(+), 205 deletions(-) delete mode 100644 kernel/src/filesystem/open_file_description.cpp delete mode 100644 kernel/src/filesystem/open_file_description.tests.cpp create mode 100644 kernel/src/filesystem/open_file_descriptor.cpp create mode 100644 kernel/src/filesystem/open_file_descriptor.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/file_descriptor_table.cpp b/kernel/src/filesystem/file_descriptor_table.cpp index db7692b..9361f37 100644 --- a/kernel/src/filesystem/file_descriptor_table.cpp +++ b/kernel/src/filesystem/file_descriptor_table.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include @@ -37,9 +37,9 @@ namespace kernel::filesystem return *global_file_descriptor_table; } - auto file_descriptor_table::add_file(kstd::shared_ptr const & file_description) -> int + auto file_descriptor_table::add_file(kstd::shared_ptr const & file_descriptor) -> int { - if (!file_description) + if (!file_descriptor) { return -1; } @@ -47,15 +47,15 @@ namespace kernel::filesystem auto it = std::ranges::find_if(m_open_files, [](auto const & open_file) { return open_file == nullptr; }); if (it != m_open_files.end()) { - *it = file_description; + *it = file_descriptor; return static_cast(it - m_open_files.begin()); } - m_open_files.push_back(file_description); + m_open_files.push_back(file_descriptor); return static_cast(m_open_files.size() - 1); } - auto file_descriptor_table::get_file(int fd) const -> kstd::shared_ptr + auto file_descriptor_table::get_file(int fd) const -> kstd::shared_ptr { if (fd < 0) { diff --git a/kernel/src/filesystem/file_descriptor_table.tests.cpp b/kernel/src/filesystem/file_descriptor_table.tests.cpp index 86ed7bf..dd04e00 100644 --- a/kernel/src/filesystem/file_descriptor_table.tests.cpp +++ b/kernel/src/filesystem/file_descriptor_table.tests.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include #include @@ -11,18 +11,18 @@ SCENARIO("File descriptor table add/get file", "[filesystem][file_descriptor_table]") { - GIVEN("a file descriptor table and an open file description") + GIVEN("a file descriptor table and an open file descriptor") { auto & table = kernel::filesystem::file_descriptor_table::get(); auto inode = kstd::make_shared(); - auto file_description_1 = kstd::make_shared(inode); - auto file_description_2 = kstd::make_shared(inode); + auto file_descriptor_1 = kstd::make_shared(inode); + auto file_descriptor_2 = kstd::make_shared(inode); - WHEN("adding the open file description to the file descriptor table") + WHEN("adding the open file descriptor to the file descriptor table") { - auto fd_1 = table.add_file(file_description_1); - auto fd_2 = table.add_file(file_description_2); - auto fd_3 = table.add_file(file_description_2); + auto fd_1 = table.add_file(file_descriptor_1); + auto fd_2 = table.add_file(file_descriptor_2); + auto fd_3 = table.add_file(file_descriptor_2); THEN("a valid file descriptor is returned") { @@ -31,67 +31,67 @@ SCENARIO("File descriptor table add/get file", "[filesystem][file_descriptor_tab REQUIRE(fd_3 == 2); } - THEN("the file description can be retrieved using the returned file descriptor") + THEN("the file descriptor can be retrieved using the returned file descriptor") { - auto retrieved_description = table.get_file(fd_1); - REQUIRE(retrieved_description == file_description_1); + auto retrieved_descriptor = table.get_file(fd_1); + REQUIRE(retrieved_descriptor == file_descriptor_1); } } } - GIVEN("a invalid open file description") + GIVEN("a invalid open file descriptor") { auto & table = kernel::filesystem::file_descriptor_table::get(); - THEN("adding a null file description returns an error code") + THEN("adding a null file descriptor returns an error code") { auto fd = table.add_file(nullptr); REQUIRE(fd == -1); } - THEN("retrieving a file description with a negative file descriptor returns a null pointer") + THEN("retrieving a file descriptor with a negative file descriptor returns a null pointer") { - auto retrieved_description = table.get_file(-1); - REQUIRE(retrieved_description == nullptr); + auto retrieved_descriptor = table.get_file(-1); + REQUIRE(retrieved_descriptor == nullptr); } - THEN("retrieving a file description with an out-of-bounds file descriptor returns a null pointer") + THEN("retrieving a file descriptor with an out-of-bounds file descriptor returns a null pointer") { - auto retrieved_description = table.get_file(1000); - REQUIRE(retrieved_description == nullptr); + auto retrieved_descriptor = table.get_file(1000); + REQUIRE(retrieved_descriptor == nullptr); } } } SCENARIO("File descriptor table remove file", "[filesystem][file_descriptor_table]") { - GIVEN("a file descriptor table with an open file description") + GIVEN("a file descriptor table with an open file descriptor") { auto & table = kernel::filesystem::file_descriptor_table::get(); auto inode = kstd::make_shared(); - auto file_description = kstd::make_shared(inode); - auto fd = table.add_file(file_description); + auto file_descriptor = kstd::make_shared(inode); + auto fd = table.add_file(file_descriptor); - WHEN("removing the file description using the file descriptor") + WHEN("removing the file descriptor using the file descriptor") { table.remove_file(fd); - THEN("the file description can no longer be retrieved using the file descriptor") + THEN("the file descriptor can no longer be retrieved using the file descriptor") { - auto retrieved_description = table.get_file(fd); - REQUIRE(retrieved_description == nullptr); + auto retrieved_descriptor = table.get_file(fd); + REQUIRE(retrieved_descriptor == nullptr); } } - WHEN("removing a file description the other file descriptor keep the same index") + WHEN("removing a file descriptor the other file descriptor keep the same index") { - auto fd2 = table.add_file(file_description); + auto fd2 = table.add_file(file_descriptor); table.remove_file(fd); - THEN("the second file description can still be retrieved using its file descriptor") + THEN("the second file descriptor can still be retrieved using its file descriptor") { - auto retrieved_description = table.get_file(fd2); - REQUIRE(retrieved_description == file_description); + auto retrieved_descriptor = table.get_file(fd2); + REQUIRE(retrieved_descriptor == file_descriptor); } } } diff --git a/kernel/src/filesystem/open_file_description.cpp b/kernel/src/filesystem/open_file_description.cpp deleted file mode 100644 index 3033e2b..0000000 --- a/kernel/src/filesystem/open_file_description.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include - -#include - -#include -#include - -#include - -namespace kernel::filesystem -{ - open_file_description::open_file_description(kstd::shared_ptr const & inode) - : m_inode(inode) - , m_offset(0) - { - if (!inode) - { - kstd::os::panic("[FILESYSTEM] open_file_description constructed with null inode."); - } - } - - auto open_file_description::read(void * buffer, size_t size) -> size_t - { - auto read_bytes = m_inode->read(buffer, m_offset, size); - m_offset += read_bytes; - return read_bytes; - } - - auto open_file_description::write(void const * buffer, size_t size) -> size_t - { - auto written_bytes = m_inode->write(buffer, m_offset, size); - m_offset += written_bytes; - return written_bytes; - } - - auto open_file_description::offset() const -> size_t - { - return m_offset; - } - -} // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/open_file_description.tests.cpp b/kernel/src/filesystem/open_file_description.tests.cpp deleted file mode 100644 index ce3c81a..0000000 --- a/kernel/src/filesystem/open_file_description.tests.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include - -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include - -SCENARIO("Open file description construction", "[filesystem][open_file_description]") -{ - GIVEN("an inode and an open file description for that inode") - { - auto inode = kstd::make_shared(); - auto file_description = kernel::filesystem::open_file_description{inode}; - - THEN("the initial offset is zero") - { - REQUIRE(file_description.offset() == 0); - } - } -} - -SCENARIO("Open file description read/write offset management", "[filesystem][open_file_description]") -{ - GIVEN("an inode that tracks read/write calls and an open file description for that inode") - { - auto inode = kstd::make_shared(); - auto file_description = kernel::filesystem::open_file_description{inode}; - - THEN("the offset is updated correctly after reads") - { - REQUIRE(file_description.read(nullptr, 100) == 100); - REQUIRE(file_description.offset() == 100); - REQUIRE(file_description.read(nullptr, 50) == 50); - REQUIRE(file_description.offset() == 150); - } - - THEN("the offset is updated correctly after writes") - { - REQUIRE(file_description.write(nullptr, 200) == 200); - REQUIRE(file_description.offset() == 200); - REQUIRE(file_description.write(nullptr, 25) == 25); - REQUIRE(file_description.offset() == 225); - } - - THEN("reads and writes both update the same offset") - { - REQUIRE(file_description.read(nullptr, 10) == 10); - REQUIRE(file_description.offset() == 10); - REQUIRE(file_description.write(nullptr, 20) == 20); - REQUIRE(file_description.offset() == 30); - REQUIRE(file_description.read(nullptr, 5) == 5); - REQUIRE(file_description.offset() == 35); - REQUIRE(file_description.write(nullptr, 15) == 15); - REQUIRE(file_description.offset() == 50); - } - } -} - -SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, - "Open file description read with real image", "[filesystem][open_file_description][img]") -{ - auto const image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img"; - - GIVEN("an open file description for a file in a real image") - { - REQUIRE(std::filesystem::exists(image_path)); - REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module"}, {image_path})); - - auto & vfs = kernel::filesystem::vfs::get(); - auto dentry = vfs.open("/information/info_1.txt"); - REQUIRE(dentry != nullptr); - auto ofd = kstd::make_shared(dentry->get_inode()); - - THEN("the file can be read and the offset is updated") - { - kstd::vector buffer(32); - auto bytes_read = ofd->read(buffer.data(), buffer.size()); - REQUIRE(bytes_read == 32); - REQUIRE(ofd->offset() == 32); - - std::string_view buffer_as_str{reinterpret_cast(buffer.data()), static_cast(bytes_read)}; - auto const content_end = buffer_as_str.find('\0'); - REQUIRE(buffer_as_str.substr(0, content_end) == "info_1\n"); - - for (auto i = content_end; i < buffer_as_str.size(); ++i) - { - REQUIRE(buffer_as_str[i] == '\0'); - } - } - - THEN("the file can be read multiple times") - { - kstd::vector 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_2 = ofd->read(buffer.data() + buffer.size() / 2, buffer.size() / 2); - REQUIRE(bytes_read_2 == buffer.size() / 2); - REQUIRE(ofd->offset() == buffer.size()); - - std::string_view buffer_as_str{reinterpret_cast(buffer.data()), bytes_read_1 + bytes_read_2}; - REQUIRE(buffer_as_str == "info"); - } - } -} diff --git a/kernel/src/filesystem/open_file_descriptor.cpp b/kernel/src/filesystem/open_file_descriptor.cpp new file mode 100644 index 0000000..25bffbd --- /dev/null +++ b/kernel/src/filesystem/open_file_descriptor.cpp @@ -0,0 +1,40 @@ +#include +#include + +#include +#include + +#include + +namespace kernel::filesystem +{ + open_file_descriptor::open_file_descriptor(kstd::shared_ptr const & inode) + : m_inode(inode) + , m_offset(0) + { + if (!inode) + { + kstd::os::panic("[FILESYSTEM] open_file_descriptor constructed with null inode."); + } + } + + auto open_file_descriptor::read(void * buffer, size_t size) -> size_t + { + auto read_bytes = m_inode->read(buffer, m_offset, size); + m_offset += read_bytes; + return read_bytes; + } + + auto open_file_descriptor::write(void const * buffer, size_t size) -> size_t + { + auto written_bytes = m_inode->write(buffer, m_offset, size); + m_offset += written_bytes; + return written_bytes; + } + + auto open_file_descriptor::offset() const -> size_t + { + return m_offset; + } + +} // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/open_file_descriptor.tests.cpp b/kernel/src/filesystem/open_file_descriptor.tests.cpp new file mode 100644 index 0000000..095e203 --- /dev/null +++ b/kernel/src/filesystem/open_file_descriptor.tests.cpp @@ -0,0 +1,114 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +SCENARIO("Open file descriptor construction", "[filesystem][open_file_descriptor]") +{ + GIVEN("an inode and an open file descriptor for that inode") + { + auto inode = kstd::make_shared(); + auto file_descriptor = kernel::filesystem::open_file_descriptor{inode}; + + THEN("the initial offset is zero") + { + REQUIRE(file_descriptor.offset() == 0); + } + } +} + +SCENARIO("Open file descriptor read/write offset management", "[filesystem][open_file_descriptor]") +{ + GIVEN("an inode that tracks read/write calls and an open file descriptor for that inode") + { + auto inode = kstd::make_shared(); + auto file_descriptor = kernel::filesystem::open_file_descriptor{inode}; + + 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); + } + + 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); + } + + 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); + } + } +} + +SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Open file descriptor read with real image", + "[filesystem][open_file_descriptor][img]") +{ + auto const image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img"; + + GIVEN("an open file descriptor for a file in a real image") + { + REQUIRE(std::filesystem::exists(image_path)); + REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module"}, {image_path})); + + auto & vfs = kernel::filesystem::vfs::get(); + auto dentry = vfs.open("/information/info_1.txt"); + REQUIRE(dentry != nullptr); + auto ofd = kstd::make_shared(dentry->get_inode()); + + THEN("the file can be read and the offset is updated") + { + kstd::vector buffer(32); + auto bytes_read = ofd->read(buffer.data(), buffer.size()); + REQUIRE(bytes_read == 32); + REQUIRE(ofd->offset() == 32); + + std::string_view buffer_as_str{reinterpret_cast(buffer.data()), static_cast(bytes_read)}; + auto const content_end = buffer_as_str.find('\0'); + REQUIRE(buffer_as_str.substr(0, content_end) == "info_1\n"); + + for (auto i = content_end; i < buffer_as_str.size(); ++i) + { + REQUIRE(buffer_as_str[i] == '\0'); + } + } + + THEN("the file can be read multiple times") + { + kstd::vector 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_2 = ofd->read(buffer.data() + buffer.size() / 2, buffer.size() / 2); + REQUIRE(bytes_read_2 == buffer.size() / 2); + REQUIRE(ofd->offset() == buffer.size()); + + std::string_view buffer_as_str{reinterpret_cast(buffer.data()), bytes_read_1 + bytes_read_2}; + REQUIRE(buffer_as_str == "info"); + } + } +} diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 9cadb4d..979ea42 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include #include @@ -185,7 +185,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto dentry = vfs.open("/information/sheep_1.txt"); REQUIRE(dentry != nullptr); - auto sheep_1_ofd = kstd::make_shared(dentry->get_inode()); + auto sheep_1_ofd = kstd::make_shared(dentry->get_inode()); kstd::vector buffer(7); auto bytes_read = sheep_1_ofd->read(buffer.data(), buffer.size()); @@ -210,8 +210,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(sheep_1 != nullptr); REQUIRE(goat_1 != nullptr); - auto sheep_1_ofd = kstd::make_shared(sheep_1->get_inode()); - auto goat_1_ofd = kstd::make_shared(goat_1->get_inode()); + auto sheep_1_ofd = kstd::make_shared(sheep_1->get_inode()); + auto goat_1_ofd = kstd::make_shared(goat_1->get_inode()); kstd::vector sheep_buffer(7); auto bytes_read = sheep_1_ofd->read(sheep_buffer.data(), sheep_buffer.size()); diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 9f4ec1e..9878d20 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include @@ -36,7 +36,7 @@ auto test_device_names() -> void }); } -auto test_file_description_manually() -> void +auto test_file_descriptor_manually() -> void { // setup auto fd_table = kernel::filesystem::file_descriptor_table::get(); @@ -45,7 +45,7 @@ auto test_file_description_manually() -> void auto dev_node = kstd::make_shared(device); - auto ofd = kstd::make_shared(dev_node); + auto ofd = kstd::make_shared(dev_node); auto fd_index = fd_table.add_file(ofd); // use: read two bytes and write two again @@ -71,7 +71,7 @@ auto test_file_description_manually() -> void fd_table.remove_file(fd_index); // use: read four bytes again -> two old bytes two new bytes - auto ofd1 = kstd::make_shared(dev_node); + auto ofd1 = kstd::make_shared(dev_node); fd_index = fd_table.add_file(ofd1); auto fd1 = fd_table.get_file(fd_index); @@ -96,7 +96,7 @@ auto test_device_with_vfs() -> void } auto fd_table = kernel::filesystem::file_descriptor_table::get(); - auto ofd = kstd::make_shared(dentry->get_inode()); + auto ofd = kstd::make_shared(dentry->get_inode()); auto fd = fd_table.add_file(ofd); kstd::vector buffer{2}; auto file = fd_table.get_file(fd); @@ -122,7 +122,7 @@ auto test_file_lookup() -> void } kstd::vector buffer{32}; - auto ofd = kstd::make_shared(dentry->get_inode()); + auto ofd = kstd::make_shared(dentry->get_inode()); auto number_of_read_bytes = ofd->read(buffer.data(), buffer.size()); kstd::println("read bytes: {}", number_of_read_bytes); kstd::println("buffer: {::#04x}", buffer); @@ -175,8 +175,8 @@ auto run_test_code() -> void test_device_names(); kstd::println("---------------------------------"); - kstd::println("[TEST] file description manually"); - test_file_description_manually(); + kstd::println("[TEST] file descriptor manually"); + test_file_descriptor_manually(); kstd::println("---------------------------------"); kstd::println("[TEST] device with VFS"); -- cgit v1.2.3 From e0854bc0aad9e59d67fbf300cb223b116b127ffc Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sun, 26 Apr 2026 12:36:26 +0200 Subject: rename file_descriptor_table to open_file_table --- kernel/src/filesystem/file_descriptor_table.cpp | 98 ------------------ .../src/filesystem/file_descriptor_table.tests.cpp | 113 --------------------- kernel/src/filesystem/open_file_table.cpp | 98 ++++++++++++++++++ kernel/src/filesystem/open_file_table.tests.cpp | 113 +++++++++++++++++++++ kernel/src/main.cpp | 10 +- kernel/src/test_support/state_reset_listener.cpp | 8 +- 6 files changed, 220 insertions(+), 220 deletions(-) delete mode 100644 kernel/src/filesystem/file_descriptor_table.cpp delete mode 100644 kernel/src/filesystem/file_descriptor_table.tests.cpp create mode 100644 kernel/src/filesystem/open_file_table.cpp create mode 100644 kernel/src/filesystem/open_file_table.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/file_descriptor_table.cpp b/kernel/src/filesystem/file_descriptor_table.cpp deleted file mode 100644 index 9361f37..0000000 --- a/kernel/src/filesystem/file_descriptor_table.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include - -#include - -#include - -#include - -#include -#include -#include - -namespace -{ - constinit auto static global_file_descriptor_table = std::optional{}; -} // namespace - -namespace kernel::filesystem -{ - auto file_descriptor_table::init() -> void - { - if (global_file_descriptor_table) - { - kapi::system::panic("[FILESYSTEM] File descriptor table has already been initialized."); - } - - global_file_descriptor_table.emplace(file_descriptor_table{}); - } - - auto file_descriptor_table::get() -> file_descriptor_table & - { - if (!global_file_descriptor_table) - { - kapi::system::panic("[FILESYSTEM] File descriptor table has not been initialized."); - } - - return *global_file_descriptor_table; - } - - auto file_descriptor_table::add_file(kstd::shared_ptr const & file_descriptor) -> int - { - if (!file_descriptor) - { - return -1; - } - - auto it = std::ranges::find_if(m_open_files, [](auto const & open_file) { return open_file == nullptr; }); - if (it != m_open_files.end()) - { - *it = file_descriptor; - return static_cast(it - m_open_files.begin()); - } - - m_open_files.push_back(file_descriptor); - return static_cast(m_open_files.size() - 1); - } - - auto file_descriptor_table::get_file(int fd) const -> kstd::shared_ptr - { - if (fd < 0) - { - return nullptr; - } - - auto const index = static_cast(fd); - if (index >= m_open_files.size()) - { - return nullptr; - } - - return m_open_files.at(index); - } - - auto file_descriptor_table::remove_file(int fd) -> int - { - if (fd < 0) - { - return -1; - } - - auto const index = static_cast(fd); - if (index >= m_open_files.size()) - { - return -1; - } - - m_open_files.at(index) = nullptr; - return 0; - } -} // namespace kernel::filesystem - -namespace kernel::tests::filesystem::file_descriptor_table -{ - auto deinit() -> void - { - global_file_descriptor_table.reset(); - } -} // namespace kernel::tests::filesystem::file_descriptor_table diff --git a/kernel/src/filesystem/file_descriptor_table.tests.cpp b/kernel/src/filesystem/file_descriptor_table.tests.cpp deleted file mode 100644 index dd04e00..0000000 --- a/kernel/src/filesystem/file_descriptor_table.tests.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include - -#include -#include - -#include -#include -#include - -#include - -SCENARIO("File descriptor table add/get file", "[filesystem][file_descriptor_table]") -{ - GIVEN("a file descriptor table and an open file descriptor") - { - auto & table = kernel::filesystem::file_descriptor_table::get(); - auto inode = kstd::make_shared(); - auto file_descriptor_1 = kstd::make_shared(inode); - auto file_descriptor_2 = kstd::make_shared(inode); - - WHEN("adding the open file descriptor to the file descriptor table") - { - auto fd_1 = table.add_file(file_descriptor_1); - auto fd_2 = table.add_file(file_descriptor_2); - auto fd_3 = table.add_file(file_descriptor_2); - - THEN("a valid file descriptor is returned") - { - REQUIRE(fd_1 == 0); - REQUIRE(fd_2 == 1); - REQUIRE(fd_3 == 2); - } - - THEN("the file descriptor can be retrieved using the returned file descriptor") - { - auto retrieved_descriptor = table.get_file(fd_1); - REQUIRE(retrieved_descriptor == file_descriptor_1); - } - } - } - - GIVEN("a invalid open file descriptor") - { - auto & table = kernel::filesystem::file_descriptor_table::get(); - - THEN("adding a null file descriptor returns an error code") - { - auto fd = table.add_file(nullptr); - REQUIRE(fd == -1); - } - - THEN("retrieving a file descriptor with a negative file descriptor returns a null pointer") - { - auto retrieved_descriptor = table.get_file(-1); - REQUIRE(retrieved_descriptor == nullptr); - } - - THEN("retrieving a file descriptor with an out-of-bounds file descriptor returns a null pointer") - { - auto retrieved_descriptor = table.get_file(1000); - REQUIRE(retrieved_descriptor == nullptr); - } - } -} - -SCENARIO("File descriptor table remove file", "[filesystem][file_descriptor_table]") -{ - GIVEN("a file descriptor table with an open file descriptor") - { - auto & table = kernel::filesystem::file_descriptor_table::get(); - auto inode = kstd::make_shared(); - auto file_descriptor = kstd::make_shared(inode); - auto fd = table.add_file(file_descriptor); - - WHEN("removing the file descriptor using the file descriptor") - { - table.remove_file(fd); - - THEN("the file descriptor can no longer be retrieved using the file descriptor") - { - auto retrieved_descriptor = table.get_file(fd); - REQUIRE(retrieved_descriptor == nullptr); - } - } - - WHEN("removing a file descriptor the other file descriptor keep the same index") - { - auto fd2 = table.add_file(file_descriptor); - table.remove_file(fd); - - THEN("the second file descriptor can still be retrieved using its file descriptor") - { - auto retrieved_descriptor = table.get_file(fd2); - REQUIRE(retrieved_descriptor == file_descriptor); - } - } - } - - GIVEN("an invalid file descriptor") - { - auto & table = kernel::filesystem::file_descriptor_table::get(); - - THEN("removing a file with a negative file descriptor does nothing") - { - REQUIRE_NOTHROW(table.remove_file(-1)); - } - - THEN("removing a file with an out-of-bounds file descriptor does nothing") - { - REQUIRE_NOTHROW(table.remove_file(1000)); - } - } -} \ No newline at end of file diff --git a/kernel/src/filesystem/open_file_table.cpp b/kernel/src/filesystem/open_file_table.cpp new file mode 100644 index 0000000..e47d229 --- /dev/null +++ b/kernel/src/filesystem/open_file_table.cpp @@ -0,0 +1,98 @@ +#include + +#include + +#include + +#include + +#include +#include +#include + +namespace +{ + constinit auto static global_open_file_table = std::optional{}; +} // namespace + +namespace kernel::filesystem +{ + auto open_file_table::init() -> void + { + if (global_open_file_table) + { + kapi::system::panic("[FILESYSTEM] Open file table has already been initialized."); + } + + global_open_file_table.emplace(open_file_table{}); + } + + auto open_file_table::get() -> open_file_table & + { + if (!global_open_file_table) + { + kapi::system::panic("[FILESYSTEM] Open file table has not been initialized."); + } + + return *global_open_file_table; + } + + auto open_file_table::add_file(kstd::shared_ptr const & file_descriptor) -> int + { + if (!file_descriptor) + { + return -1; + } + + auto it = std::ranges::find_if(m_open_files, [](auto const & open_file) { return open_file == nullptr; }); + if (it != m_open_files.end()) + { + *it = file_descriptor; + return static_cast(it - m_open_files.begin()); + } + + m_open_files.push_back(file_descriptor); + return static_cast(m_open_files.size() - 1); + } + + auto open_file_table::get_file(int fd) const -> kstd::shared_ptr + { + if (fd < 0) + { + return nullptr; + } + + auto const index = static_cast(fd); + if (index >= m_open_files.size()) + { + return nullptr; + } + + return m_open_files.at(index); + } + + auto open_file_table::remove_file(int fd) -> int + { + if (fd < 0) + { + return -1; + } + + auto const index = static_cast(fd); + if (index >= m_open_files.size()) + { + return -1; + } + + m_open_files.at(index) = nullptr; + return 0; + } +} // namespace kernel::filesystem + +namespace kernel::tests::filesystem::open_file_table +{ + auto deinit() -> void + { + global_open_file_table.reset(); + } +} // namespace kernel::tests::filesystem::open_file_table diff --git a/kernel/src/filesystem/open_file_table.tests.cpp b/kernel/src/filesystem/open_file_table.tests.cpp new file mode 100644 index 0000000..a5c791d --- /dev/null +++ b/kernel/src/filesystem/open_file_table.tests.cpp @@ -0,0 +1,113 @@ +#include + +#include +#include + +#include +#include +#include + +#include + +SCENARIO("Open file table add/get file", "[filesystem][open_file_table]") +{ + GIVEN("a open file table and an open file descriptor") + { + auto & table = kernel::filesystem::open_file_table::get(); + auto inode = kstd::make_shared(); + auto file_descriptor_1 = kstd::make_shared(inode); + auto file_descriptor_2 = kstd::make_shared(inode); + + WHEN("adding the open file descriptor to the open file table") + { + auto fd_1 = table.add_file(file_descriptor_1); + auto fd_2 = table.add_file(file_descriptor_2); + auto fd_3 = table.add_file(file_descriptor_2); + + THEN("a valid file descriptor is returned") + { + REQUIRE(fd_1 == 0); + REQUIRE(fd_2 == 1); + REQUIRE(fd_3 == 2); + } + + THEN("the file descriptor can be retrieved using the returned file descriptor") + { + auto retrieved_descriptor = table.get_file(fd_1); + REQUIRE(retrieved_descriptor == file_descriptor_1); + } + } + } + + GIVEN("a invalid open file descriptor") + { + auto & table = kernel::filesystem::open_file_table::get(); + + THEN("adding a null file descriptor returns an error code") + { + auto fd = table.add_file(nullptr); + REQUIRE(fd == -1); + } + + THEN("retrieving a file descriptor with a negative file descriptor returns a null pointer") + { + auto retrieved_descriptor = table.get_file(-1); + REQUIRE(retrieved_descriptor == nullptr); + } + + THEN("retrieving a file descriptor with an out-of-bounds file descriptor returns a null pointer") + { + auto retrieved_descriptor = table.get_file(1000); + REQUIRE(retrieved_descriptor == nullptr); + } + } +} + +SCENARIO("Open file table remove file", "[filesystem][open_file_table]") +{ + GIVEN("a open file table with an open file descriptor") + { + auto & table = kernel::filesystem::open_file_table::get(); + auto inode = kstd::make_shared(); + auto file_descriptor = kstd::make_shared(inode); + auto fd = table.add_file(file_descriptor); + + WHEN("removing the file descriptor using the file descriptor") + { + table.remove_file(fd); + + THEN("the file descriptor can no longer be retrieved using the file descriptor") + { + auto retrieved_descriptor = table.get_file(fd); + REQUIRE(retrieved_descriptor == nullptr); + } + } + + WHEN("removing a file descriptor the other file descriptor keep the same index") + { + auto fd2 = table.add_file(file_descriptor); + table.remove_file(fd); + + THEN("the second file descriptor can still be retrieved using its file descriptor") + { + auto retrieved_descriptor = table.get_file(fd2); + REQUIRE(retrieved_descriptor == file_descriptor); + } + } + } + + GIVEN("an invalid file descriptor") + { + auto & table = kernel::filesystem::open_file_table::get(); + + THEN("removing a file with a negative file descriptor does nothing") + { + REQUIRE_NOTHROW(table.remove_file(-1)); + } + + THEN("removing a file with an out-of-bounds file descriptor does nothing") + { + REQUIRE_NOTHROW(table.remove_file(1000)); + } + } +} \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 9878d20..ffea979 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,7 +1,7 @@ #include #include -#include #include +#include #include #include @@ -39,7 +39,7 @@ auto test_device_names() -> void auto test_file_descriptor_manually() -> void { // setup - auto fd_table = kernel::filesystem::file_descriptor_table::get(); + auto fd_table = kernel::filesystem::open_file_table::get(); auto storage_mgmt = kernel::devices::storage::management::get(); auto device = storage_mgmt.device_by_major_minor(1, 0); @@ -95,7 +95,7 @@ auto test_device_with_vfs() -> void kstd::os::panic("test code failed"); } - auto fd_table = kernel::filesystem::file_descriptor_table::get(); + auto fd_table = kernel::filesystem::open_file_table::get(); auto ofd = kstd::make_shared(dentry->get_inode()); auto fd = fd_table.add_file(ofd); kstd::vector buffer{2}; @@ -274,8 +274,8 @@ auto main() -> int kernel::devices::storage::management::init(); kstd::println("[OS] Storage management initialized."); - kernel::filesystem::file_descriptor_table::init(); - kstd::println("[OS] Global file descriptor table initialized."); + kernel::filesystem::open_file_table::init(); + kstd::println("[OS] Global open file table initialized."); kernel::filesystem::vfs::init(); kstd::println("[OS] Virtual filesystem initialized."); diff --git a/kernel/src/test_support/state_reset_listener.cpp b/kernel/src/test_support/state_reset_listener.cpp index 1815110..6bb7537 100644 --- a/kernel/src/test_support/state_reset_listener.cpp +++ b/kernel/src/test_support/state_reset_listener.cpp @@ -1,9 +1,9 @@ -#include +#include #include #include #include #include -#include +#include #include #include @@ -22,7 +22,7 @@ struct state_reset_listener : Catch::EventListenerBase void testCaseStarting(Catch::TestCaseInfo const &) override { - kernel::filesystem::file_descriptor_table::init(); + kernel::filesystem::open_file_table::init(); kapi::cio::init(); kapi::cpu::init(); @@ -31,7 +31,7 @@ struct state_reset_listener : Catch::EventListenerBase void testCaseEnded(Catch::TestCaseStats const &) override { - kernel::tests::filesystem::file_descriptor_table::deinit(); + kernel::tests::filesystem::open_file_table::deinit(); kernel::tests::filesystem::vfs::deinit(); kernel::tests::boot_modules::deinit(); kernel::tests::devices::storage::management::deinit(); -- cgit v1.2.3 From 9fc9d3b011db40027e8c1220c535007a786d03ff Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 30 Apr 2026 18:01:23 +0200 Subject: build: upgrade to GCC 16 --- kernel/src/devices/storage/management.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/devices/storage/management.cpp b/kernel/src/devices/storage/management.cpp index 7361cd5..1f2acba 100644 --- a/kernel/src/devices/storage/management.cpp +++ b/kernel/src/devices/storage/management.cpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace { @@ -63,18 +64,20 @@ namespace kernel::devices::storage auto management::device_by_major_minor(size_t major, size_t minor) -> kstd::shared_ptr { - kstd::shared_ptr found = nullptr; - - std::ranges::find_if(m_controllers, [&](auto const & controller) { + auto found = std::ranges::find_if(m_controllers, [=](auto const & controller) { if (controller != nullptr && controller->major() == major) { - found = controller->device_by_minor(minor); - return found != nullptr; + return controller->device_by_minor(minor) != nullptr; } return false; }); - return found; + if (found != std::ranges::cend(m_controllers)) + { + return found->get()->device_by_minor(minor); + } + + return nullptr; } auto management::determine_boot_device() -> kstd::shared_ptr -- cgit v1.2.3 From d3e02e6d9de4751910a8c51079e9489bd15948c7 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 30 Apr 2026 18:42:08 +0200 Subject: kernel/acpi: simplify manager constructor --- kernel/src/acpi/manager.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp index 99c8860..bb895fd 100644 --- a/kernel/src/acpi/manager.cpp +++ b/kernel/src/acpi/manager.cpp @@ -20,22 +20,19 @@ namespace kernel::acpi manager::manager(::acpi::rsdp const & sdp) : m_sdp{&sdp} { - if (m_sdp->signature() != "RSD PTR ") + if (!m_sdp->validate()) { kapi::system::panic("[OS:ACPI] Invalid RSDP signature!"); } - if (m_sdp->revision() >= 2) + m_extended = m_sdp->revision() >= 2; + + if (m_extended) { - auto const xsdp = static_cast<::acpi::xsdp const *>(m_sdp); - if (!xsdp->validate()) + if (!static_cast<::acpi::xsdp const *>(m_sdp)->validate()) { kapi::system::panic("[OS:ACPI] Invalid XSDP signature!"); } - auto physical_extended_table_address = kapi::memory::physical_address{xsdp->table_address()}; - auto linear_extended_table_address = kapi::memory::hhdm_to_linear(physical_extended_table_address); - m_rsdt = static_cast<::acpi::xsdt const *>(linear_extended_table_address); - m_extended = true; } else { @@ -43,10 +40,11 @@ namespace kernel::acpi { kapi::system::panic("[OS:ACPI] Invalid RSDP checksum!"); } - auto physical_root_table_address = kapi::memory::physical_address{m_sdp->table_address()}; - auto linear_root_table_address = kapi::memory::hhdm_to_linear(physical_root_table_address); - m_rsdt = static_cast<::acpi::rsdt const *>(linear_root_table_address); } + + auto physical_address = kapi::memory::physical_address{m_sdp->table_address()}; + auto linear_address = kapi::memory::hhdm_to_linear(physical_address); + m_rsdt = static_cast<::acpi::table_header const *>(linear_address); } auto manager::load_tables() -> bool -- cgit v1.2.3 From b3209ac2564f21f3b78ecf5e0c05ca346a4a4276 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 28 Apr 2026 10:49:34 +0200 Subject: refactor inode kind --- kernel/src/filesystem/devfs/inode.cpp | 11 ++++----- kernel/src/filesystem/device_inode.cpp | 9 ++++--- kernel/src/filesystem/ext2/filesystem.cpp | 36 +++------------------------ kernel/src/filesystem/ext2/inode.cpp | 21 +++++++++++++--- kernel/src/filesystem/ext2/inode.tests.cpp | 37 +++++++++++++++++++--------- kernel/src/filesystem/inode.cpp | 10 +++----- kernel/src/filesystem/rootfs/inode.cpp | 9 ++++--- kernel/src/test_support/filesystem/inode.cpp | 9 ++++--- 8 files changed, 72 insertions(+), 70 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/devfs/inode.cpp b/kernel/src/filesystem/devfs/inode.cpp index 0ed66ad..2029a7f 100644 --- a/kernel/src/filesystem/devfs/inode.cpp +++ b/kernel/src/filesystem/devfs/inode.cpp @@ -1,15 +1,9 @@ #include -#include - #include namespace kernel::filesystem::devfs { - inode::inode() - : kernel::filesystem::inode(inode_kind::directory) - {} - auto inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t { return 0; @@ -19,4 +13,9 @@ namespace kernel::filesystem::devfs { return 0; } + + auto inode::is_directory() const -> bool + { + return true; + } } // namespace kernel::filesystem::devfs \ No newline at end of file diff --git a/kernel/src/filesystem/device_inode.cpp b/kernel/src/filesystem/device_inode.cpp index 3bafe06..81a784c 100644 --- a/kernel/src/filesystem/device_inode.cpp +++ b/kernel/src/filesystem/device_inode.cpp @@ -1,7 +1,6 @@ #include #include -#include #include #include @@ -13,8 +12,7 @@ namespace kernel::filesystem { device_inode::device_inode(kstd::shared_ptr const & device) - : inode(inode_kind::device) - , m_device(device) + : m_device(device) { if (!device) { @@ -51,4 +49,9 @@ namespace kernel::filesystem return m_device; } + auto device_inode::is_device() const -> bool + { + return true; + } + } // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 41572ee..47e54fe 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -16,19 +16,6 @@ namespace kernel::filesystem::ext2 { - namespace - { - auto S_ISREG(uint16_t mode) -> bool - { - return (mode & constants::mode_mask) == constants::mode_regular; - } - - auto S_ISDIR(uint16_t mode) -> bool - { - return (mode & constants::mode_mask) == constants::mode_directory; - } - } // namespace - auto filesystem::mount(kstd::shared_ptr const & backing_inode) -> operation_result { kernel::filesystem::filesystem::mount(backing_inode); @@ -74,7 +61,7 @@ namespace kernel::filesystem::ext2 } auto const block_size = get_block_size(); - auto const & inode_data = ext2_parent->m_data; + auto const & inode_data = ext2_parent->data(); kstd::vector buffer(block_size); for (uint32_t i = 0; i < get_inode_block_count(inode_data); ++i) @@ -119,25 +106,10 @@ namespace kernel::filesystem::ext2 auto const inode_table_offset = static_cast(inode_table_start_block) * block_size; auto const inode_offset = inode_table_offset + inode_index_within_group * get_inode_size(); - auto new_inode = kstd::make_shared(this); - m_backing_inode->read(&new_inode->m_data, inode_offset, sizeof(inode_data)); - - // TODO BA-FS26 improve inode_kind really needed? or just map it to the mode bits? - if (S_ISREG(new_inode->m_data.mode)) - { - new_inode->m_kind = inode::inode_kind::regular; - } - else if (S_ISDIR(new_inode->m_data.mode)) - { - new_inode->m_kind = inode::inode_kind::directory; - } - else - { - // TODO BA-FS26 really correct?? - return nullptr; - } + auto new_inode_data = inode_data{}; + m_backing_inode->read(&new_inode_data, inode_offset, sizeof(inode_data)); - return new_inode; + return kstd::make_shared(this, new_inode_data); } auto filesystem::map_inode_block_index_to_global_block_number(uint32_t inode_block_index, inode_data data) -> uint32_t diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp index c45c41e..279c84f 100644 --- a/kernel/src/filesystem/ext2/inode.cpp +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -11,9 +11,9 @@ namespace kernel::filesystem::ext2 { - inode::inode(filesystem * fs) - : kernel::filesystem::inode(inode_kind::regular) - , m_filesystem(fs) + inode::inode(filesystem * fs, inode_data const & data) + : m_filesystem(fs) + , m_data(data) { if (!m_filesystem) { @@ -57,4 +57,19 @@ namespace kernel::filesystem::ext2 kapi::system::panic("[EXT2] inode::write is not implemented yet"); return 0; } + + [[nodiscard]] auto inode::data() const -> inode_data const & + { + return m_data; + } + + auto inode::is_regular() const -> bool + { + return (m_data.mode & constants::mode_mask) == constants::mode_regular; + } + + auto inode::is_directory() const -> bool + { + return (m_data.mode & constants::mode_mask) == constants::mode_directory; + } } // namespace kernel::filesystem::ext2 diff --git a/kernel/src/filesystem/ext2/inode.tests.cpp b/kernel/src/filesystem/ext2/inode.tests.cpp index 4d61790..e68352f 100644 --- a/kernel/src/filesystem/ext2/inode.tests.cpp +++ b/kernel/src/filesystem/ext2/inode.tests.cpp @@ -23,21 +23,34 @@ SCENARIO("Ext2 inode initialization and properties", "[filesystem][ext2][inode]" GIVEN("an ext2 filesystem") { auto fs = kernel::filesystem::ext2::filesystem{}; + auto data = kernel::filesystem::ext2::inode_data{}; - THEN("the inode is initialized and has the kind regular") + THEN("the inode is initialized with regular file mode in data and has the kind regular") { - auto inode = kernel::filesystem::ext2::inode{&fs}; + data.mode = kernel::filesystem::ext2::constants::mode_regular; + auto inode = kernel::filesystem::ext2::inode(&fs, data); + REQUIRE(inode.is_regular()); REQUIRE(!inode.is_directory()); REQUIRE(!inode.is_device()); } + + THEN("the inode is initialized with directory mode in data and has the kind directory") + { + data.mode = kernel::filesystem::ext2::constants::mode_directory; + auto inode = kernel::filesystem::ext2::inode(&fs, data); + + REQUIRE(!inode.is_regular()); + REQUIRE(inode.is_directory()); + REQUIRE(!inode.is_device()); + } } GIVEN("no filesystem (null pointer)") { THEN("constructing an inode with a null filesystem pointer panics") { - REQUIRE_THROWS_AS(kernel::filesystem::ext2::inode{nullptr}, kernel::tests::cpu::halt); + REQUIRE_THROWS_AS(kernel::filesystem::ext2::inode(nullptr, {}), kernel::tests::cpu::halt); } } } @@ -102,9 +115,10 @@ SCENARIO("Ext2 inode read stops when block mapping resolves to zero", "[filesyst auto fs = kernel::filesystem::ext2::filesystem{}; REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success); - auto inode = kernel::filesystem::ext2::inode{&fs}; - inode.m_data.blocks = 2; - inode.m_data.block[0] = 0; + auto data = kernel::filesystem::ext2::inode_data{}; + data.blocks = 2; + data.block[0] = 0; + auto inode = kernel::filesystem::ext2::inode{&fs, data}; auto buffer = kstd::vector(32, std::byte{0xAB}); @@ -130,12 +144,13 @@ SCENARIO("Ext2 inode read across block boundaries", "[filesystem][ext2][inode]") auto fs = kernel::filesystem::ext2::filesystem{}; REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success); - auto inode = kernel::filesystem::ext2::inode{&fs}; - inode.m_data.blocks = 2; - inode.m_data.block[0] = 20; + auto inode_data = kernel::filesystem::ext2::inode_data{}; + inode_data.blocks = 2; + inode_data.block[0] = 20; kernel::tests::filesystem::ext2::write_bytes(*device, 21 * block_size - 6, "Hello ", 6); - inode.m_data.block[1] = 21; + inode_data.block[1] = 21; kernel::tests::filesystem::ext2::write_bytes(*device, 21 * block_size, "World!", 6); + auto inode = kernel::filesystem::ext2::inode{&fs, inode_data}; auto buffer = kstd::vector(12, std::byte{0x00}); @@ -155,7 +170,7 @@ SCENARIO("Ext2 inode write is not implemented", "[filesystem][ext2][inode]") GIVEN("an ext2 inode") { auto fs = kernel::filesystem::ext2::filesystem{}; - auto inode = kernel::filesystem::ext2::inode{&fs}; + auto inode = kernel::filesystem::ext2::inode{&fs, kernel::filesystem::ext2::inode_data{}}; THEN("writing to the inode panics") { diff --git a/kernel/src/filesystem/inode.cpp b/kernel/src/filesystem/inode.cpp index 2f0764c..f2a7741 100644 --- a/kernel/src/filesystem/inode.cpp +++ b/kernel/src/filesystem/inode.cpp @@ -2,22 +2,18 @@ namespace kernel::filesystem { - inode::inode(inode_kind kind) - : m_kind(kind) - {} - auto inode::is_directory() const -> bool { - return m_kind == inode_kind::directory; + return false; } auto inode::is_regular() const -> bool { - return m_kind == inode_kind::regular; + return false; } auto inode::is_device() const -> bool { - return m_kind == inode_kind::device; + return false; } } // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/rootfs/inode.cpp b/kernel/src/filesystem/rootfs/inode.cpp index eeea3fe..d099676 100644 --- a/kernel/src/filesystem/rootfs/inode.cpp +++ b/kernel/src/filesystem/rootfs/inode.cpp @@ -12,10 +12,6 @@ namespace kernel::filesystem::rootfs { - inode::inode() - : kernel::filesystem::inode(inode_kind::directory) - {} - auto inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t { return 0; @@ -36,4 +32,9 @@ namespace kernel::filesystem::rootfs auto it = std::ranges::find_if(m_children, [&](auto const & pair) { return pair.first == name; }); return (it != m_children.end()) ? it->second : nullptr; } + + auto inode::is_directory() const -> bool + { + return true; + } } // namespace kernel::filesystem::rootfs diff --git a/kernel/src/test_support/filesystem/inode.cpp b/kernel/src/test_support/filesystem/inode.cpp index 54bd7e0..0c8d956 100644 --- a/kernel/src/test_support/filesystem/inode.cpp +++ b/kernel/src/test_support/filesystem/inode.cpp @@ -6,10 +6,6 @@ namespace kernel::tests::filesystem { - inode::inode() - : kernel::filesystem::inode(inode_kind::regular) - {} - auto inode::read(void *, size_t, size_t size) const -> size_t { return size; @@ -19,4 +15,9 @@ namespace kernel::tests::filesystem { return size; } + + auto inode::is_regular() const -> bool + { + return true; + } } // namespace kernel::tests::filesystem \ No newline at end of file -- cgit v1.2.3 From 6790ab170578594f26e8e84a3e57b80cb6094e21 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 28 Apr 2026 10:55:37 +0200 Subject: add is_symbolic_link method in ext2 inode --- kernel/src/filesystem/ext2/inode.cpp | 5 +++++ kernel/src/filesystem/ext2/inode.tests.cpp | 24 ++++++++++++++++++++++++ kernel/src/filesystem/inode.cpp | 5 +++++ 3 files changed, 34 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp index 279c84f..5b6bcb3 100644 --- a/kernel/src/filesystem/ext2/inode.cpp +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -72,4 +72,9 @@ namespace kernel::filesystem::ext2 { return (m_data.mode & constants::mode_mask) == constants::mode_directory; } + + auto inode::is_symbolic_link() const -> bool + { + return (m_data.mode & constants::mode_mask) == constants::mode_symbolic_link; + } } // namespace kernel::filesystem::ext2 diff --git a/kernel/src/filesystem/ext2/inode.tests.cpp b/kernel/src/filesystem/ext2/inode.tests.cpp index e68352f..f0f4aaf 100644 --- a/kernel/src/filesystem/ext2/inode.tests.cpp +++ b/kernel/src/filesystem/ext2/inode.tests.cpp @@ -33,6 +33,7 @@ SCENARIO("Ext2 inode initialization and properties", "[filesystem][ext2][inode]" REQUIRE(inode.is_regular()); REQUIRE(!inode.is_directory()); REQUIRE(!inode.is_device()); + REQUIRE(!inode.is_symbolic_link()); } THEN("the inode is initialized with directory mode in data and has the kind directory") @@ -43,6 +44,29 @@ SCENARIO("Ext2 inode initialization and properties", "[filesystem][ext2][inode]" REQUIRE(!inode.is_regular()); REQUIRE(inode.is_directory()); REQUIRE(!inode.is_device()); + REQUIRE(!inode.is_symbolic_link()); + } + + THEN("the inode is initialized with symbolic link mode in data and has the kind symbolic link") + { + data.mode = kernel::filesystem::ext2::constants::mode_symbolic_link; + auto inode = kernel::filesystem::ext2::inode(&fs, data); + + REQUIRE(!inode.is_regular()); + REQUIRE(!inode.is_directory()); + REQUIRE(!inode.is_device()); + REQUIRE(inode.is_symbolic_link()); + } + + THEN("the inode is initialized with zero mode in data and has no specific kind") + { + data.mode = 0; + auto inode = kernel::filesystem::ext2::inode(&fs, data); + + REQUIRE(!inode.is_regular()); + REQUIRE(!inode.is_directory()); + REQUIRE(!inode.is_device()); + REQUIRE(!inode.is_symbolic_link()); } } diff --git a/kernel/src/filesystem/inode.cpp b/kernel/src/filesystem/inode.cpp index f2a7741..c188917 100644 --- a/kernel/src/filesystem/inode.cpp +++ b/kernel/src/filesystem/inode.cpp @@ -16,4 +16,9 @@ namespace kernel::filesystem { return false; } + + auto inode::is_symbolic_link() const -> bool + { + return false; + } } // namespace kernel::filesystem \ No newline at end of file -- cgit v1.2.3 From 8550b6a1aacc2bfce733dcac7a44065b7e9116a1 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 2 May 2026 14:14:24 +0200 Subject: relative path support --- kernel/src/filesystem/mount_table.cpp | 4 +- kernel/src/filesystem/vfs.cpp | 115 +++++++++++++++++++++++++++++----- 2 files changed, 102 insertions(+), 17 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index da3c451..e21e497 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -54,7 +54,7 @@ namespace kernel::filesystem m_mounts.push_back(mount); if (auto mount_dentry = mount->get_mount_dentry()) { - mount_dentry->set_flag(dentry::dentry_flags::dcache_mounted); + mount_dentry->set_flag(dentry::dentry_flags::mounted); } } @@ -75,7 +75,7 @@ namespace kernel::filesystem return operation_result::has_child_mounts; } - mount->get_mount_dentry()->unset_flag(dentry::dentry_flags::dcache_mounted); + mount->get_mount_dentry()->unset_flag(dentry::dentry_flags::mounted); m_mounts.erase(std::ranges::find(m_mounts, mount)); return operation_result::removed; } diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 5b454f6..41afad3 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -10,6 +10,8 @@ #include #include +#include +#include #include #include @@ -35,21 +37,38 @@ namespace kernel::filesystem auto vfs::init_internal() -> void { + // Mount rootfs at / as the temporary base auto root_fs = kstd::make_shared(); root_fs->mount(nullptr); - auto root_fs_root_dentry = kstd::make_shared(nullptr, root_fs->root_inode()); - m_mount_table.add_mount(kstd::make_shared(nullptr, root_fs_root_dentry, root_fs, "", nullptr)); + auto root_fs_root_dentry = kstd::make_shared(nullptr, root_fs->root_inode(), "/"); + m_mount_table.add_mount(kstd::make_shared(nullptr, root_fs_root_dentry, root_fs, "/", nullptr)); + // Mount devfs at /dev in rootfs (temporary, will be shadowed) auto device_fs = kstd::make_shared(); device_fs->mount(nullptr); - do_mount_internal("/dev", root_fs_root_dentry, device_fs); + auto dev_mount_point_dentry = resolve_path("/dev"); + if (!dev_mount_point_dentry) + { + kapi::system::panic("[FILESYSTEM] failed to resolve /dev for initial devfs mount."); + } + do_mount_internal("/dev", dev_mount_point_dentry, device_fs); - if (auto boot_device_dentry = resolve_path("/dev/ram0")) // TODO BA-FS26 better boot device detection + // Mount boot filesystem at / (will shadow rootfs) + if (auto boot_device_dentry = resolve_path("/dev/ram0")) { if (auto boot_root_fs = kernel::filesystem::filesystem::probe_and_mount(boot_device_dentry->get_inode())) { do_mount_internal("/", root_fs_root_dentry, boot_root_fs); + + // Resolve / to get the boot root dentry + if (auto boot_root_dentry = resolve_path("/")) + { + auto dev_dentry = kstd::make_shared(boot_root_dentry, device_fs->root_inode(), "dev"); + boot_root_dentry->add_child(dev_dentry); + + do_mount_internal("/dev", dev_dentry, device_fs); + } } } } @@ -117,33 +136,46 @@ namespace kernel::filesystem kstd::shared_ptr const & fs) -> void { auto parent_mount = m_mount_table.find_longest_prefix_mount(path); - auto new_fs_root = kstd::make_shared(mount_point_dentry, fs->root_inode()); + auto new_fs_root = + kstd::make_shared(mount_point_dentry->get_parent(), fs->root_inode(), mount_point_dentry->get_name()); auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, path, parent_mount); m_mount_table.add_mount(new_mount); } auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr { - // TODO BA-FS26 implement full path resolution semantics. // TODO BA-FS26 better path validation // TODO BA-FS26 implement a path parser (maybe in libs?) and use it here and in do_mount - if (path.empty() || path.front() != '/') return nullptr; - // TODO BA-FS26 longest match in mount_table -> jump into final fs directly - // TODO BA-FS26 performance optimization first check mounted_flag O(1) then check mount_table O(n) - - auto best_mount = m_mount_table.find_longest_prefix_mount(path); - if (!best_mount) + auto current_mount = m_mount_table.find_longest_prefix_mount("/"); + if (!current_mount) { kapi::system::panic("[FILESYSTEM] no root mount found."); } - auto current_dentry = best_mount->root_dentry(); - auto current_fs = best_mount->get_filesystem(); + auto current_dentry = current_mount->root_dentry(); + kstd::vector resolved_parts{}; + + // TODO BA-FS26 remove again an get path out of the dentires instead of building it up again here + auto build_resolved_path = [&resolved_parts]() { + kstd::string resolved_path{"/"}; + + for (auto const & resolved_part : resolved_parts) + { + if (resolved_path.size() > 1) + { + resolved_path += '/'; + } + + resolved_path += resolved_part; + } - std::string_view remaining = path.substr(best_mount->get_mount_path().size()); + return resolved_path; + }; + + std::string_view remaining = path.substr(current_mount->get_mount_path().size()); auto path_parts = std::views::split(remaining, '/') | std::views::filter([](auto const & part) { return !part.empty(); }); @@ -152,9 +184,50 @@ namespace kernel::filesystem { std::string_view part_view{part}; + if (part_view == ".") + { + continue; + } + + if (part_view == "..") + { + if (!resolved_parts.empty()) + { + resolved_parts.pop_back(); + } + + auto parent_dentry = current_dentry->get_parent(); + + if (current_dentry == current_mount->root_dentry()) + { + // change the mount point + if (auto parent_mount = current_mount->get_parent_mount()) + { + current_mount = parent_mount; + current_dentry = current_dentry->get_parent(); + + if (!parent_dentry) + { + parent_dentry = current_mount->root_dentry(); + } + } + } + + if (!parent_dentry) + { + return nullptr; + } + + current_dentry = parent_dentry; + continue; + } + + resolved_parts.push_back(part_view); + auto next_dentry = current_dentry->find_child(part_view); if (!next_dentry) { + auto current_fs = current_mount->get_filesystem(); auto found_inode = current_fs->lookup(current_dentry->get_inode(), part_view); if (!found_inode) return nullptr; @@ -162,6 +235,18 @@ namespace kernel::filesystem next_dentry = kstd::make_shared(current_dentry, found_inode, part_view); current_dentry->add_child(next_dentry); } + else if (next_dentry->has_flag(dentry::dentry_flags::mounted)) + { + // change the mount point + // TODO BA-FS26 get resolved path out of the dentry... + current_mount = m_mount_table.find_longest_prefix_mount(build_resolved_path().view()); + if (!current_mount) + { + kapi::system::panic("[FILESYSTEM] mount for dentry with mounted flag not found."); + } + + next_dentry = current_mount->root_dentry(); + } current_dentry = next_dentry; } -- cgit v1.2.3 From a096d84920aa078b5775149a95e5d3f010ae995e Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 2 May 2026 14:14:55 +0200 Subject: fix bht build --- kernel/src/filesystem/dentry.tests.cpp | 16 ++++++++-------- kernel/src/filesystem/mount_table.tests.cpp | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.tests.cpp b/kernel/src/filesystem/dentry.tests.cpp index f81c260..c42c405 100644 --- a/kernel/src/filesystem/dentry.tests.cpp +++ b/kernel/src/filesystem/dentry.tests.cpp @@ -28,7 +28,7 @@ SCENARIO("Dentry construction", "[filesystem][dentry]") THEN("no flag is set") { - REQUIRE_FALSE(child_dentry.has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + REQUIRE_FALSE(child_dentry.has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); } } @@ -45,7 +45,7 @@ SCENARIO("Dentry construction", "[filesystem][dentry]") THEN("no flag is set") { - REQUIRE_FALSE(child_dentry.has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + REQUIRE_FALSE(child_dentry.has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); } } @@ -62,7 +62,7 @@ SCENARIO("Dentry construction", "[filesystem][dentry]") THEN("no flag is set") { - REQUIRE_FALSE(child_dentry.has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + REQUIRE_FALSE(child_dentry.has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); } } @@ -113,22 +113,22 @@ SCENARIO("Dentry Flag logic", "[filesystem][dentry]") WHEN("setting a flag") { - dentry.set_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted); + dentry.set_flag(kernel::filesystem::dentry::dentry_flags::mounted); THEN("the flag is set") { - REQUIRE(dentry.has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + REQUIRE(dentry.has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); } } WHEN("unsetting a flag") { - dentry.set_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted); - dentry.unset_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted); + dentry.set_flag(kernel::filesystem::dentry::dentry_flags::mounted); + dentry.unset_flag(kernel::filesystem::dentry::dentry_flags::mounted); THEN("the flag is unset") { - REQUIRE_FALSE(dentry.has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + REQUIRE_FALSE(dentry.has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); } } } diff --git a/kernel/src/filesystem/mount_table.tests.cpp b/kernel/src/filesystem/mount_table.tests.cpp index 747ffdf..60b1755 100644 --- a/kernel/src/filesystem/mount_table.tests.cpp +++ b/kernel/src/filesystem/mount_table.tests.cpp @@ -54,8 +54,8 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("dentry flags are set correctly for mounted dentries") { - REQUIRE(root_dentry1->has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); - REQUIRE(!root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + REQUIRE(root_dentry1->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE(!root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); } THEN("finding mounts by path returns the correct mount") @@ -70,7 +70,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("removing a mount that has no child mounts succeeds") { REQUIRE(table.remove_mount("/mnt") == kernel::filesystem::mount_table::operation_result::removed); - REQUIRE(!root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + REQUIRE(!root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); REQUIRE(table.find_longest_prefix_mount("/mnt") == mount1); } @@ -109,7 +109,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("removing the topmost mount with the same path succeeds") { REQUIRE(table.remove_mount("/") == kernel::filesystem::mount_table::operation_result::removed); - REQUIRE(!root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + REQUIRE(!root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); REQUIRE(table.find_longest_prefix_mount("/") == mount1); } } @@ -156,7 +156,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("removing a leaf mount succeeds") { REQUIRE(table.remove_mount("/mnt/submnt") == kernel::filesystem::mount_table::operation_result::removed); - REQUIRE(!root_dentry3->has_flag(kernel::filesystem::dentry::dentry_flags::dcache_mounted)); + REQUIRE(!root_dentry3->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); REQUIRE(table.find_longest_prefix_mount("/mnt/submnt") == mount2); } } -- cgit v1.2.3 From 46f3992c10e960d33dbb314dad597650902686da Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 2 May 2026 14:15:26 +0200 Subject: add relative path tests --- kernel/src/filesystem/vfs.tests.cpp | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 979ea42..109ee89 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -168,6 +168,52 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(vfs.unmount("/information/nonexistent") == kernel::filesystem::vfs::operation_result::mount_point_not_found); } + + THEN("a file can be access if . in the path") + { + auto info_1 = vfs.open("/information/./info_1.txt"); + REQUIRE(info_1 != nullptr); + } + + THEN("a file can be accessed within the same mount if path contains .. ") + { + auto info_1 = vfs.open("/archiv/../information/info_1.txt"); + REQUIRE(info_1 != nullptr); + + auto img = vfs.open("/archiv/../information/../archiv/2024.img"); + REQUIRE(img != nullptr); + } + + THEN("a file can be accessed over multiple mounts if path contains .. or . ") + { + REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); + + auto img = vfs.open("/information/monkey_house/caretaker/../../../archiv/2024.img"); + REQUIRE(img != nullptr); + + auto dev_32 = vfs.open("/information/monkey_house/caretaker/../../../dev/ram32"); + REQUIRE(dev_32 != nullptr); + + auto water = vfs.open("/information/./monkey_house/infrastructure/water.txt"); + REQUIRE(water != nullptr); + } + + THEN("a file can be accessed over multiple mounts (device and file) if path contains .. ") + { + REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/archiv/2024.img", "/information/monkey_house/infrastructure") == + kernel::filesystem::vfs::operation_result::success); + + auto pig_1 = vfs.open("/information/monkey_house/infrastructure/stable/pig_1.txt"); + REQUIRE(pig_1 != nullptr); + + auto isabelle = + vfs.open("/information/monkey_house/infrastructure/stable/../../../monkey_house/caretaker/isabelle.txt"); + REQUIRE(isabelle != nullptr); + + auto closed = vfs.open("/information/monkey_house/infrastructure/stable/../../../../closed.txt"); + REQUIRE(closed != nullptr); + } } GIVEN("A real image file containing as filesystem formatted files") -- cgit v1.2.3 From d3c8b74020bfeee554394b7e41c58d5ddda6f396 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 2 May 2026 14:23:19 +0200 Subject: refactoring --- kernel/src/filesystem/dentry.cpp | 17 +++++++++++++++++ kernel/src/filesystem/vfs.cpp | 32 ++------------------------------ 2 files changed, 19 insertions(+), 30 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index 572dd82..72500fd 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -38,6 +39,22 @@ namespace kernel::filesystem return m_name.view(); } + // TODO BA-FS26 fix warning (do not use recursion) + auto dentry::get_full_path() const -> kstd::string + { + if (m_parent) + { + auto parent_path = m_parent->get_full_path(); + if (parent_path != "/") + { + parent_path += '/'; + } + return parent_path + m_name.view(); + } + + return m_name.empty() ? "/" : m_name.view(); + } + auto dentry::add_child(kstd::shared_ptr const & child) -> void { m_children.push_back(child); diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 41afad3..9a6625d 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -11,7 +11,6 @@ #include #include -#include #include #include @@ -156,25 +155,6 @@ namespace kernel::filesystem } auto current_dentry = current_mount->root_dentry(); - kstd::vector resolved_parts{}; - - // TODO BA-FS26 remove again an get path out of the dentires instead of building it up again here - auto build_resolved_path = [&resolved_parts]() { - kstd::string resolved_path{"/"}; - - for (auto const & resolved_part : resolved_parts) - { - if (resolved_path.size() > 1) - { - resolved_path += '/'; - } - - resolved_path += resolved_part; - } - - return resolved_path; - }; - std::string_view remaining = path.substr(current_mount->get_mount_path().size()); auto path_parts = @@ -191,11 +171,6 @@ namespace kernel::filesystem if (part_view == "..") { - if (!resolved_parts.empty()) - { - resolved_parts.pop_back(); - } - auto parent_dentry = current_dentry->get_parent(); if (current_dentry == current_mount->root_dentry()) @@ -222,8 +197,6 @@ namespace kernel::filesystem continue; } - resolved_parts.push_back(part_view); - auto next_dentry = current_dentry->find_child(part_view); if (!next_dentry) { @@ -237,9 +210,8 @@ namespace kernel::filesystem } else if (next_dentry->has_flag(dentry::dentry_flags::mounted)) { - // change the mount point - // TODO BA-FS26 get resolved path out of the dentry... - current_mount = m_mount_table.find_longest_prefix_mount(build_resolved_path().view()); + // TODO BA-FS26 really do it like this? or just call "get" without longes_prefix stuff + current_mount = m_mount_table.find_longest_prefix_mount(next_dentry->get_full_path().view()); if (!current_mount) { kapi::system::panic("[FILESYSTEM] mount for dentry with mounted flag not found."); -- cgit v1.2.3 From e74e56559ae99fd14715371ebceb2545f68008de Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 2 May 2026 14:24:46 +0200 Subject: add todos --- kernel/src/filesystem/vfs.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 9a6625d..a3da258 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -89,6 +89,7 @@ namespace kernel::filesystem auto vfs::do_mount(std::string_view source, std::string_view target) -> operation_result { + // TODO BA-FS26 better path validation if (target.empty() || target.front() != '/' || (target.size() > 1 && target.back() == '/')) { return operation_result::invalid_path; @@ -112,6 +113,7 @@ namespace kernel::filesystem auto vfs::unmount(std::string_view path) -> operation_result { + // TODO BA-FS26 better path validation if (path.empty() || path.front() != '/' || (path.size() > 1 && path.back() == '/')) { return operation_result::invalid_path; -- cgit v1.2.3 From 40fbefab704695b905e3de3e80668447cc64b20e Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 2 May 2026 15:36:19 +0200 Subject: refactoring and extend tests --- kernel/src/filesystem/devfs/filesystem.tests.cpp | 2 +- kernel/src/filesystem/devfs/inode.tests.cpp | 1 + kernel/src/filesystem/device_inode.tests.cpp | 1 + kernel/src/filesystem/ext2/inode.tests.cpp | 26 ++++++++++++------------ kernel/src/filesystem/mount_table.tests.cpp | 8 ++++---- kernel/src/filesystem/rootfs/inode.tests.cpp | 1 + 6 files changed, 21 insertions(+), 18 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/devfs/filesystem.tests.cpp b/kernel/src/filesystem/devfs/filesystem.tests.cpp index 2b6c09b..36cb411 100644 --- a/kernel/src/filesystem/devfs/filesystem.tests.cpp +++ b/kernel/src/filesystem/devfs/filesystem.tests.cpp @@ -47,7 +47,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, { auto non_directory_inode = fs.lookup(fs.root_inode(), "ram0"); REQUIRE(non_directory_inode != nullptr); - REQUIRE(!non_directory_inode->is_directory()); + REQUIRE_FALSE(non_directory_inode->is_directory()); auto result = fs.lookup(non_directory_inode, "anything"); REQUIRE(result == nullptr); diff --git a/kernel/src/filesystem/devfs/inode.tests.cpp b/kernel/src/filesystem/devfs/inode.tests.cpp index 030d709..ae26e74 100644 --- a/kernel/src/filesystem/devfs/inode.tests.cpp +++ b/kernel/src/filesystem/devfs/inode.tests.cpp @@ -19,6 +19,7 @@ SCENARIO("Devfs inode creation", "[filesystem][devfs][inode]") REQUIRE(inode.is_directory()); REQUIRE_FALSE(inode.is_device()); REQUIRE_FALSE(inode.is_regular()); + REQUIRE_FALSE(inode.is_symbolic_link()); } } } diff --git a/kernel/src/filesystem/device_inode.tests.cpp b/kernel/src/filesystem/device_inode.tests.cpp index 8ac4eff..025a22a 100644 --- a/kernel/src/filesystem/device_inode.tests.cpp +++ b/kernel/src/filesystem/device_inode.tests.cpp @@ -33,6 +33,7 @@ SCENARIO("Device inode construction", "[filesystem][device_inode]") REQUIRE(inode.is_device()); REQUIRE_FALSE(inode.is_directory()); REQUIRE_FALSE(inode.is_regular()); + REQUIRE_FALSE(inode.is_symbolic_link()); } } diff --git a/kernel/src/filesystem/ext2/inode.tests.cpp b/kernel/src/filesystem/ext2/inode.tests.cpp index f0f4aaf..49ba21b 100644 --- a/kernel/src/filesystem/ext2/inode.tests.cpp +++ b/kernel/src/filesystem/ext2/inode.tests.cpp @@ -31,9 +31,9 @@ SCENARIO("Ext2 inode initialization and properties", "[filesystem][ext2][inode]" auto inode = kernel::filesystem::ext2::inode(&fs, data); REQUIRE(inode.is_regular()); - REQUIRE(!inode.is_directory()); - REQUIRE(!inode.is_device()); - REQUIRE(!inode.is_symbolic_link()); + REQUIRE_FALSE(inode.is_directory()); + REQUIRE_FALSE(inode.is_device()); + REQUIRE_FALSE(inode.is_symbolic_link()); } THEN("the inode is initialized with directory mode in data and has the kind directory") @@ -41,10 +41,10 @@ SCENARIO("Ext2 inode initialization and properties", "[filesystem][ext2][inode]" data.mode = kernel::filesystem::ext2::constants::mode_directory; auto inode = kernel::filesystem::ext2::inode(&fs, data); - REQUIRE(!inode.is_regular()); + REQUIRE_FALSE(inode.is_regular()); REQUIRE(inode.is_directory()); - REQUIRE(!inode.is_device()); - REQUIRE(!inode.is_symbolic_link()); + REQUIRE_FALSE(inode.is_device()); + REQUIRE_FALSE(inode.is_symbolic_link()); } THEN("the inode is initialized with symbolic link mode in data and has the kind symbolic link") @@ -52,9 +52,9 @@ SCENARIO("Ext2 inode initialization and properties", "[filesystem][ext2][inode]" data.mode = kernel::filesystem::ext2::constants::mode_symbolic_link; auto inode = kernel::filesystem::ext2::inode(&fs, data); - REQUIRE(!inode.is_regular()); - REQUIRE(!inode.is_directory()); - REQUIRE(!inode.is_device()); + REQUIRE_FALSE(inode.is_regular()); + REQUIRE_FALSE(inode.is_directory()); + REQUIRE_FALSE(inode.is_device()); REQUIRE(inode.is_symbolic_link()); } @@ -63,10 +63,10 @@ SCENARIO("Ext2 inode initialization and properties", "[filesystem][ext2][inode]" data.mode = 0; auto inode = kernel::filesystem::ext2::inode(&fs, data); - REQUIRE(!inode.is_regular()); - REQUIRE(!inode.is_directory()); - REQUIRE(!inode.is_device()); - REQUIRE(!inode.is_symbolic_link()); + REQUIRE_FALSE(inode.is_regular()); + REQUIRE_FALSE(inode.is_directory()); + REQUIRE_FALSE(inode.is_device()); + REQUIRE_FALSE(inode.is_symbolic_link()); } } diff --git a/kernel/src/filesystem/mount_table.tests.cpp b/kernel/src/filesystem/mount_table.tests.cpp index 60b1755..e028ac8 100644 --- a/kernel/src/filesystem/mount_table.tests.cpp +++ b/kernel/src/filesystem/mount_table.tests.cpp @@ -55,7 +55,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("dentry flags are set correctly for mounted dentries") { REQUIRE(root_dentry1->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); - REQUIRE(!root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE_FALSE(root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); } THEN("finding mounts by path returns the correct mount") @@ -70,7 +70,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("removing a mount that has no child mounts succeeds") { REQUIRE(table.remove_mount("/mnt") == kernel::filesystem::mount_table::operation_result::removed); - REQUIRE(!root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE_FALSE(root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); REQUIRE(table.find_longest_prefix_mount("/mnt") == mount1); } @@ -109,7 +109,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("removing the topmost mount with the same path succeeds") { REQUIRE(table.remove_mount("/") == kernel::filesystem::mount_table::operation_result::removed); - REQUIRE(!root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE_FALSE(root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); REQUIRE(table.find_longest_prefix_mount("/") == mount1); } } @@ -156,7 +156,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("removing a leaf mount succeeds") { REQUIRE(table.remove_mount("/mnt/submnt") == kernel::filesystem::mount_table::operation_result::removed); - REQUIRE(!root_dentry3->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE_FALSE(root_dentry3->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); REQUIRE(table.find_longest_prefix_mount("/mnt/submnt") == mount2); } } diff --git a/kernel/src/filesystem/rootfs/inode.tests.cpp b/kernel/src/filesystem/rootfs/inode.tests.cpp index 879818c..7cc217f 100644 --- a/kernel/src/filesystem/rootfs/inode.tests.cpp +++ b/kernel/src/filesystem/rootfs/inode.tests.cpp @@ -17,6 +17,7 @@ SCENARIO("Rootfs inode creation", "[filesystem][rootfs][inode]") REQUIRE(inode.is_directory()); REQUIRE_FALSE(inode.is_device()); REQUIRE_FALSE(inode.is_regular()); + REQUIRE_FALSE(inode.is_symbolic_link()); } THEN("the inode has no children") -- cgit v1.2.3 From 1269410c4c733ed38859b3e70713728afb273443 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Sun, 3 May 2026 15:01:49 +0200 Subject: Use iterator in path resolution, start with symlink implementation --- kernel/src/filesystem/vfs.cpp | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index a3da258..ba4f404 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -94,7 +94,7 @@ namespace kernel::filesystem { return operation_result::invalid_path; } - + // TODO BA-FS26 check if target is directory? if (auto mount_point_dentry = resolve_path(target)) { if (auto source_dentry = resolve_path(source)) @@ -162,9 +162,9 @@ namespace kernel::filesystem auto path_parts = std::views::split(remaining, '/') | std::views::filter([](auto const & part) { return !part.empty(); }); - for (auto const & part : path_parts) + for (auto it = path_parts.begin(); it != path_parts.end(); ++it) { - std::string_view part_view{part}; + std::string_view part_view{*it}; if (part_view == ".") { @@ -205,7 +205,9 @@ namespace kernel::filesystem auto current_fs = current_mount->get_filesystem(); auto found_inode = current_fs->lookup(current_dentry->get_inode(), part_view); if (!found_inode) + { return nullptr; + } next_dentry = kstd::make_shared(current_dentry, found_inode, part_view); current_dentry->add_child(next_dentry); @@ -222,6 +224,38 @@ namespace kernel::filesystem next_dentry = current_mount->root_dentry(); } + if (next_dentry->get_inode()->is_symbolic_link()) + { + // TODO BA-FS26 this for loop is ugly --> fix + kstd::string symlink_path = "halo"; + if (symlink_path.size() > 0 && symlink_path.front() == '/') + { + for (auto it2 = std::next(it); it2 != path_parts.end(); ++it2) + { + symlink_path += "/"; + symlink_path.append(std::string_view{*it2}); + } + return resolve_path(symlink_path.view()); + } + else + { + kstd::string combined; + for (auto it3 = path_parts.begin(); it3 != it; ++it3) + { + combined += "/"; + combined.append(std::string_view{*it3}); + } + combined += "/"; + combined += symlink_path; + for (auto it4 = std::next(it); it4 != path_parts.end(); ++it4) + { + combined += "/"; + combined.append(std::string_view{*it4}); + } + return resolve_path(combined.view()); + } + } + current_dentry = next_dentry; } -- cgit v1.2.3 From 7ff97f0fe861bb7382f41ecd4bab26cbb62b1f7d Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 4 May 2026 19:47:57 +0200 Subject: Resolve TODOs concerning path validation --- kernel/src/filesystem/vfs.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index ba4f404..8f48820 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -89,12 +90,11 @@ namespace kernel::filesystem auto vfs::do_mount(std::string_view source, std::string_view target) -> operation_result { - // TODO BA-FS26 better path validation - if (target.empty() || target.front() != '/' || (target.size() > 1 && target.back() == '/')) + if (!kernel::filesystem::path::is_valid_path(source) || !kernel::filesystem::path::is_valid_path(target)) { return operation_result::invalid_path; } - // TODO BA-FS26 check if target is directory? + if (auto mount_point_dentry = resolve_path(target)) { if (auto source_dentry = resolve_path(source)) @@ -113,8 +113,7 @@ namespace kernel::filesystem auto vfs::unmount(std::string_view path) -> operation_result { - // TODO BA-FS26 better path validation - if (path.empty() || path.front() != '/' || (path.size() > 1 && path.back() == '/')) + if (!kernel::filesystem::path::is_valid_path(path)) { return operation_result::invalid_path; } @@ -145,11 +144,12 @@ namespace kernel::filesystem auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr { - // TODO BA-FS26 better path validation - // TODO BA-FS26 implement a path parser (maybe in libs?) and use it here and in do_mount - if (path.empty() || path.front() != '/') + if (!kernel::filesystem::path::is_valid_absolute_path(path)) + { return nullptr; + } + // TODO BA-FS26 refactor (get mount by path, no more prefix matching) auto current_mount = m_mount_table.find_longest_prefix_mount("/"); if (!current_mount) { @@ -157,10 +157,8 @@ namespace kernel::filesystem } auto current_dentry = current_mount->root_dentry(); - std::string_view remaining = path.substr(current_mount->get_mount_path().size()); - auto path_parts = - std::views::split(remaining, '/') | std::views::filter([](auto const & part) { return !part.empty(); }); + auto path_parts = kernel::filesystem::path::split(path); for (auto it = path_parts.begin(); it != path_parts.end(); ++it) { -- cgit v1.2.3 From d90d6bb4b4820df6cb4b0747439293bb85b8cbec Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 4 May 2026 20:17:43 +0200 Subject: Implement symlink read in inode, fix max amount of bytes to read --- kernel/src/filesystem/ext2/inode.cpp | 16 +++++++++++++++- kernel/src/filesystem/open_file_descriptor.tests.cpp | 13 ++++--------- 2 files changed, 19 insertions(+), 10 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp index 5b6bcb3..1914c70 100644 --- a/kernel/src/filesystem/ext2/inode.cpp +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -5,6 +5,8 @@ #include +#include + #include #include #include @@ -23,6 +25,17 @@ namespace kernel::filesystem::ext2 auto inode::read(void * buffer, size_t offset, size_t size) const -> size_t { + // TODO BA-FS26 use revision 1 size + auto const max_readable = static_cast(m_data.size) - offset; + auto const requested_size = std::min(size, max_readable); + + if (is_symbolic_link() && m_data.size <= sizeof(m_data.block)) + { + auto inline_target = reinterpret_cast(m_data.block.data()); + kstd::libc::memcpy(static_cast(buffer), inline_target + offset, requested_size); + return requested_size; + } + auto block_index = offset / m_filesystem->get_block_size(); auto in_block_offset = offset % m_filesystem->get_block_size(); @@ -40,7 +53,8 @@ namespace kernel::filesystem::ext2 auto const block_start_offset = block_number * m_filesystem->get_block_size(); auto const read_offset = block_start_offset + in_block_offset; - auto const bytes_to_read = std::min(size - bytes_read, m_filesystem->get_block_size() - in_block_offset); + auto const bytes_to_read = + std::min(requested_size - bytes_read, m_filesystem->get_block_size() - in_block_offset); bytes_read += m_filesystem->backing_inode()->read(static_cast(buffer) + bytes_read, read_offset, bytes_to_read); diff --git a/kernel/src/filesystem/open_file_descriptor.tests.cpp b/kernel/src/filesystem/open_file_descriptor.tests.cpp index 095e203..53835ba 100644 --- a/kernel/src/filesystem/open_file_descriptor.tests.cpp +++ b/kernel/src/filesystem/open_file_descriptor.tests.cpp @@ -1,4 +1,5 @@ #include + #include #include #include @@ -83,17 +84,11 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Ope { kstd::vector buffer(32); auto bytes_read = ofd->read(buffer.data(), buffer.size()); - REQUIRE(bytes_read == 32); - REQUIRE(ofd->offset() == 32); + REQUIRE(bytes_read == 7); + REQUIRE(ofd->offset() == 7); std::string_view buffer_as_str{reinterpret_cast(buffer.data()), static_cast(bytes_read)}; - auto const content_end = buffer_as_str.find('\0'); - REQUIRE(buffer_as_str.substr(0, content_end) == "info_1\n"); - - for (auto i = content_end; i < buffer_as_str.size(); ++i) - { - REQUIRE(buffer_as_str[i] == '\0'); - } + REQUIRE(buffer_as_str == "info_1\n"); } THEN("the file can be read multiple times") -- cgit v1.2.3 From d1e64340abb960c579651635d580660c12f94e6e Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 4 May 2026 20:31:58 +0200 Subject: Refactor path resolution, use vector and while instead of iterator and for-loop --- kernel/src/filesystem/vfs.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 8f48820..c9939fa 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -12,7 +12,9 @@ #include #include +#include +#include #include #include #include @@ -159,10 +161,13 @@ namespace kernel::filesystem auto current_dentry = current_mount->root_dentry(); auto path_parts = kernel::filesystem::path::split(path); + kstd::vector path_parts_vector(path_parts.begin(), path_parts.end()); + std::ranges::reverse(path_parts_vector); - for (auto it = path_parts.begin(); it != path_parts.end(); ++it) + while (!path_parts_vector.empty()) { - std::string_view part_view{*it}; + std::string_view part_view{path_parts_vector.back()}; + path_parts_vector.pop_back(); if (part_view == ".") { -- cgit v1.2.3 From bddee0f0cb77eb247eceea18005dc575b433bb69 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 4 May 2026 20:51:49 +0200 Subject: Implement symlink non-recursive --- kernel/src/filesystem/vfs.cpp | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index c9939fa..06d36ce 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -229,33 +230,21 @@ namespace kernel::filesystem if (next_dentry->get_inode()->is_symbolic_link()) { - // TODO BA-FS26 this for loop is ugly --> fix - kstd::string symlink_path = "halo"; - if (symlink_path.size() > 0 && symlink_path.front() == '/') - { - for (auto it2 = std::next(it); it2 != path_parts.end(); ++it2) - { - symlink_path += "/"; - symlink_path.append(std::string_view{*it2}); - } - return resolve_path(symlink_path.view()); - } - else + // TODO BA-FS26 max symbolic link depth to prevent infinite loops + kstd::vector buffer(4096); // TODO BA-FS26 max symlink size? + auto const bytes_read = next_dentry->get_inode()->read(buffer.data(), 0, buffer.size()); + auto const symbolic_link_path = std::string_view{reinterpret_cast(buffer.data()), bytes_read}; + + auto symbolic_link_parts = kernel::filesystem::path::split(symbolic_link_path); + kstd::vector symbolic_link_parts_vector(symbolic_link_parts.begin(), symbolic_link_parts.end()); + std::ranges::reverse(symbolic_link_parts_vector); + + path_parts_vector.insert_range(path_parts_vector.end(), symbolic_link_parts_vector); + + if (kernel::filesystem::path::is_valid_absolute_path(symbolic_link_path)) { - kstd::string combined; - for (auto it3 = path_parts.begin(); it3 != it; ++it3) - { - combined += "/"; - combined.append(std::string_view{*it3}); - } - combined += "/"; - combined += symlink_path; - for (auto it4 = std::next(it); it4 != path_parts.end(); ++it4) - { - combined += "/"; - combined.append(std::string_view{*it4}); - } - return resolve_path(combined.view()); + current_mount = m_mount_table.find_longest_prefix_mount("/"); + next_dentry = current_mount->root_dentry(); } } -- cgit v1.2.3 From 9aaabb2cf73f20cc4d4c68588e7bf4592837626f Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 4 May 2026 23:25:16 +0200 Subject: Add simple symlink tests --- kernel/src/filesystem/vfs.tests.cpp | 20 ++++++++++++++++++++ .../filesystem/test_assets/ext2_1KB_fs.img | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 109ee89..829c9d2 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -283,4 +283,24 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(unmounted_sheep_1 == nullptr); } } + + GIVEN("one real image files, containing symbolic links") + { + REQUIRE(std::filesystem::exists(image_path_1)); + REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module_1"}, {image_path_1})); + + THEN("file can be opened through absolute symbolic link") + { + auto & vfs = kernel::filesystem::vfs::get(); + auto info_1 = vfs.open("/symlinks/info_1_absolute"); + REQUIRE(info_1 != nullptr); + } + + THEN("file can be opened through relative symbolic link") + { + auto & vfs = kernel::filesystem::vfs::get(); + auto info_1 = vfs.open("/symlinks/info_1_relative"); + REQUIRE(info_1 != nullptr); + } + } } diff --git a/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img b/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img index 5bbb76d..0312727 100644 --- a/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img +++ b/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c2ef9536a439825520d9e230eedaa9ae327f9763350eddbc0f24bf5b9b5d2bf2 +oid sha256:7cf40c3cf3d8e3be614cadf2da1c76138c492734c3730eadbca645f50ed99a50 size 10485760 -- cgit v1.2.3 From 2ab9d6ffbc4aad8ab3a393bd32191e3c07103c0a Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 5 May 2026 14:37:47 +0200 Subject: fix problem with string_view lifetime --- kernel/src/filesystem/vfs.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 06d36ce..03921df 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -167,15 +167,15 @@ namespace kernel::filesystem while (!path_parts_vector.empty()) { - std::string_view part_view{path_parts_vector.back()}; + auto part = path_parts_vector.back(); path_parts_vector.pop_back(); - if (part_view == ".") + if (part == ".") { continue; } - if (part_view == "..") + if (part == "..") { auto parent_dentry = current_dentry->get_parent(); @@ -203,17 +203,17 @@ namespace kernel::filesystem continue; } - auto next_dentry = current_dentry->find_child(part_view); + auto next_dentry = current_dentry->find_child(part.view()); if (!next_dentry) { auto current_fs = current_mount->get_filesystem(); - auto found_inode = current_fs->lookup(current_dentry->get_inode(), part_view); + auto found_inode = current_fs->lookup(current_dentry->get_inode(), part.view()); if (!found_inode) { return nullptr; } - next_dentry = kstd::make_shared(current_dentry, found_inode, part_view); + next_dentry = kstd::make_shared(current_dentry, found_inode, part.view()); current_dentry->add_child(next_dentry); } else if (next_dentry->has_flag(dentry::dentry_flags::mounted)) @@ -244,8 +244,9 @@ namespace kernel::filesystem if (kernel::filesystem::path::is_valid_absolute_path(symbolic_link_path)) { current_mount = m_mount_table.find_longest_prefix_mount("/"); - next_dentry = current_mount->root_dentry(); + current_dentry = current_mount->root_dentry(); } + continue; } current_dentry = next_dentry; -- cgit v1.2.3 From 88ebc124ed0e703e02dfe96006d0d490e83de4fe Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Tue, 5 May 2026 14:46:21 +0200 Subject: Fix vfs tests --- kernel/src/filesystem/vfs.tests.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 829c9d2..cbd67be 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -140,8 +140,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS THEN("mount with invalid path fails") { REQUIRE(vfs.do_mount("/dev/ram16", "") == kernel::filesystem::vfs::operation_result::invalid_path); - REQUIRE(vfs.do_mount("/dev/ram16", "information") == kernel::filesystem::vfs::operation_result::invalid_path); - REQUIRE(vfs.do_mount("/dev/ram16", "/information/") == kernel::filesystem::vfs::operation_result::invalid_path); + REQUIRE(vfs.do_mount("/dev/ram16", "information") == + kernel::filesystem::vfs::operation_result::mount_point_not_found); } THEN("mount with non-existent source path fails") @@ -159,8 +159,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS THEN("unmount with invalid path fails") { REQUIRE(vfs.unmount("") == kernel::filesystem::vfs::operation_result::invalid_path); - REQUIRE(vfs.unmount("information") == kernel::filesystem::vfs::operation_result::invalid_path); - REQUIRE(vfs.unmount("/information/") == kernel::filesystem::vfs::operation_result::invalid_path); + REQUIRE(vfs.unmount("information") == kernel::filesystem::vfs::operation_result::mount_point_not_found); } THEN("unmounting non-existent mount point returns expected error code") -- cgit v1.2.3 From b6cc02c3bac002ebac8e6ba734b00f0e60b24778 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Tue, 5 May 2026 16:05:48 +0200 Subject: Add check for max symlink count --- kernel/src/filesystem/vfs.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 03921df..e6d9241 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -93,7 +94,7 @@ namespace kernel::filesystem auto vfs::do_mount(std::string_view source, std::string_view target) -> operation_result { - if (!kernel::filesystem::path::is_valid_path(source) || !kernel::filesystem::path::is_valid_path(target)) + if (!path::is_valid_path(source) || !path::is_valid_path(target)) { return operation_result::invalid_path; } @@ -116,7 +117,7 @@ namespace kernel::filesystem auto vfs::unmount(std::string_view path) -> operation_result { - if (!kernel::filesystem::path::is_valid_path(path)) + if (!path::is_valid_path(path)) { return operation_result::invalid_path; } @@ -147,7 +148,7 @@ namespace kernel::filesystem auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr { - if (!kernel::filesystem::path::is_valid_absolute_path(path)) + if (!path::is_valid_absolute_path(path)) { return nullptr; } @@ -161,10 +162,12 @@ namespace kernel::filesystem auto current_dentry = current_mount->root_dentry(); - auto path_parts = kernel::filesystem::path::split(path); + auto path_parts = path::split(path); kstd::vector path_parts_vector(path_parts.begin(), path_parts.end()); std::ranges::reverse(path_parts_vector); + auto symlink_counter = 0uz; + while (!path_parts_vector.empty()) { auto part = path_parts_vector.back(); @@ -230,18 +233,22 @@ namespace kernel::filesystem if (next_dentry->get_inode()->is_symbolic_link()) { - // TODO BA-FS26 max symbolic link depth to prevent infinite loops - kstd::vector buffer(4096); // TODO BA-FS26 max symlink size? + if (symlink_counter++ > constants::symloop_max) + { + return nullptr; + } + + kstd::vector buffer(constants::symlink_max_path_length); auto const bytes_read = next_dentry->get_inode()->read(buffer.data(), 0, buffer.size()); auto const symbolic_link_path = std::string_view{reinterpret_cast(buffer.data()), bytes_read}; - auto symbolic_link_parts = kernel::filesystem::path::split(symbolic_link_path); + auto symbolic_link_parts = path::split(symbolic_link_path); kstd::vector symbolic_link_parts_vector(symbolic_link_parts.begin(), symbolic_link_parts.end()); std::ranges::reverse(symbolic_link_parts_vector); path_parts_vector.insert_range(path_parts_vector.end(), symbolic_link_parts_vector); - if (kernel::filesystem::path::is_valid_absolute_path(symbolic_link_path)) + if (path::is_valid_absolute_path(symbolic_link_path)) { current_mount = m_mount_table.find_longest_prefix_mount("/"); current_dentry = current_mount->root_dentry(); -- cgit v1.2.3 From 94232ac15ce987cf6792be0c4d5b0141d7cac0b1 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Tue, 5 May 2026 16:18:54 +0200 Subject: Add tests for path utility --- kernel/src/filesystem/path.tests.cpp | 69 ++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 kernel/src/filesystem/path.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/path.tests.cpp b/kernel/src/filesystem/path.tests.cpp new file mode 100644 index 0000000..3c18b5c --- /dev/null +++ b/kernel/src/filesystem/path.tests.cpp @@ -0,0 +1,69 @@ +#include + +#include + +#include +#include +#include +#include + +SCENARIO("path utilities", "[filesystem][path]") +{ + GIVEN("valid and invalid paths") + { + THEN("valid absolute paths are recognized as valid") + { + REQUIRE(kernel::filesystem::path::is_valid_path("/valid/absolute/path")); + REQUIRE(kernel::filesystem::path::is_valid_path("/")); + } + + THEN("valid relative paths are recognized as valid") + { + REQUIRE(kernel::filesystem::path::is_valid_path("valid/../relative/.././path")); + REQUIRE(kernel::filesystem::path::is_valid_path("valid/relative/path")); + REQUIRE(kernel::filesystem::path::is_valid_path("file.txt")); + } + + THEN("invalid paths are recognized as invalid") + { + REQUIRE_FALSE(kernel::filesystem::path::is_valid_path("")); + REQUIRE_FALSE(kernel::filesystem::path::is_valid_path(std::string(4096, 'a'))); + } + + THEN("valid absolute paths are recognized as absolute") + { + REQUIRE(kernel::filesystem::path::is_valid_absolute_path("/valid/absolute/path")); + REQUIRE_FALSE(kernel::filesystem::path::is_valid_absolute_path("valid/relative/path")); + } + + THEN("invalid paths are not recognized as absolute") + { + REQUIRE_FALSE(kernel::filesystem::path::is_valid_absolute_path("")); + REQUIRE_FALSE(kernel::filesystem::path::is_valid_absolute_path(std::string(4096, 'a'))); + REQUIRE_FALSE(kernel::filesystem::path::is_valid_absolute_path("invalid/absolute/path")); + } + + THEN("valid relative paths are recognized as relative") + { + REQUIRE(kernel::filesystem::path::is_valid_relative_path("valid/relative/path")); + REQUIRE_FALSE(kernel::filesystem::path::is_valid_relative_path("/valid/absolute/path")); + } + + THEN("invalid paths are not recognized as relative") + { + REQUIRE_FALSE(kernel::filesystem::path::is_valid_relative_path("")); + REQUIRE_FALSE(kernel::filesystem::path::is_valid_relative_path(std::string(4096, 'a'))); + REQUIRE_FALSE(kernel::filesystem::path::is_valid_relative_path("/invalid/absolute/path")); + } + } + + GIVEN("a valid path") + { + THEN("it can be split into components") + { + auto components = kernel::filesystem::path::split("/a/b///c/d.txt"); + std::vector expected = {"a", "b", "c", "d.txt"}; + REQUIRE(std::ranges::equal(components, expected)); + } + } +} \ No newline at end of file -- cgit v1.2.3 From c60f2e345231e03176e0882a88f8675c1814e456 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Tue, 5 May 2026 16:22:23 +0200 Subject: Remove manual tests --- kernel/src/main.cpp | 168 +--------------------------------------------------- 1 file changed, 1 insertion(+), 167 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index ffea979..bfb731a 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -21,173 +21,11 @@ #include #include -#include #include #include using namespace kstd::units_literals; -auto test_device_names() -> void -{ - auto storage_mgmt = kernel::devices::storage::management::get(); - std::ranges::for_each(storage_mgmt.all_controllers(), [](auto const & controller) { - std::ranges::for_each(controller->all_devices(), - [](auto const & device) { kstd::println("{}", device->name().view()); }); - }); -} - -auto test_file_descriptor_manually() -> void -{ - // setup - auto fd_table = kernel::filesystem::open_file_table::get(); - auto storage_mgmt = kernel::devices::storage::management::get(); - auto device = storage_mgmt.device_by_major_minor(1, 0); - - auto dev_node = kstd::make_shared(device); - - auto ofd = kstd::make_shared(dev_node); - auto fd_index = fd_table.add_file(ofd); - - // use: read two bytes and write two again - auto fd = fd_table.get_file(fd_index); - if (!fd) - { - kstd::os::panic("test code failed"); - } - - kstd::vector buffer{2}; - auto number_of_read_bytes = fd->read(buffer.data(), buffer.size()); - kstd::println("read bytes: {}", number_of_read_bytes); - kstd::println("buffer: {::#04x}", buffer); - - // write half of the file new - auto const value1 = std::byte{0xAA}; - auto const value2 = std::byte{0xBB}; - kstd::vector write_buffer{value1, value2}; - auto written_bytes = fd->write(write_buffer.data(), write_buffer.size()); - - kstd::println("written bytes: {}", written_bytes); - - fd_table.remove_file(fd_index); - - // use: read four bytes again -> two old bytes two new bytes - auto ofd1 = kstd::make_shared(dev_node); - fd_index = fd_table.add_file(ofd1); - auto fd1 = fd_table.get_file(fd_index); - - if (!fd1) - { - kstd::os::panic("test code failed"); - } - - kstd::vector buffer1{4}; - number_of_read_bytes = fd1->read(buffer1.data(), buffer1.size()); - kstd::println("read bytes: {}", number_of_read_bytes); - kstd::println("buffer: {::#04x}", buffer1); -} - -auto test_device_with_vfs() -> void -{ - auto vfs = kernel::filesystem::vfs::get(); - auto dentry = vfs.open("/dev/ram0"); - if (!dentry) - { - kstd::os::panic("test code failed"); - } - - auto fd_table = kernel::filesystem::open_file_table::get(); - auto ofd = kstd::make_shared(dentry->get_inode()); - auto fd = fd_table.add_file(ofd); - kstd::vector buffer{2}; - auto file = fd_table.get_file(fd); - if (!file) - { - kstd::os::panic("test code failed"); - } - - auto number_of_read_bytes = file->read(buffer.data(), buffer.size()); - kstd::println("read bytes: {}", number_of_read_bytes); - kstd::println("buffer: {::#04x}", buffer); -} - -auto test_file_lookup() -> void -{ - auto vfs = kernel::filesystem::vfs::get(); - auto read_and_write_file = [&vfs](std::string_view path) { - kstd::println("[TEST] Reading and writing file at path: {}", path); - auto dentry = vfs.open(path); - if (!dentry) - { - kstd::os::panic("test code failed"); - } - - kstd::vector buffer{32}; - auto ofd = kstd::make_shared(dentry->get_inode()); - auto number_of_read_bytes = ofd->read(buffer.data(), buffer.size()); - kstd::println("read bytes: {}", number_of_read_bytes); - kstd::println("buffer: {::#04x}", buffer); - - std::string_view buffer_as_str{reinterpret_cast(buffer.data()), number_of_read_bytes}; - kstd::println("buffer_as_str: {}", buffer_as_str); - }; - - read_and_write_file("/info.txt"); - read_and_write_file("/enclosures/info.txt"); - read_and_write_file("/enclosures/aquarium/tank_1/fish_4.txt"); - read_and_write_file("/enclosures/elephant_house/elephant_1.txt"); - read_and_write_file( - "/enclosures/aquarium/tank_2/" - "this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_" - "limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_30.txt"); - - vfs.do_mount("/dev/ram16", "/enclosures/aquarium"); - read_and_write_file("/enclosures/aquarium/closed.txt"); - read_and_write_file("/enclosures/aquarium/information/info_2.txt"); - - vfs.unmount("/enclosures/aquarium"); - read_and_write_file("/enclosures/aquarium/tank_1/fish_4.txt"); - - vfs.do_mount("/dev/ram32", "/enclosures/elephant_house"); - read_and_write_file("/enclosures/elephant_house/monkey_house/infrastructure/info.txt"); - - vfs.do_mount("/dev/ram16", "/enclosures/elephant_house/monkey_house"); - read_and_write_file("/enclosures/elephant_house/monkey_house/information/info_2.txt"); - - auto result = vfs.unmount("/enclosures/elephant_house"); - if (result == kernel::filesystem::vfs::operation_result::unmount_failed) - { - kstd::println("[TEST] Unmount failed as expected due to active child mount."); - } - - vfs.unmount("/enclosures/elephant_house/monkey_house"); - result = vfs.unmount("/enclosures/elephant_house"); - if (result == kernel::filesystem::vfs::operation_result::success) - { - kstd::println("[TEST] Unmount succeeded after unmounting child mount."); - } -} - -auto run_test_code() -> void -{ - kstd::println("[TEST] Running test code..."); - - kstd::println("[TEST] device names"); - test_device_names(); - kstd::println("---------------------------------"); - - kstd::println("[TEST] file descriptor manually"); - test_file_descriptor_manually(); - kstd::println("---------------------------------"); - - kstd::println("[TEST] device with VFS"); - test_device_with_vfs(); - kstd::println("---------------------------------"); - - kstd::println("[TEST] file lookup"); - test_file_lookup(); - kstd::println("---------------------------------"); -} - auto run_demo() -> void { // 1) open a file @@ -280,12 +118,8 @@ auto main() -> int kernel::filesystem::vfs::init(); kstd::println("[OS] Virtual filesystem initialized."); - // TODO BA-FS26 remove demo and test code again? + // TODO BA-FS26 remove demo code? // run_demo(); - // TODO BA-FS26 remove demo and test code again? - run_test_code(); - kstd::println("[TEST] All tests completed."); - kapi::system::panic("Returning from kernel main!"); } -- cgit v1.2.3 From 9f729ef76de79c8dabace2b4a6255f006385f6df Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Tue, 5 May 2026 16:29:50 +0200 Subject: Disable recursion-warning --- kernel/src/filesystem/dentry.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index 72500fd..1cf8730 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -39,7 +39,7 @@ namespace kernel::filesystem return m_name.view(); } - // TODO BA-FS26 fix warning (do not use recursion) + // NOLINTNEXTLINE(misc-no-recursion) auto dentry::get_full_path() const -> kstd::string { if (m_parent) @@ -52,7 +52,7 @@ namespace kernel::filesystem return parent_path + m_name.view(); } - return m_name.empty() ? "/" : m_name.view(); + return m_name.view(); } auto dentry::add_child(kstd::shared_ptr const & child) -> void -- cgit v1.2.3 From 2c24321681974e1aa8b1240155420f49a16f3c2e Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Tue, 5 May 2026 17:15:09 +0200 Subject: Add testing symlinks to filesystem images --- kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img | 2 +- kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img | 2 +- kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img b/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img index 0312727..a5202ca 100644 --- a/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img +++ b/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7cf40c3cf3d8e3be614cadf2da1c76138c492734c3730eadbca645f50ed99a50 +oid sha256:98ac3c1be872806e25fb14eea168ca79a91959f4e6a5ac3d00c5d8224c1f73a3 size 10485760 diff --git a/kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img b/kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img index 1880911..8327022 100644 --- a/kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img +++ b/kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a13da5abb9c65c737105b1da0d4344c7cd7604c7952c762c4f4e3d3f96fd42d +oid sha256:a1d102f2e40083613060d43b2b32d31031137bbef99761a2d1bf4d38e155adb7 size 5242880 diff --git a/kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img b/kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img index 3aaceb8..2cd452f 100644 --- a/kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img +++ b/kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ce6a1aea277906e1af6de223c017ff900b96569f076b4d99fc04eaa1ee986f4 +oid sha256:62e1fa40f95e0cb037c43e3f55d0094ab6cb4d68e00914f555a90faf7cc00c31 size 10485760 -- cgit v1.2.3 From 491d7cb23f48b995e954b7cbb836ab3efb47ea88 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Tue, 5 May 2026 17:22:27 +0200 Subject: Update readme for images, add symlink to readme into test_assets folder --- kernel/src/test_support/filesystem/test_assets/README.md | 1 + 1 file changed, 1 insertion(+) create mode 120000 kernel/src/test_support/filesystem/test_assets/README.md (limited to 'kernel/src') diff --git a/kernel/src/test_support/filesystem/test_assets/README.md b/kernel/src/test_support/filesystem/test_assets/README.md new file mode 120000 index 0000000..718a227 --- /dev/null +++ b/kernel/src/test_support/filesystem/test_assets/README.md @@ -0,0 +1 @@ +/arch/x86_64/support/modules/README.md \ No newline at end of file -- cgit v1.2.3 From 265ac82029665921bd95d74411682968ee0d4ada Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 5 May 2026 19:41:50 +0200 Subject: refactoring do_mount_internal (retrieve path from dentry), handle .. correctly in relative path --- kernel/src/filesystem/vfs.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index e6d9241..4defc81 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -56,14 +56,14 @@ namespace kernel::filesystem { kapi::system::panic("[FILESYSTEM] failed to resolve /dev for initial devfs mount."); } - do_mount_internal("/dev", dev_mount_point_dentry, device_fs); + do_mount_internal(dev_mount_point_dentry, device_fs); // Mount boot filesystem at / (will shadow rootfs) if (auto boot_device_dentry = resolve_path("/dev/ram0")) { if (auto boot_root_fs = kernel::filesystem::filesystem::probe_and_mount(boot_device_dentry->get_inode())) { - do_mount_internal("/", root_fs_root_dentry, boot_root_fs); + do_mount_internal(root_fs_root_dentry, boot_root_fs); // Resolve / to get the boot root dentry if (auto boot_root_dentry = resolve_path("/")) @@ -71,7 +71,7 @@ namespace kernel::filesystem auto dev_dentry = kstd::make_shared(boot_root_dentry, device_fs->root_inode(), "dev"); boot_root_dentry->add_child(dev_dentry); - do_mount_internal("/dev", dev_dentry, device_fs); + do_mount_internal(dev_dentry, device_fs); } } } @@ -105,7 +105,7 @@ namespace kernel::filesystem { if (auto fs = kernel::filesystem::filesystem::probe_and_mount(source_dentry->get_inode())) { - do_mount_internal(target, mount_point_dentry, fs); + do_mount_internal(mount_point_dentry, fs); return operation_result::success; } return operation_result::invalid_filesystem; @@ -136,13 +136,15 @@ namespace kernel::filesystem return operation_result::mount_point_not_found; } - auto vfs::do_mount_internal(std::string_view path, kstd::shared_ptr const & mount_point_dentry, + auto vfs::do_mount_internal(kstd::shared_ptr const & mount_point_dentry, kstd::shared_ptr const & fs) -> void { - auto parent_mount = m_mount_table.find_longest_prefix_mount(path); + auto mount_path = mount_point_dentry->get_full_path(); + + auto parent_mount = m_mount_table.find_longest_prefix_mount(mount_path.view()); auto new_fs_root = kstd::make_shared(mount_point_dentry->get_parent(), fs->root_inode(), mount_point_dentry->get_name()); - auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, path, parent_mount); + auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, mount_path.view(), parent_mount); m_mount_table.add_mount(new_mount); } @@ -188,16 +190,15 @@ namespace kernel::filesystem if (auto parent_mount = current_mount->get_parent_mount()) { current_mount = parent_mount; - current_dentry = current_dentry->get_parent(); + current_dentry = parent_dentry; + } - if (!parent_dentry) - { - parent_dentry = current_mount->root_dentry(); - } + if (!parent_dentry) + { + parent_dentry = current_mount->root_dentry(); } } - - if (!parent_dentry) + else if (!parent_dentry) { return nullptr; } -- cgit v1.2.3 From b7fba373341dd44b53642d7233396efbef4526b2 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 5 May 2026 20:07:37 +0200 Subject: avoid to traverse back over the root --- kernel/src/filesystem/vfs.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 4defc81..7f21a5c 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -186,22 +186,17 @@ namespace kernel::filesystem if (current_dentry == current_mount->root_dentry()) { - // change the mount point - if (auto parent_mount = current_mount->get_parent_mount()) + if (current_mount->get_mount_path() == "/") { - current_mount = parent_mount; - current_dentry = parent_dentry; + continue; } - if (!parent_dentry) + if (auto parent_mount = current_mount->get_parent_mount()) { - parent_dentry = current_mount->root_dentry(); + current_mount = parent_mount; + current_dentry = parent_dentry; } } - else if (!parent_dentry) - { - return nullptr; - } current_dentry = parent_dentry; continue; -- cgit v1.2.3 From a0f1c6f2199f55d2faaa5d9eafa9f763b2b299e4 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 5 May 2026 20:08:00 +0200 Subject: add symbolic link tests --- kernel/src/filesystem/vfs.tests.cpp | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index cbd67be..5160d15 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -301,5 +301,47 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto info_1 = vfs.open("/symlinks/info_1_relative"); REQUIRE(info_1 != nullptr); } + + THEN("file can be opened through symbolic link pointing absolute to the directory containing the file") + { + auto & vfs = kernel::filesystem::vfs::get(); + auto info_1 = vfs.open("/symlinks/information_directory_absolute/info_1.txt"); + REQUIRE(info_1 != nullptr); + } + + THEN("file can be opened through symbolic link pointing relative to the directory containing the file") + { + auto & vfs = kernel::filesystem::vfs::get(); + auto info_1 = vfs.open("/symlinks/information_directory_relative/info_1.txt"); + REQUIRE(info_1 != nullptr); + } + + THEN("symbolic link with path traversing back to the root") + { + auto & vfs = kernel::filesystem::vfs::get(); + auto info_1 = vfs.open("/symlinks/traverse_back_5_times/information/info_1.txt"); + REQUIRE(info_1 != nullptr); + } + + THEN("symbolic link containing an invalid absolute path is handled correctly") + { + auto & vfs = kernel::filesystem::vfs::get(); + auto invalid_symlink = vfs.open("/symlinks/invalid_absolute"); + REQUIRE(invalid_symlink == nullptr); + } + + THEN("symbolic link containing an invalid relative path is handled correctly") + { + auto & vfs = kernel::filesystem::vfs::get(); + auto invalid_symlink = vfs.open("/symlinks/invalid_relative"); + REQUIRE(invalid_symlink == nullptr); + } + + THEN("circular symbolic links are detected and handled correctly") + { + auto & vfs = kernel::filesystem::vfs::get(); + auto circular_symlink = vfs.open("/symlinks/symloop_a"); + REQUIRE(circular_symlink == nullptr); + } } } -- cgit v1.2.3 From 7414148b662a33cf6c69f89b7b0c3162f6880d6c Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 5 May 2026 20:33:28 +0200 Subject: refactoring mount_table lookup --- kernel/src/filesystem/mount_table.cpp | 8 ++++++++ kernel/src/filesystem/vfs.cpp | 10 ++++------ 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index e21e497..965e83b 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -102,4 +102,12 @@ namespace kernel::filesystem return mount_with_longest_prefix; } + + auto mount_table::find_exact_mount(std::string_view path) const -> kstd::shared_ptr + { + auto reversed_mounts = std::ranges::reverse_view(m_mounts); + auto mount_it = + std::ranges::find_if(reversed_mounts, [&](auto const & mount) { return mount->get_mount_path() == path; }); + return (mount_it != reversed_mounts.end()) ? *mount_it : nullptr; + } } // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 7f21a5c..19f5f48 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -41,7 +41,6 @@ namespace kernel::filesystem auto vfs::init_internal() -> void { - // Mount rootfs at / as the temporary base auto root_fs = kstd::make_shared(); root_fs->mount(nullptr); @@ -140,8 +139,8 @@ namespace kernel::filesystem kstd::shared_ptr const & fs) -> void { auto mount_path = mount_point_dentry->get_full_path(); - auto parent_mount = m_mount_table.find_longest_prefix_mount(mount_path.view()); + auto new_fs_root = kstd::make_shared(mount_point_dentry->get_parent(), fs->root_inode(), mount_point_dentry->get_name()); auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, mount_path.view(), parent_mount); @@ -156,7 +155,7 @@ namespace kernel::filesystem } // TODO BA-FS26 refactor (get mount by path, no more prefix matching) - auto current_mount = m_mount_table.find_longest_prefix_mount("/"); + auto current_mount = m_mount_table.find_exact_mount("/"); if (!current_mount) { kapi::system::panic("[FILESYSTEM] no root mount found."); @@ -217,8 +216,7 @@ namespace kernel::filesystem } else if (next_dentry->has_flag(dentry::dentry_flags::mounted)) { - // TODO BA-FS26 really do it like this? or just call "get" without longes_prefix stuff - current_mount = m_mount_table.find_longest_prefix_mount(next_dentry->get_full_path().view()); + current_mount = m_mount_table.find_exact_mount(next_dentry->get_full_path().view()); if (!current_mount) { kapi::system::panic("[FILESYSTEM] mount for dentry with mounted flag not found."); @@ -246,7 +244,7 @@ namespace kernel::filesystem if (path::is_valid_absolute_path(symbolic_link_path)) { - current_mount = m_mount_table.find_longest_prefix_mount("/"); + current_mount = m_mount_table.find_exact_mount("/"); current_dentry = current_mount->root_dentry(); } continue; -- cgit v1.2.3 From 8739d65ea50f13dbbb5bd1a27f461c367deb5b99 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 5 May 2026 20:59:52 +0200 Subject: add symlink chain to image --- kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img b/kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img index 2cd452f..c3f6daf 100644 --- a/kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img +++ b/kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62e1fa40f95e0cb037c43e3f55d0094ab6cb4d68e00914f555a90faf7cc00c31 +oid sha256:026ca30269dbd80beb2dd74677c94676d1d4a7f6b5fe406c4ddb82836ba2dc00 size 10485760 -- cgit v1.2.3 From 9d1fc7cbe7d3851541f1986dc4bc66a2bc944c89 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 5 May 2026 21:00:17 +0200 Subject: add vfs symlink tests --- kernel/src/filesystem/vfs.tests.cpp | 63 ++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 5160d15..2eec572 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -283,7 +283,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS } } - GIVEN("one real image files, containing symbolic links") + GIVEN("A real image files, containing symbolic links") { REQUIRE(std::filesystem::exists(image_path_1)); REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module_1"}, {image_path_1})); @@ -344,4 +344,65 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(circular_symlink == nullptr); } } + + GIVEN("A real image file containing as filesystem formatted files and this filesystem contains a symbolic link") + { + REQUIRE(std::filesystem::exists(image_path_1)); + REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module_1"}, {image_path_1})); + + auto & vfs = kernel::filesystem::vfs::get(); + vfs.do_mount("/archiv/2024.img", "/information"); + + THEN("file can be opened through symbolic link pointing to the parent filesystem") + { + auto closed_file = vfs.open("/information/symlinks/traverse_back_twice/closed.txt"); + REQUIRE(closed_file != nullptr); + } + } + + GIVEN("Two real images, one containing a symbolic link leaving and reentering filesystem again") + { + REQUIRE(std::filesystem::exists(image_path_1)); + REQUIRE(std::filesystem::exists(image_path_2)); + REQUIRE_NOTHROW( + setup_modules_from_img_and_init_vfs({"test_img_module_1", "test_img_module_2"}, {image_path_1, image_path_2})); + + auto & vfs = kernel::filesystem::vfs::get(); + vfs.do_mount("/dev/ram16", "/information"); + + THEN("file can be opened through symbolic link pointing to the parent filesystem and back into the mounted " + "filesystem again") + { + auto monkey_1 = vfs.open("/information/symlinks/leave_and_reenter_mount/monkey_1.txt"); + REQUIRE(monkey_1 != nullptr); + } + } + + GIVEN("One real image containing a very long symbolic link") + { + REQUIRE(std::filesystem::exists(image_path_3)); + REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module_3"}, {image_path_3})); + + auto & vfs = kernel::filesystem::vfs::get(); + + THEN("file can be opened through symbolic link with a long path") + { + auto fish_30 = vfs.open("/symlinks/very_long_symlink"); + REQUIRE(fish_30 != nullptr); + } + } + + GIVEN("One real image containing a valid symbolic link chain") + { + REQUIRE(std::filesystem::exists(image_path_3)); + REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module_3"}, {image_path_3})); + + auto & vfs = kernel::filesystem::vfs::get(); + + THEN("file can be opened through symbolic link chain") + { + auto map = vfs.open("/symlinks/symlink_chain_1/map.txt"); + REQUIRE(map != nullptr); + } + } } -- cgit v1.2.3 From 7ccfa26a3dde4d4266f8c59f4e3de8bd6f760059 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 5 May 2026 21:17:23 +0200 Subject: small refactoring, add todo --- kernel/src/filesystem/vfs.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 19f5f48..b84f690 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -139,6 +139,7 @@ namespace kernel::filesystem kstd::shared_ptr const & fs) -> void { auto mount_path = mount_point_dentry->get_full_path(); + // TODO BA-FS26 refactoring, implement dentry lookup to get the parent mount... auto parent_mount = m_mount_table.find_longest_prefix_mount(mount_path.view()); auto new_fs_root = -- cgit v1.2.3 From 870039d48d28f479eea88c7548b8d2b2a28c09bc Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 5 May 2026 21:18:48 +0200 Subject: add mount table find_exact_mount tests, remove todo --- kernel/src/filesystem/mount_table.tests.cpp | 21 +++++++++++++++++++-- kernel/src/filesystem/vfs.cpp | 1 - 2 files changed, 19 insertions(+), 3 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.tests.cpp b/kernel/src/filesystem/mount_table.tests.cpp index e028ac8..efacdfe 100644 --- a/kernel/src/filesystem/mount_table.tests.cpp +++ b/kernel/src/filesystem/mount_table.tests.cpp @@ -58,7 +58,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] REQUIRE_FALSE(root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); } - THEN("finding mounts by path returns the correct mount") + THEN("finding mounts by longest prefix returns the correct mount") { REQUIRE(table.find_longest_prefix_mount("/") == mount1); REQUIRE(table.find_longest_prefix_mount("/file") == mount1); @@ -67,6 +67,18 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] REQUIRE(table.find_longest_prefix_mount("/other") == mount1); } + THEN("finding mounts by exact valid path returns the correct mount") + { + REQUIRE(table.find_exact_mount("/") == mount1); + REQUIRE(table.find_exact_mount("/mnt") == mount2); + } + + THEN("finding mounts by exact invalid path returns null") + { + REQUIRE(table.find_exact_mount("/nonexistent") == nullptr); + REQUIRE(table.find_exact_mount("/mnt/file") == nullptr); + } + THEN("removing a mount that has no child mounts succeeds") { REQUIRE(table.remove_mount("/mnt") == kernel::filesystem::mount_table::operation_result::removed); @@ -97,7 +109,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] table.add_mount(mount1); table.add_mount(mount2); - THEN("finding mounts by path returns the correct mount based on longest prefix") + THEN("finding mounts by longest prefix returns the correct mount") { REQUIRE(table.find_longest_prefix_mount("/") == mount2); REQUIRE(table.find_longest_prefix_mount("/file") == mount2); @@ -106,6 +118,11 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] REQUIRE(table.find_longest_prefix_mount("/other") == mount2); } + THEN("finding mounts by exact valid path returns the correct mount") + { + REQUIRE(table.find_exact_mount("/") == mount2); + } + THEN("removing the topmost mount with the same path succeeds") { REQUIRE(table.remove_mount("/") == kernel::filesystem::mount_table::operation_result::removed); diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index b84f690..519550b 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -155,7 +155,6 @@ namespace kernel::filesystem return nullptr; } - // TODO BA-FS26 refactor (get mount by path, no more prefix matching) auto current_mount = m_mount_table.find_exact_mount("/"); if (!current_mount) { -- cgit v1.2.3 From 4522374b902ee9a30c83c2ec23880522e80febea Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 5 May 2026 21:37:12 +0200 Subject: .. int the root directory remains in the root --- kernel/src/filesystem/vfs.tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 2eec572..8e4cb70 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -187,7 +187,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS { REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); - auto img = vfs.open("/information/monkey_house/caretaker/../../../archiv/2024.img"); + auto img = vfs.open("/information/monkey_house/caretaker/../../../../../../archiv/2024.img"); REQUIRE(img != nullptr); auto dev_32 = vfs.open("/information/monkey_house/caretaker/../../../dev/ram32"); -- cgit v1.2.3 From 8a11512eb8030de09ed806d8b40b7f54c2f204ab Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 11 May 2026 14:48:46 +0200 Subject: Refactor get_full_path remove recursion --- kernel/src/filesystem/dentry.cpp | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index 1cf8730..a3bd7f4 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -39,20 +40,35 @@ namespace kernel::filesystem return m_name.view(); } - // NOLINTNEXTLINE(misc-no-recursion) auto dentry::get_full_path() const -> kstd::string { - if (m_parent) + if (m_name == "/") { - auto parent_path = m_parent->get_full_path(); - if (parent_path != "/") - { - parent_path += '/'; - } - return parent_path + m_name.view(); + return "/"; } - return m_name.view(); + kstd::vector components; + components.push_back(m_name.view()); + components.push_back("/"); + + auto parent = m_parent; + + while (parent && parent->m_name != "/") + { + components.push_back(parent->m_name.view()); + components.push_back("/"); + parent = parent->get_parent(); + } + + std::ranges::reverse(components); + + kstd::string full_path = ""; + for (auto const & view : components) + { + full_path += view; + } + + return full_path; } auto dentry::add_child(kstd::shared_ptr const & child) -> void -- cgit v1.2.3 From 7ea0aa798e3062dea20a317e2b19d7cf879611ca Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 11 May 2026 18:46:10 +0200 Subject: Refactor dentry --- kernel/src/filesystem/dentry.cpp | 40 +++++++++++++++------------------- kernel/src/filesystem/dentry.tests.cpp | 15 +++---------- 2 files changed, 21 insertions(+), 34 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index a3bd7f4..7617b28 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -23,6 +23,10 @@ namespace kernel::filesystem { kapi::system::panic("[FILESYSTEM] dentry constructed with null inode."); } + if (m_name.empty()) + { + kapi::system::panic("[FILESYSTEM] dentry constructed with empty name."); + } } auto dentry::get_inode() const -> kstd::shared_ptr const & @@ -42,33 +46,25 @@ namespace kernel::filesystem auto dentry::get_full_path() const -> kstd::string { - if (m_name == "/") - { - return "/"; - } - - kstd::vector components; - components.push_back(m_name.view()); - components.push_back("/"); + kstd::string path = m_name; auto parent = m_parent; - - while (parent && parent->m_name != "/") - { - components.push_back(parent->m_name.view()); - components.push_back("/"); - parent = parent->get_parent(); - } - - std::ranges::reverse(components); - - kstd::string full_path = ""; - for (auto const & view : components) + while (parent) { - full_path += view; + auto parent_name = parent->m_name; + if (parent_name == "/") + { + path = "/" + path; + } + else + { + path = parent_name + "/" + path; + } + + parent = parent->m_parent; } - return full_path; + return path; } auto dentry::add_child(kstd::shared_ptr const & child) -> void diff --git a/kernel/src/filesystem/dentry.tests.cpp b/kernel/src/filesystem/dentry.tests.cpp index c42c405..200262a 100644 --- a/kernel/src/filesystem/dentry.tests.cpp +++ b/kernel/src/filesystem/dentry.tests.cpp @@ -13,7 +13,7 @@ SCENARIO("Dentry construction", "[filesystem][dentry]") GIVEN("A parent dentry and inode") { auto inode = kstd::make_shared(); - auto parent_dentry = kstd::make_shared(nullptr, inode); + auto parent_dentry = kstd::make_shared(nullptr, inode, "parent"); WHEN("constructing a dentry") { @@ -34,18 +34,9 @@ SCENARIO("Dentry construction", "[filesystem][dentry]") WHEN("constructing a dentry with an empty name") { - auto child_dentry = kernel::filesystem::dentry{parent_dentry, inode}; - THEN("the dentry has the correct parent and inode, and an empty name") { - REQUIRE(child_dentry.get_parent() == parent_dentry); - REQUIRE(child_dentry.get_inode() == inode); - REQUIRE(child_dentry.get_name().empty()); - } - - THEN("no flag is set") - { - REQUIRE_FALSE(child_dentry.has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE_THROWS_AS((kernel::filesystem::dentry{parent_dentry, inode, ""}), kernel::tests::cpu::halt); } } @@ -81,7 +72,7 @@ SCENARIO("Dentry child logic", "[filesystem][dentry]") GIVEN("A parent dentry and inode") { auto inode = kstd::make_shared(); - auto parent_dentry = kstd::make_shared(nullptr, inode); + auto parent_dentry = kstd::make_shared(nullptr, inode, "parent"); WHEN("adding child dentries") { -- cgit v1.2.3 From 7683d52861f05566a3b82e24484e367fcdc63ea8 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 11 May 2026 18:52:59 +0200 Subject: Add test for dentry get_full_path --- kernel/src/filesystem/dentry.tests.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.tests.cpp b/kernel/src/filesystem/dentry.tests.cpp index 200262a..1a5a784 100644 --- a/kernel/src/filesystem/dentry.tests.cpp +++ b/kernel/src/filesystem/dentry.tests.cpp @@ -124,3 +124,27 @@ SCENARIO("Dentry Flag logic", "[filesystem][dentry]") } } } + +SCENARIO("Dentry path resolution", "[filesystem][dentry]") +{ + GIVEN("A dentry with a parent hierarchy") + { + auto root_inode = kstd::make_shared(); + auto root_dentry = kstd::make_shared(nullptr, root_inode, "/"); + + auto home_inode = kstd::make_shared(); + auto home_dentry = kstd::make_shared(root_dentry, home_inode, "home"); + root_dentry->add_child(home_dentry); + + auto user_inode = kstd::make_shared(); + auto user_dentry = kstd::make_shared(home_dentry, user_inode, "user"); + home_dentry->add_child(user_dentry); + + THEN("the full path is constructed correctly") + { + REQUIRE(root_dentry->get_full_path() == "/"); + REQUIRE(home_dentry->get_full_path() == "/home"); + REQUIRE(user_dentry->get_full_path() == "/home/user"); + } + } +} \ No newline at end of file -- cgit v1.2.3 From a4c9b9bdb768ce20c9f9eac353a34598e4a422a9 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 11 May 2026 18:54:27 +0200 Subject: Rename get_full_path to get_absolute_path --- kernel/src/filesystem/dentry.cpp | 2 +- kernel/src/filesystem/dentry.tests.cpp | 6 +++--- kernel/src/filesystem/vfs.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index 7617b28..59fd89e 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -44,7 +44,7 @@ namespace kernel::filesystem return m_name.view(); } - auto dentry::get_full_path() const -> kstd::string + auto dentry::get_absolute_path() const -> kstd::string { kstd::string path = m_name; diff --git a/kernel/src/filesystem/dentry.tests.cpp b/kernel/src/filesystem/dentry.tests.cpp index 1a5a784..dd01394 100644 --- a/kernel/src/filesystem/dentry.tests.cpp +++ b/kernel/src/filesystem/dentry.tests.cpp @@ -142,9 +142,9 @@ SCENARIO("Dentry path resolution", "[filesystem][dentry]") THEN("the full path is constructed correctly") { - REQUIRE(root_dentry->get_full_path() == "/"); - REQUIRE(home_dentry->get_full_path() == "/home"); - REQUIRE(user_dentry->get_full_path() == "/home/user"); + REQUIRE(root_dentry->get_absolute_path() == "/"); + REQUIRE(home_dentry->get_absolute_path() == "/home"); + REQUIRE(user_dentry->get_absolute_path() == "/home/user"); } } } \ No newline at end of file diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 519550b..1410b2a 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -138,7 +138,7 @@ namespace kernel::filesystem auto vfs::do_mount_internal(kstd::shared_ptr const & mount_point_dentry, kstd::shared_ptr const & fs) -> void { - auto mount_path = mount_point_dentry->get_full_path(); + auto mount_path = mount_point_dentry->get_absolute_path(); // TODO BA-FS26 refactoring, implement dentry lookup to get the parent mount... auto parent_mount = m_mount_table.find_longest_prefix_mount(mount_path.view()); @@ -216,7 +216,7 @@ namespace kernel::filesystem } else if (next_dentry->has_flag(dentry::dentry_flags::mounted)) { - current_mount = m_mount_table.find_exact_mount(next_dentry->get_full_path().view()); + current_mount = m_mount_table.find_exact_mount(next_dentry->get_absolute_path().view()); if (!current_mount) { kapi::system::panic("[FILESYSTEM] mount for dentry with mounted flag not found."); -- cgit v1.2.3 From c958b72922b89fff35c0b8e0bbf21ad42a667022 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 11 May 2026 20:27:01 +0200 Subject: Remove unused include --- kernel/src/filesystem/dentry.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index 59fd89e..a77ce23 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include -- cgit v1.2.3 From e05b52111d952c626c29d92a862ee0d1dce180f3 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sun, 10 May 2026 13:21:25 +0200 Subject: renaming --- kernel/src/devices/storage/management.cpp | 31 +++++++++++++------------- kernel/src/devices/storage/ram_disk/device.cpp | 4 ++-- 2 files changed, 17 insertions(+), 18 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/devices/storage/management.cpp b/kernel/src/devices/storage/management.cpp index 1f2acba..06efc27 100644 --- a/kernel/src/devices/storage/management.cpp +++ b/kernel/src/devices/storage/management.cpp @@ -17,43 +17,42 @@ namespace { - constexpr size_t static MINORS_PER_DEVICE = 16; - constexpr size_t static START_MAJOR = 1; - constinit size_t static next_free_major = START_MAJOR; + constexpr size_t static minors_per_device = 16; + constexpr size_t static start_major = 1; + constinit size_t static next_free_major = start_major; - constinit auto static active_storage_management = std::optional{}; + constinit auto static storage_management = std::optional{}; } // namespace namespace kernel::devices::storage { auto management::init() -> void { - if (active_storage_management) + if (storage_management) { kapi::system::panic("[DEVICES] Storage management has already been initialized."); } - active_storage_management.emplace(management{}); + storage_management.emplace(management{}); - auto current_ram_disk_controller = - kstd::make_shared(&kapi::boot_modules::get_boot_module_registry()); - active_storage_management->add_controller(current_ram_disk_controller); + auto ram_disk_controller = kstd::make_shared(&kapi::boot_modules::get_boot_module_registry()); + storage_management->add_controller(ram_disk_controller); - std::ranges::for_each(active_storage_management->m_controllers, [](auto controller) { controller->probe(); }); + std::ranges::for_each(storage_management->m_controllers, [](auto controller) { controller->probe(); }); } auto management::get() -> management & { - if (!active_storage_management) + if (!storage_management) { kapi::system::panic("[DEVICES] Storage management has not been initialized."); } - return *active_storage_management; + return *storage_management; } auto management::add_controller(kstd::shared_ptr const & controller) -> void { - controller->set_ids(next_free_major++, MINORS_PER_DEVICE); + controller->set_ids(next_free_major++, minors_per_device); m_controllers.push_back(controller); } @@ -82,7 +81,7 @@ namespace kernel::devices::storage auto management::determine_boot_device() -> kstd::shared_ptr { - return device_by_major_minor(START_MAJOR, 0); + return device_by_major_minor(start_major, 0); } } // namespace kernel::devices::storage @@ -90,7 +89,7 @@ namespace kernel::tests::devices::storage::management { auto deinit() -> void { - active_storage_management.reset(); - next_free_major = START_MAJOR; + storage_management.reset(); + next_free_major = start_major; } } // namespace kernel::tests::devices::storage::management diff --git a/kernel/src/devices/storage/ram_disk/device.cpp b/kernel/src/devices/storage/ram_disk/device.cpp index 21b0000..1557204 100644 --- a/kernel/src/devices/storage/ram_disk/device.cpp +++ b/kernel/src/devices/storage/ram_disk/device.cpp @@ -14,11 +14,11 @@ namespace kernel::devices::storage::ram_disk { namespace { - constexpr size_t RAM_DISK_BLOCK_SIZE = 512uz; + constexpr size_t ram_disk_block_size = 512uz; } // namespace device::device(kapi::boot_modules::boot_module const & module, size_t major, size_t minor) - : block_device(major, minor, "ram" + kstd::to_string(minor), RAM_DISK_BLOCK_SIZE) + : block_device(major, minor, "ram" + kstd::to_string(minor), ram_disk_block_size) , m_boot_module(module) {} -- cgit v1.2.3 From 00aa2c8695b81944798010d81d600038e1f1ef3d Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sun, 10 May 2026 19:08:07 +0200 Subject: remove mount_path from mount struct (retrieve path from m_mount_dentry) --- kernel/src/filesystem/mount.cpp | 14 ++++--- kernel/src/filesystem/mount.tests.cpp | 4 +- kernel/src/filesystem/mount_table.cpp | 7 +++- kernel/src/filesystem/mount_table.tests.cpp | 60 ++++++++++++++++++----------- kernel/src/filesystem/vfs.cpp | 7 +++- 5 files changed, 57 insertions(+), 35 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index 67450b7..c474c8e 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -13,10 +13,8 @@ namespace kernel::filesystem { mount::mount(kstd::shared_ptr const & mount_dentry, kstd::shared_ptr const & root_dentry, - kstd::shared_ptr const & fs, std::string_view mount_path, - kstd::shared_ptr const & parent_mount) - : m_mount_path(mount_path) - , m_mount_dentry(mount_dentry) + kstd::shared_ptr const & fs, kstd::shared_ptr const & parent_mount) + : m_mount_dentry(mount_dentry) , m_root_dentry(root_dentry) , m_filesystem(fs) , m_parent_mount(parent_mount) @@ -42,9 +40,13 @@ namespace kernel::filesystem return m_root_dentry; } - auto mount::get_mount_path() const -> std::string_view + auto mount::get_mount_path() const -> kstd::string { - return m_mount_path.view(); + if (m_mount_dentry) + { + return m_mount_dentry->get_full_path(); + } + return "/"; } auto mount::get_parent_mount() const -> kstd::shared_ptr const & diff --git a/kernel/src/filesystem/mount.tests.cpp b/kernel/src/filesystem/mount.tests.cpp index d630464..4b44983 100644 --- a/kernel/src/filesystem/mount.tests.cpp +++ b/kernel/src/filesystem/mount.tests.cpp @@ -21,7 +21,7 @@ SCENARIO("Mount construction", "[filesystem][mount]") WHEN("constructing a mount with the filesystem and root dentry") { - auto mount = kernel::filesystem::mount{root_dentry, root_dentry, fs, "/", nullptr}; + auto mount = kernel::filesystem::mount{root_dentry, root_dentry, fs, nullptr}; THEN("the mount has the correct filesystem, root dentry, mount dentry, and mount path") { @@ -41,7 +41,7 @@ SCENARIO("Mount construction", "[filesystem][mount]") { THEN("the constructor panics") { - REQUIRE_THROWS_AS((kernel::filesystem::mount{root_dentry, root_dentry, nullptr, "/", nullptr}), + REQUIRE_THROWS_AS((kernel::filesystem::mount{root_dentry, root_dentry, nullptr, nullptr}), kernel::tests::cpu::halt); } } diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index 965e83b..b67e05c 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -37,7 +37,9 @@ namespace kernel::filesystem kstd::vector> const & mounts) -> bool { return std::ranges::none_of(mounts, [&](auto const & other) { - return other != candidate && is_strict_prefix(other->get_mount_path(), candidate->get_mount_path()) && + // TODO BA-FS26 really correct? + return other != candidate && + is_strict_prefix(other->get_mount_path().view(), candidate->get_mount_path().view()) && !is_descendant_of(candidate, other); }); } @@ -80,6 +82,7 @@ namespace kernel::filesystem return operation_result::removed; } + // TODO BA-FS26 remove? auto mount_table::find_longest_prefix_mount(std::string_view path) const -> kstd::shared_ptr { kstd::shared_ptr mount_with_longest_prefix = nullptr; @@ -90,7 +93,7 @@ namespace kernel::filesystem auto mp = mount->get_mount_path(); // /a/b/c should match /a/b but not /a/bb or /a/b/c/d, / should match everything - bool is_prefix = path.starts_with(mp) && (mp == "/" || path.size() == mp.size() || path[mp.size()] == '/'); + bool is_prefix = path.starts_with(mp.view()) && (mp == "/" || path.size() == mp.size() || path[mp.size()] == '/'); bool visible = is_visible_mount(mount, m_mounts); if (is_prefix && visible && mp.size() >= best_len) diff --git a/kernel/src/filesystem/mount_table.tests.cpp b/kernel/src/filesystem/mount_table.tests.cpp index efacdfe..732d32f 100644 --- a/kernel/src/filesystem/mount_table.tests.cpp +++ b/kernel/src/filesystem/mount_table.tests.cpp @@ -40,22 +40,26 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] kernel::filesystem::mount_table table; auto fs1 = kstd::make_shared(); - auto root_inode1 = kstd::make_shared(); - auto root_dentry1 = kstd::make_shared(nullptr, root_inode1, "/"); - auto mount1 = kstd::make_shared(root_dentry1, root_dentry1, fs1, "/", nullptr); + auto root_dentry1 = kstd::make_shared( + nullptr, kstd::make_shared(), "/"); + auto mount_dentry1 = kstd::make_shared( + nullptr, kstd::make_shared(), "/"); + auto mount1 = kstd::make_shared(mount_dentry1, root_dentry1, fs1, nullptr); auto fs2 = kstd::make_shared(); - auto root_inode2 = kstd::make_shared(); - auto root_dentry2 = kstd::make_shared(nullptr, root_inode2, "/"); - auto mount2 = kstd::make_shared(root_dentry1, root_dentry2, fs2, "/mnt", nullptr); + auto root_dentry2 = kstd::make_shared( + nullptr, kstd::make_shared(), "/"); + auto mount_dentry2 = kstd::make_shared( + nullptr, kstd::make_shared(), "/mnt"); + auto mount2 = kstd::make_shared(mount_dentry2, root_dentry2, fs2, nullptr); table.add_mount(mount1); table.add_mount(mount2); THEN("dentry flags are set correctly for mounted dentries") { - REQUIRE(root_dentry1->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); - REQUIRE_FALSE(root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE(mount_dentry1->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE(mount_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); } THEN("finding mounts by longest prefix returns the correct mount") @@ -97,14 +101,18 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] kernel::filesystem::mount_table table; auto fs1 = kstd::make_shared(); - auto root_inode1 = kstd::make_shared(); - auto root_dentry1 = kstd::make_shared(nullptr, root_inode1, "/"); - auto mount1 = kstd::make_shared(root_dentry1, root_dentry1, fs1, "/", nullptr); + auto root_dentry1 = kstd::make_shared( + nullptr, kstd::make_shared(), "/"); + auto mount_dentry1 = kstd::make_shared( + nullptr, kstd::make_shared(), "/"); + auto mount1 = kstd::make_shared(mount_dentry1, root_dentry1, fs1, nullptr); auto fs2 = kstd::make_shared(); - auto root_inode2 = kstd::make_shared(); - auto root_dentry2 = kstd::make_shared(nullptr, root_inode2, "/"); - auto mount2 = kstd::make_shared(root_dentry1, root_dentry2, fs2, "/", mount1); + auto root_dentry2 = kstd::make_shared( + nullptr, kstd::make_shared(), "/"); + auto mount_dentry2 = kstd::make_shared( + nullptr, kstd::make_shared(), "/"); + auto mount2 = kstd::make_shared(mount_dentry2, root_dentry2, fs2, nullptr); table.add_mount(mount1); table.add_mount(mount2); @@ -136,19 +144,25 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] kernel::filesystem::mount_table table; auto fs1 = kstd::make_shared(); - auto root_inode1 = kstd::make_shared(); - auto root_dentry1 = kstd::make_shared(nullptr, root_inode1, "/"); - auto mount1 = kstd::make_shared(root_dentry1, root_dentry1, fs1, "/", nullptr); + auto root_dentry1 = kstd::make_shared( + nullptr, kstd::make_shared(), "/"); + auto mount_dentry1 = kstd::make_shared( + nullptr, kstd::make_shared(), "/"); + auto mount1 = kstd::make_shared(mount_dentry1, root_dentry1, fs1, nullptr); auto fs2 = kstd::make_shared(); - auto root_inode2 = kstd::make_shared(); - auto root_dentry2 = kstd::make_shared(nullptr, root_inode2, "/"); - auto mount2 = kstd::make_shared(root_dentry1, root_dentry2, fs2, "/mnt", mount1); + auto root_dentry2 = kstd::make_shared( + nullptr, kstd::make_shared(), "/"); + auto mount_dentry2 = kstd::make_shared( + mount_dentry1, kstd::make_shared(), "mnt"); + auto mount2 = kstd::make_shared(mount_dentry2, root_dentry2, fs2, mount1); auto fs3 = kstd::make_shared(); - auto root_inode3 = kstd::make_shared(); - auto root_dentry3 = kstd::make_shared(nullptr, root_inode3, "/"); - auto mount3 = kstd::make_shared(root_dentry2, root_dentry3, fs3, "/mnt/submnt", mount2); + auto root_dentry3 = kstd::make_shared( + nullptr, kstd::make_shared(), "/"); + auto mount_dentry3 = kstd::make_shared( + mount_dentry2, kstd::make_shared(), "submnt"); + auto mount3 = kstd::make_shared(mount_dentry3, root_dentry3, fs3, mount2); table.add_mount(mount1); table.add_mount(mount2); diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 1410b2a..ea060a9 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -45,7 +45,7 @@ namespace kernel::filesystem root_fs->mount(nullptr); auto root_fs_root_dentry = kstd::make_shared(nullptr, root_fs->root_inode(), "/"); - m_mount_table.add_mount(kstd::make_shared(nullptr, root_fs_root_dentry, root_fs, "/", nullptr)); + m_mount_table.add_mount(kstd::make_shared(nullptr, root_fs_root_dentry, root_fs, nullptr)); // Mount devfs at /dev in rootfs (temporary, will be shadowed) auto device_fs = kstd::make_shared(); @@ -142,9 +142,12 @@ namespace kernel::filesystem // TODO BA-FS26 refactoring, implement dentry lookup to get the parent mount... auto parent_mount = m_mount_table.find_longest_prefix_mount(mount_path.view()); + // auto parent_mount_dentry = mount_point_dentry->get_parent_mounted_dentry(); + // auto parent_mount = m_mount_table.find_exact_mount(parent_mount_dentry->get_full_path()); + auto new_fs_root = kstd::make_shared(mount_point_dentry->get_parent(), fs->root_inode(), mount_point_dentry->get_name()); - auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, mount_path.view(), parent_mount); + auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, parent_mount); m_mount_table.add_mount(new_mount); } -- cgit v1.2.3 From feab4cd81f2bbc89e55353a54df2575b9c21b514 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Sun, 10 May 2026 20:07:51 +0200 Subject: Add method that returns the next ancestor with mount flag set --- kernel/src/filesystem/dentry.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index a77ce23..6945a27 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -66,6 +66,16 @@ namespace kernel::filesystem return path; } + auto dentry::get_ancestor_with_mount_flag() const -> kstd::shared_ptr + { + auto parent = m_parent; + while (parent && !parent->has_flag(dentry_flags::mounted)) + { + parent = parent->get_parent(); + } + return parent; + } + auto dentry::add_child(kstd::shared_ptr const & child) -> void { m_children.push_back(child); -- cgit v1.2.3 From 85fd2e3b4da7d84a9357b35bde740b780fe0cb72 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Sun, 10 May 2026 21:49:20 +0200 Subject: Rename root_dentry() to get_root_dentry() --- kernel/src/filesystem/mount.cpp | 2 +- kernel/src/filesystem/mount.tests.cpp | 2 +- kernel/src/filesystem/vfs.cpp | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index c474c8e..ebacf32 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -35,7 +35,7 @@ namespace kernel::filesystem return m_filesystem; } - auto mount::root_dentry() const -> kstd::shared_ptr const & + auto mount::get_root_dentry() const -> kstd::shared_ptr const & { return m_root_dentry; } diff --git a/kernel/src/filesystem/mount.tests.cpp b/kernel/src/filesystem/mount.tests.cpp index 4b44983..58e9bab 100644 --- a/kernel/src/filesystem/mount.tests.cpp +++ b/kernel/src/filesystem/mount.tests.cpp @@ -26,7 +26,7 @@ SCENARIO("Mount construction", "[filesystem][mount]") THEN("the mount has the correct filesystem, root dentry, mount dentry, and mount path") { REQUIRE(mount.get_filesystem() == fs); - REQUIRE(mount.root_dentry() == root_dentry); + REQUIRE(mount.get_root_dentry() == root_dentry); REQUIRE(mount.get_mount_dentry() == root_dentry); REQUIRE(mount.get_mount_path() == "/"); } diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index ea060a9..2b8c3bd 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -164,7 +164,7 @@ namespace kernel::filesystem kapi::system::panic("[FILESYSTEM] no root mount found."); } - auto current_dentry = current_mount->root_dentry(); + auto current_dentry = current_mount->get_root_dentry(); auto path_parts = path::split(path); kstd::vector path_parts_vector(path_parts.begin(), path_parts.end()); @@ -186,7 +186,7 @@ namespace kernel::filesystem { auto parent_dentry = current_dentry->get_parent(); - if (current_dentry == current_mount->root_dentry()) + if (current_dentry == current_mount->get_root_dentry()) { if (current_mount->get_mount_path() == "/") { @@ -225,7 +225,7 @@ namespace kernel::filesystem kapi::system::panic("[FILESYSTEM] mount for dentry with mounted flag not found."); } - next_dentry = current_mount->root_dentry(); + next_dentry = current_mount->get_root_dentry(); } if (next_dentry->get_inode()->is_symbolic_link()) @@ -248,7 +248,7 @@ namespace kernel::filesystem if (path::is_valid_absolute_path(symbolic_link_path)) { current_mount = m_mount_table.find_exact_mount("/"); - current_dentry = current_mount->root_dentry(); + current_dentry = current_mount->get_root_dentry(); } continue; } -- cgit v1.2.3 From 636551d03ac725e015dd88631d531c02067ed3de Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Sun, 10 May 2026 21:51:11 +0200 Subject: Create first draft of get_parent_mount without find_longest_prefix_mount --- kernel/src/filesystem/vfs.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 2b8c3bd..e7f9015 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -138,13 +138,13 @@ namespace kernel::filesystem auto vfs::do_mount_internal(kstd::shared_ptr const & mount_point_dentry, kstd::shared_ptr const & fs) -> void { - auto mount_path = mount_point_dentry->get_absolute_path(); - // TODO BA-FS26 refactoring, implement dentry lookup to get the parent mount... - auto parent_mount = m_mount_table.find_longest_prefix_mount(mount_path.view()); - - // auto parent_mount_dentry = mount_point_dentry->get_parent_mounted_dentry(); - // auto parent_mount = m_mount_table.find_exact_mount(parent_mount_dentry->get_full_path()); - + auto parent_mount_dentry = mount_point_dentry->get_ancestor_with_mount_flag(); + kstd::shared_ptr parent_mount = nullptr; + if (parent_mount_dentry) + { + parent_mount = m_mount_table.find_exact_mount(parent_mount_dentry->get_absolute_path().view()); + } + auto new_fs_root = kstd::make_shared(mount_point_dentry->get_parent(), fs->root_inode(), mount_point_dentry->get_name()); auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, parent_mount); -- cgit v1.2.3 From 763227e31adf924a5dfe3139db158e26162294a0 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Sun, 10 May 2026 21:58:54 +0200 Subject: Remove find_longest_prefix_mount --- kernel/src/filesystem/mount_table.cpp | 24 ------------------- kernel/src/filesystem/mount_table.tests.cpp | 37 ----------------------------- 2 files changed, 61 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index b67e05c..30a94f4 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -82,30 +82,6 @@ namespace kernel::filesystem return operation_result::removed; } - // TODO BA-FS26 remove? - auto mount_table::find_longest_prefix_mount(std::string_view path) const -> kstd::shared_ptr - { - kstd::shared_ptr mount_with_longest_prefix = nullptr; - std::size_t best_len = 0; - - for (auto const & mount : m_mounts) - { - auto mp = mount->get_mount_path(); - - // /a/b/c should match /a/b but not /a/bb or /a/b/c/d, / should match everything - bool is_prefix = path.starts_with(mp.view()) && (mp == "/" || path.size() == mp.size() || path[mp.size()] == '/'); - bool visible = is_visible_mount(mount, m_mounts); - - if (is_prefix && visible && mp.size() >= best_len) - { - mount_with_longest_prefix = mount; - best_len = mp.size(); - } - } - - return mount_with_longest_prefix; - } - auto mount_table::find_exact_mount(std::string_view path) const -> kstd::shared_ptr { auto reversed_mounts = std::ranges::reverse_view(m_mounts); diff --git a/kernel/src/filesystem/mount_table.tests.cpp b/kernel/src/filesystem/mount_table.tests.cpp index 732d32f..80772ca 100644 --- a/kernel/src/filesystem/mount_table.tests.cpp +++ b/kernel/src/filesystem/mount_table.tests.cpp @@ -19,12 +19,6 @@ SCENARIO("Mount table construction", "[filesystem][mount_table]") { kernel::filesystem::mount_table table; - THEN("finding any mount returns null") - { - REQUIRE(table.find_longest_prefix_mount("/") == nullptr); - REQUIRE(table.find_longest_prefix_mount("/any/path") == nullptr); - } - THEN("removing any mount returns mount_not_found") { REQUIRE(table.remove_mount("/") == kernel::filesystem::mount_table::operation_result::mount_not_found); @@ -62,15 +56,6 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] REQUIRE(mount_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); } - THEN("finding mounts by longest prefix returns the correct mount") - { - REQUIRE(table.find_longest_prefix_mount("/") == mount1); - REQUIRE(table.find_longest_prefix_mount("/file") == mount1); - REQUIRE(table.find_longest_prefix_mount("/mnt") == mount2); - REQUIRE(table.find_longest_prefix_mount("/mnt/file") == mount2); - REQUIRE(table.find_longest_prefix_mount("/other") == mount1); - } - THEN("finding mounts by exact valid path returns the correct mount") { REQUIRE(table.find_exact_mount("/") == mount1); @@ -87,7 +72,6 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] { REQUIRE(table.remove_mount("/mnt") == kernel::filesystem::mount_table::operation_result::removed); REQUIRE_FALSE(root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); - REQUIRE(table.find_longest_prefix_mount("/mnt") == mount1); } THEN("removing a mount that does not exist returns mount_not_found") @@ -117,15 +101,6 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] table.add_mount(mount1); table.add_mount(mount2); - THEN("finding mounts by longest prefix returns the correct mount") - { - REQUIRE(table.find_longest_prefix_mount("/") == mount2); - REQUIRE(table.find_longest_prefix_mount("/file") == mount2); - REQUIRE(table.find_longest_prefix_mount("/mnt") == mount2); - REQUIRE(table.find_longest_prefix_mount("/mnt/file") == mount2); - REQUIRE(table.find_longest_prefix_mount("/other") == mount2); - } - THEN("finding mounts by exact valid path returns the correct mount") { REQUIRE(table.find_exact_mount("/") == mount2); @@ -135,7 +110,6 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] { REQUIRE(table.remove_mount("/") == kernel::filesystem::mount_table::operation_result::removed); REQUIRE_FALSE(root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); - REQUIRE(table.find_longest_prefix_mount("/") == mount1); } } @@ -168,16 +142,6 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] table.add_mount(mount2); table.add_mount(mount3); - THEN("finding mounts by path returns the correct mount based on longest prefix") - { - REQUIRE(table.find_longest_prefix_mount("/") == mount1); - REQUIRE(table.find_longest_prefix_mount("/file") == mount1); - REQUIRE(table.find_longest_prefix_mount("/mnt") == mount2); - REQUIRE(table.find_longest_prefix_mount("/mnt/file") == mount2); - REQUIRE(table.find_longest_prefix_mount("/mnt/submnt") == mount3); - REQUIRE(table.find_longest_prefix_mount("/other") == mount1); - } - THEN("removing a mount with child mounts returns has_child_mounts") { REQUIRE(table.remove_mount("/") == kernel::filesystem::mount_table::operation_result::has_child_mounts); @@ -188,7 +152,6 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] { REQUIRE(table.remove_mount("/mnt/submnt") == kernel::filesystem::mount_table::operation_result::removed); REQUIRE_FALSE(root_dentry3->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); - REQUIRE(table.find_longest_prefix_mount("/mnt/submnt") == mount2); } } } -- cgit v1.2.3 From 5d72c256d4e2b8a9d2fd70e5a27e883a0f733e50 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 11 May 2026 20:48:03 +0200 Subject: Add is_mount_root flag to dentry and use in find_mount_root_dentry --- kernel/src/filesystem/dentry.cpp | 4 ++-- kernel/src/filesystem/dentry.tests.cpp | 14 +++++++------- kernel/src/filesystem/mount_table.cpp | 9 ++++++--- kernel/src/filesystem/mount_table.tests.cpp | 10 +++++----- kernel/src/filesystem/vfs.cpp | 4 ++-- 5 files changed, 22 insertions(+), 19 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index 6945a27..c21771b 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -66,10 +66,10 @@ namespace kernel::filesystem return path; } - auto dentry::get_ancestor_with_mount_flag() const -> kstd::shared_ptr + auto dentry::find_mount_root_dentry() const -> kstd::shared_ptr { auto parent = m_parent; - while (parent && !parent->has_flag(dentry_flags::mounted)) + while (parent && !parent->has_flag(dentry_flags::is_mount_root)) { parent = parent->get_parent(); } diff --git a/kernel/src/filesystem/dentry.tests.cpp b/kernel/src/filesystem/dentry.tests.cpp index dd01394..e9ecbc8 100644 --- a/kernel/src/filesystem/dentry.tests.cpp +++ b/kernel/src/filesystem/dentry.tests.cpp @@ -28,7 +28,7 @@ SCENARIO("Dentry construction", "[filesystem][dentry]") THEN("no flag is set") { - REQUIRE_FALSE(child_dentry.has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE_FALSE(child_dentry.has_flag(kernel::filesystem::dentry::dentry_flags::is_mount_point)); } } @@ -53,7 +53,7 @@ SCENARIO("Dentry construction", "[filesystem][dentry]") THEN("no flag is set") { - REQUIRE_FALSE(child_dentry.has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE_FALSE(child_dentry.has_flag(kernel::filesystem::dentry::dentry_flags::is_mount_point)); } } @@ -104,22 +104,22 @@ SCENARIO("Dentry Flag logic", "[filesystem][dentry]") WHEN("setting a flag") { - dentry.set_flag(kernel::filesystem::dentry::dentry_flags::mounted); + dentry.set_flag(kernel::filesystem::dentry::dentry_flags::is_mount_point); THEN("the flag is set") { - REQUIRE(dentry.has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE(dentry.has_flag(kernel::filesystem::dentry::dentry_flags::is_mount_point)); } } WHEN("unsetting a flag") { - dentry.set_flag(kernel::filesystem::dentry::dentry_flags::mounted); - dentry.unset_flag(kernel::filesystem::dentry::dentry_flags::mounted); + dentry.set_flag(kernel::filesystem::dentry::dentry_flags::is_mount_point); + dentry.unset_flag(kernel::filesystem::dentry::dentry_flags::is_mount_point); THEN("the flag is unset") { - REQUIRE_FALSE(dentry.has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE_FALSE(dentry.has_flag(kernel::filesystem::dentry::dentry_flags::is_mount_point)); } } } diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index 30a94f4..74c18ca 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -7,7 +7,6 @@ #include #include -#include #include #include @@ -56,7 +55,11 @@ namespace kernel::filesystem m_mounts.push_back(mount); if (auto mount_dentry = mount->get_mount_dentry()) { - mount_dentry->set_flag(dentry::dentry_flags::mounted); + mount_dentry->set_flag(dentry::dentry_flags::is_mount_point); + } + if (auto root_dentry = mount->get_root_dentry()) + { + root_dentry->set_flag(dentry::dentry_flags::is_mount_root); } } @@ -77,7 +80,7 @@ namespace kernel::filesystem return operation_result::has_child_mounts; } - mount->get_mount_dentry()->unset_flag(dentry::dentry_flags::mounted); + mount->get_mount_dentry()->unset_flag(dentry::dentry_flags::is_mount_point); m_mounts.erase(std::ranges::find(m_mounts, mount)); return operation_result::removed; } diff --git a/kernel/src/filesystem/mount_table.tests.cpp b/kernel/src/filesystem/mount_table.tests.cpp index 80772ca..4ae8711 100644 --- a/kernel/src/filesystem/mount_table.tests.cpp +++ b/kernel/src/filesystem/mount_table.tests.cpp @@ -52,8 +52,8 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("dentry flags are set correctly for mounted dentries") { - REQUIRE(mount_dentry1->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); - REQUIRE(mount_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE(mount_dentry1->has_flag(kernel::filesystem::dentry::dentry_flags::is_mount_point)); + REQUIRE(mount_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::is_mount_point)); } THEN("finding mounts by exact valid path returns the correct mount") @@ -71,7 +71,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("removing a mount that has no child mounts succeeds") { REQUIRE(table.remove_mount("/mnt") == kernel::filesystem::mount_table::operation_result::removed); - REQUIRE_FALSE(root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE_FALSE(root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::is_mount_point)); } THEN("removing a mount that does not exist returns mount_not_found") @@ -109,7 +109,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("removing the topmost mount with the same path succeeds") { REQUIRE(table.remove_mount("/") == kernel::filesystem::mount_table::operation_result::removed); - REQUIRE_FALSE(root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE_FALSE(root_dentry2->has_flag(kernel::filesystem::dentry::dentry_flags::is_mount_point)); } } @@ -151,7 +151,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("removing a leaf mount succeeds") { REQUIRE(table.remove_mount("/mnt/submnt") == kernel::filesystem::mount_table::operation_result::removed); - REQUIRE_FALSE(root_dentry3->has_flag(kernel::filesystem::dentry::dentry_flags::mounted)); + REQUIRE_FALSE(root_dentry3->has_flag(kernel::filesystem::dentry::dentry_flags::is_mount_point)); } } } diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index e7f9015..ee7c262 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -138,7 +138,7 @@ namespace kernel::filesystem auto vfs::do_mount_internal(kstd::shared_ptr const & mount_point_dentry, kstd::shared_ptr const & fs) -> void { - auto parent_mount_dentry = mount_point_dentry->get_ancestor_with_mount_flag(); + auto parent_mount_dentry = mount_point_dentry->find_mount_root_dentry(); kstd::shared_ptr parent_mount = nullptr; if (parent_mount_dentry) { @@ -217,7 +217,7 @@ namespace kernel::filesystem next_dentry = kstd::make_shared(current_dentry, found_inode, part.view()); current_dentry->add_child(next_dentry); } - else if (next_dentry->has_flag(dentry::dentry_flags::mounted)) + else if (next_dentry->has_flag(dentry::dentry_flags::is_mount_point)) { current_mount = m_mount_table.find_exact_mount(next_dentry->get_absolute_path().view()); if (!current_mount) -- cgit v1.2.3 From 5bac7cc7cc37d137b633afd3910f251a22818b80 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Mon, 11 May 2026 22:49:22 +0200 Subject: fix build after rebase --- kernel/src/filesystem/mount.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index ebacf32..749c86a 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -44,7 +44,7 @@ namespace kernel::filesystem { if (m_mount_dentry) { - return m_mount_dentry->get_full_path(); + return m_mount_dentry->get_absolute_path(); } return "/"; } -- cgit v1.2.3 From cb86b1fdb4656d37937a27343a4971ee5896bd3a Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 12 May 2026 08:51:17 +0200 Subject: remove unused include --- kernel/src/main.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index bfb731a..22d2b1e 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,6 +1,4 @@ #include -#include -#include #include #include #include @@ -15,7 +13,6 @@ #include #include -#include #include #include #include -- cgit v1.2.3 From ac5213633721fcf0e72da814d7ef70c51090c3f9 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 12 May 2026 08:51:49 +0200 Subject: refactoring, simplify code --- kernel/src/filesystem/mount_table.cpp | 51 +++++++---------------------------- 1 file changed, 10 insertions(+), 41 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index 74c18ca..daef93e 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -12,38 +12,6 @@ namespace kernel::filesystem { - namespace - { - auto is_descendant_of(kstd::shared_ptr const & candidate, kstd::shared_ptr const & ancestor) -> bool - { - for (auto current = candidate; current; current = current->get_parent_mount()) - { - if (current == ancestor) - { - return true; - } - } - - return false; - } - - auto is_strict_prefix(std::string_view prefix, std::string_view path) -> bool - { - return prefix != "/" && path.starts_with(prefix) && path.size() > prefix.size() && path[prefix.size()] == '/'; - } - - auto is_visible_mount(kstd::shared_ptr const & candidate, - kstd::vector> const & mounts) -> bool - { - return std::ranges::none_of(mounts, [&](auto const & other) { - // TODO BA-FS26 really correct? - return other != candidate && - is_strict_prefix(other->get_mount_path().view(), candidate->get_mount_path().view()) && - !is_descendant_of(candidate, other); - }); - } - } // namespace - auto mount_table::has_child_mounts(kstd::shared_ptr const & parent_mount) const -> bool { return std::ranges::any_of( @@ -53,6 +21,7 @@ namespace kernel::filesystem void mount_table::add_mount(kstd::shared_ptr const & mount) { m_mounts.push_back(mount); + if (auto mount_dentry = mount->get_mount_dentry()) { mount_dentry->set_flag(dentry::dentry_flags::is_mount_point); @@ -65,11 +34,11 @@ namespace kernel::filesystem auto mount_table::remove_mount(std::string_view path) -> operation_result { - auto mount_it = std::ranges::find_if(std::ranges::reverse_view(m_mounts), [&](auto const & mount) { - return mount->get_mount_path() == path && is_visible_mount(mount, m_mounts); - }); + auto mount_range = + std::ranges::find_last_if(m_mounts, [&](auto const & mount) { return mount->get_mount_path() == path; }); + auto mount_it = mount_range.begin(); - if (mount_it == std::ranges::reverse_view(m_mounts).end()) + if (mount_it == m_mounts.end()) { return operation_result::mount_not_found; } @@ -81,15 +50,15 @@ namespace kernel::filesystem } mount->get_mount_dentry()->unset_flag(dentry::dentry_flags::is_mount_point); - m_mounts.erase(std::ranges::find(m_mounts, mount)); + m_mounts.erase(mount_it); return operation_result::removed; } auto mount_table::find_exact_mount(std::string_view path) const -> kstd::shared_ptr { - auto reversed_mounts = std::ranges::reverse_view(m_mounts); - auto mount_it = - std::ranges::find_if(reversed_mounts, [&](auto const & mount) { return mount->get_mount_path() == path; }); - return (mount_it != reversed_mounts.end()) ? *mount_it : nullptr; + auto mount_range = + std::ranges::find_last_if(m_mounts, [&](auto const & mount) { return mount->get_mount_path() == path; }); + auto mount_it = mount_range.begin(); + return (mount_it != m_mounts.end()) ? *mount_it : nullptr; } } // namespace kernel::filesystem \ No newline at end of file -- cgit v1.2.3 From 91821da0110e05724640903434c3d85fc3d02466 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Tue, 12 May 2026 12:00:40 +0200 Subject: if the boot_root_fs contains a /dev directory, vfs mounts the devfs onto the existing directory --- kernel/src/filesystem/vfs.cpp | 40 +++++++++++++++------- kernel/src/filesystem/vfs.tests.cpp | 17 +++++++++ .../filesystem/test_assets/ext2_2KB_fs.img | 2 +- 3 files changed, 45 insertions(+), 14 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index ee7c262..535f898 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -41,36 +41,35 @@ namespace kernel::filesystem auto vfs::init_internal() -> void { + // mount rootfs at / auto root_fs = kstd::make_shared(); root_fs->mount(nullptr); auto root_fs_root_dentry = kstd::make_shared(nullptr, root_fs->root_inode(), "/"); m_mount_table.add_mount(kstd::make_shared(nullptr, root_fs_root_dentry, root_fs, nullptr)); - // Mount devfs at /dev in rootfs (temporary, will be shadowed) + // mount devfs at /dev (inside rootfs, temporary, will be shadowed) auto device_fs = kstd::make_shared(); device_fs->mount(nullptr); - auto dev_mount_point_dentry = resolve_path("/dev"); - if (!dev_mount_point_dentry) + + if (auto dev_mount_point_dentry = resolve_path("/dev")) + { + do_mount_internal(dev_mount_point_dentry, device_fs); + } + else { kapi::system::panic("[FILESYSTEM] failed to resolve /dev for initial devfs mount."); } - do_mount_internal(dev_mount_point_dentry, device_fs); - // Mount boot filesystem at / (will shadow rootfs) + // mount boot fs at / (shadows rootfs), re-graft devfs if (auto boot_device_dentry = resolve_path("/dev/ram0")) { if (auto boot_root_fs = kernel::filesystem::filesystem::probe_and_mount(boot_device_dentry->get_inode())) { - do_mount_internal(root_fs_root_dentry, boot_root_fs); - - // Resolve / to get the boot root dentry - if (auto boot_root_dentry = resolve_path("/")) + if (auto root_dentry = resolve_path("/")) { - auto dev_dentry = kstd::make_shared(boot_root_dentry, device_fs->root_inode(), "dev"); - boot_root_dentry->add_child(dev_dentry); - - do_mount_internal(dev_dentry, device_fs); + do_mount_internal(root_dentry, boot_root_fs); + graft_persistent_device_fs(device_fs); } } } @@ -151,6 +150,21 @@ namespace kernel::filesystem m_mount_table.add_mount(new_mount); } + auto vfs::graft_persistent_device_fs(kstd::shared_ptr const & device_fs) -> void + { + if (auto new_root_dentry = resolve_path("/")) + { + auto dev_dentry = new_root_dentry->find_child("dev"); + if (!dev_dentry) + { + dev_dentry = kstd::make_shared(new_root_dentry, device_fs->root_inode(), "dev"); + new_root_dentry->add_child(dev_dentry); + } + + do_mount_internal(dev_dentry, device_fs); + } + } + auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr { if (!path::is_valid_absolute_path(path)) diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 8e4cb70..add96aa 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -62,6 +62,23 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS } } + GIVEN("a real image file containing a /dev directory") + { + REQUIRE(std::filesystem::exists(image_path_2)); + REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module_2"}, {image_path_2})); + + THEN("vfs hides the image's /dev behind the devfs mount") + { + auto & vfs = kernel::filesystem::vfs::get(); + + auto image_1 = vfs.open("/dev/image_1.txt"); + REQUIRE(image_1 == nullptr); + + auto dev = vfs.open("/dev/ram0"); + REQUIRE(dev != nullptr); + } + } + GIVEN("three real image files") { REQUIRE(std::filesystem::exists(image_path_1)); diff --git a/kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img b/kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img index 8327022..7f297f0 100644 --- a/kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img +++ b/kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1d102f2e40083613060d43b2b32d31031137bbef99761a2d1bf4d38e155adb7 +oid sha256:6d9e872916e7d9107b321cc007e151899d5f19400a694666c0b24d482aef61ca size 5242880 -- cgit v1.2.3 From 988977b80cd118749b6b813e0909f4607a4f27fe Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Tue, 12 May 2026 13:50:56 +0200 Subject: Determine ext2 inode size depending on revision level, add const to several methods --- kernel/src/filesystem/ext2/filesystem.cpp | 20 +++++++++++++------- kernel/src/filesystem/ext2/inode.cpp | 20 ++++++++++++++++---- 2 files changed, 29 insertions(+), 11 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 47e54fe..aaa50c7 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -89,7 +89,7 @@ namespace kernel::filesystem::ext2 return nullptr; } - auto filesystem::read_inode(uint32_t inode_number) -> kstd::shared_ptr + auto filesystem::read_inode(uint32_t inode_number) const -> kstd::shared_ptr { auto const block_size = get_block_size(); auto const inodes_per_group = m_superblock.inodes_per_group; @@ -112,7 +112,8 @@ namespace kernel::filesystem::ext2 return kstd::make_shared(this, new_inode_data); } - auto filesystem::map_inode_block_index_to_global_block_number(uint32_t inode_block_index, inode_data data) -> uint32_t + auto filesystem::map_inode_block_index_to_global_block_number(uint32_t inode_block_index, inode_data data) const + -> uint32_t { if (inode_block_index < constants::direct_block_count) { @@ -170,7 +171,7 @@ namespace kernel::filesystem::ext2 return 0; // TODO BA-FS26 really correct?? } - auto filesystem::read_block_number_at_index(uint32_t block_number, uint32_t index) -> uint32_t + auto filesystem::read_block_number_at_index(uint32_t block_number, uint32_t index) const -> uint32_t { uint32_t block_number_buffer = 0; @@ -181,17 +182,22 @@ namespace kernel::filesystem::ext2 return block_number_buffer; } - auto filesystem::get_block_size() -> size_t + auto filesystem::get_block_size() const -> size_t { return constants::base_block_size << m_superblock.log_block_size; } - auto filesystem::get_inode_size() -> size_t + auto filesystem::get_revision_level() const -> size_t { - return m_superblock.rev_level == 0 ? 128 : m_superblock.inode_size; + return m_superblock.rev_level; } - auto filesystem::get_inode_block_count(inode_data const & data) -> uint32_t + auto filesystem::get_inode_size() const -> size_t + { + return get_revision_level() == constants::good_old_revision ? 128 : m_superblock.inode_size; + } + + auto filesystem::get_inode_block_count(inode_data const & data) const -> uint32_t { return data.blocks / (2 << m_superblock.log_block_size); } diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp index 1914c70..303838e 100644 --- a/kernel/src/filesystem/ext2/inode.cpp +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -13,7 +13,7 @@ namespace kernel::filesystem::ext2 { - inode::inode(filesystem * fs, inode_data const & data) + inode::inode(filesystem const * fs, inode_data const & data) : m_filesystem(fs) , m_data(data) { @@ -25,11 +25,10 @@ namespace kernel::filesystem::ext2 auto inode::read(void * buffer, size_t offset, size_t size) const -> size_t { - // TODO BA-FS26 use revision 1 size - auto const max_readable = static_cast(m_data.size) - offset; + auto const max_readable = get_size() - offset; auto const requested_size = std::min(size, max_readable); - if (is_symbolic_link() && m_data.size <= sizeof(m_data.block)) + if (is_symbolic_link() && get_size() <= sizeof(m_data.block)) { auto inline_target = reinterpret_cast(m_data.block.data()); kstd::libc::memcpy(static_cast(buffer), inline_target + offset, requested_size); @@ -91,4 +90,17 @@ namespace kernel::filesystem::ext2 { return (m_data.mode & constants::mode_mask) == constants::mode_symbolic_link; } + + auto inode::get_size() const -> size_t + { + uint64_t size = m_data.size; + + if (m_filesystem->get_revision_level() > constants::good_old_revision && is_regular()) + { + size |= static_cast(m_data.dir_acl) << 32; + } + + return size; + } + } // namespace kernel::filesystem::ext2 -- cgit v1.2.3 From 7b1e578480f2f522fe39a742e688012a7f5ea4ed Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Tue, 12 May 2026 14:46:02 +0200 Subject: Add tests for ext2 inode get_size() --- kernel/src/filesystem/ext2/inode.tests.cpp | 90 ++++++++++++++++++++++++++++- kernel/src/test_support/filesystem/ext2.cpp | 6 ++ 2 files changed, 94 insertions(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/inode.tests.cpp b/kernel/src/filesystem/ext2/inode.tests.cpp index 49ba21b..783d930 100644 --- a/kernel/src/filesystem/ext2/inode.tests.cpp +++ b/kernel/src/filesystem/ext2/inode.tests.cpp @@ -1,5 +1,6 @@ #include +#include "kernel/filesystem/ext2/superblock.hpp" #include #include #include @@ -127,7 +128,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 in SCENARIO("Ext2 inode read stops when block mapping resolves to zero", "[filesystem][ext2][inode]") { - auto const block_size = 1024; + auto const block_size = 1024uz; GIVEN("an ext2 inode without mapped data blocks") { auto device = kstd::make_shared(0, 0, "mock", block_size, 64 * block_size); @@ -156,7 +157,7 @@ SCENARIO("Ext2 inode read stops when block mapping resolves to zero", "[filesyst SCENARIO("Ext2 inode read across block boundaries", "[filesystem][ext2][inode]") { - auto const block_size = 1024; + auto const block_size = 1024uz; GIVEN("an ext2 inode with two direct blocks and a block size of 1024 bytes") { auto device = kstd::make_shared(0, 0, "mock", block_size, 64 * block_size); @@ -203,3 +204,88 @@ SCENARIO("Ext2 inode write is not implemented", "[filesystem][ext2][inode]") } } } + +SCENARIO("Ext2 inode get_size() correctly returns size depending on revision level", "[filesystem][ext2][inode]") +{ + auto const block_size = 1024uz; + + auto superblock = kernel::filesystem::ext2::superblock{}; + superblock.magic = kernel::filesystem::ext2::constants::magic_number; + superblock.log_block_size = 0; + superblock.blocks_count = 64; + superblock.blocks_per_group = 64; + superblock.inodes_per_group = 32; + superblock.inode_size = 128; + + GIVEN("an ext2 inode with good old revision and inode_data.size = 256, inode_data.dir_acl = 32") + { + superblock.rev_level = 0; + + auto device = kstd::make_shared(0, 0, "mock", block_size, 64 * block_size); + REQUIRE(device != nullptr); + kernel::tests::filesystem::ext2::setup_mock_ext2_layout(*device, superblock); + + auto dev_inode = kstd::make_shared(device); + + auto fs = kernel::filesystem::ext2::filesystem{}; + REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success); + + auto data = kernel::filesystem::ext2::inode_data{}; + data.size = 256; + data.dir_acl = 32; + + THEN("the inode size is 256 if mode = regular") + { + data.mode = kernel::filesystem::ext2::constants::mode_regular; + + auto inode = kernel::filesystem::ext2::inode{&fs, data}; + + REQUIRE(inode.get_size() == 256); + } + + THEN("the inode size is 256 if mode = directory") + { + data.mode = kernel::filesystem::ext2::constants::mode_directory; + + auto inode = kernel::filesystem::ext2::inode{&fs, data}; + + REQUIRE(inode.get_size() == 256); + } + } + + GIVEN("an ext2 inode with good dynamic revision and inode_data.size = 256, inode_data.dir_acl = 32") + { + superblock.rev_level = 1; + + auto device = kstd::make_shared(0, 0, "mock", block_size, 64 * block_size); + REQUIRE(device != nullptr); + kernel::tests::filesystem::ext2::setup_mock_ext2_layout(*device, superblock); + + auto dev_inode = kstd::make_shared(device); + + auto fs = kernel::filesystem::ext2::filesystem{}; + REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success); + + auto data = kernel::filesystem::ext2::inode_data{}; + data.size = 256; + data.dir_acl = 32; + + THEN("the inode size is 256 if mode = regular") + { + data.mode = kernel::filesystem::ext2::constants::mode_regular; + + auto inode = kernel::filesystem::ext2::inode{&fs, data}; + + REQUIRE(inode.get_size() == 0x0000'0020'0000'0100); + } + + THEN("the inode size is 256 if mode = directory") + { + data.mode = kernel::filesystem::ext2::constants::mode_directory; + + auto inode = kernel::filesystem::ext2::inode{&fs, data}; + + REQUIRE(inode.get_size() == 256); + } + } +} \ No newline at end of file diff --git a/kernel/src/test_support/filesystem/ext2.cpp b/kernel/src/test_support/filesystem/ext2.cpp index 5a27b63..52b6efe 100644 --- a/kernel/src/test_support/filesystem/ext2.cpp +++ b/kernel/src/test_support/filesystem/ext2.cpp @@ -43,6 +43,12 @@ namespace kernel::tests::filesystem::ext2 superblock.inodes_per_group = 32; superblock.rev_level = 1; superblock.inode_size = 128; + setup_mock_ext2_layout(device, superblock); + } + + auto setup_mock_ext2_layout(kernel::tests::devices::block_device & device, + kernel::filesystem::ext2::superblock const & superblock) -> void + { write_bytes(device, kernel::filesystem::ext2::constants::superblock_offset, &superblock, sizeof(superblock)); auto group_descriptor = kernel::filesystem::ext2::block_group_descriptor{}; -- cgit v1.2.3 From d061f31f33feccb4203979c6e8d9bbaeabecb453 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 13 May 2026 10:13:13 +0200 Subject: refactor ext2 map_inode_block_index_to_global_block_number --- kernel/src/filesystem/ext2/filesystem.cpp | 86 ++++++++++++++++++------- kernel/src/filesystem/ext2/filesystem.tests.cpp | 2 +- kernel/src/filesystem/vfs.cpp | 2 +- 3 files changed, 63 insertions(+), 27 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index aaa50c7..0f34cfe 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace kernel::filesystem::ext2 { @@ -113,7 +114,7 @@ namespace kernel::filesystem::ext2 } auto filesystem::map_inode_block_index_to_global_block_number(uint32_t inode_block_index, inode_data data) const - -> uint32_t + -> ssize_t { if (inode_block_index < constants::direct_block_count) { @@ -121,9 +122,7 @@ namespace kernel::filesystem::ext2 } inode_block_index -= constants::direct_block_count; - auto const block_size = get_block_size(); - auto const numbers_per_block = block_size / sizeof(uint32_t); - + auto const numbers_per_block = block_numbers_per_block(); auto const block_numbers_per_singly_indirect_block = numbers_per_block; auto const block_numbers_per_doubly_indirect_block = numbers_per_block * block_numbers_per_singly_indirect_block; auto const block_numbers_per_triply_indirect_block = numbers_per_block * block_numbers_per_doubly_indirect_block; @@ -131,44 +130,76 @@ namespace kernel::filesystem::ext2 if (inode_block_index < block_numbers_per_singly_indirect_block) { auto const singly_indirect_block_number = data.block.at(constants::singly_indirect_block_index); - return read_block_number_at_index(singly_indirect_block_number, inode_block_index); + return read_singly_indirect_block_number(singly_indirect_block_number, inode_block_index); } inode_block_index -= block_numbers_per_singly_indirect_block; if (inode_block_index < block_numbers_per_doubly_indirect_block) { auto const doubly_indirect_block_number = data.block.at(constants::doubly_indirect_block_index); - auto const singly_indirect_block_index_in_doubly_indirect_block = - inode_block_index / block_numbers_per_singly_indirect_block; - auto const singly_indirect_block_number = read_block_number_at_index( - doubly_indirect_block_number, singly_indirect_block_index_in_doubly_indirect_block); - - auto const block_index_in_singly_indirect_block = inode_block_index % block_numbers_per_singly_indirect_block; - return read_block_number_at_index(singly_indirect_block_number, block_index_in_singly_indirect_block); + return read_doubly_indirect_block_number(doubly_indirect_block_number, inode_block_index); } inode_block_index -= block_numbers_per_doubly_indirect_block; if (inode_block_index < block_numbers_per_triply_indirect_block) { auto const triply_indirect_block_number = data.block.at(constants::triply_indirect_block_index); - auto const doubly_indirect_block_index_in_triply_indirect_block = - inode_block_index / block_numbers_per_doubly_indirect_block; - auto const doubly_indirect_block_number = read_block_number_at_index( - triply_indirect_block_number, doubly_indirect_block_index_in_triply_indirect_block); + return read_triply_indirect_block_number(triply_indirect_block_number, inode_block_index); + } + + return -1; + } + + auto filesystem::read_singly_indirect_block_number(uint32_t singly_indirect_block_number, + uint32_t block_index_in_singly_indirect_block) const -> uint32_t + { + if (singly_indirect_block_number == 0) + { + return 0; + } + return read_block_number_at_index(singly_indirect_block_number, block_index_in_singly_indirect_block); + } + + auto filesystem::read_doubly_indirect_block_number(uint32_t doubly_indirect_block_number, + uint32_t block_index_in_doubly_indirect_block) const -> uint32_t + { + auto const block_numbers_per_singly_indirect_block = block_numbers_per_block(); - auto const remaining_block_numbers = inode_block_index % block_numbers_per_doubly_indirect_block; + if (doubly_indirect_block_number == 0) + { + return 0; + } + + auto const singly_indirect_block_index_in_doubly_indirect_block = + block_index_in_doubly_indirect_block / block_numbers_per_singly_indirect_block; + auto const block_index_in_singly_indirect_block = + block_index_in_doubly_indirect_block % block_numbers_per_singly_indirect_block; + + auto const singly_indirect_block_number = + read_block_number_at_index(doubly_indirect_block_number, singly_indirect_block_index_in_doubly_indirect_block); - auto const singly_indirect_block_index_in_doubly_indirect_block = - remaining_block_numbers / block_numbers_per_singly_indirect_block; - auto const singly_indirect_block_number = read_block_number_at_index( - doubly_indirect_block_number, singly_indirect_block_index_in_doubly_indirect_block); + return read_singly_indirect_block_number(singly_indirect_block_number, block_index_in_singly_indirect_block); + } + + auto filesystem::read_triply_indirect_block_number(uint32_t triply_indirect_block_number, + uint32_t block_index_in_triply_indirect_block) const -> uint32_t + { + auto const block_numbers_per_doubly_indirect_block = block_numbers_per_block() * block_numbers_per_block(); - auto const block_index_in_singly_indirect_block = - remaining_block_numbers % block_numbers_per_singly_indirect_block; - return read_block_number_at_index(singly_indirect_block_number, block_index_in_singly_indirect_block); + if (triply_indirect_block_number == 0) + { + return 0; } - return 0; // TODO BA-FS26 really correct?? + auto const doubly_indirect_block_index_in_triply_indirect_block = + block_index_in_triply_indirect_block / block_numbers_per_doubly_indirect_block; + auto const block_index_in_doubly_indirect_block = + block_index_in_triply_indirect_block % block_numbers_per_doubly_indirect_block; + + auto const doubly_indirect_block_number = + read_block_number_at_index(triply_indirect_block_number, doubly_indirect_block_index_in_triply_indirect_block); + + return read_doubly_indirect_block_number(doubly_indirect_block_number, block_index_in_doubly_indirect_block); } auto filesystem::read_block_number_at_index(uint32_t block_number, uint32_t index) const -> uint32_t @@ -182,6 +213,11 @@ namespace kernel::filesystem::ext2 return block_number_buffer; } + auto filesystem::block_numbers_per_block() const -> uint32_t + { + return get_block_size() / sizeof(uint32_t); + } + auto filesystem::get_block_size() const -> size_t { return constants::base_block_size << m_superblock.log_block_size; diff --git a/kernel/src/filesystem/ext2/filesystem.tests.cpp b/kernel/src/filesystem/ext2/filesystem.tests.cpp index 31c4c29..8341070 100644 --- a/kernel/src/filesystem/ext2/filesystem.tests.cpp +++ b/kernel/src/filesystem/ext2/filesystem.tests.cpp @@ -133,7 +133,7 @@ SCENARIO("Ext2 block mapping includes direct and all indirect levels", "[filesys THEN("mapping returns zero for out-of-range indexes") { auto const beyond_triply = triply_start + numbers_per_block * numbers_per_block * numbers_per_block; - REQUIRE(fs.map_inode_block_index_to_global_block_number(beyond_triply, inode_data) == 0); + REQUIRE(fs.map_inode_block_index_to_global_block_number(beyond_triply, inode_data) == -1); } } } diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 535f898..f5d57be 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -143,7 +143,7 @@ namespace kernel::filesystem { parent_mount = m_mount_table.find_exact_mount(parent_mount_dentry->get_absolute_path().view()); } - + auto new_fs_root = kstd::make_shared(mount_point_dentry->get_parent(), fs->root_inode(), mount_point_dentry->get_name()); auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, parent_mount); -- cgit v1.2.3 From de0ef46e7bab75d0ab94f02d569df62e2b4281f2 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 13 May 2026 10:14:21 +0200 Subject: implement sparse files, fix bug with reading more than inode size --- kernel/src/filesystem/ext2/inode.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp index 303838e..cfe0a35 100644 --- a/kernel/src/filesystem/ext2/inode.cpp +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -40,23 +40,29 @@ namespace kernel::filesystem::ext2 auto bytes_read = 0uz; - while (bytes_read < size) + while (bytes_read < requested_size) { auto const block_number = m_filesystem->map_inode_block_index_to_global_block_number(block_index, m_data); - // TODO BA-FS26 really correct? sparse files -> 0 means a full block with zeros --> function - // map_inode_block_index_to_global_block_number should return 0 if not possible to find an block - if (block_number == 0) + if (block_number == -1) { break; } - auto const block_start_offset = block_number * m_filesystem->get_block_size(); - auto const read_offset = block_start_offset + in_block_offset; auto const bytes_to_read = std::min(requested_size - bytes_read, m_filesystem->get_block_size() - in_block_offset); + if (block_number == 0) + { + kstd::libc::memset(static_cast(buffer) + bytes_read, 0, bytes_to_read); + bytes_read += bytes_to_read; + } + else + { + auto const block_start_offset = block_number * m_filesystem->get_block_size(); + auto const read_offset = block_start_offset + in_block_offset; - bytes_read += - m_filesystem->backing_inode()->read(static_cast(buffer) + bytes_read, read_offset, bytes_to_read); + bytes_read += m_filesystem->backing_inode()->read(static_cast(buffer) + bytes_read, read_offset, + bytes_to_read); + } block_index++; in_block_offset = 0; // After the first block, we always start at the beginning of the block -- cgit v1.2.3 From 06b4c8bebbcd8aa845a845817cdeceeb86fbfc13 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 13 May 2026 10:15:09 +0200 Subject: add todos --- kernel/src/filesystem/mount_table.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index daef93e..5a49e7a 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -34,6 +34,7 @@ namespace kernel::filesystem auto mount_table::remove_mount(std::string_view path) -> operation_result { + // TODO BA-FS26 check wheter something is open in this mount auto mount_range = std::ranges::find_last_if(m_mounts, [&](auto const & mount) { return mount->get_mount_path() == path; }); auto mount_it = mount_range.begin(); -- cgit v1.2.3 From f0715177763e1154668a656fbd7abfb8bb2c3261 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 13 May 2026 11:04:47 +0200 Subject: add inode sparse files tests --- kernel/src/filesystem/ext2/inode.tests.cpp | 101 ++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 8 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/inode.tests.cpp b/kernel/src/filesystem/ext2/inode.tests.cpp index 783d930..8381ee0 100644 --- a/kernel/src/filesystem/ext2/inode.tests.cpp +++ b/kernel/src/filesystem/ext2/inode.tests.cpp @@ -15,6 +15,7 @@ #include +#include #include #include #include @@ -126,10 +127,10 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 in } } -SCENARIO("Ext2 inode read stops when block mapping resolves to zero", "[filesystem][ext2][inode]") +SCENARIO("Ext2 inode handles zeros in block mappings as file holes", "[filesystem][ext2][inode]") { auto const block_size = 1024uz; - GIVEN("an ext2 inode without mapped data blocks") + GIVEN("an ext2 inode with only direct mapped data blocks") { auto device = kstd::make_shared(0, 0, "mock", block_size, 64 * block_size); REQUIRE(device != nullptr); @@ -141,16 +142,100 @@ SCENARIO("Ext2 inode read stops when block mapping resolves to zero", "[filesyst REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success); auto data = kernel::filesystem::ext2::inode_data{}; - data.blocks = 2; - data.block[0] = 0; + data.block[0] = 30; + data.block[1] = 0; + data.block[2] = 31; + data.size = block_size * 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); + + auto inode = kernel::filesystem::ext2::inode{&fs, data}; + + auto buffer = kstd::vector(data.size, std::byte{0xAB}); + + 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 text = std::string_view{reinterpret_cast(buffer.data()), bytes_read}; + 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'; })); + } + } + + GIVEN("an ext2 indode with file holes in singly indirect blocks") + { + auto device = kstd::make_shared(0, 0, "mock", block_size, 64 * block_size); + REQUIRE(device != nullptr); + kernel::tests::filesystem::ext2::setup_mock_ext2_layout(*device); + + auto dev_inode = kstd::make_shared(device); + + auto fs = kernel::filesystem::ext2::filesystem{}; + REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success); + + auto data = kernel::filesystem::ext2::inode_data{}; + data.block[0] = 30; + data.block[12] = 31; + data.size = block_size * 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_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); + + auto inode = kernel::filesystem::ext2::inode{&fs, data}; + + auto buffer = kstd::vector(data.size, std::byte{0xAB}); + + 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 text = std::string_view{reinterpret_cast(buffer.data()), bytes_read}; + 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'; })); + } + } + + GIVEN("an ext2 inode with zero singly indirect block pointer") + { + auto device = kstd::make_shared(0, 0, "mock", block_size, 64 * block_size); + REQUIRE(device != nullptr); + kernel::tests::filesystem::ext2::setup_mock_ext2_layout(*device); + + auto dev_inode = kstd::make_shared(device); + + auto fs = kernel::filesystem::ext2::filesystem{}; + REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success); + + auto data = kernel::filesystem::ext2::inode_data{}; + data.block[12] = 0; + data.size = block_size * 15; + auto inode = kernel::filesystem::ext2::inode{&fs, data}; - auto buffer = kstd::vector(32, std::byte{0xAB}); + auto buffer = kstd::vector(block_size * 3, std::byte{0xAB}); - THEN("no bytes are read") + 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 == 0); + REQUIRE(bytes_read == buffer.size()); + REQUIRE(std::ranges::all_of(buffer, [](std::byte c) { return c == std::byte{0x00}; })); } } } @@ -170,7 +255,7 @@ SCENARIO("Ext2 inode read across block boundaries", "[filesystem][ext2][inode]") REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success); auto inode_data = kernel::filesystem::ext2::inode_data{}; - inode_data.blocks = 2; + inode_data.size = block_size * 2; inode_data.block[0] = 20; kernel::tests::filesystem::ext2::write_bytes(*device, 21 * block_size - 6, "Hello ", 6); inode_data.block[1] = 21; -- cgit v1.2.3 From 117b16cc5e3506da637a806a25bb22b82a02ef9e Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 13 May 2026 11:11:22 +0200 Subject: refactoring --- kernel/src/filesystem/ext2/filesystem.cpp | 42 ++++++++++++++++++------------- 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 0f34cfe..893cc38 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -122,26 +122,21 @@ namespace kernel::filesystem::ext2 } inode_block_index -= constants::direct_block_count; - auto const numbers_per_block = block_numbers_per_block(); - auto const block_numbers_per_singly_indirect_block = numbers_per_block; - auto const block_numbers_per_doubly_indirect_block = numbers_per_block * block_numbers_per_singly_indirect_block; - auto const block_numbers_per_triply_indirect_block = numbers_per_block * block_numbers_per_doubly_indirect_block; - - if (inode_block_index < block_numbers_per_singly_indirect_block) + if (inode_block_index < block_numbers_per_singly_indirect_block()) { auto const singly_indirect_block_number = data.block.at(constants::singly_indirect_block_index); return read_singly_indirect_block_number(singly_indirect_block_number, inode_block_index); } - inode_block_index -= block_numbers_per_singly_indirect_block; + inode_block_index -= block_numbers_per_singly_indirect_block(); - if (inode_block_index < block_numbers_per_doubly_indirect_block) + if (inode_block_index < block_numbers_per_doubly_indirect_block()) { auto const doubly_indirect_block_number = data.block.at(constants::doubly_indirect_block_index); return read_doubly_indirect_block_number(doubly_indirect_block_number, inode_block_index); } - inode_block_index -= block_numbers_per_doubly_indirect_block; + inode_block_index -= block_numbers_per_doubly_indirect_block(); - if (inode_block_index < block_numbers_per_triply_indirect_block) + if (inode_block_index < block_numbers_per_triply_indirect_block()) { auto const triply_indirect_block_number = data.block.at(constants::triply_indirect_block_index); return read_triply_indirect_block_number(triply_indirect_block_number, inode_block_index); @@ -163,17 +158,15 @@ namespace kernel::filesystem::ext2 auto filesystem::read_doubly_indirect_block_number(uint32_t doubly_indirect_block_number, uint32_t block_index_in_doubly_indirect_block) const -> uint32_t { - auto const block_numbers_per_singly_indirect_block = block_numbers_per_block(); - if (doubly_indirect_block_number == 0) { return 0; } auto const singly_indirect_block_index_in_doubly_indirect_block = - block_index_in_doubly_indirect_block / block_numbers_per_singly_indirect_block; + block_index_in_doubly_indirect_block / block_numbers_per_singly_indirect_block(); auto const block_index_in_singly_indirect_block = - block_index_in_doubly_indirect_block % block_numbers_per_singly_indirect_block; + block_index_in_doubly_indirect_block % block_numbers_per_singly_indirect_block(); auto const singly_indirect_block_number = read_block_number_at_index(doubly_indirect_block_number, singly_indirect_block_index_in_doubly_indirect_block); @@ -184,17 +177,15 @@ namespace kernel::filesystem::ext2 auto filesystem::read_triply_indirect_block_number(uint32_t triply_indirect_block_number, uint32_t block_index_in_triply_indirect_block) const -> uint32_t { - auto const block_numbers_per_doubly_indirect_block = block_numbers_per_block() * block_numbers_per_block(); - if (triply_indirect_block_number == 0) { return 0; } auto const doubly_indirect_block_index_in_triply_indirect_block = - block_index_in_triply_indirect_block / block_numbers_per_doubly_indirect_block; + block_index_in_triply_indirect_block / block_numbers_per_doubly_indirect_block(); auto const block_index_in_doubly_indirect_block = - block_index_in_triply_indirect_block % block_numbers_per_doubly_indirect_block; + block_index_in_triply_indirect_block % block_numbers_per_doubly_indirect_block(); auto const doubly_indirect_block_number = read_block_number_at_index(triply_indirect_block_number, doubly_indirect_block_index_in_triply_indirect_block); @@ -218,6 +209,21 @@ namespace kernel::filesystem::ext2 return get_block_size() / sizeof(uint32_t); } + auto filesystem::block_numbers_per_singly_indirect_block() const -> uint32_t + { + return block_numbers_per_block(); + } + + auto filesystem::block_numbers_per_doubly_indirect_block() const -> uint32_t + { + return block_numbers_per_singly_indirect_block() * block_numbers_per_block(); + } + + auto filesystem::block_numbers_per_triply_indirect_block() const -> uint32_t + { + return block_numbers_per_doubly_indirect_block() * block_numbers_per_block(); + } + auto filesystem::get_block_size() const -> size_t { return constants::base_block_size << m_superblock.log_block_size; -- cgit v1.2.3 From 15afa6a030ee6e1fc6c255f9567b54d78c530d25 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 13 May 2026 11:23:33 +0200 Subject: increase buffer size to really test the singly indirect block pointer --- kernel/src/filesystem/ext2/inode.tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/inode.tests.cpp b/kernel/src/filesystem/ext2/inode.tests.cpp index 8381ee0..45bea51 100644 --- a/kernel/src/filesystem/ext2/inode.tests.cpp +++ b/kernel/src/filesystem/ext2/inode.tests.cpp @@ -229,7 +229,7 @@ SCENARIO("Ext2 inode handles zeros in block mappings as file holes", "[filesyste auto inode = kernel::filesystem::ext2::inode{&fs, data}; - auto buffer = kstd::vector(block_size * 3, std::byte{0xAB}); + auto buffer = kstd::vector(block_size * 15, std::byte{0xAB}); THEN("all direct blocks are zero when singly indirect block pointer is zero") { -- cgit v1.2.3 From a5e65a09667cbaad0259ebf7315d09401651bbc2 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 13 May 2026 13:37:15 +0200 Subject: add tests for mount and unmount boot root filesystem --- kernel/src/filesystem/vfs.tests.cpp | 63 +++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index add96aa..0f1d6d5 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -148,6 +148,69 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(mounted_monkey != nullptr); } + THEN("image can be mounted on / file opened and unmounted again") + { + auto info_1 = vfs.open("/information/info_1.txt"); + REQUIRE(info_1 != nullptr); + + REQUIRE(vfs.do_mount("/dev/ram16", "/") == kernel::filesystem::vfs::operation_result::success); + + info_1 = vfs.open("/information/info_1.txt"); + REQUIRE(info_1 == nullptr); + + auto water = vfs.open("/monkey_house/infrastructure/water.txt"); + REQUIRE(water != nullptr); + + REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success); + + info_1 = vfs.open("/information/info_1.txt"); + REQUIRE(info_1 != nullptr); + } + + THEN("image can be mounted on / just the boot root has /dev") + { + auto info_1 = vfs.open("/information/info_1.txt"); + REQUIRE(info_1 != nullptr); + + REQUIRE(vfs.do_mount("/dev/ram16", "/") == kernel::filesystem::vfs::operation_result::success); + + info_1 = vfs.open("/information/info_1.txt"); + REQUIRE(info_1 == nullptr); + + auto water = vfs.open("/monkey_house/infrastructure/water.txt"); + REQUIRE(water != nullptr); + + auto dev_ram_16 = vfs.open("/dev/ram16"); + REQUIRE(dev_ram_16 == nullptr); + + REQUIRE(vfs.do_mount("/dev/ram32", "/") == kernel::filesystem::vfs::operation_result::non_existent_path); + + REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success); + + auto dev_ram_32 = vfs.open("/dev/ram32"); + REQUIRE(dev_ram_32 != nullptr); + } + + THEN("boot root can be unmounted and remounted again but /dev is not re-grafted") + { + auto info_1 = vfs.open("/information/info_1.txt"); + REQUIRE(info_1 != nullptr); + + REQUIRE(vfs.unmount("/dev") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success); + + info_1 = vfs.open("/information/info_1.txt"); + REQUIRE(info_1 == nullptr); + + REQUIRE(vfs.do_mount("/dev/ram0", "/") == kernel::filesystem::vfs::operation_result::success); + + info_1 = vfs.open("/information/info_1.txt"); + REQUIRE(info_1 != nullptr); + + auto dev_ram_0 = vfs.open("/dev/ram0"); + REQUIRE(dev_ram_0 == nullptr); + } + THEN("mount with null file system fails") { REQUIRE(vfs.do_mount("/closed.txt", "/information") == -- cgit v1.2.3 From 2833fa2a2d2bf1f98f627503e52531615d1c1496 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 14 May 2026 15:41:21 +0200 Subject: small refactoring --- kernel/src/filesystem/dentry.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index c21771b..7603e11 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -17,6 +17,7 @@ namespace kernel::filesystem : m_name(name) , m_parent(parent) , m_inode(inode) + , m_flags(0) { if (!m_inode) { -- cgit v1.2.3 From 13f41e3816bd0be96c9bf728b534a58e6d4e5c28 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 14 May 2026 15:41:54 +0200 Subject: add todo --- kernel/src/filesystem/mount_table.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index 5a49e7a..e0cf140 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -35,6 +35,7 @@ namespace kernel::filesystem auto mount_table::remove_mount(std::string_view path) -> operation_result { // TODO BA-FS26 check wheter something is open in this mount + // TODO BA-FS26 nearly the same code is in find_exact_mount -> refactor to avoid code duplication auto mount_range = std::ranges::find_last_if(m_mounts, [&](auto const & mount) { return mount->get_mount_path() == path; }); auto mount_it = mount_range.begin(); -- cgit v1.2.3 From 245f47af9362e83235a28f993c89f844886e65c3 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Thu, 14 May 2026 16:25:15 +0200 Subject: Unify header inclusion syntax --- kernel/src/filesystem/ext2/inode.tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/inode.tests.cpp b/kernel/src/filesystem/ext2/inode.tests.cpp index 45bea51..efc0660 100644 --- a/kernel/src/filesystem/ext2/inode.tests.cpp +++ b/kernel/src/filesystem/ext2/inode.tests.cpp @@ -1,9 +1,9 @@ #include -#include "kernel/filesystem/ext2/superblock.hpp" #include #include #include +#include #include #include #include -- cgit v1.2.3 From c6953852b9e10823830688bdfb269650b080f1bb Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Thu, 14 May 2026 16:29:29 +0200 Subject: Track dentry instead of inode in open_file_descriptor --- kernel/src/filesystem/open_file_descriptor.cpp | 15 ++++++++------- kernel/src/filesystem/open_file_descriptor.tests.cpp | 14 +++++++++----- kernel/src/filesystem/open_file_table.tests.cpp | 10 +++++++--- kernel/src/filesystem/vfs.tests.cpp | 6 +++--- 4 files changed, 27 insertions(+), 18 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/open_file_descriptor.cpp b/kernel/src/filesystem/open_file_descriptor.cpp index 25bffbd..27e6449 100644 --- a/kernel/src/filesystem/open_file_descriptor.cpp +++ b/kernel/src/filesystem/open_file_descriptor.cpp @@ -1,6 +1,7 @@ -#include #include +#include + #include #include @@ -8,26 +9,26 @@ namespace kernel::filesystem { - open_file_descriptor::open_file_descriptor(kstd::shared_ptr const & inode) - : m_inode(inode) + open_file_descriptor::open_file_descriptor(kstd::shared_ptr const & dentry) + : m_dentry(dentry) , m_offset(0) { - if (!inode) + if (!dentry) { - kstd::os::panic("[FILESYSTEM] open_file_descriptor constructed with null inode."); + kstd::os::panic("[FILESYSTEM] open_file_descriptor constructed with null dentry."); } } auto open_file_descriptor::read(void * buffer, size_t size) -> size_t { - auto read_bytes = m_inode->read(buffer, m_offset, size); + auto read_bytes = m_dentry->get_inode()->read(buffer, m_offset, size); m_offset += read_bytes; return read_bytes; } auto open_file_descriptor::write(void const * buffer, size_t size) -> size_t { - auto written_bytes = m_inode->write(buffer, m_offset, size); + auto written_bytes = m_dentry->get_inode()->write(buffer, m_offset, size); m_offset += written_bytes; return written_bytes; } diff --git a/kernel/src/filesystem/open_file_descriptor.tests.cpp b/kernel/src/filesystem/open_file_descriptor.tests.cpp index 53835ba..8c24cf0 100644 --- a/kernel/src/filesystem/open_file_descriptor.tests.cpp +++ b/kernel/src/filesystem/open_file_descriptor.tests.cpp @@ -1,5 +1,7 @@ #include +#include +#include #include #include #include @@ -16,10 +18,11 @@ SCENARIO("Open file descriptor construction", "[filesystem][open_file_descriptor]") { - GIVEN("an inode and an open file descriptor for that inode") + GIVEN("a dentry and an open file descriptor for that dentry") { auto inode = kstd::make_shared(); - auto file_descriptor = kernel::filesystem::open_file_descriptor{inode}; + auto dentry = kstd::make_shared(nullptr, inode, "test_dentry"); + auto file_descriptor = kernel::filesystem::open_file_descriptor{dentry}; THEN("the initial offset is zero") { @@ -30,10 +33,11 @@ SCENARIO("Open file descriptor construction", "[filesystem][open_file_descriptor SCENARIO("Open file descriptor read/write offset management", "[filesystem][open_file_descriptor]") { - GIVEN("an inode that tracks read/write calls and an open file descriptor for that inode") + GIVEN("a dentry that tracks read/write calls and an open file descriptor for that dentry") { auto inode = kstd::make_shared(); - auto file_descriptor = kernel::filesystem::open_file_descriptor{inode}; + auto dentry = kstd::make_shared(nullptr, inode, "test_dentry"); + auto file_descriptor = kernel::filesystem::open_file_descriptor{dentry}; THEN("the offset is updated correctly after reads") { @@ -78,7 +82,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Ope auto & vfs = kernel::filesystem::vfs::get(); auto dentry = vfs.open("/information/info_1.txt"); REQUIRE(dentry != nullptr); - auto ofd = kstd::make_shared(dentry->get_inode()); + auto ofd = kstd::make_shared(dentry); THEN("the file can be read and the offset is updated") { diff --git a/kernel/src/filesystem/open_file_table.tests.cpp b/kernel/src/filesystem/open_file_table.tests.cpp index a5c791d..456d6b7 100644 --- a/kernel/src/filesystem/open_file_table.tests.cpp +++ b/kernel/src/filesystem/open_file_table.tests.cpp @@ -1,5 +1,6 @@ #include +#include #include #include @@ -15,8 +16,10 @@ SCENARIO("Open file table add/get file", "[filesystem][open_file_table]") { auto & table = kernel::filesystem::open_file_table::get(); auto inode = kstd::make_shared(); - auto file_descriptor_1 = kstd::make_shared(inode); - auto file_descriptor_2 = kstd::make_shared(inode); + auto dentry = kstd::make_shared(nullptr, inode, "test_dentry"); + + auto file_descriptor_1 = kstd::make_shared(dentry); + auto file_descriptor_2 = kstd::make_shared(dentry); WHEN("adding the open file descriptor to the open file table") { @@ -69,7 +72,8 @@ SCENARIO("Open file table remove file", "[filesystem][open_file_table]") { auto & table = kernel::filesystem::open_file_table::get(); auto inode = kstd::make_shared(); - auto file_descriptor = kstd::make_shared(inode); + auto dentry = kstd::make_shared(nullptr, inode, "test_dentry"); + auto file_descriptor = kstd::make_shared(dentry); auto fd = table.add_file(file_descriptor); WHEN("removing the file descriptor using the file descriptor") diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 0f1d6d5..eaffbc9 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -310,7 +310,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto dentry = vfs.open("/information/sheep_1.txt"); REQUIRE(dentry != nullptr); - auto sheep_1_ofd = kstd::make_shared(dentry->get_inode()); + auto sheep_1_ofd = kstd::make_shared(dentry); kstd::vector buffer(7); auto bytes_read = sheep_1_ofd->read(buffer.data(), buffer.size()); @@ -335,8 +335,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(sheep_1 != nullptr); REQUIRE(goat_1 != nullptr); - auto sheep_1_ofd = kstd::make_shared(sheep_1->get_inode()); - auto goat_1_ofd = kstd::make_shared(goat_1->get_inode()); + auto sheep_1_ofd = kstd::make_shared(sheep_1); + auto goat_1_ofd = kstd::make_shared(goat_1); kstd::vector sheep_buffer(7); auto bytes_read = sheep_1_ofd->read(sheep_buffer.data(), sheep_buffer.size()); -- cgit v1.2.3 From 216ec44cf2fdc914ce38e3ab56eb3a8d82b54c77 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Thu, 14 May 2026 16:59:56 +0200 Subject: Refactor resolve_path --- kernel/src/filesystem/vfs.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index f5d57be..52ffcc8 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace { @@ -165,11 +166,11 @@ namespace kernel::filesystem } } - auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr + auto vfs::resolve_path_internal(std::string_view path) -> std::pair, kstd::shared_ptr> { if (!path::is_valid_absolute_path(path)) { - return nullptr; + return {nullptr, nullptr}; } auto current_mount = m_mount_table.find_exact_mount("/"); @@ -225,7 +226,7 @@ namespace kernel::filesystem auto found_inode = current_fs->lookup(current_dentry->get_inode(), part.view()); if (!found_inode) { - return nullptr; + return {nullptr, nullptr}; } next_dentry = kstd::make_shared(current_dentry, found_inode, part.view()); @@ -246,7 +247,7 @@ namespace kernel::filesystem { if (symlink_counter++ > constants::symloop_max) { - return nullptr; + return {nullptr, nullptr}; } kstd::vector buffer(constants::symlink_max_path_length); @@ -269,9 +270,19 @@ namespace kernel::filesystem current_dentry = next_dentry; } + return {current_dentry, current_mount}; + } + + auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr + { + return resolve_path_internal(path).first; + } - return current_dentry; + auto vfs::find_mount(std::string_view path) -> kstd::shared_ptr + { + return resolve_path_internal(path).second; } + } // namespace kernel::filesystem namespace kernel::tests::filesystem::vfs -- cgit v1.2.3 From 146c40b22b834e4bf8d5e1d7256d3071f11d4bf9 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Thu, 14 May 2026 17:33:14 +0200 Subject: Rename mount_point_dentry to target_dentry --- kernel/src/filesystem/vfs.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 52ffcc8..31ffa42 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -53,9 +53,9 @@ namespace kernel::filesystem auto device_fs = kstd::make_shared(); device_fs->mount(nullptr); - if (auto dev_mount_point_dentry = resolve_path("/dev")) + if (auto dev_target_dentry = resolve_path("/dev")) { - do_mount_internal(dev_mount_point_dentry, device_fs); + do_mount_internal(dev_target_dentry, device_fs); } else { @@ -98,13 +98,13 @@ namespace kernel::filesystem return operation_result::invalid_path; } - if (auto mount_point_dentry = resolve_path(target)) + if (auto target_dentry = resolve_path(target)) { if (auto source_dentry = resolve_path(source)) { if (auto fs = kernel::filesystem::filesystem::probe_and_mount(source_dentry->get_inode())) { - do_mount_internal(mount_point_dentry, fs); + do_mount_internal(target_dentry, fs); return operation_result::success; } return operation_result::invalid_filesystem; @@ -135,10 +135,10 @@ namespace kernel::filesystem return operation_result::mount_point_not_found; } - auto vfs::do_mount_internal(kstd::shared_ptr const & mount_point_dentry, - kstd::shared_ptr const & fs) -> void + auto vfs::do_mount_internal(kstd::shared_ptr const & target_dentry, kstd::shared_ptr const & fs) + -> void { - auto parent_mount_dentry = mount_point_dentry->find_mount_root_dentry(); + auto parent_mount_dentry = target_dentry->find_mount_root_dentry(); kstd::shared_ptr parent_mount = nullptr; if (parent_mount_dentry) { @@ -146,8 +146,8 @@ namespace kernel::filesystem } auto new_fs_root = - kstd::make_shared(mount_point_dentry->get_parent(), fs->root_inode(), mount_point_dentry->get_name()); - auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, parent_mount); + kstd::make_shared(target_dentry->get_parent(), fs->root_inode(), target_dentry->get_name()); + auto new_mount = kstd::make_shared(target_dentry, new_fs_root, fs, parent_mount); m_mount_table.add_mount(new_mount); } -- cgit v1.2.3 From 4cc120e7dba5c858a3a0f68b63e91e8d7b831701 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Thu, 14 May 2026 18:03:44 +0200 Subject: Refactor do_mount_internal to use target_mount as parameter --- kernel/src/filesystem/vfs.cpp | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 31ffa42..c395e74 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -47,7 +47,8 @@ namespace kernel::filesystem root_fs->mount(nullptr); auto root_fs_root_dentry = kstd::make_shared(nullptr, root_fs->root_inode(), "/"); - m_mount_table.add_mount(kstd::make_shared(nullptr, root_fs_root_dentry, root_fs, nullptr)); + auto root_mount = kstd::make_shared(nullptr, root_fs_root_dentry, root_fs, nullptr); + m_mount_table.add_mount(root_mount); // mount devfs at /dev (inside rootfs, temporary, will be shadowed) auto device_fs = kstd::make_shared(); @@ -55,7 +56,7 @@ namespace kernel::filesystem if (auto dev_target_dentry = resolve_path("/dev")) { - do_mount_internal(dev_target_dentry, device_fs); + do_mount_internal(dev_target_dentry, root_mount, device_fs); } else { @@ -69,7 +70,7 @@ namespace kernel::filesystem { if (auto root_dentry = resolve_path("/")) { - do_mount_internal(root_dentry, boot_root_fs); + do_mount_internal(root_dentry, root_mount, boot_root_fs); graft_persistent_device_fs(device_fs); } } @@ -98,13 +99,15 @@ namespace kernel::filesystem return operation_result::invalid_path; } - if (auto target_dentry = resolve_path(target)) + auto [target_dentry, target_mount] = resolve_path_internal(target); + + if (target_dentry && target_mount) { if (auto source_dentry = resolve_path(source)) { if (auto fs = kernel::filesystem::filesystem::probe_and_mount(source_dentry->get_inode())) { - do_mount_internal(target_dentry, fs); + do_mount_internal(target_dentry, target_mount, fs); return operation_result::success; } return operation_result::invalid_filesystem; @@ -135,25 +138,20 @@ namespace kernel::filesystem return operation_result::mount_point_not_found; } - auto vfs::do_mount_internal(kstd::shared_ptr const & target_dentry, kstd::shared_ptr const & fs) + auto vfs::do_mount_internal(kstd::shared_ptr const & target_dentry, + kstd::shared_ptr const & target_mount, kstd::shared_ptr const & fs) -> void { - auto parent_mount_dentry = target_dentry->find_mount_root_dentry(); - kstd::shared_ptr parent_mount = nullptr; - if (parent_mount_dentry) - { - parent_mount = m_mount_table.find_exact_mount(parent_mount_dentry->get_absolute_path().view()); - } - auto new_fs_root = kstd::make_shared(target_dentry->get_parent(), fs->root_inode(), target_dentry->get_name()); - auto new_mount = kstd::make_shared(target_dentry, new_fs_root, fs, parent_mount); + auto new_mount = kstd::make_shared(target_dentry, new_fs_root, fs, target_mount); m_mount_table.add_mount(new_mount); } auto vfs::graft_persistent_device_fs(kstd::shared_ptr const & device_fs) -> void { - if (auto new_root_dentry = resolve_path("/")) + auto [new_root_dentry, root_mount] = resolve_path_internal("/"); + if (new_root_dentry && root_mount) { auto dev_dentry = new_root_dentry->find_child("dev"); if (!dev_dentry) @@ -162,7 +160,7 @@ namespace kernel::filesystem new_root_dentry->add_child(dev_dentry); } - do_mount_internal(dev_dentry, device_fs); + do_mount_internal(dev_dentry, root_mount, device_fs); } } -- cgit v1.2.3 From 5b97abfc9ce1032a0e42be213906b1abd51355dd Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Thu, 14 May 2026 18:09:17 +0200 Subject: Remove unneeded functionality --- kernel/src/filesystem/dentry.cpp | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index 7603e11..d963ed7 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -67,16 +67,6 @@ namespace kernel::filesystem return path; } - auto dentry::find_mount_root_dentry() const -> kstd::shared_ptr - { - auto parent = m_parent; - while (parent && !parent->has_flag(dentry_flags::is_mount_root)) - { - parent = parent->get_parent(); - } - return parent; - } - auto dentry::add_child(kstd::shared_ptr const & child) -> void { m_children.push_back(child); -- cgit v1.2.3 From fe0b38db0f8848da8cf28bb883e01bbbb889dd0a Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Thu, 14 May 2026 21:02:25 +0200 Subject: Remove unneeded functionality part 2 --- kernel/src/filesystem/mount_table.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index e0cf140..4b61fb0 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -26,10 +26,6 @@ namespace kernel::filesystem { mount_dentry->set_flag(dentry::dentry_flags::is_mount_point); } - if (auto root_dentry = mount->get_root_dentry()) - { - root_dentry->set_flag(dentry::dentry_flags::is_mount_root); - } } auto mount_table::remove_mount(std::string_view path) -> operation_result -- cgit v1.2.3 From 963c926c68aac4606d80743aca8e7b052eee7efe Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Fri, 15 May 2026 11:42:33 +0200 Subject: Rename mount_table method from find_exact_mount to find_mount --- kernel/src/filesystem/mount_table.cpp | 4 ++-- kernel/src/filesystem/mount_table.tests.cpp | 10 +++++----- kernel/src/filesystem/vfs.cpp | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index 4b61fb0..78ac727 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -31,7 +31,7 @@ namespace kernel::filesystem auto mount_table::remove_mount(std::string_view path) -> operation_result { // TODO BA-FS26 check wheter something is open in this mount - // TODO BA-FS26 nearly the same code is in find_exact_mount -> refactor to avoid code duplication + // TODO BA-FS26 nearly the same code is in find_mount -> refactor to avoid code duplication auto mount_range = std::ranges::find_last_if(m_mounts, [&](auto const & mount) { return mount->get_mount_path() == path; }); auto mount_it = mount_range.begin(); @@ -52,7 +52,7 @@ namespace kernel::filesystem return operation_result::removed; } - auto mount_table::find_exact_mount(std::string_view path) const -> kstd::shared_ptr + auto mount_table::find_mount(std::string_view path) const -> kstd::shared_ptr { auto mount_range = std::ranges::find_last_if(m_mounts, [&](auto const & mount) { return mount->get_mount_path() == path; }); diff --git a/kernel/src/filesystem/mount_table.tests.cpp b/kernel/src/filesystem/mount_table.tests.cpp index 4ae8711..f22b25e 100644 --- a/kernel/src/filesystem/mount_table.tests.cpp +++ b/kernel/src/filesystem/mount_table.tests.cpp @@ -58,14 +58,14 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("finding mounts by exact valid path returns the correct mount") { - REQUIRE(table.find_exact_mount("/") == mount1); - REQUIRE(table.find_exact_mount("/mnt") == mount2); + REQUIRE(table.find_mount("/") == mount1); + REQUIRE(table.find_mount("/mnt") == mount2); } THEN("finding mounts by exact invalid path returns null") { - REQUIRE(table.find_exact_mount("/nonexistent") == nullptr); - REQUIRE(table.find_exact_mount("/mnt/file") == nullptr); + REQUIRE(table.find_mount("/nonexistent") == nullptr); + REQUIRE(table.find_mount("/mnt/file") == nullptr); } THEN("removing a mount that has no child mounts succeeds") @@ -103,7 +103,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("finding mounts by exact valid path returns the correct mount") { - REQUIRE(table.find_exact_mount("/") == mount2); + REQUIRE(table.find_mount("/") == mount2); } THEN("removing the topmost mount with the same path succeeds") diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index c395e74..9b0440d 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -171,7 +171,7 @@ namespace kernel::filesystem return {nullptr, nullptr}; } - auto current_mount = m_mount_table.find_exact_mount("/"); + auto current_mount = m_mount_table.find_mount("/"); if (!current_mount) { kapi::system::panic("[FILESYSTEM] no root mount found."); @@ -232,7 +232,7 @@ namespace kernel::filesystem } else if (next_dentry->has_flag(dentry::dentry_flags::is_mount_point)) { - current_mount = m_mount_table.find_exact_mount(next_dentry->get_absolute_path().view()); + current_mount = m_mount_table.find_mount(next_dentry->get_absolute_path().view()); if (!current_mount) { kapi::system::panic("[FILESYSTEM] mount for dentry with mounted flag not found."); @@ -260,7 +260,7 @@ namespace kernel::filesystem if (path::is_valid_absolute_path(symbolic_link_path)) { - current_mount = m_mount_table.find_exact_mount("/"); + current_mount = m_mount_table.find_mount("/"); current_dentry = current_mount->get_root_dentry(); } continue; -- cgit v1.2.3 From 66d0e68376c9ad3e2b13f6ff8d999a0c85bda1a4 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 15 May 2026 15:47:06 +0200 Subject: renaming --- kernel/src/filesystem/vfs.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 9b0440d..77ae015 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -54,9 +54,9 @@ namespace kernel::filesystem auto device_fs = kstd::make_shared(); device_fs->mount(nullptr); - if (auto dev_target_dentry = resolve_path("/dev")) + if (auto dev_mount_point_dentry = resolve_path("/dev")) { - do_mount_internal(dev_target_dentry, root_mount, device_fs); + do_mount_internal(dev_mount_point_dentry, root_mount, device_fs); } else { @@ -99,15 +99,15 @@ namespace kernel::filesystem return operation_result::invalid_path; } - auto [target_dentry, target_mount] = resolve_path_internal(target); + auto [mount_point_dentry, mount_context] = resolve_path_internal(target); - if (target_dentry && target_mount) + if (mount_point_dentry && mount_context) { if (auto source_dentry = resolve_path(source)) { if (auto fs = kernel::filesystem::filesystem::probe_and_mount(source_dentry->get_inode())) { - do_mount_internal(target_dentry, target_mount, fs); + do_mount_internal(mount_point_dentry, mount_context, fs); return operation_result::success; } return operation_result::invalid_filesystem; @@ -138,26 +138,26 @@ namespace kernel::filesystem return operation_result::mount_point_not_found; } - auto vfs::do_mount_internal(kstd::shared_ptr const & target_dentry, - kstd::shared_ptr const & target_mount, kstd::shared_ptr const & fs) + auto vfs::do_mount_internal(kstd::shared_ptr const & mount_point_dentry, + kstd::shared_ptr const & parent_mount, kstd::shared_ptr const & fs) -> void { auto new_fs_root = - kstd::make_shared(target_dentry->get_parent(), fs->root_inode(), target_dentry->get_name()); - auto new_mount = kstd::make_shared(target_dentry, new_fs_root, fs, target_mount); + kstd::make_shared(mount_point_dentry->get_parent(), fs->root_inode(), mount_point_dentry->get_name()); + auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, parent_mount); m_mount_table.add_mount(new_mount); } auto vfs::graft_persistent_device_fs(kstd::shared_ptr const & device_fs) -> void { - auto [new_root_dentry, root_mount] = resolve_path_internal("/"); - if (new_root_dentry && root_mount) + auto [root_mount_point_dentry, root_mount] = resolve_path_internal("/"); + if (root_mount_point_dentry && root_mount) { - auto dev_dentry = new_root_dentry->find_child("dev"); + auto dev_dentry = root_mount_point_dentry->find_child("dev"); if (!dev_dentry) { - dev_dentry = kstd::make_shared(new_root_dentry, device_fs->root_inode(), "dev"); - new_root_dentry->add_child(dev_dentry); + dev_dentry = kstd::make_shared(root_mount_point_dentry, device_fs->root_inode(), "dev"); + root_mount_point_dentry->add_child(dev_dentry); } do_mount_internal(dev_dentry, root_mount, device_fs); -- cgit v1.2.3 From 95ff59017db74a6988f791ca9f122254dd743541 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 15 May 2026 16:17:50 +0200 Subject: refactor find_mount_iterator to avoid code duplication --- kernel/src/filesystem/mount_table.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index 78ac727..b582fd9 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -31,11 +31,7 @@ namespace kernel::filesystem auto mount_table::remove_mount(std::string_view path) -> operation_result { // TODO BA-FS26 check wheter something is open in this mount - // TODO BA-FS26 nearly the same code is in find_mount -> refactor to avoid code duplication - auto mount_range = - std::ranges::find_last_if(m_mounts, [&](auto const & mount) { return mount->get_mount_path() == path; }); - auto mount_it = mount_range.begin(); - + auto mount_it = find_mount_iterator(path); if (mount_it == m_mounts.end()) { return operation_result::mount_not_found; @@ -54,9 +50,14 @@ namespace kernel::filesystem auto mount_table::find_mount(std::string_view path) const -> kstd::shared_ptr { - auto mount_range = - std::ranges::find_last_if(m_mounts, [&](auto const & mount) { return mount->get_mount_path() == path; }); - auto mount_it = mount_range.begin(); + auto mount_it = find_mount_iterator(path); return (mount_it != m_mounts.end()) ? *mount_it : nullptr; } + + auto mount_table::find_mount_iterator(std::string_view path) const + -> kstd::vector>::const_iterator + { + return std::ranges::find_last_if(m_mounts, [&](auto const & mount) { return mount->get_mount_path() == path; }) + .begin(); + } } // namespace kernel::filesystem \ No newline at end of file -- cgit v1.2.3 From 1d647adb1ba20121eeb5c8e4470f48b2e972b3d4 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 15 May 2026 16:50:55 +0200 Subject: Mount can only be unmounted if no references are present, increment references on open file and decrement on close file --- kernel/src/filesystem/mount.cpp | 22 ++++++++++++++++++++ kernel/src/filesystem/mount_table.cpp | 5 ++++- kernel/src/filesystem/open_file_descriptor.cpp | 7 ++++++- .../src/filesystem/open_file_descriptor.tests.cpp | 24 +++++++++++----------- kernel/src/filesystem/vfs.cpp | 17 ++++++++++++++- 5 files changed, 60 insertions(+), 15 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index 749c86a..3016509 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -18,6 +18,7 @@ namespace kernel::filesystem , m_root_dentry(root_dentry) , m_filesystem(fs) , m_parent_mount(parent_mount) + , m_ref_count(0) { if (!m_filesystem) { @@ -53,4 +54,25 @@ namespace kernel::filesystem { return m_parent_mount; } + + auto mount::increment_ref_count() -> void + { + m_ref_count += 1; + } + + auto mount::decrement_ref_count() -> bool + { + if (m_ref_count == 0) + { + return false; + } + + m_ref_count -= 1; + return true; + } + + auto mount::is_ready_to_unmount() const -> bool + { + return m_ref_count == 0; + } } // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index b582fd9..9951590 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -30,7 +30,6 @@ namespace kernel::filesystem auto mount_table::remove_mount(std::string_view path) -> operation_result { - // TODO BA-FS26 check wheter something is open in this mount auto mount_it = find_mount_iterator(path); if (mount_it == m_mounts.end()) { @@ -38,6 +37,10 @@ namespace kernel::filesystem } auto const & mount = *mount_it; + if (!mount->is_ready_to_unmount()) + { + return operation_result::cannot_be_unmounted; + } if (has_child_mounts(mount)) { return operation_result::has_child_mounts; diff --git a/kernel/src/filesystem/open_file_descriptor.cpp b/kernel/src/filesystem/open_file_descriptor.cpp index 27e6449..ebaabef 100644 --- a/kernel/src/filesystem/open_file_descriptor.cpp +++ b/kernel/src/filesystem/open_file_descriptor.cpp @@ -33,9 +33,14 @@ namespace kernel::filesystem return written_bytes; } - auto open_file_descriptor::offset() const -> size_t + auto open_file_descriptor::get_offset() const -> size_t { return m_offset; } + auto open_file_descriptor::get_dentry() const -> kstd::shared_ptr const & + { + return m_dentry; + } + } // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/open_file_descriptor.tests.cpp b/kernel/src/filesystem/open_file_descriptor.tests.cpp index 8c24cf0..1910b8b 100644 --- a/kernel/src/filesystem/open_file_descriptor.tests.cpp +++ b/kernel/src/filesystem/open_file_descriptor.tests.cpp @@ -26,7 +26,7 @@ SCENARIO("Open file descriptor construction", "[filesystem][open_file_descriptor THEN("the initial offset is zero") { - REQUIRE(file_descriptor.offset() == 0); + REQUIRE(file_descriptor.get_offset() == 0); } } } @@ -42,29 +42,29 @@ 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.get_offset() == 100); REQUIRE(file_descriptor.read(nullptr, 50) == 50); - REQUIRE(file_descriptor.offset() == 150); + REQUIRE(file_descriptor.get_offset() == 150); } THEN("the offset is updated correctly after writes") { REQUIRE(file_descriptor.write(nullptr, 200) == 200); - REQUIRE(file_descriptor.offset() == 200); + REQUIRE(file_descriptor.get_offset() == 200); REQUIRE(file_descriptor.write(nullptr, 25) == 25); - REQUIRE(file_descriptor.offset() == 225); + REQUIRE(file_descriptor.get_offset() == 225); } THEN("reads and writes both update the same offset") { REQUIRE(file_descriptor.read(nullptr, 10) == 10); - REQUIRE(file_descriptor.offset() == 10); + REQUIRE(file_descriptor.get_offset() == 10); REQUIRE(file_descriptor.write(nullptr, 20) == 20); - REQUIRE(file_descriptor.offset() == 30); + REQUIRE(file_descriptor.get_offset() == 30); REQUIRE(file_descriptor.read(nullptr, 5) == 5); - REQUIRE(file_descriptor.offset() == 35); + REQUIRE(file_descriptor.get_offset() == 35); REQUIRE(file_descriptor.write(nullptr, 15) == 15); - REQUIRE(file_descriptor.offset() == 50); + REQUIRE(file_descriptor.get_offset() == 50); } } } @@ -89,7 +89,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Ope kstd::vector buffer(32); auto bytes_read = ofd->read(buffer.data(), buffer.size()); REQUIRE(bytes_read == 7); - REQUIRE(ofd->offset() == 7); + REQUIRE(ofd->get_offset() == 7); std::string_view buffer_as_str{reinterpret_cast(buffer.data()), static_cast(bytes_read)}; REQUIRE(buffer_as_str == "info_1\n"); @@ -100,11 +100,11 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Ope kstd::vector 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); + REQUIRE(ofd->get_offset() == 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()); + REQUIRE(ofd->get_offset() == buffer.size()); std::string_view buffer_as_str{reinterpret_cast(buffer.data()), bytes_read_1 + bytes_read_2}; REQUIRE(buffer_as_str == "info"); diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 77ae015..3b3d6ff 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -89,7 +89,22 @@ namespace kernel::filesystem auto vfs::open(std::string_view path) -> kstd::shared_ptr { - return resolve_path(path); + auto [dentry, mount] = resolve_path_internal(path); + mount->increment_ref_count(); + return dentry; + } + + auto vfs::close(kstd::shared_ptr const & dentry) -> operation_result + { + if (auto mount = find_mount(dentry->get_absolute_path().view())) + { + if (mount->decrement_ref_count()) + { + return operation_result::success; + } + return operation_result::close_failed; + } + return operation_result::invalid_path; } auto vfs::do_mount(std::string_view source, std::string_view target) -> operation_result -- cgit v1.2.3 From 0e279db4e1b799c4db0cc7c714d57686e3de7089 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 15 May 2026 22:36:05 +0200 Subject: refactoring rootfs, no separate child management needed --- kernel/src/filesystem/rootfs/filesystem.cpp | 9 +---- kernel/src/filesystem/rootfs/filesystem.tests.cpp | 7 ---- kernel/src/filesystem/rootfs/inode.cpp | 19 --------- kernel/src/filesystem/rootfs/inode.tests.cpp | 47 ----------------------- kernel/src/filesystem/vfs.cpp | 10 +---- 5 files changed, 3 insertions(+), 89 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/rootfs/filesystem.cpp b/kernel/src/filesystem/rootfs/filesystem.cpp index 6187c3c..d49e237 100644 --- a/kernel/src/filesystem/rootfs/filesystem.cpp +++ b/kernel/src/filesystem/rootfs/filesystem.cpp @@ -11,18 +11,13 @@ namespace kernel::filesystem::rootfs { auto filesystem::mount(kstd::shared_ptr const &) -> operation_result { - auto rfs_inode = kstd::make_shared(); - rfs_inode->add_child("dev"); - m_root_inode = rfs_inode; - + m_root_inode = kstd::make_shared(); return operation_result::success; } - auto filesystem::lookup(kstd::shared_ptr const & parent, std::string_view name) + auto filesystem::lookup(kstd::shared_ptr const &, std::string_view) -> kstd::shared_ptr { - if (auto * rfs_inode = static_cast(parent.get())) - return rfs_inode->lookup_child(name); return nullptr; } } // namespace kernel::filesystem::rootfs diff --git a/kernel/src/filesystem/rootfs/filesystem.tests.cpp b/kernel/src/filesystem/rootfs/filesystem.tests.cpp index 81ac9e4..ae320e9 100644 --- a/kernel/src/filesystem/rootfs/filesystem.tests.cpp +++ b/kernel/src/filesystem/rootfs/filesystem.tests.cpp @@ -21,13 +21,6 @@ SCENARIO("Rootfs filesystem mount and lookup", "[filesystem][rootfs][filesystem] REQUIRE(fs.root_inode() != nullptr); } - THEN("looking up the 'dev' directory returns a valid inode") - { - auto dev_inode = fs.lookup(fs.root_inode(), "dev"); - REQUIRE(dev_inode != nullptr); - REQUIRE(dev_inode->is_directory()); - } - THEN("looking up a non-existent directory returns null") { auto non_existent_inode_1 = fs.lookup(fs.root_inode(), ""); diff --git a/kernel/src/filesystem/rootfs/inode.cpp b/kernel/src/filesystem/rootfs/inode.cpp index d099676..2ad4815 100644 --- a/kernel/src/filesystem/rootfs/inode.cpp +++ b/kernel/src/filesystem/rootfs/inode.cpp @@ -5,10 +5,7 @@ #include #include -#include #include -#include -#include namespace kernel::filesystem::rootfs { @@ -21,20 +18,4 @@ namespace kernel::filesystem::rootfs { return 0; } - - auto inode::add_child(std::string_view name) -> void - { - m_children.push_back(std::make_pair(kstd::string{name}, kstd::make_shared())); - } - - auto inode::lookup_child(std::string_view name) -> kstd::shared_ptr - { - auto it = std::ranges::find_if(m_children, [&](auto const & pair) { return pair.first == name; }); - return (it != m_children.end()) ? it->second : nullptr; - } - - auto inode::is_directory() const -> bool - { - return true; - } } // namespace kernel::filesystem::rootfs diff --git a/kernel/src/filesystem/rootfs/inode.tests.cpp b/kernel/src/filesystem/rootfs/inode.tests.cpp index 7cc217f..f4b634f 100644 --- a/kernel/src/filesystem/rootfs/inode.tests.cpp +++ b/kernel/src/filesystem/rootfs/inode.tests.cpp @@ -6,53 +6,6 @@ #include -SCENARIO("Rootfs inode creation", "[filesystem][rootfs][inode]") -{ - GIVEN("a rootfs inode") - { - auto inode = kernel::filesystem::rootfs::inode{}; - - THEN("the inode has the correct kind") - { - REQUIRE(inode.is_directory()); - REQUIRE_FALSE(inode.is_device()); - REQUIRE_FALSE(inode.is_regular()); - REQUIRE_FALSE(inode.is_symbolic_link()); - } - - THEN("the inode has no children") - { - REQUIRE(inode.lookup_child("child") == nullptr); - } - } -} - -SCENARIO("Rootfs inode child management", "[filesystem][rootfs][inode]") -{ - GIVEN("a rootfs inode") - { - auto inode = kernel::filesystem::rootfs::inode{}; - - WHEN("adding a child inode") - { - inode.add_child("child"); - inode.add_child("another child"); - - THEN("the child can be looked up by name") - { - auto child_inode = inode.lookup_child("child"); - REQUIRE(child_inode != nullptr); - REQUIRE(child_inode->is_directory()); - } - - THEN("looking up a non-existent child returns null") - { - REQUIRE(inode.lookup_child("nonexistent") == nullptr); - } - } - } -} - SCENARIO("Rootfs inode read/write", "[filesystem][rootfs][inode]") { GIVEN("a rootfs inode") diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 3b3d6ff..67671e2 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -53,15 +53,7 @@ namespace kernel::filesystem // mount devfs at /dev (inside rootfs, temporary, will be shadowed) auto device_fs = kstd::make_shared(); device_fs->mount(nullptr); - - if (auto dev_mount_point_dentry = resolve_path("/dev")) - { - do_mount_internal(dev_mount_point_dentry, root_mount, device_fs); - } - else - { - kapi::system::panic("[FILESYSTEM] failed to resolve /dev for initial devfs mount."); - } + graft_persistent_device_fs(device_fs); // mount boot fs at / (shadows rootfs), re-graft devfs if (auto boot_device_dentry = resolve_path("/dev/ram0")) -- cgit v1.2.3 From 1f9fe3cf18b561749cfbdb2db8ab7572ddc40c03 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 15 May 2026 22:38:24 +0200 Subject: uniform interface for open and close --- kernel/src/filesystem/vfs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 67671e2..de19d38 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -86,9 +86,9 @@ namespace kernel::filesystem return dentry; } - auto vfs::close(kstd::shared_ptr const & dentry) -> operation_result + auto vfs::close(std::string_view path) -> operation_result { - if (auto mount = find_mount(dentry->get_absolute_path().view())) + if (auto mount = find_mount(path)) { if (mount->decrement_ref_count()) { -- cgit v1.2.3 From 2396fe6174ec875ba12dc135ab18f84550c07e9a Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 15 May 2026 22:40:52 +0200 Subject: avoid nullptr access --- kernel/src/filesystem/vfs.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index de19d38..f6eae25 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -82,6 +82,10 @@ namespace kernel::filesystem auto vfs::open(std::string_view path) -> kstd::shared_ptr { auto [dentry, mount] = resolve_path_internal(path); + if (!dentry || !mount) + { + return nullptr; + } mount->increment_ref_count(); return dentry; } -- cgit v1.2.3 From 16ccdee935d3b14edf93eea5a135e413b2fd47b5 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 15 May 2026 22:59:23 +0200 Subject: rootfs inode is a directory inode --- kernel/src/filesystem/rootfs/inode.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/rootfs/inode.cpp b/kernel/src/filesystem/rootfs/inode.cpp index 2ad4815..dbe7948 100644 --- a/kernel/src/filesystem/rootfs/inode.cpp +++ b/kernel/src/filesystem/rootfs/inode.cpp @@ -18,4 +18,9 @@ namespace kernel::filesystem::rootfs { return 0; } + + auto inode::is_directory() const -> bool + { + return true; + } } // namespace kernel::filesystem::rootfs -- cgit v1.2.3 From ba2f62972823df320e05dea7080adf658c2977b3 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 16 May 2026 13:43:38 +0200 Subject: fix tests, all files must be closed before unmounting --- kernel/src/filesystem/vfs.tests.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index eaffbc9..28782ec 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -105,6 +105,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); REQUIRE(mounted_monkey_1 != nullptr); + REQUIRE(vfs.close(mounted_monkey_1->get_absolute_path().view()) == + kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); auto unmounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); @@ -126,6 +128,11 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(mounted_monkey_1 != nullptr); REQUIRE(mounted_fish1 != nullptr); + REQUIRE(vfs.close(mounted_monkey_1->get_absolute_path().view()) == + kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(mounted_fish1->get_absolute_path().view()) == + kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); REQUIRE(vfs.unmount("/information/monkey_house/infrastructure") == kernel::filesystem::vfs::operation_result::success); @@ -140,6 +147,9 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto mounted_tickets = vfs.open("/information/entrance/tickets.txt"); REQUIRE(mounted_tickets != nullptr); + REQUIRE(vfs.close(mounted_tickets->get_absolute_path().view()) == + kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); mounted_tickets = vfs.open("/information/entrance/tickets.txt"); REQUIRE(mounted_tickets == nullptr); @@ -161,6 +171,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto water = vfs.open("/monkey_house/infrastructure/water.txt"); REQUIRE(water != nullptr); + REQUIRE(vfs.close(water->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success); info_1 = vfs.open("/information/info_1.txt"); @@ -180,6 +192,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto water = vfs.open("/monkey_house/infrastructure/water.txt"); REQUIRE(water != nullptr); + REQUIRE(vfs.close(water->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + auto dev_ram_16 = vfs.open("/dev/ram16"); REQUIRE(dev_ram_16 == nullptr); @@ -196,6 +210,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto info_1 = vfs.open("/information/info_1.txt"); REQUIRE(info_1 != nullptr); + REQUIRE(vfs.close(info_1->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/dev") == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success); @@ -317,6 +333,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS std::string_view buffer_as_str{reinterpret_cast(buffer.data()), bytes_read}; REQUIRE(buffer_as_str == "sheep_1"); + REQUIRE(vfs.close(dentry->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); auto unmounted_sheep_1 = vfs.open("/information/sheep_1.txt"); REQUIRE(unmounted_sheep_1 == nullptr); @@ -348,6 +366,9 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS buffer_as_str = std::string_view{reinterpret_cast(goat_buffer.data()), bytes_read}; REQUIRE(buffer_as_str == "goat_1"); + REQUIRE(vfs.close(sheep_1->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(goat_1->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); REQUIRE(vfs.unmount("/information/stable") == kernel::filesystem::vfs::operation_result::success); @@ -357,6 +378,9 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto still_mounted_sheep_1 = vfs.open("/information/sheep_1.txt"); REQUIRE(still_mounted_sheep_1 != nullptr); + REQUIRE(vfs.close(still_mounted_sheep_1->get_absolute_path().view()) == + kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); auto unmounted_sheep_1 = vfs.open("/information/sheep_1.txt"); REQUIRE(unmounted_sheep_1 == nullptr); -- cgit v1.2.3 From 7ecf092ca7ff91dd59e81eda7ef2b05fe837844d Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 16 May 2026 13:53:34 +0200 Subject: add mount tests --- kernel/src/filesystem/mount.cpp | 6 +++++ kernel/src/filesystem/mount.tests.cpp | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index 3016509..1e04083 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -8,6 +8,7 @@ #include #include +#include #include namespace kernel::filesystem @@ -75,4 +76,9 @@ namespace kernel::filesystem { return m_ref_count == 0; } + + auto mount::get_ref_count() const -> size_t + { + return m_ref_count; + } } // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/mount.tests.cpp b/kernel/src/filesystem/mount.tests.cpp index 58e9bab..e7dd709 100644 --- a/kernel/src/filesystem/mount.tests.cpp +++ b/kernel/src/filesystem/mount.tests.cpp @@ -29,6 +29,7 @@ SCENARIO("Mount construction", "[filesystem][mount]") REQUIRE(mount.get_root_dentry() == root_dentry); REQUIRE(mount.get_mount_dentry() == root_dentry); REQUIRE(mount.get_mount_path() == "/"); + REQUIRE(mount.is_ready_to_unmount()); } THEN("the mount has no parent mount") @@ -47,3 +48,44 @@ SCENARIO("Mount construction", "[filesystem][mount]") } } } + +SCENARIO("Mount reference counting", "[filesystem][mount]") +{ + GIVEN("a filesystem and a root dentry") + { + auto fs = kstd::make_shared(); + auto root_inode = kstd::make_shared(); + auto root_dentry = kstd::make_shared(nullptr, root_inode, "/"); + + THEN("reference count can be incremented and decremented, the mount is ready to unmount when the reference " + "count == 0") + { + auto mount = kernel::filesystem::mount{root_dentry, root_dentry, fs, nullptr}; + + mount.increment_ref_count(); + REQUIRE(mount.get_ref_count() == 1); + REQUIRE_FALSE(mount.is_ready_to_unmount()); + + mount.increment_ref_count(); + REQUIRE(mount.get_ref_count() == 2); + REQUIRE_FALSE(mount.is_ready_to_unmount()); + + REQUIRE(mount.decrement_ref_count()); + REQUIRE(mount.get_ref_count() == 1); + REQUIRE_FALSE(mount.is_ready_to_unmount()); + + REQUIRE(mount.decrement_ref_count()); + REQUIRE(mount.get_ref_count() == 0); + REQUIRE(mount.is_ready_to_unmount()); + } + + THEN("decrementing reference count when it is already zero does not decrement it below zero") + { + auto mount = kernel::filesystem::mount{root_dentry, root_dentry, fs, nullptr}; + + REQUIRE_FALSE(mount.decrement_ref_count()); + REQUIRE(mount.get_ref_count() == 0); + REQUIRE(mount.is_ready_to_unmount()); + } + } +} \ No newline at end of file -- cgit v1.2.3 From efc7ba748b977a792188724c461852f01c111957 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 16 May 2026 14:05:49 +0200 Subject: add vfs tests --- kernel/src/filesystem/vfs.cpp | 7 +++---- kernel/src/filesystem/vfs.tests.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index f6eae25..8636d0f 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -140,13 +140,12 @@ namespace kernel::filesystem { return operation_result::success; } - - if (remove_result == mount_table::operation_result::has_child_mounts) + else if (remove_result == mount_table::operation_result::mount_not_found) { - return operation_result::unmount_failed; + return operation_result::mount_point_not_found; } - return operation_result::mount_point_not_found; + return operation_result::unmount_failed; } auto vfs::do_mount_internal(kstd::shared_ptr const & mount_point_dentry, diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 28782ec..648ebb8 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -139,6 +139,36 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); } + THEN("image can be mounted, unmount only if no files are open") + { + REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); + + auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); + REQUIRE(mounted_monkey_1 != nullptr); + + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); + + REQUIRE(vfs.close(mounted_monkey_1->get_absolute_path().view()) == + kernel::filesystem::vfs::operation_result::success); + + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); + } + + THEN("file with invalid path or not opened file cannot be closed") + { + REQUIRE(vfs.close("invalid_path") == kernel::filesystem::vfs::operation_result::invalid_path); + REQUIRE(vfs.close("/information/info_1.txt") == kernel::filesystem::vfs::operation_result::close_failed); + } + + THEN("file cannot be closed twice") + { + auto info_1 = vfs.open("/information/info_1.txt"); + REQUIRE(info_1 != nullptr); + + REQUIRE(vfs.close(info_1->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(info_1->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::close_failed); + } + THEN("images can be stacked mounted and correct file system is unmounted again") { REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); -- cgit v1.2.3 From 3b2f36d242eb895fd893ec7a674ff608f44f69ac Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 16 May 2026 16:12:36 +0200 Subject: refactoring --- kernel/src/devices/block_device_utils.cpp | 2 + kernel/src/filesystem/dentry.cpp | 6 +- kernel/src/filesystem/dentry.tests.cpp | 14 ++--- kernel/src/filesystem/devfs/filesystem.cpp | 10 ++-- kernel/src/filesystem/devfs/inode.cpp | 4 +- kernel/src/filesystem/ext2/filesystem.cpp | 70 +++++++++++----------- kernel/src/filesystem/ext2/inode.cpp | 19 +++--- kernel/src/filesystem/ext2/inode.tests.cpp | 8 +-- kernel/src/filesystem/mount.cpp | 12 ++-- kernel/src/filesystem/mount.tests.cpp | 18 +++--- kernel/src/filesystem/mount_table.cpp | 11 ++-- kernel/src/filesystem/open_file_descriptor.cpp | 2 +- .../src/filesystem/open_file_descriptor.tests.cpp | 24 ++++---- kernel/src/filesystem/open_file_table.cpp | 31 ++++------ kernel/src/filesystem/open_file_table.tests.cpp | 19 ++---- kernel/src/filesystem/rootfs/filesystem.cpp | 3 +- kernel/src/filesystem/rootfs/inode.cpp | 7 +-- kernel/src/filesystem/vfs.cpp | 25 ++++---- kernel/src/filesystem/vfs.tests.cpp | 30 +++++----- kernel/src/test_support/filesystem/filesystem.cpp | 2 +- 20 files changed, 147 insertions(+), 170 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/devices/block_device_utils.cpp b/kernel/src/devices/block_device_utils.cpp index cb8ecba..18d1e9d 100644 --- a/kernel/src/devices/block_device_utils.cpp +++ b/kernel/src/devices/block_device_utils.cpp @@ -42,7 +42,9 @@ namespace kernel::devices::block_device_utils size_t const capacity = block_dev->capacity(); if (offset >= capacity) + { return 0; + } size_t const total_to_process = std::min(size, capacity - offset); kstd::vector scratch_buffer{block_size}; diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index d963ed7..14de875 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -34,17 +34,17 @@ namespace kernel::filesystem return m_inode; } - auto dentry::get_parent() const -> kstd::shared_ptr const & + auto dentry::parent() const -> kstd::shared_ptr const & { return m_parent; } - auto dentry::get_name() const -> std::string_view + auto dentry::name() const -> std::string_view { return m_name.view(); } - auto dentry::get_absolute_path() const -> kstd::string + auto dentry::absolute_path() const -> kstd::string { kstd::string path = m_name; diff --git a/kernel/src/filesystem/dentry.tests.cpp b/kernel/src/filesystem/dentry.tests.cpp index e9ecbc8..b7690f5 100644 --- a/kernel/src/filesystem/dentry.tests.cpp +++ b/kernel/src/filesystem/dentry.tests.cpp @@ -21,9 +21,9 @@ SCENARIO("Dentry construction", "[filesystem][dentry]") THEN("the dentry has the correct parent, inode, and name") { - REQUIRE(child_dentry.get_parent() == parent_dentry); + REQUIRE(child_dentry.parent() == parent_dentry); REQUIRE(child_dentry.get_inode() == inode); - REQUIRE(child_dentry.get_name() == "child"); + REQUIRE(child_dentry.name() == "child"); } THEN("no flag is set") @@ -46,9 +46,9 @@ SCENARIO("Dentry construction", "[filesystem][dentry]") THEN("the dentry has a null parent, the correct inode, and the correct name") { - REQUIRE(child_dentry.get_parent() == nullptr); + REQUIRE(child_dentry.parent() == nullptr); REQUIRE(child_dentry.get_inode() == inode); - REQUIRE(child_dentry.get_name() == "child"); + REQUIRE(child_dentry.name() == "child"); } THEN("no flag is set") @@ -142,9 +142,9 @@ SCENARIO("Dentry path resolution", "[filesystem][dentry]") THEN("the full path is constructed correctly") { - REQUIRE(root_dentry->get_absolute_path() == "/"); - REQUIRE(home_dentry->get_absolute_path() == "/home"); - REQUIRE(user_dentry->get_absolute_path() == "/home/user"); + REQUIRE(root_dentry->absolute_path() == "/"); + REQUIRE(home_dentry->absolute_path() == "/home"); + REQUIRE(user_dentry->absolute_path() == "/home/user"); } } } \ No newline at end of file diff --git a/kernel/src/filesystem/devfs/filesystem.cpp b/kernel/src/filesystem/devfs/filesystem.cpp index 96e40a8..f0d8bf7 100644 --- a/kernel/src/filesystem/devfs/filesystem.cpp +++ b/kernel/src/filesystem/devfs/filesystem.cpp @@ -1,5 +1,6 @@ #include +#include "kernel/filesystem/filesystem.hpp" #include #include #include @@ -22,7 +23,7 @@ namespace kernel::filesystem::devfs return operation_result::success; } - auto filesystem::lookup(kstd::shared_ptr const & parent, std::string_view name) + auto filesystem::lookup(kstd::shared_ptr const & parent, std::string_view name) const -> kstd::shared_ptr { if (!parent || !parent->is_directory()) @@ -36,12 +37,11 @@ namespace kernel::filesystem::devfs } auto it = std::ranges::find_if(m_inodes, [&](auto const & dev_node) { - auto device_inode_ptr = static_cast(dev_node.get()); - if (!device_inode_ptr) + if (auto device_inode_ptr = static_cast(dev_node.get())) { - return false; + return device_inode_ptr->device()->name() == name; } - return device_inode_ptr->device()->name() == name; + return false; }); return (it != m_inodes.end()) ? *it : nullptr; } diff --git a/kernel/src/filesystem/devfs/inode.cpp b/kernel/src/filesystem/devfs/inode.cpp index 2029a7f..7bbfbbe 100644 --- a/kernel/src/filesystem/devfs/inode.cpp +++ b/kernel/src/filesystem/devfs/inode.cpp @@ -4,12 +4,12 @@ namespace kernel::filesystem::devfs { - auto inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t + auto inode::read(void *, size_t, size_t) const -> size_t { return 0; } - auto inode::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t + auto inode::write(void const *, size_t, size_t) -> size_t { return 0; } diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 893cc38..7633972 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -28,14 +28,12 @@ namespace kernel::filesystem::ext2 return operation_result::invalid_magic_number; } - auto const block_size = get_block_size(); auto const blocks_per_group = m_superblock.blocks_per_group; auto const num_block_groups = (m_superblock.blocks_count + blocks_per_group - 1) / blocks_per_group; m_block_group_descriptors = kstd::vector(num_block_groups); - auto const block_group_descriptor_table_offset = block_size == 1024 ? 2 * block_size : block_size; - m_backing_inode->read(m_block_group_descriptors.data(), block_group_descriptor_table_offset, + m_backing_inode->read(m_block_group_descriptors.data(), block_group_descriptor_table_offset(), num_block_groups * sizeof(block_group_descriptor)); m_root_inode = read_inode(constants::root_inode_number); @@ -47,7 +45,7 @@ namespace kernel::filesystem::ext2 return operation_result::success; } - auto filesystem::lookup(kstd::shared_ptr const & parent, std::string_view name) + auto filesystem::lookup(kstd::shared_ptr const & parent, std::string_view name) const -> kstd::shared_ptr { if (!parent || !parent->is_directory()) @@ -61,20 +59,19 @@ namespace kernel::filesystem::ext2 return nullptr; } - auto const block_size = get_block_size(); auto const & inode_data = ext2_parent->data(); - kstd::vector buffer(block_size); + kstd::vector buffer(block_size()); - for (uint32_t i = 0; i < get_inode_block_count(inode_data); ++i) + for (auto i = 0uz; i < inode_block_count(inode_data); ++i) { auto const global_block_number = map_inode_block_index_to_global_block_number(i, inode_data); - auto const block_offset = global_block_number * block_size; - m_backing_inode->read(buffer.data(), block_offset, block_size); + auto const block_offset = global_block_number * block_size(); + m_backing_inode->read(buffer.data(), block_offset, block_size()); auto const * entry = reinterpret_cast(buffer.data()); auto bytes_read = 0uz; - while (bytes_read < block_size && entry->inode != 0) + while (bytes_read < block_size() && entry->inode != 0) { auto const entry_name = std::string_view{entry->name.data(), entry->name_len}; if (entry_name == name) @@ -90,9 +87,8 @@ namespace kernel::filesystem::ext2 return nullptr; } - auto filesystem::read_inode(uint32_t inode_number) const -> kstd::shared_ptr + auto filesystem::read_inode(size_t inode_number) const -> kstd::shared_ptr { - auto const block_size = get_block_size(); auto const inodes_per_group = m_superblock.inodes_per_group; auto const block_group_index = (inode_number - 1) / inodes_per_group; auto const inode_index_within_group = (inode_number - 1) % inodes_per_group; @@ -104,8 +100,8 @@ 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(inode_table_start_block) * block_size; - auto const inode_offset = inode_table_offset + inode_index_within_group * get_inode_size(); + auto const inode_table_offset = static_cast(inode_table_start_block) * block_size(); + auto const inode_offset = inode_table_offset + inode_index_within_group * inode_size(); auto new_inode_data = inode_data{}; m_backing_inode->read(&new_inode_data, inode_offset, sizeof(inode_data)); @@ -113,7 +109,7 @@ namespace kernel::filesystem::ext2 return kstd::make_shared(this, new_inode_data); } - auto filesystem::map_inode_block_index_to_global_block_number(uint32_t inode_block_index, inode_data data) const + auto filesystem::map_inode_block_index_to_global_block_number(size_t inode_block_index, inode_data data) const -> ssize_t { if (inode_block_index < constants::direct_block_count) @@ -145,18 +141,19 @@ namespace kernel::filesystem::ext2 return -1; } - auto filesystem::read_singly_indirect_block_number(uint32_t singly_indirect_block_number, - uint32_t block_index_in_singly_indirect_block) const -> uint32_t + auto filesystem::read_singly_indirect_block_number(size_t singly_indirect_block_number, + size_t block_index_in_singly_indirect_block) const -> size_t { if (singly_indirect_block_number == 0) { return 0; } + return read_block_number_at_index(singly_indirect_block_number, block_index_in_singly_indirect_block); } - auto filesystem::read_doubly_indirect_block_number(uint32_t doubly_indirect_block_number, - uint32_t block_index_in_doubly_indirect_block) const -> uint32_t + auto filesystem::read_doubly_indirect_block_number(size_t doubly_indirect_block_number, + size_t block_index_in_doubly_indirect_block) const -> size_t { if (doubly_indirect_block_number == 0) { @@ -174,8 +171,8 @@ namespace kernel::filesystem::ext2 return read_singly_indirect_block_number(singly_indirect_block_number, block_index_in_singly_indirect_block); } - auto filesystem::read_triply_indirect_block_number(uint32_t triply_indirect_block_number, - uint32_t block_index_in_triply_indirect_block) const -> uint32_t + auto filesystem::read_triply_indirect_block_number(size_t triply_indirect_block_number, + size_t block_index_in_triply_indirect_block) const -> size_t { if (triply_indirect_block_number == 0) { @@ -193,54 +190,59 @@ namespace kernel::filesystem::ext2 return read_doubly_indirect_block_number(doubly_indirect_block_number, block_index_in_doubly_indirect_block); } - auto filesystem::read_block_number_at_index(uint32_t block_number, uint32_t index) const -> uint32_t + auto filesystem::read_block_number_at_index(size_t block_number, size_t index) const -> size_t { - uint32_t block_number_buffer = 0; + auto block_number_buffer = 0uz; - auto const block_start_offset = block_number * get_block_size(); + auto const block_start_offset = block_number * block_size(); auto const number_start_address = block_start_offset + index * sizeof(uint32_t); m_backing_inode->read(&block_number_buffer, number_start_address, sizeof(uint32_t)); return block_number_buffer; } - auto filesystem::block_numbers_per_block() const -> uint32_t + auto filesystem::block_numbers_per_block() const -> size_t { - return get_block_size() / sizeof(uint32_t); + return block_size() / sizeof(uint32_t); } - auto filesystem::block_numbers_per_singly_indirect_block() const -> uint32_t + auto filesystem::block_numbers_per_singly_indirect_block() const -> size_t { return block_numbers_per_block(); } - auto filesystem::block_numbers_per_doubly_indirect_block() const -> uint32_t + auto filesystem::block_numbers_per_doubly_indirect_block() const -> size_t { return block_numbers_per_singly_indirect_block() * block_numbers_per_block(); } - auto filesystem::block_numbers_per_triply_indirect_block() const -> uint32_t + auto filesystem::block_numbers_per_triply_indirect_block() const -> size_t { return block_numbers_per_doubly_indirect_block() * block_numbers_per_block(); } - auto filesystem::get_block_size() const -> size_t + auto filesystem::block_size() const -> size_t { return constants::base_block_size << m_superblock.log_block_size; } - auto filesystem::get_revision_level() const -> size_t + auto filesystem::revision_level() const -> size_t { return m_superblock.rev_level; } - auto filesystem::get_inode_size() const -> size_t + auto filesystem::inode_size() const -> size_t { - return get_revision_level() == constants::good_old_revision ? 128 : m_superblock.inode_size; + return revision_level() == constants::good_old_revision ? 128 : m_superblock.inode_size; } - auto filesystem::get_inode_block_count(inode_data const & data) const -> uint32_t + auto filesystem::inode_block_count(inode_data const & data) const -> size_t { return data.blocks / (2 << m_superblock.log_block_size); } + + auto filesystem::block_group_descriptor_table_offset() const -> size_t + { + return block_size() == 1024 ? 2 * block_size() : block_size(); + } } // namespace kernel::filesystem::ext2 diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp index cfe0a35..f8c818c 100644 --- a/kernel/src/filesystem/ext2/inode.cpp +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -25,18 +25,18 @@ namespace kernel::filesystem::ext2 auto inode::read(void * buffer, size_t offset, size_t size) const -> size_t { - auto const max_readable = get_size() - offset; + auto const max_readable = this->size() - offset; auto const requested_size = std::min(size, max_readable); - if (is_symbolic_link() && get_size() <= sizeof(m_data.block)) + if (is_symbolic_link() && this->size() <= sizeof(m_data.block)) { auto inline_target = reinterpret_cast(m_data.block.data()); kstd::libc::memcpy(static_cast(buffer), inline_target + offset, requested_size); return requested_size; } - auto block_index = offset / m_filesystem->get_block_size(); - auto in_block_offset = offset % m_filesystem->get_block_size(); + auto block_index = offset / m_filesystem->block_size(); + auto in_block_offset = offset % m_filesystem->block_size(); auto bytes_read = 0uz; @@ -48,8 +48,7 @@ namespace kernel::filesystem::ext2 break; } - auto const bytes_to_read = - std::min(requested_size - bytes_read, m_filesystem->get_block_size() - in_block_offset); + 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(buffer) + bytes_read, 0, bytes_to_read); @@ -57,7 +56,7 @@ namespace kernel::filesystem::ext2 } else { - auto const block_start_offset = block_number * m_filesystem->get_block_size(); + auto const block_start_offset = block_number * m_filesystem->block_size(); auto const read_offset = block_start_offset + in_block_offset; bytes_read += m_filesystem->backing_inode()->read(static_cast(buffer) + bytes_read, read_offset, @@ -71,7 +70,7 @@ namespace kernel::filesystem::ext2 return bytes_read; } - auto inode::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t + auto inode::write(void const *, size_t, size_t) -> size_t { kapi::system::panic("[EXT2] inode::write is not implemented yet"); return 0; @@ -97,11 +96,11 @@ namespace kernel::filesystem::ext2 return (m_data.mode & constants::mode_mask) == constants::mode_symbolic_link; } - auto inode::get_size() const -> size_t + auto inode::size() const -> size_t { uint64_t size = m_data.size; - if (m_filesystem->get_revision_level() > constants::good_old_revision && is_regular()) + if (m_filesystem->revision_level() > constants::good_old_revision && is_regular()) { size |= static_cast(m_data.dir_acl) << 32; } diff --git a/kernel/src/filesystem/ext2/inode.tests.cpp b/kernel/src/filesystem/ext2/inode.tests.cpp index efc0660..4aecc04 100644 --- a/kernel/src/filesystem/ext2/inode.tests.cpp +++ b/kernel/src/filesystem/ext2/inode.tests.cpp @@ -325,7 +325,7 @@ SCENARIO("Ext2 inode get_size() correctly returns size depending on revision lev auto inode = kernel::filesystem::ext2::inode{&fs, data}; - REQUIRE(inode.get_size() == 256); + REQUIRE(inode.size() == 256); } THEN("the inode size is 256 if mode = directory") @@ -334,7 +334,7 @@ SCENARIO("Ext2 inode get_size() correctly returns size depending on revision lev auto inode = kernel::filesystem::ext2::inode{&fs, data}; - REQUIRE(inode.get_size() == 256); + REQUIRE(inode.size() == 256); } } @@ -361,7 +361,7 @@ SCENARIO("Ext2 inode get_size() correctly returns size depending on revision lev auto inode = kernel::filesystem::ext2::inode{&fs, data}; - REQUIRE(inode.get_size() == 0x0000'0020'0000'0100); + REQUIRE(inode.size() == 0x0000'0020'0000'0100); } THEN("the inode size is 256 if mode = directory") @@ -370,7 +370,7 @@ SCENARIO("Ext2 inode get_size() correctly returns size depending on revision lev auto inode = kernel::filesystem::ext2::inode{&fs, data}; - REQUIRE(inode.get_size() == 256); + REQUIRE(inode.size() == 256); } } } \ No newline at end of file diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index 1e04083..b64c370 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -27,7 +27,7 @@ namespace kernel::filesystem } } - auto mount::get_mount_dentry() const -> kstd::shared_ptr const & + auto mount::mount_dentry() const -> kstd::shared_ptr const & { return m_mount_dentry; } @@ -37,21 +37,21 @@ namespace kernel::filesystem return m_filesystem; } - auto mount::get_root_dentry() const -> kstd::shared_ptr const & + auto mount::root_dentry() const -> kstd::shared_ptr const & { return m_root_dentry; } - auto mount::get_mount_path() const -> kstd::string + auto mount::mount_path() const -> kstd::string { if (m_mount_dentry) { - return m_mount_dentry->get_absolute_path(); + return m_mount_dentry->absolute_path(); } return "/"; } - auto mount::get_parent_mount() const -> kstd::shared_ptr const & + auto mount::parent_mount() const -> kstd::shared_ptr const & { return m_parent_mount; } @@ -77,7 +77,7 @@ namespace kernel::filesystem return m_ref_count == 0; } - auto mount::get_ref_count() const -> size_t + auto mount::ref_count() const -> size_t { return m_ref_count; } diff --git a/kernel/src/filesystem/mount.tests.cpp b/kernel/src/filesystem/mount.tests.cpp index e7dd709..6b66571 100644 --- a/kernel/src/filesystem/mount.tests.cpp +++ b/kernel/src/filesystem/mount.tests.cpp @@ -26,15 +26,15 @@ SCENARIO("Mount construction", "[filesystem][mount]") THEN("the mount has the correct filesystem, root dentry, mount dentry, and mount path") { REQUIRE(mount.get_filesystem() == fs); - REQUIRE(mount.get_root_dentry() == root_dentry); - REQUIRE(mount.get_mount_dentry() == root_dentry); - REQUIRE(mount.get_mount_path() == "/"); + REQUIRE(mount.root_dentry() == root_dentry); + REQUIRE(mount.mount_dentry() == root_dentry); + REQUIRE(mount.mount_path() == "/"); REQUIRE(mount.is_ready_to_unmount()); } THEN("the mount has no parent mount") { - REQUIRE(mount.get_parent_mount() == nullptr); + REQUIRE(mount.parent_mount() == nullptr); } } @@ -63,19 +63,19 @@ SCENARIO("Mount reference counting", "[filesystem][mount]") auto mount = kernel::filesystem::mount{root_dentry, root_dentry, fs, nullptr}; mount.increment_ref_count(); - REQUIRE(mount.get_ref_count() == 1); + REQUIRE(mount.ref_count() == 1); REQUIRE_FALSE(mount.is_ready_to_unmount()); mount.increment_ref_count(); - REQUIRE(mount.get_ref_count() == 2); + REQUIRE(mount.ref_count() == 2); REQUIRE_FALSE(mount.is_ready_to_unmount()); REQUIRE(mount.decrement_ref_count()); - REQUIRE(mount.get_ref_count() == 1); + REQUIRE(mount.ref_count() == 1); REQUIRE_FALSE(mount.is_ready_to_unmount()); REQUIRE(mount.decrement_ref_count()); - REQUIRE(mount.get_ref_count() == 0); + REQUIRE(mount.ref_count() == 0); REQUIRE(mount.is_ready_to_unmount()); } @@ -84,7 +84,7 @@ SCENARIO("Mount reference counting", "[filesystem][mount]") auto mount = kernel::filesystem::mount{root_dentry, root_dentry, fs, nullptr}; REQUIRE_FALSE(mount.decrement_ref_count()); - REQUIRE(mount.get_ref_count() == 0); + REQUIRE(mount.ref_count() == 0); REQUIRE(mount.is_ready_to_unmount()); } } diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index 9951590..26828b4 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -14,15 +14,15 @@ namespace kernel::filesystem { auto mount_table::has_child_mounts(kstd::shared_ptr const & parent_mount) const -> bool { - return std::ranges::any_of( - m_mounts, [&parent_mount](auto const & mount) { return mount->get_parent_mount() == parent_mount; }); + return std::ranges::any_of(m_mounts, + [&parent_mount](auto const & mount) { return mount->parent_mount() == parent_mount; }); } void mount_table::add_mount(kstd::shared_ptr const & mount) { m_mounts.push_back(mount); - if (auto mount_dentry = mount->get_mount_dentry()) + if (auto mount_dentry = mount->mount_dentry()) { mount_dentry->set_flag(dentry::dentry_flags::is_mount_point); } @@ -46,7 +46,7 @@ namespace kernel::filesystem return operation_result::has_child_mounts; } - mount->get_mount_dentry()->unset_flag(dentry::dentry_flags::is_mount_point); + mount->mount_dentry()->unset_flag(dentry::dentry_flags::is_mount_point); m_mounts.erase(mount_it); return operation_result::removed; } @@ -60,7 +60,6 @@ namespace kernel::filesystem auto mount_table::find_mount_iterator(std::string_view path) const -> kstd::vector>::const_iterator { - return std::ranges::find_last_if(m_mounts, [&](auto const & mount) { return mount->get_mount_path() == path; }) - .begin(); + return std::ranges::find_last_if(m_mounts, [&](auto const & mount) { return mount->mount_path() == path; }).begin(); } } // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/open_file_descriptor.cpp b/kernel/src/filesystem/open_file_descriptor.cpp index ebaabef..a5567bf 100644 --- a/kernel/src/filesystem/open_file_descriptor.cpp +++ b/kernel/src/filesystem/open_file_descriptor.cpp @@ -33,7 +33,7 @@ namespace kernel::filesystem return written_bytes; } - auto open_file_descriptor::get_offset() const -> size_t + auto open_file_descriptor::offset() const -> size_t { return m_offset; } diff --git a/kernel/src/filesystem/open_file_descriptor.tests.cpp b/kernel/src/filesystem/open_file_descriptor.tests.cpp index 1910b8b..8c24cf0 100644 --- a/kernel/src/filesystem/open_file_descriptor.tests.cpp +++ b/kernel/src/filesystem/open_file_descriptor.tests.cpp @@ -26,7 +26,7 @@ SCENARIO("Open file descriptor construction", "[filesystem][open_file_descriptor THEN("the initial offset is zero") { - REQUIRE(file_descriptor.get_offset() == 0); + REQUIRE(file_descriptor.offset() == 0); } } } @@ -42,29 +42,29 @@ 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.get_offset() == 100); + REQUIRE(file_descriptor.offset() == 100); REQUIRE(file_descriptor.read(nullptr, 50) == 50); - REQUIRE(file_descriptor.get_offset() == 150); + REQUIRE(file_descriptor.offset() == 150); } THEN("the offset is updated correctly after writes") { REQUIRE(file_descriptor.write(nullptr, 200) == 200); - REQUIRE(file_descriptor.get_offset() == 200); + REQUIRE(file_descriptor.offset() == 200); REQUIRE(file_descriptor.write(nullptr, 25) == 25); - REQUIRE(file_descriptor.get_offset() == 225); + REQUIRE(file_descriptor.offset() == 225); } THEN("reads and writes both update the same offset") { REQUIRE(file_descriptor.read(nullptr, 10) == 10); - REQUIRE(file_descriptor.get_offset() == 10); + REQUIRE(file_descriptor.offset() == 10); REQUIRE(file_descriptor.write(nullptr, 20) == 20); - REQUIRE(file_descriptor.get_offset() == 30); + REQUIRE(file_descriptor.offset() == 30); REQUIRE(file_descriptor.read(nullptr, 5) == 5); - REQUIRE(file_descriptor.get_offset() == 35); + REQUIRE(file_descriptor.offset() == 35); REQUIRE(file_descriptor.write(nullptr, 15) == 15); - REQUIRE(file_descriptor.get_offset() == 50); + REQUIRE(file_descriptor.offset() == 50); } } } @@ -89,7 +89,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Ope kstd::vector buffer(32); auto bytes_read = ofd->read(buffer.data(), buffer.size()); REQUIRE(bytes_read == 7); - REQUIRE(ofd->get_offset() == 7); + REQUIRE(ofd->offset() == 7); std::string_view buffer_as_str{reinterpret_cast(buffer.data()), static_cast(bytes_read)}; REQUIRE(buffer_as_str == "info_1\n"); @@ -100,11 +100,11 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Ope kstd::vector buffer(4); auto bytes_read_1 = ofd->read(buffer.data(), buffer.size() / 2); REQUIRE(bytes_read_1 == buffer.size() / 2); - REQUIRE(ofd->get_offset() == buffer.size() / 2); + REQUIRE(ofd->offset() == 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->get_offset() == buffer.size()); + REQUIRE(ofd->offset() == buffer.size()); std::string_view buffer_as_str{reinterpret_cast(buffer.data()), bytes_read_1 + bytes_read_2}; REQUIRE(buffer_as_str == "info"); diff --git a/kernel/src/filesystem/open_file_table.cpp b/kernel/src/filesystem/open_file_table.cpp index e47d229..4d52d36 100644 --- a/kernel/src/filesystem/open_file_table.cpp +++ b/kernel/src/filesystem/open_file_table.cpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace { @@ -37,7 +38,7 @@ namespace kernel::filesystem return *global_open_file_table; } - auto open_file_table::add_file(kstd::shared_ptr const & file_descriptor) -> int + auto open_file_table::add_file(kstd::shared_ptr const & file_descriptor) -> ssize_t { if (!file_descriptor) { @@ -48,43 +49,31 @@ namespace kernel::filesystem if (it != m_open_files.end()) { *it = file_descriptor; - return static_cast(it - m_open_files.begin()); + return it - m_open_files.begin(); } m_open_files.push_back(file_descriptor); - return static_cast(m_open_files.size() - 1); + return m_open_files.size() - 1; } - auto open_file_table::get_file(int fd) const -> kstd::shared_ptr + auto open_file_table::file(size_t fd) const -> kstd::shared_ptr { - if (fd < 0) + if (fd >= m_open_files.size()) { return nullptr; } - auto const index = static_cast(fd); - if (index >= m_open_files.size()) - { - return nullptr; - } - - return m_open_files.at(index); + return m_open_files.at(fd); } - auto open_file_table::remove_file(int fd) -> int + auto open_file_table::remove_file(size_t fd) -> ssize_t { - if (fd < 0) - { - return -1; - } - - auto const index = static_cast(fd); - if (index >= m_open_files.size()) + if (fd >= m_open_files.size()) { return -1; } - m_open_files.at(index) = nullptr; + m_open_files.at(fd) = nullptr; return 0; } } // namespace kernel::filesystem diff --git a/kernel/src/filesystem/open_file_table.tests.cpp b/kernel/src/filesystem/open_file_table.tests.cpp index 456d6b7..3e91111 100644 --- a/kernel/src/filesystem/open_file_table.tests.cpp +++ b/kernel/src/filesystem/open_file_table.tests.cpp @@ -36,7 +36,7 @@ SCENARIO("Open file table add/get file", "[filesystem][open_file_table]") THEN("the file descriptor can be retrieved using the returned file descriptor") { - auto retrieved_descriptor = table.get_file(fd_1); + auto retrieved_descriptor = table.file(fd_1); REQUIRE(retrieved_descriptor == file_descriptor_1); } } @@ -52,15 +52,9 @@ SCENARIO("Open file table add/get file", "[filesystem][open_file_table]") REQUIRE(fd == -1); } - THEN("retrieving a file descriptor with a negative file descriptor returns a null pointer") - { - auto retrieved_descriptor = table.get_file(-1); - REQUIRE(retrieved_descriptor == nullptr); - } - THEN("retrieving a file descriptor with an out-of-bounds file descriptor returns a null pointer") { - auto retrieved_descriptor = table.get_file(1000); + auto retrieved_descriptor = table.file(1000); REQUIRE(retrieved_descriptor == nullptr); } } @@ -82,7 +76,7 @@ SCENARIO("Open file table remove file", "[filesystem][open_file_table]") THEN("the file descriptor can no longer be retrieved using the file descriptor") { - auto retrieved_descriptor = table.get_file(fd); + auto retrieved_descriptor = table.file(fd); REQUIRE(retrieved_descriptor == nullptr); } } @@ -94,7 +88,7 @@ SCENARIO("Open file table remove file", "[filesystem][open_file_table]") THEN("the second file descriptor can still be retrieved using its file descriptor") { - auto retrieved_descriptor = table.get_file(fd2); + auto retrieved_descriptor = table.file(fd2); REQUIRE(retrieved_descriptor == file_descriptor); } } @@ -104,11 +98,6 @@ SCENARIO("Open file table remove file", "[filesystem][open_file_table]") { auto & table = kernel::filesystem::open_file_table::get(); - THEN("removing a file with a negative file descriptor does nothing") - { - REQUIRE_NOTHROW(table.remove_file(-1)); - } - THEN("removing a file with an out-of-bounds file descriptor does nothing") { REQUIRE_NOTHROW(table.remove_file(1000)); diff --git a/kernel/src/filesystem/rootfs/filesystem.cpp b/kernel/src/filesystem/rootfs/filesystem.cpp index d49e237..0ba2936 100644 --- a/kernel/src/filesystem/rootfs/filesystem.cpp +++ b/kernel/src/filesystem/rootfs/filesystem.cpp @@ -1,5 +1,6 @@ #include +#include "kernel/filesystem/filesystem.hpp" #include #include @@ -15,7 +16,7 @@ namespace kernel::filesystem::rootfs return operation_result::success; } - auto filesystem::lookup(kstd::shared_ptr const &, std::string_view) + auto filesystem::lookup(kstd::shared_ptr const &, std::string_view) const -> kstd::shared_ptr { return nullptr; diff --git a/kernel/src/filesystem/rootfs/inode.cpp b/kernel/src/filesystem/rootfs/inode.cpp index dbe7948..f64fb87 100644 --- a/kernel/src/filesystem/rootfs/inode.cpp +++ b/kernel/src/filesystem/rootfs/inode.cpp @@ -2,19 +2,16 @@ #include -#include -#include - #include namespace kernel::filesystem::rootfs { - auto inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t + auto inode::read(void *, size_t, size_t) const -> size_t { return 0; } - auto inode::write(void const * /*buffer*/, size_t /*offset*/, size_t /*size*/) -> size_t + auto inode::write(void const *, size_t, size_t) -> size_t { return 0; } diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 8636d0f..bf9a77d 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -153,7 +153,7 @@ namespace kernel::filesystem -> void { auto new_fs_root = - kstd::make_shared(mount_point_dentry->get_parent(), fs->root_inode(), mount_point_dentry->get_name()); + kstd::make_shared(mount_point_dentry->parent(), fs->root_inode(), mount_point_dentry->name()); auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, parent_mount); m_mount_table.add_mount(new_mount); } @@ -174,7 +174,8 @@ namespace kernel::filesystem } } - auto vfs::resolve_path_internal(std::string_view path) -> std::pair, kstd::shared_ptr> + auto vfs::resolve_path_internal(std::string_view path) const + -> std::pair, kstd::shared_ptr> { if (!path::is_valid_absolute_path(path)) { @@ -187,7 +188,7 @@ namespace kernel::filesystem kapi::system::panic("[FILESYSTEM] no root mount found."); } - auto current_dentry = current_mount->get_root_dentry(); + auto current_dentry = current_mount->root_dentry(); auto path_parts = path::split(path); kstd::vector path_parts_vector(path_parts.begin(), path_parts.end()); @@ -207,16 +208,16 @@ namespace kernel::filesystem if (part == "..") { - auto parent_dentry = current_dentry->get_parent(); + auto parent_dentry = current_dentry->parent(); - if (current_dentry == current_mount->get_root_dentry()) + if (current_dentry == current_mount->root_dentry()) { - if (current_mount->get_mount_path() == "/") + if (current_mount->mount_path() == "/") { continue; } - if (auto parent_mount = current_mount->get_parent_mount()) + if (auto parent_mount = current_mount->parent_mount()) { current_mount = parent_mount; current_dentry = parent_dentry; @@ -242,13 +243,13 @@ namespace kernel::filesystem } else if (next_dentry->has_flag(dentry::dentry_flags::is_mount_point)) { - current_mount = m_mount_table.find_mount(next_dentry->get_absolute_path().view()); + current_mount = m_mount_table.find_mount(next_dentry->absolute_path().view()); if (!current_mount) { kapi::system::panic("[FILESYSTEM] mount for dentry with mounted flag not found."); } - next_dentry = current_mount->get_root_dentry(); + next_dentry = current_mount->root_dentry(); } if (next_dentry->get_inode()->is_symbolic_link()) @@ -271,7 +272,7 @@ namespace kernel::filesystem if (path::is_valid_absolute_path(symbolic_link_path)) { current_mount = m_mount_table.find_mount("/"); - current_dentry = current_mount->get_root_dentry(); + current_dentry = current_mount->root_dentry(); } continue; } @@ -281,12 +282,12 @@ namespace kernel::filesystem return {current_dentry, current_mount}; } - auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr + auto vfs::resolve_path(std::string_view path) const -> kstd::shared_ptr { return resolve_path_internal(path).first; } - auto vfs::find_mount(std::string_view path) -> kstd::shared_ptr + auto vfs::find_mount(std::string_view path) const -> kstd::shared_ptr { return resolve_path_internal(path).second; } diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 648ebb8..6fcc84e 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -105,7 +105,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); REQUIRE(mounted_monkey_1 != nullptr); - REQUIRE(vfs.close(mounted_monkey_1->get_absolute_path().view()) == + REQUIRE(vfs.close(mounted_monkey_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); @@ -128,10 +128,9 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(mounted_monkey_1 != nullptr); REQUIRE(mounted_fish1 != nullptr); - REQUIRE(vfs.close(mounted_monkey_1->get_absolute_path().view()) == - kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.close(mounted_fish1->get_absolute_path().view()) == + REQUIRE(vfs.close(mounted_monkey_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(mounted_fish1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); REQUIRE(vfs.unmount("/information/monkey_house/infrastructure") == @@ -148,7 +147,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); - REQUIRE(vfs.close(mounted_monkey_1->get_absolute_path().view()) == + REQUIRE(vfs.close(mounted_monkey_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); @@ -165,8 +164,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto info_1 = vfs.open("/information/info_1.txt"); REQUIRE(info_1 != nullptr); - REQUIRE(vfs.close(info_1->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.close(info_1->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::close_failed); + REQUIRE(vfs.close(info_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(info_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::close_failed); } THEN("images can be stacked mounted and correct file system is unmounted again") @@ -177,8 +176,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto mounted_tickets = vfs.open("/information/entrance/tickets.txt"); REQUIRE(mounted_tickets != nullptr); - REQUIRE(vfs.close(mounted_tickets->get_absolute_path().view()) == - kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(mounted_tickets->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); mounted_tickets = vfs.open("/information/entrance/tickets.txt"); @@ -201,7 +199,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto water = vfs.open("/monkey_house/infrastructure/water.txt"); REQUIRE(water != nullptr); - REQUIRE(vfs.close(water->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(water->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success); @@ -222,7 +220,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto water = vfs.open("/monkey_house/infrastructure/water.txt"); REQUIRE(water != nullptr); - REQUIRE(vfs.close(water->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(water->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); auto dev_ram_16 = vfs.open("/dev/ram16"); REQUIRE(dev_ram_16 == nullptr); @@ -240,7 +238,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto info_1 = vfs.open("/information/info_1.txt"); REQUIRE(info_1 != nullptr); - REQUIRE(vfs.close(info_1->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(info_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/dev") == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success); @@ -363,7 +361,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS std::string_view buffer_as_str{reinterpret_cast(buffer.data()), bytes_read}; REQUIRE(buffer_as_str == "sheep_1"); - REQUIRE(vfs.close(dentry->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(dentry->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); auto unmounted_sheep_1 = vfs.open("/information/sheep_1.txt"); @@ -396,8 +394,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS buffer_as_str = std::string_view{reinterpret_cast(goat_buffer.data()), bytes_read}; REQUIRE(buffer_as_str == "goat_1"); - REQUIRE(vfs.close(sheep_1->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.close(goat_1->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(sheep_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(goat_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); @@ -408,7 +406,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto still_mounted_sheep_1 = vfs.open("/information/sheep_1.txt"); REQUIRE(still_mounted_sheep_1 != nullptr); - REQUIRE(vfs.close(still_mounted_sheep_1->get_absolute_path().view()) == + REQUIRE(vfs.close(still_mounted_sheep_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); diff --git a/kernel/src/test_support/filesystem/filesystem.cpp b/kernel/src/test_support/filesystem/filesystem.cpp index 12d43e0..ec70607 100644 --- a/kernel/src/test_support/filesystem/filesystem.cpp +++ b/kernel/src/test_support/filesystem/filesystem.cpp @@ -9,7 +9,7 @@ namespace kernel::tests::filesystem { - auto filesystem::lookup(kstd::shared_ptr const &, std::string_view) + auto filesystem::lookup(kstd::shared_ptr const &, std::string_view) const -> kstd::shared_ptr { return kstd::make_shared(); -- cgit v1.2.3 From 3d8ea5b1b833f39b77f0591fb2a301842ed5eb1c Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Sat, 16 May 2026 17:00:10 +0200 Subject: Refactor data types in ext2 --- kernel/src/filesystem/ext2/filesystem.cpp | 20 ++++++++++---------- kernel/src/filesystem/ext2/inode.cpp | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 7633972..df5b4c4 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -62,7 +62,7 @@ namespace kernel::filesystem::ext2 auto const & inode_data = ext2_parent->data(); kstd::vector buffer(block_size()); - for (auto i = 0uz; i < inode_block_count(inode_data); ++i) + for (uint32_t i = 0; i < inode_block_count(inode_data); ++i) { auto const global_block_number = map_inode_block_index_to_global_block_number(i, inode_data); auto const block_offset = global_block_number * block_size(); @@ -87,7 +87,7 @@ namespace kernel::filesystem::ext2 return nullptr; } - auto filesystem::read_inode(size_t inode_number) const -> kstd::shared_ptr + auto filesystem::read_inode(uint32_t inode_number) const -> kstd::shared_ptr { auto const inodes_per_group = m_superblock.inodes_per_group; auto const block_group_index = (inode_number - 1) / inodes_per_group; @@ -141,7 +141,7 @@ namespace kernel::filesystem::ext2 return -1; } - auto filesystem::read_singly_indirect_block_number(size_t singly_indirect_block_number, + auto filesystem::read_singly_indirect_block_number(uint32_t singly_indirect_block_number, size_t block_index_in_singly_indirect_block) const -> size_t { if (singly_indirect_block_number == 0) @@ -152,7 +152,7 @@ namespace kernel::filesystem::ext2 return read_block_number_at_index(singly_indirect_block_number, block_index_in_singly_indirect_block); } - auto filesystem::read_doubly_indirect_block_number(size_t doubly_indirect_block_number, + auto filesystem::read_doubly_indirect_block_number(uint32_t doubly_indirect_block_number, size_t block_index_in_doubly_indirect_block) const -> size_t { if (doubly_indirect_block_number == 0) @@ -171,7 +171,7 @@ namespace kernel::filesystem::ext2 return read_singly_indirect_block_number(singly_indirect_block_number, block_index_in_singly_indirect_block); } - auto filesystem::read_triply_indirect_block_number(size_t triply_indirect_block_number, + auto filesystem::read_triply_indirect_block_number(uint32_t triply_indirect_block_number, size_t block_index_in_triply_indirect_block) const -> size_t { if (triply_indirect_block_number == 0) @@ -190,9 +190,9 @@ namespace kernel::filesystem::ext2 return read_doubly_indirect_block_number(doubly_indirect_block_number, block_index_in_doubly_indirect_block); } - auto filesystem::read_block_number_at_index(size_t block_number, size_t index) const -> size_t + auto filesystem::read_block_number_at_index(uint32_t block_number, size_t index) const -> uint32_t { - auto block_number_buffer = 0uz; + 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); @@ -226,17 +226,17 @@ namespace kernel::filesystem::ext2 return constants::base_block_size << m_superblock.log_block_size; } - auto filesystem::revision_level() const -> size_t + auto filesystem::revision_level() const -> uint32_t { return m_superblock.rev_level; } - auto filesystem::inode_size() const -> size_t + auto filesystem::inode_size() const -> uint16_t { return revision_level() == constants::good_old_revision ? 128 : m_superblock.inode_size; } - auto filesystem::inode_block_count(inode_data const & data) const -> size_t + auto filesystem::inode_block_count(inode_data const & data) const -> uint32_t { return data.blocks / (2 << m_superblock.log_block_size); } diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp index f8c818c..35a32ee 100644 --- a/kernel/src/filesystem/ext2/inode.cpp +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -96,7 +96,7 @@ namespace kernel::filesystem::ext2 return (m_data.mode & constants::mode_mask) == constants::mode_symbolic_link; } - auto inode::size() const -> size_t + auto inode::size() const -> uint64_t { uint64_t size = m_data.size; -- cgit v1.2.3 From 2063d3e165a1b92a46c73badf56927228ed4d5e8 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 25 May 2026 10:15:21 +0200 Subject: Refactor ssize_t --- kernel/src/filesystem/ext2/filesystem.cpp | 4 ++-- kernel/src/filesystem/open_file_table.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index df5b4c4..a30149e 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -8,12 +8,12 @@ #include #include +#include #include #include #include #include -#include namespace kernel::filesystem::ext2 { @@ -110,7 +110,7 @@ namespace kernel::filesystem::ext2 } auto filesystem::map_inode_block_index_to_global_block_number(size_t inode_block_index, inode_data data) const - -> ssize_t + -> kstd::ssize_t { if (inode_block_index < constants::direct_block_count) { diff --git a/kernel/src/filesystem/open_file_table.cpp b/kernel/src/filesystem/open_file_table.cpp index 4d52d36..2afe3aa 100644 --- a/kernel/src/filesystem/open_file_table.cpp +++ b/kernel/src/filesystem/open_file_table.cpp @@ -5,11 +5,11 @@ #include #include +#include #include #include #include -#include namespace { @@ -38,7 +38,7 @@ namespace kernel::filesystem return *global_open_file_table; } - auto open_file_table::add_file(kstd::shared_ptr const & file_descriptor) -> ssize_t + auto open_file_table::add_file(kstd::shared_ptr const & file_descriptor) -> kstd::ssize_t { if (!file_descriptor) { @@ -66,7 +66,7 @@ namespace kernel::filesystem return m_open_files.at(fd); } - auto open_file_table::remove_file(size_t fd) -> ssize_t + auto open_file_table::remove_file(size_t fd) -> kstd::ssize_t { if (fd >= m_open_files.size()) { -- cgit v1.2.3 From 61d29a288334960cd9f43df91e4fd632a7f6ad66 Mon Sep 17 00:00:00 2001 From: Marcel Braun Date: Mon, 25 May 2026 11:13:18 +0200 Subject: Increase reference count of source_mount when one of its files is mounted somewhere --- kernel/src/filesystem/mount.cpp | 14 ++++++++++---- kernel/src/filesystem/mount.tests.cpp | 16 +++++++++------- kernel/src/filesystem/mount_table.cpp | 16 +++++++++++++++- kernel/src/filesystem/mount_table.tests.cpp | 14 +++++++------- kernel/src/filesystem/vfs.cpp | 26 ++++++++++++-------------- kernel/src/filesystem/vfs.tests.cpp | 5 +++-- 6 files changed, 56 insertions(+), 35 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index b64c370..ead7479 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -14,11 +14,13 @@ namespace kernel::filesystem { mount::mount(kstd::shared_ptr const & mount_dentry, kstd::shared_ptr const & root_dentry, - kstd::shared_ptr const & fs, kstd::shared_ptr const & parent_mount) + kstd::shared_ptr const & fs, kstd::shared_ptr const & parent_mount, + kstd::shared_ptr const & source_mount) : m_mount_dentry(mount_dentry) , m_root_dentry(root_dentry) , m_filesystem(fs) , m_parent_mount(parent_mount) + , m_source_mount(source_mount) , m_ref_count(0) { if (!m_filesystem) @@ -56,20 +58,24 @@ namespace kernel::filesystem return m_parent_mount; } + auto mount::source_mount() const -> kstd::shared_ptr + { + return m_source_mount.lock(); + } + auto mount::increment_ref_count() -> void { m_ref_count += 1; } - auto mount::decrement_ref_count() -> bool + auto mount::decrement_ref_count() -> void { if (m_ref_count == 0) { - return false; + kapi::system::panic("[FILESYSTEM] decrement_ref_count() was called but ref_count is 0"); } m_ref_count -= 1; - return true; } auto mount::is_ready_to_unmount() const -> bool diff --git a/kernel/src/filesystem/mount.tests.cpp b/kernel/src/filesystem/mount.tests.cpp index 6b66571..40b7cbb 100644 --- a/kernel/src/filesystem/mount.tests.cpp +++ b/kernel/src/filesystem/mount.tests.cpp @@ -11,6 +11,8 @@ #include +#include + SCENARIO("Mount construction", "[filesystem][mount]") { GIVEN("a filesystem and a root dentry") @@ -21,7 +23,7 @@ SCENARIO("Mount construction", "[filesystem][mount]") WHEN("constructing a mount with the filesystem and root dentry") { - auto mount = kernel::filesystem::mount{root_dentry, root_dentry, fs, nullptr}; + auto mount = kernel::filesystem::mount{root_dentry, root_dentry, fs, nullptr, nullptr}; THEN("the mount has the correct filesystem, root dentry, mount dentry, and mount path") { @@ -42,7 +44,7 @@ SCENARIO("Mount construction", "[filesystem][mount]") { THEN("the constructor panics") { - REQUIRE_THROWS_AS((kernel::filesystem::mount{root_dentry, root_dentry, nullptr, nullptr}), + REQUIRE_THROWS_AS((kernel::filesystem::mount{root_dentry, root_dentry, nullptr, nullptr, nullptr}), kernel::tests::cpu::halt); } } @@ -60,7 +62,7 @@ SCENARIO("Mount reference counting", "[filesystem][mount]") THEN("reference count can be incremented and decremented, the mount is ready to unmount when the reference " "count == 0") { - auto mount = kernel::filesystem::mount{root_dentry, root_dentry, fs, nullptr}; + auto mount = kernel::filesystem::mount{root_dentry, root_dentry, fs, nullptr, nullptr}; mount.increment_ref_count(); REQUIRE(mount.ref_count() == 1); @@ -70,20 +72,20 @@ SCENARIO("Mount reference counting", "[filesystem][mount]") REQUIRE(mount.ref_count() == 2); REQUIRE_FALSE(mount.is_ready_to_unmount()); - REQUIRE(mount.decrement_ref_count()); + mount.decrement_ref_count(); REQUIRE(mount.ref_count() == 1); REQUIRE_FALSE(mount.is_ready_to_unmount()); - REQUIRE(mount.decrement_ref_count()); + mount.decrement_ref_count(); REQUIRE(mount.ref_count() == 0); REQUIRE(mount.is_ready_to_unmount()); } THEN("decrementing reference count when it is already zero does not decrement it below zero") { - auto mount = kernel::filesystem::mount{root_dentry, root_dentry, fs, nullptr}; + auto mount = kernel::filesystem::mount{root_dentry, root_dentry, fs, nullptr, nullptr}; - REQUIRE_FALSE(mount.decrement_ref_count()); + REQUIRE_THROWS_AS(mount.decrement_ref_count(), std::runtime_error); REQUIRE(mount.ref_count() == 0); REQUIRE(mount.is_ready_to_unmount()); } diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index 26828b4..af8434b 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -22,6 +22,11 @@ namespace kernel::filesystem { m_mounts.push_back(mount); + if (auto source_mount = mount->source_mount()) + { + source_mount->increment_ref_count(); + } + if (auto mount_dentry = mount->mount_dentry()) { mount_dentry->set_flag(dentry::dentry_flags::is_mount_point); @@ -46,7 +51,16 @@ namespace kernel::filesystem return operation_result::has_child_mounts; } - mount->mount_dentry()->unset_flag(dentry::dentry_flags::is_mount_point); + if (auto source_mount = mount->source_mount()) + { + source_mount->decrement_ref_count(); + } + + if (auto mount_dentry = mount->mount_dentry()) + { + mount_dentry->unset_flag(dentry::dentry_flags::is_mount_point); + } + m_mounts.erase(mount_it); return operation_result::removed; } diff --git a/kernel/src/filesystem/mount_table.tests.cpp b/kernel/src/filesystem/mount_table.tests.cpp index f22b25e..8118e19 100644 --- a/kernel/src/filesystem/mount_table.tests.cpp +++ b/kernel/src/filesystem/mount_table.tests.cpp @@ -38,14 +38,14 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] nullptr, kstd::make_shared(), "/"); auto mount_dentry1 = kstd::make_shared( nullptr, kstd::make_shared(), "/"); - auto mount1 = kstd::make_shared(mount_dentry1, root_dentry1, fs1, nullptr); + auto mount1 = kstd::make_shared(mount_dentry1, root_dentry1, fs1, nullptr, nullptr); auto fs2 = kstd::make_shared(); auto root_dentry2 = kstd::make_shared( nullptr, kstd::make_shared(), "/"); auto mount_dentry2 = kstd::make_shared( nullptr, kstd::make_shared(), "/mnt"); - auto mount2 = kstd::make_shared(mount_dentry2, root_dentry2, fs2, nullptr); + auto mount2 = kstd::make_shared(mount_dentry2, root_dentry2, fs2, nullptr, nullptr); table.add_mount(mount1); table.add_mount(mount2); @@ -89,14 +89,14 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] nullptr, kstd::make_shared(), "/"); auto mount_dentry1 = kstd::make_shared( nullptr, kstd::make_shared(), "/"); - auto mount1 = kstd::make_shared(mount_dentry1, root_dentry1, fs1, nullptr); + auto mount1 = kstd::make_shared(mount_dentry1, root_dentry1, fs1, nullptr, nullptr); auto fs2 = kstd::make_shared(); auto root_dentry2 = kstd::make_shared( nullptr, kstd::make_shared(), "/"); auto mount_dentry2 = kstd::make_shared( nullptr, kstd::make_shared(), "/"); - auto mount2 = kstd::make_shared(mount_dentry2, root_dentry2, fs2, nullptr); + auto mount2 = kstd::make_shared(mount_dentry2, root_dentry2, fs2, nullptr, nullptr); table.add_mount(mount1); table.add_mount(mount2); @@ -122,21 +122,21 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] nullptr, kstd::make_shared(), "/"); auto mount_dentry1 = kstd::make_shared( nullptr, kstd::make_shared(), "/"); - auto mount1 = kstd::make_shared(mount_dentry1, root_dentry1, fs1, nullptr); + auto mount1 = kstd::make_shared(mount_dentry1, root_dentry1, fs1, nullptr, nullptr); auto fs2 = kstd::make_shared(); auto root_dentry2 = kstd::make_shared( nullptr, kstd::make_shared(), "/"); auto mount_dentry2 = kstd::make_shared( mount_dentry1, kstd::make_shared(), "mnt"); - auto mount2 = kstd::make_shared(mount_dentry2, root_dentry2, fs2, mount1); + auto mount2 = kstd::make_shared(mount_dentry2, root_dentry2, fs2, mount1, nullptr); auto fs3 = kstd::make_shared(); auto root_dentry3 = kstd::make_shared( nullptr, kstd::make_shared(), "/"); auto mount_dentry3 = kstd::make_shared( mount_dentry2, kstd::make_shared(), "submnt"); - auto mount3 = kstd::make_shared(mount_dentry3, root_dentry3, fs3, mount2); + auto mount3 = kstd::make_shared(mount_dentry3, root_dentry3, fs3, mount2, nullptr); table.add_mount(mount1); table.add_mount(mount2); diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index bf9a77d..ae85291 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -47,7 +47,7 @@ namespace kernel::filesystem root_fs->mount(nullptr); auto root_fs_root_dentry = kstd::make_shared(nullptr, root_fs->root_inode(), "/"); - auto root_mount = kstd::make_shared(nullptr, root_fs_root_dentry, root_fs, nullptr); + auto root_mount = kstd::make_shared(nullptr, root_fs_root_dentry, root_fs, nullptr, nullptr); m_mount_table.add_mount(root_mount); // mount devfs at /dev (inside rootfs, temporary, will be shadowed) @@ -56,13 +56,14 @@ namespace kernel::filesystem graft_persistent_device_fs(device_fs); // mount boot fs at / (shadows rootfs), re-graft devfs - if (auto boot_device_dentry = resolve_path("/dev/ram0")) + auto [boot_device_dentry, boot_device_mount_context] = resolve_path_internal("/dev/ram0"); + if (boot_device_dentry && boot_device_mount_context) { if (auto boot_root_fs = kernel::filesystem::filesystem::probe_and_mount(boot_device_dentry->get_inode())) { if (auto root_dentry = resolve_path("/")) { - do_mount_internal(root_dentry, root_mount, boot_root_fs); + do_mount_internal(root_dentry, root_mount, boot_root_fs, boot_device_mount_context); graft_persistent_device_fs(device_fs); } } @@ -94,11 +95,8 @@ namespace kernel::filesystem { if (auto mount = find_mount(path)) { - if (mount->decrement_ref_count()) - { - return operation_result::success; - } - return operation_result::close_failed; + mount->decrement_ref_count(); + return operation_result::success; } return operation_result::invalid_path; } @@ -111,14 +109,14 @@ namespace kernel::filesystem } auto [mount_point_dentry, mount_context] = resolve_path_internal(target); - if (mount_point_dentry && mount_context) { - if (auto source_dentry = resolve_path(source)) + auto [source_dentry, source_mount_context] = resolve_path_internal(source); + if (source_dentry && source_mount_context) { if (auto fs = kernel::filesystem::filesystem::probe_and_mount(source_dentry->get_inode())) { - do_mount_internal(mount_point_dentry, mount_context, fs); + do_mount_internal(mount_point_dentry, mount_context, fs, source_mount_context); return operation_result::success; } return operation_result::invalid_filesystem; @@ -149,12 +147,12 @@ namespace kernel::filesystem } auto vfs::do_mount_internal(kstd::shared_ptr const & mount_point_dentry, - kstd::shared_ptr const & parent_mount, kstd::shared_ptr const & fs) - -> void + kstd::shared_ptr const & parent_mount, kstd::shared_ptr const & fs, + kstd::shared_ptr const & source_mount) -> void { auto new_fs_root = kstd::make_shared(mount_point_dentry->parent(), fs->root_inode(), mount_point_dentry->name()); - auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, parent_mount); + auto new_mount = kstd::make_shared(mount_point_dentry, new_fs_root, fs, parent_mount, source_mount); m_mount_table.add_mount(new_mount); } diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 6fcc84e..8ae206a 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -10,6 +10,7 @@ #include #include +#include #include SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS with dummy modules", @@ -156,7 +157,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS THEN("file with invalid path or not opened file cannot be closed") { REQUIRE(vfs.close("invalid_path") == kernel::filesystem::vfs::operation_result::invalid_path); - REQUIRE(vfs.close("/information/info_1.txt") == kernel::filesystem::vfs::operation_result::close_failed); + REQUIRE_THROWS_AS(vfs.close("/information/info_1.txt"), std::runtime_error); } THEN("file cannot be closed twice") @@ -165,7 +166,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(info_1 != nullptr); REQUIRE(vfs.close(info_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.close(info_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::close_failed); + REQUIRE_THROWS_AS(vfs.close(info_1->absolute_path().view()), std::runtime_error); } THEN("images can be stacked mounted and correct file system is unmounted again") -- cgit v1.2.3 From 90d4163c336348cd21db8cbdb292994ddcfa3908 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Mon, 25 May 2026 11:43:00 +0200 Subject: improve demo code --- kernel/src/main.cpp | 50 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 12 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 22d2b1e..25b5c00 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -26,57 +26,83 @@ using namespace kstd::units_literals; auto run_demo() -> void { // 1) open a file + kstd::println("attempting to open /entrance/tickets.txt"); auto fd_1 = kapi::filesystem::open("/entrance/tickets.txt"); if (fd_1 == -1) { - kstd::os::panic("demo failed"); + kapi::system::panic("demo failed"); + } + else + { + kstd::println("--> successfully opened /entrance/tickets.txt with file descriptor {}", fd_1); } // 2) read from the file kstd::vector buffer_1{10}; auto bytes_read = kapi::filesystem::read(fd_1, buffer_1.data(), buffer_1.size()); auto buffer_as_str = std::string_view{reinterpret_cast(buffer_1.data()), static_cast(bytes_read)}; - kstd::println("Read {} bytes from /entrance/tickets.txt: {}", bytes_read, buffer_as_str); + kstd::println("--> read {} bytes from /entrance/tickets.txt: {}", bytes_read, buffer_as_str); + kstd::println(""); // 3) show that /entrance/information/info_1.txt is not accessible before mounting + kstd::println("attempting to open /entrance/information/info_1.txt before mounting"); auto fd_before_mount = kapi::filesystem::open("/entrance/information/info_1.txt"); if (fd_before_mount == -1) { - kstd::println("/entrance/information/info_1.txt is not accessible before mounting, as expected."); + kstd::println("--> as expected the file could not be opened before mounting"); } // 4) mount a new filesystem on top of /entrance - kapi::filesystem::mount("/dev/ram16", "/entrance"); + kstd::println("mount /dev/ram16 to /entrance"); + if (kapi::filesystem::mount("/dev/ram16", "/entrance") == 0) + { + kstd::println("--> successfully mounted /dev/ram16 to /entrance"); + } + else + { + kapi::system::panic("demo failed"); + } + kstd::println(""); // 5) open a file from the new filesystem + kstd::println("attempting to open /entrance/information/info_1.txt"); auto fd_2 = kapi::filesystem::open("/entrance/information/info_1.txt"); - if (fd_2 == -1) + if (fd_2 != -1) + { + kstd::println("--> successfully opened /entrance/information/info_1.txt with file descriptor {}", fd_2); + } + else { - kstd::os::panic("demo failed"); + kapi::system::panic("demo failed"); } // 6) read from the new file kstd::vector buffer_2{10}; bytes_read = kapi::filesystem::read(fd_2, buffer_2.data(), buffer_2.size()); buffer_as_str = std::string_view{reinterpret_cast(buffer_2.data()), static_cast(bytes_read)}; - kstd::println("Read {} bytes from /entrance/information/info_1.txt: {}", bytes_read, buffer_as_str); + kstd::println("--> read {} bytes from /entrance/information/info_1.txt: {} ", bytes_read, buffer_as_str); // 7) open device as file - auto fd_3 = kapi::filesystem::open("/dev/ram48"); - if (fd_3 == -1) + kstd::println("attempting to open /dev/ram32 as a file"); + auto fd_3 = kapi::filesystem::open("/dev/ram32"); + if (fd_3 != -1) + { + kstd::println("--> successfully opened /dev/ram32 as a file with file descriptor {}", fd_3); + } + else { - kstd::os::panic("demo failed"); + kapi::system::panic("demo failed"); } // 8) read from the device file kstd::vector buffer_3{2}; bytes_read = kapi::filesystem::read(fd_3, buffer_3.data(), buffer_3.size()); - kstd::println("Read {} bytes from /dev/ram48: {::#04x}", bytes_read, buffer_3); + kstd::println("--> read {} bytes from /dev/ram32: {::#04x} ", bytes_read, buffer_3); // 9) write to the device file kstd::vector write_buffer{std::byte{0xAA}, std::byte{0xAA}}; auto bytes_written = kapi::filesystem::write(fd_3, write_buffer.data(), write_buffer.size()); - kstd::println("Written {} bytes to /dev/ram48: {::#04x}", bytes_written, write_buffer); + kstd::println("--> written {} bytes to /dev/ram32: {::#04x}", bytes_written, write_buffer); // 10) do memory dump to show that the write to the device file had an effect } -- cgit v1.2.3 From d916ecfc94aab583d60bba94de257a675accab7a Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Mon, 25 May 2026 13:04:22 +0200 Subject: add vfs tests --- kernel/src/filesystem/vfs.tests.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 8ae206a..fc1ea0d 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -416,6 +416,37 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS } } + GIVEN("two real image files where the second contains as filesystem formatted files") + { + REQUIRE(std::filesystem::exists(image_path_1)); + REQUIRE(std::filesystem::exists(image_path_3)); + REQUIRE_NOTHROW( + setup_modules_from_img_and_init_vfs({"test_img_module_3", "test_img_module_1"}, {image_path_3, image_path_1})); + + auto & vfs = kernel::filesystem::vfs::get(); + + THEN("cannot unmount a filesystem if files are mounted") + { + REQUIRE(vfs.do_mount("/dev/ram16", "/entrance") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/entrance/archiv/2024.img", "/enclosures") == + kernel::filesystem::vfs::operation_result::success); + + REQUIRE(vfs.unmount("/entrance") == kernel::filesystem::vfs::operation_result::unmount_failed); + REQUIRE(vfs.unmount("/enclosures") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/entrance") == kernel::filesystem::vfs::operation_result::success); + } + + THEN("can mount filesystem ontop of the path where this is inside") + { + REQUIRE(vfs.do_mount("/dev/ram16", "/entrance") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/entrance/archiv/2024.img", "/entrance") == + kernel::filesystem::vfs::operation_result::success); + + REQUIRE(vfs.unmount("/entrance") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/entrance") == kernel::filesystem::vfs::operation_result::success); + } + } + GIVEN("A real image files, containing symbolic links") { REQUIRE(std::filesystem::exists(image_path_1)); -- cgit v1.2.3 From 756854104db95f247ad9bed5eb59fb90a9a1cb69 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Mon, 25 May 2026 13:04:36 +0200 Subject: add mount table and mount tests --- kernel/src/filesystem/mount.tests.cpp | 3 ++- kernel/src/filesystem/mount_table.tests.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount.tests.cpp b/kernel/src/filesystem/mount.tests.cpp index 40b7cbb..c9ff82e 100644 --- a/kernel/src/filesystem/mount.tests.cpp +++ b/kernel/src/filesystem/mount.tests.cpp @@ -34,9 +34,10 @@ SCENARIO("Mount construction", "[filesystem][mount]") REQUIRE(mount.is_ready_to_unmount()); } - THEN("the mount has no parent mount") + THEN("the mount has no parent mount and no source mount") { REQUIRE(mount.parent_mount() == nullptr); + REQUIRE(mount.source_mount() == nullptr); } } diff --git a/kernel/src/filesystem/mount_table.tests.cpp b/kernel/src/filesystem/mount_table.tests.cpp index 8118e19..19b47b2 100644 --- a/kernel/src/filesystem/mount_table.tests.cpp +++ b/kernel/src/filesystem/mount_table.tests.cpp @@ -155,3 +155,30 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] } } } + +SCENARIO("Mount reference counting", "[filesystem][mount_table]") +{ + kernel::filesystem::mount_table table; + + GIVEN("a filesystem and a root dentry") + { + auto fs = kstd::make_shared(); + auto root_inode = kstd::make_shared(); + auto root_dentry = kstd::make_shared(nullptr, root_inode, "/"); + + auto source_mount = kstd::make_shared(root_dentry, root_dentry, fs, nullptr, nullptr); + auto mount = kstd::make_shared(root_dentry, root_dentry, fs, nullptr, source_mount); + + THEN("reference count of source mount is incremented when a mount is added to the mount table and decremented when " + "the mount is removed") + { + REQUIRE(source_mount->ref_count() == 0); + + table.add_mount(mount); + REQUIRE(source_mount->ref_count() == 1); + + REQUIRE(table.remove_mount("/") == kernel::filesystem::mount_table::operation_result::removed); + REQUIRE(source_mount->ref_count() == 0); + } + } +} -- cgit v1.2.3 From 685990ae8c4fad6847e8f90cccb52bb34280298c Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Mon, 25 May 2026 13:14:07 +0200 Subject: Apply 1 suggestion(s) to 1 file(s) Co-authored-by: Marcel Braun --- kernel/src/filesystem/vfs.tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index fc1ea0d..962e067 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -436,7 +436,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(vfs.unmount("/entrance") == kernel::filesystem::vfs::operation_result::success); } - THEN("can mount filesystem ontop of the path where this is inside") + THEN("can mount filesystem onto the directory that contains it") { REQUIRE(vfs.do_mount("/dev/ram16", "/entrance") == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.do_mount("/entrance/archiv/2024.img", "/entrance") == -- cgit v1.2.3 From 649bf64b4d4ec0742e56539348761f5957d64922 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Mon, 25 May 2026 14:03:56 +0200 Subject: fix linter warnings --- kernel/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 25b5c00..a84ca64 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -100,7 +99,8 @@ auto run_demo() -> void kstd::println("--> read {} bytes from /dev/ram32: {::#04x} ", bytes_read, buffer_3); // 9) write to the device file - kstd::vector write_buffer{std::byte{0xAA}, std::byte{0xAA}}; + auto const buffer_fill_byte = std::byte{0xAA}; + kstd::vector write_buffer{buffer_fill_byte, buffer_fill_byte}; auto bytes_written = kapi::filesystem::write(fd_3, write_buffer.data(), write_buffer.size()); kstd::println("--> written {} bytes to /dev/ram32: {::#04x}", bytes_written, write_buffer); -- cgit v1.2.3 From adb1b5f2d6858097227fa610e86d1152b79d0bfa Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Mon, 25 May 2026 14:05:38 +0200 Subject: renaming --- kernel/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index a84ca64..6985e94 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -99,8 +99,8 @@ auto run_demo() -> void kstd::println("--> read {} bytes from /dev/ram32: {::#04x} ", bytes_read, buffer_3); // 9) write to the device file - auto const buffer_fill_byte = std::byte{0xAA}; - kstd::vector write_buffer{buffer_fill_byte, buffer_fill_byte}; + auto const default_buffer_value = std::byte{0xAA}; + kstd::vector write_buffer{default_buffer_value, default_buffer_value}; auto bytes_written = kapi::filesystem::write(fd_3, write_buffer.data(), write_buffer.size()); kstd::println("--> written {} bytes to /dev/ram32: {::#04x}", bytes_written, write_buffer); -- cgit v1.2.3 From e4dfaac871b9c0e38ed3e500f86ff1f74d8a3a52 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sun, 31 May 2026 15:55:47 +0200 Subject: refactor and simplify mapping logic --- kernel/src/filesystem/ext2/filesystem.cpp | 101 ++++++++++++------------------ 1 file changed, 39 insertions(+), 62 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index a30149e..720f0a8 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -109,6 +110,15 @@ namespace kernel::filesystem::ext2 return kstd::make_shared(this, new_inode_data); } + auto filesystem::indirect_levels() const -> std::array + { + return { + {{constants::singly_indirect_block_index, block_numbers_per_singly_indirect_block()}, + {constants::doubly_indirect_block_index, block_numbers_per_doubly_indirect_block()}, + {constants::triply_indirect_block_index, block_numbers_per_triply_indirect_block()}} + }; + } + auto filesystem::map_inode_block_index_to_global_block_number(size_t inode_block_index, inode_data data) const -> kstd::ssize_t { @@ -116,78 +126,45 @@ namespace kernel::filesystem::ext2 { return data.block.at(inode_block_index); } - inode_block_index -= constants::direct_block_count; - - if (inode_block_index < block_numbers_per_singly_indirect_block()) - { - auto const singly_indirect_block_number = data.block.at(constants::singly_indirect_block_index); - return read_singly_indirect_block_number(singly_indirect_block_number, inode_block_index); - } - inode_block_index -= block_numbers_per_singly_indirect_block(); - - if (inode_block_index < block_numbers_per_doubly_indirect_block()) - { - auto const doubly_indirect_block_number = data.block.at(constants::doubly_indirect_block_index); - return read_doubly_indirect_block_number(doubly_indirect_block_number, inode_block_index); - } - inode_block_index -= block_numbers_per_doubly_indirect_block(); - if (inode_block_index < block_numbers_per_triply_indirect_block()) - { - auto const triply_indirect_block_number = data.block.at(constants::triply_indirect_block_index); - return read_triply_indirect_block_number(triply_indirect_block_number, inode_block_index); - } - - return -1; - } + inode_block_index -= constants::direct_block_count; + auto const levels = indirect_levels(); - auto filesystem::read_singly_indirect_block_number(uint32_t singly_indirect_block_number, - size_t block_index_in_singly_indirect_block) const -> size_t - { - if (singly_indirect_block_number == 0) + for (auto const & level : levels) { - return 0; - } - - return read_block_number_at_index(singly_indirect_block_number, block_index_in_singly_indirect_block); - } + if (inode_block_index >= level.capacity) + { + inode_block_index -= level.capacity; + continue; + } - auto filesystem::read_doubly_indirect_block_number(uint32_t doubly_indirect_block_number, - size_t block_index_in_doubly_indirect_block) const -> size_t - { - if (doubly_indirect_block_number == 0) - { - return 0; - } + auto block_number = data.block[level.slot_index]; + if (block_number == 0) + { + return 0; + } - auto const singly_indirect_block_index_in_doubly_indirect_block = - block_index_in_doubly_indirect_block / block_numbers_per_singly_indirect_block(); - auto const block_index_in_singly_indirect_block = - block_index_in_doubly_indirect_block % block_numbers_per_singly_indirect_block(); + for (auto stride = level.capacity / block_numbers_per_block();; stride /= block_numbers_per_block()) + { + auto const idx = inode_block_index / stride; + inode_block_index %= stride; - auto const singly_indirect_block_number = - read_block_number_at_index(doubly_indirect_block_number, singly_indirect_block_index_in_doubly_indirect_block); + block_number = read_block_number_at_index(block_number, idx); + if (block_number == 0) + { + return 0; + } - return read_singly_indirect_block_number(singly_indirect_block_number, block_index_in_singly_indirect_block); - } + if (stride == 1) + { + break; + } + } - auto filesystem::read_triply_indirect_block_number(uint32_t triply_indirect_block_number, - size_t block_index_in_triply_indirect_block) const -> size_t - { - if (triply_indirect_block_number == 0) - { - return 0; + return block_number; } - auto const doubly_indirect_block_index_in_triply_indirect_block = - block_index_in_triply_indirect_block / block_numbers_per_doubly_indirect_block(); - auto const block_index_in_doubly_indirect_block = - block_index_in_triply_indirect_block % block_numbers_per_doubly_indirect_block(); - - auto const doubly_indirect_block_number = - read_block_number_at_index(triply_indirect_block_number, doubly_indirect_block_index_in_triply_indirect_block); - - return read_doubly_indirect_block_number(doubly_indirect_block_number, block_index_in_doubly_indirect_block); + return -1; } auto filesystem::read_block_number_at_index(uint32_t block_number, size_t index) const -> uint32_t -- cgit v1.2.3 From f26569c6a4e5f0ed61b7efa81ebdddd532d542c5 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sun, 31 May 2026 16:06:38 +0200 Subject: small refactoring --- kernel/src/filesystem/ext2/filesystem.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 720f0a8..12aeaaa 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -128,9 +128,8 @@ namespace kernel::filesystem::ext2 } inode_block_index -= constants::direct_block_count; - auto const levels = indirect_levels(); - for (auto const & level : levels) + for (auto const & level : indirect_levels()) { if (inode_block_index >= level.capacity) { -- cgit v1.2.3 From dc9bd3b44cbbd0235a176f05c27eb15ff31f5e09 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 22 May 2026 20:18:05 +0200 Subject: kernel/vfs: prepare fs type registration support --- kernel/src/filesystem/devfs/filesystem.cpp | 22 ++++++++++++++++++++++ kernel/src/filesystem/ext2/filesystem.cpp | 23 +++++++++++++++++++++++ kernel/src/filesystem/vfs.cpp | 15 +++++++++++++++ 3 files changed, 60 insertions(+) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/devfs/filesystem.cpp b/kernel/src/filesystem/devfs/filesystem.cpp index f0d8bf7..c61a3d0 100644 --- a/kernel/src/filesystem/devfs/filesystem.cpp +++ b/kernel/src/filesystem/devfs/filesystem.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -15,6 +16,27 @@ namespace kernel::filesystem::devfs { + struct type final : kernel::filesystem::type + { + [[nodiscard]] auto name() const noexcept -> std::string_view override + { + return "devfs"; + } + + [[nodiscard]] auto requires_device() const noexcept -> bool override + { + return false; + } + + [[nodiscard]] auto make_instance() const -> kstd::shared_ptr override + { + return kstd::make_shared(); + } + } const constinit type_instance{}; + + [[gnu::section(".vfs_type_descriptors"), gnu::used]] + auto const * const type_descriptor_pointer = static_cast(&type_instance); + auto filesystem::mount(kstd::shared_ptr const &) -> operation_result { m_root_inode = kstd::make_shared(); diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 12aeaaa..6959653 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -18,6 +19,28 @@ namespace kernel::filesystem::ext2 { + + struct type final : kernel::filesystem::type + { + [[nodiscard]] auto name() const noexcept -> std::string_view override + { + return "ext2"; + } + + [[nodiscard]] auto requires_device() const noexcept -> bool override + { + return true; + } + + [[nodiscard]] auto make_instance() const -> kstd::shared_ptr override + { + return kstd::make_shared(); + } + } const constinit type_instance{}; + + [[gnu::section(".vfs_type_descriptors"), gnu::used]] + auto const * const type_descriptor_pointer = static_cast(&type_instance); + auto filesystem::mount(kstd::shared_ptr const & backing_inode) -> operation_result { kernel::filesystem::filesystem::mount(backing_inode); diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index ae85291..d22c74b 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -8,10 +8,12 @@ #include #include #include +#include #include #include +#include #include #include @@ -19,9 +21,16 @@ #include #include #include +#include #include #include +extern "C" +{ + extern kernel::filesystem::type const * const __vfs_type_descriptors_begin; + extern kernel::filesystem::type const * const __vfs_type_descriptors_end; +} + namespace { constinit auto static active_vfs = std::optional{}; @@ -42,6 +51,12 @@ namespace kernel::filesystem auto vfs::init_internal() -> void { + auto type_descriptors = std::span{&__vfs_type_descriptors_begin, &__vfs_type_descriptors_end} | + std::views::filter([](auto p) { return p != nullptr; }); + std::ranges::for_each(type_descriptors, [](auto descriptor) { + kstd::println("[OS] registering filesystem '{}'", descriptor->name()); + }); + // mount rootfs at / auto root_fs = kstd::make_shared(); root_fs->mount(nullptr); -- cgit v1.2.3 From 86170be29f6cb72b29865db0975de09bec89f854 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 1 Jun 2026 10:40:39 +0200 Subject: kernel/vfs: rename type descriptor section --- kernel/src/filesystem/devfs/filesystem.cpp | 2 +- kernel/src/filesystem/ext2/filesystem.cpp | 2 +- kernel/src/filesystem/vfs.cpp | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/devfs/filesystem.cpp b/kernel/src/filesystem/devfs/filesystem.cpp index c61a3d0..1aaa0d1 100644 --- a/kernel/src/filesystem/devfs/filesystem.cpp +++ b/kernel/src/filesystem/devfs/filesystem.cpp @@ -34,7 +34,7 @@ namespace kernel::filesystem::devfs } } const constinit type_instance{}; - [[gnu::section(".vfs_type_descriptors"), gnu::used]] + [[gnu::section("vfs_type_descriptors"), gnu::used]] auto const * const type_descriptor_pointer = static_cast(&type_instance); auto filesystem::mount(kstd::shared_ptr const &) -> operation_result diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 6959653..7b5d2d7 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -38,7 +38,7 @@ namespace kernel::filesystem::ext2 } } const constinit type_instance{}; - [[gnu::section(".vfs_type_descriptors"), gnu::used]] + [[gnu::section("vfs_type_descriptors"), gnu::used]] auto const * const type_descriptor_pointer = static_cast(&type_instance); auto filesystem::mount(kstd::shared_ptr const & backing_inode) -> operation_result diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index d22c74b..c297210 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -27,8 +27,8 @@ extern "C" { - extern kernel::filesystem::type const * const __vfs_type_descriptors_begin; - extern kernel::filesystem::type const * const __vfs_type_descriptors_end; + extern kernel::filesystem::type const * const __start_vfs_type_descriptors; + extern kernel::filesystem::type const * const __stop_vfs_type_descriptors; } namespace @@ -51,7 +51,7 @@ namespace kernel::filesystem auto vfs::init_internal() -> void { - auto type_descriptors = std::span{&__vfs_type_descriptors_begin, &__vfs_type_descriptors_end} | + auto type_descriptors = std::span{&__start_vfs_type_descriptors, &__stop_vfs_type_descriptors} | std::views::filter([](auto p) { return p != nullptr; }); std::ranges::for_each(type_descriptors, [](auto descriptor) { kstd::println("[OS] registering filesystem '{}'", descriptor->name()); -- cgit v1.2.3 From 568e9586c036fc319fc36b12495e5deacb167be9 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 1 Jun 2026 20:10:57 +0200 Subject: kernel/vfs: simplify initialization --- kernel/src/filesystem/vfs.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index c297210..91afc13 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -45,12 +45,12 @@ namespace kernel::filesystem kapi::system::panic("[FILESYSTEM] vfs has already been initialized."); } - active_vfs.emplace(vfs{}); - active_vfs->init_internal(); + active_vfs.emplace(); } - auto vfs::init_internal() -> void + vfs::vfs() { + // Register all compiled-in filesystems auto type_descriptors = std::span{&__start_vfs_type_descriptors, &__stop_vfs_type_descriptors} | std::views::filter([](auto p) { return p != nullptr; }); std::ranges::for_each(type_descriptors, [](auto descriptor) { -- cgit v1.2.3 From 6c8b068c15e28e91117f84cb8d5789f5fe6fcbd0 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 1 Jun 2026 20:31:57 +0200 Subject: kstd/string: simplify comparisons --- kernel/src/filesystem/dentry.cpp | 2 +- kernel/src/filesystem/vfs.cpp | 8 ++++---- kernel/src/filesystem/vfs.tests.cpp | 32 ++++++++++++++------------------ 3 files changed, 19 insertions(+), 23 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index 14de875..3d8e01a 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -41,7 +41,7 @@ namespace kernel::filesystem auto dentry::name() const -> std::string_view { - return m_name.view(); + return m_name; } auto dentry::absolute_path() const -> kstd::string diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 91afc13..b0d63a2 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -241,22 +241,22 @@ namespace kernel::filesystem continue; } - auto next_dentry = current_dentry->find_child(part.view()); + auto next_dentry = current_dentry->find_child(part); if (!next_dentry) { auto current_fs = current_mount->get_filesystem(); - auto found_inode = current_fs->lookup(current_dentry->get_inode(), part.view()); + auto found_inode = current_fs->lookup(current_dentry->get_inode(), part); if (!found_inode) { return {nullptr, nullptr}; } - next_dentry = kstd::make_shared(current_dentry, found_inode, part.view()); + next_dentry = kstd::make_shared(current_dentry, found_inode, part); current_dentry->add_child(next_dentry); } else if (next_dentry->has_flag(dentry::dentry_flags::is_mount_point)) { - current_mount = m_mount_table.find_mount(next_dentry->absolute_path().view()); + current_mount = m_mount_table.find_mount(next_dentry->absolute_path()); if (!current_mount) { kapi::system::panic("[FILESYSTEM] mount for dentry with mounted flag not found."); diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 962e067..f1d0df0 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -106,8 +106,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); REQUIRE(mounted_monkey_1 != nullptr); - REQUIRE(vfs.close(mounted_monkey_1->absolute_path().view()) == - kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(mounted_monkey_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); auto unmounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); @@ -129,9 +128,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(mounted_monkey_1 != nullptr); REQUIRE(mounted_fish1 != nullptr); - REQUIRE(vfs.close(mounted_monkey_1->absolute_path().view()) == - kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.close(mounted_fish1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(mounted_monkey_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(mounted_fish1->absolute_path()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); REQUIRE(vfs.unmount("/information/monkey_house/infrastructure") == @@ -148,8 +146,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); - REQUIRE(vfs.close(mounted_monkey_1->absolute_path().view()) == - kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(mounted_monkey_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); } @@ -165,8 +162,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto info_1 = vfs.open("/information/info_1.txt"); REQUIRE(info_1 != nullptr); - REQUIRE(vfs.close(info_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); - REQUIRE_THROWS_AS(vfs.close(info_1->absolute_path().view()), std::runtime_error); + REQUIRE(vfs.close(info_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE_THROWS_AS(vfs.close(info_1->absolute_path()), std::runtime_error); } THEN("images can be stacked mounted and correct file system is unmounted again") @@ -177,7 +174,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto mounted_tickets = vfs.open("/information/entrance/tickets.txt"); REQUIRE(mounted_tickets != nullptr); - REQUIRE(vfs.close(mounted_tickets->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(mounted_tickets->absolute_path()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); mounted_tickets = vfs.open("/information/entrance/tickets.txt"); @@ -200,7 +197,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto water = vfs.open("/monkey_house/infrastructure/water.txt"); REQUIRE(water != nullptr); - REQUIRE(vfs.close(water->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(water->absolute_path()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success); @@ -221,7 +218,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto water = vfs.open("/monkey_house/infrastructure/water.txt"); REQUIRE(water != nullptr); - REQUIRE(vfs.close(water->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(water->absolute_path()) == kernel::filesystem::vfs::operation_result::success); auto dev_ram_16 = vfs.open("/dev/ram16"); REQUIRE(dev_ram_16 == nullptr); @@ -239,7 +236,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto info_1 = vfs.open("/information/info_1.txt"); REQUIRE(info_1 != nullptr); - REQUIRE(vfs.close(info_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(info_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/dev") == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success); @@ -362,7 +359,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS std::string_view buffer_as_str{reinterpret_cast(buffer.data()), bytes_read}; REQUIRE(buffer_as_str == "sheep_1"); - REQUIRE(vfs.close(dentry->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(dentry->absolute_path()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); auto unmounted_sheep_1 = vfs.open("/information/sheep_1.txt"); @@ -395,8 +392,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS buffer_as_str = std::string_view{reinterpret_cast(goat_buffer.data()), bytes_read}; REQUIRE(buffer_as_str == "goat_1"); - REQUIRE(vfs.close(sheep_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.close(goat_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(sheep_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(goat_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); @@ -407,8 +404,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto still_mounted_sheep_1 = vfs.open("/information/sheep_1.txt"); REQUIRE(still_mounted_sheep_1 != nullptr); - REQUIRE(vfs.close(still_mounted_sheep_1->absolute_path().view()) == - kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(still_mounted_sheep_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); auto unmounted_sheep_1 = vfs.open("/information/sheep_1.txt"); -- cgit v1.2.3 From ad2319188269331f4873adbeb44380d63e8e83c5 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 1 Jun 2026 21:15:25 +0200 Subject: kernel/vfs: manage filesystem registrations --- kernel/src/filesystem/vfs.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index b0d63a2..8dcae2c 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -53,8 +53,9 @@ namespace kernel::filesystem // Register all compiled-in filesystems auto type_descriptors = std::span{&__start_vfs_type_descriptors, &__stop_vfs_type_descriptors} | std::views::filter([](auto p) { return p != nullptr; }); - std::ranges::for_each(type_descriptors, [](auto descriptor) { - kstd::println("[OS] registering filesystem '{}'", descriptor->name()); + std::ranges::for_each(type_descriptors, [this](auto descriptor) { + kstd::println("[FILESYSTEM] registering '{}'", descriptor->name()); + m_filesystems.emplace(descriptor->name(), descriptor); }); // mount rootfs at / -- cgit v1.2.3 From d2d4fa3330a09f421b8658c077166cc493532b9e Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 2 Jun 2026 10:54:17 +0200 Subject: kernel/vfs: extract fs type registry --- kernel/src/filesystem/devfs/filesystem.cpp | 6 +-- kernel/src/filesystem/ext2/filesystem.cpp | 6 +-- kernel/src/filesystem/type_registry.cpp | 67 ++++++++++++++++++++++++++++++ kernel/src/filesystem/vfs.cpp | 17 -------- kernel/src/main.cpp | 2 + 5 files changed, 75 insertions(+), 23 deletions(-) create mode 100644 kernel/src/filesystem/type_registry.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/devfs/filesystem.cpp b/kernel/src/filesystem/devfs/filesystem.cpp index 1aaa0d1..ce887ff 100644 --- a/kernel/src/filesystem/devfs/filesystem.cpp +++ b/kernel/src/filesystem/devfs/filesystem.cpp @@ -32,10 +32,10 @@ namespace kernel::filesystem::devfs { return kstd::make_shared(); } - } const constinit type_instance{}; + }; - [[gnu::section("vfs_type_descriptors"), gnu::used]] - auto const * const type_descriptor_pointer = static_cast(&type_instance); + [[gnu::used]] + constexpr auto registration = type_registration{}; auto filesystem::mount(kstd::shared_ptr const &) -> operation_result { diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp index 7b5d2d7..3180a19 100644 --- a/kernel/src/filesystem/ext2/filesystem.cpp +++ b/kernel/src/filesystem/ext2/filesystem.cpp @@ -36,10 +36,10 @@ namespace kernel::filesystem::ext2 { return kstd::make_shared(); } - } const constinit type_instance{}; + }; - [[gnu::section("vfs_type_descriptors"), gnu::used]] - auto const * const type_descriptor_pointer = static_cast(&type_instance); + [[gnu::used]] + constexpr auto registration = type_registration{}; auto filesystem::mount(kstd::shared_ptr const & backing_inode) -> operation_result { diff --git a/kernel/src/filesystem/type_registry.cpp b/kernel/src/filesystem/type_registry.cpp new file mode 100644 index 0000000..033b879 --- /dev/null +++ b/kernel/src/filesystem/type_registry.cpp @@ -0,0 +1,67 @@ +#include + +#include + +#include +#include + +#include +#include +#include +#include + +namespace kernel::filesystem +{ + + extern "C" + { + extern type_registry::pointer const __start_fs_types; + extern type_registry::pointer const __stop_fs_types; + } + + namespace + { + auto constinit instance = std::optional{}; + } + + auto type_registry::init() -> void + { + if (instance) + { + kapi::system::panic("[FILESYSTEM] tried to initialize type registry more than once!"); + } + + instance.emplace(); + + auto type_descriptors = std::span{&__start_fs_types, &__stop_fs_types} | // + std::views::filter([](auto p) { return p != nullptr; }); + + std::ranges::for_each(type_descriptors, [](auto descriptor) { + kstd::println("[FILESYSTEM] registering '{}'", descriptor->name()); + instance->add(descriptor); + }); + } + + auto type_registry::get() -> type_registry & + { + if (!instance) + { + kapi::system::panic("[FILESYSTEM] type registry has not been initialized!"); + } + + return *instance; + } + + auto type_registry::add(pointer descriptor) -> bool + { + auto result = m_descriptors.emplace(descriptor->name(), descriptor); + return result.second; + } + + [[nodiscard]] auto type_registry::all() const noexcept -> std::span + { + // TODO: implement value accessor for flat_map + return {}; + } + +} // namespace kernel::filesystem diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 8dcae2c..8d1fd23 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -8,29 +8,20 @@ #include #include #include -#include #include #include #include -#include #include #include #include #include #include -#include #include #include -extern "C" -{ - extern kernel::filesystem::type const * const __start_vfs_type_descriptors; - extern kernel::filesystem::type const * const __stop_vfs_type_descriptors; -} - namespace { constinit auto static active_vfs = std::optional{}; @@ -50,14 +41,6 @@ namespace kernel::filesystem vfs::vfs() { - // Register all compiled-in filesystems - auto type_descriptors = std::span{&__start_vfs_type_descriptors, &__stop_vfs_type_descriptors} | - std::views::filter([](auto p) { return p != nullptr; }); - std::ranges::for_each(type_descriptors, [this](auto descriptor) { - kstd::println("[FILESYSTEM] registering '{}'", descriptor->name()); - m_filesystems.emplace(descriptor->name(), descriptor); - }); - // mount rootfs at / auto root_fs = kstd::make_shared(); root_fs->mount(nullptr); diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 6985e94..5063d18 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,3 +1,4 @@ +#include "kernel/filesystem/type_registry.hpp" #include #include #include @@ -138,6 +139,7 @@ auto main() -> int kernel::filesystem::open_file_table::init(); kstd::println("[OS] Global open file table initialized."); + kernel::filesystem::type_registry::init(); kernel::filesystem::vfs::init(); kstd::println("[OS] Virtual filesystem initialized."); -- cgit v1.2.3 From b34db5a8acd0639fde9a81b38e96776f7c2ef61e Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 2 Jun 2026 11:38:48 +0200 Subject: kernel/vfs: add type descriptor for rootfs --- kernel/src/filesystem/rootfs/filesystem.cpp | 25 ++++++++++++++++++++++++- kernel/src/main.cpp | 2 ++ 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/rootfs/filesystem.cpp b/kernel/src/filesystem/rootfs/filesystem.cpp index 0ba2936..7fe5c1e 100644 --- a/kernel/src/filesystem/rootfs/filesystem.cpp +++ b/kernel/src/filesystem/rootfs/filesystem.cpp @@ -1,8 +1,9 @@ #include -#include "kernel/filesystem/filesystem.hpp" +#include #include #include +#include #include @@ -10,6 +11,28 @@ namespace kernel::filesystem::rootfs { + + struct type final : kernel::filesystem::type + { + [[nodiscard]] auto name() const noexcept -> std::string_view override + { + return "rootfs"; + } + + [[nodiscard]] auto requires_device() const noexcept -> bool override + { + return true; + } + + [[nodiscard]] auto make_instance() const -> kstd::shared_ptr override + { + return kstd::make_shared(); + } + }; + + [[gnu::used]] + constexpr auto registration = type_registration{}; + auto filesystem::mount(kstd::shared_ptr const &) -> operation_result { m_root_inode = kstd::make_shared(); diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 5063d18..8dc1349 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -140,6 +140,8 @@ auto main() -> int kstd::println("[OS] Global open file table initialized."); kernel::filesystem::type_registry::init(); + kstd::println("[OS] Builtin filesystems registered."); + kernel::filesystem::vfs::init(); kstd::println("[OS] Virtual filesystem initialized."); -- cgit v1.2.3 From 772861fc5fae1c126fcc63a8809b0a9c729bd152 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 2 Jun 2026 13:43:49 +0200 Subject: kernel/vfs: add type registry tests --- kernel/src/filesystem/type_registry.cpp | 11 ++-- kernel/src/filesystem/type_registry.tests.cpp | 77 +++++++++++++++++++++++++++ kernel/src/filesystem/vfs.cpp | 1 - 3 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 kernel/src/filesystem/type_registry.tests.cpp (limited to 'kernel/src') diff --git a/kernel/src/filesystem/type_registry.cpp b/kernel/src/filesystem/type_registry.cpp index 033b879..d917c81 100644 --- a/kernel/src/filesystem/type_registry.cpp +++ b/kernel/src/filesystem/type_registry.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -58,10 +59,14 @@ namespace kernel::filesystem return result.second; } - [[nodiscard]] auto type_registry::all() const noexcept -> std::span + auto type_registry::all() const noexcept -> std::span { - // TODO: implement value accessor for flat_map - return {}; + return {m_descriptors.values().begin(), m_descriptors.values().end()}; + } + + auto type_registry::size() const noexcept -> std::size_t + { + return m_descriptors.size(); } } // namespace kernel::filesystem diff --git a/kernel/src/filesystem/type_registry.tests.cpp b/kernel/src/filesystem/type_registry.tests.cpp new file mode 100644 index 0000000..8382579 --- /dev/null +++ b/kernel/src/filesystem/type_registry.tests.cpp @@ -0,0 +1,77 @@ +#include + +#include +#include + +#include + +#include + +#include +#include + +struct test_type final : kernel::filesystem::type +{ + [[nodiscard]] auto name() const noexcept -> std::string_view override + { + return "bht_testfs"; + } + + [[nodiscard]] auto requires_device() const noexcept -> bool override + { + return false; + } + + [[nodiscard]] auto make_instance() const -> kstd::shared_ptr override + { + return nullptr; + } +}; + +SCENARIO("Filesystem type registry initialization and construction", "[filesystem]") +{ + GIVEN("A default constructed type_registry") + { + auto instance = kernel::filesystem::type_registry{}; + + WHEN("getting the span of filesystem descriptors") + { + auto descriptors = instance.all(); + + THEN("the span is empty") + { + REQUIRE(descriptors.empty()); + } + } + } +} + +SCENARIO("Filesystem type registry modifiers", "[filesystem]") +{ + GIVEN("A default constructed type_registry") + { + auto instance = kernel::filesystem::type_registry{}; + + WHEN("adding a type descriptor") + { + auto descriptor = test_type{}; + + instance.add(kstd::make_observer(&descriptor)); + + THEN("the size of the registry is one") + { + REQUIRE(instance.size() == 1); + } + + THEN("the span is not empty") + { + REQUIRE_FALSE(instance.all().empty()); + } + + THEN("the span's size is equal to the registry size") + { + REQUIRE(std::size(instance.all()) == std::size(instance)); + } + } + } +} diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 8d1fd23..e5dff8c 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include -- cgit v1.2.3 From 66ea58d7c5b41475e0be61172966613fbd14d43b Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sun, 7 Jun 2026 18:54:49 +0200 Subject: small refactoring --- kernel/src/filesystem/mount_table.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/src') diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index af8434b..e4baac7 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -18,7 +18,7 @@ namespace kernel::filesystem [&parent_mount](auto const & mount) { return mount->parent_mount() == parent_mount; }); } - void mount_table::add_mount(kstd::shared_ptr const & mount) + auto mount_table::add_mount(kstd::shared_ptr const & mount) -> void { m_mounts.push_back(mount); -- cgit v1.2.3