]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.3-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 23 Mar 2012 17:24:56 +0000 (10:24 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 23 Mar 2012 17:24:56 +0000 (10:24 -0700)
added patches:
mm-vmscan-forcibly-scan-highmem-if-there-are-too-many-buffer_heads-pinning-highmem.patch

queue-3.3/mm-vmscan-forcibly-scan-highmem-if-there-are-too-many-buffer_heads-pinning-highmem.patch [new file with mode: 0644]
queue-3.3/series

diff --git a/queue-3.3/mm-vmscan-forcibly-scan-highmem-if-there-are-too-many-buffer_heads-pinning-highmem.patch b/queue-3.3/mm-vmscan-forcibly-scan-highmem-if-there-are-too-many-buffer_heads-pinning-highmem.patch
new file mode 100644 (file)
index 0000000..5331756
--- /dev/null
@@ -0,0 +1,124 @@
+From cc715d99e529d470dde2f33a6614f255adea71f3 Mon Sep 17 00:00:00 2001
+From: Mel Gorman <mel@csn.ul.ie>
+Date: Wed, 21 Mar 2012 16:34:00 -0700
+Subject: mm: vmscan: forcibly scan highmem if there are too many buffer_heads pinning highmem
+
+From: Mel Gorman <mel@csn.ul.ie>
+
+commit cc715d99e529d470dde2f33a6614f255adea71f3 upstream.
+
+Stuart Foster reported on bugzilla that copying large amounts of data
+from NTFS caused an OOM kill on 32-bit X86 with 16G of memory.  Andrew
+Morton correctly identified that the problem was NTFS was using 512
+blocks meaning each page had 8 buffer_heads in low memory pinning it.
+
+In the past, direct reclaim used to scan highmem even if the allocating
+process did not specify __GFP_HIGHMEM but not any more.  kswapd no longer
+will reclaim from zones that are above the high watermark.  The intention
+in both cases was to minimise unnecessary reclaim.  The downside is on
+machines with large amounts of highmem that lowmem can be fully consumed
+by buffer_heads with nothing trying to free them.
+
+The following patch is based on a suggestion by Andrew Morton to extend
+the buffer_heads_over_limit case to force kswapd and direct reclaim to
+scan the highmem zone regardless of the allocation request or watermarks.
+
+Addresses https://bugzilla.kernel.org/show_bug.cgi?id=42578
+
+[hughd@google.com: move buffer_heads_over_limit check up]
+[akpm@linux-foundation.org: buffer_heads_over_limit is unlikely]
+Reported-by: Stuart Foster <smf.linux@ntlworld.com>
+Tested-by: Stuart Foster <smf.linux@ntlworld.com>
+Signed-off-by: Mel Gorman <mgorman@suse.de>
+Signed-off-by: Hugh Dickins <hughd@google.com>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Christoph Lameter <cl@linux.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ mm/vmscan.c |   42 +++++++++++++++++++++++++++++-------------
+ 1 file changed, 29 insertions(+), 13 deletions(-)
+
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -1643,18 +1643,6 @@ static void move_active_pages_to_lru(str
+       unsigned long pgmoved = 0;
+       struct page *page;
+-      if (buffer_heads_over_limit) {
+-              spin_unlock_irq(&zone->lru_lock);
+-              list_for_each_entry(page, list, lru) {
+-                      if (page_has_private(page) && trylock_page(page)) {
+-                              if (page_has_private(page))
+-                                      try_to_release_page(page, 0);
+-                              unlock_page(page);
+-                      }
+-              }
+-              spin_lock_irq(&zone->lru_lock);
+-      }
+-
+       while (!list_empty(list)) {
+               struct lruvec *lruvec;
+@@ -1737,6 +1725,14 @@ static void shrink_active_list(unsigned
+                       continue;
+               }
++              if (unlikely(buffer_heads_over_limit)) {
++                      if (page_has_private(page) && trylock_page(page)) {
++                              if (page_has_private(page))
++                                      try_to_release_page(page, 0);
++                              unlock_page(page);
++                      }
++              }
++
+               if (page_referenced(page, 0, mz->mem_cgroup, &vm_flags)) {
+                       nr_rotated += hpage_nr_pages(page);
+                       /*
+@@ -2235,6 +2231,14 @@ static bool shrink_zones(int priority, s
+       unsigned long nr_soft_scanned;
+       bool aborted_reclaim = false;
++      /*
++       * If the number of buffer_heads in the machine exceeds the maximum
++       * allowed level, force direct reclaim to scan the highmem zone as
++       * highmem pages could be pinning lowmem pages storing buffer_heads
++       */
++      if (buffer_heads_over_limit)
++              sc->gfp_mask |= __GFP_HIGHMEM;
++
+       for_each_zone_zonelist_nodemask(zone, z, zonelist,
+                                       gfp_zone(sc->gfp_mask), sc->nodemask) {
+               if (!populated_zone(zone))
+@@ -2724,6 +2728,17 @@ loop_again:
+                        */
+                       age_active_anon(zone, &sc, priority);
++                      /*
++                       * If the number of buffer_heads in the machine
++                       * exceeds the maximum allowed level and this node
++                       * has a highmem zone, force kswapd to reclaim from
++                       * it to relieve lowmem pressure.
++                       */
++                      if (buffer_heads_over_limit && is_highmem_idx(i)) {
++                              end_zone = i;
++                              break;
++                      }
++
+                       if (!zone_watermark_ok_safe(zone, order,
+                                       high_wmark_pages(zone), 0, 0)) {
+                               end_zone = i;
+@@ -2786,7 +2801,8 @@ loop_again:
+                               (zone->present_pages +
+                                       KSWAPD_ZONE_BALANCE_GAP_RATIO-1) /
+                               KSWAPD_ZONE_BALANCE_GAP_RATIO);
+-                      if (!zone_watermark_ok_safe(zone, order,
++                      if ((buffer_heads_over_limit && is_highmem_idx(i)) ||
++                                  !zone_watermark_ok_safe(zone, order,
+                                       high_wmark_pages(zone) + balance_gap,
+                                       end_zone, 0)) {
+                               shrink_zone(priority, zone, &sc);
index 57942249f6cb089e8b3b27becd0594561d25920b..6ff567eda2a2394e9b30e1cf4060bc0ab92c4648 100644 (file)
@@ -99,3 +99,4 @@ ahci_platform-add-strict_ahci-platform-type.patch
 pata_legacy-correctly-mask-recovery-field-for-ht6560b.patch
 firewire-ohci-fix-too-early-completion-of-ir-multichannel-buffers.patch
 video-uvesafb-fix-oops-that-uvesafb-try-to-execute-nx-protected-page.patch
+mm-vmscan-forcibly-scan-highmem-if-there-are-too-many-buffer_heads-pinning-highmem.patch