[PATCH 2/3] ext4: fix directory i_blocks after fast commit replay
From: Mani Tofigh via B4 Relay
Date: Wed Nov 11 2026 - 18:17:45 EST
From: Mani Tofigh <mt4022@xxxxxxxxxxxx>
After a crash, a directory created by the fast commit replay has an
i_blocks of 0. e2fsck reports:
Inode 14, i_blocks is 0, should be 8.
The same happens to a directory that gets new blocks while the replay
adds entries to it, e.g., a new directory that got many files in the
same fast commit:
Inode 14, i_blocks is 8, should be 24.
Fast commits don't track directories. The replay allocates their
blocks in ext4_init_new_dir() and __ext4_link() through
ext4_mb_new_blocks_simple(), which leaves i_blocks alone. For regular
files ext4_fc_replay_inode() recounts i_blocks with
ext4_ext_replay_set_iblocks(). Nothing does that for directories.
Recount i_blocks of the new directory after ext4_init_new_dir() and of
the parent after a new entry is added.
With the fix, e2fsck doesn't find a wrong i_blocks after the replay
anymore.
Fixes: 8016e29f4362 ("ext4: fast commit recovery path")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Mani Tofigh <mt4022@xxxxxxxxxxxx>
---
fs/ext4/fast_commit.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
index 0eac7be3f58c..9c170986f0b2 100644
--- a/fs/ext4/fast_commit.c
+++ b/fs/ext4/fast_commit.c
@@ -1858,6 +1858,9 @@ static int ext4_fc_replay_link_internal(struct super_block *sb,
goto out;
}
+ /* The replay allocator doesn't count blocks added to the dir */
+ if (!ret && !ext4_test_inode_flag(dir, EXT4_INODE_INLINE_DATA))
+ ext4_ext_replay_set_iblocks(dir);
ret = 0;
out:
if (dir)
@@ -2070,6 +2073,9 @@ static int ext4_fc_replay_create(struct super_block *sb,
ret = 0;
goto out;
}
+ /* The replay allocator doesn't count the new dir block */
+ if (!ext4_test_inode_flag(inode, EXT4_INODE_INLINE_DATA))
+ ext4_ext_replay_set_iblocks(inode);
}
ret = ext4_fc_replay_link_internal(sb, &darg, inode);
if (ret)
--
2.53.0