aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-04-16 06:38:30 -0400
committerIngo Molnar <mingo@kernel.org>2015-04-18 07:31:26 -0400
commit0c99241c93b8060441f3c8434848e54b5338f922 (patch)
tree8e1182be161578cf64af32a3a8e91b2b1d17c4aa /arch/x86
parent78d504bcd769cc496f63b626f507039eab2316b7 (diff)
perf/x86/intel/pt: Fix and clean up error handling in pt_event_add()
Dan Carpenter reported that pt_event_add() has buggy error handling logic: it returns 0 instead of -EBUSY when it fails to start a newly added event. Furthermore, the control flow in this function is messy, with cleanup labels mixed with direct returns. Fix the bug and clean up the code by converting it to a straight fast path for the regular non-failing case, plus a clear sequence of cascading goto labels to do all cleanup. NOTE: I materially changed the existing clean up logic in the pt_event_start() failure case to use the direct perf_aux_output_end() path, not pt_event_del(), because perf_aux_output_end() is enough here. Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Acked-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Arnaldo Carvalho de Melo <acme@kernel.org> Cc: Julia Lawall <julia.lawall@lip6.fr> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/20150416103830.GB7847@gmail.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_pt.c33
1 files changed, 15 insertions, 18 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_intel_pt.c b/arch/x86/kernel/cpu/perf_event_intel_pt.c
index f2770641c0fd..ffe666c2c6b5 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_pt.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_pt.c
@@ -988,39 +988,36 @@ static int pt_event_add(struct perf_event *event, int mode)
988 int ret = -EBUSY; 988 int ret = -EBUSY;
989 989
990 if (pt->handle.event) 990 if (pt->handle.event)
991 goto out; 991 goto fail;
992 992
993 buf = perf_aux_output_begin(&pt->handle, event); 993 buf = perf_aux_output_begin(&pt->handle, event);
994 if (!buf) { 994 ret = -EINVAL;
995 ret = -EINVAL; 995 if (!buf)
996 goto out; 996 goto fail_stop;
997 }
998 997
999 pt_buffer_reset_offsets(buf, pt->handle.head); 998 pt_buffer_reset_offsets(buf, pt->handle.head);
1000 if (!buf->snapshot) { 999 if (!buf->snapshot) {
1001 ret = pt_buffer_reset_markers(buf, &pt->handle); 1000 ret = pt_buffer_reset_markers(buf, &pt->handle);
1002 if (ret) { 1001 if (ret)
1003 perf_aux_output_end(&pt->handle, 0, true); 1002 goto fail_end_stop;
1004 goto out;
1005 }
1006 } 1003 }
1007 1004
1008 if (mode & PERF_EF_START) { 1005 if (mode & PERF_EF_START) {
1009 pt_event_start(event, 0); 1006 pt_event_start(event, 0);
1010 if (hwc->state == PERF_HES_STOPPED) { 1007 ret = -EBUSY;
1011 pt_event_del(event, 0); 1008 if (hwc->state == PERF_HES_STOPPED)
1012 ret = -EBUSY; 1009 goto fail_end_stop;
1013 }
1014 } else { 1010 } else {
1015 hwc->state = PERF_HES_STOPPED; 1011 hwc->state = PERF_HES_STOPPED;
1016 } 1012 }
1017 1013
1018 ret = 0; 1014 return 0;
1019out:
1020
1021 if (ret)
1022 hwc->state = PERF_HES_STOPPED;
1023 1015
1016fail_end_stop:
1017 perf_aux_output_end(&pt->handle, 0, true);
1018fail_stop:
1019 hwc->state = PERF_HES_STOPPED;
1020fail:
1024 return ret; 1021 return ret;
1025} 1022}
1026 1023