Skip to content

Commit e944fd6

Browse files
Mel Gormantorvalds
Mel Gorman
authored andcommitted
mm: numa: do not trap faults on the huge zero page
Faults on the huge zero page are pointless and there is a BUG_ON to catch them during fault time. This patch reintroduces a check that avoids marking the zero page PAGE_NONE. Signed-off-by: Mel Gorman <[email protected]> Cc: Aneesh Kumar K.V <[email protected]> Cc: Benjamin Herrenschmidt <[email protected]> Cc: Dave Jones <[email protected]> Cc: Hugh Dickins <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Kirill Shutemov <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Paul Mackerras <[email protected]> Cc: Rik van Riel <[email protected]> Cc: Sasha Levin <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 21d9ee3 commit e944fd6

File tree

4 files changed

+27
-4
lines changed

4 files changed

+27
-4
lines changed

include/linux/huge_mm.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ extern int move_huge_pmd(struct vm_area_struct *vma,
3131
unsigned long new_addr, unsigned long old_end,
3232
pmd_t *old_pmd, pmd_t *new_pmd);
3333
extern int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
34-
unsigned long addr, pgprot_t newprot);
34+
unsigned long addr, pgprot_t newprot,
35+
int prot_numa);
3536

3637
enum transparent_hugepage_flag {
3738
TRANSPARENT_HUGEPAGE_FLAG,

mm/huge_memory.c

+12-1
Original file line numberDiff line numberDiff line change
@@ -1471,14 +1471,25 @@ int move_huge_pmd(struct vm_area_struct *vma, struct vm_area_struct *new_vma,
14711471
* - HPAGE_PMD_NR is protections changed and TLB flush necessary
14721472
*/
14731473
int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
1474-
unsigned long addr, pgprot_t newprot)
1474+
unsigned long addr, pgprot_t newprot, int prot_numa)
14751475
{
14761476
struct mm_struct *mm = vma->vm_mm;
14771477
spinlock_t *ptl;
14781478
int ret = 0;
14791479

14801480
if (__pmd_trans_huge_lock(pmd, vma, &ptl) == 1) {
14811481
pmd_t entry;
1482+
1483+
/*
1484+
* Avoid trapping faults against the zero page. The read-only
1485+
* data is likely to be read-cached on the local CPU and
1486+
* local/remote hits to the zero page are not interesting.
1487+
*/
1488+
if (prot_numa && is_huge_zero_pmd(*pmd)) {
1489+
spin_unlock(ptl);
1490+
return 0;
1491+
}
1492+
14821493
ret = 1;
14831494
entry = pmdp_get_and_clear_notify(mm, addr, pmd);
14841495
entry = pmd_modify(entry, newprot);

mm/memory.c

-1
Original file line numberDiff line numberDiff line change
@@ -3040,7 +3040,6 @@ static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
30403040
pte_unmap_unlock(ptep, ptl);
30413041
return 0;
30423042
}
3043-
BUG_ON(is_zero_pfn(page_to_pfn(page)));
30443043

30453044
/*
30463045
* Avoid grouping on DSO/COW pages in specific and RO pages

mm/mprotect.c

+13-1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,18 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
7676
if (pte_present(oldpte)) {
7777
pte_t ptent;
7878

79+
/*
80+
* Avoid trapping faults against the zero or KSM
81+
* pages. See similar comment in change_huge_pmd.
82+
*/
83+
if (prot_numa) {
84+
struct page *page;
85+
86+
page = vm_normal_page(vma, addr, oldpte);
87+
if (!page || PageKsm(page))
88+
continue;
89+
}
90+
7991
ptent = ptep_modify_prot_start(mm, addr, pte);
8092
ptent = pte_modify(ptent, newprot);
8193

@@ -142,7 +154,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
142154
split_huge_page_pmd(vma, addr, pmd);
143155
else {
144156
int nr_ptes = change_huge_pmd(vma, pmd, addr,
145-
newprot);
157+
newprot, prot_numa);
146158

147159
if (nr_ptes) {
148160
if (nr_ptes == HPAGE_PMD_NR) {

0 commit comments

Comments
 (0)