| From | "Srivatsa S. Bhat" <> | Subject | [PATCH 36/51] drivers/base/topology.c: Fix CPU hotplug callback registration | Date | Thu, 06 Feb 2014 03:41:02 +0530 |
| |
Subsystems that want to register CPU hotplug callbacks, as well as perform initialization for the CPUs that are already online, often do it as shown below:
get_online_cpus();
for_each_online_cpu(cpu) init_cpu(cpu);
register_cpu_notifier(&foobar_cpu_notifier);
put_online_cpus();
This is wrong, since it is prone to ABBA deadlocks involving the cpu_add_remove_lock and the cpu_hotplug.lock (when running concurrently with CPU hotplug operations).
Instead, the correct and race-free way of performing the callback registration is:
cpu_maps_update_begin();
for_each_online_cpu(cpu) init_cpu(cpu);
/* Note the use of the double underscored version of the API */ __register_cpu_notifier(&foobar_cpu_notifier);
cpu_maps_update_done();
Fix the topology code by using this latter form of callback registration.
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> ---
drivers/base/topology.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 94ffee3..9db29cc 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -161,16 +161,20 @@ static int topology_cpu_callback(struct notifier_block *nfb, static int topology_sysfs_init(void) { int cpu; - int rc; + int rc = 0; + + cpu_maps_update_begin(); for_each_online_cpu(cpu) { rc = topology_add_dev(cpu); if (rc) - return rc; + goto out; } - hotcpu_notifier(topology_cpu_callback, 0); + __hotcpu_notifier(topology_cpu_callback, 0); - return 0; +out: + cpu_maps_update_done(); + return rc; } device_initcall(topology_sysfs_init);
|