系列:[PATCH resend v6 00/30] mm/virtio: skip redundant zeroing of host-zeroed pages作者: Michael S. Tsirkin版本: v6(30 patches)
在虚拟化环境中,当 guest 通过 virtio-balloon 的 free page reporting 机制向 hypervisor 报告空闲页面时,host 端通常会在回收这些页面的后备内存时将其置零(例如通过 MADV_DONTNEED 对匿名映射页执行清零)。然而当 guest 之后再分配这些页面时,内核的 post_alloc_hook() 会因为 __GFP_ZERO 而再次无条件清零——这是完全冗余的工作。作者在 cover letter 中指出:
"When a guest reports free pages to the hypervisor via virtio-balloon's free page reporting, the host typically zeros those pages when reclaiming their backing memory. When the guest later reallocates those pages, the kernel zeros them again, redundantly."
对于透明大页(THP)和 hugetlb 分配,这种重复清零的代价尤其显著——清零 2MB 大页不仅消耗 CPU 周期,还会污染数据缓存并引发大量 cache miss。
此外,在带有别名缓存(VIPT alias cache)的架构上,init_on_alloc 路径本身就存在双重清零问题:post_alloc_hook() 中的 kernel_init_pages() 会清零一次,之后调用处的 clear_user_highpage()(因为 user_alloc_needs_zeroing() 返回 true)会再清零一次。作者明确指出:
"Further, on architectures with aliasing caches, upstream with init_on_alloc double-zeros user pages: once via kernel_init_pages() in post_alloc_hook, and again via clear_user_highpage() at the callsite."
该系列涉及两个新的 virtio 规范特性:VIRTIO_BALLOON_F_DEVICE_INIT_REPORTED(bit 6)用于 page reporting 路径,VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE(bit 7)用于 balloon inflate/deflate 路径。
post_alloc_hook() 和 clear_user_highpage() 各清零一次用户页。PageReported 标志,导致下一次 reporting cycle 中重复报告。PAGE_REPORTING_CAPACITY 为编译期常量,驱动无法根据 virtqueue 大小动态调整。整个方案的核心思想是:在 buddy allocator 的空闲链表页面上引入 PG_zeroed 标志(共享 PG_private 比特位,仅在空闲链表页面上安全),由两个数据源设置此标志——page reporting(host 在回收时清零)和 balloon deflate(host 在 inflate 时清零)——通过 buddy 合并/拆分逻辑传播,最终在 post_alloc_hook() 中消费此标志来跳过冗余清零。
PG_zeroed 的生命周期管理:
page_reporting_drain() 在 host 确认清零后设置;balloon deflate 路径使用 free_frozen_pages_zeroed() 携带 FPI_ZEROED 内部标志释放expand() 将高 order 已清零页的状态传播到拆分出的子页;__free_one_page() 中的 buddy merge 在合并前检查两个 buddy 是否都为 PG_zeroed,若都为真则保留标志,否则清除rmqueue_buddy() / __rmqueue_pcplist() 分配时 read-then-clear,将 zeroed 状态作为 bool 传递到 prep_new_page() → post_alloc_hook(),当 zeroed && !zero_tags 时跳过内存清零__free_pages_prepare() 因 PG_zeroed 别名到 PG_private 而自动清除,__free_one_page() 在 VM_BUG_ON_PAGE 检查掩码中排除 __PG_ZEROEDPage reporting 集成:page_reporting_dev_info 新增 host_zeroes_pages、zeroed_bitmap、capacity 字段。virtio-balloon 在 report 回调中管理 bitmap:发送前清零,根据 host 返回的 used_len 设置对应 bit。page_reporting_drain() 通过 page_reporting_host_zeroes_pages() 静态分支检查后,按 bitmap 设置 PG_zeroed。
Balloon 路径集成: inflate 时 driver 在描述符链中追加 device-writable bitmap 缓冲区。Host 处理完后返回 bitmap,driver 对对应页面调用 __SetPageZeroed()。Deflate 时对 PageZeroed 页面使用 put_page_zeroed() 释放。
Hugetlb 特殊处理: 引入 HPG_zeroed 标志(hugetlb folio private 位),在 pool 预分配时设置,alloc_hugetlb_folio() 新增 bool *zeroed 输出参数。
系列的前 16 个 patch 是可独立合入的 cleanups 和 fix(包括 init_on_alloc 双重清零修复、page_reporting capacity bugfix),核心 PG_zeroed 机制(patch 18-30)依赖于新的 virtio feature bits,未协商时静态分支处于关闭状态,对非 virtio 环境无性能影响。
作者在 2GB VM、1 vCPU 环境下分配 256MB 匿名页面进行 benchmark 测试。
THP 启用场景:
| -78% | |||
| -76% | |||
| -15% |
Hugetlb surplus 页面场景:
| -70% | |||
| -78% | |||
| -16% |
性能提升的主要来源是免去了对大页(2MB/1GB)的冗余内存清零操作——清零大页不仅消耗 CPU 周期,还会污染数据缓存并引发大量 cache miss。
系列:[PATCH v7 0/3] mm: improve write performance with RWF_DONTCACHE作者: Jeff Layton版本: v7(3 patches)
RWF_DONTCACHE 标志允许应用在缓冲 I/O 写入后立即丢弃 page cache 中的页面,避免污染缓存。这对于备份、日志写入、数据复制等"写一次不再读"的场景非常有价值。在 v6 及之前版本的实现中,generic_write_sync() 对设置了 IOCB_DONTCACHE 的写入调用 filemap_flush_range() 进行同步写回——这意味着写入者被阻塞直至所有数据刷到磁盘。
这种同步 flush 方式带来了严重的尾延迟问题:p99.9 延迟高达 8.9 秒。同时,无视 DONTCACHE 与普通缓冲写的比例进行无差别 flush,导致带宽分配严重不均。
本系列的核心思路是将同步的 filemap_flush_range() 替换为异步的 flusher kick 机制,并通过 per-bdi_writeback 的 DONTCACHE 脏页计数器来精确控制写回范围。
首先在 folio split 路径(__split_folio_to_order())中保留 PG_dropbehind 标志,确保拆分出的 tail folio 不会丢失该标记,从而在后续被清理时能正确递减 DONTCACHE 脏页计数器。
其次在 enum wb_stat_item 中新增 WB_DONTCACHE_DIRTY 计数器,与 WB_RECLAIMABLE 并行递增/递减。在 inode_do_switch_wbs()(cgroup writeback 域迁移)中同步迁移该计数器。当非 DONTCACHE 的 __filemap_get_folio_mpol() lookup 命中带 PG_dropbehind 标志的 folio 时,使用原子的 folio_test_clear_dropbehind() 清除标志并递减计数器,防止并发 reader 重复递减。
最后将 generic_write_sync() 中的 filemap_flush_range() 替换为 filemap_dontcache_kick_writeback():使用 test_and_clear_bit 设置 WB_start_dontcache 标志后唤醒 flusher 线程。Flusher 的 wb_check_start_dontcache() 通过 wb_stat_sum() 读取 DONTCACHE 脏页数量(聚合 per-CPU 批次以捕获低于 percpu 阈值的小写入),写入对应数量的页面。整个流程异步执行,不阻塞写入者。
关键设计细节:filemap_dontcache_kick_writeback() 中先获取 wb 引用再唤醒 flusher,避免 unlocked_inode_to_wb_end() 释放 wb 后的 UAF;wb_wakeup() 移到 unlocked_inode_to_wb_begin/end 区间外部,防止 cgroup writeback 切换时 spin_unlock_irq() 在 i_pages xa_lock 持有时重新使能中断。
作者提供了两组 benchmark(测试环境未具体说明):
单流顺序写:
| +201% | |||
| -99.7% |
多写入者竞争场景:
性能提升来自两个层面:(1) 异步 flusher kick 消除了写入者的同步等待,(2) 按比例的 DONTCACHE 脏页写回避免了过量 flush 和带宽不公平。
系列:[PATCH mm-unstable v17 00/14] khugepaged: mTHP support作者: Nico Pache, Dev Jain, Baolin Wang版本: v17(14 patches)
多尺寸透明大页(mTHP)允许内核使用 16KB、32KB、64KB、128KB、256KB、512KB、1MB 等中间大小的 huge page,而非仅限 PMD 大小的 2MB THP。用户空间的 MADV_COLLAPSE 已支持 mTHP collapse,但内核后台的 khugepaged 扫描线程仍然只能产生 PMD-order THP。这意味着在内存碎片化严重、无法分配完整 2MB 大页的场景下,khugepaged 完全无法发挥作用。作者在 cover letter 中描述其目标:
"The following series provides khugepaged with the capability to collapse anonymous memory regions to mTHPs."
方案分四个层次变更,核心是通过 bitmap 跟踪 PMD 扫描范围内的页面占用情况,使用 DFS 算法确定最优 mTHP collapse 大小。
第一层:函数通用化。 将 hugepage_vma_revalidate()、alloc_charge_folio()、__collapse_huge_page_isolate()、__collapse_huge_page_copy() 等关键函数从硬编码 HPAGE_PMD_ORDER 改为接受 order 参数。collapse_huge_page() 采用 "enter with lock, exit with lock dropped" 的锁契约——进入时持有 mmap_read_lock,退出时已释放,中间通过 mmap_read_unlock() + mmap_read_lock() 重获取来打破锁持有时间窗口。
第二层:核心算法。 在 struct collapse_control 中引入 mthp_bitmap(unsigned long 数组),在 PMD 扫描过程中记录每个 PTE 位置是否被占用(!none/zero)。扫描完成后,使用迭代式 DFS 算法在 bitmap 上搜索满足 collapse 条件的最优 mTHP 大小:从 PMD order 开始,当高 order collapse 失败时递归拆分为左右两个半区在更低 order 尝试。使用 mthp_bitmap_stack 作为显式栈,避免递归深度限制。
第三层:可见性。 新增 per-order collapse 失败统计(collapse_exceed_none_pte、collapse_exceed_swap_pte、collapse_exceed_shared_pte),通过 sysfs /sys/kernel/mm/transparent_hugepage/khugepaged/ 暴露。在已有 tracepoint 中增加 order 字段。
第四层:资格检查。collapse_allowable_orders() 统一 VMA 级别资格检查,综合考虑 transparent_hugepage_flags、MADV_HUGEPAGE/MADV_NOHUGEPAGE、prctl 设置和 mTHP 启用的 order。collapse_max_ptes_none() 对 mTHP 仅接受 0 或 HPAGE_PMD_NR - 1(511)两个值,防止不合理的阈值导致 collapse "creep"(不断将 mTHP 提升到下一级大小)。
作者在 x86_64、aarch64、ppc64le、s390x 上构建通过,通过了 kernel-tests suites、selftests mm、Redis 测试和大量日常使用。作者在 cover letter 中总结:
"The summary from my testings was that there was no significant regression noticed through this test. In some cases my changes had better collapse latencies, and was able to scan more pages in the same amount of time/work."
作者未提供量化 benchmark 数据。从代码逻辑推断的预期收益:
系列:[PATCH v13 0/5] mm/vmalloc: free unused pages on vrealloc() shrink作者: Shivam Kalra版本: v13(5 patches)
vrealloc() 是 vmalloc 子系统的 realloc 接口,允许对已分配的虚拟映射区进行扩容和缩容。在此之前,当 vrealloc() 执行缩容(shrink)时,仅更新记账信息(vm->requested_size 和 KASAN shadow),但不释放底层的物理页面。这意味着即使调用者明确缩小了分配,被释放区域对应的物理内存仍然被占用,直到整个 vm_struct 生命周期结束(即 vfree() 时)才会被归还。Rust binder driver 的 KVVec::shrink_to 是一个具体的使用场景——它通过显式调用 vrealloc shrink 来做内存回收,当前实现下这些 shrink 调用并没有真正释放物理内存。
get_vm_area_size()(虚拟预留大小)而非实际物理页面数,shrink 后引入页面释放会导致该检查错误地允许在已释放物理页面的地址上做原地扩容。vread_iter() 使用虚拟区域大小推导可读范围,shrink 后该值不会更新,导致尝试从已 unmap 的地址读取数据。整体方案围绕一个设计决策:shrink 时释放物理页面,但保留虚拟地址预留区间不变(vm->size / vmap_area 不变),为将来支持原地扩容(grow-in-place)预留空间。
首先从 vfree() 中提取 vm_area_free_pages() 可复用 helper,使用 free_pages_bulk() 批量释放页面、更新 NR_VMALLOC 统计并置 vm->pages[] 条目为 NULL。vfree() 也改为调用该 helper。
然后将 grow-in-place 检查和 vread_iter() 的区间大小计算从 get_vm_area_size(vm) 切换到 vm->nr_pages << PAGE_SHIFT,使其反映实际已分配的物理页面数。
核心 shrink 逻辑在安全条件保护下执行实际释放:跳过 huge page 分配(需要拆页)、VM_FLUSH_RESET_PERMS(需重置 direct-map 权限)、VM_USERMAP(remap_vmalloc_range_partial 按不变的 vm->size 校验映射)、GFP_NOFS/GFP_NOIO(kmemleak_free_part() 内部使用 GFP_KERNEL 分配可能触发递归死锁)。释放过程:获取 node lock 保护 vm->nr_pages 更新 → kmemleak_free_part() 通知 kmemleak → vunmap_range() 解除虚拟映射 → vm_area_free_pages() 释放物理页面。
lib/test_vmalloc.c 中新增 vrealloc_test 测试用例,覆盖 grow、shrink 跨页、shrink 同页内、grow 在已分配页数内四种场景。
作者未提供性能数据,通过 KASAN KUnit 和 test_vmalloc 压力测试(百万次迭代)验证正确性。
从代码逻辑推断的预期收益:
(old_nr_pages - new_nr_pages) 个物理页面KVVec::shrink_to 从"仅逻辑缩小"变为"实际释放物理内存"系列:[PATCH RESEND v2] mm/percpu-internal.h: optimise pcpu_chunk struct to save memory作者: zenghongling版本: v2(1 patch)
struct pcpu_chunk 是 per-CPU 内存分配器的核心数据结构。通过 pahole 工具分析发现当前结构体布局存在多处 padding hole,字段排列顺序不合理导致编译器插入对齐填充。per-CPU 分配器通常会创建多个 chunk(reserved chunk、first chunk 及动态创建的 chunk),每个 chunk 结构体大小的节省具有累积效应。
struct pcpu_chunk 在 allmodconfig 配置下存在多个 padding hole,总计浪费 14 字节将三个 int 型字段 nr_pages、nr_populated、nr_empty_pop_pages 从 NEED_PCPUOBJ_EXT 条件编译块之后移到之前。这三个连续的 int 字段填满了现有 padding holes,配合整体对齐优化,将结构体从 3 cache lines 压缩到 2 cache lines。
主要收益来自消除一条浪费的 cache line。在多 CPU 系统上,每个 chunk 节省 64 字节具有累积效应。
系列:[PATCH v1] mm/damon/vaddr: attempt per-vma lock during page table walk作者: Kefeng Wang版本: v1(1 patch)
DAMON(Data Access Monitor)的虚拟地址操作(damon_va_mkold、damon_va_young、damos_va_migrate、damos_va_stat)在进行 page table walk 时当前统一使用 mmap_read_lock() 获取整个进程地址空间的读锁。mmap_read_lock 是一个 per-mm 的读写信号量(rwsem),在高并发场景下(例如多线程进程同时有 DAMON 采样和其他 mm 操作)会成为性能瓶颈。
Linux 内核自 5.20 起引入了 per-VMA lock 机制(lock_vma_under_rcu),允许在 RCU 读锁保护下锁定单个 VMA 而不必获取整个 mm 的锁,已在 page fault 路径中广泛应用并证明有效。Page table walk 框架也已支持 PGWALK_VMA_RDLOCK_VERIFY 模式。
mmap_read_lock,高并发下造成不必要的锁竞争damon_va_mkold() 和 damon_va_young() 是每条采样记录都会调用的热路径,但每次只操作单页,使用重量级锁显著浪费引入 damon_va_walk_page_range() 作为所有 DAMON page table walk 的统一入口。内部采用"先尝试 per-VMA lock,失败再回退到 mmap_read_lock"的策略:调用 lock_vma_under_rcu(mm, start) 尝试获取 per-VMA lock,若成功且目标范围完全在单个 VMA 内,设置 PGWALK_VMA_RDLOCK_VERIFY 通过 walk_page_range_vma() 执行遍历后 vma_end_read(vma) 释放;若失败或需要跨多个 VMA,回退到 mmap_read_lock + walk_page_range + mmap_read_unlock 的传统路径。
将该函数应用到 damon_va_mkold、damon_va_young、damos_va_migrate、damos_va_stat 四个调用点。
作者未提供性能数据。从代码逻辑推断的预期收益:
damon_va_mkold() 和 damon_va_young() 从 mmap_read_lock 切换为 per-VMA lock,消除与其他 mm 操作(page fault、mmap/munmap)之间的锁竞争系列:[PATCH v6 0/3] mm/page_owner: add filter infrastructure for print_mode and NUMA filtering作者: Zhen Ni版本: v6(3 patches)
page_owner 是内核调试和内存分析的核心工具,记录每个物理页面的分配者、调用栈和分配时间。在生产环境中分析内存使用问题时,page_owner 的输出文件(通常位于 /sys/kernel/debug/page_owner)动辄达到 GB 级别,主要是因为每页需要输出数十行的完整调用栈。对于 NUMA 系统上的内存分布分析,用户往往只关心特定节点的页面状态,但现有接口不支持按 NUMA 节点过滤。
在 debugfs 下新增 /sys/kernel/debug/page_owner_filter/ 目录,提供两个过滤器:
**print_mode**:支持字符串切换——full_stack 输出完整调用栈(现有行为),stack_handle 模式下每页仅输出一行 handle: NNNNN 取代数十行调用栈。stack 到 handle 的映射可通过已有的 show_stacks_handles 接口获取。
**nid**:支持 nodelist 格式(逗号分隔、范围、混合)的 NUMA 节点过滤。通过 nodelist_parse() 解析用户输入,转换为节点 bitmask,在 PFN 遍历循环中以 nodes_subset() bitmask 操作实现 O(1) 过滤。
两个过滤器可同时使用且互不影响。
作者未提供性能数据。从代码逻辑推断的预期收益:
stack_handle 模式可将 GB 级输出压缩 1-2 个数量级,显著提升分析效率系列:[PATCH 0/8] per-memcg-per-node kmem accounting作者: Alexandre Ghiti版本: v1(8 patches)
当前内核内存记账(MEMCG_KMEM)是一个全局扁平计数器,无法感知 NUMA 节点的分布情况。随着数据中心应用对 NUMA 亲和性和内存拓扑感知的需求日益增长,缺乏 per-node 粒度的 kmem 统计成为一个重要的可观测性缺口。例如,当某个 NUMA 节点承受不成比例的内核内存压力时,当前的统计机制无法给出指示。
利用 Qi Zheng 的 per-node obj_cgroup 基础设施,将 MEMCG_KMEM 从全局计数重构为 per-node NR_KMEM(在 lruvec_stats 中)。核心为三阶段 API:
obj_cgroup_precharge():在计费之前预先确保 per-node objcg 存在且有能力接收计费obj_cgroup_account_kmem():在获取确切分配节点后执行实际记账obj_cgroup_unprecharge():回滚未使用的 precharge 信用Percpu 分配路径(pcpu_alloc_account())使用 per-node 信用数组,在 post-alloc 阶段按实际页面归属节点精确记账。Slab、page charges、zswap 各自通过 obj_cgroup_get_nid() 获取 per-node objcg 后执行记账。同时修复了 flush_nmi_stats() 中 NMI slab 统计未传播到 memcg vmstats 的既有 bug。
作者未提供性能数据。从代码逻辑推断的预期收益:
/sys/devices/system/node/node*/memcg 查看 per-node kmem 使用情况系列:[PATCH 0/3] mm/zswap: Implement per-cgroup proactive writeback作者: Hao Jia版本: v1(3 patches)
Zswap 是压缩交换缓存,在内存压力下将匿名页面压缩存储在 RAM 中,避免直接交换到慢速的 swap 设备。当前 zswap 的写回(writeback)完全是被动触发——只有内存压力达到 watermark 阈值时,内核才将压缩页解压并写出到 swap 设备以回收 zswap 池空间。这种被动模式缺乏主动性:用户可能有特定的 workload 或时间窗口希望主动清空某个 cgroup 的 zswap 缓存,但现有接口不支持。
在 cgroup v2 中新增 memory.zswap.proactive_writeback 接口,支持两个参数:
max=<bytes>:限制单次写回的最大字节数<age>:仅写回存储时间超过指定秒数的压缩页核心技术组件:
struct zswap_wb_iter 嵌入 struct mem_cgroup):支持在指定 cgroup 子树的 zswap LRU 上持续推进写回,避免每次都从链表头部扫描。struct zswap_entry 新增 store_time 字段记录压缩页存入时间,回调中通过 ktime_after() 比较年龄。ZSWAP_PROACTIVE_WB_SCAN_RATIO(16x)和 ZSWAP_PROACTIVE_WB_BATCH(128 页)防止单次操作扫描过多页面。zswpwb_proactive 计数器,与已有 zswpwb 被动计数器区分。作者未提供性能数据。预期收益:
系列:[PATCH v3] mm: process_mrelease: introduce PROCESS_MRELEASE_REAP_KILL flag作者: Minchan Kim版本: v3(1 patch)
process_mrelease() 系统调用于 Linux 5.15 引入,允许 userspace(典型场景如 Android 的 LMKD, Low Memory Killer Daemon)在 SIGKILL 目标进程后立刻启动其地址空间的快速回收(reap),避免等待 RCU 宽限期或引用计数自然降为零的延迟。然而,现有接口将"发送 SIGKILL"和"调用 process_mrelease()"设计为两个独立步骤。
在 OOM 压力场景下,这种分离存在天然的调度竞态窗口:目标进程可能在 SIGKILL 投递之后、process_mrelease() 调用之前进入 do_exit() → exit_mm() 路径并将 task->mm 清空,导致 reap 返回 -ESRCH 失败。作者在 patch 描述中指出:
"arbitrary reference counts (reading /proc/
/cmdline, or various other remote VM accesses) frequently delay this teardown indefinitely, defeating the purpose of expedited reclamation."
这导致 Android LMKD 场景下:"In Android's LMKD scenarios, this delay keeps memory pressure high, forcing the system to unnecessarily kill additional innocent background apps before the memory from the first victim is recovered."
/proc/<pid>/cmdline 等外部访问临时增加 mm 引用计数,钉住内存回收。引入新的 UAPI 标志 PROCESS_MRELEASE_REAP_KILL(1 << 0),在单次系统调用中原子化 SIGKILL 投递和内存回收的全流程。
核心变化:
kill_all_shared_mm() 函数,遍历所有进程使用 process_shares_mm() 检测共享 mm_struct 的进程,向整个线程组投递 SIGKILL(跳过 is_global_init 和 PF_KTHREAD)。reap = reap_kill || task_will_free_mem(p)),消除了竞态窗口。do_pidfd_send_signal_pidns() 导出函数,统一 PID namespace 安全检查,消除 sys_pidfd_send_signal 中的代码重复。-EINVAL。作者未提供量化数据。从代码逻辑推断的预期收益:
系列:[PATCH v6 0/4] mm/memory-failure: add panic option for unrecoverable pages作者: Breno Leitao版本: v6(4 patches)
当硬件内存错误(multi-bit ECC)命中内核拥有的页面时,memory_failure() 尝试隔离和恢复受影响的页面。但如果页面属于内核保留区(PageReserved)、slab 缓存、vmalloc 区域、页表、内核栈等不可恢复类型,当前默认行为是静默记录一条 MF_IGNORED 日志并继续运行。损坏的数据仍然可以被内核访问,导致两种严重后果:(1) 静默数据损坏,(2) 延迟的随机崩溃——可能在原始错误发生数秒或数分钟后触发,此时原始错误上下文(MCE/GHES 记录、页面状态、故障地址)已经丢失。
此外,get_hwpoison_page() 返回失败时,所有失败路径被合并为单一的 MF_MSG_GET_HWPOISON 分类,无法区分"真不可恢复的内核页面"和"短暂的 page allocator 竞态"。
get_any_page() 返回 -EIO/-EBUSY 时失败原因信息丢失,所有失败被无差别对待。action_result() 之后重新检查页面状态时未持有引用。方案从三个维度系统化地解决问题:
失败原因分类细化: 在 get_hwpoison_page() 之前采样 PageReserved(p) 标志(因为在 MF_COUNT_INCREASED 路径下 get_any_page() 可能在返回前已释放引用)。引入 enum mf_get_page_status(MF_GET_PAGE_OK/RACE/UNHANDLABLE)通过输出参数向上传递失败原因。MF_GET_PAGE_UNHANDLABLE 被提升为 MF_MSG_KERNEL(与 reserved pages 合并),MF_GET_PAGE_RACE 保留为 MF_MSG_GET_HWPOISON。MF_MSG_KERNEL 的 tracepoint 标签从 "reserved kernel page" 改为 "kernel page",反映其覆盖范围已扩大到所有不可处理的内核页面类型。
Panic 机制: 新增 vm.panic_on_unrecoverable_memory_failure sysctl(默认 0,权限 0644)。Panic 条件刻意窄化:仅当 result == MF_IGNORED && type == MF_MSG_KERNEL 时触发。明确排除 MF_MSG_GET_HWPOISON 和 MF_MSG_KERNEL_HIGH_ORDER(两者均可由 transient buddy allocator 竞态触发)以及 MF_MSG_UNKNOWN。当条件满足时调用 panic("Memory failure: %#lx: unrecoverable page", pfn),在原始错误现场产生干净的 crash dump。
文档: 在 Documentation/admin-guide/sysctl/vm.rst 中详细说明触发 panic 的页面类型、排除的路径及原因、四种典型使用场景(大型 fleet 事后诊断、kdump 配置、HA 集群 failover、error-injection 测试)。
作者未提供量化数据。预期收益:
| mm/virtio: skip redundant zeroing | ||
| RWF_DONTCACHE write performance | ||
| khugepaged mTHP support | ||
| vrealloc shrink | ||
| percpu chunk 结构体重排 | ||
| DAMON per-VMA lock |
| page_owner filter | ||
| per-memcg-per-node kmem | ||
| zswap per-cgroup writeback | ||
| PROCESS_MRELEASE_REAP_KILL | ||
| memory-failure panic |