diff options
author | Pavel Begunkov <asml.silence@gmail.com> | 2024-07-24 12:16:16 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-08-03 09:00:37 +0200 |
commit | 4d909285f6d28083229729dd51323486bda4783a (patch) | |
tree | 666ffc13ef92025b77399a1133819c891bfce9cc /io_uring | |
parent | 2a03e99ff9421d0be3a93a407b0f31748bed0312 (diff) | |
download | linux-stable-4d909285f6d28083229729dd51323486bda4783a.tar.gz linux-stable-4d909285f6d28083229729dd51323486bda4783a.tar.bz2 linux-stable-4d909285f6d28083229729dd51323486bda4783a.zip |
io_uring: tighten task exit cancellations
commit f8b632e89a101dae349a7b212c1771d7925f441b upstream.
io_uring_cancel_generic() should retry if any state changes like a
request is completed, however in case of a task exit it only goes for
another loop and avoids schedule() if any tracked (i.e. REQ_F_INFLIGHT)
request got completed.
Let's assume we have a non-tracked request executing in iowq and a
tracked request linked to it. Let's also assume
io_uring_cancel_generic() fails to find and cancel the request, i.e.
via io_run_local_work(), which may happen as io-wq has gaps.
Next, the request logically completes, io-wq still hold a ref but queues
it for completion via tw, which happens in
io_uring_try_cancel_requests(). After, right before prepare_to_wait()
io-wq puts the request, grabs the linked one and tries executes it, e.g.
arms polling. Finally the cancellation loop calls prepare_to_wait(),
there are no tw to run, no tracked request was completed, so the
tctx_inflight() check passes and the task is put to indefinite sleep.
Cc: stable@vger.kernel.org
Fixes: 3f48cf18f886c ("io_uring: unify files and task cancel")
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/acac7311f4e02ce3c43293f8f1fda9c705d158f1.1721819383.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'io_uring')
-rw-r--r-- | io_uring/io_uring.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index c326e2127dd4..896e707e0618 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -3071,8 +3071,11 @@ __cold void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd) bool loop = false; io_uring_drop_tctx_refs(current); + if (!tctx_inflight(tctx, !cancel_all)) + break; + /* read completions before cancelations */ - inflight = tctx_inflight(tctx, !cancel_all); + inflight = tctx_inflight(tctx, false); if (!inflight) break; |