]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
slab: fix bootstrap on memoryless node from Pekka
authorChris Wright <chrisw@sous-sol.org>
Mon, 28 Jan 2008 19:45:57 +0000 (11:45 -0800)
committerChris Wright <chrisw@sous-sol.org>
Mon, 28 Jan 2008 19:45:57 +0000 (11:45 -0800)
queue-2.6.24/series
queue-2.6.24/slab-fix-bootstrap-on-memoryless-node.patch [new file with mode: 0644]

index 34bfac1bff1d72fc9f0eb83bd82f37e5e3b7d702..9cbf10fe56e606f06ca2b0e392fc2384d2b7bab3 100644 (file)
@@ -1 +1,2 @@
 dvb-cx23885-add-missing-subsystem-id-for-hauppauge-hvr1800-retail.patch
+slab-fix-bootstrap-on-memoryless-node.patch
diff --git a/queue-2.6.24/slab-fix-bootstrap-on-memoryless-node.patch b/queue-2.6.24/slab-fix-bootstrap-on-memoryless-node.patch
new file mode 100644 (file)
index 0000000..6d9c575
--- /dev/null
@@ -0,0 +1,125 @@
+From stable-bounces@linux.kernel.org  Mon Jan 28 11:42:17 2008
+Date: Sat, 26 Jan 2008 14:15:54 +0200 (EET)
+From: Pekka J Enberg <penberg@cs.helsinki.fi>
+To: stable@kernel.org
+Message-ID: <Pine.LNX.4.64.0801261413030.19335@sbz-30.cs.Helsinki.FI>
+Cc: mel@csn.ul.ie, olaf@aepfle.de, torvalds@linux-foundation.org, clameter@sgi.com
+Subject: slab: fix bootstrap on memoryless node
+
+[ Upstream commit: 556a169dab38b5100df6f4a45b655dddd3db94c1 ]
+
+If the node we're booting on doesn't have memory, bootstrapping kmalloc()
+caches resorts to fallback_alloc() which requires ->nodelists set for all
+nodes.  Fix that by calling set_up_list3s() for CACHE_CACHE in
+kmem_cache_init().
+    
+As kmem_getpages() is called with GFP_THISNODE set, this used to work before
+because of breakage in 2.6.22 and before with GFP_THISNODE returning pages from
+the wrong node if a node had no memory. So it may have worked accidentally and
+in an unsafe manner because the pages would have been associated with the wrong
+node which could trigger bug ons and locking troubles.
+    
+Tested-by: Mel Gorman <mel@csn.ul.ie>
+Tested-by: Olaf Hering <olaf@aepfle.de>
+Reviewed-by: Christoph Lameter <clameter@sgi.com>
+[ With additional one-liner by Olaf Hering  - Linus ]
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+ mm/slab.c |   46 +++++++++++++++++++++++-----------------------
+ 1 file changed, 23 insertions(+), 23 deletions(-)
+
+--- linux-2.6.24.1.orig/mm/slab.c
++++ linux-2.6.24.1/mm/slab.c
+@@ -304,11 +304,11 @@ struct kmem_list3 {
+ /*
+  * Need this for bootstrapping a per node allocator.
+  */
+-#define NUM_INIT_LISTS (2 * MAX_NUMNODES + 1)
++#define NUM_INIT_LISTS (3 * MAX_NUMNODES)
+ struct kmem_list3 __initdata initkmem_list3[NUM_INIT_LISTS];
+ #define       CACHE_CACHE 0
+-#define       SIZE_AC 1
+-#define       SIZE_L3 (1 + MAX_NUMNODES)
++#define       SIZE_AC MAX_NUMNODES
++#define       SIZE_L3 (2 * MAX_NUMNODES)
+ static int drain_freelist(struct kmem_cache *cache,
+                       struct kmem_list3 *l3, int tofree);
+@@ -1410,6 +1410,22 @@ static void init_list(struct kmem_cache 
+ }
+ /*
++ * For setting up all the kmem_list3s for cache whose buffer_size is same as
++ * size of kmem_list3.
++ */
++static void __init set_up_list3s(struct kmem_cache *cachep, int index)
++{
++      int node;
++
++      for_each_online_node(node) {
++              cachep->nodelists[node] = &initkmem_list3[index + node];
++              cachep->nodelists[node]->next_reap = jiffies +
++                  REAPTIMEOUT_LIST3 +
++                  ((unsigned long)cachep) % REAPTIMEOUT_LIST3;
++      }
++}
++
++/*
+  * Initialisation.  Called after the page allocator have been initialised and
+  * before smp_init().
+  */
+@@ -1432,6 +1448,7 @@ void __init kmem_cache_init(void)
+               if (i < MAX_NUMNODES)
+                       cache_cache.nodelists[i] = NULL;
+       }
++      set_up_list3s(&cache_cache, CACHE_CACHE);
+       /*
+        * Fragmentation resistance on low memory - only use bigger
+@@ -1587,10 +1604,9 @@ void __init kmem_cache_init(void)
+       {
+               int nid;
+-              /* Replace the static kmem_list3 structures for the boot cpu */
+-              init_list(&cache_cache, &initkmem_list3[CACHE_CACHE], node);
+-
+               for_each_online_node(nid) {
++                      init_list(&cache_cache, &initkmem_list3[CACHE_CACHE], nid);
++
+                       init_list(malloc_sizes[INDEX_AC].cs_cachep,
+                                 &initkmem_list3[SIZE_AC + nid], nid);
+@@ -1960,22 +1976,6 @@ static void slab_destroy(struct kmem_cac
+       }
+ }
+-/*
+- * For setting up all the kmem_list3s for cache whose buffer_size is same as
+- * size of kmem_list3.
+- */
+-static void __init set_up_list3s(struct kmem_cache *cachep, int index)
+-{
+-      int node;
+-
+-      for_each_online_node(node) {
+-              cachep->nodelists[node] = &initkmem_list3[index + node];
+-              cachep->nodelists[node]->next_reap = jiffies +
+-                  REAPTIMEOUT_LIST3 +
+-                  ((unsigned long)cachep) % REAPTIMEOUT_LIST3;
+-      }
+-}
+-
+ static void __kmem_cache_destroy(struct kmem_cache *cachep)
+ {
+       int i;
+@@ -2099,7 +2099,7 @@ static int __init_refok setup_cpu_cache(
+                       g_cpucache_up = PARTIAL_L3;
+               } else {
+                       int node;
+-                      for_each_node_state(node, N_NORMAL_MEMORY) {
++                      for_each_online_node(node) {
+                               cachep->nodelists[node] =
+                                   kmalloc_node(sizeof(struct kmem_list3),
+                                               GFP_KERNEL, node);