tracing/events: don't use wake up for events
Impact: fix hard-lockup with sched switch events Some ftrace events, such as sched wakeup, can be traced while the runqueue lock is hold. Since they are using trace_current_buffer_unlock_commit(), they call wake_up() which can try to grab the runqueue lock too, resulting in a deadlock. Now for all event, we call a new helper: trace_nowake_buffer_unlock_commit() which do pretty the same than trace_current_buffer_unlock_commit() except than it doesn't call trace_wake_up(). Reported-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> LKML-Reference: <1237759847-21025-4-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
9bd7d099ab
commit
07edf71213
@ -860,15 +860,25 @@ static void ftrace_trace_stack(struct trace_array *tr,
|
|||||||
static void ftrace_trace_userstack(struct trace_array *tr,
|
static void ftrace_trace_userstack(struct trace_array *tr,
|
||||||
unsigned long flags, int pc);
|
unsigned long flags, int pc);
|
||||||
|
|
||||||
void trace_buffer_unlock_commit(struct trace_array *tr,
|
static inline void __trace_buffer_unlock_commit(struct trace_array *tr,
|
||||||
struct ring_buffer_event *event,
|
struct ring_buffer_event *event,
|
||||||
unsigned long flags, int pc)
|
unsigned long flags, int pc,
|
||||||
|
int wake)
|
||||||
{
|
{
|
||||||
ring_buffer_unlock_commit(tr->buffer, event);
|
ring_buffer_unlock_commit(tr->buffer, event);
|
||||||
|
|
||||||
ftrace_trace_stack(tr, flags, 6, pc);
|
ftrace_trace_stack(tr, flags, 6, pc);
|
||||||
ftrace_trace_userstack(tr, flags, pc);
|
ftrace_trace_userstack(tr, flags, pc);
|
||||||
trace_wake_up();
|
|
||||||
|
if (wake)
|
||||||
|
trace_wake_up();
|
||||||
|
}
|
||||||
|
|
||||||
|
void trace_buffer_unlock_commit(struct trace_array *tr,
|
||||||
|
struct ring_buffer_event *event,
|
||||||
|
unsigned long flags, int pc)
|
||||||
|
{
|
||||||
|
__trace_buffer_unlock_commit(tr, event, flags, pc, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ring_buffer_event *
|
struct ring_buffer_event *
|
||||||
@ -882,7 +892,13 @@ trace_current_buffer_lock_reserve(unsigned char type, unsigned long len,
|
|||||||
void trace_current_buffer_unlock_commit(struct ring_buffer_event *event,
|
void trace_current_buffer_unlock_commit(struct ring_buffer_event *event,
|
||||||
unsigned long flags, int pc)
|
unsigned long flags, int pc)
|
||||||
{
|
{
|
||||||
return trace_buffer_unlock_commit(&global_trace, event, flags, pc);
|
return __trace_buffer_unlock_commit(&global_trace, event, flags, pc, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void trace_nowake_buffer_unlock_commit(struct ring_buffer_event *event,
|
||||||
|
unsigned long flags, int pc)
|
||||||
|
{
|
||||||
|
return __trace_buffer_unlock_commit(&global_trace, event, flags, pc, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -483,6 +483,8 @@ trace_current_buffer_lock_reserve(unsigned char type, unsigned long len,
|
|||||||
unsigned long flags, int pc);
|
unsigned long flags, int pc);
|
||||||
void trace_current_buffer_unlock_commit(struct ring_buffer_event *event,
|
void trace_current_buffer_unlock_commit(struct ring_buffer_event *event,
|
||||||
unsigned long flags, int pc);
|
unsigned long flags, int pc);
|
||||||
|
void trace_nowake_buffer_unlock_commit(struct ring_buffer_event *event,
|
||||||
|
unsigned long flags, int pc);
|
||||||
|
|
||||||
struct trace_entry *tracing_get_trace_entry(struct trace_array *tr,
|
struct trace_entry *tracing_get_trace_entry(struct trace_array *tr,
|
||||||
struct trace_array_cpu *data);
|
struct trace_array_cpu *data);
|
||||||
|
@ -222,7 +222,7 @@ static void ftrace_raw_event_##call(proto) \
|
|||||||
\
|
\
|
||||||
assign; \
|
assign; \
|
||||||
\
|
\
|
||||||
trace_current_buffer_unlock_commit(event, irq_flags, pc); \
|
trace_nowake_buffer_unlock_commit(event, irq_flags, pc); \
|
||||||
\
|
\
|
||||||
if (call->preds && !filter_match_preds(call, entry)) \
|
if (call->preds && !filter_match_preds(call, entry)) \
|
||||||
ring_buffer_event_discard(event); \
|
ring_buffer_event_discard(event); \
|
||||||
|
Loading…
Reference in New Issue
Block a user