|
|
3c6e85 |
From b07af7d76a087066c597aec11bef189e0da88541 Mon Sep 17 00:00:00 2001
|
|
|
3c6e85 |
From: Himanshu Madhani <hmadhani@redhat.com>
|
|
|
3c6e85 |
Date: Thu, 21 Nov 2019 16:36:43 -0500
|
|
|
3c6e85 |
Subject: [PATCH 133/155] [scsi] scsi: qla2xxx: Fix a race condition between
|
|
|
3c6e85 |
aborting and completing a SCSI command
|
|
|
3c6e85 |
|
|
|
3c6e85 |
Message-id: <20191121163701.43688-9-hmadhani@redhat.com>
|
|
|
3c6e85 |
Patchwork-id: 287863
|
|
|
3c6e85 |
O-Subject: [RHLE 7.8 e-stor PATCH v3 08/26] scsi: qla2xxx: Fix a race condition between aborting and completing a SCSI command
|
|
|
3c6e85 |
Bugzilla: 1731581
|
|
|
3c6e85 |
RH-Acked-by: Jarod Wilson <jarod@redhat.com>
|
|
|
3c6e85 |
RH-Acked-by: Ewan Milne <emilne@redhat.com>
|
|
|
3c6e85 |
RH-Acked-by: Tony Camuso <tcamuso@redhat.com>
|
|
|
3c6e85 |
|
|
|
3c6e85 |
From: Bart Van Assche <bvanassche@acm.org>
|
|
|
3c6e85 |
|
|
|
3c6e85 |
Bugzilla 1731581
|
|
|
3c6e85 |
|
|
|
3c6e85 |
Instead of allocating a struct srb dynamically from inside .queuecommand(),
|
|
|
3c6e85 |
set qla2xxx_driver_template.cmd_size such that struct scsi_cmnd and struct
|
|
|
3c6e85 |
srb are contiguous. Do not call QLA_QPAIR_MARK_BUSY() /
|
|
|
3c6e85 |
QLA_QPAIR_MARK_NOT_BUSY() for SRBs associated with SCSI commands. That is
|
|
|
3c6e85 |
safe because scsi_remove_host() is called before queue pairs are deleted
|
|
|
3c6e85 |
and scsi_remove_host() waits for all outstanding SCSI commands to finish.
|
|
|
3c6e85 |
|
|
|
3c6e85 |
Cc: Himanshu Madhani <hmadhani@marvell.com>
|
|
|
3c6e85 |
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
|
|
|
3c6e85 |
Tested-by: Himanshu Madhani <hmadhani@marvell.com>
|
|
|
3c6e85 |
Reviewed-by: Himanshu Madhani <hmadhani@marvell.com>
|
|
|
3c6e85 |
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
|
|
|
3c6e85 |
(cherry picked from commit 85cffefa09e448906a6f0bc20f422d75a18675bd)
|
|
|
3c6e85 |
Signed-off-by: Himanshu Madhani <hmadhani@redhat.com>
|
|
|
3c6e85 |
Signed-off-by: Jan Stancek <jstancek@redhat.com>
|
|
|
3c6e85 |
---
|
|
|
3c6e85 |
drivers/scsi/qla2xxx/qla_def.h | 1 -
|
|
|
3c6e85 |
drivers/scsi/qla2xxx/qla_os.c | 45 ++++++++----------------------------------
|
|
|
3c6e85 |
2 files changed, 8 insertions(+), 38 deletions(-)
|
|
|
3c6e85 |
|
|
|
3c6e85 |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
|
|
|
3c6e85 |
index 5975f107d65d..3f6319edabd4 100644
|
|
|
3c6e85 |
--- a/drivers/scsi/qla2xxx/qla_def.h
|
|
|
3c6e85 |
+++ b/drivers/scsi/qla2xxx/qla_def.h
|
|
|
3c6e85 |
@@ -569,7 +569,6 @@ typedef struct srb {
|
|
|
3c6e85 |
} srb_t;
|
|
|
3c6e85 |
|
|
|
3c6e85 |
#define GET_CMD_SP(sp) (sp->u.scmd.cmd)
|
|
|
3c6e85 |
-#define SET_CMD_SP(sp, cmd) (sp->u.scmd.cmd = cmd)
|
|
|
3c6e85 |
#define GET_CMD_CTX_SP(sp) (sp->u.scmd.ctx)
|
|
|
3c6e85 |
|
|
|
3c6e85 |
#define GET_CMD_SENSE_LEN(sp) \
|
|
|
3c6e85 |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
|
|
|
3c6e85 |
index 9e0a724f08f6..b2500db628f1 100644
|
|
|
3c6e85 |
--- a/drivers/scsi/qla2xxx/qla_os.c
|
|
|
3c6e85 |
+++ b/drivers/scsi/qla2xxx/qla_os.c
|
|
|
3c6e85 |
@@ -725,7 +725,6 @@ qla2x00_sp_compl(void *ptr, int res)
|
|
|
3c6e85 |
cmd->scsi_done(cmd);
|
|
|
3c6e85 |
if (comp)
|
|
|
3c6e85 |
complete(comp);
|
|
|
3c6e85 |
- qla2x00_rel_sp(sp);
|
|
|
3c6e85 |
}
|
|
|
3c6e85 |
|
|
|
3c6e85 |
void
|
|
|
3c6e85 |
@@ -830,7 +829,6 @@ qla2xxx_qpair_sp_compl(void *ptr, int res)
|
|
|
3c6e85 |
cmd->scsi_done(cmd);
|
|
|
3c6e85 |
if (comp)
|
|
|
3c6e85 |
complete(comp);
|
|
|
3c6e85 |
- qla2xxx_rel_qpair_sp(sp->qpair, sp);
|
|
|
3c6e85 |
}
|
|
|
3c6e85 |
|
|
|
3c6e85 |
static int
|
|
|
3c6e85 |
@@ -927,9 +925,8 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
|
|
|
3c6e85 |
else
|
|
|
3c6e85 |
goto qc24_target_busy;
|
|
|
3c6e85 |
|
|
|
3c6e85 |
- sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
|
|
|
3c6e85 |
- if (!sp)
|
|
|
3c6e85 |
- goto qc24_host_busy;
|
|
|
3c6e85 |
+ sp = scsi_cmd_priv(cmd);
|
|
|
3c6e85 |
+ qla2xxx_init_sp(sp, vha, vha->hw->base_qpair, fcport);
|
|
|
3c6e85 |
|
|
|
3c6e85 |
sp->u.scmd.cmd = cmd;
|
|
|
3c6e85 |
sp->type = SRB_SCSI_CMD;
|
|
|
3c6e85 |
@@ -950,9 +947,6 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
|
|
|
3c6e85 |
qc24_host_busy_free_sp:
|
|
|
3c6e85 |
sp->free(sp);
|
|
|
3c6e85 |
|
|
|
3c6e85 |
-qc24_host_busy:
|
|
|
3c6e85 |
- return SCSI_MLQUEUE_HOST_BUSY;
|
|
|
3c6e85 |
-
|
|
|
3c6e85 |
qc24_target_busy:
|
|
|
3c6e85 |
return SCSI_MLQUEUE_TARGET_BUSY;
|
|
|
3c6e85 |
|
|
|
3c6e85 |
@@ -1013,9 +1007,8 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
|
|
|
3c6e85 |
else
|
|
|
3c6e85 |
goto qc24_target_busy;
|
|
|
3c6e85 |
|
|
|
3c6e85 |
- sp = qla2xxx_get_qpair_sp(vha, qpair, fcport, GFP_ATOMIC);
|
|
|
3c6e85 |
- if (!sp)
|
|
|
3c6e85 |
- goto qc24_host_busy;
|
|
|
3c6e85 |
+ sp = scsi_cmd_priv(cmd);
|
|
|
3c6e85 |
+ qla2xxx_init_sp(sp, vha, qpair, fcport);
|
|
|
3c6e85 |
|
|
|
3c6e85 |
sp->u.scmd.cmd = cmd;
|
|
|
3c6e85 |
sp->type = SRB_SCSI_CMD;
|
|
|
3c6e85 |
@@ -1039,9 +1032,6 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
|
|
|
3c6e85 |
qc24_host_busy_free_sp:
|
|
|
3c6e85 |
sp->free(sp);
|
|
|
3c6e85 |
|
|
|
3c6e85 |
-qc24_host_busy:
|
|
|
3c6e85 |
- return SCSI_MLQUEUE_HOST_BUSY;
|
|
|
3c6e85 |
-
|
|
|
3c6e85 |
qc24_target_busy:
|
|
|
3c6e85 |
return SCSI_MLQUEUE_TARGET_BUSY;
|
|
|
3c6e85 |
|
|
|
3c6e85 |
@@ -1275,10 +1265,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
|
|
|
3c6e85 |
srb_t *sp;
|
|
|
3c6e85 |
int ret;
|
|
|
3c6e85 |
unsigned int id, lun;
|
|
|
3c6e85 |
- unsigned long flags;
|
|
|
3c6e85 |
int rval;
|
|
|
3c6e85 |
struct qla_hw_data *ha = vha->hw;
|
|
|
3c6e85 |
- struct qla_qpair *qpair;
|
|
|
3c6e85 |
|
|
|
3c6e85 |
if (qla2x00_isp_reg_stat(ha)) {
|
|
|
3c6e85 |
ql_log(ql_log_info, vha, 0x8042,
|
|
|
3c6e85 |
@@ -1290,32 +1278,14 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
|
|
|
3c6e85 |
if (ret != 0)
|
|
|
3c6e85 |
return ret;
|
|
|
3c6e85 |
|
|
|
3c6e85 |
- sp = (srb_t *) CMD_SP(cmd);
|
|
|
3c6e85 |
- if (!sp)
|
|
|
3c6e85 |
- return SUCCESS;
|
|
|
3c6e85 |
-
|
|
|
3c6e85 |
- qpair = sp->qpair;
|
|
|
3c6e85 |
- if (!qpair)
|
|
|
3c6e85 |
- return SUCCESS;
|
|
|
3c6e85 |
+ sp = scsi_cmd_priv(cmd);
|
|
|
3c6e85 |
|
|
|
3c6e85 |
if (sp->fcport && sp->fcport->deleted)
|
|
|
3c6e85 |
return SUCCESS;
|
|
|
3c6e85 |
|
|
|
3c6e85 |
- spin_lock_irqsave(qpair->qp_lock_ptr, flags);
|
|
|
3c6e85 |
- if (sp->type != SRB_SCSI_CMD || GET_CMD_SP(sp) != cmd) {
|
|
|
3c6e85 |
- /* there's a chance an interrupt could clear
|
|
|
3c6e85 |
- the ptr as part of done & free */
|
|
|
3c6e85 |
- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
|
|
|
3c6e85 |
- return SUCCESS;
|
|
|
3c6e85 |
- }
|
|
|
3c6e85 |
-
|
|
|
3c6e85 |
- /* Get a reference to the sp and drop the lock. */
|
|
|
3c6e85 |
- if (sp_get(sp)){
|
|
|
3c6e85 |
- /* ref_count is already 0 */
|
|
|
3c6e85 |
- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
|
|
|
3c6e85 |
+ /* Return if the command has already finished. */
|
|
|
3c6e85 |
+ if (sp_get(sp))
|
|
|
3c6e85 |
return SUCCESS;
|
|
|
3c6e85 |
- }
|
|
|
3c6e85 |
- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
|
|
|
3c6e85 |
|
|
|
3c6e85 |
id = cmd->device->id;
|
|
|
3c6e85 |
lun = cmd->device->lun;
|
|
|
3c6e85 |
@@ -7268,6 +7238,7 @@ struct scsi_host_template qla2xxx_driver_template = {
|
|
|
3c6e85 |
|
|
|
3c6e85 |
.supported_mode = MODE_INITIATOR,
|
|
|
3c6e85 |
.use_host_wide_tags = 1,
|
|
|
3c6e85 |
+ .cmd_size = sizeof(srb_t),
|
|
|
3c6e85 |
};
|
|
|
3c6e85 |
|
|
|
3c6e85 |
static const struct pci_error_handlers qla2xxx_err_handler = {
|
|
|
3c6e85 |
--
|
|
|
3c6e85 |
2.13.6
|
|
|
3c6e85 |
|