diff options
author | Vitaly Kuznetsov <vkuznets@redhat.com> | 2015-08-05 03:52:46 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-08-05 14:46:44 -0400 |
commit | 89af7ba5740b5937d10c8de93e79e71e5a933041 (patch) | |
tree | 0717f4e10938962d7fb57683d1efc8236e9956fd /kernel/cpu.c | |
parent | 54bf725e5d21022b25fe0d3c103fe82ed13b870b (diff) |
cpu-hotplug: convert cpu_hotplug_disabled to a counter
As a prerequisite to exporting cpu_hotplug_enable/cpu_hotplug_disable
functions to modules we need to convert cpu_hotplug_disabled to a counter
to properly support disable -> disable -> enable call sequences. E.g.
after Hyper-V vmbus module (which is supposed to be the first user of
exported cpu_hotplug_enable/cpu_hotplug_disable) did cpu_hotplug_disable()
hibernate path calls disable_nonboot_cpus() and if we hit an error in
_cpu_down() enable_nonboot_cpus() will be called on the failure path (thus
making cpu_hotplug_disabled = 0 and leaving cpu hotplug in 'enabled'
state). Same problem is possible if more than 1 module use
cpu_hotplug_disable/cpu_hotplug_enable on their load/unload paths. When
one of these modules is been unloaded it is logical to leave cpu hotplug
in 'disabled' state.
To support the change we need to increse cpu_hotplug_disabled counter
in disable_nonboot_cpus() unconditionally as all users of
disable_nonboot_cpus() are supposed to do enable_nonboot_cpus() in case
an error was returned.
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel/cpu.c')
-rw-r--r-- | kernel/cpu.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c index 5644ec5582b9..0fca2ba96138 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
@@ -191,14 +191,14 @@ void cpu_hotplug_done(void) | |||
191 | void cpu_hotplug_disable(void) | 191 | void cpu_hotplug_disable(void) |
192 | { | 192 | { |
193 | cpu_maps_update_begin(); | 193 | cpu_maps_update_begin(); |
194 | cpu_hotplug_disabled = 1; | 194 | cpu_hotplug_disabled++; |
195 | cpu_maps_update_done(); | 195 | cpu_maps_update_done(); |
196 | } | 196 | } |
197 | 197 | ||
198 | void cpu_hotplug_enable(void) | 198 | void cpu_hotplug_enable(void) |
199 | { | 199 | { |
200 | cpu_maps_update_begin(); | 200 | cpu_maps_update_begin(); |
201 | cpu_hotplug_disabled = 0; | 201 | WARN_ON(--cpu_hotplug_disabled < 0); |
202 | cpu_maps_update_done(); | 202 | cpu_maps_update_done(); |
203 | } | 203 | } |
204 | 204 | ||
@@ -608,13 +608,18 @@ int disable_nonboot_cpus(void) | |||
608 | } | 608 | } |
609 | } | 609 | } |
610 | 610 | ||
611 | if (!error) { | 611 | if (!error) |
612 | BUG_ON(num_online_cpus() > 1); | 612 | BUG_ON(num_online_cpus() > 1); |
613 | /* Make sure the CPUs won't be enabled by someone else */ | 613 | else |
614 | cpu_hotplug_disabled = 1; | ||
615 | } else { | ||
616 | pr_err("Non-boot CPUs are not disabled\n"); | 614 | pr_err("Non-boot CPUs are not disabled\n"); |
617 | } | 615 | |
616 | /* | ||
617 | * Make sure the CPUs won't be enabled by someone else. We need to do | ||
618 | * this even in case of failure as all disable_nonboot_cpus() users are | ||
619 | * supposed to do enable_nonboot_cpus() on the failure path. | ||
620 | */ | ||
621 | cpu_hotplug_disabled++; | ||
622 | |||
618 | cpu_maps_update_done(); | 623 | cpu_maps_update_done(); |
619 | return error; | 624 | return error; |
620 | } | 625 | } |
@@ -633,7 +638,7 @@ void __ref enable_nonboot_cpus(void) | |||
633 | 638 | ||
634 | /* Allow everyone to use the CPU hotplug again */ | 639 | /* Allow everyone to use the CPU hotplug again */ |
635 | cpu_maps_update_begin(); | 640 | cpu_maps_update_begin(); |
636 | cpu_hotplug_disabled = 0; | 641 | WARN_ON(--cpu_hotplug_disabled < 0); |
637 | if (cpumask_empty(frozen_cpus)) | 642 | if (cpumask_empty(frozen_cpus)) |
638 | goto out; | 643 | goto out; |
639 | 644 | ||