diff options
| -rw-r--r-- | kernel/kernel/filesystem/ext2/filesystem.hpp | 2 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/ext2/inode.tests.cpp | 77 |
2 files changed, 69 insertions, 10 deletions
diff --git a/kernel/kernel/filesystem/ext2/filesystem.hpp b/kernel/kernel/filesystem/ext2/filesystem.hpp index 7361943a..f440d4dc 100644 --- a/kernel/kernel/filesystem/ext2/filesystem.hpp +++ b/kernel/kernel/filesystem/ext2/filesystem.hpp @@ -90,6 +90,7 @@ namespace kernel::filesystem::ext2 auto write_inode(uint32_t inode_number, inode_data const & data) -> kstd::result<void>; + [[nodiscard]] auto inode_size() const -> uint16_t; /** @brief Maps an inode block index to a global block number. @param inode_block_index The index of the block within the inode. @@ -116,7 +117,6 @@ namespace kernel::filesystem::ext2 auto ensure_and_get_block(uint32_t & block_number) -> bool; - [[nodiscard]] auto inode_size() const -> uint16_t; [[nodiscard]] auto block_group_descriptor_table_offset() const -> size_t; [[nodiscard]] auto block_numbers_per_block() const -> size_t; diff --git a/kernel/kernel/filesystem/ext2/inode.tests.cpp b/kernel/kernel/filesystem/ext2/inode.tests.cpp index 752d17d7..90274f6f 100644 --- a/kernel/kernel/filesystem/ext2/inode.tests.cpp +++ b/kernel/kernel/filesystem/ext2/inode.tests.cpp @@ -359,7 +359,7 @@ SCENARIO("Ext2 inode write across block boundaries", "[filesystem][ext2][inode]" auto block_bitmap = std::vector<std::byte>(block_size, std::byte{0x00}); block_bitmap[0] = std::byte{0b1111'1111}; block_bitmap[1] = std::byte{0b1111'1111}; - block_bitmap[2] = std::byte{0b0001'1000}; + block_bitmap[2] = std::byte{0b0011'0000}; dev_inode->write(block_bitmap.data(), block_group_descriptor.block_bitmap * block_size, block_size); @@ -374,15 +374,47 @@ SCENARIO("Ext2 inode write across block boundaries", "[filesystem][ext2][inode]" inode_data.mode = kernel::filesystem::ext2::constants::mode_regular; uint32_t inode_number = 3; + auto const inode_data_offset = + block_group_descriptor.inode_table * block_size + (inode_number - 1) * fs.inode_size(); + auto inode = kernel::filesystem::ext2::inode{&fs, inode_number, inode_data}; - dev_inode->write(&inode, inode_number * block_size, sizeof(kernel::filesystem::ext2::inode_data)); + dev_inode->write(&inode, inode_data_offset, sizeof(kernel::filesystem::ext2::inode_data)); - THEN("writing over block boundaries updates backing device no additional blocks allocated") + auto buffer = kstd::vector<std::byte>{std::byte{'H'}, std::byte{'e'}, std::byte{'l'}, std::byte{'l'}, + std::byte{'o'}, std::byte{' '}, std::byte{'W'}, std::byte{'o'}, + std::byte{'r'}, std::byte{'l'}, std::byte{'d'}, std::byte{'!'}}; + + auto do_read_inode = [&]() { + auto inode_data = kernel::filesystem::ext2::inode_data{}; + dev_inode->read(&inode_data, inode_data_offset, sizeof(kernel::filesystem::ext2::inode_data)); + auto read_inode = kernel::filesystem::ext2::inode{&fs, inode_number, inode_data}; + return read_inode; + }; + + THEN("writing in the current size does not update the size and does not allocate new blocks") { - auto buffer = kstd::vector<std::byte>{std::byte{'H'}, std::byte{'e'}, std::byte{'l'}, std::byte{'l'}, - std::byte{'o'}, std::byte{' '}, std::byte{'W'}, std::byte{'o'}, - std::byte{'r'}, std::byte{'l'}, std::byte{'d'}, std::byte{'!'}}; + auto const expected_bytes_written = 3; + auto const bytes_written = inode.write(buffer.data(), 0, expected_bytes_written); + REQUIRE(bytes_written == expected_bytes_written); + + auto const text = std::string_view{reinterpret_cast<char const *>(device->data.data() + 20 * block_size), 3}; + REQUIRE(text == "Hel"); + + auto read_block_bitmap = std::vector<std::byte>(block_size, std::byte{0x00}); + dev_inode->read(read_block_bitmap.data(), block_group_descriptor.block_bitmap * block_size, block_size); + REQUIRE(block_bitmap == read_block_bitmap); + + auto read_inode = do_read_inode(); + REQUIRE(inode_data.size == read_inode.size()); + REQUIRE(inode_data.blocks == read_inode.data().blocks); + + auto const current_blocks = inode_data.block; + auto const read_blocks = read_inode.data().block; + REQUIRE(current_blocks == read_blocks); + } + THEN("writing over block boundaries updates backing device no additional blocks allocated") + { auto const offset = block_size - 4; auto const bytes_written = inode.write(buffer.data(), offset, buffer.size()); REQUIRE(bytes_written == buffer.size()); @@ -395,15 +427,42 @@ SCENARIO("Ext2 inode write across block boundaries", "[filesystem][ext2][inode]" dev_inode->read(read_block_bitmap.data(), block_group_descriptor.block_bitmap * block_size, block_size); REQUIRE(block_bitmap == read_block_bitmap); - auto read_inode = kernel::filesystem::ext2::inode{&fs, inode_number, {}}; - dev_inode->read(&read_inode, inode_number * block_size, sizeof(kernel::filesystem::ext2::inode)); - REQUIRE(offset + 12 == inode.size()); + auto read_inode = do_read_inode(); + REQUIRE(offset + buffer.size() == read_inode.size()); REQUIRE(inode_data.blocks == read_inode.data().blocks); auto const current_blocks = inode_data.block; auto const read_blocks = read_inode.data().block; REQUIRE(current_blocks == read_blocks); } + + THEN("writing over the current size and over allocated blocks updates backing device and allocates a new block") + { + auto const offset = block_size * 2 - 4; + auto const bytes_written = inode.write(buffer.data(), offset, buffer.size()); + REQUIRE(bytes_written == buffer.size()); + + auto read_buffer = std::vector<std::byte>(buffer.size(), std::byte{0x00}); + auto const bytes_read = inode.read(read_buffer.data(), offset, buffer.size()); + auto const text = std::string_view{reinterpret_cast<char const *>(read_buffer.data()), bytes_read}; + REQUIRE(text == "Hello World!"); + + auto read_block_bitmap = std::vector<std::byte>(block_size, std::byte{0x00}); + dev_inode->read(read_block_bitmap.data(), block_group_descriptor.block_bitmap * block_size, block_size); + + auto expected_block_bitmap = block_bitmap; + expected_block_bitmap[2] = std::byte{0b0011'0001}; + REQUIRE(expected_block_bitmap == read_block_bitmap); + + auto read_inode = do_read_inode(); + REQUIRE(offset + buffer.size() == read_inode.size()); + REQUIRE(inode_data.blocks + 2 == read_inode.data().blocks); + + auto expected_blocks = inode_data.block; + expected_blocks[2] = 16; + auto const read_blocks = read_inode.data().block; + REQUIRE(expected_blocks == read_blocks); + } } } |
