Re: [PATCH] mm/huge_memory: recheck a special PMD under the lock in copy_huge_pmd()

From: Lance Yang

Date: Wed Oct 14 2026 - 09:37:05 EST




On 2026/10/14 19:57, Konstantin Khorenko wrote:
[...]
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 1e5d68acf62a5..fcea98f0d8865 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1965,13 +1965,22 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
src_ptl = pmd_lockptr(src_mm, src_pmd);
spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING);
/*
- * No need to recheck the pmd, it can't change with write
- * mmap lock held here.
- *
- * Meanwhile, making sure it's not a CoW VMA with writable
- * mapping, otherwise it means either the anon page wrongly
- * applied special bit, or we made the PRIVATE mapping be
- * able to wrongly write to the backend MMIO.
+ * The mmap and VMA write locks of the source keep faults
+ * out, but unmap_mapping_range() does not take the mmap
+ * lock and may have cleared the pmd since the lockless
+ * read. Let copy_pmd_range() skip it then.
+ */
+ pmd = pmdp_get(src_pmd);
+ if (unlikely(!pmd_present(pmd) || !pmd_special(pmd))) {

Why not just check pmd_none(pmd) here? We're holding the source mmap/VMA
write locks, so the PMD either stays special or gets cleared, right?

Cheers, Lance

+ spin_unlock(src_ptl);
+ spin_unlock(dst_ptl);
+ return -EAGAIN;
+ }
+ /*
+ * Make sure it's not a CoW VMA with writable mapping,
+ * otherwise it means either the anon page wrongly applied
+ * special bit, or we made the PRIVATE mapping be able to
+ * wrongly write to the backend MMIO.
*/
VM_WARN_ON_ONCE(vma_is_cow_mapping(src_vma) && pmd_write(pmd));
goto set_pmd;

---
base-commit: 24a19b953e2a3d0ea5a8c4951a0ab8f32720c907
change-id: 20261014-b4-prep-vstor-149847-copy_huge_pmd-recheck-special-pmd-bdf7efb612c2

Best regards,
--
Konstantin Khorenko <khorenko@xxxxxxxxxxxxx>