]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
scsi: lpfc: Handle duplicate D_IDs in ndlp search-by D_ID routine
authorJustin Tee <justin.tee@broadcom.com>
Fri, 31 Jan 2025 00:05:22 +0000 (16:05 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 May 2025 09:13:40 +0000 (11:13 +0200)
[ Upstream commit 56c3d809b7b450379162d0b8a70bbe71ab8db706 ]

After a port swap between separate fabrics, there may be multiple nodes in
the vport's fc_nodes list with the same fabric well known address.
Duplication is temporary and eventually resolves itself after dev_loss_tmo
expires, but nameserver queries may still occur before dev_loss_tmo.  This
possibly results in returning stale fabric ndlp objects.  Fix by adding an
nlp_state check to ensure the ndlp search routine returns the correct newer
allocated ndlp fabric object.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://lore.kernel.org/r/20250131000524.163662-5-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/scsi/lpfc/lpfc_hbadisc.c

index 36e66df36a18cbe184034514dc8a330c9df71da7..45d268d49060e60fd3f0747c8b989423fb958e7e 100644 (file)
@@ -5564,6 +5564,7 @@ static struct lpfc_nodelist *
 __lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did)
 {
        struct lpfc_nodelist *ndlp;
+       struct lpfc_nodelist *np = NULL;
        uint32_t data1;
 
        list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
@@ -5578,14 +5579,20 @@ __lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did)
                                         ndlp, ndlp->nlp_DID,
                                         ndlp->nlp_flag, data1, ndlp->nlp_rpi,
                                         ndlp->active_rrqs_xri_bitmap);
-                       return ndlp;
+
+                       /* Check for new or potentially stale node */
+                       if (ndlp->nlp_state != NLP_STE_UNUSED_NODE)
+                               return ndlp;
+                       np = ndlp;
                }
        }
 
-       /* FIND node did <did> NOT FOUND */
-       lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE,
-                        "0932 FIND node did x%x NOT FOUND.\n", did);
-       return NULL;
+       if (!np)
+               /* FIND node did <did> NOT FOUND */
+               lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE,
+                                "0932 FIND node did x%x NOT FOUND.\n", did);
+
+       return np;
 }
 
 struct lpfc_nodelist *