当前位置:首页>Linux>Linux MM 2026-04-17~19 最新 Feature 分析报告

Linux MM 2026-04-17~19 最新 Feature 分析报告

  • 2026-06-25 05:03:37
Linux MM 2026-04-17~19 最新 Feature 分析报告

目录

  1. khugepaged: mTHP 支持
  2. Remove read-only THP support for FSes without large folio support
  3. mm: shmem: always support large folios for internal shmem mount
  4. mm/page_owner: add filter infrastructure for print_mode and NUMA filtering
  5. mm/swap: use swap_ops to register swap device's methods
  6. rust: Add helper functions and constants for Tyr driver
  7. make MM selftests more CI friendly
  8. mm/mglru: Use folio_mark_accessed to replace folio_set_active in PF
  9. mm/damon/modules: detect and use fresh status
  10. mm: prepare anon_vma before swapin rmap

1. khugepaged: mTHP 支持

系列[PATCH 7.2 v16 00/13] khugepaged: mTHP support作者: Nico Pache(Red Hat)版本: v16(13 个 patch)

背景

透明大页(Transparent Huge Page,THP)机制在 anon 内存上长期只支持 PMD 级别(x86_64 上为 2MB)的"全或无"大页:khugepaged 在后台扫描并尝试把 512 个连续 4KB 页面提升为一个 PMD THP。近年来内核引入了 mTHP(multi-size THP),允许 anon 内存使用 2^n × 4KB(例如 16KB/64KB/1MB 等)的中间大小折叠,并通过 /sys/kernel/mm/transparent_hugepage/hugepages-*kB/enabled 按 order 独立配置。然而此前 mTHP 仅能在缺页路径(page fault)中被分配,一旦落盘为普通 4KB 页,khugepaged 就无法再把它们折叠成任何 mTHP 尺寸——折叠路径在 hugepage_pmd_enabled()collapse_huge_page()__collapse_huge_page_*() 中硬编码了 HPAGE_PMD_ORDER,使 mTHP 成为"只生不养"的孤儿。

解决的问题

  • khugepaged 无法为已经碎片化为 4KB 页的 anon 区折叠出 mTHP,导致 mTHP 的内存收益无法持续
  • 当用户仅开启 mTHP(未开启 PMD THP)时,khugepaged 线程根本不会启动
  • max_ptes_none(允许填充的空 PTE 数)在 PMD 扫描阶段会提前截断扫描,使小尺寸 mTHP 折叠机会被漏掉
  • 缺少 per-order 的折叠失败统计和 tracepoint,无法诊断为何 mTHP 折叠成功率偏低
  • 需要避免"collapse creep":一次 mTHP 折叠引入过多新 none 页,会使后续扫描反复把它升级到更大的 order

如何做

整套方案采取"先泛化、再扩展"两步走。前半部分(patch 1–5)把 hugepage_vma_revalidate()alloc_charge_folio()__collapse_huge_page_isolate/copy/swapin() 和 collapse_huge_page() 统统按 order 参数泛化,并用 collapse_max_ptes_none/shared/swap() 辅助把 is_khugepaged 与 madvise_collapse 的特殊逻辑封装起来。patch 6 加入"不把已经较大的 mTHP 折叠成更小 mTHP"的防倒退检查(通过 SCAN_PTE_MAPPED_HUGEPAGE 结果向上层通知),patch 9 引入 collapse_allowable_orders(vma, tva_flags) 作为折叠时可选 order 集合的单一入口。

核心实现位于 patch 10(位图扫描)和 patch 11(早退优化)。在 struct collapse_control 中新增两段位图和一个栈:

#define KHUGEPAGED_MIN_MTHP_ORDER  2
#define MTHP_STACK_SIZE  (1UL << (ilog2(MAX_PTRS_PER_PTE) - KHUGEPAGED_MIN_MTHP_ORDER))
DECLARE_BITMAP(mthp_bitmap, MAX_PTRS_PER_PTE);
DECLARE_BITMAP(mthp_bitmap_mask, MAX_PTRS_PER_PTE);
structmthp_rangemthp_bitmap_stack[MTHP_STACK_SIZE];

collapse_scan_pmd() 在扫描 PMD 的 512 个 PTE 时,若开启了任何 mTHP order,就把 max_ptes_none 抬到 KHUGEPAGED_MAX_PTES_LIMIT 以跑完整个 PMD,并对每个非空、非零的 PTE 位置 __set_bit(i, cc->mthp_bitmap)。扫描结束后进入新函数 mthp_collapse(),以 (offset, order) 为单元在栈上做非递归的二叉搜索:从 (0, HPAGE_PMD_ORDER) 开始,用 bitmap_weight_and() 统计该区间的占用 PTE 数,若满足该 order 的 max_ptes_none 门槛就调用 collapse_huge_page(..., order) 尝试折叠;失败或不合格则压入左右两半 (offset, order-1) 和 (offset + nr_ptes/2, order-1),一路降到 KHUGEPAGED_MIN_MTHP_ORDER=2 为止。patch 11 进一步根据 collapse_huge_page() 的返回结果分类:SCAN_SUCCEED 继续下一段,SCAN_LACK_REFERENCED_PAGE/SCAN_EXCEED_* 等尝试更低 order,而 OOM 或 ENOMEM 等致命错误直接 return collapsed 终止整轮。

为防止"collapse creep",patch 10 把 mTHP 路径的 max_ptes_none 限定为 0 或 HPAGE_PMD_NR-1 两个极端值——中间值会因一次折叠引入大量 none 页后触发下轮向更高 order 的"升级",形成反复折腾;collapse_max_ptes_none() 对非法值直接告警并跳过 mTHP 尝试。含 swap 或 shared 页的 mTHP 区间同样被拒绝。

patch 7 新增三项 per-order 统计 collapse_exceed_swap_pte / collapse_exceed_none_pte / collapse_exceed_shared_pte(暴露于 /sys/kernel/mm/transparent_hugepage/hugepages-*kB/stats/),patch 8 为 mm_collapse_huge_pagemm_collapse_huge_page_isolatemm_collapse_huge_page_swapin 三个 tracepoint 追加 order 字段。patch 12 把原 hugepage_pmd_enabled() 改名并扩展为 hugepage_enabled()——只要任一 anon order 位图非零(READ_ONCE(huge_anon_orders_always/madvise/inherit))即启动 khugepaged,同时在 collapse_allowable_orders() 中对 khugepaged 扫描 anon VMA 时返回 THP_ORDERS_ALL_ANON 全集。至此仅开启 mTHP(未开启 PMD THP)的用户也能享受后台折叠。

收益

作者未提供 benchmark 数据表格,但给出以下测试观察:

  • 在 x86_64、aarch64、ppc64le、s390x 上构建并通过 kernel-tests 和 selftests/mm 全量回归
  • 作者自研的 khugepaged 压力脚本测试显示:"there was no significant regression noticed... In some cases my changes had better collapse latencies, and was able to scan more pages in the same amount of time/work"
  • Redis 场景下配合后续 defer 系列测试,本次先合入 mTHP 基础设施

从代码逻辑推断的预期收益:mTHP 用户首次获得持续的后台折叠能力——既可以在应用运行中把已碎片化的 anon 区折回 16KB/64KB/…/2MB 等任意开启的 order,显著降低 TLB miss 与 page table 占用;bitmap + 栈的 O(N log N) 搜索相比对每个 order 独立扫描 N 次更高效;per-order 统计与 tracepoint 首次让 mTHP 折叠成功率可观测,为后续调参提供数据基础。


2. Remove read-only THP support for FSes without large folio support

系列[PATCH 7.2 v3 00/12] Remove read-only THP support for FSes without large folio support作者: Zi Yan(NVIDIA)版本: v3(12 个 patch)

背景

CONFIG_READ_ONLY_THP_FOR_FS 是 2019 年引入的实验性选项,允许 khugepaged 和 madvise(MADV_COLLAPSE) 为不支持 large folio 的文件系统(当时几乎所有 FS 都不支持)创建只读 PMD THP。为了防止写入一个被折叠成 THP 的只读文件时产生数据损坏,它依赖一套精巧的同步机制:collapse_file() 在折叠前增加 mapping->nr_thps 计数并执行 smp_mb(),随后检查 inode->i_writecount;而 do_dentry_open() 以写模式打开文件时先 get_write_access() 自增 i_writecount、执行全内存屏障,再检测 nr_thps > 0 并截断整个页缓存。近几年 XFS、ext4、btrfs 等主流 FS 已陆续原生支持 large folio(mapping_large_folio_support()),但这条 RO-THP 旧路径仍与新路径并存,形成互斥的两套矩阵:large folio FS 走缺页路径但 khugepaged/MADV_COLLAPSE 不可用,非 large folio FS 反而能走 RO-THP。这种割裂难以维护,也让 pagecache 折叠能力在"现代"FS 上缺失。

解决的问题

  • 支持 large folio 的 FS 无法通过 khugepaged 和 MADV_COLLAPSE 创建 PMD THP(只能依赖缺页路径凑出)
  • CONFIG_READ_ONLY_THP_FOR_FS 蕴含"该 FS 不支持 large folio",两套机制相互排斥且均需 PMD 尺寸的 large folio 支持
  • mapping->nr_thps 与 inode->i_writecount 的跨子系统屏障同步复杂、易错,长期占用 struct address_space 8 字节
  • 非 large folio FS 借 RO-THP 绕路合成 PMD THP,再在 truncate_inode_partial_folio() 里用 try_folio_split_to_order() 强制非均匀拆回 order-0,使拆分路径凭空多出一条分支
  • 不再允许向一个已被折叠为 THP 的文件写入时 invalidate 整个 pagecache 这种"粗暴"行为

如何做

方案的关键洞见在 cover letter 的对比表:移除 READ_ONLY_THP_FOR_FS 后,矩阵从"large folio FS 只能 PF + 不支持 FS 只能 collapse"归一为"large folio FS 三条路径全通、不支持 FS 全不可用"。实施路径分两阶段。

阶段一(patch 1–4)先把 large folio FS 的折叠路径打通,防止移除旧机制时出现功能回退

  • patch 1:collapse_file() 把 VM_BUG_ON(!IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS) && !is_shmem) 替换为新 helper mapping_pmd_thp_support(),该 helper 封装 mapping_max_folio_order(mapping) >= PMD_ORDER,并在 include/linux/pagemap.h 中提供;同时 VM_BUG_ON 降级为 VM_WARN_ON_ONCE

  • patch 2:这是取代旧同步机制的核心。在 collapse_file() 对每个候选 folio 执行 try_to_unmap() 之后、try_to_unmap_flush() 之前,新增 folio_test_dirty() 检查:

    if (!is_shmem && folio_test_dirty(folio)) {
        result = SCAN_PAGE_DIRTY_OR_WRITEBACK;
    goto out_unlock;
    }

    原理是:folio 已被 lock 且 unmap,但某 CPU 可能持有脏 TLB 条目并在此窗口内写入。只要在 TLB flush 之前确认 folio 未被弄脏,之后任何新写都必须先走 page walk 拿 folio lock(已被 khugepaged 持有),从而保证折叠后的 THP 不会与脏页共存。

  • patch 3:file_thp_enabled() 去掉 IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS) 和 !inode_is_open_for_write(inode) 两个条件,改用 mapping_pmd_thp_support()——现在读写打开的文件也能享受 PMD THP 缺页

  • patch 4:hugepage_pmd_enabled() 重构,不再把 READ_ONLY_THP_FOR_FS 做为 true 分支;若全局 THP 开启就允许 file/anon/shmem 三类 khugepaged 运行,否则 anon/shmem 分别回退到 per-size 控制

阶段二(patch 5–12)拆除旧机制及其所有依赖

  • patch 5 删除 CONFIG_READ_ONLY_THP_FOR_FS Kconfig 项
  • patch 6 删除 filemap_nr_thps()filemap_nr_thps_inc/dec(),同时 fs/open.c::do_dentry_open() 中那段在写打开时 invalidate 整个 pagecache 的 27 行魔法块连同 collapse_file() 的 nr_thps 自增/回滚代码一并删除
  • patch 7 从 struct address_space 删除 atomic_t nr_thps 字段(64 位系统上省 8 字节,对大量 inode 缓存的系统有益)
  • patch 8 删除 folio_check_splittable() 中针对 READ_ONLY_THP_FOR_FS 的特判
  • patch 9 在 truncate_inode_partial_folio() 中把 try_folio_split_to_order() 替换为直接 folio_split(folio, min_order, split_at, NULL)——既然大 folio 只会出现在支持 large folio 的 FS 上,就一定允许非均匀拆分;老的 try_folio_split_to_order() 整个函数被删除
  • patch 10 清理 btrfs defrag 注释
  • patch 11、12 更新 selftests(khugepagedguard-regions),新增 read-write 文件折叠测试,去除只读 fd 限制

收益

作者未提供性能 benchmark 数据,但改动本身带来明显收益:

  • struct address_space 缩小 8 字节(作者原话:"This shrinks struct address_space by 8 bytes on 64-bit systems which may increase the number of inodes we can cache")
  • 代码净删除约 73 行(全系列 +156 / -229
  • 功能矩阵统一:所有支持 large folio(含 PMD_ORDER)的 FS 自动获得 khugepaged 和 MADV_COLLAPSE 能力,首次允许读写打开的文件被折叠为 PMD THP
  • 删除 do_dentry_open() 中"写打开即 invalidate 整个 pagecache"的粗暴回收——对大文件只读 → 读写切换的场景避免了缓存冷启动损耗
  • 简化同步语义:用一次 folio_test_dirty() 检查取代跨 fs/mm 子系统的 nr_thps + i_writecount + smp_mb() 三方屏障协议

3. mm: shmem: always support large folios for internal shmem mount

系列[PATCH v3] mm: shmem: always support large folios for internal shmem mount作者: Baolin Wang(Alibaba Cloud)版本: v3(单 patch)

背景

shmem 有两种使用形态:通过 mount -t tmpfs 或 ramfs 等挂载出的 tmpfs 用户挂载点,以及由内核内部(SB_KERNMOUNT 标志)挂起的 internal shmem mount——后者即 anonymous shmem,被 memfd_create()/dev/shm、SysV shm、GPU/DRM 的 shmem helper 等广泛使用。tmpfs 通过 mount -o huge=always/within_size/advise/never 配置是否支持大 folio,值保存在 sbinfo->huge;而 anonymous shmem 还暴露了 /sys/kernel/mm/transparent_hugepage/shmem_enabled 以及 per-order 的 hugepages-*kB/shmem_enabled 两级 sysfs,可运行时动态切换 huge 策略。然而 __shmem_get_inode() 在创建 inode 时只根据静态的 sbinfo->huge 决定是否调用 mapping_set_large_folios()——一旦创建时 sbinfo->huge=0,后续即便用户通过 sysfs 开启了 mTHP order,该 inode 的 AS_LARGE_FOLIO_SUPPORT 标志也不会回写,导致无法分配大 folio。

解决的问题

  • anonymous shmem 的 mapping_set_large_folios() 只在 inode 创建瞬间依据 sbinfo->huge 决定,无法反映 sysfs shmem_enabled 的运行时变化
  • 用户看到 sysfs 配置开启了大 folio 但实际分配仍退化到 order-0,cover letter 链接 [1] 记录了已出现的用户困惑
  • sbinfo->huge 与 per-size sysfs 控制之间语义不一致,形成双重开关

如何做

与 David Hildenbrand 讨论后确定的方案是:对 internal shmem mount 始终设置 mapping_set_large_folios(),具体允许哪些 order 完全由动态 sysfs 接口决定。实现只改动 mm/shmem.c::__shmem_get_inode() 中的一个判断:

-   /* Don't consider 'deny' for emergencies and 'force' for testing */
-   if (sbinfo->huge)
+   if (sbinfo->huge || (sb->s_flags & SB_KERNMOUNT))
        mapping_set_large_folios(inode->i_mapping);

通过 SB_KERNMOUNT 这个 super_block 标志识别"内核内部挂起"的 shmem(与用户 mount -t tmpfs 区分开):对内核内部挂载一律打开 large folio 支持位,这样 mapping 层不再成为限制,真正的 order 过滤交给 shmem_allowable_huge_orders() 这条路径按 shmem_enabled sysfs 动态裁剪;对用户态 tmpfs 则保持旧语义,仍尊重 mount 时的 huge= 选项。v3 相对 v2 的唯一改动就是采纳 David 的建议从"有条件打开"改为"internal mount 无条件打开",将配置权彻底让渡给 sysfs。

收益

作者未提供性能数据。从代码逻辑推断的预期收益:

  • 消除了 anonymous shmem 用户"开了 sysfs shmem_enabled 却分不到大 folio"的语义陷阱
  • memfd、SysV shm、GPU 驱动 shmem 对象等内核内部 shmem 场景在运行时切换 mTHP 配置后立即生效,无需重启
  • 使 shmem 大 folio 的 运行时可配置语义 与 anon mTHP 对齐,统一收敛到 sysfs 单一真源
  • 改动极小(+11 / -2 共 13 行),SB_KERNMOUNT 判定在 inode 创建快路径上开销可忽略

4. mm/page_owner: add filter infrastructure for print_mode and NUMA filtering

系列[PATCH v2 0/3] mm/page_owner: add filter infrastructure for print_mode and NUMA filtering作者: Zhen Ni(EasyStack)版本: v2(3 个 patch)

背景

page_owner 是内核用于追踪每个物理页分配者(调用栈、PID、GFP flags、NUMA 节点等)的核心调试特性,广泛应用于内存泄漏、碎片化和 OOM 问题的诊断。当用户 cat /sys/kernel/debug/page_owner 时,内核会遍历所有在线页帧,并对每一页通过 stack_depot_snprint() 打印完整的调用栈字符串。在大内存(250 GB+)生产环境中,单次转储的文件体积通常在几 GB 到 10 GB 以上。同时,在 NUMA 感知的部署场景(如 DPDK 云环境中 QEMU 进程绑定到指定节点),OOM 通常是节点局部事件,却必须收集全节点数据后再用 tools/mm/page_owner_sort.c 在用户态做合并与过滤。现有接口缺少任何服务端过滤能力,把所有选择工作都推给了离线后处理。

解决的问题

  • 生产机上 page_owner 输出动辄 GB 级,占用本地存储并使跨机传输困难
  • 调用栈在内核 stackdepot 中早已去重,却在打印时被展开为完整文本,用户态又得重新去重,做了双倍功
  • 无法按 NUMA 节点过滤:排查单节点 OOM 时必须拉全部节点的数据
  • v1 采用 bool compact 和单节点 int 两种过于粗糙的控制语义,社区反馈后需要更具描述性和扩展性的接口

如何做

patch 1 在 mm/page_owner.c 引入 filter 基础设施:新增 enum page_owner_print_modePAGE_OWNER_PRINT_FULL_STACK / PAGE_OWNER_PRINT_STACK_HANDLE),定义 struct page_owner_filter { enum print_mode; nodemask_t nid_mask; } 的静态实例 owner_filter,并在 pageowner_init() 中创建 /sys/kernel/debug/page_owner_filter/ 目录承载各过滤器旋钮。

patch 2 在 print_page_owner() 的打印路径把原本无条件的 stack_depot_snprint(handle, ...) 改为按 READ_ONCE(owner_filter.print_mode) 分支:handle 模式下只写一行 handle: %d,其余字段(order、gfp mask、pid、tgid、comm、PFN、migratetype、flags、memcg 等)保持不变。handle 到真实栈的映射通过已有的 page_owner_stacks/show_stacks_handles 接口查询,实现了"分取数据 + 分取字典"的拆分存储。旋钮通过 DEFINE_SIMPLE_ATTRIBUTE(page_owner_print_mode_fops, ...) 注册为可读写的 debugfs 文件。

patch 3 加入 NUMA 节点过滤器 nid:写路径 nid_filter_write() 使用动态 kmalloc,输入长度上限沿用 cpuset 的 (100 + 6 * MAX_NUMNODES) 模式,支持 "-1" 清空以及 "0""0,2,3""0-3""0,2-4,7" 等 nodelist 格式,核心解析复用内核已有的 nodelist_parse();读路径则用 %*pbl 紧凑打印 nodemask(如 0-2 或 0,2-4,7)。过滤动作下沉到 read_page_owner() 的遍历循环中:对每个候选页 READ_ONCE(owner_filter.nid_mask),若 mask 非空则 node_isset(page_to_nid(page), mask) 不满足就 goto ext_put_continue 跳过。READ_ONCE/WRITE_ONCE 保证用户态修改旋钮和内核态读取之间的无锁并发安全。

收益

作者未给出压测数字,但从实现逻辑可直接推断:开启 print_mode=1 后每条记录由若干行调用栈缩成一行 handle: N,对典型深度 8-16 帧的分配栈意味着输出体积降至原先的 1/5 到 1/10,10 GB 级 dump 可压缩到 1-2 GB 量级;而调用栈信息并未丢失,show_stacks_handles 仍可按需反查。NUMA 过滤则把遍历开销(仍需扫全内存)和 I/O 开销(仅写目标节点)解耦,单节点 OOM 分析时输出和传输成本按节点数近似线性下降。封面信把该基础设施描述为"可扩展的 filter 框架",明确规划了未来的 PID/TGID、时间窗、GFP 标志、迁移类型等过滤维度,本次改动因此不仅是两个新旋钮,更是一个面向生产诊断的长期接口底座。整个系列 mm/page_owner.c 仅 +122/-2 行,侵入面非常有限。


5. mm/swap: use swap_ops to register swap device's methods

系列[PATCH v4 0/3] mm/swap: use swap_ops to register swap device's methods作者: Baoquan He(Red Hat)版本: v4(3 个 patch)

背景

Linux swap 子系统当前支持三类 swap 后端:基于文件系统的 SWP_FS_OPS(走 ->swap_rw 回调,例如 nfs/tmpfs-on-btrfs 等)、基于块设备的同步 I/O SWP_SYNCHRONOUS_IO(典型场景是 zram、pmem 这类可直接完成的快速设备),以及普通的异步块设备 swap。历史上这三种路径都集中在 mm/page_io.c__swap_writepage() 与 swap_read_folio() 内部通过一连串 if (sis->flags & SWP_FS_OPS) ... else if (SWP_SYNCHRONOUS_IO) ... else ... 的分支分派到 swap_writepage_fs/bdev_sync/bdev_async 以及对应的 swap_read_folio_fs/bdev_sync/bdev_async。与此同时,mm/page_io.c 这个沿用自 1991 年的文件名容易让人误以为是通用 page I/O,实际上它已经演化为纯粹的 swap I/O 实现。

解决的问题

  • 读、写路径各自重复同一套 flags 分支判定,三种设备类型再扩展时需要同时修改读、写两条 if/else 链,维护和扩展成本高。
  • 分派逻辑与 data_race() 注释散落在两处,新增 swap 后端类型(例如未来可能的 zswap 直通、swap-over-RDMA、swap_activate 等扩展回调)时没有统一入口可插桩。
  • 文件名 mm/page_io.c 与其实际内容(纯 swap I/O)不匹配,MAINTAINERS、include 注释、git 历史都在 swap 上下文里引用它,容易造成混淆。
  • 函数命名 swap_writepage_* 仍残留早期 page 语义,而参数和实现已经是 folio,与对端 swap_read_folio_* 风格不对称。

如何做

整套改动分三个递进步骤:

  1. 文件与命名归位(patch 1/3):将 mm/page_io.c 重命名为 mm/swap_io.c,同步更新 mm/Makefilemm/swap.h 注释、MAINTAINERS 中对应的 F: 条目;patch 3/3 进一步把 swap_writepage_fs/bdev_sync/bdev_async 改名为 swap_write_folio_fs/bdev_sync/bdev_async,与 swap_read_folio_* 形成对称命名。
  2. 引入 swap_ops vtable(patch 2/3):在 mm/swap.h 定义抽象操作集:
    structswap_ops {
    void (*read_folio)(struct swap_info_struct *sis,
                           struct folio *folio, struct swap_iocb **plug);
    void (*write_folio)(struct swap_info_struct *sis,
                            struct folio *folio, struct swap_iocb **plug);
    };
    在 struct swap_info_struct 新增 const struct swap_ops *ops 字段;把原先的三对分派函数改为实例化三个 const 静态 vtable:bdev_fs_swap_opsbdev_sync_swap_opsbdev_async_swap_ops
  3. 集中初始化:新增 init_swap_ops(),在 SYSCALL_DEFINE2(swapon, ...) 中 setup_swap_extents() 之前调用,一次性依据 SWP_FS_OPS / SWP_SYNCHRONOUS_IO 标志挑选 vtable,若 sis->ops 或其 read_folio/write_folio 为空则直接让 swapon 失败返回 -EINVAL(此 NULL 校验是 v3 采纳 Chris Li 的建议后加入)。I/O 热路径从此只剩一行 sis->ops->read_folio(sis, folio, plug) 与 sis->ops->write_folio(...),原来的 __swap_writepage() 被彻底删除,zswap 的 writeback 路径 (zswap_writeback_entry) 也改为调用 si->ops->write_folio(),三条 I/O 判定分支一次性归并到 swapon 时刻。

收益

作者未提供性能基准数据(这是一次结构性清理,不涉及热路径行为变化)。从代码逻辑可推断的收益:

  • 热路径的 data_race(sis->flags & SWP_FS_OPS) 与 SWP_SYNCHRONOUS_IO 分支被消除,每次 swap-in/swap-out 少两次原子性无保证的标志检查,替换为一次间接调用;由于 vtable 在 swapon 时绑定且 const,分支预测和 I-cache 行为更稳定。
  • 后续添加新 swap 后端(例如 Chris Li 在 v3 评审中提到的未来 swap_activate 回调、或第三方快速存储如 CXL.mem、RDMA swap)时只需新增一个 swap_ops 实例并扩展 init_swap_ops() 的分支,无需再改动 I/O 热路径。
  • 文件重命名使 MAINTAINERS 路径语义清晰(mm/swap_io.c 与已有的 mm/swap.cmm/swap_state.cmm/swap_table.h 成系列),函数改名消除了 page/folio 术语不一致,降低新贡献者理解门槛。该系列已被 Kairui Song、Chris Li、Nhat Pham、Barry Song、Usama 等核心 swap 维护者 Reviewed-by / Acked-by,v4 主要是修正 v3 中 init_swap_ops() 的一个未实测的 code bug 与拼写。

6. rust: Add helper functions and constants for Tyr driver

系列[PATCH 0/4] rust: Add helper functions and constants for Tyr driver作者: Alvin Sun版本: v1(4 个 patch)

背景

Tyr 是正在上游化的 Arm Mali CSF(Command Stream Frontend)系列 GPU 的 Rust 版 DRM 驱动(对标现有 C 实现 Panthor),目标是作为 Rust-for-Linux 在大型 DRM 驱动上的首批落地之一。Tyr 的 VM/BO(virtual memory / buffer object)ioctl 在上游 merge request(gitlab.freedesktop.org/panfrost/linux MR 64)中进入实现阶段后,发现 Rust kernel crate 里缺若干基础砖:没有 SZ_4G 常量、Mm 抽象没有暴露 task_sizeXArray 的 Guard 缺少「找到第一个已占用索引」的辅助接口,同时 StoreError 的文档没有同步即将引入的 alloc() 语义。这些缺失都是阻塞 Tyr 驱动继续合入的「前置依赖」。

解决的问题

  • GPU 用户 VA 空间布局计算(VmLayout)需要以 4 GiB 为粒度做对齐,而 rust/kernel/sizes.rs 目前只停在 SZ_2G
  • 当 Tyr 驱动接受 VmUserSize::Auto 时需要查询当前进程的 task size(即 mm_struct.task_size)以决定用户 VA 范围的上界,但 Rust 的 Mm 抽象未开放此字段。
  • Tyr 在释放 VM 对象时需要遍历 XArray 清理遗留条目,而 Guard 当前只有 store/remove 类基本操作,没有「首个 present 索引」查询,C 侧对应的是 xa_find(..., XA_PRESENT)
  • Onur Özkan 的 xa_alloc 前置系列会让 StoreError 同时用于 store 与 alloc 两条路径,原 doc 只提 store,容易误导。

如何做

四个 patch 都是小而精确的 Rust 绑定补齐,无 behavior change:

  1. SZ_4G 常量rust/kernel/sizes.rs):直接 pub const SZ_4G: usize = SZ_2G * 2;(沿用本文件既有风格:SZ_1G/SZ_2G 来自 bindings::SZ_*,但 C 侧没导出 SZ_4G,故以 SZ_2G * 2 实现,注释值 0x100000000)。
  2. **Mm::task_size()**(rust/kernel/mm.rs):
    #[inline]
    pubfntask_size(&self) -> u64 {
    // SAFETY: self.as_raw() is a valid pointer to an mm_struct.
    unsafe { (*self.as_raw()).__bindgen_anon_1.task_size asu64 }
    }
    注意读取的是 mm_struct 内匿名 union(__bindgen_anon_1)里的 task_size 字段;SAFETY 注释沿袭 Mm 类型不变式。
  3. StoreError 文档同步rust/kernel/xarray.rs):把 rustdoc 中 store 的单点引用改为 [Guard::store] 与 [Guard::alloc] 并列,并在两个字段注释里补上 "or allocated" 语义,为 Onur 的 alloc() 合入做铺垫。
  4. **Guard::find()**(rust/kernel/xarray.rs):新增返回 Option<usize> 的 helper,内部调用 bindings::xa_find(self.xa.xa.get(), &mut index, usize::MAX, bindings::XA_PRESENT)index 初值 0,命中返回 Some(index)、空数组返回 None。因为方法接收 &mut self,与 Guard 的锁契约一致,SAFETY 注释强调「类型不变式保证 xa 有效且持锁」。

收益

作者未提供性能数据,本系列是典型的「enablement」型补丁,收益以解除下游阻塞为主:

  • 解除 Tyr 驱动合入阻塞:四项前置砖齐备后,Tyr 的 VM/BO ioctl 补丁(MR 64)就可以直接基于 Mm::task_size()SZ_4GGuard::find() 编写 safe-by-default 的 Rust 实现,而不必再在驱动里手写 bindgen 字段访问或临时 helper。
  • 扩大 Rust 通用 crate 的覆盖:新增的三项 API(SZ_4GMm::task_sizeGuard::find)对后续其他 Rust-for-Linux 驱动同样可复用,尤其 Guard::find 填补了 XArray 遍历语义的缺口,使 Rust 侧的 XArray 用法更接近 C 侧 xa_find(..., XA_PRESENT) 的能力。
  • 文档一致性StoreError 注释的前瞻性更新避免了 Onur 的 xa_alloc 系列合入后出现文档与 API 不一致的过渡窗口,降低评审 churn。
  • 风险面小:所有改动要么是 const、要么是薄 wrapper,SAFETY 注释清晰;改动行数极少(rust/kernel/mm.rs +7、rust/kernel/sizes.rs +2、rust/kernel/xarray.rs +25/-3),易于 review 与后续维护。

7. make MM selftests more CI friendly

系列[PATCH v2 00/53] make MM selftests more CI friendly作者: Mike Rapoport(Microsoft)版本: v2(53 个 patch)

背景

tools/testing/selftests/mm/ 下的 HugeTLB 相关测试多年来分别由不同作者提交,彼此约定不一:有的要求"若干默认大页",有的硬编码"至少 256 MB 大页",有的在缺失任一大小的大页时直接跳过一整组用例。驱动层的 run_vmtests.sh 因此积累了近 130 行用于扫描 /proc/meminfo、调整 /proc/sys/vm/nr_hugepages、保存恢复 shmmax/shmall、遍历 /sys/kernel/mm/hugepages/**/nr_hugepages 的脚本代码,逻辑割裂且难以维护。与此同时,大量 HugeTLB 与 THP 测试没有使用 kselftest 框架,输出不是 TAP13 格式,对 CI 系统不友好:结果解析困难、失败定位粗糙、无法与其他 kselftest 汇总。

解决的问题

  • run_vmtests.sh 承担了过多"大页管理员"职责,与具体测试的需求高度耦合但又不够精确——例如 uffd-wp-mremap 需要每种 hugepage size 至少 1 个,脚本里用一段 bash 循环逐个 /sys/kernel/mm/hugepages/*-kB/nr_hugepages 写 1 并在 trap 里恢复
  • 多个测试硬编码 TWOMEG 作为 THP 和 HugeTLB 页大小,在 ARM64 64 KB PAGE_SIZE(PMD 512 MB)或 ppc64le 16 MB 巨页的机器上直接错误
  • HugeTLB 的 hugetlb-shmhugetlb-vmemmaphugetlb-madvisehugetlb_madv_vs_maphugetlb-read-hwpoison 以及 khugepagedksm_testsprotection_keysuffd-stressuffd-unit-testsva_high_addr_switch 等都没接 kselftest harness
  • hugetlb-read-hwpoison 读到中毒页触发 SIGBUS 后直接被信号终止,CI 中表现为崩溃而非受控 fail
  • run_vmtests.sh 里 THP 和 KSM 测试被错误地用 HAVE_HUGEPAGES 门控
  • hugepage-* 命名与 hugetlb-* 命名混用,map_hugetlb 与 hugepage-mmap 功能重复

如何做

系列按 6 段有序推进:

  1. Patch 1-4(小修):为 hugetlb-read-hwpoison 装上 dummy SIGBUS handler(signal(SIGBUS, sigbus_handler),handler 只打印 "received SIGBUS\n")避免 CI 被信号杀死;让 khugepaged 的 collapse_single_pte_entry_compound 对 tmpfs 改用 MADV_REMOVE(原本因 MADV_DONTNEED 不能驱逐 tmpfs 页而 skip);migration.c 用 read_pmd_pagesize() / default_huge_page_size() 动态检测 pmd 大小替换 TWOMEG;解绑 THP/KSM 与 HAVE_HUGEPAGES
  2. Patch 5-19(机械改造):合并 map_hugetlb.c 进 hugepage-mmap.c 并统一改名 hugetlb-*;将 10+ 个 HugeTLB/THP/KSM/pkey/uffd/va_high 测试改写为 kselftest 框架(TAP13 输出、ksft_test_result_pass/fail、exit code 规范化)。
  3. Patch 20-26(API 扩展):把 thp_settings.[ch] 重命名为 hugepage_settings.[ch];在其中并入 HugeTLB 帮助函数——detect_hugetlb_page_size() 返回 unsigned long、新增 get_nr_hugepages() / set_nr_hugepages()get_free_hugepages() 改名、hugetlb_setup() 和 hugetlb_teardown() 一对 API 封装"按需申请并在退出时还原"的完整流程;另外在 thp_settings 基础上加入 atexit() + 信号 handler,保证测试异常退出时 THP/HugeTLB 旋钮被还原。
  4. Patch 27-28(基础设施):把 read_file() / read_num() / write_num() 从 thp_settings 挪到通用 vm_util;加入 shm_save() / shm_restore() 帮助函数供 hugetlb-shm 和 thuge-gen 调用。
  5. Patch 29-51(整合 API):让每个用到 HugeTLB 的测试(compaction_testcowgup_longtermgup_testhmm-testshugepage_diohugetlb_fault_after_madvhugetlb-madvisehugetlb_madv_vs_maphugetlb-mmaphugetlb-mremaphugetlb-shmhugetlb-soft-onlinehugetlb-vmemmapmigrationpagemap_ioctlprotection_keysthuge-genuffd-stressuffd-unit-testsuffd-wp-mremapva_high_addr_switch 等)在 main() 或 setup() 里自行 hugetlb_setup(),退出前 hugetlb_teardown()
  6. Patch 52-53(脚本瘦身):从 run_vmtests.sh 里彻底删除近 130 行 /proc/meminfo 扫描、uffd_min_KB 计算、nr_hugepages 试错、shmmax/shmall 保存、/sys/kernel/mm/hugepages/** 循环等代码;uffd-stress hugetlb 的参数由"动态计算的 half-free"改成固定 128 MB(测试自行申请);run_vmtests.sh 最终大幅瘦身,回归"调度器"本分。

收益

作者未提供性能数据,但从架构改动可以直接列出收益:

  • 驱动脚本 run_vmtests.sh 一次删除 128 行纯环境管理代码(patch 53 diff 为 +9/-119),维护复杂度显著下降
  • 每个 HugeTLB 测试现在都是自洽的:无论直接 ./hugetlb-mmap 还是在 CI 中被调度,setup/teardown 行为一致,不再依赖 run_vmtests.sh 预先准备环境——这对 CI 调度器(可并行分发单个测试)是关键先决条件
  • 全系列总 diff 为 +1376 / -1475 行,净减约 100 行,外加 42 个文件触及并完成 kselftest TAP13 化,CI 解析首次具备一致性
  • 消除了 TWOMEG 硬编码、MADV_DONTNEED 对 tmpfs 失效的错误 skip、SIGBUS 杀测试、HAVE_HUGEPAGES 误门控 THP/KSM 等四类长期问题

封面信把目标概括为"使测试自行处理 HugeTLB 的 setup 和 teardown",v2 相较 v1 的变更记录(修复 hugetlb mmap 测试实际覆盖文件映射、提高 khugepaged 最大测试数量、加入审阅 tag)显示系列已进入收敛阶段,作者在封面信中表态"可进入 mm-new 等待更多 review 反馈",预示近期合入。


8. mm/mglru: Use folio_mark_accessed to replace folio_set_active in PF

系列[PATCH] mm/mglru: Use folio_mark_accessed to replace folio_set_active in PF作者: Barry Song(Xiaomi)版本: v1(1 个 patch)

背景

MGLRU(Multi-Generational LRU)通过多代 LRU 替代传统 active/inactive 双队列,为页表映射页提供了更精细的老化模型。在缺页路径上,folio_add_lru() 对所有带 lru_gen_in_fault() 标记的新 folio 调用 folio_set_active(),从而把它们直接放进最年轻的代以获得最高保护等级。该设计假设只要页在缺页时被建立 PTE 映射,就是真正的工作集。commit 4d5d14a01e2c "mm/mglru: rework workingset protection" 之后,PG_active folio 改放到次年轻代,稍稍降低了过度保护,但在有 readahead 的场景下仍然过于乐观。

解决的问题

  • Readahead(尤其是 mmap 文件的 fault-around 和文件顺序预读)会把大量并未被实际访问的页加入 LRU;MGLRU 把这些"预取但未用"的页当成热页,推挤出真正的工作集
  • folio_set_active() 无条件置 PG_active,相比经典 LRU 的"二次机会"更激进,与 readahead 的存在性冲突
  • 之前 Lei Liu 尝试引入专用 readahead LRU,但该方案被视为过度工程化
  • arm64 在 commit 315d09bf30c2 之后需要依赖 arch_wants_old_prefaulted_pte() 让 fault-around PTE 初始为 old,以便硬件 AF 驱动 active 迁移;x86 因 10 年前的 UnixBench ~6% 回退将该机制关闭,但这只影响 x86 本次优化的收益面

如何做

改动极简——mm/swap.c:folio_add_lru() 中 MGLRU 缺页分支把 folio_set_active(folio) 替换为 folio_mark_accessed(folio),仅 1 行:

if (lru_gen_enabled() && !folio_test_unevictable(folio) &&
    lru_gen_in_fault() && !(current->flags & PF_MEMALLOC))
-    folio_set_active(folio);
+    folio_mark_accessed(folio);

语义差别在于:folio_set_active() 无条件给最高保护;folio_mark_accessed() 只在 folio 之前已被引用过时才提升代,否则只设 PG_referenced。这样 readahead 进来的、且在随后回收扫描 folio_check_references() 前从未被 PTE 真正触碰的 folio 不会被无谓保护;而真正被 CPU 访问的 folio 会通过硬件 access flag(arm64)把 PTE 从 old 翻成 young,folio_check_references() 在扫描时识别 young PTE 并把 folio 提升代数。作者坦率说明:这条路径的收益目前仅对 arm64 显著,因为 arch_wants_old_prefaulted_pte() 在 arm64 打开,x86 如果要复用需要在 arch/x86/include/asm/pgtable.h 打开同名 hook,但 10 年前报告的 x86 HW AF 成本是否还成立值得重新评估。

收益

作者提供了完整、可复现的 fio 压测脚本:400 MB memcg 限额内,用 fio 3.42 以 --zonemode=strided --zonesize=4K --zonerange=64K 对 600 MB 文件做"每 64 KB 读 4 KB"的稀疏访问,模拟大量被 fault-around 带入但从不访问的 PTE。

指标
无 patch
有 patch
File refault delta(60 秒窗口)
12,883,855
0
读带宽
58.5 MiB/s
5,078 MiB/s

refault 降到 0、带宽约 87 倍提升,直接验证了预期的因果链:不再把预取未访问页固定在年轻代 → 真实工作集不被错误驱逐 → 工作集命中率回到正常水平。作者明确致谢 Lance Yang 和 Xueyuan Chen 提供了测试,并借机呼吁 x86 社区基于现代微架构重新评估 HW AF 的成本——这条"顺带讨论"本身也让该 1 行 patch 成为 mm/mglru 的一个策略性改动。


9. mm/damon/modules: detect and use fresh status

系列[PATCH v3 0/3] mm/damon/modules: detect and use fresh status作者: SeongJae Park版本: v3(3 个 patch)

背景

DAMON 的三个模块化前端——DAMON_RECLAIM(主动回收冷页)、DAMON_LRU_SORT(LRU 链表排序)、DAMON_STAT(数据访问统计)——都通过 module_param 的 enabled 和 kdamond_pid 参数对外暴露自己的 kdamond 工作线程运行状态。长期以来,这些参数值都是"缓存式"维护:只有当用户显式向 enabled 写入 Y/N 触发 damon_{reclaim,lru_sort}_turn() 或 damon_stat_{start,stop}() 成功时才更新缓存。问题是 kdamond 还会因其他事件被"隐式"停止,这种状态转换路径无法在写入者侧被捕获。

解决的问题

  • 状态参数返回陈旧值:kdamond 实际已退出,但 cat enabled 仍显示 Ycat kdamond_pid 仍显示已不存在的 PID,用户被误导。
  • DAMON_RECLAIM / DAMON_LRU_SORT 无法在系统重启前重新启动 kdamond:因为两者都根据缓存的 enabled 值做幂等判定——既然缓存认为已启用,再次写 Y 就被提前 return 0,真正的 damon_start() 永远得不到执行。Cover letter 给出了可复现路径:echo Y > enabled(启动)→ echo 3 > addr_unit; echo Y > commit_inputs(用非法输入触发 damon_commit_ctx() 失败,kdamond 自行退出)→ 之后即便修正参数、再次 echo Y > enabled 也无法拉起 kdamond。
  • 触发隐式停止的三类事件:①ctx->regions_score_histogram 在 kdamond 初始化阶段分配失败;②damon_commit_ctx() 因用户输入非法而失败;③damon_commit_ctx() 自身的内部分配失败。DAMON_STAT 只受第①类影响,但因为它对 enabled 是"强制更新"语义,尚可重启,仅有显示陈旧的问题。
  • 对应的 Fixes 标签与稳定版回溯:分别回溯到 e035c280f6df(5.19.x,DAMON_RECLAIM 支持在线输入更新时引入)、40e983cca927(6.0.x,DAMON_LRU_SORT 首次引入)、369c415e6073(6.17.x,DAMON_STAT 模块引入)。

如何做

该系列摒弃了 v2 之前"在每个停止路径上同步更新缓存变量"的思路——作者自评为"跟踪所有事件是困难的"——改为"按需探测真实状态"(detect and use fresh status on demand)。核心实现是把 module_param 的 .get 回调从通用的 param_get_bool / 直接读变量替换成自定义的 load 回调,在回调里直接查询 DAMON 核心 API:

  • 新增静态 helper damon_reclaim_enabled() / damon_lru_sort_enabled() / damon_stat_enabled(),内部判断 ctx 非空后调用 damon_is_running(ctx)(声明于 include/linux/damon.h:989)。
  • 新增 *_enabled_load() 以 damon_is_running() 的实时结果打印 Y 或 N;在 DAMON_RECLAIM/LRU_SORT 里还新增 *_kdamond_pid_load(),调用 damon_kdamond_pid(ctx) 实时返回 PID,取值 <0 归一为 -1
  • store 侧相应简化:enabled_store 把 damon_reclaim_turn()/damon_lru_sort_turn() 中 kdamond_pid = damon_kdamond_pid(ctx) 与 kdamond_pid = -1 的手工同步全部删除;damon_{reclaim,lru_sort}_enabled_store() 的幂等判定也从 is_enabled == enable 改为 damon_{reclaim,lru_sort}_enabled() == enabled,这样一旦 kdamond 已隐式退出,写入 Y 就能真正进入 turn(true) 路径并拉起新 kdamond。
  • 由于 kdamond_pid 原先是 0400(只读)的纯变量参数,改为 module_param_cb 后需要提供 .set 回调——作者增加了空实现 *_kdamond_pid_store() 以容忍内核命令行可能的写入,避免 boot 阶段报错。
  • DAMON_STAT 因为原本就"强制更新",简化幅度较小:仅需补一个 damon_stat_enabled_load(),并把 enabled_store 里 err 后回滚 enabled = false 的分支去掉。

v3 相对 v2 的关键演进如封面 changelog 所述:v2 仍是尝试在所有失败路径上补齐状态同步,包括 damon_{lru_sort,reclaim}_turn() 的 N 路径 fallback、apply_parameters() 失败时重置 enabled/kdamond_pid 等;v3 彻底改为"按需探测"的思路,代码净增量从 v2 的 +104/−52 扩大到 +130/−70,但消除了补丁作者和复审者都认为脆弱的"事件追赶"逻辑。

收益

作者未提供 benchmark 数据(这是功能正确性修复,不涉及性能),但给出明确的行为收益:

  • cat enabled 与 cat kdamond_pid 永远反映 kdamond 真实运行状态,不再因为三类隐式停止事件而陈旧
  • DAMON_RECLAIM/LRU_SORT 在隐式停止后可通过 echo Y > enabled 正常重启,无需系统重启
  • 将"多处事件同步一个缓存"重构为"单点按需查询核心 API",大幅降低后续维护成本——未来再有新的 kdamond 退出路径(如新的 commit 校验失败场景)也不需要每个模块重复打补丁
  • 三个 patch 均带 Cc: stable@vger.kernel.org 分别回溯至 5.19.x / 6.0.x / 6.17.x 全部受影响的长期支持分支

10. mm: prepare anon_vma before swapin rmap

系列[PATCH] mm: prepare anon_vma before swapin rmap作者: ZhengYuan Huang版本: v1(单 patch)

背景

自 commit a373baed5a9d("mm: delay the check for a NULL anon_vma")将 anon_vma 的按需准备从通用 fault 路径下沉到各个具体的 fault handler 之后,所有会向 VMA 安装匿名 rmap 状态的 handler 都必须自行调用 vmf_anon_prepare()mm/memory.c 中 do_anonymous_page()(line 3854)和 do_cow_fault()(line 5372)都已正确调用,wp_page_copy() 路径(line 5913)也做了处理。唯独 do_swap_page() 被遗漏——虽然它最终会调用 folio_add_new_anon_rmap() 或 folio_add_anon_rmap_ptes() 把换入的页重新建立匿名映射,却从未先调用 vmf_anon_prepare() 确保 vma->anon_vma 非空。

解决的问题

  • VMA-lock 快路径下的内核 BUG:当缺页以 FAULT_FLAG_VMA_LOCK 方式进入 do_swap_page(),而此 VMA 从未挂过匿名页(vma->anon_vma == NULL),一路调到 __folio_set_anon() 就会命中 mm/rmap.c:1468 的 BUG_ON(!anon_vma)(以及 line 1445 的 VM_BUG_ON_VMA(!anon_vma, vma)),触发 invalid opcode 并让内核宕机。
  • 可触发场景madvise(MADV_HWPOISON) 经 madvise_inject_error() → get_user_pages_fast() → gup_fast_fallback() → __get_user_pages() → faultin_page() → handle_mm_fault() 把一个交换条目再 fault 回来,在 6.18 上可以确定性复现(作者原话:"I can reproduce this issue deterministically on v6.18")。关键调用栈:
    • do_swap_page+0x14c5 → handle_pte_fault/__handle_mm_fault
    • gup_fast_fallback+0x8a3 → get_user_pages_fast
    • madvise_inject_error → madvise_do_behavior → __x64_sys_madvise
  • 回归根因Fixes: a373baed5a9d ("mm: delay the check for a NULL anon_vma") 漏补 swap 路径。作者坦言在 next-20260415 上无法复现,但代码审查表明"do_swap_page() 仍然可以不经 vmf_anon_prepare() 就到达 folio_add_new_anon_rmap()/folio_add_anon_rmap_ptes(),而 __folio_set_anon() 仍会在 vma->anon_vma 为 NULL 时 BUG_ON",属于潜在仍存在的 race。

如何做

补丁在 mm/memory.c 的 do_swap_page() 中,确认 PTE 指向一个真正的 swap entry、且处理完 device-private migrate/hwpoison/marker 等非 swap 分支之后(即 line 4850 附近的 goto out 之后),在获取 swap_device 之前插入 5 行:

/* Swapin installs anonymous rmap state into the faulting VMA. */
ret = vmf_anon_prepare(vmf);
if (ret)
goto out;

vmf_anon_prepare() 已经内置了 VMA-lock 下的重试规则(__vmf_anon_prepare()mm/memory.c:3802):若 vma->anon_vma 已存在直接 likely 返回 0;若当前仅持 per-VMA lock,它会尝试 mmap_read_trylock(),失败则返回 VM_FAULT_RETRY 让上层降级到持 mmap_lock 重放,从而既不破坏 VMA-lock 快路径,又能在需要时安全访问相邻 VMA 以合并 anon_vma。作者强调 "when anon_vma is already present this stays a single likely branch in the swap fault hot path"——对 swapin 热路径只多一次 branch 判断。位置选择在 hwpoison/device-private/marker 等特殊 entry 的 goto out 之后,避免给这些非匿名映射路径做无意义的准备工作。

收益

作者未提供量化性能数据(这是一个崩溃修复),但给出具体的正确性收益:

  • 消除 madvise(MADV_HWPOISON) 与 gup_fast_fallback 组合下确定性触发的内核 BUG,保护内核免于 invalid opcode 宕机
  • 补齐 a373baed5a9d 引入的类型不变式缺口——让所有安装匿名 rmap 状态的 fault handler 统一遵守"先 vmf_anon_prepare() 后建 rmap"的契约,与 do_anonymous_page() / do_cow_fault() / wp_page_copy() 的处理保持一致
  • 对已持有 anon_vma 的常见 swap 命中路径仅新增一次 likely(vma->anon_vma) 快速返回,对 swapin 吞吐影响可以忽略
  • 带 Fixes: 标签方便 stable 维护者回溯至所有继承 delay-NULL-anon_vma-check 行为的内核版本

总结

新机制 / 新接口

#
系列
要点
1
khugepaged mTHP support
 [v16, 13p]
khugepaged 首次支持后台折叠 mTHP,bitmap+栈的 O(N log N) 搜索,新增 per-order stats/tracepoint
2
Remove RO-THP for non-large-folio FSes
 [v3, 12p]
删除 CONFIG_READ_ONLY_THP_FOR_FS,所有 large folio FS 获得 khugepaged/MADV_COLLAPSE 能力,address_space 缩 8 字节
3
shmem large folio for internal mount
 [v3, 1p]
internal shmem mount 一律 mapping_set_large_folios(),order 完全交给 sysfs 动态裁剪
4
page_owner filter infrastructure
 [v2, 3p]
debugfs 新增 print_mode(stack handle 替代完整栈)与 NUMA nid 过滤,可扩展 filter 框架
5
swap_ops vtable
 [v4, 3p]
引入 struct swap_ops 替代 SWP_FS_OPS/SWP_SYNCHRONOUS_IO if/else,page_io.c 改名 swap_io.c
6
rust helpers for Tyr driver
 [v1, 4p]
补齐 SZ_4GMm::task_sizeGuard::find,解除 Rust DRM 驱动 Tyr 合入前置依赖
7
MM selftests CI friendly
 [v2, 53p]
所有 HugeTLB 测试自行 setup/teardown,kselftest TAP13 化 42 个文件,run_vmtests.sh 删 128 行

性能优化

#
系列
量化数据
8
mglru folio_mark_accessed in PF
 [v1, 1p]
fio 稀疏访问(400MB memcg):refault 12,883,855 → 0;读带宽 58.5 → 5,078 MiB/s(约 87x)

Bug Fix

#
系列
影响
9
damon/modules fresh status
 [v3, 3p]
DAMON_RECLAIM/LRU_SORT 隐式停止后可正常重启,enabled/kdamond_pid 永远反映实际状态。Fixes: e035c280f6df(5.19)、40e983cca927(6.0)、369c415e6073(6.17),Cc stable
10
anon_vma before swapin rmap
 [v1, 1p]
修复 MADV_HWPOISON + gup_fast_fallback 在 VMA-lock 快路径下确定性触发 rmap.c:1468 BUG_ON(!anon_vma) 内核宕机。Fixes: a373baed5a9d

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-04 09:35:41 HTTP/2.0 GET : https://f.mffb.com.cn/a/488035.html
  2. 运行时间 : 0.198929s [ 吞吐率:5.03req/s ] 内存消耗:4,744.76kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=13113b0badb46c0c6a442a9c5acad330
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.001049s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001747s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000825s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000678s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001376s ]
  6. SELECT * FROM `set` [ RunTime:0.004564s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001687s ]
  8. SELECT * FROM `article` WHERE `id` = 488035 LIMIT 1 [ RunTime:0.002103s ]
  9. UPDATE `article` SET `lasttime` = 1783128941 WHERE `id` = 488035 [ RunTime:0.002841s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.000657s ]
  11. SELECT * FROM `article` WHERE `id` < 488035 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.004674s ]
  12. SELECT * FROM `article` WHERE `id` > 488035 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.002023s ]
  13. SELECT * FROM `article` WHERE `id` < 488035 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.002879s ]
  14. SELECT * FROM `article` WHERE `id` < 488035 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.002369s ]
  15. SELECT * FROM `article` WHERE `id` < 488035 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.017035s ]
0.203071s