Changing req->flags from any context other than where it's executed is racy. io_uring_cancel_files() does that for overflowed requests. Instead, keep track of already visited ones by initialising the overflow list node. Signed-off-by: Pavel Begunkov <asml.silence@xxxxxxxxx> --- fs/io_uring.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 3e406bc1f855..8eec2c5fbc9e 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -7873,8 +7873,11 @@ static void io_uring_cancel_files(struct io_ring_ctx *ctx, if (cancel_req->flags & REQ_F_OVERFLOW) { spin_lock_irq(&ctx->completion_lock); - list_del(&cancel_req->compl.list); - cancel_req->flags &= ~REQ_F_OVERFLOW; + + if (list_empty(&cancel_req->compl.list)) + goto out_wait; + list_del_init(&cancel_req->compl.list); + if (list_empty(&ctx->cq_overflow_list)) { clear_bit(0, &ctx->sq_check_overflow); clear_bit(0, &ctx->cq_check_overflow); @@ -7898,7 +7901,7 @@ static void io_uring_cancel_files(struct io_ring_ctx *ctx, io_wq_cancel_work(ctx->io_wq, &cancel_req->work); io_put_req(cancel_req); } - +out_wait: schedule(); finish_wait(&ctx->inflight_wait, &wait); } -- 2.24.0