--- include/linux/slub_def.h | 22 ++++++++--- mm/slub.c | 88 ++++++++++++++++++++++------------------------- 2 files changed, 58 insertions(+), 52 deletions(-) Index: slub/include/linux/slub_def.h =================================================================== --- slub.orig/include/linux/slub_def.h 2007-06-04 16:19:32.000000000 -0700 +++ slub/include/linux/slub_def.h 2007-06-04 16:32:49.000000000 -0700 @@ -58,14 +58,16 @@ struct kmem_cache { * Kmalloc subsystem. */ #define KMALLOC_SHIFT_LOW 3 +#define KMALLOC_SHIFT_STATIC PAGE_SHIFT #define KMALLOC_MIN_SIZE (1UL << KMALLOC_SHIFT_LOW) +#define KMALLOC_STATIC_SIZE (1UL << KMALLOC_SHIFT_STATIC) /* - * We keep the general caches in an array of slab caches that are used for - * 2^x bytes of allocations. + * Array of statically allocated slabs. Indexing into these arrays + * allows compile time calculation of slab addresses. */ -extern struct kmem_cache kmalloc_caches[KMALLOC_SHIFT_HIGH + 1]; +extern struct kmem_cache kmalloc_static_cache[KMALLOC_SHIFT_STATIC]; /* * Determine the kmalloc array index given the object size. @@ -112,7 +114,7 @@ static inline struct kmem_cache *kmalloc * If this triggers then the amount of memory requested was too large. */ BUG_ON(index < 0); - return &kmalloc_caches[index]; + return &kmalloc_static_cache[index]; } #ifdef CONFIG_ZONE_DMA @@ -136,7 +138,9 @@ static inline struct kmem_cache *kmalloc static inline void *kmalloc(size_t size, gfp_t flags) { - if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) { + if (__builtin_constant_p(size) && + size <= KMALLOC_STATIC_SIZE && + !(flags & SLUB_DMA)) { struct kmem_cache *s = kmalloc_slab(size); if (!s) @@ -149,7 +153,9 @@ static inline void *kmalloc(size_t size, static inline void *kzalloc(size_t size, gfp_t flags) { - if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) { + if (__builtin_constant_p(size) && + size <= KMALLOC_STATIC_SIZE && + !(flags & SLUB_DMA)) { struct kmem_cache *s = kmalloc_slab(size); if (!s) @@ -165,7 +171,9 @@ extern void *__kmalloc_node(size_t size, static inline void *kmalloc_node(size_t size, gfp_t flags, int node) { - if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) { + if (__builtin_constant_p(size) && + size <= KMALLOC_STATIC_SIZE && + !(flags & SLUB_DMA)) { struct kmem_cache *s = kmalloc_slab(size); if (!s) Index: slub/mm/slub.c =================================================================== --- slub.orig/mm/slub.c 2007-06-04 16:23:03.000000000 -0700 +++ slub/mm/slub.c 2007-06-04 16:38:22.000000000 -0700 @@ -2170,12 +2170,10 @@ EXPORT_SYMBOL(kmem_cache_destroy); * Kmalloc subsystem *******************************************************************/ -struct kmem_cache kmalloc_caches[KMALLOC_SHIFT_HIGH + 1] __cacheline_aligned; -EXPORT_SYMBOL(kmalloc_caches); +struct kmem_cache kmalloc_static_cache[KMALLOC_SHIFT_STATIC] __cacheline_aligned; +EXPORT_SYMBOL(kmalloc_static_cache); -#ifdef CONFIG_ZONE_DMA -static struct kmem_cache *kmalloc_caches_dma[KMALLOC_SHIFT_HIGH + 1]; -#endif +static struct kmem_cache *kmalloc_cache[(!!SLUB_DMA) + 1][KMALLOC_SHIFT_HIGH + 1]; static int __init setup_slub_min_order(char *str) { @@ -2238,6 +2236,10 @@ panic: static struct kmem_cache *get_slab(size_t size, gfp_t flags) { int index = kmalloc_index(size); + int dma = !!(flags & SLUB_DMA); + struct kmem_cache *s; + char *text; + size_t realsize; if (!index) return NULL; @@ -2245,39 +2247,32 @@ static struct kmem_cache *get_slab(size_ /* Allocation too large? */ BUG_ON(index < 0); -#ifdef CONFIG_ZONE_DMA - if ((flags & SLUB_DMA)) { - struct kmem_cache *s; - struct kmem_cache *x; - char *text; - size_t realsize; - - s = kmalloc_caches_dma[index]; - if (s) - return s; - - /* Dynamically create dma cache */ - x = kmalloc(kmem_size, flags & ~SLUB_DMA); - if (!x) - panic("Unable to allocate memory for dma cache\n"); - - if (index <= KMALLOC_SHIFT_HIGH) - realsize = 1 << index; - else { - if (index == 1) - realsize = 96; - else - realsize = 192; - } - - text = kasprintf(flags & ~SLUB_DMA, "kmalloc_dma-%d", - (unsigned int)realsize); - s = create_kmalloc_cache(x, text, realsize, flags); - kmalloc_caches_dma[index] = s; + s = kmalloc_cache[dma][index]; + if (likely(s)) return s; + + flags &= ~SLUB_DMA; + + /* On demand slab creation */ + s = kmalloc(kmem_size, flags); + if (!s) + panic("Unable to allocate memory for dma cache\n"); + + if (index <= KMALLOC_SHIFT_HIGH) + realsize = 1 << index; + else { + if (index == 1) + realsize = 96; + else + realsize = 192; } -#endif - return &kmalloc_caches[index]; + + text = kasprintf(flags, + dma ? "kmalloc_dma-%td" : "kmalloc-%td", + realsize); + s = create_kmalloc_cache(s, text, realsize, flags); + kmalloc_cache[dma][index] = s; + return s; } void *__kmalloc(size_t size, gfp_t flags) @@ -2497,29 +2492,32 @@ void __init kmem_cache_init(void) * struct kmem_cache_node's. There is special bootstrap code in * kmem_cache_open for slab_state == DOWN. */ - create_kmalloc_cache(&kmalloc_caches[0], "kmem_cache_node", + create_kmalloc_cache(&kmalloc_static_cache[0], "kmem_cache_node", sizeof(struct kmem_cache_node), GFP_KERNEL); - kmalloc_caches[0].refcount = -1; + kmalloc_static_cache[0].refcount = -1; #endif /* Able to allocate the per node structures */ slab_state = PARTIAL; /* Caches that are not of the two-to-the-power-of size */ - create_kmalloc_cache(&kmalloc_caches[1], + kmalloc_cache[0][1] = create_kmalloc_cache(&kmalloc_static_cache[1], "kmalloc-96", 96, GFP_KERNEL); - create_kmalloc_cache(&kmalloc_caches[2], + kmalloc_cache[0][2] = create_kmalloc_cache(&kmalloc_static_cache[2], "kmalloc-192", 192, GFP_KERNEL); - for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++) - create_kmalloc_cache(&kmalloc_caches[i], - "kmalloc", 1 << i, GFP_KERNEL); + for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_STATIC; i++) + kmalloc_cache[0][i] = create_kmalloc_cache( + &kmalloc_static_cache[i], + NULL, + 1 << i, + GFP_KERNEL); slab_state = UP; /* Provide the correct kmalloc names now that the caches are up */ - for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++) - kmalloc_caches[i]. name = + for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_STATIC; i++) + kmalloc_static_cache[i].name = kasprintf(GFP_KERNEL, "kmalloc-%d", 1 << i); #ifdef CONFIG_SMP