2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2025-01-10 22:54:11 +08:00

scsi: lpfc: Fix Oops in nvme_register with target logout/login

lpfc_nvme_register_port hit a null prev_ndlp pointer in a test with lots of
target ports swapping addresses. The oldport value was stale, thus it's
ndlp (prev_ndlp set to it) was used.

Fix by moving oldrport pointer checks, and if used prev_ndlp pointer
assignment, to be done while the lock is held.

Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
James Smart 2019-08-14 16:56:41 -07:00 committed by Martin K. Petersen
parent 08180db254
commit 61184f1742

View File

@ -2317,9 +2317,13 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
spin_lock_irq(&vport->phba->hbalock); spin_lock_irq(&vport->phba->hbalock);
oldrport = lpfc_ndlp_get_nrport(ndlp); oldrport = lpfc_ndlp_get_nrport(ndlp);
spin_unlock_irq(&vport->phba->hbalock); if (oldrport) {
if (!oldrport) prev_ndlp = oldrport->ndlp;
spin_unlock_irq(&vport->phba->hbalock);
} else {
spin_unlock_irq(&vport->phba->hbalock);
lpfc_nlp_get(ndlp); lpfc_nlp_get(ndlp);
}
ret = nvme_fc_register_remoteport(localport, &rpinfo, &remote_port); ret = nvme_fc_register_remoteport(localport, &rpinfo, &remote_port);
if (!ret) { if (!ret) {
@ -2338,7 +2342,6 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
/* New remoteport record does not guarantee valid /* New remoteport record does not guarantee valid
* host private memory area. * host private memory area.
*/ */
prev_ndlp = oldrport->ndlp;
if (oldrport == remote_port->private) { if (oldrport == remote_port->private) {
/* Same remoteport - ndlp should match. /* Same remoteport - ndlp should match.
* Just reuse. * Just reuse.
@ -2352,7 +2355,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
remote_port->port_name, remote_port->port_name,
remote_port->port_id, remote_port->port_id,
remote_port->port_role, remote_port->port_role,
prev_ndlp, oldrport->ndlp,
ndlp, ndlp,
ndlp->nlp_type, ndlp->nlp_type,
ndlp->nlp_DID); ndlp->nlp_DID);