0/2 已展开

LLM 分析

sched_ext: Fixes for v7.2-rc3 — GIT PULL 分析

系列基线信息

字段内容
标题[GIT PULL] sched_ext: Fixes for v7.2-rc3
作者Tejun Heo
版本v7.2-rc3 fixes
规模多个 bugfix 补丁集合,含 Andrea Righi 的 4 个补丁
Message-ID876d09cb8d47617d382a7e2af7a7fd6b@kernel.org
来源sched-ext 频道
合入状态已合入 torvalds/linux (f7574d3f906a963d7b70f01beff731ee0351d5c5)

明确目的

这是一个 rc3 阶段的 bugfix GIT PULL,由 Tejun Heo 向 Linus 提交,汇集了 sched_ext 子系统在本开发周期中积累的多类修复。

目标:在 v7.2-rc3 合入窗口前,一次性把 sched_ext 已发现的所有缺陷修掉,保证正式发布时的稳定性。

解决的具体问题可归纳为五大类:

  1. 子调度器生命周期缺陷 — 新增的 sub-scheduler 支持引入了两个 use-after-free 以及一个 enable 失败路径留下半初始化子调度器仍挂链的问题。
  2. dispatch 路径锁缺陷 — 迁移竞争导致虚假调度器 abort; stale runqueue-lock tracking 引发 lockdep splat。
  3. 回调与任务状态缺陷 — 任务离开 SCX 时残留调度器私有状态; weight 回调在 disable 之后仍执行; core-scheduling forced idle 上的虚假 warning。
  4. nohz_full tick 缺陷 — finite-slice 任务在 nohz_full 模式下可能错过过期 slice 的 tick。
  5. 小修复 — 用户态 CPU-mask helper、ratelimit 弃用警告、文档、sparse 注解。

遍历代码

这封 GIT PULL 本身不包含逐 patch 的 diff,但 commit message 列出了所有修复项。按类别逐步展开:

1. 子调度器生命周期修复

  • use-after-free #1 & #2:子调度器在卸载或切换时,其内部数据结构(如 task context 或 DSQ 引用)被释放后,仍有代码路径通过残留指针访问它们。
    修复方向:在子调度器 teardown 流程中,确保先断链、再释放,或引入 RCU / refcount 保护。

  • enable 失败路径半初始化:当 ops.enable() 失败时,子调度器数据已部分初始化(比如已挂入全局链表),但后续 cleanup 代码未完全清理,导致一个"半死不活"的子调度器留在系统中。
    修复方向:在 enable 失败分支中做完整的 rollback,包括断链和资源释放。

2. dispatch 路径锁缺陷

  • 迁移竞争 → 虚假 abort:当一个任务正在从一个 CPU 迁移到另一个 CPU 的过程中,dispatch 路径中的锁序或状态检查会误判为异常,触发 scheduler abort。
    修复方向:在 dispatch 路径中,对 migration 中间态做宽容处理或加适当的 seqlock 保护。

  • stale rq-lock tracking → lockdep splat:内核 lockdep 机制依赖 runqueue lock 的正确跟踪记录;sched_ext 的 dispatch 代码在 local DSQ dispatch 场景下,没有正确维持 rq-lock 的持有/释放状态记录,导致 lockdep 报告虚假的锁序违规。
    修复方向:在 local DSQ dispatch 中 preserve rq tracking(Andrea Righi 的补丁之一)。

3. 回调与任务状态缺陷

  • 任务离开 SCX 残留状态:当任务从 SCX 调度类退出回到 CFS 时,其 dsq_vtimeslice 仍保留着 SCX 调度器写入的值,这些值在 CFS 语境下无意义,可能干扰后续调度决策。
    修复:reset dsq_vtimeslice(Andrea Righi 的补丁之一)。

  • weight 回调在 disable 后执行:SCX disable 之后,ops.set_weight() 回调仍然会被调用,但此时子调度器已不再活跃,回调行为没有意义甚至可能出错。
    修复:对 disabled 任务 skip ops.set_weight()(这是 pull 的 tip commit 0e2f4ab68a89)。

  • core-scheduling forced idle 虚假 warning:在 core-scheduling 的 forced idle 场景下,一个本应正常的代码路径触发了 warning,属于条件判断过于严格。
    修复:放宽或修正判断条件。

4. nohz_full tick 缺陷

  • nohz_full(自适应 tickless)模式下,拥有 finite slice 的 SCX 任务被 pick 后,系统应该为其启用 tick 以保证 slice 到期时能得到调度器处理。
    但之前遗漏了这一逻辑,导致这类任务的 slice 可能过期而不被处理。
    修复:pick finite-slice 任务时启用 tick,并附带 selftest 验证。

5. 小修复

  • 用户态 CPU-mask helpers 的修正
  • 弃用警告改为 ratelimited(避免日志洪泛)
  • 文档更新
  • sparse 注解修正

ASCII 流程图

                    sched_ext Fixes for v7.2-rc3
                    ============================

  +----------------------+        +----------------------+
  | Sub-scheduler        |        | Dispatch-path        |
  | lifecycle            |        | locking              |
  |                      |        |                      |
  | * UAF #1, #2        |        | * Migration race     |
  | * Half-init on       |        |   -> spurious abort  |
  |   enable failure     |        | * Stale rq-lock      |
  +----------+-----------+        |   -> lockdep splat   |
             |                    +----------+-----------+
             v                               v
  [teardown: unlink then free]    [tolerate migration midstate]
  [enable fail: full rollback]    [preserve rq tracking on
                                    local DSQ dispatch]

  +----------------------+        +----------------------+
  | Callback & task      |        | nohz_full tick       |
  | state                |        |                      |
  |                      |        |                      |
  | * stale dsq_vtime    |        | * finite-slice task  |
  |   & slice on exit    |        |   misses expiry tick |
  | * set_weight after   |        |                      |
  |   disable            |        +----------+-----------+
  | * bogus forced-idle  |                   |
  |   warning            |                   v
  +----------+-----------+        [enable tick when
             |                     finite-slice task
             v                     is picked + selftest]
  [reset dsq_vtime/slice
   on leaving SCX]
  [skip set_weight for
   disabled tasks]
  [fix forced-idle check]

  +-----------------------------------+
  | Smaller fixes                     |
  | * CPU-mask helpers               |
  | * ratelimited deprecation warns  |
  | * docs + sparse annotation       |
  +-----------------------------------+

  Git branch: tj/sched_ext -> tags/sched_ext-for-7.2-rc3-fixes
  Tip commit: 0e2f4ab68a89 "sched_ext: Skip ops.set_weight()
                           for disabled tasks"
  Merge commit: f7574d3f906a (torvalds/linux)

概念类比

想象一个大型医院的科室轮转系统

  • 子调度器生命周期就好比一个新科室刚挂牌(enable),但挂牌过程中发现资质不合格(enable failure),这时如果不把已经挂上的牌子摘掉、把已搬进的设备退回,就会出现一个"有名无实"的科室挂在那里,病人还在往里走(use-after-free)。
  • dispatch 路径锁缺陷就像病人在转运途中(migration),挂号系统还没更新完地址,护士就按旧地址去发药,结果系统判定"这个病人不存在"而中止流程(spurious abort)。或者药房交接班的记录没及时更新(stale rq-lock tracking),内控系统以为有人违规操作(lockdep splat)。
  • 任务离开 SCX 残留状态相当于一个医生从急诊科调回普通门诊,但他的排班系统里还留着急诊科的特殊权限参数(dsq_vtime、slice),在门诊场景下这些参数完全无用甚至会产生误导。
  • set_weight 在 disable 后执行好比科室已经关停,但人事系统还在给这个科室的岗位发"调整权重"通知——通知发到了一个不存在的接收端。
  • nohz_full tick就像一个定时吃药的病人,在"自助管理"模式下(nohz_full),系统应该在病人该吃药时派护士提醒(tick),但之前忘了设置这个提醒,导致病人错过服药时间(slice 过期不被处理)。

Highlight 突出问题

  1. 子调度器 enable 失败路径是高风险区:任何涉及"部分初始化后失败需要 rollback"的逻辑,都是最容易遗漏清理步骤的地方。这次修复了半初始化挂链的问题,但类似的 rollback 不完整风险在其他 enable/callback 路径中仍需持续关注。

  2. migration 竞态与 dispatch 交互是持续痛点:sched_ext 的 dispatch 路径与 CPU migration 之间的竞态条件不是一次性问题,而是架构层面需要长期维护的交互面。每次修改 dispatch 逻辑时,都要重新审视 migration 中间态是否被正确处理。

  3. nohz_full 与 sched_ext 的组合是新兴测试盲区:finite-slice 任务在 nohz_full 下错过 tick 的问题说明,sched_ext 的 tick 管理逻辑与 nohz_full 的 tickless 模式之间的交互尚未被充分测试。附带 selftest 是正确做法,但其他 tick 相关场景(如 infinite-slice + nohz_full)也需要验证。

  4. lockdep splat 不等于真正的锁序违规:stale rq-lock tracking 导致的 lockdep splat 是"记录不准确"而非"真正的锁序死锁",这类 splat 容易引起不必要的恐慌,也容易在后续修改中被误判为真实 bug。

  5. Andrea Righi 的 4 个补丁涉及 dispatch 和状态清理两个核心路径,这些是高频执行代码,修复的 correctness 优先级极高,但性能副作用也需要在合入后观察。

版本演进

这是 v7.2-rc3 的单次 fix pull,没有多版本迭代。补丁在 rc 窗口内一次性提交并合入。

与其他相关 patch 系列的关联

  • 本 pull 中的子调度器生命周期修复,直接服务于 v7.2 开发周期中早先合入的 sub-scheduler support 新特性。新特性合入后暴露了 use-after-free 和 rollback 不完整的问题,这是典型的"新特性落地后的首轮 fix round"。
  • nohz_full tick 修复与内核 NOHZ 子系统长期存在的 tick 管理重构有关。
  • Andrea Righi 的 rq tracking 修复与之前的 sched_ext: Preserve rq tracking 系列逻辑相关。

一句话总结

sched_ext 向 Linus 提交 v7.2-rc3 集中 bugfix pull,涵盖子调度器生命周期、dispatch 锁、回调状态、nohz_full tick 及杂项修复,已合入主线。