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/CMakeLists.txt | 2 ++ kernel/include/kernel/filesystem/device_inode.hpp | 14 ++++++++++++++ kernel/include/kernel/filesystem/ext2/ext2_inode.hpp | 14 ++++++++++++++ kernel/src/filesystem/device_inode.cpp | 6 ++++++ kernel/src/filesystem/ext2/ext2_inode.cpp | 6 ++++++ 5 files changed, 42 insertions(+) create mode 100644 kernel/include/kernel/filesystem/device_inode.hpp create mode 100644 kernel/include/kernel/filesystem/ext2/ext2_inode.hpp create mode 100644 kernel/src/filesystem/device_inode.cpp create mode 100644 kernel/src/filesystem/ext2/ext2_inode.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 398022c..a36eac0 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -22,8 +22,10 @@ add_executable("kernel" "src/devices/storage/ram_disk/ram_disk_controller.cpp" "src/devices/storage/ram_disk/ram_disk_device.cpp" "src/filesystem/ext2/ext2_filesystem.cpp" + "src/filesystem/ext2/ext2_inode.cpp" "src/filesystem/custody.cpp" "src/filesystem/device_file.cpp" + "src/filesystem/device_inode.cpp" "src/filesystem/file_descriptor_table.cpp" "src/filesystem/filesystem.cpp" "src/filesystem/inode_file.cpp" diff --git a/kernel/include/kernel/filesystem/device_inode.hpp b/kernel/include/kernel/filesystem/device_inode.hpp new file mode 100644 index 0000000..a99e5d1 --- /dev/null +++ b/kernel/include/kernel/filesystem/device_inode.hpp @@ -0,0 +1,14 @@ +#ifndef TEACH_OS_KERNEL_FILESYSTEM_DEVICE_INODE_HPP +#define TEACH_OS_KERNEL_FILESYSTEM_DEVICE_INODE_HPP + +#include "kernel/filesystem/inode.hpp" + +namespace filesystem +{ + struct device_inode : inode + { + // TODO BA-FS26 + }; +} // namespace filesystem + +#endif \ No newline at end of file diff --git a/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp b/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp new file mode 100644 index 0000000..7cd6f8f --- /dev/null +++ b/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp @@ -0,0 +1,14 @@ +#ifndef TEACH_OS_KERNEL_FILESYSTEM_EXT2_INODE_HPP +#define TEACH_OS_KERNEL_FILESYSTEM_EXT2_INODE_HPP + +#include "kernel/filesystem/inode.hpp" + +namespace filesystem::ext2 +{ + struct ext2_inode : inode + { + // TODO BA-FS26 + }; +} // namespace filesystem::ext2 + +#endif \ No newline at end of file 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/include/kernel/filesystem/device_inode.hpp | 15 +++- kernel/include/kernel/filesystem/filesystem.hpp | 4 +- kernel/include/kernel/filesystem/inode.hpp | 23 +++--- .../include/kernel/filesystem/inode_metadata.hpp | 24 ------ 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 +- 9 files changed, 82 insertions(+), 132 deletions(-) delete mode 100644 kernel/include/kernel/filesystem/inode_metadata.hpp diff --git a/kernel/include/kernel/filesystem/device_inode.hpp b/kernel/include/kernel/filesystem/device_inode.hpp index a99e5d1..0287875 100644 --- a/kernel/include/kernel/filesystem/device_inode.hpp +++ b/kernel/include/kernel/filesystem/device_inode.hpp @@ -1,13 +1,26 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_DEVICE_INODE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_DEVICE_INODE_HPP +#include "kernel/devices/device.hpp" #include "kernel/filesystem/inode.hpp" +#include + +#include + namespace filesystem { struct device_inode : inode { - // TODO BA-FS26 + explicit device_inode(kstd::shared_ptr const & device); + + [[nodiscard]] auto backing_device() const -> kstd::shared_ptr const &; + + 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; + + private: + kstd::shared_ptr m_device{}; }; } // namespace filesystem diff --git a/kernel/include/kernel/filesystem/filesystem.hpp b/kernel/include/kernel/filesystem/filesystem.hpp index 23924c4..035f49d 100644 --- a/kernel/include/kernel/filesystem/filesystem.hpp +++ b/kernel/include/kernel/filesystem/filesystem.hpp @@ -17,10 +17,10 @@ namespace filesystem virtual auto mount(kstd::shared_ptr const & device) -> int = 0; virtual auto lookup(inode const & parent, std::string_view name) -> inode * = 0; - [[nodiscard]] auto root_inode() const -> inode const &; + [[nodiscard]] auto root_inode() const -> kstd::shared_ptr const &; protected: - inode m_root_inode{}; // TODO BA-FS26 set during mount? + kstd::shared_ptr m_root_inode{}; }; } // namespace filesystem diff --git a/kernel/include/kernel/filesystem/inode.hpp b/kernel/include/kernel/filesystem/inode.hpp index a2955f9..dcf83b9 100644 --- a/kernel/include/kernel/filesystem/inode.hpp +++ b/kernel/include/kernel/filesystem/inode.hpp @@ -1,9 +1,6 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_INODE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_INODE_HPP -#include "kernel/devices/device.hpp" -#include "kernel/filesystem/inode_metadata.hpp" - #include #include @@ -12,26 +9,26 @@ namespace filesystem { struct inode { - inode() = default; + enum class inode_kind + { + regular, + directory, + device + }; + explicit inode(inode_kind kind); - explicit inode(kstd::shared_ptr const & device); - [[nodiscard]] auto metadata() const -> inode_metadata; + virtual ~inode() = default; [[nodiscard]] auto is_directory() const -> bool; [[nodiscard]] auto is_regular() const -> bool; [[nodiscard]] auto is_device() const -> bool; - [[nodiscard]] auto is_block_device() const -> bool; - [[nodiscard]] auto major_device() const -> size_t; - [[nodiscard]] auto minor_device() const -> size_t; - [[nodiscard]] auto backing_device() const -> kstd::shared_ptr const &; - auto read(void * buffer, size_t offset, size_t size) const -> size_t; - auto write(void const * buffer, size_t offset, size_t size) -> size_t; + virtual auto read(void * buffer, size_t offset, size_t size) const -> size_t = 0; + virtual auto write(void const * buffer, size_t offset, size_t size) -> size_t = 0; private: inode_kind m_kind{inode_kind::regular}; - kstd::shared_ptr m_device{}; }; } // namespace filesystem diff --git a/kernel/include/kernel/filesystem/inode_metadata.hpp b/kernel/include/kernel/filesystem/inode_metadata.hpp deleted file mode 100644 index ed5a09d..0000000 --- a/kernel/include/kernel/filesystem/inode_metadata.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef TEACH_OS_KERNEL_FILESYSTEM_INODE_METADATA_HPP -#define TEACH_OS_KERNEL_FILESYSTEM_INODE_METADATA_HPP - -#include -#include - -namespace filesystem -{ - enum class inode_kind - { - regular, - directory, - device - }; - - struct inode_metadata - { - inode_kind kind{inode_kind::regular}; - std::optional major{}; - std::optional minor{}; - }; -} // namespace filesystem - -#endif // TEACH_OS_KERNEL_FILESYSTEM_INODE_METADATA_HPP \ No newline at end of file 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/CMakeLists.txt | 2 +- kernel/include/kernel/filesystem/device_file.hpp | 2 -- kernel/include/kernel/filesystem/device_inode.hpp | 8 ++--- .../include/kernel/filesystem/ext2/ext2_file.hpp | 17 +++++++++++ .../include/kernel/filesystem/ext2/ext2_inode.hpp | 10 ++++++- kernel/include/kernel/filesystem/file.hpp | 2 -- kernel/include/kernel/filesystem/inode.hpp | 7 ++--- kernel/include/kernel/filesystem/inode_file.hpp | 27 ----------------- 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 +++------ 14 files changed, 75 insertions(+), 123 deletions(-) create mode 100644 kernel/include/kernel/filesystem/ext2/ext2_file.hpp delete mode 100644 kernel/include/kernel/filesystem/inode_file.hpp create mode 100644 kernel/src/filesystem/ext2/ext2_file.cpp delete mode 100644 kernel/src/filesystem/inode_file.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index a36eac0..a8287ba 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -21,6 +21,7 @@ add_executable("kernel" "src/devices/storage/storage_management.cpp" "src/devices/storage/ram_disk/ram_disk_controller.cpp" "src/devices/storage/ram_disk/ram_disk_device.cpp" + "src/filesystem/ext2/ext2_file.cpp" "src/filesystem/ext2/ext2_filesystem.cpp" "src/filesystem/ext2/ext2_inode.cpp" "src/filesystem/custody.cpp" @@ -28,7 +29,6 @@ add_executable("kernel" "src/filesystem/device_inode.cpp" "src/filesystem/file_descriptor_table.cpp" "src/filesystem/filesystem.cpp" - "src/filesystem/inode_file.cpp" "src/filesystem/inode.cpp" "src/filesystem/mount.cpp" "src/filesystem/open_file_description.cpp" diff --git a/kernel/include/kernel/filesystem/device_file.hpp b/kernel/include/kernel/filesystem/device_file.hpp index 06aa9b2..ff803f8 100644 --- a/kernel/include/kernel/filesystem/device_file.hpp +++ b/kernel/include/kernel/filesystem/device_file.hpp @@ -15,8 +15,6 @@ namespace filesystem { explicit device_file(kstd::shared_ptr const & device); - auto open() -> void override; - 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; diff --git a/kernel/include/kernel/filesystem/device_inode.hpp b/kernel/include/kernel/filesystem/device_inode.hpp index 0287875..c38c75b 100644 --- a/kernel/include/kernel/filesystem/device_inode.hpp +++ b/kernel/include/kernel/filesystem/device_inode.hpp @@ -2,22 +2,18 @@ #define TEACH_OS_KERNEL_FILESYSTEM_DEVICE_INODE_HPP #include "kernel/devices/device.hpp" +#include "kernel/filesystem/file.hpp" #include "kernel/filesystem/inode.hpp" #include -#include - namespace filesystem { struct device_inode : inode { explicit device_inode(kstd::shared_ptr const & device); - [[nodiscard]] auto backing_device() const -> kstd::shared_ptr const &; - - 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; + [[nodiscard]] auto open_file() const -> kstd::shared_ptr override; private: kstd::shared_ptr m_device{}; diff --git a/kernel/include/kernel/filesystem/ext2/ext2_file.hpp b/kernel/include/kernel/filesystem/ext2/ext2_file.hpp new file mode 100644 index 0000000..b5708d8 --- /dev/null +++ b/kernel/include/kernel/filesystem/ext2/ext2_file.hpp @@ -0,0 +1,17 @@ +#ifndef TEACH_OS_KERNEL_FILESYSTEM_EXT2_FILE_HPP +#define TEACH_OS_KERNEL_FILESYSTEM_EXT2_FILE_HPP + +#include "kernel/filesystem/file.hpp" + +#include + +namespace filesystem::ext2 +{ + struct ext2_file : file + { + 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; + }; +} // namespace filesystem::ext2 + +#endif \ No newline at end of file diff --git a/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp b/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp index 7cd6f8f..f103877 100644 --- a/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp +++ b/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp @@ -1,13 +1,21 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_EXT2_INODE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_EXT2_INODE_HPP +#include "kernel/filesystem/file.hpp" #include "kernel/filesystem/inode.hpp" +#include + namespace filesystem::ext2 { struct ext2_inode : inode { - // TODO BA-FS26 + ext2_inode(); + + [[nodiscard]] auto open_file() const -> kstd::shared_ptr override; + + private: + // TODO BA-FS26 add ext2-specific inode metadata here (e.g. block pointers, size, permissions, etc.) }; } // namespace filesystem::ext2 diff --git a/kernel/include/kernel/filesystem/file.hpp b/kernel/include/kernel/filesystem/file.hpp index e7e1b12..5a41fab 100644 --- a/kernel/include/kernel/filesystem/file.hpp +++ b/kernel/include/kernel/filesystem/file.hpp @@ -9,8 +9,6 @@ namespace filesystem { virtual ~file() = default; - virtual auto open() -> void = 0; - virtual auto read(void * buffer, size_t offset, size_t size) const -> size_t = 0; virtual auto write(void const * buffer, size_t offset, size_t size) -> size_t = 0; }; diff --git a/kernel/include/kernel/filesystem/inode.hpp b/kernel/include/kernel/filesystem/inode.hpp index dcf83b9..79cbcf9 100644 --- a/kernel/include/kernel/filesystem/inode.hpp +++ b/kernel/include/kernel/filesystem/inode.hpp @@ -1,9 +1,9 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_INODE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_INODE_HPP -#include +#include "kernel/filesystem/file.hpp" -#include +#include namespace filesystem { @@ -24,8 +24,7 @@ namespace filesystem [[nodiscard]] auto is_regular() const -> bool; [[nodiscard]] auto is_device() const -> bool; - virtual auto read(void * buffer, size_t offset, size_t size) const -> size_t = 0; - virtual auto write(void const * buffer, size_t offset, size_t size) -> size_t = 0; + [[nodiscard]] virtual auto open_file() const -> kstd::shared_ptr = 0; private: inode_kind m_kind{inode_kind::regular}; diff --git a/kernel/include/kernel/filesystem/inode_file.hpp b/kernel/include/kernel/filesystem/inode_file.hpp deleted file mode 100644 index ee84eee..0000000 --- a/kernel/include/kernel/filesystem/inode_file.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef TEACH_OS_KERNEL_FILESYSTEM_INODE_FILE_HPP -#define TEACH_OS_KERNEL_FILESYSTEM_INODE_FILE_HPP - -#include "kernel/filesystem/file.hpp" -#include "kernel/filesystem/inode.hpp" - -#include - -#include - -namespace filesystem -{ - struct inode_file : file - { - explicit inode_file(kstd::shared_ptr const & inode); - - auto open() -> void override; - - 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; - - private: - kstd::shared_ptr m_inode; - }; -} // namespace filesystem - -#endif \ No newline at end of file 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/CMakeLists.txt | 1 + kernel/include/kernel/filesystem/disk_file.hpp | 19 +++++++++++++ .../include/kernel/filesystem/ext2/ext2_file.hpp | 4 +-- .../include/kernel/filesystem/ext2/ext2_inode.hpp | 5 ++-- kernel/include/kernel/filesystem/inode_file.hpp | 25 +++++++++++++++++ kernel/src/filesystem/ext2/ext2_inode.cpp | 8 +++--- kernel/src/filesystem/inode_file.cpp | 31 ++++++++++++++++++++++ 7 files changed, 86 insertions(+), 7 deletions(-) create mode 100644 kernel/include/kernel/filesystem/disk_file.hpp create mode 100644 kernel/include/kernel/filesystem/inode_file.hpp create mode 100644 kernel/src/filesystem/inode_file.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index a8287ba..e0b40be 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -29,6 +29,7 @@ add_executable("kernel" "src/filesystem/device_inode.cpp" "src/filesystem/file_descriptor_table.cpp" "src/filesystem/filesystem.cpp" + "src/filesystem/inode_file.cpp" "src/filesystem/inode.cpp" "src/filesystem/mount.cpp" "src/filesystem/open_file_description.cpp" diff --git a/kernel/include/kernel/filesystem/disk_file.hpp b/kernel/include/kernel/filesystem/disk_file.hpp new file mode 100644 index 0000000..c6a7655 --- /dev/null +++ b/kernel/include/kernel/filesystem/disk_file.hpp @@ -0,0 +1,19 @@ +#ifndef TEACH_OS_KERNEL_FILESYSTEM_DISK_FILE_HPP +#define TEACH_OS_KERNEL_FILESYSTEM_DISK_FILE_HPP + +#include + +#include + +namespace filesystem +{ + struct disk_file + { + virtual ~disk_file() = default; + + virtual auto read(void * buffer, size_t offset, size_t size) const -> size_t = 0; + virtual auto write(void const * buffer, size_t offset, size_t size) -> size_t = 0; + }; +} // namespace filesystem + +#endif \ No newline at end of file diff --git a/kernel/include/kernel/filesystem/ext2/ext2_file.hpp b/kernel/include/kernel/filesystem/ext2/ext2_file.hpp index b5708d8..371507d 100644 --- a/kernel/include/kernel/filesystem/ext2/ext2_file.hpp +++ b/kernel/include/kernel/filesystem/ext2/ext2_file.hpp @@ -1,13 +1,13 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_EXT2_FILE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_EXT2_FILE_HPP -#include "kernel/filesystem/file.hpp" +#include "kernel/filesystem/disk_file.hpp" #include namespace filesystem::ext2 { - struct ext2_file : file + struct ext2_file : disk_file { 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; diff --git a/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp b/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp index f103877..7b5ff3f 100644 --- a/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp +++ b/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp @@ -1,6 +1,7 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_EXT2_INODE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_EXT2_INODE_HPP +#include "kernel/filesystem/disk_file.hpp" #include "kernel/filesystem/file.hpp" #include "kernel/filesystem/inode.hpp" @@ -10,12 +11,12 @@ namespace filesystem::ext2 { struct ext2_inode : inode { - ext2_inode(); + explicit ext2_inode(kstd::shared_ptr const & disk_file); [[nodiscard]] auto open_file() const -> kstd::shared_ptr override; private: - // TODO BA-FS26 add ext2-specific inode metadata here (e.g. block pointers, size, permissions, etc.) + kstd::shared_ptr m_disk_file{}; }; } // namespace filesystem::ext2 diff --git a/kernel/include/kernel/filesystem/inode_file.hpp b/kernel/include/kernel/filesystem/inode_file.hpp new file mode 100644 index 0000000..3e2b954 --- /dev/null +++ b/kernel/include/kernel/filesystem/inode_file.hpp @@ -0,0 +1,25 @@ +#ifndef TEACH_OS_KERNEL_FILESYSTEM_INODE_FILE_HPP +#define TEACH_OS_KERNEL_FILESYSTEM_INODE_FILE_HPP + +#include "kernel/filesystem/disk_file.hpp" +#include "kernel/filesystem/file.hpp" + +#include + +#include + +namespace filesystem +{ + struct inode_file : file + { + explicit inode_file(kstd::shared_ptr const & disk_file); + + 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; + + private: + kstd::shared_ptr m_disk_file; + }; +} // namespace filesystem + +#endif \ 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 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(-) 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(-) 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/include/kernel/filesystem/vfs.hpp | 10 ++++--- kernel/src/filesystem/vfs.cpp | 49 +++++++++++++++++++++++++++++--- 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/kernel/include/kernel/filesystem/vfs.hpp b/kernel/include/kernel/filesystem/vfs.hpp index a2894a6..2ad570b 100644 --- a/kernel/include/kernel/filesystem/vfs.hpp +++ b/kernel/include/kernel/filesystem/vfs.hpp @@ -3,7 +3,7 @@ #include "kernel/devices/device.hpp" #include "kernel/filesystem/custody.hpp" -#include "kernel/filesystem/ext2/ext2_filesystem.hpp" +#include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" #include "kernel/filesystem/mount.hpp" #include "kernel/filesystem/open_file_description.hpp" @@ -24,22 +24,24 @@ namespace filesystem ~vfs() = default; auto open(std::string_view path) -> std::optional; + auto do_mount(std::string_view path, kstd::shared_ptr const & filesystem) -> int; private: + // TODO BA-FS26 remove again and use devtempfs struct device_node_entry { std::string_view name; kstd::shared_ptr node; }; + kstd::vector> m_device_nodes; // TODO BA-FS26 remove again, use devtempfs vfs() = default; auto make_device_node(kstd::shared_ptr const & device) -> void; [[nodiscard]] auto resolve_path(std::string_view path) -> std::optional; - kstd::shared_ptr m_root_fs; + kstd::shared_ptr m_root_fs; std::optional m_root_mount; - // kstd::vector m_mounts; // TODO BA-FS26 really needed? - kstd::vector> m_device_nodes; // TODO BA-FS26 remove again, use devtempfs + kstd::vector m_mounts; }; } // namespace filesystem 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/filesystem/file_descriptor_table.hpp | 10 ++++----- kernel/include/kernel/filesystem/vfs.hpp | 2 +- kernel/src/filesystem/file_descriptor_table.cpp | 24 ++++++++++++++-------- kernel/src/filesystem/vfs.cpp | 8 ++++---- kernel/src/main.cpp | 4 ++-- 5 files changed, 27 insertions(+), 21 deletions(-) diff --git a/kernel/include/kernel/filesystem/file_descriptor_table.hpp b/kernel/include/kernel/filesystem/file_descriptor_table.hpp index 6d78532..bc6fb24 100644 --- a/kernel/include/kernel/filesystem/file_descriptor_table.hpp +++ b/kernel/include/kernel/filesystem/file_descriptor_table.hpp @@ -3,10 +3,9 @@ #include "open_file_description.hpp" +#include #include -#include - namespace filesystem { struct file_descriptor_table @@ -16,15 +15,14 @@ namespace filesystem ~file_descriptor_table() = default; - auto add_file(open_file_description & f) -> int; - [[nodiscard]] auto get_file(int fd) const -> std::optional; + auto add_file(kstd::shared_ptr const & f) -> int; + [[nodiscard]] auto get_file(int fd) const -> kstd::shared_ptr; auto remove_file(int fd) -> void; private: file_descriptor_table() = default; - // TODO BA-FS26 use kstd::shared_ptr when available - kstd::vector> m_open_files{}; + kstd::vector> m_open_files{}; }; } // namespace filesystem diff --git a/kernel/include/kernel/filesystem/vfs.hpp b/kernel/include/kernel/filesystem/vfs.hpp index 2ad570b..ca51d90 100644 --- a/kernel/include/kernel/filesystem/vfs.hpp +++ b/kernel/include/kernel/filesystem/vfs.hpp @@ -23,7 +23,7 @@ namespace filesystem ~vfs() = default; - auto open(std::string_view path) -> std::optional; + auto open(std::string_view path) -> kstd::shared_ptr; auto do_mount(std::string_view path, kstd::shared_ptr const & filesystem) -> int; private: 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(-) 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/CMakeLists.txt | 1 + kernel/include/kernel/filesystem/device_file.hpp | 6 ++++-- kernel/include/kernel/filesystem/device_inode.hpp | 7 ++++-- kernel/include/kernel/filesystem/disk_file.hpp | 19 ---------------- .../include/kernel/filesystem/ext2/ext2_file.hpp | 8 +++---- .../include/kernel/filesystem/ext2/ext2_inode.hpp | 9 ++++---- kernel/include/kernel/filesystem/file.hpp | 8 +++++++ kernel/include/kernel/filesystem/inode.hpp | 8 +++---- kernel/include/kernel/filesystem/inode_file.hpp | 9 ++++---- 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 ++++- 16 files changed, 112 insertions(+), 68 deletions(-) delete mode 100644 kernel/include/kernel/filesystem/disk_file.hpp create mode 100644 kernel/src/filesystem/file.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index e0b40be..ec0d4e2 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -27,6 +27,7 @@ add_executable("kernel" "src/filesystem/custody.cpp" "src/filesystem/device_file.cpp" "src/filesystem/device_inode.cpp" + "src/filesystem/file.cpp" "src/filesystem/file_descriptor_table.cpp" "src/filesystem/filesystem.cpp" "src/filesystem/inode_file.cpp" diff --git a/kernel/include/kernel/filesystem/device_file.hpp b/kernel/include/kernel/filesystem/device_file.hpp index ff803f8..22ddb49 100644 --- a/kernel/include/kernel/filesystem/device_file.hpp +++ b/kernel/include/kernel/filesystem/device_file.hpp @@ -11,9 +11,11 @@ namespace filesystem { + struct inode; + struct device_file : file { - explicit device_file(kstd::shared_ptr const & device); + explicit device_file(kstd::shared_ptr const & 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; @@ -23,7 +25,7 @@ namespace filesystem std::byte * scratch, void * buffer); auto process_blocks(size_t offset, size_t size, void * buffer, block_op op) const -> size_t; - kstd::shared_ptr m_device; + [[nodiscard]] auto device() const -> kstd::shared_ptr const &; }; } // namespace filesystem diff --git a/kernel/include/kernel/filesystem/device_inode.hpp b/kernel/include/kernel/filesystem/device_inode.hpp index c38c75b..af2a51b 100644 --- a/kernel/include/kernel/filesystem/device_inode.hpp +++ b/kernel/include/kernel/filesystem/device_inode.hpp @@ -2,18 +2,21 @@ #define TEACH_OS_KERNEL_FILESYSTEM_DEVICE_INODE_HPP #include "kernel/devices/device.hpp" -#include "kernel/filesystem/file.hpp" #include "kernel/filesystem/inode.hpp" #include namespace filesystem { + struct file; + struct device_inode : inode { explicit device_inode(kstd::shared_ptr const & device); - [[nodiscard]] auto open_file() const -> kstd::shared_ptr override; + [[nodiscard]] auto open_file(kstd::shared_ptr const & self) const -> kstd::shared_ptr override; + + [[nodiscard]] auto device() const -> kstd::shared_ptr const &; private: kstd::shared_ptr m_device{}; diff --git a/kernel/include/kernel/filesystem/disk_file.hpp b/kernel/include/kernel/filesystem/disk_file.hpp deleted file mode 100644 index c6a7655..0000000 --- a/kernel/include/kernel/filesystem/disk_file.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef TEACH_OS_KERNEL_FILESYSTEM_DISK_FILE_HPP -#define TEACH_OS_KERNEL_FILESYSTEM_DISK_FILE_HPP - -#include - -#include - -namespace filesystem -{ - struct disk_file - { - virtual ~disk_file() = default; - - virtual auto read(void * buffer, size_t offset, size_t size) const -> size_t = 0; - virtual auto write(void const * buffer, size_t offset, size_t size) -> size_t = 0; - }; -} // namespace filesystem - -#endif \ No newline at end of file diff --git a/kernel/include/kernel/filesystem/ext2/ext2_file.hpp b/kernel/include/kernel/filesystem/ext2/ext2_file.hpp index 371507d..e5357e3 100644 --- a/kernel/include/kernel/filesystem/ext2/ext2_file.hpp +++ b/kernel/include/kernel/filesystem/ext2/ext2_file.hpp @@ -1,16 +1,14 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_EXT2_FILE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_EXT2_FILE_HPP -#include "kernel/filesystem/disk_file.hpp" - #include namespace filesystem::ext2 { - struct ext2_file : disk_file + struct ext2_file { - 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; + auto read(void * buffer, size_t offset, size_t size) const -> size_t; + auto write(void const * buffer, size_t offset, size_t size) -> size_t; }; } // namespace filesystem::ext2 diff --git a/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp b/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp index 7b5ff3f..b57d267 100644 --- a/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp +++ b/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp @@ -1,7 +1,7 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_EXT2_INODE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_EXT2_INODE_HPP -#include "kernel/filesystem/disk_file.hpp" +#include "kernel/filesystem/ext2/ext2_file.hpp" #include "kernel/filesystem/file.hpp" #include "kernel/filesystem/inode.hpp" @@ -11,12 +11,13 @@ namespace filesystem::ext2 { struct ext2_inode : inode { - explicit ext2_inode(kstd::shared_ptr const & disk_file); + explicit ext2_inode(); - [[nodiscard]] auto open_file() const -> kstd::shared_ptr override; + [[nodiscard]] auto open_file(kstd::shared_ptr const & self) const + -> kstd::shared_ptr override; private: - kstd::shared_ptr m_disk_file{}; + kstd::shared_ptr m_file{}; }; } // namespace filesystem::ext2 diff --git a/kernel/include/kernel/filesystem/file.hpp b/kernel/include/kernel/filesystem/file.hpp index 5a41fab..522f078 100644 --- a/kernel/include/kernel/filesystem/file.hpp +++ b/kernel/include/kernel/filesystem/file.hpp @@ -1,16 +1,24 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_FILE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_FILE_HPP +#include + #include namespace filesystem { + struct inode; + struct file { + explicit file(kstd::shared_ptr const & inode); virtual ~file() = default; virtual auto read(void * buffer, size_t offset, size_t size) const -> size_t = 0; virtual auto write(void const * buffer, size_t offset, size_t size) -> size_t = 0; + + protected: + kstd::shared_ptr m_inode; }; } // namespace filesystem diff --git a/kernel/include/kernel/filesystem/inode.hpp b/kernel/include/kernel/filesystem/inode.hpp index 79cbcf9..8c9f75e 100644 --- a/kernel/include/kernel/filesystem/inode.hpp +++ b/kernel/include/kernel/filesystem/inode.hpp @@ -1,12 +1,12 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_INODE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_INODE_HPP -#include "kernel/filesystem/file.hpp" - #include namespace filesystem { + struct file; + struct inode { enum class inode_kind @@ -20,12 +20,12 @@ namespace filesystem virtual ~inode() = default; + [[nodiscard]] virtual auto open_file(kstd::shared_ptr const & self) const -> kstd::shared_ptr = 0; + [[nodiscard]] auto is_directory() const -> bool; [[nodiscard]] auto is_regular() const -> bool; [[nodiscard]] auto is_device() const -> bool; - [[nodiscard]] virtual auto open_file() const -> kstd::shared_ptr = 0; - private: inode_kind m_kind{inode_kind::regular}; }; diff --git a/kernel/include/kernel/filesystem/inode_file.hpp b/kernel/include/kernel/filesystem/inode_file.hpp index 3e2b954..f87b77c 100644 --- a/kernel/include/kernel/filesystem/inode_file.hpp +++ b/kernel/include/kernel/filesystem/inode_file.hpp @@ -1,8 +1,8 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_INODE_FILE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_INODE_FILE_HPP -#include "kernel/filesystem/disk_file.hpp" #include "kernel/filesystem/file.hpp" +#include "kernel/filesystem/inode.hpp" #include @@ -10,15 +10,14 @@ namespace filesystem { + struct inode; + struct inode_file : file { - explicit inode_file(kstd::shared_ptr const & disk_file); + explicit inode_file(kstd::shared_ptr const & 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; - - private: - kstd::shared_ptr m_disk_file; }; } // namespace filesystem 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 09bf8eba8dbc76dc9c46ec1486cbf2f9530233a8 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 21 Mar 2026 10:44:05 +0100 Subject: implement simple weak_ptr and enable_shared_from_this --- libs/kstd/include/kstd/bits/shared_ptr.hpp | 320 ++++++++++++++++++++++++++--- 1 file changed, 286 insertions(+), 34 deletions(-) diff --git a/libs/kstd/include/kstd/bits/shared_ptr.hpp b/libs/kstd/include/kstd/bits/shared_ptr.hpp index 6bce83f..674807d 100644 --- a/libs/kstd/include/kstd/bits/shared_ptr.hpp +++ b/libs/kstd/include/kstd/bits/shared_ptr.hpp @@ -10,9 +10,199 @@ namespace kstd { + /** + * @brief Control block for shared_ptr and weak_ptr. This control block contains the reference counts for shared + * ownership and weak ownership. The shared_count tracks the number of shared_ptr instances that own the managed + * object, while the weak_count tracks the number of weak_ptr instances that reference the managed object. + * The weak_count is needed to determine when it is safe to delete the shared_control_block itself + */ + struct shared_control_block + { + std::atomic shared_count; + std::atomic weak_count; + + explicit shared_control_block(std::size_t shared = 1, std::size_t weak = 0) + : shared_count(shared) + , weak_count(weak) + {} + }; + template struct shared_ptr; + /** + * @brief weak_ptr is a smart pointer that holds a non-owning weak reference to an object that is managed by + * shared_ptr. It must be converted to shared_ptr in to be able to access the referenced object. A weak_ptr is created + * as a copy of a shared_ptr, or as a copy of another weak_ptr. A weak_ptr is typically used to break circular + * references between shared_ptr to avoid memory leaks. A weak_ptr does not contribute to the reference count of the + * object, and it does not manage the lifetime of the object. If the object managed by shared_ptr is destroyed, the + * weak_ptr becomes expired and cannot be used to access the object anymore. + */ + template + struct weak_ptr + { + template + friend struct shared_ptr; + + /** + * @brief Constructs a null weak_ptr. + */ + weak_ptr() noexcept + : pointer(nullptr) + , control(nullptr) + {} + + template + requires(std::is_convertible_v) + weak_ptr(shared_ptr const & other) + : pointer(other.pointer) + , control(other.control) + { + if (control != nullptr) + { + ++(control->weak_count); + } + } + + /** + * @brief Copy constructor. Constructs a weak_ptr which shares ownership of the object managed by other. + */ + weak_ptr(weak_ptr const & other) + : pointer(other.pointer) + , control(other.control) + { + if (control != nullptr) + { + ++(control->weak_count); + } + } + + /** + * @brief Move constructor. Constructs a weak_ptr which takes ownership of the object managed by other. + */ + weak_ptr(weak_ptr && other) noexcept + : pointer(other.pointer) + , control(other.control) + { + other.pointer = nullptr; + other.control = nullptr; + } + + /** + * @brief Assignment operator. Assigns the weak_ptr to another weak_ptr. + */ + auto operator=(weak_ptr const & other) -> weak_ptr & + { + if (this != &other) + { + cleanup(); + pointer = other.pointer; + control = other.control; + if (control != nullptr) + { + ++(control->weak_count); + } + } + + return *this; + } + + /** + * @brief Move assignment operator. Move-assigns a weak_ptr from other. + */ + auto operator=(weak_ptr && other) noexcept -> weak_ptr & + { + if (this != &other) + { + cleanup(); + pointer = other.pointer; + control = other.control; + other.pointer = nullptr; + other.control = nullptr; + } + + return *this; + } + + /** + * @brief Destructor. Cleans up resources if necessary. + */ + ~weak_ptr() + { + cleanup(); + } + + /** + * @brief Returns a shared_ptr that shares ownership of the managed object if the managed object still exists, or an + * empty shared_ptr otherwise. + */ + [[nodiscard]] auto lock() const -> shared_ptr + { + return shared_ptr(*this); + } + + private: + auto cleanup() -> void + { + if (control != nullptr) + { + if (--(control->weak_count) == 0 && control->shared_count == 0) + { + delete control; + } + } + } + + T * pointer; + shared_control_block * control; + }; + + /** + * @brief enable_shared_from_this is a base class that allows an object that is currently managed by a shared_ptr to + * create additional shared_ptr instances that share ownership of the same object. This is usefl when you want to + * create shared_ptr instances in a member function of the object. + * + * @tparam T The type of the managed object. + */ + template + struct enable_shared_from_this + { + template + friend struct shared_ptr; + + friend T; + + public: + /** + * @brief Returns a shared_ptr that shares ownership of *this. + */ + auto shared_from_this() -> shared_ptr + { + return shared_ptr(weak_this); + } + + /** + * @brief Returns a shared_ptr that shares ownership of *this. + */ + auto shared_from_this() const -> shared_ptr + { + return shared_ptr(weak_this); + } + + private: + enable_shared_from_this() = default; + enable_shared_from_this(enable_shared_from_this const &) = default; + auto operator=(enable_shared_from_this const &) -> enable_shared_from_this & = default; + ~enable_shared_from_this() = default; + + void internal_assign_ptr(shared_ptr const & ptr) const + { + weak_this = ptr; + } + + mutable weak_ptr weak_this{}; ///< Weak pointer to the object, used for shared_from_this functionality. + }; + /** * @brief Shared_pointer is a smart pointer that retains shared ownership of an object through a pointer. Several * shared_ptr objects may own the same object. The object is destroyed and its memory deallocated when either of @@ -31,12 +221,23 @@ namespace kstd template friend struct shared_ptr; + template + friend struct weak_ptr; + + /** + * @brief Construct an empty shared_ptr. + */ + shared_ptr() noexcept + : pointer(nullptr) + , control(nullptr) + {} + /** * @brief Construct an empty shared_ptr from nullptr. */ shared_ptr(std::nullptr_t) noexcept : pointer(nullptr) - , ref_count(nullptr) + , control(nullptr) {} /** @@ -44,11 +245,33 @@ namespace kstd * * @param pointer A pointer to an object to manage (default is nullptr). */ - explicit shared_ptr(T * pointer = nullptr) + template + requires(std::is_convertible_v) + explicit shared_ptr(U * pointer = nullptr) : pointer(pointer) - , ref_count(pointer != nullptr ? new std::atomic(1) : nullptr) + , control(pointer != nullptr ? new shared_control_block() : nullptr) + { + assign_enable_shared_from_this(pointer); + } + + /** + * @brief Constructor a shared_ptr from a weak_ptr. If other is not expired, constructs a shared_ptr which shares + * ownership of the object managed by other. Otherwise, constructs an empty shared_ptr. + * + * @param other The weak_ptr to construct from. + */ + template + requires(std::is_convertible_v) + explicit shared_ptr(weak_ptr const & other) + : pointer(nullptr) + , control(nullptr) { - // Nothing to do. + if (other.control != nullptr && other.control->shared_count != 0) + { + pointer = other.pointer; + control = other.control; + ++(control->shared_count); + } } /** @@ -58,11 +281,11 @@ namespace kstd */ shared_ptr(shared_ptr const & other) : pointer(other.pointer) - , ref_count(other.ref_count) + , control(other.control) { - if (ref_count != nullptr) + if (control != nullptr) { - ++(*ref_count); + ++(control->shared_count); } } @@ -76,11 +299,11 @@ namespace kstd requires(std::is_convertible_v) shared_ptr(shared_ptr const & other) : pointer(other.pointer) - , ref_count(other.ref_count) + , control(other.control) { - if (ref_count != nullptr) + if (control != nullptr) { - ++(*ref_count); + ++(control->shared_count); } } @@ -91,10 +314,10 @@ namespace kstd */ shared_ptr(shared_ptr && other) noexcept : pointer(other.pointer) - , ref_count(other.ref_count) + , control(other.control) { other.pointer = nullptr; - other.ref_count = nullptr; + other.control = nullptr; } /** @@ -107,10 +330,10 @@ namespace kstd requires(std::is_convertible_v) shared_ptr(shared_ptr && other) noexcept : pointer(other.pointer) - , ref_count(other.ref_count) + , control(other.control) { other.pointer = nullptr; - other.ref_count = nullptr; + other.control = nullptr; } /** @@ -127,11 +350,11 @@ namespace kstd { cleanup(); pointer = other.pointer; - ref_count = other.ref_count; + control = other.control; - if (ref_count != nullptr) + if (control != nullptr) { - ++(*ref_count); + ++(control->shared_count); } } @@ -151,11 +374,11 @@ namespace kstd { cleanup(); pointer = other.pointer; - ref_count = other.ref_count; + control = other.control; - if (ref_count != nullptr) + if (control != nullptr) { - ++(*ref_count); + ++(control->shared_count); } return *this; @@ -174,9 +397,9 @@ namespace kstd { cleanup(); pointer = other.pointer; - ref_count = other.ref_count; + control = other.control; other.pointer = nullptr; - other.ref_count = nullptr; + other.control = nullptr; } return *this; @@ -195,9 +418,9 @@ namespace kstd { cleanup(); pointer = other.pointer; - ref_count = other.ref_count; + control = other.control; other.pointer = nullptr; - other.ref_count = nullptr; + other.control = nullptr; return *this; } @@ -209,7 +432,7 @@ namespace kstd { cleanup(); pointer = nullptr; - ref_count = nullptr; + control = nullptr; return *this; } @@ -230,7 +453,8 @@ namespace kstd { cleanup(); pointer = ptr; - ref_count = ptr != nullptr ? new std::atomic(1) : nullptr; + control = ptr != nullptr ? new shared_control_block() : nullptr; + assign_enable_shared_from_this(ptr); } /** @@ -242,7 +466,7 @@ namespace kstd void swap(shared_ptr & other) { std::swap(pointer, other.pointer); - std::swap(ref_count, other.ref_count); + std::swap(control, other.control); } /** @@ -288,9 +512,9 @@ namespace kstd */ [[nodiscard]] auto use_count() const -> std::size_t { - if (ref_count != nullptr) + if (control != nullptr) { - return *ref_count; + return control->shared_count; } return 0; @@ -328,20 +552,48 @@ namespace kstd [[nodiscard]] auto operator<=>(shared_ptr const & other) const = default; private: + /** + * @brief If the candidate type inherits from enable_shared_from_this, assigns the internal weak pointer to this + * shared_ptr. This weak_ptr is used to implement shared_from_this functionality for the candidate type. If the + * candidate type does not inherit from enable_shared_from_this, this function does nothing. + * + * @tparam U The candidate type to check for enable_shared_from_this inheritance. + * @param candidate The candidate object to assign the internal weak pointer for. + */ + template + auto assign_enable_shared_from_this(U * candidate) -> void + { + if constexpr (requires(U * p, shared_ptr const & sp) { p->internal_assign_ptr(sp); }) + { + if (candidate != nullptr) + { + candidate->internal_assign_ptr(*this); + } + } + } + /** * @brief Releases ownership and deletes the object if this was the last reference to the owned managed object. */ auto cleanup() -> void { - if (ref_count != nullptr && --(*ref_count) == 0) + if (control != nullptr) { - delete pointer; - delete ref_count; + if (--(control->shared_count) == 0) + { + delete pointer; + pointer = nullptr; + + if (control->weak_count == 0) + { + delete control; + } + } } } - T * pointer; ///< The managed object. - std::atomic * ref_count; ///< Reference count. + T * pointer; ///< The managed object. + shared_control_block * control; ///< Shared control block. }; /** -- 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/include/kernel/filesystem/device_inode.hpp | 4 ++-- kernel/include/kernel/filesystem/ext2/ext2_inode.hpp | 5 ++--- kernel/include/kernel/filesystem/inode.hpp | 4 ++-- kernel/src/filesystem/device_inode.cpp | 9 ++------- kernel/src/filesystem/ext2/ext2_inode.cpp | 11 ++--------- kernel/src/filesystem/vfs.cpp | 2 +- 6 files changed, 11 insertions(+), 24 deletions(-) diff --git a/kernel/include/kernel/filesystem/device_inode.hpp b/kernel/include/kernel/filesystem/device_inode.hpp index af2a51b..10e40b3 100644 --- a/kernel/include/kernel/filesystem/device_inode.hpp +++ b/kernel/include/kernel/filesystem/device_inode.hpp @@ -14,12 +14,12 @@ namespace filesystem { explicit device_inode(kstd::shared_ptr const & device); - [[nodiscard]] auto open_file(kstd::shared_ptr const & self) const -> kstd::shared_ptr override; + [[nodiscard]] auto open_file() -> kstd::shared_ptr override; [[nodiscard]] auto device() const -> kstd::shared_ptr const &; private: - kstd::shared_ptr m_device{}; + kstd::shared_ptr m_device; }; } // namespace filesystem diff --git a/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp b/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp index b57d267..e6e8e99 100644 --- a/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp +++ b/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp @@ -13,11 +13,10 @@ namespace filesystem::ext2 { explicit ext2_inode(); - [[nodiscard]] auto open_file(kstd::shared_ptr const & self) const - -> kstd::shared_ptr override; + [[nodiscard]] auto open_file() -> kstd::shared_ptr override; private: - kstd::shared_ptr m_file{}; + kstd::shared_ptr m_file; }; } // namespace filesystem::ext2 diff --git a/kernel/include/kernel/filesystem/inode.hpp b/kernel/include/kernel/filesystem/inode.hpp index 8c9f75e..1083d13 100644 --- a/kernel/include/kernel/filesystem/inode.hpp +++ b/kernel/include/kernel/filesystem/inode.hpp @@ -7,7 +7,7 @@ namespace filesystem { struct file; - struct inode + struct inode : kstd::enable_shared_from_this { enum class inode_kind { @@ -20,7 +20,7 @@ namespace filesystem virtual ~inode() = default; - [[nodiscard]] virtual auto open_file(kstd::shared_ptr const & self) const -> kstd::shared_ptr = 0; + [[nodiscard]] virtual auto open_file() -> kstd::shared_ptr = 0; [[nodiscard]] auto is_directory() const -> bool; [[nodiscard]] auto is_regular() const -> bool; 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/CMakeLists.txt | 3 - kernel/include/kernel/filesystem/device_file.hpp | 32 ------ kernel/include/kernel/filesystem/device_inode.hpp | 14 ++- .../include/kernel/filesystem/ext2/ext2_inode.hpp | 6 +- kernel/include/kernel/filesystem/file.hpp | 25 ---- kernel/include/kernel/filesystem/inode.hpp | 7 +- kernel/include/kernel/filesystem/inode_file.hpp | 24 ---- .../kernel/filesystem/open_file_description.hpp | 6 +- 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 +- 16 files changed, 138 insertions(+), 305 deletions(-) delete mode 100644 kernel/include/kernel/filesystem/device_file.hpp delete mode 100644 kernel/include/kernel/filesystem/file.hpp delete mode 100644 kernel/include/kernel/filesystem/inode_file.hpp 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 diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index ec0d4e2..16ebb8b 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -25,12 +25,9 @@ add_executable("kernel" "src/filesystem/ext2/ext2_filesystem.cpp" "src/filesystem/ext2/ext2_inode.cpp" "src/filesystem/custody.cpp" - "src/filesystem/device_file.cpp" "src/filesystem/device_inode.cpp" - "src/filesystem/file.cpp" "src/filesystem/file_descriptor_table.cpp" "src/filesystem/filesystem.cpp" - "src/filesystem/inode_file.cpp" "src/filesystem/inode.cpp" "src/filesystem/mount.cpp" "src/filesystem/open_file_description.cpp" diff --git a/kernel/include/kernel/filesystem/device_file.hpp b/kernel/include/kernel/filesystem/device_file.hpp deleted file mode 100644 index 22ddb49..0000000 --- a/kernel/include/kernel/filesystem/device_file.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef TEACH_OS_KERNEL_FILESYSTEM_DEVICE_FILE_HPP -#define TEACH_OS_KERNEL_FILESYSTEM_DEVICE_FILE_HPP - -#include "kernel/devices/block_device.hpp" -#include "kernel/devices/device.hpp" -#include "kernel/filesystem/file.hpp" - -#include - -#include - -namespace filesystem -{ - struct inode; - - struct device_file : file - { - explicit device_file(kstd::shared_ptr const & 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; - - private: - 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(size_t offset, size_t size, void * buffer, block_op op) const -> size_t; - - [[nodiscard]] auto device() const -> kstd::shared_ptr const &; - }; -} // namespace filesystem - -#endif diff --git a/kernel/include/kernel/filesystem/device_inode.hpp b/kernel/include/kernel/filesystem/device_inode.hpp index 10e40b3..ce0f91c 100644 --- a/kernel/include/kernel/filesystem/device_inode.hpp +++ b/kernel/include/kernel/filesystem/device_inode.hpp @@ -1,24 +1,28 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_DEVICE_INODE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_DEVICE_INODE_HPP +#include "kernel/devices/block_device.hpp" #include "kernel/devices/device.hpp" #include "kernel/filesystem/inode.hpp" #include +#include + namespace filesystem { - struct file; - struct device_inode : inode { explicit device_inode(kstd::shared_ptr const & device); - [[nodiscard]] auto open_file() -> kstd::shared_ptr override; - - [[nodiscard]] auto device() const -> kstd::shared_ptr const &; + 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; private: + 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(size_t offset, size_t size, void * buffer, block_op op) const -> size_t; + kstd::shared_ptr m_device; }; } // namespace filesystem diff --git a/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp b/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp index e6e8e99..5f4d16a 100644 --- a/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp +++ b/kernel/include/kernel/filesystem/ext2/ext2_inode.hpp @@ -2,18 +2,20 @@ #define TEACH_OS_KERNEL_FILESYSTEM_EXT2_INODE_HPP #include "kernel/filesystem/ext2/ext2_file.hpp" -#include "kernel/filesystem/file.hpp" #include "kernel/filesystem/inode.hpp" #include +#include + namespace filesystem::ext2 { struct ext2_inode : inode { explicit ext2_inode(); - [[nodiscard]] auto open_file() -> kstd::shared_ptr override; + 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; private: kstd::shared_ptr m_file; diff --git a/kernel/include/kernel/filesystem/file.hpp b/kernel/include/kernel/filesystem/file.hpp deleted file mode 100644 index 522f078..0000000 --- a/kernel/include/kernel/filesystem/file.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef TEACH_OS_KERNEL_FILESYSTEM_FILE_HPP -#define TEACH_OS_KERNEL_FILESYSTEM_FILE_HPP - -#include - -#include - -namespace filesystem -{ - struct inode; - - struct file - { - explicit file(kstd::shared_ptr const & inode); - virtual ~file() = default; - - virtual auto read(void * buffer, size_t offset, size_t size) const -> size_t = 0; - virtual auto write(void const * buffer, size_t offset, size_t size) -> size_t = 0; - - protected: - kstd::shared_ptr m_inode; - }; -} // namespace filesystem - -#endif \ No newline at end of file diff --git a/kernel/include/kernel/filesystem/inode.hpp b/kernel/include/kernel/filesystem/inode.hpp index 1083d13..94ccd89 100644 --- a/kernel/include/kernel/filesystem/inode.hpp +++ b/kernel/include/kernel/filesystem/inode.hpp @@ -3,10 +3,10 @@ #include +#include + namespace filesystem { - struct file; - struct inode : kstd::enable_shared_from_this { enum class inode_kind @@ -20,7 +20,8 @@ namespace filesystem virtual ~inode() = default; - [[nodiscard]] virtual auto open_file() -> kstd::shared_ptr = 0; + virtual auto read(void * buffer, size_t offset, size_t size) const -> size_t = 0; + virtual auto write(void const * buffer, size_t offset, size_t size) -> size_t = 0; [[nodiscard]] auto is_directory() const -> bool; [[nodiscard]] auto is_regular() const -> bool; diff --git a/kernel/include/kernel/filesystem/inode_file.hpp b/kernel/include/kernel/filesystem/inode_file.hpp deleted file mode 100644 index f87b77c..0000000 --- a/kernel/include/kernel/filesystem/inode_file.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef TEACH_OS_KERNEL_FILESYSTEM_INODE_FILE_HPP -#define TEACH_OS_KERNEL_FILESYSTEM_INODE_FILE_HPP - -#include "kernel/filesystem/file.hpp" -#include "kernel/filesystem/inode.hpp" - -#include - -#include - -namespace filesystem -{ - struct inode; - - struct inode_file : file - { - explicit inode_file(kstd::shared_ptr const & 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; - }; -} // namespace filesystem - -#endif \ No newline at end of file diff --git a/kernel/include/kernel/filesystem/open_file_description.hpp b/kernel/include/kernel/filesystem/open_file_description.hpp index 5ff094d..3c97d50 100644 --- a/kernel/include/kernel/filesystem/open_file_description.hpp +++ b/kernel/include/kernel/filesystem/open_file_description.hpp @@ -1,7 +1,7 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_OPEN_FILE_DESCRIPTION_HPP #define TEACH_OS_KERNEL_FILESYSTEM_OPEN_FILE_DESCRIPTION_HPP -#include "file.hpp" +#include "kernel/filesystem/inode.hpp" #include @@ -11,7 +11,7 @@ namespace filesystem { struct open_file_description { - open_file_description(kstd::shared_ptr const & file); + open_file_description(kstd::shared_ptr const & inode); ~open_file_description() = default; @@ -19,7 +19,7 @@ namespace filesystem auto write(void const * buffer, size_t size) -> size_t; private: - kstd::shared_ptr m_file; + kstd::shared_ptr m_inode; size_t m_offset; }; 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(-) 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 10b77e5c9741211f99cefecd50bcec76dc046d84 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 21 Mar 2026 19:07:02 +0100 Subject: implement simple kstd::string --- libs/kstd/include/kstd/string | 264 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 libs/kstd/include/kstd/string diff --git a/libs/kstd/include/kstd/string b/libs/kstd/include/kstd/string new file mode 100644 index 0000000..62126a9 --- /dev/null +++ b/libs/kstd/include/kstd/string @@ -0,0 +1,264 @@ +#ifndef KSTD_STRING_HPP +#define KSTD_STRING_HPP + +#include +#include +#include + +#include +#include +#include + +namespace kstd +{ + /** + * @brief A simple string implementation that owns its data and provides basic operations. + */ + struct string + { + //! The type of the characters contained in this string. + using value_type = char; + //! The type of the underlying storage used by this string. + using storage_type = kstd::vector; + //! The type of all sizes used in and with this string. + using size_type = std::size_t; + //! The type of the difference between two iterators. + using difference_type = std::ptrdiff_t; + //! The type of references to single values in this string. + using reference = value_type &; + //! The type of references to constant single values in this string. + using const_reference = value_type const &; + //! The type of pointers to single values in this string. + using pointer = value_type *; + //! The type of pointers to constant single values in this string. + using const_pointer = value_type const *; + //! The type of iterators into this string. + using iterator = pointer; + //! The type of constant iterators into this string. + using const_iterator = const_pointer; + + /** + * @brief Constructs an empty null-terminated string. + */ + string() + : m_storage{value_type{'\0'}} + {} + + /** + * @brief Constructs a string from a string view by copying the characters into owned storage. + * @param view The string view to copy the characters from. + */ + string(std::string_view view) + : string() + { + append(view); + } + + /** + * @brief Constructs a string by copying another string. + * @param other The string to copy. + */ + constexpr string(string const & other) + : m_storage{other.m_storage} + {} + + /** + * @brief Destructs the string. + */ + constexpr ~string() = default; + + /** + * @brief Assigns the value of another string to this string. + * @param other The string to assign from. + * @return A reference to this string. + */ + constexpr auto operator=(string const & other) -> string & = default; + + /** + * @brief Returns the number of characters in this string, not including the null terminator. + */ + [[nodiscard]] constexpr auto size() const noexcept -> size_type + { + return m_storage.empty() ? 0 : m_storage.size() - 1; + } + + /** + * @brief Checks if this string is empty, not including the null terminator. + */ + [[nodiscard]] constexpr auto empty() const noexcept -> bool + { + return size() == 0; + } + + /** + * @brief Clears the content of the string, resulting in an empty string. + * The string remains null-terminated after this operation. + */ + constexpr auto clear() -> void + { + m_storage.clear(); + m_storage.push_back(value_type{'\0'}); + } + + //! Get a pointer to the underlying storage of the string + [[nodiscard]] constexpr auto data() noexcept -> pointer + { + return m_storage.data(); + } + + //! Get a const pointer to the underlying storage of the string + [[nodiscard]] constexpr auto data() const noexcept -> const_pointer + { + return m_storage.data(); + } + + //! Get a const pointer to the underlying storage of the string + [[nodiscard]] constexpr auto c_str() const noexcept -> const_pointer + { + return data(); + } + + //! Get an iterator to the beginning of the string + [[nodiscard]] constexpr auto begin() noexcept -> iterator + { + return data(); + } + + //! Get an const iterator to the beginning of the string + [[nodiscard]] constexpr auto begin() const noexcept -> const_iterator + { + return data(); + } + + //! Get an const iterator to the beginning of the string + [[nodiscard]] constexpr auto cbegin() const noexcept -> const_iterator + { + return begin(); + } + + //! Get an iterator to the end of the string + [[nodiscard]] constexpr auto end() noexcept -> iterator + { + return data() + size(); + } + + //! Get an const iterator to the end of the string + [[nodiscard]] constexpr auto end() const noexcept -> const_iterator + { + return data() + size(); + } + + //! Get an const iterator to the end of the string + [[nodiscard]] constexpr auto cend() const noexcept -> const_iterator + { + return end(); + } + + //! Get a reference to the first character of the string + [[nodiscard]] constexpr auto front() -> reference + { + return m_storage.front(); + } + + //! Get a const reference to the first character of the string + [[nodiscard]] constexpr auto front() const -> const_reference + { + return m_storage.front(); + } + + //! Get a reference to the last character of the string + [[nodiscard]] constexpr auto back() -> reference + { + return m_storage[size() - 1]; + } + + //! Get a const reference to the last character of the string + [[nodiscard]] constexpr auto back() const -> const_reference + { + return m_storage[size() - 1]; + } + + /** + * @brief Appends a character to the end of the string. + * @param ch The character to append. + */ + constexpr auto push_back(value_type ch) -> void + { + m_storage.back() = ch; + m_storage.push_back(value_type{'\0'}); + } + + /** + * @brief Appends a string view to the end of the string by copying the characters into owned storage. + * @param view The string view to append. + * @return A reference to this string. + */ + constexpr auto append(std::string_view view) -> string & + { + if (!view.empty()) + { + std::ranges::for_each(view, [this](auto const ch) { push_back(ch); }); + } + + return *this; + } + + /** + * @brief Appends another string to the end of this string by copying the characters into owned storage. + * @param other The string to append. + * @return A reference to this string. + */ + constexpr auto append(string const & other) -> string & + { + return append(other.view()); + } + + /** + * @brief Appends another string to the end of this string by copying the characters into owned storage. + * @param other The string to append. + * @return A reference to this string. + */ + constexpr auto operator+=(string const & other) -> string & + { + return append(other); + } + + /** + * @brief Appends a character to the end of the string. + * @param ch The character to append. + * @return A reference to this string. + */ + constexpr auto operator+=(value_type ch) -> string & + { + push_back(ch); + return *this; + } + + /** + * @brief Returns a string view of this string, which is a non-owning view into the characters of this string. + */ + [[nodiscard]] constexpr auto view() const noexcept -> std::string_view + { + return std::string_view{data(), size()}; + } + + private: + //! The underlying storage of the string, which owns the characters and ensures null-termination. + storage_type m_storage{}; + }; + + /** + * @brief Concatenates a strings and a character and returns the result as a new string. + * @param lhs The string to concatenate. + * @param c The character to concatenate. + * @return A new string that is the result of concatenating @p lhs and @p c. + */ + [[nodiscard]] constexpr auto inline operator+(string const & lhs, char const c) -> string + { + string result{lhs}; + result += c; + return result; + } +} // namespace kstd + +#endif \ No newline at end of file -- cgit v1.2.3 From c470ca76ce7801a2a4efb03c9ed606b34b368ded Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 21 Mar 2026 23:57:21 +0100 Subject: implement simple conversion function from unsigned integral values to kstd::string --- libs/kstd/include/kstd/string | 61 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/libs/kstd/include/kstd/string b/libs/kstd/include/kstd/string index 62126a9..f9583d5 100644 --- a/libs/kstd/include/kstd/string +++ b/libs/kstd/include/kstd/string @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -54,6 +55,29 @@ namespace kstd append(view); } + /** + * @brief Constructs a string from a null-terminated C-style string by copying the characters into owned storage. + * @param c_str The null-terminated C-style string to copy. + */ + string(char const * c_str) + : string() + { + if (c_str != nullptr) + { + append(std::string_view{c_str}); + } + } + + /** + * @brief Constructs a string containing a single character. + * @param c The character to copy. + */ + string(value_type c) + : string() + { + push_back(c); + } + /** * @brief Constructs a string by copying another string. * @param other The string to copy. @@ -250,13 +274,42 @@ namespace kstd /** * @brief Concatenates a strings and a character and returns the result as a new string. * @param lhs The string to concatenate. - * @param c The character to concatenate. - * @return A new string that is the result of concatenating @p lhs and @p c. + * @param rhs The string to concatenate. + * @return A new string that is the result of concatenating @p lhs and @p rhs. */ - [[nodiscard]] constexpr auto inline operator+(string const & lhs, char const c) -> string + [[nodiscard]] constexpr auto inline operator+(string const & lhs, string const & rhs) -> string { string result{lhs}; - result += c; + result += rhs; + return result; + } + + /** + * @brief Converts an unsigned integer to a string by converting each digit to the corresponding character and + * concatenating them. + * @tparam N The type of the unsigned integer to convert. + * @param value The unsigned integer to convert. + * @return A string representation of the given unsigned integer. + */ + template + requires std::unsigned_integral + [[nodiscard]] constexpr auto inline to_string(N value) -> string + { + if (value == 0) + { + return "0"; + } + + string result; + + while (value > 0) + { + char const digit = '0' + (value % 10); + result.push_back(digit); + value /= 10; + } + + std::reverse(result.begin(), result.end()); return result; } } // namespace kstd -- 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/include/kernel/devices/block_device.hpp | 5 +++-- kernel/include/kernel/devices/device.hpp | 9 +++++---- 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 +++++++++++++ 7 files changed, 31 insertions(+), 25 deletions(-) diff --git a/kernel/include/kernel/devices/block_device.hpp b/kernel/include/kernel/devices/block_device.hpp index fb7d104..e2026dd 100644 --- a/kernel/include/kernel/devices/block_device.hpp +++ b/kernel/include/kernel/devices/block_device.hpp @@ -3,8 +3,9 @@ #include "kernel/devices/device.hpp" +#include + #include -#include namespace devices { @@ -20,7 +21,7 @@ namespace devices * @param name Device name. * @param block_size Size of one logical block in bytes. */ - block_device(size_t major, size_t minor, std::string_view name, size_t block_size); + block_device(size_t major, size_t minor, kstd::string const & name, size_t block_size); /** * @brief Read data from the block at @p block_index into @p buffer. diff --git a/kernel/include/kernel/devices/device.hpp b/kernel/include/kernel/devices/device.hpp index d6f520f..66cb7f8 100644 --- a/kernel/include/kernel/devices/device.hpp +++ b/kernel/include/kernel/devices/device.hpp @@ -1,8 +1,9 @@ #ifndef TEACH_OS_KERNEL_DEVICES_DEVICE_HPP #define TEACH_OS_KERNEL_DEVICES_DEVICE_HPP +#include + #include -#include namespace devices { @@ -17,7 +18,7 @@ namespace devices * @param minor Device minor number. * @param name Device name. */ - device(size_t major, size_t minor, std::string_view name); + device(size_t major, size_t minor, kstd::string const & name); /** * @brief Virtual destructor for device. @@ -40,7 +41,7 @@ namespace devices * @brief Returns the name of the device. * @return Device name. */ - [[nodiscard]] auto name() const -> std::string_view; + [[nodiscard]] auto name() const -> kstd::string const &; /** * @brief Check if the device is a block device. @@ -54,7 +55,7 @@ namespace devices private: size_t m_major; size_t m_minor; - std::string_view m_name; + kstd::string m_name; }; } // namespace devices 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(-) 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 840c7fec926e7fa8a9d9b64b23167f269096b59b Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Sun, 22 Mar 2026 15:08:42 +0100 Subject: Remove unneeded enable_shared_from_this in inode --- kernel/include/kernel/filesystem/inode.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/kernel/include/kernel/filesystem/inode.hpp b/kernel/include/kernel/filesystem/inode.hpp index 94ccd89..6d8f0d4 100644 --- a/kernel/include/kernel/filesystem/inode.hpp +++ b/kernel/include/kernel/filesystem/inode.hpp @@ -1,13 +1,11 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_INODE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_INODE_HPP -#include - #include namespace filesystem { - struct inode : kstd::enable_shared_from_this + struct inode { enum class inode_kind { -- 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/CMakeLists.txt | 2 +- kernel/include/kernel/filesystem/custody.hpp | 23 --------------------- kernel/include/kernel/filesystem/dentry.hpp | 25 +++++++++++++++++++++++ kernel/include/kernel/filesystem/vfs.hpp | 6 +++--- kernel/src/filesystem/custody.cpp | 30 ---------------------------- kernel/src/filesystem/dentry.cpp | 30 ++++++++++++++++++++++++++++ kernel/src/filesystem/vfs.cpp | 16 +++++++-------- 7 files changed, 67 insertions(+), 65 deletions(-) delete mode 100644 kernel/include/kernel/filesystem/custody.hpp create mode 100644 kernel/include/kernel/filesystem/dentry.hpp delete mode 100644 kernel/src/filesystem/custody.cpp create mode 100644 kernel/src/filesystem/dentry.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 16ebb8b..01fee74 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -24,7 +24,7 @@ add_executable("kernel" "src/filesystem/ext2/ext2_file.cpp" "src/filesystem/ext2/ext2_filesystem.cpp" "src/filesystem/ext2/ext2_inode.cpp" - "src/filesystem/custody.cpp" + "src/filesystem/dentry.cpp" "src/filesystem/device_inode.cpp" "src/filesystem/file_descriptor_table.cpp" "src/filesystem/filesystem.cpp" diff --git a/kernel/include/kernel/filesystem/custody.hpp b/kernel/include/kernel/filesystem/custody.hpp deleted file mode 100644 index 8a0e09a..0000000 --- a/kernel/include/kernel/filesystem/custody.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef TEACH_OS_KERNEL_CUSTODY_HPP -#define TEACH_OS_KERNEL_CUSTODY_HPP - -#include "kernel/filesystem/inode.hpp" - -#include - -namespace filesystem -{ - struct custody - { - custody(kstd::shared_ptr const & parent, kstd::shared_ptr const & node); - - [[nodiscard]] auto get_inode() const -> kstd::shared_ptr const &; - [[nodiscard]] auto get_parent() const -> kstd::shared_ptr const &; - - private: - kstd::shared_ptr m_parent; - kstd::shared_ptr m_inode; - }; -} // namespace filesystem - -#endif \ No newline at end of file diff --git a/kernel/include/kernel/filesystem/dentry.hpp b/kernel/include/kernel/filesystem/dentry.hpp new file mode 100644 index 0000000..1532880 --- /dev/null +++ b/kernel/include/kernel/filesystem/dentry.hpp @@ -0,0 +1,25 @@ +#ifndef TEACH_OS_KERNEL_DENTRY_HPP +#define TEACH_OS_KERNEL_DENTRY_HPP + +#include "kernel/filesystem/inode.hpp" + +#include +#include + +namespace filesystem +{ + struct dentry + { + dentry(kstd::shared_ptr const & parent, kstd::shared_ptr const & node); + + [[nodiscard]] auto get_inode() const -> kstd::shared_ptr const &; + [[nodiscard]] auto get_parent() const -> kstd::shared_ptr const &; + + private: + kstd::shared_ptr m_parent; + kstd::vector> m_children; + kstd::shared_ptr m_inode; + }; +} // namespace filesystem + +#endif \ No newline at end of file diff --git a/kernel/include/kernel/filesystem/vfs.hpp b/kernel/include/kernel/filesystem/vfs.hpp index ca51d90..bcf06f7 100644 --- a/kernel/include/kernel/filesystem/vfs.hpp +++ b/kernel/include/kernel/filesystem/vfs.hpp @@ -2,7 +2,7 @@ #define TEACH_OS_KERNEL_FILESYSTEM_VFS_HPP #include "kernel/devices/device.hpp" -#include "kernel/filesystem/custody.hpp" +#include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" #include "kernel/filesystem/mount.hpp" @@ -37,11 +37,11 @@ namespace filesystem vfs() = default; auto make_device_node(kstd::shared_ptr const & device) -> void; - [[nodiscard]] auto resolve_path(std::string_view path) -> std::optional; + [[nodiscard]] auto resolve_path(std::string_view path) -> std::optional; kstd::shared_ptr m_root_fs; std::optional m_root_mount; - kstd::vector m_mounts; + kstd::vector m_mount_table; }; } // namespace filesystem 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/include/kernel/filesystem/dentry.hpp | 14 ++++++++++++++ kernel/include/kernel/filesystem/vfs.hpp | 2 +- kernel/src/filesystem/dentry.cpp | 17 +++++++++++++++++ kernel/src/filesystem/vfs.cpp | 21 +++++++++++---------- 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/kernel/include/kernel/filesystem/dentry.hpp b/kernel/include/kernel/filesystem/dentry.hpp index 1532880..db15b48 100644 --- a/kernel/include/kernel/filesystem/dentry.hpp +++ b/kernel/include/kernel/filesystem/dentry.hpp @@ -4,21 +4,35 @@ #include "kernel/filesystem/inode.hpp" #include +#include #include +#include + namespace filesystem { struct dentry { + enum class dentry_flags : uint32_t + { + dcache_mounted = 1 << 15 + }; + dentry(kstd::shared_ptr const & parent, kstd::shared_ptr const & node); [[nodiscard]] auto get_inode() const -> kstd::shared_ptr const &; [[nodiscard]] auto get_parent() const -> kstd::shared_ptr const &; + auto set_flag(dentry_flags flag) -> void; + auto unset_flag(dentry_flags flag) -> void; + [[nodiscard]] auto has_flag(dentry_flags flag) const -> bool; + private: + kstd::string m_name; kstd::shared_ptr m_parent; kstd::vector> m_children; kstd::shared_ptr m_inode; + uint32_t m_flags{0}; }; } // namespace filesystem diff --git a/kernel/include/kernel/filesystem/vfs.hpp b/kernel/include/kernel/filesystem/vfs.hpp index bcf06f7..01cd2ea 100644 --- a/kernel/include/kernel/filesystem/vfs.hpp +++ b/kernel/include/kernel/filesystem/vfs.hpp @@ -40,7 +40,7 @@ namespace filesystem [[nodiscard]] auto resolve_path(std::string_view path) -> std::optional; kstd::shared_ptr m_root_fs; - std::optional m_root_mount; + kstd::shared_ptr m_root_dentry; kstd::vector m_mount_table; }; } // namespace filesystem 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/include/kernel/filesystem/ext2/ext2_filesystem.hpp | 1 - kernel/include/kernel/filesystem/filesystem.hpp | 5 ++++- kernel/src/filesystem/ext2/ext2_filesystem.cpp | 8 ++------ kernel/src/filesystem/filesystem.cpp | 11 +++++++++++ 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/kernel/include/kernel/filesystem/ext2/ext2_filesystem.hpp b/kernel/include/kernel/filesystem/ext2/ext2_filesystem.hpp index d6f69c8..92e05c8 100644 --- a/kernel/include/kernel/filesystem/ext2/ext2_filesystem.hpp +++ b/kernel/include/kernel/filesystem/ext2/ext2_filesystem.hpp @@ -17,7 +17,6 @@ namespace filesystem::ext2 auto lookup(inode const & parent, std::string_view name) -> inode * override; private: - kstd::shared_ptr m_device{}; }; } // namespace filesystem::ext2 diff --git a/kernel/include/kernel/filesystem/filesystem.hpp b/kernel/include/kernel/filesystem/filesystem.hpp index 035f49d..733c51a 100644 --- a/kernel/include/kernel/filesystem/filesystem.hpp +++ b/kernel/include/kernel/filesystem/filesystem.hpp @@ -5,6 +5,7 @@ #include "kernel/filesystem/inode.hpp" #include +#include #include @@ -14,13 +15,15 @@ namespace filesystem { virtual ~filesystem() = default; - virtual auto mount(kstd::shared_ptr const & device) -> int = 0; + virtual auto mount(kstd::shared_ptr const & device) -> int; virtual auto lookup(inode const & parent, std::string_view name) -> inode * = 0; [[nodiscard]] auto root_inode() const -> kstd::shared_ptr const &; protected: kstd::shared_ptr m_root_inode{}; + kstd::shared_ptr m_device{}; + kstd::vector> m_inodes{}; }; } // namespace filesystem 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/include/kernel/filesystem/ext2/ext2_filesystem.hpp | 2 +- kernel/include/kernel/filesystem/filesystem.hpp | 2 +- kernel/src/filesystem/ext2/ext2_filesystem.cpp | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/include/kernel/filesystem/ext2/ext2_filesystem.hpp b/kernel/include/kernel/filesystem/ext2/ext2_filesystem.hpp index 92e05c8..1445e5a 100644 --- a/kernel/include/kernel/filesystem/ext2/ext2_filesystem.hpp +++ b/kernel/include/kernel/filesystem/ext2/ext2_filesystem.hpp @@ -14,7 +14,7 @@ namespace filesystem::ext2 struct ext2_filesystem : filesystem { auto mount(kstd::shared_ptr const & device) -> int override; - auto lookup(inode const & parent, std::string_view name) -> inode * override; + auto lookup(kstd::shared_ptr const & parent, std::string_view name) -> kstd::shared_ptr override; private: }; diff --git a/kernel/include/kernel/filesystem/filesystem.hpp b/kernel/include/kernel/filesystem/filesystem.hpp index 733c51a..e069ced 100644 --- a/kernel/include/kernel/filesystem/filesystem.hpp +++ b/kernel/include/kernel/filesystem/filesystem.hpp @@ -16,7 +16,7 @@ namespace filesystem virtual ~filesystem() = default; virtual auto mount(kstd::shared_ptr const & device) -> int; - virtual auto lookup(inode const & parent, std::string_view name) -> inode * = 0; + 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/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/include/kernel/filesystem/vfs.hpp | 2 ++ kernel/src/filesystem/vfs.cpp | 15 +++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/kernel/include/kernel/filesystem/vfs.hpp b/kernel/include/kernel/filesystem/vfs.hpp index 01cd2ea..b6d4c4c 100644 --- a/kernel/include/kernel/filesystem/vfs.hpp +++ b/kernel/include/kernel/filesystem/vfs.hpp @@ -36,6 +36,8 @@ namespace filesystem kstd::vector> m_device_nodes; // TODO BA-FS26 remove again, use devtempfs vfs() = default; + auto init_internal() -> void; + auto make_device_node(kstd::shared_ptr const & device) -> void; [[nodiscard]] auto resolve_path(std::string_view path) -> std::optional; 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 336b25458b75e28c93c0bab23ccd359042f9df41 Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Mon, 23 Mar 2026 21:40:34 +0100 Subject: Implement == and != operators for string and string_view --- libs/kstd/include/kstd/string | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/libs/kstd/include/kstd/string b/libs/kstd/include/kstd/string index f9583d5..075422e 100644 --- a/libs/kstd/include/kstd/string +++ b/libs/kstd/include/kstd/string @@ -312,6 +312,37 @@ namespace kstd std::reverse(result.begin(), result.end()); return result; } + + [[nodiscard]] constexpr auto inline operator==(string const & lhs, string const & rhs) -> bool + { + return lhs.view() == rhs.view(); + } + + [[nodiscard]] constexpr auto inline operator!=(string const & lhs, string const & rhs) -> bool + { + return !(lhs == rhs); + } + + [[nodiscard]] constexpr auto inline operator==(string const & lhs, std::string_view rhs) -> bool + { + return lhs.view() == rhs; + } + + [[nodiscard]] constexpr auto inline operator!=(string const & lhs, std::string_view rhs) -> bool + { + return !(lhs == rhs); + } + + [[nodiscard]] constexpr auto inline operator==(std::string_view lhs, string const & rhs) -> bool + { + return lhs == rhs.view(); + } + + [[nodiscard]] constexpr auto inline operator!=(std::string_view lhs, string const & rhs) -> bool + { + return !(lhs == rhs); + } + } // namespace kstd #endif \ No newline at end of file -- 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/include/kernel/filesystem/dentry.hpp | 6 ++- .../kernel/filesystem/open_file_description.hpp | 2 +- kernel/include/kernel/filesystem/vfs.hpp | 2 +- kernel/src/filesystem/dentry.cpp | 18 ++++++++- kernel/src/filesystem/vfs.cpp | 46 +++++++++++++++++++--- 5 files changed, 64 insertions(+), 10 deletions(-) diff --git a/kernel/include/kernel/filesystem/dentry.hpp b/kernel/include/kernel/filesystem/dentry.hpp index db15b48..ca7ca95 100644 --- a/kernel/include/kernel/filesystem/dentry.hpp +++ b/kernel/include/kernel/filesystem/dentry.hpp @@ -8,6 +8,7 @@ #include #include +#include namespace filesystem { @@ -18,11 +19,14 @@ namespace filesystem dcache_mounted = 1 << 15 }; - dentry(kstd::shared_ptr const & parent, kstd::shared_ptr const & node); + dentry(kstd::shared_ptr const & parent, kstd::shared_ptr const & node, std::string_view name = {}); [[nodiscard]] auto get_inode() const -> kstd::shared_ptr const &; [[nodiscard]] auto get_parent() const -> kstd::shared_ptr const &; + auto add_child(kstd::shared_ptr const & child) -> void; + [[nodiscard]] auto find_child(std::string_view name) const -> kstd::shared_ptr; + auto set_flag(dentry_flags flag) -> void; auto unset_flag(dentry_flags flag) -> void; [[nodiscard]] auto has_flag(dentry_flags flag) const -> bool; diff --git a/kernel/include/kernel/filesystem/open_file_description.hpp b/kernel/include/kernel/filesystem/open_file_description.hpp index 3c97d50..e17f9fe 100644 --- a/kernel/include/kernel/filesystem/open_file_description.hpp +++ b/kernel/include/kernel/filesystem/open_file_description.hpp @@ -11,7 +11,7 @@ namespace filesystem { struct open_file_description { - open_file_description(kstd::shared_ptr const & inode); + explicit open_file_description(kstd::shared_ptr const & inode); ~open_file_description() = default; diff --git a/kernel/include/kernel/filesystem/vfs.hpp b/kernel/include/kernel/filesystem/vfs.hpp index b6d4c4c..317f2d1 100644 --- a/kernel/include/kernel/filesystem/vfs.hpp +++ b/kernel/include/kernel/filesystem/vfs.hpp @@ -39,7 +39,7 @@ namespace filesystem auto init_internal() -> void; auto make_device_node(kstd::shared_ptr const & device) -> void; - [[nodiscard]] auto resolve_path(std::string_view path) -> std::optional; + [[nodiscard]] auto resolve_path(std::string_view path) -> kstd::shared_ptr; kstd::shared_ptr m_root_fs; kstd::shared_ptr m_root_dentry; 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(-) 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/CMakeLists.txt | 1 + kernel/include/kernel/filesystem/mount_table.hpp | 23 +++++++++++++++++++ kernel/src/filesystem/mount_table.cpp | 29 ++++++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 kernel/include/kernel/filesystem/mount_table.hpp create mode 100644 kernel/src/filesystem/mount_table.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 01fee74..ee1f585 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -29,6 +29,7 @@ add_executable("kernel" "src/filesystem/file_descriptor_table.cpp" "src/filesystem/filesystem.cpp" "src/filesystem/inode.cpp" + "src/filesystem/mount_table.cpp" "src/filesystem/mount.cpp" "src/filesystem/open_file_description.cpp" "src/filesystem/vfs.cpp" diff --git a/kernel/include/kernel/filesystem/mount_table.hpp b/kernel/include/kernel/filesystem/mount_table.hpp new file mode 100644 index 0000000..14d6d08 --- /dev/null +++ b/kernel/include/kernel/filesystem/mount_table.hpp @@ -0,0 +1,23 @@ +#ifndef TEACH_OS_KERNEL_FILESYSTEM_MOUNT_TABLE_HPP +#define TEACH_OS_KERNEL_FILESYSTEM_MOUNT_TABLE_HPP + +#include "kernel/filesystem/dentry.hpp" +#include "kernel/filesystem/mount.hpp" + +#include +#include + +namespace filesystem +{ + struct mount_table + { + public: + void add_mount(kstd::shared_ptr); + auto find_mount_by_dentry(kstd::shared_ptr const & dentry) -> kstd::shared_ptr; + + private: + kstd::vector> m_mounts; + }; +} // namespace filesystem + +#endif 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 6110774495a10d1dd8766f8fa8597fb3bdc4aabd Mon Sep 17 00:00:00 2001 From: "marcel.braun" Date: Tue, 24 Mar 2026 16:51:28 +0100 Subject: Fix dentry header guards --- kernel/include/kernel/filesystem/dentry.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/include/kernel/filesystem/dentry.hpp b/kernel/include/kernel/filesystem/dentry.hpp index ca7ca95..c28246f 100644 --- a/kernel/include/kernel/filesystem/dentry.hpp +++ b/kernel/include/kernel/filesystem/dentry.hpp @@ -1,5 +1,5 @@ -#ifndef TEACH_OS_KERNEL_DENTRY_HPP -#define TEACH_OS_KERNEL_DENTRY_HPP +#ifndef TEACH_OS_KERNEL_FILESYSTEM_DENTRY_HPP +#define TEACH_OS_KERNEL_FILESYSTEM_DENTRY_HPP #include "kernel/filesystem/inode.hpp" -- 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/include/kernel/filesystem/mount.hpp | 9 ++++----- kernel/src/filesystem/mount.cpp | 9 +++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/kernel/include/kernel/filesystem/mount.hpp b/kernel/include/kernel/filesystem/mount.hpp index 232a9be..dd47ce7 100644 --- a/kernel/include/kernel/filesystem/mount.hpp +++ b/kernel/include/kernel/filesystem/mount.hpp @@ -1,23 +1,22 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_MOUNT_HPP #define TEACH_OS_KERNEL_FILESYSTEM_MOUNT_HPP +#include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/filesystem.hpp" #include -#include - namespace filesystem { struct mount { - mount(std::string_view const & path, kstd::shared_ptr const & fs); + mount(kstd::shared_ptr const & mount_dentry, kstd::shared_ptr const & fs); - [[nodiscard]] auto path() const -> std::string_view; + [[nodiscard]] auto get_dentry() const -> kstd::shared_ptr; [[nodiscard]] auto get_filesystem() const -> kstd::shared_ptr const &; private: - std::string_view m_path; + kstd::shared_ptr m_dentry; kstd::shared_ptr m_filesystem{}; }; } // namespace filesystem 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/include/kernel/filesystem/filesystem.hpp | 5 +++++ kernel/src/filesystem/filesystem.cpp | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/kernel/include/kernel/filesystem/filesystem.hpp b/kernel/include/kernel/filesystem/filesystem.hpp index e069ced..362242f 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 "kernel/devices/device.hpp" +#include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/inode.hpp" #include @@ -19,11 +20,15 @@ namespace 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 root_dentry() const -> kstd::shared_ptr const &; + + auto set_root_dentry(kstd::shared_ptr dentry) -> void; protected: kstd::shared_ptr m_root_inode{}; kstd::shared_ptr m_device{}; kstd::vector> m_inodes{}; + kstd::shared_ptr m_root_dentry; }; } // namespace filesystem 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/include/kernel/filesystem/vfs.hpp | 3 +- kernel/src/filesystem/vfs.cpp | 53 ++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/kernel/include/kernel/filesystem/vfs.hpp b/kernel/include/kernel/filesystem/vfs.hpp index 317f2d1..55bf6a4 100644 --- a/kernel/include/kernel/filesystem/vfs.hpp +++ b/kernel/include/kernel/filesystem/vfs.hpp @@ -6,6 +6,7 @@ #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" #include "kernel/filesystem/mount.hpp" +#include "kernel/filesystem/mount_table.hpp" #include "kernel/filesystem/open_file_description.hpp" #include @@ -43,7 +44,7 @@ namespace filesystem kstd::shared_ptr m_root_fs; kstd::shared_ptr m_root_dentry; - kstd::vector m_mount_table; + mount_table m_mount_table; }; } // namespace filesystem 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(-) 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 +-- libs/kstd/include/kstd/bits/shared_ptr.hpp | 29 ++++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) 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; diff --git a/libs/kstd/include/kstd/bits/shared_ptr.hpp b/libs/kstd/include/kstd/bits/shared_ptr.hpp index 674807d..8930095 100644 --- a/libs/kstd/include/kstd/bits/shared_ptr.hpp +++ b/libs/kstd/include/kstd/bits/shared_ptr.hpp @@ -546,11 +546,6 @@ namespace kstd return ptr.pointer == nullptr; } - /** - * @brief Defaulted three-way comparator operator. - */ - [[nodiscard]] auto operator<=>(shared_ptr const & other) const = default; - private: /** * @brief If the candidate type inherits from enable_shared_from_this, assigns the internal weak pointer to this @@ -624,6 +619,30 @@ namespace kstd { return shared_ptr(new T(std::forward(args)...)); } + + /** + * @brief Equality operator for shared_ptr. Two shared_ptr instances are equal if they point to the same object + * @tparam T, U Types of the managed objects of the shared_ptr instances being compared. + * @param lhs, rhs The shared_ptr instances to compare. + * @return true if lhs and rhs point to the same object, false otherwise. + */ + template + [[nodiscard]] auto inline operator==(shared_ptr const & lhs, shared_ptr const & rhs) -> bool + { + return lhs.get() == rhs.get(); + } + + /** + * @brief Three-way comparison operator for shared_ptr. Compares the stored pointers of lhs and rhs using operator<=>. + * @tparam T, U Types of the managed objects of the shared_ptr instances being compared. + * @param lhs, rhs The shared_ptr instances to compare. + * @return The result of comparing the stored pointers of lhs and rhs using operator<=> + */ + template + [[nodiscard]] auto inline operator<=>(shared_ptr const & lhs, shared_ptr const & rhs) + { + return lhs.get() <=> rhs.get(); + } } // namespace kstd #endif \ No newline at end of file -- 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/include/kernel/filesystem/mount_table.hpp | 2 + kernel/include/kernel/filesystem/vfs.hpp | 3 -- kernel/src/filesystem/mount_table.cpp | 7 ++++ kernel/src/filesystem/vfs.cpp | 53 ++++++++++++++---------- kernel/src/main.cpp | 1 - 5 files changed, 40 insertions(+), 26 deletions(-) diff --git a/kernel/include/kernel/filesystem/mount_table.hpp b/kernel/include/kernel/filesystem/mount_table.hpp index 14d6d08..cf523c1 100644 --- a/kernel/include/kernel/filesystem/mount_table.hpp +++ b/kernel/include/kernel/filesystem/mount_table.hpp @@ -13,6 +13,8 @@ namespace filesystem { public: void add_mount(kstd::shared_ptr); + + [[nodiscard]] auto get_root_mount() const -> kstd::shared_ptr; auto find_mount_by_dentry(kstd::shared_ptr const & dentry) -> kstd::shared_ptr; private: diff --git a/kernel/include/kernel/filesystem/vfs.hpp b/kernel/include/kernel/filesystem/vfs.hpp index 55bf6a4..cf268a3 100644 --- a/kernel/include/kernel/filesystem/vfs.hpp +++ b/kernel/include/kernel/filesystem/vfs.hpp @@ -5,7 +5,6 @@ #include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" -#include "kernel/filesystem/mount.hpp" #include "kernel/filesystem/mount_table.hpp" #include "kernel/filesystem/open_file_description.hpp" @@ -42,8 +41,6 @@ namespace filesystem auto make_device_node(kstd::shared_ptr const & device) -> void; [[nodiscard]] auto resolve_path(std::string_view path) -> kstd::shared_ptr; - kstd::shared_ptr m_root_fs; - kstd::shared_ptr m_root_dentry; mount_table m_mount_table; }; } // namespace filesystem 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/CMakeLists.txt | 2 + kernel/include/kernel/filesystem/filesystem.hpp | 5 --- kernel/include/kernel/filesystem/mount.hpp | 10 +++-- .../kernel/filesystem/rootfs/rootfs_filesystem.hpp | 21 +++++++++++ .../kernel/filesystem/rootfs/rootfs_inode.hpp | 19 ++++++++++ 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 +++++ 12 files changed, 149 insertions(+), 47 deletions(-) create mode 100644 kernel/include/kernel/filesystem/rootfs/rootfs_filesystem.hpp create mode 100644 kernel/include/kernel/filesystem/rootfs/rootfs_inode.hpp create mode 100644 kernel/src/filesystem/rootfs/rootfs_filesystem.cpp create mode 100644 kernel/src/filesystem/rootfs/rootfs_inode.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index ee1f585..406ac54 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -32,6 +32,8 @@ add_executable("kernel" "src/filesystem/mount_table.cpp" "src/filesystem/mount.cpp" "src/filesystem/open_file_description.cpp" + "src/filesystem/rootfs/rootfs_filesystem.cpp" + "src/filesystem/rootfs/rootfs_inode.cpp" "src/filesystem/vfs.cpp" ) diff --git a/kernel/include/kernel/filesystem/filesystem.hpp b/kernel/include/kernel/filesystem/filesystem.hpp index 362242f..e069ced 100644 --- a/kernel/include/kernel/filesystem/filesystem.hpp +++ b/kernel/include/kernel/filesystem/filesystem.hpp @@ -2,7 +2,6 @@ #define TEACH_OS_KERNEL_FILESYSTEM_FILESYSTEM_HPP #include "kernel/devices/device.hpp" -#include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/inode.hpp" #include @@ -20,15 +19,11 @@ namespace 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 root_dentry() const -> kstd::shared_ptr const &; - - auto set_root_dentry(kstd::shared_ptr dentry) -> void; protected: kstd::shared_ptr m_root_inode{}; kstd::shared_ptr m_device{}; kstd::vector> m_inodes{}; - kstd::shared_ptr m_root_dentry; }; } // namespace filesystem diff --git a/kernel/include/kernel/filesystem/mount.hpp b/kernel/include/kernel/filesystem/mount.hpp index dd47ce7..0cd30b4 100644 --- a/kernel/include/kernel/filesystem/mount.hpp +++ b/kernel/include/kernel/filesystem/mount.hpp @@ -10,13 +10,17 @@ namespace filesystem { struct mount { - mount(kstd::shared_ptr const & mount_dentry, kstd::shared_ptr const & fs); + mount(kstd::shared_ptr const & mount_dentry, kstd::shared_ptr const & root_dentry, + kstd::shared_ptr const & fs); + + [[nodiscard]] auto get_mount_dentry() const -> kstd::shared_ptr; + [[nodiscard]] auto root_dentry() const -> kstd::shared_ptr const &; - [[nodiscard]] auto get_dentry() const -> kstd::shared_ptr; [[nodiscard]] auto get_filesystem() const -> kstd::shared_ptr const &; private: - kstd::shared_ptr m_dentry; + kstd::shared_ptr m_mount_dentry; + kstd::shared_ptr m_root_dentry; kstd::shared_ptr m_filesystem{}; }; } // namespace filesystem diff --git a/kernel/include/kernel/filesystem/rootfs/rootfs_filesystem.hpp b/kernel/include/kernel/filesystem/rootfs/rootfs_filesystem.hpp new file mode 100644 index 0000000..949ac83 --- /dev/null +++ b/kernel/include/kernel/filesystem/rootfs/rootfs_filesystem.hpp @@ -0,0 +1,21 @@ +#ifndef TEACH_OS_KERNEL_FILESYSTEM_ROOTFS_ROOTFS_FILESYSTEM_HPP +#define TEACH_OS_KERNEL_FILESYSTEM_ROOTFS_ROOTFS_FILESYSTEM_HPP + +#include "kernel/devices/device.hpp" +#include "kernel/filesystem/filesystem.hpp" +#include "kernel/filesystem/inode.hpp" + +#include + +#include + +namespace filesystem::rootfs +{ + struct rootfs_filesystem : filesystem + { + auto mount(kstd::shared_ptr const & device) -> int override; + auto lookup(kstd::shared_ptr const & parent, std::string_view name) -> kstd::shared_ptr override; + }; +} // namespace filesystem::rootfs + +#endif diff --git a/kernel/include/kernel/filesystem/rootfs/rootfs_inode.hpp b/kernel/include/kernel/filesystem/rootfs/rootfs_inode.hpp new file mode 100644 index 0000000..d533e8e --- /dev/null +++ b/kernel/include/kernel/filesystem/rootfs/rootfs_inode.hpp @@ -0,0 +1,19 @@ +#ifndef TEACH_OS_KERNEL_FILESYSTEM_ROOTFS_ROOTFS_INODE_HPP +#define TEACH_OS_KERNEL_FILESYSTEM_ROOTFS_ROOTFS_INODE_HPP + +#include "kernel/filesystem/inode.hpp" + +#include + +namespace filesystem::rootfs +{ + struct rootfs_inode : inode + { + rootfs_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; + }; +} // namespace filesystem::rootfs + +#endif 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(-) 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/CMakeLists.txt | 2 + .../kernel/filesystem/devfs/devfs_filesystem.hpp | 25 ++++++++++ .../kernel/filesystem/devfs/devfs_root_inode.hpp | 19 ++++++++ kernel/include/kernel/filesystem/device_inode.hpp | 2 + kernel/include/kernel/filesystem/vfs.hpp | 13 ----- 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 ++++++------------- 9 files changed, 146 insertions(+), 49 deletions(-) create mode 100644 kernel/include/kernel/filesystem/devfs/devfs_filesystem.hpp create mode 100644 kernel/include/kernel/filesystem/devfs/devfs_root_inode.hpp create mode 100644 kernel/src/filesystem/devfs/devfs_filesystem.cpp create mode 100644 kernel/src/filesystem/devfs/devfs_root_inode.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 406ac54..eb762ac 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -21,6 +21,8 @@ add_executable("kernel" "src/devices/storage/storage_management.cpp" "src/devices/storage/ram_disk/ram_disk_controller.cpp" "src/devices/storage/ram_disk/ram_disk_device.cpp" + "src/filesystem/devfs/devfs_filesystem.cpp" + "src/filesystem/devfs/devfs_root_inode.cpp" "src/filesystem/ext2/ext2_file.cpp" "src/filesystem/ext2/ext2_filesystem.cpp" "src/filesystem/ext2/ext2_inode.cpp" diff --git a/kernel/include/kernel/filesystem/devfs/devfs_filesystem.hpp b/kernel/include/kernel/filesystem/devfs/devfs_filesystem.hpp new file mode 100644 index 0000000..5559c2a --- /dev/null +++ b/kernel/include/kernel/filesystem/devfs/devfs_filesystem.hpp @@ -0,0 +1,25 @@ +#ifndef TEACH_OS_KERNEL_FILESYSTEM_DEVFS_DEVFS_FILESYSTEM_HPP +#define TEACH_OS_KERNEL_FILESYSTEM_DEVFS_DEVFS_FILESYSTEM_HPP + +#include "kernel/devices/device.hpp" +#include "kernel/filesystem/filesystem.hpp" +#include "kernel/filesystem/inode.hpp" + +#include +#include + +#include + +namespace filesystem::devfs +{ + struct devfs_filesystem : filesystem + { + auto mount(kstd::shared_ptr const & device) -> int override; + auto lookup(kstd::shared_ptr const & parent, std::string_view name) -> kstd::shared_ptr override; + + private: + auto build_device_inode_table() -> void; + }; +} // namespace filesystem::devfs + +#endif \ No newline at end of file diff --git a/kernel/include/kernel/filesystem/devfs/devfs_root_inode.hpp b/kernel/include/kernel/filesystem/devfs/devfs_root_inode.hpp new file mode 100644 index 0000000..b1d37ab --- /dev/null +++ b/kernel/include/kernel/filesystem/devfs/devfs_root_inode.hpp @@ -0,0 +1,19 @@ +#ifndef TEACH_OS_KERNEL_FILESYSTEM_DEVFS_DEVFS_ROOT_INODE_HPP +#define TEACH_OS_KERNEL_FILESYSTEM_DEVFS_DEVFS_ROOT_INODE_HPP + +#include "kernel/filesystem/inode.hpp" + +#include + +namespace filesystem::devfs +{ + struct devfs_root_inode : inode + { + devfs_root_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; + }; +} // namespace filesystem::devfs + +#endif \ No newline at end of file diff --git a/kernel/include/kernel/filesystem/device_inode.hpp b/kernel/include/kernel/filesystem/device_inode.hpp index ce0f91c..1cf08d4 100644 --- a/kernel/include/kernel/filesystem/device_inode.hpp +++ b/kernel/include/kernel/filesystem/device_inode.hpp @@ -18,6 +18,8 @@ namespace filesystem 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; + [[nodiscard]] auto device() const -> kstd::shared_ptr const &; + private: 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); diff --git a/kernel/include/kernel/filesystem/vfs.hpp b/kernel/include/kernel/filesystem/vfs.hpp index cf268a3..f301b7a 100644 --- a/kernel/include/kernel/filesystem/vfs.hpp +++ b/kernel/include/kernel/filesystem/vfs.hpp @@ -1,17 +1,13 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_VFS_HPP #define TEACH_OS_KERNEL_FILESYSTEM_VFS_HPP -#include "kernel/devices/device.hpp" #include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/filesystem.hpp" -#include "kernel/filesystem/inode.hpp" #include "kernel/filesystem/mount_table.hpp" #include "kernel/filesystem/open_file_description.hpp" #include -#include -#include #include namespace filesystem @@ -27,18 +23,9 @@ namespace filesystem auto do_mount(std::string_view path, kstd::shared_ptr const & filesystem) -> int; private: - // TODO BA-FS26 remove again and use devtempfs - struct device_node_entry - { - std::string_view name; - kstd::shared_ptr node; - }; - kstd::vector> m_device_nodes; // TODO BA-FS26 remove again, use devtempfs - vfs() = default; auto init_internal() -> void; - auto make_device_node(kstd::shared_ptr const & device) -> void; [[nodiscard]] auto resolve_path(std::string_view path) -> kstd::shared_ptr; mount_table m_mount_table; 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/filesystem/rootfs/rootfs_filesystem.hpp | 4 ++++ .../include/kernel/filesystem/rootfs/rootfs_inode.hpp | 12 ++++++++++++ kernel/src/filesystem/rootfs/rootfs_filesystem.cpp | 9 +++++++-- kernel/src/filesystem/rootfs/rootfs_inode.cpp | 17 +++++++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/kernel/include/kernel/filesystem/rootfs/rootfs_filesystem.hpp b/kernel/include/kernel/filesystem/rootfs/rootfs_filesystem.hpp index 949ac83..cb07111 100644 --- a/kernel/include/kernel/filesystem/rootfs/rootfs_filesystem.hpp +++ b/kernel/include/kernel/filesystem/rootfs/rootfs_filesystem.hpp @@ -4,10 +4,14 @@ #include "kernel/devices/device.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" +#include "kernel/filesystem/rootfs/rootfs_inode.hpp" #include +#include +#include #include +#include namespace filesystem::rootfs { diff --git a/kernel/include/kernel/filesystem/rootfs/rootfs_inode.hpp b/kernel/include/kernel/filesystem/rootfs/rootfs_inode.hpp index d533e8e..de4fb7c 100644 --- a/kernel/include/kernel/filesystem/rootfs/rootfs_inode.hpp +++ b/kernel/include/kernel/filesystem/rootfs/rootfs_inode.hpp @@ -3,7 +3,13 @@ #include "kernel/filesystem/inode.hpp" +#include +#include +#include + #include +#include +#include namespace filesystem::rootfs { @@ -13,6 +19,12 @@ namespace filesystem::rootfs 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; + + auto add_child(std::string_view name) -> void; + auto lookup_child(std::string_view name) -> kstd::shared_ptr; + + private: + kstd::vector>> m_children; }; } // namespace filesystem::rootfs 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(-) 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(-) 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 610707e896504a33fa82db4905e57a4822d3bb9d Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 27 Mar 2026 19:39:55 +0100 Subject: add string tests --- libs/kstd/CMakeLists.txt | 1 + libs/kstd/tests/src/string.cpp | 390 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 391 insertions(+) create mode 100644 libs/kstd/tests/src/string.cpp diff --git a/libs/kstd/CMakeLists.txt b/libs/kstd/CMakeLists.txt index 06543ab..d4f415f 100644 --- a/libs/kstd/CMakeLists.txt +++ b/libs/kstd/CMakeLists.txt @@ -46,6 +46,7 @@ if(NOT CMAKE_CROSSCOMPILING) add_executable("kstd_tests" "tests/src/vector.cpp" "tests/src/os_panic.cpp" + "tests/src/string.cpp" ) target_include_directories("kstd_tests" PRIVATE diff --git a/libs/kstd/tests/src/string.cpp b/libs/kstd/tests/src/string.cpp new file mode 100644 index 0000000..f7f629d --- /dev/null +++ b/libs/kstd/tests/src/string.cpp @@ -0,0 +1,390 @@ +#include + +#include + +#include +#include +#include + +SCENARIO("String initialization and construction", "[string]") +{ + GIVEN("Nothing") + { + WHEN("constructing an empty string") + { + auto str = kstd::string{}; + + THEN("the size is zero and therefore the string is empty") + { + REQUIRE(str.empty()); + REQUIRE(str.size() == 0); + } + + THEN("the string is empty") + { + REQUIRE(str.view() == std::string_view{}); + } + } + } + + GIVEN("A string view") + { + auto view = std::string_view{"Blub Blub"}; + + WHEN("constructing a string from string_view") + { + auto str = kstd::string{view}; + + THEN("the string is not empty and has the same size as the view") + { + REQUIRE(!str.empty()); + REQUIRE(str.size() == view.size()); + } + + THEN("the string contains the same characters as the view") + { + REQUIRE(str.view() == view); + } + } + } + + GIVEN("A C-style string") + { + auto c_str = "Blub Blub"; + + WHEN("constructing a string from the C-style string") + { + auto str = kstd::string{c_str}; + + THEN("the string is not empty and has the same size as the C-style string") + { + REQUIRE(!str.empty()); + REQUIRE(str.size() == strlen(c_str)); + } + + THEN("the string contains the same characters as the C-style string") + { + REQUIRE(str.view() == c_str); + } + } + } + + GIVEN("A character") + { + auto ch = 'x'; + + WHEN("constructing a string from the character") + { + auto str = kstd::string{ch}; + + THEN("the string is not empty and has size 1") + { + REQUIRE(!str.empty()); + REQUIRE(str.size() == 1); + } + + THEN("the string contains the same character as the given character") + { + REQUIRE(str.view() == std::string_view{&ch, 1}); + } + } + } + + GIVEN("Another string") + { + auto other = kstd::string{"Blub Blub"}; + + WHEN("copy constructing a new string") + { + auto str = kstd::string{other}; + + THEN("the new string contains the same characters as the original") + { + REQUIRE(str.view() == other.view()); + } + } + + auto str = kstd::string{"Blub"}; + + WHEN("copy assigning another string") + { + auto other = kstd::string{"Blub Blub"}; + str = other; + + THEN("the string contains the same characters as the assigned string") + { + REQUIRE(str.view() == other.view()); + } + } + } + + GIVEN("A string") + { + auto str = kstd::string{"Hello"}; + + WHEN("copy assigning a string view") + { + auto view = std::string_view{"Hello, world!"}; + str = view; + + THEN("the string contains the same characters as the assigned view") + { + REQUIRE(str.view() == view); + } + } + } + + GIVEN("A string") + { + auto str = kstd::string{"Hello"}; + + WHEN("copy assigning a C-style string") + { + auto c_str = "Hello, world!"; + str = c_str; + + THEN("the string contains the same characters as the assigned C-style string") + { + REQUIRE(str.view() == c_str); + } + } + } +} + +SCENARIO("String concatenation", "[string]") +{ + GIVEN("Two strings") + { + auto str1 = kstd::string{"Blub"}; + auto str2 = kstd::string{" Blub"}; + + WHEN("appending the second string to the first string") + { + str1.append(str2); + + THEN("the first string contains the characters of both strings concatenated") + { + REQUIRE(str1.view() == "Blub Blub"); + } + + THEN("the size of the first string is the sum of the sizes of both strings") + { + REQUIRE(str1.size() == str2.size() + 4); + } + } + + WHEN("using operator+= to append the second string to the first string") + { + str1 += str2; + + THEN("the first string contains the characters of both strings concatenated") + { + REQUIRE(str1.view() == "Blub Blub"); + } + + THEN("the size of the first string is the sum of the sizes of both strings") + { + REQUIRE(str1.size() == str2.size() + 4); + } + } + + WHEN("using operator+ to concatenate the two strings into a new string") + { + auto str3 = str1 + str2; + + THEN("the new string contains the characters of both strings concatenated") + { + REQUIRE(str3.view() == "Blub Blub"); + } + + THEN("the size of the new string is the sum of the sizes of both strings") + { + REQUIRE(str3.size() == str1.size() + str2.size()); + } + } + } + + GIVEN("A string and a string view") + { + auto str = kstd::string{"Blub"}; + auto view = std::string_view{" Blub"}; + + WHEN("appending the string view to the string") + { + str.append(view); + + THEN("the string contains the characters of both the original string and the appended view concatenated") + { + REQUIRE(str.view() == "Blub Blub"); + } + + THEN("the size of the string is the sum of the sizes of the original string and the appended view") + { + REQUIRE(str.size() == view.size() + 4); + } + } + } + + GIVEN("A string and a character") + { + auto str = kstd::string{"Blub"}; + auto ch = '!'; + + WHEN("appending the character to the string") + { + str.push_back(ch); + + THEN("the string contains the original characters followed by the appended character") + { + REQUIRE(str.view() == "Blub!"); + } + + THEN("the size of the string is one more than the original size") + { + REQUIRE(str.size() == 5); + } + } + + WHEN("using operator+= to append the character to the string") + { + str += ch; + + THEN("the string contains the original characters followed by the appended character") + { + REQUIRE(str.view() == "Blub!"); + } + + THEN("the size of the string is one more than the original size") + { + REQUIRE(str.size() == 5); + } + } + } +} + +SCENARIO("String conversion and comparison", "[string]") +{ + GIVEN("An unsigned integer") + { + auto value1 = 12345u; + auto value2 = 0u; + + WHEN("converting the unsigned integer to a string") + { + auto str1 = kstd::to_string(value1); + auto str2 = kstd::to_string(value2); + + THEN("the string contains the decimal representation of the unsigned integer") + { + REQUIRE(str1.view() == "12345"); + REQUIRE(str2.view() == "0"); + } + } + } + + GIVEN("Two strings with the same characters") + { + auto str1 = kstd::string{"Blub Blub"}; + auto str2 = kstd::string{"Blub Blub"}; + + THEN("the strings are equal") + { + REQUIRE(str1 == str2); + } + + THEN("the strings are not unequal") + { + REQUIRE(!(str1 != str2)); + } + } + + GIVEN("A string and a string view with the same characters") + { + auto str = kstd::string{"Blub Blub"}; + auto view = std::string_view{"Blub Blub"}; + + THEN("the string and the string view are equal") + { + REQUIRE(str == view); + REQUIRE(view == str); + } + + THEN("the string and the string view are not unequal") + { + REQUIRE(!(str != view)); + REQUIRE(!(view != str)); + } + } +} + +SCENARIO("String clearing", "[string]") +{ + GIVEN("A non-empty string") + { + auto str = kstd::string{"Blub Blub"}; + + WHEN("clearing the string") + { + str.clear(); + + THEN("the string is empty and has size zero") + { + REQUIRE(str.empty()); + REQUIRE(str.size() == 0); + } + + THEN("the string contains no characters") + { + REQUIRE(str.view() == std::string_view{}); + } + } + } +} + +SCENARIO("String iteration", "[string]") +{ + GIVEN("A string") + { + auto str = kstd::string{"Blub"}; + + WHEN("iterating over the characters of the string as string_view using a range-based for loop") + { + kstd::string result; + + for (auto ch : str.view()) + { + result.push_back(ch); + } + + THEN("the iterated characters are the same as the characters in the string") + { + REQUIRE(result == str); + } + } + + WHEN("using std::ranges::for_each to iterate over the characters of the string") + { + kstd::string result; + + std::ranges::for_each(str, [&result](auto ch) { result.push_back(ch); }); + + THEN("the iterated characters are the same as the characters in the string") + { + REQUIRE(result == str); + } + } + + WHEN("using front and back to access the first and last characters of the string") + { + THEN("front returns the first character of the string") + { + REQUIRE(str.front() == 'B'); + } + + THEN("back returns the last character of the string") + { + REQUIRE(str.back() == 'b'); + } + } + } +} -- cgit v1.2.3 From feea1b8101bd148a93ebf6f1622dcf78efbbbd6d Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 27 Mar 2026 19:59:39 +0100 Subject: generate visual coverage report --- .gitlab-ci.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 05bba19..a48e4a7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -27,18 +27,26 @@ bht: image: registry.gitlab.ost.ch:45023/teachos/devcontainers/x86-64:15.2.0-4 before_script: - apt update - - apt install -y build-essential cmake ninja-build lcov libcatch2-dev + - apt install -y build-essential cmake ninja-build lcov libcatch2-dev gcovr script: - cmake --preset bht - cmake --build --preset bht-dbg - ctest --preset bht-dbg - lcov --config-file .lcovrc --capture --directory $(pwd) --output-file coverage.info - lcov --config-file .lcovrc --list coverage.info + - genhtml --prefix $(pwd) --output-directory coverage coverage.info + - gcovr --root . --cobertura-pretty --output coverage/cobertura-coverage.xml coverage: '/Total:\|\s*(\d+(\.\d+)?)\%/' artifacts: paths: - coverage.info + - coverage/ expire_in: 24 hours + when: always + reports: + coverage_report: + coverage_format: cobertura + path: coverage/cobertura-coverage.xml license_check: stage: .pre -- cgit v1.2.3 From 2c913506a0e07d88883aa7624ecba17e9a4fd328 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 27 Mar 2026 20:04:17 +0100 Subject: echo public coverage report url --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a48e4a7..1479cf8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -36,6 +36,8 @@ bht: - lcov --config-file .lcovrc --list coverage.info - genhtml --prefix $(pwd) --output-directory coverage coverage.info - gcovr --root . --cobertura-pretty --output coverage/cobertura-coverage.xml + after_script: + - echo "CoverageReport public URL - https://gitlab.ost.ch/teachos/kernel/-/jobs/$CI_JOB_ID/artifacts/browse/coverage/index.html" coverage: '/Total:\|\s*(\d+(\.\d+)?)\%/' artifacts: paths: -- cgit v1.2.3 From b0b7c83fb3798832a4bec5b314af2d1633da0640 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 27 Mar 2026 20:06:37 +0100 Subject: fix url --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1479cf8..b655e60 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -37,7 +37,7 @@ bht: - genhtml --prefix $(pwd) --output-directory coverage coverage.info - gcovr --root . --cobertura-pretty --output coverage/cobertura-coverage.xml after_script: - - echo "CoverageReport public URL - https://gitlab.ost.ch/teachos/kernel/-/jobs/$CI_JOB_ID/artifacts/browse/coverage/index.html" + - echo "CoverageReport public URL - https://gitlab.ost.ch/teachos/kernel/-/jobs/$CI_JOB_ID/artifacts/external_file/coverage/index.html" coverage: '/Total:\|\s*(\d+(\.\d+)?)\%/' artifacts: paths: -- cgit v1.2.3 From c3893d6f31b79719035f383ab489c2d18f01b3a3 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 27 Mar 2026 20:10:24 +0100 Subject: fix url --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b655e60..2231956 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -37,7 +37,7 @@ bht: - genhtml --prefix $(pwd) --output-directory coverage coverage.info - gcovr --root . --cobertura-pretty --output coverage/cobertura-coverage.xml after_script: - - echo "CoverageReport public URL - https://gitlab.ost.ch/teachos/kernel/-/jobs/$CI_JOB_ID/artifacts/external_file/coverage/index.html" + - echo "CoverageReport public URL - https://teachos.pages.ost.ch/-/kernel/-/jobs/$CI_JOB_ID/artifacts/coverage/index.html" coverage: '/Total:\|\s*(\d+(\.\d+)?)\%/' artifacts: paths: -- cgit v1.2.3 From 4f7ae11655807acf68f49637cc9dd01a03af36d5 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Fri, 27 Mar 2026 20:31:48 +0100 Subject: add some more tests --- libs/kstd/tests/src/string.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/libs/kstd/tests/src/string.cpp b/libs/kstd/tests/src/string.cpp index f7f629d..43e9a6b 100644 --- a/libs/kstd/tests/src/string.cpp +++ b/libs/kstd/tests/src/string.cpp @@ -387,4 +387,59 @@ SCENARIO("String iteration", "[string]") } } } + + GIVEN("A const string") + { + auto const str = kstd::string{"Blub"}; + + WHEN("iterating over the characters of the string as string_view using a range-based for loop") + { + kstd::string result; + + for (auto ch : str.view()) + { + result.push_back(ch); + } + + THEN("the iterated characters are the same as the characters in the string") + { + REQUIRE(result == str.view()); + } + } + + WHEN("using front and back to access the first and last characters of the string") + { + THEN("front returns the first character of the string") + { + REQUIRE(str.front() == 'B'); + } + + THEN("back returns the last character of the string") + { + REQUIRE(str.back() == 'b'); + } + } + } + + GIVEN("An empty string") + { + auto str = kstd::string{}; + + WHEN("iterating over the characters of an empty string") + { + kstd::string result; + + for (auto ch : str.view()) + { + result.push_back(ch); + } + + THEN("no characters are iterated and the result is an empty string") + { + REQUIRE(result.empty()); + REQUIRE(result.size() == 0); + REQUIRE(result.view() == std::string_view{}); + } + } + } } -- 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/include/kernel/filesystem/mount.hpp | 7 +- kernel/include/kernel/filesystem/mount_table.hpp | 6 +- .../kernel/filesystem/rootfs/rootfs_filesystem.hpp | 2 - kernel/include/kernel/filesystem/vfs.hpp | 2 + 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 +++++++++------------ 9 files changed, 93 insertions(+), 91 deletions(-) diff --git a/kernel/include/kernel/filesystem/mount.hpp b/kernel/include/kernel/filesystem/mount.hpp index 0cd30b4..0f37687 100644 --- a/kernel/include/kernel/filesystem/mount.hpp +++ b/kernel/include/kernel/filesystem/mount.hpp @@ -5,20 +5,25 @@ #include "kernel/filesystem/filesystem.hpp" #include +#include + +#include namespace filesystem { struct mount { mount(kstd::shared_ptr const & mount_dentry, kstd::shared_ptr const & root_dentry, - kstd::shared_ptr const & fs); + kstd::shared_ptr const & fs, std::string_view mount_path); [[nodiscard]] auto get_mount_dentry() const -> kstd::shared_ptr; [[nodiscard]] auto root_dentry() const -> kstd::shared_ptr const &; [[nodiscard]] auto get_filesystem() const -> kstd::shared_ptr const &; + [[nodiscard]] auto get_mount_path() const -> std::string_view; private: + kstd::string m_mount_path; kstd::shared_ptr m_mount_dentry; kstd::shared_ptr m_root_dentry; kstd::shared_ptr m_filesystem{}; diff --git a/kernel/include/kernel/filesystem/mount_table.hpp b/kernel/include/kernel/filesystem/mount_table.hpp index cf523c1..2cd66ea 100644 --- a/kernel/include/kernel/filesystem/mount_table.hpp +++ b/kernel/include/kernel/filesystem/mount_table.hpp @@ -1,12 +1,13 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_MOUNT_TABLE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_MOUNT_TABLE_HPP -#include "kernel/filesystem/dentry.hpp" #include "kernel/filesystem/mount.hpp" #include #include +#include + namespace filesystem { struct mount_table @@ -14,8 +15,7 @@ namespace filesystem public: void add_mount(kstd::shared_ptr); - [[nodiscard]] auto get_root_mount() const -> kstd::shared_ptr; - auto find_mount_by_dentry(kstd::shared_ptr const & dentry) -> kstd::shared_ptr; + [[nodiscard]] auto find_longest_prefix_mount(std::string_view path) const -> kstd::shared_ptr; private: kstd::vector> m_mounts; diff --git a/kernel/include/kernel/filesystem/rootfs/rootfs_filesystem.hpp b/kernel/include/kernel/filesystem/rootfs/rootfs_filesystem.hpp index cb07111..b3e03a9 100644 --- a/kernel/include/kernel/filesystem/rootfs/rootfs_filesystem.hpp +++ b/kernel/include/kernel/filesystem/rootfs/rootfs_filesystem.hpp @@ -4,14 +4,12 @@ #include "kernel/devices/device.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/inode.hpp" -#include "kernel/filesystem/rootfs/rootfs_inode.hpp" #include #include #include #include -#include namespace filesystem::rootfs { diff --git a/kernel/include/kernel/filesystem/vfs.hpp b/kernel/include/kernel/filesystem/vfs.hpp index f301b7a..9bee104 100644 --- a/kernel/include/kernel/filesystem/vfs.hpp +++ b/kernel/include/kernel/filesystem/vfs.hpp @@ -27,6 +27,8 @@ namespace filesystem auto init_internal() -> void; [[nodiscard]] auto resolve_path(std::string_view path) -> kstd::shared_ptr; + auto do_mount_internal(std::string_view path, kstd::shared_ptr const & mount_point_dentry, + kstd::shared_ptr const & fs) -> void; mount_table m_mount_table; }; 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 1f0d290bc303ac8f039963c4eb6421536d36827c Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 28 Mar 2026 17:29:31 +0100 Subject: string tests --- libs/kstd/tests/src/string.cpp | 84 ++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 35 deletions(-) diff --git a/libs/kstd/tests/src/string.cpp b/libs/kstd/tests/src/string.cpp index 43e9a6b..a94f0f6 100644 --- a/libs/kstd/tests/src/string.cpp +++ b/libs/kstd/tests/src/string.cpp @@ -386,60 +386,74 @@ SCENARIO("String iteration", "[string]") REQUIRE(str.back() == 'b'); } } - } - - GIVEN("A const string") - { - auto const str = kstd::string{"Blub"}; - WHEN("iterating over the characters of the string as string_view using a range-based for loop") + GIVEN("A non-empty string") { - kstd::string result; - - for (auto ch : str.view()) - { - result.push_back(ch); - } + auto str = kstd::string{"Hello"}; - THEN("the iterated characters are the same as the characters in the string") + WHEN("using const end()") { - REQUIRE(result == str.view()); + auto it = str.end(); // calls const end() + THEN("it points past the last character") + { + REQUIRE(*std::prev(it) == 'o'); + REQUIRE(std::distance(str.begin(), it) == str.size()); + } } } - WHEN("using front and back to access the first and last characters of the string") + GIVEN("A const string") { - THEN("front returns the first character of the string") + auto const str = kstd::string{"Blub"}; + + WHEN("iterating over the characters of the string as string_view using a range-based for loop") { - REQUIRE(str.front() == 'B'); + kstd::string result; + + for (auto ch : str.view()) + { + result.push_back(ch); + } + + THEN("the iterated characters are the same as the characters in the string") + { + REQUIRE(result == str.view()); + } } - THEN("back returns the last character of the string") + WHEN("using front and back to access the first and last characters of the string") { - REQUIRE(str.back() == 'b'); + THEN("front returns the first character of the string") + { + REQUIRE(str.front() == 'B'); + } + + THEN("back returns the last character of the string") + { + REQUIRE(str.back() == 'b'); + } } } - } - - GIVEN("An empty string") - { - auto str = kstd::string{}; - WHEN("iterating over the characters of an empty string") + GIVEN("An empty string") { - kstd::string result; + auto str = kstd::string{}; - for (auto ch : str.view()) + WHEN("iterating over the characters of an empty string") { - result.push_back(ch); - } + kstd::string result; - THEN("no characters are iterated and the result is an empty string") - { - REQUIRE(result.empty()); - REQUIRE(result.size() == 0); - REQUIRE(result.view() == std::string_view{}); + for (auto ch : str.view()) + { + result.push_back(ch); + } + + THEN("no characters are iterated and the result is an empty string") + { + REQUIRE(result.empty()); + REQUIRE(result.size() == 0); + REQUIRE(result.view() == std::string_view{}); + } } } } -} -- 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(-) 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 ddfa0cd69ec06b2ccaae36cb8dd676a324742b9c Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 28 Mar 2026 17:37:17 +0100 Subject: Revert "string tests" This reverts commit 1f0d290bc303ac8f039963c4eb6421536d36827c. --- libs/kstd/tests/src/string.cpp | 84 ++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 49 deletions(-) diff --git a/libs/kstd/tests/src/string.cpp b/libs/kstd/tests/src/string.cpp index a94f0f6..43e9a6b 100644 --- a/libs/kstd/tests/src/string.cpp +++ b/libs/kstd/tests/src/string.cpp @@ -386,74 +386,60 @@ SCENARIO("String iteration", "[string]") REQUIRE(str.back() == 'b'); } } + } + + GIVEN("A const string") + { + auto const str = kstd::string{"Blub"}; - GIVEN("A non-empty string") + WHEN("iterating over the characters of the string as string_view using a range-based for loop") { - auto str = kstd::string{"Hello"}; + kstd::string result; + + for (auto ch : str.view()) + { + result.push_back(ch); + } - WHEN("using const end()") + THEN("the iterated characters are the same as the characters in the string") { - auto it = str.end(); // calls const end() - THEN("it points past the last character") - { - REQUIRE(*std::prev(it) == 'o'); - REQUIRE(std::distance(str.begin(), it) == str.size()); - } + REQUIRE(result == str.view()); } } - GIVEN("A const string") + WHEN("using front and back to access the first and last characters of the string") { - auto const str = kstd::string{"Blub"}; - - WHEN("iterating over the characters of the string as string_view using a range-based for loop") + THEN("front returns the first character of the string") { - kstd::string result; - - for (auto ch : str.view()) - { - result.push_back(ch); - } - - THEN("the iterated characters are the same as the characters in the string") - { - REQUIRE(result == str.view()); - } + REQUIRE(str.front() == 'B'); } - WHEN("using front and back to access the first and last characters of the string") + THEN("back returns the last character of the string") { - THEN("front returns the first character of the string") - { - REQUIRE(str.front() == 'B'); - } - - THEN("back returns the last character of the string") - { - REQUIRE(str.back() == 'b'); - } + REQUIRE(str.back() == 'b'); } } + } + + GIVEN("An empty string") + { + auto str = kstd::string{}; - GIVEN("An empty string") + WHEN("iterating over the characters of an empty string") { - auto str = kstd::string{}; + kstd::string result; - WHEN("iterating over the characters of an empty string") + for (auto ch : str.view()) { - kstd::string result; - - for (auto ch : str.view()) - { - result.push_back(ch); - } + result.push_back(ch); + } - THEN("no characters are iterated and the result is an empty string") - { - REQUIRE(result.empty()); - REQUIRE(result.size() == 0); - REQUIRE(result.view() == std::string_view{}); - } + THEN("no characters are iterated and the result is an empty string") + { + REQUIRE(result.empty()); + REQUIRE(result.size() == 0); + REQUIRE(result.view() == std::string_view{}); } } } +} -- 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(+) 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(+) 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