|
@@ -1502,6 +1502,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
|
|
|
{
|
|
|
size_t left_over, slab_size, ralign;
|
|
|
kmem_cache_t *cachep = NULL;
|
|
|
+ struct list_head *p;
|
|
|
|
|
|
/*
|
|
|
* Sanity checks... these are all serious usage bugs.
|
|
@@ -1516,6 +1517,35 @@ kmem_cache_create (const char *name, size_t size, size_t align,
|
|
|
BUG();
|
|
|
}
|
|
|
|
|
|
+ down(&cache_chain_sem);
|
|
|
+
|
|
|
+ list_for_each(p, &cache_chain) {
|
|
|
+ kmem_cache_t *pc = list_entry(p, kmem_cache_t, next);
|
|
|
+ mm_segment_t old_fs = get_fs();
|
|
|
+ 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.
|
|
|
+ */
|
|
|
+ set_fs(KERNEL_DS);
|
|
|
+ res = __get_user(tmp, pc->name);
|
|
|
+ set_fs(old_fs);
|
|
|
+ if (res) {
|
|
|
+ printk("SLAB: cache with size %d has lost its name\n",
|
|
|
+ pc->objsize);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!strcmp(pc->name,name)) {
|
|
|
+ printk("kmem_cache_create: duplicate cache %s\n", name);
|
|
|
+ dump_stack();
|
|
|
+ goto oops;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
#if DEBUG
|
|
|
WARN_ON(strchr(name, ' ')); /* It confuses parsers */
|
|
|
if ((flags & SLAB_DEBUG_INITIAL) && !ctor) {
|
|
@@ -1592,7 +1622,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
|
|
|
/* Get cache's description obj. */
|
|
|
cachep = (kmem_cache_t *) kmem_cache_alloc(&cache_cache, SLAB_KERNEL);
|
|
|
if (!cachep)
|
|
|
- goto opps;
|
|
|
+ goto oops;
|
|
|
memset(cachep, 0, sizeof(kmem_cache_t));
|
|
|
|
|
|
#if DEBUG
|
|
@@ -1686,7 +1716,7 @@ next:
|
|
|
printk("kmem_cache_create: couldn't create cache %s.\n", name);
|
|
|
kmem_cache_free(&cache_cache, cachep);
|
|
|
cachep = NULL;
|
|
|
- goto opps;
|
|
|
+ goto oops;
|
|
|
}
|
|
|
slab_size = ALIGN(cachep->num*sizeof(kmem_bufctl_t)
|
|
|
+ sizeof(struct slab), align);
|
|
@@ -1781,43 +1811,14 @@ next:
|
|
|
cachep->limit = BOOT_CPUCACHE_ENTRIES;
|
|
|
}
|
|
|
|
|
|
- /* Need the semaphore to access the chain. */
|
|
|
- down(&cache_chain_sem);
|
|
|
- {
|
|
|
- struct list_head *p;
|
|
|
- mm_segment_t old_fs;
|
|
|
-
|
|
|
- old_fs = get_fs();
|
|
|
- set_fs(KERNEL_DS);
|
|
|
- list_for_each(p, &cache_chain) {
|
|
|
- kmem_cache_t *pc = list_entry(p, kmem_cache_t, next);
|
|
|
- char tmp;
|
|
|
- /* This happens when the module gets unloaded and doesn't
|
|
|
- destroy its slab cache and noone else reuses the vmalloc
|
|
|
- area of the module. Print a warning. */
|
|
|
- if (__get_user(tmp,pc->name)) {
|
|
|
- printk("SLAB: cache with size %d has lost its name\n",
|
|
|
- pc->objsize);
|
|
|
- continue;
|
|
|
- }
|
|
|
- if (!strcmp(pc->name,name)) {
|
|
|
- printk("kmem_cache_create: duplicate cache %s\n",name);
|
|
|
- up(&cache_chain_sem);
|
|
|
- unlock_cpu_hotplug();
|
|
|
- BUG();
|
|
|
- }
|
|
|
- }
|
|
|
- set_fs(old_fs);
|
|
|
- }
|
|
|
-
|
|
|
/* cache setup completed, link it into the list */
|
|
|
list_add(&cachep->next, &cache_chain);
|
|
|
- up(&cache_chain_sem);
|
|
|
unlock_cpu_hotplug();
|
|
|
-opps:
|
|
|
+oops:
|
|
|
if (!cachep && (flags & SLAB_PANIC))
|
|
|
panic("kmem_cache_create(): failed to create slab `%s'\n",
|
|
|
name);
|
|
|
+ up(&cache_chain_sem);
|
|
|
return cachep;
|
|
|
}
|
|
|
EXPORT_SYMBOL(kmem_cache_create);
|