From: Greg Kroah-Hartman Date: Wed, 15 Sep 2010 20:54:03 +0000 (-0700) Subject: .35 patches X-Git-Tag: v2.6.27.54~28 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=384b4e052b686c10132d957e2a845baf905f8718;p=thirdparty%2Fkernel%2Fstable-queue.git .35 patches --- diff --git a/queue-2.6.35/series b/queue-2.6.35/series index 3de3deed25b..04bd57cf720 100644 --- a/queue-2.6.35/series +++ b/queue-2.6.35/series @@ -59,3 +59,4 @@ alsa-hda-add-errata-initverb-sequence-for-cs42xx-codecs.patch alsa-hda-fix-wrong-hp-pin-detection-in-snd_hda_parse_pin_def_config.patch alsa-usb-audio-assume-first-control-interface-is-for-audio.patch alsa-hda-patch_nvhdmi.c-add-missing-codec-ids-unify-names.patch +swap-prevent-reuse-during-hibernation.patch diff --git a/queue-2.6.35/swap-prevent-reuse-during-hibernation.patch b/queue-2.6.35/swap-prevent-reuse-during-hibernation.patch new file mode 100644 index 00000000000..1812f27e43c --- /dev/null +++ b/queue-2.6.35/swap-prevent-reuse-during-hibernation.patch @@ -0,0 +1,74 @@ +From b73d7fcecd93dc15eaa3c45c8c587b613f6673c4 Mon Sep 17 00:00:00 2001 +From: Hugh Dickins +Date: Thu, 9 Sep 2010 16:38:09 -0700 +Subject: swap: prevent reuse during hibernation + +From: Hugh Dickins + +commit b73d7fcecd93dc15eaa3c45c8c587b613f6673c4 upstream. + +Move the hibernation check from scan_swap_map() into try_to_free_swap(): +to catch not only the common case when hibernation's allocation itself +triggers swap reuse, but also the less likely case when concurrent page +reclaim (shrink_page_list) might happen to try_to_free_swap from a page. + +Hibernation already clears __GFP_IO from the gfp_allowed_mask, to stop +reclaim from going to swap: check that to prevent swap reuse too. + +Signed-off-by: Hugh Dickins +Cc: KAMEZAWA Hiroyuki +Cc: KOSAKI Motohiro +Cc: "Rafael J. Wysocki" +Cc: Ondrej Zary +Cc: Andrea Gelmini +Cc: Balbir Singh +Cc: Andrea Arcangeli +Cc: Nigel Cunningham +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/swapfile.c | 24 ++++++++++++++++++++---- + 1 file changed, 20 insertions(+), 4 deletions(-) + +--- a/mm/swapfile.c ++++ b/mm/swapfile.c +@@ -318,10 +318,8 @@ checks: + if (offset > si->highest_bit) + scan_base = offset = si->lowest_bit; + +- /* reuse swap entry of cache-only swap if not hibernation. */ +- if (vm_swap_full() +- && usage == SWAP_HAS_CACHE +- && si->swap_map[offset] == SWAP_HAS_CACHE) { ++ /* reuse swap entry of cache-only swap if not busy. */ ++ if (vm_swap_full() && si->swap_map[offset] == SWAP_HAS_CACHE) { + int swap_was_freed; + spin_unlock(&swap_lock); + swap_was_freed = __try_to_reclaim_swap(si, offset); +@@ -688,6 +686,24 @@ int try_to_free_swap(struct page *page) + if (page_swapcount(page)) + return 0; + ++ /* ++ * Once hibernation has begun to create its image of memory, ++ * there's a danger that one of the calls to try_to_free_swap() ++ * - most probably a call from __try_to_reclaim_swap() while ++ * hibernation is allocating its own swap pages for the image, ++ * but conceivably even a call from memory reclaim - will free ++ * the swap from a page which has already been recorded in the ++ * image as a clean swapcache page, and then reuse its swap for ++ * another page of the image. On waking from hibernation, the ++ * original page might be freed under memory pressure, then ++ * later read back in from swap, now with the wrong data. ++ * ++ * Hibernation clears bits from gfp_allowed_mask to prevent ++ * memory reclaim from writing to disk, so check that here. ++ */ ++ if (!(gfp_allowed_mask & __GFP_IO)) ++ return 0; ++ + delete_from_swap_cache(page); + SetPageDirty(page); + return 1;