[PATCH] bcachefs: Check and reset ro_ref in bch2_fsck_thread_exit
From: Edward Adam Davis
Date: Mon Jun 17 2024 - 09:02:23 EST
The following is the normal execution situation:
CPU1 CPU2 CPU3
====================== ========================= =====
bch2_run_thread_with_file
bch2_ioctl_fsck_online
bch2_fsck_online_thread_fn
bch2_fsck_thread_exit
cleanup_mnt
deactivate_super
deactivate_locked_super
bch2_kill_sb
generic_shutdown_super
bch2_put_super
__bch2_fs_stop
If the execution of bch2_fsck_online_thread_fn is later than that of
bch2_fsck_thread_exit, it will result in the ro_ref value being greater
than 1, when executing __bch2_fs_stop, the wait_event wait timeout will
occur due to the fact that the ro_ref value can never be 0.
The solution is to check the ro_ref value when exiting the fsck thread,
and if it is greater than 1, set it to 1 to avoid timeouts in __bch2_fs
_stop due to the ro_ref value never being able to be 0.
Fixes: 267b801fda10 ("bcachefs: BCH_IOCTL_FSCK_ONLINE")
Reported-by: syzbot+6d3e28b33490b3085412@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=6d3e28b33490b3085412
Signed-off-by: Edward Adam Davis <eadavis@xxxxxx>
---
fs/bcachefs/chardev.c | 5 ++++
1 file changed, 5 insertions(+)
diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c
index 9e54323f0f5f..487a01db2b72 100644
--- a/fs/bcachefs/chardev.c
+++ b/fs/bcachefs/chardev.c
@@ -135,6 +135,11 @@ struct fsck_thread {
static void bch2_fsck_thread_exit(struct thread_with_stdio *_thr)
{
struct fsck_thread *thr = container_of(_thr, struct fsck_thread, thr);
+ struct bch_fs *c = thr->c;
+
+ if (refcount_read(&c->ro_ref) > 1)
+ refcount_set(&c->ro_ref, 1);
+
kfree(thr);
}
--
2.43.0