[RFC PATCH 1/2] workqueue: Add warn and fallback if system_{unbound}_wq is used
From: Marco Crivellari
Date: Thu May 14 2026 - 05:25:07 EST
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@xxxxxxxxxxxxx/
Suggested-by: Tejun Heo <tj@xxxxxxxxxx>
Signed-off-by: Marco Crivellari <marco.crivellari@xxxxxxxx>
---
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