io_uring: fix poll_remove stalled req completion
authorPavel Begunkov <asml.silence@gmail.com>
Fri, 15 Mar 2024 15:29:51 +0000 (15:29 +0000)
committerJens Axboe <axboe@kernel.dk>
Fri, 15 Mar 2024 15:36:56 +0000 (09:36 -0600)
Taking the ctx lock is not enough to use the deferred request completion
infrastructure, it'll get queued into the list but no one would expect
it there, so it will sit there until next io_submit_flush_completions().
It's hard to care about the cancellation path, so complete it via tw.

Fixes: ef7dfac51d8ed ("io_uring/poll: serialize poll linked timer start with poll removal")
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/c446740bc16858f8a2a8dcdce899812f21d15f23.1710514702.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/poll.c

index 5f779139cae1849e30f6caaae484c060f938febc..6db1dcb2c7977662dc62127803d6bd1ef5d0b517 100644 (file)
@@ -996,7 +996,6 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
        struct io_hash_bucket *bucket;
        struct io_kiocb *preq;
        int ret2, ret = 0;
-       struct io_tw_state ts = { .locked = true };
 
        io_ring_submit_lock(ctx, issue_flags);
        preq = io_poll_find(ctx, true, &cd, &ctx->cancel_table, &bucket);
@@ -1045,7 +1044,8 @@ found:
 
        req_set_fail(preq);
        io_req_set_res(preq, -ECANCELED, 0);
-       io_req_task_complete(preq, &ts);
+       preq->io_task_work.func = io_req_task_complete;
+       io_req_task_work_add(preq);
 out:
        io_ring_submit_unlock(ctx, issue_flags);
        if (ret < 0) {