debugobjects: Make debug_object_activate() return status
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Tue, 23 Apr 2013 19:51:11 +0000 (12:51 -0700)
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Mon, 19 Aug 2013 00:39:55 +0000 (17:39 -0700)
In order to better respond to things like duplicate invocations
of call_rcu(), RCU needs to see the status of a call to
debug_object_activate().  This would allow RCU to leak the callback in
order to avoid adding freelist-reuse mischief to the duplicate invoations.
This commit therefore makes debug_object_activate() return status,
zero for success and -EINVAL for failure.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Sedat Dilek <sedat.dilek@gmail.com>
Cc: Davidlohr Bueso <davidlohr.bueso@hp.com>
Cc: Rik van Riel <riel@surriel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
include/linux/debugobjects.h
lib/debugobjects.c

index 0e5f5785d9f2df3c524099142da6202b54f0ff47..98ffcbd4888ea0d088f2d4e8c4b41757b0e472c2 100644 (file)
@@ -63,7 +63,7 @@ struct debug_obj_descr {
 extern void debug_object_init      (void *addr, struct debug_obj_descr *descr);
 extern void
 debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr);
-extern void debug_object_activate  (void *addr, struct debug_obj_descr *descr);
+extern int debug_object_activate  (void *addr, struct debug_obj_descr *descr);
 extern void debug_object_deactivate(void *addr, struct debug_obj_descr *descr);
 extern void debug_object_destroy   (void *addr, struct debug_obj_descr *descr);
 extern void debug_object_free      (void *addr, struct debug_obj_descr *descr);
@@ -85,8 +85,8 @@ static inline void
 debug_object_init      (void *addr, struct debug_obj_descr *descr) { }
 static inline void
 debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr) { }
-static inline void
-debug_object_activate  (void *addr, struct debug_obj_descr *descr) { }
+static inline int
+debug_object_activate  (void *addr, struct debug_obj_descr *descr) { return 0; }
 static inline void
 debug_object_deactivate(void *addr, struct debug_obj_descr *descr) { }
 static inline void
index 37061ede8b8124e7fa59cd0963ede7ba27979007..bf2c8b1043d8bb5a8b44d19a139842ffb5514067 100644 (file)
@@ -381,19 +381,21 @@ void debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr)
  * debug_object_activate - debug checks when an object is activated
  * @addr:      address of the object
  * @descr:     pointer to an object specific debug description structure
+ * Returns 0 for success, -EINVAL for check failed.
  */
-void debug_object_activate(void *addr, struct debug_obj_descr *descr)
+int debug_object_activate(void *addr, struct debug_obj_descr *descr)
 {
        enum debug_obj_state state;
        struct debug_bucket *db;
        struct debug_obj *obj;
        unsigned long flags;
+       int ret;
        struct debug_obj o = { .object = addr,
                               .state = ODEBUG_STATE_NOTAVAILABLE,
                               .descr = descr };
 
        if (!debug_objects_enabled)
-               return;
+               return 0;
 
        db = get_bucket((unsigned long) addr);
 
@@ -405,23 +407,26 @@ void debug_object_activate(void *addr, struct debug_obj_descr *descr)
                case ODEBUG_STATE_INIT:
                case ODEBUG_STATE_INACTIVE:
                        obj->state = ODEBUG_STATE_ACTIVE;
+                       ret = 0;
                        break;
 
                case ODEBUG_STATE_ACTIVE:
                        debug_print_object(obj, "activate");
                        state = obj->state;
                        raw_spin_unlock_irqrestore(&db->lock, flags);
-                       debug_object_fixup(descr->fixup_activate, addr, state);
-                       return;
+                       ret = debug_object_fixup(descr->fixup_activate, addr, state);
+                       return ret ? -EINVAL : 0;
 
                case ODEBUG_STATE_DESTROYED:
                        debug_print_object(obj, "activate");
+                       ret = -EINVAL;
                        break;
                default:
+                       ret = 0;
                        break;
                }
                raw_spin_unlock_irqrestore(&db->lock, flags);
-               return;
+               return ret;
        }
 
        raw_spin_unlock_irqrestore(&db->lock, flags);
@@ -431,8 +436,11 @@ void debug_object_activate(void *addr, struct debug_obj_descr *descr)
         * true or not.
         */
        if (debug_object_fixup(descr->fixup_activate, addr,
-                          ODEBUG_STATE_NOTAVAILABLE))
+                          ODEBUG_STATE_NOTAVAILABLE)) {
                debug_print_object(&o, "activate");
+               return -EINVAL;
+       }
+       return 0;
 }
 
 /**