]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
workqueue: Process extra works in rescuer on memory pressure
authorLai Jiangshan <jiangshan.ljs@antgroup.com>
Mon, 8 Dec 2025 13:25:19 +0000 (21:25 +0800)
committerTejun Heo <tj@kernel.org>
Mon, 8 Dec 2025 19:18:02 +0000 (09:18 -1000)
Make the rescuer process more work on the last pwq when there are no
more to rescue for the whole workqueue to help the regular workers in
case it is a temporary memory pressure relief and to reduce relapse.

Signed-off-by: Lai Jiangshan <jiangshan.ljs@antgroup.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
kernel/workqueue.c

index 7f9225936cd9848569b8cd8435647a6dffb63211..64fe81f30e852aacda7acc1074223e8aba48ecdb 100644 (file)
@@ -3461,10 +3461,37 @@ static bool assign_rescuer_work(struct pool_workqueue *pwq, struct worker *rescu
        struct work_struct *cursor = &pwq->mayday_cursor;
        struct work_struct *work, *n;
 
-       /* need rescue? */
-       if (!pwq->nr_active || !need_to_create_worker(pool))
+       /* have work items to rescue? */
+       if (!pwq->nr_active)
                return false;
 
+       /* need rescue? */
+       if (!need_to_create_worker(pool)) {
+               /*
+                * The pool has idle workers and doesn't need the rescuer, so it
+                * could simply return false here.
+                *
+                * However, the memory pressure might not be fully relieved.
+                * In PERCPU pool with concurrency enabled, having idle workers
+                * does not necessarily mean memory pressure is gone; it may
+                * simply mean regular workers have woken up, completed their
+                * work, and gone idle again due to concurrency limits.
+                *
+                * In this case, those working workers may later sleep again,
+                * the pool may run out of idle workers, and it will have to
+                * allocate new ones and wait for the timer to send mayday,
+                * causing unnecessary delay - especially if memory pressure
+                * was never resolved throughout.
+                *
+                * Do more work if memory pressure is still on to reduce
+                * relapse, using (pool->flags & POOL_MANAGER_ACTIVE), though
+                * not precisely, unless there are other PWQs needing help.
+                */
+               if (!(pool->flags & POOL_MANAGER_ACTIVE) ||
+                   !list_empty(&pwq->wq->maydays))
+                       return false;
+       }
+
        /* search from the start or cursor if available */
        if (list_empty(&cursor->entry))
                work = list_first_entry(&pool->worklist, struct work_struct, entry);