From fbaebc312cf9fd39e40c5c498ba295a52268f069 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 25 Nov 2023 09:23:24 +0800 Subject: [PATCH 01/17] block: fold register_disk into device_add_disk mainline inclusion from mainline-v5.15-rc1 commit 52b85909f85d06efa69aaf4210e72467f1f58d2b category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=52b85909f85d06efa69aaf4210e72467f1f58d2b ---------------------------------------- There is no real reason these should be separate. Also simplify the groups assignment a bit. Signed-off-by: Christoph Hellwig Link: https://lore.kernel.org/r/20210818144542.19305-3-hch@lst.de Signed-off-by: Jens Axboe conflict: block/genhd.c Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 97 +++++++++++++++++++++++---------------------------- 1 file changed, 44 insertions(+), 53 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 83f407e1563a..aef153a824a4 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -687,55 +687,6 @@ static int exact_lock(dev_t devt, void *data) return 0; } -static void register_disk(struct device *parent, struct gendisk *disk, - const struct attribute_group **groups) -{ - struct device *ddev = disk_to_dev(disk); - int err; - - ddev->parent = parent; - - dev_set_name(ddev, "%s", disk->disk_name); - - /* delay uevents, until we scanned partition table */ - dev_set_uevent_suppress(ddev, 1); - - if (groups) { - WARN_ON(ddev->groups); - ddev->groups = groups; - } - if (device_add(ddev)) - return; - if (!sysfs_deprecated) { - err = sysfs_create_link(block_depr, &ddev->kobj, - kobject_name(&ddev->kobj)); - if (err) { - device_del(ddev); - return; - } - } - - /* - * avoid probable deadlock caused by allocating memory with - * GFP_KERNEL in runtime_resume callback of its all ancestor - * devices - */ - pm_runtime_set_memalloc_noio(ddev, true); - - disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj); - disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj); - - if (disk->flags & GENHD_FL_HIDDEN) - return; - - if (disk->queue->backing_dev_info->dev) { - err = sysfs_create_link(&ddev->kobj, - &disk->queue->backing_dev_info->dev->kobj, - "bdi"); - WARN_ON(err); - } -} - int disk_scan_partitions(struct gendisk *disk, fmode_t mode) { struct block_device *bdev; @@ -820,6 +771,7 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk, const struct attribute_group **groups, bool register_queue) { + struct device *ddev = disk_to_dev(disk); dev_t devt; int retval; @@ -859,18 +811,57 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk, disk->flags |= GENHD_FL_NO_PART_SCAN; } else { struct backing_dev_info *bdi = disk->queue->backing_dev_info; - struct device *dev = disk_to_dev(disk); int ret; /* Register BDI before referencing it from bdev */ - dev->devt = devt; + ddev->devt = devt; ret = bdi_register(bdi, "%u:%u", MAJOR(devt), MINOR(devt)); WARN_ON(ret); - bdi_set_owner(bdi, dev); + bdi_set_owner(bdi, ddev); blk_register_region(disk_devt(disk), disk->minors, NULL, exact_match, exact_lock, disk); } - register_disk(parent, disk, groups); + + /* delay uevents, until we scanned partition table */ + dev_set_uevent_suppress(ddev, 1); + + ddev->parent = parent; + if (groups) { + WARN_ON(ddev->groups); + ddev->groups = groups; + } + dev_set_name(ddev, "%s", disk->disk_name); + if (device_add(ddev)) + return; + if (!sysfs_deprecated) { + retval = sysfs_create_link(block_depr, &ddev->kobj, + kobject_name(&ddev->kobj)); + if (retval) { + device_del(ddev); + return; + } + } + + /* + * avoid probable deadlock caused by allocating memory with + * GFP_KERNEL in runtime_resume callback of its all ancestor + * devices + */ + pm_runtime_set_memalloc_noio(ddev, true); + + disk->part0.holder_dir = + kobject_create_and_add("holders", &ddev->kobj); + disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj); + + if (!(disk->flags & GENHD_FL_HIDDEN)) { + if (disk->queue->backing_dev_info->dev) { + retval = sysfs_create_link(&ddev->kobj, + &disk->queue->backing_dev_info->dev->kobj, + "bdi"); + WARN_ON(retval); + } + } + if (register_queue) blk_register_queue(disk); -- Gitee From 2d016e0ca43bfe871f0055eff1d312c9c4a1f84d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 25 Nov 2023 09:23:26 +0800 Subject: [PATCH 02/17] block: call blk_integrity_add earlier in device_add_disk mainline inclusion from mainline-v5.15-rc1 commit bab53f6b617d9f530978d6e3693f88e586d81a8a category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bab53f6b617d9f530978d6e3693f88e586d81a8a ---------------------------------------- Doing all the sysfs file creation before adding the bdev and thus allowing it to be opened will simplify the about to be added error handling. Signed-off-by: Christoph Hellwig Reviewed-by: Hannes Reinecke Link: https://lore.kernel.org/r/20210818144542.19305-6-hch@lst.de Signed-off-by: Jens Axboe conflict: block/genhd.c Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/block/genhd.c b/block/genhd.c index aef153a824a4..d2153303ae05 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -849,6 +849,8 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk, */ pm_runtime_set_memalloc_noio(ddev, true); + blk_integrity_add(disk); + disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj); disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj); @@ -872,7 +874,6 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk, WARN_ON_ONCE(!blk_get_queue(disk->queue)); disk_add_events(disk); - blk_integrity_add(disk); /* Make sure the first partition scan will be proceed */ if (get_capacity(disk) && disk_part_scan_enabled(disk)) -- Gitee From c6e4d6d1a3a0c033ec057ad3dffd16381b1a08d4 Mon Sep 17 00:00:00 2001 From: Luis Chamberlain Date: Sat, 25 Nov 2023 09:23:27 +0800 Subject: [PATCH 03/17] block: return errors from blk_integrity_add mainline inclusion from mainline-v5.15-rc1 commit 614310c9c8ca15359f4e71a5bbd9165897b4d54e category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=614310c9c8ca15359f4e71a5bbd9165897b4d54e ---------------------------------------- Prepare for proper error handling in add_disk. Signed-off-by: Luis Chamberlain [hch: split from a larger patch] Signed-off-by: Christoph Hellwig Reviewed-by: Hannes Reinecke Link: https://lore.kernel.org/r/20210818144542.19305-8-hch@lst.de Signed-off-by: Jens Axboe Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/blk-integrity.c | 12 +++++++----- block/blk.h | 5 +++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/block/blk-integrity.c b/block/blk-integrity.c index 9e83159f5a52..16d5d5338392 100644 --- a/block/blk-integrity.c +++ b/block/blk-integrity.c @@ -438,13 +438,15 @@ void blk_integrity_unregister(struct gendisk *disk) } EXPORT_SYMBOL(blk_integrity_unregister); -void blk_integrity_add(struct gendisk *disk) +int blk_integrity_add(struct gendisk *disk) { - if (kobject_init_and_add(&disk->integrity_kobj, &integrity_ktype, - &disk_to_dev(disk)->kobj, "%s", "integrity")) - return; + int ret; - kobject_uevent(&disk->integrity_kobj, KOBJ_ADD); + ret = kobject_init_and_add(&disk->integrity_kobj, &integrity_ktype, + &disk_to_dev(disk)->kobj, "%s", "integrity"); + if (!ret) + kobject_uevent(&disk->integrity_kobj, KOBJ_ADD); + return ret; } void blk_integrity_del(struct gendisk *disk) diff --git a/block/blk.h b/block/blk.h index 7b3693149183..4bbcc971d4f7 100644 --- a/block/blk.h +++ b/block/blk.h @@ -134,7 +134,7 @@ static inline bool integrity_req_gap_front_merge(struct request *req, bip_next->bip_vec[0].bv_offset); } -void blk_integrity_add(struct gendisk *); +int blk_integrity_add(struct gendisk *disk); void blk_integrity_del(struct gendisk *); #else /* CONFIG_BLK_DEV_INTEGRITY */ static inline bool blk_integrity_merge_rq(struct request_queue *rq, @@ -168,8 +168,9 @@ static inline bool bio_integrity_endio(struct bio *bio) static inline void bio_integrity_free(struct bio *bio) { } -static inline void blk_integrity_add(struct gendisk *disk) +static inline int blk_integrity_add(struct gendisk *disk) { + return 0; } static inline void blk_integrity_del(struct gendisk *disk) { -- Gitee From ac08a10cde241cf82ba91aa299e0a69b833f6ca0 Mon Sep 17 00:00:00 2001 From: Luis Chamberlain Date: Sat, 25 Nov 2023 09:23:28 +0800 Subject: [PATCH 04/17] block: return errors from disk_alloc_events mainline inclusion from mainline-v5.15-rc1 commit 92e7755ebc69233e25a2d1b760aeff536dc4016b category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=92e7755ebc69233e25a2d1b760aeff536dc4016b ---------------------------------------- Prepare for proper error handling in add_disk. Signed-off-by: Luis Chamberlain [hch: split from a larger patch] Signed-off-by: Christoph Hellwig Reviewed-by: Hannes Reinecke Link: https://lore.kernel.org/r/20210818144542.19305-9-hch@lst.de Signed-off-by: Jens Axboe conflict: block/genhd.c Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index d2153303ae05..ef13a9689dd7 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -40,7 +40,7 @@ static DEFINE_IDR(ext_devt_idr); static void disk_check_events(struct disk_events *ev, unsigned int *clearing_ptr); -static void disk_alloc_events(struct gendisk *disk); +static int disk_alloc_events(struct gendisk *disk); static void disk_add_events(struct gendisk *disk); static void disk_del_events(struct gendisk *disk); static void disk_release_events(struct gendisk *disk); @@ -2396,17 +2396,17 @@ module_param_cb(events_dfl_poll_msecs, &disk_events_dfl_poll_msecs_param_ops, /* * disk_{alloc|add|del|release}_events - initialize and destroy disk_events. */ -static void disk_alloc_events(struct gendisk *disk) +static int disk_alloc_events(struct gendisk *disk) { struct disk_events *ev; if (!disk->fops->check_events || !disk->events) - return; + return 0; ev = kzalloc(sizeof(*ev), GFP_KERNEL); if (!ev) { pr_warn("%s: failed to initialize events\n", disk->disk_name); - return; + return -ENOMEM; } INIT_LIST_HEAD(&ev->node); @@ -2418,6 +2418,7 @@ static void disk_alloc_events(struct gendisk *disk) INIT_DELAYED_WORK(&ev->dwork, disk_events_workfn); disk->ev = ev; + return 0; } static void disk_add_events(struct gendisk *disk) -- Gitee From 62c5af18115e7c82a09eca7361786fd7d60feb6b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 25 Nov 2023 09:23:29 +0800 Subject: [PATCH 05/17] block: add the events* attributes to disk_attrs mainline inclusion from mainline-v5.14-rc1 commit 2bc8cda5ea4b42ff78be1b11011092d57b424d37 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2bc8cda5ea4b42ff78be1b11011092d57b424d37 ---------------------------------------- Add the events attributes to the disk_attrs array, which ensures they are added by the driver core when the device is created rather than adding them after the device has been added, which is racy versus uevents and requires more boilerplate code. Signed-off-by: Christoph Hellwig Reviewed-by: Hannes Reinecke Link: https://lore.kernel.org/r/20210624073843.251178-3-hch@lst.de Signed-off-by: Jens Axboe conflict: block/genhd.c Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index ef13a9689dd7..261a71360b5c 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -44,6 +44,9 @@ static int disk_alloc_events(struct gendisk *disk); static void disk_add_events(struct gendisk *disk); static void disk_del_events(struct gendisk *disk); static void disk_release_events(struct gendisk *disk); +static struct device_attribute dev_attr_events; +static struct device_attribute dev_attr_events_async; +static struct device_attribute dev_attr_events_poll_msecs; /* * Set disk capacity and notify if the size is not currently @@ -1513,6 +1516,9 @@ static struct attribute *disk_attrs[] = { &dev_attr_stat.attr, &dev_attr_inflight.attr, &dev_attr_badblocks.attr, + &dev_attr_events.attr, + &dev_attr_events_async.attr, + &dev_attr_events_poll_msecs.attr, #ifdef CONFIG_FAIL_MAKE_REQUEST &dev_attr_fail.attr, #endif @@ -2343,18 +2349,10 @@ static ssize_t disk_events_poll_msecs_store(struct device *dev, return count; } -static const DEVICE_ATTR(events, 0444, disk_events_show, NULL); -static const DEVICE_ATTR(events_async, 0444, disk_events_async_show, NULL); -static const DEVICE_ATTR(events_poll_msecs, 0644, - disk_events_poll_msecs_show, - disk_events_poll_msecs_store); - -static const struct attribute *disk_events_attrs[] = { - &dev_attr_events.attr, - &dev_attr_events_async.attr, - &dev_attr_events_poll_msecs.attr, - NULL, -}; +static DEVICE_ATTR(events, 0444, disk_events_show, NULL); +static DEVICE_ATTR(events_async, 0444, disk_events_async_show, NULL); +static DEVICE_ATTR(events_poll_msecs, 0644, disk_events_poll_msecs_show, + disk_events_poll_msecs_store); /* * The default polling interval can be specified by the kernel @@ -2423,11 +2421,6 @@ static int disk_alloc_events(struct gendisk *disk) static void disk_add_events(struct gendisk *disk) { - /* FIXME: error handling */ - if (sysfs_create_files(&disk_to_dev(disk)->kobj, disk_events_attrs) < 0) - pr_warn("%s: failed to create sysfs files for events\n", - disk->disk_name); - if (!disk->ev) return; @@ -2451,8 +2444,6 @@ static void disk_del_events(struct gendisk *disk) list_del_init(&disk->ev->node); mutex_unlock(&disk_events_mutex); } - - sysfs_remove_files(&disk_to_dev(disk)->kobj, disk_events_attrs); } static void disk_release_events(struct gendisk *disk) -- Gitee From 8fb9434f1e3ffa0a71d25f5a9016ae73b7928718 Mon Sep 17 00:00:00 2001 From: Zhong Jinghua Date: Sat, 25 Nov 2023 09:23:30 +0800 Subject: [PATCH 06/17] block: return errors from blk_register_region hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK ---------------------------------------- Modify the return value type of blk_register_region to prepare for adding error handling. Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 5 +++-- include/linux/genhd.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 261a71360b5c..11c6869005c6 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -649,12 +649,13 @@ static char *bdevt_str(dev_t devt, char *buf) * Register device numbers dev..(dev+range-1) * range must be nonzero * The hash chain is sorted on range, so that subranges can override. + * Add error handling. */ -void blk_register_region(dev_t devt, unsigned long range, struct module *module, +int blk_register_region(dev_t devt, unsigned long range, struct module *module, struct kobject *(*probe)(dev_t, int *, void *), int (*lock)(dev_t, void *), void *data) { - kobj_map(bdev_map, devt, range, module, probe, lock, data); + return kobj_map(bdev_map, devt, range, module, probe, lock, data); } EXPORT_SYMBOL(blk_register_region); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 959add98b686..61b5e9359152 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -361,7 +361,7 @@ extern struct gendisk *__alloc_disk_node(int minors, int node_id); extern struct kobject *get_disk_and_module(struct gendisk *disk); extern void put_disk(struct gendisk *disk); extern void put_disk_and_module(struct gendisk *disk); -extern void blk_register_region(dev_t devt, unsigned long range, +extern int blk_register_region(dev_t devt, unsigned long range, struct module *module, struct kobject *(*probe)(dev_t, int *, void *), int (*lock)(dev_t, void *), -- Gitee From a0259762e3dd22989bf470e5e0562ecc68a6593e Mon Sep 17 00:00:00 2001 From: Luis Chamberlain Date: Sat, 25 Nov 2023 09:23:31 +0800 Subject: [PATCH 07/17] block: add error handling for device_add_disk / add_disk mainline inclusion from mainline-v5.15-rc1 commit 83cbce9574462c6b4eed6797bdaf18fae6859ab3 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=83cbce9574462c6b4eed6797bdaf18fae6859ab3 ---------------------------------------- Properly unwind on errors in device_add_disk. This is the initial work as drivers are not converted yet, which will follow in separate patches. Signed-off-by: Luis Chamberlain [hch: major rebase. All bugs are probably mine] Signed-off-by: Christoph Hellwig Reviewed-by: Hannes Reinecke Link: https://lore.kernel.org/r/20210818144542.19305-10-hch@lst.de Signed-off-by: Jens Axboe conflicts: block/genhd.c include/linux/genhd.h Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 95 +++++++++++++++++++++++++++++-------------- include/linux/genhd.h | 6 +-- 2 files changed, 67 insertions(+), 34 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 11c6869005c6..3a2c8be1b79a 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -768,10 +768,8 @@ static void disk_init_partition(struct gendisk *disk) * * This function registers the partitioning information in @disk * with the kernel. - * - * FIXME: error handling */ -static void __device_add_disk(struct device *parent, struct gendisk *disk, +static int __device_add_disk(struct device *parent, struct gendisk *disk, const struct attribute_group **groups, bool register_queue) { @@ -797,14 +795,14 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk, !(disk->flags & (GENHD_FL_EXT_DEVT | GENHD_FL_HIDDEN))); retval = blk_alloc_devt(&disk->part0, &devt); - if (retval) { - WARN_ON(1); - return; - } + if (retval) + return retval; disk->major = MAJOR(devt); disk->first_minor = MINOR(devt); - disk_alloc_events(disk); + retval = disk_alloc_events(disk); + if (retval) + goto out_free_ext_minor; if (disk->flags & GENHD_FL_HIDDEN) { /* @@ -815,15 +813,17 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk, disk->flags |= GENHD_FL_NO_PART_SCAN; } else { struct backing_dev_info *bdi = disk->queue->backing_dev_info; - int ret; /* Register BDI before referencing it from bdev */ ddev->devt = devt; - ret = bdi_register(bdi, "%u:%u", MAJOR(devt), MINOR(devt)); - WARN_ON(ret); + retval = bdi_register(bdi, "%u:%u", MAJOR(devt), MINOR(devt)); + if (retval) + goto out_disk_release_events; bdi_set_owner(bdi, ddev); - blk_register_region(disk_devt(disk), disk->minors, NULL, - exact_match, exact_lock, disk); + retval = blk_register_region(disk_devt(disk), disk->minors, + NULL, exact_match, exact_lock, disk); + if (retval) + goto out_unregister_bdi; } /* delay uevents, until we scanned partition table */ @@ -835,15 +835,14 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk, ddev->groups = groups; } dev_set_name(ddev, "%s", disk->disk_name); - if (device_add(ddev)) - return; + retval = device_add(ddev); + if (retval) + goto out_unregister_region; if (!sysfs_deprecated) { retval = sysfs_create_link(block_depr, &ddev->kobj, - kobject_name(&ddev->kobj)); - if (retval) { - device_del(ddev); - return; - } + kobject_name(&ddev->kobj)); + if (retval) + goto out_device_del; } /* @@ -853,23 +852,30 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk, */ pm_runtime_set_memalloc_noio(ddev, true); - blk_integrity_add(disk); + retval = blk_integrity_add(disk); + if (retval) + goto out_del_block_link; disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj); + if (!disk->part0.holder_dir) + goto out_del_integrity; disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj); + if (!disk->slave_dir) + goto out_put_holder_dir; if (!(disk->flags & GENHD_FL_HIDDEN)) { - if (disk->queue->backing_dev_info->dev) { - retval = sysfs_create_link(&ddev->kobj, - &disk->queue->backing_dev_info->dev->kobj, - "bdi"); - WARN_ON(retval); - } + retval = sysfs_create_link(&ddev->kobj, + &disk->queue->backing_dev_info->dev->kobj, "bdi"); + if (retval) + goto out_put_slave_dir; } - if (register_queue) - blk_register_queue(disk); + if (register_queue) { + retval = blk_register_queue(disk); + if (retval) + goto out_del_bdi_sysfs_link; + } /* * Take an extra ref on queue which will be put on disk_release() @@ -889,13 +895,40 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk, */ disk->flags |= GENHD_FL_UP; disk_init_partition(disk); + return 0; + +out_del_bdi_sysfs_link: + if (!(disk->flags & GENHD_FL_HIDDEN)) + sysfs_remove_link(&ddev->kobj, "bdi"); +out_put_slave_dir: + kobject_put(disk->slave_dir); +out_put_holder_dir: + kobject_put(disk->part0.holder_dir); +out_del_integrity: + blk_integrity_del(disk); +out_del_block_link: + if (!sysfs_deprecated) + sysfs_remove_link(block_depr, kobject_name(&ddev->kobj)); +out_device_del: + device_del(ddev); +out_unregister_region: + if (!(disk->flags & GENHD_FL_HIDDEN)) + blk_unregister_region(disk_devt(disk), disk->minors); +out_unregister_bdi: + if (!(disk->flags & GENHD_FL_HIDDEN)) + bdi_unregister(disk->queue->backing_dev_info); +out_disk_release_events: + disk_release_events(disk); +out_free_ext_minor: + blk_free_devt(devt); + return WARN_ON_ONCE(retval); /* keep until all callers handle errors */ } -void device_add_disk(struct device *parent, struct gendisk *disk, +int device_add_disk(struct device *parent, struct gendisk *disk, const struct attribute_group **groups) { - __device_add_disk(parent, disk, groups, true); + return __device_add_disk(parent, disk, groups, true); } EXPORT_SYMBOL(device_add_disk); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 61b5e9359152..bd44031cf35b 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -305,11 +305,11 @@ extern bool disk_has_partitions(struct gendisk *disk); /* block/genhd.c */ extern unsigned int part_in_flight(struct hd_struct *part); -extern void device_add_disk(struct device *parent, struct gendisk *disk, +extern int device_add_disk(struct device *parent, struct gendisk *disk, const struct attribute_group **groups); -static inline void add_disk(struct gendisk *disk) +static inline int add_disk(struct gendisk *disk) { - device_add_disk(NULL, disk, NULL); + return device_add_disk(NULL, disk, NULL); } extern void device_add_disk_no_queue_reg(struct device *parent, struct gendisk *disk); static inline void add_disk_no_queue_reg(struct gendisk *disk) -- Gitee From 40a06eb91ba8003221e5ff0989bb9dcf8539aeeb Mon Sep 17 00:00:00 2001 From: Luis Chamberlain Date: Sat, 25 Nov 2023 09:23:32 +0800 Subject: [PATCH 08/17] block: fix device_add_disk() kobject_create_and_add() error handling mainline inclusion from mainline-v5.16-rc1 commit fe7d064fa3faec5d8157029fb8720b4fddc9e1e8 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fe7d064fa3faec5d8157029fb8720b4fddc9e1e8 ---------------------------------------- Commit 83cbce957446 ("block: add error handling for device_add_disk / add_disk") added error handling to device_add_disk(), however the goto label for the kobject_create_and_add() failure did not set the return value correctly, and so we can end up in a situation where kobject_create_and_add() fails but we report success. Fixes: 83cbce957446 ("block: add error handling for device_add_disk / add_disk") Reported-by: kernel test robot Reported-by: Dan Carpenter Signed-off-by: Luis Chamberlain Reviewed-by: Christoph Hellwig Link: https://lore.kernel.org/r/20211103164023.1384821-1-mcgrof@kernel.org [axboe: fold in followup fix from Wu Bo ] Signed-off-by: Jens Axboe conflict: block/genhd.c Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 3a2c8be1b79a..96db5ae191d6 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -858,11 +858,15 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj); - if (!disk->part0.holder_dir) + if (!disk->part0.holder_dir) { + retval = -ENOMEM; goto out_del_integrity; + } disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj); - if (!disk->slave_dir) + if (!disk->slave_dir) { + retval = -ENOMEM; goto out_put_holder_dir; + } if (!(disk->flags & GENHD_FL_HIDDEN)) { retval = sysfs_create_link(&ddev->kobj, -- Gitee From 2874bafed4cbf1431789293bf030f68f4ba6ff8b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 25 Nov 2023 09:23:33 +0800 Subject: [PATCH 09/17] block: fix error unwinding in device_add_disk mainline inclusion from mainline-v5.17-rc1 commit 99d8690aae4b2f0d1d90075de355ac087f820a66 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=99d8690aae4b2f0d1d90075de355ac087f820a66 ---------------------------------------- One device_add is called disk->ev will be freed by disk_release, so we should free it twice. Fix this by allocating disk->ev after device_add so that the extra local unwinding can be removed entirely. Based on an earlier patch from Tetsuo Handa. Reported-by: syzbot Tested-by: syzbot Fixes: 83cbce9574462c6b ("block: add error handling for device_add_disk / add_disk") Signed-off-by: Christoph Hellwig Link: https://lore.kernel.org/r/20211221161851.788424-1-hch@lst.de Signed-off-by: Jens Axboe conflict: block/genhd.c Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 96db5ae191d6..878d521523a2 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -800,10 +800,6 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, disk->major = MAJOR(devt); disk->first_minor = MINOR(devt); - retval = disk_alloc_events(disk); - if (retval) - goto out_free_ext_minor; - if (disk->flags & GENHD_FL_HIDDEN) { /* * Don't let hidden disks show up in /proc/partitions, @@ -818,7 +814,7 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, ddev->devt = devt; retval = bdi_register(bdi, "%u:%u", MAJOR(devt), MINOR(devt)); if (retval) - goto out_disk_release_events; + goto out_free_ext_minor; bdi_set_owner(bdi, ddev); retval = blk_register_region(disk_devt(disk), disk->minors, NULL, exact_match, exact_lock, disk); @@ -838,6 +834,9 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, retval = device_add(ddev); if (retval) goto out_unregister_region; + retval = disk_alloc_events(disk); + if (retval) + goto out_device_del; if (!sysfs_deprecated) { retval = sysfs_create_link(block_depr, &ddev->kobj, kobject_name(&ddev->kobj)); @@ -921,8 +920,6 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, out_unregister_bdi: if (!(disk->flags & GENHD_FL_HIDDEN)) bdi_unregister(disk->queue->backing_dev_info); -out_disk_release_events: - disk_release_events(disk); out_free_ext_minor: blk_free_devt(devt); return WARN_ON_ONCE(retval); /* keep until all callers handle errors */ -- Gitee From 1f663b6b4b4fccc1d6dcc6e7a0c78d9a9ea1b6a3 Mon Sep 17 00:00:00 2001 From: Zhong Jinghua Date: Sat, 25 Nov 2023 09:23:34 +0800 Subject: [PATCH 10/17] block: Fix the kabi change in device_add_disk hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK ---------------------------------------- Fix the kabi change caused by changing the return value of device_add_disk. Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 21 +++++++++++++++++++-- include/linux/genhd.h | 19 ++++++++++++++++--- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 878d521523a2..3c3ba1e7a62f 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -925,20 +925,37 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, return WARN_ON_ONCE(retval); /* keep until all callers handle errors */ } -int device_add_disk(struct device *parent, struct gendisk *disk, +void device_add_disk(struct device *parent, struct gendisk *disk, const struct attribute_group **groups) { - return __device_add_disk(parent, disk, groups, true); + __device_add_disk(parent, disk, groups, true); } EXPORT_SYMBOL(device_add_disk); + +int __must_check device_add_disk_safe(struct device *parent, + struct gendisk *disk, + const struct attribute_group **groups) + +{ + return __device_add_disk(parent, disk, groups, true); +} +EXPORT_SYMBOL(device_add_disk_safe); + void device_add_disk_no_queue_reg(struct device *parent, struct gendisk *disk) { __device_add_disk(parent, disk, NULL, false); } EXPORT_SYMBOL(device_add_disk_no_queue_reg); +int __must_check device_add_disk_no_queue_reg_safe(struct device *parent, + struct gendisk *disk) +{ + return __device_add_disk(parent, disk, NULL, false); +} +EXPORT_SYMBOL(device_add_disk_no_queue_reg_safe); + static void invalidate_partition(struct gendisk *disk, int partno) { struct block_device *bdev; diff --git a/include/linux/genhd.h b/include/linux/genhd.h index bd44031cf35b..92396234e96f 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -305,17 +305,30 @@ extern bool disk_has_partitions(struct gendisk *disk); /* block/genhd.c */ extern unsigned int part_in_flight(struct hd_struct *part); -extern int device_add_disk(struct device *parent, struct gendisk *disk, +extern void device_add_disk(struct device *parent, struct gendisk *disk, const struct attribute_group **groups); -static inline int add_disk(struct gendisk *disk) +extern int __must_check device_add_disk_safe(struct device *parent, + struct gendisk *disk, + const struct attribute_group **groups); +static inline void add_disk(struct gendisk *disk) { - return device_add_disk(NULL, disk, NULL); + device_add_disk(NULL, disk, NULL); } extern void device_add_disk_no_queue_reg(struct device *parent, struct gendisk *disk); +extern int __must_check device_add_disk_no_queue_reg_safe(struct device *parent, + struct gendisk *disk); static inline void add_disk_no_queue_reg(struct gendisk *disk) { device_add_disk_no_queue_reg(NULL, disk); } +static inline int __must_check add_disk_no_queue_reg_safe(struct gendisk *disk) +{ + return device_add_disk_no_queue_reg_safe(NULL, disk); +} +static inline int __must_check add_disk_safe(struct gendisk *disk) +{ + return device_add_disk_safe(NULL, disk, NULL); +} extern void del_gendisk(struct gendisk *gp); extern struct gendisk *get_gendisk(dev_t dev, int *partno); -- Gitee From 656e47282a27c8d0eeda37f0b0d0a36cbb9b59f1 Mon Sep 17 00:00:00 2001 From: Zhong Jinghua Date: Sat, 25 Nov 2023 09:23:35 +0800 Subject: [PATCH 11/17] block: Fix the kabi change on blk_register_region hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK ---------------------------------------- Fix kabi change caused by blk_register_region change return value. Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 8 ++++---- include/linux/genhd.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 3c3ba1e7a62f..ea4899e92788 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -651,11 +651,11 @@ static char *bdevt_str(dev_t devt, char *buf) * The hash chain is sorted on range, so that subranges can override. * Add error handling. */ -int blk_register_region(dev_t devt, unsigned long range, struct module *module, +void blk_register_region(dev_t devt, unsigned long range, struct module *module, struct kobject *(*probe)(dev_t, int *, void *), int (*lock)(dev_t, void *), void *data) { - return kobj_map(bdev_map, devt, range, module, probe, lock, data); + kobj_map(bdev_map, devt, range, module, probe, lock, data); } EXPORT_SYMBOL(blk_register_region); @@ -816,8 +816,8 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, if (retval) goto out_free_ext_minor; bdi_set_owner(bdi, ddev); - retval = blk_register_region(disk_devt(disk), disk->minors, - NULL, exact_match, exact_lock, disk); + retval = kobj_map(bdev_map, disk_devt(disk), disk->minors, NULL, + exact_match, exact_lock, disk); if (retval) goto out_unregister_bdi; } diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 92396234e96f..b0b9c4fa6311 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -374,7 +374,7 @@ extern struct gendisk *__alloc_disk_node(int minors, int node_id); extern struct kobject *get_disk_and_module(struct gendisk *disk); extern void put_disk(struct gendisk *disk); extern void put_disk_and_module(struct gendisk *disk); -extern int blk_register_region(dev_t devt, unsigned long range, +extern void blk_register_region(dev_t devt, unsigned long range, struct module *module, struct kobject *(*probe)(dev_t, int *, void *), int (*lock)(dev_t, void *), -- Gitee From 414b9469e35cefe8ae5ba0885f3082775921a920 Mon Sep 17 00:00:00 2001 From: Yu Kuai Date: Sat, 25 Nov 2023 09:23:36 +0800 Subject: [PATCH 12/17] block: fix memory leak for elevator on add_disk failure mainline inclusion from mainline-v6.1-rc3 commit 02341a08c9dec5a88527981b0bdf0fb6f7499cbf category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=02341a08c9dec5a88527981b0bdf0fb6f7499cbf ---------------------------------------- The default elevator is allocated in the beginning of device_add_disk(), however, it's not freed in the following error path. Fixes: 50e34d78815e ("block: disable the elevator int del_gendisk") Signed-off-by: Yu Kuai Reviewed-by: Christoph Hellwig Reviewed-by: Jason Yan Link: https://lore.kernel.org/r/20221022021615.2756171-1-yukuai1@huaweicloud.com Signed-off-by: Jens Axboe confilic: block/genhd.c Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index ea4899e92788..bfbc61be3ddd 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -786,6 +786,7 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, if (register_queue) elevator_init_mq(disk->queue); + retval = -EINVAL; /* minors == 0 indicates to use ext devt from part0 and should * be accompanied with EXT_DEVT flag. Make sure all * parameters make sense. @@ -796,7 +797,7 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, retval = blk_alloc_devt(&disk->part0, &devt); if (retval) - return retval; + goto out_exit_elevator; disk->major = MAJOR(devt); disk->first_minor = MINOR(devt); @@ -922,7 +923,14 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, bdi_unregister(disk->queue->backing_dev_info); out_free_ext_minor: blk_free_devt(devt); - return WARN_ON_ONCE(retval); /* keep until all callers handle errors */ +out_exit_elevator: + if (register_queue && disk->queue->elevator) { + mutex_lock(&disk->queue->sysfs_lock); + elevator_exit(disk->queue, disk->queue->elevator); + mutex_unlock(&disk->queue->sysfs_lock); + } + WARN_ON_ONCE(retval); /* keep until all callers handle errors */ + return retval; } void device_add_disk(struct device *parent, struct gendisk *disk, -- Gitee From a70f954158521786eaa3450c0ccde108f684f26a Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sat, 25 Nov 2023 09:23:37 +0800 Subject: [PATCH 13/17] block: check minor range in device_add_disk() mainline inclusion from mainline-v5.17-rc1 commit e338924bd05d6e71574bc13e310c89e10e49a8a5 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e338924bd05d6e71574bc13e310c89e10e49a8a5 ---------------------------------------- ioctl(fd, LOOP_CTL_ADD, 1048576) causes sysfs: cannot create duplicate filename '/dev/block/7:0' message because such request is treated as if ioctl(fd, LOOP_CTL_ADD, 0) due to MINORMASK == 1048575. Verify that all minor numbers for that device fit in the minor range. Reported-by: wangyangbo Signed-off-by: Tetsuo Handa Reviewed-by: Christoph Hellwig Link: https://lore.kernel.org/r/b1b19379-23ee-5379-0eb5-94bf5f79f1b4@i-love.sakura.ne.jp Signed-off-by: Jens Axboe conflict: block/genhd.c Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/block/genhd.c b/block/genhd.c index bfbc61be3ddd..1f2940cbb68e 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -795,6 +795,9 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, WARN_ON(!disk->minors && !(disk->flags & (GENHD_FL_EXT_DEVT | GENHD_FL_HIDDEN))); + if (disk->minors != 0 && + disk->first_minor + disk->minors > MINORMASK + 1) + goto out_exit_elevator; retval = blk_alloc_devt(&disk->part0, &devt); if (retval) goto out_exit_elevator; -- Gitee From 0129bade6dd13b1ae77f3cd2d446422c5a126925 Mon Sep 17 00:00:00 2001 From: Zhong Jinghua Date: Sat, 25 Nov 2023 09:23:38 +0800 Subject: [PATCH 14/17] block: call blk_get_queue earlier in __device_add_disk hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK ---------------------------------------- When adding a disk, first obtain the reference count of the request_queue, and release the reference count when error handling, which will make it easier for the driver to add error handling. Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 1f2940cbb68e..d03588201416 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -777,6 +777,11 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, dev_t devt; int retval; + /* + * Take an extra ref on queue which will be put on disk_release() + * so that it sticks around as long as @disk is there. + */ + WARN_ON_ONCE(!blk_get_queue(disk->queue)); /* * The disk queue should now be all set with enough information about * the device for the elevator code to pick an adequate default @@ -884,12 +889,6 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, goto out_del_bdi_sysfs_link; } - /* - * Take an extra ref on queue which will be put on disk_release() - * so that it sticks around as long as @disk is there. - */ - WARN_ON_ONCE(!blk_get_queue(disk->queue)); - disk_add_events(disk); /* Make sure the first partition scan will be proceed */ -- Gitee From a8adbe043b7a98fe3813fd55a1b2acc6e63ab92b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 25 Nov 2023 09:23:39 +0800 Subject: [PATCH 15/17] block: clear ->slave_dir when dropping the main slave_dir reference mainline inclusion from mainline-v6.2-rc1 commit d90db3b1c8676bc88b4309c5a571333de2263b8e category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d90db3b1c8676bc88b4309c5a571333de2263b8e ---------------------------------------- Zero out the pointer to ->slave_dir so that the holder code doesn't incorrectly treat the object as alive when add_disk failed or after del_gendisk was called. Fixes: 89f871af1b26 ("dm: delay registering the gendisk") Reported-by: Yu Kuai Signed-off-by: Christoph Hellwig Signed-off-by: Yu Kuai Reviewed-by: Mike Snitzer Link: https://lore.kernel.org/r/20221115141054.1051801-2-yukuai1@huaweicloud.com Signed-off-by: Jens Axboe conflict: block/genhd.c Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/block/genhd.c b/block/genhd.c index d03588201416..ff61a19b2260 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -908,6 +908,7 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, sysfs_remove_link(&ddev->kobj, "bdi"); out_put_slave_dir: kobject_put(disk->slave_dir); + disk->slave_dir = NULL; out_put_holder_dir: kobject_put(disk->part0.holder_dir); out_del_integrity: @@ -1059,6 +1060,7 @@ void del_gendisk(struct gendisk *disk) kobject_put(disk->part0.holder_dir); kobject_put(disk->slave_dir); + disk->slave_dir = NULL; part_stat_set_all(&disk->part0, 0); disk->part0.stamp = 0; -- Gitee From 3fa79ac404d6a5c45d33a166b8675faf19ffd691 Mon Sep 17 00:00:00 2001 From: Zhong Jinghua Date: Sat, 25 Nov 2023 09:23:40 +0800 Subject: [PATCH 16/17] block: Fix minor range check in device_add_disk() hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK ---------------------------------------- Checks added in patch: 51901d95c47e("block: check minor range in device_add_disk()") ignore the problem of first_minore < 0 and disk->minors < 0. Fix it by adding first_minore < 0 and disk->minors < 0 check. Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index ff61a19b2260..aa8e22f026a5 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -800,8 +800,9 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, WARN_ON(!disk->minors && !(disk->flags & (GENHD_FL_EXT_DEVT | GENHD_FL_HIDDEN))); - if (disk->minors != 0 && - disk->first_minor + disk->minors > MINORMASK + 1) + if (disk->minors != 0 && (disk->first_minor > MINORMASK || + disk->minors > (1U << MINORBITS) || + disk->first_minor + disk->minors > (1U << MINORBITS))) goto out_exit_elevator; retval = blk_alloc_devt(&disk->part0, &devt); if (retval) -- Gitee From ffe0955ad7bbbd1228328734776c951970b6e6a8 Mon Sep 17 00:00:00 2001 From: Zhong Jinghua Date: Sat, 25 Nov 2023 09:23:41 +0800 Subject: [PATCH 17/17] block: Set memalloc_noio to false in the error path hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81XCK ---------------------------------------- In del_gendisk, memalloc_noio is set to false, so it would be better to do the same thing in the error path. Fixes: c6b84a94528e ("block: add error handling for device_add_disk / add_disk") Signed-off-by: Zhong Jinghua Signed-off-by: Li Nan --- block/genhd.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/block/genhd.c b/block/genhd.c index aa8e22f026a5..e5df4d63ecd2 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -917,6 +917,11 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, out_del_block_link: if (!sysfs_deprecated) sysfs_remove_link(block_depr, kobject_name(&ddev->kobj)); + /* + * The error path needs to set memalloc_noio to false + * consistent with del_gendisk. + */ + pm_runtime_set_memalloc_noio(ddev, false); out_device_del: device_del(ddev); out_unregister_region: -- Gitee