2026-06-15 内核社区日报

今天的关键词是 slab 分配器数据结构重构:Vlastimil Babka 发布 v3,将 slab 内部 alloc_flags 机制、slab_alloc_context 统一及 __GFP_NO_OBJ_EXT 的替代方案推进到可合入状态,并已入 slab/for-next。同时 zram 试图绕过通用 swap 路径,直接注册自有的 swap I/O ops,可能为压缩后端带来性能与灵活性的提升。


🧠 重点 · 内存

1. slab 分配器:alloc_flagsslab_alloc_context 全面落定 v3,进入 for-next

发生了什么:
Vlastimil Babka 发布 [PATCH v3 0/15] mm/slab: introduce alloc_flags and slab_alloc_context。v3 基于 slab-for-7.2 标签,已合入 slab/for-next。核心改动:
(1)引入 slab 层面的 alloc_flags,定义 SLAB_ALLOC_DEFAULTSLAB_ALLOC_NOLOCK(v3 中由 SLAB_ALLOC_TRYLOCK 重命名而来)、SLAB_ALLOC_NEW_SLABSLAB_ALLOC_NO_RECURSE 等内部标志。
(2)引入 struct slab_alloc_context 作为参数聚合体,替代 get_from_partial_node()___slab_alloc()slab_post_alloc_hook() 等函数中大量分散传递的参数。
(3)移除 __GFP_NO_OBJ_EXT 的使用——该标志占用了一个 GFP bit 且用于 slab 内部递归保护。替换为 SLAB_ALLOC_NO_RECURSE,完全用 slab 内部 alloc_flags 控制。
(4)新增 kmalloc_flags() 包装,允许调用方传 alloc_flags,用于 alloc_slab_obj_exts() 和 sheaves 分配路径,彻底清除 __GFP_NO_OBJ_EXT 的外部痕迹。

为什么重要:
该系列将 slab 分配器的内部控制标志从全局 GFP flags 迁移到私有的 alloc_flags,避免了 GFP 空间中 bit 的占用以及因标志误解释(如 __GFP_RECLAIM 的缺失被错误理解为不能自旋)导致的分配失败。同时引入 slab_alloc_context 集中传递参数,减少了内部函数的参数数量,使代码结构更清晰。

来源

2. zram 绕过通用 swap 路径,直接注册自有 swap I/O 回调

发生了什么:
Jianyue Wu 提交 [PATCH v1] mm/zram: route block swap I/O through swap_ops(3 个 patch)。核心设计:

  • mm/page_io.c 中新增接口:允许 block driver 调用 register_block_swap_io_ops() 注册一组自定义的 swap_io_ops(包含 submit_biosubmit_read 等回调),取代默认的 __swap_writepage() / swap_readpage() 路径。
  • zram 作为首个用户,调用该接口注册自己的读写回调(zram_swap_submit_write / zram_swap_submit_read),直接操作 zram 压缩块,不再经过通用 submit_bio I/O 栈(如 zram_submit_bio 中区分 read/write/discard 的拆分)。
  • patch 2 移除了 zram 中对 REQ_OP_DISCARD 路径的单独处理(因为 zram 为块设备时 discard 由 block layer 层处理;swap 场景下不需要)。patch 3 将 swap_readpage() 中的页面锁定逻辑剥离到通用层,使自定义读回调无需重复实现 same_page 锁定。

为什么重要:
zram 目前作为块设备注册时,swap I/O 依然经过 zram_submit_bio() 这个通用块层入口,内部通过判断 bio_op 来派发读写。如果能直接注册 swap_ops,zram 可以跳过 bio 层的构造与解析开销,也避免了 bio 拆分、多 page 请求等通用机制带来的复杂度。对纯 zram 作为 swap 后端的 Android 等场景,可能降低每笔 swap I/O 延迟。但该系列处于 v1 阶段,reviewer 反馈了“自定义 ops 只支持单注册”的限制,当前 register_block_swap_io_ops() 只预留了一个全局结构体,不支持多后端同时注册,后续需要扩展为多实例。

来源


3. khugepaged collapse_file 泛化为支持任意 order,为 shmem mTHP 折叠做准备

发生了什么:
Baolin Wang 的 RFC v2 patch 将 collapse_file() 函数的 order 参数化,使其不再硬编码为 HPAGE_PMD_ORDER,而是通过调用方传入 order。该改动替换了函数内多处硬编码的 HPAGE_PMD_NR 和 HPAGE_PMD_ORDER,并调整了参数注释。Nico Pache 询问对 shmem 路径中 NR_SHMEM_THPS 的统计是否遗漏了按页计数的问题,Baolin 解释该统计自 commit 57b2847d3c1d 后以 pages 为单位,HPAGE_PMD_NR 增量正确。

为什么重要:
这是将 khugepaged 的 collapse_file 从仅支持 PMD-order 扩展到支持任意 order 的基础工作,为后续 shmem mTHP collapse 功能提供了通用框架。该系列仍处于 RFC 阶段,方向获得维护者关注。

来源

4. memory-failure: 在 dissolve 成功后跳过 take_page_off_buddy

发生了什么:
Jiaqi Yan 提交了补丁,为 memory_failure 中处理的 HugeTLB 页面引入 __hugepage_handle_poison() 函数。该补丁的核心逻辑是:由于 HWPoison 子页面在 dissolve_free_hugetlb_folio() 成功后会直接被 buddy 分配器拒绝,因此不再需要调用 drain_all_pages()take_page_off_buddy()(后者在 dissolve 后返回 false,导致调用者误以为 __page_handle_poison() 失败)。Miaohe Lin 询问了 hugetlb_raw_hwp_unreliable folios 的处理方式,Jiaqi Yan 回应这些 folios 应被“泄漏”处理——既不释放给 buddy,也不由 dequeue_hugetlb_folio_node_exact() 分配。

为什么重要:
该补丁消除了 dissolve 后错误调用 take_page_off_buddy 的风险,使 HugeTLB 页面的软隔离流程更清晰、健壮,避免因返回 false 导致的误判。

来源

5. vmsplice 改为预读/写系统调用的简单包装器,讨论进入细节

发生了什么:
Al Viro 发布的 [PATCH 0/3] vmsplice: make vmsplice a trivial wrapper for preadv2/pwritev2 进入深度技术讨论。vmsplice 目前实现中直接操作 pipe buffer,绕过 VFS read/write 路径,在兼容性和安全边界上有多处问题(如 pipe buffer 的 page->mapping 检查、跨用户态访问的边界)。Al Viro 的方案是:将 vmsplice 内部转换为直接调用 preadv2 / pwritev2,复用现有的 VFS I/O 路径,不再自行处理 pipe buffer 的 pinning。讨论主要围绕 import_iovecpipe_read 的系统调优差异。

为什么重要:
vmsplice 是 splice 系列中最复杂的系统调用之一,历史上多次因 pipe buffer 的引用计数错误导致 UAF。重写为 wrapper 后,所有 pipe 相关的 pinning 和安全检查都归到核心 pipe 代码,大幅减少暴露面。虽然这是大改动,但方向得到 Linus Torvalds 和 Al Viro 双方认可,讨论进入具体实现细节。

来源


🔧 其它子系统

eBPF

  • skmsg 系列收集此前多个修复并以 v4 发出[PATCH bpf-next v4 0/6] bpf, skmsg: some fixes for skmsg 由 Jiayuan Chen 汇总此前 Weiming Shi、Zhang Cen、Kuniyuki Iwashima、Sechang Lim 等人发送的补丁,涵盖 bpf_msg_push_data() 的 copy+len 溢出检查、rsge 偏移错误、udp_bpf_recvmsg() 的 use-after-free、bpf_msg_pop_data() 整数溢出以及 sk_msg copy 状态同步等问题,系列在经 reviewers 确认后以 v4 形式向 bpf-next 提交。来源

  • bpf:修复 JIT 回退路径的 helper call 偏移未修正致内核 panic:Tiezhu Yang 发 v4。当架构实现 bpf_jit_inlines_helper_call()(如 LoongArch、ARM64、RISC-V),verifier 在 fixup 阶段跳过重写 helper call 偏移(insn->imm),留作原始 helper 枚举 ID。若运行时 JIT 被禁用或动态编译失败(如 OOM),内核回退到 interpreter,__bpf_call_base + insn->imm 会跳入未对齐的非法地址,触发指令对齐错误(ADEF)或非法内存访问内核 panic。v4 在 __bpf_prog_select_runtime() 中引入 bpf_fixup_fallback_helpers(),当 JIT 编译失败或禁用时,将原先跳过的 helper call 偏移重写为相对内存偏移,再交 interpreter 执行。来源

  • TCP 本地 ECMP rehash 补丁系列 v14 发布:Neal T Spring 发布 [PATCH net-next v14 0/2] tcp: rehash onto different local ECMP path on retransmit timeout。补丁 1 在使用 sk_rethink_txhash() 重新生成 txhash 后,同时调用 __sk_dst_reset() 使缓存路由失效,并在每次路由查找前从 sk_txhash 设置 fl6->mp_hash,使 fib6_select_path() 能根据新的 txhash 选择另一条 ECMP 路径(仅影响默认 L3 策略)。补丁 2 新增 selftest,覆盖 SYN、SYN/ACK、RTO、虚假重传、PLB 等场景下的 rehash 验证。来源


文件系统 / VFS


👀 值得追的讨论 / Patch

zswap shrink_worker 回写 cursor 设计:决定暂弃 per-memcg cursor,保留 root cgroup cursor

在 zswap shrink_worker 回写性能优化系列讨论中,Hao Jia 根据 Yosry Ahmed、Nhat Pham 和 Shakeel Butt 的建议,决定下一版本暂时丢弃 per-memcg cursor,保持原有 root cgroup cursor(zswap_next_shrink)逻辑不变;改用 zswap_writeback_only key,并将 shrink_worker() 与 shrink_memcg() 的批量回写逻辑合并。Shakeel Butt 表示 swap tiering 交互可后续解决,Hao 可继续推进该系列。

为什么重要:该决定简化了 API 设计,避免引入 per-memcg 复杂度,并为后续在 shrink_worker 路径启用批量回写、提升回写效率奠定基础,同时保持了与现有 memcg 接口的兼容性。

来源

⚡ 一句话速览

  • arm64 ptep_try_set() 注释清理:Tejun Heo 去除一条无根据(从 x86 copy-paste)的 pte_none() 注释,补丁已合入 bpf-next来源

  • slab pull request for 7.2:Vlastimil Babka 发出 [GIT,PULL] slab updates for 7.2,包含 sheaves、alloc_flags 重构等系列。来源

  • kmemleak 任务栈扫描可提前终止的讨论:Breno Leitao 建议在扫描每个 task 的栈循环中添加 scan_should_stop() 检查以允许提前退出;Catalin Marinas 指出 scan_block() 已有提前退出机制,但可考虑后续让 scan_block() 返回非零值以简化判断。来源

  • cpuset mempolicy rebind 修复 v1 获认可,v2 应采用 newmems:David Hildenbrand 在回复中确认,cgroup/cpuset 的 mempolicy rebind 补丁 v1 使用 newmems 是正确的方案;v2 误改为 effective_mems,应回退至 newmems,以保证使用的值在那一刻确定非空。来源

  • percpu_ref 文档最大值更新:Matthew Wilcox (Oracle) 提交补丁修正 percpu_ref 文档,将 int 改为 long(2014 年已变更),Tejun Heo Acked-by。来源

  • kfree_rcu_nolock() v3 发出:Harry Yoo 的 [for-next,v3,0/9] mm/slab: introduce kfree_rcu_nolock() 系列新增 test 覆盖 kfree_rcu_nolock() 在 NMI/hardirq 与 PREEMPT_RT 下的行为,并允许在 PREEMPT_RT 上使用 kfree_rcu_sheaf()来源

  • page_owner_sort 内存泄漏修复:Yichong Chen 发补丁修复 tools/mm/page_owner_sortadd_list() 分配 commtxt 后只在清理路径释放外层数组而不释放字符串缓冲区的问题,在 add_list()、丢弃记录及退出时正确释放缓冲区。来源

  • HMM 测试允许 PUD 级 entry:Aboorva Devarajan 报送了 Sayali Patil 的补丁,使 HMM compound 测试接受 PUD 级映射。当前测试仅假设 PMD 级,在设置 default_hugepagesz=1G 的系统上会误 FAIL。补丁通过检测设备报告的映射级别(PMD 或 PUD),要求每个页面精确匹配,接受 PUD 并拒绝混合 PMD/PUD 的碎片映射。来源

  • 大页 split 后尾页不加入 LRU 修复继续讨论:Zhaoyang Huang 的 [PATCHv2] mm/huge_memory: do not add dropped split tail folios to LRU 讨论持续,核心问题在于 split 过程中 tail folio 的 lru 指针可能指向已释放的链表,导致内核崩溃。补丁旨在确保 split_huge_page_to_list_to_order() 内清理尾页的 LRU 链接。David Hildenbrand 提出对 race 条件的疑问,Zhaoyang Huang 解释该条件可能存在于 folio_isolate_lru 与 folio_put 之间。来源