dm mpath: push back requests instead of queueing
authorHannes Reinecke <hare@suse.de>
Fri, 28 Feb 2014 14:33:44 +0000 (15:33 +0100)
committerMike Snitzer <snitzer@redhat.com>
Thu, 27 Mar 2014 20:56:24 +0000 (16:56 -0400)
There is no reason why multipath needs to queue requests internally for
queue_if_no_path or pg_init; we should rather push them back onto the
request queue.

And while we're at it we can simplify the conditional statement in
map_io() to make it easier to read.

Since mpath no longer does internal queuing of I/O the table info no
longer emits the internal queue_size.  Instead it displays 1 if queuing
is being used or 0 if it is not.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Reviewed-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
drivers/md/dm-mpath.c

index c78e6a9e59cea0bacb112031aa1dd93929605d3d..e1c3ed31c9df40b049a14b040d02f2dd75df05a7 100644 (file)
@@ -93,9 +93,7 @@ struct multipath {
        unsigned pg_init_count;         /* Number of times pg_init called */
        unsigned pg_init_delay_msecs;   /* Number of msecs before pg_init retry */
 
-       unsigned queue_size;
        struct work_struct process_queued_ios;
-       struct list_head queued_ios;
 
        struct work_struct trigger_event;
 
@@ -124,6 +122,7 @@ static struct workqueue_struct *kmultipathd, *kmpath_handlerd;
 static void process_queued_ios(struct work_struct *work);
 static void trigger_event(struct work_struct *work);
 static void activate_path(struct work_struct *work);
+static int __pgpath_busy(struct pgpath *pgpath);
 
 
 /*-----------------------------------------------
@@ -195,7 +194,6 @@ static struct multipath *alloc_multipath(struct dm_target *ti)
        m = kzalloc(sizeof(*m), GFP_KERNEL);
        if (m) {
                INIT_LIST_HEAD(&m->priority_groups);
-               INIT_LIST_HEAD(&m->queued_ios);
                spin_lock_init(&m->lock);
                m->queue_io = 1;
                m->pg_init_delay_msecs = DM_PG_INIT_DELAY_DEFAULT;
@@ -368,12 +366,15 @@ failed:
  */
 static int __must_push_back(struct multipath *m)
 {
-       return (m->queue_if_no_path != m->saved_queue_if_no_path &&
-               dm_noflush_suspending(m->ti));
+       return (m->queue_if_no_path ||
+               (m->queue_if_no_path != m->saved_queue_if_no_path &&
+                dm_noflush_suspending(m->ti)));
 }
 
+#define pg_ready(m) (!(m)->queue_io && !(m)->pg_init_required)
+
 static int map_io(struct multipath *m, struct request *clone,
-                 union map_info *map_context, unsigned was_queued)
+                 union map_info *map_context)
 {
        int r = DM_MAPIO_REMAPPED;
        size_t nr_bytes = blk_rq_bytes(clone);
@@ -391,37 +392,28 @@ static int map_io(struct multipath *m, struct request *clone,
 
        pgpath = m->current_pgpath;
 
-       if (was_queued)
-               m->queue_size--;
-
-       if (m->pg_init_required) {
-               if (!m->pg_init_in_progress)
-                       queue_work(kmultipathd, &m->process_queued_ios);
-               r = DM_MAPIO_REQUEUE;
-       } else if ((pgpath && m->queue_io) ||
-                  (!pgpath && m->queue_if_no_path)) {
-               /* Queue for the daemon to resubmit */
-               list_add_tail(&clone->queuelist, &m->queued_ios);
-               m->queue_size++;
-               if (!m->queue_io)
-                       queue_work(kmultipathd, &m->process_queued_ios);
-               pgpath = NULL;
-               r = DM_MAPIO_SUBMITTED;
-       } else if (pgpath) {
-               bdev = pgpath->path.dev->bdev;
-               clone->q = bdev_get_queue(bdev);
-               clone->rq_disk = bdev->bd_disk;
-       } else if (__must_push_back(m))
-               r = DM_MAPIO_REQUEUE;
-       else
-               r = -EIO;       /* Failed */
-
-       mpio->pgpath = pgpath;
-       mpio->nr_bytes = nr_bytes;
-
-       if (r == DM_MAPIO_REMAPPED && pgpath->pg->ps.type->start_io)
-               pgpath->pg->ps.type->start_io(&pgpath->pg->ps, &pgpath->path,
-                                             nr_bytes);
+       if (pgpath) {
+               if (pg_ready(m)) {
+                       bdev = pgpath->path.dev->bdev;
+                       clone->q = bdev_get_queue(bdev);
+                       clone->rq_disk = bdev->bd_disk;
+                       mpio->pgpath = pgpath;
+                       mpio->nr_bytes = nr_bytes;
+                       if (pgpath->pg->ps.type->start_io)
+                               pgpath->pg->ps.type->start_io(&pgpath->pg->ps,
+                                                             &pgpath->path,
+                                                             nr_bytes);
+               } else {
+                       __pg_init_all_paths(m);
+                       r = DM_MAPIO_REQUEUE;
+               }
+       } else {
+               /* No path */
+               if (__must_push_back(m))
+                       r = DM_MAPIO_REQUEUE;
+               else
+                       r = -EIO;       /* Failed */
+       }
 
        spin_unlock_irqrestore(&m->lock, flags);
 
@@ -443,7 +435,7 @@ static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path,
        else
                m->saved_queue_if_no_path = queue_if_no_path;
        m->queue_if_no_path = queue_if_no_path;
-       if (!m->queue_if_no_path && m->queue_size)
+       if (!m->queue_if_no_path)
                queue_work(kmultipathd, &m->process_queued_ios);
 
        spin_unlock_irqrestore(&m->lock, flags);
@@ -451,40 +443,6 @@ static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path,
        return 0;
 }
 
-/*-----------------------------------------------------------------
- * The multipath daemon is responsible for resubmitting queued ios.
- *---------------------------------------------------------------*/
-
-static void dispatch_queued_ios(struct multipath *m)
-{
-       int r;
-       unsigned long flags;
-       union map_info *info;
-       struct request *clone, *n;
-       LIST_HEAD(cl);
-
-       spin_lock_irqsave(&m->lock, flags);
-       list_splice_init(&m->queued_ios, &cl);
-       spin_unlock_irqrestore(&m->lock, flags);
-
-       list_for_each_entry_safe(clone, n, &cl, queuelist) {
-               list_del_init(&clone->queuelist);
-
-               info = dm_get_rq_mapinfo(clone);
-
-               r = map_io(m, clone, info, 1);
-               if (r < 0) {
-                       clear_mapinfo(m, info);
-                       dm_kill_unmapped_request(clone, r);
-               } else if (r == DM_MAPIO_REMAPPED)
-                       dm_dispatch_request(clone);
-               else if (r == DM_MAPIO_REQUEUE) {
-                       clear_mapinfo(m, info);
-                       dm_requeue_unmapped_request(clone);
-               }
-       }
-}
-
 static void process_queued_ios(struct work_struct *work)
 {
        struct multipath *m =
@@ -509,7 +467,7 @@ static void process_queued_ios(struct work_struct *work)
 
        spin_unlock_irqrestore(&m->lock, flags);
        if (!must_queue)
-               dispatch_queued_ios(m);
+               dm_table_run_md_queue_async(m->ti->table);
 }
 
 /*
@@ -987,7 +945,7 @@ static int multipath_map(struct dm_target *ti, struct request *clone,
                return DM_MAPIO_REQUEUE;
 
        clone->cmd_flags |= REQ_FAILFAST_TRANSPORT;
-       r = map_io(m, clone, map_context, 0);
+       r = map_io(m, clone, map_context);
        if (r < 0 || r == DM_MAPIO_REQUEUE)
                clear_mapinfo(m, map_context);
 
@@ -1056,7 +1014,7 @@ static int reinstate_path(struct pgpath *pgpath)
 
        pgpath->is_active = 1;
 
-       if (!m->nr_valid_paths++ && m->queue_size) {
+       if (!m->nr_valid_paths++) {
                m->current_pgpath = NULL;
                queue_work(kmultipathd, &m->process_queued_ios);
        } else if (m->hw_handler_name && (m->current_pg == pgpath->pg)) {
@@ -1435,7 +1393,7 @@ static void multipath_status(struct dm_target *ti, status_type_t type,
 
        /* Features */
        if (type == STATUSTYPE_INFO)
-               DMEMIT("2 %u %u ", m->queue_size, m->pg_init_count);
+               DMEMIT("2 %u %u ", m->queue_io, m->pg_init_count);
        else {
                DMEMIT("%u ", m->queue_if_no_path +
                              (m->pg_init_retries > 0) * 2 +
@@ -1686,7 +1644,7 @@ static int multipath_busy(struct dm_target *ti)
        spin_lock_irqsave(&m->lock, flags);
 
        /* pg_init in progress, requeue until done */
-       if (m->pg_init_in_progress) {
+       if (!pg_ready(m)) {
                busy = 1;
                goto out;
        }
@@ -1739,7 +1697,7 @@ out:
  *---------------------------------------------------------------*/
 static struct target_type multipath_target = {
        .name = "multipath",
-       .version = {1, 6, 0},
+       .version = {1, 7, 0},
        .module = THIS_MODULE,
        .ctr = multipath_ctr,
        .dtr = multipath_dtr,