0/5 已展开

LLM 分析

sched_ext:把 cgroup 的初始 cpu.idle 状态传给 BPF 调度器

系列概况

  • 标题: [PATCH v3 0/2] sched_ext: pass the initial cpu.idle state in scx_cgroup_init_args
  • 作者: Tao Cui cuitao@kylinos.cn
  • 版本: v3,共 2 个补丁
  • 规模: 4 个文件,+11 / −4 行
  • 修改文件: include/linux/sched/ext.hkernel/sched/ext/ext.ckernel/sched/ext/internal.hkernel/sched/ext/sub.c
  • 代码统计: ext.c 8 处改动、internal.h 3 处新增、ext.h 2 处改动、sub.c 2 处新增
  • Message-ID: 20260825023557.27881-1-cui.tao@linux.dev
  • 完整性: 完整;已被 Tejun Heo 接收,1/2 走 sched_ext/for-7.3-fixes,2/2 走 sched_ext/for-7.4,并带 Andrea Righi 的 Reviewed-by

补丁目的

scx_cgroup_init_args 是 scx 把 cgroup 初始参数交给 BPF 调度器 ops.cgroup_init() 的结构体,里面已经带上了 weightbw_period_usbw_quota_usbw_burst_us,但漏掉了 cpu.idle 状态。结果就是:一个 cgroup 在 sched_ext 加载之前(或者在该调度器下 online 之前)就已经被设成 SCHED_IDLE,加载之后 BPF 调度器却仍然看到非 idle;要等到下次再写一次 cpu.idle,状态才会通过 ops.cgroup_set_idle() 同步过去。

补丁 1/2 把这个初始状态补回去。补丁 2/2 顺手把容易和 CPU idle 混淆的字段名 tg->scx.idle 改名为 tg->scx.sched_idle,让命名和 SCHED_IDLE 策略对齐。

旧流程的问题

  1. scx_cgroup_init_args 只有 weight 和带宽字段,没有 idle,结构体不完整。
  2. scx_tg_online()scx_cgroup_init()scx_cgroup_claim_subtree()scx_cgroup_return_subtree() 这四处构造 args 的地方都漏掉了 idle。
  3. 加载 BPF 调度器后,那些先被设成 idle 的 cgroup 在 ops.cgroup_init() 里以非 idle 出现,BPF 调度器内部状态与 cgroup 真实状态不一致。
  4. tg->scx.idle 字段名在 sched_ext 里很容易被误读成 CPU idle(如 ops.update_idle()、idle cpumasks、scx_bpf_pick_idle_cpu()),命名上不清晰。

新流程

  1. struct scx_cgroup_init_args 里新增 bool sched_idle
  2. 在上述四个构造 args 的位置都把 tg->scx.sched_idle(重命名前是 tg->scx.idle)填进去。
  3. patch 2/2 把 tg->scx.idle 同步改名为 tg->scx.sched_idle,与 args 字段名对齐。
  4. 验证方式:在 VM 里跑一个 probe 调度器打印 init args;预先 cpu.idle=1 的 cgroup 加载后立即看到 sched_idle=1,默认 cgroup 看到 0;之后 cpu.idle 的写入仍然走 ops.cgroup_set_idle()

Patch 概览

  • 1/2 修 bug: 在 scx_cgroup_init_args 里新增 sched_idle,四个填充点全部补上赋值;带 Fixes: 347ed2d566da
  • 2/2 cleanup: 把 tg->scx.idle 改名为 tg->scx.sched_idle,纯改名,零行为变化。

关键实现

/* 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 SCHED_IDLE via cpu.idle */
    bool sched_idle;
};

/* kernel/sched/ext/ext.c, scx_tg_online() */
{
    .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,
    .sched_idle    = tg->scx.sched_idle,   /* 新增 */
};

/* scx_cgroup_init()、scx_cgroup_claim_subtree()、scx_cgroup_return_subtree()
 也都同步补上 .sched_idle = tg->scx.sched_idle */

重命名 patch 的关键改动:

/* include/linux/sched/ext.h */
struct scx_task_group {
    ...
-   bool idle;
+   bool sched_idle;
};

/* kernel/sched/ext/ext.c */
- tg->scx.idle = false;
+ tg->scx.sched_idle = false;

/* scx_group_set_idle() 里所有读/写 tg->scx.idle 的地方一并替换 */

流程图

   old flow                              new flow
   --------                              --------
   cgroup cpu.idle=1 cgroup cpu.idle=1
        |                                     |
        v                                     v
   scx loaded                         scx loaded
        |                                     |
        v                                     v
   cgroup_init(args)                   cgroup_init(args)
   args.weight = 1024                  args.weight       = 1024
   args.bw_* = ...                   args.bw_*         = ...
   args.sched_idle = MISSING (bug)     args.sched_idle   = 1    (fix)
        |                                     |
        v                                     v
   BPF sees "not idle"                 BPF sees "idle"
   until next cpu.idle write           matches cgroup state immediately

   thread outcome
   --------------
   Tao Cui v3 cover |
        |-->1/2  fix  (Fixes: 347ed2d566da)
        |       \---> for-7.3-fixes  (Tejun applied)
        |
        |--> 2/2  rename cleanup \---> for-7.4 (Tejun applied)
 ^
 |
 Andrea Righi Reviewed-by

类比

把 BPF 调度器想成新上岗的物业经理,cgroup 是住户登记表。

经理第一天上班挨家挨户登记:体重限额、用水额度都填了,但漏写一栏「这户是否申请了节能模式」。
结果:申请过节能的住户在经理眼里跟普通住户一样,空调照常开,只有等业主再来物业补登记一次,状态才被纠正。

这个 patch 就是把那栏「节能模式」补上,并把英文名从 Idle 改成更精确的 Sched_Idle,免得和「电梯空闲楼层」这种 CPU idle 概念混淆。这样后续无论是查看 cgroup 文件、调试 BPF 程序,还是给同事讲解,命名都不会再撞车。

Highlight:风险与注意点

  1. 真实 bug,stable backport 价值高:1/2 的 Fixes tag 指向 347ed2d566da,所以走 for-7.3-fixes 进入 stable 是对的。
  2. 拆分 patch 的目的要理解:1/2 保持最小修复,2/2 单独做 rename cleanup,避免把无关改动混进 stable backport。
  3. sub-scheduler 路径只做了编译测试:review 阶段 Andrea 没有跑运行时验证,可以追加在后续版本里加上更彻底的测试。
  4. 命名一致性:现在 sched_idle 同时出现在 scx_task_groupscx_cgroup_init_args,含义与 SCHED_IDLE 策略对齐,比单写 idle 更不容易误读为 CPU 空闲。
  5. ABI 影响面:在结构体末尾追加字段,源码侧兼容性没问题;但 BPF 程序依赖自动生成的 vmlinux.h,字段顺序会随之调整,下游 BPF 调度器重新生成头文件即可。
  6. 共识度:Andrea 直接给了 Reviewed-by,Tejun 一锤定音拆分接收,说明评审意见高度一致;后续 merge风险很低。

版本变化

  • v1 → v2:本邮件正文未展开。
  • v2 → v3
    • 按 Tejun 建议把新增字段名从 idle 改成 sched_idle,避免与 CPU idle 混淆。
    • 把 rename 单独拆成 2/2,让 1/2 保持最小修复以便 stable backport。
    • 添加 Fixes: 347ed2d566da(Andrea 建议)。
    • 在当前 linux-next 上重新生成,顺带解决 v2 报出的 CI 冲突。
    • 按惯例把 subject 大小写规范化。

一句话总结

v3 两件套把 scx_cgroup_init_args 里漏掉的初始 cpu.idle 状态补上,并把容易和 CPU idle 混淆的字段统一改名为 sched_idle,已被 Tejun 分别合入 for-7.3-fixesfor-7.4,共识度高。