aboutsummaryrefslogtreecommitdiffstats
path: root/mm/backing-dev.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2017-03-08 11:48:31 -0500
committerJens Axboe <axboe@fb.com>2017-03-08 12:55:17 -0500
commitb6f8fec4448aa52a8c36a392aa1ca2ea99acd460 (patch)
tree659041df7070189896307ebe2bee2cf2b6d713b7 /mm/backing-dev.c
parentb0bfdfc2bf7fa85317824c6a389fc373dfcef5bc (diff)
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 commit 165a5e22fafb "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. After 165a5e22fafb 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: 165a5e22fafb127ecb5914e12e8c32a1f0d3f820 Signed-off-by: Jan Kara <jack@suse.cz> Tested-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'mm/backing-dev.c')
-rw-r--r--mm/backing-dev.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 6d861d090e9f..6ac932210f56 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -710,6 +710,11 @@ static void cgwb_bdi_destroy(struct backing_dev_info *bdi)
710 */ 710 */
711 atomic_dec(&bdi->usage_cnt); 711 atomic_dec(&bdi->usage_cnt);
712 wait_event(cgwb_release_wait, !atomic_read(&bdi->usage_cnt)); 712 wait_event(cgwb_release_wait, !atomic_read(&bdi->usage_cnt));
713 /*
714 * Grab back our reference so that we hold it when @bdi gets
715 * re-registered.
716 */
717 atomic_inc(&bdi->usage_cnt);
713} 718}
714 719
715/** 720/**
@@ -857,6 +862,8 @@ int bdi_register_owner(struct backing_dev_info *bdi, struct device *owner)
857 MINOR(owner->devt)); 862 MINOR(owner->devt));
858 if (rc) 863 if (rc)
859 return rc; 864 return rc;
865 /* Leaking owner reference... */
866 WARN_ON(bdi->owner);
860 bdi->owner = owner; 867 bdi->owner = owner;
861 get_device(owner); 868 get_device(owner);
862 return 0; 869 return 0;