Re: [PATCH] scsi: fix sense_slab/bio swapping livelock

From: Pekka J Enberg
Date: Mon Apr 07 2008 - 18:05:29 EST


On Tue, 8 Apr 2008, Pekka Enberg wrote:
> Actually, a trivial way to implement that is to have a few "emergency kmalloc"
> caches say for sizes 64, 128, 256, and 512 that have some pre-allocated pages
> into which these GFP_TEMPORARY allocations are allowed to dip into on OOM and
> OOM only.

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,"
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/