Christoph Hellwig (6): md: convert to blk_alloc_disk/blk_cleanup_disk md: add the bitmap group to the default groups for the md kobject md: extend disks_mutex coverage md: properly unwind when failing to add the kobject in md_alloc md: fix mddev->kobj lifetime md: fix error handling in md_alloc
Eric Dumazet (1): md: use msleep() in md_notify_reboot()
Luis Chamberlain (1): md: add error handling support for add_disk()
Rikard Falkeborn (1): md: Constify attribute_group structs
Yu Kuai (1): md/raid10: fix improper BUG_ON() in raise_barrier()
zhangyue (1): md: fix double free of mddev->private in autorun_array()
drivers/md/md.h | 4 +- drivers/md/md-bitmap.c | 2 +- drivers/md/md.c | 108 ++++++++++++++++++++++++----------------- drivers/md/raid10.c | 2 +- drivers/md/raid5.c | 2 +- 5 files changed, 68 insertions(+), 50 deletions(-)
From: zhangyue zhangyue1@kylinos.cn
mainline inclusion from mainline-v5.16-rc5 commit 07641b5f32f6991758b08da9b1f4173feeb64f2a category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I63WZE
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
In driver/md/md.c, if the function autorun_array() is called, the problem of double free may occur.
In function autorun_array(), when the function do_md_run() returns an error, the function do_md_stop() will be called.
The function do_md_run() called function md_run(), but in function md_run(), the pointer mddev->private may be freed.
The function do_md_stop() called the function __md_stop(), but in function __md_stop(), the pointer mddev->private also will be freed without judging null.
At this time, the pointer mddev->private will be double free, so it needs to be judged null or not.
Signed-off-by: zhangyue zhangyue1@kylinos.cn Signed-off-by: Song Liu songliubraving@fb.com Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index f52ce85c6561..db2a535f5c71 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -6363,7 +6363,8 @@ static void __md_stop(struct mddev *mddev) spin_lock(&mddev->lock); mddev->pers = NULL; spin_unlock(&mddev->lock); - pers->free(mddev, mddev->private); + if (mddev->private) + pers->free(mddev, mddev->private); mddev->private = NULL; if (pers->sync_request && mddev->to_remove == NULL) mddev->to_remove = &md_redundancy_group;
From: Eric Dumazet edumazet@google.com
mainline inclusion from mainline-v5.18-rc1 commit 7d959f6e978cbbca90e26a192cc39480e977182f category: bugfix bugzilla: 188015, https://gitee.com/openeuler/kernel/issues/I63WZE
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/commit/?id=...
--------------------------------
Calling mdelay(1000) from process context, even while a reboot is in progress, does not make sense.
Using msleep() allows other threads to make progress.
Signed-off-by: Eric Dumazet edumazet@google.com Cc: linux-raid@vger.kernel.org Signed-off-by: Song Liu song@kernel.org 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 db2a535f5c71..97580c86ab35 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -9656,7 +9656,7 @@ static int md_notify_reboot(struct notifier_block *this, * driver, we do want to have a safe RAID driver ... */ if (need_delay) - mdelay(1000*1); + msleep(1000);
return NOTIFY_DONE; }
From: Yu Kuai yukuai3@huawei.com
mainline inclusion from mainline-v6.1-rc1 commit 4f350284a7306b3dff676caeafd3faf1b5c068d5 category: bugfix bugzilla: 188015, https://gitee.com/openeuler/kernel/issues/I63WZE
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/commit/?id=...
--------------------------------
'conf->barrier' is protected by 'conf->resync_lock', reading 'conf->barrier' without holding the lock is wrong.
Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Logan Gunthorpe logang@deltatee.com Acked-by: Guoqing Jiang guoqing.jiang@linux.dev Signed-off-by: Song Liu song@kernel.org Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/raid10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 222d9ed76b4b..f1ff63c0444c 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -941,8 +941,8 @@ static void flush_pending_writes(struct r10conf *conf)
static void raise_barrier(struct r10conf *conf, int force) { - BUG_ON(force && !conf->barrier); spin_lock_irq(&conf->resync_lock); + BUG_ON(force && !conf->barrier);
/* Wait until no block IO is waiting (unless 'force') */ wait_event_lock_irq(conf->wait_barrier, force || !conf->nr_waiting,
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v5.14-rc1 commit 0f1d2e0643c544df50dbc436da930201218fa1e2 category: bugfix bugzilla: 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 97580c86ab35..bba90a46cdf4 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5665,12 +5665,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); @@ -5774,20 +5772,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) @@ -5796,7 +5787,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: 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 bba90a46cdf4..78d603fb8036 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5798,7 +5798,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: 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 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 78d603fb8036..dd34e44d9962 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5588,6 +5588,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, @@ -5610,6 +5614,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) { @@ -5684,7 +5694,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; @@ -5693,7 +5703,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); } @@ -5813,9 +5822,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: mutex_unlock(&disks_mutex); if (!error && mddev->kobj.sd) {
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v5.16-rc1 commit 94f3cd7d832c28681f1dea54b4dd8606e5e2bc75 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
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 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 dd34e44d9962..480144fbeb1e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5823,12 +5823,12 @@ static int md_alloc(dev_t dev, char *name) error = 0; } 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.16-rc1 commit 7ad1069166c0ccdd572d27e01cc7f7f84477df1e category: bugfix bugzilla: 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 Because add_disk_safe().
Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index 480144fbeb1e..b1a671eb2d6d 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5770,7 +5770,7 @@ static int md_alloc(dev_t dev, char *name) strcmp(mddev2->gendisk->disk_name, name) == 0) { spin_unlock(&all_mddevs_lock); error = -EEXIST; - goto abort; + goto out_unlock_disks_mutex; } spin_unlock(&all_mddevs_lock); } @@ -5783,7 +5783,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; @@ -5808,26 +5808,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, 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: drivers/md/md.c 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 b1a671eb2d6d..0cf90ed4cfe3 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -686,7 +686,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); @@ -5675,10 +5674,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); @@ -5703,7 +5701,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); }
@@ -5811,6 +5808,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: Rikard Falkeborn rikard.falkeborn@gmail.com
mainline inclusion from mainline-v5.14-rc1 commit c32dc04059c79ddb4f7cff94ad5de6e92ea2218d category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
The attribute_group structs are never modified, they're only passed to sysfs_create_group() and sysfs_remove_group(). Make them const to allow the compiler to put them in read-only memory.
Signed-off-by: Rikard Falkeborn rikard.falkeborn@gmail.com Signed-off-by: Song Liu song@kernel.org Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.h | 4 ++-- drivers/md/md-bitmap.c | 2 +- drivers/md/md.c | 6 +++--- drivers/md/raid5.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/md/md.h b/drivers/md/md.h index 845ccd842975..72e9f31c3ef9 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -500,7 +500,7 @@ struct mddev { atomic_t max_corr_read_errors; /* max read retries */ struct list_head all_mddevs;
- struct attribute_group *to_remove; + const struct attribute_group *to_remove;
struct bio_set bio_set; struct bio_set sync_set; /* for sync operations like @@ -637,7 +637,7 @@ struct md_sysfs_entry { ssize_t (*show)(struct mddev *, char *); ssize_t (*store)(struct mddev *, const char *, size_t); }; -extern struct attribute_group md_bitmap_group; +extern const struct attribute_group md_bitmap_group;
static inline struct kernfs_node *sysfs_get_dirent_safe(struct kernfs_node *sd, char *name) { diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c index e842beb89858..895bbb512135 100644 --- a/drivers/md/md-bitmap.c +++ b/drivers/md/md-bitmap.c @@ -2637,7 +2637,7 @@ static struct attribute *md_bitmap_attrs[] = { &max_backlog_used.attr, NULL }; -struct attribute_group md_bitmap_group = { +const struct attribute_group md_bitmap_group = { .name = "bitmap", .attrs = md_bitmap_attrs, }; diff --git a/drivers/md/md.c b/drivers/md/md.c index 0cf90ed4cfe3..b841b6ed379b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -800,7 +800,7 @@ static struct mddev *mddev_alloc(dev_t unit) return ERR_PTR(error); }
-static struct attribute_group md_redundancy_group; +static const struct attribute_group md_redundancy_group;
void mddev_unlock(struct mddev *mddev) { @@ -817,7 +817,7 @@ void mddev_unlock(struct mddev *mddev) * test it under the same mutex to ensure its correct value * is seen. */ - struct attribute_group *to_remove = mddev->to_remove; + const struct attribute_group *to_remove = mddev->to_remove; mddev->to_remove = NULL; mddev->sysfs_active = 1; mutex_unlock(&mddev->reconfig_mutex); @@ -5608,7 +5608,7 @@ static struct attribute *md_redundancy_attrs[] = { &md_degraded.attr, NULL, }; -static struct attribute_group md_redundancy_group = { +static const struct attribute_group md_redundancy_group = { .name = NULL, .attrs = md_redundancy_attrs, }; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index bef14340f9c1..7e78499aa9d3 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -6950,7 +6950,7 @@ static struct attribute *raid5_attrs[] = { &ppl_write_hint.attr, NULL, }; -static struct attribute_group raid5_attrs_group = { +static const struct attribute_group raid5_attrs_group = { .name = NULL, .attrs = raid5_attrs, };
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v6.0-rc1 commit c57094a6e1ed5dd2d6401f79b8e6da34dd28f959 category: bugfix bugzilla: 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 8b9ab6266204 ("block: remove blk_cleanup_disk") change blk_cleanup_disk() to put_disk(). Keep using blk_cleanup_disk() here. And add_disk_safe().
Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.c | 45 ++++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index b841b6ed379b..02dcf64103ca 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -800,6 +800,15 @@ static struct mddev *mddev_alloc(dev_t unit) return ERR_PTR(error); }
+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 const struct attribute_group md_redundancy_group;
void mddev_unlock(struct mddev *mddev) @@ -5748,8 +5757,8 @@ static int md_alloc(dev_t dev, char *name) mutex_lock(&disks_mutex); mddev = mddev_alloc(dev); if (IS_ERR(mddev)) { - mutex_unlock(&disks_mutex); - return PTR_ERR(mddev); + error = PTR_ERR(mddev); + goto out_unlock; }
partitioned = (MAJOR(mddev->unit) != MD_MAJOR); @@ -5767,7 +5776,7 @@ static int md_alloc(dev_t dev, char *name) strcmp(mddev2->gendisk->disk_name, name) == 0) { spin_unlock(&all_mddevs_lock); error = -EEXIST; - goto out_unlock_disks_mutex; + goto out_free_mddev; } spin_unlock(&all_mddevs_lock); } @@ -5780,7 +5789,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; @@ -5806,26 +5815,36 @@ 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); +out_unlock: + mutex_unlock(&disks_mutex); + return error; }
static struct kobject *md_probe(dev_t dev, int *part, void *data)
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/3756 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/7...
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/3756 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/7...