Skip to content
  • Oleg Nesterov's avatar
    stop_machine: Ensure that a queued callback will be called before cpu_stop_park() · 233e7f26
    Oleg Nesterov authored
    
    
    cpu_stop_queue_work() checks stopper->enabled before it queues the
    work, but ->enabled == T can only guarantee cpu_stop_signal_done()
    if we race with cpu_down().
    
    This is not enough for stop_two_cpus() or stop_machine(), they will
    deadlock if multi_cpu_stop() won't be called by one of the target
    CPU's. stop_machine/stop_cpus are fine, they rely on stop_cpus_mutex.
    But stop_two_cpus() has to check cpu_active() to avoid the same race
    with hotplug, and this check is very unobvious and probably not even
    correct if we race with cpu_up().
    
    Change cpu_down() pass to clear ->enabled before cpu_stopper_thread()
    flushes the pending ->works and returns with KTHREAD_SHOULD_PARK set.
    
    Note also that smpboot_thread_call() calls cpu_stop_unpark() which
    sets enabled == T at CPU_ONLINE stage, so this CPU can't go away until
    cpu_stopper_thread() is called at least once. This all means that if
    cpu_stop_queue_work() succeeds, we know that work->fn() will be called.
    
    Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
    Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Mike Galbraith <efault@gmx.de>
    Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Rik van Riel <riel@redhat.com>
    Cc: Tejun Heo <tj@kernel.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: heiko.carstens@de.ibm.com
    Link: http://lkml.kernel.org/r/20151008145131.GA18139@redhat.com
    
    
    Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
    233e7f26