2026-06-25 内核社区日报

今天最值得关注的是 Rik van Riel 提交的 __access_remote_vm 通过 per-VMA lock 避免 mmap lock 争用的系列,有望大幅降低 proc/pid/mem 等监控工具的延迟;此外 Mike Rapoport 修复了 kernelcore=mirror 导致 ZONE_NORMAL 与 ZONE_MOVABLE 重叠的 bug,影响内存初始化的正确性。

🧠 重点 · 内存

1. __access_remote_vm 通过 per-VMA lock 避免 mmap lock 争用

发生了什么: Rik van Riel 提交了 v2 系列,让 __access_remote_vm() 在读取已驻留页面时无需全程持有 mmap_read_lock。系列包含三个补丁:
(1)x86/mm: 对 mm->context.untag_mask 添加 READ_ONCE/WRITE_ONCE 以支持无锁读取;
(2)mm/pagewalk: 让 folio_walk_start() 在 per-VMA lock 下运行;
(3)mm: 修改 __access_remote_vm(),对已驻留页面的读取路径优先使用 per-VMA lock + folio_walk_start(),仅在需要 page fault 时才退回到 get_user_pages_remote() + mmap lock。

v2 版本简化了代码、清理了逻辑并修复了 tlb_remove_table_sync_one() 相关的锁问题。

为什么重要: 监控工具(如 /proc/<pid>/mem、ptrace、crash 工具)在读取远程进程内存时可能因 mmap_lock 长时持有而阻塞,影响系统监控的可靠性。此系列通过引入 per-VMA 细粒度锁路径,减少了全局锁争用,有助于提升监控工具在重负载下的响应能力。

来源

2. 修复 kernelcore=mirror 导致 zone 重叠问题

发生了什么: Mike Rapoport 提交了一个补丁系列,包含两个改动:

  • mm/mm_init: don't overlap NORMAL and MOVABLE zones with kernelcore=mirror:避免在 kernelcore=mirror 参数下 NORMAL 与 MOVABLE 区域重叠。
  • mm/mm_init: drop overlap_memmap_init():删除原有的 overlap_memmap_init() 函数及相关逻辑。

该系列旨在统一 kernelcore= 参数的行为,将 mirror 视为另一种调整 zone 大小的方式,并清理内存映射初始化中一处奇怪的代码。

为什么重要: 补丁清理了内存映射初始化的奇怪部分,使 kernelcore= 参数在 mirror 模式下的行为与其他模式一致,消除了因特殊处理可能引发的潜在问题。

来源

3. 修复 page_owner 中的 TOCTOU 竞态

发生了什么: Ye Liu 发现 page_owner 在无锁读取 page 状态时存在两处 TOCTOU(time-of-check time-of-use)竞态:
(1)在 skip_buddy_pages() 中,buddy_order_unsafe() 返回的 order 值可能在 PageBuddy 检查与 private 字段读取之间被并发修改,产生垃圾值,导致 PFN 推进越过 pfn_valid() 边界,进而访问到无关内存。
(2)print_page_owner_memcg() 在函数开头通过 READ_ONCE 快照了 page->memcg_data,但末尾调用 PageMemcgKmem() 时却重新读取了 folio->memcg_data,可能与快照不一致,若页面在此期间被重分配为尾页或 slab 页则会触发 VM_BUG_ON

修复方案:对 skip_buddy_pages() 的 PFN 推进添加 MAX_ORDER_NR_PAGES 剪裁;在 memcg 打印处使用已快照的 memcg_data 值,不再二次读取 memcg_data

为什么重要: page_owner 是调试内存问题的关键工具,其无锁读取设计在避免性能影响的同时引入了 TOCTOU 竞态,可能导致调试信息错误甚至内核 panic。此修复消除了两个竞态路径,使工具在并发压力下更稳健。

来源

4. 避免 swap 耗尽时拆分 large folios(RFC 讨论继续)

发生了什么: David Hildenbrand 在该系列 RFC 讨论中指出,swap 路径不仅要检查“是否有 swap”,还应检查“是否有 free swap space”(即 get_nr_swap_pages() 的返回值),以区分拆分后是否可能成功 swap out。有讨论者对 get_nr_swap_pages() 的含义表示困惑,David 进一步说明需要向 memcg 查询拆分后能否成功 charge,以便向调用者清晰返回 -E2BIG(拆分后有希望)或 -ENOSPC/-ENOMEM(拆分也无用)。讨论聚焦于如何从 mem_cgroup_try_charge_swap() 获取可用 quota 信息。

为什么重要: 该讨论旨在让 large folio swap 逻辑能更精确地判断拆分是否可行,避免在 swap 空间实际不足时仍尝试拆分写入,从而改进 reclaim 路径的决策准确性。

来源

5. zswap 绕过 swap readahead 讨论持续

发生了什么: Alexandre Ghiti 提交 RFC,在 zswap 场景下跳过 swap readahead,理由是该读预取对内存压缩后端无用。Yosry Ahmed 回复指出,swap readahead 的触发时机可能影响顺序访问模式,并提出可保留 readahead 但仅实际预取位于磁盘的 swap 条目。Kairui Song 补充建议先检查 zswap_never_enabled 以避免非必要时执行 xa_load

为什么重要: zswap 作为内存压缩缓存,其访问模式与磁盘 swap 不同。调整 readahead 策略可减少不必要的设备访问,同时避免顺序性收益损失,该讨论影响 zswap 的最终实现路径。

来源

6. MGLRU: 修复 memcg reparenting 后 stale batch 更新(实现讨论)

发生了什么: Qi Zheng 提出 lock_batch_lruvec() 的实现方案:在 RCU 读锁下检查 css_is_dying,若当前 memcg 正在 dying,则向上遍历父 memcg 直至找到非 dying 的 memcg,然后对该父 memcg 的 lruvec 加锁并返回。Harry Yoo 表示同意该方案,并补充指出由于 reparenting 在 RCU 工作(于 lruvec 锁下进行),检查需同时在 RCU 和 lruvec 锁下进行。Qi 表示将采用此方法并更新至 v3。

为什么重要: 该修复确保在 memcg reparenting 过程中,aging batch 不会引用已释放或正在 dying 的 memcg 的 lruvec,从而避免因访问无效 lruvec 导致的问题,提升了 MGLRU 在动态创建/销毁 memcg 场景下的健壮性。

来源

🔧 其它子系统

eBPF

  • pahole BTF true signatures v10:Yonghong Song 提交了第 10 版补丁系列,使 vmlinux BTF 能编码编译器优化后的真实函数签名。编译器(特别是 clang)可能因死参数消除等优化改变源级签名,例如将结构体参数展开为对应字段,导致源级签名与实际 ABI 不匹配。该系列通过 DWARF 分析识别实际参数传递位置(如寄存器),在 BTF 中反映真实签名,并对 DW_CC_nocall 函数及无法通过位置检查的函数予以丢弃。实验显示,x86_64 上 69103 个内核函数中有 875 个签名被修改,最终仅 20 个无法获得真实签名;arm64 上 863 个修改,108 个无法获得。该系列在 btf_functions.sh 测试中已进行验证 来源
  • LoongArch BPF JIT: 修复 tail call count 处理:George Guo 修复了 LoongArch BPF JIT 中两个 tail call count 处理缺陷:① arena 程序在 prologue 中因多出的 REG_ARENA slot 使 BPF_TAIL_CALL_CNT_PTR_STACK_OFF() 未适配偏移,导致加载了 counter 值而非指针,可能引发内存损坏或内核恐慌;② emit_bpf_tail_call() 在空 prog_array slot 检查前就递增了 tail call count,导致每次空 slot 跳跃被计为一次调用,使程序提前达到 MAX_TAIL_CALL_CNT 限制。两补丁均带 Fixes 标签并 Cc: stable来源
  • bpf per-CPU global data 系列:Leon Hwang 回应 Andrii 的 review,讨论 skeleton 中 percpu map 的 mprotect 处理与 dangling pointer 清除(来源

文件系统 / VFS

今日无独立条目。

调度 / 锁

今日无独立条目。

👀 值得追的讨论 / Patch

1. hugetlb PTE 访问修复系列

Dev Jain 提交了 5 个补丁,指出多处代码直接使用 ptep_get() 访问 hugetlb 的 PTE 项,但某些架构(如 arm64)的 hugetlb PTE 对应的是 cont-PTE 或 PMD 级别,需要专用 huge_ptep_get()。此前 try_to_unmap_one() 已有一份独立补丁(来源),但该补丁被 kbuild test robot 报告在 csky 架构上产生编译错误(未定义 huge_ptep_get)。dev.independent 的工作尚处于 review 阶段,需要解决架构兼容性问题。

2. zswap + zeroswap 作为 vswap 后端(RFC v2)

Yosry Ahmed review 该补丁,建议将一处注释归入前一个补丁,指出 partial_store 变量可省略而直接检查 index,并建议将 vswap 相关代码整理到 if (!ret) 块内以增强可读性。讨论聚焦于代码结构优化。来源

3. mm/mmu_notifier, drm/amdgpu: 为 GPU 用户映射阻止 THP

蒋亦韬 提交 RFC,通过 mmu_notifier 的 interval notifier 机制,允许驱动标记某个 VMA 范围内不允许 THP 用户映射。这在来自 GPU(amdgpu、amdkfd)的 HSA userptr 场景中非常必要,因为 GPU MMU 可能不兼容 page 的 struct page 连续性。这是对 drm 子系统的补充。

来源

⚡ 一句话速览

  • zsmalloc 锁释放:Nhat Pham 的 v5 补丁在 64 位系统上从 zs_free() 中移除 pool->lock,今日讨论聚焦于如何优雅获取对象类锁(get_and_lock_obj_class()),尚未定稿 来源
  • page_owner per-file-descriptor 过滤:Zhen Ni 提交系列为 page_owner 增加 per-file-descriptor 过滤能力;Ye Liu 指出其功能与 commit 156c0c5d1463(“mm/page_owner: introduce struct stack_print_ctx”)相似,并计划提供审查意见 来源
  • DAMON 清理与文档更新:SeongJae Park 提交 RFC v1.1,包含 11 个补丁:更新设计文档、添加 sysfs 测试、重构 probe 和 filter 的 setup 函数、修复 typos 等 来源
  • memcg 移除废弃宏:Joshua Hahn 清理了未使用的 for_each_mem_cgroup 宏及相关代码 来源
  • page_vma_mapped 增加 THP 编译保护:Wei Yang 为 check_pmd() 添加 CONFIG_TRANSPARENT_HUGEPAGE 保护,避免未定义引用 来源
  • arch_numa 移除冗余 nodemask 清除:Sang-Heon Jeon 移除了 numa_init() 中重复的 nodes_clear() 调用,因为这些 mask 已在 numa_memblks_init() 中被清除,无功能变化。来源
  • KASAN 在 5 级 paging 下误报修复:Boris 在回复中建议,若需稳定版修复,可先以禁用 5 级页表时 KASAN inline 的一行补丁作为临时方案,后续补丁再移除该修复 来源
  • kmalloc_obj 等文档警告修复:Jakov Novak 修复了 kernel-doc 注释中 GFP 参数缺失导致的文档生成警告 来源
  • tools/mm: 添加 thp_swap_allocator_test 到 .gitignore:Zenghui Yu 提交单补丁,避免测试二进制文件被意外 track 来源