Christoph Hellwig (9): md: extend disks_mutex coverage md: convert to blk_alloc_disk/blk_cleanup_disk md: add the bitmap group to the default groups for the md kobject md: properly unwind when failing to add the kobject in md_alloc md: fix mddev->kobj lifetime md: fix error handling in md_alloc md: factor out a mddev_alloc_unit helper from mddev_find md: refactor mddev_find_or_alloc md: do not return existing mddevs from mddev_find_or_alloc
Luis Chamberlain (1): md: add error handling support for add_disk()
drivers/md/md.c | 231 +++++++++++++++++++++++++----------------------- 1 file changed, 121 insertions(+), 110 deletions(-)
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v5.16-rc1 commit 94f3cd7d832c28681f1dea54b4dd8606e5e2bc75 category: bugfix bugzilla: 188015, https://gitee.com/openeuler/kernel/issues/I81XCK
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/commit/?id=...
--------------------------------
disks_mutex is intended to serialize md_alloc. Extended it to also cover the kobject_uevent call and getting the sysfs dirent to help reducing error handling complexity.
Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Song Liu songliubraving@fb.com Signed-off-by: Jens Axboe axboe@kernel.dk
Conflict: drivers/md/md.c
Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index b9065f26d3d2..eb5a886b3ca4 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5831,12 +5831,12 @@ static int md_alloc(dev_t dev, char *name) sysfs_create_group(&mddev->kobj, &md_bitmap_group)) pr_debug("pointless warning\n"); abort: - mutex_unlock(&disks_mutex); if (!error && mddev->kobj.sd) { kobject_uevent(&mddev->kobj, KOBJ_ADD); mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, "array_state"); mddev->sysfs_level = sysfs_get_dirent_safe(mddev->kobj.sd, "level"); } + mutex_unlock(&disks_mutex); mddev_put(mddev); return error; }
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v5.14-rc1 commit 0f1d2e0643c544df50dbc436da930201218fa1e2 category: bugfix bugzilla: 188733, https://gitee.com/openeuler/kernel/issues/I81XCK
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
-------------------------------------------------
Convert the md driver to use the blk_alloc_disk and blk_cleanup_disk helpers to simplify gendisk and request_queue allocation.
Signed-off-by: Christoph Hellwig hch@lst.de Reviewed-by: Hannes Reinecke hare@suse.de Reviewed-by: Ulf Hansson ulf.hansson@linaro.org Link: https://lore.kernel.org/r/20210521055116.1053587-15-hch@lst.de Signed-off-by: Jens Axboe axboe@kernel.dk
Conflict: drivers/md/md.c the merging order of commit ad3fc798800f ("md: revert io stats accounting") is inconsistent.
Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index eb5a886b3ca4..96e3807c4881 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5677,12 +5677,10 @@ static void md_free(struct kobject *ko) if (mddev->sysfs_level) sysfs_put(mddev->sysfs_level);
- if (mddev->gendisk) + if (mddev->gendisk) { del_gendisk(mddev->gendisk); - if (mddev->queue) - blk_cleanup_queue(mddev->queue); - if (mddev->gendisk) - put_disk(mddev->gendisk); + blk_cleanup_disk(mddev->gendisk); + } percpu_ref_exit(&mddev->writes_pending);
bioset_exit(&mddev->bio_set); @@ -5785,20 +5783,13 @@ static int md_alloc(dev_t dev, char *name) mddev->hold_active = UNTIL_STOP;
error = -ENOMEM; - mddev->queue = blk_alloc_queue(NUMA_NO_NODE); - if (!mddev->queue) + disk = blk_alloc_disk(NUMA_NO_NODE); + if (!disk) goto abort;
- blk_set_stacking_limits(&mddev->queue->limits); - - disk = alloc_disk(1 << shift); - if (!disk) { - blk_cleanup_queue(mddev->queue); - mddev->queue = NULL; - goto abort; - } disk->major = MAJOR(mddev->unit); disk->first_minor = unit << shift; + disk->minors = 1 << shift; if (name) strcpy(disk->disk_name, name); else if (partitioned) @@ -5807,7 +5798,9 @@ static int md_alloc(dev_t dev, char *name) sprintf(disk->disk_name, "md%d", unit); disk->fops = &md_fops; disk->private_data = mddev; - disk->queue = mddev->queue; + + mddev->queue = disk->queue; + blk_set_stacking_limits(&mddev->queue->limits); blk_queue_write_cache(mddev->queue, true, true); /* Allow extended partitions. This makes the * 'mdp' device redundant, but we can't really
From: Luis Chamberlain mcgrof@kernel.org
mainline inclusion from mainline-v5.16-rc1 commit 9be68dd7ac0e13be2ac57770c1f921d6b3294c6e category: bugfix bugzilla: 188733, https://gitee.com/openeuler/kernel/issues/I81XCK
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
-------------------------------------------------
We never checked for errors on add_disk() as this function returned void. Now that this is fixed, use the shiny new error handling.
We just do the unwinding of what was not done before, and are sure to unlock prior to bailing.
Signed-off-by: Luis Chamberlain mcgrof@kernel.org Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Song Liu songliubraving@fb.com Signed-off-by: Jens Axboe axboe@kernel.dk
Conflict: drivers/md/md.c use add_disk_safe().
Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index 96e3807c4881..188367b56b02 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5809,7 +5809,11 @@ static int md_alloc(dev_t dev, char *name) disk->flags |= GENHD_FL_EXT_DEVT; disk->events |= DISK_EVENT_MEDIA_CHANGE; mddev->gendisk = disk; - add_disk(disk); + error = add_disk_safe(disk); + if (error) { + blk_cleanup_disk(disk); + goto abort; + }
error = kobject_add(&mddev->kobj, &disk_to_dev(disk)->kobj, "%s", "md"); if (error) {
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v5.16-rc1 commit 51238e7fbd6182e36dbc093c92ae93142c57c0f5 category: bugfix bugzilla: 188733, https://gitee.com/openeuler/kernel/issues/I81XCK
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
-------------------------------------------------
Replace the deprecated default_attrs with the default_groups mechanism, and add the always visible bitmap group to the groups created add kobject_add time.
Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Song Liu songliubraving@fb.com Signed-off-by: Jens Axboe axboe@kernel.dk
Conflict: drivers/md/md.c the merging order of commit 94f3cd7d832c ("md: extend disks_mutex coverage") is inconsistent.
Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index 188367b56b02..7e2ce1edfafb 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5600,6 +5600,10 @@ static struct attribute *md_default_attrs[] = { NULL, };
+static const struct attribute_group md_default_group = { + .attrs = md_default_attrs, +}; + static struct attribute *md_redundancy_attrs[] = { &md_scan_mode.attr, &md_last_scan_mode.attr, @@ -5622,6 +5626,12 @@ static struct attribute_group md_redundancy_group = { .attrs = md_redundancy_attrs, };
+static const struct attribute_group *md_attr_groups[] = { + &md_default_group, + &md_bitmap_group, + NULL, +}; + static ssize_t md_attr_show(struct kobject *kobj, struct attribute *attr, char *page) { @@ -5696,7 +5706,7 @@ static const struct sysfs_ops md_sysfs_ops = { static struct kobj_type md_ktype = { .release = md_free, .sysfs_ops = &md_sysfs_ops, - .default_attrs = md_default_attrs, + .default_groups = md_attr_groups, };
int mdp_major = 0; @@ -5705,7 +5715,6 @@ static void mddev_delayed_delete(struct work_struct *ws) { struct mddev *mddev = container_of(ws, struct mddev, del_work);
- sysfs_remove_group(&mddev->kobj, &md_bitmap_group); kobject_del(&mddev->kobj); kobject_put(&mddev->kobj); } @@ -5824,9 +5833,6 @@ static int md_alloc(dev_t dev, char *name) disk->disk_name); error = 0; } - if (mddev->kobj.sd && - sysfs_create_group(&mddev->kobj, &md_bitmap_group)) - pr_debug("pointless warning\n"); abort: if (!error && mddev->kobj.sd) { kobject_uevent(&mddev->kobj, KOBJ_ADD);
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v5.16-rc1 commit 7ad1069166c0ccdd572d27e01cc7f7f84477df1e category: bugfix bugzilla: 188733, https://gitee.com/openeuler/kernel/issues/I81XCK
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
-------------------------------------------------
Add proper error handling to delete the gendisk when failing to add the md kobject and clean up the error unwinding in general.
Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Song Liu songliubraving@fb.com Signed-off-by: Jens Axboe axboe@kernel.dk
Conflict: drivers/md/md.c Commit ("0d809b3837a0 md: do not return existing mddevs from mddev_find_or_alloc") has not been merged, which remove the check of mddev->gendisk. We will not merge it since it is not abount error handle and relies on other patchs. Just goto out_unlock_disks_mutex if mddev->gendisk exists to fix conflict.
Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index 7e2ce1edfafb..cdc801c07bfc 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5769,7 +5769,7 @@ static int md_alloc(dev_t dev, char *name) mutex_lock(&disks_mutex); error = -EEXIST; if (mddev->gendisk) - goto abort; + goto out_unlock_disks_mutex;
if (name && !dev) { /* Need to ensure that 'name' is not a duplicate. @@ -5781,7 +5781,7 @@ static int md_alloc(dev_t dev, char *name) if (mddev2->gendisk && strcmp(mddev2->gendisk->disk_name, name) == 0) { spin_unlock(&all_mddevs_lock); - goto abort; + goto out_unlock_disks_mutex; } spin_unlock(&all_mddevs_lock); } @@ -5794,7 +5794,7 @@ static int md_alloc(dev_t dev, char *name) error = -ENOMEM; disk = blk_alloc_disk(NUMA_NO_NODE); if (!disk) - goto abort; + goto out_unlock_disks_mutex;
disk->major = MAJOR(mddev->unit); disk->first_minor = unit << shift; @@ -5819,26 +5819,23 @@ static int md_alloc(dev_t dev, char *name) disk->events |= DISK_EVENT_MEDIA_CHANGE; mddev->gendisk = disk; error = add_disk_safe(disk); - if (error) { - blk_cleanup_disk(disk); - goto abort; - } + if (error) + goto out_cleanup_disk;
error = kobject_add(&mddev->kobj, &disk_to_dev(disk)->kobj, "%s", "md"); - if (error) { - /* This isn't possible, but as kobject_init_and_add is marked - * __must_check, we must do something with the result - */ - pr_debug("md: cannot register %s/md - name in use\n", - disk->disk_name); - error = 0; - } - abort: - if (!error && mddev->kobj.sd) { - kobject_uevent(&mddev->kobj, KOBJ_ADD); - mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, "array_state"); - mddev->sysfs_level = sysfs_get_dirent_safe(mddev->kobj.sd, "level"); - } + if (error) + goto out_del_gendisk; + + kobject_uevent(&mddev->kobj, KOBJ_ADD); + mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, "array_state"); + mddev->sysfs_level = sysfs_get_dirent_safe(mddev->kobj.sd, "level"); + goto out_unlock_disks_mutex; + +out_del_gendisk: + del_gendisk(disk); +out_cleanup_disk: + blk_cleanup_disk(disk); +out_unlock_disks_mutex: mutex_unlock(&disks_mutex); mddev_put(mddev); return error;
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v6.0-rc1 commit ca39f7502425d437cbf83d29d99b43bd61342858 category: bugfix bugzilla: 188733, https://gitee.com/openeuler/kernel/issues/I81XCK
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
-------------------------------------------------
Once a kobject is initialized, the containing object should not be directly freed. So delay initialization until it is added. Also remove the kobject_del call as the last put will remove the kobject as well. The explicitly delete isn't needed here, and dropping it will simplify further fixes.
With this md_free now does not need to check that ->gendisk is non-NULL as it is always set by the time that kobject_init is called on mddev->kobj.
Signed-off-by: Christoph Hellwig hch@lst.de Reviewed-by: Logan Gunthorpe logang@deltatee.com Reviewed-by: Hannes Reinecke hare@suse.de Signed-off-by: Song Liu song@kernel.org Signed-off-by: Jens Axboe axboe@kernel.dk
Conflict: Commit 8b9ab6266204 ("block: remove blk_cleanup_disk") change blk_cleanup_disk() to put_disk(). Keep using blk_cleanup_disk() here.
Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index cdc801c07bfc..33905999bb05 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -687,7 +687,6 @@ static void md_safemode_timeout(struct timer_list *t);
void mddev_init(struct mddev *mddev) { - kobject_init(&mddev->kobj, &md_ktype); mutex_init(&mddev->open_mutex); mutex_init(&mddev->reconfig_mutex); mutex_init(&mddev->bitmap_info.mutex); @@ -5687,10 +5686,9 @@ static void md_free(struct kobject *ko) if (mddev->sysfs_level) sysfs_put(mddev->sysfs_level);
- if (mddev->gendisk) { - del_gendisk(mddev->gendisk); - blk_cleanup_disk(mddev->gendisk); - } + del_gendisk(mddev->gendisk); + blk_cleanup_disk(mddev->gendisk); + percpu_ref_exit(&mddev->writes_pending);
bioset_exit(&mddev->bio_set); @@ -5715,7 +5713,6 @@ static void mddev_delayed_delete(struct work_struct *ws) { struct mddev *mddev = container_of(ws, struct mddev, del_work);
- kobject_del(&mddev->kobj); kobject_put(&mddev->kobj); }
@@ -5822,6 +5819,7 @@ static int md_alloc(dev_t dev, char *name) if (error) goto out_cleanup_disk;
+ kobject_init(&mddev->kobj, &md_ktype); error = kobject_add(&mddev->kobj, &disk_to_dev(disk)->kobj, "%s", "md"); if (error) goto out_del_gendisk;
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v6.0-rc1 commit c57094a6e1ed5dd2d6401f79b8e6da34dd28f959 category: bugfix bugzilla: 188733, https://gitee.com/openeuler/kernel/issues/I81XCK
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
-------------------------------------------------
Error handling in md_alloc is a mess. Untangle it to just free the mddev directly before add_disk is called and thus the gendisk is globally visible. After that clear the hold flag and let the mddev_put take care of cleaning up the mddev through the usual mechanisms.
Fixes: 5e55e2f5fc95 ("[PATCH] md: convert compile time warnings into runtime warnings") Fixes: 9be68dd7ac0e ("md: add error handling support for add_disk()") Fixes: 7ad1069166c0 ("md: properly unwind when failing to add the kobject in md_alloc") Signed-off-by: Christoph Hellwig hch@lst.de Reviewed-by: Logan Gunthorpe logang@deltatee.com Reviewed-by: Hannes Reinecke hare@suse.de Signed-off-by: Song Liu song@kernel.org Signed-off-by: Jens Axboe axboe@kernel.dk
Conflict: drivers/md/md.c Commit 0d809b3837a0 ("md: do not return existing mddevs from mddev_find_or_alloc") introduce mddev_alloc(). Fix conflict by dropping the error handle of it and label out_unlock, goto done if mddev->gendisk exists. Commit 8b9ab6266204 ("block: remove blk_cleanup_disk") change blk_cleanup_disk() to put_disk(). Keep using blk_cleanup_disk(),
Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.c | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index 33905999bb05..bf9a08a9af8a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5731,6 +5731,15 @@ int mddev_init_writes_pending(struct mddev *mddev) } EXPORT_SYMBOL_GPL(mddev_init_writes_pending);
+static void mddev_free(struct mddev *mddev) +{ + spin_lock(&all_mddevs_lock); + list_del(&mddev->all_mddevs); + spin_unlock(&all_mddevs_lock); + + kfree(mddev); +} + static int md_alloc(dev_t dev, char *name) { /* @@ -5766,7 +5775,7 @@ static int md_alloc(dev_t dev, char *name) mutex_lock(&disks_mutex); error = -EEXIST; if (mddev->gendisk) - goto out_unlock_disks_mutex; + goto done;
if (name && !dev) { /* Need to ensure that 'name' is not a duplicate. @@ -5778,7 +5787,7 @@ static int md_alloc(dev_t dev, char *name) if (mddev2->gendisk && strcmp(mddev2->gendisk->disk_name, name) == 0) { spin_unlock(&all_mddevs_lock); - goto out_unlock_disks_mutex; + goto out_free_mddev; } spin_unlock(&all_mddevs_lock); } @@ -5791,7 +5800,7 @@ static int md_alloc(dev_t dev, char *name) error = -ENOMEM; disk = blk_alloc_disk(NUMA_NO_NODE); if (!disk) - goto out_unlock_disks_mutex; + goto out_free_mddev;
disk->major = MAJOR(mddev->unit); disk->first_minor = unit << shift; @@ -5817,26 +5826,35 @@ static int md_alloc(dev_t dev, char *name) mddev->gendisk = disk; error = add_disk_safe(disk); if (error) - goto out_cleanup_disk; + goto out_put_disk;
kobject_init(&mddev->kobj, &md_ktype); error = kobject_add(&mddev->kobj, &disk_to_dev(disk)->kobj, "%s", "md"); - if (error) - goto out_del_gendisk; + if (error) { + /* + * The disk is already live at this point. Clear the hold flag + * and let mddev_put take care of the deletion, as it isn't any + * different from a normal close on last release now. + */ + mddev->hold_active = 0; + goto done; + }
kobject_uevent(&mddev->kobj, KOBJ_ADD); mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, "array_state"); mddev->sysfs_level = sysfs_get_dirent_safe(mddev->kobj.sd, "level"); - goto out_unlock_disks_mutex;
-out_del_gendisk: - del_gendisk(disk); -out_cleanup_disk: - blk_cleanup_disk(disk); -out_unlock_disks_mutex: +done: mutex_unlock(&disks_mutex); mddev_put(mddev); return error; + +out_put_disk: + blk_cleanup_disk(disk); +out_free_mddev: + mddev_free(mddev); + mutex_unlock(&disks_mutex); + return error; }
static struct kobject *md_probe(dev_t dev, int *part, void *data)
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v5.13-rc1 commit 85c8c3c1f8d9e31f626c93435dd91c2f85603e07 category: bugfix bugzilla: 189427, https://gitee.com/openeuler/kernel/issues/I8O6NL
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
-------------------------------------------------
Split out a self contained helper to find a free minor for the md "unit" number.
Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Song Liu song@kernel.org Signed-off-by: Li Lingfeng lilingfeng3@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.c | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index bf9a08a9af8a..ba4c7d6505da 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -722,6 +722,27 @@ static struct mddev *mddev_find_locked(dev_t unit) return NULL; }
+/* find an unused unit number */ +static dev_t mddev_alloc_unit(void) +{ + static int next_minor = 512; + int start = next_minor; + bool is_free = 0; + dev_t dev = 0; + + while (!is_free) { + dev = MKDEV(MD_MAJOR, next_minor); + next_minor++; + if (next_minor > MINORMASK) + next_minor = 0; + if (next_minor == start) + return 0; /* Oh dear, all in use. */ + is_free = !mddev_find_locked(dev); + } + + return dev; +} + static struct mddev *mddev_find(dev_t unit) { struct mddev *mddev; @@ -764,27 +785,13 @@ static struct mddev *mddev_find_or_alloc(dev_t unit) return new; } } else if (new) { - /* find an unused unit number */ - static int next_minor = 512; - int start = next_minor; - int is_free = 0; - int dev = 0; - while (!is_free) { - dev = MKDEV(MD_MAJOR, next_minor); - next_minor++; - if (next_minor > MINORMASK) - next_minor = 0; - if (next_minor == start) { - /* Oh dear, all in use. */ - spin_unlock(&all_mddevs_lock); - kfree(new); - return NULL; - } - - is_free = !mddev_find_locked(dev); + new->unit = mddev_alloc_unit(); + if (!new->unit) { + spin_unlock(&all_mddevs_lock); + kfree(new); + return NULL; } - new->unit = dev; - new->md_minor = MINOR(dev); + new->md_minor = MINOR(new->unit); new->hold_active = UNTIL_STOP; list_add(&new->all_mddevs, &all_mddevs); spin_unlock(&all_mddevs_lock);
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v5.13-rc1 commit d144fe6ff176d79efd411e520103a99e11874c36 category: bugfix bugzilla: 189427, https://gitee.com/openeuler/kernel/issues/I8O6NL
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
-------------------------------------------------
Allocate the new mddev first speculatively, which greatly simplifies the code flow.
Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Song Liu song@kernel.org Signed-off-by: Li Lingfeng lilingfeng3@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.c | 60 ++++++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 36 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index ba4c7d6505da..acf3341a1c40 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -761,57 +761,45 @@ static struct mddev *mddev_find(dev_t unit)
static struct mddev *mddev_find_or_alloc(dev_t unit) { - struct mddev *mddev, *new = NULL; + struct mddev *mddev = NULL, *new;
if (unit && MAJOR(unit) != MD_MAJOR) - unit &= ~((1<<MdpMinorShift)-1); + unit &= ~((1 << MdpMinorShift) - 1);
- retry: - spin_lock(&all_mddevs_lock); + new = kzalloc(sizeof(*new), GFP_KERNEL); + if (!new) + return NULL; + mddev_init(new);
+ spin_lock(&all_mddevs_lock); if (unit) { mddev = mddev_find_locked(unit); if (mddev) { mddev_get(mddev); - spin_unlock(&all_mddevs_lock); - kfree(new); - return mddev; + goto out_free_new; }
- if (new) { - list_add(&new->all_mddevs, &all_mddevs); - spin_unlock(&all_mddevs_lock); - new->hold_active = UNTIL_IOCTL; - return new; - } - } else if (new) { + new->unit = unit; + if (MAJOR(unit) == MD_MAJOR) + new->md_minor = MINOR(unit); + else + new->md_minor = MINOR(unit) >> MdpMinorShift; + new->hold_active = UNTIL_IOCTL; + } else { new->unit = mddev_alloc_unit(); - if (!new->unit) { - spin_unlock(&all_mddevs_lock); - kfree(new); - return NULL; - } + if (!new->unit) + goto out_free_new; new->md_minor = MINOR(new->unit); new->hold_active = UNTIL_STOP; - list_add(&new->all_mddevs, &all_mddevs); - spin_unlock(&all_mddevs_lock); - return new; } - spin_unlock(&all_mddevs_lock); - - new = kzalloc(sizeof(*new), GFP_KERNEL); - if (!new) - return NULL;
- new->unit = unit; - if (MAJOR(unit) == MD_MAJOR) - new->md_minor = MINOR(unit); - else - new->md_minor = MINOR(unit) >> MdpMinorShift; - - mddev_init(new); - - goto retry; + list_add(&new->all_mddevs, &all_mddevs); + spin_unlock(&all_mddevs_lock); + return new; +out_free_new: + spin_unlock(&all_mddevs_lock); + kfree(new); + return mddev; }
static struct attribute_group md_redundancy_group;
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v5.13-rc1 commit 0d809b3837a0bede8f58a67e303e339585777bf4 category: bugfix bugzilla: 189427, https://gitee.com/openeuler/kernel/issues/I8O6NL
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
-------------------------------------------------
Instead of returning an existing mddev, just for it to be discarded later directly return -EEXIST. Rename the function to mddev_alloc now that it doesn't find an existing mddev.
Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Song Liu song@kernel.org
Conflicts: Commit 5e8daf906f89 ("md: Flush workqueue md_rdev_misc_wq in md_alloc()") add flushing md_rdev_misc_wq in md_alloc(); Commit a4c94d46c7dc ("[Backport] md: properly unwind when failing to add the kobject in md_alloc") changed "goto abort" to "goto out_unlock_disks_mutex" and commit fe8412162d24 ("[Backport] md: fix error handling in md_alloc") changed "goto out_unlock_disks_mutex" to "goto done"; Commit a4c94d46c7dc ("[Backport] md: properly unwind when failing to add the kobject in md_alloc") changed "goto abort" to "goto out_unlock_disks_mutex" and commit fe8412162d24 ("[Backport] md: fix error handling in md_alloc") changed "goto out_unlock_disks_mutex" to "goto out_free_mddev". Signed-off-by: Li Lingfeng lilingfeng3@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index acf3341a1c40..804ad7b74ecf 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -759,26 +759,24 @@ static struct mddev *mddev_find(dev_t unit) return mddev; }
-static struct mddev *mddev_find_or_alloc(dev_t unit) +static struct mddev *mddev_alloc(dev_t unit) { - struct mddev *mddev = NULL, *new; + struct mddev *new; + int error;
if (unit && MAJOR(unit) != MD_MAJOR) unit &= ~((1 << MdpMinorShift) - 1);
new = kzalloc(sizeof(*new), GFP_KERNEL); if (!new) - return NULL; + return ERR_PTR(-ENOMEM); mddev_init(new);
spin_lock(&all_mddevs_lock); if (unit) { - mddev = mddev_find_locked(unit); - if (mddev) { - mddev_get(mddev); + error = -EEXIST; + if (mddev_find_locked(unit)) goto out_free_new; - } - new->unit = unit; if (MAJOR(unit) == MD_MAJOR) new->md_minor = MINOR(unit); @@ -786,6 +784,7 @@ static struct mddev *mddev_find_or_alloc(dev_t unit) new->md_minor = MINOR(unit) >> MdpMinorShift; new->hold_active = UNTIL_IOCTL; } else { + error = -ENODEV; new->unit = mddev_alloc_unit(); if (!new->unit) goto out_free_new; @@ -799,7 +798,7 @@ static struct mddev *mddev_find_or_alloc(dev_t unit) out_free_new: spin_unlock(&all_mddevs_lock); kfree(new); - return mddev; + return ERR_PTR(error); }
static struct attribute_group md_redundancy_group; @@ -5747,30 +5746,30 @@ static int md_alloc(dev_t dev, char *name) * writing to /sys/module/md_mod/parameters/new_array. */ static DEFINE_MUTEX(disks_mutex); - struct mddev *mddev = mddev_find_or_alloc(dev); + struct mddev *mddev; struct gendisk *disk; int partitioned; int shift; int unit; - int error; - - if (!mddev) - return -ENODEV; + int error ;
- partitioned = (MAJOR(mddev->unit) != MD_MAJOR); - shift = partitioned ? MdpMinorShift : 0; - unit = MINOR(mddev->unit) >> shift; - - /* wait for any previous instance of this device to be - * completely removed (mddev_delayed_delete). + /* + * Wait for any previous instance of this device to be completely + * removed (mddev_delayed_delete). */ flush_workqueue(md_misc_wq); flush_workqueue(md_rdev_misc_wq);
mutex_lock(&disks_mutex); - error = -EEXIST; - if (mddev->gendisk) - goto done; + mddev = mddev_alloc(dev); + if (IS_ERR(mddev)) { + mutex_unlock(&disks_mutex); + return PTR_ERR(mddev); + } + + partitioned = (MAJOR(mddev->unit) != MD_MAJOR); + shift = partitioned ? MdpMinorShift : 0; + unit = MINOR(mddev->unit) >> shift;
if (name && !dev) { /* Need to ensure that 'name' is not a duplicate. @@ -5782,6 +5781,7 @@ static int md_alloc(dev_t dev, char *name) if (mddev2->gendisk && strcmp(mddev2->gendisk->disk_name, name) == 0) { spin_unlock(&all_mddevs_lock); + error = -EEXIST; goto out_free_mddev; } spin_unlock(&all_mddevs_lock);
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/3443 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/B...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/3443 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/B...