debugobjects: Make debug_object_activate() return status
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>
This commit is contained in:
parent
15100df81f
commit
b778ae2536
|
@ -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 (void *addr, struct debug_obj_descr *descr);
|
||||||
extern void
|
extern void
|
||||||
debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr);
|
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_deactivate(void *addr, struct debug_obj_descr *descr);
|
||||||
extern void debug_object_destroy (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);
|
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) { }
|
debug_object_init (void *addr, struct debug_obj_descr *descr) { }
|
||||||
static inline void
|
static inline void
|
||||||
debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr) { }
|
debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr) { }
|
||||||
static inline void
|
static inline int
|
||||||
debug_object_activate (void *addr, struct debug_obj_descr *descr) { }
|
debug_object_activate (void *addr, struct debug_obj_descr *descr) { return 0; }
|
||||||
static inline void
|
static inline void
|
||||||
debug_object_deactivate(void *addr, struct debug_obj_descr *descr) { }
|
debug_object_deactivate(void *addr, struct debug_obj_descr *descr) { }
|
||||||
static inline void
|
static inline void
|
||||||
|
|
|
@ -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
|
* debug_object_activate - debug checks when an object is activated
|
||||||
* @addr: address of the object
|
* @addr: address of the object
|
||||||
* @descr: pointer to an object specific debug description structure
|
* @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;
|
enum debug_obj_state state;
|
||||||
struct debug_bucket *db;
|
struct debug_bucket *db;
|
||||||
struct debug_obj *obj;
|
struct debug_obj *obj;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int ret;
|
||||||
struct debug_obj o = { .object = addr,
|
struct debug_obj o = { .object = addr,
|
||||||
.state = ODEBUG_STATE_NOTAVAILABLE,
|
.state = ODEBUG_STATE_NOTAVAILABLE,
|
||||||
.descr = descr };
|
.descr = descr };
|
||||||
|
|
||||||
if (!debug_objects_enabled)
|
if (!debug_objects_enabled)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
db = get_bucket((unsigned long) addr);
|
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_INIT:
|
||||||
case ODEBUG_STATE_INACTIVE:
|
case ODEBUG_STATE_INACTIVE:
|
||||||
obj->state = ODEBUG_STATE_ACTIVE;
|
obj->state = ODEBUG_STATE_ACTIVE;
|
||||||
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ODEBUG_STATE_ACTIVE:
|
case ODEBUG_STATE_ACTIVE:
|
||||||
debug_print_object(obj, "activate");
|
debug_print_object(obj, "activate");
|
||||||
state = obj->state;
|
state = obj->state;
|
||||||
raw_spin_unlock_irqrestore(&db->lock, flags);
|
raw_spin_unlock_irqrestore(&db->lock, flags);
|
||||||
debug_object_fixup(descr->fixup_activate, addr, state);
|
ret = debug_object_fixup(descr->fixup_activate, addr, state);
|
||||||
return;
|
return ret ? -EINVAL : 0;
|
||||||
|
|
||||||
case ODEBUG_STATE_DESTROYED:
|
case ODEBUG_STATE_DESTROYED:
|
||||||
debug_print_object(obj, "activate");
|
debug_print_object(obj, "activate");
|
||||||
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
raw_spin_unlock_irqrestore(&db->lock, flags);
|
raw_spin_unlock_irqrestore(&db->lock, flags);
|
||||||
return;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_spin_unlock_irqrestore(&db->lock, flags);
|
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.
|
* true or not.
|
||||||
*/
|
*/
|
||||||
if (debug_object_fixup(descr->fixup_activate, addr,
|
if (debug_object_fixup(descr->fixup_activate, addr,
|
||||||
ODEBUG_STATE_NOTAVAILABLE))
|
ODEBUG_STATE_NOTAVAILABLE)) {
|
||||||
debug_print_object(&o, "activate");
|
debug_print_object(&o, "activate");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue