Index: mm/mm/slab.c =================================================================== --- mm.orig/mm/slab.c 2005-09-04 12:28:12.000000000 +0200 +++ mm/mm/slab.c 2005-09-05 21:47:06.000000000 +0200 @@ -491,6 +491,9 @@ #define POISON_FREE 0x6b /* for use-after-free poisoning */ #define POISON_END 0xa5 /* end-byte of poisoning */ +/* The number of object caller functions we save */ +#define DBG_USERWORDS 3 + /* memory layout of objects: * 0 : objp * 0 .. cachep->dbghead - BYTES_PER_WORD - 1: padding. This ensures that @@ -522,14 +525,15 @@ { BUG_ON(!(cachep->flags & SLAB_RED_ZONE)); if (cachep->flags & SLAB_STORE_USER) - return (unsigned long*) (objp+cachep->objsize-2*BYTES_PER_WORD); + return (unsigned long*) (objp+cachep->objsize-(1+DBG_USERWORDS)*BYTES_PER_WORD); return (unsigned long*) (objp+cachep->objsize-BYTES_PER_WORD); } -static void **dbg_userword(kmem_cache_t *cachep, void *objp) +static unsigned long *dbg_userword(kmem_cache_t *cachep, void *objp) { + BUILD_BUG_ON(DBG_USERWORDS == 0); BUG_ON(!(cachep->flags & SLAB_STORE_USER)); - return (void**)(objp+cachep->objsize-BYTES_PER_WORD); + return (unsigned long*)(objp+cachep->objsize - DBG_USERWORDS*BYTES_PER_WORD); } #else @@ -1313,12 +1317,16 @@ } if (cachep->flags & SLAB_STORE_USER) { - printk(KERN_ERR "Last user: [<%p>]", - *dbg_userword(cachep, objp)); - print_symbol("(%s)", - (unsigned long)*dbg_userword(cachep, objp)); + int i; + + printk(KERN_ERR "Last user:\n"); + for (i = 0; i < DBG_USERWORDS; i++) { + printk(KERN_ERR "[<%p>]", (void *) dbg_userword(cachep, objp)[i]); + print_symbol("(%s)", dbg_userword(cachep, objp)[i]); + } printk("\n"); } + realobj = (char*)objp+obj_dbghead(cachep); size = obj_reallen(cachep); for (i=0; i= malloc_sizes[INDEX_L3+1].cs_size && cachep->reallen > cache_line_size() && size < PAGE_SIZE) { @@ -2082,8 +2089,12 @@ /* need to poison the objs? */ if (cachep->flags & SLAB_POISON) poison_obj(cachep, objp, POISON_FREE); - if (cachep->flags & SLAB_STORE_USER) - *dbg_userword(cachep, objp) = NULL; + if (cachep->flags & SLAB_STORE_USER) { + int i; + + for (i = 0; i < DBG_USERWORDS; i++) + dbg_userword(cachep, objp)[i] = 0; + } if (cachep->flags & SLAB_RED_ZONE) { *dbg_redzone1(cachep, objp) = RED_INACTIVE; @@ -2257,7 +2268,7 @@ } } -static void *cache_free_debugcheck(kmem_cache_t *cachep, void *objp, +static void inline *cache_free_debugcheck(kmem_cache_t *cachep, void *objp, void *caller) { struct page *page; @@ -2287,8 +2298,17 @@ *dbg_redzone1(cachep, objp) = RED_INACTIVE; *dbg_redzone2(cachep, objp) = RED_INACTIVE; } - if (cachep->flags & SLAB_STORE_USER) - *dbg_userword(cachep, objp) = caller; + if (cachep->flags & SLAB_STORE_USER) { + unsigned long *call_ptr = (unsigned long *) &call_ptr; + int i; + + for (i = 0; i < DBG_USERWORDS; i++) { + call_ptr = next_stack_func(call_ptr, i); + if (!call_ptr) + break; + dbg_userword(cachep, objp)[i] = *call_ptr; + } + } objnr = (objp-slabp->s_mem)/cachep->objsize; @@ -2463,7 +2483,7 @@ } #if DEBUG -static void * +static void inline * cache_alloc_debugcheck_after(kmem_cache_t *cachep, unsigned int __nocast flags, void *objp, void *caller) { @@ -2480,8 +2500,17 @@ #endif poison_obj(cachep, objp, POISON_INUSE); } - if (cachep->flags & SLAB_STORE_USER) - *dbg_userword(cachep, objp) = caller; + if (cachep->flags & SLAB_STORE_USER) { + unsigned long *call_ptr = (unsigned long *) &call_ptr; + int i; + + for (i = 0; i < DBG_USERWORDS; i++) { + call_ptr = next_stack_func(call_ptr, i); + if (!call_ptr) + break; + dbg_userword(cachep, objp)[i] = *call_ptr; + } + } if (cachep->flags & SLAB_RED_ZONE) { if (*dbg_redzone1(cachep, objp) != RED_INACTIVE || *dbg_redzone2(cachep, objp) != RED_INACTIVE) { @@ -3518,6 +3547,34 @@ .show = s_show, }; +#if DEBUG +#include +static inline void dump_slab(kmem_cache_t *cachep, struct slab *slabp) +{ + int i; + int slab_user = cachep->flags & SLAB_STORE_USER; + + for (i = 0; i < cachep->num; i++) { + if (slab_user) { + void *objp = slabp->s_mem + cachep->objsize * i; + int x; + + for (x = 0; x < DBG_USERWORDS; x++) { + printk("obj:%p [%p] ", objp, (void *) dbg_userword(cachep, objp)[x]); + print_symbol("<%s>", dbg_userword(cachep, objp)[x]); + printk("\n"); + } + } else { + unsigned long sym = slab_bufctl(slabp)[i]; + + printk("obj %p/%d: %p", slabp, i, (void *)sym); + print_symbol(" <%s>", sym); + printk("\n"); + } + } +} +#endif + static void do_dump_slabp(kmem_cache_t *cachep) { #if DEBUG @@ -3531,16 +3588,9 @@ spin_lock(&rl3->list_lock); list_for_each(q, &rl3->slabs_full) { - int i; struct slab *slabp = list_entry(q, struct slab, list); - - for (i = 0; i < cachep->num; i++) { - unsigned long sym = slab_bufctl(slabp)[i]; - - printk("obj %p/%d: %p", slabp, i, (void *)sym); - print_symbol(" <%s>", sym); - printk("\n"); - } + dump_slab(cachep, slabp); + touch_nmi_watchdog(); } spin_unlock(&rl3->list_lock); }