[SCSI] dm mpath: propagate target errors immediately
authorHannes Reinecke <hare@suse.de>
Tue, 18 Jan 2011 09:13:12 +0000 (10:13 +0100)
committerJames Bottomley <James.Bottomley@suse.de>
Sat, 12 Feb 2011 16:33:29 +0000 (10:33 -0600)
DM now has more information about the nature of the underlying storage
failure.  Path failure is avoided if a request failed due to a target
error.  Instead the target error is immediately passed up the stack.

Discard requests that fail due to non-target errors may now be retried.

Errors restricted to the path will be retried or returned if no
paths are available, irregarding the no_path_retry setting.

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Acked-by: Alasdair G Kergon <agk@redhat.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/md/dm-mpath.c

index b82d288..4b0b63c 100644 (file)
@@ -1283,24 +1283,22 @@ static int do_end_io(struct multipath *m, struct request *clone,
        if (!error && !clone->errors)
                return 0;       /* I/O complete */
 
-       if (error == -EOPNOTSUPP)
-               return error;
-
-       if (clone->cmd_flags & REQ_DISCARD)
-               /*
-                * Pass all discard request failures up.
-                * FIXME: only fail_path if the discard failed due to a
-                * transport problem.  This requires precise understanding
-                * of the underlying failure (e.g. the SCSI sense).
-                */
+       if (error == -EOPNOTSUPP || error == -EREMOTEIO)
                return error;
 
        if (mpio->pgpath)
                fail_path(mpio->pgpath);
 
        spin_lock_irqsave(&m->lock, flags);
-       if (!m->nr_valid_paths && !m->queue_if_no_path && !__must_push_back(m))
-               r = -EIO;
+       if (!m->nr_valid_paths) {
+               if (!m->queue_if_no_path) {
+                       if (!__must_push_back(m))
+                               r = -EIO;
+               } else {
+                       if (error == -EBADE)
+                               r = error;
+               }
+       }
        spin_unlock_irqrestore(&m->lock, flags);
 
        return r;