enum debug_obj_state state; struct debug_bucket *db; struct debug_obj *obj; unsigned long flags; if (!debug_objects_enabled) return; db = get_bucket((unsigned long) addr); raw_spin_lock_irqsave(&db->lock, flags); obj = lookup_object(addr, db); if (!obj) goto out_unlock; switch (obj->state) { case ODEBUG_STATE_NONE: case ODEBUG_STATE_INIT: case ODEBUG_STATE_INACTIVE: obj->state = ODEBUG_STATE_DESTROYED; break; case ODEBUG_STATE_ACTIVE: debug_print_object(obj, "destroy"); state = obj->state; raw_spin_unlock_irqrestore(&db->lock, flags); debug_object_fixup(descr->fixup_destroy, addr, state); return; case ODEBUG_STATE_DESTROYED: debug_print_object(obj, "destroy"); break; default: break; }out_unlock: raw_spin_unlock_irqrestore(&db->lock, flags);} /** * debug_object_free - debug checks when an object is freed * @addr: address of the object * @descr: pointer to an object specific debug description structure */void debug_object_free(void *addr, struct debug_obj_descr *descr){ enum debug_obj_state state; struct debug_bucket *db; struct debug_obj *obj; unsigned long flags; if (!debug_objects_enabled) return; db = get_bucket((unsigned long) addr); raw_spin_lock_irqsave(&db->lock, flags); obj = lookup_object(addr, db); if (!obj) goto out_unlock; switch (obj->state) { case ODEBUG_STATE_ACTIVE: debug_print_object(obj, "free"); state = obj->state; raw_spin_unlock_irqrestore(&db->lock, flags); debug_object_fixup(descr->fixup_free, addr, state); return; default: hlist_del(&obj->node); raw_spin_unlock_irqrestore(&db->lock, flags); free_object(obj); return; }out_unlock: raw_spin_unlock_irqrestore(&db->lock, flags);} /** * debug_object_assert_init - debug checks when object should be init-ed * @addr: address of the object * @descr: pointer to an object specific debug description structure */void debug_object_assert_init(void *addr, struct debug_obj_descr *descr){ struct debug_bucket *db; struct debug_obj *obj; unsigned long flags; if (!debug_objects_enabled) return; db = get_bucket((unsigned long) addr); raw_spin_lock_irqsave(&db->lock, flags); obj = lookup_object(addr, db); if (!obj) { struct debug_obj o = { .object = addr, .state = ODEBUG_STATE_NOTAVAILABLE, .descr = descr }; raw_spin_unlock_irqrestore(&db->lock, flags); /* * Maybe the object is static. Let the type specific * code decide what to do. */ if (debug_object_fixup(descr->fixup_assert_init, addr, ODEBUG_STATE_NOTAVAILABLE)) debug_print_object(&o, "assert_init"); return; } raw_spin_unlock_irqrestore(&db->lock, flags);} /** * debug_object_active_state - debug checks object usage state machine * @addr: address of the object * @descr: pointer to an object specific debug description structure * @expect: expected state * @next: state to move to if expected state is found */voiddebug_object_active_state(void *addr, struct debug_obj_descr *descr, unsigned int expect, unsigned int next){ struct debug_bucket *db; struct debug_obj *obj; unsigned long flags; if (!debug_objects_enabled) return; db = get_bucket((unsigned long) addr); raw_spin_lock_irqsave(&db->lock, flags); obj = lookup_object(addr, db); if (obj) { switch (obj->state) { case ODEBUG_STATE_ACTIVE: if (obj->astate == expect) obj->astate = next; else debug_print_object(obj, "active_state"); break; default: debug_print_object(obj, "active_state"); break; } } else { struct debug_obj o = { .object = addr, .state = ODEBUG_STATE_NOTAVAILABLE, .descr = descr }; debug_print_object(&o, "active_state"); } raw_spin_unlock_irqrestore(&db->lock, flags);} #ifdef CONFIG_DEBUG_OBJECTS_FREEstatic void __debug_check_no_obj_freed(const void *address, unsigned long size){ unsigned long flags, oaddr, saddr, eaddr, paddr, chunks; struct hlist_node *tmp; HLIST_HEAD(freelist); struct debug_obj_descr *descr; enum debug_obj_state state; struct debug_bucket *db; struct debug_obj *obj; int cnt; saddr = (unsigned long) address; eaddr = saddr + size; paddr = saddr & ODEBUG_CHUNK_MASK; chunks = ((eaddr - paddr) + (ODEBUG_CHUNK_SIZE - 1)); chunks >>= ODEBUG_CHUNK_SHIFT; for (;chunks > 0; chunks--, paddr += ODEBUG_CHUNK_SIZE) { db = get_bucket(paddr); repeat: cnt = 0; raw_spin_lock_irqsave(&db->lock, flags); hlist_for_each_entry_safe(obj, tmp, &db->list, node) { cnt++; oaddr = (unsigned long) obj->object; if (oaddr < saddr || oaddr >= eaddr) continue; switch (obj->state) { case ODEBUG_STATE_ACTIVE: debug_print_object(obj, "free"); descr = obj->descr; state = obj->state; raw_spin_unlock_irqrestore(&db->lock, flags); debug_object_fixup(descr->fixup_free, (void *) oaddr, state); goto repeat; default: hlist_del(&obj->node); hlist_add_head(&obj->node, &freelist); break; } } raw_spin_unlock_irqrestore(&db->lock, flags); /* Now free them */ hlist_for_each_entry_safe(obj, tmp, &freelist, node) { hlist_del(&obj->node); free_object(obj); } if (cnt > debug_objects_maxchain) debug_objects_maxchain = cnt; }} void debug_check_no_obj_freed(const void *address, unsigned long size){ if (debug_objects_enabled) __debug_check_no_obj_freed(address, size);}#endif #ifdef CONFIG_DEBUG_FS static int debug_stats_show(struct seq_file *m, void *v){ seq_printf(m, "max_chain :%d\n", debug_objects_maxchain); seq_printf(m, "warnings :%d\n", debug_objects_warnings); seq_printf(m, "fixups :%d\n", debug_objects_fixups); seq_printf(m, "pool_free :%d\n", obj_pool_free); seq_printf(m, "pool_min_free :%d\n", obj_pool_min_free); seq_printf(m, "pool_used :%d\n", obj_pool_used); seq_printf(m, "pool_max_used :%d\n", obj_pool_max_used); return 0;} static int debug_stats_open(struct inode *inode, struct file *filp){ return single_open(filp, debug_stats_show, NULL);} static const struct file_operations debug_stats_fops = { .open = debug_stats_open, .read = seq_read, .llseek = seq_lseek, .release = single_release,}; static int __init debug_objects_init_debugfs(void){ struct dentry *dbgdir, *dbgstats; if (!debug_objects_enabled) return 0; dbgdir = debugfs_create_dir("debug_objects", NULL); if (!dbgdir) return -ENOMEM; dbgstats = debugfs_create_file("stats", 0444, dbgdir, NULL, &debug_stats_fops); if (!dbgstats) goto err; return 0; err: debugfs_remove(dbgdir); return -ENOMEM;}__initcall(debug_objects_init_debugfs); #elsestatic inline void debug_objects_init_debugfs(void) { }#endif #ifdef CONFIG_DEBUG_OBJECTS_SELFTEST /* Random data structure for the self test */struct self_test { unsigned long dummy1[6]; int static_init; unsigned long dummy2[3];}; static __initdata struct debug_obj_descr descr_type_test; /* * fixup_init is called when: * - an active object is initialized */static int __init fixup_init(void *addr, enum debug_obj_state state){ struct self_test *obj = addr; switch (state) { case ODEBUG_STATE_ACTIVE: debug_object_deactivate(obj, &descr_type_test); debug_object_init(obj, &descr_type_test); return 1; default: return 0; }} /* * fixup_activate is called when: * - an active object is activated * - an unknown object is activated (might be a statically initialized object) */static int __init fixup_activate(void *addr, enum debug_obj_state state){ struct self_test *obj = addr; switch (state) { case ODEBUG_STATE_NOTAVAILABLE: if (obj->static_init == 1) { debug_object_init(obj, &descr_type_test); debug_object_activate(obj, &descr_type_test); return 0; } return 1; case ODEBUG_STATE_ACTIVE: debug_object_deactivate(obj, &descr_type_test); debug_object_activate(obj, &descr_type_test); return 1; default: return 0; }} /* * fixup_destroy is called when: * - an active object is destroyed */static int __init fixup_destroy(void *addr, enum debug_obj_state state){ struct self_test *obj = addr; switch (state) { case ODEBUG_STATE_ACTIVE: debug_object_deactivate(obj, &descr_type_test); debug_object_destroy(obj, &descr_type_test); return 1; default: return 0; }} /* * fixup_free is called when: * - an active object is freed */static int __init fixup_free(void *addr, enum debug_obj_state state){ struct self_test *obj = addr; switch (state) { case ODEBUG_STATE_ACTIVE: debug_object_deactivate(obj, &descr_type_test); debug_object_free(obj, &descr_type_test); return 1; default: return 0; }} static int __initcheck_results(void *addr, enum debug_obj_state state, int fixups, int warnings){ struct debug_bucket *db; struct debug_obj *obj; unsigned long flags; int res = -EINVAL; db = get_bucket((unsigned long) addr); raw_spin_lock_irqsave(&db->lock, flags); obj = lookup_object(addr, db); if (!obj && state != ODEBUG_STATE_NONE) { WARN(1, KERN_ERR "ODEBUG: selftest object not found\n"); goto out; } if (obj && obj->state != state) { WARN(1, KERN_ERR "ODEBUG: selftest wrong state: %d != %d\n", obj->state, state); goto out; } if (fixups != debug_objects_fixups) { WARN(1, KERN_ERR "ODEBUG: selftest fixups failed %d != %d\n", fixups, debug_objects_fixups); goto out; } if (warnings != debug_objects_warnings) { WARN(1, KERN_ERR "ODEBUG: selftest warnings failed %d != %d\n", warnings, debug_objects_warnings); goto out; } res = 0;out: raw_spin_unlock_irqrestore(&db->lock, flags); if (res) debug_objects_enabled = 0; return res;} static __initdata struct debug_obj_descr descr_type_test = { .name = "selftest", .fixup_init = fixup_init, .fixup_activate = fixup_activate, .fixup_destroy = fixup_destroy, .fixup_free = fixup_free,}; static __initdata struct self_test obj = { .static_init = 0 }; static void __init debug_objects_selftest(void){ int fixups, oldfixups, warnings, oldwarnings; unsigned long flags; local_irq_save(flags); fixups = oldfixups = debug_objects_fixups; warnings = oldwarnings = debug_objects_warnings; descr_test = &descr_type_test; debug_object_init(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_INIT, fixups, warnings)) goto out; debug_object_activate(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_ACTIVE, fixups, warnings)) goto out; debug_object_activate(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_ACTIVE, ++fixups, ++warnings)) goto out; debug_object_deactivate(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_INACTIVE, fixups, warnings)) goto out; debug_object_destroy(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, warnings)) goto out; debug_object_init(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings)) goto out; debug_object_activate(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings)) goto out; debug_object_deactivate(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings)) goto out; debug_object_free(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_NONE, fixups, warnings)) goto out; obj.static_init = 1; debug_object_activate(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_ACTIVE, fixups, warnings)) goto out; debug_object_init(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_INIT, ++fixups, ++warnings)) goto out; debug_object_free(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_NONE, fixups, warnings)) goto out; #ifdef CONFIG_DEBUG_OBJECTS_FREE debug_object_init(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_INIT, fixups, warnings)) goto out; debug_object_activate(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_ACTIVE, fixups, warnings)) goto out; __debug_check_no_obj_freed(&obj, sizeof(obj)); if (check_results(&obj, ODEBUG_STATE_NONE, ++fixups, ++warnings)) goto out;#endif pr_info("selftest passed\n"); out: debug_objects_fixups = oldfixups; debug_objects_warnings = oldwarnings; descr_test = NULL; local_irq_restore(flags);}#elsestatic inline void debug_objects_selftest(void) { }#endifLines 501–1000 of 1097. Previous lines Load more
enum debug_obj_state state; struct debug_bucket *db; struct debug_obj *obj; unsigned long flags; if (!debug_objects_enabled) return; db = get_bucket((unsigned long) addr); raw_spin_lock_irqsave(&db->lock, flags); obj = lookup_object(addr, db); if (!obj) goto out_unlock; switch (obj->state) { case ODEBUG_STATE_NONE: case ODEBUG_STATE_INIT: case ODEBUG_STATE_INACTIVE: obj->state = ODEBUG_STATE_DESTROYED; break; case ODEBUG_STATE_ACTIVE: debug_print_object(obj, "destroy"); state = obj->state; raw_spin_unlock_irqrestore(&db->lock, flags); debug_object_fixup(descr->fixup_destroy, addr, state); return; case ODEBUG_STATE_DESTROYED: debug_print_object(obj, "destroy"); break; default: break; } out_unlock: raw_spin_unlock_irqrestore(&db->lock, flags); } /** * debug_object_free - debug checks when an object is freed * @addr: address of the object * @descr: pointer to an object specific debug description structure */ void debug_object_free(void *addr, struct debug_obj_descr *descr) { enum debug_obj_state state; struct debug_bucket *db; struct debug_obj *obj; unsigned long flags; if (!debug_objects_enabled) return; db = get_bucket((unsigned long) addr); raw_spin_lock_irqsave(&db->lock, flags); obj = lookup_object(addr, db); if (!obj) goto out_unlock; switch (obj->state) { case ODEBUG_STATE_ACTIVE: debug_print_object(obj, "free"); state = obj->state; raw_spin_unlock_irqrestore(&db->lock, flags); debug_object_fixup(descr->fixup_free, addr, state); return; default: hlist_del(&obj->node); raw_spin_unlock_irqrestore(&db->lock, flags); free_object(obj); return; } out_unlock: raw_spin_unlock_irqrestore(&db->lock, flags); } /** * debug_object_assert_init - debug checks when object should be init-ed * @addr: address of the object * @descr: pointer to an object specific debug description structure */ void debug_object_assert_init(void *addr, struct debug_obj_descr *descr) { struct debug_bucket *db; struct debug_obj *obj; unsigned long flags; if (!debug_objects_enabled) return; db = get_bucket((unsigned long) addr); raw_spin_lock_irqsave(&db->lock, flags); obj = lookup_object(addr, db); if (!obj) { struct debug_obj o = { .object = addr, .state = ODEBUG_STATE_NOTAVAILABLE, .descr = descr }; raw_spin_unlock_irqrestore(&db->lock, flags); /* * Maybe the object is static. Let the type specific * code decide what to do. */ if (debug_object_fixup(descr->fixup_assert_init, addr, ODEBUG_STATE_NOTAVAILABLE)) debug_print_object(&o, "assert_init"); return; } raw_spin_unlock_irqrestore(&db->lock, flags); } /** * debug_object_active_state - debug checks object usage state machine * @addr: address of the object * @descr: pointer to an object specific debug description structure * @expect: expected state * @next: state to move to if expected state is found */ void debug_object_active_state(void *addr, struct debug_obj_descr *descr, unsigned int expect, unsigned int next) { struct debug_bucket *db; struct debug_obj *obj; unsigned long flags; if (!debug_objects_enabled) return; db = get_bucket((unsigned long) addr); raw_spin_lock_irqsave(&db->lock, flags); obj = lookup_object(addr, db); if (obj) { switch (obj->state) { case ODEBUG_STATE_ACTIVE: if (obj->astate == expect) obj->astate = next; else debug_print_object(obj, "active_state"); break; default: debug_print_object(obj, "active_state"); break; } } else { struct debug_obj o = { .object = addr, .state = ODEBUG_STATE_NOTAVAILABLE, .descr = descr }; debug_print_object(&o, "active_state"); } raw_spin_unlock_irqrestore(&db->lock, flags); } #ifdef CONFIG_DEBUG_OBJECTS_FREE static void __debug_check_no_obj_freed(const void *address, unsigned long size) { unsigned long flags, oaddr, saddr, eaddr, paddr, chunks; struct hlist_node *tmp; HLIST_HEAD(freelist); struct debug_obj_descr *descr; enum debug_obj_state state; struct debug_bucket *db; struct debug_obj *obj; int cnt; saddr = (unsigned long) address; eaddr = saddr + size; paddr = saddr & ODEBUG_CHUNK_MASK; chunks = ((eaddr - paddr) + (ODEBUG_CHUNK_SIZE - 1)); chunks >>= ODEBUG_CHUNK_SHIFT; for (;chunks > 0; chunks--, paddr += ODEBUG_CHUNK_SIZE) { db = get_bucket(paddr); repeat: cnt = 0; raw_spin_lock_irqsave(&db->lock, flags); hlist_for_each_entry_safe(obj, tmp, &db->list, node) { cnt++; oaddr = (unsigned long) obj->object; if (oaddr < saddr || oaddr >= eaddr) continue; switch (obj->state) { case ODEBUG_STATE_ACTIVE: debug_print_object(obj, "free"); descr = obj->descr; state = obj->state; raw_spin_unlock_irqrestore(&db->lock, flags); debug_object_fixup(descr->fixup_free, (void *) oaddr, state); goto repeat; default: hlist_del(&obj->node); hlist_add_head(&obj->node, &freelist); break; } } raw_spin_unlock_irqrestore(&db->lock, flags); /* Now free them */ hlist_for_each_entry_safe(obj, tmp, &freelist, node) { hlist_del(&obj->node); free_object(obj); } if (cnt > debug_objects_maxchain) debug_objects_maxchain = cnt; } } void debug_check_no_obj_freed(const void *address, unsigned long size) { if (debug_objects_enabled) __debug_check_no_obj_freed(address, size); } #endif #ifdef CONFIG_DEBUG_FS static int debug_stats_show(struct seq_file *m, void *v) { seq_printf(m, "max_chain :%d\n", debug_objects_maxchain); seq_printf(m, "warnings :%d\n", debug_objects_warnings); seq_printf(m, "fixups :%d\n", debug_objects_fixups); seq_printf(m, "pool_free :%d\n", obj_pool_free); seq_printf(m, "pool_min_free :%d\n", obj_pool_min_free); seq_printf(m, "pool_used :%d\n", obj_pool_used); seq_printf(m, "pool_max_used :%d\n", obj_pool_max_used); return 0; } static int debug_stats_open(struct inode *inode, struct file *filp) { return single_open(filp, debug_stats_show, NULL); } static const struct file_operations debug_stats_fops = { .open = debug_stats_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; static int __init debug_objects_init_debugfs(void) { struct dentry *dbgdir, *dbgstats; if (!debug_objects_enabled) return 0; dbgdir = debugfs_create_dir("debug_objects", NULL); if (!dbgdir) return -ENOMEM; dbgstats = debugfs_create_file("stats", 0444, dbgdir, NULL, &debug_stats_fops); if (!dbgstats) goto err; return 0; err: debugfs_remove(dbgdir); return -ENOMEM; } __initcall(debug_objects_init_debugfs); #else static inline void debug_objects_init_debugfs(void) { } #endif #ifdef CONFIG_DEBUG_OBJECTS_SELFTEST /* Random data structure for the self test */ struct self_test { unsigned long dummy1[6]; int static_init; unsigned long dummy2[3]; }; static __initdata struct debug_obj_descr descr_type_test; /* * fixup_init is called when: * - an active object is initialized */ static int __init fixup_init(void *addr, enum debug_obj_state state) { struct self_test *obj = addr; switch (state) { case ODEBUG_STATE_ACTIVE: debug_object_deactivate(obj, &descr_type_test); debug_object_init(obj, &descr_type_test); return 1; default: return 0; } } /* * fixup_activate is called when: * - an active object is activated * - an unknown object is activated (might be a statically initialized object) */ static int __init fixup_activate(void *addr, enum debug_obj_state state) { struct self_test *obj = addr; switch (state) { case ODEBUG_STATE_NOTAVAILABLE: if (obj->static_init == 1) { debug_object_init(obj, &descr_type_test); debug_object_activate(obj, &descr_type_test); return 0; } return 1; case ODEBUG_STATE_ACTIVE: debug_object_deactivate(obj, &descr_type_test); debug_object_activate(obj, &descr_type_test); return 1; default: return 0; } } /* * fixup_destroy is called when: * - an active object is destroyed */ static int __init fixup_destroy(void *addr, enum debug_obj_state state) { struct self_test *obj = addr; switch (state) { case ODEBUG_STATE_ACTIVE: debug_object_deactivate(obj, &descr_type_test); debug_object_destroy(obj, &descr_type_test); return 1; default: return 0; } } /* * fixup_free is called when: * - an active object is freed */ static int __init fixup_free(void *addr, enum debug_obj_state state) { struct self_test *obj = addr; switch (state) { case ODEBUG_STATE_ACTIVE: debug_object_deactivate(obj, &descr_type_test); debug_object_free(obj, &descr_type_test); return 1; default: return 0; } } static int __init check_results(void *addr, enum debug_obj_state state, int fixups, int warnings) { struct debug_bucket *db; struct debug_obj *obj; unsigned long flags; int res = -EINVAL; db = get_bucket((unsigned long) addr); raw_spin_lock_irqsave(&db->lock, flags); obj = lookup_object(addr, db); if (!obj && state != ODEBUG_STATE_NONE) { WARN(1, KERN_ERR "ODEBUG: selftest object not found\n"); goto out; } if (obj && obj->state != state) { WARN(1, KERN_ERR "ODEBUG: selftest wrong state: %d != %d\n", obj->state, state); goto out; } if (fixups != debug_objects_fixups) { WARN(1, KERN_ERR "ODEBUG: selftest fixups failed %d != %d\n", fixups, debug_objects_fixups); goto out; } if (warnings != debug_objects_warnings) { WARN(1, KERN_ERR "ODEBUG: selftest warnings failed %d != %d\n", warnings, debug_objects_warnings); goto out; } res = 0; out: raw_spin_unlock_irqrestore(&db->lock, flags); if (res) debug_objects_enabled = 0; return res; } static __initdata struct debug_obj_descr descr_type_test = { .name = "selftest", .fixup_init = fixup_init, .fixup_activate = fixup_activate, .fixup_destroy = fixup_destroy, .fixup_free = fixup_free, }; static __initdata struct self_test obj = { .static_init = 0 }; static void __init debug_objects_selftest(void) { int fixups, oldfixups, warnings, oldwarnings; unsigned long flags; local_irq_save(flags); fixups = oldfixups = debug_objects_fixups; warnings = oldwarnings = debug_objects_warnings; descr_test = &descr_type_test; debug_object_init(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_INIT, fixups, warnings)) goto out; debug_object_activate(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_ACTIVE, fixups, warnings)) goto out; debug_object_activate(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_ACTIVE, ++fixups, ++warnings)) goto out; debug_object_deactivate(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_INACTIVE, fixups, warnings)) goto out; debug_object_destroy(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, warnings)) goto out; debug_object_init(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings)) goto out; debug_object_activate(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings)) goto out; debug_object_deactivate(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings)) goto out; debug_object_free(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_NONE, fixups, warnings)) goto out; obj.static_init = 1; debug_object_activate(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_ACTIVE, fixups, warnings)) goto out; debug_object_init(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_INIT, ++fixups, ++warnings)) goto out; debug_object_free(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_NONE, fixups, warnings)) goto out; #ifdef CONFIG_DEBUG_OBJECTS_FREE debug_object_init(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_INIT, fixups, warnings)) goto out; debug_object_activate(&obj, &descr_type_test); if (check_results(&obj, ODEBUG_STATE_ACTIVE, fixups, warnings)) goto out; __debug_check_no_obj_freed(&obj, sizeof(obj)); if (check_results(&obj, ODEBUG_STATE_NONE, ++fixups, ++warnings)) goto out; #endif pr_info("selftest passed\n"); out: debug_objects_fixups = oldfixups; debug_objects_warnings = oldwarnings; descr_test = NULL; local_irq_restore(flags); } #else static inline void debug_objects_selftest(void) { } #endif