To make applying the mainline patch easier, reorder the nbd commit about the first_minor check here.
Christoph Hellwig (5): block: fold register_disk into device_add_disk block: call blk_integrity_add earlier in device_add_disk block: add the events* attributes to disk_attrs block: fix error unwinding in device_add_disk block: clear ->slave_dir when dropping the main slave_dir reference
Luis Chamberlain (4): block: return errors from blk_integrity_add block: return errors from disk_alloc_events block: add error handling for device_add_disk / add_disk block: fix device_add_disk() kobject_create_and_add() error handling
Tetsuo Handa (1): block: check minor range in device_add_disk()
Wen Yang (1): Revert "Revert "block: nbd: add sanity check for first_minor""
Yu Kuai (3): nbd: fix max value for 'first_minor' nbd: fix possible overflow for 'first_minor' in nbd_dev_add() block: fix memory leak for elevator on add_disk failure
Zhang Wensheng (1): nbd: fix possible overflow on 'first_minor' in nbd_dev_add()
Zhong Jinghua (7): nbd: Reorganize the messy commit log about the first_minor check block: return errors from blk_register_region block: Fix the kabi change in device_add_disk block: Fix the kabi change on blk_register_region block: call blk_get_queue earlier in __device_add_disk block: Fix minor range check in device_add_disk() block: Set memalloc_noio to false in the error path
block/blk.h | 5 +- include/linux/genhd.h | 13 +++ block/blk-integrity.c | 12 ++- block/genhd.c | 246 +++++++++++++++++++++++++----------------- drivers/block/nbd.c | 15 +-- 5 files changed, 175 insertions(+), 116 deletions(-)
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,转换为PR失败! 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/U... 失败原因:应用补丁/补丁集失败,Patch failed at 0001 nbd: Reorganize the messy commit log about the first_minor check 建议解决方法:请查看失败原因, 确认补丁是否可以应用在当前期望分支的最新代码上
FeedBack: The patch(es) which you have sent to kernel@openeuler.org has been converted to PR failed! Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/U... Failed Reason: apply patch(es) failed, Patch failed at 0001 nbd: Reorganize the messy commit log about the first_minor check Suggest Solution: please checkout if the failed patch(es) can work on the newest codes in expected branch
From: Zhong Jinghua zhongjinghua@huawei.com
hulk inclusion category: bugfix bugzilla: 188217
----------------------------------------
Commits on our branch with check issues on first_minor had serious confusion, resulting in duplicate checks in nbd_dev_add and nbd_genl_connect.
So I revert the messy commit, backport lts patch.
Revert 84c282c6ad41 ("nbd: fix possible overflow for 'first_minor' in nbd_dev_add()") Revert 39a42d5e5137 ("nbd: fix max value for 'first_minor'") Revert 3ddba49a1d3b ("Revert "Revert "block: nbd: add sanity check for first_minor""") Revert 3bb2913d0cc5 ("nbd: fix assignment error for first_minor in nbd_dev_add") Revert 648bb72a02a3 ("nbd: fix possible overflow on 'first_minor' in nbd_dev_add()") Revert 60141517d289 ("nbd: Fix use-after-free in blk_mq_free_rqs") Revert 98d3ad1d2589 ("nbd: add sanity check for first_minor")
Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- drivers/block/nbd.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index fa08f380f5be..29884a0f1fca 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1875,17 +1875,7 @@ static int nbd_dev_add(int index) refcount_set(&nbd->refs, 1); INIT_LIST_HEAD(&nbd->list); disk->major = NBD_MAJOR; - - /* Too big first_minor can cause duplicate creation of - * sysfs files/links, since index << part_shift might overflow, or - * MKDEV() expect that the max bits of first_minor is 20. - */ disk->first_minor = index << part_shift; - if (disk->first_minor < index || disk->first_minor > MINORMASK) { - err = -EINVAL; - goto out_free_idr; - } - disk->fops = &nbd_fops; disk->private_data = nbd; sprintf(disk->disk_name, "nbd%d", index); @@ -1972,20 +1962,8 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) if (!netlink_capable(skb, CAP_SYS_ADMIN)) return -EPERM;
- if (info->attrs[NBD_ATTR_INDEX]) { + if (info->attrs[NBD_ATTR_INDEX]) index = nla_get_u32(info->attrs[NBD_ATTR_INDEX]); - - /* - * Too big first_minor can cause duplicate creation of - * sysfs files/links, since index << part_shift might - * overflow, or MKDEV() expect that the max bits of - * first_minor is 20. - */ - if (index < 0 || index > MINORMASK >> part_shift) { - printk(KERN_ERR "nbd: illegal input index %d\n", index); - return -EINVAL; - } - } if (!info->attrs[NBD_ATTR_SOCKETS]) { printk(KERN_ERR "nbd: must specify at least one socket\n"); return -EINVAL;
From: Wen Yang wenyang.linux@foxmail.com
stable inclusion from stable-v5.10.170 commit f3f6b33b77bac0bd27f1f1bec05ab58a54948fc9 category: bugfix bugzilla: 188217
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
This reverts commit 0daa75bf750c400af0a0127fae37cd959d36dee7.
These problems such as: https://lore.kernel.org/all/CACPK8XfUWoOHr-0RwRoYoskia4fbAbZ7DYf5wWBnv6qUnGq... It was introduced by introduced by commit b1a811633f73 ("block: nbd: add sanity check for first_minor") and has been have been fixed by commit e4c4871a7394 ("nbd: fix max value for 'first_minor'").
Cc: Joel Stanley joel@jms.id.au Cc: Christoph Hellwig hch@lst.de Cc: Pavel Skripkin paskripkin@gmail.com Cc: Jens Axboe axboe@kernel.dk Cc: Sasha Levin sashal@kernel.org Cc: stable@vger.kernel.org # v5.10+ Signed-off-by: Wen Yang wenyang.linux@foxmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- drivers/block/nbd.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 29884a0f1fca..7f26571a8ca0 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1875,7 +1875,17 @@ static int nbd_dev_add(int index) refcount_set(&nbd->refs, 1); INIT_LIST_HEAD(&nbd->list); disk->major = NBD_MAJOR; + + /* Too big first_minor can cause duplicate creation of + * sysfs files/links, since first_minor will be truncated to + * byte in __device_add_disk(). + */ disk->first_minor = index << part_shift; + if (disk->first_minor > 0xff) { + err = -EINVAL; + goto out_free_idr; + } + disk->fops = &nbd_fops; disk->private_data = nbd; sprintf(disk->disk_name, "nbd%d", index);
From: Yu Kuai yukuai3@huawei.com
stable inclusion from stable-v5.10.170 commit fd8107206a672f5a529a819e8930bf81fb54ae0f category: bugfix bugzilla: 188217
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
commit e4c4871a73944353ea23e319de27ef73ce546623 upstream.
commit b1a811633f73 ("block: nbd: add sanity check for first_minor") checks that 'first_minor' should not be greater than 0xff, which is wrong. Whitout the commit, the details that when user pass 0x100000, it ends up create sysfs dir "/sys/block/43:0" are as follows:
nbd_dev_add disk->first_minor = index << part_shift -> default part_shift is 5, first_minor is 0x2000000 device_add_disk ddev->devt = MKDEV(disk->major, disk->first_minor) -> (0x2b << 20) | (0x2000000) = 0x2b00000 device_add device_create_sys_dev_entry format_dev_t sprintf(buffer, "%u:%u", MAJOR(dev), MINOR(dev)); -> got 43:0 sysfs_create_link -> /sys/block/43:0
By the way, with the wrong fix, when part_shift is the default value, only 8 ndb devices can be created since 8 << 5 is greater than 0xff.
Since the max bits for 'first_minor' should be the same as what MKDEV() does, which is 20. Change the upper bound of 'first_minor' from 0xff to 0xfffff.
Fixes: b1a811633f73 ("block: nbd: add sanity check for first_minor") Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Josef Bacik josef@toxicpanda.com Link: https://lore.kernel.org/r/20211102015237.2309763-2-yebin10@huawei.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Wen Yang wenyang.linux@foxmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- drivers/block/nbd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 7f26571a8ca0..626e83fc0d81 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1877,11 +1877,11 @@ static int nbd_dev_add(int index) disk->major = NBD_MAJOR;
/* Too big first_minor can cause duplicate creation of - * sysfs files/links, since first_minor will be truncated to - * byte in __device_add_disk(). + * sysfs files/links, since MKDEV() expect that the max bits of + * first_minor is 20. */ disk->first_minor = index << part_shift; - if (disk->first_minor > 0xff) { + if (disk->first_minor > MINORMASK) { err = -EINVAL; goto out_free_idr; }
From: Yu Kuai yukuai3@huawei.com
stable inclusion from stable-v5.10.170 commit 2e0c3e43ebb99c2b495229f8fade4c043fbd06a5 category: bugfix bugzilla: 188217
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
commit 940c264984fd1457918393c49674f6b39ee16506 upstream.
If 'part_shift' is not zero, then 'index << part_shift' might overflow to a value that is not greater than '0xfffff', then sysfs might complains about duplicate creation.
Fixes: b0d9111a2d53 ("nbd: use an idr to keep track of nbd devices") Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Josef Bacik josef@toxicpanda.com Link: https://lore.kernel.org/r/20211102015237.2309763-3-yebin10@huawei.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Wen Yang wenyang.linux@foxmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- drivers/block/nbd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 626e83fc0d81..8290c1ac2e4f 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1877,11 +1877,11 @@ static int nbd_dev_add(int index) disk->major = NBD_MAJOR;
/* Too big first_minor can cause duplicate creation of - * sysfs files/links, since MKDEV() expect that the max bits of - * first_minor is 20. + * sysfs files/links, since index << part_shift might overflow, or + * MKDEV() expect that the max bits of first_minor is 20. */ disk->first_minor = index << part_shift; - if (disk->first_minor > MINORMASK) { + if (disk->first_minor < index || disk->first_minor > MINORMASK) { err = -EINVAL; goto out_free_idr; }
From: Zhang Wensheng zhangwensheng5@huawei.com
stable inclusion from stable-v5.10.170 commit 4311ad1e7654f9dd569a4d1b0059f838f474e9d3 category: bugfix bugzilla: 188217
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
commit 858f1bf65d3d9c00b5e2d8ca87dc79ed88267c98 upstream.
When 'index' is a big numbers, it may become negative which forced to 'int'. then 'index << part_shift' might overflow to a positive value that is not greater than '0xfffff', then sysfs might complains about duplicate creation. Because of this, move the 'index' judgment to the front will fix it and be better.
Fixes: b0d9111a2d53 ("nbd: use an idr to keep track of nbd devices") Fixes: 940c264984fd ("nbd: fix possible overflow for 'first_minor' in nbd_dev_add()") Signed-off-by: Zhang Wensheng zhangwensheng5@huawei.com Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Josef Bacik josef@toxicpanda.com Link: https://lore.kernel.org/r/20220521073749.3146892-6-yukuai3@huawei.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Wen Yang wenyang.linux@foxmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- drivers/block/nbd.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 8290c1ac2e4f..33113d6d668f 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1875,17 +1875,7 @@ static int nbd_dev_add(int index) refcount_set(&nbd->refs, 1); INIT_LIST_HEAD(&nbd->list); disk->major = NBD_MAJOR; - - /* Too big first_minor can cause duplicate creation of - * sysfs files/links, since index << part_shift might overflow, or - * MKDEV() expect that the max bits of first_minor is 20. - */ disk->first_minor = index << part_shift; - if (disk->first_minor < index || disk->first_minor > MINORMASK) { - err = -EINVAL; - goto out_free_idr; - } - disk->fops = &nbd_fops; disk->private_data = nbd; sprintf(disk->disk_name, "nbd%d", index); @@ -1972,8 +1962,19 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) if (!netlink_capable(skb, CAP_SYS_ADMIN)) return -EPERM;
- if (info->attrs[NBD_ATTR_INDEX]) + if (info->attrs[NBD_ATTR_INDEX]) { index = nla_get_u32(info->attrs[NBD_ATTR_INDEX]); + + /* + * Too big first_minor can cause duplicate creation of + * sysfs files/links, since index << part_shift might overflow, or + * MKDEV() expect that the max bits of first_minor is 20. + */ + if (index < 0 || index > MINORMASK >> part_shift) { + printk(KERN_ERR "nbd: illegal input index %d\n", index); + return -EINVAL; + } + } if (!info->attrs[NBD_ATTR_SOCKETS]) { printk(KERN_ERR "nbd: must specify at least one socket\n"); return -EINVAL;
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v5.15-rc1 commit 52b85909f85d06efa69aaf4210e72467f1f58d2b category: bugfix bugzilla: 188733
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
There is no real reason these should be separate. Also simplify the groups assignment a bit.
Signed-off-by: Christoph Hellwig hch@lst.de Link: https://lore.kernel.org/r/20210818144542.19305-3-hch@lst.de Signed-off-by: Jens Axboe axboe@kernel.dk conflict: block/genhd.c Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- 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);
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v5.15-rc1 commit bab53f6b617d9f530978d6e3693f88e586d81a8a category: bugfix bugzilla: 188733
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
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 hch@lst.de Reviewed-by: Hannes Reinecke hare@suse.de Link: https://lore.kernel.org/r/20210818144542.19305-6-hch@lst.de Signed-off-by: Jens Axboe axboe@kernel.dk conflict: block/genhd.c Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- 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))
From: Luis Chamberlain mcgrof@kernel.org
mainline inclusion from mainline-v5.15-rc1 commit 614310c9c8ca15359f4e71a5bbd9165897b4d54e category: bugfix bugzilla: 188733
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
Prepare for proper error handling in add_disk.
Signed-off-by: Luis Chamberlain mcgrof@kernel.org [hch: split from a larger patch] Signed-off-by: Christoph Hellwig hch@lst.de Reviewed-by: Hannes Reinecke hare@suse.de Link: https://lore.kernel.org/r/20210818144542.19305-8-hch@lst.de Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- block/blk.h | 5 +++-- block/blk-integrity.c | 12 +++++++----- 2 files changed, 10 insertions(+), 7 deletions(-)
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) { 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)
From: Luis Chamberlain mcgrof@kernel.org
mainline inclusion from mainline-v5.15-rc1 commit 92e7755ebc69233e25a2d1b760aeff536dc4016b category: bugfix bugzilla: 188733
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
Prepare for proper error handling in add_disk.
Signed-off-by: Luis Chamberlain mcgrof@kernel.org [hch: split from a larger patch] Signed-off-by: Christoph Hellwig hch@lst.de Reviewed-by: Hannes Reinecke hare@suse.de Link: https://lore.kernel.org/r/20210818144542.19305-9-hch@lst.de Signed-off-by: Jens Axboe axboe@kernel.dk conflict: block/genhd.c Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- 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)
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v5.14-rc1 commit 2bc8cda5ea4b42ff78be1b11011092d57b424d37 category: bugfix bugzilla: 188733
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
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 hch@lst.de Reviewed-by: Hannes Reinecke hare@suse.de Link: https://lore.kernel.org/r/20210624073843.251178-3-hch@lst.de Signed-off-by: Jens Axboe axboe@kernel.dk conflict: block/genhd.c Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- 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)
From: Zhong Jinghua zhongjinghua@huawei.com
hulk inclusion category: bugfix bugzilla: 188733
----------------------------------------
Modify the return value type of blk_register_region to prepare for adding error handling.
Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- include/linux/genhd.h | 2 +- block/genhd.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-)
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 *), 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);
From: Luis Chamberlain mcgrof@kernel.org
mainline inclusion from mainline-v5.15-rc1 commit 83cbce9574462c6b4eed6797bdaf18fae6859ab3 category: bugfix bugzilla: 188733
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
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 mcgrof@kernel.org [hch: major rebase. All bugs are probably mine] Signed-off-by: Christoph Hellwig hch@lst.de Reviewed-by: Hannes Reinecke hare@suse.de Link: https://lore.kernel.org/r/20210818144542.19305-10-hch@lst.de Signed-off-by: Jens Axboe axboe@kernel.dk conflicts: block/genhd.c include/linux/genhd.h Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- include/linux/genhd.h | 6 +-- block/genhd.c | 95 +++++++++++++++++++++++++++++-------------- 2 files changed, 67 insertions(+), 34 deletions(-)
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) 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);
From: Luis Chamberlain mcgrof@kernel.org
mainline inclusion from mainline-v5.16-rc1 commit fe7d064fa3faec5d8157029fb8720b4fddc9e1e8 category: bugfix bugzilla: 188733
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
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 lkp@intel.com Reported-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Luis Chamberlain mcgrof@kernel.org Reviewed-by: Christoph Hellwig hch@lst.de Link: https://lore.kernel.org/r/20211103164023.1384821-1-mcgrof@kernel.org [axboe: fold in followup fix from Wu Bo wubo40@huawei.com] Signed-off-by: Jens Axboe axboe@kernel.dk conflict: block/genhd.c Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- 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,
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v5.17-rc1 commit 99d8690aae4b2f0d1d90075de355ac087f820a66 category: bugfix bugzilla: 188733
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
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 syzbot+28a66a9fbc621c939000@syzkaller.appspotmail.com Tested-by: syzbot syzbot+28a66a9fbc621c939000@syzkaller.appspotmail.com Fixes: 83cbce9574462c6b ("block: add error handling for device_add_disk / add_disk") Signed-off-by: Christoph Hellwig hch@lst.de Link: https://lore.kernel.org/r/20211221161851.788424-1-hch@lst.de Signed-off-by: Jens Axboe axboe@kernel.dk conflict: block/genhd.c Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- 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 */
From: Zhong Jinghua zhongjinghua@huawei.com
hulk inclusion category: bugfix bugzilla: 188733
----------------------------------------
Fix the kabi change caused by changing the return value of device_add_disk.
Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- include/linux/genhd.h | 19 ++++++++++++++++--- block/genhd.c | 21 +++++++++++++++++++-- 2 files changed, 35 insertions(+), 5 deletions(-)
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); 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;
From: Zhong Jinghua zhongjinghua@huawei.com
hulk inclusion category: bugfix bugzilla: 188733
----------------------------------------
Fix kabi change caused by blk_register_region change return value.
Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- include/linux/genhd.h | 2 +- block/genhd.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-)
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 *), 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; }
From: Yu Kuai yukuai3@huawei.com
mainline inclusion from mainline-v6.1-rc3 commit 02341a08c9dec5a88527981b0bdf0fb6f7499cbf category: bugfix bugzilla: 188733
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
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 yukuai3@huawei.com Reviewed-by: Christoph Hellwig hch@lst.de Reviewed-by: Jason Yan yanaijie@huawei.com Link: https://lore.kernel.org/r/20221022021615.2756171-1-yukuai1@huaweicloud.com Signed-off-by: Jens Axboe axboe@kernel.dk confilic: block/genhd.c Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- 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,
From: Tetsuo Handa penguin-kernel@i-love.sakura.ne.jp
mainline inclusion from mainline-v5.17-rc1 commit e338924bd05d6e71574bc13e310c89e10e49a8a5 category: bugfix bugzilla: 188733
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
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 wangyangbo@uniontech.com Signed-off-by: Tetsuo Handa penguin-kernel@I-love.SAKURA.ne.jp Reviewed-by: Christoph Hellwig hch@lst.de Link: https://lore.kernel.org/r/b1b19379-23ee-5379-0eb5-94bf5f79f1b4@i-love.sakura... Signed-off-by: Jens Axboe axboe@kernel.dk conflict: block/genhd.c Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- 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;
From: Zhong Jinghua zhongjinghua@huaweicloud.com
hulk inclusion category: bugfix bugzilla: 188733
----------------------------------------
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 zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- 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 */
From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v6.2-rc1 commit d90db3b1c8676bc88b4309c5a571333de2263b8e category: bugfix bugzilla: 188733
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
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 yukuai3@huawei.com Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Mike Snitzer snitzer@kernel.org Link: https://lore.kernel.org/r/20221115141054.1051801-2-yukuai1@huaweicloud.com Signed-off-by: Jens Axboe axboe@kernel.dk conflict: block/genhd.c Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- 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;
From: Zhong Jinghua zhongjinghua@huawei.com
hulk inclusion category: bugfix bugzilla: 188733
----------------------------------------
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 zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- 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)
From: Zhong Jinghua zhongjinghua@huawei.com
hulk inclusion category: bugfix bugzilla: 188217
----------------------------------------
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 zhongjinghua@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- 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: