io_uring processed by tctx_task_work() can't get freed until the function returns. The reason is that io_ring_exit_work() executes a task_work after all references are put, where the task works execution is naturally serialised. Remove extra ctx pinning. Signed-off-by: Pavel Begunkov <asml.silence@xxxxxxxxx> --- fs/io_uring.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 719d62b6e3d5..202517860c83 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2004,9 +2004,14 @@ static void ctx_flush_and_put(struct io_ring_ctx *ctx) io_submit_flush_completions(ctx); mutex_unlock(&ctx->uring_lock); } - percpu_ref_put(&ctx->refs); } +/* + * All the ctxs we operate on here will stay alive until the function returns. + * That's because initially they're refcounted by the requests, and after + * io_ring_exit_work() synchronises with the current task by injecting and + * waiting for a task_work, which can't be executed until it returns. + */ static void tctx_task_work(struct callback_head *cb) { struct io_ring_ctx *ctx = NULL; @@ -2033,7 +2038,6 @@ static void tctx_task_work(struct callback_head *cb) if (req->ctx != ctx) { ctx_flush_and_put(ctx); ctx = req->ctx; - percpu_ref_get(&ctx->refs); } req->io_task_work.func(req); node = next; -- 2.32.0