diff options
author | Hugh Dickins <hugh.dickins@tiscali.co.uk> | 2009-12-14 20:59:17 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-15 11:53:18 -0500 |
commit | 31e855ea7173bdb0520f9684580423a9560f66e0 (patch) | |
tree | 20ff327e2a58929696946971a8201da559785338 /mm/ksm.c | |
parent | 93d17715a5b960d34220f2edba3e6cee9b5b1c58 (diff) |
ksm: remove redundancies when merging page
There is no need for replace_page() to calculate a write-protected prot
vm_page_prot must already be write-protected for an anonymous page (see
mm/memory.c do_anonymous_page() for similar reliance on vm_page_prot).
There is no need for try_to_merge_one_page() to get_page and put_page on
newpage and oldpage: in every case we already hold a reference to each of
them.
But some instinct makes me move try_to_merge_one_page()'s unlock_page of
oldpage down after replace_page(): that doesn't increase contention on the
ksm page, and makes thinking about the transition easier.
Signed-off-by: Hugh Dickins <hugh.dickins@tiscali.co.uk>
Cc: 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>
Diffstat (limited to 'mm/ksm.c')
-rw-r--r-- | mm/ksm.c | 26 |
1 files changed, 6 insertions, 20 deletions
@@ -647,7 +647,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page, | |||
647 | * Check that no O_DIRECT or similar I/O is in progress on the | 647 | * Check that no O_DIRECT or similar I/O is in progress on the |
648 | * page | 648 | * page |
649 | */ | 649 | */ |
650 | if ((page_mapcount(page) + 2 + swapped) != page_count(page)) { | 650 | if (page_mapcount(page) + 1 + swapped != page_count(page)) { |
651 | set_pte_at_notify(mm, addr, ptep, entry); | 651 | set_pte_at_notify(mm, addr, ptep, entry); |
652 | goto out_unlock; | 652 | goto out_unlock; |
653 | } | 653 | } |
@@ -682,11 +682,8 @@ static int replace_page(struct vm_area_struct *vma, struct page *oldpage, | |||
682 | pte_t *ptep; | 682 | pte_t *ptep; |
683 | spinlock_t *ptl; | 683 | spinlock_t *ptl; |
684 | unsigned long addr; | 684 | unsigned long addr; |
685 | pgprot_t prot; | ||
686 | int err = -EFAULT; | 685 | int err = -EFAULT; |
687 | 686 | ||
688 | prot = vm_get_page_prot(vma->vm_flags & ~VM_WRITE); | ||
689 | |||
690 | addr = page_address_in_vma(oldpage, vma); | 687 | addr = page_address_in_vma(oldpage, vma); |
691 | if (addr == -EFAULT) | 688 | if (addr == -EFAULT) |
692 | goto out; | 689 | goto out; |
@@ -714,7 +711,7 @@ static int replace_page(struct vm_area_struct *vma, struct page *oldpage, | |||
714 | 711 | ||
715 | flush_cache_page(vma, addr, pte_pfn(*ptep)); | 712 | flush_cache_page(vma, addr, pte_pfn(*ptep)); |
716 | ptep_clear_flush(vma, addr, ptep); | 713 | ptep_clear_flush(vma, addr, ptep); |
717 | set_pte_at_notify(mm, addr, ptep, mk_pte(newpage, prot)); | 714 | set_pte_at_notify(mm, addr, ptep, mk_pte(newpage, vma->vm_page_prot)); |
718 | 715 | ||
719 | page_remove_rmap(oldpage); | 716 | page_remove_rmap(oldpage); |
720 | put_page(oldpage); | 717 | put_page(oldpage); |
@@ -746,13 +743,9 @@ static int try_to_merge_one_page(struct vm_area_struct *vma, | |||
746 | 743 | ||
747 | if (!(vma->vm_flags & VM_MERGEABLE)) | 744 | if (!(vma->vm_flags & VM_MERGEABLE)) |
748 | goto out; | 745 | goto out; |
749 | |||
750 | if (!PageAnon(oldpage)) | 746 | if (!PageAnon(oldpage)) |
751 | goto out; | 747 | goto out; |
752 | 748 | ||
753 | get_page(newpage); | ||
754 | get_page(oldpage); | ||
755 | |||
756 | /* | 749 | /* |
757 | * We need the page lock to read a stable PageSwapCache in | 750 | * We need the page lock to read a stable PageSwapCache in |
758 | * write_protect_page(). We use trylock_page() instead of | 751 | * write_protect_page(). We use trylock_page() instead of |
@@ -761,25 +754,18 @@ static int try_to_merge_one_page(struct vm_area_struct *vma, | |||
761 | * then come back to this page when it is unlocked. | 754 | * then come back to this page when it is unlocked. |
762 | */ | 755 | */ |
763 | if (!trylock_page(oldpage)) | 756 | if (!trylock_page(oldpage)) |
764 | goto out_putpage; | 757 | goto out; |
765 | /* | 758 | /* |
766 | * If this anonymous page is mapped only here, its pte may need | 759 | * If this anonymous page is mapped only here, its pte may need |
767 | * to be write-protected. If it's mapped elsewhere, all of its | 760 | * to be write-protected. If it's mapped elsewhere, all of its |
768 | * ptes are necessarily already write-protected. But in either | 761 | * ptes are necessarily already write-protected. But in either |
769 | * case, we need to lock and check page_count is not raised. | 762 | * case, we need to lock and check page_count is not raised. |
770 | */ | 763 | */ |
771 | if (write_protect_page(vma, oldpage, &orig_pte)) { | 764 | if (write_protect_page(vma, oldpage, &orig_pte) == 0 && |
772 | unlock_page(oldpage); | 765 | pages_identical(oldpage, newpage)) |
773 | goto out_putpage; | ||
774 | } | ||
775 | unlock_page(oldpage); | ||
776 | |||
777 | if (pages_identical(oldpage, newpage)) | ||
778 | err = replace_page(vma, oldpage, newpage, orig_pte); | 766 | err = replace_page(vma, oldpage, newpage, orig_pte); |
779 | 767 | ||
780 | out_putpage: | 768 | unlock_page(oldpage); |
781 | put_page(oldpage); | ||
782 | put_page(newpage); | ||
783 | out: | 769 | out: |
784 | return err; | 770 | return err; |
785 | } | 771 | } |