aboutsummaryrefslogtreecommitdiffstats
path: root/mm/ksm.c
diff options
context:
space:
mode:
authorAndrea Arcangeli <aarcange@redhat.com>2011-01-13 18:47:19 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 20:32:48 -0500
commit29ad768cfc08611a4c1070d0f13f82eeea2bac7b (patch)
treea1cc7326d3a12bed79071559e2d4e8d43fb14814 /mm/ksm.c
parent60ab3244ec85c44276c585a2a20d3750402e1cf4 (diff)
thp: KSM on THP
This makes KSM full operational with THP pages. Subpages are scanned while the hugepage is still in place and delivering max cpu performance, and only if there's a match and we're going to deduplicate memory, the single hugepages with the subpage match is split. There will be no false sharing between ksmd and khugepaged. khugepaged won't collapse 2m virtual regions with KSM pages inside. ksmd also should only split pages when the checksum matches and we're likely to split an hugepage for some long living ksm page (usual ksm heuristic to avoid sharing pages that get de-cowed). Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> Cc: Hugh Dickins <hughd@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/ksm.c')
-rw-r--r--mm/ksm.c67
1 files changed, 58 insertions, 9 deletions
diff --git a/mm/ksm.c b/mm/ksm.c
index e2b0afd0a031..4d5a681923bb 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -412,6 +412,29 @@ out:
412 up_read(&mm->mmap_sem); 412 up_read(&mm->mmap_sem);
413} 413}
414 414
415static struct page *page_trans_compound_anon(struct page *page)
416{
417 if (PageTransCompound(page)) {
418 struct page *head;
419 head = compound_head(page);
420 /*
421 * head may be a dangling pointer.
422 * __split_huge_page_refcount clears PageTail
423 * before overwriting first_page, so if
424 * PageTail is still there it means the head
425 * pointer isn't dangling.
426 */
427 if (head != page) {
428 smp_rmb();
429 if (!PageTransCompound(page))
430 return NULL;
431 }
432 if (PageAnon(head))
433 return head;
434 }
435 return NULL;
436}
437
415static struct page *get_mergeable_page(struct rmap_item *rmap_item) 438static struct page *get_mergeable_page(struct rmap_item *rmap_item)
416{ 439{
417 struct mm_struct *mm = rmap_item->mm; 440 struct mm_struct *mm = rmap_item->mm;
@@ -431,7 +454,7 @@ static struct page *get_mergeable_page(struct rmap_item *rmap_item)
431 page = follow_page(vma, addr, FOLL_GET); 454 page = follow_page(vma, addr, FOLL_GET);
432 if (IS_ERR_OR_NULL(page)) 455 if (IS_ERR_OR_NULL(page))
433 goto out; 456 goto out;
434 if (PageAnon(page) && !PageTransCompound(page)) { 457 if (PageAnon(page) || page_trans_compound_anon(page)) {
435 flush_anon_page(vma, page, addr); 458 flush_anon_page(vma, page, addr);
436 flush_dcache_page(page); 459 flush_dcache_page(page);
437 } else { 460 } else {
@@ -709,6 +732,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
709 if (addr == -EFAULT) 732 if (addr == -EFAULT)
710 goto out; 733 goto out;
711 734
735 BUG_ON(PageTransCompound(page));
712 ptep = page_check_address(page, mm, addr, &ptl, 0); 736 ptep = page_check_address(page, mm, addr, &ptl, 0);
713 if (!ptep) 737 if (!ptep)
714 goto out; 738 goto out;
@@ -784,6 +808,7 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
784 goto out; 808 goto out;
785 809
786 pmd = pmd_offset(pud, addr); 810 pmd = pmd_offset(pud, addr);
811 BUG_ON(pmd_trans_huge(*pmd));
787 if (!pmd_present(*pmd)) 812 if (!pmd_present(*pmd))
788 goto out; 813 goto out;
789 814
@@ -811,6 +836,33 @@ out:
811 return err; 836 return err;
812} 837}
813 838
839static int page_trans_compound_anon_split(struct page *page)
840{
841 int ret = 0;
842 struct page *transhuge_head = page_trans_compound_anon(page);
843 if (transhuge_head) {
844 /* Get the reference on the head to split it. */
845 if (get_page_unless_zero(transhuge_head)) {
846 /*
847 * Recheck we got the reference while the head
848 * was still anonymous.
849 */
850 if (PageAnon(transhuge_head))
851 ret = split_huge_page(transhuge_head);
852 else
853 /*
854 * Retry later if split_huge_page run
855 * from under us.
856 */
857 ret = 1;
858 put_page(transhuge_head);
859 } else
860 /* Retry later if split_huge_page run from under us. */
861 ret = 1;
862 }
863 return ret;
864}
865
814/* 866/*
815 * try_to_merge_one_page - take two pages and merge them into one 867 * try_to_merge_one_page - take two pages and merge them into one
816 * @vma: the vma that holds the pte pointing to page 868 * @vma: the vma that holds the pte pointing to page
@@ -831,6 +883,9 @@ static int try_to_merge_one_page(struct vm_area_struct *vma,
831 883
832 if (!(vma->vm_flags & VM_MERGEABLE)) 884 if (!(vma->vm_flags & VM_MERGEABLE))
833 goto out; 885 goto out;
886 if (PageTransCompound(page) && page_trans_compound_anon_split(page))
887 goto out;
888 BUG_ON(PageTransCompound(page));
834 if (!PageAnon(page)) 889 if (!PageAnon(page))
835 goto out; 890 goto out;
836 891
@@ -1285,14 +1340,8 @@ next_mm:
1285 cond_resched(); 1340 cond_resched();
1286 continue; 1341 continue;
1287 } 1342 }
1288 if (PageTransCompound(*page)) { 1343 if (PageAnon(*page) ||
1289 put_page(*page); 1344 page_trans_compound_anon(*page)) {
1290 ksm_scan.address &= HPAGE_PMD_MASK;
1291 ksm_scan.address += HPAGE_PMD_SIZE;
1292 cond_resched();
1293 continue;
1294 }
1295 if (PageAnon(*page)) {
1296 flush_anon_page(vma, *page, ksm_scan.address); 1345 flush_anon_page(vma, *page, ksm_scan.address);
1297 flush_dcache_page(*page); 1346 flush_dcache_page(*page);
1298 rmap_item = get_next_rmap_item(slot, 1347 rmap_item = get_next_rmap_item(slot,