diff options
author | Christoph Lameter <cl@linux-foundation.org> | 2010-07-19 12:39:11 -0400 |
---|---|---|
committer | Pekka Enberg <penberg@cs.helsinki.fi> | 2010-08-03 00:28:32 -0400 |
commit | 2bce64858442149784f6c8803c9095a8556320a2 (patch) | |
tree | f9a097d8da73f33703622d8ef4237997248b6f39 /mm/slub.c | |
parent | e438444de82f354563d46ee5d991b5916dd19b01 (diff) |
slub: Allow removal of slab caches during boot
Serialize kmem_cache_create and kmem_cache_destroy using the slub_lock. Only
possible after the use of the slub_lock during dynamic dma creation has been
removed.
Then make sure that the setup of the slab sysfs entries does not race
with kmem_cache_create and kmem_cache destroy.
If a slab cache is removed before we have setup sysfs then simply skip over
the sysfs handling.
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Roland Dreier <rdreier@cisco.com>
Signed-off-by: Christoph Lameter <cl@linux-foundation.org>
Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
Diffstat (limited to 'mm/slub.c')
-rw-r--r-- | mm/slub.c | 24 |
1 files changed, 15 insertions, 9 deletions
@@ -2491,7 +2491,6 @@ void kmem_cache_destroy(struct kmem_cache *s) | |||
2491 | s->refcount--; | 2491 | s->refcount--; |
2492 | if (!s->refcount) { | 2492 | if (!s->refcount) { |
2493 | list_del(&s->list); | 2493 | list_del(&s->list); |
2494 | up_write(&slub_lock); | ||
2495 | if (kmem_cache_close(s)) { | 2494 | if (kmem_cache_close(s)) { |
2496 | printk(KERN_ERR "SLUB %s: %s called for cache that " | 2495 | printk(KERN_ERR "SLUB %s: %s called for cache that " |
2497 | "still has objects.\n", s->name, __func__); | 2496 | "still has objects.\n", s->name, __func__); |
@@ -2500,8 +2499,8 @@ void kmem_cache_destroy(struct kmem_cache *s) | |||
2500 | if (s->flags & SLAB_DESTROY_BY_RCU) | 2499 | if (s->flags & SLAB_DESTROY_BY_RCU) |
2501 | rcu_barrier(); | 2500 | rcu_barrier(); |
2502 | sysfs_slab_remove(s); | 2501 | sysfs_slab_remove(s); |
2503 | } else | 2502 | } |
2504 | up_write(&slub_lock); | 2503 | up_write(&slub_lock); |
2505 | } | 2504 | } |
2506 | EXPORT_SYMBOL(kmem_cache_destroy); | 2505 | EXPORT_SYMBOL(kmem_cache_destroy); |
2507 | 2506 | ||
@@ -3227,14 +3226,12 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, | |||
3227 | */ | 3226 | */ |
3228 | s->objsize = max(s->objsize, (int)size); | 3227 | s->objsize = max(s->objsize, (int)size); |
3229 | s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *))); | 3228 | s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *))); |
3230 | up_write(&slub_lock); | ||
3231 | 3229 | ||
3232 | if (sysfs_slab_alias(s, name)) { | 3230 | if (sysfs_slab_alias(s, name)) { |
3233 | down_write(&slub_lock); | ||
3234 | s->refcount--; | 3231 | s->refcount--; |
3235 | up_write(&slub_lock); | ||
3236 | goto err; | 3232 | goto err; |
3237 | } | 3233 | } |
3234 | up_write(&slub_lock); | ||
3238 | return s; | 3235 | return s; |
3239 | } | 3236 | } |
3240 | 3237 | ||
@@ -3243,14 +3240,12 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, | |||
3243 | if (kmem_cache_open(s, GFP_KERNEL, name, | 3240 | if (kmem_cache_open(s, GFP_KERNEL, name, |
3244 | size, align, flags, ctor)) { | 3241 | size, align, flags, ctor)) { |
3245 | list_add(&s->list, &slab_caches); | 3242 | list_add(&s->list, &slab_caches); |
3246 | up_write(&slub_lock); | ||
3247 | if (sysfs_slab_add(s)) { | 3243 | if (sysfs_slab_add(s)) { |
3248 | down_write(&slub_lock); | ||
3249 | list_del(&s->list); | 3244 | list_del(&s->list); |
3250 | up_write(&slub_lock); | ||
3251 | kfree(s); | 3245 | kfree(s); |
3252 | goto err; | 3246 | goto err; |
3253 | } | 3247 | } |
3248 | up_write(&slub_lock); | ||
3254 | return s; | 3249 | return s; |
3255 | } | 3250 | } |
3256 | kfree(s); | 3251 | kfree(s); |
@@ -4498,6 +4493,13 @@ static int sysfs_slab_add(struct kmem_cache *s) | |||
4498 | 4493 | ||
4499 | static void sysfs_slab_remove(struct kmem_cache *s) | 4494 | static void sysfs_slab_remove(struct kmem_cache *s) |
4500 | { | 4495 | { |
4496 | if (slab_state < SYSFS) | ||
4497 | /* | ||
4498 | * Sysfs has not been setup yet so no need to remove the | ||
4499 | * cache from sysfs. | ||
4500 | */ | ||
4501 | return; | ||
4502 | |||
4501 | kobject_uevent(&s->kobj, KOBJ_REMOVE); | 4503 | kobject_uevent(&s->kobj, KOBJ_REMOVE); |
4502 | kobject_del(&s->kobj); | 4504 | kobject_del(&s->kobj); |
4503 | kobject_put(&s->kobj); | 4505 | kobject_put(&s->kobj); |
@@ -4543,8 +4545,11 @@ static int __init slab_sysfs_init(void) | |||
4543 | struct kmem_cache *s; | 4545 | struct kmem_cache *s; |
4544 | int err; | 4546 | int err; |
4545 | 4547 | ||
4548 | down_write(&slub_lock); | ||
4549 | |||
4546 | slab_kset = kset_create_and_add("slab", &slab_uevent_ops, kernel_kobj); | 4550 | slab_kset = kset_create_and_add("slab", &slab_uevent_ops, kernel_kobj); |
4547 | if (!slab_kset) { | 4551 | if (!slab_kset) { |
4552 | up_write(&slub_lock); | ||
4548 | printk(KERN_ERR "Cannot register slab subsystem.\n"); | 4553 | printk(KERN_ERR "Cannot register slab subsystem.\n"); |
4549 | return -ENOSYS; | 4554 | return -ENOSYS; |
4550 | } | 4555 | } |
@@ -4569,6 +4574,7 @@ static int __init slab_sysfs_init(void) | |||
4569 | kfree(al); | 4574 | kfree(al); |
4570 | } | 4575 | } |
4571 | 4576 | ||
4577 | up_write(&slub_lock); | ||
4572 | resiliency_test(); | 4578 | resiliency_test(); |
4573 | return 0; | 4579 | return 0; |
4574 | } | 4580 | } |