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/include/kernel/filesystem/filesystem.hpp | 3 ++- kernel/src/filesystem/filesystem.cpp | 29 +++++++++++++++++++++---- kernel/src/filesystem/vfs.cpp | 5 +---- kernel/src/main.cpp | 4 ++-- 4 files changed, 30 insertions(+), 11 deletions(-) (limited to 'kernel') diff --git a/kernel/include/kernel/filesystem/filesystem.hpp b/kernel/include/kernel/filesystem/filesystem.hpp index 1d86178..05f96dc 100644 --- a/kernel/include/kernel/filesystem/filesystem.hpp +++ b/kernel/include/kernel/filesystem/filesystem.hpp @@ -2,6 +2,7 @@ #define TEACH_OS_KERNEL_FILESYSTEM_FILESYSTEM_HPP #include "kapi/devices/device.hpp" + #include "kernel/filesystem/inode.hpp" #include @@ -15,7 +16,7 @@ namespace kernel::filesystem { virtual ~filesystem() = default; - virtual auto mount(kstd::shared_ptr const & device) -> int; + auto static mount(kstd::shared_ptr const & device) -> kstd::shared_ptr; virtual auto lookup(kstd::shared_ptr const & parent, std::string_view name) -> kstd::shared_ptr = 0; [[nodiscard]] auto root_inode() const -> kstd::shared_ptr const &; 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 --- .../include/kernel/filesystem/ext2/filesystem.hpp | 11 +++- kernel/src/filesystem/ext2/filesystem.cpp | 66 ++++++++++++---------- 2 files changed, 47 insertions(+), 30 deletions(-) (limited to 'kernel') diff --git a/kernel/include/kernel/filesystem/ext2/filesystem.hpp b/kernel/include/kernel/filesystem/ext2/filesystem.hpp index 078da31..176d83c 100644 --- a/kernel/include/kernel/filesystem/ext2/filesystem.hpp +++ b/kernel/include/kernel/filesystem/ext2/filesystem.hpp @@ -2,20 +2,29 @@ #define TEACH_OS_KERNEL_FILESYSTEM_EXT2_FILESYSTEM_HPP #include "kapi/devices/device.hpp" + +#include "kernel/filesystem/ext2/superblock.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" #include +#include #include namespace kernel::filesystem::ext2 { struct filesystem : kernel::filesystem::filesystem { - auto mount(kstd::shared_ptr const & device) -> int override; + auto mount(kstd::shared_ptr const & device) -> int; auto lookup(kstd::shared_ptr const & parent, std::string_view name) -> kstd::shared_ptr override; + + private: + auto get_block_size() -> size_t; + auto get_inode_size() -> size_t; + + superblock m_superblock; }; } // namespace kernel::filesystem::ext2 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 --- .../include/kernel/filesystem/devfs/filesystem.hpp | 1 + .../include/kernel/filesystem/ext2/filesystem.hpp | 2 +- kernel/include/kernel/filesystem/filesystem.hpp | 4 +++- .../kernel/filesystem/rootfs/filesystem.hpp | 1 + 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 ++-- 9 files changed, 32 insertions(+), 19 deletions(-) (limited to 'kernel') diff --git a/kernel/include/kernel/filesystem/devfs/filesystem.hpp b/kernel/include/kernel/filesystem/devfs/filesystem.hpp index 29ae388..3edeabb 100644 --- a/kernel/include/kernel/filesystem/devfs/filesystem.hpp +++ b/kernel/include/kernel/filesystem/devfs/filesystem.hpp @@ -2,6 +2,7 @@ #define TEACH_OS_KERNEL_FILESYSTEM_DEVFS_FILESYSTEM_HPP #include "kapi/devices/device.hpp" + #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" diff --git a/kernel/include/kernel/filesystem/ext2/filesystem.hpp b/kernel/include/kernel/filesystem/ext2/filesystem.hpp index 176d83c..f6cd17f 100644 --- a/kernel/include/kernel/filesystem/ext2/filesystem.hpp +++ b/kernel/include/kernel/filesystem/ext2/filesystem.hpp @@ -16,7 +16,7 @@ namespace kernel::filesystem::ext2 { struct filesystem : kernel::filesystem::filesystem { - auto mount(kstd::shared_ptr const & device) -> int; + auto mount(kstd::shared_ptr const & device) -> int override; auto lookup(kstd::shared_ptr const & parent, std::string_view name) -> kstd::shared_ptr override; diff --git a/kernel/include/kernel/filesystem/filesystem.hpp b/kernel/include/kernel/filesystem/filesystem.hpp index 05f96dc..1c45377 100644 --- a/kernel/include/kernel/filesystem/filesystem.hpp +++ b/kernel/include/kernel/filesystem/filesystem.hpp @@ -16,7 +16,9 @@ namespace kernel::filesystem { virtual ~filesystem() = default; - auto static mount(kstd::shared_ptr const & device) -> kstd::shared_ptr; + auto static probe_and_mount(kstd::shared_ptr const & device) -> kstd::shared_ptr; + + virtual auto mount(kstd::shared_ptr const & device) -> int; virtual auto lookup(kstd::shared_ptr const & parent, std::string_view name) -> kstd::shared_ptr = 0; [[nodiscard]] auto root_inode() const -> kstd::shared_ptr const &; diff --git a/kernel/include/kernel/filesystem/rootfs/filesystem.hpp b/kernel/include/kernel/filesystem/rootfs/filesystem.hpp index 5632d86..7931d87 100644 --- a/kernel/include/kernel/filesystem/rootfs/filesystem.hpp +++ b/kernel/include/kernel/filesystem/rootfs/filesystem.hpp @@ -2,6 +2,7 @@ #define TEACH_OS_KERNEL_FILESYSTEM_ROOTFS_FILESYSTEM_HPP #include "kapi/devices/device.hpp" + #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" 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/include/kernel/filesystem/ext2/filesystem.hpp | 3 +++ kernel/src/filesystem/ext2/filesystem.cpp | 13 +++++++++++++ 2 files changed, 16 insertions(+) (limited to 'kernel') diff --git a/kernel/include/kernel/filesystem/ext2/filesystem.hpp b/kernel/include/kernel/filesystem/ext2/filesystem.hpp index f6cd17f..59b9cba 100644 --- a/kernel/include/kernel/filesystem/ext2/filesystem.hpp +++ b/kernel/include/kernel/filesystem/ext2/filesystem.hpp @@ -3,11 +3,13 @@ #include "kapi/devices/device.hpp" +#include "kernel/filesystem/ext2/block_group_descriptor.hpp" #include "kernel/filesystem/ext2/superblock.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" #include +#include #include #include @@ -25,6 +27,7 @@ namespace kernel::filesystem::ext2 auto get_inode_size() -> size_t; superblock m_superblock; + kstd::vector m_block_group_descriptors; }; } // namespace kernel::filesystem::ext2 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 91db623189133cb14693ae60ee54ac293cec3b54 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Thu, 2 Apr 2026 11:33:14 +0200 Subject: remove todos --- kernel/include/kernel/filesystem/ext2/superblock.hpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'kernel') diff --git a/kernel/include/kernel/filesystem/ext2/superblock.hpp b/kernel/include/kernel/filesystem/ext2/superblock.hpp index 8600b4c..e7e15f2 100644 --- a/kernel/include/kernel/filesystem/ext2/superblock.hpp +++ b/kernel/include/kernel/filesystem/ext2/superblock.hpp @@ -41,11 +41,8 @@ namespace kernel::filesystem::ext2 uint32_t feature_compat; uint32_t feature_incompat; uint32_t feature_ro_compat; - // uint8_t uuid[16]; // TODO BA-FS26 really correct? std::array uuid; - // uint8_t volume_name[16]; // TODO BA-FS26 really correct? std::array volume_name; - // uint8_t last_mounted[64]; // TODO BA-FS26 really correct? std::array last_mounted; uint32_t algorithm_usage_bitmap; @@ -55,14 +52,12 @@ namespace kernel::filesystem::ext2 uint16_t padding1; // Journaling Support - // uint8_t journal_uuid[16]; // TODO BA-FS26 really correct? std::array journal_uuid; uint32_t journal_inum; uint32_t journal_dev; uint32_t last_orphan; // Directory Indexing Support - // uint32_t hash_seed[4]; // TODO BA-FS26 really correct? std::array hash_seed; uint8_t def_hash_version; std::array padding2; -- 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 --- .../filesystem/ext2/block_group_descriptor.hpp | 2 +- .../include/kernel/filesystem/ext2/filesystem.hpp | 4 +++ kernel/include/kernel/filesystem/ext2/inode.hpp | 19 +++++++----- .../filesystem/ext2/linked_directory_entry.hpp | 2 +- .../include/kernel/filesystem/ext2/superblock.hpp | 2 +- kernel/src/filesystem/ext2/filesystem.cpp | 35 +++++++++++++++++----- 6 files changed, 45 insertions(+), 19 deletions(-) (limited to 'kernel') diff --git a/kernel/include/kernel/filesystem/ext2/block_group_descriptor.hpp b/kernel/include/kernel/filesystem/ext2/block_group_descriptor.hpp index a23c045..2ff91d9 100644 --- a/kernel/include/kernel/filesystem/ext2/block_group_descriptor.hpp +++ b/kernel/include/kernel/filesystem/ext2/block_group_descriptor.hpp @@ -6,7 +6,7 @@ namespace kernel::filesystem::ext2 { - struct block_group_descriptor + struct [[gnu::packed]] block_group_descriptor { uint32_t block_bitmap; uint32_t inode_bitmap; diff --git a/kernel/include/kernel/filesystem/ext2/filesystem.hpp b/kernel/include/kernel/filesystem/ext2/filesystem.hpp index 59b9cba..ccee172 100644 --- a/kernel/include/kernel/filesystem/ext2/filesystem.hpp +++ b/kernel/include/kernel/filesystem/ext2/filesystem.hpp @@ -4,6 +4,7 @@ #include "kapi/devices/device.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" @@ -12,6 +13,7 @@ #include #include +#include #include namespace kernel::filesystem::ext2 @@ -23,6 +25,8 @@ namespace kernel::filesystem::ext2 -> kstd::shared_ptr override; private: + auto read_inode(uint32_t inode_number) -> kstd::shared_ptr; + auto get_block_size() -> size_t; auto get_inode_size() -> size_t; diff --git a/kernel/include/kernel/filesystem/ext2/inode.hpp b/kernel/include/kernel/filesystem/ext2/inode.hpp index 2c27c17..4284e6f 100644 --- a/kernel/include/kernel/filesystem/ext2/inode.hpp +++ b/kernel/include/kernel/filesystem/ext2/inode.hpp @@ -11,13 +11,8 @@ namespace kernel::filesystem::ext2 { - struct inode : kernel::filesystem::inode + struct [[gnu::packed]] inode_data { - inode(); - - auto read(void * buffer, size_t offset, size_t size) const -> size_t override; - auto write(void const * buffer, size_t offset, size_t size) -> size_t override; - uint16_t mode; uint16_t uid; uint32_t size; @@ -30,15 +25,23 @@ namespace kernel::filesystem::ext2 uint32_t blocks; uint32_t flags; uint32_t osd1; - // uint32_t block[15]; // TODO BA-FS26 really correct? std::array block; // NOLINT(readability-magic-numbers) uint32_t generation; uint32_t file_acl; uint32_t dir_acl; uint32_t faddr; - // uint8_t osd2[12]; // TODO BA-FS26 really correct? std::array osd2; // NOLINT(readability-magic-numbers) }; + + struct inode : kernel::filesystem::inode + { + inode(); + + auto read(void * buffer, size_t offset, size_t size) const -> size_t override; + auto write(void const * buffer, size_t offset, size_t size) -> size_t override; + + inode_data m_data{}; + }; } // namespace kernel::filesystem::ext2 #endif \ No newline at end of file diff --git a/kernel/include/kernel/filesystem/ext2/linked_directory_entry.hpp b/kernel/include/kernel/filesystem/ext2/linked_directory_entry.hpp index 8dd42a1..f44255a 100644 --- a/kernel/include/kernel/filesystem/ext2/linked_directory_entry.hpp +++ b/kernel/include/kernel/filesystem/ext2/linked_directory_entry.hpp @@ -6,7 +6,7 @@ namespace kernel::filesystem::ext2 { - struct linked_directory_entry + struct [[gnu::packed]] linked_directory_entry { uint32_t inode; uint16_t rec_len; diff --git a/kernel/include/kernel/filesystem/ext2/superblock.hpp b/kernel/include/kernel/filesystem/ext2/superblock.hpp index e7e15f2..8e57ae7 100644 --- a/kernel/include/kernel/filesystem/ext2/superblock.hpp +++ b/kernel/include/kernel/filesystem/ext2/superblock.hpp @@ -6,7 +6,7 @@ namespace kernel::filesystem::ext2 { - struct superblock + struct [[gnu::packed]] superblock { uint32_t inodes_count; uint32_t blocks_count; 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/include/kernel/filesystem/inode.hpp | 3 ++- kernel/src/filesystem/ext2/filesystem.cpp | 41 +++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 13 deletions(-) (limited to 'kernel') diff --git a/kernel/include/kernel/filesystem/inode.hpp b/kernel/include/kernel/filesystem/inode.hpp index d97b5ab..59207df 100644 --- a/kernel/include/kernel/filesystem/inode.hpp +++ b/kernel/include/kernel/filesystem/inode.hpp @@ -25,7 +25,8 @@ namespace kernel::filesystem [[nodiscard]] auto is_regular() const -> bool; [[nodiscard]] auto is_device() const -> bool; - private: + // TODO BA-FS26 improve inode_kind really needed? + public: inode_kind m_kind{inode_kind::regular}; }; } // namespace kernel::filesystem 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') 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 15ea1551e54c36ebac26f21dc156636e326298c6 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 3 Apr 2026 14:29:32 +0200 Subject: fix linked_directory_entry struct --- kernel/include/kernel/filesystem/ext2/linked_directory_entry.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'kernel') diff --git a/kernel/include/kernel/filesystem/ext2/linked_directory_entry.hpp b/kernel/include/kernel/filesystem/ext2/linked_directory_entry.hpp index f44255a..76eb6f5 100644 --- a/kernel/include/kernel/filesystem/ext2/linked_directory_entry.hpp +++ b/kernel/include/kernel/filesystem/ext2/linked_directory_entry.hpp @@ -12,8 +12,7 @@ namespace kernel::filesystem::ext2 uint16_t rec_len; uint8_t name_len; uint8_t file_type; - uint8_t pad; - std::array name; // NOLINT(readability-magic-numbers) + std::array name; // NOLINT(readability-magic-numbers) }; } // namespace kernel::filesystem::ext2 -- 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 --- .../include/kernel/filesystem/ext2/filesystem.hpp | 2 + kernel/src/filesystem/ext2/filesystem.cpp | 120 ++++++++++++++++----- 2 files changed, 98 insertions(+), 24 deletions(-) (limited to 'kernel') diff --git a/kernel/include/kernel/filesystem/ext2/filesystem.hpp b/kernel/include/kernel/filesystem/ext2/filesystem.hpp index ccee172..dea059f 100644 --- a/kernel/include/kernel/filesystem/ext2/filesystem.hpp +++ b/kernel/include/kernel/filesystem/ext2/filesystem.hpp @@ -26,9 +26,11 @@ namespace kernel::filesystem::ext2 private: auto read_inode(uint32_t inode_number) -> kstd::shared_ptr; + auto map_inode_block_index_to_global_block_number(uint32_t inode_block_index, inode_data data) -> uint32_t; auto get_block_size() -> size_t; auto get_inode_size() -> size_t; + auto get_inode_block_count(inode_data const & data) -> uint32_t; superblock m_superblock; kstd::vector m_block_group_descriptors; 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 --- .../include/kernel/filesystem/ext2/filesystem.hpp | 1 + kernel/src/filesystem/ext2/filesystem.cpp | 101 ++++++++++----------- 2 files changed, 49 insertions(+), 53 deletions(-) (limited to 'kernel') diff --git a/kernel/include/kernel/filesystem/ext2/filesystem.hpp b/kernel/include/kernel/filesystem/ext2/filesystem.hpp index dea059f..9761903 100644 --- a/kernel/include/kernel/filesystem/ext2/filesystem.hpp +++ b/kernel/include/kernel/filesystem/ext2/filesystem.hpp @@ -27,6 +27,7 @@ namespace kernel::filesystem::ext2 private: auto read_inode(uint32_t inode_number) -> kstd::shared_ptr; auto map_inode_block_index_to_global_block_number(uint32_t inode_block_index, inode_data data) -> uint32_t; + auto read_block_number_at_index(uint32_t block_number, uint32_t index) -> uint32_t; auto get_block_size() -> size_t; auto get_inode_size() -> size_t; 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/include/kernel/filesystem/ext2/inode.hpp | 5 ++++- kernel/src/filesystem/ext2/filesystem.cpp | 2 +- kernel/src/filesystem/ext2/inode.cpp | 12 ++++++++++-- 3 files changed, 15 insertions(+), 4 deletions(-) (limited to 'kernel') diff --git a/kernel/include/kernel/filesystem/ext2/inode.hpp b/kernel/include/kernel/filesystem/ext2/inode.hpp index 4284e6f..9318008 100644 --- a/kernel/include/kernel/filesystem/ext2/inode.hpp +++ b/kernel/include/kernel/filesystem/ext2/inode.hpp @@ -11,6 +11,8 @@ namespace kernel::filesystem::ext2 { + struct filesystem; + struct [[gnu::packed]] inode_data { uint16_t mode; @@ -35,12 +37,13 @@ namespace kernel::filesystem::ext2 struct inode : kernel::filesystem::inode { - inode(); + explicit inode(filesystem * fs); auto read(void * buffer, size_t offset, size_t size) const -> size_t override; auto write(void const * buffer, size_t offset, size_t size) -> size_t override; inode_data m_data{}; + filesystem * m_filesystem; }; } // namespace kernel::filesystem::ext2 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 --- .../include/kernel/filesystem/ext2/filesystem.hpp | 5 ++-- kernel/include/kernel/filesystem/filesystem.hpp | 1 + kernel/src/filesystem/ext2/inode.cpp | 33 ++++++++++++++++++++-- kernel/src/filesystem/filesystem.cpp | 5 ++++ 4 files changed, 39 insertions(+), 5 deletions(-) (limited to 'kernel') diff --git a/kernel/include/kernel/filesystem/ext2/filesystem.hpp b/kernel/include/kernel/filesystem/ext2/filesystem.hpp index 9761903..762f590 100644 --- a/kernel/include/kernel/filesystem/ext2/filesystem.hpp +++ b/kernel/include/kernel/filesystem/ext2/filesystem.hpp @@ -24,12 +24,13 @@ namespace kernel::filesystem::ext2 auto lookup(kstd::shared_ptr const & parent, std::string_view name) -> kstd::shared_ptr override; + auto get_block_size() -> size_t; + auto map_inode_block_index_to_global_block_number(uint32_t inode_block_index, inode_data data) -> uint32_t; + private: auto read_inode(uint32_t inode_number) -> kstd::shared_ptr; - auto map_inode_block_index_to_global_block_number(uint32_t inode_block_index, inode_data data) -> uint32_t; auto read_block_number_at_index(uint32_t block_number, uint32_t index) -> uint32_t; - auto get_block_size() -> size_t; auto get_inode_size() -> size_t; auto get_inode_block_count(inode_data const & data) -> uint32_t; diff --git a/kernel/include/kernel/filesystem/filesystem.hpp b/kernel/include/kernel/filesystem/filesystem.hpp index 1c45377..0f9de9f 100644 --- a/kernel/include/kernel/filesystem/filesystem.hpp +++ b/kernel/include/kernel/filesystem/filesystem.hpp @@ -22,6 +22,7 @@ namespace kernel::filesystem virtual auto lookup(kstd::shared_ptr const & parent, std::string_view name) -> kstd::shared_ptr = 0; [[nodiscard]] auto root_inode() const -> kstd::shared_ptr const &; + [[nodiscard]] auto device() const -> kstd::shared_ptr const &; protected: kstd::shared_ptr m_root_inode{}; 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') 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/include/kernel/filesystem/ext2/filesystem.hpp | 2 +- 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 -- 5 files changed, 3 insertions(+), 8 deletions(-) (limited to 'kernel') diff --git a/kernel/include/kernel/filesystem/ext2/filesystem.hpp b/kernel/include/kernel/filesystem/ext2/filesystem.hpp index 762f590..abab0a6 100644 --- a/kernel/include/kernel/filesystem/ext2/filesystem.hpp +++ b/kernel/include/kernel/filesystem/ext2/filesystem.hpp @@ -34,7 +34,7 @@ namespace kernel::filesystem::ext2 auto get_inode_size() -> size_t; auto get_inode_block_count(inode_data const & data) -> uint32_t; - superblock m_superblock; + superblock m_superblock; // TODO BA-FS26 initialize kstd::vector m_block_group_descriptors; }; } // namespace kernel::filesystem::ext2 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