hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/mm/khugepaged.c
....@@ -623,6 +623,10 @@
623623 result = SCAN_PTE_NON_PRESENT;
624624 goto out;
625625 }
626
+ if (pte_uffd_wp(pteval)) {
627
+ result = SCAN_PTE_UFFD_WP;
628
+ goto out;
629
+ }
626630 page = vm_normal_page(vma, address, pteval);
627631 if (unlikely(!page)) {
628632 result = SCAN_PAGE_NULL;
....@@ -1464,14 +1468,6 @@
14641468 if (!hugepage_vma_check(vma, vma->vm_flags | VM_HUGEPAGE))
14651469 return;
14661470
1467
- /*
1468
- * Symmetry with retract_page_tables(): Exclude MAP_PRIVATE mappings
1469
- * that got written to. Without this, we'd have to also lock the
1470
- * anon_vma if one exists.
1471
- */
1472
- if (vma->anon_vma)
1473
- return;
1474
-
14751471 hpage = find_lock_page(vma->vm_file->f_mapping,
14761472 linear_page_index(vma, haddr));
14771473 if (!hpage)
....@@ -1545,6 +1541,10 @@
15451541 }
15461542
15471543 /* step 4: collapse pmd */
1544
+ /* we make no change to anon, but protect concurrent anon page lookup */
1545
+ if (vma->anon_vma)
1546
+ anon_vma_lock_write(vma->anon_vma);
1547
+
15481548 mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, NULL, mm, haddr,
15491549 haddr + HPAGE_PMD_SIZE);
15501550 mmu_notifier_invalidate_range_start(&range);
....@@ -1555,6 +1555,8 @@
15551555 mmu_notifier_invalidate_range_end(&range);
15561556 pte_free(mm, pmd_pgtable(_pmd));
15571557
1558
+ if (vma->anon_vma)
1559
+ anon_vma_unlock_write(vma->anon_vma);
15581560 i_mmap_unlock_write(vma->vm_file->f_mapping);
15591561
15601562 drop_hpage: