Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 0ef6e01

Browse files
Justin Teegregkh
authored andcommitted
scsi: lpfc: Ensure DA_ID handling completion before deleting an NPIV instance
[ Upstream commit 0a3c84f ] Deleting an NPIV instance requires all fabric ndlps to be released before an NPIV's resources can be torn down. Failure to release fabric ndlps beforehand opens kref imbalance race conditions. Fix by forcing the DA_ID to complete synchronously with usage of wait_queue. Signed-off-by: Justin Tee <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin K. Petersen <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent ab88c77 commit 0ef6e01

File tree

3 files changed

+55
-7
lines changed

3 files changed

+55
-7
lines changed

drivers/scsi/lpfc/lpfc_ct.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,6 +1671,18 @@ lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
16711671
}
16721672

16731673
out:
1674+
/* If the caller wanted a synchronous DA_ID completion, signal the
1675+
* wait obj and clear flag to reset the vport.
1676+
*/
1677+
if (ndlp->save_flags & NLP_WAIT_FOR_DA_ID) {
1678+
if (ndlp->da_id_waitq)
1679+
wake_up(ndlp->da_id_waitq);
1680+
}
1681+
1682+
spin_lock_irq(&ndlp->lock);
1683+
ndlp->save_flags &= ~NLP_WAIT_FOR_DA_ID;
1684+
spin_unlock_irq(&ndlp->lock);
1685+
16741686
lpfc_ct_free_iocb(phba, cmdiocb);
16751687
lpfc_nlp_put(ndlp);
16761688
return;

drivers/scsi/lpfc/lpfc_disc.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ enum lpfc_nlp_save_flags {
9090
NLP_IN_RECOV_POST_DEV_LOSS = 0x1,
9191
/* wait for outstanding LOGO to cmpl */
9292
NLP_WAIT_FOR_LOGO = 0x2,
93+
/* wait for outstanding DA_ID to finish */
94+
NLP_WAIT_FOR_DA_ID = 0x4
9395
};
9496

9597
struct lpfc_nodelist {
@@ -159,7 +161,12 @@ struct lpfc_nodelist {
159161
uint32_t nvme_fb_size; /* NVME target's supported byte cnt */
160162
#define NVME_FB_BIT_SHIFT 9 /* PRLI Rsp first burst in 512B units. */
161163
uint32_t nlp_defer_did;
164+
165+
/* These wait objects are NPIV specific. These IOs must complete
166+
* synchronously.
167+
*/
162168
wait_queue_head_t *logo_waitq;
169+
wait_queue_head_t *da_id_waitq;
163170
};
164171

165172
struct lpfc_node_rrq {

drivers/scsi/lpfc/lpfc_vport.c

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
633633
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
634634
struct lpfc_hba *phba = vport->phba;
635635
int rc;
636+
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
636637

637638
if (vport->port_type == LPFC_PHYSICAL_PORT) {
638639
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
@@ -688,21 +689,49 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
688689
if (!ndlp)
689690
goto skip_logo;
690691

692+
/* Send the DA_ID and Fabric LOGO to cleanup the NPIV fabric entries. */
691693
if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
692694
phba->link_state >= LPFC_LINK_UP &&
693695
phba->fc_topology != LPFC_TOPOLOGY_LOOP) {
694696
if (vport->cfg_enable_da_id) {
695-
/* Send DA_ID and wait for a completion. */
697+
/* Send DA_ID and wait for a completion. This is best
698+
* effort. If the DA_ID fails, likely the fabric will
699+
* "leak" NportIDs but at least the driver issued the
700+
* command.
701+
*/
702+
ndlp = lpfc_findnode_did(vport, NameServer_DID);
703+
if (!ndlp)
704+
goto issue_logo;
705+
706+
spin_lock_irq(&ndlp->lock);
707+
ndlp->da_id_waitq = &waitq;
708+
ndlp->save_flags |= NLP_WAIT_FOR_DA_ID;
709+
spin_unlock_irq(&ndlp->lock);
710+
696711
rc = lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0);
697-
if (rc) {
698-
lpfc_printf_log(vport->phba, KERN_WARNING,
699-
LOG_VPORT,
700-
"1829 CT command failed to "
701-
"delete objects on fabric, "
702-
"rc %d\n", rc);
712+
if (!rc) {
713+
wait_event_timeout(waitq,
714+
!(ndlp->save_flags & NLP_WAIT_FOR_DA_ID),
715+
msecs_to_jiffies(phba->fc_ratov * 2000));
703716
}
717+
718+
lpfc_printf_vlog(vport, KERN_INFO, LOG_VPORT | LOG_ELS,
719+
"1829 DA_ID issue status %d. "
720+
"SFlag x%x NState x%x, NFlag x%x "
721+
"Rpi x%x\n",
722+
rc, ndlp->save_flags, ndlp->nlp_state,
723+
ndlp->nlp_flag, ndlp->nlp_rpi);
724+
725+
/* Remove the waitq and save_flags. It no
726+
* longer matters if the wake happened.
727+
*/
728+
spin_lock_irq(&ndlp->lock);
729+
ndlp->da_id_waitq = NULL;
730+
ndlp->save_flags &= ~NLP_WAIT_FOR_DA_ID;
731+
spin_unlock_irq(&ndlp->lock);
704732
}
705733

734+
issue_logo:
706735
/*
707736
* If the vpi is not registered, then a valid FDISC doesn't
708737
* exist and there is no need for a ELS LOGO. Just cleanup

0 commit comments

Comments
 (0)