• O
    md/raid5: Fix CPU hotplug callback registration · 789b5e03
    Oleg Nesterov 提交于
    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
    Cc: stable@vger.kernel.org (v2.6.32+)
    Fixes: 36d1c647Signed-off-by: NOleg 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: NSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
    Signed-off-by: NNeilBrown <neilb@suse.de>
    789b5e03
raid5.c 197.0 KB