Skip to content

Commit f55fc2a

Browse files
Peter ZijlstraIngo Molnar
authored andcommitted
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) <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: [email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent dfe1f3c commit f55fc2a

File tree

1 file changed

+32
-17
lines changed

1 file changed

+32
-17
lines changed

kernel/events/core.c

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8297,27 +8297,38 @@ SYSCALL_DEFINE5(perf_event_open,
82978297

82988298
if (move_group) {
82998299
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+
}
83008316

8317+
WARN_ON_ONCE(ctx->parent_ctx);
8318+
8319+
if (move_group) {
83018320
/*
83028321
* See perf_event_ctx_lock() for comments on the details
83038322
* of swizzling perf_event::ctx.
83048323
*/
8305-
mutex_lock_double(&gctx->mutex, &ctx->mutex);
8306-
83078324
perf_remove_from_context(group_leader, false);
83088325

83098326
list_for_each_entry(sibling, &group_leader->sibling_list,
83108327
group_entry) {
83118328
perf_remove_from_context(sibling, false);
83128329
put_ctx(gctx);
83138330
}
8314-
} else {
8315-
mutex_lock(&ctx->mutex);
8316-
}
8317-
8318-
WARN_ON_ONCE(ctx->parent_ctx);
83198331

8320-
if (move_group) {
83218332
/*
83228333
* Wait for everybody to stop referencing the events through
83238334
* the old lists, before installing it on new lists.
@@ -8349,22 +8360,20 @@ SYSCALL_DEFINE5(perf_event_open,
83498360
perf_event__state_init(group_leader);
83508361
perf_install_in_context(ctx, group_leader, group_leader->cpu);
83518362
get_ctx(ctx);
8352-
}
83538363

8354-
if (!exclusive_event_installable(event, ctx)) {
8355-
err = -EBUSY;
8356-
mutex_unlock(&ctx->mutex);
8357-
fput(event_file);
8358-
goto err_context;
8364+
/*
8365+
* Now that all events are installed in @ctx, nothing
8366+
* references @gctx anymore, so drop the last reference we have
8367+
* on it.
8368+
*/
8369+
put_ctx(gctx);
83598370
}
83608371

83618372
perf_install_in_context(ctx, event, event->cpu);
83628373
perf_unpin_context(ctx);
83638374

8364-
if (move_group) {
8375+
if (move_group)
83658376
mutex_unlock(&gctx->mutex);
8366-
put_ctx(gctx);
8367-
}
83688377
mutex_unlock(&ctx->mutex);
83698378

83708379
put_online_cpus();
@@ -8391,6 +8400,12 @@ SYSCALL_DEFINE5(perf_event_open,
83918400
fd_install(event_fd, event_file);
83928401
return event_fd;
83938402

8403+
err_locked:
8404+
if (move_group)
8405+
mutex_unlock(&gctx->mutex);
8406+
mutex_unlock(&ctx->mutex);
8407+
/* err_file: */
8408+
fput(event_file);
83948409
err_context:
83958410
perf_unpin_context(ctx);
83968411
put_ctx(ctx);

0 commit comments

Comments
 (0)