Commit 60beda84 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar

perf: Untangle 'owner' confusion

There are two concepts of owner wrt an event and they are conflated:

 - event::owner / event::owner_list,
   used by prctl(.option = PR_TASK_PERF_EVENTS_{EN,DIS}ABLE).

 - the 'owner' of the event object, typically the file descriptor.

Currently these two concepts are conflated, which gives trouble with
scm_rights passing of file descriptors. Passing the event and then
closing the creating task would render the event 'orphan' and would
have it cleared out. Unlikely what is expectd.

This patch untangles these two concepts by using PERF_EVENT_STATE_EXIT
to denote the second type.
Reported-by: default avatarAlexei Starovoitov <alexei.starovoitov@gmail.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 45a0e07a
...@@ -1650,7 +1650,7 @@ static void perf_group_detach(struct perf_event *event) ...@@ -1650,7 +1650,7 @@ static void perf_group_detach(struct perf_event *event)
*/ */
static bool is_orphaned_event(struct perf_event *event) static bool is_orphaned_event(struct perf_event *event)
{ {
return event && !is_kernel_event(event) && !READ_ONCE(event->owner); return event && event->state == PERF_EVENT_STATE_EXIT;
} }
/* /*
...@@ -1771,6 +1771,7 @@ group_sched_out(struct perf_event *group_event, ...@@ -1771,6 +1771,7 @@ group_sched_out(struct perf_event *group_event,
} }
#define DETACH_GROUP 0x01UL #define DETACH_GROUP 0x01UL
#define DETACH_STATE 0x02UL
/* /*
* Cross CPU call to remove a performance event * Cross CPU call to remove a performance event
...@@ -1790,6 +1791,8 @@ __perf_remove_from_context(struct perf_event *event, ...@@ -1790,6 +1791,8 @@ __perf_remove_from_context(struct perf_event *event,
if (flags & DETACH_GROUP) if (flags & DETACH_GROUP)
perf_group_detach(event); perf_group_detach(event);
list_del_event(event, ctx); list_del_event(event, ctx);
if (flags & DETACH_STATE)
event->state = PERF_EVENT_STATE_EXIT;
if (!ctx->nr_events && ctx->is_active) { if (!ctx->nr_events && ctx->is_active) {
ctx->is_active = 0; ctx->is_active = 0;
...@@ -3801,9 +3804,16 @@ static void put_event(struct perf_event *event) ...@@ -3801,9 +3804,16 @@ static void put_event(struct perf_event *event)
*/ */
ctx = perf_event_ctx_lock_nested(event, SINGLE_DEPTH_NESTING); ctx = perf_event_ctx_lock_nested(event, SINGLE_DEPTH_NESTING);
WARN_ON_ONCE(ctx->parent_ctx); WARN_ON_ONCE(ctx->parent_ctx);
perf_remove_from_context(event, DETACH_GROUP); perf_remove_from_context(event, DETACH_GROUP | DETACH_STATE);
perf_event_ctx_unlock(event, ctx); perf_event_ctx_unlock(event, ctx);
/*
* At this point we must have event->state == PERF_EVENT_STATE_EXIT,
* either from the above perf_remove_from_context() or through
* perf_event_exit_event().
*/
WARN_ON_ONCE(event->state != PERF_EVENT_STATE_EXIT);
_free_event(event); _free_event(event);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment