* [PATCH v4 1/2] workqueue: Make alloc_workqueue() unbound by default
2026-10-15 14:01 [PATCH v4 0/2] workqueue: Make WQ_UNBOUND the default behavior Marco Crivellari
@ 2026-10-15 14:01 ` Marco Crivellari
2026-10-16 11:45 ` Breno Leitao
2026-10-16 15:53 ` Breno Leitao
2026-10-15 14:01 ` [PATCH v4 2/2] doc: Update WQ_UNBOUND and WQ_BH documentation Marco Crivellari
2026-10-16 18:03 ` [PATCH v4 0/2] workqueue: Make WQ_UNBOUND the default behavior Tejun Heo
2 siblings, 2 replies; 10+ messages in thread
From: Marco Crivellari @ 2026-10-15 14:01 UTC (permalink / raw)
To: linux-kernel
Cc: Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
Sebastian Andrzej Siewior, Marco Crivellari, Michal Hocko,
Breno Leitao
Currently alloc_workqueue() ensure that one among WQ_PERCPU or WQ_UNBOUND
is present. Now every user has one among these two flags.
In order to achive the future goal of removing WQ_UNBOUND from the code,
start changing the default behavior making alloc_workqueue() act this way:
- if WQ_PERCPU and WQ_UNBOUND are present: remove WQ_PERCPU (as before)
- if neither are present: add WQ_UNBOUND
BH workqueues (WQ_BH) are always per-CPU and can't be unbound, so
WQ_PERCPU is now unconditionally forced for them before the above
defaulting logic runs.
The WARN_ONCE() when neither flags are present has been removed and it has
been replaced by pr_warn_once(): from now on, every alloc_users()
without WQ_PERCPU will be considered unbound.
The pr_warn_once() will be removed along with WQ_UNBOUND in the future.
Link: https://lore.kernel.org/all/20250221112003.1dSuoGyc@linutronix.de/
Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
---
kernel/workqueue.c | 44 ++++++++++++++++++++++++++++----------------
1 file changed, 28 insertions(+), 16 deletions(-)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index c56c042d1c35..aba94a8e0c38 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -5895,12 +5895,33 @@ static struct workqueue_struct *__alloc_workqueue(const char *fmt,
struct workqueue_struct *wq;
size_t wq_size;
int name_len;
+ bool wq_unbound_by_default = false;
+ bool wq_dropped_percpu = false;
if (flags & WQ_BH) {
if (WARN_ON_ONCE(flags & ~__WQ_BH_ALLOWS))
return NULL;
if (WARN_ON_ONCE(max_active))
return NULL;
+ flags |= WQ_PERCPU;
+ }
+
+ /*
+ * Every caller that doesn't explicitly specify WQ_PERCPU will be
+ * unbound (WQ_UNBOUND) by default.
+ *
+ * If both flags are present at the same time, WQ_PERCPU will be
+ * removed.
+ *
+ * This must happen before wq_size is computed below, since that
+ * depends on the finalized WQ_UNBOUND flag.
+ */
+ if (unlikely(!(flags & (WQ_UNBOUND | WQ_PERCPU)))) {
+ flags |= WQ_UNBOUND;
+ wq_unbound_by_default = true;
+ } else if (unlikely((flags & WQ_PERCPU) && (flags & WQ_UNBOUND))) {
+ flags &= ~WQ_PERCPU;
+ wq_dropped_percpu = true;
}
/* see the comment above the definition of WQ_POWER_EFFICIENT */
@@ -5927,22 +5948,13 @@ static struct workqueue_struct *__alloc_workqueue(const char *fmt,
pr_warn_once("workqueue: name exceeds WQ_NAME_LEN. Truncating to: %s\n",
wq->name);
- /*
- * One among WQ_PERCPU and WQ_UNBOUND must be set, but not both.
- * - If neither is set, default to WQ_PERCPU
- * - If both are set, default to WQ_UNBOUND
- *
- * This code can be removed after workqueue are unbound by default
- */
- if (unlikely(!(flags & (WQ_UNBOUND | WQ_PERCPU)))) {
- WARN_ONCE(1, "workqueue: %s is using neither WQ_PERCPU or WQ_UNBOUND. "
- "Setting WQ_PERCPU.\n", wq->name);
- flags |= WQ_PERCPU;
- } else if (unlikely((flags & WQ_PERCPU) && (flags & WQ_UNBOUND))) {
- WARN_ONCE(1, "workqueue: %s uses both WQ_PERCPU and WQ_UNBOUND. "
- "Dropped WQ_PERCPU, keeping WQ_UNBOUND.\n", wq->name);
- flags &= ~WQ_PERCPU;
- }
+ if (unlikely(wq_unbound_by_default))
+ pr_warn_once("workqueue: %s is using neither WQ_PERCPU or WQ_UNBOUND. "
+ "Setting WQ_UNBOUND.\n", wq->name);
+
+ WARN_ONCE(wq_dropped_percpu,
+ "workqueue: %s uses both WQ_PERCPU and WQ_UNBOUND. "
+ "Dropped WQ_PERCPU, keeping WQ_UNBOUND.\n", wq->name);
if (flags & WQ_BH) {
/*
--
2.55.0
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v4 1/2] workqueue: Make alloc_workqueue() unbound by default
2026-10-15 14:01 ` [PATCH v4 1/2] workqueue: Make alloc_workqueue() unbound by default Marco Crivellari
@ 2026-10-16 11:45 ` Breno Leitao
2026-10-16 12:57 ` Marco Crivellari
2026-10-16 15:53 ` Breno Leitao
1 sibling, 1 reply; 10+ messages in thread
From: Breno Leitao @ 2026-10-16 11:45 UTC (permalink / raw)
To: Marco Crivellari
Cc: linux-kernel, Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
Sebastian Andrzej Siewior, Michal Hocko
On Thu, Oct 15, 2026 at 04:01:47PM +0200, Marco Crivellari wrote:
> + if (unlikely(wq_unbound_by_default))
> + pr_warn_once("workqueue: %s is using neither WQ_PERCPU or WQ_UNBOUND. "
> + "Setting WQ_UNBOUND.\n", wq->name);
Why do we need to warn here? With this new approach, shouldn't users be
able to rely on WQ_UNBOUND being the default and leave it out?
Thanks,
--breno
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v4 1/2] workqueue: Make alloc_workqueue() unbound by default
2026-10-16 11:45 ` Breno Leitao
@ 2026-10-16 12:57 ` Marco Crivellari
0 siblings, 0 replies; 10+ messages in thread
From: Marco Crivellari @ 2026-10-16 12:57 UTC (permalink / raw)
To: Breno Leitao
Cc: linux-kernel, Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
Sebastian Andrzej Siewior, Michal Hocko
On Fri, Oct 16, 2026 at 1:45 PM Breno Leitao <leitao@debian.org> wrote:
>
> On Thu, Oct 15, 2026 at 04:01:47PM +0200, Marco Crivellari wrote:
> > + if (unlikely(wq_unbound_by_default))
> > + pr_warn_once("workqueue: %s is using neither WQ_PERCPU or WQ_UNBOUND. "
> > + "Setting WQ_UNBOUND.\n", wq->name);
>
> Why do we need to warn here? With this new approach, shouldn't users be
> able to rely on WQ_UNBOUND being the default and leave it out?
Yes, it was mostly to ensure users notice the change in behavior when
flags are not specified.
But I can remove it for the next version.
Thanks!
--
Marco Crivellari
SUSE Labs
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4 1/2] workqueue: Make alloc_workqueue() unbound by default
2026-10-15 14:01 ` [PATCH v4 1/2] workqueue: Make alloc_workqueue() unbound by default Marco Crivellari
2026-10-16 11:45 ` Breno Leitao
@ 2026-10-16 15:53 ` Breno Leitao
2026-10-16 16:18 ` Marco Crivellari
1 sibling, 1 reply; 10+ messages in thread
From: Breno Leitao @ 2026-10-16 15:53 UTC (permalink / raw)
To: Marco Crivellari
Cc: linux-kernel, Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
Sebastian Andrzej Siewior, Michal Hocko
On Thu, Oct 15, 2026 at 04:01:47PM +0200, Marco Crivellari wrote:
> Currently alloc_workqueue() ensure that one among WQ_PERCPU or WQ_UNBOUND
> is present. Now every user has one among these two flags.
>
> In order to achive the future goal of removing WQ_UNBOUND from the code,
> start changing the default behavior making alloc_workqueue() act this way:
>
> - if WQ_PERCPU and WQ_UNBOUND are present: remove WQ_PERCPU (as before)
> - if neither are present: add WQ_UNBOUND
>
> BH workqueues (WQ_BH) are always per-CPU and can't be unbound, so
> WQ_PERCPU is now unconditionally forced for them before the above
> defaulting logic runs.
>
> The WARN_ONCE() when neither flags are present has been removed and it has
> been replaced by pr_warn_once(): from now on, every alloc_users()
> without WQ_PERCPU will be considered unbound.
>
> The pr_warn_once() will be removed along with WQ_UNBOUND in the future.
>
> Link: https://lore.kernel.org/all/20250221112003.1dSuoGyc@linutronix.de/
> Suggested-by: Tejun Heo <tj@kernel.org>
> Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Reviewed-by: Breno Leitao <leitao@debian.org>
> @@ -5895,12 +5895,33 @@ static struct workqueue_struct *__alloc_workqueue(const char *fmt,
> struct workqueue_struct *wq;
> size_t wq_size;
> int name_len;
> + bool wq_unbound_by_default = false;
> + bool wq_dropped_percpu = false;
Nit: I think these declarations would look better in reverse xmas tree
order. I know Tejun doesn't feel strongly about it, so it's just a nit.
--breno
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4 1/2] workqueue: Make alloc_workqueue() unbound by default
2026-10-16 15:53 ` Breno Leitao
@ 2026-10-16 16:18 ` Marco Crivellari
2026-10-16 16:19 ` Marco Crivellari
0 siblings, 1 reply; 10+ messages in thread
From: Marco Crivellari @ 2026-10-16 16:18 UTC (permalink / raw)
To: Breno Leitao
Cc: linux-kernel, Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
Sebastian Andrzej Siewior, Michal Hocko
On Fri, Oct 16, 2026 at 5:54 PM Breno Leitao <leitao@debian.org> wrote:
> [...]
> > @@ -5895,12 +5895,33 @@ static struct workqueue_struct *__alloc_workqueue(const char *fmt,
> > struct workqueue_struct *wq;
> > size_t wq_size;
> > int name_len;
> > + bool wq_unbound_by_default = false;
> > + bool wq_dropped_percpu = false;
>
> Nit: I think these declarations would look better in reverse xmas tree
> order. I know Tejun doesn't feel strongly about it, so it's just a nit.
>
> --breno
Cool, thanks for the hint, I will change this along with the removal
of pr_warn_once().
--
Marco Crivellari
SUSE Labs
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4 1/2] workqueue: Make alloc_workqueue() unbound by default
2026-10-16 16:18 ` Marco Crivellari
@ 2026-10-16 16:19 ` Marco Crivellari
0 siblings, 0 replies; 10+ messages in thread
From: Marco Crivellari @ 2026-10-16 16:19 UTC (permalink / raw)
To: Breno Leitao
Cc: linux-kernel, Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
Sebastian Andrzej Siewior, Michal Hocko
On Fri, Oct 16, 2026 at 6:18 PM Marco Crivellari
<marco.crivellari@suse.com> wrote:
>
> On Fri, Oct 16, 2026 at 5:54 PM Breno Leitao <leitao@debian.org> wrote:
> > [...]
> > > @@ -5895,12 +5895,33 @@ static struct workqueue_struct *__alloc_workqueue(const char *fmt,
> > > struct workqueue_struct *wq;
> > > size_t wq_size;
> > > int name_len;
> > > + bool wq_unbound_by_default = false;
> > > + bool wq_dropped_percpu = false;
> >
> > Nit: I think these declarations would look better in reverse xmas tree
> > order. I know Tejun doesn't feel strongly about it, so it's just a nit.
> >
> > --breno
>
> Cool, thanks for the hint, I will change this along with the removal
> of pr_warn_once().
>
Oh wait: only one of the bool, the other is going away with the
removal of the pr_warn_once().
--
Marco Crivellari
SUSE Labs
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v4 2/2] doc: Update WQ_UNBOUND and WQ_BH documentation
2026-10-15 14:01 [PATCH v4 0/2] workqueue: Make WQ_UNBOUND the default behavior Marco Crivellari
2026-10-15 14:01 ` [PATCH v4 1/2] workqueue: Make alloc_workqueue() unbound by default Marco Crivellari
@ 2026-10-15 14:01 ` Marco Crivellari
2026-10-16 15:16 ` Breno Leitao
2026-10-16 18:03 ` [PATCH v4 0/2] workqueue: Make WQ_UNBOUND the default behavior Tejun Heo
2 siblings, 1 reply; 10+ messages in thread
From: Marco Crivellari @ 2026-10-15 14:01 UTC (permalink / raw)
To: linux-kernel
Cc: Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
Sebastian Andrzej Siewior, Marco Crivellari, Michal Hocko,
Breno Leitao
When WQ_PERCPU is not present the default behavior is now WQ_UNBOUND,
so update the documentation, reflecting this change.
WQ_BH workqueues are the exception to this rule: they are always
per-CPU and can't be unbound, so WQ_PERCPU is implicitly set for them
regardless of what the caller passes. Update the WQ_BH section
accordingly, as WQ_HIGHPRI is no longer the only additional flag
involved.
Link: https://lore.kernel.org/all/20250221112003.1dSuoGyc@linutronix.de/
Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
---
Documentation/core-api/workqueue.rst | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/Documentation/core-api/workqueue.rst b/Documentation/core-api/workqueue.rst
index bb770f556568..76b70e7f4e3f 100644
--- a/Documentation/core-api/workqueue.rst
+++ b/Documentation/core-api/workqueue.rst
@@ -177,8 +177,9 @@ resources, scheduled and executed.
workqueues are always per-CPU and all BH work items are executed in the
queueing CPU's softirq context in the queueing order.
- All BH workqueues must have 0 ``max_active`` and ``WQ_HIGHPRI`` is the
- only allowed additional flag.
+ All BH workqueues must have 0 ``max_active``. ``WQ_HIGHPRI`` and
+ ``WQ_PERCPU`` are the only permitted flags. ``WQ_PERCPU`` is enforced by
+ default as BH workqueueus cannot be unbound.
BH work items cannot sleep. All other features such as delayed queueing,
flushing and canceling are supported.
@@ -206,6 +207,10 @@ resources, scheduled and executed.
* Long running CPU intensive workloads which can be better
managed by the system scheduler.
+ Workqueue without ``WQ_PERCPU`` are unbound by default, with the
+ exception of ``WQ_BH`` workqueues, which always have ``WQ_PERCPU``
+ set since they can't be unbound.
+
``WQ_FREEZABLE``
A freezable wq participates in the freeze phase of the system
suspend operations. Work items on the wq are drained and no
--
2.55.0
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v4 2/2] doc: Update WQ_UNBOUND and WQ_BH documentation
2026-10-15 14:01 ` [PATCH v4 2/2] doc: Update WQ_UNBOUND and WQ_BH documentation Marco Crivellari
@ 2026-10-16 15:16 ` Breno Leitao
0 siblings, 0 replies; 10+ messages in thread
From: Breno Leitao @ 2026-10-16 15:16 UTC (permalink / raw)
To: Marco Crivellari
Cc: linux-kernel, Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
Sebastian Andrzej Siewior, Michal Hocko
On Thu, Oct 15, 2026 at 04:01:48PM +0200, Marco Crivellari wrote:
> When WQ_PERCPU is not present the default behavior is now WQ_UNBOUND,
> so update the documentation, reflecting this change.
>
> WQ_BH workqueues are the exception to this rule: they are always
> per-CPU and can't be unbound, so WQ_PERCPU is implicitly set for them
> regardless of what the caller passes. Update the WQ_BH section
> accordingly, as WQ_HIGHPRI is no longer the only additional flag
> involved.
>
> Link: https://lore.kernel.org/all/20250221112003.1dSuoGyc@linutronix.de/
> Suggested-by: Tejun Heo <tj@kernel.org>
> Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Reviewed-by: Breno Leitao <leitao@debian.org>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4 0/2] workqueue: Make WQ_UNBOUND the default behavior
2026-10-15 14:01 [PATCH v4 0/2] workqueue: Make WQ_UNBOUND the default behavior Marco Crivellari
2026-10-15 14:01 ` [PATCH v4 1/2] workqueue: Make alloc_workqueue() unbound by default Marco Crivellari
2026-10-15 14:01 ` [PATCH v4 2/2] doc: Update WQ_UNBOUND and WQ_BH documentation Marco Crivellari
@ 2026-10-16 18:03 ` Tejun Heo
2 siblings, 0 replies; 10+ messages in thread
From: Tejun Heo @ 2026-10-16 18:03 UTC (permalink / raw)
To: Marco Crivellari
Cc: linux-kernel, Lai Jiangshan, Frederic Weisbecker,
Sebastian Andrzej Siewior, Michal Hocko, Breno Leitao
Hello, Marco.
The following is a Claude-generated review.
On Thu, Oct 15, 2026 at 04:01:46PM +0200, Marco Crivellari wrote:
> Currently alloc_workqueue() make sure one among WQ_UNBOUND or WQ_PERCPU is
> present. This is enforced warning and setting WQ_PERCPU as default when
> alloc_workqueue() without WQ_PERCPU or WQ_UNBOUND.
- 1/2: The description gives the future removal of WQ_UNBOUND as the only
reason. Can it lead with why unbound should be the default, as
dadb3ebcf395 ("workqueue: WQ_PERCPU added to alloc_workqueue users")
does?
Moving the defaulting above the wq_size computation is the one subtle
point. Maybe add a sentence on it to the description?
The new comment says WQ_UNBOUND is final at that point, but the
WQ_POWER_EFFICIENT block right below can still set it. The first two
paragraphs restate the if/else. Maybe trim it to the ordering
constraint against wq_size?
unlikely() on the neither-flag branch now marks the path that's meant
to become the default. Maybe drop it?
The WQ_POWER_EFFICIENT comment in include/linux/workqueue.h says such
workqueues are per-cpu by default. With this patch, one without
WQ_PERCPU is unbound regardless of workqueue.power_efficient. All
in-tree users pass WQ_PERCPU, so only the text needs updating.
Typos: "achive", "alloc_users()" (alloc_workqueue() users), "ensure" ->
"ensures", "neither flags are" -> "neither flag is".
- 2/2: The description says WQ_PERCPU is set for WQ_BH "regardless of
what the caller passes", but WQ_BH | WQ_UNBOUND is rejected by the
__WQ_BH_ALLOWS check.
"the only permitted flags" dropped "additional", but WQ_BH itself is
in __WQ_BH_ALLOWS too. Also, "workqueueus" typo.
The new WQ_UNBOUND sentence sits after the "useful for the following
cases" bullets and reads as one more case. Maybe move it to the top of
the entry? Also, "Workqueue without" -> "Workqueues without".
The Guidelines section still says "using a bound wq is usually
beneficial", which now contradicts the default. Can that be updated
too?
Nit: doc patches in this tree usually use the "workqueue: doc:" prefix.
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 10+ messages in thread