diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index 615933a6e8ff..03724419c4e1 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -423,6 +423,17 @@ static __always_inline bool io_assign_file(struct io_kiocb *req, return !!req->file; } +static void io_req_queue_iowq_tw(struct io_tw_req tw_req, io_tw_token_t tw) +{ + struct io_kiocb *req = tw_req.req; + + io_tw_lock(req->ctx, tw); + if (unlikely(tw.cancel)) + io_req_defer_failed(req, -ECANCELED); + else + io_queue_iowq(req); +} + void io_queue_iowq(struct io_kiocb *req) { struct io_uring_task *tctx = req->tctx; @@ -430,10 +441,17 @@ void io_queue_iowq(struct io_kiocb *req) BUG_ON(!tctx); lockdep_assert_held(&req->ctx->uring_lock); - if ((current->flags & PF_KTHREAD) || !tctx->io_wq) { - io_req_task_queue_fail(req, -ECANCELED); + if (current->flags & PF_KTHREAD) + goto cancel; + + /* Only the submitter can safely access its io-wq during task exit. */ + if (unlikely(current != tctx->task)) { + req->io_task_work.func = io_req_queue_iowq_tw; + io_req_task_work_add(req); return; } + if (!tctx->io_wq) + goto cancel; /* * The file is looked up as late as possible, as it may be the result @@ -462,6 +480,9 @@ void io_queue_iowq(struct io_kiocb *req) trace_io_uring_queue_async_work(req, io_wq_is_hashed(&req->work)); io_wq_enqueue(tctx->io_wq, &req->work); + return; +cancel: + io_req_task_queue_fail(req, -ECANCELED); } unsigned io_linked_nr(struct io_kiocb *req)