diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-11-25 22:37:01 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-11-25 22:37:01 +0300 |
commit | 7e5192b93c3b8661791f65f0d477d0da234ca202 (patch) | |
tree | 31a2918cda1342c216d8eace807b7716e5fe4f9a /fs/block_dev.c | |
parent | 464a47f45d2ae2db859f0e7c128b5f01aff19a53 (diff) | |
parent | 979c690d9a017db14b7759a099478e3faad991ac (diff) | |
download | linux-7e5192b93c3b8661791f65f0d477d0da234ca202.tar.xz |
Merge tag 'for-5.5/disk-revalidate-20191122' of git://git.kernel.dk/linux-block
Pull disk revalidation updates from Jens Axboe:
"This continues the work that Jan Kara started to thoroughly cleanup
and consolidate how we handle rescans and revalidations"
* tag 'for-5.5/disk-revalidate-20191122' of git://git.kernel.dk/linux-block:
block: move clearing bd_invalidated into check_disk_size_change
block: remove (__)blkdev_reread_part as an exported API
block: fix bdev_disk_changed for non-partitioned devices
block: move rescan_partitions to fs/block_dev.c
block: merge invalidate_partitions into rescan_partitions
block: refactor rescan_partitions
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r-- | fs/block_dev.c | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index d612468ee66b..ee63c2732fa2 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1416,8 +1416,8 @@ static void flush_disk(struct block_device *bdev, bool kill_dirty) * and adjusts it if it differs. When shrinking the bdev size, its all caches * are freed. */ -void check_disk_size_change(struct gendisk *disk, struct block_device *bdev, - bool verbose) +static void check_disk_size_change(struct gendisk *disk, + struct block_device *bdev, bool verbose) { loff_t disk_size, bdev_size; @@ -1433,6 +1433,7 @@ void check_disk_size_change(struct gendisk *disk, struct block_device *bdev, if (bdev_size > disk_size) flush_disk(bdev, false); } + bdev->bd_invalidated = 0; } /** @@ -1462,7 +1463,6 @@ int revalidate_disk(struct gendisk *disk) mutex_lock(&bdev->bd_mutex); check_disk_size_change(disk, bdev, ret == 0); - bdev->bd_invalidated = 0; mutex_unlock(&bdev->bd_mutex); bdput(bdev); } @@ -1508,18 +1508,44 @@ EXPORT_SYMBOL(bd_set_size); static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part); -static void bdev_disk_changed(struct block_device *bdev, bool invalidate) +int bdev_disk_changed(struct block_device *bdev, bool invalidate) { - if (disk_part_scan_enabled(bdev->bd_disk)) { - if (invalidate) - invalidate_partitions(bdev->bd_disk, bdev); - else - rescan_partitions(bdev->bd_disk, bdev); + struct gendisk *disk = bdev->bd_disk; + int ret; + + lockdep_assert_held(&bdev->bd_mutex); + +rescan: + ret = blk_drop_partitions(disk, bdev); + if (ret) + return ret; + + if (invalidate) + set_capacity(disk, 0); + else if (disk->fops->revalidate_disk) + disk->fops->revalidate_disk(disk); + + check_disk_size_change(disk, bdev, !invalidate); + + if (get_capacity(disk)) { + ret = blk_add_partitions(disk, bdev); + if (ret == -EAGAIN) + goto rescan; } else { - check_disk_size_change(bdev->bd_disk, bdev, !invalidate); - bdev->bd_invalidated = 0; + /* + * Tell userspace that the media / partition table may have + * changed. + */ + kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE); } + + return ret; } +/* + * Only exported for for loop and dasd for historic reasons. Don't use in new + * code! + */ +EXPORT_SYMBOL_GPL(bdev_disk_changed); /* * bd_mutex locking: |