Skip to content

Commit 63caf36

Browse files
Christof SchmittJames Bottomley
Christof Schmitt
authored and
James Bottomley
committed
[SCSI] zfcp: Improve reliability of SCSI eh handlers in zfcp
When the SCSI midlayer is running error recovery, the low-level error recovery in zfcp could be running and preventing the SCSI midlayer to issue error recovery requests. To avoid unnecessary error recovery escalation, wait for the zfcp erp to finish and retry if necessary. While reworking the SCSI eh handlers, alsa cleanup the code and simplify the interface from zfcp_scsi to the fsf layer. Acked-by: Swen Schillig <[email protected]> Signed-off-by: Christof Schmitt <[email protected]> Signed-off-by: James Bottomley <[email protected]>
1 parent 92cab0d commit 63caf36

File tree

4 files changed

+78
-99
lines changed

4 files changed

+78
-99
lines changed

drivers/s390/scsi/zfcp_def.h

-3
Original file line numberDiff line numberDiff line change
@@ -586,9 +586,6 @@ struct zfcp_fsf_req_qtcb {
586586

587587
/********************** ZFCP SPECIFIC DEFINES ********************************/
588588

589-
#define ZFCP_REQ_AUTO_CLEANUP 0x00000002
590-
#define ZFCP_REQ_NO_QTCB 0x00000008
591-
592589
#define ZFCP_SET 0x00000100
593590
#define ZFCP_CLEAR 0x00000200
594591

drivers/s390/scsi/zfcp_ext.h

+4-7
Original file line numberDiff line numberDiff line change
@@ -125,16 +125,13 @@ extern int zfcp_status_read_refill(struct zfcp_adapter *adapter);
125125
extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *,
126126
struct zfcp_erp_action *);
127127
extern int zfcp_fsf_send_els(struct zfcp_send_els *);
128-
extern int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *,
129-
struct zfcp_unit *,
130-
struct scsi_cmnd *, int, int);
128+
extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *,
129+
struct scsi_cmnd *);
131130
extern void zfcp_fsf_req_complete(struct zfcp_fsf_req *);
132131
extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
133-
extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *,
134-
struct zfcp_unit *, u8, int);
132+
extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *, u8);
135133
extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long,
136-
struct zfcp_adapter *,
137-
struct zfcp_unit *, int);
134+
struct zfcp_unit *);
138135

139136
/* zfcp_qdio.c */
140137
extern int zfcp_qdio_allocate(struct zfcp_adapter *);

drivers/s390/scsi/zfcp_fsf.c

+14-25
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#include <linux/blktrace_api.h>
1313
#include "zfcp_ext.h"
1414

15+
#define ZFCP_REQ_AUTO_CLEANUP 0x00000002
16+
#define ZFCP_REQ_NO_QTCB 0x00000008
17+
1518
static void zfcp_fsf_request_timeout_handler(unsigned long data)
1619
{
1720
struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
@@ -913,27 +916,22 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
913916
/**
914917
* zfcp_fsf_abort_fcp_command - abort running SCSI command
915918
* @old_req_id: unsigned long
916-
* @adapter: pointer to struct zfcp_adapter
917919
* @unit: pointer to struct zfcp_unit
918-
* @req_flags: integer specifying the request flags
919920
* Returns: pointer to struct zfcp_fsf_req
920-
*
921-
* FIXME(design): should be watched by a timeout !!!
922921
*/
923922

924923
struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
925-
struct zfcp_adapter *adapter,
926-
struct zfcp_unit *unit,
927-
int req_flags)
924+
struct zfcp_unit *unit)
928925
{
929926
struct qdio_buffer_element *sbale;
930927
struct zfcp_fsf_req *req = NULL;
928+
struct zfcp_adapter *adapter = unit->port->adapter;
931929

932930
spin_lock_bh(&adapter->req_q_lock);
933931
if (zfcp_fsf_req_sbal_get(adapter))
934932
goto out;
935933
req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND,
936-
req_flags, adapter->pool.fsf_req_abort);
934+
0, adapter->pool.fsf_req_abort);
937935
if (IS_ERR(req)) {
938936
req = NULL;
939937
goto out;
@@ -2309,21 +2307,17 @@ static void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, u32 fcp_dl)
23092307

23102308
/**
23112309
* zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
2312-
* @adapter: adapter where scsi command is issued
23132310
* @unit: unit where command is sent to
23142311
* @scsi_cmnd: scsi command to be sent
2315-
* @timer: timer to be started when request is initiated
2316-
* @req_flags: flags for fsf_request
23172312
*/
2318-
int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
2319-
struct zfcp_unit *unit,
2320-
struct scsi_cmnd *scsi_cmnd,
2321-
int use_timer, int req_flags)
2313+
int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
2314+
struct scsi_cmnd *scsi_cmnd)
23222315
{
23232316
struct zfcp_fsf_req *req;
23242317
struct fcp_cmnd_iu *fcp_cmnd_iu;
23252318
unsigned int sbtype;
23262319
int real_bytes, retval = -EIO;
2320+
struct zfcp_adapter *adapter = unit->port->adapter;
23272321

23282322
if (unlikely(!(atomic_read(&unit->status) &
23292323
ZFCP_STATUS_COMMON_UNBLOCKED)))
@@ -2332,7 +2326,8 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
23322326
spin_lock(&adapter->req_q_lock);
23332327
if (!zfcp_fsf_sbal_available(adapter))
23342328
goto out;
2335-
req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags,
2329+
req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND,
2330+
ZFCP_REQ_AUTO_CLEANUP,
23362331
adapter->pool.fsf_req_scsi);
23372332
if (IS_ERR(req)) {
23382333
retval = PTR_ERR(req);
@@ -2414,9 +2409,6 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
24142409

24152410
zfcp_set_fcp_dl(fcp_cmnd_iu, real_bytes);
24162411

2417-
if (use_timer)
2418-
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
2419-
24202412
retval = zfcp_fsf_req_send(req);
24212413
if (unlikely(retval))
24222414
goto failed_scsi_cmnd;
@@ -2434,19 +2426,16 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
24342426

24352427
/**
24362428
* zfcp_fsf_send_fcp_ctm - send SCSI task management command
2437-
* @adapter: pointer to struct zfcp-adapter
24382429
* @unit: pointer to struct zfcp_unit
24392430
* @tm_flags: unsigned byte for task management flags
2440-
* @req_flags: int request flags
24412431
* Returns: on success pointer to struct fsf_req, NULL otherwise
24422432
*/
2443-
struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter,
2444-
struct zfcp_unit *unit,
2445-
u8 tm_flags, int req_flags)
2433+
struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
24462434
{
24472435
struct qdio_buffer_element *sbale;
24482436
struct zfcp_fsf_req *req = NULL;
24492437
struct fcp_cmnd_iu *fcp_cmnd_iu;
2438+
struct zfcp_adapter *adapter = unit->port->adapter;
24502439

24512440
if (unlikely(!(atomic_read(&unit->status) &
24522441
ZFCP_STATUS_COMMON_UNBLOCKED)))
@@ -2455,7 +2444,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter,
24552444
spin_lock_bh(&adapter->req_q_lock);
24562445
if (zfcp_fsf_req_sbal_get(adapter))
24572446
goto out;
2458-
req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags,
2447+
req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, 0,
24592448
adapter->pool.fsf_req_scsi);
24602449
if (IS_ERR(req)) {
24612450
req = NULL;

drivers/s390/scsi/zfcp_scsi.c

+60-64
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
8787
return 0;;
8888
}
8989

90-
ret = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, 0,
91-
ZFCP_REQ_AUTO_CLEANUP);
90+
ret = zfcp_fsf_send_fcp_command_task(unit, scpnt);
9291
if (unlikely(ret == -EBUSY))
9392
return SCSI_MLQUEUE_DEVICE_BUSY;
9493
else if (unlikely(ret < 0))
@@ -145,79 +144,91 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *sdp)
145144

146145
static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
147146
{
148-
struct Scsi_Host *scsi_host;
149-
struct zfcp_adapter *adapter;
150-
struct zfcp_unit *unit;
151-
struct zfcp_fsf_req *fsf_req;
147+
struct Scsi_Host *scsi_host = scpnt->device->host;
148+
struct zfcp_adapter *adapter =
149+
(struct zfcp_adapter *) scsi_host->hostdata[0];
150+
struct zfcp_unit *unit = scpnt->device->hostdata;
151+
struct zfcp_fsf_req *old_req, *abrt_req;
152152
unsigned long flags;
153153
unsigned long old_req_id = (unsigned long) scpnt->host_scribble;
154154
int retval = SUCCESS;
155-
156-
scsi_host = scpnt->device->host;
157-
adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
158-
unit = scpnt->device->hostdata;
155+
int retry = 3;
159156

160157
/* avoid race condition between late normal completion and abort */
161158
write_lock_irqsave(&adapter->abort_lock, flags);
162159

163-
/* Check whether corresponding fsf_req is still pending */
164160
spin_lock(&adapter->req_list_lock);
165-
fsf_req = zfcp_reqlist_find(adapter, old_req_id);
161+
old_req = zfcp_reqlist_find(adapter, old_req_id);
166162
spin_unlock(&adapter->req_list_lock);
167-
if (!fsf_req) {
163+
if (!old_req) {
168164
write_unlock_irqrestore(&adapter->abort_lock, flags);
169-
zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, 0);
170-
return retval;
165+
zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL,
166+
old_req_id);
167+
return SUCCESS;
171168
}
172-
fsf_req->data = NULL;
169+
old_req->data = NULL;
173170

174171
/* don't access old fsf_req after releasing the abort_lock */
175172
write_unlock_irqrestore(&adapter->abort_lock, flags);
176173

177-
fsf_req = zfcp_fsf_abort_fcp_command(old_req_id, adapter, unit, 0);
178-
if (!fsf_req) {
179-
zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
180-
old_req_id);
181-
retval = FAILED;
182-
return retval;
174+
while (retry--) {
175+
abrt_req = zfcp_fsf_abort_fcp_command(old_req_id, unit);
176+
if (abrt_req)
177+
break;
178+
179+
zfcp_erp_wait(adapter);
180+
if (!(atomic_read(&adapter->status) &
181+
ZFCP_STATUS_COMMON_RUNNING)) {
182+
zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
183+
old_req_id);
184+
return SUCCESS;
185+
}
183186
}
187+
if (!abrt_req)
188+
return FAILED;
184189

185-
__wait_event(fsf_req->completion_wq,
186-
fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
190+
wait_event(abrt_req->completion_wq,
191+
abrt_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
187192

188-
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
189-
zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, fsf_req, 0);
190-
} else if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
191-
zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, fsf_req, 0);
192-
} else {
193-
zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, fsf_req, 0);
193+
if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED)
194+
zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, abrt_req, 0);
195+
else if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED)
196+
zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, abrt_req, 0);
197+
else {
198+
zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, abrt_req, 0);
194199
retval = FAILED;
195200
}
196-
zfcp_fsf_req_free(fsf_req);
197-
201+
zfcp_fsf_req_free(abrt_req);
198202
return retval;
199203
}
200204

201-
static int zfcp_task_mgmt_function(struct zfcp_unit *unit, u8 tm_flags,
202-
struct scsi_cmnd *scpnt)
205+
static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
203206
{
207+
struct zfcp_unit *unit = scpnt->device->hostdata;
204208
struct zfcp_adapter *adapter = unit->port->adapter;
205209
struct zfcp_fsf_req *fsf_req;
206210
int retval = SUCCESS;
207-
208-
/* issue task management function */
209-
fsf_req = zfcp_fsf_send_fcp_ctm(adapter, unit, tm_flags, 0);
210-
if (!fsf_req) {
211-
zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit, scpnt);
212-
return FAILED;
211+
int retry = 3;
212+
213+
while (retry--) {
214+
fsf_req = zfcp_fsf_send_fcp_ctm(unit, tm_flags);
215+
if (fsf_req)
216+
break;
217+
218+
zfcp_erp_wait(adapter);
219+
if (!(atomic_read(&adapter->status) &
220+
ZFCP_STATUS_COMMON_RUNNING)) {
221+
zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit,
222+
scpnt);
223+
return SUCCESS;
224+
}
213225
}
226+
if (!fsf_req)
227+
return FAILED;
214228

215-
__wait_event(fsf_req->completion_wq,
216-
fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
229+
wait_event(fsf_req->completion_wq,
230+
fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
217231

218-
/*
219-
* check completion status of task management function
220-
*/
221232
if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
222233
zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt);
223234
retval = FAILED;
@@ -228,39 +239,24 @@ static int zfcp_task_mgmt_function(struct zfcp_unit *unit, u8 tm_flags,
228239
zfcp_scsi_dbf_event_devreset("okay", tm_flags, unit, scpnt);
229240

230241
zfcp_fsf_req_free(fsf_req);
231-
232242
return retval;
233243
}
234244

235245
static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
236246
{
237-
struct zfcp_unit *unit = scpnt->device->hostdata;
238-
239-
if (!unit) {
240-
WARN_ON(1);
241-
return SUCCESS;
242-
}
243-
return zfcp_task_mgmt_function(unit, FCP_LOGICAL_UNIT_RESET, scpnt);
247+
return zfcp_task_mgmt_function(scpnt, FCP_LOGICAL_UNIT_RESET);
244248
}
245249

246250
static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
247251
{
248-
struct zfcp_unit *unit = scpnt->device->hostdata;
249-
250-
if (!unit) {
251-
WARN_ON(1);
252-
return SUCCESS;
253-
}
254-
return zfcp_task_mgmt_function(unit, FCP_TARGET_RESET, scpnt);
252+
return zfcp_task_mgmt_function(scpnt, FCP_TARGET_RESET);
255253
}
256254

257255
static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
258256
{
259-
struct zfcp_unit *unit;
260-
struct zfcp_adapter *adapter;
257+
struct zfcp_unit *unit = scpnt->device->hostdata;
258+
struct zfcp_adapter *adapter = unit->port->adapter;
261259

262-
unit = scpnt->device->hostdata;
263-
adapter = unit->port->adapter;
264260
zfcp_erp_adapter_reopen(adapter, 0, 141, scpnt);
265261
zfcp_erp_wait(adapter);
266262

0 commit comments

Comments
 (0)