block: check disk exist before trying to add partition
authorYufen Yu <yuyufen@huawei.com>
Thu, 10 Jun 2021 02:32:41 +0000 (10:32 +0800)
committerJens Axboe <axboe@kernel.dk>
Thu, 1 Jul 2021 01:38:48 +0000 (19:38 -0600)
If disk have been deleted, we should return fail for ioctl
BLKPG_DEL_PARTITION. Otherwise, the directory /sys/class/block
may remain invalid symlinks file. The race as following:

blkdev_open
del_gendisk
    disk->flags &= ~GENHD_FL_UP;
    blk_drop_partitions
blkpg_ioctl
    bdev_add_partition
    add_partition
        device_add
    device_add_class_symlinks

ioctl may add_partition after del_gendisk() have tried to delete
partitions. Then, symlinks file will be created.

Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Yufen Yu <yuyufen@huawei.com>
Link: https://lore.kernel.org/r/20210610023241.3646241-1-yuyufen@huawei.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/partitions/core.c

index 347c56a..ed78cdf 100644 (file)
@@ -453,17 +453,26 @@ int bdev_add_partition(struct block_device *bdev, int partno,
                sector_t start, sector_t length)
 {
        struct block_device *part;
+       struct gendisk *disk = bdev->bd_disk;
+       int ret;
 
-       mutex_lock(&bdev->bd_disk->open_mutex);
-       if (partition_overlaps(bdev->bd_disk, start, length, -1)) {
-               mutex_unlock(&bdev->bd_disk->open_mutex);
-               return -EBUSY;
+       mutex_lock(&disk->open_mutex);
+       if (!(disk->flags & GENHD_FL_UP)) {
+               ret = -ENXIO;
+               goto out;
        }
 
-       part = add_partition(bdev->bd_disk, partno, start, length,
+       if (partition_overlaps(disk, start, length, -1)) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       part = add_partition(disk, partno, start, length,
                        ADDPART_FLAG_NONE, NULL);
-       mutex_unlock(&bdev->bd_disk->open_mutex);
-       return PTR_ERR_OR_ZERO(part);
+       ret = PTR_ERR_OR_ZERO(part);
+out:
+       mutex_unlock(&disk->open_mutex);
+       return ret;
 }
 
 int bdev_del_partition(struct block_device *bdev, int partno)