Re: [PATCH] Check return value of fc_block_scsi_eh()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Oct 13, 2010 at 01:42:28PM +0200, Hannes Reinecke wrote:
> 
> fc_block_scsi_eh() might return with status FAST_IO_FAIL
> indicating I/O has been terminated due to fast_io_fail timeout.
> In this case the rport is still blocked, so any error recovery
> will be failing on this port.
> Hence each driver needs to check if the return value from
> fc_block_scsi_eh() is something other than SUCCESS, in which
> case it should just return with that status.
> And we need to update the error handler to deal with a
> status of FAST_IO_FAIL, too.
> And fc_block_scsi_eh() should return SUCCESS on success,
> not 0. Otherwise the calling routine will become confused
> when reusing that value.
> 
> Signed-off-by: Hannes Reinecke <hare@xxxxxxx>
> Cc: James Smart <james.smart@xxxxxxxxxx>
> Cc: Andrew Vasquez <andrew.vasquez@xxxxxxxxxx>
> Cc: Christof Schmitt <christof.schmitt@xxxxxxxxxx>
> Cc: Abhijeet Joglekar <abjoglek@xxxxxxxxx>
> 
> diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
> index ae10883..d5f8b90 100644
> --- a/drivers/s390/scsi/zfcp_scsi.c
> +++ b/drivers/s390/scsi/zfcp_scsi.c
> @@ -199,7 +199,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
> 
>  		zfcp_erp_wait(adapter);
>  		ret = fc_block_scsi_eh(scpnt);
> -		if (ret)
> +		if (ret != SUCCESS)
>  			return ret;
>  		if (!(atomic_read(&adapter->status) &
>  		      ZFCP_STATUS_COMMON_RUNNING)) {
> @@ -241,7 +241,7 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
> 
>  		zfcp_erp_wait(adapter);
>  		ret = fc_block_scsi_eh(scpnt);
> -		if (ret)
> +		if (ret != SUCCESS)
>  			return ret;
> 
>  		if (!(atomic_read(&adapter->status) &

When fc_block_scsi_eh returns SUCCESS, the two functions above could
reuse the retval variable and get rid of ret.

> @@ -283,11 +283,7 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
> 
>  	zfcp_erp_adapter_reopen(adapter, 0, "schrh_1", scpnt);
>  	zfcp_erp_wait(adapter);
> -	ret = fc_block_scsi_eh(scpnt);
> -	if (ret)
> -		return ret;
> -
> -	return SUCCESS;
> +	return fc_block_scsi_eh(scpnt);
>  }
> 
>  int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)

This results in:
drivers/s390/scsi/zfcp_scsi.c: In function âzfcp_scsi_eh_host_reset_handlerâ:
drivers/s390/scsi/zfcp_scsi.c:282: warning: unused variable âretâ

> diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
> index 198cbab..8d797a6 100644
> --- a/drivers/scsi/fnic/fnic_scsi.c
> +++ b/drivers/scsi/fnic/fnic_scsi.c
> @@ -1240,7 +1240,9 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
>  	DECLARE_COMPLETION_ONSTACK(tm_done);
> 
>  	/* Wait for rport to unblock */
> -	fc_block_scsi_eh(sc);
> +	ret = fc_block_scsi_eh(sc);
> +	if (ret != SUCCESS)
> +		return ret;
> 
>  	/* Get local-port, check ready and link up */
>  	lp = shost_priv(sc->device->host);
> @@ -1512,13 +1514,15 @@ int fnic_device_reset(struct scsi_cmnd *sc)
>  	struct fnic_io_req *io_req;
>  	struct fc_rport *rport;
>  	int status;
> -	int ret = FAILED;
> +	int ret;
>  	spinlock_t *io_lock;
>  	unsigned long flags;
>  	DECLARE_COMPLETION_ONSTACK(tm_done);
> 
>  	/* Wait for rport to unblock */
> -	fc_block_scsi_eh(sc);
> +	ret = fc_block_scsi_eh(sc);
> +	if (ret != SUCCESS)
> +		return ret;
> 
>  	/* Get local-port, check ready and link up */
>  	lp = shost_priv(sc->device->host);
> diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
> index 00d08b2..a270a00 100644
> --- a/drivers/scsi/ibmvscsi/ibmvfc.c
> +++ b/drivers/scsi/ibmvscsi/ibmvfc.c
> @@ -2360,17 +2360,21 @@ 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 rc = FAILED;
> +	int rc;
> 
>  	ENTER;
> -	fc_block_scsi_eh(cmd);
> +	rc = fc_block_scsi_eh(cmd);
> +	if (rc != SUCCESS)
> +		goto leave;
>  	ibmvfc_wait_while_resetting(vhost);
>  	cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
>  	abort_rc = ibmvfc_abort_task_set(sdev);
> 
>  	if (!cancel_rc && !abort_rc)
>  		rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun);
> -
> +	else
> +		rc = FAILED;
> +leave:
>  	LEAVE;
>  	return rc;
>  }
> @@ -2387,17 +2391,21 @@ 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 rc = FAILED;
> +	int rc;
> 
>  	ENTER;
> -	fc_block_scsi_eh(cmd);
> +	rc = fc_block_scsi_eh(cmd);
> +	if (rc != SUCCESS)
> +		goto leave;
>  	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 (!cancel_rc && !reset_rc)
>  		rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun);
> -
> +	else
> +		rc = FAILED;
> +leave:
>  	LEAVE;
>  	return rc;
>  }
> @@ -2427,18 +2435,22 @@ static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd)
>  	struct ibmvfc_host *vhost = shost_priv(sdev->host);
>  	struct scsi_target *starget = scsi_target(sdev);
>  	int reset_rc;
> -	int rc = FAILED;
> +	int rc;
>  	unsigned long cancel_rc = 0;
> 
>  	ENTER;
> -	fc_block_scsi_eh(cmd);
> +	rc = fc_block_scsi_eh(cmd);
> +	if (rc != SUCCESS)
> +		goto leave;
>  	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 (!cancel_rc && !reset_rc)
>  		rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target);
> -
> +	else
> +		rc = FAILED;
> +leave:
>  	LEAVE;
>  	return rc;
>  }
> @@ -2453,7 +2465,10 @@ static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd)
>  	int rc;
>  	struct ibmvfc_host *vhost = shost_priv(cmd->device->host);
> 
> -	fc_block_scsi_eh(cmd);
> +	rc = fc_block_scsi_eh(cmd);
> +	if (rc != SUCCESS)
> +		return rc;
> +
>  	dev_err(vhost->dev, "Resetting connection due to error recovery\n");
>  	rc = ibmvfc_issue_fc_host_lip(vhost->host);
>  	return rc ? FAILED : SUCCESS;
> diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
> index 3a65895..c516ba8 100644
> --- a/drivers/scsi/lpfc/lpfc_scsi.c
> +++ b/drivers/scsi/lpfc/lpfc_scsi.c
> @@ -3080,7 +3080,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
>  	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
> 
>  	ret = fc_block_scsi_eh(cmnd);
> -	if (ret)
> +	if (ret != SUCCESS)
>  		return ret;
>  	lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
>  	if (!lpfc_cmd) {
> @@ -3407,7 +3407,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
>  	}
>  	pnode = rdata->pnode;
>  	status = fc_block_scsi_eh(cmnd);
> -	if (status)
> +	if (status != SUCCESS)
>  		return status;
> 
>  	status = lpfc_chk_tgt_mapped(vport, cmnd);
> @@ -3474,7 +3474,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
>  	}
>  	pnode = rdata->pnode;
>  	status = fc_block_scsi_eh(cmnd);
> -	if (status)
> +	if (status != SUCCESS)
>  		return status;
> 
>  	status = lpfc_chk_tgt_mapped(vport, cmnd);
> @@ -3542,7 +3542,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
>  		sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID);
> 
>  	ret = fc_block_scsi_eh(cmnd);
> -	if (ret)
> +	if (ret != SUCCESS)
>  		return ret;
> 
>  	/*
> diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> index bdd53f0..75e7719 100644
> --- a/drivers/scsi/qla2xxx/qla_os.c
> +++ b/drivers/scsi/qla2xxx/qla_os.c
> @@ -834,12 +834,12 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
>  	srb_t *spt;
>  	int got_ref = 0;
> 
> -	fc_block_scsi_eh(cmd);
> -
>  	if (!CMD_SP(cmd))
>  		return SUCCESS;
> 
> -	ret = SUCCESS;
> +	ret = fc_block_scsi_eh(cmd);
> +	if (ret != SUCCESS)
> +		return ret;
> 
>  	id = cmd->device->id;
>  	lun = cmd->device->lun;
> @@ -966,11 +966,13 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
>  	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
>  	int err;
> 
> -	fc_block_scsi_eh(cmd);
> -
>  	if (!fcport)
>  		return FAILED;
> 
> +	err = fc_block_scsi_eh(cmd);
> +	if (err != SUCCESS)
> +		return err;
> +
>  	qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET ISSUED.\n",
>  	    vha->host_no, cmd->device->id, cmd->device->lun, name);
> 
> @@ -1045,8 +1047,6 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
>  	unsigned int id, lun;
>  	unsigned long serial;
> 
> -	fc_block_scsi_eh(cmd);
> -
>  	id = cmd->device->id;
>  	lun = cmd->device->lun;
>  	serial = cmd->serial_number;
> @@ -1054,6 +1054,11 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
>  	if (!fcport)
>  		return ret;
> 
> +	ret = fc_block_scsi_eh(cmd);
> +	if (ret != SUCCESS)
> +		return ret;
> +	ret = FAILED;
> +
>  	qla_printk(KERN_INFO, vha->hw,
>  	    "scsi(%ld:%d:%d): BUS RESET ISSUED.\n", vha->host_no, id, lun);
> 
> @@ -1107,8 +1112,6 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
>  	unsigned long serial;
>  	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
> 
> -	fc_block_scsi_eh(cmd);
> -
>  	id = cmd->device->id;
>  	lun = cmd->device->lun;
>  	serial = cmd->serial_number;
> @@ -1116,6 +1119,11 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
>  	if (!fcport)
>  		return ret;
> 
> +	ret = fc_block_scsi_eh(cmd);
> +	if (ret != SUCCESS)
> +		return ret;
> +	ret = FAILED;
> +
>  	qla_printk(KERN_INFO, ha,
>  	    "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", vha->host_no, id, lun);
> 
> diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
> index 1de30eb..4279e7c 100644
> --- a/drivers/scsi/scsi_error.c
> +++ b/drivers/scsi/scsi_error.c
> @@ -655,11 +655,21 @@ static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
> 
>  static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
>  {
> -	if (__scsi_try_to_abort_cmd(scmd) != SUCCESS)
> -		if (scsi_try_bus_device_reset(scmd) != SUCCESS)
> -			if (scsi_try_target_reset(scmd) != SUCCESS)
> -				if (scsi_try_bus_reset(scmd) != SUCCESS)
> -					scsi_try_host_reset(scmd);
> +	int ret;
> +
> +	ret = __scsi_try_to_abort_cmd(scmd);
> +	if ((ret == SUCCESS) || (ret == FAST_IO_FAIL))
> +		return;
> +	ret = scsi_try_bus_device_reset(scmd);
> +	if ((ret == SUCCESS) || (ret == FAST_IO_FAIL))
> +		return;
> +	ret = scsi_try_target_reset(scmd);
> +	if ((ret == SUCCESS) || (ret == FAST_IO_FAIL))
> +		return;
> +	ret = scsi_try_bus_reset(scmd);
> +	if ((ret == SUCCESS) || (ret == FAST_IO_FAIL))
> +		return;
> +	scsi_try_host_reset(scmd);
>  }
> 
>  /**
> @@ -958,6 +968,7 @@ retry_tur:
>  		if (retry_cnt--)
>  			goto retry_tur;
>  		/*FALLTHRU*/
> +	case FAST_IO_FAIL:
>  	case SUCCESS:
>  		return 0;
>  	default:
> @@ -1026,7 +1037,7 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
>  		for (i = 0; rtn == NEEDS_RETRY && i < 2; i++)
>  			rtn = scsi_send_eh_cmnd(scmd, stu_command, 6, scmd->device->request_queue->rq_timeout, 0);
> 
> -		if (rtn == SUCCESS)
> +		if (rtn == SUCCESS || rtn == FAST_IO_FAIL)
>  			return 0;
>  	}
> 
> @@ -1928,17 +1939,17 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
>  	switch (flag) {
>  	case SCSI_TRY_RESET_DEVICE:
>  		rtn = scsi_try_bus_device_reset(scmd);
> -		if (rtn == SUCCESS)
> +		if (rtn == SUCCESS || rtn == FAST_IO_FAIL)
>  			break;
>  		/* FALLTHROUGH */
>  	case SCSI_TRY_RESET_TARGET:
>  		rtn = scsi_try_target_reset(scmd);
> -		if (rtn == SUCCESS)
> +		if (rtn == SUCCESS || rtn == FAST_IO_FAIL)
>  			break;
>  		/* FALLTHROUGH */
>  	case SCSI_TRY_RESET_BUS:
>  		rtn = scsi_try_bus_reset(scmd);
> -		if (rtn == SUCCESS)
> +		if (rtn == SUCCESS || rtn == FAST_IO_FAIL)
>  			break;
>  		/* FALLTHROUGH */
>  	case SCSI_TRY_RESET_HOST:
> @@ -1966,7 +1977,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
> 
>  	scsi_next_command(scmd);
>  	scsi_autopm_put_host(shost);
> -	return rtn;
> +	return (rtn == FAST_IO_FAIL) ? SUCCESS : rtn;
>  }
>  EXPORT_SYMBOL(scsi_reset_provider);
> 
> diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
> index 998c01b..fae5bcd 100644
> --- a/drivers/scsi/scsi_transport_fc.c
> +++ b/drivers/scsi/scsi_transport_fc.c
> @@ -3257,7 +3257,7 @@ fc_scsi_scan_rport(struct work_struct *work)
>   * necessary to avoid the scsi_eh failing recovery actions for blocked
>   * rports which would lead to offlined SCSI devices.
>   *
> - * Returns: 0 if the fc_rport left the state FC_PORTSTATE_BLOCKED.
> + * Returns: SUCCESS if the fc_rport left the state FC_PORTSTATE_BLOCKED.
>   *	    FAST_IO_FAIL if the fast_io_fail_tmo fired, this should be
>   *	    passed back to scsi_eh.
>   */
> @@ -3279,7 +3279,7 @@ int fc_block_scsi_eh(struct scsi_cmnd *cmnd)
>  	if (rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT)
>  		return FAST_IO_FAIL;
> 
> -	return 0;
> +	return SUCCESS;
>  }
>  EXPORT_SYMBOL(fc_block_scsi_eh);
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux