diff options
author | Christoph Hellwig <hch@lst.de> | 2021-07-22 09:53:58 +0200 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2021-08-02 21:37:28 +0200 |
commit | 9d3b8813895d737fcef4ec8df518f67e5cc381b8 (patch) | |
tree | 13db699bd15205a45a9b571c4d8643000f9b61dc /block/partitions | |
parent | block: allocate bd_meta_info later in add_partitions (diff) | |
download | linux-9d3b8813895d737fcef4ec8df518f67e5cc381b8.tar.xz linux-9d3b8813895d737fcef4ec8df518f67e5cc381b8.zip |
block: change the refcounting for partitions
Instead of acquiring an inode reference on open make sure partitions
always hold device model references to the disk while alive, and switch
open to grab only a device model reference to the opened block device.
If that is a partition the disk reference is transitively held by the
partition already.
Link: https://lore.kernel.org/r/20210722075402.983367-6-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/partitions')
-rw-r--r-- | block/partitions/core.c | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/block/partitions/core.c b/block/partitions/core.c index 09c58a110a89..4f7a1a9cd544 100644 --- a/block/partitions/core.c +++ b/block/partitions/core.c @@ -261,6 +261,7 @@ static void part_release(struct device *dev) { if (MAJOR(dev->devt) == BLOCK_EXT_MAJOR) blk_free_ext_minor(MINOR(dev->devt)); + put_disk(dev_to_bdev(dev)->bd_disk); bdput(dev_to_bdev(dev)); } @@ -349,9 +350,13 @@ static struct block_device *add_partition(struct gendisk *disk, int partno, if (xa_load(&disk->part_tbl, partno)) return ERR_PTR(-EBUSY); + /* ensure we always have a reference to the whole disk */ + get_device(disk_to_dev(disk)); + + err = -ENOMEM; bdev = bdev_alloc(disk, partno); if (!bdev) - return ERR_PTR(-ENOMEM); + goto out_put_disk; bdev->bd_start_sect = start; bdev_set_nr_sectors(bdev, len); @@ -420,6 +425,8 @@ out_del: device_del(pdev); out_put: put_device(pdev); +out_put_disk: + put_disk(disk); return ERR_PTR(err); } |