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 | |
| 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>
| -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 | } |
