Merge tag 'iio-fixes-for-3.14a' of git://git.kernel.org/pub/scm/linux/kernel/git...
[firefly-linux-kernel-4.4.55.git] / drivers / md / dm-mpath.c
index de570a55876451a0326d071da4cf68fd772eec2e..6eb9dc9ef8f36c4b709df6f3b46170598964e88d 100644 (file)
@@ -87,6 +87,7 @@ struct multipath {
        unsigned queue_if_no_path:1;    /* Queue I/O if last path fails? */
        unsigned saved_queue_if_no_path:1; /* Saved state during suspension */
        unsigned retain_attached_hw_handler:1; /* If there's already a hw_handler present, don't change it. */
+       unsigned pg_init_disabled:1;    /* pg_init is not currently allowed */
 
        unsigned pg_init_retries;       /* Number of times to retry pg_init */
        unsigned pg_init_count;         /* Number of times pg_init called */
@@ -390,13 +391,16 @@ static int map_io(struct multipath *m, struct request *clone,
        if (was_queued)
                m->queue_size--;
 
-       if ((pgpath && m->queue_io) ||
-           (!pgpath && m->queue_if_no_path)) {
+       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->pg_init_required && !m->pg_init_in_progress) ||
-                   !m->queue_io)
+               if (!m->queue_io)
                        queue_work(kmultipathd, &m->process_queued_ios);
                pgpath = NULL;
                r = DM_MAPIO_SUBMITTED;
@@ -497,7 +501,8 @@ static void process_queued_ios(struct work_struct *work)
            (!pgpath && !m->queue_if_no_path))
                must_queue = 0;
 
-       if (m->pg_init_required && !m->pg_init_in_progress && pgpath)
+       if (m->pg_init_required && !m->pg_init_in_progress && pgpath &&
+           !m->pg_init_disabled)
                __pg_init_all_paths(m);
 
        spin_unlock_irqrestore(&m->lock, flags);
@@ -942,10 +947,20 @@ static void multipath_wait_for_pg_init_completion(struct multipath *m)
 
 static void flush_multipath_work(struct multipath *m)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&m->lock, flags);
+       m->pg_init_disabled = 1;
+       spin_unlock_irqrestore(&m->lock, flags);
+
        flush_workqueue(kmpath_handlerd);
        multipath_wait_for_pg_init_completion(m);
        flush_workqueue(kmultipathd);
        flush_work(&m->trigger_event);
+
+       spin_lock_irqsave(&m->lock, flags);
+       m->pg_init_disabled = 0;
+       spin_unlock_irqrestore(&m->lock, flags);
 }
 
 static void multipath_dtr(struct dm_target *ti)
@@ -1164,7 +1179,7 @@ static int pg_init_limit_reached(struct multipath *m, struct pgpath *pgpath)
 
        spin_lock_irqsave(&m->lock, flags);
 
-       if (m->pg_init_count <= m->pg_init_retries)
+       if (m->pg_init_count <= m->pg_init_retries && !m->pg_init_disabled)
                m->pg_init_required = 1;
        else
                limit_reached = 1;
@@ -1665,6 +1680,11 @@ 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) {
+               busy = 1;
+               goto out;
+       }
        /* Guess which priority_group will be used at next mapping time */
        if (unlikely(!m->current_pgpath && m->next_pg))
                pg = m->next_pg;
@@ -1714,7 +1734,7 @@ out:
  *---------------------------------------------------------------*/
 static struct target_type multipath_target = {
        .name = "multipath",
-       .version = {1, 5, 1},
+       .version = {1, 6, 0},
        .module = THIS_MODULE,
        .ctr = multipath_ctr,
        .dtr = multipath_dtr,