sched-ext discussion
[PATCHSET sched_ext/for-7.3] sched_ext: Rename the cid-form cgroup ops to cpuctl_*
LLM 分析
sched_ext: Rename the cid-form cgroup ops to cpuctl_*
系列基线信息
| 字段 | 内容 |
|---|---|
| 标题 | sched_ext: Rename the cid-form cgroup ops to cpuctl_* |
| 作者 | Tejun Heo (tj@kernel.org) |
| 版本 | 无版本号标记,单次提交 |
| 规模 | 2 patches,6 files,+66 −53 |
| Message-ID | 20260718101029.725350-1-tj@kernel.org |
| 来源 | sched-ext 频道 |
| 基线分支 | sched_ext/for-7.3 (7c2cd767705d) + cgroup migration patchset |
明确目的
sched_ext 的 cid 形式(struct sched_ext_ops_cid)中,"cgroup" 这个名字承载了两层含义:
- 子调度器(sub-scheduler)挂载到 cgroup——这是 cgroup2 层级的概念;
cgroup_*()回调 ops 传递的是 cpu controller 事件——这是 cgroup cpu 控制器的概念。
两个概念并不相同,但 ops 名字 cgroup_* 暗示的是 cgroup2 层级,实际操作的是 cpu controller。
cid 形式目前只有 scx_qmap 一个用户,ABI 还能改。因此趁此窗口期把 cgroup_* 重命名为 cpuctl_*,让名字准确反映实际语义。
cpu 形式(struct sched_ext_ops)已是 deployed ABI,保持旧名不变。
遍历代码
Patch 1/2:添加 SCX_OPS_CID_OPEN
问题背景:SCX_OPS_OPEN() 在打开 skeleton 时会对缺失的 ops 字段做 load-time compat fix-up(清零)。这些 fix-up 通过硬编码引用 sched_ext_ops(cpu 形式)的成员名来操作。cid 形式的 skeleton 之所以能编译通过,仅仅是因为两种 ops struct 当前把 cgroup ops 取了相同名字——而即将到来的重命名会让这个名字一致性消失,编译将失败。
此外,cid 形式晚于所有 compat-gated ops 的引入时间,根本不需要任何 fix-up。
改动逻辑:
-
将
SCX_OPS_OPEN()里的 skeleton 打开公共路径提取为__SCX_OPS_OPEN(__ops_name, __scx_name, __ops_struct)内联宏:- 检查
dump字段是否存在(版本兼容性检查); - 打开 skeleton;
- 设置
hotplug_seq; - 执行
SCX_ENUM_INIT。
- 检查
-
原
SCX_OPS_OPEN()调用__SCX_OPS_OPEN(..., "sched_ext_ops"),然后继续做 compat 清零。 -
新增
SCX_OPS_CID_OPEN()调用__SCX_OPS_OPEN(..., "sched_ext_ops_cid"),跳过所有 compat 清零。 -
scx_qmap 从
SCX_OPS_OPEN切换到SCX_OPS_CID_OPEN。
// 新增的公共路径
#define __SCX_OPS_OPEN(__ops_name, __scx_name, __ops_struct) ({ \
struct __scx_name *__oskel; \
SCX_BUG_ON(!__COMPAT_struct_has_field(__ops_struct, "dump"),\
__ops_struct ".dump() missing, kernel too old?"); \
__oskel = __scx_name##__open(); \
SCX_BUG_ON(!__oskel, "Could not open " #__scx_name); \
__oskel->struct_ops.__ops_name->hotplug_seq = scx_hotplug_seq(); \
SCX_ENUM_INIT(__oskel); \
__oskel; \
})
// cid 形式只走公共路径,不做 compat fix-up
#define SCX_OPS_CID_OPEN(__ops_name, __scx_name) \
__SCX_OPS_OPEN(__ops_name, __scx_name, "sched_ext_ops_cid")
Patch 2/2:重命名 cgroup_* → cpuctl_*
改动范围:
-
internal.h—struct sched_ext_ops_cid:8 个回调字段名全部改名:cgroup_init→cpuctl_initcgroup_exit→cpuctl_exitcgroup_prep_move→cpuctl_prep_movecgroup_move→cpuctl_movecgroup_cancel_move→cpuctl_cancel_movecgroup_set_weight→cpuctl_set_weightcgroup_set_bandwidth→cpuctl_set_bandwidthcgroup_set_idle→cpuctl_set_idle
-
ext.c—__bpf_ops_sched_ext_ops_cid:同名映射,实现函数名不变(如sched_ext_ops__cgroup_init),只是 ops 字段名改了。 -
ext.c—CID_OFFSET_MATCH:确保重命名的 cid 字段与对应的 cpu 字段占据同一 layout slot:CID_OFFSET_MATCH(cgroup_init, cpuctl_init); CID_OFFSET_MATCH(cgroup_set_bandwidth, cpuctl_set_bandwidth); // ...共 8 对 -
scx_qmap.bpf.c:BPF 回调函数名从qmap_cgroup_*改为qmap_cpuctl_*;ops 注册表里同步改名。 -
scx_qmap.c/scx_qmap.h:注释和帮助文本里的cgroup_init改为cpuctl_init。
关键约束:layout 不变,内核通过 cpu 形式的 union 视图调用,实现函数名不变。
ASCII 流程图
┌──────────────────────────────────────────────────────┐
│ sched_ext ops 形式对比 │
├─────────────────────┬────────────────────────────────┤
│ cpu 形式 (deployed │ cid 形式 (可变 ABI) │
│ ABI, 不可改) │ │
│ │ │
│ cgroup_init │ cpuctl_init ← 重命名后 │
│ cgroup_exit │ cpuctl_exit │
│ cgroup_prep_move │ cpuctl_prep_move │
│ cgroup_move │ cpuctl_move │
│ cgroup_cancel_move │ cpuctl_cancel_move │
│ cgroup_set_weight │ cpuctl_set_weight │
│ cgroup_set_bandwd │ cpuctl_set_bandwidth │
│ cgroup_set_idle │ cpuctl_set_idle │
├─────────────────────┴────────────────────────────────┤
│ CID_OFFSET_MATCH 保证两者在同一 slot │
│ 内核通过 cpu-form union 视图调用 → 实现函数名不变 │
└──────────────────────────────────────────────────────┘
┌──── Skeleton 打开路径 ────────────────────────────┐
│ │
│ SCX_OPS_OPEN() SCX_OPS_CID_OPEN() │
│ ├─ __SCX_OPS_OPEN() ├─ __SCX_OPS_OPEN() │
│ │ ├─ dump 检查 │ ├─ dump 检查 │
│ │ ├─ skeleton open │ ├─ skeleton open │
│ │ ├─ hotplug_seq │ ├─ hotplug_seq │
│ │ └─ SCX_ENUM_INIT │ └─ SCX_ENUM_INIT │
│ ├─ compat 清零 ← cpu名 │ └─ 直接返回 (无清零) │
│ └─ 返回 __skel │ │
└────────────────────────────────────────────────────┘
概念类比
想象一座大楼有两套门牌系统——旧楼(已交付住户)和新楼(还在施工)。旧楼每层的会议室叫 "会议室A/B/C",新楼原想也叫同样的名字,但这些会议室其实是 "空调控制室",不是开会的。
现在新楼还没住户,趁这个机会把门牌从 "会议室" 换成 "空调控制室",名字终于和实际用途吻合了。旧楼的住户已经习惯了 "会议室A" 这个门牌,不能改——但两栋楼共享同一套管线(CID_OFFSET_MATCH),所以换门牌不影响管线走向。
SCX_OPS_CID_OPEN 就像是给新楼单独配了一把钥匙,不再需要走旧楼钥匙那一串"检查旧锁"的流程——因为新楼压根没有旧锁。
Highlight 突出问题
-
ABI 窗口期有限:cid 形式目前只有 scx_qmap 一个用户,所以还能改。一旦更多调度器采用 cid 形式,重命名就不可逆了。此 patchset 是最后的机会。
-
CID_OFFSET_MATCH 必须持续维护:重命名后,cid 字段名和 cpu 字段名不再一致,
CID_OFFSET_MATCH是保证两者在同一 layout slot 的唯一防线。未来新增字段或进一步重命名时,必须同步更新这些匹配声明,否则 union 视图调用会错位。 -
SCX_OPS_CID_OPEN 不能混用:cid-form 调度器必须用
SCX_OPS_CID_OPEN,不能用SCX_OPS_OPEN——否则 compat 清零会引用不存在的 cpu-form 成员名导致编译失败。这个区别在文档和代码注释里已说明,但未来新调度器作者容易误用。 -
cpu 形式永久保留旧名:
struct sched_ext_ops里的cgroup_*名字语义不准确但已成 deployed ABI,无法修正。这是历史包袱,后续代码阅读者需意识到 cpu 形式的cgroup_*实际操作的是 cpu controller。
版本演进
本系列无多版本迭代,首次提交即被 maintainer 应用。
与其他相关 patch 系列的关联
- 依赖前置系列:cgroup migration patchset(cover letter 中引用了
20260718081727.582037-1-tj@kernel.org)。 - 目标分支
sched_ext/for-7.3,属于 7.3 merge window 的准入改动。
一句话总结
趁 cid 形式 ABI 尚可变更,将 sched_ext_ops_cid 中语义不准确的 cgroup_* ops 重命名为 cpuctl_*,同时拆出 SCX_OPS_CID_OPEN 避免 cid skeleton 依赖 cpu-form 成员名的 compat 清零路径。