aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2009-06-15 06:35:10 -0400
committerPekka Enberg <penberg@cs.helsinki.fi>2009-06-15 06:55:26 -0400
commit964cf35c88f93b4927dbc4e950dfa4d880c7f9d1 (patch)
treea5be2d66c2a53e9483007f7581bb5170f50d6ff7 /mm
parent45e3e1935e2857c54783291107d33323b3ef33c8 (diff)
SLUB: Fix early boot GFP_DMA allocations
Recent change to use slab allocations earlier exposed a bug where SLUB can call schedule_work and try to call sysfs before it is safe to do so. Reported-by: Heiko Carstens <heiko.carstens@de.ibm.com> Tested-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Nick Piggin <npiggin@suse.de> Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
Diffstat (limited to 'mm')
-rw-r--r--mm/slub.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/mm/slub.c b/mm/slub.c
index 30354bfeb43..dcbfda0b02e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2610,6 +2610,7 @@ static noinline struct kmem_cache *dma_kmalloc_cache(int index, gfp_t flags)
2610 struct kmem_cache *s; 2610 struct kmem_cache *s;
2611 char *text; 2611 char *text;
2612 size_t realsize; 2612 size_t realsize;
2613 unsigned long slabflags;
2613 2614
2614 s = kmalloc_caches_dma[index]; 2615 s = kmalloc_caches_dma[index];
2615 if (s) 2616 if (s)
@@ -2631,9 +2632,18 @@ static noinline struct kmem_cache *dma_kmalloc_cache(int index, gfp_t flags)
2631 (unsigned int)realsize); 2632 (unsigned int)realsize);
2632 s = kmalloc(kmem_size, flags & ~SLUB_DMA); 2633 s = kmalloc(kmem_size, flags & ~SLUB_DMA);
2633 2634
2635 /*
2636 * Must defer sysfs creation to a workqueue because we don't know
2637 * what context we are called from. Before sysfs comes up, we don't
2638 * need to do anything because our sysfs initcall will start by
2639 * adding all existing slabs to sysfs.
2640 */
2641 slabflags = SLAB_CACHE_DMA;
2642 if (slab_state >= SYSFS)
2643 slabflags |= __SYSFS_ADD_DEFERRED;
2644
2634 if (!s || !text || !kmem_cache_open(s, flags, text, 2645 if (!s || !text || !kmem_cache_open(s, flags, text,
2635 realsize, ARCH_KMALLOC_MINALIGN, 2646 realsize, ARCH_KMALLOC_MINALIGN, slabflags, NULL)) {
2636 SLAB_CACHE_DMA|__SYSFS_ADD_DEFERRED, NULL)) {
2637 kfree(s); 2647 kfree(s);
2638 kfree(text); 2648 kfree(text);
2639 goto unlock_out; 2649 goto unlock_out;
@@ -2642,7 +2652,8 @@ static noinline struct kmem_cache *dma_kmalloc_cache(int index, gfp_t flags)
2642 list_add(&s->list, &slab_caches); 2652 list_add(&s->list, &slab_caches);
2643 kmalloc_caches_dma[index] = s; 2653 kmalloc_caches_dma[index] = s;
2644 2654
2645 schedule_work(&sysfs_add_work); 2655 if (slab_state >= SYSFS)
2656 schedule_work(&sysfs_add_work);
2646 2657
2647unlock_out: 2658unlock_out:
2648 up_write(&slub_lock); 2659 up_write(&slub_lock);