Commit 85cffefa authored by Bart Van Assche's avatar Bart Van Assche Committed by Martin K. Petersen
Browse files

scsi: qla2xxx: Fix a race condition between aborting and completing a SCSI command



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: default avatarBart Van Assche <bvanassche@acm.org>
Tested-by: default avatarHimanshu Madhani <hmadhani@marvell.com>
Reviewed-by: default avatarHimanshu Madhani <hmadhani@marvell.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent bdb61b9b
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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) \
+8 −37
Original line number Diff line number Diff line
@@ -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 = {