diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2010-12-08 09:29:02 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-12-08 14:16:31 -0500 |
commit | c277443cfc29b1623b4923219ff0bdb48b91b589 (patch) | |
tree | 0655516f81164a42dfb06e416b54c50cac33f433 /kernel/perf_event.c | |
parent | c079c791c5a0627fc7b752d31d72e274e0596ba8 (diff) |
perf: Stop all counters on reboot
Use the reboot notifier to detach all running counters on reboot, this
solves a problem with kexec where the new kernel doesn't expect
running counters (rightly so).
It will however decrease the coverage of the NMI watchdog. Making a
kexec specific reboot notifier callback would be best, however that
would require touching all notifier callback handlers as they are not
properly structured to deal with new state.
As a compromise, place the perf reboot notifier at the very last
position in the list.
Reported-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Jason Wessel <jason.wessel@windriver.com>
Cc: Don Zickus <dzickus@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/perf_event.c')
-rw-r--r-- | kernel/perf_event.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 77ad22c00b9d..f9d2645b5546 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/dcache.h> | 21 | #include <linux/dcache.h> |
22 | #include <linux/percpu.h> | 22 | #include <linux/percpu.h> |
23 | #include <linux/ptrace.h> | 23 | #include <linux/ptrace.h> |
24 | #include <linux/reboot.h> | ||
24 | #include <linux/vmstat.h> | 25 | #include <linux/vmstat.h> |
25 | #include <linux/vmalloc.h> | 26 | #include <linux/vmalloc.h> |
26 | #include <linux/hardirq.h> | 27 | #include <linux/hardirq.h> |
@@ -6429,7 +6430,7 @@ static void __cpuinit perf_event_init_cpu(int cpu) | |||
6429 | mutex_unlock(&swhash->hlist_mutex); | 6430 | mutex_unlock(&swhash->hlist_mutex); |
6430 | } | 6431 | } |
6431 | 6432 | ||
6432 | #ifdef CONFIG_HOTPLUG_CPU | 6433 | #if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC |
6433 | static void perf_pmu_rotate_stop(struct pmu *pmu) | 6434 | static void perf_pmu_rotate_stop(struct pmu *pmu) |
6434 | { | 6435 | { |
6435 | struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); | 6436 | struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); |
@@ -6483,6 +6484,26 @@ static void perf_event_exit_cpu(int cpu) | |||
6483 | static inline void perf_event_exit_cpu(int cpu) { } | 6484 | static inline void perf_event_exit_cpu(int cpu) { } |
6484 | #endif | 6485 | #endif |
6485 | 6486 | ||
6487 | static int | ||
6488 | perf_reboot(struct notifier_block *notifier, unsigned long val, void *v) | ||
6489 | { | ||
6490 | int cpu; | ||
6491 | |||
6492 | for_each_online_cpu(cpu) | ||
6493 | perf_event_exit_cpu(cpu); | ||
6494 | |||
6495 | return NOTIFY_OK; | ||
6496 | } | ||
6497 | |||
6498 | /* | ||
6499 | * Run the perf reboot notifier at the very last possible moment so that | ||
6500 | * the generic watchdog code runs as long as possible. | ||
6501 | */ | ||
6502 | static struct notifier_block perf_reboot_notifier = { | ||
6503 | .notifier_call = perf_reboot, | ||
6504 | .priority = INT_MIN, | ||
6505 | }; | ||
6506 | |||
6486 | static int __cpuinit | 6507 | static int __cpuinit |
6487 | perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) | 6508 | perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) |
6488 | { | 6509 | { |
@@ -6518,6 +6539,7 @@ void __init perf_event_init(void) | |||
6518 | perf_pmu_register(&perf_task_clock); | 6539 | perf_pmu_register(&perf_task_clock); |
6519 | perf_tp_register(); | 6540 | perf_tp_register(); |
6520 | perf_cpu_notifier(perf_cpu_notify); | 6541 | perf_cpu_notifier(perf_cpu_notify); |
6542 | register_reboot_notifier(&perf_reboot_notifier); | ||
6521 | 6543 | ||
6522 | ret = init_hw_breakpoint(); | 6544 | ret = init_hw_breakpoint(); |
6523 | WARN(ret, "hw_breakpoint initialization failed with: %d", ret); | 6545 | WARN(ret, "hw_breakpoint initialization failed with: %d", ret); |