aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>2014-03-10 16:41:56 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-03-20 08:43:48 -0400
commitd39ad278a3001c860da4d7c13e51259b1904bec5 (patch)
tree1b807bc3790e62f9c7abeb75a7f99d63052736bd /kernel
parent43ea9536499e80d858e26cecb7abcc893f86d222 (diff)
trace, ring-buffer: Fix CPU hotplug callback registration
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_notifier_register_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_notifier_register_done(); Fix the tracing ring-buffer code by using this latter form of callback registration. Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@kernel.org> Acked-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/ring_buffer.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index fc4da2d97f9b..c634868c2921 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -1301,7 +1301,7 @@ struct ring_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
1301 * In that off case, we need to allocate for all possible cpus. 1301 * In that off case, we need to allocate for all possible cpus.
1302 */ 1302 */
1303#ifdef CONFIG_HOTPLUG_CPU 1303#ifdef CONFIG_HOTPLUG_CPU
1304 get_online_cpus(); 1304 cpu_notifier_register_begin();
1305 cpumask_copy(buffer->cpumask, cpu_online_mask); 1305 cpumask_copy(buffer->cpumask, cpu_online_mask);
1306#else 1306#else
1307 cpumask_copy(buffer->cpumask, cpu_possible_mask); 1307 cpumask_copy(buffer->cpumask, cpu_possible_mask);
@@ -1324,10 +1324,10 @@ struct ring_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
1324#ifdef CONFIG_HOTPLUG_CPU 1324#ifdef CONFIG_HOTPLUG_CPU
1325 buffer->cpu_notify.notifier_call = rb_cpu_notify; 1325 buffer->cpu_notify.notifier_call = rb_cpu_notify;
1326 buffer->cpu_notify.priority = 0; 1326 buffer->cpu_notify.priority = 0;
1327 register_cpu_notifier(&buffer->cpu_notify); 1327 __register_cpu_notifier(&buffer->cpu_notify);
1328 cpu_notifier_register_done();
1328#endif 1329#endif
1329 1330
1330 put_online_cpus();
1331 mutex_init(&buffer->mutex); 1331 mutex_init(&buffer->mutex);
1332 1332
1333 return buffer; 1333 return buffer;
@@ -1341,7 +1341,9 @@ struct ring_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
1341 1341
1342 fail_free_cpumask: 1342 fail_free_cpumask:
1343 free_cpumask_var(buffer->cpumask); 1343 free_cpumask_var(buffer->cpumask);
1344 put_online_cpus(); 1344#ifdef CONFIG_HOTPLUG_CPU
1345 cpu_notifier_register_done();
1346#endif
1345 1347
1346 fail_free_buffer: 1348 fail_free_buffer:
1347 kfree(buffer); 1349 kfree(buffer);
@@ -1358,16 +1360,17 @@ ring_buffer_free(struct ring_buffer *buffer)
1358{ 1360{
1359 int cpu; 1361 int cpu;
1360 1362
1361 get_online_cpus();
1362
1363#ifdef CONFIG_HOTPLUG_CPU 1363#ifdef CONFIG_HOTPLUG_CPU
1364 unregister_cpu_notifier(&buffer->cpu_notify); 1364 cpu_notifier_register_begin();
1365 __unregister_cpu_notifier(&buffer->cpu_notify);
1365#endif 1366#endif
1366 1367
1367 for_each_buffer_cpu(buffer, cpu) 1368 for_each_buffer_cpu(buffer, cpu)
1368 rb_free_cpu_buffer(buffer->buffers[cpu]); 1369 rb_free_cpu_buffer(buffer->buffers[cpu]);
1369 1370
1370 put_online_cpus(); 1371#ifdef CONFIG_HOTPLUG_CPU
1372 cpu_notifier_register_done();
1373#endif
1371 1374
1372 kfree(buffer->buffers); 1375 kfree(buffer->buffers);
1373 free_cpumask_var(buffer->cpumask); 1376 free_cpumask_var(buffer->cpumask);