背景

GUP-fast 路径对每个 folio 过 gup_fast_folio_allowed() 安检:secretmem 页不许 pin,long-term writable pin(reject_file_backed)不许碰文件页。

此前 secretmem 检查并入这道安检后,folio->mapping 为 NULL 的 order-0 folio 一律回退慢路径。这个 NULL 判断的本意是防被截断的文件页(mapping 被清掉了,无法确认是否安全),属于 reject_file_backed 的考虑,与 secretmem 无关。

NULL mapping 一律回退殃及驱动页
┌─────────────────────────────────────────┐
│ gup_fast_folio_allowed() 安检每个 folio │
└────────────────────┬────────────────────┘
                     ▼
┌─────────────────────────────────────────┐
│       NULL mapping 一律回退慢路径       │
└────────────────────┬────────────────────┘
                     ▼
┌─────────────────────────────────────────┐
│    驱动页 mapping 本就 NULL,被殃及     │
└─────────────────────────────────────────┘

问题

  • NULL mapping 的 order-0 folio 一律回退 GUP 慢路径
  • alloc_page() 加 vm_insert_page() 的驱动页 mapping 本来就 NULL,被殃及
  • secretmem 页必然挂在 secretmem inode 的 page cache 上,mapping 必有值,NULL mapping 恰好证明它不是 secretmem
  • CONFIG_SECRETMEM=y 时回归成立

方案

把 NULL mapping 的判定按检查目的分开:mapping 为 NULL 时返回 !reject_file_backed。

    if (!mapping)
-       return false;
+       return !reject_file_backed;
NULL mapping 分情形判定
                                ┌────────────────────────┐
                                │ folio->mapping 为 NULL │
                                └───────────┬────────────┘
                     ┌──────────────────────┴──────────────────────┐
                     ▼                                             ▼
┌─────────────────────────────────────────┐      ┌───────────────────────────────────┐
│ 只查 secretmem,NULL 即证非 secretmem, │      │ reject_file_backed 场景回退慢路径 │
│ 快路径放行                              │      │                                   │
└─────────────────────────────────────────┘      └───────────────────────────────────┘

只查 secretmem 时,NULL mapping 即证清白,快路径放行;reject_file_backed 场景仍回退慢路径,被截断文件页的保守处理不变。

收益

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

  • 驱动页的 GUP-fast 恢复,不再无谓回退慢路径
  • secretmem 与 reject_file_backed 两类检查各归各位,语义分清