diff options
author | Hugh Dickins <hughd@google.com> | 2013-02-22 19:36:10 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-23 20:50:24 -0500 |
commit | 56f31801ccdecb420d0d1fd2bf9f337c355214a9 (patch) | |
tree | 868442b02e6c83bdd52e4e129b17b90341190b6d /mm | |
parent | 9e16b7fb1d066d38d01fd57c449f2640c5d208cb (diff) |
mm: cleanup "swapcache" in do_swap_page
I dislike the way in which "swapcache" gets used in do_swap_page():
there is always a page from swapcache there (even if maybe uncached by
the time we lock it), but tests are made according to "swapcache".
Rework that with "page != swapcache", as has been done in unuse_pte().
Signed-off-by: Hugh Dickins <hughd@google.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Petr Holasek <pholasek@redhat.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Izik Eidus <izik.eidus@ravellosystems.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/memory.c | 18 |
1 files changed, 8 insertions, 10 deletions
diff --git a/mm/memory.c b/mm/memory.c index ec8ba011fa7d..705473afc1f4 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -2954,7 +2954,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2954 | unsigned int flags, pte_t orig_pte) | 2954 | unsigned int flags, pte_t orig_pte) |
2955 | { | 2955 | { |
2956 | spinlock_t *ptl; | 2956 | spinlock_t *ptl; |
2957 | struct page *page, *swapcache = NULL; | 2957 | struct page *page, *swapcache; |
2958 | swp_entry_t entry; | 2958 | swp_entry_t entry; |
2959 | pte_t pte; | 2959 | pte_t pte; |
2960 | int locked; | 2960 | int locked; |
@@ -3005,9 +3005,11 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3005 | */ | 3005 | */ |
3006 | ret = VM_FAULT_HWPOISON; | 3006 | ret = VM_FAULT_HWPOISON; |
3007 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); | 3007 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); |
3008 | swapcache = page; | ||
3008 | goto out_release; | 3009 | goto out_release; |
3009 | } | 3010 | } |
3010 | 3011 | ||
3012 | swapcache = page; | ||
3011 | locked = lock_page_or_retry(page, mm, flags); | 3013 | locked = lock_page_or_retry(page, mm, flags); |
3012 | 3014 | ||
3013 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); | 3015 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); |
@@ -3025,16 +3027,12 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3025 | if (unlikely(!PageSwapCache(page) || page_private(page) != entry.val)) | 3027 | if (unlikely(!PageSwapCache(page) || page_private(page) != entry.val)) |
3026 | goto out_page; | 3028 | goto out_page; |
3027 | 3029 | ||
3028 | swapcache = page; | ||
3029 | page = ksm_might_need_to_copy(page, vma, address); | 3030 | page = ksm_might_need_to_copy(page, vma, address); |
3030 | if (unlikely(!page)) { | 3031 | if (unlikely(!page)) { |
3031 | ret = VM_FAULT_OOM; | 3032 | ret = VM_FAULT_OOM; |
3032 | page = swapcache; | 3033 | page = swapcache; |
3033 | swapcache = NULL; | ||
3034 | goto out_page; | 3034 | goto out_page; |
3035 | } | 3035 | } |
3036 | if (page == swapcache) | ||
3037 | swapcache = NULL; | ||
3038 | 3036 | ||
3039 | if (mem_cgroup_try_charge_swapin(mm, page, GFP_KERNEL, &ptr)) { | 3037 | if (mem_cgroup_try_charge_swapin(mm, page, GFP_KERNEL, &ptr)) { |
3040 | ret = VM_FAULT_OOM; | 3038 | ret = VM_FAULT_OOM; |
@@ -3078,10 +3076,10 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3078 | } | 3076 | } |
3079 | flush_icache_page(vma, page); | 3077 | flush_icache_page(vma, page); |
3080 | set_pte_at(mm, address, page_table, pte); | 3078 | set_pte_at(mm, address, page_table, pte); |
3081 | if (swapcache) /* ksm created a completely new copy */ | 3079 | if (page == swapcache) |
3082 | page_add_new_anon_rmap(page, vma, address); | ||
3083 | else | ||
3084 | do_page_add_anon_rmap(page, vma, address, exclusive); | 3080 | do_page_add_anon_rmap(page, vma, address, exclusive); |
3081 | else /* ksm created a completely new copy */ | ||
3082 | page_add_new_anon_rmap(page, vma, address); | ||
3085 | /* It's better to call commit-charge after rmap is established */ | 3083 | /* It's better to call commit-charge after rmap is established */ |
3086 | mem_cgroup_commit_charge_swapin(page, ptr); | 3084 | mem_cgroup_commit_charge_swapin(page, ptr); |
3087 | 3085 | ||
@@ -3089,7 +3087,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3089 | if (vm_swap_full() || (vma->vm_flags & VM_LOCKED) || PageMlocked(page)) | 3087 | if (vm_swap_full() || (vma->vm_flags & VM_LOCKED) || PageMlocked(page)) |
3090 | try_to_free_swap(page); | 3088 | try_to_free_swap(page); |
3091 | unlock_page(page); | 3089 | unlock_page(page); |
3092 | if (swapcache) { | 3090 | if (page != swapcache) { |
3093 | /* | 3091 | /* |
3094 | * Hold the lock to avoid the swap entry to be reused | 3092 | * Hold the lock to avoid the swap entry to be reused |
3095 | * until we take the PT lock for the pte_same() check | 3093 | * until we take the PT lock for the pte_same() check |
@@ -3122,7 +3120,7 @@ out_page: | |||
3122 | unlock_page(page); | 3120 | unlock_page(page); |
3123 | out_release: | 3121 | out_release: |
3124 | page_cache_release(page); | 3122 | page_cache_release(page); |
3125 | if (swapcache) { | 3123 | if (page != swapcache) { |
3126 | unlock_page(swapcache); | 3124 | unlock_page(swapcache); |
3127 | page_cache_release(swapcache); | 3125 | page_cache_release(swapcache); |
3128 | } | 3126 | } |