All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC] fs: fix superblock freeze rollback on sync_blockdev failure
@ 2026-07-20 14:25 syzbot
  2026-08-06 10:22 ` Uladzislau Zhauniarovich
  0 siblings, 1 reply; 2+ messages in thread
From: syzbot @ 2026-07-20 14:25 UTC (permalink / raw)
  To: syzkaller-upstream-moderation; +Cc: syzbot

If sync_blockdev() fails during fs_bdev_freeze(), the superblock is left in
a frozen state, but the block device is not. When the filesystem is later
unmounted and destroyed, the s_writers.rw_sem per-CPU rw-semaphores are
freed while still held for write, triggering a warning in rcu_sync_dtor():

READ_ONCE(rsp->gp_state) == GP_PASSED
WARNING: kernel/rcu/sync.c:177 at rcu_sync_dtor+0xcd/0x180
kernel/rcu/sync.c:177, CPU#0: kworker/0:2/5024
Call Trace:
 <TASK>
 percpu_free_rwsem+0x43/0x80 kernel/locking/percpu-rwsem.c:42
 destroy_super_work+0x217/0x310 fs/super.c:284
 process_one_work kernel/workqueue.c:3322 [inline]
 process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
 worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
 kthread+0x388/0x470 kernel/kthread.c:436
 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
 </TASK>

This happens because of two issues. First, in fs_bdev_freeze(), if
freeze_super() succeeds but sync_blockdev() fails, thaw_super() is not
called to roll back the freeze. Second, in exfat, an I/O error during
sync_blockdev() triggers the error handler (__exfat_fs_error()), which
directly sets SB_RDONLY without holding the s_umount semaphore. If
thaw_super() is called after this, it sees the filesystem as read-only and
skips releasing the freeze semaphores.

Fix this by adding the missing thaw_super() rollback in fs_bdev_freeze()
when sync_blockdev() fails. Additionally, modify the exfat error handler to
set EXFAT_FLAGS_SHUTDOWN instead of directly setting SB_RDONLY, which
prevents confusing the VFS freeze logic and allows thaw_super() to
correctly release the semaphores.

Fixes: 49ef8832fb1a ("bdev: implement freeze and thaw holder operations")
Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by: syzbot+823cd0d24881f21ab9f1@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=823cd0d24881f21ab9f1
Link: https://syzkaller.appspot.com/ai_job?id=431fcee8-0777-4619-a114-4a86af680864
To: "Christian Brauner" <brauner@kernel.org>
To: "Namjae Jeon" <linkinjeon@kernel.org>
To: <linux-fsdevel@vger.kernel.org>
To: "Sungjong Seo" <sj1557.seo@samsung.com>
To: "Alexander Viro" <viro@zeniv.linux.org.uk>
Cc: "Jan Kara" <jack@suse.cz>
Cc: <linux-kernel@vger.kernel.org>
Cc: "Yuezhang Mo" <yuezhang.mo@sony.com>

---
diff --git a/fs/exfat/misc.c b/fs/exfat/misc.c
index 6f11a96a4..dbb3b2907 100644
--- a/fs/exfat/misc.c
+++ b/fs/exfat/misc.c
@@ -41,7 +41,14 @@ void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
 		panic("exFAT-fs (%s): fs panic from previous error\n",
 			sb->s_id);
 	} else if (opts->errors == EXFAT_ERRORS_RO && !sb_rdonly(sb)) {
-		sb->s_flags |= SB_RDONLY;
+		set_bit(EXFAT_FLAGS_SHUTDOWN, &EXFAT_SB(sb)->s_exfat_flags);
+		/*
+		 * We have already set EXFAT_FLAGS_SHUTDOWN flag to stop all updates
+		 * to filesystem, so it doesn't need to set SB_RDONLY flag here
+		 * because the flag should be set covered w/ sb->s_umount semaphore
+		 * via remount procedure, otherwise, it will confuse code like
+		 * freeze_super() which will lead to deadlocks and other problems.
+		 */
 		exfat_err(sb, "Filesystem has been set read-only");
 	}
 }
diff --git a/fs/super.c b/fs/super.c
index a8fd61136..909d8b9ab 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1481,8 +1481,23 @@ static int fs_bdev_freeze(struct block_device *bdev)
 	else
 		error = freeze_super(sb,
 				FREEZE_MAY_NEST | FREEZE_HOLDER_USERSPACE, NULL);
-	if (!error)
+	if (!error) {
 		error = sync_blockdev(bdev);
+		if (error) {
+			if (sb->s_op->thaw_super)
+				(void)sb->s_op->thaw_super(
+					sb,
+					FREEZE_MAY_NEST |
+						FREEZE_HOLDER_USERSPACE,
+					NULL);
+			else
+				(void)thaw_super(
+					sb,
+					FREEZE_MAY_NEST |
+						FREEZE_HOLDER_USERSPACE,
+					NULL);
+		}
+	}
 	deactivate_super(sb);
 	return error;
 }


base-commit: 1590cf0329716306e948a8fc29f1d3ee87d3989f
-- 
This is an AI-generated patch subject to moderation.
Reply with '#syz upstream' to Sign-off the patch as a human author
and send it to the upstream kernel mailing lists.
Reply with '#syz reject' to reject it ('#syz unreject' to undo).

See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
You can comment on the patch as usual, syzbot will try to address
the comments and send a new version of the patch if necessary.
syzbot engineers can be reached at syzkaller@googlegroups.com.

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH RFC] fs: fix superblock freeze rollback on sync_blockdev failure
  2026-07-20 14:25 [PATCH RFC] fs: fix superblock freeze rollback on sync_blockdev failure syzbot
@ 2026-08-06 10:22 ` Uladzislau Zhauniarovich
  0 siblings, 0 replies; 2+ messages in thread
From: Uladzislau Zhauniarovich @ 2026-08-06 10:22 UTC (permalink / raw)
  To: syzbot, syzkaller-upstream-moderation; +Cc: syzbot

The core idea is right — exFAT must not set SB_RDONLY on its own —
but this version has two problems and the fix should stay inside exfat.

1) Don't reuse EXFAT_FLAGS_SHUTDOWN.

Since commit 47e35366bc6f ("exfat: fix missing shutdown check"), the read
paths ->read_iter, ->splice_read, ->mmap and ->file_open all test
exfat_forced_shutdown() and return -EIO. Setting EXFAT_FLAGS_SHUTDOWN from
the error handler therefore breaks *reads* with -EIO and turns the default
errors=remount-ro into a full shutdown, which is a regression. It also
re-logs "Filesystem has been set read-only" on every subsequent error.

Please track the post-error read-only state in a *separate* superblock flag
(e.g. EXFAT_FLAGS_ERROR_RO) and fail only *modifying* operations with
-EROFS, exactly like ext4's EXT4_FLAGS_EMERGENCY_RO / ext4_emergency_state()
(commit d3476f3dad4a "ext4: don't set SB_RDONLY after filesystem errors")
and f2fs (commit 930c6ab93492). Concretely:

   - add a new flag EXFAT_FLAGS_ERROR_RO;
   - in __exfat_fs_error(), for EXFAT_ERRORS_RO, test_and_set that bit
     instead of "sb->s_flags |= SB_RDONLY" (log once);
   - add a small helper (returning -EIO on shutdown, -EROFS on error-RO) and
     call it at every modifying entry point only: ->write_iter,
     ->page_mkwrite, ->setattr, ->fallocate, and the namei ops create,
     unlink, mkdir, rmdir, rename;
   - leave ->read_iter, ->splice_read, ->mmap, ->file_open, ->fsync and
     writeback untouched, so reads and flushing of already-dirty data keep
     working just as they did with SB_RDONLY;
   - clear the flag on a read-write remount in exfat_reconfigure(), so the
     filesystem can be made writable again by remounting, as documented.

2) Drop the fs/super.c hunk.

It does not fix this warning. freeze_super() holds an s_active reference for
the freeze, so a superblock left frozen is never torn down — 
destroy_super_work()
does not run and the rcu_sync_dtor() splat cannot originate there. The 
actual
race is entirely inside exfat: __exfat_fs_error() flips SB_RDONLY without
sb->s_umount between freeze_super() (which took the s_writers 
semaphores) and
thaw_super_locked() (which re-reads sb_rdonly() and then skips
sb_freeze_unlock()). Fixing exfat alone is sufficient; please remove the
fs/super.c change and keep this exfat-only.

3) Fixes tag.

Use the cause-bisection commit:
   Fixes: f761fcdd289d ("exfat: Implement sops->shutdown and ioctl")
not 49ef8832fb1a.

On 20/07/2026 16:25, syzbot wrote:
> If sync_blockdev() fails during fs_bdev_freeze(), the superblock is left in
> a frozen state, but the block device is not. When the filesystem is later
> unmounted and destroyed, the s_writers.rw_sem per-CPU rw-semaphores are
> freed while still held for write, triggering a warning in rcu_sync_dtor():
>
> READ_ONCE(rsp->gp_state) == GP_PASSED
> WARNING: kernel/rcu/sync.c:177 at rcu_sync_dtor+0xcd/0x180
> kernel/rcu/sync.c:177, CPU#0: kworker/0:2/5024
> Call Trace:
>   <TASK>
>   percpu_free_rwsem+0x43/0x80 kernel/locking/percpu-rwsem.c:42
>   destroy_super_work+0x217/0x310 fs/super.c:284
>   process_one_work kernel/workqueue.c:3322 [inline]
>   process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
>   worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
>   kthread+0x388/0x470 kernel/kthread.c:436
>   ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
>   ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
>   </TASK>
>
> This happens because of two issues. First, in fs_bdev_freeze(), if
> freeze_super() succeeds but sync_blockdev() fails, thaw_super() is not
> called to roll back the freeze. Second, in exfat, an I/O error during
> sync_blockdev() triggers the error handler (__exfat_fs_error()), which
> directly sets SB_RDONLY without holding the s_umount semaphore. If
> thaw_super() is called after this, it sees the filesystem as read-only and
> skips releasing the freeze semaphores.
>
> Fix this by adding the missing thaw_super() rollback in fs_bdev_freeze()
> when sync_blockdev() fails. Additionally, modify the exfat error handler to
> set EXFAT_FLAGS_SHUTDOWN instead of directly setting SB_RDONLY, which
> prevents confusing the VFS freeze logic and allows thaw_super() to
> correctly release the semaphores.
>
> Fixes: 49ef8832fb1a ("bdev: implement freeze and thaw holder operations")
> Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot
> Reported-by: syzbot+823cd0d24881f21ab9f1@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=823cd0d24881f21ab9f1
> Link: https://syzkaller.appspot.com/ai_job?id=431fcee8-0777-4619-a114-4a86af680864
> To: "Christian Brauner" <brauner@kernel.org>
> To: "Namjae Jeon" <linkinjeon@kernel.org>
> To: <linux-fsdevel@vger.kernel.org>
> To: "Sungjong Seo" <sj1557.seo@samsung.com>
> To: "Alexander Viro" <viro@zeniv.linux.org.uk>
> Cc: "Jan Kara" <jack@suse.cz>
> Cc: <linux-kernel@vger.kernel.org>
> Cc: "Yuezhang Mo" <yuezhang.mo@sony.com>
>
> ---
> diff --git a/fs/exfat/misc.c b/fs/exfat/misc.c
> index 6f11a96a4..dbb3b2907 100644
> --- a/fs/exfat/misc.c
> +++ b/fs/exfat/misc.c
> @@ -41,7 +41,14 @@ void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
>   		panic("exFAT-fs (%s): fs panic from previous error\n",
>   			sb->s_id);
>   	} else if (opts->errors == EXFAT_ERRORS_RO && !sb_rdonly(sb)) {
> -		sb->s_flags |= SB_RDONLY;
> +		set_bit(EXFAT_FLAGS_SHUTDOWN, &EXFAT_SB(sb)->s_exfat_flags);
> +		/*
> +		 * We have already set EXFAT_FLAGS_SHUTDOWN flag to stop all updates
> +		 * to filesystem, so it doesn't need to set SB_RDONLY flag here
> +		 * because the flag should be set covered w/ sb->s_umount semaphore
> +		 * via remount procedure, otherwise, it will confuse code like
> +		 * freeze_super() which will lead to deadlocks and other problems.
> +		 */
>   		exfat_err(sb, "Filesystem has been set read-only");
>   	}
>   }
> diff --git a/fs/super.c b/fs/super.c
> index a8fd61136..909d8b9ab 100644
> --- a/fs/super.c
> +++ b/fs/super.c
> @@ -1481,8 +1481,23 @@ static int fs_bdev_freeze(struct block_device *bdev)
>   	else
>   		error = freeze_super(sb,
>   				FREEZE_MAY_NEST | FREEZE_HOLDER_USERSPACE, NULL);
> -	if (!error)
> +	if (!error) {
>   		error = sync_blockdev(bdev);
> +		if (error) {
> +			if (sb->s_op->thaw_super)
> +				(void)sb->s_op->thaw_super(
> +					sb,
> +					FREEZE_MAY_NEST |
> +						FREEZE_HOLDER_USERSPACE,
> +					NULL);
> +			else
> +				(void)thaw_super(
> +					sb,
> +					FREEZE_MAY_NEST |
> +						FREEZE_HOLDER_USERSPACE,
> +					NULL);
> +		}
> +	}
>   	deactivate_super(sb);
>   	return error;
>   }
>
>
> base-commit: 1590cf0329716306e948a8fc29f1d3ee87d3989f

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-08-06 10:23 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-20 14:25 [PATCH RFC] fs: fix superblock freeze rollback on sync_blockdev failure syzbot
2026-08-06 10:22 ` Uladzislau Zhauniarovich

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.