aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorMel Gorman <mgorman@suse.de>2013-10-07 06:28:49 -0400
committerIngo Molnar <mingo@kernel.org>2013-10-09 06:39:49 -0400
commitf123d74abf91574837d14e5ea58f6a779a387bf5 (patch)
tree4347ff38dea6a74a53d811e63c21e805a5d25cfd /mm
parente920e14ca29b0b2a981cfc90e4e20edd6f078d19 (diff)
mm: Only flush TLBs if a transhuge PMD is modified for NUMA pte scanning
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>
Diffstat (limited to 'mm')
-rw-r--r--mm/huge_memory.c19
-rw-r--r--mm/mprotect.c14
2 files changed, 26 insertions, 7 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index d4928769680f..de8d5cfc2bf2 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1458,6 +1458,12 @@ out:
1458 return ret; 1458 return ret;
1459} 1459}
1460 1460
1461/*
1462 * Returns
1463 * - 0 if PMD could not be locked
1464 * - 1 if PMD was locked but protections unchange and TLB flush unnecessary
1465 * - HPAGE_PMD_NR is protections changed and TLB flush necessary
1466 */
1461int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, 1467int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
1462 unsigned long addr, pgprot_t newprot, int prot_numa) 1468 unsigned long addr, pgprot_t newprot, int prot_numa)
1463{ 1469{
@@ -1466,9 +1472,11 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
1466 1472
1467 if (__pmd_trans_huge_lock(pmd, vma) == 1) { 1473 if (__pmd_trans_huge_lock(pmd, vma) == 1) {
1468 pmd_t entry; 1474 pmd_t entry;
1469 entry = pmdp_get_and_clear(mm, addr, pmd); 1475 ret = 1;
1470 if (!prot_numa) { 1476 if (!prot_numa) {
1477 entry = pmdp_get_and_clear(mm, addr, pmd);
1471 entry = pmd_modify(entry, newprot); 1478 entry = pmd_modify(entry, newprot);
1479 ret = HPAGE_PMD_NR;
1472 BUG_ON(pmd_write(entry)); 1480 BUG_ON(pmd_write(entry));
1473 } else { 1481 } else {
1474 struct page *page = pmd_page(*pmd); 1482 struct page *page = pmd_page(*pmd);
@@ -1476,12 +1484,17 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
1476 /* only check non-shared pages */ 1484 /* only check non-shared pages */
1477 if (page_mapcount(page) == 1 && 1485 if (page_mapcount(page) == 1 &&
1478 !pmd_numa(*pmd)) { 1486 !pmd_numa(*pmd)) {
1487 entry = pmdp_get_and_clear(mm, addr, pmd);
1479 entry = pmd_mknuma(entry); 1488 entry = pmd_mknuma(entry);
1489 ret = HPAGE_PMD_NR;
1480 } 1490 }
1481 } 1491 }
1482 set_pmd_at(mm, addr, pmd, entry); 1492
1493 /* Set PMD if cleared earlier */
1494 if (ret == HPAGE_PMD_NR)
1495 set_pmd_at(mm, addr, pmd, entry);
1496
1483 spin_unlock(&vma->vm_mm->page_table_lock); 1497 spin_unlock(&vma->vm_mm->page_table_lock);
1484 ret = 1;
1485 } 1498 }
1486 1499
1487 return ret; 1500 return ret;
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 7bdbd4b0f6d9..2da33dca6134 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -144,10 +144,16 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
144 if (pmd_trans_huge(*pmd)) { 144 if (pmd_trans_huge(*pmd)) {
145 if (next - addr != HPAGE_PMD_SIZE) 145 if (next - addr != HPAGE_PMD_SIZE)
146 split_huge_page_pmd(vma, addr, pmd); 146 split_huge_page_pmd(vma, addr, pmd);
147 else if (change_huge_pmd(vma, pmd, addr, newprot, 147 else {
148 prot_numa)) { 148 int nr_ptes = change_huge_pmd(vma, pmd, addr,
149 pages++; 149 newprot, prot_numa);
150 continue; 150
151 if (nr_ptes) {
152 if (nr_ptes == HPAGE_PMD_NR)
153 pages++;
154
155 continue;
156 }
151 } 157 }
152 /* fall through */ 158 /* fall through */
153 } 159 }