* [PATCH 0/2] block: 7th -- last batch of add_disk() error handling conversions @ 2021-09-04 1:39 Luis Chamberlain 2021-09-04 1:39 ` [PATCH 1/2] block: make __register_blkdev() return an error Luis Chamberlain 2021-09-04 1:39 ` [PATCH 2/2] block: add __must_check for *add_disk*() callers Luis Chamberlain 0 siblings, 2 replies; 11+ messages in thread From: Luis Chamberlain @ 2021-09-04 1:39 UTC (permalink / raw) To: axboe, hch, efremov, song, jejb, martin.petersen, viro, hare, jack, ming.lei, tj Cc: linux-raid, linux-scsi, linux-fsdevel, linux-block, linux-kernel, Luis Chamberlain This is the 7th and final set of changes to convert all drivers over to use and finally enforce add_disk() error handling. This set deals with those old drivers using __register_blkdev() which in turn have a respective add_disk() call made. The last patch ensures we won't add new drivers without a check for the add_disk() call. You can find the full set of patches on my kernel.org linux 20210901-for-axboe-add-disk-error-handling branch [0] which is now based on axboe/master. [0] https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git/log/?h=20210901-for-axboe-add-disk-error-handling Luis Chamberlain (2): block: make __register_blkdev() return an error block: add __must_check for *add_disk*() callers block/genhd.c | 21 ++++++++++++--------- drivers/block/ataflop.c | 20 +++++++++++++++----- drivers/block/brd.c | 7 +++++-- drivers/block/floppy.c | 14 ++++++++++---- drivers/block/loop.c | 6 +++--- drivers/md/md.c | 10 +++++++--- drivers/scsi/sd.c | 3 ++- fs/block_dev.c | 5 ++++- include/linux/genhd.h | 10 +++++----- 9 files changed, 63 insertions(+), 33 deletions(-) -- 2.30.2 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/2] block: make __register_blkdev() return an error 2021-09-04 1:39 [PATCH 0/2] block: 7th -- last batch of add_disk() error handling conversions Luis Chamberlain @ 2021-09-04 1:39 ` Luis Chamberlain 2021-09-04 2:49 ` Tetsuo Handa 2021-09-04 1:39 ` [PATCH 2/2] block: add __must_check for *add_disk*() callers Luis Chamberlain 1 sibling, 1 reply; 11+ messages in thread From: Luis Chamberlain @ 2021-09-04 1:39 UTC (permalink / raw) To: axboe, hch, efremov, song, jejb, martin.petersen, viro, hare, jack, ming.lei, tj Cc: linux-raid, linux-scsi, linux-fsdevel, linux-block, linux-kernel, Luis Chamberlain This makes __register_blkdev() return an error, and also changes the probe() call to return an error as well. Signed-off-by: Luis Chamberlain <mcgrof@kernel.org> --- block/genhd.c | 15 +++++++++------ drivers/block/ataflop.c | 20 +++++++++++++++----- drivers/block/brd.c | 7 +++++-- drivers/block/floppy.c | 14 ++++++++++---- drivers/block/loop.c | 6 +++--- drivers/md/md.c | 10 +++++++--- drivers/scsi/sd.c | 3 ++- fs/block_dev.c | 5 ++++- include/linux/genhd.h | 4 ++-- 9 files changed, 57 insertions(+), 27 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 567549a011d1..c4836296a974 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -180,7 +180,7 @@ static struct blk_major_name { struct blk_major_name *next; int major; char name[16]; - void (*probe)(dev_t devt); + int (*probe)(dev_t devt); } *major_names[BLKDEV_MAJOR_HASH_SIZE]; static DEFINE_MUTEX(major_names_lock); @@ -209,7 +209,7 @@ void blkdev_show(struct seq_file *seqf, off_t offset) * @major: the requested major device number [1..BLKDEV_MAJOR_MAX-1]. If * @major = 0, try to allocate any unused major number. * @name: the name of the new block device as a zero terminated string - * @probe: allback that is called on access to any minor number of @major + * @probe: callback that is called on access to any minor number of @major * * The @name must be unique within the system. * @@ -227,7 +227,7 @@ void blkdev_show(struct seq_file *seqf, off_t offset) * Use register_blkdev instead for any new code. */ int __register_blkdev(unsigned int major, const char *name, - void (*probe)(dev_t devt)) + int (*probe)(dev_t devt)) { struct blk_major_name **n, *p; int index, ret = 0; @@ -621,17 +621,18 @@ static ssize_t disk_badblocks_store(struct device *dev, return badblocks_store(disk->bb, page, len, 0); } -void blk_request_module(dev_t devt) +int blk_request_module(dev_t devt) { unsigned int major = MAJOR(devt); struct blk_major_name **n; + int err; mutex_lock(&major_names_lock); for (n = &major_names[major_to_index(major)]; *n; n = &(*n)->next) { if ((*n)->major == major && (*n)->probe) { - (*n)->probe(devt); + err = (*n)->probe(devt); mutex_unlock(&major_names_lock); - return; + return err; } } mutex_unlock(&major_names_lock); @@ -639,6 +640,8 @@ void blk_request_module(dev_t devt) if (request_module("block-major-%d-%d", MAJOR(devt), MINOR(devt)) > 0) /* Make old-style 2.4 aliases work */ request_module("block-major-%d", MAJOR(devt)); + + return 0; } /* diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 5dc9b3d32415..e55824e27188 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -1989,24 +1989,34 @@ static int ataflop_alloc_disk(unsigned int drive, unsigned int type) static DEFINE_MUTEX(ataflop_probe_lock); -static void ataflop_probe(dev_t dev) +static int ataflop_probe(dev_t dev) { int drive = MINOR(dev) & 3; int type = MINOR(dev) >> 2; + int err = -ENODEV; if (type) type--; - if (drive >= FD_MAX_UNITS || type >= NUM_DISK_MINORS) - return; + if (drive >= FD_MAX_UNITS || type >= NUM_DISK_MINORS) { + err = -EINVAL; + goto out; + } + mutex_lock(&ataflop_probe_lock); if (!unit[drive].disk[type]) { - if (ataflop_alloc_disk(drive, type) == 0) { - add_disk(unit[drive].disk[type]); + err = ataflop_alloc_disk(drive, type); + if (err == 0) { + err = add_disk(unit[drive].disk[type]); + if (err) + blk_cleanup_disk(unit[drive].disk[type]); unit[drive].registered[type] = true; } } mutex_unlock(&ataflop_probe_lock); + +out: + return err; } static void atari_cleanup_floppy_disk(struct atari_floppy_struct *fs) diff --git a/drivers/block/brd.c b/drivers/block/brd.c index c2bf4946f4e3..82a93044de95 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -426,10 +426,11 @@ static int brd_alloc(int i) return err; } -static void brd_probe(dev_t dev) +static int brd_probe(dev_t dev) { int i = MINOR(dev) / max_part; struct brd_device *brd; + int err = 0; mutex_lock(&brd_devices_mutex); list_for_each_entry(brd, &brd_devices, brd_list) { @@ -437,9 +438,11 @@ static void brd_probe(dev_t dev) goto out_unlock; } - brd_alloc(i); + err = brd_alloc(i); out_unlock: mutex_unlock(&brd_devices_mutex); + + return err; } static void brd_del_one(struct brd_device *brd) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 0434f28742e7..5ecffc7f6e22 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4517,21 +4517,27 @@ static int floppy_alloc_disk(unsigned int drive, unsigned int type) static DEFINE_MUTEX(floppy_probe_lock); -static void floppy_probe(dev_t dev) +static int floppy_probe(dev_t dev) { unsigned int drive = (MINOR(dev) & 3) | ((MINOR(dev) & 0x80) >> 5); unsigned int type = (MINOR(dev) >> 2) & 0x1f; + int err = -ENODEV; if (drive >= N_DRIVE || !floppy_available(drive) || type >= ARRAY_SIZE(floppy_type)) - return; + return -EINVAL; mutex_lock(&floppy_probe_lock); if (!disks[drive][type]) { - if (floppy_alloc_disk(drive, type) == 0) - add_disk(disks[drive][type]); + if (floppy_alloc_disk(drive, type) == 0) { + err = add_disk(disks[drive][type]); + if (err) + blk_cleanup_disk(disks[drive][type]); + } } mutex_unlock(&floppy_probe_lock); + + return err; } static int __init do_floppy_init(void) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index b8b9e2349e77..6bc1c075741e 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -2425,13 +2425,13 @@ static void loop_remove(struct loop_device *lo) kfree(lo); } -static void loop_probe(dev_t dev) +static int loop_probe(dev_t dev) { int idx = MINOR(dev) >> part_shift; if (max_loop && idx >= max_loop) - return; - loop_add(idx); + return -EINVAL; + return loop_add(idx); } static int loop_control_remove(int idx) diff --git a/drivers/md/md.c b/drivers/md/md.c index 5c0d3536d7c7..fc2790979686 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5735,12 +5735,16 @@ static int md_alloc(dev_t dev, char *name) return error; } -static void md_probe(dev_t dev) +static int md_probe(dev_t dev) { + int error = 0; + if (MAJOR(dev) == MD_MAJOR && MINOR(dev) >= 512) - return; + return -EINVAL; if (create_on_open) - md_alloc(dev, NULL); + error = md_alloc(dev, NULL); + + return error; } static int add_named_array(const char *val, const struct kernel_param *kp) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8c1273fff23e..50872c6ce030 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -630,8 +630,9 @@ static struct scsi_driver sd_template = { * Don't request a new module, as that could deadlock in multipath * environment. */ -static void sd_default_probe(dev_t devt) +static int sd_default_probe(dev_t devt) { + return 0; } /* diff --git a/fs/block_dev.c b/fs/block_dev.c index 45df6cbccf12..81a4738910a8 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1144,10 +1144,13 @@ struct block_device *blkdev_get_no_open(dev_t dev) { struct block_device *bdev; struct inode *inode; + int ret; inode = ilookup(blockdev_superblock, dev); if (!inode) { - blk_request_module(dev); + ret = blk_request_module(dev); + if (ret) + return NULL; inode = ilookup(blockdev_superblock, dev); if (!inode) return NULL; diff --git a/include/linux/genhd.h b/include/linux/genhd.h index c68d83c87f83..5828ecda5c49 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -281,7 +281,7 @@ struct gendisk *__blk_alloc_disk(int node, struct lock_class_key *lkclass); void blk_cleanup_disk(struct gendisk *disk); int __register_blkdev(unsigned int major, const char *name, - void (*probe)(dev_t devt)); + int (*probe)(dev_t devt)); #define register_blkdev(major, name) \ __register_blkdev(major, name, NULL) void unregister_blkdev(unsigned int major, const char *name); @@ -317,7 +317,7 @@ static inline int bd_register_pending_holders(struct gendisk *disk) dev_t part_devt(struct gendisk *disk, u8 partno); void inc_diskseq(struct gendisk *disk); dev_t blk_lookup_devt(const char *name, int partno); -void blk_request_module(dev_t devt); +int blk_request_module(dev_t devt); #ifdef CONFIG_BLOCK void printk_all_partitions(void); #else /* CONFIG_BLOCK */ -- 2.30.2 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] block: make __register_blkdev() return an error 2021-09-04 1:39 ` [PATCH 1/2] block: make __register_blkdev() return an error Luis Chamberlain @ 2021-09-04 2:49 ` Tetsuo Handa 2021-09-04 4:14 ` Jens Axboe 2021-09-05 18:11 ` Luis Chamberlain 0 siblings, 2 replies; 11+ messages in thread From: Tetsuo Handa @ 2021-09-04 2:49 UTC (permalink / raw) To: Luis Chamberlain, axboe, hch; +Cc: linux-block On 2021/09/04 10:39, Luis Chamberlain wrote: > diff --git a/fs/block_dev.c b/fs/block_dev.c > index 45df6cbccf12..81a4738910a8 100644 > --- a/fs/block_dev.c > +++ b/fs/block_dev.c > @@ -1144,10 +1144,13 @@ struct block_device *blkdev_get_no_open(dev_t dev) > { > struct block_device *bdev; > struct inode *inode; > + int ret; > > inode = ilookup(blockdev_superblock, dev); > if (!inode) { > - blk_request_module(dev); > + ret = blk_request_module(dev); > + if (ret) > + return NULL; Since e.g. loop_add() from loop_probe() returns -EEXIST when /dev/loop$num already exists (e.g. raced with ioctl(LOOP_CTL_ADD)), isn't unconditionally failing an over-failing? > inode = ilookup(blockdev_superblock, dev); > if (!inode) > return NULL; By the way, Jens, will you pick up https://lkml.kernel.org/r/adb1e792-fc0e-ee81-7ea0-0906fc36419d@i-love.sakura.ne.jp before these "add error handling" changes? ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] block: make __register_blkdev() return an error 2021-09-04 2:49 ` Tetsuo Handa @ 2021-09-04 4:14 ` Jens Axboe 2021-09-05 18:11 ` Luis Chamberlain 1 sibling, 0 replies; 11+ messages in thread From: Jens Axboe @ 2021-09-04 4:14 UTC (permalink / raw) To: Tetsuo Handa, Luis Chamberlain, hch; +Cc: linux-block On 9/3/21 8:49 PM, Tetsuo Handa wrote: > By the way, Jens, will you pick up > https://lkml.kernel.org/r/adb1e792-fc0e-ee81-7ea0-0906fc36419d@i-love.sakura.ne.jp > before these "add error handling" changes? Yes, that one is 5.15 material, the rest of the error handling changes are not. Hence the ordering follows naturally from that. -- Jens Axboe ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] block: make __register_blkdev() return an error 2021-09-04 2:49 ` Tetsuo Handa 2021-09-04 4:14 ` Jens Axboe @ 2021-09-05 18:11 ` Luis Chamberlain 2021-09-06 5:59 ` Tetsuo Handa 1 sibling, 1 reply; 11+ messages in thread From: Luis Chamberlain @ 2021-09-05 18:11 UTC (permalink / raw) To: Tetsuo Handa; +Cc: axboe, hch, linux-block On Sat, Sep 04, 2021 at 11:49:06AM +0900, Tetsuo Handa wrote: > On 2021/09/04 10:39, Luis Chamberlain wrote: > > diff --git a/fs/block_dev.c b/fs/block_dev.c > > index 45df6cbccf12..81a4738910a8 100644 > > --- a/fs/block_dev.c > > +++ b/fs/block_dev.c > > @@ -1144,10 +1144,13 @@ struct block_device *blkdev_get_no_open(dev_t dev) > > { > > struct block_device *bdev; > > struct inode *inode; > > + int ret; > > > > inode = ilookup(blockdev_superblock, dev); > > if (!inode) { > > - blk_request_module(dev); > > + ret = blk_request_module(dev); > > + if (ret) > > + return NULL; > > Since e.g. loop_add() from loop_probe() returns -EEXIST when /dev/loop$num already > exists (e.g. raced with ioctl(LOOP_CTL_ADD)), isn't unconditionally failing an over-failing? It's not clear to me how. What do we loose by capturing the failure on blk_request_module()? Luis ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] block: make __register_blkdev() return an error 2021-09-05 18:11 ` Luis Chamberlain @ 2021-09-06 5:59 ` Tetsuo Handa 2021-09-07 14:57 ` Luis Chamberlain 0 siblings, 1 reply; 11+ messages in thread From: Tetsuo Handa @ 2021-09-06 5:59 UTC (permalink / raw) To: Luis Chamberlain; +Cc: axboe, hch, linux-block On 2021/09/06 3:11, Luis Chamberlain wrote: > On Sat, Sep 04, 2021 at 11:49:06AM +0900, Tetsuo Handa wrote: >> On 2021/09/04 10:39, Luis Chamberlain wrote: >>> diff --git a/fs/block_dev.c b/fs/block_dev.c >>> index 45df6cbccf12..81a4738910a8 100644 >>> --- a/fs/block_dev.c >>> +++ b/fs/block_dev.c >>> @@ -1144,10 +1144,13 @@ struct block_device *blkdev_get_no_open(dev_t dev) >>> { >>> struct block_device *bdev; >>> struct inode *inode; >>> + int ret; >>> >>> inode = ilookup(blockdev_superblock, dev); >>> if (!inode) { >>> - blk_request_module(dev); >>> + ret = blk_request_module(dev); >>> + if (ret) >>> + return NULL; >> >> Since e.g. loop_add() from loop_probe() returns -EEXIST when /dev/loop$num already >> exists (e.g. raced with ioctl(LOOP_CTL_ADD)), isn't unconditionally failing an over-failing? > > It's not clear to me how. What do we loose by capturing the failure on > blk_request_module()? > We loose ability to handle concurrent request. diff --git a/fs/block_dev.c b/fs/block_dev.c index 45df6cbccf12..9559c8aabc88 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -36,6 +36,7 @@ #include <linux/suspend.h> #include "internal.h" #include "../block/blk.h" +#include <linux/debug_locks.h> struct bdev_inode { struct block_device bdev; @@ -1147,7 +1148,11 @@ struct block_device *blkdev_get_no_open(dev_t dev) inode = ilookup(blockdev_superblock, dev); if (!inode) { + dump_stack(); + debug_show_held_locks(current); blk_request_module(dev); + if (!strcmp(current->comm, "cat")) + schedule_timeout_killable(10 * HZ); inode = ilookup(blockdev_superblock, dev); if (!inode) return NULL; Try "mknod /dev/loop$num b 7 $num" followed by concurrent "cat /dev/loop$num" requests. [ 535.847823] [ T5261] CPU: 1 PID: 5261 Comm: cat Tainted: G E 5.14.0-next-20210903+ #3 [ 535.851419] [ T5261] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 02/27/2020 [ 535.855563] [ T5261] Call Trace: [ 535.856746] [ T5261] dump_stack_lvl+0x79/0xbf [ 535.858332] [ T5261] blkdev_get_no_open+0x86/0xe0 [ 535.860036] [ T5261] blkdev_get_by_dev+0x5f/0x540 [ 535.861747] [ T5261] ? block_ioctl+0x40/0x40 [ 535.863305] [ T5261] blkdev_open+0x58/0x90 [ 535.864865] [ T5261] do_dentry_open+0x144/0x3a0 [ 535.866538] [ T5261] path_openat+0xa57/0xda0 [ 535.868139] [ T5261] do_filp_open+0x9f/0x140 [ 535.869933] [ T5261] ? _raw_spin_unlock+0x1a/0x30 [ 535.871570] [ T5261] do_sys_openat2+0x71/0x150 [ 535.873195] [ T5261] __x64_sys_openat+0x78/0xa0 [ 535.874740] [ T5261] do_syscall_64+0x3d/0xb0 [ 535.876234] [ T5261] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 535.878428] [ T5261] RIP: 0033:0x7f6b997d28db [ 535.879927] [ T5261] Code: 25 00 00 41 00 3d 00 00 41 00 74 4b 64 8b 04 25 18 00 00 00 85 c0 75 67 44 89 e2 48 89 ee bf 9c ff ff ff b8 01 01 00 00 0f 05 <48> 3d 00 f0 ff ff 0f 87 91 00 00 00 48 8b 4c 24 28 64 48 2b 0c 25 [ 535.886778] [ T5261] RSP: 002b:00007ffe8bdad880 EFLAGS: 00000246 ORIG_RAX: 0000000000000101 [ 535.889727] [ T5261] RAX: ffffffffffffffda RBX: 000055f741e5b634 RCX: 00007f6b997d28db [ 535.892466] [ T5261] RDX: 0000000000000000 RSI: 00007ffe8bdaf764 RDI: 00000000ffffff9c [ 535.895226] [ T5261] RBP: 00007ffe8bdaf764 R08: 0000000000000001 R09: 0000000000000000 [ 535.898162] [ T5261] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 [ 535.900858] [ T5261] R13: 00007ffe8bdadb68 R14: 0000000000000000 R15: 0000000000020000 [ 535.903752] [ T5262] CPU: 2 PID: 5262 Comm: cat Tainted: G E 5.14.0-next-20210903+ #3 [ 535.904759] [ T5261] no locks held by cat/5261. [ 535.906905] [ T5262] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 02/27/2020 [ 535.906908] [ T5262] Call Trace: [ 535.906912] [ T5262] dump_stack_lvl+0x79/0xbf [ 535.915279] [ T5262] blkdev_get_no_open+0x86/0xe0 [ 535.916942] [ T5262] blkdev_get_by_dev+0x5f/0x540 [ 535.918608] [ T5262] ? block_ioctl+0x40/0x40 [ 535.920250] [ T5262] blkdev_open+0x58/0x90 [ 535.921696] [ T5262] do_dentry_open+0x144/0x3a0 [ 535.923291] [ T5262] path_openat+0xa57/0xda0 [ 535.924816] [ T5262] do_filp_open+0x9f/0x140 [ 535.926359] [ T5262] ? _raw_spin_unlock+0x1a/0x30 [ 535.928030] [ T5262] do_sys_openat2+0x71/0x150 [ 535.929600] [ T5262] __x64_sys_openat+0x78/0xa0 [ 535.931215] [ T5262] do_syscall_64+0x3d/0xb0 [ 535.932768] [ T5262] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 535.934817] [ T5262] RIP: 0033:0x7efe3a0aa8db [ 535.936354] [ T5262] Code: 25 00 00 41 00 3d 00 00 41 00 74 4b 64 8b 04 25 18 00 00 00 85 c0 75 67 44 89 e2 48 89 ee bf 9c ff ff ff b8 01 01 00 00 0f 05 <48> 3d 00 f0 ff ff 0f 87 91 00 00 00 48 8b 4c 24 28 64 48 2b 0c 25 [ 535.943021] [ T5262] RSP: 002b:00007ffe1697dfb0 EFLAGS: 00000246 ORIG_RAX: 0000000000000101 [ 535.945883] [ T5262] RAX: ffffffffffffffda RBX: 000055982a4e1634 RCX: 00007efe3a0aa8db [ 535.948580] [ T5262] RDX: 0000000000000000 RSI: 00007ffe1697e764 RDI: 00000000ffffff9c [ 535.951298] [ T5262] RBP: 00007ffe1697e764 R08: 0000000000000001 R09: 0000000000000000 [ 535.954064] [ T5262] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 [ 535.956789] [ T5262] R13: 00007ffe1697e298 R14: 0000000000000000 R15: 0000000000020000 [ 535.959522] [ T5263] CPU: 0 PID: 5263 Comm: cat Tainted: G E 5.14.0-next-20210903+ #3 [ 535.962995] [ T5263] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 02/27/2020 [ 535.965787] [ T5262] no locks held by cat/5262. [ 535.966998] [ T5263] Call Trace: [ 535.970068] [ T5263] dump_stack_lvl+0x79/0xbf [ 535.971572] [ T5263] blkdev_get_no_open+0x86/0xe0 [ 535.973199] [ T5263] blkdev_get_by_dev+0x5f/0x540 [ 535.974893] [ T5263] ? block_ioctl+0x40/0x40 [ 535.976364] [ T5263] blkdev_open+0x58/0x90 [ 535.977781] [ T5263] do_dentry_open+0x144/0x3a0 [ 535.979378] [ T5263] path_openat+0xa57/0xda0 [ 535.980882] [ T5263] do_filp_open+0x9f/0x140 [ 535.982333] [ T5263] ? _raw_spin_unlock+0x1a/0x30 [ 535.984002] [ T5263] do_sys_openat2+0x71/0x150 [ 535.985554] [ T5263] __x64_sys_openat+0x78/0xa0 [ 535.987232] [ T5263] do_syscall_64+0x3d/0xb0 [ 535.988790] [ T5263] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 535.990804] [ T5263] RIP: 0033:0x7ff84ab408db [ 535.992275] [ T5263] Code: 25 00 00 41 00 3d 00 00 41 00 74 4b 64 8b 04 25 18 00 00 00 85 c0 75 67 44 89 e2 48 89 ee bf 9c ff ff ff b8 01 01 00 00 0f 05 <48> 3d 00 f0 ff ff 0f 87 91 00 00 00 48 8b 4c 24 28 64 48 2b 0c 25 [ 535.998888] [ T5263] RSP: 002b:00007ffda9b89a70 EFLAGS: 00000246 ORIG_RAX: 0000000000000101 [ 536.001628] [ T5263] RAX: ffffffffffffffda RBX: 000055626f376634 RCX: 00007ff84ab408db [ 536.004350] [ T5263] RDX: 0000000000000000 RSI: 00007ffda9b8a764 RDI: 00000000ffffff9c [ 536.007009] [ T5263] RBP: 00007ffda9b8a764 R08: 0000000000000001 R09: 0000000000000000 [ 536.009753] [ T5263] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 [ 536.012493] [ T5263] R13: 00007ffda9b89d58 R14: 0000000000000000 R15: 0000000000020000 [ 536.015854] [ T5263] no locks held by cat/5263. If blk_request_module() does not ignore -EEXIST error, only the first open() request would succeed because loop_add() returns 0 and all other concurrent requests would fail because loop_add() returns -EEXIST. Actually, blk_request_module() failures should be ignored, for subsequent ilookup() will fail if blk_request_module() failed to create the requested block device. ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] block: make __register_blkdev() return an error 2021-09-06 5:59 ` Tetsuo Handa @ 2021-09-07 14:57 ` Luis Chamberlain 2021-09-07 15:23 ` Tetsuo Handa 0 siblings, 1 reply; 11+ messages in thread From: Luis Chamberlain @ 2021-09-07 14:57 UTC (permalink / raw) To: Tetsuo Handa; +Cc: axboe, hch, linux-block On Mon, Sep 06, 2021 at 02:59:38PM +0900, Tetsuo Handa wrote: > On 2021/09/06 3:11, Luis Chamberlain wrote: > > On Sat, Sep 04, 2021 at 11:49:06AM +0900, Tetsuo Handa wrote: > >> On 2021/09/04 10:39, Luis Chamberlain wrote: > >>> diff --git a/fs/block_dev.c b/fs/block_dev.c > >>> index 45df6cbccf12..81a4738910a8 100644 > >>> --- a/fs/block_dev.c > >>> +++ b/fs/block_dev.c > >>> @@ -1144,10 +1144,13 @@ struct block_device *blkdev_get_no_open(dev_t dev) > >>> { > >>> struct block_device *bdev; > >>> struct inode *inode; > >>> + int ret; > >>> > >>> inode = ilookup(blockdev_superblock, dev); > >>> if (!inode) { > >>> - blk_request_module(dev); > >>> + ret = blk_request_module(dev); > >>> + if (ret) > >>> + return NULL; > >> > >> Since e.g. loop_add() from loop_probe() returns -EEXIST when /dev/loop$num already > >> exists (e.g. raced with ioctl(LOOP_CTL_ADD)), isn't unconditionally failing an over-failing? > > > > It's not clear to me how. What do we loose by capturing the failure on > > blk_request_module()? > > > > We loose ability to handle concurrent request. > If blk_request_module() does not ignore -EEXIST error, only the first > open() request would succeed because loop_add() returns 0 and all > other concurrent requests would fail because loop_add() returns > -EEXIST. Yes I see that now thanks! > Actually, blk_request_module() failures should be ignored, for > subsequent ilookup() will fail if blk_request_module() failed to > create the requested block device. Then how about this: Since we would like to use __must_check for add_disk() we proceed with the change to capture the errors and propagate them and we just document on fs/block_dev.c's use of blk_request_module() about the above issue and how we prefer the errror that ilookup() would return. Luis ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] block: make __register_blkdev() return an error 2021-09-07 14:57 ` Luis Chamberlain @ 2021-09-07 15:23 ` Tetsuo Handa 2021-09-07 15:28 ` Luis Chamberlain 0 siblings, 1 reply; 11+ messages in thread From: Tetsuo Handa @ 2021-09-07 15:23 UTC (permalink / raw) To: Luis Chamberlain; +Cc: axboe, hch, linux-block On 2021/09/07 23:57, Luis Chamberlain wrote: >> Actually, blk_request_module() failures should be ignored, for >> subsequent ilookup() will fail if blk_request_module() failed to >> create the requested block device. > > Then how about this: > > Since we would like to use __must_check for add_disk() we proceed with > the change to capture the errors and propagate them and we just document on > fs/block_dev.c's use of blk_request_module() about the above issue and > how we prefer the errror that ilookup() would return. Marking add_disk() as __must_check makes it possible to enforce "don't leave partially initialized devices". That's already an enough improvement. Probe functions can remain "void", and hence blk_request_module() can remain "void". That is, I would drop "[PATCH 1/2] block: make __register_blkdev() return an error". ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] block: make __register_blkdev() return an error 2021-09-07 15:23 ` Tetsuo Handa @ 2021-09-07 15:28 ` Luis Chamberlain 2021-09-08 14:00 ` Luis Chamberlain 0 siblings, 1 reply; 11+ messages in thread From: Luis Chamberlain @ 2021-09-07 15:28 UTC (permalink / raw) To: Tetsuo Handa; +Cc: axboe, hch, linux-block On Wed, Sep 08, 2021 at 12:23:02AM +0900, Tetsuo Handa wrote: > On 2021/09/07 23:57, Luis Chamberlain wrote: > >> Actually, blk_request_module() failures should be ignored, for > >> subsequent ilookup() will fail if blk_request_module() failed to > >> create the requested block device. > > > > Then how about this: > > > > Since we would like to use __must_check for add_disk() we proceed with > > the change to capture the errors and propagate them and we just document on > > fs/block_dev.c's use of blk_request_module() about the above issue and > > how we prefer the errror that ilookup() would return. > > Marking add_disk() as __must_check makes it possible to enforce "don't leave > partially initialized devices". That's already an enough improvement. > > Probe functions can remain "void", and hence blk_request_module() can remain "void". > That is, I would drop "[PATCH 1/2] block: make __register_blkdev() return an error". Probe calls can be left voide, but because of the new __must_check we'd still have to modify all probe calls as they use add_disk() and it would seem odd to just capture the error to ignore it without documenting any of this. Luis ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] block: make __register_blkdev() return an error 2021-09-07 15:28 ` Luis Chamberlain @ 2021-09-08 14:00 ` Luis Chamberlain 0 siblings, 0 replies; 11+ messages in thread From: Luis Chamberlain @ 2021-09-08 14:00 UTC (permalink / raw) To: Tetsuo Handa; +Cc: axboe, hch, linux-block On Tue, Sep 07, 2021 at 08:28:06AM -0700, Luis Chamberlain wrote: > On Wed, Sep 08, 2021 at 12:23:02AM +0900, Tetsuo Handa wrote: > > On 2021/09/07 23:57, Luis Chamberlain wrote: > > >> Actually, blk_request_module() failures should be ignored, for > > >> subsequent ilookup() will fail if blk_request_module() failed to > > >> create the requested block device. > > > > > > Then how about this: > > > > > > Since we would like to use __must_check for add_disk() we proceed with > > > the change to capture the errors and propagate them and we just document on > > > fs/block_dev.c's use of blk_request_module() about the above issue and > > > how we prefer the errror that ilookup() would return. > > > > Marking add_disk() as __must_check makes it possible to enforce "don't leave > > partially initialized devices". That's already an enough improvement. > > > > Probe functions can remain "void", and hence blk_request_module() can remain "void". > > That is, I would drop "[PATCH 1/2] block: make __register_blkdev() return an error". > > Probe calls can be left voide, but because of the new __must_check we'd > still have to modify all probe calls as they use add_disk() and it would > seem odd to just capture the error to ignore it without documenting > any of this. So indeed, all probe() routines would need to be modified anyway because of the added final __must_check. Because of this I still think that if we want to *ignore* the error, we should just document and ignore it on the caller side. That is, still modify __register_blkdev() to propagate the error, and the caller can decide to ignore or not. In this case we can document on fs/block_dev.c *why* we are ignoring the error. Thoughts? Luis ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/2] block: add __must_check for *add_disk*() callers 2021-09-04 1:39 [PATCH 0/2] block: 7th -- last batch of add_disk() error handling conversions Luis Chamberlain 2021-09-04 1:39 ` [PATCH 1/2] block: make __register_blkdev() return an error Luis Chamberlain @ 2021-09-04 1:39 ` Luis Chamberlain 1 sibling, 0 replies; 11+ messages in thread From: Luis Chamberlain @ 2021-09-04 1:39 UTC (permalink / raw) To: axboe, hch, efremov, song, jejb, martin.petersen, viro, hare, jack, ming.lei, tj Cc: linux-raid, linux-scsi, linux-fsdevel, linux-block, linux-kernel, Luis Chamberlain Now that we have done a spring cleaning on all drivers and added error checking / handling, let's keep it that way and ensure no new drivers fail to stick with it. Signed-off-by: Luis Chamberlain <mcgrof@kernel.org> --- block/genhd.c | 6 +++--- include/linux/genhd.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index c4836296a974..4c80e6c3d8dd 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -383,8 +383,8 @@ static void disk_scan_partitions(struct gendisk *disk) * This function registers the partitioning information in @disk * with the kernel. */ -int device_add_disk(struct device *parent, struct gendisk *disk, - const struct attribute_group **groups) +int __must_check device_add_disk(struct device *parent, struct gendisk *disk, + const struct attribute_group **groups) { struct device *ddev = disk_to_dev(disk); @@ -529,7 +529,7 @@ int device_add_disk(struct device *parent, struct gendisk *disk, out_free_ext_minor: if (disk->major == BLOCK_EXT_MAJOR) blk_free_ext_minor(disk->first_minor); - return WARN_ON_ONCE(ret); /* keep until all callers handle errors */ + return ret; } EXPORT_SYMBOL(device_add_disk); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 5828ecda5c49..8d78d36c424e 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -214,9 +214,9 @@ static inline dev_t disk_devt(struct gendisk *disk) void disk_uevent(struct gendisk *disk, enum kobject_action action); /* block/genhd.c */ -int device_add_disk(struct device *parent, struct gendisk *disk, - const struct attribute_group **groups); -static inline int add_disk(struct gendisk *disk) +int __must_check device_add_disk(struct device *parent, struct gendisk *disk, + const struct attribute_group **groups); +static inline int __must_check add_disk(struct gendisk *disk) { return device_add_disk(NULL, disk, NULL); } -- 2.30.2 ^ permalink raw reply related [flat|nested] 11+ messages in thread
end of thread, other threads:[~2021-09-08 14:00 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-09-04 1:39 [PATCH 0/2] block: 7th -- last batch of add_disk() error handling conversions Luis Chamberlain 2021-09-04 1:39 ` [PATCH 1/2] block: make __register_blkdev() return an error Luis Chamberlain 2021-09-04 2:49 ` Tetsuo Handa 2021-09-04 4:14 ` Jens Axboe 2021-09-05 18:11 ` Luis Chamberlain 2021-09-06 5:59 ` Tetsuo Handa 2021-09-07 14:57 ` Luis Chamberlain 2021-09-07 15:23 ` Tetsuo Handa 2021-09-07 15:28 ` Luis Chamberlain 2021-09-08 14:00 ` Luis Chamberlain 2021-09-04 1:39 ` [PATCH 2/2] block: add __must_check for *add_disk*() callers Luis Chamberlain
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).