2026-06-01 内核社区日报

0 阅读8分钟

一句话导读:Christoph Hellwig 发布 block swap I/O batching 系列,将 swap_iocb 机制从远端文件系统扩展到块设备;同时 ANON_VMA_LAZY 系列提案尝试推迟匿名 VMA 的 anon_vma 创建以降低 fork 开销。

🧠 重点 · 内存

1. block swap I/O batching:swap_iocb 扩展到块设备,新增 NRSWP{IN,OUT} 计数器

发生了什么:Christoph Hellwig 发布了 better block swap batching and a different take on swap_ops v2 系列(共 8 个 patch),核心改动有三点。

(1)将 struct swap_iocb 从远端文件系统(如 NFS)的专用机制扩展到块设备:改写 block-based swap 的 I/O 路径,让块 swap 也能一次构建一个 bio、批量提交多个 swap 页,不再逐页发起单次 bio。此前 swap_iocb 仅用于远端文件系统以支持异步批量提交。

(2)合并 writeoutpageoutwriteout 原本只在 pageout 末尾被调用,且是一个连续流程,现在直接内联,减少一层函数调用。

(3)新增 /proc/vmstat 计数器 NRSWPINNRSWPOUT:统计实际发生的 swap I/O 次数(注意不是页数)。由于 batching 后一次 I/O 可以携带多个页,这个计数可以直观反映 batching 效率。

为什么重要:块设备 swap 是 Linux 最主流的 swap 后端(包括 zram 在底层也是块设备)。当前块 swap 每页发起一次单独 bio,在高吞吐换入换出场景下性能受限。该系列将 swap_iocb 的 batching 能力引入块设备,预期能显著减少提交 bio 时的锁竞争与中断开销。新增的计数器也方便管理员评估 batching 效果。

来源

2. ANON_VMA_LAZY:延迟创建 anon_vma,降低 fork/COW 开销

发生了什么:来自 Honor 的开发者提出 ANON_VMA_LAZY 系列(15 个 patch),目标是在匿名 VMA 的 fork 和 COW 路径中推迟 anon_vma 的创建。当前行为:每次 fork 一个匿名 VMA 时,会立即为子进程的 VMA 分配并关联 anon_vma,即使该 VMA 后续可能并不需要(例如子进程立即执行 exec 或映射新页面)。该系列引入一种"惰性"模式:在 dup_mmap() 中只复制 VMA 结构与页表,但暂时不创建 anon_vma,等到实际发生 COW page fault 时再按需创建。

为什么重要:fork() 是进程创建的核心,其耗时直接拉长应用启动延迟。对于大量使用匿名映射的场景(如 Android 的 Zygote fork),延迟 anon_vma 创建可以减少 fork 路径中的内存分配和加锁开销。该系列属于设计提案阶段,但方向明确——已有其他开发者(如 Matthew Wilcox)曾建议将 anon_vmarb_tree 替换为 maple tree,该系列也引用了这一讨论。

来源

3. list_lru reparent 并发修复:drain 再清 xarray,避免 slab 泄露

发生了什么:Shakeel Butt 提交了一个单 patch 修复 mm/list_lru.c 中的并发 bug。在 memcg_reparent_list_lrus() 中,代码先通过 xas_store(&xas, NULL) 清空了 dying memcg 的 xarray 条目,然后才进行 per-node list 的 reparent 操作。这导致在清空 xarray 到真正 reparent 之间的窗口内,并发调用 list_lru_del() 可能会找不到该 memcg 的条目(因为 xarray 已空),从而将对象留在 list_lru 中,最终泄漏。修复方式:先 drain 所有 per-node list(即 reparent 完成),再清 xarray 条目。

为什么重要list_lru 是 slab shrinker 和 memcg reclaim 的核心数据结构,泄漏会导致 slab 内存不可回收,直接影响 memcg 删除后的内存释放。该 bug 可能影响主动删除 memcg 的场景(如容器销毁),属于中等严重级别的并发错误。

来源

4. shmem read 优化:减少 xarray 查找次数 + folio batching

发生了什么:Chi Zhiling 继续打磨 shmem 读路径优化系列(v2)。该系列包含两个改动。

(1)在 shmem_get_folio_gfp() 内部使用 filemap_get_folios() 之类的批量查找接口,一次 xarray 遍历返回多个 contiguous folio,减少 walk 次数。

(2)为读路径中填充零页的场景引入 copy_zero_to_iter() 专用函数:当读到的页是零页时,直接使用 memset 填充用户缓冲区,避免先拿 folio 再判别是否为 zero-filled 的冗余路径。

性能数据:使用 fio 进行 seq_read 测试(sync ioengine, 1G 文件, 180s 运行),修改后的吞吐量相比基线有显著提升,具体提升幅度因 block size 不同而异(素材未给出精确百分比,但作者宣称有提升)。

为什么重要:shmem(tmpfs)是内核最常用的内存文件系统之一,高频读写场景(如编译、日志、容器 overlay)直接受益。批量查找与零页特化路径减少了 xarray 加锁开销和函数调用次数,属于易收益的优化。

来源

5. swap tier infrastructure v7:per-memcg 的 tier mask 限制,Nhat Pham 进一步评审

发生了什么:Youngjun Park 的 swap tier 系列 v7 进入第二轮评审。Nhat Pham 在 review 中提出两个技术问题:per-device 的 per-CPU cache 对多 swap 设备场景的开销评估,以及 swap allocation 时按 memcg 的 tier mask 过滤的实现细节。该系列核心思想是将多个 swap 设备按性能分成 tier(层级),reclaim 时优先从低 tier 换出,写回时优先写到高 tier。

为什么重要:多 swap 设备在服务器和嵌入式场景中均有应用(如 NVMe + SATA SSD + HDD),tier 化管理可以让 hot 页留在快速设备,cold 页下沉到慢速设备,提升整体交换效率。当前仍是 RFC 阶段,但 v7 表明设计正在收敛。

来源

🔧 其它子系统

  • 文件系统(VFS): Andy Lutomirski 提出 vmsplice 退化为 preadv2/pwritev2 包装的提议,讨论仍在进行,焦点是 uAPI 兼容性。 来源
  • 文件系统(f2fs): 讨论如何在大 folio 写入中记住 inode 编号以优化 large folio 设置,Christoph Hellwig 提出不同看法。 来源
  • Rust: 修复 block: rust: fix generation of bindings to BLK_STS_.*,属于 Rust for Linux 基础设施的持续完善。 来源
  • arm64: Ard Biesheuvel 的线性映射解耦系列(v7)继续评审,今天讨论 unmap kernel data/bss entirely from the linear map 对直接映射攻击的缓解效果。 来源

👀 值得追的讨论 / Patch

  • khugepaged mTHP collapse v18 系列: David Hildenbrand 在 review collapse_huge_page 推广到 mTHP 的 patch 时,指出 mmap_lock 持有下的 map_anon_folio 调用可能导致死锁,作者 Lance Yang 正在与 David 讨论安全替换方案。该系列的设计方向尚未最终确认。 来源
  • Virtual Swap Space(Swap Table Edition): Kairui Song 基于 swap-table phase IV 提供了一个更完整的虚拟 swap 实现(ghost device),旨在创建一个不绑定物理后备存储的 swap 设备,用于内存压缩、page offline 等场景。Nhat Pham 对其与 zswap/zram 的关系提出疑问。 来源
  • copy_process() 返回无效错误指针: Alexei Starovoitov 指出 copy_process() 存在返回非 ERR_PTR 的路径(retval 可能为正或零),但该问题已有内部修复,声称当前 patch 方案不完整。 来源

⚡ 一句话速览

  • zswap: shrink_worker 的 writeback cursor 改为 per-memcg,避免反复扫描已无 zpages 的 memcg,v3 获 Yosry Ahmed Ack,后续待评审。 来源
  • slub: 为 oversized sheaves 使用 empty sheaf helper 的 v5 补丁已由 Vlastimil Babka 应用。 来源
  • slub: node partial slab 状态管理引入 helper,并在 get_partial 路径中批量 detach/reattach,减少锁竞争,v3 已合并。 来源
  • slub: 为 sheaf struct 分配指定 local memory node,避免跨 NUMA 节点分配,v2 获 review。 来源
  • mm/percpu: 修复 chunk create/populate 路径中未保存 NOFS/NOIO 标志,v1 已在讨论。 来源
  • DAMON selftests: 修复多个测试用例 bug(跨上下文状态污染、memcg filter 路径、空 tried regions 处理),v3 已提交。 来源
  • mm/filemap: 使用 folio_next_index() 替代 folio->index + folio_nr_pages(folio) 计算索引,简化代码。 来源
  • HWPoison: 引入 zone->lock 序列化 TestSetPageHWPoison,防止与非原子操作并发竞争,v9 已合入 mm-unstable。 来源
  • selftests/mm: pkey 测试重构:提取公共 helper,统一断言钩子,修复 klone_raw 失败后 hung 住的问题。 来源
  • memory hotplug: 引入 zone->pages_with_online_memmap 成员,避免在 zone contiguous 检查时逐 pageblock 扫描,v5 正被 review。 来源
  • msm_iommu: msm_iommu_pagetable_prealloc_allocate 调用 kmem_cache_alloc_bulk 异常回溯,Christoph 标记为 kmem_cache_alloc_bulk 的潜在缺陷。 来源
  • schmem zeroing: copy_zero_to_iter() 用于大块零填充,已获 Matthew Wilcox review 并建议进一步优化。 来源
  • arm64 FEAT_D128: 为 TLB 范围操作引入抽象层,添加 tlbi_op 以支持新指令 TLBIP来源
  • rcu: 进程地址空间检查简化(mm_access)。 来源
  • riscv: 调用 mark_new_valid_map() 刷新 vmemmap hotplug 后的 TLB,v6 已合入 kvm-riscv。 来源
  • hugetlb: 移除 !CONFIG_HUGETLB_PAGE 下的 alloc_hugetlb_folio stub,已是死代码。 来源
  • deferred split shrinker: 切换到 list_lru 管理,简化实现,v5 获 Johannes Weiner 审阅。 来源
  • bvec_folio: 新增 helper 避免直接访问 bv_page,已合入 mm-stable。 来源
  • 消歧注释: 删除了关于 cachelines 的过时注释(自 NR_FREE_PAGES_BLOCKS 加入后已失效)。 来源

💡 本文由 Linux 内核社区日报自动聚合整理,每日发布。
更多内容,欢迎关注微信公众号:探索 Linux 内核
博客原文(含可点击链接):ohlinux.com/kernel-dail…

公众号二维码