|
@@ -141,6 +141,7 @@ alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr)
|
|
|
obj->object = addr;
|
|
|
obj->descr = descr;
|
|
|
obj->state = ODEBUG_STATE_NONE;
|
|
|
+ obj->astate = 0;
|
|
|
hlist_del(&obj->node);
|
|
|
|
|
|
hlist_add_head(&obj->node, &b->list);
|
|
@@ -252,8 +253,10 @@ static void debug_print_object(struct debug_obj *obj, char *msg)
|
|
|
|
|
|
if (limit < 5 && obj->descr != descr_test) {
|
|
|
limit++;
|
|
|
- WARN(1, KERN_ERR "ODEBUG: %s %s object type: %s\n", msg,
|
|
|
- obj_states[obj->state], obj->descr->name);
|
|
|
+ WARN(1, KERN_ERR "ODEBUG: %s %s (active state %u) "
|
|
|
+ "object type: %s\n",
|
|
|
+ msg, obj_states[obj->state], obj->astate,
|
|
|
+ obj->descr->name);
|
|
|
}
|
|
|
debug_objects_warnings++;
|
|
|
}
|
|
@@ -447,7 +450,10 @@ void debug_object_deactivate(void *addr, struct debug_obj_descr *descr)
|
|
|
case ODEBUG_STATE_INIT:
|
|
|
case ODEBUG_STATE_INACTIVE:
|
|
|
case ODEBUG_STATE_ACTIVE:
|
|
|
- obj->state = ODEBUG_STATE_INACTIVE;
|
|
|
+ if (!obj->astate)
|
|
|
+ obj->state = ODEBUG_STATE_INACTIVE;
|
|
|
+ else
|
|
|
+ debug_print_object(obj, "deactivate");
|
|
|
break;
|
|
|
|
|
|
case ODEBUG_STATE_DESTROYED:
|
|
@@ -553,6 +559,53 @@ out_unlock:
|
|
|
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)
|
|
|
{
|