aboutsummaryrefslogtreecommitdiffstats
path: root/mm/slub.c
diff options
context:
space:
mode:
authorDavid Rientjes <rientjes@google.com>2008-12-18 01:09:46 -0500
committerPekka Enberg <penberg@cs.helsinki.fi>2008-12-29 04:40:58 -0500
commit7b8f3b66d9d7e5f021ae535620b9b52833f4876e (patch)
tree0495da27c549f9abd8bcb75c158edf20e35ca711 /mm/slub.c
parentdfcd3610289132a762b7dc0eaf33998262cd9e20 (diff)
slub: avoid leaking caches or refcounts on sysfs error
If a slab cache is mergeable and the sysfs alias cannot be added, the target cache shall have its refcount decremented. kmem_cache_create() will return NULL, so if kmem_cache_destroy() is ever called on the target cache, it will never be freed if the refcount has been leaked. Likewise, if a slab cache is not mergeable and the sysfs link cannot be added, the new cache shall be removed from the slab_caches list. kmem_cache_create() will return NULL, so it will be impossible to call kmem_cache_destroy() on it. Both of these operations require slub_lock since refcount of all slab caches and slab_caches are protected by the lock. In the mergeable case, it would be better to restore objsize and offset back to their original values, but this could race with another merge since slub_lock was dropped. Cc: Christoph Lameter <cl@linux-foundation.org> Signed-off-by: David Rientjes <rientjes@google.com> Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
Diffstat (limited to 'mm/slub.c')
-rw-r--r--mm/slub.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/mm/slub.c b/mm/slub.c
index 704cfa34f9ab..d057ceb3645f 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -3124,8 +3124,12 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
3124 s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *))); 3124 s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *)));
3125 up_write(&slub_lock); 3125 up_write(&slub_lock);
3126 3126
3127 if (sysfs_slab_alias(s, name)) 3127 if (sysfs_slab_alias(s, name)) {
3128 down_write(&slub_lock);
3129 s->refcount--;
3130 up_write(&slub_lock);
3128 goto err; 3131 goto err;
3132 }
3129 return s; 3133 return s;
3130 } 3134 }
3131 3135
@@ -3135,8 +3139,13 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
3135 size, align, flags, ctor)) { 3139 size, align, flags, ctor)) {
3136 list_add(&s->list, &slab_caches); 3140 list_add(&s->list, &slab_caches);
3137 up_write(&slub_lock); 3141 up_write(&slub_lock);
3138 if (sysfs_slab_add(s)) 3142 if (sysfs_slab_add(s)) {
3143 down_write(&slub_lock);
3144 list_del(&s->list);
3145 up_write(&slub_lock);
3146 kfree(s);
3139 goto err; 3147 goto err;
3148 }
3140 return s; 3149 return s;
3141 } 3150 }
3142 kfree(s); 3151 kfree(s);