Skip to content

Commit 752863b

Browse files
Christoph Hellwigaxboe
authored andcommitted
block: propagate partition scanning errors to the BLKRRPART ioctl
Commit 4601b4b ("block: reopen the device in blkdev_reread_part") lost the propagation of I/O errors from the low-level read of the partition table to the user space caller of the BLKRRPART. Apparently some user space relies on, so restore the propagation. This isn't exactly pretty as other block device open calls explicitly do not are about these errors, so add a new BLK_OPEN_STRICT_SCAN to opt into the error propagation. Fixes: 4601b4b ("block: reopen the device in blkdev_reread_part") Reported-by: Saranya Muruganandam <saranyamohan@google.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com> Reviewed-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com> Tested-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com> Link: https://lore.kernel.org/r/20240417144743.2277601-1-hch@lst.de Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 3ec4848 commit 752863b

File tree

3 files changed

+23
-11
lines changed

3 files changed

+23
-11
lines changed

block/bdev.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,14 @@ static void blkdev_flush_mapping(struct block_device *bdev)
652652
bdev_write_inode(bdev);
653653
}
654654

655+
static void blkdev_put_whole(struct block_device *bdev)
656+
{
657+
if (atomic_dec_and_test(&bdev->bd_openers))
658+
blkdev_flush_mapping(bdev);
659+
if (bdev->bd_disk->fops->release)
660+
bdev->bd_disk->fops->release(bdev->bd_disk);
661+
}
662+
655663
static int blkdev_get_whole(struct block_device *bdev, blk_mode_t mode)
656664
{
657665
struct gendisk *disk = bdev->bd_disk;
@@ -670,20 +678,21 @@ static int blkdev_get_whole(struct block_device *bdev, blk_mode_t mode)
670678

671679
if (!atomic_read(&bdev->bd_openers))
672680
set_init_blocksize(bdev);
673-
if (test_bit(GD_NEED_PART_SCAN, &disk->state))
674-
bdev_disk_changed(disk, false);
675681
atomic_inc(&bdev->bd_openers);
682+
if (test_bit(GD_NEED_PART_SCAN, &disk->state)) {
683+
/*
684+
* Only return scanning errors if we are called from contexts
685+
* that explicitly want them, e.g. the BLKRRPART ioctl.
686+
*/
687+
ret = bdev_disk_changed(disk, false);
688+
if (ret && (mode & BLK_OPEN_STRICT_SCAN)) {
689+
blkdev_put_whole(bdev);
690+
return ret;
691+
}
692+
}
676693
return 0;
677694
}
678695

679-
static void blkdev_put_whole(struct block_device *bdev)
680-
{
681-
if (atomic_dec_and_test(&bdev->bd_openers))
682-
blkdev_flush_mapping(bdev);
683-
if (bdev->bd_disk->fops->release)
684-
bdev->bd_disk->fops->release(bdev->bd_disk);
685-
}
686-
687696
static int blkdev_get_part(struct block_device *part, blk_mode_t mode)
688697
{
689698
struct gendisk *disk = part->bd_disk;

block/ioctl.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,8 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
563563
return -EACCES;
564564
if (bdev_is_partition(bdev))
565565
return -EINVAL;
566-
return disk_scan_partitions(bdev->bd_disk, mode);
566+
return disk_scan_partitions(bdev->bd_disk,
567+
mode | BLK_OPEN_STRICT_SCAN);
567568
case BLKTRACESTART:
568569
case BLKTRACESTOP:
569570
case BLKTRACETEARDOWN:

include/linux/blkdev.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ typedef unsigned int __bitwise blk_mode_t;
128128
#define BLK_OPEN_WRITE_IOCTL ((__force blk_mode_t)(1 << 4))
129129
/* open is exclusive wrt all other BLK_OPEN_WRITE opens to the device */
130130
#define BLK_OPEN_RESTRICT_WRITES ((__force blk_mode_t)(1 << 5))
131+
/* return partition scanning errors */
132+
#define BLK_OPEN_STRICT_SCAN ((__force blk_mode_t)(1 << 6))
131133

132134
struct gendisk {
133135
/*

0 commit comments

Comments
 (0)