From: Lai Jiangshan <jiangshan.ljs@antgroup.com>
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 relief and to reduce relapse.
Also limit the number of extra works.
Signed-off-by: Lai Jiangshan <jiangshan.ljs@antgroup.com>
---
kernel/workqueue.c | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 9bc155545492..86acf2a9cd41 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -3473,10 +3473,30 @@ static bool assign_rescuer_work(struct pool_workqueue *pwq, struct worker *rescu
list_del_init(&cursor->entry);
}
- /* 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, and if the regular workers later
+ * go to sleep and the pool runs out of idle workers, mayday
+ * would be triggered again.
+ *
+ * Do more work even if it doesn't need rescue, to help the
+ * regular workers in case it is a temporary relief and to
+ * reduce relapse.
+ *
+ * Unless the limit is reached or there are other PWQs needing
+ * help.
+ */
+ if (limited || !list_empty(&pwq->wq->maydays))
+ return false;
+ }
+
/* try to assign a work to rescue */
list_for_each_entry_safe_from(work, n, &pool->worklist, entry) {
if (get_work_pwq(work) != pwq)
--
2.19.1.6.gb485710b
On Fri, Nov 21, 2025 at 10:57:20PM +0800, Lai Jiangshan wrote: > From: Lai Jiangshan <jiangshan.ljs@antgroup.com> > > 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 relief and to reduce relapse. > > Also limit the number of extra works. > > Signed-off-by: Lai Jiangshan <jiangshan.ljs@antgroup.com> Is this based on some empirical case? Can you give a concrete example? Thanks. -- tejun
On Sat, Nov 22, 2025 at 3:29 AM Tejun Heo <tj@kernel.org> wrote:
>
> On Fri, Nov 21, 2025 at 10:57:20PM +0800, Lai Jiangshan wrote:
> > From: Lai Jiangshan <jiangshan.ljs@antgroup.com>
> >
> > 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 relief and to reduce relapse.
> >
> > Also limit the number of extra works.
> >
> > Signed-off-by: Lai Jiangshan <jiangshan.ljs@antgroup.com>
>
> Is this based on some empirical case? Can you give a concrete example?
>
It is not a case observed in production, but it can be achieved by test.
If the pool is a PERCPU pool with concurrency enabled, having idle
workers does not necessarily mean memory pressure is relieved; it may
simply reflect regular workers waking up, completing work and going idle
due to concurrency.
In such a case, those working workers may later sleep again, the pool may
run out of idle workers, and it will need to allocate new one again, becoming
stalled and waiting for the rescuer. This can cause unnecessary delay,
especially if memory pressure was never resolved throughout.
Before patch 2/7, the rescuer processed all active work items
unconditionally, so this situation was less problematic.
But this patch does not really check if memory pressure is still on,
using (pool->flags & POOL_MANAGER_ACTIVE) can kind of
achieve it, though not precisely. There is never a precise way,
but the system has poured some resources to create the rescuer,
it is better to make the best use of it, like before patch 2/7.
this patch:
if (!pwq->nr_active)
return false;
if (!need_to_create_worker(pool)) {
if (limited || !list_empty(&pwq->wq->maydays))
return false;
}
with memory pressure test via POOL_MANAGER_ACTIVE:
if (!pwq->nr_active)
return false;
if (!need_to_create_worker(pool)) {
if (limited || !(pool->flags & POOL_MANAGER_ACTIVE) ||
!list_empty(&pwq->wq->maydays))
return false;
}
What do you think?
Thanks
Lai
Hello,
On Sat, Nov 22, 2025 at 03:07:25PM +0800, Lai Jiangshan wrote:
...
> But this patch does not really check if memory pressure is still on,
> using (pool->flags & POOL_MANAGER_ACTIVE) can kind of
> achieve it, though not precisely. There is never a precise way,
> but the system has poured some resources to create the rescuer,
> it is better to make the best use of it, like before patch 2/7.
>
> this patch:
> if (!pwq->nr_active)
> return false;
> if (!need_to_create_worker(pool)) {
> if (limited || !list_empty(&pwq->wq->maydays))
> return false;
> }
>
> with memory pressure test via POOL_MANAGER_ACTIVE:
>
> if (!pwq->nr_active)
> return false;
> if (!need_to_create_worker(pool)) {
> if (limited || !(pool->flags & POOL_MANAGER_ACTIVE) ||
> !list_empty(&pwq->wq->maydays))
> return false;
> }
>
> What do you think?
Yeah, POOL_MANAGER_ACTIVE seems like a more reliable condition to test.
Let's do that.
Thanks.
--
tejun
© 2016 - 2025 Red Hat, Inc.