perf: stop deadlock if attempt to bring cpu up fails

When an attempt is made to free an event on a CPU which is
no longer online, perf tries to bring the CPU online. This
can fail, resulting in an UP_CANCELLED notifier, which
eventually tries to acquire the ctx->mutex which is already
being held by the code, which brings up the CPU.

Removing the attempt to bring the cpu up will remove this
deadlock, but also requires temporarily removing support of
counting events across hotplug. This will be restored in a
later patch.

Conflicts:
	kernel/events/core.c
	kernel/events/hw_breakpoint.c

Change-Id: Iaafa3c6688d26508857472fd5bb32139a137880e
Signed-off-by: Neil Leeder <nleeder@codeaurora.org>
This commit is contained in:
Neil Leeder 2015-09-24 12:14:20 -04:00 committed by Imran Khan
parent 6f56b2a9c8
commit 5f71e693df
3 changed files with 1 additions and 41 deletions

View file

@ -552,7 +552,6 @@ static void armpmu_init(struct arm_pmu *armpmu)
.stop = armpmu_stop,
.read = armpmu_read,
.filter_match = armpmu_filter_match,
.events_across_hotplug = 1,
};
}

View file

@ -1693,32 +1693,6 @@ static int __perf_remove_from_context(void *info)
return 0;
}
#ifdef CONFIG_SMP
static void perf_retry_remove(struct perf_event *event,
struct remove_event *rep)
{
int up_ret;
/*
* CPU was offline. Bring it online so we can
* gracefully exit a perf context.
*/
up_ret = cpu_up(event->cpu);
if (!up_ret)
/* Try the remove call once again. */
cpu_function_call(event->cpu, __perf_remove_from_context,
rep);
else
pr_err("Failed to bring up CPU: %d, ret: %d\n",
event->cpu, up_ret);
}
#else
static void perf_retry_remove(struct perf_event *event,
struct remove_event *rep)
{
}
#endif
/*
* Remove the event from a task's (or a CPU's) list of events.
*
@ -1754,9 +1728,6 @@ static void __ref perf_remove_from_context(struct perf_event *event,
*/
ret = cpu_function_call(event->cpu, __perf_remove_from_context,
&re);
if (ret == -ENXIO)
perf_retry_remove(event, &re);
return;
}
@ -7138,8 +7109,6 @@ static struct pmu perf_swevent = {
.start = perf_swevent_start,
.stop = perf_swevent_stop,
.read = perf_swevent_read,
.events_across_hotplug = 1,
};
#ifdef CONFIG_EVENT_TRACING
@ -7261,8 +7230,6 @@ static struct pmu perf_tracepoint = {
.start = perf_swevent_start,
.stop = perf_swevent_stop,
.read = perf_swevent_read,
.events_across_hotplug = 1,
};
static inline void perf_tp_register(void)
@ -7550,8 +7517,6 @@ static struct pmu perf_cpu_clock = {
.start = cpu_clock_event_start,
.stop = cpu_clock_event_stop,
.read = cpu_clock_event_read,
.events_across_hotplug = 1,
};
/*
@ -7633,8 +7598,6 @@ static struct pmu perf_task_clock = {
.start = task_clock_event_start,
.stop = task_clock_event_stop,
.read = task_clock_event_read,
.events_across_hotplug = 1,
};
static void perf_pmu_nop_void(struct pmu *pmu)

View file

@ -614,8 +614,6 @@ static struct pmu perf_breakpoint = {
.start = hw_breakpoint_start,
.stop = hw_breakpoint_stop,
.read = hw_breakpoint_pmu_read,
.events_across_hotplug = 1,
};
int __init init_hw_breakpoint(void)