swim3: add real error handling in setup
authorOmar Sandoval <osandov@fb.com>
Thu, 11 Oct 2018 19:20:43 +0000 (12:20 -0700)
committerJens Axboe <axboe@kernel.dk>
Tue, 16 Oct 2018 15:49:26 +0000 (09:49 -0600)
The driver doesn't have support for removing a device that has already
been configured, but with more careful ordering we can avoid the need
for that and make sure that we don't leak generic resources.

Signed-off-by: Omar Sandoval <osandov@fb.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/swim3.c

index 469541c1e51eed13b589f47b295f0e916ade4170..df7ebe016e2c28c0d4922cb3c33af4cb52616c49 100644 (file)
@@ -1202,47 +1202,59 @@ static int swim3_add_device(struct macio_dev *mdev, int index)
 static int swim3_attach(struct macio_dev *mdev,
                        const struct of_device_id *match)
 {
+       struct floppy_state *fs;
        struct gendisk *disk;
-       int index, rc;
+       int rc;
 
-       index = floppy_count++;
-       if (index >= MAX_FLOPPIES)
+       if (floppy_count >= MAX_FLOPPIES)
                return -ENXIO;
 
-       /* Add the drive */
-       rc = swim3_add_device(mdev, index);
-       if (rc)
-               return rc;
-       /* Now register that disk. Same comment about failure handling */
-       disk = disks[index] = alloc_disk(1);
-       if (disk == NULL)
-               return -ENOMEM;
+       if (floppy_count == 0) {
+               rc = register_blkdev(FLOPPY_MAJOR, "fd");
+               if (rc)
+                       return rc;
+       }
+
+       fs = &floppy_states[floppy_count];
+
+       disk = alloc_disk(1);
+       if (disk == NULL) {
+               rc = -ENOMEM;
+               goto out_unregister;
+       }
        disk->queue = blk_init_queue(do_fd_request, &swim3_lock);
        if (disk->queue == NULL) {
-               put_disk(disk);
-               return -ENOMEM;
+               rc = -ENOMEM;
+               goto out_put_disk;
        }
        blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH);
-       disk->queue->queuedata = &floppy_states[index];
+       disk->queue->queuedata = fs;
 
-       if (index == 0) {
-               /* If we failed, there isn't much we can do as the driver is still
-                * too dumb to remove the device, just bail out
-                */
-               if (register_blkdev(FLOPPY_MAJOR, "fd"))
-                       return 0;
-       }
+       rc = swim3_add_device(mdev, floppy_count);
+       if (rc)
+               goto out_cleanup_queue;
 
        disk->major = FLOPPY_MAJOR;
-       disk->first_minor = index;
+       disk->first_minor = floppy_count;
        disk->fops = &floppy_fops;
-       disk->private_data = &floppy_states[index];
+       disk->private_data = fs;
        disk->flags |= GENHD_FL_REMOVABLE;
-       sprintf(disk->disk_name, "fd%d", index);
+       sprintf(disk->disk_name, "fd%d", floppy_count);
        set_capacity(disk, 2880);
        add_disk(disk);
 
+       disks[floppy_count++] = disk;
        return 0;
+
+out_cleanup_queue:
+       blk_cleanup_queue(disk->queue);
+       disk->queue = NULL;
+out_put_disk:
+       put_disk(disk);
+out_unregister:
+       if (floppy_count == 0)
+               unregister_blkdev(FLOPPY_MAJOR, "fd");
+       return rc;
 }
 
 static const struct of_device_id swim3_match[] =