From: Chris Wright Date: Mon, 28 Jan 2008 19:45:57 +0000 (-0800) Subject: slab: fix bootstrap on memoryless node from Pekka X-Git-Tag: v2.6.22.19~51 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b0f19fd7ccd0b98b382bb1e8f717e20baa89d5c2;p=thirdparty%2Fkernel%2Fstable-queue.git slab: fix bootstrap on memoryless node from Pekka --- diff --git a/queue-2.6.24/series b/queue-2.6.24/series index 34bfac1bff1..9cbf10fe56e 100644 --- a/queue-2.6.24/series +++ b/queue-2.6.24/series @@ -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 index 00000000000..6d9c575aba5 --- /dev/null +++ b/queue-2.6.24/slab-fix-bootstrap-on-memoryless-node.patch @@ -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 +To: stable@kernel.org +Message-ID: +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 +Tested-by: Olaf Hering +Reviewed-by: Christoph Lameter +[ With additional one-liner by Olaf Hering - Linus ] +Signed-off-by: Linus Torvalds +Signed-off-by: Pekka Enberg +Signed-off-by: Chris Wright +--- + 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);