summaryrefslogtreecommitdiff
path: root/Kernel/FileSystem
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-01-17 16:56:07 +0100
committerAndreas Kling <kling@serenityos.org>2021-01-17 16:56:07 +0100
commit6613cef2f8c63eb033c73a70654213f2b18aa078 (patch)
treec4278cdf6c96b6027e13868ba8244d557e7a3294 /Kernel/FileSystem
parent1382bbfc57abfc6d3e89d53c837ffefc0f72b13d (diff)
downloadserenity-6613cef2f8c63eb033c73a70654213f2b18aa078.zip
Ext2FS: Update block group directory count after directory removal
When freeing an inode, we were checking if it's a directory *after* wiping the inode metadata. This caused us to forget updating the block group descriptor with the new directory count.
Diffstat (limited to 'Kernel/FileSystem')
-rw-r--r--Kernel/FileSystem/Ext2FileSystem.cpp19
1 files changed, 10 insertions, 9 deletions
diff --git a/Kernel/FileSystem/Ext2FileSystem.cpp b/Kernel/FileSystem/Ext2FileSystem.cpp
index 2037c75313..a097d05d9f 100644
--- a/Kernel/FileSystem/Ext2FileSystem.cpp
+++ b/Kernel/FileSystem/Ext2FileSystem.cpp
@@ -531,28 +531,29 @@ void Ext2FS::free_inode(Ext2FSInode& inode)
dbgln("Ext2FS: Inode {} has no more links, time to delete!", inode.index());
#endif
+ // Mark all blocks used by this inode as free.
auto block_list = block_list_for_inode(inode.m_raw_inode, true);
-
for (auto block_index : block_list) {
ASSERT(block_index <= super_block().s_blocks_count);
if (block_index)
set_block_allocation_state(block_index, false);
}
- struct timeval now;
- kgettimeofday(now);
- memset(&inode.m_raw_inode, 0, sizeof(ext2_inode));
- inode.m_raw_inode.i_dtime = now.tv_sec;
- write_ext2_inode(inode.index(), inode.m_raw_inode);
-
- set_inode_allocation_state(inode.index(), false);
-
+ // If the inode being freed is a directory, update block group directory counter.
if (inode.is_directory()) {
auto& bgd = const_cast<ext2_group_desc&>(group_descriptor(group_index_from_inode(inode.index())));
--bgd.bg_used_dirs_count;
dbgln("Ext2FS: Decremented bg_used_dirs_count to {}", bgd.bg_used_dirs_count);
m_block_group_descriptors_dirty = true;
}
+
+ // NOTE: After this point, the inode metadata is wiped.
+ memset(&inode.m_raw_inode, 0, sizeof(ext2_inode));
+ inode.m_raw_inode.i_dtime = kgettimeofday().tv_sec;
+ write_ext2_inode(inode.index(), inode.m_raw_inode);
+
+ // Mark the inode as free.
+ set_inode_allocation_state(inode.index(), false);
}
void Ext2FS::flush_block_group_descriptor_table()