diff options
-rw-r--r-- | mm/slab.c | 33 |
1 files changed, 28 insertions, 5 deletions
@@ -3418,7 +3418,7 @@ const char *kmem_cache_name(struct kmem_cache *cachep) | |||
3418 | EXPORT_SYMBOL_GPL(kmem_cache_name); | 3418 | EXPORT_SYMBOL_GPL(kmem_cache_name); |
3419 | 3419 | ||
3420 | /* | 3420 | /* |
3421 | * This initializes kmem_list3 for all nodes. | 3421 | * This initializes kmem_list3 or resizes varioius caches for all nodes. |
3422 | */ | 3422 | */ |
3423 | static int alloc_kmemlist(struct kmem_cache *cachep) | 3423 | static int alloc_kmemlist(struct kmem_cache *cachep) |
3424 | { | 3424 | { |
@@ -3433,10 +3433,13 @@ static int alloc_kmemlist(struct kmem_cache *cachep) | |||
3433 | if (!new_alien) | 3433 | if (!new_alien) |
3434 | goto fail; | 3434 | goto fail; |
3435 | 3435 | ||
3436 | new_shared = alloc_arraycache(node, cachep->shared*cachep->batchcount, | 3436 | new_shared = alloc_arraycache(node, |
3437 | cachep->shared*cachep->batchcount, | ||
3437 | 0xbaadf00d); | 3438 | 0xbaadf00d); |
3438 | if (!new_shared) | 3439 | if (!new_shared) { |
3440 | free_alien_cache(new_alien); | ||
3439 | goto fail; | 3441 | goto fail; |
3442 | } | ||
3440 | 3443 | ||
3441 | l3 = cachep->nodelists[node]; | 3444 | l3 = cachep->nodelists[node]; |
3442 | if (l3) { | 3445 | if (l3) { |
@@ -3445,7 +3448,8 @@ static int alloc_kmemlist(struct kmem_cache *cachep) | |||
3445 | spin_lock_irq(&l3->list_lock); | 3448 | spin_lock_irq(&l3->list_lock); |
3446 | 3449 | ||
3447 | if (shared) | 3450 | if (shared) |
3448 | free_block(cachep, shared->entry, shared->avail, node); | 3451 | free_block(cachep, shared->entry, |
3452 | shared->avail, node); | ||
3449 | 3453 | ||
3450 | l3->shared = new_shared; | 3454 | l3->shared = new_shared; |
3451 | if (!l3->alien) { | 3455 | if (!l3->alien) { |
@@ -3460,8 +3464,11 @@ static int alloc_kmemlist(struct kmem_cache *cachep) | |||
3460 | continue; | 3464 | continue; |
3461 | } | 3465 | } |
3462 | l3 = kmalloc_node(sizeof(struct kmem_list3), GFP_KERNEL, node); | 3466 | l3 = kmalloc_node(sizeof(struct kmem_list3), GFP_KERNEL, node); |
3463 | if (!l3) | 3467 | if (!l3) { |
3468 | free_alien_cache(new_alien); | ||
3469 | kfree(new_shared); | ||
3464 | goto fail; | 3470 | goto fail; |
3471 | } | ||
3465 | 3472 | ||
3466 | kmem_list3_init(l3); | 3473 | kmem_list3_init(l3); |
3467 | l3->next_reap = jiffies + REAPTIMEOUT_LIST3 + | 3474 | l3->next_reap = jiffies + REAPTIMEOUT_LIST3 + |
@@ -3473,7 +3480,23 @@ static int alloc_kmemlist(struct kmem_cache *cachep) | |||
3473 | cachep->nodelists[node] = l3; | 3480 | cachep->nodelists[node] = l3; |
3474 | } | 3481 | } |
3475 | return 0; | 3482 | return 0; |
3483 | |||
3476 | fail: | 3484 | fail: |
3485 | if (!cachep->next.next) { | ||
3486 | /* Cache is not active yet. Roll back what we did */ | ||
3487 | node--; | ||
3488 | while (node >= 0) { | ||
3489 | if (cachep->nodelists[node]) { | ||
3490 | l3 = cachep->nodelists[node]; | ||
3491 | |||
3492 | kfree(l3->shared); | ||
3493 | free_alien_cache(l3->alien); | ||
3494 | kfree(l3); | ||
3495 | cachep->nodelists[node] = NULL; | ||
3496 | } | ||
3497 | node--; | ||
3498 | } | ||
3499 | } | ||
3477 | return -ENOMEM; | 3500 | return -ENOMEM; |
3478 | } | 3501 | } |
3479 | 3502 | ||