diff options
-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); |