sched-ext discussion
[PATCH v2] sched_ext: pass the initial cpu.idle state in scx_cgroup_init_args
LLM 分析
sched_ext:在 scx_cgroup_init_args 中传递初始 cpu.idle 状态
系列概况
- 标题:
[PATCH v2] sched_ext: pass the initial cpu.idle state in scx_cgroup_init_args - 作者:Tao Cui cuitao@kylinos.cn
- 版本:v2(线程内预告 v3 重命名字段)
- 规模:单 patch,3 个文件,+8/-1
- 修改文件:
kernel/sched/ext/ext.c、kernel/sched/ext/internal.h、kernel/sched/ext/sub.c - 代码统计:3 文件,8 处新增,1 处删除(v1 自述,v2 diff 与之接近)
- Message-ID(首封):
20260824142817.568085-1-cui.tao@linux.dev - 完整性:单 patch + 3 封回复(Andrea Righi、Tejun Heo、Tao 两次回应),v3 未在本线程展开。
补丁目的
scx_cgroup_init_args 把 cgroup 的初始 weight 与带宽控制参数传给 BPF 调度器的 ops.cgroup_init(),但漏掉了 cpu.idle 标记。结果是:调度器加载时已处于 idle 的 cgroup 在 init 阶段被当作非 idle,BPF 调度器只有等到用户再次写 cpu.idle 时才会经由 ops.cgroup_set_idle() 收到通知,造成「初始状态丢失」。
旧流程的问题
user writes cpu.idle=1 sched_ext is loaded
| |
v v
cgroup fs marks idle walk already-existing cgroups
| |
| v
| scx_cgroup_init() fills weight/bw_*
| |
| v
| ops.cgroup_init() sees idle=0 (WRONG)
| |
v |
ops.cgroup_set_idle() callback only on next write
| |
v v
finally known initial state lost
cpu.idle 的初值被忽略,调度器只能被动等下一次写入。
新流程
any place that builds scx_cgroup_init_args
|
+----------------+----------------+
| | |
v v v
scx_tg_online scx_cgroup_init sub.c: claim / return
| | |
+--------+-------+--------+
| |
v v
args.idle = tg->scx.idle (v3 -> sched_idle)
|
v
ops.cgroup_init() sees initial idle (CORRECT)
struct scx_cgroup_init_args 新增 bool idle(v3 改名 sched_idle),四处构造位置统一填上 tg->scx.idle。
Patch 概览
v1 漏了 sub-scheduler 交接路径(Andrea Righi 与 sashiko AI review bot 指出);v2 在 sub.c 的 scx_cgroup_claim_subtree() 与 scx_cgroup_return_subtree() 补齐:
/* kernel/sched/ext/internal.h */
struct scx_cgroup_init_args {
u64 weight;
u64 bw_period_us;
u64 bw_quota_us;
u64 bw_burst_us;
/* whether the cgroup is configured idle via cpu.idle */
bool idle; /* v3: -> sched_idle */
};
四个填充点都加一行 .idle = tg->scx.idle,。
关键实现
/* scx_tg_online(): cgroup 在调度器之后上线 */
static int scx_tg_online(struct task_group *tg)
{
struct scx_cgroup_init_args args = {
.weight = tg->scx.weight,
.bw_period_us = tg->scx.bw_period_us,
.bw_quota_us = tg->scx.bw_quota_us,
.bw_burst_us = tg->scx.bw_burst_us,
.idle = tg->scx.idle, /* new */
};
...
}
/* scx_cgroup_init(): cgroup 已存在,调度器加载 */
.idle = tg->scx.idle, /* new */
/* sub.c: 子调度器交接 */
.idle = tg->scx.idle, /* new in v2 */
.idle = tg->scx.idle, /* new in v2 */
验证:作者用 probe BPF 调度器在 VM 中打印 init args,确认「加载前 cpu.idle=1 的 cgroup 在 ops.cgroup_init() 中看到 idle=1、默认看到 0、后续 cpu.idle 写入仍走 ops.cgroup_set_idle()」。sub-scheduler 路径只做了编译验证。
类比
把 cgroup_init_args 想成「新生婴儿登记表」:宝宝出生(cgroup 创建或被 sched_ext 接管)就要把当时的体重、血型记上去。旧流程漏了「是否标记为『安静型宝宝』」这一栏,托儿所(BPF 调度器)只能默认所有婴儿都活泼,等家长下次再强调一遍才知道。补丁补上这一栏;同时 Tejun 建议把字段从 idle 改成 sched_idle,避免和「CPU 是否闲着」(CPU idle)混淆——就像把登记表的「安静型」明确写成「安静型(SCHED_IDLE)」,避免保育员把它误解成「宝宝在睡觉」。
Highlight:风险与注意点
- 命名歧义:Tejun 指出 sched_ext 中裸
idle一律指 CPU idle(ops.update_idle()、idle cpumasks、scx_bpf_pick_idle_cpu()),args.idle会让 BPF 作者误读;v3 必须改为sched_idle,建议同步重命名tg->scx.idle。 - API 兼容性:
scx_cgroup_init_args是 BPF 调度器通过 vmlinux.h 看到的公开 ABI,字段重命名是一次破坏性变更,需在 release notes 中同步强调。 - Fixes tag:Andrea 建议补
Fixes: 347ed2d566da ("sched/ext: Implement cgroup_set_idle() callback"),补上后才能进 stable。 - Patch 拆分:作者计划把「新增字段」与「
tg->scx.idle重命名」拆成 1/2 与 2/2,前者保持最小、便于 stable backport。 - 验证深度:sub-scheduler 两条路径只跑了编译,未来若新增构造 args 的位置(如某条 hotplug 路径),需保持同步。
- AI 评审信号:sashiko AI review bot 协助发现 v1 漏掉的 sub.c 两处,说明 AI 评审正在进入内核 review 流程,值得后续观察其准确率与误报率。
版本变化
- v1 → v2:补齐
sub.c的scx_cgroup_claim_subtree()与scx_cgroup_return_subtree()两处.idle(Andrea Righi 与 sashiko AI 指出)。 - v2 → v3(作者预告,未在本线程展开):
scx_cgroup_init_args.idle→sched_idle;tg->scx.idle→tg->scx.sched_idle(独立第二 patch);- 补
Fixes:tag; - Andrea Righi 给
Reviewed-by。
一句话总结
补丁修复 sched_ext 在 init 阶段丢失 cgroup cpu.idle 状态的问题,统一在四处构造 scx_cgroup_init_args 的路径补齐该字段,v3 按 Tejun 建议改名为 sched_idle 以消除与 CPU idle 的歧义。