SLUB: Fix dynamic dma kmalloc cache creation

The dynamic dma kmalloc creation can run into trouble if a
GFP_ATOMIC allocation is the first one performed for a certain size
of dma kmalloc slab.

- Move the adding of the slab to sysfs into a workqueue
(sysfs does GFP_KERNEL allocations)
- Do not call kmem_cache_destroy() (uses slub_lock)
- Only acquire the slub_lock once and--if we cannot wait--do a trylock.

This introduces a slight risk of the first kmalloc(x, GFP_DMA|GFP_ATOMIC)
for a range of sizes failing due to another process holding the slub_lock.
However, we only need to acquire the spinlock once in order to establish
each power of two DMA kmalloc cache. The possible conflict is with the
slub_lock taken during slab management actions (create / remove slab cache).

It is rather typical that a driver will first fill its buffers using
GFP_KERNEL allocations which will wait until the slub_lock can be acquired.
Drivers will also create its slab caches first outside of an atomic
context before starting to use atomic kmalloc from an interrupt context.

If there are any failures then they will occur early after boot or when
loading of multiple drivers concurrently. Drivers can already accomodate
failures of GFP_ATOMIC for other reasons. Retries will then create the slab.

Signed-off-by: Christoph Lameter <clameter@sgi.com>

+45 -14
+45 -14
mm/slub.c
··· 211 #define MAX_OBJECTS_PER_SLAB 65535 212 213 /* Internal SLUB flags */ 214 - #define __OBJECT_POISON 0x80000000 /* Poison object */ 215 216 /* Not all arches define cache_line_size */ 217 #ifndef cache_line_size ··· 2278 } 2279 2280 #ifdef CONFIG_ZONE_DMA 2281 static noinline struct kmem_cache *dma_kmalloc_cache(int index, gfp_t flags) 2282 { 2283 struct kmem_cache *s; 2284 - struct kmem_cache *x; 2285 char *text; 2286 size_t realsize; 2287 ··· 2306 return s; 2307 2308 /* Dynamically create dma cache */ 2309 - x = kmalloc(kmem_size, flags & ~SLUB_DMA); 2310 - if (!x) 2311 - panic("Unable to allocate memory for dma cache\n"); 2312 2313 realsize = kmalloc_caches[index].objsize; 2314 - text = kasprintf(flags & ~SLUB_DMA, "kmalloc_dma-%d", 2315 - (unsigned int)realsize); 2316 - s = create_kmalloc_cache(x, text, realsize, flags); 2317 - down_write(&slub_lock); 2318 - if (!kmalloc_caches_dma[index]) { 2319 - kmalloc_caches_dma[index] = s; 2320 - up_write(&slub_lock); 2321 - return s; 2322 } 2323 up_write(&slub_lock); 2324 - kmem_cache_destroy(s); 2325 return kmalloc_caches_dma[index]; 2326 } 2327 #endif
··· 211 #define MAX_OBJECTS_PER_SLAB 65535 212 213 /* Internal SLUB flags */ 214 + #define __OBJECT_POISON 0x80000000 /* Poison object */ 215 + #define __SYSFS_ADD_DEFERRED 0x40000000 /* Not yet visible via sysfs */ 216 217 /* Not all arches define cache_line_size */ 218 #ifndef cache_line_size ··· 2277 } 2278 2279 #ifdef CONFIG_ZONE_DMA 2280 + 2281 + static void sysfs_add_func(struct work_struct *w) 2282 + { 2283 + struct kmem_cache *s; 2284 + 2285 + down_write(&slub_lock); 2286 + list_for_each_entry(s, &slab_caches, list) { 2287 + if (s->flags & __SYSFS_ADD_DEFERRED) { 2288 + s->flags &= ~__SYSFS_ADD_DEFERRED; 2289 + sysfs_slab_add(s); 2290 + } 2291 + } 2292 + up_write(&slub_lock); 2293 + } 2294 + 2295 + static DECLARE_WORK(sysfs_add_work, sysfs_add_func); 2296 + 2297 static noinline struct kmem_cache *dma_kmalloc_cache(int index, gfp_t flags) 2298 { 2299 struct kmem_cache *s; 2300 char *text; 2301 size_t realsize; 2302 ··· 2289 return s; 2290 2291 /* Dynamically create dma cache */ 2292 + if (flags & __GFP_WAIT) 2293 + down_write(&slub_lock); 2294 + else { 2295 + if (!down_write_trylock(&slub_lock)) 2296 + goto out; 2297 + } 2298 + 2299 + if (kmalloc_caches_dma[index]) 2300 + goto unlock_out; 2301 2302 realsize = kmalloc_caches[index].objsize; 2303 + text = kasprintf(flags & ~SLUB_DMA, "kmalloc_dma-%d", (unsigned int)realsize), 2304 + s = kmalloc(kmem_size, flags & ~SLUB_DMA); 2305 + 2306 + if (!s || !text || !kmem_cache_open(s, flags, text, 2307 + realsize, ARCH_KMALLOC_MINALIGN, 2308 + SLAB_CACHE_DMA|__SYSFS_ADD_DEFERRED, NULL)) { 2309 + kfree(s); 2310 + kfree(text); 2311 + goto unlock_out; 2312 } 2313 + 2314 + list_add(&s->list, &slab_caches); 2315 + kmalloc_caches_dma[index] = s; 2316 + 2317 + schedule_work(&sysfs_add_work); 2318 + 2319 + unlock_out: 2320 up_write(&slub_lock); 2321 + out: 2322 return kmalloc_caches_dma[index]; 2323 } 2324 #endif