On Tue, 8 Apr 2008, Pekka Enberg wrote:So something like the following (totally untested) patch modulo the pre-allocation bits. Pekka diff --git a/mm/slub.c b/mm/slub.c index acc975f..e8f7cf3 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -264,6 +264,67 @@ static inline void stat(struct kmem_cache_cpu *c, enum stat_item si) #endif } +/* + * Emergency caches are for GFP_TEMPORARY allocations to dip into when we're + * OOM to make sure we can make some progress for writeback. + */ + +#define MIN_EMERGENCY_SIZE 32 +#define NR_EMERGENCY_CACHES 4 + +struct kmem_cache *emergency_caches[NR_EMERGENCY_CACHES]; + +static void init_emergency_caches(void) +{ + unsigned long size = MIN_EMERGENCY_SIZE; + int i; + + for (i = 0; i < NR_EMERGENCY_CACHES; i++) { + struct kmem_cache *cache; + char *name; + + name = kasprintf(GFP_KERNEL, "kmalloc-%d", 1 << i); + BUG_ON(!name); + + cache = kmem_cache_create(name, size, 0, 0, NULL); + BUG_ON(!cache); + kfree(name); + + emergency_caches[i] = cache; + + size *= 2; + } +} + +static struct kmem_cache *lookup_emergency_cache(unsigned long size) +{ + unsigned long cache_size = MIN_EMERGENCY_SIZE; + int i; + + for (i = 0; i < NR_EMERGENCY_CACHES; i++) { + if (size < cache_size) + return emergency_caches[i]; + + cache_size *= 2; + } + return NULL; +} + +static void *emergency_alloc(struct kmem_cache *cache, gfp_t gfp) +{ + struct kmem_cache *emergency_cache; + void *p; + + emergency_cache = lookup_emergency_cache(cache->objsize); + if (!emergency_cache) + return NULL; + + p = kmem_cache_alloc(emergency_cache, gfp); + if (p && cache->ctor) + cache->ctor(cache, p); + return p; +} + /******************************************************************** * Core slab cache functions *******************************************************************/ @@ -1528,6 +1589,9 @@ new_slab: goto load_freelist; } + if ((gfpflags & GFP_TEMPORARY) == GFP_TEMPORARY) + return emergency_alloc(s, gfpflags); + /* * No memory available. * @@ -2970,6 +3034,7 @@ void __init kmem_cache_init(void) #else kmem_size = sizeof(struct kmem_cache); #endif + init_emergency_caches(); printk(KERN_INFO "SLUB: Genslabs=%d, HWalign=%d, Order=%d-%d, MinObjects=%d," --
| Ingo Molnar | Re: Dual-Licensing Linux Kernel with GPL V2 and GPL V3 |
| Greg Kroah-Hartman | [PATCH 001/196] Chinese: Add the known_regression URI to the HOWTO |
| Roland Dreier | Re: Integration of SCST in the mainstream Linux kernel |
git: | |
| David Miller | Re: [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
| Arjan van de Ven | Re: [GIT]: Networking |
| Linus Torvalds | Re: iptables very slow after commit 784544739a25c30637397ace5489eeb6e15d7d49 |
