1 From: Brian King <brking@linux.vnet.ibm.com>
2 Date: Thu, 25 Apr 2013 08:24:41 +0200
3 Subject: ibmvfc: Support FAST_IO_FAIL in EH handlers
5 Patch-Mainline: posted to linux-scsi
7 Adds support for receiving FAST_IO_FAIL from fc_block_scsi_eh
8 when in error recovery. This fixes cases of devices being
9 taken offline when they are no longer accessible on the fabric,
10 preventing them from coming back online when the fabric recovers.
12 Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
13 Acked-by: Hannes Reinecke <hare@suse.de>
15 drivers/scsi/ibmvscsi/ibmvfc.c | 87 ++++++++++++++++++++++++++++--------------
16 1 file changed, 58 insertions(+), 29 deletions(-)
18 diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
19 index 7bcb183..6e4977f 100644
20 --- a/drivers/scsi/ibmvscsi/ibmvfc.c
21 +++ b/drivers/scsi/ibmvscsi/ibmvfc.c
22 @@ -2383,26 +2383,30 @@ out:
23 * @cmd: scsi command to abort
27 + * SUCCESS / FAST_IO_FAIL / FAILED
29 static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd)
31 struct scsi_device *sdev = cmd->device;
32 struct ibmvfc_host *vhost = shost_priv(sdev->host);
33 - int cancel_rc, abort_rc;
35 + int cancel_rc, block_rc, abort_rc = 0;
39 - rc = fc_block_scsi_eh(cmd);
42 + block_rc = fc_block_scsi_eh(cmd);
43 ibmvfc_wait_while_resetting(vhost);
44 - cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
45 - abort_rc = ibmvfc_abort_task_set(sdev);
46 + if (block_rc != FAST_IO_FAIL) {
47 + cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
48 + abort_rc = ibmvfc_abort_task_set(sdev);
50 + cancel_rc = ibmvfc_cancel_all(sdev, 0);
52 if (!cancel_rc && !abort_rc)
53 rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun);
56 + if (block_rc == FAST_IO_FAIL && rc != FAILED)
62 @@ -2412,31 +2416,47 @@ out:
63 * @cmd: scsi command struct
67 + * SUCCESS / FAST_IO_FAIL / FAILED
69 static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd)
71 struct scsi_device *sdev = cmd->device;
72 struct ibmvfc_host *vhost = shost_priv(sdev->host);
73 - int cancel_rc, reset_rc;
75 + int cancel_rc, block_rc, reset_rc = 0;
79 - rc = fc_block_scsi_eh(cmd);
82 + block_rc = fc_block_scsi_eh(cmd);
83 ibmvfc_wait_while_resetting(vhost);
84 - cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET);
85 - reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN");
86 + if (block_rc != FAST_IO_FAIL) {
87 + cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET);
88 + reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN");
90 + cancel_rc = ibmvfc_cancel_all(sdev, 0);
92 if (!cancel_rc && !reset_rc)
93 rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun);
96 + if (block_rc == FAST_IO_FAIL && rc != FAILED)
104 + * ibmvfc_dev_cancel_all_noreset - Device iterated cancel all function
105 + * @sdev: scsi device struct
106 + * @data: return code
109 +static void ibmvfc_dev_cancel_all_noreset(struct scsi_device *sdev, void *data)
111 + unsigned long *rc = data;
112 + *rc |= ibmvfc_cancel_all(sdev, 0);
116 * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function
117 * @sdev: scsi device struct
119 @@ -2453,28 +2473,33 @@ static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data)
120 * @cmd: scsi command struct
124 + * SUCCESS / FAST_IO_FAIL / FAILED
126 static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd)
128 struct scsi_device *sdev = cmd->device;
129 struct ibmvfc_host *vhost = shost_priv(sdev->host);
130 struct scsi_target *starget = scsi_target(sdev);
136 unsigned long cancel_rc = 0;
139 - rc = fc_block_scsi_eh(cmd);
142 + block_rc = fc_block_scsi_eh(cmd);
143 ibmvfc_wait_while_resetting(vhost);
144 - starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset);
145 - reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target");
146 + if (block_rc != FAST_IO_FAIL) {
147 + starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset);
148 + reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target");
150 + starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_noreset);
152 if (!cancel_rc && !reset_rc)
153 rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target);
156 + if (block_rc == FAST_IO_FAIL && rc != FAILED)
162 @@ -2486,12 +2511,16 @@ out:
164 static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd)
168 struct ibmvfc_host *vhost = shost_priv(cmd->device->host);
170 - fc_block_scsi_eh(cmd);
171 + block_rc = fc_block_scsi_eh(cmd);
172 dev_err(vhost->dev, "Resetting connection due to error recovery\n");
173 rc = ibmvfc_issue_fc_host_lip(vhost->host);
175 + if (block_rc == FAST_IO_FAIL)
176 + return FAST_IO_FAIL;
178 return rc ? FAILED : SUCCESS;