diff options
| -rw-r--r-- | kernel/kernel/filesystem/ext2/error.hpp | 4 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/ext2/filesystem.cpp | 78 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/ext2/filesystem.hpp | 10 |
3 files changed, 89 insertions, 3 deletions
diff --git a/kernel/kernel/filesystem/ext2/error.hpp b/kernel/kernel/filesystem/ext2/error.hpp index 986ab167..7de3b24b 100644 --- a/kernel/kernel/filesystem/ext2/error.hpp +++ b/kernel/kernel/filesystem/ext2/error.hpp @@ -21,6 +21,7 @@ namespace kernel::filesystem::ext2 failed_to_read_superblock, failed_to_read_block_group_descriptors, not_enough_free_blocks, + not_enough_inodes }; namespace detail @@ -52,6 +53,8 @@ namespace kernel::filesystem::ext2 return "failed to read block group descriptors"; case ext2_errc::not_enough_free_blocks: return "not enough free blocks"; + case ext2_errc::not_enough_inodes: + return "not enough inodes"; default: return "unknown ext2 error"; }; @@ -84,6 +87,7 @@ namespace kernel::filesystem::ext2 } break; case ext2_errc::not_enough_free_blocks: + case ext2_errc::not_enough_inodes: if (condition.category() == kstd::generic_category()) { return condition.value() == static_cast<int>(kstd::errc::no_space_on_device); diff --git a/kernel/kernel/filesystem/ext2/filesystem.cpp b/kernel/kernel/filesystem/ext2/filesystem.cpp index a68f7930..8860f213 100644 --- a/kernel/kernel/filesystem/ext2/filesystem.cpp +++ b/kernel/kernel/filesystem/ext2/filesystem.cpp @@ -223,15 +223,14 @@ namespace kernel::filesystem::ext2 continue; } - kstd::vector<uint8_t> block_bitmap{}; - block_bitmap.resize(block_size(), 0); + kstd::vector<uint8_t> block_bitmap(block_size(), 0); if (auto read_result = read_block(block_group_descriptor.block_bitmap, block_bitmap.data()); !read_result) { return kstd::failure(read_result.error()); } bool is_bitmap_dirty = false; - for (auto i = 0uz; i < block_bitmap.size() * 8 && allocated_blocks.size() < count; ++i) + for (auto i = 0uz; i < static_cast<size_t>(m_superblock.blocks_per_group) && allocated_blocks.size() < count; ++i) { if (!bitmap_is_set(block_bitmap, i)) { @@ -279,6 +278,61 @@ namespace kernel::filesystem::ext2 return allocated_blocks; } + auto filesystem::allocate_inode() -> kstd::result<uint32_t> + { + if (m_block_group_descriptors.empty() || m_superblock.free_inodes_count == 0) + { + return kstd::failure(ext2_errc::not_enough_inodes); + } + + for (auto block_group_descriptor_index = 0uz; block_group_descriptor_index < m_block_group_descriptors.size(); + ++block_group_descriptor_index) + { + auto & block_group_descriptor = m_block_group_descriptors.at(block_group_descriptor_index); + if (block_group_descriptor.free_inodes_count == 0) + { + continue; + } + + kstd::vector<uint8_t> inode_bitmap(block_size(), 0); + if (auto read_result = read_block(block_group_descriptor.inode_bitmap, inode_bitmap.data()); !read_result) + { + return kstd::failure(read_result.error()); + } + + for (auto i = 0uz; i < static_cast<size_t>(m_superblock.inodes_per_group); ++i) + { + if (!bitmap_is_set(inode_bitmap, i)) + { + bitmap_set(inode_bitmap, i); + block_group_descriptor.free_inodes_count--; + m_superblock.free_inodes_count--; + + if (auto write_result = write_block(block_group_descriptor.inode_bitmap, inode_bitmap.data()); !write_result) + { + return kstd::failure(write_result.error()); + } + + if (auto write_result = write_block_group_descriptor(block_group_descriptor, block_group_descriptor_index); + !write_result) + { + return kstd::failure(write_result.error()); + } + + // TODO update all superblocks + if (auto write_result = write_superblock(); !write_result) + { + return kstd::failure(write_result.error()); + } + + return block_group_descriptor_index * m_superblock.inodes_per_group + i + 1; + } + } + } + + return kstd::failure(ext2_errc::not_enough_inodes); + } + auto filesystem::indirect_levels() const -> std::array<indirect_level, 3> { return { @@ -464,6 +518,24 @@ namespace kernel::filesystem::ext2 return m_backing_inode->write(buffer, block_offset, block_size()); } + auto filesystem::write_block_group_descriptor(block_group_descriptor const & block_group_descriptor, + size_t block_group_descriptor_index) const -> kstd::result<void> + { + // TODO update all block group descriptors + return m_backing_inode + ->write(&block_group_descriptor, + block_group_descriptor_table_offset() + block_group_descriptor_index * sizeof(block_group_descriptor), + sizeof(block_group_descriptor)) + .transform([](auto) {}); + } + + auto filesystem::write_superblock() const -> kstd::result<void> + { + // TODO update all superblocks + return m_backing_inode->write(&m_superblock, constants::superblock_offset, sizeof(m_superblock)) + .transform([](auto) {}); + } + auto filesystem::block_numbers_per_block() const -> size_t { return block_size() / sizeof(uint32_t); diff --git a/kernel/kernel/filesystem/ext2/filesystem.hpp b/kernel/kernel/filesystem/ext2/filesystem.hpp index 6af49473..33b7b95c 100644 --- a/kernel/kernel/filesystem/ext2/filesystem.hpp +++ b/kernel/kernel/filesystem/ext2/filesystem.hpp @@ -103,6 +103,12 @@ namespace kernel::filesystem::ext2 auto allocate_blocks(size_t count) -> kstd::result<kstd::vector<uint32_t>>; /** + @brief Allocates a new inode. + @return The inode number within the filesystem. + */ + auto allocate_inode() -> kstd::result<uint32_t>; + + /** @brief Gets the size of an inode in the filesystem. @return The size of an inode in bytes. */ @@ -169,6 +175,10 @@ namespace kernel::filesystem::ext2 [[nodiscard]] auto block_numbers_per_doubly_indirect_block() const -> size_t; [[nodiscard]] auto block_numbers_per_triply_indirect_block() const -> size_t; + [[nodiscard]] auto write_block_group_descriptor(block_group_descriptor const & block_group_descriptor, + size_t block_group_descriptor_index) const -> kstd::result<void>; + [[nodiscard]] auto write_superblock() const -> kstd::result<void>; + superblock m_superblock{}; kstd::vector<block_group_descriptor> m_block_group_descriptors; }; |
