提交 a8e5a2d5 编写于 作者: S Stewart, Sean 提交者: James Bottomley

[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
c0d289b3 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: NSean Stewart <Sean.Stewart@netapp.com>
Acked-by: NHannes Reinecke <hare@suse.de>
Signed-off-by: NJames Bottomley <JBottomley@Parallels.com>
上级 c20ee7b5
...@@ -522,12 +522,13 @@ static int alua_check_sense(struct scsi_device *sdev, ...@@ -522,12 +522,13 @@ static int alua_check_sense(struct scsi_device *sdev,
/* /*
* alua_rtpg - Evaluate REPORT TARGET GROUP STATES * alua_rtpg - Evaluate REPORT TARGET GROUP STATES
* @sdev: the device to be evaluated. * @sdev: the device to be evaluated.
* @wait_for_transition: if nonzero, wait ALUA_FAILOVER_TIMEOUT seconds for device to exit transitioning state
* *
* Evaluate the Target Port Group State. * Evaluate the Target Port Group State.
* Returns SCSI_DH_DEV_OFFLINED if the path is * Returns SCSI_DH_DEV_OFFLINED if the path is
* found to be unusable. * found to be unusable.
*/ */
static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_for_transition)
{ {
struct scsi_sense_hdr sense_hdr; struct scsi_sense_hdr sense_hdr;
int len, k, off, valid_states = 0; 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,7 +600,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
else else
h->transition_tmo = ALUA_FAILOVER_TIMEOUT; h->transition_tmo = ALUA_FAILOVER_TIMEOUT;
if (orig_transition_tmo != h->transition_tmo) { if (wait_for_transition && (orig_transition_tmo != h->transition_tmo)) {
sdev_printk(KERN_INFO, sdev, sdev_printk(KERN_INFO, sdev,
"%s: transition timeout set to %d seconds\n", "%s: transition timeout set to %d seconds\n",
ALUA_DH_NAME, h->transition_tmo); ALUA_DH_NAME, h->transition_tmo);
...@@ -637,14 +638,19 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) ...@@ -637,14 +638,19 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
switch (h->state) { switch (h->state) {
case TPGS_STATE_TRANSITIONING: case TPGS_STATE_TRANSITIONING:
if (wait_for_transition) {
if (time_before(jiffies, expiry)) { if (time_before(jiffies, expiry)) {
/* State transition, retry */ /* State transition, retry */
interval += 2000; interval += 2000;
msleep(interval); msleep(interval);
goto retry; goto retry;
} }
/* Transitioning time exceeded, set port to standby */
err = SCSI_DH_RETRY; err = SCSI_DH_RETRY;
} else {
err = SCSI_DH_OK;
}
/* Transitioning time exceeded, set port to standby */
h->state = TPGS_STATE_STANDBY; h->state = TPGS_STATE_STANDBY;
break; break;
case TPGS_STATE_OFFLINE: case TPGS_STATE_OFFLINE:
...@@ -678,7 +684,7 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h) ...@@ -678,7 +684,7 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
if (err != SCSI_DH_OK) if (err != SCSI_DH_OK)
goto out; goto out;
err = alua_rtpg(sdev, h); err = alua_rtpg(sdev, h, 0);
if (err != SCSI_DH_OK) if (err != SCSI_DH_OK)
goto out; goto out;
...@@ -738,7 +744,7 @@ static int alua_activate(struct scsi_device *sdev, ...@@ -738,7 +744,7 @@ static int alua_activate(struct scsi_device *sdev,
int err = SCSI_DH_OK; int err = SCSI_DH_OK;
int stpg = 0; int stpg = 0;
err = alua_rtpg(sdev, h); err = alua_rtpg(sdev, h, 1);
if (err != SCSI_DH_OK) if (err != SCSI_DH_OK)
goto out; goto out;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册