[PATCH 2/3] workqueue: Maintain pwq->total_in_flight

From: Tejun Heo

Date: Tue Sep 01 2026 - 17:11:00 EST


pwq_busy() scans all of pwq->nr_in_flight[] to tell whether anything is in
flight. Maintain the sum in pwq->total_in_flight, which fits in existing
padding, and test that instead.

Signed-off-by: Tejun Heo <tj@xxxxxxxxxx>
---
kernel/workqueue.c | 29 ++++++++++++++++++++++-------
1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 9c69efcf5e2e..d19d2e59ec05 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -274,6 +274,7 @@ struct pool_workqueue {
int work_color; /* L: current color */
int flush_color; /* L: flushing color */
int refcnt; /* L: reference count */
+ int total_in_flight; /* L: sum of nr_in_flight[] */
int nr_in_flight[WORK_NR_COLORS];
/* L: nr of in_flight works */
bool plugged; /* L: execution suspended */
@@ -2082,6 +2083,22 @@ static void pwq_dec_nr_active(struct pool_workqueue *pwq)
node_activate_pending_pwq(nna, pool);
}

+/**
+ * pwq_inc_nr_in_flight - increment pwq's nr_in_flight
+ * @pwq: pwq of interest
+ * @work_color: color of the work item being queued
+ *
+ * A work item or a barrier with @work_color is being queued to @pwq.
+ *
+ * CONTEXT:
+ * raw_spin_lock_irq(pool->lock).
+ */
+static void pwq_inc_nr_in_flight(struct pool_workqueue *pwq, int work_color)
+{
+ pwq->nr_in_flight[work_color]++;
+ pwq->total_in_flight++;
+}
+
/**
* pwq_dec_nr_in_flight - decrement pwq's nr_in_flight
* @pwq: pwq of interest
@@ -2106,6 +2123,7 @@ static void pwq_dec_nr_in_flight(struct pool_workqueue *pwq, unsigned long work_
pwq_dec_nr_active(pwq);

pwq->nr_in_flight[color]--;
+ pwq->total_in_flight--;

/* is flush in progress and are we at the flushing tip? */
if (likely(pwq->flush_color != color))
@@ -2455,7 +2473,7 @@ static void __queue_work(int cpu, struct workqueue_struct *wq,
if (WARN_ON(!list_empty(&work->entry)))
goto out;

- pwq->nr_in_flight[pwq->work_color]++;
+ pwq_inc_nr_in_flight(pwq, pwq->work_color);
work_flags = work_color_to_flags(pwq->work_color);

/*
@@ -4031,7 +4049,7 @@ static void insert_wq_barrier(struct pool_workqueue *pwq,
__set_bit(WORK_STRUCT_LINKED_BIT, bits);
}

- pwq->nr_in_flight[work_color]++;
+ pwq_inc_nr_in_flight(pwq, work_color);
work_flags |= work_color_to_flags(work_color);

insert_work(pwq, &barr->work, head, work_flags);
@@ -6098,11 +6116,8 @@ EXPORT_SYMBOL_GPL(alloc_workqueue_lockdep_map);

static bool pwq_busy(struct pool_workqueue *pwq)
{
- int i;
-
- for (i = 0; i < WORK_NR_COLORS; i++)
- if (pwq->nr_in_flight[i])
- return true;
+ if (pwq->total_in_flight)
+ return true;

if ((pwq != rcu_access_pointer(pwq->wq->dfl_pwq)) && (pwq->refcnt > 1))
return true;
--
2.55.0