Index: linux-2.6/include/linux/slub_def.h =================================================================== --- linux-2.6.orig/include/linux/slub_def.h 2006-12-09 18:33:54.000000000 -0800 +++ linux-2.6/include/linux/slub_def.h 2006-12-09 18:37:11.000000000 -0800 @@ -19,6 +19,8 @@ int offset; int size; int referenced; + int max_inuse; + void *freelist; #ifdef CONFIG_SMP int flush_active; struct delayed_work flush; Index: linux-2.6/mm/slub.c =================================================================== --- linux-2.6.orig/mm/slub.c 2006-12-09 18:37:20.000000000 -0800 +++ linux-2.6/mm/slub.c 2006-12-09 19:05:00.000000000 -0800 @@ -450,12 +450,25 @@ */ static void __always_inline deactivate_slab(struct active_slab *a) { - struct page *page = a->page; - + if (!page->freelist) { + /* + * Page has no freelist so adopt freelist of + * the active slab. + */ + page->freelist = a->freelist; + page->inuse = a->max_inuse; + } else + /* Transfer freelist to the page freelist */ + while (a->freelist) { + /* Verify this */ + a->freelist[a->offset] = page->freelist; + page->freelist = a->freelist; + a->freelist = a->freelist[a->offset]; + } + __ClearPageActive(a->page); a->page = NULL; a->referenced = 0; - __ClearPageActive(page); - + a->freelist = NULL; putback_slab(a->slab, page); } @@ -527,6 +540,14 @@ local_irq_save(flags); a = &s->active[smp_processor_id()]; + if (likely(a->freelist)) { + /* Fastpath */ + object = a->freelist; + a->freelist = object[a->offset]; + local_irq_restore(flags); + return object; + } + if (!a->page) goto new_slab; @@ -535,12 +556,16 @@ if (unlikely(!a->page->freelist)) goto another_slab; + a->freelist = page->freelist; + page->freelist = NULL; + a->max_inuse = xxx; + if (unlikely(node != -1 && page_to_nid(a->page) != node)) goto another_slab; redo: - a->page->inuse++; - object = a->page->freelist; - a->page->freelist = next_object = object[a->offset]; + a->max_inuse++; + object = a->freelist; + a->freelist = next_object = object[a->offset]; a->referenced = 1; slab_unlock(a->page); local_irq_restore(flags); @@ -580,6 +605,9 @@ a->page = page; __SetPageActive(a->page); + a->max_inuse = page->inuse; + a->freelist = page->freelist; + page->freelist = NULL; check_free_chain(s, a->page); #ifdef CONFIG_SMP @@ -639,7 +667,7 @@ goto double_free; #endif - prior = object[page->offset] = page->freelist; + prior = object[s->offset] = page->freelist; page->freelist = object; page->inuse--; Index: linux-2.6/include/linux/mm_types.h =================================================================== --- linux-2.6.orig/include/linux/mm_types.h 2006-12-09 19:02:13.000000000 -0800 +++ linux-2.6/include/linux/mm_types.h 2006-12-09 19:02:49.000000000 -0800 @@ -24,10 +24,7 @@ * to show when page is mapped * & limit reverse map searches. */ - struct { /* Slub */ - short unsigned int inuse; - short unsigned int offset; - }; + unsigned int inuse; }; union { struct {