Skip to content

Commit 2f2eb58

Browse files
Christof SchmittJames Bottomley
authored andcommitted
[SCSI] Allow FC LLD to fast-fail scsi eh by introducing new eh return
If the scsi eh is running and then a FC LLD calls fc_remote_port_delete, the SCSI commands sent from the eh will fail. To prevent this, a FC LLD can call fc_block_scsi_eh from the eh callback, blocking the eh thread until the dev_loss_tmo fires or the remote port is available again. If (e.g. for a multipathing setup) the dev_loss_tmo is set to a very large value, thus preventing the scsi device removal , the scsi eh can block for a long time. For multipathing, the fast_io_fail_tmo is then set to a low value to detect path problems sooner. This patch introduces a new return code FAST_IO_FAIL. The function fc_block_scsi_eh now returns FAST_IO_FAIL when the fast_io_fail_tmo fires. This indicates that the LLD terminated all pending I/O requests and there are no more pending SCSI commands for the scsi eh to wait for. This return code can be passed back to the scsi eh to stop the escalation and finish the recovery process for this device. Signed-off-by: Christof Schmitt <[email protected]> Signed-off-by: James Bottomley <[email protected]>
1 parent 7794a5a commit 2f2eb58

File tree

4 files changed

+27
-11
lines changed

4 files changed

+27
-11
lines changed

drivers/scsi/scsi_error.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -957,9 +957,10 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
957957
"0x%p\n", current->comm,
958958
scmd));
959959
rtn = scsi_try_to_abort_cmd(scmd);
960-
if (rtn == SUCCESS) {
960+
if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
961961
scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD;
962962
if (!scsi_device_online(scmd->device) ||
963+
rtn == FAST_IO_FAIL ||
963964
!scsi_eh_tur(scmd)) {
964965
scsi_eh_finish_cmd(scmd, done_q);
965966
}
@@ -1086,8 +1087,9 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
10861087
" 0x%p\n", current->comm,
10871088
sdev));
10881089
rtn = scsi_try_bus_device_reset(bdr_scmd);
1089-
if (rtn == SUCCESS) {
1090+
if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
10901091
if (!scsi_device_online(sdev) ||
1092+
rtn == FAST_IO_FAIL ||
10911093
!scsi_eh_tur(bdr_scmd)) {
10921094
list_for_each_entry_safe(scmd, next,
10931095
work_q, eh_entry) {
@@ -1150,10 +1152,11 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
11501152
"to target %d\n",
11511153
current->comm, id));
11521154
rtn = scsi_try_target_reset(tgtr_scmd);
1153-
if (rtn == SUCCESS) {
1155+
if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
11541156
list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
11551157
if (id == scmd_id(scmd))
11561158
if (!scsi_device_online(scmd->device) ||
1159+
rtn == FAST_IO_FAIL ||
11571160
!scsi_eh_tur(tgtr_scmd))
11581161
scsi_eh_finish_cmd(scmd,
11591162
done_q);
@@ -1209,10 +1212,11 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
12091212
" %d\n", current->comm,
12101213
channel));
12111214
rtn = scsi_try_bus_reset(chan_scmd);
1212-
if (rtn == SUCCESS) {
1215+
if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
12131216
list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
12141217
if (channel == scmd_channel(scmd))
12151218
if (!scsi_device_online(scmd->device) ||
1219+
rtn == FAST_IO_FAIL ||
12161220
!scsi_eh_tur(scmd))
12171221
scsi_eh_finish_cmd(scmd,
12181222
done_q);
@@ -1246,9 +1250,10 @@ static int scsi_eh_host_reset(struct list_head *work_q,
12461250
, current->comm));
12471251

12481252
rtn = scsi_try_host_reset(scmd);
1249-
if (rtn == SUCCESS) {
1253+
if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
12501254
list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
12511255
if (!scsi_device_online(scmd->device) ||
1256+
rtn == FAST_IO_FAIL ||
12521257
(!scsi_eh_try_stu(scmd) && !scsi_eh_tur(scmd)) ||
12531258
!scsi_eh_tur(scmd))
12541259
scsi_eh_finish_cmd(scmd, done_q);

drivers/scsi/scsi_transport_fc.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3197,23 +3197,33 @@ fc_scsi_scan_rport(struct work_struct *work)
31973197
*
31983198
* This routine can be called from a FC LLD scsi_eh callback. It
31993199
* blocks the scsi_eh thread until the fc_rport leaves the
3200-
* FC_PORTSTATE_BLOCKED. This is necessary to avoid the scsi_eh
3201-
* failing recovery actions for blocked rports which would lead to
3202-
* offlined SCSI devices.
3200+
* FC_PORTSTATE_BLOCKED, or the fast_io_fail_tmo fires. This is
3201+
* necessary to avoid the scsi_eh failing recovery actions for blocked
3202+
* rports which would lead to offlined SCSI devices.
3203+
*
3204+
* Returns: 0 if the fc_rport left the state FC_PORTSTATE_BLOCKED.
3205+
* FAST_IO_FAIL if the fast_io_fail_tmo fired, this should be
3206+
* passed back to scsi_eh.
32033207
*/
3204-
void fc_block_scsi_eh(struct scsi_cmnd *cmnd)
3208+
int fc_block_scsi_eh(struct scsi_cmnd *cmnd)
32053209
{
32063210
struct Scsi_Host *shost = cmnd->device->host;
32073211
struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
32083212
unsigned long flags;
32093213

32103214
spin_lock_irqsave(shost->host_lock, flags);
3211-
while (rport->port_state == FC_PORTSTATE_BLOCKED) {
3215+
while (rport->port_state == FC_PORTSTATE_BLOCKED &&
3216+
!(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT)) {
32123217
spin_unlock_irqrestore(shost->host_lock, flags);
32133218
msleep(1000);
32143219
spin_lock_irqsave(shost->host_lock, flags);
32153220
}
32163221
spin_unlock_irqrestore(shost->host_lock, flags);
3222+
3223+
if (rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT)
3224+
return FAST_IO_FAIL;
3225+
3226+
return 0;
32173227
}
32183228
EXPORT_SYMBOL(fc_block_scsi_eh);
32193229

include/scsi/scsi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ static inline int scsi_is_wlun(unsigned int lun)
423423
#define ADD_TO_MLQUEUE 0x2006
424424
#define TIMEOUT_ERROR 0x2007
425425
#define SCSI_RETURN_NOT_HANDLED 0x2008
426+
#define FAST_IO_FAIL 0x2009
426427

427428
/*
428429
* Midlevel queue return values.

include/scsi/scsi_transport_fc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,6 @@ void fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
807807
struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel,
808808
struct fc_vport_identifiers *);
809809
int fc_vport_terminate(struct fc_vport *vport);
810-
void fc_block_scsi_eh(struct scsi_cmnd *cmnd);
810+
int fc_block_scsi_eh(struct scsi_cmnd *cmnd);
811811

812812
#endif /* SCSI_TRANSPORT_FC_H */

0 commit comments

Comments
 (0)