0/12 已展开

LLM 分析

sched/isolation 与 cgroup/cpuset:DHM v4 运行时 housekeeping 管理

系列概况

  • 标题[PATCH v4 00/11] Dynamic Housekeeping Management (DHM) via CPUSets
  • 作者:Jing Wu <realwujing@gmail.com>;Qiliang Yuan 共同开发并签署补丁
  • 版本:v4
  • 规模:1 封 cover letter、11 个 patch,共 12 封邮件
  • 修改文件:涉及 sched/isolationcpusetcontext_tracking、RCU NOCB、tick/nohz、watchdog、Hyper-V、arm64 topology、cgroup 文档和 selftests,共 20 个文件
  • 代码统计:1181 行新增、65 行删除
  • Message-ID20260710-wujing-dhm-v4-0-2e912e5d9645@gmail.com
  • 完整性:输入包含 cover letter 和 11/11 patch;部分邮件中的 diff 被整理或截断,尤其 patch 01 和 patch 11,因此细节分析以可见代码、commit message 和 cover letter 为限。基线提交为 eb3f4b7426cfd2b79d65b7d37155480b32259a11

补丁目的

DHM 希望把过去主要由启动参数确定的 kernel-noise housekeeping 隔离,接入现有的 cgroup v2 cpuset isolated partition,使管理员能够在运行时动态完成:

  • nohz_full 调度 tick 抑制;
  • RCU callback NOCB offload;
  • managed IRQ 迁移;
  • watchdog 从隔离 CPU 上撤出;
  • 销毁 isolated partition 后恢复启动时的 housekeeping 配置。

该系列不新增 cgroup 文件或其他用户空间 ABI。用户仍然只需向 cpuset.cpus.partition 写入 isolated

其中最明确的“零启动参数”能力是:即使启动时没有 nohz_full=rcu_nocbs=,也可以在首次运行时隔离时懒初始化 tick 和 RCU NOCB 基础设施。

旧流程的问题

  1. HK_TYPE_KERNEL_NOISEHK_TYPE_MANAGED_IRQ 等 mask 主要在启动时形成,缺少安全的运行时更新模型。
  2. 直接并发修改 mask 不足以让 tick、RCU 和 IRQ 的 per-CPU 状态同步改变,也可能让 reader 访问已经释放的旧 mask。
  3. context_tracking_key 原来是只允许启动阶段修改的 static key,ct_cpu_track_user() 也带有 __init 限制。
  4. 没有 rcu_nocbs=nohz_full= 时,RCU NOCB 组织结构没有初始化,运行时 offload 会因 nocb_gp_rdp 未建立而失败。
  5. CPU cycling 的临时 offline 状态会使 cpuset 的 effective CPU 集短暂变空,进而被误判为 partition 失效。
  6. watchdog 在启动后持有独立 mask;housekeeping mask 运行时改变时,它不会自然同步。
  7. v3 尝试通过 subsystem apply callback 原地应用新 mask,但 cover letter 记录 Thomas Gleixner 认为这种并发应用方式从根本上不安全,因此 v4 改用 CPU hotplug 生命周期。

新流程

创建 isolated partition 时,cpuset 先更新 sched-domain housekeeping mask,再从不可变的启动快照计算 kernel-noise 和 managed-IRQ mask。随后释放 cpuset 与 CPU read-side 锁,逐个循环状态发生变化的 CPU。

隔离 CPU 的主要顺序是:

  1. remove_cpu() 将 CPU offline;
  2. 将 CPU 加入 tick_nohz_full_mask,启用 context tracking;
  3. 懒初始化 RCU NOCB,并 offload 该 CPU 的 callback;
  4. add_cpu() 重新上线;
  5. 让 IRQ dying/online hotplug callback 根据新的 HK_TYPE_MANAGED_IRQ mask 完成迁移;
  6. 全部 CPU 处理后重新同步 watchdog mask。

解除隔离时,系统根据 dhm_prev_isolated 计算反向差集,在 CPU offline 期间执行 RCU de-offload 和 tick de-isolation,再重新上线。

User writes "isolated" to cpuset.cpus.partition
                     |
                     v
Update DOMAIN, KERNEL_NOISE, and MANAGED_IRQ masks
                     |
                     v
Drop cpuset and CPU read locks
                     |
                     v
Mark changed CPUs in dhm_cycling_cpus
                     |
                     v
remove_cpu -> update tick and RCU state -> add_cpu
                     |
                     v
IRQ hotplug callbacks read the new masks
                     |
                     v
Clear cycling mask -> resync watchdog

dhm_cycling_cpus 相当于告诉 cpuset:这些 CPU 的暂时消失是 DHM 主动执行的中间步骤,不应把 partition 标记为 invalid。

Patch 概览

  1. Patch 01,housekeeping 基础模型
    增加 HK_TYPE_KERNEL_NOISE_BOOTHK_TYPE_MANAGED_IRQ_BOOT 等启动快照类型,并增加 housekeeping_cpumask_rcu()housekeeping_update_types()。运行时 mask 始终从不可变 boot mask 重新计算。

  2. Patch 02,RCU reader 审计
    修改 sched/core、hrtimer、arm64 topology、Hyper-V 和 CPU sysfs 等 reader,使它们在 RCU read-side critical section 内读取可能被替换的 cpumask。TIMER 和 TICK 的修改属于防御性修正。

  3. Patch 03,cpuset 触发 mask 更新
    isolated partition 除更新 HK_TYPE_DOMAIN 外,也更新 HK_TYPE_KERNEL_NOISEHK_TYPE_MANAGED_IRQ。sched-domain 更新排在前面,因为 workqueue flush 和 timer migration 依赖它。

  4. Patch 04,运行时 context tracking
    拆分 ct_cpu_track_user()ct_cpu_untrack_user() 和启动期包装函数,允许 offline CPU 在运行时启停 user/kernel context tracking。

  5. Patch 05,RCU NOCB 懒初始化
    新增 rcu_nocb_lazy_init()rcu_nocb_cpu_isolate();首次隔离时才分配 NOCB mask、组织 GP/CB 关系并创建 kthread。

  6. Patch 06,watchdog 同步
    保存 watchdog 启动快照,并通过 lockup_detector_hk_update() 将它与当前 HK_TYPE_KERNEL_NOISE mask 求交后重配 detector。

  7. Patch 07,运行时 full-dynticks
    新增 tick_nohz_cpu_isolate()tick_nohz_cpu_deisolate(),首次调用时懒分配 tick_nohz_full_mask

  8. Patch 08,抑制临时 partition invalidation
    增加 dhm_cycling_cpus 和对应 spinlock,同时覆盖 local partition 与 remote-partition disable 判断路径。

  9. Patch 09,核心 hotplug orchestration
    实现 dhm_cycle_isolated_cpus(),计算 newly-isolated 和 newly-deisolated 差集,并串联 CPU offline、tick、RCU、IRQ hotplug callback 和 online 流程。

  10. Patch 10,文档
    说明 isolated partition 会扩展到 tick、RCU NOCB 和 managed IRQ,并记录 non-hotpluggable CPU 的限制。

  11. Patch 11,自测试
    增加 cpulist range 解析、nohz_full 精确集合比较、RCU NOCB kthread affinity 检查,以及创建、销毁、全 CPU 隔离拒绝、SMT 和不可 hotplug CPU 等场景。

关键实现

运行时 mask 不能基于当前已经缩小的 mask 继续求差集,否则 CPU 一旦退出 housekeeping 集合,销毁 partition 时也无法恢复。正确做法是始终以 boot snapshot 为锚点:

if (type == HK_TYPE_KERNEL_NOISE &&
    !(housekeeping.flags & HK_FLAG_KERNEL_NOISE_BOOT))
        base = cpu_possible_mask;
else if (type == HK_TYPE_KERNEL_NOISE)
        base = housekeeping_cpumask(HK_TYPE_KERNEL_NOISE_BOOT);
else if (type == HK_TYPE_MANAGED_IRQ)
        base = housekeeping_cpumask(HK_TYPE_MANAGED_IRQ_BOOT);

cpumask_andnot(trial, base, isol_mask);

新 mask 分配并验证后,通过 RCU 替换指针;旧 mask 只能在 grace period 结束后释放。对应 reader 必须在 RCU 临界区内完成解引用和使用,不能把返回的指针带出临界区。

Patch 09 的核心状态计算是:

cpumask_andnot(newly_isolated,
               new_isolated, dhm_prev_isolated);
cpumask_andnot(newly_deisolated,
               dhm_prev_isolated, new_isolated);
cpumask_copy(dhm_prev_isolated, new_isolated);

因此只 cycling 状态真正发生变化的 CPU,而不是每次重做整个 isolated 集合。

managed IRQ 没有新增专用 apply 函数。CPU offline 时的 irq_migrate_all_off_this_cpu() 和 online 时的 irq_affinity_online_cpu() 会读取已经更新的 housekeeping mask,从而复用现有 hotplug 机制。

类比

可以把 housekeeping CPU 看成工厂里的“后勤班组”,隔离 CPU 则是要求保持安静的“精密加工车间”。

启动参数像建厂时确定的固定规划图。旧模式只能在开工前决定哪些车间承担巡检、清运和广播任务,运行中很难安全改变。

DHM 则像一次受控的车间停产改造:

  • remove_cpu() 是让车间暂时停产并清空现场;
  • tick suppression 是关闭周期性广播;
  • RCU NOCB offload 是把待处理单据送到后勤办公室;
  • managed IRQ migration 是把临时通知转给其他车间;
  • add_cpu() 是按新职责重新开工;
  • boot snapshot 是永久保留的原始厂区图,撤销隔离时据此精确恢复,而不是根据多次修改后的临时图猜测原状;
  • dhm_cycling_cpus 是门口的“计划检修中”标志,避免管理系统把短暂停产误报为车间永久失效。

Highlight:风险与注意点

  1. 失败处理不是事务式的tick_nohz_cpu_isolate()rcu_nocb_cpu_isolate()add_cpu() 的失败主要通过 WARN_ON_ONCE() 报告。若中间步骤失败,mask、tick、RCU 和 CPU online 状态可能只完成了一部分,代码片段中没有完整 rollback。

  2. mask 更新错误是否应阻止 cycling:patch 03 对 housekeeping_update_types() 的错误使用 WARN_ON_ONCE(),而不是向上返回;随后 patch 09 仍可能继续 cycling。需要验证 -ENOMEM-EINVAL 时不会出现“per-CPU 状态已变化但全局 mask 未变化”的不一致。

  3. 必须保留 housekeeping CPU:trial mask 会检查是否仍与 cpu_online_mask 相交。全 CPU 隔离应被拒绝,自测试也专门覆盖这一点。

  4. non-hotpluggable CPU 无法获得完整 DHM 隔离:典型的 x86-64 CPU0 会被跳过并告警。它可以出现在 isolated partition 中,但仍可能保留 tick 和 RCU housekeeping 职责,用户不能把 sched-domain isolation 等同于完整 kernel-noise isolation。

  5. managed IRQ 的零启动参数语义需确认:可见的 patch 01 只允许 HK_TYPE_KERNEL_NOISE 在未 boot-enable 时首次启用;其他类型会被跳过。因而“无 nohz_full=/rcu_nocbs=”能力很清楚,但从未启用 isolcpus=managed_irq 时 managed IRQ mask 的预期行为需要结合完整代码验证。

  6. watchdog 与运行时 sysctl 的交互需验证:可见代码只在 lockup_detector_init() 中保存 watchdog_cpumask_boot。如果管理员启动后通过 sysctl 收窄 watchdog mask,后续 DHM 更新是否会覆盖该设置,取决于未展示路径是否同步更新快照。

  7. RCU reader 审计必须完整:任何遗漏的 reader 如果在 RCU 临界区外长期使用 runtime-mutable mask 指针,都可能访问 grace period 后已经释放的内存。

  8. hotplug cycling 有运行时扰动:每个变化的 CPU 都要真实 offline/online。即使设计上安全,也需要评估任务迁移、设备 callback、CPU hotplug 延迟和多 CPU 大批量切换的管理面影响。

  9. remote partition 是已知脆弱点:v4 特别扩展 dhm_cycling_cpus 检查以修复 TEST_MATRIX[69],说明 local 与 remote partition 的 transient-empty 判断都必须持续回归测试。

  10. 相关系列:cover letter 明确关联 Waiman Long 的 [PATCH-next 00/23]。两者都面向 cpuset runtime housekeeping,DHM 的突出差异是通过 hotplug cycling 实现无 nohz_full=/rcu_nocbs= 的首次运行时激活;输入未包含两系列最终合并或取舍结论。

版本变化

  • V3 到 V4:删除 struct housekeeping_cbspre_validateapply 和通知式 subsystem apply 架构,改成逐 CPU hotplug cycling;修复 RCU NOCB 函数被放入 .init.text 后引发的 NX page fault;扩展 cycling 抑制到 remote-partition disable 路径,修复 TEST_MATRIX[69]

  • V2 到 V3:notifier chain 改为显式 per-type callback;housekeeping cpumask 指针改为 RCU 保护;修复 CPU hotplug 锁死锁和异步 work 中保存旧 mask 导致的 UAF;补充 context tracking、watchdog、RCU reader 和 selftest。该 callback 架构随后在 v4 被整体撤销。

  • V1 到 V2:系列从 DHEI 改名为 DHM;删除自定义 sysfs ABI,改用 cgroup v2 cpuset isolated partition;增加 SMT-aware 限制、文档、自测试和 RCU-safe mask handover。

一句话总结

DHM v4 通过“先更新 RCU-protected housekeeping mask,再逐 CPU offline、重配并 online”的方式,把 nohz_full 和 RCU NOCB 等隔离能力接入 cpuset isolated partition,但错误回滚、不可 hotplug CPU、managed IRQ 首次启用语义及 watchdog 配置交互仍是评审时最值得关注的部分。