aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugh Dickins <hugh.dickins@tiscali.co.uk>2009-09-21 20:02:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-22 10:17:32 -0400
commit81464e30609cdbd3d96d8dd6991e7481195a89a1 (patch)
treeec25711be5bf99e94264e3b201c0e148b9c8641a
parent6e15838425ac855982f10419558649954a0684a3 (diff)
ksm: five little cleanups
1. We don't use __break_cow entry point now: merge it into break_cow. 2. remove_all_slot_rmap_items is just a special case of remove_trailing_rmap_items: use the latter instead. 3. Extend comment on unmerge_ksm_pages and rmap_items. 4. try_to_merge_two_pages should use try_to_merge_with_ksm_page instead of duplicating its code; and so swap them around. 5. Comment on cmp_and_merge_page described last year's: update it. Signed-off-by: Hugh Dickins <hugh.dickins@tiscali.co.uk> Acked-by: Izik Eidus <ieidus@redhat.com> Cc: Andrea Arcangeli <aarcange@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--mm/ksm.c112
1 files changed, 44 insertions, 68 deletions
diff --git a/mm/ksm.c b/mm/ksm.c
index 2849422448a3..c49bb7156a1d 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -315,22 +315,18 @@ static void break_ksm(struct vm_area_struct *vma, unsigned long addr)
315 /* Which leaves us looping there if VM_FAULT_OOM: hmmm... */ 315 /* Which leaves us looping there if VM_FAULT_OOM: hmmm... */
316} 316}
317 317
318static void __break_cow(struct mm_struct *mm, unsigned long addr) 318static void break_cow(struct mm_struct *mm, unsigned long addr)
319{ 319{
320 struct vm_area_struct *vma; 320 struct vm_area_struct *vma;
321 321
322 down_read(&mm->mmap_sem);
322 vma = find_vma(mm, addr); 323 vma = find_vma(mm, addr);
323 if (!vma || vma->vm_start > addr) 324 if (!vma || vma->vm_start > addr)
324 return; 325 goto out;
325 if (!(vma->vm_flags & VM_MERGEABLE) || !vma->anon_vma) 326 if (!(vma->vm_flags & VM_MERGEABLE) || !vma->anon_vma)
326 return; 327 goto out;
327 break_ksm(vma, addr); 328 break_ksm(vma, addr);
328} 329out:
329
330static void break_cow(struct mm_struct *mm, unsigned long addr)
331{
332 down_read(&mm->mmap_sem);
333 __break_cow(mm, addr);
334 up_read(&mm->mmap_sem); 330 up_read(&mm->mmap_sem);
335} 331}
336 332
@@ -439,17 +435,6 @@ static void remove_rmap_item_from_tree(struct rmap_item *rmap_item)
439 cond_resched(); /* we're called from many long loops */ 435 cond_resched(); /* we're called from many long loops */
440} 436}
441 437
442static void remove_all_slot_rmap_items(struct mm_slot *mm_slot)
443{
444 struct rmap_item *rmap_item, *node;
445
446 list_for_each_entry_safe(rmap_item, node, &mm_slot->rmap_list, link) {
447 remove_rmap_item_from_tree(rmap_item);
448 list_del(&rmap_item->link);
449 free_rmap_item(rmap_item);
450 }
451}
452
453static void remove_trailing_rmap_items(struct mm_slot *mm_slot, 438static void remove_trailing_rmap_items(struct mm_slot *mm_slot,
454 struct list_head *cur) 439 struct list_head *cur)
455{ 440{
@@ -471,6 +456,11 @@ static void remove_trailing_rmap_items(struct mm_slot *mm_slot,
471 * page and upping mmap_sem. Nor does it fit with the way we skip dup'ing 456 * page and upping mmap_sem. Nor does it fit with the way we skip dup'ing
472 * rmap_items from parent to child at fork time (so as not to waste time 457 * rmap_items from parent to child at fork time (so as not to waste time
473 * if exit comes before the next scan reaches it). 458 * if exit comes before the next scan reaches it).
459 *
460 * Similarly, although we'd like to remove rmap_items (so updating counts
461 * and freeing memory) when unmerging an area, it's easier to leave that
462 * to the next pass of ksmd - consider, for example, how ksmd might be
463 * in cmp_and_merge_page on one of the rmap_items we would be removing.
474 */ 464 */
475static void unmerge_ksm_pages(struct vm_area_struct *vma, 465static void unmerge_ksm_pages(struct vm_area_struct *vma,
476 unsigned long start, unsigned long end) 466 unsigned long start, unsigned long end)
@@ -495,7 +485,7 @@ static void unmerge_and_remove_all_rmap_items(void)
495 continue; 485 continue;
496 unmerge_ksm_pages(vma, vma->vm_start, vma->vm_end); 486 unmerge_ksm_pages(vma, vma->vm_start, vma->vm_end);
497 } 487 }
498 remove_all_slot_rmap_items(mm_slot); 488 remove_trailing_rmap_items(mm_slot, mm_slot->rmap_list.next);
499 up_read(&mm->mmap_sem); 489 up_read(&mm->mmap_sem);
500 } 490 }
501 491
@@ -533,7 +523,7 @@ static void remove_mm_from_lists(struct mm_struct *mm)
533 list_del(&mm_slot->mm_list); 523 list_del(&mm_slot->mm_list);
534 spin_unlock(&ksm_mmlist_lock); 524 spin_unlock(&ksm_mmlist_lock);
535 525
536 remove_all_slot_rmap_items(mm_slot); 526 remove_trailing_rmap_items(mm_slot, mm_slot->rmap_list.next);
537 free_mm_slot(mm_slot); 527 free_mm_slot(mm_slot);
538 clear_bit(MMF_VM_MERGEABLE, &mm->flags); 528 clear_bit(MMF_VM_MERGEABLE, &mm->flags);
539} 529}
@@ -740,6 +730,29 @@ out:
740} 730}
741 731
742/* 732/*
733 * try_to_merge_with_ksm_page - like try_to_merge_two_pages,
734 * but no new kernel page is allocated: kpage must already be a ksm page.
735 */
736static int try_to_merge_with_ksm_page(struct mm_struct *mm1,
737 unsigned long addr1,
738 struct page *page1,
739 struct page *kpage)
740{
741 struct vm_area_struct *vma;
742 int err = -EFAULT;
743
744 down_read(&mm1->mmap_sem);
745 vma = find_vma(mm1, addr1);
746 if (!vma || vma->vm_start > addr1)
747 goto out;
748
749 err = try_to_merge_one_page(vma, page1, kpage);
750out:
751 up_read(&mm1->mmap_sem);
752 return err;
753}
754
755/*
743 * try_to_merge_two_pages - take two identical pages and prepare them 756 * try_to_merge_two_pages - take two identical pages and prepare them
744 * to be merged into one page. 757 * to be merged into one page.
745 * 758 *
@@ -772,9 +785,8 @@ static int try_to_merge_two_pages(struct mm_struct *mm1, unsigned long addr1,
772 down_read(&mm1->mmap_sem); 785 down_read(&mm1->mmap_sem);
773 vma = find_vma(mm1, addr1); 786 vma = find_vma(mm1, addr1);
774 if (!vma || vma->vm_start > addr1) { 787 if (!vma || vma->vm_start > addr1) {
775 put_page(kpage);
776 up_read(&mm1->mmap_sem); 788 up_read(&mm1->mmap_sem);
777 return err; 789 goto out;
778 } 790 }
779 791
780 copy_user_highpage(kpage, page1, addr1, vma); 792 copy_user_highpage(kpage, page1, addr1, vma);
@@ -782,56 +794,20 @@ static int try_to_merge_two_pages(struct mm_struct *mm1, unsigned long addr1,
782 up_read(&mm1->mmap_sem); 794 up_read(&mm1->mmap_sem);
783 795
784 if (!err) { 796 if (!err) {
785 down_read(&mm2->mmap_sem); 797 err = try_to_merge_with_ksm_page(mm2, addr2, page2, kpage);
786 vma = find_vma(mm2, addr2);
787 if (!vma || vma->vm_start > addr2) {
788 put_page(kpage);
789 up_read(&mm2->mmap_sem);
790 break_cow(mm1, addr1);
791 return -EFAULT;
792 }
793
794 err = try_to_merge_one_page(vma, page2, kpage);
795 up_read(&mm2->mmap_sem);
796
797 /* 798 /*
798 * If the second try_to_merge_one_page failed, we have a 799 * If that fails, we have a ksm page with only one pte
799 * ksm page with just one pte pointing to it, so break it. 800 * pointing to it: so break it.
800 */ 801 */
801 if (err) 802 if (err)
802 break_cow(mm1, addr1); 803 break_cow(mm1, addr1);
803 } 804 }
804 805out:
805 put_page(kpage); 806 put_page(kpage);
806 return err; 807 return err;
807} 808}
808 809
809/* 810/*
810 * try_to_merge_with_ksm_page - like try_to_merge_two_pages,
811 * but no new kernel page is allocated: kpage must already be a ksm page.
812 */
813static int try_to_merge_with_ksm_page(struct mm_struct *mm1,
814 unsigned long addr1,
815 struct page *page1,
816 struct page *kpage)
817{
818 struct vm_area_struct *vma;
819 int err = -EFAULT;
820
821 down_read(&mm1->mmap_sem);
822 vma = find_vma(mm1, addr1);
823 if (!vma || vma->vm_start > addr1) {
824 up_read(&mm1->mmap_sem);
825 return err;
826 }
827
828 err = try_to_merge_one_page(vma, page1, kpage);
829 up_read(&mm1->mmap_sem);
830
831 return err;
832}
833
834/*
835 * stable_tree_search - search page inside the stable tree 811 * stable_tree_search - search page inside the stable tree
836 * @page: the page that we are searching identical pages to. 812 * @page: the page that we are searching identical pages to.
837 * @page2: pointer into identical page that we are holding inside the stable 813 * @page2: pointer into identical page that we are holding inside the stable
@@ -1033,10 +1009,10 @@ static void stable_tree_append(struct rmap_item *rmap_item,
1033} 1009}
1034 1010
1035/* 1011/*
1036 * cmp_and_merge_page - take a page computes its hash value and check if there 1012 * cmp_and_merge_page - first see if page can be merged into the stable tree;
1037 * is similar hash value to different page, 1013 * if not, compare checksum to previous and if it's the same, see if page can
1038 * in case we find that there is similar hash to different page we call to 1014 * be inserted into the unstable tree, or merged with a page already there and
1039 * try_to_merge_two_pages(). 1015 * both transferred to the stable tree.
1040 * 1016 *
1041 * @page: the page that we are searching identical page to. 1017 * @page: the page that we are searching identical page to.
1042 * @rmap_item: the reverse mapping into the virtual address of this page 1018 * @rmap_item: the reverse mapping into the virtual address of this page