2026-07-10 内核社区日报

今日核心:swap 块设备 I/O 迎来高效 batching(v4),预计可大幅降低随机读写延迟;ptdump 与 vmap 之间的 UAF 竞争终于彻底修复,arm64 受益最大。

🧠 重点 · 内存

1. swap 块设备 I/O 支持 bio batching,swap_ops 架构再重构

发生了什么: Christoph Hellwig 提交该系列,将此前仅为远端文件系统(如 NFS)设计的 struct swap_iocb 推广到块设备 swap,使其不再执行低效的单页单 bio I/O。同时,将 Baoquan 的 swap_ops 重构重新基址于该新的方法结构。测试显示在内核构建场景下,写回聚类达到 2 倍,读回聚类 1.2 倍,但总体运行时间未见变化。

为什么重要: 该系列使块设备 swap 能批量提交 bio,写回和读回的聚类因子得到提升,改善了 I/O 模式,并重构了 swap_ops 架构。

来源

2. 修复 ptdump 与 vmap huge page 之间的 UAF 竞争

发生了什么: Lorenzo Stoakes 提交两补丁系列,修复内核页表遍历(ptdump)与 vmap 在建立 huge 映射时发生的 use-after-free(UAF)竞争。vmap 在将页表提升为 huge leaf 条目时,会释放下级叶子页表,但该操作不持有任何有效锁;而 ptdump 可能同时并行遍历同一页表,导致读取到已释放的页表项。解决方法是:在 vmap huge promotion 逻辑中,于设置大页表项并释放之前页表时获取 init_mm 的读锁(mmap_read_lock),与 ptdump 路径已经持有的 mmap_write_lock 形成互斥。第二个补丁回退 arm64 之前为缓解此问题而应用的 commit a93b45fd397(“arm64: Enable vmalloc-huge with ptdump”),该修改通过加锁缓解问题,但若直接与本系列组合会导致死锁,因此需要部分回退并保留 huge vmap 的启用。

为什么重要: 该系列从根源上锁住竞争,消除因 vmap 释放页表而 ptdump 仍在访问导致的 use-after-free 错误,使代码更健壮。arm64 之前的缓解措施需要配合此系列重新调整,最终得以安全保留 huge vmap 支持。

来源

3. DAMON 引入 probe weight 及 attrs-only monitoring 支持

发生了什么: SJ Park 发送了 [RFC,v1.3,00/19] mm/damon: introduce data attributes only monitoring 补丁系列。该系列引入 damon_probe->weight 字段,新增 apply_probes() ops 回调的采样地址请求参数,并后续实现基于 probe hits 的合并阈值、禁用访问监控等改动。

为什么重要: 该系列使 DAMON 支持基于权重的采样与 attrs-only 监控模式,扩展了监控机制的配置灵活性。

来源

4. kmemleak:通过第二次扫描确认泄漏,减少误报

发生了什么: Catalin Marinas 提交 mm: kmemleak: confirm suspected leaks with a second scan,为 kmemleak 增加一项确认机制。当前 kmemleak 在标记阶段并非原子,内核可能在此期间修改指针、分配或释放内存,导致误报。新 patch 在首次标记后延迟再执行一次扫描,将两次扫描结果对比:如果第一次视为“疑似泄漏”的对象在第二次扫描时已被重新引用(即已经有新的 reference),则将其从泄漏报告中去掉。这大幅减少因 ASLR、大规模分配释放等造成的假阳性。

为什么重要: kmemleak 误报一直是调试内存泄漏时的困扰,尤其在高负载 kernel 使用 ASLR 的 Android 设备上。此改进使得 kmemleak 可直接生产环境使用,无需工程师反复手工验证每个疑似对象。

来源

5. slab:修复 kmalloc 别名导致的内存泄漏及 memalloc profiling 引发的递归

发生了什么: Harry Yoo 提交 [slab/for-next-fixes,v2,0/3] mm/slab: fix unbounded recursion in free path with memalloc profiling,包含三个修复补丁:

  • (1) 修复了一个内存泄漏:当 kmalloc caches 别名(多个 cache 指向同一 kmem_cache 结构)时,引导阶段 bootstrapping sheaves 可能对同一个 cache 执行两次,导致 sheave 内存泄漏。
  • (2)SLAB_NO_SHEAVESSLAB_NO_OBJ_EXT 解耦:引导 cache 原本同时禁止 sheaves 和 obj_exts,现在允许在禁用 obj_exts 的同时启用 sheaves。
  • (3) 修复 memalloc profiling 开启时的递归:当 kmalloc 分配 obj_exts 数组时,若该数组所在 slab 本身就是被追踪的 kmalloc 类型,则分配 “obj_exts” 又会触发新的 kmalloc,造成无限递归。V2 通过追踪一个新的 kmalloc 类型并确保其分配不触发 profiling 来解决。

为什么重要: slub 是默认 slab 分配器,此处涉及的内存泄漏 + 递归崩溃在生产环境中可导致不可修复的旧式 panic。修复也保持了对 memalloc profiling 的支持。

来源


6. swap_ops 架构重构 v4

发生了什么: Christoph Hellwig 提交了 swap_ops 架构重构的 v4 补丁集,该系列将 swap_iocb 用于块设备 swap 以替代单 bio I/O,并在新的方法结构基础上重新对齐了 Baoquan 的 swap_ops。在内核构建测试中,写回聚类达到 2x,读回聚类达到 1.2x,但总编译时间没有实际变化。

为什么重要: 该系列提升了 swap I/O 的聚类效率,但并未改善整体内核编译耗时。

来源

7. DAMON 引入 data attributes only monitoring 模式

发生了什么: SJ Park 提交的系列引入了让 DAMON 以最佳努力精度监控用户指定的非访问数据属性的方法。Sashiko 审查后未发现阻塞性问题,相关反馈已发送至 damon@ 邮件列表并由 SJ 逐一回复。

为什么重要: 该系列提供了一种机制,使 DAMON 能够将监控重点放在用户关注的非访问数据属性上,从而满足此类属性的监控需求。

来源

8. 跳过禁用任务的 ops.set_weight() 调用

发生了什么: Kuba Piecuch 提交补丁,在 sched_ext 的 reweight_task_scx() 中增加检查,当任务状态不是 SCX_TASK_ENABLED 时跳过 ops.set_weight() 调用。当前流程中,ops.disable() 后仍会调用 ops.set_weight(),违反回调语义(ops.disable() 后只能跟 ops.exit_task()ops.enable())。

为什么重要: 修复了 ops.disable() 后仍可能调用 ops.set_weight() 的时序问题,确保禁用任务不会在错误阶段被调整权重,且后续如果任务重新加入 SCX,权重会在 scx_enable_task() 中重新计算。

来源

9. kmemleak 二次扫描确认泄漏

发生了什么: Catalin Marinas 提交的补丁为 kmemleak 增加第二次扫描确认机制。由于标记阶段非原子性,对象图遍历期间内核可能移动指针或释放对象,导致首次扫描误报。补丁在首次扫描发现疑似泄漏后,执行第二次扫描确认,若未发现新泄漏则跳过确认扫描。

为什么重要: 消除因指针移动等瞬态操作导致的误报,减少对 kmemleak_transient_leak() 等显式注释的依赖,提升泄漏检测准确性。

来源

10. memory-failure 移除 raw_hwp_list_head() 辅助函数

发生了什么: Matthew Wilcox 提交了补丁 v2 05/10 以移除 raw_hwp_list_head() 辅助函数,将 struct folio 中的 _hugetlb_hwpoison 字段从 void* 直接改为 struct llist_head,并更新所有调用点直接访问 folio->hugetlb_hwpoison。补丁未引入功能变化(No functional change intended)。Usama Arif 给出了 Acked-by。

为什么重要: 该改动消除了不必要的类型转换和封装层,使内核代码更清晰易读,降低了后续维护成本。

来源

11. zswap batching 补丁测试数据讨论

发生了什么: Hao Jia 提交了 zswap 批量 writeback 补丁的测试数据。在 cgroup 内存约束 1GB、stress-ng 内存压力下,对比基线内核,补丁后的 shrink_worker 唤醒次数从约 5587 次降至 878 次,shrink_memcg 调用从约 780 万次降至 230 万次,实际 writeback 页面从约 257 页增至 78 万页。Yosry Ahmed 指出 writeback 数量增幅远高于预期(基于 batch 大小 64 估算应为约 20 倍),并询问是否表明基线内核在高压下无法有效 writeback,进而可能导致 LRU 反转等问题。Hao Jia 解释测试环境存在持续 zswapin/zswapout 循环,基线扫描速度过慢导致大部分条目仅被扫描一次(99.21% 为 LRU_ROTATE),而补丁的单次扫描可覆盖更多条目,因此 writeback 效率显著提升。双方还讨论了测试方法的合理性和需要观察的指标。

为什么重要: 该讨论通过实测数据揭示了 zswap shrinker 在高压场景下的瓶颈,batching 机制能显著提高 writeback 效率,但也需要确认其是否会导致过度 writeback。这有助于优化 zswap 的内存压力响应,减少内核回收开销,提升系统在内存受限环境下的稳定性。

来源

🔧 其它子系统

虚拟化 / 驱动

  • virtio_balloon:修复 PM freeze 期间的 Use-After-Free:Link Lin 提交修复,在系统挂起/休眠时 virtballoon_freeze() 调用 remove_common() 释放 page reporting 相关数据结构,但后续 disable 路径仍可能引用已释放内存,导致 UAF。补丁在 freeze 路径中增加同步或提前释放检查。来源

文件系统

  • binfmt_misc:写访问修复与 RCU handler 查找:Christian Brauner 提交系列,包含写访问修复(恢复删除条目时的写权限、为解释器克隆使用 exe_file_deny_write_access())、将条目链表转为 hlist、使用 RCU 进行 handler 查找、对 ->enabled 进行数据竞争标注等清理。RCU handler 查找使 exec 路径的条目遍历不再需要持锁,可减少锁竞争。来源

调试 / 跟踪

  • 追踪 refcount 最终 put 的 tracepoint:Eugene Mavick 提交 v2 系列,为 refcount、percpu-refcount 及各种 ref 类型添加 ref_trace_final_put tracepoint。当 refcount 降到 0 时触发,帮助定位对象生命周期泄漏。来源

👀 值得追的讨论 / Patch

1. device-private PMD 在 walk 回调中的全面处理

Usama Arif 提交 v3 系列 mm: handle device-private PMDs in walk callbacks。自 commit 368076f52ebe 起,PMD 可能持有 device-private swap 条目(在 HMM GPU 驱动通过 migrate_vma_pages() 将匿名 THP 迁移至设备内存后)。pmd_trans_huge_lock() 对此类 PMD 成功,导致若干 MM walk 回调(原本假定为 present THP 或迁移条目)现在可访问 device-private PMD,结果包括 VM_BUG_ON、oops 或错误隔离 LRU folio。v3 系列在 mm/mempolicymm/madvisemm/huge_memory 中增加跳过逻辑,处理非 present PMD 或专门检测 device-private PMD。来源

2. zswap shrinker 启用/禁用对 swap 性能的影响对比

Yunzhao Li 报告了在 Cloudflare 生产环境中启用 zswap shrinker 后的 swap 性能数据:启用后同步交换开销从 22.5 ms 降至 10.3 ms,交换率从约 1.7K/s 降至约 800/s。他认为这是因为 shrinker 额外释放了 16 GiB 空闲内存,降低了整体内存压力,从而减少了需要换入的页面数量。提问者进一步建议尝试消除 flushes 作为替代方案。来源

⚡ 一句话速览

  • mm/page_owner:修复 TOCTOU 导致的 VM_BUG_ON:Ye Liu 在 print_page_owner_memcg() 中改用 READ_ONCE 捕捉 memcg_data 快照,在检查与使用间防止并发修改触发断言。来源
  • mm/vmscan: 当全局直接回收有进展时清除 hopeless kswapd 状态:此前直接回收仅在节点达到平衡后清除 hopeless kswapd 状态,这导致全局直接回收在持续内存压力下即使有进展也无法唤醒 kswapd。该补丁修改条件:全局直接回收(non-memcg)在回收有进展时即可清除该状态,而 memcg 回收仍要求节点平衡,从而让 kswapd 能恢复异步回收工作。来源
  • zswap:在压缩解压路径中 flush dcache:Song Hu 提交 mm/zswap: flush dcache in the compressed decompression path,在软解压后清除 dcache,防止后续 CPU 读脏数据。arm64 等架构之前依赖 crc check 或其他手段,但此 fix 更为正统。来源
  • mm/percpu-km:修复 pcpu_create_chunk() 中 bitmap 溢出与计数问题pcpu_create_chunk() 之前使用总连续分配页数 nr_pages 调用 pcpu_chunk_populated(),但 chunk->populated bitmap 大小仅为 pcpu_unit_pages,当 nr_units > 1 时写入越界。现改用 chunk->nr_pages,同时修复了 pcpu_nr_empty_pop_pages 会计错误(pcpu_balance_free() 只遍历至 chunk->nr_pages)。来源
  • hugetlb subpool 泄漏修复收到感谢与技术讨论:Ackerley Tng 的系列修复了 alloc_hugetlb_folio 在早期分配失败后错误返回 subpool 页用量的问题。Joshua Hahn 回复该系列,表达了感谢,并就修复中关于 minimum subpage 的处理提出了讨论与疑问,同时引用了此前两次类似的修复尝试。来源
  • shmem:修复 direct swapin 可能导致的活锁:Baolin Wang 提交 backport 补丁到 6.18.y,在使用 swap 的 shmem 路径中避免重复获取 lock 导致无进展。来源
  • DAMON sysfs ABI 文档修复与补充:Song Hu 提交 4 补片系列,修正 typo、遗漏的 update_tuned_intervals 等 sysfs 条目。来源
  • mm/rmap:重构 try_to_unmap_one:Dev Jain 提交 v2 系列,将 try_to_unmap_one 中的 hwpoison 检查移植到 folio 化版本,并抽离 hugetlb 专用函数。来源