Add/del gendisk code is actually reader of 'nr_hw_queues' in case of blk-mq: - debugfs / hctx sysfs register - setup scheduler since ->sched_tags depends on hctx, which relies on 'nr_hw_queues' Add & pass 'struct gendisk_data' to add/del disk helper and prepare for retrying add/del disk when updating nr_hw_queues is in-progress. Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxx> --- block/genhd.c | 105 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 67 insertions(+), 38 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index c2bd86cd09de..4370c5be1f34 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -33,6 +33,13 @@ #include "blk-rq-qos.h" #include "blk-cgroup.h" +struct gendisk_data { + struct gendisk *disk; + struct device *parent; + const struct attribute_group **groups; + struct fwnode_handle *fwnode; +}; + static struct kobject *block_depr; /* @@ -389,21 +396,9 @@ int disk_scan_partitions(struct gendisk *disk, blk_mode_t mode) return ret; } -/** - * add_disk_fwnode - add disk information to kernel list with fwnode - * @parent: parent device for the disk - * @disk: per-device partitioning information - * @groups: Additional per-device sysfs groups - * @fwnode: attached disk fwnode - * - * This function registers the partitioning information in @disk - * with the kernel. Also attach a fwnode to the disk device. - */ -int __must_check add_disk_fwnode(struct device *parent, struct gendisk *disk, - const struct attribute_group **groups, - struct fwnode_handle *fwnode) - +static int __add_disk_fwnode(struct gendisk_data *data) { + struct gendisk *disk = data->disk; struct device *ddev = disk_to_dev(disk); int ret; @@ -463,11 +458,11 @@ int __must_check add_disk_fwnode(struct device *parent, struct gendisk *disk, /* delay uevents, until we scanned partition table */ dev_set_uevent_suppress(ddev, 1); - ddev->parent = parent; - ddev->groups = groups; + ddev->parent = data->parent; + ddev->groups = data->groups; dev_set_name(ddev, "%s", disk->disk_name); - if (fwnode) - device_set_node(ddev, fwnode); + if (data->fwnode) + device_set_node(ddev, data->fwnode); if (!(disk->flags & GENHD_FL_HIDDEN)) ddev->devt = MKDEV(disk->major, disk->first_minor); ret = device_add(ddev); @@ -572,6 +567,30 @@ int __must_check add_disk_fwnode(struct device *parent, struct gendisk *disk, } return ret; } + +/** + * add_disk_fwnode - add disk information to kernel list with fwnode + * @parent: parent device for the disk + * @disk: per-device partitioning information + * @groups: Additional per-device sysfs groups + * @fwnode: attached disk fwnode + * + * This function registers the partitioning information in @disk + * with the kernel. Also attach a fwnode to the disk device. + */ +int __must_check add_disk_fwnode(struct device *parent, struct gendisk *disk, + const struct attribute_group **groups, + struct fwnode_handle *fwnode) +{ + struct gendisk_data data = { + .disk = disk, + .parent = parent, + .groups = groups, + .fwnode = fwnode, + }; + + return __add_disk_fwnode(&data); +} EXPORT_SYMBOL_GPL(add_disk_fwnode); /** @@ -652,27 +671,9 @@ void blk_mark_disk_dead(struct gendisk *disk) } EXPORT_SYMBOL_GPL(blk_mark_disk_dead); -/** - * del_gendisk - remove the gendisk - * @disk: the struct gendisk to remove - * - * Removes the gendisk and all its associated resources. This deletes the - * partitions associated with the gendisk, and unregisters the associated - * request_queue. - * - * This is the counter to the respective __device_add_disk() call. - * - * The final removal of the struct gendisk happens when its refcount reaches 0 - * with put_disk(), which should be called after del_gendisk(), if - * __device_add_disk() was used. - * - * Drivers exist which depend on the release of the gendisk to be synchronous, - * it should not be deferred. - * - * Context: can sleep - */ -void del_gendisk(struct gendisk *disk) +static void __del_gendisk(struct gendisk_data *data) { + struct gendisk *disk = data->disk; struct request_queue *q = disk->queue; struct block_device *part; unsigned long idx; @@ -766,6 +767,34 @@ void del_gendisk(struct gendisk *disk) } EXPORT_SYMBOL(del_gendisk); +/** + * del_gendisk - remove the gendisk + * @disk: the struct gendisk to remove + * + * Removes the gendisk and all its associated resources. This deletes the + * partitions associated with the gendisk, and unregisters the associated + * request_queue. + * + * This is the counter to the respective __device_add_disk() call. + * + * The final removal of the struct gendisk happens when its refcount reaches 0 + * with put_disk(), which should be called after del_gendisk(), if + * __device_add_disk() was used. + * + * Drivers exist which depend on the release of the gendisk to be synchronous, + * it should not be deferred. + * + * Context: can sleep + */ +void del_gendisk(struct gendisk *disk) +{ + struct gendisk_data data = { + .disk = disk, + }; + + __del_gendisk(&data); +} + /** * invalidate_disk - invalidate the disk * @disk: the struct gendisk to invalidate -- 2.47.0