sched-ext discussion
[PATCH] sched_ext: Set errno on ENABLING -> ENABLED transition failure
LLM 分析
sched_ext: Set errno on ENABLING → ENABLED transition failure
系列基线信息
| 字段 | 值 |
|---|---|
| 标题 | [PATCH] sched_ext: Set errno on ENABLING -> ENABLED transition failure |
| 作者 | Liang Luo (luoliang@kylinos.cn) |
| 版本 | 单 patch,无版本号 |
| 规模 | 1 文件,1 行插入 |
| Message-ID | 20260728060955.4102964-1-luoliang@kylinos.cn |
| 来源 | sched-ext |
| 状态 | 已被 Tejun Heo 合入 sched_ext/for-7.3 |
明确目的
scx_root_enable_workfn() 在完成所有初始化后,尝试用 cmpxchg 将 enable 状态从 SCX_ENABLING 切换到 SCX_ENABLED。如果该原子操作失败(说明有其他路径已经触发了 disable),函数跳转到 err_disable,但此时 ret 仍为上一次 __scx_init_task() 返回的 0。
最终错误日志输出 scx_root_enable() failed (0)——errno 为 0,既无诊断意义,也不符合调用者预期。
本 patch 在跳转前将 ret 设为 -EBUSY,与函数顶部其他 enable-state 守卫逻辑一致,确保 fallback 总是报告真实 errno。
遍历代码
/* kernel/sched/ext/ext.c — scx_root_enable_workfn() 关键路径 */
/* 顶部守卫:状态不对时 ret = -EBUSY */
if (!scx_tryset_enable_state(SCX_ENABLING, SCX_DISABLED))
{ ret = -EBUSY; goto err_disable; }
/* ... 大量初始化工作 ... */
/* __scx_init_task() 成功返回 0,ret 被赋值为 0 */
/* 尾部:ENABLING -> ENABLED 原子切换 */
if (!scx_tryset_enable_state(SCX_ENABLED, SCX_ENABLING)) {
WARN_ON_ONCE(atomic_read(&sch->exit_kind) == SCX_EXIT_NONE);
ret = -EBUSY; /* <-- 本 patch 新增的唯一样行 */
goto err_disable;
}
return;
err_disable:
/* 用 ret 报告错误 */
scx_root_enable_failure(sch, ret);
改动只有一行:在 goto err_disable 前加 ret = -EBUSY,与函数顶部其他状态守卫保持一致。
ASCII 流程图
scx_root_enable_workfn()
|
+-----------v-----------+
| scx_tryset_enable_state|
| (ENABLING, DISABLED) |
+-----+---------+-------+
| |
success fail
| |
| ret=-EBUSY --> err_disable
v
[ ... init tasks ... ]
ret = __scx_init_task() = 0
|
+-----------v-----------+
| scx_tryset_enable_state|
| (ENABLED, ENABLING) | <-- tail cmpxchg
+-----+---------+-------+
| |
success fail
| |
| +----v----+
| |WARN_ON |
| |ret=-EBUSY| <-- PATCH: 新增
| +----+----+
| |
v v
return err_disable
--> scx_root_enable_failure(sch, ret)
修复前: "failed (0)" 无意义
修复后: "failed (-EBUSY)" 有意义
概念类比
想象一个酒店入住流程:前台确认房间可用(DISABLED → ENABLING),然后安排客人入住、录入信息(__scx_init_task()),最后把房卡交给客人(ENABLING → ENABLED)。
如果房卡发放时发现房间已被其他人取消,前台需要登记一个"房间被占用"的失败原因。但修复前,前台只记下了上一步"录入成功"的 0,导致系统日志写着"入住失败(0)"——看起来像成功一样。修复后,前台会在房卡发放失败时明确标注"房间被占用(-EBUSY)",日志才真正有意义。
Highlight 突出问题
-
Sashiko 机器人误报:AI review 指出
scx_sub_enable_workfn()缺少scx_error()调用,但作者已澄清该问题已被 commitdb4e9defd2e8修复,属于过时分析。使用 AI review 时需注意其知识可能滞后于主线代码。 -
err_disable 路径的 ret 依赖:
err_disable是多个错误路径的汇聚点,不同路径需各自设置ret。本 patch 只修了其中一个路径,其他人若后续新增跳转点,仍需记得在跳转前赋值ret——这是代码结构上的脆弱点。 -
cmpxchg 失败的根因:
ENABLING → ENABLED失败意味着有其他路径并发触发了 disable,此时WARN_ON_ONCE会检查exit_kind,但ret=-EBUSY只表达"状态忙",不区分具体退出原因,后续可考虑是否需要更细粒度的 errno。
版本演进
无多版本。单 patch 一次提交即被合入。
与其他相关 patch 系列的关联
- commit
db4e9defd2e8("sched_ext: Record an error on errno-only sub-enable failure"):此前已修复scx_sub_enable_workfn()中类似的 silent failure 问题,在err_disable处添加了 catch-allscx_error()。本 patch 是对scx_root_enable_workfn()的对应修复,两者逻辑对称。
一句话总结
在 scx_root_enable_workfn() 的 ENABLING→ENABLED 竞争失败路径上补设 ret=-EBUSY,消除无意义的 failed (0) 错误日志。