diff options
-rw-r--r-- | kernel/perf_event.c | 73 |
1 files changed, 35 insertions, 38 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 8462e69409ae..a3c86a8335c4 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -827,6 +827,8 @@ perf_install_in_context(struct perf_event_context *ctx, | |||
827 | { | 827 | { |
828 | struct task_struct *task = ctx->task; | 828 | struct task_struct *task = ctx->task; |
829 | 829 | ||
830 | event->ctx = ctx; | ||
831 | |||
830 | if (!task) { | 832 | if (!task) { |
831 | /* | 833 | /* |
832 | * Per cpu events are installed via an smp call and | 834 | * Per cpu events are installed via an smp call and |
@@ -5038,20 +5040,17 @@ struct pmu *perf_init_event(struct perf_event *event) | |||
5038 | * Allocate and initialize a event structure | 5040 | * Allocate and initialize a event structure |
5039 | */ | 5041 | */ |
5040 | static struct perf_event * | 5042 | static struct perf_event * |
5041 | perf_event_alloc(struct perf_event_attr *attr, | 5043 | perf_event_alloc(struct perf_event_attr *attr, int cpu, |
5042 | int cpu, | ||
5043 | struct perf_event_context *ctx, | ||
5044 | struct perf_event *group_leader, | 5044 | struct perf_event *group_leader, |
5045 | struct perf_event *parent_event, | 5045 | struct perf_event *parent_event, |
5046 | perf_overflow_handler_t overflow_handler, | 5046 | perf_overflow_handler_t overflow_handler) |
5047 | gfp_t gfpflags) | ||
5048 | { | 5047 | { |
5049 | struct pmu *pmu; | 5048 | struct pmu *pmu; |
5050 | struct perf_event *event; | 5049 | struct perf_event *event; |
5051 | struct hw_perf_event *hwc; | 5050 | struct hw_perf_event *hwc; |
5052 | long err; | 5051 | long err; |
5053 | 5052 | ||
5054 | event = kzalloc(sizeof(*event), gfpflags); | 5053 | event = kzalloc(sizeof(*event), GFP_KERNEL); |
5055 | if (!event) | 5054 | if (!event) |
5056 | return ERR_PTR(-ENOMEM); | 5055 | return ERR_PTR(-ENOMEM); |
5057 | 5056 | ||
@@ -5076,7 +5075,6 @@ perf_event_alloc(struct perf_event_attr *attr, | |||
5076 | event->attr = *attr; | 5075 | event->attr = *attr; |
5077 | event->group_leader = group_leader; | 5076 | event->group_leader = group_leader; |
5078 | event->pmu = NULL; | 5077 | event->pmu = NULL; |
5079 | event->ctx = ctx; | ||
5080 | event->oncpu = -1; | 5078 | event->oncpu = -1; |
5081 | 5079 | ||
5082 | event->parent = parent_event; | 5080 | event->parent = parent_event; |
@@ -5321,20 +5319,26 @@ SYSCALL_DEFINE5(perf_event_open, | |||
5321 | if (event_fd < 0) | 5319 | if (event_fd < 0) |
5322 | return event_fd; | 5320 | return event_fd; |
5323 | 5321 | ||
5322 | event = perf_event_alloc(&attr, cpu, group_leader, NULL, NULL); | ||
5323 | if (IS_ERR(event)) { | ||
5324 | err = PTR_ERR(event); | ||
5325 | goto err_fd; | ||
5326 | } | ||
5327 | |||
5324 | /* | 5328 | /* |
5325 | * Get the target context (task or percpu): | 5329 | * Get the target context (task or percpu): |
5326 | */ | 5330 | */ |
5327 | ctx = find_get_context(pid, cpu); | 5331 | ctx = find_get_context(pid, cpu); |
5328 | if (IS_ERR(ctx)) { | 5332 | if (IS_ERR(ctx)) { |
5329 | err = PTR_ERR(ctx); | 5333 | err = PTR_ERR(ctx); |
5330 | goto err_fd; | 5334 | goto err_alloc; |
5331 | } | 5335 | } |
5332 | 5336 | ||
5333 | if (group_fd != -1) { | 5337 | if (group_fd != -1) { |
5334 | group_leader = perf_fget_light(group_fd, &fput_needed); | 5338 | group_leader = perf_fget_light(group_fd, &fput_needed); |
5335 | if (IS_ERR(group_leader)) { | 5339 | if (IS_ERR(group_leader)) { |
5336 | err = PTR_ERR(group_leader); | 5340 | err = PTR_ERR(group_leader); |
5337 | goto err_put_context; | 5341 | goto err_context; |
5338 | } | 5342 | } |
5339 | group_file = group_leader->filp; | 5343 | group_file = group_leader->filp; |
5340 | if (flags & PERF_FLAG_FD_OUTPUT) | 5344 | if (flags & PERF_FLAG_FD_OUTPUT) |
@@ -5354,37 +5358,30 @@ SYSCALL_DEFINE5(perf_event_open, | |||
5354 | * becoming part of another group-sibling): | 5358 | * becoming part of another group-sibling): |
5355 | */ | 5359 | */ |
5356 | if (group_leader->group_leader != group_leader) | 5360 | if (group_leader->group_leader != group_leader) |
5357 | goto err_put_context; | 5361 | goto err_context; |
5358 | /* | 5362 | /* |
5359 | * Do not allow to attach to a group in a different | 5363 | * Do not allow to attach to a group in a different |
5360 | * task or CPU context: | 5364 | * task or CPU context: |
5361 | */ | 5365 | */ |
5362 | if (group_leader->ctx != ctx) | 5366 | if (group_leader->ctx != ctx) |
5363 | goto err_put_context; | 5367 | goto err_context; |
5364 | /* | 5368 | /* |
5365 | * Only a group leader can be exclusive or pinned | 5369 | * Only a group leader can be exclusive or pinned |
5366 | */ | 5370 | */ |
5367 | if (attr.exclusive || attr.pinned) | 5371 | if (attr.exclusive || attr.pinned) |
5368 | goto err_put_context; | 5372 | goto err_context; |
5369 | } | ||
5370 | |||
5371 | event = perf_event_alloc(&attr, cpu, ctx, group_leader, | ||
5372 | NULL, NULL, GFP_KERNEL); | ||
5373 | if (IS_ERR(event)) { | ||
5374 | err = PTR_ERR(event); | ||
5375 | goto err_put_context; | ||
5376 | } | 5373 | } |
5377 | 5374 | ||
5378 | if (output_event) { | 5375 | if (output_event) { |
5379 | err = perf_event_set_output(event, output_event); | 5376 | err = perf_event_set_output(event, output_event); |
5380 | if (err) | 5377 | if (err) |
5381 | goto err_free_put_context; | 5378 | goto err_context; |
5382 | } | 5379 | } |
5383 | 5380 | ||
5384 | event_file = anon_inode_getfile("[perf_event]", &perf_fops, event, O_RDWR); | 5381 | event_file = anon_inode_getfile("[perf_event]", &perf_fops, event, O_RDWR); |
5385 | if (IS_ERR(event_file)) { | 5382 | if (IS_ERR(event_file)) { |
5386 | err = PTR_ERR(event_file); | 5383 | err = PTR_ERR(event_file); |
5387 | goto err_free_put_context; | 5384 | goto err_context; |
5388 | } | 5385 | } |
5389 | 5386 | ||
5390 | event->filp = event_file; | 5387 | event->filp = event_file; |
@@ -5410,11 +5407,11 @@ SYSCALL_DEFINE5(perf_event_open, | |||
5410 | fd_install(event_fd, event_file); | 5407 | fd_install(event_fd, event_file); |
5411 | return event_fd; | 5408 | return event_fd; |
5412 | 5409 | ||
5413 | err_free_put_context: | 5410 | err_context: |
5414 | free_event(event); | ||
5415 | err_put_context: | ||
5416 | fput_light(group_file, fput_needed); | 5411 | fput_light(group_file, fput_needed); |
5417 | put_ctx(ctx); | 5412 | put_ctx(ctx); |
5413 | err_alloc: | ||
5414 | free_event(event); | ||
5418 | err_fd: | 5415 | err_fd: |
5419 | put_unused_fd(event_fd); | 5416 | put_unused_fd(event_fd); |
5420 | return err; | 5417 | return err; |
@@ -5432,25 +5429,24 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, | |||
5432 | pid_t pid, | 5429 | pid_t pid, |
5433 | perf_overflow_handler_t overflow_handler) | 5430 | perf_overflow_handler_t overflow_handler) |
5434 | { | 5431 | { |
5435 | struct perf_event *event; | ||
5436 | struct perf_event_context *ctx; | 5432 | struct perf_event_context *ctx; |
5433 | struct perf_event *event; | ||
5437 | int err; | 5434 | int err; |
5438 | 5435 | ||
5439 | /* | 5436 | /* |
5440 | * Get the target context (task or percpu): | 5437 | * Get the target context (task or percpu): |
5441 | */ | 5438 | */ |
5442 | 5439 | ||
5440 | event = perf_event_alloc(attr, cpu, NULL, NULL, overflow_handler); | ||
5441 | if (IS_ERR(event)) { | ||
5442 | err = PTR_ERR(event); | ||
5443 | goto err; | ||
5444 | } | ||
5445 | |||
5443 | ctx = find_get_context(pid, cpu); | 5446 | ctx = find_get_context(pid, cpu); |
5444 | if (IS_ERR(ctx)) { | 5447 | if (IS_ERR(ctx)) { |
5445 | err = PTR_ERR(ctx); | 5448 | err = PTR_ERR(ctx); |
5446 | goto err_exit; | 5449 | goto err_free; |
5447 | } | ||
5448 | |||
5449 | event = perf_event_alloc(attr, cpu, ctx, NULL, | ||
5450 | NULL, overflow_handler, GFP_KERNEL); | ||
5451 | if (IS_ERR(event)) { | ||
5452 | err = PTR_ERR(event); | ||
5453 | goto err_put_context; | ||
5454 | } | 5450 | } |
5455 | 5451 | ||
5456 | event->filp = NULL; | 5452 | event->filp = NULL; |
@@ -5468,9 +5464,9 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, | |||
5468 | 5464 | ||
5469 | return event; | 5465 | return event; |
5470 | 5466 | ||
5471 | err_put_context: | 5467 | err_free: |
5472 | put_ctx(ctx); | 5468 | free_event(event); |
5473 | err_exit: | 5469 | err: |
5474 | return ERR_PTR(err); | 5470 | return ERR_PTR(err); |
5475 | } | 5471 | } |
5476 | EXPORT_SYMBOL_GPL(perf_event_create_kernel_counter); | 5472 | EXPORT_SYMBOL_GPL(perf_event_create_kernel_counter); |
@@ -5498,9 +5494,9 @@ inherit_event(struct perf_event *parent_event, | |||
5498 | parent_event = parent_event->parent; | 5494 | parent_event = parent_event->parent; |
5499 | 5495 | ||
5500 | child_event = perf_event_alloc(&parent_event->attr, | 5496 | child_event = perf_event_alloc(&parent_event->attr, |
5501 | parent_event->cpu, child_ctx, | 5497 | parent_event->cpu, |
5502 | group_leader, parent_event, | 5498 | group_leader, parent_event, |
5503 | NULL, GFP_KERNEL); | 5499 | NULL); |
5504 | if (IS_ERR(child_event)) | 5500 | if (IS_ERR(child_event)) |
5505 | return child_event; | 5501 | return child_event; |
5506 | get_ctx(child_ctx); | 5502 | get_ctx(child_ctx); |
@@ -5525,6 +5521,7 @@ inherit_event(struct perf_event *parent_event, | |||
5525 | local64_set(&hwc->period_left, sample_period); | 5521 | local64_set(&hwc->period_left, sample_period); |
5526 | } | 5522 | } |
5527 | 5523 | ||
5524 | child_event->ctx = child_ctx; | ||
5528 | child_event->overflow_handler = parent_event->overflow_handler; | 5525 | child_event->overflow_handler = parent_event->overflow_handler; |
5529 | 5526 | ||
5530 | /* | 5527 | /* |