• Coly Li's avatar
    bcache: avoid a deadlock in bcache_reboot() · a59ff6cc
    Coly Li authored
    It is quite frequently to observe deadlock in bcache_reboot() happens
    and hang the system reboot process. The reason is, in bcache_reboot()
    when calling bch_cache_set_stop() and bcache_device_stop() the mutex
    bch_register_lock is held. But in the process to stop cache set and
    bcache device, bch_register_lock will be acquired again. If this mutex
    is held here, deadlock will happen inside the stopping process. The
    aftermath of the deadlock is, whole system reboot gets hung.
    
    The fix is to avoid holding bch_register_lock for the following loops
    in bcache_reboot(),
           list_for_each_entry_safe(c, tc, &bch_cache_sets, list)
                    bch_cache_set_stop(c);
    
            list_for_each_entry_safe(dc, tdc, &uncached_devices, list)
                    bcache_device_stop(&dc->disk);
    
    A module range variable 'bcache_is_reboot' is added, it sets to true
    in bcache_reboot(). In register_bcache(), if bcache_is_reboot is checked
    to be true, reject the registration by returning -EBUSY immediately.
    Signed-off-by: default avatarColy Li <colyli@suse.de>
    Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
    a59ff6cc
super.c 65.3 KB