perf: Fix hotplug splat
Subsystems (2)
tip-bot for Peter Zijlstra
merge botCommit-ID: e3703f8cdfcf39c25c4338c3ad8e68891cca3731 Gitweb: http://git.kernel.org/tip/e3703f8cdfcf39c25c4338c3ad8e68891cca3731 Author: Peter Zijlstra <[email protected]> AuthorDate: Mon, 24 Feb 2014 12:06:12 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 27 Feb 2014 12:38:03 +0100
perf: Fix hotplug splat
Drew Richardson reported that he could make the kernel go *boom* when hotplugging while having perf events active.
It turned out that when you have a group event, the code in __perf_event_exit_context() fails to remove the group siblings from the context.
We then proceed with destroying and freeing the event, and when you re-plug the CPU and try and add another event to that CPU, things go *boom* because you've still got dead entries there.
Reported-by Drew Richardson <[email protected]>
Signed-off-by Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc <[email protected]>
Signed-off-by Ingo Molnar <[email protected]>
--- kernel/events/core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
kernel/events/core.c +6 -6
@@ -7856,14 +7856,14 @@ static void perf_pmu_rotate_stop(struct pmu *pmu)static void __perf_event_exit_context (void *__info) {struct perf_event_context *ctx = __info; -struct perf_event *event, *tmp; +struct perf_event *event;perf_pmu_rotate_stop (ctx->pmu); -list_for_each_entry_safe (event, tmp, &ctx->pinned_groups, group_entry) -__perf_remove_from_context (event); -list_for_each_entry_safe (event, tmp, &ctx->flexible_groups, group_entry) +rcu_read_lock (); +list_for_each_entry_rcu (event, &ctx->event_list, event_entry)__perf_remove_from_context (event); +rcu_read_unlock (); }static void perf_event_exit_cpu_context (int cpu)
@@ -7887,11 +7887,11 @@ static void perf_event_exit_cpu(int cpu) {struct swevent_htable *swhash = &per_cpu (swevent_htable, cpu); +perf_event_exit_cpu_context (cpu); +mutex_lock (&swhash->hlist_mutex);swevent_hlist_release (swhash);mutex_unlock (&swhash->hlist_mutex); - -perf_event_exit_cpu_context (cpu); }#else static inline void perf_event_exit_cpu (int cpu) { }