Remove io_sq_thread_stop() from io_uring_flush() and just clear ->sqo_files, etc. instead. The first reason is that io_sq_thread_stop() null's ctx->sq_data without any lock held, that's racy. Also, it kills an SQPOLL thread even though there may be other processes wanting to continue using the io_uring instance. syzbot+b64c3e0ed576fc1d70e5@xxxxxxxxxxxxxxxxxxxxxxxxx Signed-off-by: Pavel Begunkov <asml.silence@xxxxxxxxx> --- fs/io_uring.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 6523500e4ae2..0ab0c3aefefd 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -8548,13 +8548,7 @@ static int io_uring_flush(struct file *file, void *data) { struct io_ring_ctx *ctx = file->private_data; - /* - * If the task is going away, cancel work it may have pending - */ - if (fatal_signal_pending(current) || (current->flags & PF_EXITING)) { - io_sq_thread_stop(ctx); - io_wq_cancel_cb(ctx->io_wq, io_cancel_task_cb, current, true); - } else if (ctx->flags & IORING_SETUP_SQPOLL) { + if (ctx->flags & IORING_SETUP_SQPOLL) { struct io_sq_data *sqd = ctx->sq_data; /* Ring is being closed, mark us as neding new assignment */ @@ -8568,6 +8562,12 @@ static int io_uring_flush(struct file *file, void *data) io_sq_thread_unpark(sqd); } + /* + * If the task is going away, cancel work it may have pending + */ + if (fatal_signal_pending(current) || (current->flags & PF_EXITING)) + io_wq_cancel_cb(ctx->io_wq, io_cancel_task_cb, current, true); + io_uring_cancel_files(ctx, data); return 0; -- 2.24.0