Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

scsi: lpfc: Fix leaked lpfc_dmabuf mbox allocations with NPIV

During rmmod testing, messages appeared indicating lpfc_mbuf_pool entries
were still busy. This situation was only seen doing rmmod after at least 1
vport (NPIV) instance was created and destroyed. The number of messages
scaled with the number of vports created.

When a vport is created, it can receive a PLOGI from another initiator
Nport. When this happens, the driver prepares to ack the PLOGI and
prepares an RPI for registration (via mbx cmd) which includes an mbuf
allocation. During the unsolicited PLOGI processing and after the RPI
preparation, the driver recognizes it is one of the vport instances and
decides to reject the PLOGI. During the LS_RJT preparation for the PLOGI,
the mailbox struct allocated for RPI registration is freed, but the mbuf
that was also allocated is not released.

Fix by freeing the mbuf with the mailbox struct in the LS_RJT path.

As part of the code review to figure the issue out a couple of other areas
where found that also would not have released the mbuf. Those are cleaned
up as well.

Link: https://lore.kernel.org/r/20211204002644.116455-2-jsmart2021@gmail.com
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>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

James Smart and committed by
Martin K. Petersen
f0d39196 eaab9b57

+17 -3
+5 -1
drivers/scsi/lpfc/lpfc_els.c
··· 6904 6904 lpfc_get_rdp_info(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context) 6905 6905 { 6906 6906 LPFC_MBOXQ_t *mbox = NULL; 6907 + struct lpfc_dmabuf *mp; 6907 6908 int rc; 6908 6909 6909 6910 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); ··· 6920 6919 mbox->mbox_cmpl = lpfc_mbx_cmpl_rdp_page_a0; 6921 6920 mbox->ctx_ndlp = (struct lpfc_rdp_context *)rdp_context; 6922 6921 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); 6923 - if (rc == MBX_NOT_FINISHED) 6922 + if (rc == MBX_NOT_FINISHED) { 6923 + mp = (struct lpfc_dmabuf *)mbox->ctx_buf; 6924 + lpfc_mbuf_free(phba, mp->virt, mp->phys); 6924 6925 goto issue_mbox_fail; 6926 + } 6925 6927 6926 6928 return 0; 6927 6929
+6 -2
drivers/scsi/lpfc/lpfc_init.c
··· 5373 5373 */ 5374 5374 if (!(phba->hba_flag & HBA_FCOE_MODE)) { 5375 5375 rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); 5376 - if (rc == MBX_NOT_FINISHED) 5376 + if (rc == MBX_NOT_FINISHED) { 5377 + lpfc_mbuf_free(phba, mp->virt, mp->phys); 5377 5378 goto out_free_dmabuf; 5379 + } 5378 5380 return; 5379 5381 } 5380 5382 /* ··· 6339 6337 } 6340 6338 6341 6339 rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); 6342 - if (rc == MBX_NOT_FINISHED) 6340 + if (rc == MBX_NOT_FINISHED) { 6341 + lpfc_mbuf_free(phba, mp->virt, mp->phys); 6343 6342 goto out_free_dmabuf; 6343 + } 6344 6344 return; 6345 6345 6346 6346 out_free_dmabuf:
+6
drivers/scsi/lpfc/lpfc_nportdisc.c
··· 322 322 { 323 323 struct lpfc_hba *phba = vport->phba; 324 324 struct lpfc_dmabuf *pcmd; 325 + struct lpfc_dmabuf *mp; 325 326 uint64_t nlp_portwwn = 0; 326 327 uint32_t *lp; 327 328 IOCB_t *icmd; ··· 572 571 * a default RPI. 573 572 */ 574 573 if (phba->sli_rev == LPFC_SLI_REV4) { 574 + mp = (struct lpfc_dmabuf *)login_mbox->ctx_buf; 575 + if (mp) { 576 + lpfc_mbuf_free(phba, mp->virt, mp->phys); 577 + kfree(mp); 578 + } 575 579 mempool_free(login_mbox, phba->mbox_mem_pool); 576 580 login_mbox = NULL; 577 581 } else {