__register_blkdev() is used to register a probe callback, and that callback is typically used to call add_disk(). Now that we are able to capture errors for add_disk(), we need to fix those probe calls where add_disk() fails and clean up resources. We don't extend the probe call to return the error given: 1) we'd have to always special-case the case where the disk was already present, as otherwise concurrent requests to open an existing block device would fail, and this would be a userspace visible change 2) the error from ilookup() on blkdev_get_no_open() is sufficient 3) The only thing the probe call is used for is to support pre-devtmpfs, pre-udev semantics that want to create disks when their pre-created device node is accessed, and so we don't care for failures on probe there. We expand documentation for the probe callback to ensure users cleanup resources if add_disk() is used and to clarify this interface may be removed in the future. This fixes the ataflop and floppy driver uses of the probe call, which lacked proper error handling for the add_disk() calls. Cc: Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx> Signed-off-by: Luis Chamberlain <mcgrof@xxxxxxxxxx> --- block/genhd.c | 5 ++++- drivers/block/ataflop.c | 12 +++++++++--- drivers/block/floppy.c | 11 +++++++++-- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 4ed87f25276a..8837a89242a2 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -213,7 +213,10 @@ 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: pre-devtmpfs / pre-udev callback used to create disks when their + * their pre-created device node is accessed. When a probe call + * uses add_disk() and it fails the driver must cleanup resources. + * This interface may soon be removed. * * The @name must be unique within the system. * diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 170dd193cef6..cce6615fe10a 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -2012,6 +2012,7 @@ static void ataflop_probe(dev_t dev) { int drive = MINOR(dev) & 3; int type = MINOR(dev) >> 2; + int err = 0; if (type) type--; @@ -2019,9 +2020,14 @@ static void ataflop_probe(dev_t dev) if (drive >= FD_MAX_UNITS || type >= NUM_DISK_MINORS) return; if (!unit[drive].disk[type]) { - if (ataflop_alloc_disk(drive, type) == 0) { - add_disk(unit[drive].disk[type]); - unit[drive].registered[type] = true; + 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].disk[type] = NULL; + } else + unit[drive].registered[type] = true; } } } diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 3873e789478e..cebc11b74b1a 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4522,6 +4522,7 @@ static void floppy_probe(dev_t dev) { unsigned int drive = (MINOR(dev) & 3) | ((MINOR(dev) & 0x80) >> 5); unsigned int type = (MINOR(dev) >> 2) & 0x1f; + int err = 0; if (drive >= N_DRIVE || !floppy_available(drive) || type >= ARRAY_SIZE(floppy_type)) @@ -4529,8 +4530,14 @@ static void floppy_probe(dev_t dev) mutex_lock(&floppy_probe_lock); if (!disks[drive][type]) { - if (floppy_alloc_disk(drive, type) == 0) - add_disk(disks[drive][type]); + err = floppy_alloc_disk(drive, type); + if (err == 0) { + err = add_disk(disks[drive][type]); + if (err) { + blk_cleanup_disk(disks[drive][type]); + disks[drive][type] = NULL; + } + } } mutex_unlock(&floppy_probe_lock); } -- 2.33.0