]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
scsi: lpfc: Fix sg_reset on SCSI device causing kernel crash
authorJames Smart <james.smart@broadcom.com>
Thu, 13 Oct 2016 22:06:04 +0000 (15:06 -0700)
committerChuck Anderson <chuck.anderson@oracle.com>
Mon, 27 Feb 2017 06:13:25 +0000 (22:13 -0800)
Orabug: 25486030

Fix sg_reset on SCSI device causing kernel crash

Driver could reference stale node pointers in task mgmt call.
Changed to use resetting cmd and look up node pointer in task mgmt
function.

Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
(cherry picked from commit eed695d70e7eff55595f222b55b96f105d4a27ca)
Signed-off-by: Brian Maly <brian.maly@oracle.com>
drivers/scsi/lpfc/lpfc_scsi.c

index 8429b246110deb7b1d68718436333b7e954520c2..4d6afc682e139e3aa646e32b49505810e49f3c38 100644 (file)
@@ -4945,26 +4945,30 @@ lpfc_check_fcp_rsp(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd)
  *   0x2002 - Success.
  **/
 static int
-lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata,
-                   unsigned  tgt_id, uint64_t lun_id,
-                   uint8_t task_mgmt_cmd)
+lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd,
+                  unsigned int tgt_id, uint64_t lun_id,
+                  uint8_t task_mgmt_cmd)
 {
        struct lpfc_hba   *phba = vport->phba;
        struct lpfc_scsi_buf *lpfc_cmd;
        struct lpfc_iocbq *iocbq;
        struct lpfc_iocbq *iocbqrsp;
-       struct lpfc_nodelist *pnode = rdata->pnode;
+       struct lpfc_rport_data *rdata;
+       struct lpfc_nodelist *pnode;
        int ret;
        int status;
 
-       if (!pnode || !NLP_CHK_NODE_ACT(pnode))
+       rdata = lpfc_rport_data_from_scsi_device(cmnd->device);
+       if (!rdata || !rdata->pnode || !NLP_CHK_NODE_ACT(rdata->pnode))
                return FAILED;
+       pnode = rdata->pnode;
 
-       lpfc_cmd = lpfc_get_scsi_buf(phba, rdata->pnode);
+       lpfc_cmd = lpfc_get_scsi_buf(phba, pnode);
        if (lpfc_cmd == NULL)
                return FAILED;
        lpfc_cmd->timeout = phba->cfg_task_mgmt_tmo;
        lpfc_cmd->rdata = rdata;
+       lpfc_cmd->pCmd = cmnd;
 
        status = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id,
                                           task_mgmt_cmd);
@@ -5171,7 +5175,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
        fc_host_post_vendor_event(shost, fc_get_event_number(),
                sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID);
 
-       status = lpfc_send_taskmgmt(vport, rdata, tgt_id, lun_id,
+       status = lpfc_send_taskmgmt(vport, cmnd, tgt_id, lun_id,
                                                FCP_LUN_RESET);
 
        lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
@@ -5249,7 +5253,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
        fc_host_post_vendor_event(shost, fc_get_event_number(),
                sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID);
 
-       status = lpfc_send_taskmgmt(vport, rdata, tgt_id, lun_id,
+       status = lpfc_send_taskmgmt(vport, cmnd, tgt_id, lun_id,
                                        FCP_TARGET_RESET);
 
        lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
@@ -5328,7 +5332,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
                if (!match)
                        continue;
 
-               status = lpfc_send_taskmgmt(vport, ndlp->rport->dd_data,
+               status = lpfc_send_taskmgmt(vport, cmnd,
                                        i, 0, FCP_TARGET_RESET);
 
                if (status != SUCCESS) {