0/9 已展开

LLM 分析

sched/deadline:修订后的唤醒规则只对正在运行的 dl_server 生效

系列概况

  • 标题:[PATCH] sched/deadline: Use revised wakeup rule only for running dl_server
  • 作者:Gabriele Monaco gmonaco@redhat.com
  • 版本:v1(单 patch,无版本号字段)
  • 规模:1 个文件,+2/-1 行(kernel/sched/deadline.cupdate_dl_entity 的一个分支条件)
  • 修改文件kernel/sched/deadline.c
  • 代码统计2 insertions(+), 1 deletion(-),外加 commit message 与 Tested-by/Acked-by 等签名行
  • Message-ID(首封)20260522125833.264145-1-gmonaco@redhat.com
  • 完整性:完整可分析。包含初版 patch、两位 reviewer 的答复(Acked-by、Tested-by)、作者 ping maintainer、maintainer 安排合并、tip-bot 自动发布到 sched/urgent 的通知

补丁目的

这条 patch 是对上游 commit 14a857056466 ("sched/deadline: Use revised wakeup rule for dl_server") 的修正。

该上游 commit 改写了 update_dl_entity() 中的判定条件,把"修订后的 wakeup 规则"应用到了所有 deferrable server:

  • 旧条件:!dl_is_implicit(dl_se) || dl_se->dl_defer
  • 含义:只要这个 dl 实体不是 implicit,或者它本身就是一个 deferrable server,就走 update_dl_revised_wakeup。

问题在于:dl_defer == 1 只能说明"这是一个可以延期的 server",并不代表"它当前正处于运行态"。当一个 server 一开始就发生 deadline 溢出但 dl_defer_running == 0 时,上游逻辑会错误地把它当作"正在运行的 server",直接入队并触发 boost,破坏了 defer 语义和文档化的状态模型。

本 patch 的目标:把这条规则收紧为"只有当 server 是 deferrable 且当前正在 running 时,才走 revised wakeup rule"。也就是把条件改成:

if (unlikely((!dl_is_implicit(dl_se) ||
              (dl_se->dl_defer && dl_se->dl_defer_running)) &&
             ...))

旧流程的问题

   update_dl_entity(dl_se)
            |
            v
   deadline expired / overflow?
            |-- no  --> normal path
            |
            v yes
   check: !dl_is_implicit || dl_defer
            |-- true --> update_dl_revised_wakeup()
            |             (no check on dl_defer_running)
            v
   non-running server with overflow
 is enqueued as "running" -> wrong boost

后果:

  • 状态机错乱:defer 规则要求 server 在未 running 时不应擅自 boost,但旧条件放行了这个情况。
  • 可能被反复触发:带有过时 deadline 的 server 哪怕从未被选中运行,也会持续因 overflow 反复入队。
  • 破坏 dl_server 的文档化模型

新流程

   update_dl_entity(dl_se)
            |
            v
   deadline expired / overflow?
            |-- no  --> normal path
            |
            v yes
   check: !dl_is_implicit
        || (dl_defer && dl_defer_running)
            |-- true --> update_dl_revised_wakeup()
            |             (only running servers)
            v
   dl_defer_running == 0 server stays quiet

dl_defer_running 作为新增的"运行标志"参与判定,把它从"一个描述 server 类别的字段",升级为"运行时可见的状态门控"。

Patch 概览

只改动一个判定表达式:

if (unlikely((!dl_is_implicit(dl_se) ||
              (dl_se->dl_defer && dl_se->dl_defer_running)) &&
             (dl_time_before(dl_se->deadline, rq_clock(rq)) ||
              dl_entity_overflow(dl_se, rq_clock(rq))) &&
             !dl_time_before(dl_se->deadline, rq_clock(rq)) &&
             !is_dl_boosted(dl_se))) {
    update_dl_revised_wakeup(dl_se, rq);
}

意图上保持其他前置判断不变,只在"启用 revised wakeup 规则的对象范围"上收紧一格。

关键实现

修改集中在 kernel/sched/deadline.c:update_dl_entity(),核心是把一个"OR 条件"拆成"二选一":

- if (unlikely((!dl_is_implicit(dl_se) || dl_se->dl_defer) &&
+ if (unlikely((!dl_is_implicit(dl_se) ||
+              (dl_se->dl_defer && dl_se->dl_defer_running)) &&

逻辑等价:

  • 情形 A:!dl_is_implicit(dl_se) -> 普通 dl 任务(旧路径保留)
  • 情形 B:dl_defer && dl_defer_running -> 既是 deferrable 又处于 running 状态
  • 情形 C:dl_defer && !dl_defer_running -> 不再命中,避免错误的 wakeup/boost

这样:

  • 真正的 dl_task 行为不变(情形 A)。
  • 运行中的 dl_server 继续遵循修订后的 wakeup rule(情形 B)。
  • 处于闲置/未激活状态的 dl_server 将走正常的 deadline 推进路径,不再误触发 update_dl_revised_wakeup()

测试覆盖:

  • 作者在 16 CPU 上跑 ksched_football:无回归,check-in 1 秒,game over 10 秒。
  • John Stultz 在 64 vCPU guest 上同样验证通过(提供 Tested-by)。
  • rt_stall sched_ext selftest 在该机器上原本就不是稳定高于 4%,与本 patch 无因果关系。

类比

把 dl_server 想成公司里负责"代管任务配额"的项目经理(deferrable server)。dl_defer 是他的岗位资质(能不能代管),dl_defer_running 是他今天是否在岗

旧逻辑像:只要他是项目经理(dl_defer),哪怕今天他请假了(!dl_defer_running),只要看到某个任务 deadline 过期了,就立刻去签字加塞(boost)。结果他在休假时也能动用公司资源,破坏规则。

新逻辑是:他必须今天在岗dl_defer_running),才能执行"修订后的 wakeup 规则"。请假时就按普通流程处理,不擅自出手。

Highlight:风险与注意点

  • dl_defer vs dl_defer_running 的语义差异dl_defer 只是类型/能力位,写作或评审时极易把两者混用,写出像 (dl_se->dl_defer) 这样"看上去对、其实只在某些 server 上对"的判断。
  • update_dl_revised_wakeup 的副作用:被错误调用后会入队并触发 boost,可能引发真实负载下可观察到的延迟/优先级反转,不只是"理论 bug"。
  • 上游 commit 的回归定位:本 patch 写明 Fixes: 14a857056466,合入 stable 时需要排查该 commit 影响到的 stable 分支;只看 Fixes tag 不要忽视测试覆盖。
  • ksched_football 的回归测试需要较大机器:单 CPU 或小机器上,defer server 触发概率低,可能测不出来;选择测试机型时要避免假阴性。
  • rt_stall selftest 的基线:作者提醒它在该机器上原本就不稳,分析 selftest 失败时要先确认基线,不要立刻归咎于本 patch。
  • 维护路径走 sched/urgent:Peter Zijlstra 在评审中明确通过 sched/urgent 分支 tip,说明此问题被定位为可观察回归而不是普通清理,下游 stable/分发版应当同步回移。

版本变化

本线索只有 v1,没有 v2/v3。但维护过程中可观察到以下状态演变:

2026-05-22  author posts v1
2026-05-22  Andrea Righi replies (no ack/fix stance)
2026-05-25  Juri Lelli gives Acked-by
2026-07-29  author pings Peter (maintainer) after maintainer returns from vacation
2026-07-29  Peter agrees, suggests sched/urgent branch
2026-07-29  John Stultz adds Tested-by on 64 vCPU guest
2026-07-30  tip-bot2 posts commit 1842bf97af... to sched/urgent

最终通过 tip 的 sched/urgent 分支以 commit 1842bf97af109f5ebf830175c9725bf81ebb78b1 落地,由 Peter Zijlstra 提交,base-commit 8bc67e4db64aa72732c474b44ea8622062c903f0

一句话总结

update_dl_entity 走"修订 wakeup 规则"的条件从"任何 deferrable server"收紧为"deferrable 且当前 dl_defer_running 的 server",修正上游 commit 14a857056466 对未运行 dl_server 的错误 boost,并通过 sched/urgent 通道推送修复。