Index: linux-2.6.19-mm1/mm/slub.c =================================================================== --- linux-2.6.19-mm1.orig/mm/slub.c 2006-12-12 15:23:02.000000000 -0800 +++ linux-2.6.19-mm1/mm/slub.c 2006-12-12 15:28:58.000000000 -0800 @@ -160,7 +160,7 @@ static void free_slab(struct kmem_cache *s, struct page *page) { - if (s->flags & SLAB_DESTROY_BY_RCU) { + if (unlikely(s->flags & SLAB_DESTROY_BY_RCU)) { struct rcu_head *head = (void *)&page->lru; page->mapping = (void *)s; @@ -834,19 +834,29 @@ s->ctor = ctor; s->dtor = dtor; s->objsize = size; + /* * Here is the place to add other management type information * to the end of the object F.e. debug info */ - size = ALIGN(size, sizeof(void *)); + size = ALIGN(size, sizeof(void *)); s->inuse = size; - if ((flags & SLAB_DESTROY_BY_RCU) || ctor || dtor) { + + if (size *2 >= (PAGE_SIZE << calculate_order(size)) && + ((flags & SLAB_DESTROY_BY_RCU) || ctor || dtor)) { /* - * Relocate free pointer after the object if we need - * to do RCU - */ - s->offset = size; + * Relocate free pointer after the object if it is not + * permitted to overwrite the first word of the object on + * kmem_cache_free. + * + * This is the case if we do RCU, have a constructor or + * destructor. + * + * We never need a free pointer if each slab only has + * a single object. + */ + s->offset = size / sizeof(void *); size += sizeof(void *); }