sched discussion
[PATCH 0/2] sched/numa: stop VMA scan filters from gating promotion
LLM 分析
sched/numa:解除 VMA 扫描过滤器对 tiering promotion 的封锁
系列概况
- 标题: [PATCH 0/2] sched/numa: stop VMA scan filters from gating promotion
- 作者: Gregory Price (Meta) gourry@gourry.net
- 版本: 无显式版本号,按 v1 处理(作者已声明下周发 v2)
- 规模: 3 个文件,+47 / -10
- 修改文件:
include/linux/mm_types.h、kernel/sched/fair.c、mm/mempolicy.c - 代码统计: Patch 1:+32/-9;Patch 2:+16/-2
- Message-ID:
20260904182006.1562449-1/2/3-gourry@gourry.net;回复apsWE-y0nV5r1_5Z@gourry-fedora-PF4VCD3F、apsX_E8GBzfp6lui@gourry-fedora-PF4VCD3F - 完整性: 完整 2/2 系列 + 2 封作者自回复(自我披露的 v2 计划),无 maintainer 评审
补丁目的
NUMA balancing 在 task_numa_work() 里对 VMA 做两层过滤——per-VMA PID filter(要求扫描任务本任务曾经 hint-fault 过该 VMA)和 read-only file mapping 排除——这两条规则源自 socket-residency 时代:跳过 VMA 顶多损失一点扫描精度。
进入 memory tiering(DRAM + CXL)后语义反转:hint fault 不再只是 placement 信号,而是 promotion 的入口——慢层 folio 被 promote 的唯一理由就是"被扫到 + 被访问"。被过滤掉的 VMA 永远进不了 promotion 候选。结果是大型 shmem VMA 吃光扫描周期,其余 ~84G 地址空间卡在"inactive"——一个 20G hash table 全部堆到 CXL 上,DRAM 带宽从 200GB/s 跌到 150GB/s,请求延迟从 800us 飙到 5ms。
旧流程的问题
- PID filter 自指:VMA 需要 hint fault 才能在
pids_active里留下痕迹;没扫就没有 hint fault;没有 hint fault 扫描任务就被vma_is_accessed()拒绝——自我锁死。 - RO 文件一刀切:
commit 4591ce4f2d22(shared library hint 优化)的前提是"RO 文本在多核间 cache 复制,迁移收益低",但 tiering 下慢层 folio 是可以 promote 的,只是一直没人扫它——91% 主程序二进制跑到了 CXL。
新流程
不删任何过滤。在 VMA 状态里加 vma->numab_state->slow_only 标志。被旧过滤拒绝的 VMA 仍被扫描一次,但只对非 toptier 节点的 folio 做 hint fault 标记;toptier folio 的标记行为与旧过滤完全一致。受限扫描可能没走完 VMA,故不能动 prev_scan_seq,否则会让该 VMA 永久跳过 vma_is_accessed()。
Old flow (task_numa_work):
+--------------------------------------------------+
| for vma in vma_list: |
| if vma_is_ro_file(vma): skip (all) |
| if !vma_is_accessed(mm,vma): skip (all) |
| scan_vma(vma) mark all folios|
| prev_scan_seq = numa_scan_seq |
+--------------------------------------------------+
New flow (tiering mode only):
+--------------------------------------------------+
| for vma in vma_list: |
| ro_file = vma_is_ro_file(vma) |
| if ro_file && !tiering: skip |
| slow_only = ro_file |
| if !vma_is_accessed(mm,vma): |
| if !tiering: skip |
| slow_only = true |
| scan_vma(vma, slow_only) |
| if !slow_only: |
| prev_scan_seq = numa_scan_seq |
+--------------------------------------------------+
folio_can_map_prot_numa() gate:
+--------------------------------------------------+
| if node_is_toptier(nid) && |
| (!(mode & NORMAL) || slow_only): |
| return false (this folio not marked) |
| else: |
| allow hint fault |
+--------------------------------------------------+
Patch 概览
- Patch 1:在
struct vma_numab_state增加bool slow_only;task_numa_work()在 tiering 模式下把被 PID filter 拒绝的 VMA 降级为slow_only扫描;folio_can_map_prot_numa()同步识别slow_only,对 toptier folio 退避。 - Patch 2:新增
vma_is_ro_file()helper;task_numa_work()在 tiering 模式下不再 skip RO 文件映射,转而设slow_only = ro_file。
关键实现
/* Patch 1: restricted scan entry */
vma->numab_state->slow_only = false;
if (!vma_pids_forced && !vma_is_accessed(mm, vma)) {
if (!(sysctl_numa_balancing_mode &
NUMA_BALANCING_MEMORY_TIERING)) {
vma_pids_skipped = true;
trace_sched_skip_vma_numa(mm, vma,
NUMAB_SKIP_PID_INACTIVE);
continue;
}
vma->numab_state->slow_only = true;
}
/* Patch 1: restricted scan may not finish the VMA,
* so do not disarm the get_nr_threads() horizon. */
if (!vma->numab_state->slow_only)
vma->numab_state->prev_scan_seq = mm->numa_scan_seq;
/* Patch 2: RO file mapping takes the restricted path */
static bool vma_is_ro_file(struct vm_area_struct *vma)
{
return vma->vm_file &&
(vma->vm_flags & (VM_READ | VM_WRITE)) == VM_READ;
}
...
/* inside task_numa_work() */
ro_file = vma_is_ro_file(vma);
...
vma->numab_state->slow_only = ro_file;
/* mm/mempolicy.c: toptier folio suppressed under slow_only */
if (node_is_toptier(nid) &&
(!(sysctl_numa_balancing_mode & NUMA_BALANCING_NORMAL) ||
(vma->numab_state &&
vma->numab_state->slow_only)))
return false;
类比
旧过滤像门禁——住户必须先刷卡(hint fault)访客才会登记,扫楼只能记已经登记的房间。tiering 模式改成"代收快递":访客每轮把整栋楼信箱都过一遍,但只挑地下室(慢层)包裹送上去,顶楼住户的箱子纹丝不动。地面秩序不变,地下室积压才被搬到顶楼。
Highlight:风险与注意点
- 作者自爆 bug:sashiko 指出 Patch 1 无条件
slow_only = false会让跨两次扫描的 VMA 过早重新受扫描;Patch 2 的slow_only = ro_file会让正常 VMA 在首轮后被错误标为受限扫描。作者承认并将出 v2。 - v2 计划修复:
if (mm->numa_scan_offset <= vma->vm_start) slow_only = false;,以及 patch 2 中对slow_only = ro_file语义的复核。 numa_scan_offset单点救援:作者在回复中解释光标防 restart、reset_ptenuma_scan()bump sequence、mm->numa_next_scan串行化扫描器,但 pte_protnone 重走路径的代价需要 trace 验证。- 首次扫描僵局:fork 后第一次扫且大 VMA 吃光周期时,小 VMA 永远凑不齐 hint fault,本 patch 只在 tiering 模式打破这一僵局,普通 NUMA 模式不受影响。
- 正确性边界:
slow_only仅控制 hint fault 标记,不影响 promotion 触发后task_numa_fault()报目的节点到numa_faults[]——即只改变"谁可以发起 promotion",不改变 promotion 之后的行为。
版本变化
本帖仅 v1,作者已声明 v2 待发,关键改动:
- Patch 1:
slow_only复位加 guardif (mm->numa_scan_offset <= vma->vm_start); - Patch 2:复核
slow_only = ro_file对正常 VMA 的副作用(避免首次扫描后误分类)。
一句话总结
在 memory tiering 模式下,让被 per-VMA PID filter 与 RO 文件映射过滤掉的 VMA 仍以"只看慢层 folio"的受限方式参与扫描,从而为 CXL 等慢层 folio 打开 promotion 通道,toptier 标记行为不变。