mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 13:22:23 +00:00
mm, sl[aou]b: Move kmem_cache_create mutex handling to common code
Move the mutex handling into the common kmem_cache_create() function. Then we can also move more checks out of SLAB's kmem_cache_create() into the common code. Reviewed-by: Glauber Costa <glommer@parallels.com> Signed-off-by: Christoph Lameter <cl@linux.com> Signed-off-by: Pekka Enberg <penberg@kernel.org>
This commit is contained in:
parent
18004c5d40
commit
20cea9683e
52
mm/slab.c
52
mm/slab.c
@ -2228,55 +2228,10 @@ __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;
|
||||||
struct kmem_cache *cachep = NULL, *pc;
|
struct kmem_cache *cachep = NULL;
|
||||||
gfp_t gfp;
|
gfp_t gfp;
|
||||||
|
|
||||||
/*
|
|
||||||
* Sanity checks... these are all serious usage bugs.
|
|
||||||
*/
|
|
||||||
if (!name || in_interrupt() || (size < BYTES_PER_WORD) ||
|
|
||||||
size > KMALLOC_MAX_SIZE) {
|
|
||||||
printk(KERN_ERR "%s: Early error in slab %s\n", __func__,
|
|
||||||
name);
|
|
||||||
BUG();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We use cache_chain_mutex to ensure a consistent view of
|
|
||||||
* cpu_online_mask as well. Please see cpuup_callback
|
|
||||||
*/
|
|
||||||
if (slab_is_available()) {
|
|
||||||
get_online_cpus();
|
|
||||||
mutex_lock(&slab_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry(pc, &slab_caches, list) {
|
|
||||||
char tmp;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This happens when the module gets unloaded and doesn't
|
|
||||||
* destroy its slab cache and no-one else reuses the vmalloc
|
|
||||||
* area of the module. Print a warning.
|
|
||||||
*/
|
|
||||||
res = probe_kernel_address(pc->name, tmp);
|
|
||||||
if (res) {
|
|
||||||
printk(KERN_ERR
|
|
||||||
"SLAB: cache with size %d has lost its name\n",
|
|
||||||
pc->size);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(pc->name, name)) {
|
|
||||||
printk(KERN_ERR
|
|
||||||
"kmem_cache_create: duplicate cache %s\n", name);
|
|
||||||
dump_stack();
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
WARN_ON(strchr(name, ' ')); /* It confuses parsers */
|
|
||||||
#if FORCED_DEBUG
|
#if FORCED_DEBUG
|
||||||
/*
|
/*
|
||||||
* Enable redzoning and last user accounting, except for caches with
|
* Enable redzoning and last user accounting, except for caches with
|
||||||
@ -2495,11 +2450,6 @@ __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, &slab_caches);
|
list_add(&cachep->list, &slab_caches);
|
||||||
oops:
|
|
||||||
if (slab_is_available()) {
|
|
||||||
mutex_unlock(&slab_mutex);
|
|
||||||
put_online_cpus();
|
|
||||||
}
|
|
||||||
return cachep;
|
return cachep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,8 @@
|
|||||||
#include <linux/memory.h>
|
#include <linux/memory.h>
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/cpu.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/tlbflush.h>
|
#include <asm/tlbflush.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
@ -61,8 +62,46 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
get_online_cpus();
|
||||||
|
mutex_lock(&slab_mutex);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_VM
|
||||||
|
list_for_each_entry(s, &slab_caches, list) {
|
||||||
|
char tmp;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This happens when the module gets unloaded and doesn't
|
||||||
|
* destroy its slab cache and no-one else reuses the vmalloc
|
||||||
|
* area of the module. Print a warning.
|
||||||
|
*/
|
||||||
|
res = probe_kernel_address(s->name, tmp);
|
||||||
|
if (res) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"Slab cache with size %d has lost its name\n",
|
||||||
|
s->object_size);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(s->name, name)) {
|
||||||
|
printk(KERN_ERR "kmem_cache_create(%s): Cache name"
|
||||||
|
" already exists.\n",
|
||||||
|
name);
|
||||||
|
dump_stack();
|
||||||
|
s = NULL;
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WARN_ON(strchr(name, ' ')); /* It confuses parsers */
|
||||||
|
#endif
|
||||||
|
|
||||||
s = __kmem_cache_create(name, size, align, flags, ctor);
|
s = __kmem_cache_create(name, size, align, flags, ctor);
|
||||||
|
|
||||||
|
oops:
|
||||||
|
mutex_unlock(&slab_mutex);
|
||||||
|
put_online_cpus();
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_VM
|
#ifdef CONFIG_DEBUG_VM
|
||||||
out:
|
out:
|
||||||
#endif
|
#endif
|
||||||
|
28
mm/slub.c
28
mm/slub.c
@ -3911,7 +3911,6 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
|
|||||||
struct kmem_cache *s;
|
struct kmem_cache *s;
|
||||||
char *n;
|
char *n;
|
||||||
|
|
||||||
mutex_lock(&slab_mutex);
|
|
||||||
s = find_mergeable(size, align, flags, name, ctor);
|
s = find_mergeable(size, align, flags, name, ctor);
|
||||||
if (s) {
|
if (s) {
|
||||||
s->refcount++;
|
s->refcount++;
|
||||||
@ -3924,37 +3923,36 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
|
|||||||
|
|
||||||
if (sysfs_slab_alias(s, name)) {
|
if (sysfs_slab_alias(s, name)) {
|
||||||
s->refcount--;
|
s->refcount--;
|
||||||
goto err;
|
return NULL;
|
||||||
}
|
}
|
||||||
mutex_unlock(&slab_mutex);
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = kstrdup(name, GFP_KERNEL);
|
n = kstrdup(name, GFP_KERNEL);
|
||||||
if (!n)
|
if (!n)
|
||||||
goto err;
|
return NULL;
|
||||||
|
|
||||||
s = kmalloc(kmem_size, GFP_KERNEL);
|
s = kmalloc(kmem_size, GFP_KERNEL);
|
||||||
if (s) {
|
if (s) {
|
||||||
if (kmem_cache_open(s, n,
|
if (kmem_cache_open(s, n,
|
||||||
size, align, flags, ctor)) {
|
size, align, flags, ctor)) {
|
||||||
|
int r;
|
||||||
|
|
||||||
list_add(&s->list, &slab_caches);
|
list_add(&s->list, &slab_caches);
|
||||||
mutex_unlock(&slab_mutex);
|
mutex_unlock(&slab_mutex);
|
||||||
if (sysfs_slab_add(s)) {
|
r = sysfs_slab_add(s);
|
||||||
mutex_lock(&slab_mutex);
|
mutex_lock(&slab_mutex);
|
||||||
list_del(&s->list);
|
|
||||||
kfree(n);
|
if (!r)
|
||||||
kfree(s);
|
return s;
|
||||||
goto err;
|
|
||||||
}
|
list_del(&s->list);
|
||||||
return s;
|
kmem_cache_close(s);
|
||||||
}
|
}
|
||||||
kfree(s);
|
kfree(s);
|
||||||
}
|
}
|
||||||
kfree(n);
|
kfree(n);
|
||||||
err:
|
return NULL;
|
||||||
mutex_unlock(&slab_mutex);
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
Loading…
Reference in New Issue
Block a user