* [RFC PATCH 1/2] workqueue: Add warn and fallback if system_{unbound}_wq is used
2026-05-14 9:23 [RFC PATCH 0/2] workqueue: Add wornings and check WQ flags usage Marco Crivellari
@ 2026-05-14 9:23 ` Marco Crivellari
2026-05-14 9:23 ` [RFC PATCH 2/2] workqueue: Add warnings and ensure one among WQ_PERCPU or WQ_UNBOUND is present Marco Crivellari
2026-05-15 12:17 ` [RFC PATCH 0/2] workqueue: Add wornings and check WQ flags usage Breno Leitao
2 siblings, 0 replies; 6+ messages in thread
From: Marco Crivellari @ 2026-05-14 9:23 UTC (permalink / raw)
To: linux-kernel
Cc: Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
Sebastian Andrzej Siewior, Marco Crivellari, Michal Hocko,
Breno Leitao
Currently many users transitioned already to the new introduced workqueue
(system_percpu_wq, system_dfl_wq), but there are new users who still use the
older system_wq and system_unbound_wq.
This change try to push this transition forward, by warning whether the old
workqueus are used and redirecting them old used workqueue with the appropriate
new one.
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 | 54 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 3d2e3b2ec528..80d9c91ae606 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -2425,6 +2425,24 @@ bool queue_work_on(int cpu, struct workqueue_struct *wq,
bool ret = false;
unsigned long irq_flags;
+ /*
+ * NOTE: These checks are here to assure that no users will still
+ * rely on system_wq and system_unbound wq.
+ * They can be removed along with those workqueue when the
+ * time comes.
+ */
+ if (unlikely(wq == system_wq)) {
+ pr_warn_once("workqueue: system_wq will be removed shortly. "
+ "Use system_percpu_wq instead. Caller: %ps\n",
+ __builtin_return_address(0));
+ wq = system_percpu_wq;
+ } else if (unlikely(wq == system_unbound_wq)) {
+ pr_warn_once("workqueue: system_unbound_wq will be removed shortly. "
+ "Use system_dfl_wq instead. Caller: %ps\n",
+ __builtin_return_address(0));
+ wq = system_dfl_wq;
+ }
+
local_irq_save(irq_flags);
if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work)) &&
@@ -2592,6 +2610,24 @@ bool queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
bool ret = false;
unsigned long irq_flags;
+ /*
+ * NOTE: These checks are here to assure that no users will still
+ * rely on system_wq and system_unbound wq.
+ * They can be removed along with those workqueue when the
+ * time comes.
+ */
+ if (unlikely(wq == system_wq)) {
+ pr_warn_once("workqueue: system_wq will be removed shortly. "
+ "Use system_percpu_wq instead. Caller: %ps\n",
+ __builtin_return_address(0));
+ wq = system_percpu_wq;
+ } else if (unlikely(wq == system_unbound_wq)) {
+ pr_warn_once("workqueue: system_unbound_wq will be removed shortly. "
+ "Use system_dfl_wq instead. Caller: %ps\n",
+ __builtin_return_address(0));
+ wq = system_dfl_wq;
+ }
+
/* read the comment in __queue_work() */
local_irq_save(irq_flags);
@@ -2630,6 +2666,24 @@ bool mod_delayed_work_on(int cpu, struct workqueue_struct *wq,
unsigned long irq_flags;
bool ret;
+ /*
+ * NOTE: These checks are here to assure that no users will still
+ * rely on system_wq and system_unbound wq.
+ * They can be removed along with those workqueue when the
+ * time comes.
+ */
+ if (unlikely(wq == system_wq)) {
+ pr_warn_once("workqueue: system_wq will be removed shortly. "
+ "Use system_percpu_wq instead. Caller: %ps\n",
+ __builtin_return_address(0));
+ wq = system_percpu_wq;
+ } else if (unlikely(wq == system_unbound_wq)) {
+ pr_warn_once("workqueue: system_unbound_wq will be removed shortly. "
+ "Use system_dfl_wq instead. Caller: %ps\n",
+ __builtin_return_address(0));
+ wq = system_dfl_wq;
+ }
+
ret = work_grab_pending(&dwork->work, WORK_CANCEL_DELAYED, &irq_flags);
if (!clear_pending_if_disabled(&dwork->work))
--
2.54.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [RFC PATCH 2/2] workqueue: Add warnings and ensure one among WQ_PERCPU or WQ_UNBOUND is present
2026-05-14 9:23 [RFC PATCH 0/2] workqueue: Add wornings and check WQ flags usage Marco Crivellari
2026-05-14 9:23 ` [RFC PATCH 1/2] workqueue: Add warn and fallback if system_{unbound}_wq is used Marco Crivellari
@ 2026-05-14 9:23 ` Marco Crivellari
2026-05-15 9:09 ` Marco Crivellari
2026-05-15 12:17 ` [RFC PATCH 0/2] workqueue: Add wornings and check WQ flags usage Breno Leitao
2 siblings, 1 reply; 6+ messages in thread
From: Marco Crivellari @ 2026-05-14 9:23 UTC (permalink / raw)
To: linux-kernel
Cc: Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
Sebastian Andrzej Siewior, Marco Crivellari, Michal Hocko,
Breno Leitao
Currently there are no checks in order to enforce the use of WQ_PERCPU and
avoid this flag is used if WQ_UNBOUND is already present.
So act as following:
- if neither of them is present, set WQ_PERCPU
- if both are present, remove WQ_PERCPU
Along with this change, print a warning, so that the code still uses both or
neither of them, can be changed.
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 | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 80d9c91ae606..80e6efb4aa52 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -5882,6 +5882,24 @@ 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 (!(flags & (WQ_UNBOUND | WQ_PERCPU))) {
+ pr_warn_ratelimited("workqueue: %s is using neither WQ_PERCPU or WQ_UNBOUND. "
+ "Seting WQ_PERCPU.\n", wq->name);
+ flags |= WQ_PERCPU;
+ }
+ else if((flags & WQ_PERCPU) && (flags & WQ_UNBOUND)) {
+ pr_warn_ratelimited("workqueue: %s uses both WQ_PERCPU and WQ_UNBOUND. "
+ "Dropped WQ_PERCPU, keeping WQ_UNBOUND.\n", wq->name);
+ flags &= (~WQ_PERCPU);
+ }
+
if (flags & WQ_BH) {
/*
* BH workqueues always share a single execution context per CPU
--
2.54.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [RFC PATCH 2/2] workqueue: Add warnings and ensure one among WQ_PERCPU or WQ_UNBOUND is present
2026-05-14 9:23 ` [RFC PATCH 2/2] workqueue: Add warnings and ensure one among WQ_PERCPU or WQ_UNBOUND is present Marco Crivellari
@ 2026-05-15 9:09 ` Marco Crivellari
0 siblings, 0 replies; 6+ messages in thread
From: Marco Crivellari @ 2026-05-15 9:09 UTC (permalink / raw)
To: linux-kernel
Cc: Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
Sebastian Andrzej Siewior, Michal Hocko, Breno Leitao
On Thu, May 14, 2026 at 11:24 AM Marco Crivellari
<marco.crivellari@suse.com> wrote:
> [...]
> diff --git a/kernel/workqueue.c b/kernel/workqueue.c
> index 80d9c91ae606..80e6efb4aa52 100644
> --- a/kernel/workqueue.c
> +++ b/kernel/workqueue.c
> @@ -5882,6 +5882,24 @@ 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 (!(flags & (WQ_UNBOUND | WQ_PERCPU))) {
> + pr_warn_ratelimited("workqueue: %s is using neither WQ_PERCPU or WQ_UNBOUND. "
> + "Seting WQ_PERCPU.\n", wq->name);
> + flags |= WQ_PERCPU;
> + }
> + else if((flags & WQ_PERCPU) && (flags & WQ_UNBOUND)) {
> + pr_warn_ratelimited("workqueue: %s uses both WQ_PERCPU and WQ_UNBOUND. "
> + "Dropped WQ_PERCPU, keeping WQ_UNBOUND.\n", wq->name);
> + flags &= (~WQ_PERCPU);
> + }
> +
> if (flags & WQ_BH) {
> /*
> * BH workqueues always share a single execution context per CPU
That's very likely the check about power efficiency should be changed like this:
@@ -5804,7 +5804,7 @@ static struct workqueue_struct
*__alloc_workqueue(const char *fmt,
/* see the comment above the definition of WQ_POWER_EFFICIENT */
if ((flags & WQ_POWER_EFFICIENT) && wq_power_efficient)
- flags |= WQ_UNBOUND;
+ flags = (flags & ~WQ_PERCPU) | WQ_UNBOUND;
Otherwise, we'll have a warning in case WQ_PERCPU was present if
wq_power_efficient = true. I will fix this for v2.
--
Marco Crivellari
SUSE Labs
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC PATCH 0/2] workqueue: Add wornings and check WQ flags usage
2026-05-14 9:23 [RFC PATCH 0/2] workqueue: Add wornings and check WQ flags usage Marco Crivellari
2026-05-14 9:23 ` [RFC PATCH 1/2] workqueue: Add warn and fallback if system_{unbound}_wq is used Marco Crivellari
2026-05-14 9:23 ` [RFC PATCH 2/2] workqueue: Add warnings and ensure one among WQ_PERCPU or WQ_UNBOUND is present Marco Crivellari
@ 2026-05-15 12:17 ` Breno Leitao
2026-05-15 13:25 ` Marco Crivellari
2 siblings, 1 reply; 6+ messages in thread
From: Breno Leitao @ 2026-05-15 12:17 UTC (permalink / raw)
To: Marco Crivellari
Cc: linux-kernel, Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
Sebastian Andrzej Siewior, Michal Hocko
On Thu, May 14, 2026 at 11:23:52AM +0200, Marco Crivellari wrote:
> Hi,
>
> Currently system_wq and system_unbound_wq can still be used and no message
> is printed. To avoid further use of them, add a warning and route the
> workqueue on system_percpu_wq or system_dfl_wq.
>
> Similar scenario for WQ_PERCPU and WQ_UNBOUND. Currently there are still
> users that use alloc_workqueue(,0,). To avoid such situations, a couple
> of checks have been added:
>
> - if neither of the flag is present, set WQ_PERCPU
> - if both are present, remove WQ_PERCPU
>
> Along with these, a warning will be printed.
How many users will seee this warning once this patch lands?
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [RFC PATCH 0/2] workqueue: Add wornings and check WQ flags usage
2026-05-15 12:17 ` [RFC PATCH 0/2] workqueue: Add wornings and check WQ flags usage Breno Leitao
@ 2026-05-15 13:25 ` Marco Crivellari
0 siblings, 0 replies; 6+ messages in thread
From: Marco Crivellari @ 2026-05-15 13:25 UTC (permalink / raw)
To: Breno Leitao
Cc: linux-kernel, Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
Sebastian Andrzej Siewior, Michal Hocko
On Fri, May 15, 2026 at 2:17 PM Breno Leitao <leitao@debian.org> wrote:
>
> On Thu, May 14, 2026 at 11:23:52AM +0200, Marco Crivellari wrote:
> > Hi,
> >
> > Currently system_wq and system_unbound_wq can still be used and no message
> > is printed. To avoid further use of them, add a warning and route the
> > workqueue on system_percpu_wq or system_dfl_wq.
> >
> > Similar scenario for WQ_PERCPU and WQ_UNBOUND. Currently there are still
> > users that use alloc_workqueue(,0,). To avoid such situations, a couple
> > of checks have been added:
> >
> > - if neither of the flag is present, set WQ_PERCPU
> > - if both are present, remove WQ_PERCPU
> >
> > Along with these, a warning will be printed.
>
> How many users will seee this warning once this patch lands?
About WQ_*, I would say (currently, v7.1-rc3) there are 8 users, but 4
of them are accepted (2 by Tejun, because we didn't receive replies
for a long time) and the other 2 will likely be accepted in May (they
are new and were sent a few days ago).
About the deprecated workqueues:
system_wq: 8 (-3, accepted, 1 handled by Tejun)
system_unbound_wq: 19
Among the 19, 2 are new (recently introduced and still pending
changes), and Tejun handles other two of them. Note that 7 of the
remaining 15 are part of the same series.
I think the most important change, because it is also a blocker, is
requiring alloc_workqueue() users to have one of the flags. This will
allow us to switch to the unbound workqueue as default, removing
`WQ_UNBOUND` as well. We cannot of course do that now.
What do you think?
Thanks!
--
Marco Crivellari
SUSE Labs
^ permalink raw reply [flat|nested] 6+ messages in thread