Re: [PATCH] sched/cache: honor migrate_llc_task semantics in active load balance

From: Tim Chen

Date: Tue Aug 04 2026 - 15:43:08 EST


On Tue, 2026-08-04 at 23:07 +0800, Lu Wang wrote:
> Thanks, Chenyu.
>
> On Tue, 2026-08-04 at 16:17 +0800, Chen, Yu C wrote:
> > Yes. Besides, if I understand correctly, I suppose Lu Wang was
> > referring to the following scenario:
> >
> > src_rq has 2 runnable tasks, p1 and p2. p1 prefers dst_rq (dst_llc),
> > while p2 prefers src_rq (src_llc). In this case, migrate_llc_task is
> > set because src_rq has at least one task, p1, that wants to migrate
> > to dst_rq. In ALB, can_migrate_task() found p2 and returns true for p2
> > thus moves p2 out of its preferred LLC.
>
> That's exactly the scenario I had in mind.
>
> > Firstly, before ALB is triggered, the generic (passive) load balance is
> > triggered. It iterates over p1 and p2 on src_rq to see if it can move any
> > one of them to dst_rq, and in most cases it succeeds in moving p1 to
> > dst_cpu. As a result, ALB will not be triggered.
>
> My question is whether p1 is guaranteed to be moved out in passive
> LB. can_migrate_task()/migrate_degrades_llc() can reject p1 for
> several independent reasons — p1 pinned by cpus_ptr, p1 cache-hot
> with nr_balance_failed still below cache_nice_tries, or
> can_migrate_llc_task() returning something other than mig_forbid due
> to capacity constraints on dst_llc at that instant. If passive LB
> rejects p1 for any of these, ALB is still triggered with p1 and p2
> both present on src_rq.
>
> Can we conclude that p1 and p2 never end up on src_rq together when
> ALB fires? Or would it help to set up a simple experiment and trace
> this path to see whether it actually occurs in practice?
>
>

With 2 tasks on rq with different preference, active load balance could
pick the wrong task as can_migrate_task() checked in active load balance
will not consult migrate_degrades_llc(). How about the following patch
to fix this issue.

Tim

---
sched/cache: skip active load balance for LLC-motivated imbalance

For a migrate_llc_task imbalance, ALB runs detach_one_task() with
LBF_ACTIVE_LB set, which makes can_migrate_task() return early before
migrate_degrades_llc() is consulted. The victim is then the first
eligible task at the tail of cfs_tasks, regardless of LLC preference, so
ALB can pull a task that prefers the source LLC - the opposite of the
intent.

Skip ALB for migrate_llc_task when more than one CFS task is runnable,
and let a later balance pass pull a task that prefers the destination
LLC. With a single runnable task ALB is retained: that task prefers the
destination LLC and cannot migrate otherwise. Other ALB reasons (asym,
misfit, imbalanced, capacity) arrive with a different migration_type and
are unaffected.

Reported-by: Lu Wang <wanglu.priv@xxxxxxxxx>
Signed-off-by: Tim Chen <tim.c.chen@xxxxxxxxxxxxxxx>
---
kernel/sched/fair.c | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index d78467ec6ee1..615c9aeab621 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -10642,6 +10642,19 @@ alb_break_llc(struct lb_env *env)
return true;
}

+ /*
+ * When the imbalance is for migrate_llc_task, the ALB victim is
+ * chosen by can_migrate_task() under LBF_ACTIVE_LB, which ignores
+ * LLC preference and may pull a task that prefers the source LLC.
+ * Skip ALB when more than one CFS task is runnable, and let a
+ * later balance pass pull a task that prefers the destination LLC
+ * instead. With a single runnable task, ALB is still needed: that
+ * task prefers the destination LLC and cannot migrate otherwise.
+ */
+ if (env->migration_type == migrate_llc_task &&
+ env->src_rq->cfs.h_nr_runnable > 1)
+ return true;
+
return false;
}