• Oleg Nesterov's avatar
    md/raid5: Fix CPU hotplug callback registration · 4d4ef86d
    Oleg Nesterov authored
    commit 789b5e03 upstream.
    
    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).
    
    Interestingly, the raid5 code can actually prevent double initialization and
    hence can use the following simplified form of callback registration:
    
    	register_cpu_notifier(&foobar_cpu_notifier);
    
    	get_online_cpus();
    
    	for_each_online_cpu(cpu)
    		init_cpu(cpu);
    
    	put_online_cpus();
    
    A hotplug operation that occurs between registering the notifier and calling
    get_online_cpus(), won't disrupt anything, because the code takes care to
    perform the memory allocations only once.
    
    So reorganize the code in raid5 this way to fix the deadlock with callback
    registration.
    
    Cc: linux-raid@vger.kernel.org
    Fixes: 36d1c647Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
    [Srivatsa: Fixed the unregister_cpu_notifier() deadlock, added the
    free_scratch_buffer() helper to condense code further and wrote the changelog.]
    Signed-off-by: default avatarSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
    Signed-off-by: default avatarNeilBrown <neilb@suse.de>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    4d4ef86d
raid5.c 182 KB