aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/swapfile.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c
index f08d165871b3..ed5151079f59 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -318,10 +318,8 @@ checks:
318 if (offset > si->highest_bit) 318 if (offset > si->highest_bit)
319 scan_base = offset = si->lowest_bit; 319 scan_base = offset = si->lowest_bit;
320 320
321 /* reuse swap entry of cache-only swap if not hibernation. */ 321 /* reuse swap entry of cache-only swap if not busy. */
322 if (vm_swap_full() 322 if (vm_swap_full() && si->swap_map[offset] == SWAP_HAS_CACHE) {
323 && usage == SWAP_HAS_CACHE
324 && si->swap_map[offset] == SWAP_HAS_CACHE) {
325 int swap_was_freed; 323 int swap_was_freed;
326 spin_unlock(&swap_lock); 324 spin_unlock(&swap_lock);
327 swap_was_freed = __try_to_reclaim_swap(si, offset); 325 swap_was_freed = __try_to_reclaim_swap(si, offset);
@@ -688,6 +686,24 @@ int try_to_free_swap(struct page *page)
688 if (page_swapcount(page)) 686 if (page_swapcount(page))
689 return 0; 687 return 0;
690 688
689 /*
690 * Once hibernation has begun to create its image of memory,
691 * there's a danger that one of the calls to try_to_free_swap()
692 * - most probably a call from __try_to_reclaim_swap() while
693 * hibernation is allocating its own swap pages for the image,
694 * but conceivably even a call from memory reclaim - will free
695 * the swap from a page which has already been recorded in the
696 * image as a clean swapcache page, and then reuse its swap for
697 * another page of the image. On waking from hibernation, the
698 * original page might be freed under memory pressure, then
699 * later read back in from swap, now with the wrong data.
700 *
701 * Hibernation clears bits from gfp_allowed_mask to prevent
702 * memory reclaim from writing to disk, so check that here.
703 */
704 if (!(gfp_allowed_mask & __GFP_IO))
705 return 0;
706
691 delete_from_swap_cache(page); 707 delete_from_swap_cache(page);
692 SetPageDirty(page); 708 SetPageDirty(page);
693 return 1; 709 return 1;