scsi: lpfc: Synchronize access to remoteport via rport
The driver currently uses the ndlp to get the local rport which is then used to get the nvme transport remoteport pointer. There can be cases where a stale remoteport pointer is obtained as synchronization isn't done through the different dereferences. Correct by using locks to synchronize the dereferences. 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:
Родитель
d87161bea4
Коммит
9e21017826
|
@ -360,12 +360,12 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
|
|||
goto buffer_done;
|
||||
|
||||
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
|
||||
nrport = NULL;
|
||||
spin_lock(&vport->phba->hbalock);
|
||||
rport = lpfc_ndlp_get_nrport(ndlp);
|
||||
if (!rport)
|
||||
continue;
|
||||
|
||||
/* local short-hand pointer. */
|
||||
nrport = rport->remoteport;
|
||||
if (rport)
|
||||
nrport = rport->remoteport;
|
||||
spin_unlock(&vport->phba->hbalock);
|
||||
if (!nrport)
|
||||
continue;
|
||||
|
||||
|
@ -3386,6 +3386,7 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
|
|||
struct lpfc_nodelist *ndlp;
|
||||
#if (IS_ENABLED(CONFIG_NVME_FC))
|
||||
struct lpfc_nvme_rport *rport;
|
||||
struct nvme_fc_remote_port *remoteport = NULL;
|
||||
#endif
|
||||
|
||||
shost = lpfc_shost_from_vport(vport);
|
||||
|
@ -3396,8 +3397,12 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
|
|||
if (ndlp->rport)
|
||||
ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo;
|
||||
#if (IS_ENABLED(CONFIG_NVME_FC))
|
||||
spin_lock(&vport->phba->hbalock);
|
||||
rport = lpfc_ndlp_get_nrport(ndlp);
|
||||
if (rport)
|
||||
remoteport = rport->remoteport;
|
||||
spin_unlock(&vport->phba->hbalock);
|
||||
if (remoteport)
|
||||
nvme_fc_set_remoteport_devloss(rport->remoteport,
|
||||
vport->cfg_devloss_tmo);
|
||||
#endif
|
||||
|
|
|
@ -551,7 +551,7 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
|
|||
unsigned char *statep;
|
||||
struct nvme_fc_local_port *localport;
|
||||
struct lpfc_nvmet_tgtport *tgtp;
|
||||
struct nvme_fc_remote_port *nrport;
|
||||
struct nvme_fc_remote_port *nrport = NULL;
|
||||
struct lpfc_nvme_rport *rport;
|
||||
|
||||
cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
|
||||
|
@ -696,11 +696,11 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
|
|||
len += snprintf(buf + len, size - len, "\tRport List:\n");
|
||||
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
|
||||
/* local short-hand pointer. */
|
||||
spin_lock(&phba->hbalock);
|
||||
rport = lpfc_ndlp_get_nrport(ndlp);
|
||||
if (!rport)
|
||||
continue;
|
||||
|
||||
nrport = rport->remoteport;
|
||||
if (rport)
|
||||
nrport = rport->remoteport;
|
||||
spin_unlock(&phba->hbalock);
|
||||
if (!nrport)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -2725,7 +2725,9 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
|||
rpinfo.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
|
||||
rpinfo.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
|
||||
|
||||
spin_lock_irq(&vport->phba->hbalock);
|
||||
oldrport = lpfc_ndlp_get_nrport(ndlp);
|
||||
spin_unlock_irq(&vport->phba->hbalock);
|
||||
if (!oldrport)
|
||||
lpfc_nlp_get(ndlp);
|
||||
|
||||
|
@ -2840,7 +2842,7 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
|||
struct nvme_fc_local_port *localport;
|
||||
struct lpfc_nvme_lport *lport;
|
||||
struct lpfc_nvme_rport *rport;
|
||||
struct nvme_fc_remote_port *remoteport;
|
||||
struct nvme_fc_remote_port *remoteport = NULL;
|
||||
|
||||
localport = vport->localport;
|
||||
|
||||
|
@ -2854,11 +2856,14 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
|||
if (!lport)
|
||||
goto input_err;
|
||||
|
||||
spin_lock_irq(&vport->phba->hbalock);
|
||||
rport = lpfc_ndlp_get_nrport(ndlp);
|
||||
if (!rport)
|
||||
if (rport)
|
||||
remoteport = rport->remoteport;
|
||||
spin_unlock_irq(&vport->phba->hbalock);
|
||||
if (!remoteport)
|
||||
goto input_err;
|
||||
|
||||
remoteport = rport->remoteport;
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC,
|
||||
"6033 Unreg nvme remoteport %p, portname x%llx, "
|
||||
"port_id x%06x, portstate x%x port type x%x\n",
|
||||
|
|
Загрузка…
Ссылка в новой задаче