aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Evers <revers@redhat.com>2012-05-18 14:08:54 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-07-20 03:58:32 -0400
commit3588c5a21aef8c8dcc3b30d72c62971e97af1322 (patch)
treee988d106664bb37c8044165ce18319b65c249e38
parent6ad819b06ddf13a5a1d995eb26555903f6c3b71a (diff)
[SCSI] scsi_dh_alua: implement 'implied transition timeout'
During alua transitions, an array can return transitioning status in response to rtpg requests. These requests get retried for a maximum of 60 seconds by default before timing out. Sometimes this timeout isn't sufficient to allow the array to complete the transition. T10-spc4 addresses this under 'Report Target Port Groups' command. This update retrieves the timeout value from the storage array if available and retries the transitioning rtpgs for up to the 'implied transitioning timeout' value Signed-off-by: Rob Evers <revers@redhat.com> Reviewed-by: Babu Moger <babu.moger@netapp.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c41
-rw-r--r--include/scsi/scsi.h2
2 files changed, 38 insertions, 5 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index fda9cdea0e60..ac6fddf99e99 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -46,13 +46,16 @@
46#define TPGS_SUPPORT_OFFLINE 0x40 46#define TPGS_SUPPORT_OFFLINE 0x40
47#define TPGS_SUPPORT_TRANSITION 0x80 47#define TPGS_SUPPORT_TRANSITION 0x80
48 48
49#define RTPG_FMT_MASK 0x70
50#define RTPG_FMT_EXT_HDR 0x10
51
49#define TPGS_MODE_UNINITIALIZED -1 52#define TPGS_MODE_UNINITIALIZED -1
50#define TPGS_MODE_NONE 0x0 53#define TPGS_MODE_NONE 0x0
51#define TPGS_MODE_IMPLICIT 0x1 54#define TPGS_MODE_IMPLICIT 0x1
52#define TPGS_MODE_EXPLICIT 0x2 55#define TPGS_MODE_EXPLICIT 0x2
53 56
54#define ALUA_INQUIRY_SIZE 36 57#define ALUA_INQUIRY_SIZE 36
55#define ALUA_FAILOVER_TIMEOUT (60 * HZ) 58#define ALUA_FAILOVER_TIMEOUT 60
56#define ALUA_FAILOVER_RETRIES 5 59#define ALUA_FAILOVER_RETRIES 5
57 60
58/* flags passed from user level */ 61/* flags passed from user level */
@@ -68,6 +71,7 @@ struct alua_dh_data {
68 unsigned char inq[ALUA_INQUIRY_SIZE]; 71 unsigned char inq[ALUA_INQUIRY_SIZE];
69 unsigned char *buff; 72 unsigned char *buff;
70 int bufflen; 73 int bufflen;
74 unsigned char transition_tmo;
71 unsigned char sense[SCSI_SENSE_BUFFERSIZE]; 75 unsigned char sense[SCSI_SENSE_BUFFERSIZE];
72 int senselen; 76 int senselen;
73 struct scsi_device *sdev; 77 struct scsi_device *sdev;
@@ -128,7 +132,7 @@ static struct request *get_alua_req(struct scsi_device *sdev,
128 rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | 132 rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
129 REQ_FAILFAST_DRIVER; 133 REQ_FAILFAST_DRIVER;
130 rq->retries = ALUA_FAILOVER_RETRIES; 134 rq->retries = ALUA_FAILOVER_RETRIES;
131 rq->timeout = ALUA_FAILOVER_TIMEOUT; 135 rq->timeout = ALUA_FAILOVER_TIMEOUT * HZ;
132 136
133 return rq; 137 return rq;
134} 138}
@@ -185,7 +189,7 @@ static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
185 189
186 /* Prepare the command. */ 190 /* Prepare the command. */
187 rq->cmd[0] = MAINTENANCE_IN; 191 rq->cmd[0] = MAINTENANCE_IN;
188 rq->cmd[1] = MI_REPORT_TARGET_PGS; 192 rq->cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
189 rq->cmd[6] = (h->bufflen >> 24) & 0xff; 193 rq->cmd[6] = (h->bufflen >> 24) & 0xff;
190 rq->cmd[7] = (h->bufflen >> 16) & 0xff; 194 rq->cmd[7] = (h->bufflen >> 16) & 0xff;
191 rq->cmd[8] = (h->bufflen >> 8) & 0xff; 195 rq->cmd[8] = (h->bufflen >> 8) & 0xff;
@@ -519,8 +523,14 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
519 unsigned char *ucp; 523 unsigned char *ucp;
520 unsigned err; 524 unsigned err;
521 unsigned long expiry, interval = 1000; 525 unsigned long expiry, interval = 1000;
526 unsigned int tpg_desc_tbl_off;
527 unsigned char orig_transition_tmo;
528
529 if (!h->transition_tmo)
530 expiry = round_jiffies_up(jiffies + ALUA_FAILOVER_TIMEOUT * HZ);
531 else
532 expiry = round_jiffies_up(jiffies + h->transition_tmo * HZ);
522 533
523 expiry = round_jiffies_up(jiffies + ALUA_FAILOVER_TIMEOUT);
524 retry: 534 retry:
525 err = submit_rtpg(sdev, h); 535 err = submit_rtpg(sdev, h);
526 536
@@ -556,7 +566,28 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
556 goto retry; 566 goto retry;
557 } 567 }
558 568
559 for (k = 4, ucp = h->buff + 4; k < len; k += off, ucp += off) { 569 orig_transition_tmo = h->transition_tmo;
570 if ((h->buff[4] & RTPG_FMT_MASK) == RTPG_FMT_EXT_HDR && h->buff[5] != 0)
571 h->transition_tmo = h->buff[5];
572 else
573 h->transition_tmo = ALUA_FAILOVER_TIMEOUT;
574
575 if (orig_transition_tmo != h->transition_tmo) {
576 sdev_printk(KERN_INFO, sdev,
577 "%s: transition timeout set to %d seconds\n",
578 ALUA_DH_NAME, h->transition_tmo);
579 expiry = jiffies + h->transition_tmo * HZ;
580 }
581
582 if ((h->buff[4] & RTPG_FMT_MASK) == RTPG_FMT_EXT_HDR)
583 tpg_desc_tbl_off = 8;
584 else
585 tpg_desc_tbl_off = 4;
586
587 for (k = tpg_desc_tbl_off, ucp = h->buff + tpg_desc_tbl_off;
588 k < len;
589 k += off, ucp += off) {
590
560 if (h->group_id == (ucp[2] << 8) + ucp[3]) { 591 if (h->group_id == (ucp[2] << 8) + ucp[3]) {
561 h->state = ucp[0] & 0x0f; 592 h->state = ucp[0] & 0x0f;
562 h->pref = ucp[0] >> 7; 593 h->pref = ucp[0] >> 7;
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index f34a5a87af38..c6f0974b8916 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -161,6 +161,8 @@ struct scsi_cmnd;
161#define MI_REPORT_PRIORITY 0x0e 161#define MI_REPORT_PRIORITY 0x0e
162#define MI_REPORT_TIMESTAMP 0x0f 162#define MI_REPORT_TIMESTAMP 0x0f
163#define MI_MANAGEMENT_PROTOCOL_IN 0x10 163#define MI_MANAGEMENT_PROTOCOL_IN 0x10
164/* value for MI_REPORT_TARGET_PGS ext header */
165#define MI_EXT_HDR_PARAM_FMT 0x20
164/* values for maintenance out */ 166/* values for maintenance out */
165#define MO_SET_IDENTIFYING_INFORMATION 0x06 167#define MO_SET_IDENTIFYING_INFORMATION 0x06
166#define MO_SET_TARGET_PGS 0x0a 168#define MO_SET_TARGET_PGS 0x0a