aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/events
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2014-09-30 13:23:08 -0400
committerIngo Molnar <mingo@kernel.org>2014-10-02 23:41:06 -0400
commit211de6eba8960521e2be450a7d07db85fba4604c (patch)
tree8906de527a99e671d03f6f9fc0b4a11eac892a62 /kernel/events
parentfe82dcec644244676d55a1384c958d5f67979adb (diff)
perf: Fix unclone_ctx() vs. locking
The idiot who did 4a1c0f262f88 ("perf: Fix lockdep warning on process exit") forgot to pay attention and fix all similar cases. Do so now. In particular, unclone_ctx() must be called while holding ctx->lock, therefore all such sites are broken for the same reason. Pull the put_ctx() call out from under ctx->lock. Reported-by: Sasha Levin <sasha.levin@oracle.com> Probably-also-reported-by: Vince Weaver <vincent.weaver@maine.edu> Fixes: 4a1c0f262f88 ("perf: Fix lockdep warning on process exit") Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@kernel.org> Cc: Sasha Levin <sasha.levin@oracle.com> Cc: Cong Wang <cwang@twopensource.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Link: http://lkml.kernel.org/r/20140930172308.GI4241@worktop.programming.kicks-ass.net Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/events')
-rw-r--r--kernel/events/core.c54
1 files changed, 31 insertions, 23 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index d640a8b4dcbc..afdd9e1d7144 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -902,13 +902,23 @@ static void put_ctx(struct perf_event_context *ctx)
902 } 902 }
903} 903}
904 904
905static void unclone_ctx(struct perf_event_context *ctx) 905/*
906 * This must be done under the ctx->lock, such as to serialize against
907 * context_equiv(), therefore we cannot call put_ctx() since that might end up
908 * calling scheduler related locks and ctx->lock nests inside those.
909 */
910static __must_check struct perf_event_context *
911unclone_ctx(struct perf_event_context *ctx)
906{ 912{
907 if (ctx->parent_ctx) { 913 struct perf_event_context *parent_ctx = ctx->parent_ctx;
908 put_ctx(ctx->parent_ctx); 914
915 lockdep_assert_held(&ctx->lock);
916
917 if (parent_ctx)
909 ctx->parent_ctx = NULL; 918 ctx->parent_ctx = NULL;
910 }
911 ctx->generation++; 919 ctx->generation++;
920
921 return parent_ctx;
912} 922}
913 923
914static u32 perf_event_pid(struct perf_event *event, struct task_struct *p) 924static u32 perf_event_pid(struct perf_event *event, struct task_struct *p)
@@ -2210,6 +2220,9 @@ static void ctx_sched_out(struct perf_event_context *ctx,
2210static int context_equiv(struct perf_event_context *ctx1, 2220static int context_equiv(struct perf_event_context *ctx1,
2211 struct perf_event_context *ctx2) 2221 struct perf_event_context *ctx2)
2212{ 2222{
2223 lockdep_assert_held(&ctx1->lock);
2224 lockdep_assert_held(&ctx2->lock);
2225
2213 /* Pinning disables the swap optimization */ 2226 /* Pinning disables the swap optimization */
2214 if (ctx1->pin_count || ctx2->pin_count) 2227 if (ctx1->pin_count || ctx2->pin_count)
2215 return 0; 2228 return 0;
@@ -2943,6 +2956,7 @@ static int event_enable_on_exec(struct perf_event *event,
2943 */ 2956 */
2944static void perf_event_enable_on_exec(struct perf_event_context *ctx) 2957static void perf_event_enable_on_exec(struct perf_event_context *ctx)
2945{ 2958{
2959 struct perf_event_context *clone_ctx = NULL;
2946 struct perf_event *event; 2960 struct perf_event *event;
2947 unsigned long flags; 2961 unsigned long flags;
2948 int enabled = 0; 2962 int enabled = 0;
@@ -2974,7 +2988,7 @@ static void perf_event_enable_on_exec(struct perf_event_context *ctx)
2974 * Unclone this context if we enabled any event. 2988 * Unclone this context if we enabled any event.
2975 */ 2989 */
2976 if (enabled) 2990 if (enabled)
2977 unclone_ctx(ctx); 2991 clone_ctx = unclone_ctx(ctx);
2978 2992
2979 raw_spin_unlock(&ctx->lock); 2993 raw_spin_unlock(&ctx->lock);
2980 2994
@@ -2984,6 +2998,9 @@ static void perf_event_enable_on_exec(struct perf_event_context *ctx)
2984 perf_event_context_sched_in(ctx, ctx->task); 2998 perf_event_context_sched_in(ctx, ctx->task);
2985out: 2999out:
2986 local_irq_restore(flags); 3000 local_irq_restore(flags);
3001
3002 if (clone_ctx)
3003 put_ctx(clone_ctx);
2987} 3004}
2988 3005
2989void perf_event_exec(void) 3006void perf_event_exec(void)
@@ -3135,7 +3152,7 @@ errout:
3135static struct perf_event_context * 3152static struct perf_event_context *
3136find_get_context(struct pmu *pmu, struct task_struct *task, int cpu) 3153find_get_context(struct pmu *pmu, struct task_struct *task, int cpu)
3137{ 3154{
3138 struct perf_event_context *ctx; 3155 struct perf_event_context *ctx, *clone_ctx = NULL;
3139 struct perf_cpu_context *cpuctx; 3156 struct perf_cpu_context *cpuctx;
3140 unsigned long flags; 3157 unsigned long flags;
3141 int ctxn, err; 3158 int ctxn, err;
@@ -3169,9 +3186,12 @@ find_get_context(struct pmu *pmu, struct task_struct *task, int cpu)
3169retry: 3186retry:
3170 ctx = perf_lock_task_context(task, ctxn, &flags); 3187 ctx = perf_lock_task_context(task, ctxn, &flags);
3171 if (ctx) { 3188 if (ctx) {
3172 unclone_ctx(ctx); 3189 clone_ctx = unclone_ctx(ctx);
3173 ++ctx->pin_count; 3190 ++ctx->pin_count;
3174 raw_spin_unlock_irqrestore(&ctx->lock, flags); 3191 raw_spin_unlock_irqrestore(&ctx->lock, flags);
3192
3193 if (clone_ctx)
3194 put_ctx(clone_ctx);
3175 } else { 3195 } else {
3176 ctx = alloc_perf_context(pmu, task); 3196 ctx = alloc_perf_context(pmu, task);
3177 err = -ENOMEM; 3197 err = -ENOMEM;
@@ -7523,7 +7543,7 @@ __perf_event_exit_task(struct perf_event *child_event,
7523static void perf_event_exit_task_context(struct task_struct *child, int ctxn) 7543static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
7524{ 7544{
7525 struct perf_event *child_event, *next; 7545 struct perf_event *child_event, *next;
7526 struct perf_event_context *child_ctx, *parent_ctx; 7546 struct perf_event_context *child_ctx, *clone_ctx = NULL;
7527 unsigned long flags; 7547 unsigned long flags;
7528 7548
7529 if (likely(!child->perf_event_ctxp[ctxn])) { 7549 if (likely(!child->perf_event_ctxp[ctxn])) {
@@ -7550,28 +7570,16 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
7550 child->perf_event_ctxp[ctxn] = NULL; 7570 child->perf_event_ctxp[ctxn] = NULL;
7551 7571
7552 /* 7572 /*
7553 * In order to avoid freeing: child_ctx->parent_ctx->task
7554 * under perf_event_context::lock, grab another reference.
7555 */
7556 parent_ctx = child_ctx->parent_ctx;
7557 if (parent_ctx)
7558 get_ctx(parent_ctx);
7559
7560 /*
7561 * If this context is a clone; unclone it so it can't get 7573 * If this context is a clone; unclone it so it can't get
7562 * swapped to another process while we're removing all 7574 * swapped to another process while we're removing all
7563 * the events from it. 7575 * the events from it.
7564 */ 7576 */
7565 unclone_ctx(child_ctx); 7577 clone_ctx = unclone_ctx(child_ctx);
7566 update_context_time(child_ctx); 7578 update_context_time(child_ctx);
7567 raw_spin_unlock_irqrestore(&child_ctx->lock, flags); 7579 raw_spin_unlock_irqrestore(&child_ctx->lock, flags);
7568 7580
7569 /* 7581 if (clone_ctx)
7570 * Now that we no longer hold perf_event_context::lock, drop 7582 put_ctx(clone_ctx);
7571 * our extra child_ctx->parent_ctx reference.
7572 */
7573 if (parent_ctx)
7574 put_ctx(parent_ctx);
7575 7583
7576 /* 7584 /*
7577 * Report the task dead after unscheduling the events so that we 7585 * Report the task dead after unscheduling the events so that we