]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
loop: implement ->free_disk
authorChristoph Hellwig <hch@lst.de>
Wed, 30 Mar 2022 05:29:13 +0000 (07:29 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jun 2022 08:29:35 +0000 (10:29 +0200)
[ Upstream commit d2c7f56f8b5256d57f9e3fc7794c31361d43bdd9 ]

Ensure that the lo_device which is stored in the gendisk private
data is valid until the gendisk is freed.  Currently the loop driver
uses a lot of effort to make sure a device is not freed when it is
still in use, but to to fix a potential deadlock this will be relaxed
a bit soon.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20220330052917.2566582-12-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/block/loop.c

index a58595f5ee2c8f450a03b651fd6650ddc79f5e0a..ed7bec11948cd81456bceb155495875fbd4ae8b0 100644 (file)
@@ -1768,6 +1768,14 @@ out_unlock:
        mutex_unlock(&lo->lo_mutex);
 }
 
+static void lo_free_disk(struct gendisk *disk)
+{
+       struct loop_device *lo = disk->private_data;
+
+       mutex_destroy(&lo->lo_mutex);
+       kfree(lo);
+}
+
 static const struct block_device_operations lo_fops = {
        .owner =        THIS_MODULE,
        .open =         lo_open,
@@ -1776,6 +1784,7 @@ static const struct block_device_operations lo_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl = lo_compat_ioctl,
 #endif
+       .free_disk =    lo_free_disk,
 };
 
 /*
@@ -2090,15 +2099,14 @@ static void loop_remove(struct loop_device *lo)
 {
        /* Make this loop device unreachable from pathname. */
        del_gendisk(lo->lo_disk);
-       blk_cleanup_disk(lo->lo_disk);
+       blk_cleanup_queue(lo->lo_disk->queue);
        blk_mq_free_tag_set(&lo->tag_set);
 
        mutex_lock(&loop_ctl_mutex);
        idr_remove(&loop_index_idr, lo->lo_number);
        mutex_unlock(&loop_ctl_mutex);
-       /* There is no route which can find this loop device. */
-       mutex_destroy(&lo->lo_mutex);
-       kfree(lo);
+
+       put_disk(lo->lo_disk);
 }
 
 static void loop_probe(dev_t dev)