Protect VMA from concurrent page fault handler while collapsing a huge
page. Page fault handler needs a stable PMD to use PTL and relies on
per-VMA lock to prevent concurrent PMD changes. pmdp_collapse_flush(),
set_huge_pmd() and collapse_and_free_pmd() can modify a PMD, which will
not be detected by a page fault handler without proper locking.

Signed-off-by: Suren Baghdasaryan <sur...@google.com>
---
 mm/khugepaged.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 5376246a3052..d8d0647f0c2c 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -1032,6 +1032,7 @@ static int collapse_huge_page(struct mm_struct *mm, 
unsigned long address,
        if (result != SCAN_SUCCEED)
                goto out_up_write;
 
+       vma_write_lock(vma);
        anon_vma_lock_write(vma->anon_vma);
 
        mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, NULL, mm,
@@ -1503,6 +1504,9 @@ int collapse_pte_mapped_thp(struct mm_struct *mm, 
unsigned long addr,
                goto drop_hpage;
        }
 
+       /* Lock the vma before taking i_mmap and page table locks */
+       vma_write_lock(vma);
+
        /*
         * We need to lock the mapping so that from here on, only GUP-fast and
         * hardware page walks can access the parts of the page tables that
@@ -1690,6 +1694,7 @@ static int retract_page_tables(struct address_space 
*mapping, pgoff_t pgoff,
                                result = SCAN_PTE_UFFD_WP;
                                goto unlock_next;
                        }
+                       vma_write_lock(vma);
                        collapse_and_free_pmd(mm, vma, addr, pmd);
                        if (!cc->is_khugepaged && is_target)
                                result = set_huge_pmd(vma, addr, pmd, hpage);
-- 
2.39.0

Reply via email to