aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2015-06-11 04:32:01 -0400
committerIngo Molnar <mingo@kernel.org>2015-08-04 03:57:52 -0400
commitfed66e2cdd4f127a43fd11b8d92a99bdd429528c (patch)
treecc275577a4a4e9e2cc44fd6df67b36f022b654c1
parent5542b2aa9eea3f2bb922029c8cc4b4346c4f6b1c (diff)
perf: Fix fasync handling on inherited events
Vince reported that the fasync signal stuff doesn't work proper for inherited events. So fix that. Installing fasync allocates memory and sets filp->f_flags |= FASYNC, which upon the demise of the file descriptor ensures the allocation is freed and state is updated. Now for perf, we can have the events stick around for a while after the original FD is dead because of references from child events. So we cannot copy the fasync pointer around. We can however consistently use the parent's fasync, as that will be updated. Reported-and-Tested-by: Vince Weaver <vincent.weaver@maine.edu> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: <stable@vger.kernel.org> Cc: Arnaldo Carvalho deMelo <acme@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: eranian@google.com Link: http://lkml.kernel.org/r/1434011521.1495.71.camel@twins Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--kernel/events/core.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 10d076b2572c..072b8a686517 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4740,12 +4740,20 @@ static const struct file_operations perf_fops = {
4740 * to user-space before waking everybody up. 4740 * to user-space before waking everybody up.
4741 */ 4741 */
4742 4742
4743static inline struct fasync_struct **perf_event_fasync(struct perf_event *event)
4744{
4745 /* only the parent has fasync state */
4746 if (event->parent)
4747 event = event->parent;
4748 return &event->fasync;
4749}
4750
4743void perf_event_wakeup(struct perf_event *event) 4751void perf_event_wakeup(struct perf_event *event)
4744{ 4752{
4745 ring_buffer_wakeup(event); 4753 ring_buffer_wakeup(event);
4746 4754
4747 if (event->pending_kill) { 4755 if (event->pending_kill) {
4748 kill_fasync(&event->fasync, SIGIO, event->pending_kill); 4756 kill_fasync(perf_event_fasync(event), SIGIO, event->pending_kill);
4749 event->pending_kill = 0; 4757 event->pending_kill = 0;
4750 } 4758 }
4751} 4759}
@@ -6124,7 +6132,7 @@ static int __perf_event_overflow(struct perf_event *event,
6124 else 6132 else
6125 perf_event_output(event, data, regs); 6133 perf_event_output(event, data, regs);
6126 6134
6127 if (event->fasync && event->pending_kill) { 6135 if (*perf_event_fasync(event) && event->pending_kill) {
6128 event->pending_wakeup = 1; 6136 event->pending_wakeup = 1;
6129 irq_work_queue(&event->pending); 6137 irq_work_queue(&event->pending);
6130 } 6138 }