Skip to content

Commit bc02afb

Browse files
xzpeterakpm00
authored andcommitted
mm/fork: accept huge pfnmap entries
Teach the fork code to properly copy pfnmaps for pmd/pud levels. Pud is much easier, the write bit needs to be persisted though for writable and shared pud mappings like PFNMAP ones, otherwise a follow up write in either parent or child process will trigger a write fault. Do the same for pmd level. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Peter Xu <[email protected]> Cc: Alexander Gordeev <[email protected]> Cc: Alex Williamson <[email protected]> Cc: Aneesh Kumar K.V <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Catalin Marinas <[email protected]> Cc: Christian Borntraeger <[email protected]> Cc: Dave Hansen <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Gavin Shan <[email protected]> Cc: Gerald Schaefer <[email protected]> Cc: Heiko Carstens <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Jason Gunthorpe <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Niklas Schnelle <[email protected]> Cc: Paolo Bonzini <[email protected]> Cc: Ryan Roberts <[email protected]> Cc: Sean Christopherson <[email protected]> Cc: Sven Schnelle <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Vasily Gorbik <[email protected]> Cc: Will Deacon <[email protected]> Cc: Zi Yan <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 10d83d7 commit bc02afb

File tree

1 file changed

+26
-3
lines changed

1 file changed

+26
-3
lines changed

mm/huge_memory.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,6 +1583,24 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
15831583
pgtable_t pgtable = NULL;
15841584
int ret = -ENOMEM;
15851585

1586+
pmd = pmdp_get_lockless(src_pmd);
1587+
if (unlikely(pmd_special(pmd))) {
1588+
dst_ptl = pmd_lock(dst_mm, dst_pmd);
1589+
src_ptl = pmd_lockptr(src_mm, src_pmd);
1590+
spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING);
1591+
/*
1592+
* No need to recheck the pmd, it can't change with write
1593+
* mmap lock held here.
1594+
*
1595+
* Meanwhile, making sure it's not a CoW VMA with writable
1596+
* mapping, otherwise it means either the anon page wrongly
1597+
* applied special bit, or we made the PRIVATE mapping be
1598+
* able to wrongly write to the backend MMIO.
1599+
*/
1600+
VM_WARN_ON_ONCE(is_cow_mapping(src_vma->vm_flags) && pmd_write(pmd));
1601+
goto set_pmd;
1602+
}
1603+
15861604
/* Skip if can be re-fill on fault */
15871605
if (!vma_is_anonymous(dst_vma))
15881606
return 0;
@@ -1664,7 +1682,9 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
16641682
pmdp_set_wrprotect(src_mm, addr, src_pmd);
16651683
if (!userfaultfd_wp(dst_vma))
16661684
pmd = pmd_clear_uffd_wp(pmd);
1667-
pmd = pmd_mkold(pmd_wrprotect(pmd));
1685+
pmd = pmd_wrprotect(pmd);
1686+
set_pmd:
1687+
pmd = pmd_mkold(pmd);
16681688
set_pmd_at(dst_mm, addr, dst_pmd, pmd);
16691689

16701690
ret = 0;
@@ -1710,8 +1730,11 @@ int copy_huge_pud(struct mm_struct *dst_mm, struct mm_struct *src_mm,
17101730
* TODO: once we support anonymous pages, use
17111731
* folio_try_dup_anon_rmap_*() and split if duplicating fails.
17121732
*/
1713-
pudp_set_wrprotect(src_mm, addr, src_pud);
1714-
pud = pud_mkold(pud_wrprotect(pud));
1733+
if (is_cow_mapping(vma->vm_flags) && pud_write(pud)) {
1734+
pudp_set_wrprotect(src_mm, addr, src_pud);
1735+
pud = pud_wrprotect(pud);
1736+
}
1737+
pud = pud_mkold(pud);
17151738
set_pud_at(dst_mm, addr, dst_pud, pud);
17161739

17171740
ret = 0;

0 commit comments

Comments
 (0)