diff options
| author | Shang En Sim <sim@shangen.org> | 2026-10-30 00:03:17 -0500 |
|---|---|---|
| committer | Jens Axboe <axboe@kernel.dk> | 2026-11-03 07:26:46 -0700 |
| commit | 9eff9c07e927dcd9c57150cd6fb3d4ec76f00480 (patch) | |
| tree | a336d66e203438b0d419ba8756b19dc556934f08 /tools/lib/python | |
| parent | 21ddbb14f7c3baab50a2a6c13ee375edc2bbe031 (diff) | |
io_uring/poll: cancel all matching requests in one pass
With IORING_ASYNC_CANCEL_ALL, __io_async_cancel() calls io_try_cancel()
until nothing is found, and io_poll_cancel() cancels one request per
call, starting each lookup at the beginning of the hash. A cancelled
request stays hashed until its task work runs, so every lookup walks
past the ones already cancelled. Cancelling K of N pending polls visits
about K*N/2 requests in one io_uring_enter(), with uring_lock held.
A single CANCEL_FD|ALL on 80000 polls on one eventfd takes 17.06s,
0.02s with this change. With voluntary preemption the soft lockup
watchdog fires:
watchdog: BUG: soft lockup - CPU#1 stuck for 26s! [repro:100]
RIP: 0010:io_cancel_req_match+0x19/0xa0
io_poll_cancel+0x73/0x170
io_try_cancel+0x7b/0xf0
__io_async_cancel+0x41/0x110
Walk the hash once and cancel every match, as io_cancel_remove() does
for futex and waitid. Cancel by user_data only needs its own bucket.
__io_async_cancel() still loops until nothing is found, so a request
that io-wq parks in the poll hash meanwhile is still cancelled.
A cancel that matches one request now walks the whole hash twice instead
of stopping at the match.
Cc: stable@vger.kernel.org
Fixes: 8e29da69fead ("io_uring: add support for IORING_ASYNC_CANCEL_ALL")
Signed-off-by: Shang En Sim <sim@shangen.org>
Link: https://patch.msgid.link/20261030050319.1448530-3-sim@shangen.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'tools/lib/python')
0 files changed, 0 insertions, 0 deletions
