swim: stop sharing request queue across multiple gendisks
authorOmar Sandoval <osandov@fb.com>
Tue, 28 Mar 2017 06:28:46 +0000 (23:28 -0700)
committerJens Axboe <axboe@fb.com>
Tue, 28 Mar 2017 21:06:58 +0000 (15:06 -0600)
Compile-tested only (by hacking it to compile on x86).

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

index b5afd495d482e8971be1cc431bb7b0ea8b54cae2..3064be6cf3755a4017cbd2a30cda023977250cbf 100644 (file)
@@ -211,7 +211,7 @@ enum head {
 struct swim_priv {
        struct swim __iomem *base;
        spinlock_t lock;
-       struct request_queue *queue;
+       int fdc_queue;
        int floppy_count;
        struct floppy_state unit[FD_MAX_UNIT];
 };
@@ -525,12 +525,33 @@ static int floppy_read_sectors(struct floppy_state *fs,
        return 0;
 }
 
-static void redo_fd_request(struct request_queue *q)
+static struct request *swim_next_request(struct swim_priv *swd)
 {
+       struct request_queue *q;
+       struct request *rq;
+       int old_pos = swd->fdc_queue;
+
+       do {
+               q = swd->unit[swd->fdc_queue].disk->queue;
+               if (++swd->fdc_queue == swd->floppy_count)
+                       swd->fdc_queue = 0;
+               if (q) {
+                       rq = blk_fetch_request(q);
+                       if (rq)
+                               return rq;
+               }
+       } while (swd->fdc_queue != old_pos);
+
+       return NULL;
+}
+
+static void do_fd_request(struct request_queue *q)
+{
+       struct swim_priv *swd = q->queuedata;
        struct request *req;
        struct floppy_state *fs;
 
-       req = blk_fetch_request(q);
+       req = swim_next_request(swd);
        while (req) {
                int err = -EIO;
 
@@ -554,15 +575,10 @@ static void redo_fd_request(struct request_queue *q)
                }
        done:
                if (!__blk_end_request_cur(req, err))
-                       req = blk_fetch_request(q);
+                       req = swim_next_request(swd);
        }
 }
 
-static void do_fd_request(struct request_queue *q)
-{
-       redo_fd_request(q);
-}
-
 static struct floppy_struct floppy_type[4] = {
        {    0,  0, 0,  0, 0, 0x00, 0x00, 0x00, 0x00, NULL }, /* no testing   */
        {  720,  9, 1, 80, 0, 0x2A, 0x02, 0xDF, 0x50, NULL }, /* 360KB SS 3.5"*/
@@ -833,22 +849,25 @@ static int swim_floppy_init(struct swim_priv *swd)
                return -EBUSY;
        }
 
+       spin_lock_init(&swd->lock);
+
        for (drive = 0; drive < swd->floppy_count; drive++) {
                swd->unit[drive].disk = alloc_disk(1);
                if (swd->unit[drive].disk == NULL) {
                        err = -ENOMEM;
                        goto exit_put_disks;
                }
+               swd->unit[drive].disk->queue = blk_init_queue(do_fd_request,
+                                                             &swd->lock);
+               if (!swd->unit[drive].disk->queue) {
+                       err = -ENOMEM;
+                       put_disk(swd->unit[drive].disk);
+                       goto exit_put_disks;
+               }
+               swd->unit[drive].disk->queue->queuedata = swd;
                swd->unit[drive].swd = swd;
        }
 
-       spin_lock_init(&swd->lock);
-       swd->queue = blk_init_queue(do_fd_request, &swd->lock);
-       if (!swd->queue) {
-               err = -ENOMEM;
-               goto exit_put_disks;
-       }
-
        for (drive = 0; drive < swd->floppy_count; drive++) {
                swd->unit[drive].disk->flags = GENHD_FL_REMOVABLE;
                swd->unit[drive].disk->major = FLOPPY_MAJOR;
@@ -856,7 +875,6 @@ static int swim_floppy_init(struct swim_priv *swd)
                sprintf(swd->unit[drive].disk->disk_name, "fd%d", drive);
                swd->unit[drive].disk->fops = &floppy_fops;
                swd->unit[drive].disk->private_data = &swd->unit[drive];
-               swd->unit[drive].disk->queue = swd->queue;
                set_capacity(swd->unit[drive].disk, 2880);
                add_disk(swd->unit[drive].disk);
        }
@@ -943,13 +961,12 @@ static int swim_remove(struct platform_device *dev)
 
        for (drive = 0; drive < swd->floppy_count; drive++) {
                del_gendisk(swd->unit[drive].disk);
+               blk_cleanup_queue(swd->unit[drive].disk->queue);
                put_disk(swd->unit[drive].disk);
        }
 
        unregister_blkdev(FLOPPY_MAJOR, "fd");
 
-       blk_cleanup_queue(swd->queue);
-
        /* eject floppies */
 
        for (drive = 0; drive < swd->floppy_count; drive++)