summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2026-08-04 12:41:13 +0200
committerChristian Brauner <brauner@kernel.org>2026-08-21 13:57:44 +0200
commit0ecd56573c1f272c72298154a3854380876dbb7c (patch)
tree6e68623a120cfcd5de4065da1bcbf52ac5c571f1
parent818bebeb63dd6bf5f4e07e145f6cdbace520a34c (diff)
downloadlinux-0ecd56573c1f272c72298154a3854380876dbb7c.tar.gz
linux-0ecd56573c1f272c72298154a3854380876dbb7c.zip
ext4: Avoid entering writeback paths during fastcommit replay
Fastcommit replay effectively happens in nojournal mode. This results in ext4_mark_iloc_dirty() setting I_METADATA_WRITEBACK flag and as a result we end up entering filesystem writeback functions. However during fastcommit replay s_writepages_rwsem isn't initialized yet and hence we crash. Fix the problem by avoiding setting I_METADATA_WRITEBACK during fastcommit replay. Journal replay flushes the whole block device after replay anyway so all metadata is properly persisted and replay is faster this way as a bonus. Fixes: c26339e1df33 ("ext4: Fix data integrity writeout issues in nojournal mode") Reported-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com> Reported-by: Ojaswin Mujoo <ojaswin@linux.ibm.com> Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260804104112.93202-2-jack@suse.cz Tested-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com> Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
-rw-r--r--fs/ext4/inode.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index bd4b778df9eb..26f0f9714f03 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -6456,9 +6456,10 @@ int ext4_chunk_trans_blocks(struct inode *inode, int nrblocks)
int ext4_mark_iloc_dirty(handle_t *handle,
struct inode *inode, struct ext4_iloc *iloc)
{
+ struct super_block *sb = inode->i_sb;
int err = 0;
- err = ext4_emergency_state(inode->i_sb);
+ err = ext4_emergency_state(sb);
if (unlikely(err)) {
put_bh(iloc->bh);
return err;
@@ -6473,9 +6474,13 @@ int ext4_mark_iloc_dirty(handle_t *handle,
put_bh(iloc->bh);
/*
* Mark that there's metadata writeout pending for the inode so that it
- * gets properly flushed on fsync(2) and similar.
+ * gets properly flushed on fsync(2) and similar. We don't bother for
+ * fastcommit replay as that flushes the whole bdev afterwards anyway.
+ * It is faster this way and we avoid entering fs writeback paths which
+ * aren't fully initialized yet.
*/
- if (!EXT4_SB(inode->i_sb)->s_journal) {
+ if (!ext4_handle_valid(handle) &&
+ !(EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY)) {
/*
* Inode didn't need to go through dirtying, make sure it is
* attached to wb so that writeback can handle it.