diff options
author | James Smart <james.smart@avagotech.com> | 2015-05-21 13:55:28 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Odin.com> | 2015-06-05 22:40:19 -0700 |
commit | 466e840b7809e00ab3a1af9b4a5b5751e681730d (patch) | |
tree | 149a3be013344fda727df0f00086b77d5b0bc07b /drivers/scsi/lpfc/lpfc_els.c | |
parent | e5abba4c6aa7f094d32c0115193516697da60df8 (diff) | |
download | lwn-466e840b7809e00ab3a1af9b4a5b5751e681730d.tar.gz lwn-466e840b7809e00ab3a1af9b4a5b5751e681730d.zip |
lpfc: Fix rport leak.
Correct locking and refcounting in tracking our rports
Signed-off-by: Dick Kennedy <dick.kennedy@avagotech.com>
Signed-off-by: James Smart <james.smart@avagotech.com>
Signed-off-by: James Bottomley <JBottomley@Odin.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 4d3d931b177a..011c8d8dba0b 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1624,8 +1624,9 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, if (rport) { rdata = rport->dd_data; if (rdata->pnode == ndlp) { - lpfc_nlp_put(ndlp); + /* break the link before dropping the ref */ ndlp->rport = NULL; + lpfc_nlp_put(ndlp); rdata->pnode = lpfc_nlp_get(new_ndlp); new_ndlp->rport = rport; } @@ -3674,6 +3675,7 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * Remove the ndlp reference if it's a fabric node that has * sent us an unsolicted LOGO. */ + /* FIXME: this one frees ndlp before breaking rport link */ if (ndlp->nlp_type & NLP_FABRIC) lpfc_nlp_put(ndlp); @@ -7351,8 +7353,13 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, * Do not process any unsolicited ELS commands * if the ndlp is in DEV_LOSS */ - if (ndlp->nlp_add_flag & NLP_IN_DEV_LOSS) + shost = lpfc_shost_from_vport(vport); + spin_lock_irq(shost->host_lock); + if (ndlp->nlp_flag & NLP_IN_DEV_LOSS) { + spin_unlock_irq(shost->host_lock); goto dropit; + } + spin_unlock_irq(shost->host_lock); elsiocb->context1 = lpfc_nlp_get(ndlp); elsiocb->vport = vport; @@ -7396,7 +7403,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, rjt_exp = LSEXP_NOTHING_MORE; break; } - shost = lpfc_shost_from_vport(vport); if (vport->port_state < LPFC_DISC_AUTH) { if (!(phba->pport->fc_flag & FC_PT2PT) || (phba->pport->fc_flag & FC_PT2PT_PLOGI)) { |