]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
workqueue: Add warnings and ensure one among WQ_PERCPU or WQ_UNBOUND is present
authorMarco Crivellari <marco.crivellari@suse.com>
Fri, 29 May 2026 13:06:40 +0000 (15:06 +0200)
committerTejun Heo <tj@kernel.org>
Fri, 29 May 2026 17:56:48 +0000 (07:56 -1000)
Currently there are no checks in order to enforce the use of one between
WQ_PERCPU or WQ_UNBOUND.

So act as following:
- if neither of them is present, set WQ_PERCPU
- if both are present, remove WQ_PERCPU

Along with this change, WARN_ONCE(), 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>
Signed-off-by: Tejun Heo <tj@kernel.org>
kernel/workqueue.c

index 088cd9b70fca3800ed60f7c3fc2a9c623d74066a..34c7c61c69aa8470b5b95ce57ebfaf6b9ab44f24 100644 (file)
@@ -5802,7 +5802,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)
@@ -5826,6 +5826,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 (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 (flags & WQ_BH) {
                /*
                 * BH workqueues always share a single execution context per CPU