mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
[SCSI] ibmvfc: Support FAST_IO_FAIL in EH handlers
Adds support for receiving FAST_IO_FAIL from fc_block_scsi_eh when in error recovery. This fixes cases of devices being taken offline when they are no longer accessible on the fabric, preventing them from coming back online when the fabric recovers. Signed-off-by: Brian King <brking@linux.vnet.ibm.com> Acked-by: Robert Jennings <rcj@linux.vnet.ibm.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
f8804b7239
commit
93631b4aac
1 changed files with 52 additions and 17 deletions
|
@ -2383,24 +2383,30 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
|
|||
* @cmd: scsi command to abort
|
||||
*
|
||||
* Returns:
|
||||
* SUCCESS / FAILED
|
||||
* SUCCESS / FAST_IO_FAIL / FAILED
|
||||
**/
|
||||
static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct scsi_device *sdev = cmd->device;
|
||||
struct ibmvfc_host *vhost = shost_priv(sdev->host);
|
||||
int cancel_rc, abort_rc;
|
||||
int cancel_rc, block_rc, abort_rc = 0;
|
||||
int rc = FAILED;
|
||||
|
||||
ENTER;
|
||||
fc_block_scsi_eh(cmd);
|
||||
block_rc = fc_block_scsi_eh(cmd);
|
||||
ibmvfc_wait_while_resetting(vhost);
|
||||
cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
|
||||
abort_rc = ibmvfc_abort_task_set(sdev);
|
||||
if (block_rc != FAST_IO_FAIL) {
|
||||
cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
|
||||
abort_rc = ibmvfc_abort_task_set(sdev);
|
||||
} else
|
||||
cancel_rc = ibmvfc_cancel_all(sdev, 0);
|
||||
|
||||
if (!cancel_rc && !abort_rc)
|
||||
rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun);
|
||||
|
||||
if (block_rc == FAST_IO_FAIL && rc != FAILED)
|
||||
rc = FAST_IO_FAIL;
|
||||
|
||||
LEAVE;
|
||||
return rc;
|
||||
}
|
||||
|
@ -2410,28 +2416,46 @@ static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd)
|
|||
* @cmd: scsi command struct
|
||||
*
|
||||
* Returns:
|
||||
* SUCCESS / FAILED
|
||||
* SUCCESS / FAST_IO_FAIL / FAILED
|
||||
**/
|
||||
static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct scsi_device *sdev = cmd->device;
|
||||
struct ibmvfc_host *vhost = shost_priv(sdev->host);
|
||||
int cancel_rc, reset_rc;
|
||||
int cancel_rc, block_rc, reset_rc = 0;
|
||||
int rc = FAILED;
|
||||
|
||||
ENTER;
|
||||
fc_block_scsi_eh(cmd);
|
||||
block_rc = fc_block_scsi_eh(cmd);
|
||||
ibmvfc_wait_while_resetting(vhost);
|
||||
cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET);
|
||||
reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN");
|
||||
if (block_rc != FAST_IO_FAIL) {
|
||||
cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET);
|
||||
reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN");
|
||||
} else
|
||||
cancel_rc = ibmvfc_cancel_all(sdev, 0);
|
||||
|
||||
if (!cancel_rc && !reset_rc)
|
||||
rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun);
|
||||
|
||||
if (block_rc == FAST_IO_FAIL && rc != FAILED)
|
||||
rc = FAST_IO_FAIL;
|
||||
|
||||
LEAVE;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* ibmvfc_dev_cancel_all_noreset - Device iterated cancel all function
|
||||
* @sdev: scsi device struct
|
||||
* @data: return code
|
||||
*
|
||||
**/
|
||||
static void ibmvfc_dev_cancel_all_noreset(struct scsi_device *sdev, void *data)
|
||||
{
|
||||
unsigned long *rc = data;
|
||||
*rc |= ibmvfc_cancel_all(sdev, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* ibmvfc_dev_cancel_all_reset - Device iterated cancel all function
|
||||
* @sdev: scsi device struct
|
||||
|
@ -2449,26 +2473,33 @@ static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data)
|
|||
* @cmd: scsi command struct
|
||||
*
|
||||
* Returns:
|
||||
* SUCCESS / FAILED
|
||||
* SUCCESS / FAST_IO_FAIL / FAILED
|
||||
**/
|
||||
static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct scsi_device *sdev = cmd->device;
|
||||
struct ibmvfc_host *vhost = shost_priv(sdev->host);
|
||||
struct scsi_target *starget = scsi_target(sdev);
|
||||
int reset_rc;
|
||||
int block_rc;
|
||||
int reset_rc = 0;
|
||||
int rc = FAILED;
|
||||
unsigned long cancel_rc = 0;
|
||||
|
||||
ENTER;
|
||||
fc_block_scsi_eh(cmd);
|
||||
block_rc = fc_block_scsi_eh(cmd);
|
||||
ibmvfc_wait_while_resetting(vhost);
|
||||
starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset);
|
||||
reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target");
|
||||
if (block_rc != FAST_IO_FAIL) {
|
||||
starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset);
|
||||
reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target");
|
||||
} else
|
||||
starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_noreset);
|
||||
|
||||
if (!cancel_rc && !reset_rc)
|
||||
rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target);
|
||||
|
||||
if (block_rc == FAST_IO_FAIL && rc != FAILED)
|
||||
rc = FAST_IO_FAIL;
|
||||
|
||||
LEAVE;
|
||||
return rc;
|
||||
}
|
||||
|
@ -2480,12 +2511,16 @@ static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd)
|
|||
**/
|
||||
static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd)
|
||||
{
|
||||
int rc;
|
||||
int rc, block_rc;
|
||||
struct ibmvfc_host *vhost = shost_priv(cmd->device->host);
|
||||
|
||||
fc_block_scsi_eh(cmd);
|
||||
block_rc = fc_block_scsi_eh(cmd);
|
||||
dev_err(vhost->dev, "Resetting connection due to error recovery\n");
|
||||
rc = ibmvfc_issue_fc_host_lip(vhost->host);
|
||||
|
||||
if (block_rc == FAST_IO_FAIL)
|
||||
return FAST_IO_FAIL;
|
||||
|
||||
return rc ? FAILED : SUCCESS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue