Here's my test program. Fengnan Chang 于2025年8月13日周三 20:02写道: > > After commit 0b2b066f8a85 ("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 > Reviewed-by: Diangang Li > --- > io_uring/io-wq.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > > diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c > index be91edf34f01..17dfaa0395c4 100644 > --- a/io_uring/io-wq.c > +++ b/io_uring/io-wq.c > @@ -357,6 +357,13 @@ static void create_worker_cb(struct callback_head *cb) > worker = container_of(cb, struct io_worker, create_work); > wq = worker->wq; > acct = worker->acct; > + > + rcu_read_lock(); > + do_create = !io_acct_activate_free_worker(acct); > + rcu_read_unlock(); > + if (!do_create) > + goto no_need_create; > + > raw_spin_lock(&acct->workers_lock); > > if (acct->nr_workers < acct->max_workers) { > @@ -367,6 +374,7 @@ static void create_worker_cb(struct callback_head *cb) > if (do_create) { > create_io_worker(wq, acct); > } else { > +no_need_create: > atomic_dec(&acct->nr_running); > io_worker_ref_put(wq); > } > -- > 2.20.1 >