dm mpath: factor out SCSI vs NVMe path selection
authorMike Snitzer <snitzer@redhat.com>
Mon, 11 Dec 2017 16:02:29 +0000 (11:02 -0500)
committerMike Snitzer <snitzer@redhat.com>
Sat, 6 Jan 2018 16:23:28 +0000 (11:23 -0500)
Trying to do both SCSI and NVMe bio-based handling with branching in the
same common code has proven too tedious on a code maintenance level.  In
addition it slightly hurts IO performance.

Fix this by factoring out __map_bio() and __map_bio_nvme().

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
drivers/md/dm-mpath.c

index fa5ee78..6d1a990 100644 (file)
@@ -555,7 +555,8 @@ static void multipath_release_clone(struct request *clone)
 /*
  * Map cloned bios (bio-based multipath)
  */
-static int __multipath_map_bio(struct multipath *m, struct bio *bio, struct dm_mpath_io *mpio)
+
+static struct pgpath *__map_bio(struct multipath *m, struct bio *bio)
 {
        struct pgpath *pgpath;
        unsigned long flags;
@@ -563,30 +564,71 @@ static int __multipath_map_bio(struct multipath *m, struct bio *bio, struct dm_m
 
        /* Do we need to select a new pgpath? */
        pgpath = READ_ONCE(m->current_pgpath);
-       /* MPATHF_QUEUE_IO will never be set for NVMe */
        queue_io = test_bit(MPATHF_QUEUE_IO, &m->flags);
        if (!pgpath || !queue_io)
-               pgpath = choose_pgpath(m, mpio->nr_bytes);
+               pgpath = choose_pgpath(m, bio->bi_iter.bi_size);
 
-       if ((!pgpath && test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) ||
-           (pgpath && queue_io)) {
+       if ((pgpath && queue_io) ||
+           (!pgpath && test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))) {
                /* Queue for the daemon to resubmit */
                spin_lock_irqsave(&m->lock, flags);
                bio_list_add(&m->queued_bios, bio);
                spin_unlock_irqrestore(&m->lock, flags);
 
-               if (m->queue_mode == DM_TYPE_NVME_BIO_BASED) {
+               /* PG_INIT_REQUIRED cannot be set without QUEUE_IO */
+               if (queue_io || test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags))
+                       pg_init_all_paths(m);
+               else if (!queue_io)
                        queue_work(kmultipathd, &m->process_queued_bios);
-               } else {
-                       /* PG_INIT_REQUIRED cannot be set without QUEUE_IO */
-                       if (queue_io || test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags))
-                               pg_init_all_paths(m);
-                       else if (!queue_io)
-                               queue_work(kmultipathd, &m->process_queued_bios);
+
+               return ERR_PTR(-EAGAIN);
+       }
+
+       return pgpath;
+}
+
+static struct pgpath *__map_bio_nvme(struct multipath *m, struct bio *bio)
+{
+       struct pgpath *pgpath;
+       unsigned long flags;
+
+       /* Do we need to select a new pgpath? */
+       /*
+        * FIXME: currently only switching path if no path (due to failure, etc)
+        * - which negates the point of using a path selector
+        */
+       pgpath = READ_ONCE(m->current_pgpath);
+       if (!pgpath)
+               pgpath = choose_pgpath(m, bio->bi_iter.bi_size);
+
+       if (!pgpath) {
+               if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
+                       /* Queue for the daemon to resubmit */
+                       spin_lock_irqsave(&m->lock, flags);
+                       bio_list_add(&m->queued_bios, bio);
+                       spin_unlock_irqrestore(&m->lock, flags);
+                       queue_work(kmultipathd, &m->process_queued_bios);
+
+                       return ERR_PTR(-EAGAIN);
                }
+               return NULL;
+       }
 
+       return pgpath;
+}
+
+static int __multipath_map_bio(struct multipath *m, struct bio *bio,
+                              struct dm_mpath_io *mpio)
+{
+       struct pgpath *pgpath;
+
+       if (m->queue_mode == DM_TYPE_NVME_BIO_BASED)
+               pgpath = __map_bio_nvme(m, bio);
+       else
+               pgpath = __map_bio(m, bio);
+
+       if (IS_ERR(pgpath))
                return DM_MAPIO_SUBMITTED;
-       }
 
        if (!pgpath) {
                if (must_push_back_bio(m))