2026-07-03 内核社区日报

今日多位开发者提交了 khugepaged 在 collapse 文件页时确保回写所有 dirty folio 的修补、hugetlb 的 NULL 指针解引用修复、以及 KHO 机制支持保留高 order 页面的新能力。同时,userfaultfd 的 guest 内存工作集追踪系列更新至 v8,alloc_flags 外层重构也推进到 v5。

🧠 重点 · 内存

1. 对 mTHP 统计计数进行调整

发生了什么: Nico Pache 提交了两个补丁:在 free_zone_device_folio() 中递减 MTHP_STAT_NR_ANON;在迁移路径中排除 hugetlb folio 的 MTHP_STAT_NR_ANON 统计。

为什么重要: 这两个调整使 MTHP_STAT_NR_ANON 在 zone device folio 释放和 hugetlb folio 迁移时不被误计,保证统计准确性。

来源

2. hugetlb PTE 访问修正系列(统一使用 huge_ptep_get()

发生了什么: Dev Jain 发布了 v3 系列(6 个补丁),统一将 hugetlb 相关路径中的 ptep_get() 替换为 huge_ptep_get()。动机:部分架构(如 s390)需要特殊处理才能正确计算 hugetlb 的 PTE 值,因此提供了 huge_ptep_get() 辅助函数;同时,arm64 上存在向 huge_ptep_get() 传入非对齐地址的问题,补丁 1 专门修复了该情况。受影响函数包括 try_to_unmap_one()try_to_migrate_one()remove_migration_pte()page_vma_mapped_walk()prot_none_hugetlb_entry() 等。

为什么重要: 该系列使 hugetlb 的 PTE 读取在不同架构间保持一致行为,并解决了 arm64 上因地址未对齐而可能获取错误 PTE 值的问题,提高了代码健壮性和可移植性。

来源

3. userfaultfd:重新注册时不清理旧 uffd-wp 状态

发生了什么: Jianhui Zhou 发现对同一 userfaultfd 上下文重复执行 UFFDIO_REGISTER 时,若第二次注册移除了写保护(WP)模式(如从 UFFDIO_REGISTER_MODE_WP 改为 MODE_MISSING),内核会更新 VMA 标志但不清除页表项中残留的 uffd-wp 状态。该残留状态可能存在于交换 PTE 中,当 do_swap_page() 从交换 PTE 恢复 _PAGE_UFFD_WP 并安装可写 PTE 时,会触发 page_table_check 报警(pte_uffd_wp(pte) && pte_write(pte))。补丁在注册路径中检测 VMA 是否已在同一上下文下注册,若新模式不再包含 WP 则调用 uffd_wp_range 清除 PTEs 上的 uffd-wp 标记,并在同一上下文的快速路径中要求模式精确匹配而非子集检查。

为什么重要: 修复了 re-register 可能导致的 page_table_check 误报,使内核在切换 uffd 模式时正确清理页表状态,避免潜在的内存检查异常。

来源

4. memcg 的 css_reset 遗漏 zswap 和 oom.group 重置

发生了什么: Jiayuan Chen 提交了 2 个修补(v3),修复 mem_cgroup_css_reset() 未正确重置 memory.zswap.maxmemory.zswap.writebackmemory.oom.group 的问题。当 memory controller 被禁用但 cgroup 因子系统依赖(如 io 控制器声明 depends_on)无法销毁时,css_reset 应当将 memcg 恢复为默认状态,但 zswap 限流值、writeback 设置及 oom_group 未被清除,导致残留策略在后续重新启用 memory 控制器后继续生效。

为什么重要: 该 bug 使得 cgroup 被重新使用(例如通过 cgroup.subtree_control 禁用再启用 memory 控制器)时,旧的 zswap 限流和 oom.group 行为错误地继承,可能引发内存策略泄漏或 OOM 行为异常,影响内存管理的正确性。

来源

5. alloc_flags API 清理系列 v5

发生了什么: Brendan Jackman 发布了 18 个补丁的 v5 系列,涉及 page allocator 内部 API 的清理。改动包括:(1)将 ALLOC_TRYLOCK 重命名为 ALLOC_NOLOCK;(2)在 mm/page_alloc.h 中拆分出内部 alloc_flags 定义;(3)统一 __alloc_frozen_pages_nolock_noprof() 与普通入口;(4)移除 __alloc_pages_node();(5)将 __GFP_NO_CODETAG 从 GFP 标志移入 alloc_flags 位(ALLOC_NO_CODETAG);(6)移除 __GFP_NO_OBJ_EXT 标志;(7)解耦 can_spin_trylock() 检查。

为什么重要: 该系列通过重命名、分割头文件、统一路径、移除废弃接口和移动标志位,减少了 alloc_flags 命名空间的混淆,简化了 page allocator 的内部 API。

来源

6. KHO 支持保留未拆分的 high-order 页面

发生了什么: Pranjal Shrivastava 发布了一个 4 补丁的 RFC,扩展 Kexec Handover (KHO) 机制以正确保留未拆分的 high-order buddy 分配。当前 KHO 恢复阶段对所有 multi-page 块按拆分页方式初始化(每页 refcount = 1),但 DMA 分配器(如 dma_alloc_coherent)常返回 high-order non-compound 页面,此时只有 head page 的 refcount 为 1,tail pages 为 0。恢复时强制将 tail pages 的 refcount 置为 1,在 CONFIG_DEBUG_VMdebug_pagealloc=on 下会触发 page_expected_state() 检测到异常,导致内核 taint 并泄漏页面。该系列引入 Page Type 字段,在保存时通过检查每块第二页的 refcount 检测物理状态(CONTIG 或 SPLIT),将类型位存储在 KHO radix tree key 高位和 page->private 中;恢复时根据元数据应用正确的 refcount 模式,并新增 kho_split_preserved_pages() 辅助函数供驱动调用。

为什么重要: 若不区分 high-order 页与普通页,恢复后的 high-order 页被伙伴系统误当作分散的 order-0 页,会导致内核 taint 和页面泄漏。本系列填补了这一空白,使 KHO 能真实保留跨 kexec 的高 order DMA 分配,避免调试模式下因 refcount 错误引发崩溃。

来源

7. userfaultfd: working set tracking for VM guest memory (v8)

发生了什么: Kiryl Shutsemau 提交了该系列 v8 版本(15 个补丁)。主要改动包括:将 protnone 辅助宏从 CONFIG_NUMA_BALANCING 解耦,重命名 uffd-wp 的 PTE 位宏及访问器为 uffd,新增 PAGE_IS_ACCESSED 页表遍历 API,以及添加 UFFDIO_REGISTER_MODE_RWPUFFD_FEATURE_RWP_ASYNC 等用户接口。

为什么重要: 该系列为 userfaultfd 新增 RWP(Read-Write-Protect)模式,允许用户态追踪虚拟客户机内存的访问/脏状态,从而实现工作集追踪。这扩展了 userfaultfd 的应用场景,有助于更精细的内存管理。

来源

8. Keep tail page private zero at free and folio split time (v2)

发生了什么: Zi Yan 提交了 v2 系列(5 个补丁),目标是在释放和 folio split 时确保 tail page 的 page->private 为零。具体改动包括:在 percpu-km 路径释放前清零 page->private;停止在 compaction 中向 page->private 记录 free page order;在 __split_folio_to_order() 中恢复对 page->private 的检查;在 page free 时确保 tail page 的 page->private 为零;以及移除 prep_compound_tail() 中设置 page->private 的调用。

为什么重要: 这些改动统一了 tail page 的 page->private 清零行为,避免不同路径(percpu-km 释放、compaction 记录、folio split 检查、compound tail 初始化)遗留不一致的值,从而保持该字段在 free 时的干净状态。

来源

9. userfaultfd: working set tracking for VM guest memory (v8)

发生了什么: 该补丁系列为userfaultfd新增了UFFD_FEATURE_WP_UNPOPULATED特性,允许在VM客户机内存中通过写保护(write-protect)机制跟踪工作集(working set)。具体地,当启用该特性后,未分配的物理页(unpopulated pages)在首次访问时会触发userfaultfd事件,从而让用户空间(如VMM)能够记录哪些内存区域被实际使用。

为什么重要: 该特性使虚拟机监控器(VMM)能够精确识别客户机内存的工作集,从而优化内存超分配(overcommit)场景下的页面换入/换出策略,减少不必要的内存拷贝和I/O开销。v8版本修复了此前版本中与透明大页(THP)交互时的竞态条件,并改进了与UFFDIO_WRITEPROTECT ioctl的兼容性。

来源

🔧 其它子系统

驱动 / PCI

  • per-VF sysfs 延迟创建加速 SR-IOV 启动:Pavol Sakac 的 14 个补丁系列通过在 kernfs 层引入延迟目录创建(KERNFS_LAZY)标记,在第一个 VF 被打开前不生成所有 VF 的 sysfs 节点,从而大幅减少 SR-IOV 的 init 时间。这对于拥有数千 VF 的云计算 NIC 场景非常重要。来源

脚本 / ftrace

  • sorttable 脚本为 arm64 添加构建时 mcount_loc 排序:arm64 的 mcount_loc 段在 ELF 中仅含零,实际函数地址存于 .rela.dyn 段的 Elf_Rela 项。sorttable 工具通过读取 Elf_Rela 项中的地址、排序后再写回,使这些地址在启动时已有序,省去以往启动时排序的开销。该补丁进入 6.6-stable 树。来源

ACPI / NUMA

  • numa_memblks 清除 NUMA init 冗余操作(v2 合入):Sang-Heon Jeon 的系列被 Mike Rapoport 合并。核心是在 numa_add_memblk() 中统一设置 numa_nodes_parsed,从此所有架构(x86/ARM64/LoongArch)的初始化代码不再需要各自手动调用 node_set()来源

调度 / 无关项

  • seccomp __secure_computing() 改为返回 bool:Jinjie Ruan 补丁系列 v16 的第 1 个 commit 将该函数返回值从整数改为 bool,引入 !secure_computing() 逻辑反转。Michal Suchánek 不认同反转,认为命名 secure_computing() 本身语义不清;Thomas Gleixner 与 Mark Rutland 则支持反转,并建议将函数重命名为 seccomp_permits_syscall() 以明确语义。讨论无其他实质分歧。来源

👀 值得追的讨论 / Patch

  • Lorenzo Stoakes 拒绝了 damon_collapse_folio_range() 补丁,认为导出 THP 逻辑并在核心 mm 代码中放置 DAMON 包装器不可接受。SJ Park 认同 Lorenzo 的观点,指出 PMD 级 DAMOS_COLLAPSE 已存在,建议用户先进行 PMD 级 collapse 再拆分为所需 mTHP 级别,以避免对外部代码的干扰。来源

已报道系列状态更新(无新分歧)

  • huge page split 时 PG_has_hwpoisoned 设置时机修复:Rik van Riel 提交补丁,修复 __split_folio_to_order()folio_set_has_hwpoisoned()clear_compound_head()/prep_compound_page() 之前调用导致 VM_BUG_ON 的问题。该补丁将设置移到之后,以满足 FOLIO_SECOND_PAGE 前置条件,修复了 hwpoison 注入大 shmem folio 后执行 MADV_REMOVE(fallocate punch hole)触发的内核崩溃。获得多位 reviewer 的 Reviewed-by/Acked-by。来源
  • DAMON 参数校验统一至 core 层:SJ Park 发布系列 v1.1,包含 8 个补丁,将参数校验逻辑集中到 core 层并移除 DAMON sysfs、reclaim 和 lru_sort 中的重复检查。来源

⚡ 一句话速览

  • Open HugeTLB allocation routine (v4):Ackerley Tng 发送 v4,继续将 hugetlb 分配逻辑重构为通用接口,包括合并 gbl_chg 解读、移动 mpol 解读、提前 mem_cgroup 计费、提取 hugetlb_alloc_folio() 等。来源
  • HMM userfaultfd mmap lock 释放支持 (v5):Stanislav Kinsburskii 的系列允许在 userfaultfd 背板的 HMM 缺页处理中释放 mmap lock,改善并发性能。来源
  • zswap shrinker 使用限速统计 flush:Yunzhao Li 在 zswap_shrinker_count() 中增加了 ratelimited flush,防止高频 shrinker 调用反复冲刷 zswap 池统计,降低延迟。来源
  • x86/mm objtool 与 KMSAN 冲突修复:Peter Zijlstra 继续讨论 folio_zero_user() 的 asm_constraint 问题,提到 ASM_CALL_CONSTRAINT 移动可生成与未修改代码相同的代码,而使用 __builtin_frame_address(0) 约束则生成不同代码;强制 FRAME_POINTER=y 时 clang-22 下出现 objtool 堆栈状态不匹配警告。来源
  • KSM rmap walk 性能优化 (v11):该系列引入 linear_page_index 辅助函数供 ksm_rmap_item 使用,并通过传递合适的页面索引优化 rmap_walk_ksm,同时添加 mremap 自测用例。来源
  • mseal 文档修正 32-bit 描述:Leon Hwang 更正文档中关于 mseal 在 32-bit 内核上行为的描述(回退为不启用)。来源
  • secretmem 禁用 HIGHMEM:Brendan Jackman 发现 secretmem_fault()GFP_HIGHUSER 分配 folio 后调用 set_direct_map_valid_noflush() 前未检查 folio_test_highmem(),在 HIGHMEM 配置下触发 CPA 警告和进程崩溃,因此直接在该配置下禁用 secretmem。来源
  • slab cpu_partial 等 sysfs 属性文档更新:Seongjun Hong 提交补丁,将 cpu_slabsslabs_cpu_partialcpu_partial 三个属性的文档更新为已弃用(deprecated),说明它们始终返回 0 并仅用于向后兼容,同时修复 partialli 拼写错误;该补丁被 Vlastimil Babka 合入 slab/for-next。来源
  • nvdimm nfit 去除冗余 NULL 检查:Mohammad Shahid 移除 vfree() 前提的多余 NULL 判断。来源
  • selftests/mincore 适配大 base page 大小:Yijia Wang 修正 mincore 测试在 large base page sizes 上的 readahead 判断。来源