]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
io_uring: allow io-wq workers to exit when unused
authorLi Chen <me@linux.beauty>
Mon, 2 Feb 2026 14:37:54 +0000 (22:37 +0800)
committerJens Axboe <axboe@kernel.dk>
Mon, 2 Feb 2026 15:11:42 +0000 (08:11 -0700)
io_uring keeps a per-task io-wq around, even when the task no longer has
any io_uring instances.

If the task previously used io_uring for file I/O, this can leave an
unrelated iou-wrk-* worker thread behind after the last io_uring
instance is gone.

When the last io_uring ctx is removed from the task context, mark the
io-wq exit-on-idle so workers can go away. Clear the flag on subsequent
io_uring usage.

Signed-off-by: Li Chen <me@linux.beauty>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/tctx.c

index 5b66755579c08fac74b77b3f76e51bdd6f5abf35..03c278aa58120fc2f4497a746d2e4ce5aee063c4 100644 (file)
@@ -122,6 +122,14 @@ int __io_uring_add_tctx_node(struct io_ring_ctx *ctx)
                                return ret;
                }
        }
+
+       /*
+        * Re-activate io-wq keepalive on any new io_uring usage. The wq may have
+        * been marked for idle-exit when the task temporarily had no active
+        * io_uring instances.
+        */
+       if (tctx->io_wq)
+               io_wq_set_exit_on_idle(tctx->io_wq, false);
        if (!xa_load(&tctx->xa, (unsigned long)ctx)) {
                node = kmalloc(sizeof(*node), GFP_KERNEL);
                if (!node)
@@ -183,6 +191,9 @@ __cold void io_uring_del_tctx_node(unsigned long index)
        if (tctx->last == node->ctx)
                tctx->last = NULL;
        kfree(node);
+
+       if (xa_empty(&tctx->xa) && tctx->io_wq)
+               io_wq_set_exit_on_idle(tctx->io_wq, true);
 }
 
 __cold void io_uring_clean_tctx(struct io_uring_task *tctx)