Index: linux-2.6.21-rc4/mm/slub.c =================================================================== --- linux-2.6.21-rc4.orig/mm/slub.c 2007-03-21 21:06:47.000000000 -0700 +++ linux-2.6.21-rc4/mm/slub.c 2007-03-21 21:14:02.000000000 -0700 @@ -188,7 +188,12 @@ struct track *get_track(struct kmem_cache *s, void *object, int alloc) { - struct track *p = object + s->inuse + sizeof(void *); + struct track *p; + + if (s->offset) + p = object + s->offset + sizeof(void *); + else + p = object + s->inuse; return p + alloc; } @@ -196,13 +201,21 @@ static void set_track(struct kmem_cache *s, void *object, int alloc, void *addr) { - struct track *p = object + s->inuse + sizeof(void *); + struct track *p; + + if (s->offset) + p = object + s->offset + sizeof(void *); + else + p = object + s->inuse; p += alloc; - p->addr = addr; - p->cpu = smp_processor_id(); - p->pid = current ? current->pid : -1; - p->when = jiffies; + if (addr) { + p->addr = addr; + p->cpu = smp_processor_id(); + p->pid = current ? current->pid : -1; + p->when = jiffies; + } else + memset(p, 0, sizeof(struct track)); } #define set_tracking(__s, __o, __a) set_track(__s, __o, __a, \ @@ -223,7 +236,12 @@ const char *name; unsigned long offset, size; char namebuf[KSYM_NAME_LEN + 1]; +#endif + if (!t->addr) + return; + +#ifdef CONFIG_KALLSYMS name = kallsyms_lookup((unsigned long)t->addr, &size, &offset, &modname, namebuf); @@ -233,7 +251,7 @@ printk(" [%s]", modname); } else #endif - printk(KERN_ERR "%s: 0x%p", s, t->addr); + printk(KERN_ERR "%s: 0x%p", s, t->addr); printk(" jiffies since=%lu cpu=%u pid=%d\n", jiffies - t->when, t->cpu, t->pid); } @@ -241,11 +259,6 @@ { unsigned int off; /* Offset of last byte */ - if (s->offset) - off = s->offset + sizeof(void *); - else - off = s->inuse; - if (s->flags & SLAB_RED_ZONE) print_section("Redzone", p + s->objsize, s->inuse - s->objsize); @@ -254,6 +267,11 @@ p + s->offset, get_freepointer(s, p)); + if (s->offset) + off = s->offset + sizeof(void *); + else + off = s->inuse; + if (s->flags & SLAB_STORE_USER) { print_track("Last alloc", get_track(s, p, 0)); print_track("Last free ", get_track(s, p, 1)); @@ -295,7 +313,7 @@ if (s->flags & SLAB_RED_ZONE) memset(p + s->objsize, - active ? RED_ACTIVE : RED_INACTIVE, + active ? SLUB_RED_ACTIVE : SLUB_RED_INACTIVE, s->inuse - s->objsize); } @@ -342,8 +360,8 @@ * Padding to reach word boundary. This is also used for Redzoning. * Padding is extended to word size if Redzoning is enabled * and objsize == inuse. - * We fill with 0x71 (RED_INACTIVE) for inactive objects and with - * 0xa5 (RED_ACTIVE) for objects in use. + * We fill with 0xbb (RED_INACTIVE) for inactive objects and with + * 0xcc (RED_ACTIVE) for objects in use. * * object + s->inuse * A. Free pointer (if we cannot overwrite object on free) @@ -415,7 +433,7 @@ if (s->flags & SLAB_RED_ZONE) { if (!check_bytes(endobject, - active ? RED_ACTIVE : RED_INACTIVE, + active ? SLUB_RED_ACTIVE : SLUB_RED_INACTIVE, s->inuse - s->objsize)) { object_err(s, page, object, active ? "Redzone Active check fails" : @@ -564,9 +582,8 @@ init_object(s, object, 1); if (s->flags & SLAB_TRACE) { - printk("SLUB-Trace %s alloc object=0x%p slab=0x%p inuse=%d" - " freelist=0x%p\n", - s->name, object, page, page->inuse, + printk("TRACE %s alloc 0x%p inuse=%d fp=0x%p\n", + s->name, object, page->inuse, page->freelist); dump_stack(); } @@ -619,11 +636,10 @@ goto fail; } if (s->flags & SLAB_TRACE) { - printk("SLUB-Trace %s free object=0x%p slab=0x%p" - "inuse=%d freelist=0x%p\n", - s->name, object, page, page->inuse, + printk("TRACE %s free 0x%p inuse=%d fp=0x%p\n", + s->name, object, page->inuse, page->freelist); - print_section("SLUB-Trace", object, s->objsize); + print_section("Object", object, s->objsize); dump_stack(); } init_object(s, object, 0); @@ -1164,7 +1180,7 @@ * * No special cachelines need to be read */ -void slab_free(struct kmem_cache *s, struct page *page, void *x) +static void slab_free(struct kmem_cache *s, struct page *page, void *x) { void *prior; void **object = (void *)x; @@ -1216,17 +1232,15 @@ { struct page * page; - if (!x) - return; - page = virt_to_page(x); if (unlikely(PageCompound(page))) page = page->first_page; - slab_free(s, page, x); - if (PageError(page) && s->flags & SLAB_STORE_USER) + + if (unlikely(PageError(page) && (s->flags & SLAB_STORE_USER))) set_tracking(s, x, 1); + slab_free(s, page, x); } EXPORT_SYMBOL(kmem_cache_free); @@ -1899,10 +1913,10 @@ page = page->first_page; s = page->slab; - slab_free(s, page, (void *)x); - if (PageError(page) && s->flags & SLAB_STORE_USER) + if (unlikely(PageError(page) && (s->flags & SLAB_STORE_USER))) set_tracking(s, (void *)x, 1); + slab_free(s, page, (void *)x); } EXPORT_SYMBOL(kfree); @@ -2299,11 +2313,11 @@ __ATTR(_name, 0644, _name##_show, _name##_store) -static ssize_t size_show(struct kmem_cache *s, char *buf) +static ssize_t slab_size_show(struct kmem_cache *s, char *buf) { return sprintf(buf, "%d\n", s->size); } -SLAB_ATTR_RO(size); +SLAB_ATTR_RO(slab_size); static ssize_t align_show(struct kmem_cache *s, char *buf) { @@ -2331,20 +2345,16 @@ static ssize_t ctor_show(struct kmem_cache *s, char *buf) { - if (s->ctor) { - sprint_symbol(buf, (unsigned long)s->ctor); - return strlen(buf); - } + if (s->ctor) + return sprint_symbol(buf, (unsigned long)s->ctor); return 0; } SLAB_ATTR_RO(ctor); static ssize_t dtor_show(struct kmem_cache *s, char *buf) { - if (s->dtor) { - sprint_symbol(buf, (unsigned long)s->dtor); - return strlen(buf); - } + if (s->dtor) + return sprint_symbol(buf, (unsigned long)s->dtor); return 0; } SLAB_ATTR_RO(dtor); @@ -2391,26 +2401,26 @@ } SLAB_ATTR_RO(objects); -static ssize_t _sanity_checks_show(struct kmem_cache *s, char *buf) +static ssize_t sanity_checks_show(struct kmem_cache *s, char *buf) { return sprintf(buf, "%d\n", !!(s->flags & SLAB_DEBUG_FREE)); } -static ssize_t _sanity_checks_store(struct kmem_cache *s, const char *buf, size_t length) +static ssize_t sanity_checks_store(struct kmem_cache *s, const char *buf, size_t length) { s->flags &= ~SLAB_DEBUG_FREE; if (buf[0] == '1') s->flags |= SLAB_DEBUG_FREE; return length; } -SLAB_ATTR(_sanity_checks); +SLAB_ATTR(sanity_checks); -static ssize_t _trace_show(struct kmem_cache *s, char *buf) +static ssize_t trace_show(struct kmem_cache *s, char *buf) { return sprintf(buf, "%d\n", !!(s->flags & SLAB_TRACE)); } -static ssize_t _trace_store(struct kmem_cache *s, const char *buf, size_t length) +static ssize_t trace_store(struct kmem_cache *s, const char *buf, size_t length) { s->flags &= ~SLAB_TRACE; printk("_trace_store = %s\n", buf); @@ -2418,65 +2428,49 @@ s->flags |= SLAB_TRACE; return length; } -SLAB_ATTR(_trace); +SLAB_ATTR(trace); -#ifdef CONFIG_CPUSET -static ssize_t _mem_spread_show(struct kmem_cache *s, char *buf) -{ - return sprintf(buf, "%d\n", !!(s->flags & SLAB_MEM_SPREAD)); -} - -static ssize_t _mem_spread_store(struct kmem_cache *s, const char *buf, size_t length) -{ - s->flags &= ~SLAB_MEM_SPREAD; - if (buf[0] == '1') - s->flags |= SLAB_MEM_SPREAD; - return 1; -} -SLAB_ATTR(_mem_spread); -#endif - -static ssize_t _reclaim_account_show(struct kmem_cache *s, char *buf) +static ssize_t reclaim_account_show(struct kmem_cache *s, char *buf) { return sprintf(buf, "%d\n", !!(s->flags & SLAB_RECLAIM_ACCOUNT)); } -static ssize_t _reclaim_account_store(struct kmem_cache *s, const char *buf, size_t length) +static ssize_t reclaim_account_store(struct kmem_cache *s, const char *buf, size_t length) { s->flags &= ~SLAB_RECLAIM_ACCOUNT; if (buf[0] == '1') s->flags |= SLAB_RECLAIM_ACCOUNT; return length; } -SLAB_ATTR(_reclaim_account); +SLAB_ATTR(reclaim_account); -static ssize_t _hwcache_align_show(struct kmem_cache *s, char *buf) +static ssize_t hwcache_align_show(struct kmem_cache *s, char *buf) { return sprintf(buf, "%d\n", !!(s->flags & (SLAB_HWCACHE_ALIGN|SLAB_MUST_HWCACHE_ALIGN))); } -SLAB_ATTR_RO(_hwcache_align); +SLAB_ATTR_RO(hwcache_align); #ifdef CONFIG_ZONE_DMA -static ssize_t _cache_dma_show(struct kmem_cache *s, char *buf) +static ssize_t cache_dma_show(struct kmem_cache *s, char *buf) { return sprintf(buf, "%d\n", !!(s->flags & SLAB_CACHE_DMA)); } -SLAB_ATTR_RO(_cache_dma); +SLAB_ATTR_RO(cache_dma); #endif -static ssize_t _destroy_by_rcu_show(struct kmem_cache *s, char *buf) +static ssize_t destroy_by_rcu_show(struct kmem_cache *s, char *buf) { return sprintf(buf, "%d\n", !!(s->flags & SLAB_DESTROY_BY_RCU)); } -SLAB_ATTR_RO(_destroy_by_rcu); +SLAB_ATTR_RO(destroy_by_rcu); -static ssize_t _red_zone_show(struct kmem_cache *s, char *buf) +static ssize_t red_zone_show(struct kmem_cache *s, char *buf) { return sprintf(buf, "%d\n", !!(s->flags & SLAB_RED_ZONE)); } -static ssize_t _red_zone_store(struct kmem_cache *s, const char *buf, size_t length) +static ssize_t red_zone_store(struct kmem_cache *s, const char *buf, size_t length) { if (slab_objects(s, NULL, NULL, NULL, NULL)) return -EBUSY; @@ -2487,14 +2481,14 @@ calculate_sizes(s); return length; } -SLAB_ATTR(_red_zone); +SLAB_ATTR(red_zone); -static ssize_t _poison_show(struct kmem_cache *s, char *buf) +static ssize_t poison_show(struct kmem_cache *s, char *buf) { return sprintf(buf, "%d\n", !!(s->flags & SLAB_POISON)); } -static ssize_t _poison_store(struct kmem_cache *s, const char *buf, size_t length) +static ssize_t poison_store(struct kmem_cache *s, const char *buf, size_t length) { if (slab_objects(s, NULL, NULL, NULL, NULL)) return -EBUSY; @@ -2505,14 +2499,14 @@ calculate_sizes(s); return length; } -SLAB_ATTR(_poison); +SLAB_ATTR(poison); -static ssize_t _store_user_show(struct kmem_cache *s, char *buf) +static ssize_t store_user_show(struct kmem_cache *s, char *buf) { return sprintf(buf, "%d\n", !!(s->flags & SLAB_STORE_USER)); } -static ssize_t _store_user_store(struct kmem_cache *s, const char *buf, size_t length) +static ssize_t store_user_store(struct kmem_cache *s, const char *buf, size_t length) { if (slab_objects(s, NULL, NULL, NULL, NULL)) return -EBUSY; @@ -2523,10 +2517,10 @@ calculate_sizes(s); return length; } -SLAB_ATTR(_store_user); +SLAB_ATTR(store_user); static struct attribute * slab_attrs[] = { - &size_attr.attr, + &slab_size_attr.attr, &object_size_attr.attr, &objs_per_slab_attr.attr, &order_attr.attr, @@ -2538,19 +2532,16 @@ &dtor_attr.attr, &aliases_attr.attr, &align_attr.attr, - &_sanity_checks_attr.attr, - &_trace_attr.attr, - &_hwcache_align_attr.attr, - &_reclaim_account_attr.attr, - &_destroy_by_rcu_attr.attr, - &_red_zone_attr.attr, - &_poison_attr.attr, - &_store_user_attr.attr, -#ifdef CONFIG_CPUSET - &_mem_spread_attr.attr, -#endif + &sanity_checks_attr.attr, + &trace_attr.attr, + &hwcache_align_attr.attr, + &reclaim_account_attr.attr, + &destroy_by_rcu_attr.attr, + &red_zone_attr.attr, + &poison_attr.attr, + &store_user_attr.attr, #ifdef CONFIG_ZONE_DMA - &_cache_dma_attr.attr, + &cache_dma_attr.attr, #endif NULL }; @@ -2708,5 +2699,4 @@ } __initcall(slab_sysfs_init); - #endif Index: linux-2.6.21-rc4/include/linux/poison.h =================================================================== --- linux-2.6.21-rc4.orig/include/linux/poison.h 2007-03-21 21:06:05.000000000 -0700 +++ linux-2.6.21-rc4/include/linux/poison.h 2007-03-21 21:08:43.000000000 -0700 @@ -18,6 +18,9 @@ #define RED_INACTIVE 0x5A2CF071UL /* when obj is inactive */ #define RED_ACTIVE 0x170FC2A5UL /* when obj is active */ +#define SLUB_RED_INACTIVE 0xbb +#define SLUB_RED_ACTIVE 0xcc + /* ...and for poisoning */ #define POISON_INUSE 0x5a /* for use-uninitialised poisoning */ #define POISON_FREE 0x6b /* for use-after-free poisoning */