0/4 已展开

LLM 分析

sched_ext:将初始 cpu.idle 状态传入 scx_cgroup_init_args

系列概况

  • 标题:[PATCH] sched_ext: pass the initial cpu.idle state in scx_cgroup_init_args
  • 作者:Tao Cui cuitao@kylinos.cn
  • 版本:v1(单 patch,未见 [vN] 前缀)
  • 规模:1 个 patch
  • 修改文件kernel/sched/ext/ext.ckernel/sched/ext/internal.h
  • 代码统计:2 files changed, 6 insertions(+), 1 deletion(-)
  • Message-ID20260824133954.561956-1-cui.tao@linux.dev
  • 完整性:完整。包含 commit message、diff、Signed-off-by 与 author 署名;message 3、4 因原文抓取截断,仅保留 partial body

补丁目的

sched_ext 在 cgroup 初始化时,会把 cgroup 当前的 weight、带宽控制等初始参数打包进 struct scx_cgroup_init_args,通过 ops.cgroup_init() 一次性交给 BPF scheduler。但这个结构体目前缺少 cpu.idle 字段,导致:

  1. 在 sched_ext 加载之前就已经被标记为 idle 的 cgroup,BPF scheduler 看到的是 idle=0
  2. 用户必须再次向 cpu.idle 写入相同值,触发 ops.cgroup_set_idle(),BPF 侧才"后知后觉"。

本 patch 的目标就是补齐 cpu.idlecgroup_init 阶段的初始状态,让 BPF scheduler 在挂载时就能拿到正确的 idle 标记。

旧流程的问题

user writes cgroup cpu.idle=1
        |
        v
cgroup_file -> cgroup_idle_write()
        |
        v
tg->scx.idle = 1  (saved internally)
        |
        v
ops.cgroup_set_idle() notifies BPF scheduler
        |
        v
BPF knows "this cgroup is idle"

but if sched_ext was loaded AFTER cpu.idle=1 was written:
        |
        v
tg->scx.idle = 1  (already true)
scx_cgroup_init_args has no idle field
        |
        v
ops.cgroup_init() receives weight/bw but no idle flag
        |
        v
BPF scheduler wrongly assumes idle=0,
until the user rewrites cpu.idle by hand

新流程

sched_ext load / scx_tg_online
        |
        v
build scx_cgroup_init_args {
    .weight,
    .bw_period_us,
    .bw_quota_us,
    .bw_burst_us,
    .idle = tg->scx.idle     # newly added
}
        |
        v
SCX_CALL_OP_RET(ops.cgroup_init, ...)
        |
        v
BPF scheduler sees the real idle state
at attach time, no extra writes needed

Patch 概览

  • struct scx_cgroup_init_args 增加 bool idle 字段,并附注释说明语义;
  • scx_tg_online()(scheduler 已加载后上线的 cgroup)和 scx_cgroup_init()(scheduler 加载时已存在的 cgroup)两个构造点都填入 tg->scx.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 idle via cpu.idle */
    bool idle;       /* newly added */
};
/* kernel/sched/ext/ext.c, scx_tg_online() */
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,   /* newly added */
};
/* kernel/sched/ext/ext.c, scx_cgroup_init() */
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,   /* newly added */
};

两处构造点对称:一个处理"加载之后才出现的 cgroup",另一个处理"加载时已存在的 cgroup"。两条路径都把 tg->scx.idle 这个早已存在的内部状态原样透出,没有引入新的数据来源。

类比

把 sched_ext 想象成一家新上任的物业公司,要接管一栋已经有租户(cgroup)的写字楼。

物业公司搬进来时,手里有一份"住户登记表",上面写了每户的房租、面积、带宽配额——但漏掉了"哪些房间目前空置"这一栏。于是物业默认所有房间都是满租,直到住户主动再来前台补登一次。

这个 patch 就是给登记表补上"是否空置"那一栏。物业公司一接手,就能立刻掌握每户的占用情况,不需要住户再跑一趟重复登记。

Highlight:风险与注意点

  • sub-scheduler 初始化路径遗漏:sashiko-bot 指出,kernel/sched/ext/sub.cscx_cgroup_claim_subtree()scx_cgroup_return_subtree() 也构造了 scx_cgroup_init_args,但本 patch 没有同步更新这两处,.idle 隐式为 false,idle 状态仍可能丢失。这是中等级别的风险,需要在 v2 中一并修复。
  • 设计上的小争议:sched_ext 体系一直强调通过 cgroup_set_idle() 这类"事件型"回调把状态变化告知 BPF,让 BPF 自行维护一份镜像。本次 patch 选择在 cgroup_init() 一次性传入,是否暗示"挂载即镜像"是更被期待的语义?后续可以关注 maintainer(Andrea Righi 等)是否倾向统一到事件驱动、抑或在 init 路径透出更多字段。
  • 一致性注意ops.cgroup_init() 的语义是新挂载时调用,因此参数应被理解为"挂载时刻的快照",不应被 BPF 用作"当前真实状态"缓存;BPF scheduler 仍需以 cgroup_set_idle() 的事件流为准更新其内部状态。
  • 回复截断:lore 上的 message 3(Andrea Righi)和 message 4(Tao Cui 回复)正文未完整抓取,需要跟踪后续版本以了解 maintainer 的明确表态。

版本变化

只有 v1,暂无 v2。预期 v2 需要补 kernel/sched/ext/sub.c 中 sub-scheduler 路径的 .idle 初始化。

一句话总结

这个小 patch 把 cgroup 的 cpu.idle 初始状态补进 scx_cgroup_init_args,修掉了"已 idle 的 cgroup 在 sched_ext 挂载时呈现为非 idle"的语义漏洞,但仍需补齐 sub-scheduler 路径并等待 maintainer 进一步表态。