]> 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>
Wed, 4 Jun 2025 12:37:05 +0000 (14:37 +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 3ff76ca147a5a6545cf5db0f6025695651ae3156..353c360b0c6ab97602b1c12fba07241f242312c6 100644 (file)
@@ -5407,6 +5407,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) {
@@ -5421,14 +5422,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 *