]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
[SCSI] block: separate failfast into multiple bits.
authorMike Christie <michaelc@cs.wisc.edu>
Tue, 19 Aug 2008 23:45:30 +0000 (18:45 -0500)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Mon, 13 Oct 2008 13:28:52 +0000 (09:28 -0400)
Multipath is best at handling transport errors. If it gets a device
error then there is not much the multipath layer can do. It will just
access the same device but from a different path.

This patch breaks up failfast into device, transport and driver errors.
The multipath layers (md and dm mutlipath) only ask the lower levels to
fast fail transport errors. The user of failfast, read ahead, will ask
to fast fail on all errors.

Note that blk_noretry_request will return true if any failfast bit
is set. This allows drivers that do not support the multipath failfast
bits to continue to fail on any failfast error like before. Drivers
like scsi that are able to fail fast specific errors can check
for the specific fail fast type. In the next patch I will convert
scsi.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Cc: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
13 files changed:
block/blk-core.c
drivers/md/dm-mpath.c
drivers/md/multipath.c
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_fba.c
drivers/scsi/device_handler/scsi_dh_alua.c
drivers/scsi/device_handler/scsi_dh_emc.c
drivers/scsi/device_handler/scsi_dh_hp_sw.c
drivers/scsi/device_handler/scsi_dh_rdac.c
drivers/scsi/scsi_transport_spi.c
include/linux/bio.h
include/linux/blkdev.h

index 2d053b584410255c39a2209aa90aee633083e7a0..9e79a485e4f376db04180523e31b5e51b8c24a13 100644 (file)
@@ -1075,8 +1075,15 @@ void init_request_from_bio(struct request *req, struct bio *bio)
        /*
         * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST)
         */
-       if (bio_rw_ahead(bio) || bio_failfast(bio))
-               req->cmd_flags |= REQ_FAILFAST;
+       if (bio_rw_ahead(bio))
+               req->cmd_flags |= (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+                                  REQ_FAILFAST_DRIVER);
+       if (bio_failfast_dev(bio))
+               req->cmd_flags |= REQ_FAILFAST_DEV;
+       if (bio_failfast_transport(bio))
+               req->cmd_flags |= REQ_FAILFAST_TRANSPORT;
+       if (bio_failfast_driver(bio))
+               req->cmd_flags |= REQ_FAILFAST_DRIVER;
 
        /*
         * REQ_BARRIER implies no merging, but lets make it explicit
index 103304c1e3b06899d8277cd95369e3df94da36db..9bf3460c5540b9fdbefbacaed15788f7a6868fb0 100644 (file)
@@ -849,7 +849,7 @@ static int multipath_map(struct dm_target *ti, struct bio *bio,
        dm_bio_record(&mpio->details, bio);
 
        map_context->ptr = mpio;
-       bio->bi_rw |= (1 << BIO_RW_FAILFAST);
+       bio->bi_rw |= (1 << BIO_RW_FAILFAST_TRANSPORT);
        r = map_io(m, bio, mpio, 0);
        if (r < 0 || r == DM_MAPIO_REQUEUE)
                mempool_free(mpio, m->mpio_pool);
index 8bb8794129b372c9fdd065d961437c54e774d110..7ae33ebaf7ec9ed63f17e9cb712a673b0e25a30a 100644 (file)
@@ -176,7 +176,7 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio)
        mp_bh->bio = *bio;
        mp_bh->bio.bi_sector += multipath->rdev->data_offset;
        mp_bh->bio.bi_bdev = multipath->rdev->bdev;
-       mp_bh->bio.bi_rw |= (1 << BIO_RW_FAILFAST);
+       mp_bh->bio.bi_rw |= (1 << BIO_RW_FAILFAST_TRANSPORT);
        mp_bh->bio.bi_end_io = multipath_end_request;
        mp_bh->bio.bi_private = mp_bh;
        generic_make_request(&mp_bh->bio);
@@ -402,7 +402,7 @@ static void multipathd (mddev_t *mddev)
                        *bio = *(mp_bh->master_bio);
                        bio->bi_sector += conf->multipaths[mp_bh->path].rdev->data_offset;
                        bio->bi_bdev = conf->multipaths[mp_bh->path].rdev->bdev;
-                       bio->bi_rw |= (1 << BIO_RW_FAILFAST);
+                       bio->bi_rw |= (1 << BIO_RW_FAILFAST_TRANSPORT);
                        bio->bi_end_io = multipath_end_request;
                        bio->bi_private = mp_bh;
                        generic_make_request(bio);
index 85fcb43710541e4d1057bd06deeac90f29346992..7844461a995b7caf0b0b27ee32dfaf53f2d6cf69 100644 (file)
@@ -544,7 +544,7 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,
        }
        cqr->retries = DIAG_MAX_RETRIES;
        cqr->buildclk = get_clock();
-       if (req->cmd_flags & REQ_FAILFAST)
+       if (blk_noretry_request(req))
                set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
        cqr->startdev = memdev;
        cqr->memdev = memdev;
index 49f9d221e23d4de9dd0deda5867565d29330f3a7..2e60d5f968c84d81b9dd63bafb7a670b88170c4e 100644 (file)
@@ -1700,7 +1700,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
                        recid++;
                }
        }
-       if (req->cmd_flags & REQ_FAILFAST)
+       if (blk_noretry_request(req))
                set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
        cqr->startdev = startdev;
        cqr->memdev = startdev;
index 93d9b6452a94b5fb2e6606ed9efe92fffce72888..7d442aeff3d1163c6f6b728cdd0b9d2a1f2017e5 100644 (file)
@@ -355,7 +355,7 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
                        recid++;
                }
        }
-       if (req->cmd_flags & REQ_FAILFAST)
+       if (blk_noretry_request(req))
                set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
        cqr->startdev = memdev;
        cqr->memdev = memdev;
index 708e475896b9c5f21c13047a8fafe382fa22cb68..cb8aa3b58c22c6524519c8e718203308d8cd6d61 100644 (file)
@@ -109,7 +109,8 @@ static struct request *get_alua_req(struct scsi_device *sdev,
        }
 
        rq->cmd_type = REQ_TYPE_BLOCK_PC;
-       rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
+       rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+                        REQ_FAILFAST_DRIVER | REQ_NOMERGE;
        rq->retries = ALUA_FAILOVER_RETRIES;
        rq->timeout = ALUA_FAILOVER_TIMEOUT;
 
index 8f45570a8a01ca3d1943117e944e57d08d407789..0e572d2c5b0a3beb8bb88255634a6ee8248d73b3 100644 (file)
@@ -303,7 +303,8 @@ static struct request *get_req(struct scsi_device *sdev, int cmd,
 
        rq->cmd[4] = len;
        rq->cmd_type = REQ_TYPE_BLOCK_PC;
-       rq->cmd_flags |= REQ_FAILFAST;
+       rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+                        REQ_FAILFAST_DRIVER;
        rq->timeout = CLARIION_TIMEOUT;
        rq->retries = CLARIION_RETRIES;
 
index 5e93c88ad66b95e871b6d01236f9403a3269d048..9aec4ca64e56cf3f06f102b4860691ce94c12c94 100644 (file)
@@ -112,7 +112,8 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h)
                return SCSI_DH_RES_TEMP_UNAVAIL;
 
        req->cmd_type = REQ_TYPE_BLOCK_PC;
-       req->cmd_flags |= REQ_FAILFAST;
+       req->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+                         REQ_FAILFAST_DRIVER;
        req->cmd_len = COMMAND_SIZE(TEST_UNIT_READY);
        req->cmd[0] = TEST_UNIT_READY;
        req->timeout = HP_SW_TIMEOUT;
@@ -204,7 +205,8 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h)
                return SCSI_DH_RES_TEMP_UNAVAIL;
 
        req->cmd_type = REQ_TYPE_BLOCK_PC;
-       req->cmd_flags |= REQ_FAILFAST;
+       req->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+                         REQ_FAILFAST_DRIVER;
        req->cmd_len = COMMAND_SIZE(START_STOP);
        req->cmd[0] = START_STOP;
        req->cmd[4] = 1;        /* Start spin cycle */
index 50bf95f3b5c456cb7118583ed297b48b3782ed57..a43c3ed4df28c3dcb68d1843a6028459d085c0f0 100644 (file)
@@ -226,7 +226,8 @@ static struct request *get_rdac_req(struct scsi_device *sdev,
        }
 
        rq->cmd_type = REQ_TYPE_BLOCK_PC;
-       rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
+       rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+                        REQ_FAILFAST_DRIVER;
        rq->retries = RDAC_RETRIES;
        rq->timeout = RDAC_TIMEOUT;
 
index b29360ed0bdc9f0c2dd6a80c06cd4ef09a5cee66..7c2d28924d2a32e6c3f840e80d6e397429dc3e1b 100644 (file)
@@ -109,7 +109,9 @@ static int spi_execute(struct scsi_device *sdev, const void *cmd,
        for(i = 0; i < DV_RETRIES; i++) {
                result = scsi_execute(sdev, cmd, dir, buffer, bufflen,
                                      sense, DV_TIMEOUT, /* retries */ 1,
-                                     REQ_FAILFAST);
+                                     REQ_FAILFAST_DEV |
+                                     REQ_FAILFAST_TRANSPORT |
+                                     REQ_FAILFAST_DRIVER);
                if (result & DRIVER_SENSE) {
                        struct scsi_sense_hdr sshdr_tmp;
                        if (!sshdr)
index ff5b4cf9e2da71abd05b5fac387322b24c75b911..1beda208cbfbf17d1980dee03c49cd7d43678b7e 100644 (file)
@@ -129,25 +129,30 @@ struct bio {
  * bit 2 -- barrier
  *     Insert a serialization point in the IO queue, forcing previously
  *     submitted IO to be completed before this oen is issued.
- * bit 3 -- fail fast, don't want low level driver retries
- * bit 4 -- synchronous I/O hint: the block layer will unplug immediately
+ * bit 3 -- synchronous I/O hint: the block layer will unplug immediately
  *     Note that this does NOT indicate that the IO itself is sync, just
  *     that the block layer will not postpone issue of this IO by plugging.
- * bit 5 -- metadata request
+ * bit 4 -- metadata request
  *     Used for tracing to differentiate metadata and data IO. May also
  *     get some preferential treatment in the IO scheduler
- * bit 6 -- discard sectors
+ * bit 5 -- discard sectors
  *     Informs the lower level device that this range of sectors is no longer
  *     used by the file system and may thus be freed by the device. Used
  *     for flash based storage.
+ * bit 6 -- fail fast device errors
+ * bit 7 -- fail fast transport errors
+ * bit 8 -- fail fast driver errors
+ *     Don't want driver retries for any fast fail whatever the reason.
  */
 #define BIO_RW         0       /* Must match RW in req flags (blkdev.h) */
 #define BIO_RW_AHEAD   1       /* Must match FAILFAST in req flags */
 #define BIO_RW_BARRIER 2
-#define BIO_RW_FAILFAST        3
-#define BIO_RW_SYNC    4
-#define BIO_RW_META    5
-#define BIO_RW_DISCARD 6
+#define BIO_RW_SYNC    3
+#define BIO_RW_META    4
+#define BIO_RW_DISCARD 5
+#define BIO_RW_FAILFAST_DEV            6
+#define BIO_RW_FAILFAST_TRANSPORT      7
+#define BIO_RW_FAILFAST_DRIVER         8
 
 /*
  * upper 16 bits of bi_rw define the io priority of this bio
@@ -174,7 +179,10 @@ struct bio {
 #define bio_sectors(bio)       ((bio)->bi_size >> 9)
 #define bio_barrier(bio)       ((bio)->bi_rw & (1 << BIO_RW_BARRIER))
 #define bio_sync(bio)          ((bio)->bi_rw & (1 << BIO_RW_SYNC))
-#define bio_failfast(bio)      ((bio)->bi_rw & (1 << BIO_RW_FAILFAST))
+#define bio_failfast_dev(bio)  ((bio)->bi_rw & (1 << BIO_RW_FAILFAST_DEV))
+#define bio_failfast_transport(bio)    \
+       ((bio)->bi_rw & (1 << BIO_RW_FAILFAST_TRANSPORT))
+#define bio_failfast_driver(bio) ((bio)->bi_rw & (1 << BIO_RW_FAILFAST_DRIVER))
 #define bio_rw_ahead(bio)      ((bio)->bi_rw & (1 << BIO_RW_AHEAD))
 #define bio_rw_meta(bio)       ((bio)->bi_rw & (1 << BIO_RW_META))
 #define bio_discard(bio)       ((bio)->bi_rw & (1 << BIO_RW_DISCARD))
index a92d9e4ea96e1a0a5af66bf21c6dbf155674e418..f3491d2252686074ad939d511b8b762290deca99 100644 (file)
@@ -87,7 +87,9 @@ enum {
  */
 enum rq_flag_bits {
        __REQ_RW,               /* not set, read. set, write */
-       __REQ_FAILFAST,         /* no low level driver retries */
+       __REQ_FAILFAST_DEV,     /* no driver retries of device errors */
+       __REQ_FAILFAST_TRANSPORT, /* no driver retries of transport errors */
+       __REQ_FAILFAST_DRIVER,  /* no driver retries of driver errors */
        __REQ_DISCARD,          /* request to discard sectors */
        __REQ_SORTED,           /* elevator knows about this request */
        __REQ_SOFTBARRIER,      /* may not be passed by ioscheduler */
@@ -111,8 +113,10 @@ enum rq_flag_bits {
 };
 
 #define REQ_RW         (1 << __REQ_RW)
+#define REQ_FAILFAST_DEV       (1 << __REQ_FAILFAST_DEV)
+#define REQ_FAILFAST_TRANSPORT (1 << __REQ_FAILFAST_TRANSPORT)
+#define REQ_FAILFAST_DRIVER    (1 << __REQ_FAILFAST_DRIVER)
 #define REQ_DISCARD    (1 << __REQ_DISCARD)
-#define REQ_FAILFAST   (1 << __REQ_FAILFAST)
 #define REQ_SORTED     (1 << __REQ_SORTED)
 #define REQ_SOFTBARRIER        (1 << __REQ_SOFTBARRIER)
 #define REQ_HARDBARRIER        (1 << __REQ_HARDBARRIER)
@@ -560,7 +564,12 @@ enum {
 #define blk_special_request(rq)        ((rq)->cmd_type == REQ_TYPE_SPECIAL)
 #define blk_sense_request(rq)  ((rq)->cmd_type == REQ_TYPE_SENSE)
 
-#define blk_noretry_request(rq)        ((rq)->cmd_flags & REQ_FAILFAST)
+#define blk_failfast_dev(rq)   ((rq)->cmd_flags & REQ_FAILFAST_DEV)
+#define blk_failfast_transport(rq) ((rq)->cmd_flags & REQ_FAILFAST_TRANSPORT)
+#define blk_failfast_driver(rq)        ((rq)->cmd_flags & REQ_FAILFAST_DRIVER)
+#define blk_noretry_request(rq)        (blk_failfast_dev(rq) ||        \
+                                blk_failfast_transport(rq) ||  \
+                                blk_failfast_driver(rq))
 #define blk_rq_started(rq)     ((rq)->cmd_flags & REQ_STARTED)
 
 #define blk_account_rq(rq)     (blk_rq_started(rq) && (blk_fs_request(rq) || blk_discard_rq(rq)))