Commit c8276b95 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe
Browse files

block: split __blkdev_put



Split __blkdev_put into one helper for the whole device, and one for
partitions as well as another shared helper for flushing the block
device inode mapping.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarMing Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20210525061301.2242282-6-hch@lst.de


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent e54069ac
Loading
Loading
Loading
Loading
+32 −26
Original line number Diff line number Diff line
@@ -1234,7 +1234,13 @@ void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk)
EXPORT_SYMBOL_GPL(bd_unlink_disk_holder);
#endif

static void __blkdev_put(struct block_device *bdev, fmode_t mode);
static void blkdev_flush_mapping(struct block_device *bdev)
{
	WARN_ON_ONCE(bdev->bd_holders);
	sync_blockdev(bdev);
	kill_bdev(bdev);
	bdev_write_inode(bdev);
}

int bdev_disk_changed(struct block_device *bdev, bool invalidate)
{
@@ -1316,6 +1322,14 @@ static int blkdev_get_whole(struct block_device *bdev, fmode_t mode)
	return 0;;
}

static void blkdev_put_whole(struct block_device *bdev, fmode_t mode)
{
	if (!--bdev->bd_openers)
		blkdev_flush_mapping(bdev);
	if (bdev->bd_disk->fops->release)
		bdev->bd_disk->fops->release(bdev->bd_disk, mode);
}

static int blkdev_get_part(struct block_device *part, fmode_t mode)
{
	struct gendisk *disk = part->bd_disk;
@@ -1343,12 +1357,24 @@ static int blkdev_get_part(struct block_device *part, fmode_t mode)
	return 0;

out_blkdev_put:
	__blkdev_put(whole, mode);
	blkdev_put_whole(whole, mode);
out_put_whole:
	bdput(whole);
	return ret;
}

static void blkdev_put_part(struct block_device *part, fmode_t mode)
{
	struct block_device *whole = bdev_whole(part);

	if (--part->bd_openers)
		return;
	blkdev_flush_mapping(part);
	whole->bd_part_count--;
	blkdev_put_whole(whole, mode);
	bdput(whole);
}

struct block_device *blkdev_get_no_open(dev_t dev)
{
	struct block_device *bdev;
@@ -1542,29 +1568,6 @@ static int blkdev_open(struct inode * inode, struct file * filp)
	return 0;
}

static void __blkdev_put(struct block_device *bdev, fmode_t mode)
{
	struct gendisk *disk = bdev->bd_disk;
	struct block_device *victim = NULL;

	if (!--bdev->bd_openers) {
		WARN_ON_ONCE(bdev->bd_holders);
		sync_blockdev(bdev);
		kill_bdev(bdev);
		bdev_write_inode(bdev);
		if (bdev_is_partition(bdev))
			victim = bdev_whole(bdev);
	}

	if (!bdev_is_partition(bdev) && disk->fops->release)
		disk->fops->release(disk, mode);
	if (victim) {
		victim->bd_part_count--;
		__blkdev_put(victim, mode);
		bdput(victim);
	}
}

void blkdev_put(struct block_device *bdev, fmode_t mode)
{
	struct gendisk *disk = bdev->bd_disk;
@@ -1618,7 +1621,10 @@ void blkdev_put(struct block_device *bdev, fmode_t mode)
	 */
	disk_flush_events(disk, DISK_EVENT_MEDIA_CHANGE);

	__blkdev_put(bdev, mode);
	if (bdev_is_partition(bdev))
		blkdev_put_part(bdev, mode);
	else
		blkdev_put_whole(bdev, mode);
	mutex_unlock(&disk->open_mutex);

	blkdev_put_no_open(bdev);