aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSilas Boyd-Wickizer <sbw@mit.edu>2012-09-23 14:27:32 -0400
committerJean Delvare <khali@endymion.delvare>2012-09-23 14:27:32 -0400
commit641f14560035bbb86500ea4b3a27ad27f034725b (patch)
treeacf190876e015304f959294c37b302e904380baa
parent1ec3ddfd27a77db55b8c0e80bcd27c656473fb96 (diff)
hwmon: (coretemp) Use get_online_cpus to avoid races involving CPU hotplug
coretemp_init loops with for_each_online_cpu, adding platform_devices and sysfs interfaces, then calls register_hotcpu_notifier. There is a race if a CPU is offlined or onlined after the loop, but before register_hotcpu_notifier. The race might result in the absence of a platform_device+sysfs interface for an online CPU, or the presence of a platform_device+sysfs interface for an offline CPU. A similar race occurs during coretemp_exit, after the module calls unregister_hotcpu_notifier, but before it unregisters all devices, a CPU might offline and a device for an offline CPU will exist for a short while. This fix surrounds for_each_online_cpu and register_hotcpu_notifier with get_online_cpus+put_online_cpus; and surrounds unregister_hotcpu_notifier and device unregistering with get_online_cpus+put_online_cpus. Build tested. Signed-off-by: Silas Boyd-Wickizer <sbw@mit.edu> Signed-off-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r--drivers/hwmon/coretemp.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 0fa356fe82cc..984a3f13923b 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -815,17 +815,20 @@ static int __init coretemp_init(void)
815 if (err) 815 if (err)
816 goto exit; 816 goto exit;
817 817
818 get_online_cpus();
818 for_each_online_cpu(i) 819 for_each_online_cpu(i)
819 get_core_online(i); 820 get_core_online(i);
820 821
821#ifndef CONFIG_HOTPLUG_CPU 822#ifndef CONFIG_HOTPLUG_CPU
822 if (list_empty(&pdev_list)) { 823 if (list_empty(&pdev_list)) {
824 put_online_cpus();
823 err = -ENODEV; 825 err = -ENODEV;
824 goto exit_driver_unreg; 826 goto exit_driver_unreg;
825 } 827 }
826#endif 828#endif
827 829
828 register_hotcpu_notifier(&coretemp_cpu_notifier); 830 register_hotcpu_notifier(&coretemp_cpu_notifier);
831 put_online_cpus();
829 return 0; 832 return 0;
830 833
831#ifndef CONFIG_HOTPLUG_CPU 834#ifndef CONFIG_HOTPLUG_CPU
@@ -840,6 +843,7 @@ static void __exit coretemp_exit(void)
840{ 843{
841 struct pdev_entry *p, *n; 844 struct pdev_entry *p, *n;
842 845
846 get_online_cpus();
843 unregister_hotcpu_notifier(&coretemp_cpu_notifier); 847 unregister_hotcpu_notifier(&coretemp_cpu_notifier);
844 mutex_lock(&pdev_list_mutex); 848 mutex_lock(&pdev_list_mutex);
845 list_for_each_entry_safe(p, n, &pdev_list, list) { 849 list_for_each_entry_safe(p, n, &pdev_list, list) {
@@ -848,6 +852,7 @@ static void __exit coretemp_exit(void)
848 kfree(p); 852 kfree(p);
849 } 853 }
850 mutex_unlock(&pdev_list_mutex); 854 mutex_unlock(&pdev_list_mutex);
855 put_online_cpus();
851 platform_driver_unregister(&coretemp_driver); 856 platform_driver_unregister(&coretemp_driver);
852} 857}
853 858