diff options
Diffstat (limited to 'kernel/perf_event.c')
-rw-r--r-- | kernel/perf_event.c | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 7223ea875861..357ee8d5e8ae 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -4709,6 +4709,8 @@ static int perf_swevent_init(struct perf_event *event) | |||
4709 | } | 4709 | } |
4710 | 4710 | ||
4711 | static struct pmu perf_swevent = { | 4711 | static struct pmu perf_swevent = { |
4712 | .task_ctx_nr = perf_sw_context, | ||
4713 | |||
4712 | .event_init = perf_swevent_init, | 4714 | .event_init = perf_swevent_init, |
4713 | .add = perf_swevent_add, | 4715 | .add = perf_swevent_add, |
4714 | .del = perf_swevent_del, | 4716 | .del = perf_swevent_del, |
@@ -4800,6 +4802,8 @@ static int perf_tp_event_init(struct perf_event *event) | |||
4800 | } | 4802 | } |
4801 | 4803 | ||
4802 | static struct pmu perf_tracepoint = { | 4804 | static struct pmu perf_tracepoint = { |
4805 | .task_ctx_nr = perf_sw_context, | ||
4806 | |||
4803 | .event_init = perf_tp_event_init, | 4807 | .event_init = perf_tp_event_init, |
4804 | .add = perf_trace_add, | 4808 | .add = perf_trace_add, |
4805 | .del = perf_trace_del, | 4809 | .del = perf_trace_del, |
@@ -4988,6 +4992,8 @@ static int cpu_clock_event_init(struct perf_event *event) | |||
4988 | } | 4992 | } |
4989 | 4993 | ||
4990 | static struct pmu perf_cpu_clock = { | 4994 | static struct pmu perf_cpu_clock = { |
4995 | .task_ctx_nr = perf_sw_context, | ||
4996 | |||
4991 | .event_init = cpu_clock_event_init, | 4997 | .event_init = cpu_clock_event_init, |
4992 | .add = cpu_clock_event_add, | 4998 | .add = cpu_clock_event_add, |
4993 | .del = cpu_clock_event_del, | 4999 | .del = cpu_clock_event_del, |
@@ -5063,6 +5069,8 @@ static int task_clock_event_init(struct perf_event *event) | |||
5063 | } | 5069 | } |
5064 | 5070 | ||
5065 | static struct pmu perf_task_clock = { | 5071 | static struct pmu perf_task_clock = { |
5072 | .task_ctx_nr = perf_sw_context, | ||
5073 | |||
5066 | .event_init = task_clock_event_init, | 5074 | .event_init = task_clock_event_init, |
5067 | .add = task_clock_event_add, | 5075 | .add = task_clock_event_add, |
5068 | .del = task_clock_event_del, | 5076 | .del = task_clock_event_del, |
@@ -5490,6 +5498,7 @@ SYSCALL_DEFINE5(perf_event_open, | |||
5490 | struct perf_event_context *ctx; | 5498 | struct perf_event_context *ctx; |
5491 | struct file *event_file = NULL; | 5499 | struct file *event_file = NULL; |
5492 | struct file *group_file = NULL; | 5500 | struct file *group_file = NULL; |
5501 | struct pmu *pmu; | ||
5493 | int event_fd; | 5502 | int event_fd; |
5494 | int fput_needed = 0; | 5503 | int fput_needed = 0; |
5495 | int err; | 5504 | int err; |
@@ -5522,20 +5531,11 @@ SYSCALL_DEFINE5(perf_event_open, | |||
5522 | goto err_fd; | 5531 | goto err_fd; |
5523 | } | 5532 | } |
5524 | 5533 | ||
5525 | /* | ||
5526 | * Get the target context (task or percpu): | ||
5527 | */ | ||
5528 | ctx = find_get_context(event->pmu, pid, cpu); | ||
5529 | if (IS_ERR(ctx)) { | ||
5530 | err = PTR_ERR(ctx); | ||
5531 | goto err_alloc; | ||
5532 | } | ||
5533 | |||
5534 | if (group_fd != -1) { | 5534 | if (group_fd != -1) { |
5535 | group_leader = perf_fget_light(group_fd, &fput_needed); | 5535 | group_leader = perf_fget_light(group_fd, &fput_needed); |
5536 | if (IS_ERR(group_leader)) { | 5536 | if (IS_ERR(group_leader)) { |
5537 | err = PTR_ERR(group_leader); | 5537 | err = PTR_ERR(group_leader); |
5538 | goto err_context; | 5538 | goto err_alloc; |
5539 | } | 5539 | } |
5540 | group_file = group_leader->filp; | 5540 | group_file = group_leader->filp; |
5541 | if (flags & PERF_FLAG_FD_OUTPUT) | 5541 | if (flags & PERF_FLAG_FD_OUTPUT) |
@@ -5545,6 +5545,23 @@ SYSCALL_DEFINE5(perf_event_open, | |||
5545 | } | 5545 | } |
5546 | 5546 | ||
5547 | /* | 5547 | /* |
5548 | * Special case software events and allow them to be part of | ||
5549 | * any hardware group. | ||
5550 | */ | ||
5551 | pmu = event->pmu; | ||
5552 | if ((pmu->task_ctx_nr == perf_sw_context) && group_leader) | ||
5553 | pmu = group_leader->pmu; | ||
5554 | |||
5555 | /* | ||
5556 | * Get the target context (task or percpu): | ||
5557 | */ | ||
5558 | ctx = find_get_context(pmu, pid, cpu); | ||
5559 | if (IS_ERR(ctx)) { | ||
5560 | err = PTR_ERR(ctx); | ||
5561 | goto err_group_fd; | ||
5562 | } | ||
5563 | |||
5564 | /* | ||
5548 | * Look up the group leader (we will attach this event to it): | 5565 | * Look up the group leader (we will attach this event to it): |
5549 | */ | 5566 | */ |
5550 | if (group_leader) { | 5567 | if (group_leader) { |
@@ -5605,8 +5622,9 @@ SYSCALL_DEFINE5(perf_event_open, | |||
5605 | return event_fd; | 5622 | return event_fd; |
5606 | 5623 | ||
5607 | err_context: | 5624 | err_context: |
5608 | fput_light(group_file, fput_needed); | ||
5609 | put_ctx(ctx); | 5625 | put_ctx(ctx); |
5626 | err_group_fd: | ||
5627 | fput_light(group_file, fput_needed); | ||
5610 | err_alloc: | 5628 | err_alloc: |
5611 | free_event(event); | 5629 | free_event(event); |
5612 | err_fd: | 5630 | err_fd: |