Skip to content

Commit 43fa87f

Browse files
Peter ZijlstraIngo Molnar
authored andcommitted
perf/core: Fix another perf,trace,cpuhp lock inversion
Lockdep noticed the following 3-way lockup race: perf_trace_init() #0 mutex_lock(&event_mutex) perf_trace_event_init() perf_trace_event_reg() tp_event->class->reg() := tracepoint_probe_register #1 mutex_lock(&tracepoints_mutex) trace_point_add_func() #2 static_key_enable() #2 do_cpu_up() perf_event_init_cpu() #3 mutex_lock(&pmus_lock) #4 mutex_lock(&ctx->mutex) perf_ioctl() #4 ctx = perf_event_ctx_lock() _perf_iotcl() ftrace_profile_set_filter() #0 mutex_lock(&event_mutex) Fudge it for now by noting that the tracepoint state does not depend on the event <-> context relation. Ugly though :/ Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Steven Rostedt <[email protected]> Cc: Thomas Gleixner <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
1 parent 82d9485 commit 43fa87f

File tree

1 file changed

+24
-2
lines changed

1 file changed

+24
-2
lines changed

kernel/events/core.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8525,6 +8525,29 @@ perf_event_set_addr_filter(struct perf_event *event, char *filter_str)
85258525
return ret;
85268526
}
85278527

8528+
static int
8529+
perf_tracepoint_set_filter(struct perf_event *event, char *filter_str)
8530+
{
8531+
struct perf_event_context *ctx = event->ctx;
8532+
int ret;
8533+
8534+
/*
8535+
* Beware, here be dragons!!
8536+
*
8537+
* the tracepoint muck will deadlock against ctx->mutex, but the tracepoint
8538+
* stuff does not actually need it. So temporarily drop ctx->mutex. As per
8539+
* perf_event_ctx_lock() we already have a reference on ctx.
8540+
*
8541+
* This can result in event getting moved to a different ctx, but that
8542+
* does not affect the tracepoint state.
8543+
*/
8544+
mutex_unlock(&ctx->mutex);
8545+
ret = ftrace_profile_set_filter(event, event->attr.config, filter_str);
8546+
mutex_lock(&ctx->mutex);
8547+
8548+
return ret;
8549+
}
8550+
85288551
static int perf_event_set_filter(struct perf_event *event, void __user *arg)
85298552
{
85308553
char *filter_str;
@@ -8541,8 +8564,7 @@ static int perf_event_set_filter(struct perf_event *event, void __user *arg)
85418564

85428565
if (IS_ENABLED(CONFIG_EVENT_TRACING) &&
85438566
event->attr.type == PERF_TYPE_TRACEPOINT)
8544-
ret = ftrace_profile_set_filter(event, event->attr.config,
8545-
filter_str);
8567+
ret = perf_tracepoint_set_filter(event, filter_str);
85468568
else if (has_addr_filter(event))
85478569
ret = perf_event_set_addr_filter(event, filter_str);
85488570

0 commit comments

Comments
 (0)