diff options
| author | Jan Kara <jack@suse.cz> | 2026-08-04 12:41:13 +0200 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2026-08-21 13:57:44 +0200 |
| commit | 0ecd56573c1f272c72298154a3854380876dbb7c (patch) | |
| tree | 6e68623a120cfcd5de4065da1bcbf52ac5c571f1 | |
| parent | 818bebeb63dd6bf5f4e07e145f6cdbace520a34c (diff) | |
| download | linux-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.c | 11 |
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. |
