From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v5.17-rc1 commit e16e506ccd673a3a888a34f8f694698305840044 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6MRB5 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Unify the functionality that implements a partition rescan for a gendisk.
Signed-off-by: Christoph Hellwig hch@lst.de Link: https://lore.kernel.org/r/20211122130625.1136848-6-hch@lst.de Signed-off-by: Jens Axboe axboe@kernel.dk
Conflicts: - comit f0b870df80bc ("block: remove (__)blkdev_reread_part as an exported API") is not backported, and this patch doesn't remove (__)blkdev_reread_part apis as well. - commit b98bcd9ef2d6 ("block: reopen the device in blkdev_reread_part") is not backported, this patch switch blkdev_reread_part() to disk_scan_partitions() directly, which will reopen the device.
Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Hou Tao houtao1@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- block/blk.h | 1 + block/genhd.c | 20 +++++++++++++------- block/ioctl.c | 8 +++++++- 3 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/block/blk.h b/block/blk.h index 9269bb6b14f8..3f1c76b55336 100644 --- a/block/blk.h +++ b/block/blk.h @@ -214,6 +214,7 @@ unsigned int blk_plug_queued_count(struct request_queue *q); void blk_account_io_start(struct request *req, bool new_io); void blk_account_io_completion(struct request *req, unsigned int bytes); void blk_account_io_done(struct request *req, u64 now); +int disk_scan_partitions(struct gendisk *disk, fmode_t mode);
/* * EH timer and IO completion will both attempt to 'grab' the request, make diff --git a/block/genhd.c b/block/genhd.c index daf7211429c1..1f981753d4e7 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -639,20 +639,25 @@ static void register_disk(struct device *parent, struct gendisk *disk) } }
-static void disk_scan_partitions(struct gendisk *disk) +int disk_scan_partitions(struct gendisk *disk, fmode_t mode) { struct block_device *bdev; + int ret;
- if (!get_capacity(disk) || !disk_part_scan_enabled(disk)) - return; + if (!disk_part_scan_enabled(disk)) + return -EINVAL;
bdev = bdget_disk(disk, 0); if (!bdev) - return; + return -ENOMEM;
bdev->bd_invalidated = 1; - if (!blkdev_get(bdev, FMODE_READ, NULL)) - blkdev_put(bdev, FMODE_READ); + + ret = blkdev_get(bdev, mode, NULL); + if (!ret) + blkdev_put(bdev, mode); + + return ret; }
static void disk_init_partition(struct gendisk *disk) @@ -661,7 +666,8 @@ static void disk_init_partition(struct gendisk *disk) struct disk_part_iter piter; struct hd_struct *part;
- disk_scan_partitions(disk); + if (get_capacity(disk)) + disk_scan_partitions(disk, FMODE_READ);
/* announce disk after possible partitions are created */ dev_set_uevent_suppress(ddev, 0); diff --git a/block/ioctl.c b/block/ioctl.c index 93939b0cbf03..da8d09146385 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -10,6 +10,8 @@ #include <linux/pr.h> #include <linux/uaccess.h>
+#include "blk.h" + static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user *arg) { struct block_device *bdevp; @@ -597,7 +599,11 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, case BLKPG: return blkpg_ioctl(bdev, argp); case BLKRRPART: - return blkdev_reread_part(bdev); + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (bdev != bdev->bd_contains) + return -EINVAL; + return disk_scan_partitions(bdev->bd_disk, mode & ~FMODE_EXCL); case BLKGETSIZE: size = i_size_read(bdev->bd_inode); if ((size >> 9) > ~0UL)