Index: linux-2.6.21-rc3-mm2/mm/slub.c =================================================================== --- linux-2.6.21-rc3-mm2.orig/mm/slub.c 2007-03-19 11:45:38.000000000 -0700 +++ linux-2.6.21-rc3-mm2/mm/slub.c 2007-03-19 11:48:28.000000000 -0700 @@ -19,6 +19,7 @@ #include #include #include +#include /* * Lock order: @@ -131,7 +132,7 @@ static void print_section(char *text, u8 for (i = 0; i < length; i++) { if (newline) { - printk(KERN_ERR "%10s %p: ", text, addr + i); + printk(KERN_ERR "%10s 0x%p: ", text, addr + i); newline = 0; } printk(" %02x", addr[i]); @@ -173,19 +174,30 @@ static void set_freepointer(struct kmem_ /* * Tracking user of a slab. */ -static void *get_track(struct kmem_cache *s, void *object, int alloc) +struct track { + void *addr; /* Called from address */ + int cpu; /* Was running on cpu */ + int pid; /* Pid context */ + unsigned long when; /* When did the operation occur */ +}; + +struct track *get_track(struct kmem_cache *s, void *object, int alloc) { - void **p = object + s->inuse + sizeof(void *); + struct track *p = object + s->inuse + sizeof(void *); - return p[alloc]; + return p + alloc; } static void set_track(struct kmem_cache *s, void *object, int alloc, void *addr) { - void **p = object + s->inuse + sizeof(void *); + struct track *p = object + s->inuse + sizeof(void *); - p[alloc] = addr; + p += alloc; + p->addr = addr; + p->cpu = smp_processor_id(); + p->pid = current ? current->pid : -1; + p->when = jiffies; } #define set_tracking(__s, __o, __a) set_track(__s, __o, __a, \ @@ -199,6 +211,27 @@ static void init_tracking(struct kmem_ca } } +static void print_track(const char *s, struct track *t) +{ +#ifdef CONFIG_KALLSYMS + char *modname; + const char *name; + unsigned long offset, size; + char namebuf[KSYM_NAME_LEN + 1]; + + name = kallsyms_lookup((unsigned long)t->addr, &size, &offset, + &modname, namebuf); + + if (name) { + printk(KERN_ERR "%s: %s+%#lx/%#lx", s, name, offset, size); + if (modname) + printk(" [%s]", modname); + } 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); +} + static void print_trailer(struct kmem_cache *s, u8 *p) { unsigned int off; /* Offset of last byte */ @@ -212,14 +245,14 @@ static void print_trailer(struct kmem_ca print_section("Redzone", p + s->objsize, s->inuse - s->objsize); - printk(KERN_ERR "FreePointer %p: %p\n", + printk(KERN_ERR "FreePointer 0x%p -> 0x%p\n", p + s->offset, get_freepointer(s, p)); if (s->flags & SLAB_STORE_USER) { - printk(KERN_ERR "Last Allocate from %p. Last Free from %p\n", - get_track(s, p, 0), get_track(s, p, 1)); - off += 2 * sizeof(void *); + print_track("Last alloc", get_track(s, p, 0)); + print_track("Last free ", get_track(s, p, 1)); + off += 2 * sizeof(struct track); } if (off != s->size) @@ -232,9 +265,9 @@ static void object_err(struct kmem_cache { u8 *addr = page_address(page); - printk(KERN_ERR "*** SLUB: %s in %s@%p Slab %p\n", + printk(KERN_ERR "*** SLUB: %s in %s@0x%p Slab 0x%p\n", reason, s->name, object, page); - printk(KERN_ERR " offset=%u flags=%04lx inuse=%u freelist=%p\n", + printk(KERN_ERR " offset=%u flags=0x%04lx inuse=%u freelist=0x%p\n", (int)(object - addr), page->flags, page->inuse, page->freelist); if (object > addr + 16) print_section("Bytes b4", object - 16, 16); @@ -330,7 +363,7 @@ static int check_pad_bytes(struct kmem_c if (s->flags & SLAB_STORE_USER) /* We also have user information there */ - off += 2 * sizeof(void *); + off += 2 * sizeof(struct track); if (s->size == off) return 1; @@ -357,7 +390,7 @@ static int slab_pad_check(struct kmem_ca return 1; if (!check_bytes(p + length, POISON_INUSE, remainder)) { - printk(KERN_ERR "SLUB: %s slab %p: Padding fails check\n", + printk(KERN_ERR "SLUB: %s slab 0x%p: Padding fails check\n", s->name, p); print_section("Slab Pad", p + length, remainder); return 0; @@ -394,7 +427,7 @@ static int check_object(struct kmem_cach if (!active && (s->flags & __OBJECT_POISON) && (!check_bytes(p, POISON_FREE, s->objsize - 1) || p[s->objsize -1] != POISON_END)) { - object_err(s, page, p, "Poison"); + object_err(s, page, p, "Poison check failed"); return 0; } if (!check_pad_bytes(s, page, p)) @@ -425,15 +458,15 @@ static int check_object(struct kmem_cach static int check_slab(struct kmem_cache *s, struct page *page) { if (!PageSlab(page)) { - printk(KERN_CRIT "SLUB: %s Not a valid slab page @%p flags=%lx" - " mapping=%p count=%d \n", + printk(KERN_CRIT "SLUB: %s Not a valid slab page @0x%p flags=%lx" + " mapping=0x%p count=%d \n", s->name, page, page->flags, page->mapping, page_count(page)); return 0; } if (page->offset * sizeof(void *) != s->offset) { - printk(KERN_CRIT "SLUB: %s Corrupted offset %lu in slab @%p" - " flags=%lx mapping=%p count=%d\n", + printk(KERN_CRIT "SLUB: %s Corrupted offset %lu in slab @0x%p" + " flags=0x%lx mapping=0x%p count=%d\n", s->name, (unsigned long)(page->offset * sizeof(void *)), page, @@ -443,8 +476,8 @@ static int check_slab(struct kmem_cache return 0; } if (page->inuse > s->objects) { - printk(KERN_CRIT "SLUB: %s Inuse %u > max %u in slab page @%p" - " flags=%lx mapping=%p count=%d\n", + printk(KERN_CRIT "SLUB: %s Inuse %u > max %u in slab page @0x%p" + " flags=%lx mapping=0x%p count=%d\n", s->name, page->inuse, s->objects, page, page->flags, page->mapping, page_count(page)); return 0; @@ -471,11 +504,13 @@ static int on_freelist(struct kmem_cache return 1; if (!check_valid_pointer(s, page, fp)) { if (object) { - object_err(s, page, object, "Freechain corrupt"); + object_err(s, page, object, + "Freechain corrupt"); set_freepointer(s, object, NULL); break; } else { - printk(KERN_ERR "SLUB: %s slab %p freepointer %p corrupted.\n", + printk(KERN_ERR "SLUB: %s slab 0x%p " + "freepointer 0x%p corrupted.\n", s->name, page, fp); dump_stack(); page->freelist = NULL; @@ -490,7 +525,7 @@ static int on_freelist(struct kmem_cache } if (page->inuse != s->objects - nr) { - printk(KERN_CRIT "slab %s: page %p wrong object count." + printk(KERN_CRIT "slab %s: page 0x%p wrong object count." " counter is %d but counted were %d\n", s->name, page, page->inuse, s->objects - nr); @@ -506,7 +541,7 @@ static int alloc_object_checks(struct km goto bad; if (object && !on_freelist(s, page, object)) { - printk(KERN_ERR "SLAB: %s Object %p@%p already allocated.\n", + printk(KERN_ERR "SLAB: %s Object 0x%p@0x%p already allocated.\n", s->name, object, page); goto dump; } @@ -524,8 +559,8 @@ static int alloc_object_checks(struct km init_object(s, object, 1); if (s->flags & SLAB_TRACE) { - printk("SLUB-Trace %s alloc object=%p slab=%p inuse=%d" - " freelist=%p\n", + printk("SLUB-Trace %s alloc object=0x%p slab=0x%p inuse=%d" + " freelist=0x%p\n", s->name, object, page, page->inuse, page->freelist); dump_stack(); @@ -547,13 +582,13 @@ static int free_object_checks(struct kme } if (!check_valid_pointer(s, page, object)) { - printk(KERN_ERR "SLUB: %s slab %p invalid object pointer %p\n", + printk(KERN_ERR "SLUB: %s slab 0x%p invalid object pointer 0x%p\n", s->name, page, object); goto fail; } if (on_freelist(s, page, object)) { - printk(KERN_CRIT "SLUB: %s slab %p object %p already free.\n", + printk(KERN_CRIT "SLUB: %s slab 0x%p object 0x%p already free.\n", s->name, page, object); goto fail; } @@ -564,23 +599,23 @@ static int free_object_checks(struct kme if (unlikely(s != page->slab)) { if (!PageSlab(page)) printk(KERN_CRIT "slab_free %s size %d: attempt to" - "free object(%p) outside of slab.\n", + "free object(0x%p) outside of slab.\n", s->name, s->size, object); else if (!page->slab) printk(KERN_CRIT - "slab_free : no slab(NULL) for object %p.\n", + "slab_free : no slab(NULL) for object 0x%p.\n", object); else - printk(KERN_CRIT "slab_free %s(%d): object at %p" + printk(KERN_CRIT "slab_free %s(%d): object at 0x%p" " belongs to slab %s(%d)\n", s->name, s->size, object, page->slab->name, page->slab->size); goto fail; } if (s->flags & SLAB_TRACE) { - printk("SLUB-Trace %s free object=%p slab=%p" - "inuse=%d freelist=%p\n", + printk("SLUB-Trace %s free object=0x%p slab=0x%p" + "inuse=%d freelist=0x%p\n", s->name, object, page, page->inuse, page->freelist); print_section("SLUB-Trace", object, s->objsize); @@ -1429,7 +1464,7 @@ static int kmem_cache_open(struct kmem_c } if (flags & SLAB_STORE_USER) - size += 2 * sizeof(void *); + size += 2 * sizeof(struct track); align = calculate_alignment(flags, align);