diff options
| author | Peter Zijlstra <peterz@infradead.org> | 2015-09-09 13:06:33 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2015-09-18 03:20:24 -0400 |
| commit | f55fc2a57cc9ca3b1bb4fb8eb25b6e1989e5b993 (patch) | |
| tree | 213efb8002bf5e0d2cc5f97d9a394f56521f5e6c | |
| parent | dfe1f3cb312624928052413928d88b0ee3492216 (diff) | |
perf: Restructure perf syscall point of no return
The exclusive_event_installable() stuff only works because its
exclusive with the grouping bits.
Rework the code such that there is a sane place to error out before we
go do things we cannot undo.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
| -rw-r--r-- | kernel/events/core.c | 49 |
1 files changed, 32 insertions, 17 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c index f548f69c4299..39679f749500 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
| @@ -8297,13 +8297,30 @@ SYSCALL_DEFINE5(perf_event_open, | |||
| 8297 | 8297 | ||
| 8298 | if (move_group) { | 8298 | if (move_group) { |
| 8299 | gctx = group_leader->ctx; | 8299 | gctx = group_leader->ctx; |
| 8300 | mutex_lock_double(&gctx->mutex, &ctx->mutex); | ||
| 8301 | } else { | ||
| 8302 | mutex_lock(&ctx->mutex); | ||
| 8303 | } | ||
| 8304 | |||
| 8305 | /* | ||
| 8306 | * Must be under the same ctx::mutex as perf_install_in_context(), | ||
| 8307 | * because we need to serialize with concurrent event creation. | ||
| 8308 | */ | ||
| 8309 | if (!exclusive_event_installable(event, ctx)) { | ||
| 8310 | /* exclusive and group stuff are assumed mutually exclusive */ | ||
| 8311 | WARN_ON_ONCE(move_group); | ||
| 8312 | |||
| 8313 | err = -EBUSY; | ||
| 8314 | goto err_locked; | ||
| 8315 | } | ||
| 8300 | 8316 | ||
| 8317 | WARN_ON_ONCE(ctx->parent_ctx); | ||
| 8318 | |||
| 8319 | if (move_group) { | ||
| 8301 | /* | 8320 | /* |
| 8302 | * See perf_event_ctx_lock() for comments on the details | 8321 | * See perf_event_ctx_lock() for comments on the details |
| 8303 | * of swizzling perf_event::ctx. | 8322 | * of swizzling perf_event::ctx. |
| 8304 | */ | 8323 | */ |
| 8305 | mutex_lock_double(&gctx->mutex, &ctx->mutex); | ||
| 8306 | |||
| 8307 | perf_remove_from_context(group_leader, false); | 8324 | perf_remove_from_context(group_leader, false); |
| 8308 | 8325 | ||
| 8309 | list_for_each_entry(sibling, &group_leader->sibling_list, | 8326 | list_for_each_entry(sibling, &group_leader->sibling_list, |
| @@ -8311,13 +8328,7 @@ SYSCALL_DEFINE5(perf_event_open, | |||
| 8311 | perf_remove_from_context(sibling, false); | 8328 | perf_remove_from_context(sibling, false); |
| 8312 | put_ctx(gctx); | 8329 | put_ctx(gctx); |
| 8313 | } | 8330 | } |
| 8314 | } else { | ||
| 8315 | mutex_lock(&ctx->mutex); | ||
| 8316 | } | ||
| 8317 | |||
| 8318 | WARN_ON_ONCE(ctx->parent_ctx); | ||
| 8319 | 8331 | ||
| 8320 | if (move_group) { | ||
| 8321 | /* | 8332 | /* |
| 8322 | * Wait for everybody to stop referencing the events through | 8333 | * Wait for everybody to stop referencing the events through |
| 8323 | * the old lists, before installing it on new lists. | 8334 | * the old lists, before installing it on new lists. |
| @@ -8349,22 +8360,20 @@ SYSCALL_DEFINE5(perf_event_open, | |||
| 8349 | perf_event__state_init(group_leader); | 8360 | perf_event__state_init(group_leader); |
| 8350 | perf_install_in_context(ctx, group_leader, group_leader->cpu); | 8361 | perf_install_in_context(ctx, group_leader, group_leader->cpu); |
| 8351 | get_ctx(ctx); | 8362 | get_ctx(ctx); |
| 8352 | } | ||
| 8353 | 8363 | ||
| 8354 | if (!exclusive_event_installable(event, ctx)) { | 8364 | /* |
| 8355 | err = -EBUSY; | 8365 | * Now that all events are installed in @ctx, nothing |
| 8356 | mutex_unlock(&ctx->mutex); | 8366 | * references @gctx anymore, so drop the last reference we have |
| 8357 | fput(event_file); | 8367 | * on it. |
| 8358 | goto err_context; | 8368 | */ |
| 8369 | put_ctx(gctx); | ||
| 8359 | } | 8370 | } |
| 8360 | 8371 | ||
| 8361 | perf_install_in_context(ctx, event, event->cpu); | 8372 | perf_install_in_context(ctx, event, event->cpu); |
| 8362 | perf_unpin_context(ctx); | 8373 | perf_unpin_context(ctx); |
| 8363 | 8374 | ||
| 8364 | if (move_group) { | 8375 | if (move_group) |
| 8365 | mutex_unlock(&gctx->mutex); | 8376 | mutex_unlock(&gctx->mutex); |
| 8366 | put_ctx(gctx); | ||
| 8367 | } | ||
| 8368 | mutex_unlock(&ctx->mutex); | 8377 | mutex_unlock(&ctx->mutex); |
| 8369 | 8378 | ||
| 8370 | put_online_cpus(); | 8379 | put_online_cpus(); |
| @@ -8391,6 +8400,12 @@ SYSCALL_DEFINE5(perf_event_open, | |||
| 8391 | fd_install(event_fd, event_file); | 8400 | fd_install(event_fd, event_file); |
| 8392 | return event_fd; | 8401 | return event_fd; |
| 8393 | 8402 | ||
| 8403 | err_locked: | ||
| 8404 | if (move_group) | ||
| 8405 | mutex_unlock(&gctx->mutex); | ||
| 8406 | mutex_unlock(&ctx->mutex); | ||
| 8407 | /* err_file: */ | ||
| 8408 | fput(event_file); | ||
| 8394 | err_context: | 8409 | err_context: |
| 8395 | perf_unpin_context(ctx); | 8410 | perf_unpin_context(ctx); |
| 8396 | put_ctx(ctx); | 8411 | put_ctx(ctx); |
