From: Yu Kuai yukuai3@huawei.com
hulk inclusion category: bugfix bugzilla: 187345, https://gitee.com/openeuler/kernel/issues/I5KZZ0 CVE: NA
--------------------------------
Commit faf2662e328c ("block: fix that part scan is disabled in device_add_disk()") introduce a regression:
Test procedures: dmsetup create test --notable dmsetup remove test
Test result: dmsetup will stuck forever
Root cause: before: 1) dmsetup creat add_disk_add_disk_no_queue_reg() scan partitions uevent 2) blk_register_queue -> notable will not call this 3) dmsetup remove wait for uevent
after: 1) dmsetup creat add_disk_add_disk_no_queue_reg() 2) blk_register_queue() -> notable will not call this scan_partitions uevent 3) dmsetup remove wait for uevent -> impossible for notable
Fix the problem by moving scan_partitions and uevent from blk_register_queue() to the end of add_disk_add_disk_no_queue_reg().
Fixes: faf2662e328c ("block: fix that part scan is disabled in device_add_disk()") Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- block/blk-sysfs.c | 48 ----------------------------------------------- block/genhd.c | 43 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 48 deletions(-)
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 530f1bf36c87..30898a7855d7 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -881,42 +881,6 @@ struct kobj_type blk_queue_ktype = { .release = blk_release_queue, };
-static void disk_init_partition(struct gendisk *disk) -{ - struct device *ddev = disk_to_dev(disk); - struct block_device *bdev; - struct disk_part_iter piter; - struct hd_struct *part; - - /* No minors to use for partitions */ - if (!disk_part_scan_enabled(disk)) - goto exit; - - /* No such device (e.g., media were just removed) */ - if (!get_capacity(disk)) - goto exit; - - bdev = bdget_disk(disk, 0); - if (!bdev) - goto exit; - - bdev->bd_invalidated = 1; - if (blkdev_get(bdev, FMODE_READ, NULL)) - goto exit; - blkdev_put(bdev, FMODE_READ); - -exit: - /* announce disk after possible partitions are created */ - dev_set_uevent_suppress(ddev, 0); - kobject_uevent(&ddev->kobj, KOBJ_ADD); - - /* announce possible partitions */ - disk_part_iter_init(&piter, disk, 0); - while ((part = disk_part_iter_next(&piter))) - kobject_uevent(&part_to_dev(part)->kobj, KOBJ_ADD); - disk_part_iter_exit(&piter); -} - /** * blk_register_queue - register a block layer queue with sysfs * @disk: Disk of which the request queue should be registered with sysfs. @@ -972,21 +936,9 @@ int blk_register_queue(struct gendisk *disk) } }
- /* - * Set the flag at last, so that block devcie can't be opened - * before it's registration is done. - */ - disk->flags |= GENHD_FL_UP; ret = 0; unlock: mutex_unlock(&q->sysfs_lock); - /* - * Init partitions after releasing 'sysfs_lock', otherwise lockdep - * will be confused because it will treat 'bd_mutex' from different - * devices as the same lock. - */ - if (!ret) - disk_init_partition(disk);
/* * SCSI probing may synchronously create and destroy a lot of diff --git a/block/genhd.c b/block/genhd.c index 124f8d94584c..4a748603c881 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -639,6 +639,42 @@ static void register_disk(struct device *parent, struct gendisk *disk) } }
+static void disk_init_partition(struct gendisk *disk) +{ + struct device *ddev = disk_to_dev(disk); + struct block_device *bdev; + struct disk_part_iter piter; + struct hd_struct *part; + + /* No minors to use for partitions */ + if (!disk_part_scan_enabled(disk)) + goto exit; + + /* No such device (e.g., media were just removed) */ + if (!get_capacity(disk)) + goto exit; + + bdev = bdget_disk(disk, 0); + if (!bdev) + goto exit; + + bdev->bd_invalidated = 1; + if (blkdev_get(bdev, FMODE_READ, NULL)) + goto exit; + blkdev_put(bdev, FMODE_READ); + +exit: + /* announce disk after possible partitions are created */ + dev_set_uevent_suppress(ddev, 0); + kobject_uevent(&ddev->kobj, KOBJ_ADD); + + /* announce possible partitions */ + disk_part_iter_init(&piter, disk, 0); + while ((part = disk_part_iter_next(&piter))) + kobject_uevent(&part_to_dev(part)->kobj, KOBJ_ADD); + disk_part_iter_exit(&piter); +} + /** * __device_add_disk - add disk information to kernel list * @parent: parent device for the disk @@ -704,6 +740,13 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk,
disk_add_events(disk); blk_integrity_add(disk); + + /* + * Set the flag at last, so that block devcie can't be opened + * before it's registration is done. + */ + disk->flags |= GENHD_FL_UP; + disk_init_partition(disk); }
void device_add_disk(struct device *parent, struct gendisk *disk)