Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4767c58a authored by James Smart's avatar James Smart Committed by Martin K. Petersen
Browse files

scsi: lpfc: Correct nvmet buffer free race condition



A race condition resulted in receive buffers being placed in the free list
twice.

Change the locking and handling to check whether the "other" path will be
freeing the entry in a later thread and skip it if it is.

Signed-off-by: default avatarDick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 32b93865
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -343,16 +343,23 @@ lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctx_buf)
	}

	if (ctxp->rqb_buffer) {
		nvmebuf = ctxp->rqb_buffer;
		spin_lock_irqsave(&ctxp->ctxlock, iflag);
		nvmebuf = ctxp->rqb_buffer;
		/* check if freed in another path whilst acquiring lock */
		if (nvmebuf) {
			ctxp->rqb_buffer = NULL;
			if (ctxp->flag & LPFC_NVMET_CTX_REUSE_WQ) {
				ctxp->flag &= ~LPFC_NVMET_CTX_REUSE_WQ;
				spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
			nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf);
				nvmebuf->hrq->rqbp->rqb_free_buffer(phba,
								    nvmebuf);
			} else {
				spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
				/* repost */
				lpfc_rq_buf_free(phba, &nvmebuf->hbuf);
			}
		} else {
			spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
			lpfc_rq_buf_free(phba, &nvmebuf->hbuf); /* repost */
		}
	}
	ctxp->state = LPFC_NVMET_STE_FREE;