Re: [PATCH] fusion-mptbase: handle failed allocation for workqueue

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2016-02-16 at 13:33 -0500, Insu Yun wrote:
> 
> 
> On Tue, Feb 16, 2016 at 1:18 PM, Ewan Milne <emilne@xxxxxxxxxx> wrote:
>         On Mon, 2016-02-15 at 21:50 -0500, Insu Yun wrote:
>         > the failure of ioc->reset_work_q is checked,
>         > but not ioc->fw_event_q.
>         >
>         > Signed-off-by: Insu Yun <wuninsu@xxxxxxxxx>
>         > ---
>         >  drivers/message/fusion/mptbase.c | 7 +++++++
>         >  1 file changed, 7 insertions(+)
>         >
>         > diff --git a/drivers/message/fusion/mptbase.c
>         b/drivers/message/fusion/mptbase.c
>         > index 5dcc031..d4907a1 100644
>         > --- a/drivers/message/fusion/mptbase.c
>         > +++ b/drivers/message/fusion/mptbase.c
>         > @@ -1996,6 +1996,13 @@ mpt_attach(struct pci_dev *pdev,
>         const struct pci_device_id *id)
>         >       snprintf(ioc->fw_event_q_name, MPT_KOBJ_NAME_LEN,
>         "mpt/%d", ioc->id);
>         >       ioc->fw_event_q =
>         create_singlethread_workqueue(ioc->fw_event_q_name);
>         >
>         > +     if (!ioc->fw_event_q) {
>         > +             destroy_workqueue(ioc->reset_work_q);
>         > +             pci_release_selected_regions(pdev, ioc->bars);
>         > +             kfree(ioc);
>         > +             return -ENOMEM;
>         > +     }
>         > +
>         >       if ((r = mpt_do_ioc_recovery(ioc,
>         MPT_HOSTEVENT_IOC_BRINGUP,
>         >           CAN_SLEEP)) != 0){
>         >               printk(MYIOC_s_ERR_FMT "didn't initialize
>         properly! (%d)\n",
>         
>         This does not look correct to me.  The error path for the call
>         to
>         mpt_do_ioc_recovery() after create_singlethread_workqueue()
>         for
>         ioc->fw_event_q does other cleanup, including:
>         
>                         list_del(&ioc->list);
>                         if (ioc->alt_ioc)
>                                 ioc->alt_ioc->alt_ioc = NULL;
>                         iounmap(ioc->memmap);
>         
>         and
>         
>                         kfree(ioc);
>                         pci_set_drvdata(pdev, NULL);
> 
> 
> Oh yes. Right. 
> I just copied from above error handling code.
> 
> 
>  
>         
>         Here I think you are kfree()ing ioc while it is still on the
>         &ioc_list,
>         which will cause a crash.
>         
>         Note to Avago:  this code could use a symbolic return code
>         identifier:
>         
>                         if (r != -5)
>                                 pci_release_selected_regions(pdev,
>         ioc->bars);
> 
> 
> What is -5? it seems strange for me.
> 
> Is it error code? then it is better to use macro.

The comments above mpt_do_ioc_recovery() say:

 *      Returns:                                                                                                                                                                                                   
 *               0 for success                                                                                                                                                                                     
 *              -1 if failed to get board READY                                                                                                                                                                    
 *              -2 if READY but IOCFacts Failed                                                                                                                                                                    
 *              -3 if READY but PrimeIOCFifos Failed                                                                                                                                                               
 *              -4 if READY but IOCInit Failed                                                                                                                                                                     
 *              -5 if failed to enable_device and/or request_selected_regions                                                                                                                                      
 *              -6 if failed to upload firmware

and yes, it would be better to use a macro (symbolic value) hence my
comment to Avago.                                                                                                                                                      
> 
> 
>         
>         In general, with sequential allocation of resources like this,
>         error
>         handling can be performed using a series of goto's to labels
>         at the
>         end of the function that release the resources in reverse
>         order.  This
>         avoids the duplication of code within the function, and
>         reduces the
>         chance for errors when the function is later modified.  See
>         init_sd
>         in drivers/scsi/sd.c for an example.
>         
>         Reviewed-by: Ewan D. Milne <emilne@xxxxxxxxxx>
>         
>         
> 
> 
> Then in summary, after failing allocation, I need to call
> 
> 
> list_del(&ioc->list);
> if (ioc->alt_ioc)
>   ioc->alt_ioc->alt_ioc = NULL;
> iounmap(ioc->memmap);
> kfree(ioc);
> pci_set_drvdata(pdev, NULL);
> 
> 
> right?

I think you also need this:

                if (r != -5)
                        pci_release_selected_regions(pdev, ioc->bars);

                destroy_workqueue(ioc->reset_work_q);
                ioc->reset_work_q = NULL;

prior to your kfree(ioc) call.

Alternatively it looks like the code to create the ioc->fw_event_q could
be moved up to be right after the code to create the ioc->reset_work_q,
that might simplify the code a little bit as the ioc has not been added
to the &ioc_list and pci_set_drvdata() has not yet been called.

Note however that a failed call to mpt_do_ioc_recovery() still needs to
perform all the recovery actions, including destroying both work queues,
so consider putting the error handling code at the end of the function
as I mentioned above.  Otherwise, you should add:

                destroy_workqueue(ioc->fw_event_q);
                ioc->fw_event_q = NULL;

prior to the call to destroy_workqueue(ioc->reset_work_q) in that path.

-Ewan

> 
> 
> -- 
> Regards
> Insu Yun


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux