diff options
| author | Marcel Braun <marcel.braun@ost.ch> | 2026-04-12 19:15:38 +0200 |
|---|---|---|
| committer | Marcel Braun <marcel.braun@ost.ch> | 2026-04-12 19:15:38 +0200 |
| commit | 4d2a1d028f8ba28b655026b93124e71a12562619 (patch) | |
| tree | f49deef4dd3e8728fd1000b04c0908966f37663f /kernel | |
| parent | 21fd1281cf19572e202d583689b99c33ec68da50 (diff) | |
| parent | cb7edbe6d4454ee5b217b522f62f4a7b92475a32 (diff) | |
| download | teachos-develop-BA-FS26.tar.xz teachos-develop-BA-FS26.zip | |
Merge branch 'ext2' into 'develop-BA-FS26'HEADdevelop-BA-FS26
ext2 and tests
See merge request teachos/kernel!22
Diffstat (limited to 'kernel')
74 files changed, 3385 insertions, 175 deletions
diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 74233cb..2f6113a 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -101,7 +101,13 @@ else() "src/test_support/kapi/cio.cpp" "src/test_support/kapi/interrupts.cpp" "src/test_support/kapi/memory.cpp" - "src/test_support/log_buffer.cpp" + "src/test_support/devices/block_device.cpp" + "src/test_support/devices/character_device.cpp" + "src/test_support/filesystem/inode.cpp" + "src/test_support/filesystem/filesystem.cpp" + "src/test_support/filesystem/ext2.cpp" + "src/test_support/filesystem/storage_boot_module_fixture.cpp" + "src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp" "src/test_support/log_buffer.cpp" "src/test_support/output_device.cpp" "src/test_support/page_mapper.cpp" "src/test_support/simulated_memory.cpp" @@ -126,7 +132,24 @@ else() "src/memory/bitmap_allocator.tests.cpp" "src/memory/block_list_allocator.tests.cpp" + # Filesystem Subsystem Tests + "src/filesystem/devfs/filesystem.tests.cpp" + "src/filesystem/devfs/inode.tests.cpp" + "src/filesystem/ext2/filesystem.tests.cpp" + "src/filesystem/ext2/inode.tests.cpp" + "src/filesystem/rootfs/filesystem.tests.cpp" + "src/filesystem/rootfs/inode.tests.cpp" + "src/filesystem/dentry.tests.cpp" + "src/filesystem/device_inode.tests.cpp" + "src/filesystem/file_descriptor_table.tests.cpp" + "src/filesystem/mount_table.tests.cpp" + "src/filesystem/mount.tests.cpp" + "src/filesystem/open_file_description.tests.cpp" + "src/filesystem/vfs.tests.cpp" + # Storage Subsystem Tests + "src/devices/block_device_utils.tests.cpp" + "src/devices/block_device.tests.cpp" "src/devices/storage/ram_disk/device.tests.cpp" ) add_executable("os::kernel_tests" ALIAS "kernel_tests") @@ -136,6 +159,10 @@ else() "os::kernel_test_support" ) + target_compile_definitions("kernel_tests" PRIVATE + KERNEL_TEST_ASSETS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/src/test_support/filesystem/test_assets" + ) + set_target_properties("kernel_tests" PROPERTIES C_CLANG_TIDY "" CXX_CLANG_TIDY "" diff --git a/kernel/include/kernel/devices/block_device_utils.hpp b/kernel/include/kernel/devices/block_device_utils.hpp index 5e862ba..7b1daec 100644 --- a/kernel/include/kernel/devices/block_device_utils.hpp +++ b/kernel/include/kernel/devices/block_device_utils.hpp @@ -9,7 +9,34 @@ namespace kernel::devices::block_device_utils { - auto read(kstd::shared_ptr<kapi::devices::device> const & device, void * buffer, size_t offset, size_t size) -> size_t; + /** + @brief Utility functions for block devices, such as reading/writing data at specific offsets. These functions handle + the necessary logic to interact with block devices, such as calculating block boundaries and ensuring proper access + patterns. They abstract away the details of block device interactions, providing a simple interface for reading and + writing data to block devices. + */ + + /** + @brief Reads data from a @p device into a @p buffer, starting at a specific @p offset and for a given @p size. + @warning Panics if @p buffer or @p device is null. + @param device The block device to read from. + @param buffer The buffer to read data into. + @param offset The offset on the block device to start reading from. + @param size The number of bytes to read. + @return The number of bytes actually read, which may be less than the requested size. + */ + auto read(kstd::shared_ptr<kapi::devices::device> const & device, void * buffer, size_t offset, size_t size) + -> size_t; + + /** + @brief Writes data from a @p buffer to a @p device, starting at a specific @p offset and for a given @p size. + @warning Panics if @p buffer or @p device is null. + @param device The block device to write to. + @param buffer The buffer to write data from. + @param offset The offset on the block device to start writing to. + @param size The number of bytes to write. + @return The number of bytes actually written, which may be less than the requested size. + */ auto write(kstd::shared_ptr<kapi::devices::device> const & device, void const * buffer, size_t offset, size_t size) -> size_t; } // namespace kernel::devices::block_device_utils diff --git a/kernel/include/kernel/filesystem/dentry.hpp b/kernel/include/kernel/filesystem/dentry.hpp index fc85a7d..58a918f 100644 --- a/kernel/include/kernel/filesystem/dentry.hpp +++ b/kernel/include/kernel/filesystem/dentry.hpp @@ -12,23 +12,78 @@ namespace kernel::filesystem { + /** + @brief Represents a directory entry (dentry) in the filesystem. A dentry is a node in the directory tree that + represents a file or directory. It contains a reference to its parent dentry, a reference to the associated real + filesystem inode, and a list of child dentries. + */ struct dentry { + /** + @brief Flags for the dentry. + */ enum class dentry_flags : uint32_t { dcache_mounted = 1 << 15 }; - dentry(kstd::shared_ptr<dentry> const & parent, kstd::shared_ptr<inode> const & node, std::string_view name = {}); + /** + @brief Create a dentry with the given @p parent, associated @p inode, and optional @p name. The dentry is + initialized with the provided parent and inode, and the name is stored for lookup purposes. + @param parent The parent dentry. + @param inode The associated inode for this dentry. + @param name The name of the dentry (optional). + */ + dentry(kstd::shared_ptr<dentry> const & parent, kstd::shared_ptr<inode> const & inode, std::string_view name = {}); + /** + @brief Get the associated inode. + @return A reference to the associated inode. + */ [[nodiscard]] auto get_inode() const -> kstd::shared_ptr<inode> const &; + + /** + @brief Get the parent dentry. + @return A reference to the parent dentry. + */ [[nodiscard]] auto get_parent() const -> kstd::shared_ptr<dentry> const &; + /** + @brief Get the name of the dentry. + @return The name of the dentry. + */ + [[nodiscard]] auto get_name() const -> std::string_view; + + /** + @brief Add a @p child dentry. + @param child The child dentry to add. + */ auto add_child(kstd::shared_ptr<dentry> const & child) -> void; + + /** + @brief Find a child dentry by @p name. + @param name The name of the child dentry to find. + @return A pointer to the found child dentry, or a null pointer if not found. + */ [[nodiscard]] auto find_child(std::string_view name) const -> kstd::shared_ptr<dentry>; + /** + @brief Set a @p flag for the dentry. + @param flag The flag to set. + */ auto set_flag(dentry_flags flag) -> void; + + /** + @brief Unset a @p flag for the dentry. + @param flag The flag to unset. + */ auto unset_flag(dentry_flags flag) -> void; + + /** + @brief Check if the dentry has a specific @p flag. + @param flag The flag to check. + @return True if the dentry has the flag, false otherwise. + */ [[nodiscard]] auto has_flag(dentry_flags flag) const -> bool; private: diff --git a/kernel/include/kernel/filesystem/devfs/filesystem.hpp b/kernel/include/kernel/filesystem/devfs/filesystem.hpp index 29ae388..137eca3 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" @@ -12,9 +13,27 @@ namespace kernel::filesystem::devfs { + /** + @brief A filesystem for managing device nodes in the virtual filesystem. This filesystem provides a way to represent + devices as files in the /dev directory, allowing user-space applications to interact with devices using standard file + operations. The devfs filesystem dynamically creates inodes for devices registered in the system, enabling seamless + access to device functionality through the filesystem interface. + */ struct filesystem : kernel::filesystem::filesystem { - auto mount(kstd::shared_ptr<kapi::devices::device> const & device) -> int override; + /** + @brief Initializes the devfs instance and builds the device inode table. + @param device Backing device passed by the generic filesystem interface (not required by devfs). + @return The result of the mount operation. + */ + auto mount(kstd::shared_ptr<kapi::devices::device> const & device) -> operation_result override; + + /** + @brief Looks up an inode by @p name within a @p parent directory. + @param parent The parent directory inode. + @param name The name of the inode to look up. + @return A pointer to the found inode, or a null pointer if not found. + */ auto lookup(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name) -> kstd::shared_ptr<kernel::filesystem::inode> override; diff --git a/kernel/include/kernel/filesystem/devfs/inode.hpp b/kernel/include/kernel/filesystem/devfs/inode.hpp index 9c11edf..c117bd2 100644 --- a/kernel/include/kernel/filesystem/devfs/inode.hpp +++ b/kernel/include/kernel/filesystem/devfs/inode.hpp @@ -7,11 +7,33 @@ namespace kernel::filesystem::devfs { + /** + @brief Inode implementation for the devfs filesystem. + This inode represents root device node in the /dev directory. + */ struct inode : kernel::filesystem::inode { + /** + @brief Create a devfs inode. The inode is initialized with the appropriate kind (directory). + */ inode(); + /** + @brief Reads from the devfs directory inode. + @param buffer Destination buffer. + @param offset Read offset in bytes. + @param size Number of bytes requested. + @return Number of bytes read (always 0 because this inode does not expose file data). + */ auto read(void * buffer, size_t offset, size_t size) const -> size_t override; + + /** + @brief Writes to the devfs directory inode. + @param buffer Source buffer. + @param offset Write offset in bytes. + @param size Number of bytes requested. + @return Number of bytes written (always 0 because writes are not supported for this inode). + */ auto write(void const * buffer, size_t offset, size_t size) -> size_t override; }; } // namespace kernel::filesystem::devfs diff --git a/kernel/include/kernel/filesystem/device_inode.hpp b/kernel/include/kernel/filesystem/device_inode.hpp index 18a98f5..c33be2a 100644 --- a/kernel/include/kernel/filesystem/device_inode.hpp +++ b/kernel/include/kernel/filesystem/device_inode.hpp @@ -2,6 +2,7 @@ #define TEACH_OS_KERNEL_FILESYSTEM_DEVICE_INODE_HPP #include "kapi/devices/device.hpp" + #include "kernel/filesystem/inode.hpp" #include <kstd/memory> @@ -10,13 +11,43 @@ namespace kernel::filesystem { + /** + @brief Inode implementation for device inodes in the filesystem. This inode represents a device file that provides + access to a device registered in the system. The device inode allows reading from and writing to the associated + device. + */ struct device_inode : inode { + /** + @brief Create a device inode with the given @p device. + @param device The device to associate with the inode. + */ explicit device_inode(kstd::shared_ptr<kapi::devices::device> const & device); + /** + @brief Read data from the device inode (and in the background from the associated device) into a @p buffer, starting + at @p offset and reading @p size bytes. + @param buffer The buffer to read data into. + @param offset The offset to read from. + @param size The number of bytes to read. + @return The number of bytes read. + */ auto read(void * buffer, size_t offset, size_t size) const -> size_t override; + + /** + @brief Write data to the device inode (and in the background from the associated device) from a @p buffer, starting + at @p offset and writing @p size bytes. + @param buffer The buffer containing data to write. + @param offset The offset to write to. + @param size The number of bytes to write. + @return The number of bytes written. + */ auto write(void const * buffer, size_t offset, size_t size) -> size_t override; + /** + @brief Get the associated device. + @return A reference to the associated device. + */ [[nodiscard]] auto device() const -> kstd::shared_ptr<kapi::devices::device> const &; private: diff --git a/kernel/include/kernel/filesystem/ext2/block_group_descriptor.hpp b/kernel/include/kernel/filesystem/ext2/block_group_descriptor.hpp index a23c045..7fbba3f 100644 --- a/kernel/include/kernel/filesystem/ext2/block_group_descriptor.hpp +++ b/kernel/include/kernel/filesystem/ext2/block_group_descriptor.hpp @@ -6,7 +6,10 @@ namespace kernel::filesystem::ext2 { - struct block_group_descriptor + /** + @brief Represents a block group descriptor in the ext2 filesystem. + */ + 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 078da31..a71385f 100644 --- a/kernel/include/kernel/filesystem/ext2/filesystem.hpp +++ b/kernel/include/kernel/filesystem/ext2/filesystem.hpp @@ -2,20 +2,88 @@ #define TEACH_OS_KERNEL_FILESYSTEM_EXT2_FILESYSTEM_HPP #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" #include <kstd/memory> +#include <kstd/vector> +#include <cstddef> +#include <cstdint> #include <string_view> namespace kernel::filesystem::ext2 { + /** + @brief Constants related to the ext2 filesystem. + */ + namespace constants + { + constexpr size_t inline base_block_size = 1024; + constexpr size_t inline superblock_offset = base_block_size; + constexpr uint16_t inline magic_number = 0xEF53; + + constexpr uint32_t inline root_inode_number = 2; + + constexpr size_t inline direct_block_count = 12; + constexpr size_t inline singly_indirect_block_index = direct_block_count; + constexpr size_t inline doubly_indirect_block_index = singly_indirect_block_index + 1; + constexpr size_t inline triply_indirect_block_index = doubly_indirect_block_index + 1; + + constexpr uint16_t inline mode_mask = 0xF000; + constexpr uint16_t inline mode_regular = 0x8000; + constexpr uint16_t inline mode_directory = 0x4000; + } // namespace constants + + /** + @brief A filesystem implementation for the ext2 filesystem format. This class provides methods for mounting an ext2 + filesystem, and looking up inodes. + */ struct filesystem : kernel::filesystem::filesystem { - auto mount(kstd::shared_ptr<kapi::devices::device> const & device) -> int override; + /** + @brief Initializes the ext2 filesystem with the given @p device. + @param device The device to mount. + @return The result of the mount operation. + */ + auto mount(kstd::shared_ptr<kapi::devices::device> const & device) -> operation_result override; + + /** + @brief Looks up an inode by @p name within a @p parent directory. + @param parent The parent directory inode. + @param name The name of the inode to look up. + @return A pointer to the found inode, or a null pointer if not found. + */ auto lookup(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name) -> kstd::shared_ptr<kernel::filesystem::inode> override; + + /** + @brief Gets the size of a block in the filesystem. + @return The size of a block in bytes. + */ + auto get_block_size() -> size_t; + + /** + @brief Maps an inode block index to a global block number. + @param inode_block_index The index of the block within the inode. + @param data T |
