This makes the probe callback use din blk_request_module() return an error. We do this as add_disk() now has error handling, and so we can bail earlier than before. If a probe is not implemented then its not used. This is mostly useful for the following drivers: * ataflop * brd * floppy * loop * scsi/sd Signed-off-by: Luis Chamberlain <mcgrof@xxxxxxxxxx> --- 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/scsi/sd.c | 3 ++- fs/block_dev.c | 5 ++++- include/linux/genhd.h | 4 ++-- 8 files changed, 50 insertions(+), 24 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 72703d243b44..ca6393df09ad 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -161,7 +161,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); @@ -190,7 +190,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. * @@ -208,7 +208,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; @@ -728,17 +728,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); @@ -746,6 +747,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 4b3f1158fa04..ce08b8e60163 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -2005,22 +2005,32 @@ static void atari_floppy_disk_remove(void) } -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]); + if (ataflop_alloc_disk(drive, type) == 0) { + err = add_disk(unit[drive].disk[type]); + if (err) + blk_cleanup_disk(unit[drive].disk[type]); + } } mutex_unlock(&ataflop_probe_lock); + +out: + return err; } static int __init atari_floppy_init (void) diff --git a/drivers/block/brd.c b/drivers/block/brd.c index ca017ca315c5..104adf70a15a 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -429,10 +429,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) { @@ -440,9 +441,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 cad17b49e700..52bc645f3060 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; 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 efbd8e29aca7..081cccd39bc9 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -2358,13 +2358,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/scsi/sd.c b/drivers/scsi/sd.c index 01af61a38e4e..800dfd5984bd 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -633,8 +633,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 c41d0e550d39..531feb097cb2 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1326,10 +1326,13 @@ struct block_device *blkdev_get_no_open(dev_t dev) { struct block_device *bdev; struct gendisk *disk; + int err; bdev = bdget(dev); if (!bdev) { - blk_request_module(dev); + err = blk_request_module(dev); + if (err) + return NULL; bdev = bdget(dev); if (!bdev) return NULL; diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 73024416d2d5..9db56d4562ae 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -312,7 +312,7 @@ struct gendisk *__blk_alloc_disk(int node); 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); @@ -342,7 +342,7 @@ static inline void bd_unlink_disk_holder(struct block_device *bdev, dev_t part_devt(struct gendisk *disk, u8 partno); 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.27.0