]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
io_uring/io-wq: re-check IO_WQ_BIT_EXIT for each linked work item
authorRunyu Xiao <runyu.xiao@seu.edu.cn>
Wed, 27 May 2026 17:22:03 +0000 (01:22 +0800)
committerJens Axboe <axboe@kernel.dk>
Thu, 28 May 2026 14:06:22 +0000 (08:06 -0600)
commit 10dc95939817 ("io_uring/io-wq: check IO_WQ_BIT_EXIT inside work
run loop") fixed the obvious case where io_worker_handle_work() took one
exit-bit snapshot before draining pending work, but the fix stops one
level too early.

io_worker_handle_work() now re-checks IO_WQ_BIT_EXIT in its outer work
run loop, yet it still snapshots that bit once before processing a whole
dependent linked-work chain. If io_wq_exit_start() sets IO_WQ_BIT_EXIT
after the first linked item has started, the remaining linked items can
still reuse stale do_kill = false, skip IO_WQ_WORK_CANCEL, and continue
running after exit has begun.

Move the check further inside, so it covers linked items too. Note: this
is a syzbot special as it loves setting up tons of slow linked work on
weird devices like msr that take forever to read, and immediately close
the ring. Exit then takes a long time.

Fixes: 10dc95939817 ("io_uring/io-wq: check IO_WQ_BIT_EXIT inside work run loop")
Cc: stable@vger.kernel.org
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
Link: https://patch.msgid.link/20260527172203.2043962-1-runyu.xiao@seu.edu.cn
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/io-wq.c

index 7a9f94a0ce6f2f6a32d87c32900aa0f31509aa4a..15b35eb8d1f7efcaa29fe88d4496ccfc45d84468 100644 (file)
@@ -602,7 +602,6 @@ static void io_worker_handle_work(struct io_wq_acct *acct,
        struct io_wq *wq = worker->wq;
 
        do {
-               bool do_kill = test_bit(IO_WQ_BIT_EXIT, &wq->state);
                struct io_wq_work *work;
 
                /*
@@ -638,6 +637,7 @@ static void io_worker_handle_work(struct io_wq_acct *acct,
 
                /* handle a whole dependent link */
                do {
+                       bool do_kill = test_bit(IO_WQ_BIT_EXIT, &wq->state);
                        struct io_wq_work *next_hashed, *linked;
                        unsigned int work_flags = atomic_read(&work->flags);
                        unsigned int hash = __io_wq_is_hashed(work_flags)