diff options
author | Martin K. Petersen <martin.petersen@oracle.com> | 2023-12-06 03:33:05 +0100 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2023-12-06 03:33:05 +0100 |
commit | f200dad9f34d21a168d5e1286db2f96bfef5644d (patch) | |
tree | e37193cd4750cd2c5d3e4556bbd8df75b65b7b5f /drivers/scsi | |
parent | scsi: aic7xxx: Return negative error codes in aic7770_probe() (diff) | |
parent | scsi: libfc: Map FC_TIMED_OUT to DID_TIME_OUT (diff) | |
download | linux-f200dad9f34d21a168d5e1286db2f96bfef5644d.tar.xz linux-f200dad9f34d21a168d5e1286db2f96bfef5644d.zip |
Merge patch series "libfc: fixup command abort handling"
Hannes Reinecke <hare@kernel.org> says:
Hi all,
when testing command timeout with the help of XDP I found that
scsi_try_to_abort_cmd() would always return 'SUCCESS' for FCoE, even
if no commands could be sent over the wire. Which is not only
surprising, but also can lead to data corruption as commands were
never aborted. Root cause was that aborts had been sent twice, once
from FC error recovery and once from SCSI EH, with the former inducing
the latter to assume that the command was already aborted.
As usual, comments and reviews are welcome.
Link: https://lore.kernel.org/r/20231129165832.224100-1-hare@kernel.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/libfc/fc_fcp.c | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 945adca5e72f..80be3a936d92 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -265,6 +265,11 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp) if (!fsp->seq_ptr) return -EINVAL; + if (fsp->state & FC_SRB_ABORT_PENDING) { + FC_FCP_DBG(fsp, "abort already pending\n"); + return -EBUSY; + } + this_cpu_inc(fsp->lp->stats->FcpPktAborts); fsp->state |= FC_SRB_ABORT_PENDING; @@ -1671,7 +1676,7 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) fc_fcp_rec(fsp); else - fc_fcp_recovery(fsp, FC_ERROR); + fc_fcp_recovery(fsp, FC_TIMED_OUT); break; } fc_fcp_unlock_pkt(fsp); @@ -1690,11 +1695,12 @@ static void fc_fcp_recovery(struct fc_fcp_pkt *fsp, u8 code) fsp->status_code = code; fsp->cdb_status = 0; fsp->io_status = 0; - /* - * if this fails then we let the scsi command timer fire and - * scsi-ml escalate. - */ - fc_fcp_send_abort(fsp); + if (!fsp->cmd) + /* + * Only abort non-scsi commands; otherwise let the + * scsi command timer fire and scsi-ml escalate. + */ + fc_fcp_send_abort(fsp); } /** @@ -2056,9 +2062,9 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) sc_cmd->result = (DID_PARITY << 16); break; case FC_TIMED_OUT: - FC_FCP_DBG(fsp, "Returning DID_BUS_BUSY to scsi-ml " + FC_FCP_DBG(fsp, "Returning DID_TIME_OUT to scsi-ml " "due to FC_TIMED_OUT\n"); - sc_cmd->result = (DID_BUS_BUSY << 16) | fsp->io_status; + sc_cmd->result = (DID_TIME_OUT << 16); break; default: FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " |