Index: linux-2.6.21-rc3-mm2/mm/slub.c =================================================================== --- linux-2.6.21-rc3-mm2.orig/mm/slub.c 2007-03-19 11:48:28.000000000 -0700 +++ linux-2.6.21-rc3-mm2/mm/slub.c 2007-03-19 12:23:01.000000000 -0700 @@ -229,7 +229,7 @@ static void print_track(const char *s, s } else #endif printk(KERN_ERR "%s: 0x%p", s, t->addr); - printk(" jiffies ago=%d cpu=%d pid=%d\n", t->cpu, t->pid, jiffies - t->when); + printk(" jiffies since=%d cpu=%d pid=%d\n", t->cpu, t->pid, jiffies - t->when); } static void print_trailer(struct kmem_cache *s, u8 *p) @@ -1040,6 +1040,19 @@ static void flush_all(struct kmem_cache } #endif +/* + * slab_alloc is optimized to only modify two cachelines on the fast path + * (aside from the stack): + * + * 1. The page struct + * 2. The first cacheline of the object to be allocated. + * + * The only cache lines that are read (apart from code) is the + * per cpu array in the kmem_cache struct. + * + * Fastpath is not possible if we need to get a new slab or have + * debugging enabled (which means all slabs are marked with PageError) + */ static __always_inline void *slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node) { @@ -1140,24 +1153,18 @@ void *kmem_cache_alloc_node(struct kmem_ EXPORT_SYMBOL(kmem_cache_alloc_node); #endif -void kmem_cache_free(struct kmem_cache *s, void *x) +/* + * The fastpath only writes the cacheline of the page struct and the first + * cacheline of the object. + * + * No special cachelines need to be read + */ +void slab_free(struct kmem_cache *s, struct page *page, void *x) { - struct page * page; void *prior; void **object = (void *)x; unsigned long flags; - if (!object) - return; - - page = virt_to_page(x); - - if (unlikely(PageCompound(page))) - page = page->first_page; - - if (!s) - s = page->slab; - local_irq_save(flags); if (unlikely(PageError(page)) && s->objects == 1) @@ -1165,12 +1172,9 @@ void kmem_cache_free(struct kmem_cache * slab_lock(page); - if (unlikely(PageError(page))) { - if (!free_object_checks(s, page, x)) + if (unlikely(PageError(page)) && + !free_object_checks(s, page, x)) goto out_unlock; - if (s->flags & SLAB_STORE_USER) - set_tracking(s, object, 1); - } prior = object[page->offset] = page->freelist; page->freelist = object; @@ -1202,6 +1206,26 @@ out_unlock: slab_unlock(page); local_irq_restore(flags); } + +void kmem_cache_free(struct kmem_cache *s, void *x) +{ + struct page * page; + + if (!x) + return; + + page = virt_to_page(x); + + if (unlikely(PageCompound(page))) + page = page->first_page; + + if (!s) + s = page->slab; + + slab_free(s, page, x); + if (PageError(page) && s->flags & SLAB_STORE_USER) + set_tracking(s, x, 1); +} EXPORT_SYMBOL(kmem_cache_free); /* Figure out on which slab object the object resides */ @@ -1841,9 +1865,24 @@ size_t ksize(const void *object) } EXPORT_SYMBOL(ksize); -void kfree(const void *object) +void kfree(const void *x) { - kmem_cache_free(NULL, (void *)object); + struct kmem_cache *s; + struct page * page; + + if (!x) + return; + + page = virt_to_page(x); + + if (unlikely(PageCompound(page))) + page = page->first_page; + + s = page->slab; + slab_free(s, page, (void *)x); + + if (PageError(page) && s->flags & SLAB_STORE_USER) + set_tracking(s, (void *)x, 1); } EXPORT_SYMBOL(kfree); @@ -1886,10 +1925,6 @@ void *krealloc(const void *p, size_t new if (likely(page->slab == new_cache)) return (void *)p; - /* - * We are on the slow-path here so do not use __cache_alloc - * because it bloats kernel text. - */ ret = kmalloc(new_size, flags); if (ret) { memcpy(ret, p, min(new_size, ksize(p))); @@ -1915,7 +1950,7 @@ void __init kmem_cache_init(void) /* * Must first have the slab cache available for the allocations of the * struct kmalloc_cache_node's. There is special bootstrap code in - * kmem_cache_open for the situation when slab_state == DOWN. + * kmem_cache_open for slab_state == DOWN. */ create_kmalloc_cache(&kmalloc_caches[kmem_cache_node_cache - KMALLOC_SHIFT_LOW],