Skip to content

Commit

Permalink
mm: Only flush TLBs if a transhuge PMD is modified for NUMA pte scanning
Browse files Browse the repository at this point in the history
NUMA PTE scanning is expensive both in terms of the scanning itself and
the TLB flush if there are any updates. The TLB flush is avoided if no
PTEs are updated but there is a bug where transhuge PMDs are considered
to be updated even if they were already pmd_numa. This patch addresses
the problem and TLB flushes should be reduced.

Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Reviewed-by: Rik van Riel <riel@redhat.com>
Signed-off-by: Mel Gorman <mgorman@suse.de>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1381141781-10992-12-git-send-email-mgorman@suse.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Mel Gorman authored and Ingo Molnar committed Oct 9, 2013
1 parent e920e14 commit f123d74
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 7 deletions.
19 changes: 16 additions & 3 deletions mm/huge_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -1458,6 +1458,12 @@ int move_huge_pmd(struct vm_area_struct *vma, struct vm_area_struct *new_vma,
return ret;
}

/*
* Returns
* - 0 if PMD could not be locked
* - 1 if PMD was locked but protections unchange and TLB flush unnecessary
* - 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, int prot_numa)
{
Expand All @@ -1466,22 +1472,29 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,

if (__pmd_trans_huge_lock(pmd, vma) == 1) {
pmd_t entry;
entry = pmdp_get_and_clear(mm, addr, pmd);
ret = 1;
if (!prot_numa) {
entry = pmdp_get_and_clear(mm, addr, pmd);
entry = pmd_modify(entry, newprot);
ret = HPAGE_PMD_NR;
BUG_ON(pmd_write(entry));
} else {
struct page *page = pmd_page(*pmd);

/* only check non-shared pages */
if (page_mapcount(page) == 1 &&
!pmd_numa(*pmd)) {
entry = pmdp_get_and_clear(mm, addr, pmd);
entry = pmd_mknuma(entry);
ret = HPAGE_PMD_NR;
}
}
set_pmd_at(mm, addr, pmd, entry);

/* Set PMD if cleared earlier */
if (ret == HPAGE_PMD_NR)
set_pmd_at(mm, addr, pmd, entry);

spin_unlock(&vma->vm_mm->page_table_lock);
ret = 1;
}

return ret;
Expand Down
14 changes: 10 additions & 4 deletions mm/mprotect.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,16 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
if (pmd_trans_huge(*pmd)) {
if (next - addr != HPAGE_PMD_SIZE)
split_huge_page_pmd(vma, addr, pmd);
else if (change_huge_pmd(vma, pmd, addr, newprot,
prot_numa)) {
pages++;
continue;
else {
int nr_ptes = change_huge_pmd(vma, pmd, addr,
newprot, prot_numa);

if (nr_ptes) {
if (nr_ptes == HPAGE_PMD_NR)
pages++;

continue;
}
}
/* fall through */
}
Expand Down

0 comments on commit f123d74

Please sign in to comment.