Hi Liang, @@ -1200,6 +1200,11 @@ lpfc_bsg_hba_set_event(struct bsg_job *job) spin_unlock_irqrestore(&phba->ct_ev_lock, flags); if (&evt->node == &phba->ct_ev_waiters) { + + spin_lock_irqsave(&phba->ct_ev_lock, flags); + lpfc_bsg_event_unref(evt); + spin_unlock_irqrestore(&phba->ct_ev_lock, flags); + /* no event waiting struct yet - first call */ dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); if (dd_data == NULL) { if (&evt->node == &phba->ct_ev_waiters) was true, then that means the ct_ev_waiters list was empty so the *evt ptr is not pointing to a real lpfc_bsg_event structure. I think we would even crash trying to decrement evt’s kref because evt is an uninitialized lpfc_bsg_event structure and not pointing to anything real. We’re about to kzalloc a new evt with lpfc_bsg_event_new in this same if statement clause anyways. I’m not clear on the reasoning behind the suggestion to call lpfc_bsg_event_unref(evt) there. @@ -1292,6 +1297,9 @@ lpfc_bsg_hba_get_event(struct bsg_job *job) * an error indicating that there isn't anymore */ if (evt_dat == NULL) { + spin_lock_irqsave(&phba->ct_ev_lock, flags); + lpfc_bsg_event_unref(evt); + spin_unlock_irqrestore(&phba->ct_ev_lock, flags); bsg_reply->reply_payload_rcv_len = 0; rc = -ENOENT; goto job_error; Similar argument here. If (evt_dat == NULL) was true, then that means there was nothing of interest in the ct_ev_waiters list or that the ct_ev_waiters list was empty. In either case, we shouldn’t call lpfc_bsg_event_unref(evt) because we would be decrementing the wrong reg_id evt’s kref or even crash if the ct_ev_waiters list was empty trying to kref_put an uninitialized lpfc_bsg_event structure. Regards, Justin On Thu, Mar 16, 2023 at 7:02 PM Liang He <windhl@xxxxxxx> wrote: > > In lpfc_bsg_hba_get_event() and lpfc_bsg_hba_set_event(), we > should keep the refcount balance when there is some error or > the *evt* will be replaced. > > Fixes: f1c3b0fcbb81 ("[SCSI] lpfc 8.3.4: Add bsg (SGIOv4) support for ELS/CT support") > Signed-off-by: Liang He <windhl@xxxxxxx> > --- > drivers/scsi/lpfc/lpfc_bsg.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > > diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c > index 852b025e2fec..aa535bc14758 100644 > --- a/drivers/scsi/lpfc/lpfc_bsg.c > +++ b/drivers/scsi/lpfc/lpfc_bsg.c > @@ -1200,6 +1200,11 @@ lpfc_bsg_hba_set_event(struct bsg_job *job) > spin_unlock_irqrestore(&phba->ct_ev_lock, flags); > > if (&evt->node == &phba->ct_ev_waiters) { > + > + spin_lock_irqsave(&phba->ct_ev_lock, flags); > + lpfc_bsg_event_unref(evt); > + spin_unlock_irqrestore(&phba->ct_ev_lock, flags); > + > /* no event waiting struct yet - first call */ > dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); > if (dd_data == NULL) { > @@ -1292,6 +1297,9 @@ lpfc_bsg_hba_get_event(struct bsg_job *job) > * an error indicating that there isn't anymore > */ > if (evt_dat == NULL) { > + spin_lock_irqsave(&phba->ct_ev_lock, flags); > + lpfc_bsg_event_unref(evt); > + spin_unlock_irqrestore(&phba->ct_ev_lock, flags); > bsg_reply->reply_payload_rcv_len = 0; > rc = -ENOENT; > goto job_error; > -- > 2.25.1 >