]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/md/dm-mpath.c
block: introduce new block status code type
[karo-tx-linux.git] / drivers / md / dm-mpath.c
index 926a6bcb32c8600118696119fd8ebe521cadbe5e..39262e344ae14eb862603c273a65ac7f8b68135a 100644 (file)
@@ -447,7 +447,7 @@ failed:
  * it has been invoked.
  */
 #define dm_report_EIO(m)                                               \
-({                                                                     \
+do {                                                                   \
        struct mapped_device *md = dm_table_get_md((m)->ti->table);     \
                                                                        \
        pr_debug("%s: returning EIO; QIFNP = %d; SQIFNP = %d; DNFS = %d\n", \
@@ -455,8 +455,7 @@ failed:
                 test_bit(MPATHF_QUEUE_IF_NO_PATH, &(m)->flags),        \
                 test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &(m)->flags),  \
                 dm_noflush_suspending((m)->ti));                       \
-       -EIO;                                                           \
-})
+} while (0)
 
 /*
  * Map cloned requests (request-based multipath)
@@ -481,7 +480,8 @@ static int multipath_clone_and_map(struct dm_target *ti, struct request *rq,
        if (!pgpath) {
                if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
                        return DM_MAPIO_DELAY_REQUEUE;
-               return dm_report_EIO(m);        /* Failed */
+               dm_report_EIO(m);       /* Failed */
+               return DM_MAPIO_KILL;
        } else if (test_bit(MPATHF_QUEUE_IO, &m->flags) ||
                   test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags)) {
                if (pg_init_all_paths(m))
@@ -558,7 +558,8 @@ static int __multipath_map_bio(struct multipath *m, struct bio *bio, struct dm_m
        if (!pgpath) {
                if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
                        return DM_MAPIO_REQUEUE;
-               return dm_report_EIO(m);
+               dm_report_EIO(m);
+               return DM_MAPIO_KILL;
        }
 
        mpio->pgpath = pgpath;
@@ -620,11 +621,18 @@ static void process_queued_bios(struct work_struct *work)
        blk_start_plug(&plug);
        while ((bio = bio_list_pop(&bios))) {
                r = __multipath_map_bio(m, bio, get_mpio_from_bio(bio));
-               if (r < 0 || r == DM_MAPIO_REQUEUE) {
+               switch (r) {
+               case DM_MAPIO_KILL:
+                       r = -EIO;
+                       /*FALLTHRU*/
+               case DM_MAPIO_REQUEUE:
                        bio->bi_error = r;
                        bio_endio(bio);
-               } else if (r == DM_MAPIO_REMAPPED)
+                       break;
+               case DM_MAPIO_REMAPPED:
                        generic_make_request(bio);
+                       break;
+               }
        }
        blk_finish_plug(&plug);
 }
@@ -1441,22 +1449,15 @@ static void activate_path_work(struct work_struct *work)
        activate_or_offline_path(pgpath);
 }
 
-static int noretry_error(int error)
+static int noretry_error(blk_status_t error)
 {
        switch (error) {
-       case -EBADE:
-               /*
-                * EBADE signals an reservation conflict.
-                * We shouldn't fail the path here as we can communicate with
-                * the target.  We should failover to the next path, but in
-                * doing so we might be causing a ping-pong between paths.
-                * So just return the reservation conflict error.
-                */
-       case -EOPNOTSUPP:
-       case -EREMOTEIO:
-       case -EILSEQ:
-       case -ENODATA:
-       case -ENOSPC:
+       case BLK_STS_NOTSUPP:
+       case BLK_STS_NOSPC:
+       case BLK_STS_TARGET:
+       case BLK_STS_NEXUS:
+       case BLK_STS_MEDIUM:
+       case BLK_STS_RESOURCE:
                return 1;
        }
 
@@ -1465,7 +1466,7 @@ static int noretry_error(int error)
 }
 
 static int multipath_end_io(struct dm_target *ti, struct request *clone,
-                           int error, union map_info *map_context)
+                           blk_status_t error, union map_info *map_context)
 {
        struct dm_mpath_io *mpio = get_mpio(map_context);
        struct pgpath *pgpath = mpio->pgpath;
@@ -1492,8 +1493,8 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone,
 
                if (atomic_read(&m->nr_valid_paths) == 0 &&
                    !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
-                       if (error == -EIO)
-                               error = dm_report_EIO(m);
+                       if (error == BLK_STS_IOERR)
+                               dm_report_EIO(m);
                        /* complete with the original error */
                        r = DM_ENDIO_DONE;
                }
@@ -1509,23 +1510,26 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone,
        return r;
 }
 
-static int do_end_io_bio(struct multipath *m, struct bio *clone,
-                        int error, struct dm_mpath_io *mpio)
+static int multipath_end_io_bio(struct dm_target *ti, struct bio *clone, int *error)
 {
+       struct multipath *m = ti->private;
+       struct dm_mpath_io *mpio = get_mpio_from_bio(clone);
+       struct pgpath *pgpath = mpio->pgpath;
        unsigned long flags;
+       int r = DM_ENDIO_DONE;
 
-       if (!error)
-               return 0;       /* I/O complete */
-
-       if (noretry_error(error))
-               return error;
+       if (!*error || noretry_error(errno_to_blk_status(*error)))
+               goto done;
 
-       if (mpio->pgpath)
-               fail_path(mpio->pgpath);
+       if (pgpath)
+               fail_path(pgpath);
 
        if (atomic_read(&m->nr_valid_paths) == 0 &&
-           !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
-               return dm_report_EIO(m);
+           !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
+               dm_report_EIO(m);
+               *error = -EIO;
+               goto done;
+       }
 
        /* Queue for the daemon to resubmit */
        dm_bio_restore(get_bio_details_from_bio(clone), clone);
@@ -1536,23 +1540,11 @@ static int do_end_io_bio(struct multipath *m, struct bio *clone,
        if (!test_bit(MPATHF_QUEUE_IO, &m->flags))
                queue_work(kmultipathd, &m->process_queued_bios);
 
-       return DM_ENDIO_INCOMPLETE;
-}
-
-static int multipath_end_io_bio(struct dm_target *ti, struct bio *clone, int error)
-{
-       struct multipath *m = ti->private;
-       struct dm_mpath_io *mpio = get_mpio_from_bio(clone);
-       struct pgpath *pgpath;
-       struct path_selector *ps;
-       int r;
-
-       BUG_ON(!mpio);
-
-       r = do_end_io_bio(m, clone, error, mpio);
-       pgpath = mpio->pgpath;
+       r = DM_ENDIO_INCOMPLETE;
+done:
        if (pgpath) {
-               ps = &pgpath->pg->ps;
+               struct path_selector *ps = &pgpath->pg->ps;
+
                if (ps->type->end_io)
                        ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes);
        }