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()
Yu Kuai (1): block: fix memory leak for elevator on add_disk failure
Zhong Jinghua (6): 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 +++++++++++++++++++++++++----------------- 4 files changed, 173 insertions(+), 103 deletions(-)
From: Christoph Hellwig hch@lst.de
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/?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 3c34dd011585..0f169bdf5b36 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; @@ -813,6 +764,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;
@@ -852,18 +804,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: zhangwensheng zhangwensheng5@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4QXS1?from=project-issue CVE: NA
--------------------------------
UBSAN reports this problem:
[ 5984.281385] UBSAN: Undefined behaviour in drivers/md/md.c:8175:15 [ 5984.281390] signed integer overflow: [ 5984.281393] -2147483291 - 2072033152 cannot be represented in type 'int' [ 5984.281400] CPU: 25 PID: 1854 Comm: md101_resync Kdump: loaded Not tainted 4.19.90 [ 5984.281404] Hardware name: Huawei TaiShan 200 (Model 5280)/BC82AMDDA [ 5984.281406] Call trace: [ 5984.281415] dump_backtrace+0x0/0x310 [ 5984.281418] show_stack+0x28/0x38 [ 5984.281425] dump_stack+0xec/0x15c [ 5984.281430] ubsan_epilogue+0x18/0x84 [ 5984.281434] handle_overflow+0x14c/0x19c [ 5984.281439] __ubsan_handle_sub_overflow+0x34/0x44 [ 5984.281445] is_mddev_idle+0x338/0x3d8 [ 5984.281449] md_do_sync+0x1bb8/0x1cf8 [ 5984.281452] md_thread+0x220/0x288 [ 5984.281457] kthread+0x1d8/0x1e0 [ 5984.281461] ret_from_fork+0x10/0x18
When the stat aacum of the disk is greater than INT_MAX, its value becomes negative after casting to 'int', which may lead to overflow after subtracting a positive number. In the same way, when the value of sync_io is greater than INT_MAX,overflow may also occur. These situations will lead to undefined behavior.
Otherwise, if the stat accum of the disk is close to INT_MAX when creating raid arrays, the initial value of last_events would be set close to INT_MAX when mddev initializes IO event counters. 'curr_events - rdev->last_events > 64' will always false during synchronization. If all the disks of mddev are in this case, is_mddev_idle() will always return 1, which may cause non-sync IO is very slow.
To address these problems, need to use 64bit signed integer type for sync_io,last_events, and curr_events.
Signed-off-by: zhangwensheng zhangwensheng5@huawei.com Reviewed-by: Tao Hou houtao1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.h | 6 +++--- include/linux/genhd.h | 2 +- drivers/md/md.c | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/md/md.h b/drivers/md/md.h index 766ecfb0ff5c..85177d068322 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -50,7 +50,7 @@ struct md_rdev {
sector_t sectors; /* Device size (in 512bytes sectors) */ struct mddev *mddev; /* RAID array if running */ - int last_events; /* IO event timestamp */ + long long last_events; /* IO event timestamp */
/* * If meta_bdev is non-NULL, it means that a separate device is @@ -554,12 +554,12 @@ extern void mddev_unlock(struct mddev *mddev);
static inline void md_sync_acct(struct block_device *bdev, unsigned long nr_sectors) { - atomic_add(nr_sectors, &bdev->bd_disk->sync_io); + atomic64_add(nr_sectors, &bdev->bd_disk->sync_io_sectors); }
static inline void md_sync_acct_bio(struct bio *bio, unsigned long nr_sectors) { - atomic_add(nr_sectors, &bio->bi_disk->sync_io); + atomic64_add(nr_sectors, &bio->bi_disk->sync_io_sectors); }
struct md_personality diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 47ee862a7c56..09da27361620 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -208,7 +208,7 @@ struct gendisk { struct kobject *slave_dir;
struct timer_rand_state *random; - atomic_t sync_io; /* RAID */ + atomic64_t sync_io_sectors; /* RAID */ struct disk_events *ev; #ifdef CONFIG_BLK_DEV_INTEGRITY struct kobject integrity_kobj; diff --git a/drivers/md/md.c b/drivers/md/md.c index 03437140b05b..a299fda5b0e9 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -8430,14 +8430,15 @@ static int is_mddev_idle(struct mddev *mddev, int init) { struct md_rdev *rdev; int idle; - int curr_events; + long long curr_events;
idle = 1; rcu_read_lock(); rdev_for_each_rcu(rdev, mddev) { struct gendisk *disk = rdev->bdev->bd_disk; - curr_events = (int)part_stat_read_accum(&disk->part0, sectors) - - atomic_read(&disk->sync_io); + curr_events = + (long long)part_stat_read_accum(&disk->part0, sectors) - + atomic64_read(&disk->sync_io_sectors); /* sync IO will cause sync_io to increase before the disk_stats * as sync_io is counted when a request starts, and * disk_stats is counted when it completes.
From: Christoph Hellwig hch@lst.de
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/?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 0f169bdf5b36..04a3adc65e63 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -842,6 +842,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); @@ -865,7 +867,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: https://gitee.com/openeuler/kernel/issues/I81XCK
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: https://gitee.com/openeuler/kernel/issues/I81XCK
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 04a3adc65e63..7f20a4cb523e 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); @@ -2389,17 +2389,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); @@ -2411,6 +2411,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: https://gitee.com/openeuler/kernel/issues/I81XCK
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 7f20a4cb523e..33d5f8632030 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 @@ -1506,6 +1509,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 @@ -2336,18 +2342,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 @@ -2416,11 +2414,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;
@@ -2444,8 +2437,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: 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 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 33d5f8632030..c620597cfc0d 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: https://gitee.com/openeuler/kernel/issues/I81XCK
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 c620597cfc0d..599885e5bf64 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -761,10 +761,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) { @@ -790,14 +788,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) { /* @@ -808,15 +806,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 */ @@ -828,15 +828,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; }
/* @@ -846,23 +845,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() @@ -882,13 +888,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: https://gitee.com/openeuler/kernel/issues/I81XCK
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 599885e5bf64..ca082822d48a 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -851,11 +851,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: https://gitee.com/openeuler/kernel/issues/I81XCK
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 ca082822d48a..dff4b67e947d 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -793,10 +793,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, @@ -811,7 +807,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); @@ -831,6 +827,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)); @@ -914,8 +913,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: 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 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 dff4b67e947d..ec0b707cca7c 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -918,20 +918,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: https://gitee.com/openeuler/kernel/issues/I81XCK
----------------------------------------
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 ec0b707cca7c..521611ce85e0 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); @@ -809,8 +809,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: https://gitee.com/openeuler/kernel/issues/I81XCK
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 521611ce85e0..068a8005f0f6 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -779,6 +779,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. @@ -789,7 +790,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);
@@ -915,7 +916,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: https://gitee.com/openeuler/kernel/issues/I81XCK
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 068a8005f0f6..1af07f0e5387 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -788,6 +788,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: 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 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 1af07f0e5387..88acd84065ca 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -770,6 +770,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 @@ -877,12 +882,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: https://gitee.com/openeuler/kernel/issues/I81XCK
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 88acd84065ca..e004a93ccb22 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -901,6 +901,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: @@ -1052,6 +1053,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: 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 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 e004a93ccb22..c3eaabaaa154 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -793,8 +793,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: 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 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 c3eaabaaa154..96fcdbb78c07 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -910,6 +910,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:
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/2970 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/2...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/2970 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/2...