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 mce code in x86 by using this latter form of callback registration.

Cc: Tony Luck <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Srivatsa S. Bhat <[email protected]>
---

 arch/x86/kernel/cpu/mcheck/mce.c |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 4d5419b..9b7734b 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -2434,14 +2434,18 @@ static __init int mcheck_init_device(void)
        if (err)
                return err;
 
+       cpu_notifier_register_begin();
        for_each_online_cpu(i) {
                err = mce_device_create(i);
-               if (err)
+               if (err) {
+                       cpu_notifier_register_done();
                        return err;
+               }
        }
 
        register_syscore_ops(&mce_syscore_ops);
-       register_hotcpu_notifier(&mce_cpu_notifier);
+       __register_hotcpu_notifier(&mce_cpu_notifier);
+       cpu_notifier_register_done();
 
        /* register character device /dev/mcelog */
        misc_register(&mce_chrdev_device);

_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to