mm, sl[aou]b: Extract common code for kmem_cache_create()
Kmem_cache_create() does a variety of sanity checks but those vary depending on the allocator. Use the strictest tests and put them into a slab_common file. Make the tests conditional on CONFIG_DEBUG_VM. This patch has the effect of adding sanity checks for SLUB and SLOB under CONFIG_DEBUG_VM and removes the checks in SLAB for !CONFIG_DEBUG_VM. Signed-off-by: Christoph Lameter <cl@linux.com> Signed-off-by: Pekka Enberg <penberg@kernel.org>
This commit is contained in:
parent
068ce415be
commit
039363f38b
|
@ -130,6 +130,10 @@ int kmem_cache_shrink(struct kmem_cache *);
|
||||||
void kmem_cache_free(struct kmem_cache *, void *);
|
void kmem_cache_free(struct kmem_cache *, void *);
|
||||||
unsigned int kmem_cache_size(struct kmem_cache *);
|
unsigned int kmem_cache_size(struct kmem_cache *);
|
||||||
|
|
||||||
|
/* Slab internal function */
|
||||||
|
struct kmem_cache *__kmem_cache_create(const char *, size_t, size_t,
|
||||||
|
unsigned long,
|
||||||
|
void (*)(void *));
|
||||||
/*
|
/*
|
||||||
* Please use this macro to create slab caches. Simply specify the
|
* Please use this macro to create slab caches. Simply specify the
|
||||||
* name of the structure and maybe some flags that are listed above.
|
* name of the structure and maybe some flags that are listed above.
|
||||||
|
|
|
@ -16,7 +16,8 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \
|
||||||
readahead.o swap.o truncate.o vmscan.o shmem.o \
|
readahead.o swap.o truncate.o vmscan.o shmem.o \
|
||||||
prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
|
prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
|
||||||
page_isolation.o mm_init.o mmu_context.o percpu.o \
|
page_isolation.o mm_init.o mmu_context.o percpu.o \
|
||||||
compaction.o $(mmu-y)
|
compaction.o slab_common.o $(mmu-y)
|
||||||
|
|
||||||
obj-y += init-mm.o
|
obj-y += init-mm.o
|
||||||
|
|
||||||
ifdef CONFIG_NO_BOOTMEM
|
ifdef CONFIG_NO_BOOTMEM
|
||||||
|
|
24
mm/slab.c
24
mm/slab.c
|
@ -1558,7 +1558,7 @@ void __init kmem_cache_init(void)
|
||||||
* bug.
|
* bug.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sizes[INDEX_AC].cs_cachep = kmem_cache_create(names[INDEX_AC].name,
|
sizes[INDEX_AC].cs_cachep = __kmem_cache_create(names[INDEX_AC].name,
|
||||||
sizes[INDEX_AC].cs_size,
|
sizes[INDEX_AC].cs_size,
|
||||||
ARCH_KMALLOC_MINALIGN,
|
ARCH_KMALLOC_MINALIGN,
|
||||||
ARCH_KMALLOC_FLAGS|SLAB_PANIC,
|
ARCH_KMALLOC_FLAGS|SLAB_PANIC,
|
||||||
|
@ -1566,7 +1566,7 @@ void __init kmem_cache_init(void)
|
||||||
|
|
||||||
if (INDEX_AC != INDEX_L3) {
|
if (INDEX_AC != INDEX_L3) {
|
||||||
sizes[INDEX_L3].cs_cachep =
|
sizes[INDEX_L3].cs_cachep =
|
||||||
kmem_cache_create(names[INDEX_L3].name,
|
__kmem_cache_create(names[INDEX_L3].name,
|
||||||
sizes[INDEX_L3].cs_size,
|
sizes[INDEX_L3].cs_size,
|
||||||
ARCH_KMALLOC_MINALIGN,
|
ARCH_KMALLOC_MINALIGN,
|
||||||
ARCH_KMALLOC_FLAGS|SLAB_PANIC,
|
ARCH_KMALLOC_FLAGS|SLAB_PANIC,
|
||||||
|
@ -1584,14 +1584,14 @@ void __init kmem_cache_init(void)
|
||||||
* allow tighter packing of the smaller caches.
|
* allow tighter packing of the smaller caches.
|
||||||
*/
|
*/
|
||||||
if (!sizes->cs_cachep) {
|
if (!sizes->cs_cachep) {
|
||||||
sizes->cs_cachep = kmem_cache_create(names->name,
|
sizes->cs_cachep = __kmem_cache_create(names->name,
|
||||||
sizes->cs_size,
|
sizes->cs_size,
|
||||||
ARCH_KMALLOC_MINALIGN,
|
ARCH_KMALLOC_MINALIGN,
|
||||||
ARCH_KMALLOC_FLAGS|SLAB_PANIC,
|
ARCH_KMALLOC_FLAGS|SLAB_PANIC,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_ZONE_DMA
|
#ifdef CONFIG_ZONE_DMA
|
||||||
sizes->cs_dmacachep = kmem_cache_create(
|
sizes->cs_dmacachep = __kmem_cache_create(
|
||||||
names->name_dma,
|
names->name_dma,
|
||||||
sizes->cs_size,
|
sizes->cs_size,
|
||||||
ARCH_KMALLOC_MINALIGN,
|
ARCH_KMALLOC_MINALIGN,
|
||||||
|
@ -2220,7 +2220,7 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kmem_cache_create - Create a cache.
|
* __kmem_cache_create - Create a cache.
|
||||||
* @name: A string which is used in /proc/slabinfo to identify this cache.
|
* @name: A string which is used in /proc/slabinfo to identify this cache.
|
||||||
* @size: The size of objects to be created in this cache.
|
* @size: The size of objects to be created in this cache.
|
||||||
* @align: The required alignment for the objects.
|
* @align: The required alignment for the objects.
|
||||||
|
@ -2247,7 +2247,7 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp)
|
||||||
* as davem.
|
* as davem.
|
||||||
*/
|
*/
|
||||||
struct kmem_cache *
|
struct kmem_cache *
|
||||||
kmem_cache_create (const char *name, size_t size, size_t align,
|
__kmem_cache_create (const char *name, size_t size, size_t align,
|
||||||
unsigned long flags, void (*ctor)(void *))
|
unsigned long flags, void (*ctor)(void *))
|
||||||
{
|
{
|
||||||
size_t left_over, slab_size, ralign;
|
size_t left_over, slab_size, ralign;
|
||||||
|
@ -2388,7 +2388,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
|
||||||
/* Get cache's description obj. */
|
/* Get cache's description obj. */
|
||||||
cachep = kmem_cache_zalloc(&cache_cache, gfp);
|
cachep = kmem_cache_zalloc(&cache_cache, gfp);
|
||||||
if (!cachep)
|
if (!cachep)
|
||||||
goto oops;
|
return NULL;
|
||||||
|
|
||||||
cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids];
|
cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids];
|
||||||
cachep->object_size = size;
|
cachep->object_size = size;
|
||||||
|
@ -2445,8 +2445,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"kmem_cache_create: couldn't create cache %s.\n", name);
|
"kmem_cache_create: couldn't create cache %s.\n", name);
|
||||||
kmem_cache_free(&cache_cache, cachep);
|
kmem_cache_free(&cache_cache, cachep);
|
||||||
cachep = NULL;
|
return NULL;
|
||||||
goto oops;
|
|
||||||
}
|
}
|
||||||
slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t)
|
slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t)
|
||||||
+ sizeof(struct slab), align);
|
+ sizeof(struct slab), align);
|
||||||
|
@ -2504,8 +2503,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
|
||||||
|
|
||||||
if (setup_cpu_cache(cachep, gfp)) {
|
if (setup_cpu_cache(cachep, gfp)) {
|
||||||
__kmem_cache_destroy(cachep);
|
__kmem_cache_destroy(cachep);
|
||||||
cachep = NULL;
|
return NULL;
|
||||||
goto oops;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & SLAB_DEBUG_OBJECTS) {
|
if (flags & SLAB_DEBUG_OBJECTS) {
|
||||||
|
@ -2521,16 +2519,12 @@ kmem_cache_create (const char *name, size_t size, size_t align,
|
||||||
/* cache setup completed, link it into the list */
|
/* cache setup completed, link it into the list */
|
||||||
list_add(&cachep->list, &cache_chain);
|
list_add(&cachep->list, &cache_chain);
|
||||||
oops:
|
oops:
|
||||||
if (!cachep && (flags & SLAB_PANIC))
|
|
||||||
panic("kmem_cache_create(): failed to create slab `%s'\n",
|
|
||||||
name);
|
|
||||||
if (slab_is_available()) {
|
if (slab_is_available()) {
|
||||||
mutex_unlock(&cache_chain_mutex);
|
mutex_unlock(&cache_chain_mutex);
|
||||||
put_online_cpus();
|
put_online_cpus();
|
||||||
}
|
}
|
||||||
return cachep;
|
return cachep;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kmem_cache_create);
|
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
static void check_irq_off(void)
|
static void check_irq_off(void)
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Slab allocator functions that are independent of the allocator strategy
|
||||||
|
*
|
||||||
|
* (C) 2012 Christoph Lameter <cl@linux.com>
|
||||||
|
*/
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/poison.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/memory.h>
|
||||||
|
#include <linux/compiler.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
|
||||||
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/tlbflush.h>
|
||||||
|
#include <asm/page.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* kmem_cache_create - Create a cache.
|
||||||
|
* @name: A string which is used in /proc/slabinfo to identify this cache.
|
||||||
|
* @size: The size of objects to be created in this cache.
|
||||||
|
* @align: The required alignment for the objects.
|
||||||
|
* @flags: SLAB flags
|
||||||
|
* @ctor: A constructor for the objects.
|
||||||
|
*
|
||||||
|
* Returns a ptr to the cache on success, NULL on failure.
|
||||||
|
* Cannot be called within a interrupt, but can be interrupted.
|
||||||
|
* The @ctor is run when new pages are allocated by the cache.
|
||||||
|
*
|
||||||
|
* The flags are
|
||||||
|
*
|
||||||
|
* %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5)
|
||||||
|
* to catch references to uninitialised memory.
|
||||||
|
*
|
||||||
|
* %SLAB_RED_ZONE - Insert `Red' zones around the allocated memory to check
|
||||||
|
* for buffer overruns.
|
||||||
|
*
|
||||||
|
* %SLAB_HWCACHE_ALIGN - Align the objects in this cache to a hardware
|
||||||
|
* cacheline. This can be beneficial if you're counting cycles as closely
|
||||||
|
* as davem.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align,
|
||||||
|
unsigned long flags, void (*ctor)(void *))
|
||||||
|
{
|
||||||
|
struct kmem_cache *s = NULL;
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_VM
|
||||||
|
if (!name || in_interrupt() || size < sizeof(void *) ||
|
||||||
|
size > KMALLOC_MAX_SIZE) {
|
||||||
|
printk(KERN_ERR "kmem_cache_create(%s) integrity check"
|
||||||
|
" failed\n", name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
s = __kmem_cache_create(name, size, align, flags, ctor);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_VM
|
||||||
|
out:
|
||||||
|
#endif
|
||||||
|
if (!s && (flags & SLAB_PANIC))
|
||||||
|
panic("kmem_cache_create: Failed to create slab '%s'\n", name);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(kmem_cache_create);
|
|
@ -506,7 +506,7 @@ size_t ksize(const void *block)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ksize);
|
EXPORT_SYMBOL(ksize);
|
||||||
|
|
||||||
struct kmem_cache *kmem_cache_create(const char *name, size_t size,
|
struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
|
||||||
size_t align, unsigned long flags, void (*ctor)(void *))
|
size_t align, unsigned long flags, void (*ctor)(void *))
|
||||||
{
|
{
|
||||||
struct kmem_cache *c;
|
struct kmem_cache *c;
|
||||||
|
@ -529,13 +529,11 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
|
||||||
c->align = ARCH_SLAB_MINALIGN;
|
c->align = ARCH_SLAB_MINALIGN;
|
||||||
if (c->align < align)
|
if (c->align < align)
|
||||||
c->align = align;
|
c->align = align;
|
||||||
} else if (flags & SLAB_PANIC)
|
|
||||||
panic("Cannot create slab cache %s\n", name);
|
|
||||||
|
|
||||||
kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL);
|
kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL);
|
||||||
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kmem_cache_create);
|
|
||||||
|
|
||||||
void kmem_cache_destroy(struct kmem_cache *c)
|
void kmem_cache_destroy(struct kmem_cache *c)
|
||||||
{
|
{
|
||||||
|
|
11
mm/slub.c
11
mm/slub.c
|
@ -3920,15 +3920,12 @@ static struct kmem_cache *find_mergeable(size_t size,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct kmem_cache *kmem_cache_create(const char *name, size_t size,
|
struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
|
||||||
size_t align, unsigned long flags, void (*ctor)(void *))
|
size_t align, unsigned long flags, void (*ctor)(void *))
|
||||||
{
|
{
|
||||||
struct kmem_cache *s;
|
struct kmem_cache *s;
|
||||||
char *n;
|
char *n;
|
||||||
|
|
||||||
if (WARN_ON(!name))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
down_write(&slub_lock);
|
down_write(&slub_lock);
|
||||||
s = find_mergeable(size, align, flags, name, ctor);
|
s = find_mergeable(size, align, flags, name, ctor);
|
||||||
if (s) {
|
if (s) {
|
||||||
|
@ -3972,14 +3969,8 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
|
||||||
kfree(n);
|
kfree(n);
|
||||||
err:
|
err:
|
||||||
up_write(&slub_lock);
|
up_write(&slub_lock);
|
||||||
|
|
||||||
if (flags & SLAB_PANIC)
|
|
||||||
panic("Cannot create slabcache %s\n", name);
|
|
||||||
else
|
|
||||||
s = NULL;
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kmem_cache_create);
|
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue