diff options
Diffstat (limited to 'mm/ksm.c')
-rw-r--r-- | mm/ksm.c | 9 |
1 files changed, 4 insertions, 5 deletions
@@ -712,7 +712,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page, | |||
712 | if (!ptep) | 712 | if (!ptep) |
713 | goto out; | 713 | goto out; |
714 | 714 | ||
715 | if (pte_write(*ptep)) { | 715 | if (pte_write(*ptep) || pte_dirty(*ptep)) { |
716 | pte_t entry; | 716 | pte_t entry; |
717 | 717 | ||
718 | swapped = PageSwapCache(page); | 718 | swapped = PageSwapCache(page); |
@@ -735,7 +735,9 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page, | |||
735 | set_pte_at(mm, addr, ptep, entry); | 735 | set_pte_at(mm, addr, ptep, entry); |
736 | goto out_unlock; | 736 | goto out_unlock; |
737 | } | 737 | } |
738 | entry = pte_wrprotect(entry); | 738 | if (pte_dirty(entry)) |
739 | set_page_dirty(page); | ||
740 | entry = pte_mkclean(pte_wrprotect(entry)); | ||
739 | set_pte_at_notify(mm, addr, ptep, entry); | 741 | set_pte_at_notify(mm, addr, ptep, entry); |
740 | } | 742 | } |
741 | *orig_pte = *ptep; | 743 | *orig_pte = *ptep; |
@@ -1504,8 +1506,6 @@ struct page *ksm_does_need_to_copy(struct page *page, | |||
1504 | { | 1506 | { |
1505 | struct page *new_page; | 1507 | struct page *new_page; |
1506 | 1508 | ||
1507 | unlock_page(page); /* any racers will COW it, not modify it */ | ||
1508 | |||
1509 | new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address); | 1509 | new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address); |
1510 | if (new_page) { | 1510 | if (new_page) { |
1511 | copy_user_highpage(new_page, page, address, vma); | 1511 | copy_user_highpage(new_page, page, address, vma); |
@@ -1521,7 +1521,6 @@ struct page *ksm_does_need_to_copy(struct page *page, | |||
1521 | add_page_to_unevictable_list(new_page); | 1521 | add_page_to_unevictable_list(new_page); |
1522 | } | 1522 | } |
1523 | 1523 | ||
1524 | page_cache_release(page); | ||
1525 | return new_page; | 1524 | return new_page; |
1526 | } | 1525 | } |
1527 | 1526 | ||