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.c 中 page_add_anon_rmap() 新增 RMAP_LEVEL_PMD 参数,用于正确记录大页反向映射。include/linux/swapops.h 中定义了 pmd_swp_entry() 和 pmd_swp_to_page() 等内联函数,用于编码/解码 PMD 级 swap entry 的 swp_entry_t 与 pmd_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 相关进展。来源