From 660c4548f2da83b938fba88e39020eae2796dc0e Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 25 Aug 2026 22:49:44 +0200 Subject: kernel/fs: ext2: add a simple write batching type --- kernel/CMakeLists.txt | 1 + kernel/kernel/filesystem/ext2/filesystem.hpp | 2 + kernel/kernel/filesystem/ext2/write_batch.cpp | 67 +++++++++++++++++++++++++++ kernel/kernel/filesystem/ext2/write_batch.hpp | 53 +++++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 kernel/kernel/filesystem/ext2/write_batch.cpp create mode 100644 kernel/kernel/filesystem/ext2/write_batch.hpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 1a5e2421..35c3a957 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -80,6 +80,7 @@ target_sources("kernel_lib" PRIVATE "kernel/filesystem/ext2/filesystem.cpp" "kernel/filesystem/ext2/inode.cpp" "kernel/filesystem/ext2/module.cpp" + "kernel/filesystem/ext2/write_batch.cpp" # Rootfs Filesystem "kernel/filesystem/rootfs/filesystem.cpp" diff --git a/kernel/kernel/filesystem/ext2/filesystem.hpp b/kernel/kernel/filesystem/ext2/filesystem.hpp index 93836b91..f43e357c 100644 --- a/kernel/kernel/filesystem/ext2/filesystem.hpp +++ b/kernel/kernel/filesystem/ext2/filesystem.hpp @@ -191,6 +191,8 @@ namespace kernel::filesystem::ext2 -> kstd::result; private: + friend struct write_batch; + //! Allocate a single inode in the file system. //! //! @param state The driver state to operate on. diff --git a/kernel/kernel/filesystem/ext2/write_batch.cpp b/kernel/kernel/filesystem/ext2/write_batch.cpp new file mode 100644 index 00000000..e8663d21 --- /dev/null +++ b/kernel/kernel/filesystem/ext2/write_batch.cpp @@ -0,0 +1,67 @@ +#include + +#include +#include +#include + +#include + +#include +#include +#include + +namespace kernel::filesystem::ext2 +{ + + write_batch::write_batch(filesystem & filesystem, mount_state & state) + : m_filesystem{filesystem} + , m_state{state} + {} + + write_batch::~write_batch() + { + std::ranges::for_each(m_dirty_groups, [this](auto index) { + auto & descriptor = m_state.block_group_descriptors.at(index); + auto result = m_filesystem.write_block_group_descriptor(descriptor, index, m_state); + + if (!result) + { + kapi::system::panic("[FS:ext2] failed to write block groups descriptor", result.error()); + } + }); + + if (!m_dirty_groups.empty()) + { + auto result = m_filesystem.write_superblock(m_state); + if (!result) + { + kapi::system::panic("[FS:ext2] failed to write superblock", result.error()); + } + } + + std::ranges::for_each(m_dirty_inodes, [this](auto inode) { + auto result = m_filesystem.write_inode(inode->number(), inode->data(), m_state); + if (!result) + { + kapi::system::panic("[FS:ext2] failed to write inode", result.error()); + } + }); + } + + auto write_batch::mark_group(std::size_t index) -> void + { + if (std::ranges::find(m_dirty_groups, index) == std::ranges::end(m_dirty_groups)) + { + m_dirty_groups.push_back(index); + } + } + + auto write_batch::mark_inode(inode & inode) -> void + { + if (std::ranges::find(m_dirty_inodes, &inode) == std::ranges::end(m_dirty_inodes)) + { + m_dirty_inodes.push_back(&inode); + } + } + +} // namespace kernel::filesystem::ext2 diff --git a/kernel/kernel/filesystem/ext2/write_batch.hpp b/kernel/kernel/filesystem/ext2/write_batch.hpp new file mode 100644 index 00000000..103684ac --- /dev/null +++ b/kernel/kernel/filesystem/ext2/write_batch.hpp @@ -0,0 +1,53 @@ +#ifndef TEACHOS_KERNEL_FILESYSTEM_EXT2_WRITE_BATCH +#define TEACHOS_KERNEL_FILESYSTEM_EXT2_WRITE_BATCH + +#include + +#include + +namespace kernel::filesystem::ext2 +{ + + struct filesystem; + struct inode; + struct mount_state; + + //! A RAII write batching type. + //! + //! Any metadata writes are first appended to the batch. On destruction, the write is committed to the filesystem. + struct write_batch + { + //! Construct a new write batch for the given filesystem and mount state. + //! + //! @param filesystem The filesystem driver to use for writes. + //! @param state The driver state to operate on. + write_batch(filesystem & filesystem, mount_state & state); + + write_batch(write_batch const &) = delete; + write_batch(write_batch &&) = delete; + auto operator=(write_batch const &) = delete; + auto operator=(write_batch &&) = delete; + + //! Commit and destroy the batch. + ~write_batch(); + + //! Mark the group with the given index as dirty. + //! + //! @param index The index of the group to mark. + auto mark_group(std::size_t index) -> void; + + //! Mark the given inode as dirty. + //! + //! @param inode The inode to mark. + auto mark_inode(inode & inode) -> void; + + private: + filesystem & m_filesystem; + mount_state & m_state; + kstd::vector m_dirty_groups{}; + kstd::vector m_dirty_inodes{}; + }; + +} // namespace kernel::filesystem::ext2 + +#endif -- cgit v1.2.3