0/4 已展开

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-ID20260728060955.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 突出问题

  1. Sashiko 机器人误报:AI review 指出 scx_sub_enable_workfn() 缺少 scx_error() 调用,但作者已澄清该问题已被 commit db4e9defd2e8 修复,属于过时分析。使用 AI review 时需注意其知识可能滞后于主线代码。

  2. err_disable 路径的 ret 依赖err_disable 是多个错误路径的汇聚点,不同路径需各自设置 ret。本 patch 只修了其中一个路径,其他人若后续新增跳转点,仍需记得在跳转前赋值 ret——这是代码结构上的脆弱点。

  3. 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-all scx_error()。本 patch 是对 scx_root_enable_workfn() 的对应修复,两者逻辑对称。

一句话总结

scx_root_enable_workfn() 的 ENABLING→ENABLED 竞争失败路径上补设 ret=-EBUSY,消除无意义的 failed (0) 错误日志。