• Gerald Schaefer's avatar
    s390/smp: fix CPU hotplug deadlock with CPU rescan · 90814f0a
    Gerald Schaefer authored
    commit b7cb707c upstream.
    
    smp_rescan_cpus() is called without the device_hotplug_lock, which can lead
    to a dedlock when a new CPU is found and immediately set online by a udev
    rule.
    
    This was observed on an older kernel version, where the cpu_hotplug_begin()
    loop was still present, and it resulted in hanging chcpu and systemd-udev
    processes. This specific deadlock will not show on current kernels. However,
    there may be other possible deadlocks, and since smp_rescan_cpus() can still
    trigger a CPU hotplug operation, the device_hotplug_lock should be held.
    
    For reference, this was the deadlock with the old cpu_hotplug_begin() loop:
    
            chcpu (rescan)                       systemd-udevd
    
     echo 1 > /sys/../rescan
     -> smp_rescan_cpus()
     -> (*) get_online_cpus()
        (increases refcount)
     -> smp_add_present_cpu()
        (new CPU found)
     -> register_cpu()
     -> device_add()
     -> udev "add" event triggered -----------> udev rule sets CPU online
                                             -> echo 1 > /sys/.../online
                                             -> lock_device_hotplug_sysfs()
                                                (this is missing in rescan path)
                                             -> device_online()
                                             -> (**) device_lock(new CPU dev)
                                             -> cpu_up()
                                             -> cpu_hotplug_begin()
                                                (loops until refcount == 0)
                                                -> deadlock with (*)
     -> bus_probe_device()
     -> device_attach()
     -> device_lock(new CPU dev)
        -> deadlock with (**)
    
    Fix this by taking the device_hotplug_lock in the CPU rescan path.
    
    Cc: <stable@vger.kernel.org>
    Signed-off-by: default avatarGerald Schaefer <gerald.schaefer@de.ibm.com>
    Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    90814f0a
Name
Last commit
Last update
..
Kconfig Loading commit data...
Makefile Loading commit data...
con3215.c Loading commit data...
con3270.c Loading commit data...
ctrlchar.c Loading commit data...
ctrlchar.h Loading commit data...
defkeymap.c Loading commit data...
defkeymap.map Loading commit data...
diag_ftp.c Loading commit data...
diag_ftp.h Loading commit data...
fs3270.c Loading commit data...
hmcdrv_cache.c Loading commit data...
hmcdrv_cache.h Loading commit data...
hmcdrv_dev.c Loading commit data...
hmcdrv_dev.h Loading commit data...
hmcdrv_ftp.c Loading commit data...
hmcdrv_ftp.h Loading commit data...
hmcdrv_mod.c Loading commit data...
keyboard.c Loading commit data...
keyboard.h Loading commit data...
monreader.c Loading commit data...
monwriter.c Loading commit data...
raw3270.c Loading commit data...
raw3270.h Loading commit data...
sclp.c Loading commit data...
sclp.h Loading commit data...
sclp_async.c Loading commit data...
sclp_cmd.c Loading commit data...
sclp_con.c Loading commit data...
sclp_config.c Loading commit data...
sclp_cpi_sys.c Loading commit data...
sclp_cpi_sys.h Loading commit data...
sclp_ctl.c Loading commit data...
sclp_diag.h Loading commit data...
sclp_early.c Loading commit data...
sclp_early_core.c Loading commit data...
sclp_ftp.c Loading commit data...
sclp_ftp.h Loading commit data...
sclp_ocf.c Loading commit data...
sclp_pci.c Loading commit data...
sclp_quiesce.c Loading commit data...
sclp_rw.c Loading commit data...
sclp_rw.h Loading commit data...
sclp_sd.c Loading commit data...
sclp_sdias.c Loading commit data...
sclp_sdias.h Loading commit data...
sclp_tty.c Loading commit data...
sclp_tty.h Loading commit data...
sclp_vt220.c Loading commit data...
tape.h Loading commit data...
tape_34xx.c Loading commit data...
tape_3590.c Loading commit data...
tape_3590.h Loading commit data...
tape_char.c Loading commit data...
tape_class.c Loading commit data...
tape_class.h Loading commit data...
tape_core.c Loading commit data...
tape_proc.c Loading commit data...
tape_std.c Loading commit data...
tape_std.h Loading commit data...
tty3270.c Loading commit data...
tty3270.h Loading commit data...
vmcp.c Loading commit data...
vmlogrdr.c Loading commit data...
vmur.c Loading commit data...
vmur.h Loading commit data...
zcore.c Loading commit data...