mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v3 0/2] workqueue: Add warnings and check WQ flags usage
@ 2026-05-28 16:01 Marco Crivellari
  2026-05-28 16:01 ` [PATCH v3 1/2] workqueue: Add warnings and fallback if system_{unbound}_wq is used Marco Crivellari
  2026-05-28 16:01 ` [PATCH v3 2/2] workqueue: Add warnings and ensure one among WQ_PERCPU or WQ_UNBOUND is present Marco Crivellari
  0 siblings, 2 replies; 7+ messages in thread
From: Marco Crivellari @ 2026-05-28 16:01 UTC (permalink / raw)
  To: linux-kernel
  Cc: Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
	Sebastian Andrzej Siewior, Marco Crivellari, Michal Hocko,
	Breno Leitao

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. The detection of
deprecated workqueue is done using a new internal flag, called __WQ_DEPRECATED.

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.

Thanks!

Marco Crivellari (2):
  workqueue: Add warnings and fallback if system_{unbound}_wq is used
  workqueue: Add warnings and ensure one among WQ_PERCPU or WQ_UNBOUND
    is present

 include/linux/workqueue.h |  1 +
 kernel/workqueue.c        | 31 ++++++++++++++++++++++++++++---
 2 files changed, 29 insertions(+), 3 deletions(-)

---
Changes in v3:
- system_wq / system_unbond_wq not routed to the newer. The warnings have been simpliified
  keeping only one of them inside __queue_work() printing the work function.

- the deprecated status is detected using a new internal flag, called __WQ_DEPRECATED.

Link to v2: https://lore.kernel.org/all/20260526150041.365392-1-marco.crivellari@suse.com/

Changes in v2:
- rebased on v7.1-rc5

- fixed typo in the text

- cleared WQ_PERCPU when wq_pwer_efficient flag is set, to avoid triggering a warning

- if statement to route old workqueue to newer also added in queue_rcu_work()

Link to v1: https://lore.kernel.org/all/20260514092354.125149-1-marco.crivellari@suse.com/

-- 
2.54.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 1/2] workqueue: Add warnings and fallback if system_{unbound}_wq is used
  2026-05-28 16:01 [PATCH v3 0/2] workqueue: Add warnings and check WQ flags usage Marco Crivellari
@ 2026-05-28 16:01 ` Marco Crivellari
  2026-05-28 16:18   ` Breno Leitao
  2026-05-28 16:01 ` [PATCH v3 2/2] workqueue: Add warnings and ensure one among WQ_PERCPU or WQ_UNBOUND is present Marco Crivellari
  1 sibling, 1 reply; 7+ messages in thread
From: Marco Crivellari @ 2026-05-28 16:01 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.

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>
---
 include/linux/workqueue.h |  1 +
 kernel/workqueue.c        | 12 ++++++++++--
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 6177624539b3..a283766a192a 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -409,6 +409,7 @@ enum wq_flags {
 	__WQ_DRAINING		= 1 << 16, /* internal: workqueue is draining */
 	__WQ_ORDERED		= 1 << 17, /* internal: workqueue is ordered */
 	__WQ_LEGACY		= 1 << 18, /* internal: create*_workqueue() */
+	__WQ_DEPRECATED		= 1 << 19, /* internal: workqueue is deprecated */
 
 	/* BH wq only allows the following flags */
 	__WQ_BH_ALLOWS		= WQ_BH | WQ_HIGHPRI | WQ_PERCPU,
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 33b721a9af02..0b55f8009eed 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -2280,6 +2280,14 @@ static void __queue_work(int cpu, struct workqueue_struct *wq,
 	unsigned int work_flags;
 	unsigned int req_cpu = cpu;
 
+	/*
+	 * NOTE: Check whether the used workqueue is deprecated and warn
+	 */
+	if (unlikely(wq->flags & __WQ_DEPRECATED))
+		pr_warn_once("workqueue: work func %ps enqueued on deprecated workqueue. "
+			"Use system_{percpu|dfl}_wq instead.\n",
+			work->func);
+
 	/*
 	 * While a work item is PENDING && off queue, a task trying to
 	 * steal the PENDING will busy-loop waiting for it to either get
@@ -8037,12 +8045,12 @@ void __init workqueue_init_early(void)
 		ordered_wq_attrs[i] = attrs;
 	}
 
-	system_wq = alloc_workqueue("events", WQ_PERCPU, 0);
+	system_wq = alloc_workqueue("events", WQ_PERCPU | __WQ_DEPRECATED, 0);
 	system_percpu_wq = alloc_workqueue("events", WQ_PERCPU, 0);
 	system_highpri_wq = alloc_workqueue("events_highpri",
 					    WQ_HIGHPRI | WQ_PERCPU, 0);
 	system_long_wq = alloc_workqueue("events_long", WQ_PERCPU, 0);
-	system_unbound_wq = alloc_workqueue("events_unbound", WQ_UNBOUND, WQ_MAX_ACTIVE);
+	system_unbound_wq = alloc_workqueue("events_unbound", WQ_UNBOUND | __WQ_DEPRECATED, WQ_MAX_ACTIVE);
 	system_dfl_wq = alloc_workqueue("events_unbound", WQ_UNBOUND, WQ_MAX_ACTIVE);
 	system_freezable_wq = alloc_workqueue("events_freezable",
 					      WQ_FREEZABLE | WQ_PERCPU, 0);
-- 
2.54.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 2/2] workqueue: Add warnings and ensure one among WQ_PERCPU or WQ_UNBOUND is present
  2026-05-28 16:01 [PATCH v3 0/2] workqueue: Add warnings and check WQ flags usage Marco Crivellari
  2026-05-28 16:01 ` [PATCH v3 1/2] workqueue: Add warnings and fallback if system_{unbound}_wq is used Marco Crivellari
@ 2026-05-28 16:01 ` Marco Crivellari
  2026-05-28 16:25   ` Tejun Heo
  1 sibling, 1 reply; 7+ messages in thread
From: Marco Crivellari @ 2026-05-28 16:01 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 | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 0b55f8009eed..3e52956ce661 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -5826,7 +5826,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;
 
 	/* allocate wq and format name */
 	if (flags & WQ_UNBOUND)
@@ -5850,6 +5850,23 @@ 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. "
+			"Setting 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	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 1/2] workqueue: Add warnings and fallback if system_{unbound}_wq is used
  2026-05-28 16:01 ` [PATCH v3 1/2] workqueue: Add warnings and fallback if system_{unbound}_wq is used Marco Crivellari
@ 2026-05-28 16:18   ` Breno Leitao
  2026-05-29  8:30     ` Marco Crivellari
  0 siblings, 1 reply; 7+ messages in thread
From: Breno Leitao @ 2026-05-28 16:18 UTC (permalink / raw)
  To: Marco Crivellari
  Cc: linux-kernel, Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
	Sebastian Andrzej Siewior, Michal Hocko

On Thu, May 28, 2026 at 06:01:58PM +0000, Marco Crivellari wrote:
> 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.
> 
> 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>
> ---
>  include/linux/workqueue.h |  1 +
>  kernel/workqueue.c        | 12 ++++++++++--
>  2 files changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
> index 6177624539b3..a283766a192a 100644
> --- a/include/linux/workqueue.h
> +++ b/include/linux/workqueue.h
> @@ -409,6 +409,7 @@ enum wq_flags {
>  	__WQ_DRAINING		= 1 << 16, /* internal: workqueue is draining */
>  	__WQ_ORDERED		= 1 << 17, /* internal: workqueue is ordered */
>  	__WQ_LEGACY		= 1 << 18, /* internal: create*_workqueue() */
> +	__WQ_DEPRECATED		= 1 << 19, /* internal: workqueue is deprecated */
>  
>  	/* BH wq only allows the following flags */
>  	__WQ_BH_ALLOWS		= WQ_BH | WQ_HIGHPRI | WQ_PERCPU,
> diff --git a/kernel/workqueue.c b/kernel/workqueue.c
> index 33b721a9af02..0b55f8009eed 100644
> --- a/kernel/workqueue.c
> +++ b/kernel/workqueue.c
> @@ -2280,6 +2280,14 @@ static void __queue_work(int cpu, struct workqueue_struct *wq,
>  	unsigned int work_flags;
>  	unsigned int req_cpu = cpu;
>  
> +	/*
> +	 * NOTE: Check whether the used workqueue is deprecated and warn
> +	 */
> +	if (unlikely(wq->flags & __WQ_DEPRECATED))
> +		pr_warn_once("workqueue: work func %ps enqueued on deprecated workqueue. "
> +			"Use system_{percpu|dfl}_wq instead.\n",
> +			work->func);

Silly question, can we make this a build warning?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 2/2] workqueue: Add warnings and ensure one among WQ_PERCPU or WQ_UNBOUND is present
  2026-05-28 16:01 ` [PATCH v3 2/2] workqueue: Add warnings and ensure one among WQ_PERCPU or WQ_UNBOUND is present Marco Crivellari
@ 2026-05-28 16:25   ` Tejun Heo
  2026-05-29  8:48     ` Marco Crivellari
  0 siblings, 1 reply; 7+ messages in thread
From: Tejun Heo @ 2026-05-28 16:25 UTC (permalink / raw)
  To: Marco Crivellari
  Cc: linux-kernel, Lai Jiangshan, Frederic Weisbecker,
	Sebastian Andrzej Siewior, Michal Hocko, Breno Leitao

On Thu, May 28, 2026 at 06:01:59PM +0200, Marco Crivellari wrote:
...
> @@ -5850,6 +5850,23 @@ 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. "
> +			"Setting 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);
> +	}

Let's just WARN_ONCE() on these. These are outright bugs, right?

Thanks.

-- 
tejun

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 1/2] workqueue: Add warnings and fallback if system_{unbound}_wq is used
  2026-05-28 16:18   ` Breno Leitao
@ 2026-05-29  8:30     ` Marco Crivellari
  0 siblings, 0 replies; 7+ messages in thread
From: Marco Crivellari @ 2026-05-29  8:30 UTC (permalink / raw)
  To: Breno Leitao
  Cc: linux-kernel, Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
	Sebastian Andrzej Siewior, Michal Hocko

On Thu, May 28, 2026 at 6:18 PM Breno Leitao <leitao@debian.org> wrote:
>
> On Thu, May 28, 2026 at 06:01:58PM +0000, Marco Crivellari wrote:
> > 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.
> >
> > 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>
> > ---
> >  include/linux/workqueue.h |  1 +
> >  kernel/workqueue.c        | 12 ++++++++++--
> >  2 files changed, 11 insertions(+), 2 deletions(-)
> >
> > diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
> > index 6177624539b3..a283766a192a 100644
> > --- a/include/linux/workqueue.h
> > +++ b/include/linux/workqueue.h
> > @@ -409,6 +409,7 @@ enum wq_flags {
> >       __WQ_DRAINING           = 1 << 16, /* internal: workqueue is draining */
> >       __WQ_ORDERED            = 1 << 17, /* internal: workqueue is ordered */
> >       __WQ_LEGACY             = 1 << 18, /* internal: create*_workqueue() */
> > +     __WQ_DEPRECATED         = 1 << 19, /* internal: workqueue is deprecated */
> >
> >       /* BH wq only allows the following flags */
> >       __WQ_BH_ALLOWS          = WQ_BH | WQ_HIGHPRI | WQ_PERCPU,
> > diff --git a/kernel/workqueue.c b/kernel/workqueue.c
> > index 33b721a9af02..0b55f8009eed 100644
> > --- a/kernel/workqueue.c
> > +++ b/kernel/workqueue.c
> > @@ -2280,6 +2280,14 @@ static void __queue_work(int cpu, struct workqueue_struct *wq,
> >       unsigned int work_flags;
> >       unsigned int req_cpu = cpu;
> >
> > +     /*
> > +      * NOTE: Check whether the used workqueue is deprecated and warn
> > +      */
> > +     if (unlikely(wq->flags & __WQ_DEPRECATED))
> > +             pr_warn_once("workqueue: work func %ps enqueued on deprecated workqueue. "
> > +                     "Use system_{percpu|dfl}_wq instead.\n",
> > +                     work->func);
>
> Silly question, can we make this a build warning?

Mmh not sure. I tried something similar before the v1 to warn about
the workqueue, but I realized it doesn't work in every case, so at
least both should be kept if we go that way.

There is already something similar for users who try to flush the
system workqueue.

Thanks!

--

Marco Crivellari

SUSE Labs

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 2/2] workqueue: Add warnings and ensure one among WQ_PERCPU or WQ_UNBOUND is present
  2026-05-28 16:25   ` Tejun Heo
@ 2026-05-29  8:48     ` Marco Crivellari
  0 siblings, 0 replies; 7+ messages in thread
From: Marco Crivellari @ 2026-05-29  8:48 UTC (permalink / raw)
  To: Tejun Heo
  Cc: linux-kernel, Lai Jiangshan, Frederic Weisbecker,
	Sebastian Andrzej Siewior, Michal Hocko, Breno Leitao

Hi,

On Thu, May 28, 2026 at 6:25 PM Tejun Heo <tj@kernel.org> wrote:
>
> On Thu, May 28, 2026 at 06:01:59PM +0200, Marco Crivellari wrote:
> ...
> > @@ -5850,6 +5850,23 @@ 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. "
> > +                     "Setting 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);
> > +     }
>
> Let's just WARN_ONCE() on these. These are outright bugs, right?

Yes, they are. I will change this to use WARN_ONCE() for the next version.

Thanks!
-- 

Marco Crivellari

SUSE Labs

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-05-29  8:48 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-28 16:01 [PATCH v3 0/2] workqueue: Add warnings and check WQ flags usage Marco Crivellari
2026-05-28 16:01 ` [PATCH v3 1/2] workqueue: Add warnings and fallback if system_{unbound}_wq is used Marco Crivellari
2026-05-28 16:18   ` Breno Leitao
2026-05-29  8:30     ` Marco Crivellari
2026-05-28 16:01 ` [PATCH v3 2/2] workqueue: Add warnings and ensure one among WQ_PERCPU or WQ_UNBOUND is present Marco Crivellari
2026-05-28 16:25   ` Tejun Heo
2026-05-29  8:48     ` Marco Crivellari

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®