]> git.dujemihanovic.xyz Git - linux.git/commitdiff
block: delay freeing the gendisk
authorChristoph Hellwig <hch@lst.de>
Thu, 22 Jul 2021 07:53:54 +0000 (09:53 +0200)
committerJens Axboe <axboe@kernel.dk>
Wed, 28 Jul 2021 01:35:47 +0000 (19:35 -0600)
blkdev_get_no_open acquires a reference to the block_device through
the block device inode and then tries to acquire a device model
reference to the gendisk.  But at this point the disk migh already
be freed (although the race is free).  Fix this by only freeing the
gendisk from the whole device bdevs ->free_inode callback as well.

Fixes: 22ae8ce8b892 ("block: simplify bdev/disk lookup in blkdev_get")
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20210722075402.983367-2-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/genhd.c
fs/block_dev.c

index af4d2ab4a633542bb16e2aa6d1a2b0c062c1513b..298ee78c1bdac63bc3378b2a97dd6101cd649413 100644 (file)
@@ -1079,10 +1079,9 @@ static void disk_release(struct device *dev)
        disk_release_events(disk);
        kfree(disk->random);
        xa_destroy(&disk->part_tbl);
-       bdput(disk->part0);
        if (test_bit(GD_QUEUE_REF, &disk->state) && disk->queue)
                blk_put_queue(disk->queue);
-       kfree(disk);
+       bdput(disk->part0);     /* frees the disk */
 }
 struct class block_class = {
        .name           = "block",
index ca8bf1869ca85e5949d22386851da51050877621..a38b0f33211cd0a6e562d1bbe14aa8f93044973f 100644 (file)
@@ -812,6 +812,8 @@ static void bdev_free_inode(struct inode *inode)
        free_percpu(bdev->bd_stats);
        kfree(bdev->bd_meta_info);
 
+       if (!bdev_is_partition(bdev))
+               kfree(bdev->bd_disk);
        kmem_cache_free(bdev_cachep, BDEV_I(inode));
 }