mm, slab_common: Fix bootstrap creation of kmalloc caches
authorChristoph Lameter <cl@linux.com>
Fri, 3 May 2013 18:04:18 +0000 (18:04 +0000)
committerPekka Enberg <penberg@kernel.org>
Mon, 6 May 2013 20:22:17 +0000 (23:22 +0300)
For SLAB the kmalloc caches must be created in ascending sizes in order
for the OFF_SLAB sub-slab cache to work properly.

Create the non power of two caches immediately after the prior power of
two kmalloc cache. Do not create the non power of two caches before all
other caches.

Reported-and-tested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Christoph Lamete <cl@linux.com>
Link: http://lkml.kernel.org/r/201305040348.CIF81716.OStQOHFJMFLOVF@I-love.SAKURA.ne.jp
Signed-off-by: Pekka Enberg <penberg@kernel.org>
mm/slab_common.c

index c5d352e73d81f2a6443c7cfa08e21a31ef3510c6..d2517b05d5bc488ba986c1f3c2993051dc9bd736 100644 (file)
@@ -442,18 +442,24 @@ void __init create_kmalloc_caches(unsigned long flags)
                for (i = 128 + 8; i <= 192; i += 8)
                        size_index[size_index_elem(i)] = 8;
        }
-       /* Caches that are not of the two-to-the-power-of size */
-       if (KMALLOC_MIN_SIZE <= 32 && !kmalloc_caches[1])
-               kmalloc_caches[1] = create_kmalloc_cache(NULL, 96, flags);
-
-       if (KMALLOC_MIN_SIZE <= 64 && !kmalloc_caches[2])
-               kmalloc_caches[2] = create_kmalloc_cache(NULL, 192, flags);
-
-       for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++)
-               if (!kmalloc_caches[i])
+       for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++) {
+               if (!kmalloc_caches[i]) {
                        kmalloc_caches[i] = create_kmalloc_cache(NULL,
                                                        1 << i, flags);
 
+                       /*
+                        * Caches that are not of the two-to-the-power-of size.
+                        * These have to be created immediately after the
+                        * earlier power of two caches
+                        */
+                       if (KMALLOC_MIN_SIZE <= 32 && !kmalloc_caches[1] && i == 6)
+                               kmalloc_caches[1] = create_kmalloc_cache(NULL, 96, flags);
+
+                       if (KMALLOC_MIN_SIZE <= 64 && !kmalloc_caches[2] && i == 7)
+                               kmalloc_caches[2] = create_kmalloc_cache(NULL, 192, flags);
+               }
+       }
+
        /* Kmalloc array is now usable */
        slab_state = UP;