aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/memory.c')
-rw-r--r--mm/memory.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/mm/memory.c b/mm/memory.c
index 7cf762857baa..cd8e0daf1912 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1517,6 +1517,8 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
1517 page = follow_huge_pmd(mm, address, pmd, flags & FOLL_WRITE); 1517 page = follow_huge_pmd(mm, address, pmd, flags & FOLL_WRITE);
1518 goto out; 1518 goto out;
1519 } 1519 }
1520 if ((flags & FOLL_NUMA) && pmd_numa(*pmd))
1521 goto no_page_table;
1520 if (pmd_trans_huge(*pmd)) { 1522 if (pmd_trans_huge(*pmd)) {
1521 if (flags & FOLL_SPLIT) { 1523 if (flags & FOLL_SPLIT) {
1522 split_huge_page_pmd(mm, pmd); 1524 split_huge_page_pmd(mm, pmd);
@@ -1546,6 +1548,8 @@ split_fallthrough:
1546 pte = *ptep; 1548 pte = *ptep;
1547 if (!pte_present(pte)) 1549 if (!pte_present(pte))
1548 goto no_page; 1550 goto no_page;
1551 if ((flags & FOLL_NUMA) && pte_numa(pte))
1552 goto no_page;
1549 if ((flags & FOLL_WRITE) && !pte_write(pte)) 1553 if ((flags & FOLL_WRITE) && !pte_write(pte))
1550 goto unlock; 1554 goto unlock;
1551 1555
@@ -1697,6 +1701,19 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
1697 (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD); 1701 (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
1698 vm_flags &= (gup_flags & FOLL_FORCE) ? 1702 vm_flags &= (gup_flags & FOLL_FORCE) ?
1699 (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE); 1703 (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
1704
1705 /*
1706 * If FOLL_FORCE and FOLL_NUMA are both set, handle_mm_fault
1707 * would be called on PROT_NONE ranges. We must never invoke
1708 * handle_mm_fault on PROT_NONE ranges or the NUMA hinting
1709 * page faults would unprotect the PROT_NONE ranges if
1710 * _PAGE_NUMA and _PAGE_PROTNONE are sharing the same pte/pmd
1711 * bitflag. So to avoid that, don't set FOLL_NUMA if
1712 * FOLL_FORCE is set.
1713 */
1714 if (!(gup_flags & FOLL_FORCE))
1715 gup_flags |= FOLL_NUMA;
1716
1700 i = 0; 1717 i = 0;
1701 1718
1702 do { 1719 do {