--- mm/slub.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) Index: slub/mm/slub.c =================================================================== --- slub.orig/mm/slub.c 2007-05-20 17:45:52.000000000 -0700 +++ slub/mm/slub.c 2007-05-20 17:46:53.000000000 -0700 @@ -2536,17 +2536,28 @@ int kmem_cache_shrink(struct kmem_cache kmalloc(sizeof(struct list_head) * s->objects, GFP_KERNEL); unsigned long flags; LIST_HEAD(zaplist); + unsigned long t0; + unsigned long t0_partial; + unsigned long discarded; + unsigned long defrag_success; + unsigned long defrag_fail; if (!slabs_by_inuse) return -ENOMEM; flush_all(s); for_each_online_node(node) { + t0 = jiffies; n = get_node(s, node); if (!n->nr_partial) continue; + t0_partial = n->nr_partial; + discarded = 0; + defrag_success = 0; + defrag_fail = 0; + for (i = 0; i < s->objects; i++) INIT_LIST_HEAD(slabs_by_inuse + i); @@ -2559,7 +2570,9 @@ int kmem_cache_shrink(struct kmem_cache * list_lock. page->inuse here is the upper limit. */ list_for_each_entry_safe(page, t, &n->partial, lru) { - if (!page->inuse && slab_trylock(page)) { + int inuse = page->inuse; + + if (!inuse && slab_trylock(page)) { /* * Must hold slab lock here because slab_free * may have freed the last object and be @@ -2569,10 +2582,12 @@ int kmem_cache_shrink(struct kmem_cache n->nr_partial--; slab_unlock(page); discard_slab(s, page); - } else { - if (n->nr_partial > MAX_PARTIAL) - list_move(&page->lru, - slabs_by_inuse + page->inuse); + discarded++; + } else + if (inuse < (2 * s->objects) / 3 && + n->nr_partial > MAX_PARTIAL) { + list_move(&page->lru, + slabs_by_inuse + page->inuse); } } @@ -2601,7 +2616,7 @@ int kmem_cache_shrink(struct kmem_cache * We are holding the list_lock so we can only * trylock the slab */ - if (page->inuse > s->objects / 4) + if (page->inuse > s->objects / 3) break; if (!slab_trylock(page)) @@ -2621,9 +2636,16 @@ int kmem_cache_shrink(struct kmem_cache local_irq_save(flags); slab_lock(page); - __kmem_cache_vacate(s, page, flags, - (void **)slabs_by_inuse); + if (__kmem_cache_vacate(s, page, flags, + (void **)slabs_by_inuse)) + defrag_fail++; + else + defrag_success++; } + printk(KERN_INFO "Defrag %s: node=%d jiff=%lu, partial=%lu, " + "discard=%lu, defrag_success=%lu defrag_fail=%lu Pafter=%lu\n", + s->name, node, jiffies - t0, t0_partial, + discarded, defrag_success, defrag_fail, n->nr_partial); } kfree(slabs_by_inuse);