背景
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 两类检查各归各位,语义分清