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

Commit 0a3c84f

Browse files
Justin Teemartinkpetersen
authored andcommitted
scsi: lpfc: Ensure DA_ID handling completion before deleting an NPIV instance
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]>
1 parent d1a2ef6 commit 0a3c84f

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
@@ -1647,6 +1647,18 @@ lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
16471647
}
16481648

16491649
out:
1650+
/* If the caller wanted a synchronous DA_ID completion, signal the
1651+
* wait obj and clear flag to reset the vport.
1652+
*/
1653+
if (ndlp->save_flags & NLP_WAIT_FOR_DA_ID) {
1654+
if (ndlp->da_id_waitq)
1655+
wake_up(ndlp->da_id_waitq);
1656+
}
1657+
1658+
spin_lock_irq(&ndlp->lock);
1659+
ndlp->save_flags &= ~NLP_WAIT_FOR_DA_ID;
1660+
spin_unlock_irq(&ndlp->lock);
1661+
16501662
lpfc_ct_free_iocb(phba, cmdiocb);
16511663
lpfc_nlp_put(ndlp);
16521664
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
@@ -626,6 +626,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
626626
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
627627
struct lpfc_hba *phba = vport->phba;
628628
int rc;
629+
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
629630

630631
if (vport->port_type == LPFC_PHYSICAL_PORT) {
631632
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
@@ -679,21 +680,49 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
679680
if (!ndlp)
680681
goto skip_logo;
681682

683+
/* Send the DA_ID and Fabric LOGO to cleanup the NPIV fabric entries. */
682684
if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
683685
phba->link_state >= LPFC_LINK_UP &&
684686
phba->fc_topology != LPFC_TOPOLOGY_LOOP) {
685687
if (vport->cfg_enable_da_id) {
686-
/* Send DA_ID and wait for a completion. */
688+
/* Send DA_ID and wait for a completion. This is best
689+
* effort. If the DA_ID fails, likely the fabric will
690+
* "leak" NportIDs but at least the driver issued the
691+
* command.
692+
*/
693+
ndlp = lpfc_findnode_did(vport, NameServer_DID);
694+
if (!ndlp)
695+
goto issue_logo;
696+
697+
spin_lock_irq(&ndlp->lock);
698+
ndlp->da_id_waitq = &waitq;
699+
ndlp->save_flags |= NLP_WAIT_FOR_DA_ID;
700+
spin_unlock_irq(&ndlp->lock);
701+
687702
rc = lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0);
688-
if (rc) {
689-
lpfc_printf_log(vport->phba, KERN_WARNING,
690-
LOG_VPORT,
691-
"1829 CT command failed to "
692-
"delete objects on fabric, "
693-
"rc %d\n", rc);
703+
if (!rc) {
704+
wait_event_timeout(waitq,
705+
!(ndlp->save_flags & NLP_WAIT_FOR_DA_ID),
706+
msecs_to_jiffies(phba->fc_ratov * 2000));
694707
}
708+
709+
lpfc_printf_vlog(vport, KERN_INFO, LOG_VPORT | LOG_ELS,
710+
"1829 DA_ID issue status %d. "
711+
"SFlag x%x NState x%x, NFlag x%x "
712+
"Rpi x%x\n",
713+
rc, ndlp->save_flags, ndlp->nlp_state,
714+
ndlp->nlp_flag, ndlp->nlp_rpi);
715+
716+
/* Remove the waitq and save_flags. It no
717+
* longer matters if the wake happened.
718+
*/
719+
spin_lock_irq(&ndlp->lock);
720+
ndlp->da_id_waitq = NULL;
721+
ndlp->save_flags &= ~NLP_WAIT_FOR_DA_ID;
722+
spin_unlock_irq(&ndlp->lock);
695723
}
696724

725+
issue_logo:
697726
/*
698727
* If the vpi is not registered, then a valid FDISC doesn't
699728
* exist and there is no need for a ELS LOGO. Just cleanup

0 commit comments

Comments
 (0)