aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/processor_driver.c
diff options
context:
space:
mode:
authorYasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>2012-10-22 19:30:54 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-14 18:16:00 -0500
commit5e5041f3527b36b58e864886ba34c179ad40ff92 (patch)
tree16857e196f4d02f89d2934f5a59bc41fa52ef451 /drivers/acpi/processor_driver.c
parent73d4511a5f1e208399b2f7a058b73578c1977611 (diff)
ACPI / processor: prevent cpu from becoming online
Even if acpi_processor_handle_eject() offlines cpu, there is a chance to online the cpu after that. So the patch closes the window by using get/put_online_cpus(). Why does the patch change _cpu_up() logic? The patch cares the race of hot-remove cpu and _cpu_up(). If the patch does not change it, there is the following race. hot-remove cpu | _cpu_up() ------------------------------------- ------------------------------------ call acpi_processor_handle_eject() | call cpu_down() | call get_online_cpus() | | call cpu_hotplug_begin() and stop here call arch_unregister_cpu() | call acpi_unmap_lsapic() | call put_online_cpus() | | start and continue _cpu_up() return acpi_processor_remove() | continue hot-remove the cpu | So _cpu_up() can continue to itself. And hot-remove cpu can also continue itself. If the patch changes _cpu_up() logic, the race disappears as below: hot-remove cpu | _cpu_up() ----------------------------------------------------------------------- call acpi_processor_handle_eject() | call cpu_down() | call get_online_cpus() | | call cpu_hotplug_begin() and stop here call arch_unregister_cpu() | call acpi_unmap_lsapic() | cpu's cpu_present is set | to false by set_cpu_present()| call put_online_cpus() | | start _cpu_up() | check cpu_present() and return -EINVAL return acpi_processor_remove() | continue hot-remove the cpu | Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Reviewed-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> Reviewed-by: Toshi Kani <toshi.kani@hp.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/processor_driver.c')
-rw-r--r--drivers/acpi/processor_driver.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index bd4e5dca3ff7..a4352b88a331 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -852,8 +852,22 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr)
852 if (cpu_online(pr->id)) 852 if (cpu_online(pr->id))
853 cpu_down(pr->id); 853 cpu_down(pr->id);
854 854
855 get_online_cpus();
856 /*
857 * The cpu might become online again at this point. So we check whether
858 * the cpu has been onlined or not. If the cpu became online, it means
859 * that someone wants to use the cpu. So acpi_processor_handle_eject()
860 * returns -EAGAIN.
861 */
862 if (unlikely(cpu_online(pr->id))) {
863 put_online_cpus();
864 pr_warn("Failed to remove CPU %d, because other task "
865 "brought the CPU back online\n", pr->id);
866 return -EAGAIN;
867 }
855 arch_unregister_cpu(pr->id); 868 arch_unregister_cpu(pr->id);
856 acpi_unmap_lsapic(pr->id); 869 acpi_unmap_lsapic(pr->id);
870 put_online_cpus();
857 return (0); 871 return (0);
858} 872}
859#else 873#else