Kernel: Fix ext2 inode deletion cleanup

I now cleanup all blocks (including direct) in i_block array
This commit is contained in:
Bananymous 2023-10-28 16:48:19 +03:00
parent 98d702ac60
commit 99bde9aa49
3 changed files with 51 additions and 2 deletions

View File

@ -49,6 +49,7 @@ namespace Kernel
BAN::ErrorOr<void> link_inode_to_directory(Ext2Inode&, BAN::StringView name);
BAN::ErrorOr<bool> is_directory_empty();
void cleanup_indirect_block(uint32_t block, uint32_t depth);
BAN::ErrorOr<void> cleanup_default_links();
void cleanup_from_fs();

View File

@ -4,6 +4,7 @@
#define EXT2_DEBUG_PRINT 0
#define EXT2_VERIFY_INODE 0
#define EXT2_VERIFY_NO_BLOCKS 1
namespace Kernel
{
@ -244,6 +245,10 @@ namespace Kernel
auto inode_location = locate_inode(ino);
read_block(inode_location.block, inode_buffer);
auto& inode = inode_buffer.span().slice(inode_location.offset).as<Ext2::Inode>();
#if EXT2_VERIFY_NO_BLOCKS
static const char zero_buffer[sizeof(inode.block)] {};
ASSERT(memcmp(inode.block, zero_buffer, sizeof(inode.block)) == 0);
#endif
bool is_directory = Inode::Mode(inode.mode).ifdir();
memset(&inode, 0x00, m_superblock.inode_size);
write_block(inode_location.block, inode_buffer);

View File

@ -259,11 +259,54 @@ namespace Kernel
return {};
}
void Ext2Inode::cleanup_indirect_block(uint32_t block, uint32_t depth)
{
ASSERT(block);
if (depth == 0)
{
m_fs.release_block(block);
return;
}
auto block_buffer = m_fs.get_block_buffer();
m_fs.read_block(block, block_buffer);
const uint32_t ids_per_block = blksize() / sizeof(uint32_t);
for (uint32_t i = 0; i < ids_per_block; i++)
{
const uint32_t idx = ((uint32_t*)block_buffer.data())[i];
if (idx > 0)
cleanup_indirect_block(idx, depth - 1);
}
m_fs.release_block(block);
}
void Ext2Inode::cleanup_from_fs()
{
ASSERT(m_inode.links_count == 0);
for (uint32_t i = 0; i < blocks(); i++)
m_fs.release_block(fs_block_of_data_block_index(i));
// cleanup direct blocks
for (uint32_t i = 0; i < 12; i++)
if (m_inode.block[i])
m_fs.release_block(m_inode.block[i]);
// cleanup indirect blocks
if (m_inode.block[12])
cleanup_indirect_block(m_inode.block[12], 1);
if (m_inode.block[13])
cleanup_indirect_block(m_inode.block[13], 2);
if (m_inode.block[14])
cleanup_indirect_block(m_inode.block[14], 3);
// mark blocks as deleted
memset(m_inode.block, 0x00, sizeof(m_inode.block));
// FIXME: this is only required since fs does not get
// deleting inode from its cache
sync();
m_fs.delete_inode(ino());
}