]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
scsi: lpfc: devloss timeout race condition caused null pointer reference
authorJames Smart <jsmart2021@gmail.com>
Tue, 26 Jun 2018 15:24:29 +0000 (08:24 -0700)
committerBrian Maly <brian.maly@oracle.com>
Tue, 30 Oct 2018 18:29:53 +0000 (14:29 -0400)
Orabug: 27994179

A race condition between the context of devloss timeout handler and I/O
completion caused devloss timeout handler de-referencing pointer that had
been released.

Added the check in lpfc_sli_validate_fcp_iocb() on LPFC_IO_ON_TXCMPLQ to
capture the race condition of I/O completion and devloss timeout handler
attemption for aborting the I/O. Also, added check on lpfc_cmd->rdata
pointer before de-referenceing lpfc_cmd->rdata->pnode.

Also, added protection in lpfc_sli_abort_iocb() routine on driver performed
FCP I/O FLUSHING already under way before proceeding to aborting I/Os.

Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
(cherry picked from commit b0e830125b669570d8096b8ba22eb00f659fc05e)
Signed-off-by: Dan Duval <dan.duval@oracle.com>
Reviewed-by: Brian Maly <brian.maly@oracle.com>
Signed-off-by: Brian Maly <brian.maly@oracle.com>
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c

index 4f32e67dfc2bc4e0cda2b9fa8a9492cbdedbd170..13e49e29dc5331778062a11f35000a467294a683 100644 (file)
@@ -4526,6 +4526,11 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
        int err;
 
        rdata = lpfc_rport_data_from_scsi_device(cmnd->device);
+
+       /* sanity check on references */
+       if (unlikely(!rdata) || unlikely(!rport))
+               goto out_fail_command;
+
        err = fc_remote_port_chkready(rport);
        if (err) {
                cmnd->result = err;
index 9dfe292228a6171d8c95e1c8fc9685e5f980f9f7..c7467de53dcf531cdb7d32e7cf0d16b1ce104e40 100644 (file)
@@ -10186,10 +10186,11 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport,
        struct lpfc_scsi_buf *lpfc_cmd;
        int rc = 1;
 
-       if (!(iocbq->iocb_flag &  LPFC_IO_FCP))
+       if (iocbq->vport != vport)
                return rc;
 
-       if (iocbq->vport != vport)
+       if (!(iocbq->iocb_flag &  LPFC_IO_FCP) ||
+           !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ))
                return rc;
 
        lpfc_cmd = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq);
@@ -10199,13 +10200,13 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport,
 
        switch (ctx_cmd) {
        case LPFC_CTX_LUN:
-               if ((lpfc_cmd->rdata->pnode) &&
+               if ((lpfc_cmd->rdata) && (lpfc_cmd->rdata->pnode) &&
                    (lpfc_cmd->rdata->pnode->nlp_sid == tgt_id) &&
                    (scsilun_to_int(&lpfc_cmd->fcp_cmnd->fcp_lun) == lun_id))
                        rc = 0;
                break;
        case LPFC_CTX_TGT:
-               if ((lpfc_cmd->rdata->pnode) &&
+               if ((lpfc_cmd->rdata) && (lpfc_cmd->rdata->pnode) &&
                    (lpfc_cmd->rdata->pnode->nlp_sid == tgt_id))
                        rc = 0;
                break;
@@ -10319,6 +10320,10 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
        int errcnt = 0, ret_val = 0;
        int i;
 
+       /* all I/Os are in process of being flushed */
+       if (phba->hba_flag & HBA_FCP_IOQ_FLUSH)
+               return errcnt;
+
        for (i = 1; i <= phba->sli.last_iotag; i++) {
                iocbq = phba->sli.iocbq_lookup[i];