diff options
Diffstat (limited to 'mm')
-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 | } |