Skip to content

Commit 9d83e1f

Browse files
Fengnan Changaxboe
authored andcommitted
io_uring/io-wq: add check free worker before create new worker
After commit 0b2b066 ("io_uring/io-wq: only create a new worker if it can make progress"), in our produce environment, we still observe that part of io_worker threads keeps creating and destroying. After analysis, it was confirmed that this was due to a more complex scenario involving a large number of fsync operations, which can be abstracted as frequent write + fsync operations on multiple files in a single uring instance. Since write is a hash operation while fsync is not, and fsync is likely to be suspended during execution, the action of checking the hash value in io_wqe_dec_running cannot handle such scenarios. Similarly, if hash-based work and non-hash-based work are sent at the same time, similar issues are likely to occur. Returning to the starting point of the issue, when a new work arrives, io_wq_enqueue may wake up free worker A, while io_wq_dec_running may create worker B. Ultimately, only one of A and B can obtain and process the task, leaving the other in an idle state. In the end, the issue is caused by inconsistent logic in the checks performed by io_wq_enqueue and io_wq_dec_running. Therefore, the problem can be resolved by checking for available workers in io_wq_dec_running. Signed-off-by: Fengnan Chang <changfengnan@bytedance.com> Reviewed-by: Diangang Li <lidiangang@bytedance.com> Link: https://lore.kernel.org/r/20250813120214.18729-1-changfengnan@bytedance.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 41b70df commit 9d83e1f

File tree

1 file changed

+8
-0
lines changed

1 file changed

+8
-0
lines changed

io_uring/io-wq.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,13 @@ static void create_worker_cb(struct callback_head *cb)
357357
worker = container_of(cb, struct io_worker, create_work);
358358
wq = worker->wq;
359359
acct = worker->acct;
360+
361+
rcu_read_lock();
362+
do_create = !io_acct_activate_free_worker(acct);
363+
rcu_read_unlock();
364+
if (!do_create)
365+
goto no_need_create;
366+
360367
raw_spin_lock(&acct->workers_lock);
361368

362369
if (acct->nr_workers < acct->max_workers) {
@@ -367,6 +374,7 @@ static void create_worker_cb(struct callback_head *cb)
367374
if (do_create) {
368375
create_io_worker(wq, acct);
369376
} else {
377+
no_need_create:
370378
atomic_dec(&acct->nr_running);
371379
io_worker_ref_put(wq);
372380
}

0 commit comments

Comments
 (0)