block: Allow bdi re-registration
SCSI can call device_add_disk() several times for one request queue when a device in unbound and bound, creating new gendisk each time. This will lead to bdi being repeatedly registered and unregistered. This was not a big problem until commit165a5e22fa
"block: Move bdi_unregister() to del_gendisk()" since bdi was only registered repeatedly (bdi_register() handles repeated calls fine, only we ended up leaking reference to gendisk due to overwriting bdi->owner) but unregistered only in blk_cleanup_queue() which didn't get called repeatedly. After165a5e22fa
we were doing correct bdi_register() - bdi_unregister() cycles however bdi_unregister() is not prepared for it. So make sure bdi_unregister() cleans up bdi in such a way that it is prepared for a possible following bdi_register() call. An easy way to provoke this behavior is to enable CONFIG_DEBUG_TEST_DRIVER_REMOVE and use scsi_debug driver to create a scsi disk which immediately hangs without this fix. Fixes:165a5e22fa
Signed-off-by: Jan Kara <jack@suse.cz> Tested-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
parent
b0bfdfc2bf
commit
b6f8fec444
|
@ -710,6 +710,11 @@ static void cgwb_bdi_destroy(struct backing_dev_info *bdi)
|
|||
*/
|
||||
atomic_dec(&bdi->usage_cnt);
|
||||
wait_event(cgwb_release_wait, !atomic_read(&bdi->usage_cnt));
|
||||
/*
|
||||
* Grab back our reference so that we hold it when @bdi gets
|
||||
* re-registered.
|
||||
*/
|
||||
atomic_inc(&bdi->usage_cnt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -857,6 +862,8 @@ int bdi_register_owner(struct backing_dev_info *bdi, struct device *owner)
|
|||
MINOR(owner->devt));
|
||||
if (rc)
|
||||
return rc;
|
||||
/* Leaking owner reference... */
|
||||
WARN_ON(bdi->owner);
|
||||
bdi->owner = owner;
|
||||
get_device(owner);
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue