]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
scsi: qla2xxx: Fix a race condition between aborting and completing a SCSI command
authorBart Van Assche <bvanassche@acm.org>
Fri, 9 Aug 2019 03:02:06 +0000 (20:02 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 13 Aug 2019 01:34:08 +0000 (21:34 -0400)
Instead of allocating a struct srb dynamically from inside .queuecommand(),
set qla2xxx_driver_template.cmd_size such that struct scsi_cmnd and struct
srb are contiguous. Do not call QLA_QPAIR_MARK_BUSY() /
QLA_QPAIR_MARK_NOT_BUSY() for SRBs associated with SCSI commands. That is
safe because scsi_remove_host() is called before queue pairs are deleted
and scsi_remove_host() waits for all outstanding SCSI commands to finish.

Cc: Himanshu Madhani <hmadhani@marvell.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Tested-by: Himanshu Madhani <hmadhani@marvell.com>
Reviewed-by: Himanshu Madhani <hmadhani@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_os.c

index 65d79bcb7ccf62f27a4316882baea1c25640d376..3ffe7661a25b38d582ba265d0d08758e1ca2021f 100644 (file)
@@ -630,7 +630,6 @@ typedef struct srb {
 } srb_t;
 
 #define GET_CMD_SP(sp) (sp->u.scmd.cmd)
-#define SET_CMD_SP(sp, cmd) (sp->u.scmd.cmd = cmd)
 #define GET_CMD_CTX_SP(sp) (sp->u.scmd.ctx)
 
 #define GET_CMD_SENSE_LEN(sp) \
index 9ef59995f5d6e5315fcc2057a5c394467006d76c..5ca7f7913258a45ab584b08ceacf07bedcfac27b 100644 (file)
@@ -713,7 +713,6 @@ void qla2x00_sp_compl(srb_t *sp, int res)
        cmd->scsi_done(cmd);
        if (comp)
                complete(comp);
-       qla2x00_rel_sp(sp);
 }
 
 void qla2xxx_qpair_sp_free_dma(srb_t *sp)
@@ -814,7 +813,6 @@ void qla2xxx_qpair_sp_compl(srb_t *sp, int res)
        cmd->scsi_done(cmd);
        if (comp)
                complete(comp);
-       qla2xxx_rel_qpair_sp(sp->qpair, sp);
 }
 
 static int
@@ -908,9 +906,8 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
        else
                goto qc24_target_busy;
 
-       sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
-       if (!sp)
-               goto qc24_host_busy;
+       sp = scsi_cmd_priv(cmd);
+       qla2xxx_init_sp(sp, vha, vha->hw->base_qpair, fcport);
 
        sp->u.scmd.cmd = cmd;
        sp->type = SRB_SCSI_CMD;
@@ -931,9 +928,6 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
 qc24_host_busy_free_sp:
        sp->free(sp);
 
-qc24_host_busy:
-       return SCSI_MLQUEUE_HOST_BUSY;
-
 qc24_target_busy:
        return SCSI_MLQUEUE_TARGET_BUSY;
 
@@ -994,9 +988,8 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
        else
                goto qc24_target_busy;
 
-       sp = qla2xxx_get_qpair_sp(vha, qpair, fcport, GFP_ATOMIC);
-       if (!sp)
-               goto qc24_host_busy;
+       sp = scsi_cmd_priv(cmd);
+       qla2xxx_init_sp(sp, vha, qpair, fcport);
 
        sp->u.scmd.cmd = cmd;
        sp->type = SRB_SCSI_CMD;
@@ -1020,9 +1013,6 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
 qc24_host_busy_free_sp:
        sp->free(sp);
 
-qc24_host_busy:
-       return SCSI_MLQUEUE_HOST_BUSY;
-
 qc24_target_busy:
        return SCSI_MLQUEUE_TARGET_BUSY;
 
@@ -1257,10 +1247,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
        int ret;
        unsigned int id;
        uint64_t lun;
-       unsigned long flags;
        int rval;
        struct qla_hw_data *ha = vha->hw;
-       struct qla_qpair *qpair;
 
        if (qla2x00_isp_reg_stat(ha)) {
                ql_log(ql_log_info, vha, 0x8042,
@@ -1272,32 +1260,14 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
        if (ret != 0)
                return ret;
 
-       sp = (srb_t *) CMD_SP(cmd);
-       if (!sp)
-               return SUCCESS;
-
-       qpair = sp->qpair;
-       if (!qpair)
-               return SUCCESS;
+       sp = scsi_cmd_priv(cmd);
 
        if (sp->fcport && sp->fcport->deleted)
                return SUCCESS;
 
-       spin_lock_irqsave(qpair->qp_lock_ptr, flags);
-       if (sp->type != SRB_SCSI_CMD || GET_CMD_SP(sp) != cmd) {
-               /* there's a chance an interrupt could clear
-                  the ptr as part of done & free */
-               spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
-               return SUCCESS;
-       }
-
-       /* Get a reference to the sp and drop the lock. */
-       if (sp_get(sp)){
-               /* ref_count is already 0 */
-               spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+       /* Return if the command has already finished. */
+       if (sp_get(sp))
                return SUCCESS;
-       }
-       spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
 
        id = cmd->device->id;
        lun = cmd->device->lun;
@@ -7159,6 +7129,7 @@ struct scsi_host_template qla2xxx_driver_template = {
 
        .supported_mode         = MODE_INITIATOR,
        .track_queue_depth      = 1,
+       .cmd_size               = sizeof(srb_t),
 };
 
 static const struct pci_error_handlers qla2xxx_err_handler = {