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: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: James Smart <jsmart2021@gmail.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Родитель
32b9386564
Коммит
4767c58af9
|
@ -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);
|
||||
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 = 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);
|
||||
} 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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче