系列:[PATCH v5 0/3] mm: Free contiguous order-0 pages efficiently作者: Ryan Roberts, Muhammad Usama Anjum (ARM)版本: v5(3个patch)
Linux 内核 v6.19-rc1 引入了 commit a06157804399 ("mm/vmalloc: request large order pages from buddy allocator"),使 vmalloc 更积极地从 buddy 分配器请求高阶(high order)页面来建立 huge mapping。然而,这些高阶页面分配后必须立即调用 split_page() 拆分为 order-0 页面,以兼容需要访问底层 struct page 的用户。释放时,每个 order-0 页面被逐个归还到 pcp(per-cpu page)的 order-0 列表中,而非原来的高阶 pcp 列表。这导致了 test_vmalloc.ko 多个 benchmark 出现显著性能回退,部分场景劣化超过 50%。同样的低效也存在于 free_contig_range() 和 __free_contig_frozen_range()(CMA 路径)中,它们都在循环中逐页调用 __free_page() 或 free_frozen_pages()。
vfree())中逐页释放导致的性能回退,部分 benchmark 劣化达 -50.92%free_contig_range() 逐页释放 order-0 页面的低效问题__free_contig_frozen_range()(CMA frozen page 路径)同样的逐页释放低效_raw_spin_unlock_irqrestore 占 35.37%)核心思路是将一段连续的 order-0 页面"重新合并"为最大可能的 power-of-2 对齐块(chunk),然后以高阶方式一次性释放到 pcp 或 buddy。
Patch 1:在 mm/page_alloc.c 中引入新的基础设施。新增 FPI_PREPARED 标志,表示 free_pages_prepare() 已经为该页面调用过,跳过重复准备。核心函数 __free_contig_range_common() 遍历连续 PFN 范围:对每个 order-0 页面执行引用计数减一(put_page_testzero())和 free_pages_prepare();然后追踪连续的"可释放"页面段,调用 free_prepared_contig_range() 批量释放。后者计算每个 PFN 对齐到的最大 order(通过 __ffs(pfn) 和 ilog2(nr_pages) 取最小值),然后调用 __free_frozen_pages(page, order, FPI_PREPARED) 以高阶方式一次性释放。特别注意处理了跨 memory section 边界的情况(memdesc_section() 检查),避免跨越 section 的 struct page 不连续问题。
staticvoidfree_prepared_contig_range(struct page *page, unsignedlong nr_pages){while (nr_pages) {unsignedint order = pfn ? __ffs(pfn) : MAX_PAGE_ORDER; order = min_t(unsignedint, order, ilog2(nr_pages)); order = min_t(unsignedint, order, MAX_PAGE_ORDER); __free_frozen_pages(page, order, FPI_PREPARED); ... }}Patch 2:优化 vfree() 路径。新增 free_pages_bulk() 函数,接受 struct page **page_array,通过 num_pages_contiguous() 检测数组中连续 PFN 的运行段,对每段调用 __free_contig_range()。vfree() 中将统计更新(mod_lruvec_page_state)与释放分离,先批量更新统计,再调用 free_pages_bulk() 一次性释放所有页面。
Patch 3:将 __free_contig_frozen_range()(CMA 释放路径)改写为直接调用 __free_contig_range_common(pfn, nr_pages, /* is_frozen= */ true),复用 Patch 1 建立的批量释放基础设施。
该系列显著修复了 vmalloc benchmark 回退,并在大多数场景下超越了原始基线:
fix_size_alloc_test: p:512, h:1 改善 **118.09%**,fix_size_alloc_test: p:256, h:1 改善 **89.44%**,多数多核并行测试改善 50%-80%。与 v6.18 基线对比,改善范围 -14% 至 49%。free_contig_frozen_range 占比从 70.89% 降至 23.57%。系列:[PATCH v1] slab: support for compiler-assisted type-based slab cache partitioning作者: Marco Elver (Google)版本: v1(1个patch)
内核现有的 CONFIG_RANDOM_KMALLOC_CACHES 安全加固特性创建了 16 份 kmalloc slab cache 副本,通过基于调用地址(_RET_IP_)的随机哈希来选择 cache,使攻击者更难在堆上精确喷射(heap spray)脆弱内存对象。然而,这种基于调用地址的随机化方式是非确定性的(non-deterministic):同一类型 T 的对象可能因为从不同调用点分配而落入不同 cache,同时不同类型的对象也可能因哈希碰撞共享同一 cache。这意味着含指针对象(pointer-containing objects)和纯数据缓冲区(pointerless data buffers)可能混在同一 slab 中,攻击者通过溢出一个纯数据缓冲区就可能破坏相邻的含指针对象中的关键元数据。Clang 22 引入了新的编译器内建函数 __builtin_infer_alloc_token,可以从分配参数中推断出所分配的类型,为基于类型的确定性 slab 分区提供了可能。
RANDOM_KMALLOC_CACHES 的分区是随机的而非基于类型的,无法保证类型隔离__builtin_infer_alloc_token 但内核缺乏集成该 patch 将原有的 RANDOM_KMALLOC_CACHES 基础设施泛化为 PARTITION_KMALLOC_CACHES 框架,原随机模式成为其中一种 partitioning mode。
Kconfig 重构:引入 CONFIG_PARTITION_KMALLOC_CACHES 作为总开关,下设 choice:CONFIG_RANDOM_KMALLOC_CACHES(原有行为,默认)和新增的 CONFIG_TYPED_KMALLOC_CACHES(需要 Clang 22+,依赖 $(cc-option,-falloc-token-max=123) 检测)。
类型抽象:定义 kmalloc_token_t 结构体和 __kmalloc_token(...) 宏,根据配置有三种行为:
#ifdef CONFIG_RANDOM_KMALLOC_CACHEStypedefstruct {unsignedlong ip; } kmalloc_token_t;#define __kmalloc_token(...) ((kmalloc_token_t) { .ip = _RET_IP_ })#elif defined(CONFIG_TYPED_KMALLOC_CACHES)typedefstruct {unsignedlong v; } kmalloc_token_t;#define __kmalloc_token(...) ((kmalloc_token_t){ .v = __builtin_infer_alloc_token(__VA_ARGS__) })#elsetypedefstruct {} kmalloc_token_t; // no-op, zero-size#endif在 TYPED_KMALLOC_CACHES 模式下,编译器通过分析 kmalloc(sizeof(T), ...) 或 (T *)kmalloc(...) 等模式推断分配类型,返回一个基于类型名哈希的 token ID。Clang 采用 "typehashpointersplit" 模式:"the top half ID-space is reserved for types that contain pointers and the bottom half for types that do not contain pointers"。编译选项 -falloc-token-max=16 将 token 限制在 0-15 范围内,正好对应 16 个分区 cache。
接口改造:所有 kmalloc 系列函数(kmalloc_noprof, kmalloc_node_noprof, kzalloc_noprof, kvmalloc_node_noprof, kmalloc_array_noprof 等)的内部实现函数加上 _ 前缀,增加 kmalloc_token_t token 参数;然后通过宏自动追加 __kmalloc_token(__VA_ARGS__) 作为末尾参数。
kmalloc_type() 直接使用 token 值索引,省去了随机模式中 hash_64() 的计算开销。PARTITION_KMALLOC_CACHES 作为统一框架,未来可以增加其他分区策略。系列:[PATCH v2 0/3] mm/memory-failure: add panic option for unrecoverable pages作者: Breno Leitao (Debian/Meta)版本: v2(3个patch)
当硬件内存错误(如多位 ECC 错误)命中正在使用的内核页面时,内核的 memory failure handler(memory_failure())会尝试恢复。但对于 slab 对象(如 dentry cache、inode cache)、页表(page tables)、内核栈(kernel stacks)、vmalloc 分配等内核页面类型,由于缺乏反向映射(reverse mapping)来隔离所有引用,恢复机制不支持这些页面。当前行为是将错误标记为 "Ignored" 并继续运行,但被破坏的数据仍然可被内核访问。作者在生产环境的 arm64 服务器上观察到:"We frequently observe multi-bit ECC errors hitting kernel slab pages, where memory_failure() fails to recover them and the system crashes later at an unrelated code path, making root cause analysis unnecessarily difficult"。封面信给出了一个具体案例:多位 ECC 错误命中 dentry cache slab 页面,67 秒后 d_lookup() 访问被毒化的 cache line 导致 synchronous external abort,crash 的 PC 指向 d_lookup+0x5c/0x220,完全掩盖了真正的根因。
get_hwpoison_page() 返回负值时未被正确识别为内核页面Patch 1:在 mm/memory-failure.c 的 memory_failure() 函数中,当 get_hwpoison_page() 返回负值时,通过 PageReserved(p) 检查区分 reserved pages,将其报告为 MF_MSG_KERNEL 而非 MF_MSG_GET_HWPOISON,使其被正确归类为内核页面。
Patch 2:新增 sysctl vm.panic_on_unrecoverable_memory_failure(默认值 0)。在 action_result() 函数中,当该 sysctl 启用且结果为 MF_IGNORED,且页面类型为 MF_MSG_KERNEL、MF_MSG_KERNEL_HIGH_ORDER 或 MF_MSG_UNKNOWN 时,立即调用 panic():
if (sysctl_panic_on_unrecoverable_mf && result == MF_IGNORED && (type == MF_MSG_KERNEL || type == MF_MSG_KERNEL_HIGH_ORDER || type == MF_MSG_UNKNOWN)) panic("Memory failure: %#lx: unrecoverable page", pfn);Patch 3:在 Documentation/admin-guide/sysctl/vm.rst 中添加文档。
系列:[PATCH v3] mm/vmalloc: Use dedicated unbound workqueues for vmap drain作者: Uladzislau Rezki (Sony)版本: v3(1个patch)
vmalloc 子系统在释放虚拟地址映射区域时,通过 drain_vmap_area_work() 进行延迟回收(lazy purge)。当系统 CPU 数量较多且积累了大量待回收的 vmap area 时,该函数的执行时间可能超过 10ms,而它当前运行在系统全局的 bound workqueue 上。这导致在高负载场景下触发 workqueue watchdog 告警:"workqueue: drain_vmap_area_work hogged CPU for >10000us"。此外,purge helper 的调度方式基于 cpumask 迭代并使用 schedule_work_on() 绑定到特定 CPU 执行,既复杂又存在当 drain work 和 helper work 共用同一 rescuer 线程时的潜在死锁隐患。该问题由 commit 72210662c5a2 引入,标记为 Fixes 并 Cc stable。
drain_vmap_area_work() 在高 CPU 数系统上执行超过 10ms,触发 workqueue watchdog 告警引入两个专用的 WQ_UNBOUND | WQ_MEM_RECLAIM 工作队列:
**drain_vmap_wq**:用于调度顶层 drain_vmap_work。WQ_UNBOUND 使调度器可将工作分配到任意可用 CPU,避免单核长时间被占用;WQ_MEM_RECLAIM 确保内存压力下仍能通过 rescuer 线程保证前向进展。
**drain_vmap_helpers_wq**:用于调度 purge helper。与 drain work 分离到独立工作队列,避免共用 rescuer 线程产生死锁。
在 struct vmap_node 中新增 work_queued 布尔字段。调度逻辑从原来的双遍历 cpumask 简化为单次遍历 for_each_vmap_node(vn)。两个工作队列通过 early_initcall(vmalloc_init_workqueue) 在启动早期创建。
系列:[RFC PATCH] mm/hmm: Add userfaultfd support to fault handling作者: Stanislav Kinsburskii (Microsoft)版本: RFC(1个patch)
HMM(Heterogeneous Memory Management,异构内存管理)框架允许设备驱动通过 hmm_range_fault() 对用户空间虚拟地址范围进行 fault 操作,从而获取对应的物理页映射。当 HMM 遇到缺失的 PTE/PMD 时,会调用 hmm_vma_fault() -> handle_mm_fault() 来填充页表。然而,当前 HMM 的 fault 路径不处理 userfaultfd 支持的 VMA。userfaultfd 允许用户空间程序自行处理缺页,广泛用于虚拟机实时迁移(live migration)、CRIU 检查点/恢复等场景。如果一个 VMA 同时被 userfaultfd 监控并被 HMM 设备访问,HMM 框架无法正确处理 VM_FAULT_RETRY 和 VM_FAULT_COMPLETED 返回值。
handle_mm_fault() 返回 VM_FAULT_RETRY 或 VM_FAULT_COMPLETED 时缺乏处理逻辑VM_FAULT_RETRY / VM_FAULT_COMPLETED 场景下 mmap_read_lock 已被释放,需要重新获取在 mm/hmm.c 中新增 hmm_handle_mm_fault() 函数封装原有的 handle_mm_fault() 调用。对于 userfaultfd 支持的 VMA(通过 userfaultfd_missing(vma) 检测),额外设置 FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_USER 标志位。当 handle_mm_fault() 返回 VM_FAULT_COMPLETED 或 VM_FAULT_RETRY 时,重新获取 mmap_read_lock(mm) 后返回 -EBUSY,将重试逻辑留给调用者处理。作者指出关键差异:"instead of retrying or moving forward respectively, return -EBUSY after reacquiring mmap_read_lock. Since the lock was released, the VMA could have changed, so defer retry logic to the caller."
系列:[PATCH v4 0/8] dma-buf: heaps: Turn heaps into modules作者: Maxime Ripard版本: v4(8个patch)
dma-buf heaps 是 Linux 内核提供的统一内存分配框架,允许用户空间通过标准接口从不同类型的内存区域(如 buddy allocator 的 system heap、CMA 区域的 CMA heap)分配 dma-buf。目前 system heap 和 CMA heap 都是 built-in,无法作为模块加载。将 heap 转为模块有多重好处:减小内核镜像大小、允许按需加载、方便独立开发和测试。但 CMA heap 的模块化面临特殊挑战——kernel/dma/contiguous.c 中有对 CMA heap 代码的直接调用(dma_heap_cma_register_heap()),形成内核对模块的反向依赖。
dma_contiguous_default_area 全局变量直接暴露给外部模块,封装性差cma_alloc()、cma_release()、cma_get_name() 未导出符号8 个 patch 按层级依次解决依赖关系:
Patch 1:反转 heap 注册逻辑。删除 CMA heap 中的 dma_heap_cma_register_heap() 函数,在 kernel/dma/contiguous.c 中新增 dma_contiguous_areas[] 数组和迭代器供 heap 模块查询。
Patch 2-3:将 dev_get_cma_area() 从 inline 函数转为实际函数,随后将 dma_contiguous_default_area 改为 static。
Patch 4-5:导出 dev_get_cma_area()、cma_alloc()、cma_release()、cma_get_name() 为 EXPORT_SYMBOL_GPL。
Patch 6:通过 EXPORT_SYMBOL_NS_GPL(mem_accounting, "DMA_BUF_HEAP") 导出记账参数。
Patch 7-8:将 DMABUF_HEAPS_CMA 和 DMABUF_HEAPS_SYSTEM 的 Kconfig 类型从 bool 改为 tristate,添加 MODULE_LICENSE 和 MODULE_IMPORT_NS 宏。
=m),减小内核基础镜像大小dma_contiguous_default_area 变为 static,增强封装性系列:[PATCH v3 0/2] zswap pool per-CPU acomp_ctx simplifications作者: Kanchana P. Sridhar (Intel)版本: v3(2个patch)
zswap 使用 per-CPU 的异步压缩上下文(struct crypto_acomp_ctx,简称 acomp_ctx)来执行压缩和解压操作。当前实现中,这些资源在 CPU 热插拔的 online 和 offline 阶段分别被分配和释放。这导致了复杂的生命周期管理问题:zswap_compress() / zswap_decompress() 可能在持有某个 CPU 的 acomp_ctx 互斥锁时被迁移到另一个 CPU,而原 CPU 被下线后 zswap_cpu_comp_dead() 会释放资源,造成潜在的 use-after-free。为此,现有代码引入了 acomp_ctx_get_cpu_lock() 中的无限循环重试逻辑,增加了代码复杂性。
zswap_cpu_comp_dead() 中的 IS_ERR_OR_NULL() 检查与实际 API 返回值不一致Patch 1:修正 zswap_cpu_comp_dead() 中的冗余检查,简化为正确的 !acomp_ctx 和 if (req) 检查。
Patch 2(核心改动):将 per-CPU acomp_ctx 资源的生命周期绑定到 zswap pool 而非 CPU hotplug:
cpuhp_setup_state_multi() 中 teardown 设为 NULLacomp_ctx_free() 集中释放逻辑,供 pool 销毁时使用acomp_ctx_get_cpu_lock() / acomp_ctx_put_unlock() 重试循环,zswap_compress() 和 zswap_decompress() 直接使用 raw_cpu_ptr() + mutex_lock()系列:[RFC PATCH] zram: update ac_time of written back slots作者: Sergey Senozhatsky (Chromium)版本: RFC(1个patch)
zram 支持将不常用的压缩页面回写(writeback)到后端磁盘设备以释放内存。在 CONFIG_ZRAM_TRACK_ENTRY_ACTIME 启用时,zram 为每个槽位记录访问时间(ac_time),用于辅助判断页面冷热程度。然而当前实现中,槽位被成功回写后 ac_time 不会被更新,用户空间和内核无法得知已回写槽位在磁盘上停留了多长时间,也无法有效监控回写效率。
ac_time 未被刷新,导致无法追踪磁盘驻留时间从 mark_slot_accessed() 中拆分出 update_slot_ac_time() 辅助函数,专门负责更新 ac_time:
staticvoidupdate_slot_ac_time(struct zram *zram, u32 index){#ifdef CONFIG_ZRAM_TRACK_ENTRY_ACTIME zram->table[index].attr.ac_time = (u32)ktime_get_boottime_seconds();#endif}在回写完成路径 zram_writeback_complete() 中调用 update_slot_ac_time() 而非 mark_slot_accessed(),因为后者会清除 ZRAM_PP_SLOT 标志,而回写完成时槽位仍在后处理列表中,不应提前清除。
ac_time 评估回写策略有效性系列:[PATCH] liveupdate: add LIVEUPDATE_SESSION_GET_NAME ioctl作者: Luca Boccassi版本: v1(1个patch)
liveupdate(热更新)子系统允许用户空间通过创建 session 来管理热更新过程。用户空间创建 session 时指定名称并获得 FD,但缺乏从 FD 反向查询 session 名称的机制。虽然可通过 /proc/self/fd/X 符号链接获取名称,但 procfs 中 anon_inode 有字符数硬性限制,长名称会被截断。对于 systemd 这样的编排器,准确识别每个 FD 对应的 session 至关重要。
/proc/self/fd/X 方式有截断风险UAPI:新增 LIVEUPDATE_CMD_SESSION_GET_NAME = 0x43,定义 struct liveupdate_session_get_name(含 size 和 name 字段)。
内核实现:luo_session_get_name() 使用 strscpy() 复制 session 名称,通过 luo_ucmd_respond() 返回。
自测试:新增 get_session_name 和 get_session_name_max_length 两个测试用例。
系列:[PATCH v2] mm/mempolicy: fix memory leaks in weighted_interleave_auto_store()作者: Jackie Liu版本: v2
v6.16 引入的 Weighted Interleave Auto-tuning 功能(commit e341f9c3c841)中,weighted_interleave_auto_store() 负责通过 RCU 机制切换自动/手动模式。然而 old_wi_state 的获取被放在 if (!input) 条件块内部,仅在写入 "false" 时才获取旧状态,导致两条独立的内存泄漏路径。
new_wi_stateold_wi_state 始终为 NULL,旧状态永远不会被释放。用户可循环写入 "1" 反复触发泄漏将 rcu_dereference_protected() 调用提升到条件块之前,使其对两种输入都生效。统一了"模式未变化"的提前返回逻辑,确保释放 new_wi_state:
mutex_lock(&wi_state_lock);old_wi_state = rcu_dereference_protected(wi_state, lockdep_is_held(&wi_state_lock));if (old_wi_state && input == old_wi_state->mode_auto) { mutex_unlock(&wi_state_lock); kfree(new_wi_state);return count;}修复了两个可被用户空间反复触发的内核内存泄漏。标记 Cc: stable@vger.kernel.org # v6.16+。
系列:[PATCH v3] zram: do not forget to endio for partial discard requests作者: Sergey Senozhatsky (Chromium)版本: v3
zram 以 PAGE_SIZE 为单位管理数据。当 discard 请求的起始偏移未对齐到页边界时(逻辑块大小小于物理块大小的架构上可能发生),zram 无法对部分页进行 discard。commit 0120dd6e4e202 重构了 zram_bio_discard() 使其自包含处理 bio 生命周期,但在部分 discard 的提前返回路径上遗漏了 bio_endio() 调用。
submit_bio_wait() 的调用者永远不会被唤醒blkdiscard -p 4k /dev/zram0 "takes literally forever to complete"将部分 discard 场景下的 return 替换为 goto end_bio,跳转到已有的 bio_endio(bio) 调用处:
if (offset) {if (n <= (PAGE_SIZE - offset))goto end_bio; /* 原来是 return; */ ...}end_bio:bio_endio(bio);修复了导致用户空间工具永久挂起的严重回归 bug。已由 Qu Wenruo 确认测试通过。改动最小化,仅影响错误路径。
系列:[PATCH v2] mm/vma: fix memory leak in __mmap_region()作者: Sechang Lim版本: v2
commit 605f6586ecf7 引入了对 .mmap_prepare 回调替换 backing file 场景的处理。典型触发路径:以 MAP_SHARED 方式 mmap /dev/zero 时,mmap_zero_prepare() 分配新的 shmem 文件替换原文件。但该 commit 只处理了成功路径,忽略了错误路径:如果文件替换后 __mmap_new_vma() 分配 VMA 失败,新的 shmem 文件无人释放。
vm_area_alloc() 被强制失败时,shmem 文件(360 字节 struct file)永远不会被释放在 abort_munmap 错误路径中添加对替换文件的释放:
abort_munmap:if (map.file_doesnt_need_get) fput(map.file); vms_abort_munmap_vmas(&map.vms, &map.mas_detach);return error;修复了 .mmap_prepare 文件替换机制中遗漏的错误路径资源清理。由 syzkaller 发现,已获 Lorenzo Stoakes 的 Reviewed-by。
系列:[PATCH v4] mm/userfaultfd: detect VMA replacement after copy retry in mfill_copy_folio_retry()作者: David Carlier版本: v4
userfaultfd 中的 mfill_copy_folio_retry() 在 copy_from_user() 因缺页失败后需要释放所有锁进行重试。这个释放锁的窗口期存在安全隐患:另一个线程可以执行 munmap + mmap + UFFDIO_REGISTER 用完全不同的 VMA 替换原来的 VMA。现有代码仅通过 ops 检查验证 VMA 是否改变,但如果替换的 VMA 类型相同(如 shmem -> shmem),ops 检查不足以检测到替换。
56a3706fd7f9 引入引入 struct vma_snapshot 结构体和三个辅助函数:
vma_snapshot_take():释放锁前拍摄 VMA 快照,通过 get_file() 持有文件引用vma_snapshot_changed():重新获取锁后,比较 flags 和文件 inode 是否一致vma_snapshot_release():释放文件引用堵住了 userfaultfd 中可被多线程利用的竞态条件窗口,通过快照比较提供更强的 VMA 一致性保证,防止数据损坏。
系列:[PATCH v4] mm/alloc_tag: clear codetag for pages allocated before page_ext initialization作者: Hao Ge版本: v4
内存分配标记(alloc_tag)功能通过 page_ext 为每个页面记录分配来源。由于初始化顺序限制,page_ext 在启动过程中分配较晚。在其可用之前已分配的页面的 codetag 保持未初始化状态,后续被释放时触发 "alloc_tag was not set" 警告。
WARN_ONCE 警告page_ext 初始化前分配的页面缺乏 codetag 记录实现"早期 PFN 追踪"机制:
__pgalloc_tag_add() 中 page_ext 不可用时,调用 alloc_tag_add_early_pfn() 记录 PFN__initdata 数组 early_pfns[8192],通过 atomic_try_cmpxchg 实现无锁并发安全__init 函数,初始化完成后停用clear_early_alloc_pfn_tag_refs() 将早期页面标记为"空"而非未初始化消除调试配置下的虚假警告,标记 Cc: stable。__initdata 数组确保运行时零开销。
系列:[PATCH 0/3] Minor hmm_test fixes and cleanups作者: Alistair Popple (NVIDIA)版本: v1(3个patch)
HMM 自测试框架的 test_hmm 模块存在三个问题:文件关闭时未迁回设备私有页面导致 UAF;THP 大小硬编码为 2MB 在非 x86 架构上失败;模块卸载缺少 device.release 方法。这些问题由 Zenghui Yu 在 arm64 平台上首次报告。
dmirror_fops_release() 释放 dmirror 后,残留的设备私有页面持有野指针,coredump 时触发 panicTWOMEG 在 arm64 64K 页面(PMD=512MB)下测试失败device.release 导致内核告警Patch 1:在 dmirror_fops_release() 中释放 dmirror 前遍历所有 devmem_chunks 并调用 dmirror_device_evict_chunk() 迁回设备私有页面。
Patch 2:将所有 TWOMEG 常量替换为 read_pmd_pagesize() 动态获取;删除自定义解析函数,改用 vm_util.h 已有工具。净减 51 行。
Patch 3:新增 dmirror_device_release() 回调,修复错误处理顺序。
新机制 / 新接口
| slab: type-based partitioning | __builtin_infer_alloc_token 实现确定性类型隔离,含指针/不含指针对象分区 | |
| memory-failure: panic option | vm.panic_on_unrecoverable_memory_failure,不可恢复内存故障时即时 panic 获取干净 dump | |
| hmm: userfaultfd support | ||
| dma-buf heaps: modules | ||
| liveupdate: GET_NAME ioctl |
性能优化
| Free contiguous order-0 pages | ||
| vmalloc: dedicated drain WQ | ||
| zswap: acomp_ctx simplification | ||
| zram: writeback ac_time |
Bug Fix
| mempolicy: memory leaks | ||
| zram: partial discard endio | ||
| vma: __mmap_region leak | ||
| userfaultfd: VMA replacement | ||
| alloc_tag: early pfn | ||
| hmm_test: UAF + arch compat |
内部优化 / 清理
本期无独立的内部优化/清理系列入选。
编译器辅助安全加固:slab 类型分区(#2)代表了利用编译器能力进行内核安全加固的新方向,Clang 22 的 __builtin_infer_alloc_token 使确定性堆隔离成为可能,未来可能扩展到更多分配器。
批量化页面操作:连续 order-0 页面批量释放(#1)展示了将逐页操作合并为批量高阶操作的优化模式,在 vmalloc 和 CMA 路径均带来数倍性能提升。
生产环境可观测性与诊断:memory-failure panic 选项(#3)和 zram writeback ac_time(#8)反映了大规模生产环境对故障诊断和性能监控能力的持续需求。
模块化架构演进:dma-buf heaps 模块化(#6)延续了内核子系统从 built-in 向可加载模块转变的趋势,通过符号命名空间等现代机制保持模块边界清晰。
异构内存管理扩展:HMM userfaultfd 支持(#5)和 HMM 测试跨架构修复(#15)显示异构内存管理框架在向更多使用场景和硬件平台扩展。