aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/kernel/filesystem/ext2/error.hpp4
-rw-r--r--kernel/kernel/filesystem/ext2/filesystem.cpp78
-rw-r--r--kernel/kernel/filesystem/ext2/filesystem.hpp10
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;
};