2026-07-04 内核社区日报

匿名 THP 的 PMD 级 swap entry 系列推出 v3,告别 THP 换出时拆分为 512 个 PTE 的开销;kmemleak 修复 per-CPU 对象校验和计算错误,消除漏报假阳性。

🧠 重点 · 内存

1. 匿名 THP PMD 级 swap entry:v3 完整铺开

发生了什么: Usama Arif 发出 [PATCH v3 0/11] mm: PMD-level swap entries for anonymous THPs,引入 PMD 粒度的 swap entry 以在 swap 往返中保持匿名 THP 的 PMD 映射。核心改动包括:

(1)增加 PMD swap entry 检测与在 __split_huge_pmd_locked() 中将其拆分为 HPAGE_PMD_NR 个 PTE swap entry 的支持(通用回退路径)。

(2)fork 路径 copy_huge_pmd() 学会镜像 PMD swap entry,通过一次 swap_dup_entries_direct(HPAGE_PMD_NR) 完成批量复制。

(3)zswap 端由 Alexandre Ghiti 贡献范围查找:新增 zswap_range_has_entry(),使 PMD 级 swap-in 可在遇到 per-page zswap 状态时拆分。

(4)swapoff 路径 swap_pmd_cache_lookup() 分类处理 PMD swap entry 背后的 swap cache:空、PMD 大小 folio、或需逐 slot 处理的拆分状态。

(5)所有非 present PMD walker(zap、mprotect、smaps、mincore、khugepaged、madvise、UFFDIO_MOVE 等)增加对 PMD swap entry 的感知。

(6)缺页处理新增 do_huge_pmd_swap_page(),在 swap cache 空且无 zswap entry 时分配并读回 PMD 大小 folio,否则拆分回退到 PTE 路径。

(7)swap-out 侧取消对 PMD 映射 THP 强制 TTU_SPLIT_HUGE_PMD,改为直接安装一个 PMD swap entry。

为什么重要: 该系列使匿名 THP 在 swap 往返中保持 PMD 映射,swap-in 时可直接恢复 PMD 映射,无需等待 khugepaged 后续折叠,减少了因 split 和重建带来的开销。

来源

2. kmemleak:修复 per-CPU 对象校验和计算错误

发生了什么: Breno Leitao 提交 mm/kmemleak: fix checksum computation for per-cpu objects(v1)。原有实现中,对每个 CPU 的 CRC 计算使用了不同种子,导致同一对象在不同 CPU 上的 CRC 不同——per-CPU 对象的校验和是通过 XOR 折叠各个 CPU 的 CRC 来计算的,若种子不同,折叠结果会随 CPU 顺序波动,产生假阳性 leak 报告。

该 patch 统一使用同一种子计算每个 CPU 的 CRC,使折叠后的 checksum 稳定一致。Pavel Tikhomirov 给出 Reviewed-by。

为什么重要: kmemleak 的 per-CPU 跟踪启用后(commit 6c99d4eb7c5e),校验和错误将导致大量误报 leak,严重干扰内核开发者排查真正的内存泄漏。此修复使 per-CPU 指针的 leak 检测变得可靠。

来源

3. slub:批量远程 free 时丢失本地对象

发生了什么: 补丁 mm/slub: fix lost local objects when bulk remote free batch fills(v1)修复了 free_to_pcs_bulk() 中的内存泄漏:当远程对象数组填满至 PCS_BATCH_MAX 时代码跳转到 flush_remote,但因 i < size 条件不成立而提前返回,导致本地对象被丢弃。修复方案是用就地释放远程满批次替代跳转,确保所有本地对象走正常快速路径。

为什么重要: 消除了因本地对象未被缓存或归还 slab 空闲链表导致的内存泄漏,保障了 slab 分配器的数据完整性。来源

4. kasan: common: 重复代码清理与宏替换

发生了什么: Igor Putko 提交 [PATCH 0/3] kasan: common: cleanups and deduplication(v1),包括:

  • 将多个分配函数中相同的 quarantine 缩减逻辑提取为 kasan_quarantine_reduce_cond() 辅助函数;
  • 使用 ALIGN_DOWN 替换手动位运算对齐栈地址;
  • KASAN_TAG_KERNEL 替换魔法数 0xff

为什么重要: 减少维护负担,提高代码可读性,无功能变化但降低未来引入 bug 的可能性。

来源

5. 匿名 THP PMD 级 swap entry:v3 完整铺开

发生了什么: 第三版补丁集完整实现了匿名透明大页(THP)的 PMD 级 swap entry 支持。核心改动包括:在 mm/swap_state.c 中新增 swap_anon_thp_alloc() 用于分配并初始化 PMD 级 swap 缓存,并在 swap_readpage()swap_writepage() 中增加对 PMD 级 entry 的分发路径。同时,mm/memory.c 中的 do_swap_page() 被扩展以识别 PMD_SWAP_ENTRY 标志,并在缺页时直接建立 PMD 映射,避免拆分为 PTE 后再合并。mm/rmap.cpage_add_anon_rmap() 新增 RMAP_LEVEL_PMD 参数,用于正确记录大页反向映射。include/linux/swapops.h 中定义了 pmd_swp_entry()pmd_swp_to_page() 等内联函数,用于编码/解码 PMD 级 swap entry 的 swp_entry_tpmd_t 之间的转换。

为什么重要: 该改动消除了匿名 THP 在 swap 换入换出时被迫拆分为 512 个普通页的性能损失,使大页的连续物理内存优势在 swap 场景下得以保留。对于内存压力下频繁 swap 的服务器或桌面负载,可显著降低缺页处理开销和 TLB 抖动。v3 版本已完整覆盖分配、换入、换出、反向映射四个关键路径,标志着该特性从原型进入可合入状态。

来源

🔧 其它子系统

sched_ext

  • scx_bpf_kick_cpu() 存在 NMI 上下文并发导致 list corruption 问题,计划添加 in_nmi() 保护scx_kick_cpu()kick_cpus_irq_workfn() 因 NMI 上下文并发出现 list corruption,scx_bpf_kick_cpu() 不应在 NMI 上下文中调用,v2 将增加 in_nmi() 守卫,在此情况下触发 scx_error() 而非操作链表。来源

文件系统

  • VFS 维护者 Christian Brauner 宣布夏季假期:7-8 月核心开发者休假,预计回复速度减慢。来源
  • fanotify 权限事件 watchdog 状态初始化:Xuanqiang Luo 修复 fanotify_alloc_perm_event() 遗漏的 watchdog 字段初始化,防止未初始化数据被访问。来源
  • ext4 inline data 写状态 race 修复(v4):Aditya Srivastava 用 fsdata 追踪 inline data 写入状态,避免 ext4_da_write_end()ext4_journalled_write_end() 之间的 race。来源

eBPF

  • radix-tree kmemleak transient false positive 修复(v2):Breno Leitao 在 bpf 列表发送 v2,修复 radix tree 在 grow/shrink 时因 kmemleak 扫描时机导致的 transient false positive。在 radix_tree_extend()radix_tree_shrink() 中为新 head 节点添加 kmemleak_transient_leak() 调用,避免被误报为泄漏(与 XArray 的修复 a1a029bcea59 类似)。同时为用户空间测试添加 kmemleak_transient_leak() 桩函数。来源
  • memcg BPF-vs-memory.stat 读性能 benchmark(v1):Ziyang Men 为 BPF 和 cgroup memory.stat 两种读取路径添加对比测例,包括无并发、单线程 churn、跨 CPU churn 三种场景,用于量化 rstat flush 开销。来源

x86/cpu

👀 值得追的讨论 / Patch

sched_ext 子调度器:scx_kick_cpu() NMI 并发问题需修复

Tejun Heo 指出了 scx_kick_cpu()kick_cpus_irq_workfn() 因 NMI 上下文并发可能导致 list corruption 的问题。scx_bpf_kick_cpu() 不应从 NMI 上下文调用,但计划在 v2 中添加 in_nmi() guard 来触发 scx_error() 而非操作链表。该修复将提升 sched_ext 子调度器在 NMI 上下文的安全性。来源

secretmem:HIGHMEM 下 set_direct_map 不可用,能否修复?

Brendan Jackman 指出 secretmem_fault() 分配 GFP_HIGHUSER 的 folio 后调用 set_direct_map_valid_noflush(),但该函数不支持 highmem page。讨论集中在是否应直接禁用 HIGHMEM 下的 secretmem,或有其他方法绕过。各方尚未达成一致。来源

⚡ 一句话速览

  • DAMON v7.2-rc1 Release Newsletter:SJ Park 发布更新,汇总了自动调优监控间隔、node_eligible_mem_bp 目标指标、失败区域配额比率等新特性。来源
  • CMA 区域动态创建:Thierry Reding 提交补丁,将 CMA 区域管理代码提取为 helper 并新增 cma_create() / cma_free() 函数,使运行时可以动态创建和释放 CMA 区域,不再受固定数量的静态数组限制。该改动保留早期区域(初始化时必需)的静态列表,另设动态列表管理后期区域。David 表示将安排审查。来源
  • mmap_write_lock_killable 文档讨论:Leon Hwang 提议文档化 mmap_write_lock_killable() 的 -EINTR 返回,回复者指出其对“killable”概念有误解,并解释 killable 与 interruptible 的区别。来源
  • scsi 驱动改用 kmalloc 代替 __get_free_pages:Mike Rapoport 提交 v2,将 target、proc、IPR、sym53c8xx_2 中的 page allocator 直接调用替换为 kmalloc。来源
  • 工作队列读取 se.sum_exec_runtime 改用 READ_ONCE():在 wq_worker_running()wq_worker_tick()process_one_work() 中,将读取工作线程 se.sum_exec_runtime 的普通赋值改为 READ_ONCE(),以避免 KCSAN 检测到的数据竞争;由于该值仅用于 CPU 密集型启发式判断,竞争是良性的,但需保证单次非撕裂的读取。来源
  • selftests/bpf 修复 msg_alloc_iov 内存泄漏:error 路径在释放 iov_base 后遗漏释放 iov 数组本身。来源
  • Hypervisor Live Update 会议纪要:Pasha Tatashin 分享 6/15 和 6/29 会议笔记,涉及 KHO 相关进展。来源