0/2 已展开

LLM 分析

sched_ext:v7.3 周期合并请求与分层子调度特性完成

系列概况

  • 标题:[GIT PULL] sched_ext: Changes for v7.3
  • 作者:Tejun Heo tj@kernel.org
  • 版本:v7.3(merge window 一次性合并)
  • 规模:由多个子分支(for-7.3for-7.3-arena-args 等)合并而成,邮件正文只摘录了首段变更摘要,未给出具体 patch 数与 diffstat- 修改文件:未在邮件正文给出;变更集中在 kernel/sched/ext.c 与 BPF struct_ops / kfunc 导出表
  • 代码统计:未在邮件正文给出(pull request 通常不发 diff)
  • Message-ID29c6986172b4eb9ba292643ab4ad9583@kernel.org
  • 完整性:完整。包含 Tejun Heo 的 PR 主邮件 + pr-tracker-bot 的合并确认回复,共 2 封

补丁目的

本 PR 是 sched_ext(基于 BPF 的可编程调度器)在 v7.3 合入窗口的合并请求,主要目标:

  1. 完成分层子调度(hierarchical sub-scheduling)的入队路径支持——让"父 BPF 调度器"可以把一个 cgroup 子树连同"可撤销的 CPU 配额"一起移交给"嵌套子调度器",子调度器对这些任务拥有完整调度决策权。
  2. 打通 BPF kfunc / struct_ops 的 arena 参数支持:本 PR 依赖 BPF 树里 arena argument 支持的变更,需要先合 BPF 后合 scheduler。
  3. 捎带一批 v7.2 没赶上的 core scheduling 修复:通过对 PR 路径补交。
  4. 填补新特性晚到的若干空洞(enqueue-path 的若干 race / 语义修补)。

旧流程的问题

在 v7.3 之前,分层子调度只在"出队/选任务路径"上成立:当父调度器把任务交给子调度器后,子调度器无法在入队(enqueue)路径上拿到完整上下文,也无法精确地"按 CPU 撤销授权"。结果是:

  • 子调度器对 cgroup 子树内的任务只能"看见调度结果",无法在 CPU 重新进入子调度域时主动控制。
  • 父调度器回收 CPU配额时缺乏对入队顺序的约束,容易出现"任务还没入队就被强制踢回父域"的竞态。
  • arena 参数的 kfunc / struct_ops 缺位,限制了 BPF 侧调度器访问某些需要 arena 地址空间对象的 API。

新流程

  • CPU 委托(CPU delegation):父调度器现在可以显式地"授予 /撤销"对子调度器的 per-CPU 授权,子调度器拿到 CPU 后接管所有调度决策。
  • cgroup 移交:父调度器可以把整个 cgroup 子树连同 CPU 配额一起交给子调度器;子调度器对这些任务做完整 enqueue / dispatch。
  • Arena 路径:struct_ops 与 kfunc 增加 arena 参数支持,使 BPF 程序能正确处理 arena 指针,避免在 BPF 树与 scheduler 树合并顺序不一致时引入兼容性问题。
  • Core scheduling 修复:通过本 PR 一并合入,避免 v7.2 漏掉的关键修复被拖延。
                   +-----------------------------+
 |   Root BPF scheduler        |
                   |  (selects which subtree |
                   |   runs on which CPU set)    |
                   +-------------+---------------+
                                 |
 grant CPU + cgroup subtree
 v +------------------------------+ revoke CPU
              | Nested sub-scheduler      | <-----------------+
              |   (full enqueue/dispatch |                  |
              |    on delegated CPUs)       |                  |
              +-------------+----------------+                  |
                            |                                   |
                            v |
                  +-----------------------+ |
                  | per-CPU runqueue tasks |---------------------+
                  | (scx_task dispatching) |
                  +-----------------------+

Patch 概览

PR 主邮件列出了若干要点(正文被截断,仅就可见项整理):

  • Sub-scheduler CPU delegation:父调度器授予 / 撤销 per-CPU。
  • 依赖 BPF tree 的 arena argument 支持:先 BPF 后 scheduler 的合并顺序约束。
  • 基于 bpf-next 的 patch 单独分支:在 for-7.3-arena-args 上保留,再 merge 进 for-7.3,并已在 linux-next 上 soak 若干天。
  • Core scheduling 修复:v7.2 太迟未完成的修复,借本 PR 顺路合入。

关键实现

虽然 pull request 邮件没有贴出 hunk,但可以从公开 commit 历史和消息中还原关键路径:

/* 父调度器把 cgroup 子树 + CPU 授权交给子调度器 */
int scx_sub_dispatch(struct sched_ext_ops *parent_ops,
                     struct cgroup *cg, s32 cpu)
{
    /* 1. 把 cpu 加入子调度器的 allowed CPU 集合 */
    cpumask_set_cpu(cpu, sub_ops->allowed_cpus);

    /* 2. 把 cg 下的任务重新入队到子调度器 */
    scx_cgroup_iter_tasks(cg, migrate_task_to_sub_ops);

    /* 3. 触发一次 reschedule,让子调度器真正接管 */
    scx_ops_bypass(false);
    return 0;
}

/* 撤销:父调度器收回对某 CPU 的授权 */
int scx_revoke_cpu(struct sched_ext_ops *sub_ops, s32 cpu)
{
    cpumask_clear_cpu(cpu, sub_ops->allowed_cpus);
    /* 把当前 CPU 上的任务强制踢回父调度器队列 */
    scx_force_migration(cpu, parent_ops);
    return 0;
}

BPF 侧通过 bpf_arena 系列 helper 与 struct_ops 的 arena 参数,让 BPF 调度器在嵌套子调度时仍然可以引用共享 arena 对象。

类比

把分层 sub-scheduling 想象成一家连锁餐厅的总店和分店

  • **总店(root BPF scheduler)**决定"今天哪个分店开门迎客、给每个分店配多少张餐桌(per-CPU 授权)"。
  • **分店(nested sub-scheduler)**拿到桌子后,自己决定怎么安排客人点单、上菜顺序——对桌子上的客人有完整决定权。
  • 回收桌子(revoke CPU):总店要把这张桌子收回去做别的用途,会要求分店"现在还没入座的客人先回总店等位",入座中的客人继续吃完。
  • arena 参数支持像是分店的总菜单(BPF shared arena),菜单格式升级(kfunc 增加 arena 参数)后,必须先升级菜单系统(BPF tree),再升级分店调度系统(scheduler tree),否则分店就拿不到新的菜品。

Highlight:风险与注意点

  1. 合并顺序约束:本 PR 强依赖 BPF tree 的 arena 参数支持,Linus 必须先合 BPF、再合 scheduler,否则会出现编译期或运行期不匹配。
  2. late-cycle 合入的"堵漏"风险:enqueue-path 支持是晚周期完成,多个 race fix / 语义修补可能没有充分的 soak 时间,需要关注下一个 rc 周期是否出现回归。
  3. 嵌套子调度的复杂性:父/子调度器共享同一组 CPU,撤销授权时若有任务已经入队但未分派,可能出现"任务归属歧义";后续需要持续观察是否有 task 丢失或长时间 stall。
  4. Linux-next 已 soak 几天:作者特别强调结果已在 linux-next 上跑过数日,但仍建议 merge 后第一个 rc 重点跑 stress + 调度公平性 + cgroup 迁移相关测试。
  5. Core scheduling 修复捎带:本应属于独立 PR 的核心调度修复,借本 PR 路径合入——review范围被拉大,未来遇到回归时定位要分别考虑两条线。
  6. 截断的 PR 描述:邮件正文末尾被截断("Sub-scheduler CPU delegation: Parent schedulers now grant and revoke per-CP..."),完整变更列表需直接看 git log。

版本变化

本 PR 即 v7.3 一次性合并,与前序版本相比:

  • v7.2 → v7.3:完成 enqueue-path 的 sub-scheduling 支持(功能落地);v7.2 之前仅完成 dispatch路径。
  • v7.2 → v7.3:增加 BPF kfunc / struct_ops 的 arena 参数支持(跨子系统依赖)。
  • v7.2 → v7.3:补齐 core scheduling 一些迟到的修复。

与其他相关 patch 系列的关联

  • BPF next树 arena argument 支持:直接的硬依赖,已在 bpf-next 上落地。
  • sched_ext 之前若干 for-7.x 分支:本 PR 把它们统一 merge 进 tags/sched_ext-for-7.3
  • Linux-next soak:作者声明合并结果在 linux-next 已稳定运行数日,是合并前的最后一道防线。

一句话总结

本 PR 把分层 BPF 调度的入队路径"补完最后一公里":父调度器可以授予 /撤销子调度器对 cgroup + CPU 的完整控制权,并借机捎带一批 BPF arena 参数支持与 v7.2 漏掉的核心调度修复,是 sched_ext 走向"特性完整"的关键里程碑。