diff options
author | Ingo Molnar <mingo@elte.hu> | 2006-06-23 05:03:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-23 10:42:52 -0400 |
commit | e0a42726794f71336ff4b26084d453dd597471ce (patch) | |
tree | 31debb23f7cce0510a63755f0c4297086761f623 | |
parent | 668e0d8f1a02fd75f1c1e8142a6b08455914242c (diff) |
[PATCH] mm/slab.c: fix early init assumption
The SLAB bootstrap code assumes that the first two kmalloc caches created
(the INDEX_AC and INDEX_L3 kmalloc caches) wont be off-slab. But due to AC
and L3 structure size increase in lockdep, one of them ended up being
off-slab, and subsequently crashing with:
Unable to handle kernel NULL pointer dereference at 0000000000000000 RIP:
[<ffffffff80267478>] kmem_cache_alloc+0x26/0x7d
The fix is to introduce a bootstrap flag and to use it to prevent off-slab
caches being created so early during bootup.
(The calculation for off-slab caches is quite complex so i didnt want to
complicate things with introducing yet another INDEX_ calculation, the flag
approach is simpler and smaller.)
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Cc: Manfred Spraul <manfred@colorfullife.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | mm/slab.c | 12 |
1 files changed, 10 insertions, 2 deletions
@@ -331,6 +331,8 @@ static __always_inline int index_of(const size_t size) | |||
331 | return 0; | 331 | return 0; |
332 | } | 332 | } |
333 | 333 | ||
334 | static int slab_early_init = 1; | ||
335 | |||
334 | #define INDEX_AC index_of(sizeof(struct arraycache_init)) | 336 | #define INDEX_AC index_of(sizeof(struct arraycache_init)) |
335 | #define INDEX_L3 index_of(sizeof(struct kmem_list3)) | 337 | #define INDEX_L3 index_of(sizeof(struct kmem_list3)) |
336 | 338 | ||
@@ -1376,6 +1378,8 @@ void __init kmem_cache_init(void) | |||
1376 | NULL, NULL); | 1378 | NULL, NULL); |
1377 | } | 1379 | } |
1378 | 1380 | ||
1381 | slab_early_init = 0; | ||
1382 | |||
1379 | while (sizes->cs_size != ULONG_MAX) { | 1383 | while (sizes->cs_size != ULONG_MAX) { |
1380 | /* | 1384 | /* |
1381 | * For performance, all the general caches are L1 aligned. | 1385 | * For performance, all the general caches are L1 aligned. |
@@ -2106,8 +2110,12 @@ kmem_cache_create (const char *name, size_t size, size_t align, | |||
2106 | #endif | 2110 | #endif |
2107 | #endif | 2111 | #endif |
2108 | 2112 | ||
2109 | /* Determine if the slab management is 'on' or 'off' slab. */ | 2113 | /* |
2110 | if (size >= (PAGE_SIZE >> 3)) | 2114 | * Determine if the slab management is 'on' or 'off' slab. |
2115 | * (bootstrapping cannot cope with offslab caches so don't do | ||
2116 | * it too early on.) | ||
2117 | */ | ||
2118 | if ((size >= (PAGE_SIZE >> 3)) && !slab_early_init) | ||
2111 | /* | 2119 | /* |
2112 | * Size is large, assume best to place the slab management obj | 2120 | * Size is large, assume best to place the slab management obj |
2113 | * off-slab (should allow better packing of objs). | 2121 | * off-slab (should allow better packing of objs). |