sched discussion
[PATCH] sched/cache: honor migrate_llc_task semantics in active load balance
LLM 分析
sched/cache:让 active load balance 真正遵守 migrate_llc_task 语义
系列概况
- 标题:
[PATCH v2] sched/cache: honor migrate_llc_task semantics in active load balance - 作者:Lu Wang
<wanglu.priv@gmail.com>(合作者:Chen, Yu C、Tim Chen) - 版本:v1(2026-08-01)→ v2(2026-08-09);thread 中只有这两个版本,中间经过 4 轮 review
- 规模:v1 修改 2 个文件,
+23/-3;v2 修改 1 个文件,+50/-6 - 修改文件:
kernel/sched/fair.c、kernel/sched/sched.h(v1);kernel/sched/fair.c(v2) - 代码统计:v1
23 insertions(+), 3 deletions(-);v250 insertions(+), 6 deletions(-) - Message-ID:
20260801122252.2476258-1-wanglu.priv@gmail.com(v1)、20260809105343.1189051-1-wanglu.priv@gmail.com(v2) - 完整性:thread 含 v1 patch、v2 patch、两轮 review、Reviewed-by 与一条 commit log 润色建议;流程闭合,未合入状态待跟进
补丁目的
让 active load balance(ALB)这条"异步 fallback 路径"在 CAS(cache-aware scheduling)触发的 LLC 方向迁移中只搬动 preferred LLC 与目标 LLC 匹配的任务。被动 LB 在 passive_balance() 中把 group_llc_balance 标成 migrate_llc_task,但当被动 LB 拿不走任务时排队的 ALB 由 CPU stopper 在目标 CPU 上重新构造 lb_env,迁移类型被默认成 migrate_load(值 0),导致:
- ALB 在
can_migrate_task()中看到任务p的preferred_llc与目标 LLC 不一致时仍按migrate_load接受,把p从其 preferred LLC 拉走。 - 引入 CAS 没有预期的副作用:
src_rq上 p1 想往dst_llc走、p2 想留src_llc,被动 LB 因 p1 被 pinned/cache-hot/容量约束失败时触发 ALB,cfs_tasks倒序遍历撞上 p2,把它错误拽出 preferred LLC。
旧流程的问题
passive_balance() 算出 imbalance 后选最忙 group,置 busiest->active_balance = 1、push_cpu = this_cpu,并 stop_one_cpu_nowait() 排队 ALB。问题在 active_load_balance_cpu_stop() 在 dst_cpu 上构造一份全新的 lb_env:flags 只设 LBF_ACTIVE_LB,migration_type 默认 0 即 migrate_load。migrate_llc_task 的所有判断(alb_break_llc()、migrate_degrades_llc()、can_migrate_task() 的 LLC 路径)都依赖 env->migration_type == migrate_llc_task;ALB 沿用默认值后,CAS 触发的 ALB 退化成了普通 load migration,丢掉了"只搬方向匹配的任务"的约束。
新流程
v2 采纳 Chen Yu 的建议:不再把 migration_type 透传到 stopper,而是在 sched_balance_rq() 排队 ALB 时根据 env->migration_type 挑选 stopper 回调:
migrate_llc_task→active_load_balance_llc_cpu_stop()- 其它 → 原
active_load_balance_cpu_stop()
两个 stopper 都进入 __active_load_balance_cpu_stop(data, lb_flags),llc 版本把 LBF_ACTIVE_LB_LLC 加进 env->flags;migrate_llc_task_wrong_dst() 同时识别 migration_type == migrate_llc_task 与 env->flags & LBF_ACTIVE_LB_LLC。这样既避免把 migration_type 改写成非 migrate_load(防止 sched_delayed 任务被拒迁),又让 ALB 路径上的 LLC 检查仍能识别 CAS 触发的迁移方向。
关键实现
#define LBF_ACTIVE_LB_LLC 0x40
static inline bool
migrate_llc_task_wrong_dst(struct task_struct *p, struct lb_env *env)
{
return sched_cache_enabled() &&
(env->migration_type == migrate_llc_task ||
env->flags & LBF_ACTIVE_LB_LLC) &&
READ_ONCE(p->preferred_llc) != llc_id(env->dst_cpu);
}
static inline cpu_stop_fn_t alb_stop_fn(struct lb_env *env)
{
if (env->migration_type == migrate_llc_task)
return active_load_balance_llc_cpu_stop;
return active_load_balance_cpu_stop;
}
static int __active_load_balance_cpu_stop(void *data, unsigned int lb_flags)
{
/* ... 构造 lb_env,flags = LBF_ACTIVE_LB | lb_flags ... */
}
sched_balance_rq() 中用 alb_stop_fn(&env) 选择 stopper;migrate_degrades_llc() 与 can_migrate_task() 都复用 migrate_llc_task_wrong_dst(),ALB 路径上检测到 preferred_llc 不匹配时返回 0,避免把 p2 拖出 preferred LLC。
Patch 概览
v1:新增 rq->active_balance_type 保存 migration_type;stopper 构造 lb_env 时把 active_balance_type 强转回 migration_type。
v2:弃用 rq->active_balance_type;引入 LBF_ACTIVE_LB_LLC 与 alb_stop_fn();新增 active_load_balance_llc_cpu_stop() 与 __active_load_balance_cpu_stop(data, lb_flags);commit message 增 Suggested-by Chen, Yu C。v2 调整原因:v1 改写 env->migration_type 会触发 can_migrate_task() 里 (p->se.sched_delayed) && env->migration_type != migrate_load 的拒迁分支,殃及 delayed-dequeue 任务。
类比
把 ALB 想成"调度员替同事代搬一箱文件":被动 LB 是发起人,他递纸条说"把这箱搬到 3 楼那间(migrate_llc_task)";但 stopper 接收时纸条被换成了"搬到 3 楼,哪间都行(migrate_load)"。v1 的修法是让发起人把原话写进搬运动线 rq->active_balance_type,stopper 重新念一遍——但这会污染原本"搬所有可搬的东西"的语义,把不想搬的同事(sched_delayed)也挡掉。v2 改成"发起人挑一个会念原话的搬运动线(active_load_balance_llc_cpu_stop)",让搬运动线自己在 lb_env 上贴一张小标签 LBF_ACTIVE_LB_LLC,原话(migration_type)仍保留 migrate_load 默认值,搬运动线在门口核对"小标签 + 目标 LLC"再决定搬不搬。
passive_balance()
|
sets env->migration_type
= migrate_llc_task
|
v
need_active_balance()
|
if (group_llc_balance == CAS):
queue active balance
|
v
+--------- alb_stop_fn(env) ---------+
| |
env->migration_type env->migration_type
== migrate_llc_task != migrate_llc_task
| |
v v
active_load_balance_llc_cpu_stop() active_load_balance_cpu_stop()
| |
v v
__active_load_balance_cpu_stop(data, __active_load_balance_cpu_stop(data,
LBF_ACTIVE_LB_LLC) 0)
| |
v v
env->flags |= LBF_ACTIVE_LB_LLC env->flags = LBF_ACTIVE_LB
| |
+----------------+-------------------+
v
can_migrate_task(p)
|
migrate_llc_task_wrong_dst()
|
(preferred_llc != llc_id(dst_cpu)) ?
|
+----------+----------+
| |
reject accept
Highlight:风险与注意点
- 行为变更面:v1 改写
migration_type会触发can_migrate_task()中sched_delayed任务的拒迁分支;v2 通过env->flags隔离该影响,但 ALB 路径上任何对migration_type的隐式假设都值得再审计(例如未来新增的 ALB 检查分支)。 - 触发概率:被动 LB 大多数情况下会先搬走 p1,真正出现"p1/p2 同时留在 src_rq 并触发 ALB"的概率较低;review 中作者与 Tim/Chen Yu 反复讨论"是否真的会出现",缺乏 trace 数据,建议加 tracepoint 或微基准验证。
- 数据一致性:
migrate_llc_task_wrong_dst()直接读READ_ONCE(p->preferred_llc);preferred_llc在migrate_misplaced_task()命中后会被更新,需要确认节点/CPU 拓扑变化时是否会残留错误绑定。 sched_cache_enabled()关闭时wrong_dst直接返回 false,patch 在未启用 CAS 的构建里是空操作,需要测试覆盖关闭路径。- 文档与日志:Chen Yu 建议补
[Problem Statement]章节并把"为什么需要新增 stopper 函数"的论证写进 commit log,作者同意润色;正式合入前应落实。
版本变化
v1 → v2:放弃 rq->active_balance_type;引入 LBF_ACTIVE_LB_LLC 与 alb_stop_fn();新增 active_load_balance_llc_cpu_stop() 与 __active_load_balance_cpu_stop(data, lb_flags);commit message 增加 Suggested-by Chen, Yu C;v2 已获 Reviewed-by: Tim Chen。thread 末尾 Chen Yu 还提出两条 commit log 润色建议,作者同意采纳。
一句话总结
该 patch 让 active load balance 在 CAS 触发时仍只把 preferred LLC 与目标 LLC 匹配的任务拉走,避免在 fallback 异步路径上把"不想搬家的人"错误拖出 preferred LLC;v2 通过挑选 stopper 回调 + LBF_ACTIVE_LB_LLC 标志规避了改写 migration_type 对 sched_delayed 任务的副作用。