--- include/linux/slub_def.h | 1 + mm/slub.c | 25 ++++++++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) Index: linux-2.6/mm/slub.c =================================================================== --- linux-2.6.orig/mm/slub.c 2008-04-04 14:28:14.000000000 -0700 +++ linux-2.6/mm/slub.c 2008-04-04 14:30:08.000000000 -0700 @@ -2930,6 +2930,7 @@ int kmem_cache_defrag(int node) { struct kmem_cache *s; unsigned long slabs = 0; + unsigned long reclaimed; /* * kmem_cache_defrag may be called from the reclaim path which may be @@ -2941,14 +2942,32 @@ int kmem_cache_defrag(int node) return 0; list_for_each_entry(s, &slab_caches, list) { + + if (time_before(jiffies, s->next_defrag)) + continue; + + /* + * Defragmentable caches come first. If the slab cache is not + * defragmentable then we can stop traversing the list. + */ + if (!s->kick) + break; + if (node == -1) { int nid; for_each_node_state(nid, N_NORMAL_MEMORY) - slabs += __kmem_cache_shrink(s, nid, + reclaimed = __kmem_cache_shrink(s, nid, MAX_PARTIAL); } else - slabs += __kmem_cache_shrink(s, node, MAX_PARTIAL); + reclaimed = __kmem_cache_shrink(s, node, MAX_PARTIAL); + + if (reclaimed) + s->next_defrag = jiffies + HZ / 10; + else + s->next_defrag = jiffies + HZ; + + slabs += reclaimed; } up_read(&slub_lock); return slabs; @@ -3036,7 +3055,7 @@ static int slab_mem_going_online_callbac return 0; /* - * We are bringing a node online. No memory is availabe yet. We must + * We are bringing a node online. No memory is available yet. We must * allocate a kmem_cache_node structure in order to bring the node * online. */ Index: linux-2.6/include/linux/slub_def.h =================================================================== --- linux-2.6.orig/include/linux/slub_def.h 2008-04-04 14:28:12.000000000 -0700 +++ linux-2.6/include/linux/slub_def.h 2008-04-04 14:29:34.000000000 -0700 @@ -85,6 +85,7 @@ struct kmem_cache { struct kmem_cache_order_objects min; gfp_t allocflags; /* gfp flags to use on each alloc */ int refcount; /* Refcount for slab cache destroy */ + unsigned long next_defrag; void (*ctor)(struct kmem_cache *, void *); /* * Called with slab lock held and interrupts disabled.