Skip to content

Commit

Permalink
mm: numa: do not trap faults on the huge zero page
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
Mel Gorman authored and torvalds committed Feb 13, 2015
1 parent 21d9ee3 commit e944fd6
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 4 deletions.
3 changes: 2 additions & 1 deletion include/linux/huge_mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ extern int move_huge_pmd(struct vm_area_struct *vma,
unsigned long new_addr, unsigned long old_end,
pmd_t *old_pmd, pmd_t *new_pmd);
extern int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
unsigned long addr, pgprot_t newprot);
unsigned long addr, pgprot_t newprot,
int prot_numa);

enum transparent_hugepage_flag {
TRANSPARENT_HUGEPAGE_FLAG,
Expand Down
13 changes: 12 additions & 1 deletion mm/huge_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -1471,14 +1471,25 @@ int move_huge_pmd(struct vm_area_struct *vma, struct vm_area_struct *new_vma,
* - HPAGE_PMD_NR is protections changed and TLB flush necessary
*/
int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
unsigned long addr, pgprot_t newprot)
unsigned long addr, pgprot_t newprot, int prot_numa)
{
struct mm_struct *mm = vma->vm_mm;
spinlock_t *ptl;
int ret = 0;

if (__pmd_trans_huge_lock(pmd, vma, &ptl) == 1) {
pmd_t entry;

/*
* Avoid trapping faults against the zero page. The read-only
* data is likely to be read-cached on the local CPU and
* local/remote hits to the zero page are not interesting.
*/
if (prot_numa && is_huge_zero_pmd(*pmd)) {
spin_unlock(ptl);
return 0;
}

ret = 1;
entry = pmdp_get_and_clear_notify(mm, addr, pmd);
entry = pmd_modify(entry, newprot);
Expand Down
1 change: 0 additions & 1 deletion mm/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -3040,7 +3040,6 @@ static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
pte_unmap_unlock(ptep, ptl);
return 0;
}
BUG_ON(is_zero_pfn(page_to_pfn(page)));

/*
* Avoid grouping on DSO/COW pages in specific and RO pages
Expand Down
14 changes: 13 additions & 1 deletion mm/mprotect.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
if (pte_present(oldpte)) {
pte_t ptent;

/*
* Avoid trapping faults against the zero or KSM
* pages. See similar comment in change_huge_pmd.
*/
if (prot_numa) {
struct page *page;

page = vm_normal_page(vma, addr, oldpte);
if (!page || PageKsm(page))
continue;
}

ptent = ptep_modify_prot_start(mm, addr, pte);
ptent = pte_modify(ptent, newprot);

Expand Down Expand Up @@ -142,7 +154,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
split_huge_page_pmd(vma, addr, pmd);
else {
int nr_ptes = change_huge_pmd(vma, pmd, addr,
newprot);
newprot, prot_numa);

if (nr_ptes) {
if (nr_ptes == HPAGE_PMD_NR) {
Expand Down

0 comments on commit e944fd6

Please sign in to comment.