1*3ac7fe5aSThomas Gleixner /* 2*3ac7fe5aSThomas Gleixner * Generic infrastructure for lifetime debugging of objects. 3*3ac7fe5aSThomas Gleixner * 4*3ac7fe5aSThomas Gleixner * Started by Thomas Gleixner 5*3ac7fe5aSThomas Gleixner * 6*3ac7fe5aSThomas Gleixner * Copyright (C) 2008, Thomas Gleixner <[email protected]> 7*3ac7fe5aSThomas Gleixner * 8*3ac7fe5aSThomas Gleixner * For licencing details see kernel-base/COPYING 9*3ac7fe5aSThomas Gleixner */ 10*3ac7fe5aSThomas Gleixner #include <linux/debugobjects.h> 11*3ac7fe5aSThomas Gleixner #include <linux/interrupt.h> 12*3ac7fe5aSThomas Gleixner #include <linux/seq_file.h> 13*3ac7fe5aSThomas Gleixner #include <linux/debugfs.h> 14*3ac7fe5aSThomas Gleixner #include <linux/hash.h> 15*3ac7fe5aSThomas Gleixner 16*3ac7fe5aSThomas Gleixner #define ODEBUG_HASH_BITS 14 17*3ac7fe5aSThomas Gleixner #define ODEBUG_HASH_SIZE (1 << ODEBUG_HASH_BITS) 18*3ac7fe5aSThomas Gleixner 19*3ac7fe5aSThomas Gleixner #define ODEBUG_POOL_SIZE 512 20*3ac7fe5aSThomas Gleixner #define ODEBUG_POOL_MIN_LEVEL 256 21*3ac7fe5aSThomas Gleixner 22*3ac7fe5aSThomas Gleixner #define ODEBUG_CHUNK_SHIFT PAGE_SHIFT 23*3ac7fe5aSThomas Gleixner #define ODEBUG_CHUNK_SIZE (1 << ODEBUG_CHUNK_SHIFT) 24*3ac7fe5aSThomas Gleixner #define ODEBUG_CHUNK_MASK (~(ODEBUG_CHUNK_SIZE - 1)) 25*3ac7fe5aSThomas Gleixner 26*3ac7fe5aSThomas Gleixner struct debug_bucket { 27*3ac7fe5aSThomas Gleixner struct hlist_head list; 28*3ac7fe5aSThomas Gleixner spinlock_t lock; 29*3ac7fe5aSThomas Gleixner }; 30*3ac7fe5aSThomas Gleixner 31*3ac7fe5aSThomas Gleixner static struct debug_bucket obj_hash[ODEBUG_HASH_SIZE]; 32*3ac7fe5aSThomas Gleixner 33*3ac7fe5aSThomas Gleixner static struct debug_obj obj_static_pool[ODEBUG_POOL_SIZE]; 34*3ac7fe5aSThomas Gleixner 35*3ac7fe5aSThomas Gleixner static DEFINE_SPINLOCK(pool_lock); 36*3ac7fe5aSThomas Gleixner 37*3ac7fe5aSThomas Gleixner static HLIST_HEAD(obj_pool); 38*3ac7fe5aSThomas Gleixner 39*3ac7fe5aSThomas Gleixner static int obj_pool_min_free = ODEBUG_POOL_SIZE; 40*3ac7fe5aSThomas Gleixner static int obj_pool_free = ODEBUG_POOL_SIZE; 41*3ac7fe5aSThomas Gleixner static int obj_pool_used; 42*3ac7fe5aSThomas Gleixner static int obj_pool_max_used; 43*3ac7fe5aSThomas Gleixner static struct kmem_cache *obj_cache; 44*3ac7fe5aSThomas Gleixner 45*3ac7fe5aSThomas Gleixner static int debug_objects_maxchain __read_mostly; 46*3ac7fe5aSThomas Gleixner static int debug_objects_fixups __read_mostly; 47*3ac7fe5aSThomas Gleixner static int debug_objects_warnings __read_mostly; 48*3ac7fe5aSThomas Gleixner static int debug_objects_enabled __read_mostly; 49*3ac7fe5aSThomas Gleixner static struct debug_obj_descr *descr_test __read_mostly; 50*3ac7fe5aSThomas Gleixner 51*3ac7fe5aSThomas Gleixner static int __init enable_object_debug(char *str) 52*3ac7fe5aSThomas Gleixner { 53*3ac7fe5aSThomas Gleixner debug_objects_enabled = 1; 54*3ac7fe5aSThomas Gleixner return 0; 55*3ac7fe5aSThomas Gleixner } 56*3ac7fe5aSThomas Gleixner early_param("debug_objects", enable_object_debug); 57*3ac7fe5aSThomas Gleixner 58*3ac7fe5aSThomas Gleixner static const char *obj_states[ODEBUG_STATE_MAX] = { 59*3ac7fe5aSThomas Gleixner [ODEBUG_STATE_NONE] = "none", 60*3ac7fe5aSThomas Gleixner [ODEBUG_STATE_INIT] = "initialized", 61*3ac7fe5aSThomas Gleixner [ODEBUG_STATE_INACTIVE] = "inactive", 62*3ac7fe5aSThomas Gleixner [ODEBUG_STATE_ACTIVE] = "active", 63*3ac7fe5aSThomas Gleixner [ODEBUG_STATE_DESTROYED] = "destroyed", 64*3ac7fe5aSThomas Gleixner [ODEBUG_STATE_NOTAVAILABLE] = "not available", 65*3ac7fe5aSThomas Gleixner }; 66*3ac7fe5aSThomas Gleixner 67*3ac7fe5aSThomas Gleixner static int fill_pool(void) 68*3ac7fe5aSThomas Gleixner { 69*3ac7fe5aSThomas Gleixner gfp_t gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN; 70*3ac7fe5aSThomas Gleixner struct debug_obj *new; 71*3ac7fe5aSThomas Gleixner 72*3ac7fe5aSThomas Gleixner if (likely(obj_pool_free >= ODEBUG_POOL_MIN_LEVEL)) 73*3ac7fe5aSThomas Gleixner return obj_pool_free; 74*3ac7fe5aSThomas Gleixner 75*3ac7fe5aSThomas Gleixner if (unlikely(!obj_cache)) 76*3ac7fe5aSThomas Gleixner return obj_pool_free; 77*3ac7fe5aSThomas Gleixner 78*3ac7fe5aSThomas Gleixner while (obj_pool_free < ODEBUG_POOL_MIN_LEVEL) { 79*3ac7fe5aSThomas Gleixner 80*3ac7fe5aSThomas Gleixner new = kmem_cache_zalloc(obj_cache, gfp); 81*3ac7fe5aSThomas Gleixner if (!new) 82*3ac7fe5aSThomas Gleixner return obj_pool_free; 83*3ac7fe5aSThomas Gleixner 84*3ac7fe5aSThomas Gleixner spin_lock(&pool_lock); 85*3ac7fe5aSThomas Gleixner hlist_add_head(&new->node, &obj_pool); 86*3ac7fe5aSThomas Gleixner obj_pool_free++; 87*3ac7fe5aSThomas Gleixner spin_unlock(&pool_lock); 88*3ac7fe5aSThomas Gleixner } 89*3ac7fe5aSThomas Gleixner return obj_pool_free; 90*3ac7fe5aSThomas Gleixner } 91*3ac7fe5aSThomas Gleixner 92*3ac7fe5aSThomas Gleixner /* 93*3ac7fe5aSThomas Gleixner * Lookup an object in the hash bucket. 94*3ac7fe5aSThomas Gleixner */ 95*3ac7fe5aSThomas Gleixner static struct debug_obj *lookup_object(void *addr, struct debug_bucket *b) 96*3ac7fe5aSThomas Gleixner { 97*3ac7fe5aSThomas Gleixner struct hlist_node *node; 98*3ac7fe5aSThomas Gleixner struct debug_obj *obj; 99*3ac7fe5aSThomas Gleixner int cnt = 0; 100*3ac7fe5aSThomas Gleixner 101*3ac7fe5aSThomas Gleixner hlist_for_each_entry(obj, node, &b->list, node) { 102*3ac7fe5aSThomas Gleixner cnt++; 103*3ac7fe5aSThomas Gleixner if (obj->object == addr) 104*3ac7fe5aSThomas Gleixner return obj; 105*3ac7fe5aSThomas Gleixner } 106*3ac7fe5aSThomas Gleixner if (cnt > debug_objects_maxchain) 107*3ac7fe5aSThomas Gleixner debug_objects_maxchain = cnt; 108*3ac7fe5aSThomas Gleixner 109*3ac7fe5aSThomas Gleixner return NULL; 110*3ac7fe5aSThomas Gleixner } 111*3ac7fe5aSThomas Gleixner 112*3ac7fe5aSThomas Gleixner /* 113*3ac7fe5aSThomas Gleixner * Allocate a new object. If the pool is empty and no refill possible, 114*3ac7fe5aSThomas Gleixner * switch off the debugger. 115*3ac7fe5aSThomas Gleixner */ 116*3ac7fe5aSThomas Gleixner static struct debug_obj * 117*3ac7fe5aSThomas Gleixner alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr) 118*3ac7fe5aSThomas Gleixner { 119*3ac7fe5aSThomas Gleixner struct debug_obj *obj = NULL; 120*3ac7fe5aSThomas Gleixner int retry = 0; 121*3ac7fe5aSThomas Gleixner 122*3ac7fe5aSThomas Gleixner repeat: 123*3ac7fe5aSThomas Gleixner spin_lock(&pool_lock); 124*3ac7fe5aSThomas Gleixner if (obj_pool.first) { 125*3ac7fe5aSThomas Gleixner obj = hlist_entry(obj_pool.first, typeof(*obj), node); 126*3ac7fe5aSThomas Gleixner 127*3ac7fe5aSThomas Gleixner obj->object = addr; 128*3ac7fe5aSThomas Gleixner obj->descr = descr; 129*3ac7fe5aSThomas Gleixner obj->state = ODEBUG_STATE_NONE; 130*3ac7fe5aSThomas Gleixner hlist_del(&obj->node); 131*3ac7fe5aSThomas Gleixner 132*3ac7fe5aSThomas Gleixner hlist_add_head(&obj->node, &b->list); 133*3ac7fe5aSThomas Gleixner 134*3ac7fe5aSThomas Gleixner obj_pool_used++; 135*3ac7fe5aSThomas Gleixner if (obj_pool_used > obj_pool_max_used) 136*3ac7fe5aSThomas Gleixner obj_pool_max_used = obj_pool_used; 137*3ac7fe5aSThomas Gleixner 138*3ac7fe5aSThomas Gleixner obj_pool_free--; 139*3ac7fe5aSThomas Gleixner if (obj_pool_free < obj_pool_min_free) 140*3ac7fe5aSThomas Gleixner obj_pool_min_free = obj_pool_free; 141*3ac7fe5aSThomas Gleixner } 142*3ac7fe5aSThomas Gleixner spin_unlock(&pool_lock); 143*3ac7fe5aSThomas Gleixner 144*3ac7fe5aSThomas Gleixner if (fill_pool() && !obj && !retry++) 145*3ac7fe5aSThomas Gleixner goto repeat; 146*3ac7fe5aSThomas Gleixner 147*3ac7fe5aSThomas Gleixner return obj; 148*3ac7fe5aSThomas Gleixner } 149*3ac7fe5aSThomas Gleixner 150*3ac7fe5aSThomas Gleixner /* 151*3ac7fe5aSThomas Gleixner * Put the object back into the pool or give it back to kmem_cache: 152*3ac7fe5aSThomas Gleixner */ 153*3ac7fe5aSThomas Gleixner static void free_object(struct debug_obj *obj) 154*3ac7fe5aSThomas Gleixner { 155*3ac7fe5aSThomas Gleixner unsigned long idx = (unsigned long)(obj - obj_static_pool); 156*3ac7fe5aSThomas Gleixner 157*3ac7fe5aSThomas Gleixner if (obj_pool_free < ODEBUG_POOL_SIZE || idx < ODEBUG_POOL_SIZE) { 158*3ac7fe5aSThomas Gleixner spin_lock(&pool_lock); 159*3ac7fe5aSThomas Gleixner hlist_add_head(&obj->node, &obj_pool); 160*3ac7fe5aSThomas Gleixner obj_pool_free++; 161*3ac7fe5aSThomas Gleixner obj_pool_used--; 162*3ac7fe5aSThomas Gleixner spin_unlock(&pool_lock); 163*3ac7fe5aSThomas Gleixner } else { 164*3ac7fe5aSThomas Gleixner spin_lock(&pool_lock); 165*3ac7fe5aSThomas Gleixner obj_pool_used--; 166*3ac7fe5aSThomas Gleixner spin_unlock(&pool_lock); 167*3ac7fe5aSThomas Gleixner kmem_cache_free(obj_cache, obj); 168*3ac7fe5aSThomas Gleixner } 169*3ac7fe5aSThomas Gleixner } 170*3ac7fe5aSThomas Gleixner 171*3ac7fe5aSThomas Gleixner /* 172*3ac7fe5aSThomas Gleixner * We run out of memory. That means we probably have tons of objects 173*3ac7fe5aSThomas Gleixner * allocated. 174*3ac7fe5aSThomas Gleixner */ 175*3ac7fe5aSThomas Gleixner static void debug_objects_oom(void) 176*3ac7fe5aSThomas Gleixner { 177*3ac7fe5aSThomas Gleixner struct debug_bucket *db = obj_hash; 178*3ac7fe5aSThomas Gleixner struct hlist_node *node, *tmp; 179*3ac7fe5aSThomas Gleixner struct debug_obj *obj; 180*3ac7fe5aSThomas Gleixner unsigned long flags; 181*3ac7fe5aSThomas Gleixner int i; 182*3ac7fe5aSThomas Gleixner 183*3ac7fe5aSThomas Gleixner printk(KERN_WARNING "ODEBUG: Out of memory. ODEBUG disabled\n"); 184*3ac7fe5aSThomas Gleixner 185*3ac7fe5aSThomas Gleixner for (i = 0; i < ODEBUG_HASH_SIZE; i++, db++) { 186*3ac7fe5aSThomas Gleixner spin_lock_irqsave(&db->lock, flags); 187*3ac7fe5aSThomas Gleixner hlist_for_each_entry_safe(obj, node, tmp, &db->list, node) { 188*3ac7fe5aSThomas Gleixner hlist_del(&obj->node); 189*3ac7fe5aSThomas Gleixner free_object(obj); 190*3ac7fe5aSThomas Gleixner } 191*3ac7fe5aSThomas Gleixner spin_unlock_irqrestore(&db->lock, flags); 192*3ac7fe5aSThomas Gleixner } 193*3ac7fe5aSThomas Gleixner } 194*3ac7fe5aSThomas Gleixner 195*3ac7fe5aSThomas Gleixner /* 196*3ac7fe5aSThomas Gleixner * We use the pfn of the address for the hash. That way we can check 197*3ac7fe5aSThomas Gleixner * for freed objects simply by checking the affected bucket. 198*3ac7fe5aSThomas Gleixner */ 199*3ac7fe5aSThomas Gleixner static struct debug_bucket *get_bucket(unsigned long addr) 200*3ac7fe5aSThomas Gleixner { 201*3ac7fe5aSThomas Gleixner unsigned long hash; 202*3ac7fe5aSThomas Gleixner 203*3ac7fe5aSThomas Gleixner hash = hash_long((addr >> ODEBUG_CHUNK_SHIFT), ODEBUG_HASH_BITS); 204*3ac7fe5aSThomas Gleixner return &obj_hash[hash]; 205*3ac7fe5aSThomas Gleixner } 206*3ac7fe5aSThomas Gleixner 207*3ac7fe5aSThomas Gleixner static void debug_print_object(struct debug_obj *obj, char *msg) 208*3ac7fe5aSThomas Gleixner { 209*3ac7fe5aSThomas Gleixner static int limit; 210*3ac7fe5aSThomas Gleixner 211*3ac7fe5aSThomas Gleixner if (limit < 5 && obj->descr != descr_test) { 212*3ac7fe5aSThomas Gleixner limit++; 213*3ac7fe5aSThomas Gleixner printk(KERN_ERR "ODEBUG: %s %s object type: %s\n", msg, 214*3ac7fe5aSThomas Gleixner obj_states[obj->state], obj->descr->name); 215*3ac7fe5aSThomas Gleixner WARN_ON(1); 216*3ac7fe5aSThomas Gleixner } 217*3ac7fe5aSThomas Gleixner debug_objects_warnings++; 218*3ac7fe5aSThomas Gleixner } 219*3ac7fe5aSThomas Gleixner 220*3ac7fe5aSThomas Gleixner /* 221*3ac7fe5aSThomas Gleixner * Try to repair the damage, so we have a better chance to get useful 222*3ac7fe5aSThomas Gleixner * debug output. 223*3ac7fe5aSThomas Gleixner */ 224*3ac7fe5aSThomas Gleixner static void 225*3ac7fe5aSThomas Gleixner debug_object_fixup(int (*fixup)(void *addr, enum debug_obj_state state), 226*3ac7fe5aSThomas Gleixner void * addr, enum debug_obj_state state) 227*3ac7fe5aSThomas Gleixner { 228*3ac7fe5aSThomas Gleixner if (fixup) 229*3ac7fe5aSThomas Gleixner debug_objects_fixups += fixup(addr, state); 230*3ac7fe5aSThomas Gleixner } 231*3ac7fe5aSThomas Gleixner 232*3ac7fe5aSThomas Gleixner static void debug_object_is_on_stack(void *addr, int onstack) 233*3ac7fe5aSThomas Gleixner { 234*3ac7fe5aSThomas Gleixner void *stack = current->stack; 235*3ac7fe5aSThomas Gleixner int is_on_stack; 236*3ac7fe5aSThomas Gleixner static int limit; 237*3ac7fe5aSThomas Gleixner 238*3ac7fe5aSThomas Gleixner if (limit > 4) 239*3ac7fe5aSThomas Gleixner return; 240*3ac7fe5aSThomas Gleixner 241*3ac7fe5aSThomas Gleixner is_on_stack = (addr >= stack && addr < (stack + THREAD_SIZE)); 242*3ac7fe5aSThomas Gleixner 243*3ac7fe5aSThomas Gleixner if (is_on_stack == onstack) 244*3ac7fe5aSThomas Gleixner return; 245*3ac7fe5aSThomas Gleixner 246*3ac7fe5aSThomas Gleixner limit++; 247*3ac7fe5aSThomas Gleixner if (is_on_stack) 248*3ac7fe5aSThomas Gleixner printk(KERN_WARNING 249*3ac7fe5aSThomas Gleixner "ODEBUG: object is on stack, but not annotated\n"); 250*3ac7fe5aSThomas Gleixner else 251*3ac7fe5aSThomas Gleixner printk(KERN_WARNING 252*3ac7fe5aSThomas Gleixner "ODEBUG: object is not on stack, but annotated\n"); 253*3ac7fe5aSThomas Gleixner WARN_ON(1); 254*3ac7fe5aSThomas Gleixner } 255*3ac7fe5aSThomas Gleixner 256*3ac7fe5aSThomas Gleixner static void 257*3ac7fe5aSThomas Gleixner __debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack) 258*3ac7fe5aSThomas Gleixner { 259*3ac7fe5aSThomas Gleixner enum debug_obj_state state; 260*3ac7fe5aSThomas Gleixner struct debug_bucket *db; 261*3ac7fe5aSThomas Gleixner struct debug_obj *obj; 262*3ac7fe5aSThomas Gleixner unsigned long flags; 263*3ac7fe5aSThomas Gleixner 264*3ac7fe5aSThomas Gleixner db = get_bucket((unsigned long) addr); 265*3ac7fe5aSThomas Gleixner 266*3ac7fe5aSThomas Gleixner spin_lock_irqsave(&db->lock, flags); 267*3ac7fe5aSThomas Gleixner 268*3ac7fe5aSThomas Gleixner obj = lookup_object(addr, db); 269*3ac7fe5aSThomas Gleixner if (!obj) { 270*3ac7fe5aSThomas Gleixner obj = alloc_object(addr, db, descr); 271*3ac7fe5aSThomas Gleixner if (!obj) { 272*3ac7fe5aSThomas Gleixner debug_objects_enabled = 0; 273*3ac7fe5aSThomas Gleixner spin_unlock_irqrestore(&db->lock, flags); 274*3ac7fe5aSThomas Gleixner debug_objects_oom(); 275*3ac7fe5aSThomas Gleixner return; 276*3ac7fe5aSThomas Gleixner } 277*3ac7fe5aSThomas Gleixner debug_object_is_on_stack(addr, onstack); 278*3ac7fe5aSThomas Gleixner } 279*3ac7fe5aSThomas Gleixner 280*3ac7fe5aSThomas Gleixner switch (obj->state) { 281*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_NONE: 282*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_INIT: 283*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_INACTIVE: 284*3ac7fe5aSThomas Gleixner obj->state = ODEBUG_STATE_INIT; 285*3ac7fe5aSThomas Gleixner break; 286*3ac7fe5aSThomas Gleixner 287*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_ACTIVE: 288*3ac7fe5aSThomas Gleixner debug_print_object(obj, "init"); 289*3ac7fe5aSThomas Gleixner state = obj->state; 290*3ac7fe5aSThomas Gleixner spin_unlock_irqrestore(&db->lock, flags); 291*3ac7fe5aSThomas Gleixner debug_object_fixup(descr->fixup_init, addr, state); 292*3ac7fe5aSThomas Gleixner return; 293*3ac7fe5aSThomas Gleixner 294*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_DESTROYED: 295*3ac7fe5aSThomas Gleixner debug_print_object(obj, "init"); 296*3ac7fe5aSThomas Gleixner break; 297*3ac7fe5aSThomas Gleixner default: 298*3ac7fe5aSThomas Gleixner break; 299*3ac7fe5aSThomas Gleixner } 300*3ac7fe5aSThomas Gleixner 301*3ac7fe5aSThomas Gleixner spin_unlock_irqrestore(&db->lock, flags); 302*3ac7fe5aSThomas Gleixner } 303*3ac7fe5aSThomas Gleixner 304*3ac7fe5aSThomas Gleixner /** 305*3ac7fe5aSThomas Gleixner * debug_object_init - debug checks when an object is initialized 306*3ac7fe5aSThomas Gleixner * @addr: address of the object 307*3ac7fe5aSThomas Gleixner * @descr: pointer to an object specific debug description structure 308*3ac7fe5aSThomas Gleixner */ 309*3ac7fe5aSThomas Gleixner void debug_object_init(void *addr, struct debug_obj_descr *descr) 310*3ac7fe5aSThomas Gleixner { 311*3ac7fe5aSThomas Gleixner if (!debug_objects_enabled) 312*3ac7fe5aSThomas Gleixner return; 313*3ac7fe5aSThomas Gleixner 314*3ac7fe5aSThomas Gleixner __debug_object_init(addr, descr, 0); 315*3ac7fe5aSThomas Gleixner } 316*3ac7fe5aSThomas Gleixner 317*3ac7fe5aSThomas Gleixner /** 318*3ac7fe5aSThomas Gleixner * debug_object_init_on_stack - debug checks when an object on stack is 319*3ac7fe5aSThomas Gleixner * initialized 320*3ac7fe5aSThomas Gleixner * @addr: address of the object 321*3ac7fe5aSThomas Gleixner * @descr: pointer to an object specific debug description structure 322*3ac7fe5aSThomas Gleixner */ 323*3ac7fe5aSThomas Gleixner void debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr) 324*3ac7fe5aSThomas Gleixner { 325*3ac7fe5aSThomas Gleixner if (!debug_objects_enabled) 326*3ac7fe5aSThomas Gleixner return; 327*3ac7fe5aSThomas Gleixner 328*3ac7fe5aSThomas Gleixner __debug_object_init(addr, descr, 1); 329*3ac7fe5aSThomas Gleixner } 330*3ac7fe5aSThomas Gleixner 331*3ac7fe5aSThomas Gleixner /** 332*3ac7fe5aSThomas Gleixner * debug_object_activate - debug checks when an object is activated 333*3ac7fe5aSThomas Gleixner * @addr: address of the object 334*3ac7fe5aSThomas Gleixner * @descr: pointer to an object specific debug description structure 335*3ac7fe5aSThomas Gleixner */ 336*3ac7fe5aSThomas Gleixner void debug_object_activate(void *addr, struct debug_obj_descr *descr) 337*3ac7fe5aSThomas Gleixner { 338*3ac7fe5aSThomas Gleixner enum debug_obj_state state; 339*3ac7fe5aSThomas Gleixner struct debug_bucket *db; 340*3ac7fe5aSThomas Gleixner struct debug_obj *obj; 341*3ac7fe5aSThomas Gleixner unsigned long flags; 342*3ac7fe5aSThomas Gleixner 343*3ac7fe5aSThomas Gleixner if (!debug_objects_enabled) 344*3ac7fe5aSThomas Gleixner return; 345*3ac7fe5aSThomas Gleixner 346*3ac7fe5aSThomas Gleixner db = get_bucket((unsigned long) addr); 347*3ac7fe5aSThomas Gleixner 348*3ac7fe5aSThomas Gleixner spin_lock_irqsave(&db->lock, flags); 349*3ac7fe5aSThomas Gleixner 350*3ac7fe5aSThomas Gleixner obj = lookup_object(addr, db); 351*3ac7fe5aSThomas Gleixner if (obj) { 352*3ac7fe5aSThomas Gleixner switch (obj->state) { 353*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_INIT: 354*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_INACTIVE: 355*3ac7fe5aSThomas Gleixner obj->state = ODEBUG_STATE_ACTIVE; 356*3ac7fe5aSThomas Gleixner break; 357*3ac7fe5aSThomas Gleixner 358*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_ACTIVE: 359*3ac7fe5aSThomas Gleixner debug_print_object(obj, "activate"); 360*3ac7fe5aSThomas Gleixner state = obj->state; 361*3ac7fe5aSThomas Gleixner spin_unlock_irqrestore(&db->lock, flags); 362*3ac7fe5aSThomas Gleixner debug_object_fixup(descr->fixup_activate, addr, state); 363*3ac7fe5aSThomas Gleixner return; 364*3ac7fe5aSThomas Gleixner 365*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_DESTROYED: 366*3ac7fe5aSThomas Gleixner debug_print_object(obj, "activate"); 367*3ac7fe5aSThomas Gleixner break; 368*3ac7fe5aSThomas Gleixner default: 369*3ac7fe5aSThomas Gleixner break; 370*3ac7fe5aSThomas Gleixner } 371*3ac7fe5aSThomas Gleixner spin_unlock_irqrestore(&db->lock, flags); 372*3ac7fe5aSThomas Gleixner return; 373*3ac7fe5aSThomas Gleixner } 374*3ac7fe5aSThomas Gleixner 375*3ac7fe5aSThomas Gleixner spin_unlock_irqrestore(&db->lock, flags); 376*3ac7fe5aSThomas Gleixner /* 377*3ac7fe5aSThomas Gleixner * This happens when a static object is activated. We 378*3ac7fe5aSThomas Gleixner * let the type specific code decide whether this is 379*3ac7fe5aSThomas Gleixner * true or not. 380*3ac7fe5aSThomas Gleixner */ 381*3ac7fe5aSThomas Gleixner debug_object_fixup(descr->fixup_activate, addr, 382*3ac7fe5aSThomas Gleixner ODEBUG_STATE_NOTAVAILABLE); 383*3ac7fe5aSThomas Gleixner } 384*3ac7fe5aSThomas Gleixner 385*3ac7fe5aSThomas Gleixner /** 386*3ac7fe5aSThomas Gleixner * debug_object_deactivate - debug checks when an object is deactivated 387*3ac7fe5aSThomas Gleixner * @addr: address of the object 388*3ac7fe5aSThomas Gleixner * @descr: pointer to an object specific debug description structure 389*3ac7fe5aSThomas Gleixner */ 390*3ac7fe5aSThomas Gleixner void debug_object_deactivate(void *addr, struct debug_obj_descr *descr) 391*3ac7fe5aSThomas Gleixner { 392*3ac7fe5aSThomas Gleixner struct debug_bucket *db; 393*3ac7fe5aSThomas Gleixner struct debug_obj *obj; 394*3ac7fe5aSThomas Gleixner unsigned long flags; 395*3ac7fe5aSThomas Gleixner 396*3ac7fe5aSThomas Gleixner if (!debug_objects_enabled) 397*3ac7fe5aSThomas Gleixner return; 398*3ac7fe5aSThomas Gleixner 399*3ac7fe5aSThomas Gleixner db = get_bucket((unsigned long) addr); 400*3ac7fe5aSThomas Gleixner 401*3ac7fe5aSThomas Gleixner spin_lock_irqsave(&db->lock, flags); 402*3ac7fe5aSThomas Gleixner 403*3ac7fe5aSThomas Gleixner obj = lookup_object(addr, db); 404*3ac7fe5aSThomas Gleixner if (obj) { 405*3ac7fe5aSThomas Gleixner switch (obj->state) { 406*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_INIT: 407*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_INACTIVE: 408*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_ACTIVE: 409*3ac7fe5aSThomas Gleixner obj->state = ODEBUG_STATE_INACTIVE; 410*3ac7fe5aSThomas Gleixner break; 411*3ac7fe5aSThomas Gleixner 412*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_DESTROYED: 413*3ac7fe5aSThomas Gleixner debug_print_object(obj, "deactivate"); 414*3ac7fe5aSThomas Gleixner break; 415*3ac7fe5aSThomas Gleixner default: 416*3ac7fe5aSThomas Gleixner break; 417*3ac7fe5aSThomas Gleixner } 418*3ac7fe5aSThomas Gleixner } else { 419*3ac7fe5aSThomas Gleixner struct debug_obj o = { .object = addr, 420*3ac7fe5aSThomas Gleixner .state = ODEBUG_STATE_NOTAVAILABLE, 421*3ac7fe5aSThomas Gleixner .descr = descr }; 422*3ac7fe5aSThomas Gleixner 423*3ac7fe5aSThomas Gleixner debug_print_object(&o, "deactivate"); 424*3ac7fe5aSThomas Gleixner } 425*3ac7fe5aSThomas Gleixner 426*3ac7fe5aSThomas Gleixner spin_unlock_irqrestore(&db->lock, flags); 427*3ac7fe5aSThomas Gleixner } 428*3ac7fe5aSThomas Gleixner 429*3ac7fe5aSThomas Gleixner /** 430*3ac7fe5aSThomas Gleixner * debug_object_destroy - debug checks when an object is destroyed 431*3ac7fe5aSThomas Gleixner * @addr: address of the object 432*3ac7fe5aSThomas Gleixner * @descr: pointer to an object specific debug description structure 433*3ac7fe5aSThomas Gleixner */ 434*3ac7fe5aSThomas Gleixner void debug_object_destroy(void *addr, struct debug_obj_descr *descr) 435*3ac7fe5aSThomas Gleixner { 436*3ac7fe5aSThomas Gleixner enum debug_obj_state state; 437*3ac7fe5aSThomas Gleixner struct debug_bucket *db; 438*3ac7fe5aSThomas Gleixner struct debug_obj *obj; 439*3ac7fe5aSThomas Gleixner unsigned long flags; 440*3ac7fe5aSThomas Gleixner 441*3ac7fe5aSThomas Gleixner if (!debug_objects_enabled) 442*3ac7fe5aSThomas Gleixner return; 443*3ac7fe5aSThomas Gleixner 444*3ac7fe5aSThomas Gleixner db = get_bucket((unsigned long) addr); 445*3ac7fe5aSThomas Gleixner 446*3ac7fe5aSThomas Gleixner spin_lock_irqsave(&db->lock, flags); 447*3ac7fe5aSThomas Gleixner 448*3ac7fe5aSThomas Gleixner obj = lookup_object(addr, db); 449*3ac7fe5aSThomas Gleixner if (!obj) 450*3ac7fe5aSThomas Gleixner goto out_unlock; 451*3ac7fe5aSThomas Gleixner 452*3ac7fe5aSThomas Gleixner switch (obj->state) { 453*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_NONE: 454*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_INIT: 455*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_INACTIVE: 456*3ac7fe5aSThomas Gleixner obj->state = ODEBUG_STATE_DESTROYED; 457*3ac7fe5aSThomas Gleixner break; 458*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_ACTIVE: 459*3ac7fe5aSThomas Gleixner debug_print_object(obj, "destroy"); 460*3ac7fe5aSThomas Gleixner state = obj->state; 461*3ac7fe5aSThomas Gleixner spin_unlock_irqrestore(&db->lock, flags); 462*3ac7fe5aSThomas Gleixner debug_object_fixup(descr->fixup_destroy, addr, state); 463*3ac7fe5aSThomas Gleixner return; 464*3ac7fe5aSThomas Gleixner 465*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_DESTROYED: 466*3ac7fe5aSThomas Gleixner debug_print_object(obj, "destroy"); 467*3ac7fe5aSThomas Gleixner break; 468*3ac7fe5aSThomas Gleixner default: 469*3ac7fe5aSThomas Gleixner break; 470*3ac7fe5aSThomas Gleixner } 471*3ac7fe5aSThomas Gleixner out_unlock: 472*3ac7fe5aSThomas Gleixner spin_unlock_irqrestore(&db->lock, flags); 473*3ac7fe5aSThomas Gleixner } 474*3ac7fe5aSThomas Gleixner 475*3ac7fe5aSThomas Gleixner /** 476*3ac7fe5aSThomas Gleixner * debug_object_free - debug checks when an object is freed 477*3ac7fe5aSThomas Gleixner * @addr: address of the object 478*3ac7fe5aSThomas Gleixner * @descr: pointer to an object specific debug description structure 479*3ac7fe5aSThomas Gleixner */ 480*3ac7fe5aSThomas Gleixner void debug_object_free(void *addr, struct debug_obj_descr *descr) 481*3ac7fe5aSThomas Gleixner { 482*3ac7fe5aSThomas Gleixner enum debug_obj_state state; 483*3ac7fe5aSThomas Gleixner struct debug_bucket *db; 484*3ac7fe5aSThomas Gleixner struct debug_obj *obj; 485*3ac7fe5aSThomas Gleixner unsigned long flags; 486*3ac7fe5aSThomas Gleixner 487*3ac7fe5aSThomas Gleixner if (!debug_objects_enabled) 488*3ac7fe5aSThomas Gleixner return; 489*3ac7fe5aSThomas Gleixner 490*3ac7fe5aSThomas Gleixner db = get_bucket((unsigned long) addr); 491*3ac7fe5aSThomas Gleixner 492*3ac7fe5aSThomas Gleixner spin_lock_irqsave(&db->lock, flags); 493*3ac7fe5aSThomas Gleixner 494*3ac7fe5aSThomas Gleixner obj = lookup_object(addr, db); 495*3ac7fe5aSThomas Gleixner if (!obj) 496*3ac7fe5aSThomas Gleixner goto out_unlock; 497*3ac7fe5aSThomas Gleixner 498*3ac7fe5aSThomas Gleixner switch (obj->state) { 499*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_ACTIVE: 500*3ac7fe5aSThomas Gleixner debug_print_object(obj, "free"); 501*3ac7fe5aSThomas Gleixner state = obj->state; 502*3ac7fe5aSThomas Gleixner spin_unlock_irqrestore(&db->lock, flags); 503*3ac7fe5aSThomas Gleixner debug_object_fixup(descr->fixup_free, addr, state); 504*3ac7fe5aSThomas Gleixner return; 505*3ac7fe5aSThomas Gleixner default: 506*3ac7fe5aSThomas Gleixner hlist_del(&obj->node); 507*3ac7fe5aSThomas Gleixner free_object(obj); 508*3ac7fe5aSThomas Gleixner break; 509*3ac7fe5aSThomas Gleixner } 510*3ac7fe5aSThomas Gleixner out_unlock: 511*3ac7fe5aSThomas Gleixner spin_unlock_irqrestore(&db->lock, flags); 512*3ac7fe5aSThomas Gleixner } 513*3ac7fe5aSThomas Gleixner 514*3ac7fe5aSThomas Gleixner #ifdef CONFIG_DEBUG_OBJECTS_FREE 515*3ac7fe5aSThomas Gleixner static void __debug_check_no_obj_freed(const void *address, unsigned long size) 516*3ac7fe5aSThomas Gleixner { 517*3ac7fe5aSThomas Gleixner unsigned long flags, oaddr, saddr, eaddr, paddr, chunks; 518*3ac7fe5aSThomas Gleixner struct hlist_node *node, *tmp; 519*3ac7fe5aSThomas Gleixner struct debug_obj_descr *descr; 520*3ac7fe5aSThomas Gleixner enum debug_obj_state state; 521*3ac7fe5aSThomas Gleixner struct debug_bucket *db; 522*3ac7fe5aSThomas Gleixner struct debug_obj *obj; 523*3ac7fe5aSThomas Gleixner int cnt; 524*3ac7fe5aSThomas Gleixner 525*3ac7fe5aSThomas Gleixner saddr = (unsigned long) address; 526*3ac7fe5aSThomas Gleixner eaddr = saddr + size; 527*3ac7fe5aSThomas Gleixner paddr = saddr & ODEBUG_CHUNK_MASK; 528*3ac7fe5aSThomas Gleixner chunks = ((eaddr - paddr) + (ODEBUG_CHUNK_SIZE - 1)); 529*3ac7fe5aSThomas Gleixner chunks >>= ODEBUG_CHUNK_SHIFT; 530*3ac7fe5aSThomas Gleixner 531*3ac7fe5aSThomas Gleixner for (;chunks > 0; chunks--, paddr += ODEBUG_CHUNK_SIZE) { 532*3ac7fe5aSThomas Gleixner db = get_bucket(paddr); 533*3ac7fe5aSThomas Gleixner 534*3ac7fe5aSThomas Gleixner repeat: 535*3ac7fe5aSThomas Gleixner cnt = 0; 536*3ac7fe5aSThomas Gleixner spin_lock_irqsave(&db->lock, flags); 537*3ac7fe5aSThomas Gleixner hlist_for_each_entry_safe(obj, node, tmp, &db->list, node) { 538*3ac7fe5aSThomas Gleixner cnt++; 539*3ac7fe5aSThomas Gleixner oaddr = (unsigned long) obj->object; 540*3ac7fe5aSThomas Gleixner if (oaddr < saddr || oaddr >= eaddr) 541*3ac7fe5aSThomas Gleixner continue; 542*3ac7fe5aSThomas Gleixner 543*3ac7fe5aSThomas Gleixner switch (obj->state) { 544*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_ACTIVE: 545*3ac7fe5aSThomas Gleixner debug_print_object(obj, "free"); 546*3ac7fe5aSThomas Gleixner descr = obj->descr; 547*3ac7fe5aSThomas Gleixner state = obj->state; 548*3ac7fe5aSThomas Gleixner spin_unlock_irqrestore(&db->lock, flags); 549*3ac7fe5aSThomas Gleixner debug_object_fixup(descr->fixup_free, 550*3ac7fe5aSThomas Gleixner (void *) oaddr, state); 551*3ac7fe5aSThomas Gleixner goto repeat; 552*3ac7fe5aSThomas Gleixner default: 553*3ac7fe5aSThomas Gleixner hlist_del(&obj->node); 554*3ac7fe5aSThomas Gleixner free_object(obj); 555*3ac7fe5aSThomas Gleixner break; 556*3ac7fe5aSThomas Gleixner } 557*3ac7fe5aSThomas Gleixner } 558*3ac7fe5aSThomas Gleixner spin_unlock_irqrestore(&db->lock, flags); 559*3ac7fe5aSThomas Gleixner if (cnt > debug_objects_maxchain) 560*3ac7fe5aSThomas Gleixner debug_objects_maxchain = cnt; 561*3ac7fe5aSThomas Gleixner } 562*3ac7fe5aSThomas Gleixner } 563*3ac7fe5aSThomas Gleixner 564*3ac7fe5aSThomas Gleixner void debug_check_no_obj_freed(const void *address, unsigned long size) 565*3ac7fe5aSThomas Gleixner { 566*3ac7fe5aSThomas Gleixner if (debug_objects_enabled) 567*3ac7fe5aSThomas Gleixner __debug_check_no_obj_freed(address, size); 568*3ac7fe5aSThomas Gleixner } 569*3ac7fe5aSThomas Gleixner #endif 570*3ac7fe5aSThomas Gleixner 571*3ac7fe5aSThomas Gleixner #ifdef CONFIG_DEBUG_FS 572*3ac7fe5aSThomas Gleixner 573*3ac7fe5aSThomas Gleixner static int debug_stats_show(struct seq_file *m, void *v) 574*3ac7fe5aSThomas Gleixner { 575*3ac7fe5aSThomas Gleixner seq_printf(m, "max_chain :%d\n", debug_objects_maxchain); 576*3ac7fe5aSThomas Gleixner seq_printf(m, "warnings :%d\n", debug_objects_warnings); 577*3ac7fe5aSThomas Gleixner seq_printf(m, "fixups :%d\n", debug_objects_fixups); 578*3ac7fe5aSThomas Gleixner seq_printf(m, "pool_free :%d\n", obj_pool_free); 579*3ac7fe5aSThomas Gleixner seq_printf(m, "pool_min_free :%d\n", obj_pool_min_free); 580*3ac7fe5aSThomas Gleixner seq_printf(m, "pool_used :%d\n", obj_pool_used); 581*3ac7fe5aSThomas Gleixner seq_printf(m, "pool_max_used :%d\n", obj_pool_max_used); 582*3ac7fe5aSThomas Gleixner return 0; 583*3ac7fe5aSThomas Gleixner } 584*3ac7fe5aSThomas Gleixner 585*3ac7fe5aSThomas Gleixner static int debug_stats_open(struct inode *inode, struct file *filp) 586*3ac7fe5aSThomas Gleixner { 587*3ac7fe5aSThomas Gleixner return single_open(filp, debug_stats_show, NULL); 588*3ac7fe5aSThomas Gleixner } 589*3ac7fe5aSThomas Gleixner 590*3ac7fe5aSThomas Gleixner static const struct file_operations debug_stats_fops = { 591*3ac7fe5aSThomas Gleixner .open = debug_stats_open, 592*3ac7fe5aSThomas Gleixner .read = seq_read, 593*3ac7fe5aSThomas Gleixner .llseek = seq_lseek, 594*3ac7fe5aSThomas Gleixner .release = single_release, 595*3ac7fe5aSThomas Gleixner }; 596*3ac7fe5aSThomas Gleixner 597*3ac7fe5aSThomas Gleixner static int __init debug_objects_init_debugfs(void) 598*3ac7fe5aSThomas Gleixner { 599*3ac7fe5aSThomas Gleixner struct dentry *dbgdir, *dbgstats; 600*3ac7fe5aSThomas Gleixner 601*3ac7fe5aSThomas Gleixner if (!debug_objects_enabled) 602*3ac7fe5aSThomas Gleixner return 0; 603*3ac7fe5aSThomas Gleixner 604*3ac7fe5aSThomas Gleixner dbgdir = debugfs_create_dir("debug_objects", NULL); 605*3ac7fe5aSThomas Gleixner if (!dbgdir) 606*3ac7fe5aSThomas Gleixner return -ENOMEM; 607*3ac7fe5aSThomas Gleixner 608*3ac7fe5aSThomas Gleixner dbgstats = debugfs_create_file("stats", 0444, dbgdir, NULL, 609*3ac7fe5aSThomas Gleixner &debug_stats_fops); 610*3ac7fe5aSThomas Gleixner if (!dbgstats) 611*3ac7fe5aSThomas Gleixner goto err; 612*3ac7fe5aSThomas Gleixner 613*3ac7fe5aSThomas Gleixner return 0; 614*3ac7fe5aSThomas Gleixner 615*3ac7fe5aSThomas Gleixner err: 616*3ac7fe5aSThomas Gleixner debugfs_remove(dbgdir); 617*3ac7fe5aSThomas Gleixner 618*3ac7fe5aSThomas Gleixner return -ENOMEM; 619*3ac7fe5aSThomas Gleixner } 620*3ac7fe5aSThomas Gleixner __initcall(debug_objects_init_debugfs); 621*3ac7fe5aSThomas Gleixner 622*3ac7fe5aSThomas Gleixner #else 623*3ac7fe5aSThomas Gleixner static inline void debug_objects_init_debugfs(void) { } 624*3ac7fe5aSThomas Gleixner #endif 625*3ac7fe5aSThomas Gleixner 626*3ac7fe5aSThomas Gleixner #ifdef CONFIG_DEBUG_OBJECTS_SELFTEST 627*3ac7fe5aSThomas Gleixner 628*3ac7fe5aSThomas Gleixner /* Random data structure for the self test */ 629*3ac7fe5aSThomas Gleixner struct self_test { 630*3ac7fe5aSThomas Gleixner unsigned long dummy1[6]; 631*3ac7fe5aSThomas Gleixner int static_init; 632*3ac7fe5aSThomas Gleixner unsigned long dummy2[3]; 633*3ac7fe5aSThomas Gleixner }; 634*3ac7fe5aSThomas Gleixner 635*3ac7fe5aSThomas Gleixner static __initdata struct debug_obj_descr descr_type_test; 636*3ac7fe5aSThomas Gleixner 637*3ac7fe5aSThomas Gleixner /* 638*3ac7fe5aSThomas Gleixner * fixup_init is called when: 639*3ac7fe5aSThomas Gleixner * - an active object is initialized 640*3ac7fe5aSThomas Gleixner */ 641*3ac7fe5aSThomas Gleixner static int __init fixup_init(void *addr, enum debug_obj_state state) 642*3ac7fe5aSThomas Gleixner { 643*3ac7fe5aSThomas Gleixner struct self_test *obj = addr; 644*3ac7fe5aSThomas Gleixner 645*3ac7fe5aSThomas Gleixner switch (state) { 646*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_ACTIVE: 647*3ac7fe5aSThomas Gleixner debug_object_deactivate(obj, &descr_type_test); 648*3ac7fe5aSThomas Gleixner debug_object_init(obj, &descr_type_test); 649*3ac7fe5aSThomas Gleixner return 1; 650*3ac7fe5aSThomas Gleixner default: 651*3ac7fe5aSThomas Gleixner return 0; 652*3ac7fe5aSThomas Gleixner } 653*3ac7fe5aSThomas Gleixner } 654*3ac7fe5aSThomas Gleixner 655*3ac7fe5aSThomas Gleixner /* 656*3ac7fe5aSThomas Gleixner * fixup_activate is called when: 657*3ac7fe5aSThomas Gleixner * - an active object is activated 658*3ac7fe5aSThomas Gleixner * - an unknown object is activated (might be a statically initialized object) 659*3ac7fe5aSThomas Gleixner */ 660*3ac7fe5aSThomas Gleixner static int __init fixup_activate(void *addr, enum debug_obj_state state) 661*3ac7fe5aSThomas Gleixner { 662*3ac7fe5aSThomas Gleixner struct self_test *obj = addr; 663*3ac7fe5aSThomas Gleixner 664*3ac7fe5aSThomas Gleixner switch (state) { 665*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_NOTAVAILABLE: 666*3ac7fe5aSThomas Gleixner if (obj->static_init == 1) { 667*3ac7fe5aSThomas Gleixner debug_object_init(obj, &descr_type_test); 668*3ac7fe5aSThomas Gleixner debug_object_activate(obj, &descr_type_test); 669*3ac7fe5aSThomas Gleixner /* 670*3ac7fe5aSThomas Gleixner * Real code should return 0 here ! This is 671*3ac7fe5aSThomas Gleixner * not a fixup of some bad behaviour. We 672*3ac7fe5aSThomas Gleixner * merily call the debug_init function to keep 673*3ac7fe5aSThomas Gleixner * track of the object. 674*3ac7fe5aSThomas Gleixner */ 675*3ac7fe5aSThomas Gleixner return 1; 676*3ac7fe5aSThomas Gleixner } else { 677*3ac7fe5aSThomas Gleixner /* Real code needs to emit a warning here */ 678*3ac7fe5aSThomas Gleixner } 679*3ac7fe5aSThomas Gleixner return 0; 680*3ac7fe5aSThomas Gleixner 681*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_ACTIVE: 682*3ac7fe5aSThomas Gleixner debug_object_deactivate(obj, &descr_type_test); 683*3ac7fe5aSThomas Gleixner debug_object_activate(obj, &descr_type_test); 684*3ac7fe5aSThomas Gleixner return 1; 685*3ac7fe5aSThomas Gleixner 686*3ac7fe5aSThomas Gleixner default: 687*3ac7fe5aSThomas Gleixner return 0; 688*3ac7fe5aSThomas Gleixner } 689*3ac7fe5aSThomas Gleixner } 690*3ac7fe5aSThomas Gleixner 691*3ac7fe5aSThomas Gleixner /* 692*3ac7fe5aSThomas Gleixner * fixup_destroy is called when: 693*3ac7fe5aSThomas Gleixner * - an active object is destroyed 694*3ac7fe5aSThomas Gleixner */ 695*3ac7fe5aSThomas Gleixner static int __init fixup_destroy(void *addr, enum debug_obj_state state) 696*3ac7fe5aSThomas Gleixner { 697*3ac7fe5aSThomas Gleixner struct self_test *obj = addr; 698*3ac7fe5aSThomas Gleixner 699*3ac7fe5aSThomas Gleixner switch (state) { 700*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_ACTIVE: 701*3ac7fe5aSThomas Gleixner debug_object_deactivate(obj, &descr_type_test); 702*3ac7fe5aSThomas Gleixner debug_object_destroy(obj, &descr_type_test); 703*3ac7fe5aSThomas Gleixner return 1; 704*3ac7fe5aSThomas Gleixner default: 705*3ac7fe5aSThomas Gleixner return 0; 706*3ac7fe5aSThomas Gleixner } 707*3ac7fe5aSThomas Gleixner } 708*3ac7fe5aSThomas Gleixner 709*3ac7fe5aSThomas Gleixner /* 710*3ac7fe5aSThomas Gleixner * fixup_free is called when: 711*3ac7fe5aSThomas Gleixner * - an active object is freed 712*3ac7fe5aSThomas Gleixner */ 713*3ac7fe5aSThomas Gleixner static int __init fixup_free(void *addr, enum debug_obj_state state) 714*3ac7fe5aSThomas Gleixner { 715*3ac7fe5aSThomas Gleixner struct self_test *obj = addr; 716*3ac7fe5aSThomas Gleixner 717*3ac7fe5aSThomas Gleixner switch (state) { 718*3ac7fe5aSThomas Gleixner case ODEBUG_STATE_ACTIVE: 719*3ac7fe5aSThomas Gleixner debug_object_deactivate(obj, &descr_type_test); 720*3ac7fe5aSThomas Gleixner debug_object_free(obj, &descr_type_test); 721*3ac7fe5aSThomas Gleixner return 1; 722*3ac7fe5aSThomas Gleixner default: 723*3ac7fe5aSThomas Gleixner return 0; 724*3ac7fe5aSThomas Gleixner } 725*3ac7fe5aSThomas Gleixner } 726*3ac7fe5aSThomas Gleixner 727*3ac7fe5aSThomas Gleixner static int 728*3ac7fe5aSThomas Gleixner check_results(void *addr, enum debug_obj_state state, int fixups, int warnings) 729*3ac7fe5aSThomas Gleixner { 730*3ac7fe5aSThomas Gleixner struct debug_bucket *db; 731*3ac7fe5aSThomas Gleixner struct debug_obj *obj; 732*3ac7fe5aSThomas Gleixner unsigned long flags; 733*3ac7fe5aSThomas Gleixner int res = -EINVAL; 734*3ac7fe5aSThomas Gleixner 735*3ac7fe5aSThomas Gleixner db = get_bucket((unsigned long) addr); 736*3ac7fe5aSThomas Gleixner 737*3ac7fe5aSThomas Gleixner spin_lock_irqsave(&db->lock, flags); 738*3ac7fe5aSThomas Gleixner 739*3ac7fe5aSThomas Gleixner obj = lookup_object(addr, db); 740*3ac7fe5aSThomas Gleixner if (!obj && state != ODEBUG_STATE_NONE) { 741*3ac7fe5aSThomas Gleixner printk(KERN_ERR "ODEBUG: selftest object not found\n"); 742*3ac7fe5aSThomas Gleixner WARN_ON(1); 743*3ac7fe5aSThomas Gleixner goto out; 744*3ac7fe5aSThomas Gleixner } 745*3ac7fe5aSThomas Gleixner if (obj && obj->state != state) { 746*3ac7fe5aSThomas Gleixner printk(KERN_ERR "ODEBUG: selftest wrong state: %d != %d\n", 747*3ac7fe5aSThomas Gleixner obj->state, state); 748*3ac7fe5aSThomas Gleixner WARN_ON(1); 749*3ac7fe5aSThomas Gleixner goto out; 750*3ac7fe5aSThomas Gleixner } 751*3ac7fe5aSThomas Gleixner if (fixups != debug_objects_fixups) { 752*3ac7fe5aSThomas Gleixner printk(KERN_ERR "ODEBUG: selftest fixups failed %d != %d\n", 753*3ac7fe5aSThomas Gleixner fixups, debug_objects_fixups); 754*3ac7fe5aSThomas Gleixner WARN_ON(1); 755*3ac7fe5aSThomas Gleixner goto out; 756*3ac7fe5aSThomas Gleixner } 757*3ac7fe5aSThomas Gleixner if (warnings != debug_objects_warnings) { 758*3ac7fe5aSThomas Gleixner printk(KERN_ERR "ODEBUG: selftest warnings failed %d != %d\n", 759*3ac7fe5aSThomas Gleixner warnings, debug_objects_warnings); 760*3ac7fe5aSThomas Gleixner WARN_ON(1); 761*3ac7fe5aSThomas Gleixner goto out; 762*3ac7fe5aSThomas Gleixner } 763*3ac7fe5aSThomas Gleixner res = 0; 764*3ac7fe5aSThomas Gleixner out: 765*3ac7fe5aSThomas Gleixner spin_unlock_irqrestore(&db->lock, flags); 766*3ac7fe5aSThomas Gleixner if (res) 767*3ac7fe5aSThomas Gleixner debug_objects_enabled = 0; 768*3ac7fe5aSThomas Gleixner return res; 769*3ac7fe5aSThomas Gleixner } 770*3ac7fe5aSThomas Gleixner 771*3ac7fe5aSThomas Gleixner static __initdata struct debug_obj_descr descr_type_test = { 772*3ac7fe5aSThomas Gleixner .name = "selftest", 773*3ac7fe5aSThomas Gleixner .fixup_init = fixup_init, 774*3ac7fe5aSThomas Gleixner .fixup_activate = fixup_activate, 775*3ac7fe5aSThomas Gleixner .fixup_destroy = fixup_destroy, 776*3ac7fe5aSThomas Gleixner .fixup_free = fixup_free, 777*3ac7fe5aSThomas Gleixner }; 778*3ac7fe5aSThomas Gleixner 779*3ac7fe5aSThomas Gleixner static __initdata struct self_test obj = { .static_init = 0 }; 780*3ac7fe5aSThomas Gleixner 781*3ac7fe5aSThomas Gleixner static void __init debug_objects_selftest(void) 782*3ac7fe5aSThomas Gleixner { 783*3ac7fe5aSThomas Gleixner int fixups, oldfixups, warnings, oldwarnings; 784*3ac7fe5aSThomas Gleixner unsigned long flags; 785*3ac7fe5aSThomas Gleixner 786*3ac7fe5aSThomas Gleixner local_irq_save(flags); 787*3ac7fe5aSThomas Gleixner 788*3ac7fe5aSThomas Gleixner fixups = oldfixups = debug_objects_fixups; 789*3ac7fe5aSThomas Gleixner warnings = oldwarnings = debug_objects_warnings; 790*3ac7fe5aSThomas Gleixner descr_test = &descr_type_test; 791*3ac7fe5aSThomas Gleixner 792*3ac7fe5aSThomas Gleixner debug_object_init(&obj, &descr_type_test); 793*3ac7fe5aSThomas Gleixner if (check_results(&obj, ODEBUG_STATE_INIT, fixups, warnings)) 794*3ac7fe5aSThomas Gleixner goto out; 795*3ac7fe5aSThomas Gleixner debug_object_activate(&obj, &descr_type_test); 796*3ac7fe5aSThomas Gleixner if (check_results(&obj, ODEBUG_STATE_ACTIVE, fixups, warnings)) 797*3ac7fe5aSThomas Gleixner goto out; 798*3ac7fe5aSThomas Gleixner debug_object_activate(&obj, &descr_type_test); 799*3ac7fe5aSThomas Gleixner if (check_results(&obj, ODEBUG_STATE_ACTIVE, ++fixups, ++warnings)) 800*3ac7fe5aSThomas Gleixner goto out; 801*3ac7fe5aSThomas Gleixner debug_object_deactivate(&obj, &descr_type_test); 802*3ac7fe5aSThomas Gleixner if (check_results(&obj, ODEBUG_STATE_INACTIVE, fixups, warnings)) 803*3ac7fe5aSThomas Gleixner goto out; 804*3ac7fe5aSThomas Gleixner debug_object_destroy(&obj, &descr_type_test); 805*3ac7fe5aSThomas Gleixner if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, warnings)) 806*3ac7fe5aSThomas Gleixner goto out; 807*3ac7fe5aSThomas Gleixner debug_object_init(&obj, &descr_type_test); 808*3ac7fe5aSThomas Gleixner if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings)) 809*3ac7fe5aSThomas Gleixner goto out; 810*3ac7fe5aSThomas Gleixner debug_object_activate(&obj, &descr_type_test); 811*3ac7fe5aSThomas Gleixner if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings)) 812*3ac7fe5aSThomas Gleixner goto out; 813*3ac7fe5aSThomas Gleixner debug_object_deactivate(&obj, &descr_type_test); 814*3ac7fe5aSThomas Gleixner if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings)) 815*3ac7fe5aSThomas Gleixner goto out; 816*3ac7fe5aSThomas Gleixner debug_object_free(&obj, &descr_type_test); 817*3ac7fe5aSThomas Gleixner if (check_results(&obj, ODEBUG_STATE_NONE, fixups, warnings)) 818*3ac7fe5aSThomas Gleixner goto out; 819*3ac7fe5aSThomas Gleixner 820*3ac7fe5aSThomas Gleixner obj.static_init = 1; 821*3ac7fe5aSThomas Gleixner debug_object_activate(&obj, &descr_type_test); 822*3ac7fe5aSThomas Gleixner if (check_results(&obj, ODEBUG_STATE_ACTIVE, ++fixups, warnings)) 823*3ac7fe5aSThomas Gleixner goto out; 824*3ac7fe5aSThomas Gleixner debug_object_init(&obj, &descr_type_test); 825*3ac7fe5aSThomas Gleixner if (check_results(&obj, ODEBUG_STATE_INIT, ++fixups, ++warnings)) 826*3ac7fe5aSThomas Gleixner goto out; 827*3ac7fe5aSThomas Gleixner debug_object_free(&obj, &descr_type_test); 828*3ac7fe5aSThomas Gleixner if (check_results(&obj, ODEBUG_STATE_NONE, fixups, warnings)) 829*3ac7fe5aSThomas Gleixner goto out; 830*3ac7fe5aSThomas Gleixner 831*3ac7fe5aSThomas Gleixner #ifdef CONFIG_DEBUG_OBJECTS_FREE 832*3ac7fe5aSThomas Gleixner debug_object_init(&obj, &descr_type_test); 833*3ac7fe5aSThomas Gleixner if (check_results(&obj, ODEBUG_STATE_INIT, fixups, warnings)) 834*3ac7fe5aSThomas Gleixner goto out; 835*3ac7fe5aSThomas Gleixner debug_object_activate(&obj, &descr_type_test); 836*3ac7fe5aSThomas Gleixner if (check_results(&obj, ODEBUG_STATE_ACTIVE, fixups, warnings)) 837*3ac7fe5aSThomas Gleixner goto out; 838*3ac7fe5aSThomas Gleixner __debug_check_no_obj_freed(&obj, sizeof(obj)); 839*3ac7fe5aSThomas Gleixner if (check_results(&obj, ODEBUG_STATE_NONE, ++fixups, ++warnings)) 840*3ac7fe5aSThomas Gleixner goto out; 841*3ac7fe5aSThomas Gleixner #endif 842*3ac7fe5aSThomas Gleixner printk(KERN_INFO "ODEBUG: selftest passed\n"); 843*3ac7fe5aSThomas Gleixner 844*3ac7fe5aSThomas Gleixner out: 845*3ac7fe5aSThomas Gleixner debug_objects_fixups = oldfixups; 846*3ac7fe5aSThomas Gleixner debug_objects_warnings = oldwarnings; 847*3ac7fe5aSThomas Gleixner descr_test = NULL; 848*3ac7fe5aSThomas Gleixner 849*3ac7fe5aSThomas Gleixner local_irq_restore(flags); 850*3ac7fe5aSThomas Gleixner } 851*3ac7fe5aSThomas Gleixner #else 852*3ac7fe5aSThomas Gleixner static inline void debug_objects_selftest(void) { } 853*3ac7fe5aSThomas Gleixner #endif 854*3ac7fe5aSThomas Gleixner 855*3ac7fe5aSThomas Gleixner /* 856*3ac7fe5aSThomas Gleixner * Called during early boot to initialize the hash buckets and link 857*3ac7fe5aSThomas Gleixner * the static object pool objects into the poll list. After this call 858*3ac7fe5aSThomas Gleixner * the object tracker is fully operational. 859*3ac7fe5aSThomas Gleixner */ 860*3ac7fe5aSThomas Gleixner void __init debug_objects_early_init(void) 861*3ac7fe5aSThomas Gleixner { 862*3ac7fe5aSThomas Gleixner int i; 863*3ac7fe5aSThomas Gleixner 864*3ac7fe5aSThomas Gleixner for (i = 0; i < ODEBUG_HASH_SIZE; i++) 865*3ac7fe5aSThomas Gleixner spin_lock_init(&obj_hash[i].lock); 866*3ac7fe5aSThomas Gleixner 867*3ac7fe5aSThomas Gleixner for (i = 0; i < ODEBUG_POOL_SIZE; i++) 868*3ac7fe5aSThomas Gleixner hlist_add_head(&obj_static_pool[i].node, &obj_pool); 869*3ac7fe5aSThomas Gleixner } 870*3ac7fe5aSThomas Gleixner 871*3ac7fe5aSThomas Gleixner /* 872*3ac7fe5aSThomas Gleixner * Called after the kmem_caches are functional to setup a dedicated 873*3ac7fe5aSThomas Gleixner * cache pool, which has the SLAB_DEBUG_OBJECTS flag set. This flag 874*3ac7fe5aSThomas Gleixner * prevents that the debug code is called on kmem_cache_free() for the 875*3ac7fe5aSThomas Gleixner * debug tracker objects to avoid recursive calls. 876*3ac7fe5aSThomas Gleixner */ 877*3ac7fe5aSThomas Gleixner void __init debug_objects_mem_init(void) 878*3ac7fe5aSThomas Gleixner { 879*3ac7fe5aSThomas Gleixner if (!debug_objects_enabled) 880*3ac7fe5aSThomas Gleixner return; 881*3ac7fe5aSThomas Gleixner 882*3ac7fe5aSThomas Gleixner obj_cache = kmem_cache_create("debug_objects_cache", 883*3ac7fe5aSThomas Gleixner sizeof (struct debug_obj), 0, 884*3ac7fe5aSThomas Gleixner SLAB_DEBUG_OBJECTS, NULL); 885*3ac7fe5aSThomas Gleixner 886*3ac7fe5aSThomas Gleixner if (!obj_cache) 887*3ac7fe5aSThomas Gleixner debug_objects_enabled = 0; 888*3ac7fe5aSThomas Gleixner else 889*3ac7fe5aSThomas Gleixner debug_objects_selftest(); 890*3ac7fe5aSThomas Gleixner } 891