diff options
author | Hannes Reinecke <hare@suse.de> | 2016-10-13 15:10:50 +0200 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2016-11-08 17:29:52 -0500 |
commit | 9ca1e182b9d1ef3f97718c4072a18a23dc47d4f9 (patch) | |
tree | 8931ec7605a437d59eb6e7edaff18d4cf031b01b /drivers/scsi/libfc/fc_fcp.c | |
parent | b73aa56ee91cd88a4977033cfd2a18d6b25dddde (diff) | |
download | linux-9ca1e182b9d1ef3f97718c4072a18a23dc47d4f9.tar.gz linux-9ca1e182b9d1ef3f97718c4072a18a23dc47d4f9.tar.bz2 linux-9ca1e182b9d1ef3f97718c4072a18a23dc47d4f9.zip |
scsi: libfc: quarantine timed out xids
When a sequence times out we have no idea what happened to the
frame. And we do not know if we will ever receive the frame.
Hence we cannot re-use the xid as we would risk data corruption
if the xid had been re-used and the timed out frame would be
received after that.
So we need to quarantine the xid until the lport is reset.
Yes, I know this will (eventually) deplete the xid pool.
But for now it's the safest method.
Signed-off-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/libfc/fc_fcp.c')
-rw-r--r-- | drivers/scsi/libfc/fc_fcp.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index f7700cccf793..780d9f09a267 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1529,13 +1529,14 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) fsp->rport->port_id, rjt->er_reason, rjt->er_explan); /* - * If no data transfer, the command frame got dropped - * so we just retry. If data was transferred, we - * lost the response but the target has no record, - * so we abort and retry. + * If response got lost or is stuck in the + * queue somewhere we have no idea if and when + * the response will be received. So quarantine + * the xid and retry the command. */ - if (rjt->er_explan == ELS_EXPL_OXID_RXID && - fsp->xfer_len == 0) { + if (rjt->er_explan == ELS_EXPL_OXID_RXID) { + struct fc_exch *ep = fc_seq_exch(fsp->seq_ptr); + ep->state |= FC_EX_QUARANTINE; fsp->state |= FC_SRB_ABORTED; fc_fcp_retry_cmd(fsp, FC_TRANS_RESET); break; |