aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorStewart, Sean <Sean.Stewart@netapp.com>2013-10-15 11:52:54 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-10-25 06:19:33 -0400
commita8e5a2d593cbfccf530c3382c2c328d2edaa7b66 (patch)
tree879d7cc9168fbe2c9fceba2c16923f59c2f69ed1 /drivers/scsi
parentc20ee7b56e0a1937b41919813e5a98373ca48ae8 (diff)
[SCSI] scsi_dh_alua: ALUA handler attach should succeed while TPG is transitioning
During testing, it was discovered that when a device tries to attach to the alua handler while in TPG state of transitioning, the alua_rtpg function will wait for it to exit the state before allowing it to continue. As a result, if the 60 second timeout expires, the alua handler will not attach to the device. To fix this, I have introduced an input argument to alua_rtpg called wait_for_transition. The idea is that it will wait for the transition to complete before an activation (because the current TPG state has some bearing in that case), but during a discovery if it is transitioning, it will not wait, and will store the state as standby for the time being. I believe the precedent exists for this from commit c0d289b3e59577532c45ee9110ef81bd7b341272 Since if the device reports a state of transitioning, it can transition to other more valid states, and it has been established TPGS is supported on the device, if it is attaching. Signed-off-by: Sean Stewart <Sean.Stewart@netapp.com> Acked-by: Hannes Reinecke <hare@suse.de> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 78205cc2059c..5248c888552b 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -522,12 +522,13 @@ static int alua_check_sense(struct scsi_device *sdev,
522/* 522/*
523 * alua_rtpg - Evaluate REPORT TARGET GROUP STATES 523 * alua_rtpg - Evaluate REPORT TARGET GROUP STATES
524 * @sdev: the device to be evaluated. 524 * @sdev: the device to be evaluated.
525 * @wait_for_transition: if nonzero, wait ALUA_FAILOVER_TIMEOUT seconds for device to exit transitioning state
525 * 526 *
526 * Evaluate the Target Port Group State. 527 * Evaluate the Target Port Group State.
527 * Returns SCSI_DH_DEV_OFFLINED if the path is 528 * Returns SCSI_DH_DEV_OFFLINED if the path is
528 * found to be unusable. 529 * found to be unusable.
529 */ 530 */
530static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) 531static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_for_transition)
531{ 532{
532 struct scsi_sense_hdr sense_hdr; 533 struct scsi_sense_hdr sense_hdr;
533 int len, k, off, valid_states = 0; 534 int len, k, off, valid_states = 0;
@@ -599,7 +600,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
599 else 600 else
600 h->transition_tmo = ALUA_FAILOVER_TIMEOUT; 601 h->transition_tmo = ALUA_FAILOVER_TIMEOUT;
601 602
602 if (orig_transition_tmo != h->transition_tmo) { 603 if (wait_for_transition && (orig_transition_tmo != h->transition_tmo)) {
603 sdev_printk(KERN_INFO, sdev, 604 sdev_printk(KERN_INFO, sdev,
604 "%s: transition timeout set to %d seconds\n", 605 "%s: transition timeout set to %d seconds\n",
605 ALUA_DH_NAME, h->transition_tmo); 606 ALUA_DH_NAME, h->transition_tmo);
@@ -637,14 +638,19 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
637 638
638 switch (h->state) { 639 switch (h->state) {
639 case TPGS_STATE_TRANSITIONING: 640 case TPGS_STATE_TRANSITIONING:
640 if (time_before(jiffies, expiry)) { 641 if (wait_for_transition) {
641 /* State transition, retry */ 642 if (time_before(jiffies, expiry)) {
642 interval += 2000; 643 /* State transition, retry */
643 msleep(interval); 644 interval += 2000;
644 goto retry; 645 msleep(interval);
646 goto retry;
647 }
648 err = SCSI_DH_RETRY;
649 } else {
650 err = SCSI_DH_OK;
645 } 651 }
652
646 /* Transitioning time exceeded, set port to standby */ 653 /* Transitioning time exceeded, set port to standby */
647 err = SCSI_DH_RETRY;
648 h->state = TPGS_STATE_STANDBY; 654 h->state = TPGS_STATE_STANDBY;
649 break; 655 break;
650 case TPGS_STATE_OFFLINE: 656 case TPGS_STATE_OFFLINE:
@@ -678,7 +684,7 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
678 if (err != SCSI_DH_OK) 684 if (err != SCSI_DH_OK)
679 goto out; 685 goto out;
680 686
681 err = alua_rtpg(sdev, h); 687 err = alua_rtpg(sdev, h, 0);
682 if (err != SCSI_DH_OK) 688 if (err != SCSI_DH_OK)
683 goto out; 689 goto out;
684 690
@@ -738,7 +744,7 @@ static int alua_activate(struct scsi_device *sdev,
738 int err = SCSI_DH_OK; 744 int err = SCSI_DH_OK;
739 int stpg = 0; 745 int stpg = 0;
740 746
741 err = alua_rtpg(sdev, h); 747 err = alua_rtpg(sdev, h, 1);
742 if (err != SCSI_DH_OK) 748 if (err != SCSI_DH_OK)
743 goto out; 749 goto out;
744 750