aboutsummaryrefslogtreecommitdiffstats
path: root/mm/ksm.c
diff options
context:
space:
mode:
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,