summaryrefslogtreecommitdiff
path: root/fs/block_dev.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2021-05-25 08:12:58 +0200
committerJens Axboe <axboe@kernel.dk>2021-06-01 07:44:56 -0600
commitc8276b954d2dacbabe587c0421a9344529af5bad (patch)
tree3de1dcbc1cc6e11c05a9a08cfec60b3e1123463f /fs/block_dev.c
parente54069acac1a302c1adc26694963547f8b73c2b0 (diff)
downloadlwn-c8276b954d2dacbabe587c0421a9344529af5bad.tar.gz
lwn-c8276b954d2dacbabe587c0421a9344529af5bad.zip
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: Christoph Hellwig <hch@lst.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Ming Lei <ming.lei@redhat.com> Link: https://lore.kernel.org/r/20210525061301.2242282-6-hch@lst.de Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r--fs/block_dev.c58
1 files changed, 32 insertions, 26 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 43dce929e7ee..cd45b54e86b4 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -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 @@ done:
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);