floppy: convert to blk-mq
authorOmar Sandoval <osandov@fb.com>
Mon, 15 Oct 2018 15:21:34 +0000 (09:21 -0600)
committerJens Axboe <axboe@kernel.dk>
Tue, 16 Oct 2018 15:50:14 +0000 (09:50 -0600)
This driver likes to fetch requests from all over the place, so make
queue_rq put requests on a list so that the logic stays the same. Tested
with QEMU.

Signed-off-by: Omar Sandoval <osandov@fb.com>
Converted to blk_mq_init_sq_queue() and fixed a few spots where the
tag_set leaked on cleanup.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/floppy.c

index c494a771c06fcfe9fa4f1f65e1b69e714b2b5e61..a8cfa011c28483ef389ee161b5ca86af71eac13e 100644 (file)
@@ -252,13 +252,13 @@ static int allowed_drive_mask = 0x33;
 
 static int irqdma_allocated;
 
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/blkpg.h>
 #include <linux/cdrom.h>       /* for the compatibility eject ioctl */
 #include <linux/completion.h>
 
+static LIST_HEAD(floppy_reqs);
 static struct request *current_req;
-static void do_fd_request(struct request_queue *q);
 static int set_next_request(void);
 
 #ifndef fd_get_dma_residue
@@ -414,10 +414,10 @@ static struct floppy_drive_struct drive_state[N_DRIVE];
 static struct floppy_write_errors write_errors[N_DRIVE];
 static struct timer_list motor_off_timer[N_DRIVE];
 static struct gendisk *disks[N_DRIVE];
+static struct blk_mq_tag_set tag_sets[N_DRIVE];
 static struct block_device *opened_bdev[N_DRIVE];
 static DEFINE_MUTEX(open_lock);
 static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
-static int fdc_queue;
 
 /*
  * This struct defines the different floppy types.
@@ -2216,8 +2216,9 @@ static void floppy_end_request(struct request *req, blk_status_t error)
        /* current_count_sectors can be zero if transfer failed */
        if (error)
                nr_sectors = blk_rq_cur_sectors(req);
-       if (__blk_end_request(req, error, nr_sectors << 9))
+       if (blk_update_request(req, error, nr_sectors << 9))
                return;
+       __blk_mq_end_request(req, error);
 
        /* We're done with the request */
        floppy_off(drive);
@@ -2797,27 +2798,14 @@ static int make_raw_rw_request(void)
        return 2;
 }
 
-/*
- * Round-robin between our available drives, doing one request from each
- */
 static int set_next_request(void)
 {
-       struct request_queue *q;
-       int old_pos = fdc_queue;
-
-       do {
-               q = disks[fdc_queue]->queue;
-               if (++fdc_queue == N_DRIVE)
-                       fdc_queue = 0;
-               if (q) {
-                       current_req = blk_fetch_request(q);
-                       if (current_req) {
-                               current_req->error_count = 0;
-                               break;
-                       }
-               }
-       } while (fdc_queue != old_pos);
-
+       current_req = list_first_entry_or_null(&floppy_reqs, struct request,
+                                              queuelist);
+       if (current_req) {
+               current_req->error_count = 0;
+               list_del_init(&current_req->queuelist);
+       }
        return current_req != NULL;
 }
 
@@ -2901,29 +2889,38 @@ static void process_fd_request(void)
        schedule_bh(redo_fd_request);
 }
 
-static void do_fd_request(struct request_queue *q)
+static blk_status_t floppy_queue_rq(struct blk_mq_hw_ctx *hctx,
+                                   const struct blk_mq_queue_data *bd)
 {
+       blk_mq_start_request(bd->rq);
+
        if (WARN(max_buffer_sectors == 0,
                 "VFS: %s called on non-open device\n", __func__))
-               return;
+               return BLK_STS_IOERR;
 
        if (WARN(atomic_read(&usage_count) == 0,
                 "warning: usage count=0, current_req=%p sect=%ld flags=%llx\n",
                 current_req, (long)blk_rq_pos(current_req),
                 (unsigned long long) current_req->cmd_flags))
-               return;
+               return BLK_STS_IOERR;
+
+       spin_lock_irq(&floppy_lock);
+       list_add_tail(&bd->rq->queuelist, &floppy_reqs);
+       spin_unlock_irq(&floppy_lock);
 
        if (test_and_set_bit(0, &fdc_busy)) {
                /* fdc busy, this new request will be treated when the
                   current one is done */
                is_alive(__func__, "old request running");
-               return;
+               return BLK_STS_OK;
        }
+
        command_status = FD_COMMAND_NONE;
        __reschedule_timeout(MAXTIMEOUT, "fd_request");
        set_fdc(0);
        process_fd_request();
        is_alive(__func__, "");
+       return BLK_STS_OK;
 }
 
 static const struct cont_t poll_cont = {
@@ -4486,6 +4483,10 @@ static struct platform_driver floppy_driver = {
        },
 };
 
+static const struct blk_mq_ops floppy_mq_ops = {
+       .queue_rq = floppy_queue_rq,
+};
+
 static struct platform_device floppy_device[N_DRIVE];
 
 static bool floppy_available(int drive)
@@ -4533,9 +4534,12 @@ static int __init do_floppy_init(void)
                        goto out_put_disk;
                }
 
-               disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock);
-               if (!disks[drive]->queue) {
-                       err = -ENOMEM;
+               disks[drive]->queue = blk_mq_init_sq_queue(&tag_sets[drive],
+                                                          &floppy_mq_ops, 2,
+                                                          BLK_MQ_F_SHOULD_MERGE);
+               if (IS_ERR(disks[drive]->queue)) {
+                       err = PTR_ERR(disks[drive]->queue);
+                       disks[drive]->queue = NULL;
                        goto out_put_disk;
                }
 
@@ -4708,6 +4712,7 @@ out_put_disk:
                        del_timer_sync(&motor_off_timer[drive]);
                        blk_cleanup_queue(disks[drive]->queue);
                        disks[drive]->queue = NULL;
+                       blk_mq_free_tag_set(&tag_sets[drive]);
                }
                put_disk(disks[drive]);
        }
@@ -4935,6 +4940,7 @@ static void __exit floppy_module_exit(void)
                        platform_device_unregister(&floppy_device[drive]);
                }
                blk_cleanup_queue(disks[drive]->queue);
+               blk_mq_free_tag_set(&tag_sets[drive]);
 
                /*
                 * These disks have not called add_disk().  Don't put down