☰
memory pte_marker_clear
2026/11/5 3:52:29 网站建设 项目流程

pte_marker_clear是handle_pte_marker()用于处理特定类型 PTE marker(主要是uffd-wp marker)的清除函数。它的逻辑非常简洁,但核心在于一个必须保证的竞态条件。

核心实现与逻辑

static vm_fault_t pte_marker_clear(struct vm_fault *vmf) { /* * 谨慎行事:我们只会将一个特殊的 uffd-wp PTE 恢复为 none PTE。 * 否则意味着 PTE 可能已经改变,因此需要重试。 */ if (pte_same(vmf->orig_pte, ptep_get(vmf->pte))) pte_clear(vmf->vma->vm_mm, vmf->address, vmf->pte); pte_unmap_unlock(vmf->pte, vmf->ptl); return 0; }

关键设计点:pte_same而非is_pte_marker

这是该函数最核心的设计考量。早期实现使用is_pte_marker(*vmf->pte)来判断是否清除,但这不够安全。

考虑以下竞态场景:

  1. 缺页处理开始时,读取到的orig_pte是一个PTE_MARKER_UFFD_WP。

  2. 在获取 PTE 锁之前,另一个 CPU 将该 PTE 快速替换为PTE_MARKER_SWAPIN_ERROR(例如发生了交换错误)。

  3. 此时is_pte_marker(*vmf->pte)仍然返回true,因为两者都是 marker 类型。

  4. 如果直接清除,就会错误地丢弃交换错误 marker,导致后续访问无法正确处理。

修复方案是使用pte_same(vmf->orig_pte, ptep_get(vmf->pte))进行精确比对:

  • orig_pte是 uffd-wp marker:这是缺页处理路径进入pte_marker_clear的前提。

  • 当前 PTE 必须与orig_pte完全相同:只有完全相同,才能确认它仍是那个 uffd-wp marker,而非在锁外被替换为其他类型的 marker。

如果 PTE 已经改变(pte_same返回false),函数不清除,直接解锁并返回。调用者会看到返回值0(成功),但由于 PTE 未被修改,后续访问会再次触发缺页,由新的缺页处理逻辑根据新的 PTE 类型做出正确决策。

调用上下文

pte_marker_clear由handle_pte_marker()调用,后者在缺页处理中检测到非存在 PTE 是 marker 时被触发:

} else if (softleaf_is_marker(entry)) { ret = handle_pte_marker(vmf); }

handle_pte_marker()内部根据 marker 的具体类型分派:uffd-wp marker走pte_marker_clear路径(表示用户态处理程序已确认可以清除保护),而swapin error marker等其他类型走不同的处理逻辑。

返回值语义

函数始终返回0(VM_FAULT_NOPAGE的隐式等价),表示“缺页已处理”。即使 PTE 因竞态未被清除,也返回成功——因为调用者的职责只是“尝试清除”,真正的正确性由后续重试和pte_same检查保证。

历史演进

该函数在 2022 年 12 月由 Peter Xu 的补丁修复了上述竞态问题。在此之前,is_pte_marker()的宽松检查可能在某些罕见的快速状态切换场景下导致 marker 被错误丢弃。修复后,pte_same的精确比对成为标准做法,并一直沿用到现代内核。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询