mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-30 07:37:49 +00:00
[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>
This commit is contained in:
parent
c20ee7b56e
commit
a8e5a2d593
@ -522,12 +522,13 @@ static int alua_check_sense(struct scsi_device *sdev,
|
||||
/*
|
||||
* alua_rtpg - Evaluate REPORT TARGET GROUP STATES
|
||||
* @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.
|
||||
* Returns SCSI_DH_DEV_OFFLINED if the path is
|
||||
* 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;
|
||||
int len, k, off, valid_states = 0;
|
||||
@ -599,7 +600,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
|
||||
else
|
||||
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,
|
||||
"%s: transition timeout set to %d seconds\n",
|
||||
ALUA_DH_NAME, h->transition_tmo);
|
||||
@ -637,14 +638,19 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
|
||||
|
||||
switch (h->state) {
|
||||
case TPGS_STATE_TRANSITIONING:
|
||||
if (time_before(jiffies, expiry)) {
|
||||
/* State transition, retry */
|
||||
interval += 2000;
|
||||
msleep(interval);
|
||||
goto retry;
|
||||
if (wait_for_transition) {
|
||||
if (time_before(jiffies, expiry)) {
|
||||
/* State transition, retry */
|
||||
interval += 2000;
|
||||
msleep(interval);
|
||||
goto retry;
|
||||
}
|
||||
err = SCSI_DH_RETRY;
|
||||
} else {
|
||||
err = SCSI_DH_OK;
|
||||
}
|
||||
|
||||
/* Transitioning time exceeded, set port to standby */
|
||||
err = SCSI_DH_RETRY;
|
||||
h->state = TPGS_STATE_STANDBY;
|
||||
break;
|
||||
case TPGS_STATE_OFFLINE:
|
||||
@ -678,7 +684,7 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
|
||||
if (err != SCSI_DH_OK)
|
||||
goto out;
|
||||
|
||||
err = alua_rtpg(sdev, h);
|
||||
err = alua_rtpg(sdev, h, 0);
|
||||
if (err != SCSI_DH_OK)
|
||||
goto out;
|
||||
|
||||
@ -738,7 +744,7 @@ static int alua_activate(struct scsi_device *sdev,
|
||||
int err = SCSI_DH_OK;
|
||||
int stpg = 0;
|
||||
|
||||
err = alua_rtpg(sdev, h);
|
||||
err = alua_rtpg(sdev, h, 1);
|
||||
if (err != SCSI_DH_OK)
|
||||
goto out;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user