parport/pd: stop sharing request queue across multiple gendisks
authorOmar Sandoval <osandov@fb.com>
Tue, 28 Mar 2017 06:28:43 +0000 (23:28 -0700)
committerJens Axboe <axboe@fb.com>
Tue, 28 Mar 2017 21:06:58 +0000 (15:06 -0600)
Compile-tested only.

Cc: Tim Waugh <tim@cyberelk.net>
Signed-off-by: Omar Sandoval <osandov@fb.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
drivers/block/paride/pd.c

index 9cfd2e06a64917a99a3f70da9753cbc8bd27401c..b05e151c9b38eb7bb7fe54b3a82d5a8f3cdf51c7 100644 (file)
@@ -381,12 +381,33 @@ static enum action do_pd_write_start(void);
 static enum action do_pd_read_drq(void);
 static enum action do_pd_write_done(void);
 
-static struct request_queue *pd_queue;
+static int pd_queue;
 static int pd_claimed;
 
 static struct pd_unit *pd_current; /* current request's drive */
 static PIA *pi_current; /* current request's PIA */
 
+static int set_next_request(void)
+{
+       struct gendisk *disk;
+       struct request_queue *q;
+       int old_pos = pd_queue;
+
+       do {
+               disk = pd[pd_queue].gd;
+               q = disk ? disk->queue : NULL;
+               if (++pd_queue == PD_UNITS)
+                       pd_queue = 0;
+               if (q) {
+                       pd_req = blk_fetch_request(q);
+                       if (pd_req)
+                               break;
+               }
+       } while (pd_queue != old_pos);
+
+       return pd_req != NULL;
+}
+
 static void run_fsm(void)
 {
        while (1) {
@@ -418,8 +439,7 @@ static void run_fsm(void)
                                spin_lock_irqsave(&pd_lock, saved_flags);
                                if (!__blk_end_request_cur(pd_req,
                                                res == Ok ? 0 : -EIO)) {
-                                       pd_req = blk_fetch_request(pd_queue);
-                                       if (!pd_req)
+                                       if (!set_next_request())
                                                stop = 1;
                                }
                                spin_unlock_irqrestore(&pd_lock, saved_flags);
@@ -839,7 +859,13 @@ static void pd_probe_drive(struct pd_unit *disk)
        p->first_minor = (disk - pd) << PD_BITS;
        disk->gd = p;
        p->private_data = disk;
-       p->queue = pd_queue;
+       p->queue = blk_init_queue(do_pd_request, &pd_lock);
+       if (!p->queue) {
+               disk->gd = NULL;
+               put_disk(p);
+               return;
+       }
+       blk_queue_max_hw_sectors(p->queue, cluster);
 
        if (disk->drive == -1) {
                for (disk->drive = 0; disk->drive <= 1; disk->drive++)
@@ -919,26 +945,18 @@ static int __init pd_init(void)
        if (disable)
                goto out1;
 
-       pd_queue = blk_init_queue(do_pd_request, &pd_lock);
-       if (!pd_queue)
-               goto out1;
-
-       blk_queue_max_hw_sectors(pd_queue, cluster);
-
        if (register_blkdev(major, name))
-               goto out2;
+               goto out1;
 
        printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
               name, name, PD_VERSION, major, cluster, nice);
        if (!pd_detect())
-               goto out3;
+               goto out2;
 
        return 0;
 
-out3:
-       unregister_blkdev(major, name);
 out2:
-       blk_cleanup_queue(pd_queue);
+       unregister_blkdev(major, name);
 out1:
        return -ENODEV;
 }
@@ -953,11 +971,11 @@ static void __exit pd_exit(void)
                if (p) {
                        disk->gd = NULL;
                        del_gendisk(p);
+                       blk_cleanup_queue(p->queue);
                        put_disk(p);
                        pi_release(disk->pi);
                }
        }
-       blk_cleanup_queue(pd_queue);
 }
 
 MODULE_LICENSE("GPL");