Skip to content

Commit 07caedc

Browse files
Justin Teemartinkpetersen
authored andcommitted
scsi: lpfc: Fix reusing an ndlp that is marked NLP_DROPPED during FLOGI
It's possible for an unstable link to repeatedly bounce allowing a FLOGI retry, but then bounce again forcing an abort of the FLOGI. Ensure that the initial reference count on the FLOGI ndlp is restored in this faulty link scenario. Signed-off-by: Justin Tee <justin.tee@broadcom.com> Link: https://patch.msgid.link/20251106224639.139176-8-justintee8345@gmail.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 0b8b15a commit 07caedc

2 files changed

Lines changed: 32 additions & 8 deletions

File tree

drivers/scsi/lpfc/lpfc_els.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -934,10 +934,15 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
934934
/* Check to see if link went down during discovery */
935935
if (lpfc_els_chk_latt(vport)) {
936936
/* One additional decrement on node reference count to
937-
* trigger the release of the node
937+
* trigger the release of the node. Make sure the ndlp
938+
* is marked NLP_DROPPED.
938939
*/
939-
if (!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD))
940+
if (!test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag) &&
941+
!test_bit(NLP_DROPPED, &ndlp->nlp_flag) &&
942+
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) {
943+
set_bit(NLP_DROPPED, &ndlp->nlp_flag);
940944
lpfc_nlp_put(ndlp);
945+
}
941946
goto out;
942947
}
943948

@@ -995,9 +1000,10 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
9951000
IOERR_LOOP_OPEN_FAILURE)))
9961001
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
9971002
"2858 FLOGI Status:x%x/x%x TMO"
998-
":x%x Data x%lx x%x\n",
1003+
":x%x Data x%lx x%x x%lx x%x\n",
9991004
ulp_status, ulp_word4, tmo,
1000-
phba->hba_flag, phba->fcf.fcf_flag);
1005+
phba->hba_flag, phba->fcf.fcf_flag,
1006+
ndlp->nlp_flag, ndlp->fc4_xpt_flags);
10011007

10021008
/* Check for retry */
10031009
if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
@@ -1015,14 +1021,17 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
10151021
* reference to trigger node release.
10161022
*/
10171023
if (!test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag) &&
1018-
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD))
1024+
!test_bit(NLP_DROPPED, &ndlp->nlp_flag) &&
1025+
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) {
1026+
set_bit(NLP_DROPPED, &ndlp->nlp_flag);
10191027
lpfc_nlp_put(ndlp);
1028+
}
10201029

10211030
lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
10221031
"0150 FLOGI Status:x%x/x%x "
1023-
"xri x%x TMO:x%x refcnt %d\n",
1032+
"xri x%x iotag x%x TMO:x%x refcnt %d\n",
10241033
ulp_status, ulp_word4, cmdiocb->sli4_xritag,
1025-
tmo, kref_read(&ndlp->kref));
1034+
cmdiocb->iotag, tmo, kref_read(&ndlp->kref));
10261035

10271036
/* If this is not a loop open failure, bail out */
10281037
if (!(ulp_status == IOSTAT_LOCAL_REJECT &&
@@ -1279,6 +1288,19 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
12791288
uint32_t tmo, did;
12801289
int rc;
12811290

1291+
/* It's possible for lpfc to reissue a FLOGI on an ndlp that is marked
1292+
* NLP_DROPPED. This happens when the FLOGI completed with the XB bit
1293+
* set causing lpfc to reference the ndlp until the XRI_ABORTED CQE is
1294+
* issued. The time window for the XRI_ABORTED CQE can be as much as
1295+
* 2*2*RA_TOV allowing for ndlp reuse of this type when the link is
1296+
* cycling quickly. When true, restore the initial reference and remove
1297+
* the NLP_DROPPED flag as lpfc is retrying.
1298+
*/
1299+
if (test_and_clear_bit(NLP_DROPPED, &ndlp->nlp_flag)) {
1300+
if (!lpfc_nlp_get(ndlp))
1301+
return 1;
1302+
}
1303+
12821304
cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
12831305
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
12841306
ndlp->nlp_DID, ELS_CMD_FLOGI);

drivers/scsi/lpfc/lpfc_hbadisc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ lpfc_check_nlp_post_devloss(struct lpfc_vport *vport,
424424
struct lpfc_nodelist *ndlp)
425425
{
426426
if (test_and_clear_bit(NLP_IN_RECOV_POST_DEV_LOSS, &ndlp->save_flags)) {
427+
clear_bit(NLP_DROPPED, &ndlp->nlp_flag);
427428
lpfc_nlp_get(ndlp);
428429
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY | LOG_NODE,
429430
"8438 Devloss timeout reversed on DID x%x "
@@ -566,7 +567,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
566567
return fcf_inuse;
567568
}
568569

569-
lpfc_nlp_put(ndlp);
570+
if (!test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
571+
lpfc_nlp_put(ndlp);
570572
return fcf_inuse;
571573
}
572574

0 commit comments

Comments
 (0)