Skip to content
Permalink
Browse files
lpfc: Fix reference counting errors in lpfc_cmpl_els_rsp()
Call traces are being seen that result from a nodelist structure ref
counting error. They are typically seen after transmission of an LS_RJT
ELS response.

Aged code in lpfc_cmpl_els_rsp() calls lpfc_nlp_not_used() which, if the
ndlp reference count is exactly 1, will decrement the reference count.
Previously lpfc_nlp_put() was within lpfc_els_free_iocb, and the 'put'
within the free would only be invoked if cmdiocb->context1 was not NULL.
Since the nodelist structure reference count is decremented when exiting
lpfc_cmpl_els_rsp() the lpfc_nlp_not_used() calls are no longer required.
Calling them is causing the reference count issue.

Fix by removing the lpfc_nlp_not_used() calls

Co-developed-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
  • Loading branch information
jsmart-gh authored and intel-lab-lkp committed Apr 10, 2021
1 parent 98179e8 commit 14cc4aacd0b5890c9db3ce319c67b956520a2aa7
Showing 1 changed file with 1 addition and 49 deletions.
@@ -4444,10 +4444,7 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
* nlp_flag bitmap in the ndlp data structure, if the mbox command reference
* field in the command IOCB is not NULL, the referred mailbox command will
* be send out, and then invokes the lpfc_els_free_iocb() routine to release
* the IOCB. Under error conditions, such as when a LS_RJT is returned or a
* link down event occurred during the discovery, the lpfc_nlp_not_used()
* routine shall be invoked trying to release the ndlp if no other threads
* are currently referring it.
* the IOCB.
**/
static void
lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
@@ -4494,15 +4491,6 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
mempool_free(mbox, phba->mbox_mem_pool);
}
if (ndlp && (ndlp->nlp_flag & NLP_RM_DFLT_RPI))
if (lpfc_nlp_not_used(ndlp)) {
ndlp = NULL;
/* Indicate the node has already released,
* should not reference to it from within
* the routine lpfc_els_free_iocb.
*/
cmdiocb->context1 = NULL;
}
goto out;
}

@@ -4580,29 +4568,6 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
"Data: x%x x%x x%x\n",
ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
ndlp->nlp_rpi);

if (lpfc_nlp_not_used(ndlp)) {
ndlp = NULL;
/* Indicate node has already been released,
* should not reference to it from within
* the routine lpfc_els_free_iocb.
*/
cmdiocb->context1 = NULL;
}
} else {
/* Do not drop node for lpfc_els_abort'ed ELS cmds */
if (!lpfc_error_lost_link(irsp) &&
ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
if (lpfc_nlp_not_used(ndlp)) {
ndlp = NULL;
/* Indicate node has already been
* released, should not reference
* to it from within the routine
* lpfc_els_free_iocb.
*/
cmdiocb->context1 = NULL;
}
}
}
mp = (struct lpfc_dmabuf *)mbox->ctx_buf;
if (mp) {
@@ -4618,19 +4583,6 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN;
ndlp->nlp_flag &= ~NLP_RM_DFLT_RPI;
spin_unlock_irq(&ndlp->lock);

/* If the node is not being used by another discovery thread,
* and we are sending a reject, we are done with it.
* Release driver reference count here and free associated
* resources.
*/
if (ls_rjt)
if (lpfc_nlp_not_used(ndlp))
/* Indicate node has already been released,
* should not reference to it from within
* the routine lpfc_els_free_iocb.
*/
cmdiocb->context1 = NULL;
}

/* Release the originating I/O reference. */

0 comments on commit 14cc4aa

Please sign in to comment.