aboutsummaryrefslogtreecommitdiffstats
path: root/mm/huge_memory.c
diff options
context:
space:
mode:
authorAndrea Arcangeli <aarcange@redhat.com>2011-01-13 18:47:18 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 20:32:47 -0500
commit60ab3244ec85c44276c585a2a20d3750402e1cf4 (patch)
treee69e866b370243fc58a6fc721e5347a265e8fd4f /mm/huge_memory.c
parenta664b2d8555c659127bf8fe049a58449d394a707 (diff)
thp: khugepaged: make khugepaged aware about madvise
MADV_HUGEPAGE and MADV_NOHUGEPAGE were fully effective only if run after mmap and before touching the memory. While this is enough for most usages, it's little effort to make madvise more dynamic at runtime on an existing mapping by making khugepaged aware about madvise. MADV_HUGEPAGE: register in khugepaged immediately without waiting a page fault (that may not ever happen if all pages are already mapped and the "enabled" knob was set to madvise during the initial page faults). MADV_NOHUGEPAGE: skip vmas marked VM_NOHUGEPAGE in khugepaged to stop collapsing pages where not needed. [akpm@linux-foundation.org: tweak comment] Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> Cc: Michael Kerrisk <mtk.manpages@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/huge_memory.c')
-rw-r--r--mm/huge_memory.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index fce667c0281d..004c9c2aac78 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1389,7 +1389,8 @@ out:
1389 return ret; 1389 return ret;
1390} 1390}
1391 1391
1392int hugepage_madvise(unsigned long *vm_flags, int advice) 1392int hugepage_madvise(struct vm_area_struct *vma,
1393 unsigned long *vm_flags, int advice)
1393{ 1394{
1394 switch (advice) { 1395 switch (advice) {
1395 case MADV_HUGEPAGE: 1396 case MADV_HUGEPAGE:
@@ -1404,6 +1405,13 @@ int hugepage_madvise(unsigned long *vm_flags, int advice)
1404 return -EINVAL; 1405 return -EINVAL;
1405 *vm_flags &= ~VM_NOHUGEPAGE; 1406 *vm_flags &= ~VM_NOHUGEPAGE;
1406 *vm_flags |= VM_HUGEPAGE; 1407 *vm_flags |= VM_HUGEPAGE;
1408 /*
1409 * If the vma become good for khugepaged to scan,
1410 * register it here without waiting a page fault that
1411 * may not happen any time soon.
1412 */
1413 if (unlikely(khugepaged_enter_vma_merge(vma)))
1414 return -ENOMEM;
1407 break; 1415 break;
1408 case MADV_NOHUGEPAGE: 1416 case MADV_NOHUGEPAGE:
1409 /* 1417 /*
@@ -1417,6 +1425,11 @@ int hugepage_madvise(unsigned long *vm_flags, int advice)
1417 return -EINVAL; 1425 return -EINVAL;
1418 *vm_flags &= ~VM_HUGEPAGE; 1426 *vm_flags &= ~VM_HUGEPAGE;
1419 *vm_flags |= VM_NOHUGEPAGE; 1427 *vm_flags |= VM_NOHUGEPAGE;
1428 /*
1429 * Setting VM_NOHUGEPAGE will prevent khugepaged from scanning
1430 * this vma even if we leave the mm registered in khugepaged if
1431 * it got registered before VM_NOHUGEPAGE was set.
1432 */
1420 break; 1433 break;
1421 } 1434 }
1422 1435
@@ -1784,7 +1797,8 @@ static void collapse_huge_page(struct mm_struct *mm,
1784 if (address < hstart || address + HPAGE_PMD_SIZE > hend) 1797 if (address < hstart || address + HPAGE_PMD_SIZE > hend)
1785 goto out; 1798 goto out;
1786 1799
1787 if (!(vma->vm_flags & VM_HUGEPAGE) && !khugepaged_always()) 1800 if ((!(vma->vm_flags & VM_HUGEPAGE) && !khugepaged_always()) ||
1801 (vma->vm_flags & VM_NOHUGEPAGE))
1788 goto out; 1802 goto out;
1789 1803
1790 /* VM_PFNMAP vmas may have vm_ops null but vm_file set */ 1804 /* VM_PFNMAP vmas may have vm_ops null but vm_file set */
@@ -2007,8 +2021,9 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages,
2007 break; 2021 break;
2008 } 2022 }
2009 2023
2010 if (!(vma->vm_flags & VM_HUGEPAGE) && 2024 if ((!(vma->vm_flags & VM_HUGEPAGE) &&
2011 !khugepaged_always()) { 2025 !khugepaged_always()) ||
2026 (vma->vm_flags & VM_NOHUGEPAGE)) {
2012 progress++; 2027 progress++;
2013 continue; 2028 continue;
2014 } 2029 }