diff mbox series

[v3,12/13] block: fix __register_blkdev() probe add_disk() failures

Message ID 20211103174521.1426407-13-mcgrof@kernel.org
State Not Applicable
Headers show
Series block: add_disk() error handling stragglers | expand

Commit Message

Luis Chamberlain Nov. 3, 2021, 5:45 p.m. UTC
__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@i-love.sakura.ne.jp>
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
 block/genhd.c           |  5 ++++-
 drivers/block/ataflop.c | 12 +++++++++---
 drivers/block/floppy.c  | 11 +++++++++--
 3 files changed, 22 insertions(+), 6 deletions(-)

Comments

Christoph Hellwig Nov. 3, 2021, 5:48 p.m. UTC | #1
Sorry for being annoying, but I think this really should be three
patches: the documentation fix and one each for the two floppy
drivers.  And the two floppy probe routines would probably
benefit from using goto unwinding as well.
diff mbox series

Patch

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);
 }