Skip to contentSkip to conversation

io_uring/io-wq: fix `max_workers` breakage and `nr_workers` underflow

PATCH Applied Max Kellermann 3 participants 3 messages Sep 12, 2025 – Sep 15, 2025

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 io_uring/io-wq: fix `max_workers` breakage and `nr_workers` underflow

Commit 88e6c42e40de ("io_uring/io-wq: add check free worker before create new worker") reused the variable do_create for something else, abusing it for the free worker check.

This caused the value to effectively always be true at the time nr_workers < max_workers was checked, but it should really be false. This means the max_workers setting was ignored, and worse:
if the limit had already been reached, incrementing nr_workers was skipped even though another worker would be created.

When later lots of workers exit, the nr_workers field could easily underflow, making the problem worse because more and more workers would be created without incrementing nr_workers.

The simple solution is to use a different variable for the free worker check instead of using one variable for two different things.

Fixes 88e6c42e40de ("io_uring/io-wq: add check free worker before create new worker")
---
 io_uring/io-wq.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
io_uring/io-wq.c +3 -3
index 17dfaa0395c4..1d03b2fc4b25 100644
@@ -352,16 +352,16 @@ static void create_worker_cb(struct callback_head *cb)
 	struct io_wq *wq;
 
 	struct io_wq_acct *acct;
-	bool do_create = false;
+	bool activated_free_worker, do_create = false;
 
 	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);
+	activated_free_worker = io_acct_activate_free_worker(acct);
 	rcu_read_unlock();
-	if (!do_create)
+	if (activated_free_worker)
 		goto no_need_create;
 
 	raw_spin_lock(&acct->workers_lock);
Signature · 1 line
2.47.3
Reviewed-by on v1 1/1
#1 lore raw
Quoted 11 lines · Max Kellermann <[email protected]> 于2025年9月12日周五 08:06写道:

Commit 88e6c42e40de ("io_uring/io-wq: add check free worker before create new worker") reused the variable do_create for something else, abusing it for the free worker check.

This caused the value to effectively always be true at the time nr_workers < max_workers was checked, but it should really be false. This means the max_workers setting was ignored, and worse:
if the limit had already been reached, incrementing nr_workers was skipped even though another worker would be created.

Quoted 3 lines

When later lots of workers exit, the nr_workers field could easily underflow, making the problem worse because more and more workers would be created without incrementing nr_workers.

Thanks, my mistake.

Quoted 38 lines

The simple solution is to use a different variable for the free worker check instead of using one variable for two different things.

Fixes 88e6c42e40de ("io_uring/io-wq: add check free worker before create new worker")
---
 io_uring/io-wq.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
io_uring/io-wq.c +3 -4
index 17dfaa0395c4..1d03b2fc4b25 100644
@@ -352,16 +352,16 @@ static void create_worker_cb(struct callback_head *cb)
        struct io_wq *wq;
 
        struct io_wq_acct *acct;
-       bool do_create = false;
+       bool activated_free_worker, do_create = false;
 
        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);
+       activated_free_worker = io_acct_activate_free_worker(acct);
        rcu_read_unlock();
-       if (!do_create)
+       if (activated_free_worker)
                goto no_need_create;
 
        raw_spin_lock(&acct->workers_lock);
--

2.47.3

maintainer Applied
#2 lore raw
In reply to Max Kellermann
Quoted 11 lines · Max Kellermann

Commit 88e6c42e40de ("io_uring/io-wq: add check free worker before create new worker") reused the variable do_create for something else, abusing it for the free worker check.

This caused the value to effectively always be true at the time nr_workers < max_workers was checked, but it should really be false. This means the max_workers setting was ignored, and worse:
if the limit had already been reached, incrementing nr_workers was skipped even though another worker would be created.

[...]

Applied, thanks!

[1/1] io_uring/io-wq: fix max_workers breakage and nr_workers underflow
(no commit info)

Best regards,

Signature · 1 line
Jens Axboe