Re: [PATCH] ext4: do not WARN when starting a journal on a frozen filesystem

From: Christian Brauner

Date: Fri Jul 24 2026 - 04:11:20 EST


On Thu, Jul 23, 2026 at 08:50:36PM +0000, Luyao Bai wrote:
> A WARNING is triggered in ext4_journal_check_start() when a background
> writeback thread attempts to start a journal transaction while the
> filesystem is in the SB_FREEZE_COMPLETE state:
>
> WARNING: CPU: 1 PID: 2903 at fs/ext4/ext4_jbd2.c:76
> ext4_journal_check_start+0x1f8/0x250
> Call Trace:
> __ext4_journal_start_sb+0x181/0x600 fs/ext4/ext4_jbd2.c:105
> __ext4_journal_start fs/ext4/ext4_jbd2.h:326 [inline]
> ext4_do_writepages+0x112c/0x3d20 fs/ext4/inode.c:2707
> ext4_writepages+0x213/0x3c0 fs/ext4/inode.c:2813
> do_writepages+0x35f/0x870 mm/page-writeback.c:2683
> __writeback_single_inode+0x14f/0x10d0 fs/fs-writeback.c:1658
> writeback_sb_inodes+0x80c/0x1370 fs/fs-writeback.c:1954
> wb_writeback+0x41b/0xbd0 fs/fs-writeback.c:2134
> wb_workfn+0x410/0x1090 fs/fs-writeback.c:2321
>
> The background writeback flusher does not take freeze protection, so it
> can legitimately reach ext4_do_writepages() and try to start a journal
> handle while the filesystem is frozen. This happens, for example, when
> ext4_writepages() failed earlier (e.g. -ENOSPC or -EDQUOT) during the
> sync_filesystem() phase of the freeze: sync_filesystem() can still
> return 0, the freeze completes, but dirty pages are left behind. A later
> writeback pass then tries to write them out on the now-frozen
> filesystem.
>
> The same state is reachable through the EXT4_IOC_SHUTDOWN path: if
> fs_bdev_freeze() succeeds in freezing the superblock but the subsequent
> sync_blockdev() fails, the filesystem is left in SB_FREEZE_COMPLETE and
> dirty pages remain, so writeback eventually retries and trips the WARN.
>
> Because this state can be reached without any kernel bug, WARN_ON() is
> the wrong tool here: WARN_ON() must only fire on conditions that should
> never happen. Replace it with an ext4_msg() error message and return
> -EROFS, rejecting the transaction cleanly. All callers of
> __ext4_journal_start_sb() already handle an error return (it is the same
> path used for the existing is_journal_aborted() -EROFS case), so the
> dirty pages are simply kept and written back once the filesystem is
> thawed.
>
> This patch is intentionally limited to the ext4 journal-start check,
> which is the direct cause of the reported warning. Any improvements to
> the generic VFS freeze/thaw error handling in fs/super.c are a separate
> concern and are deliberately left out of this fix.
>
> Reported-by: syzbot+b75d75f957975f3d40e3@xxxxxxxxxxxxxxxxxxxxxxxxx
> Closes: https://syzkaller.appspot.com/bug?extid=b75d75f957975f3d40e3
> Fixes: 49ef8832fb1a ("bdev: implement freeze and thaw holder operations")
> Signed-off-by: Luyao Bai <bailuyao1997@xxxxxxxxx>
> ---
> Tested with the syzbot reproducer under QEMU: the WARNING at
> fs/ext4/ext4_jbd2.c fires on a clean mainline build and no longer fires
> with this patch applied.
>
> fs/ext4/ext4_jbd2.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
> index 9a8c225f2..1756039b1 100644
> --- a/fs/ext4/ext4_jbd2.c
> +++ b/fs/ext4/ext4_jbd2.c
> @@ -75,7 +75,12 @@ static int ext4_journal_check_start(struct super_block *sb)
> if (WARN_ON_ONCE(sb_rdonly(sb)))
> return -EROFS;
>
> - WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
> + if (unlikely(sb->s_writers.frozen == SB_FREEZE_COMPLETE)) {
> + ext4_msg(sb, KERN_ERR,
> + "Attempt to start a journal transaction on a frozen filesystem");
> + return -EROFS;
> + }

I can't say whether this is the right fix but it feels hacky and racy
unless this code holds s_umount - which it may well do.