On Sat, 2014-03-08 at 00:21 +0100, Maurizio Lombardi wrote:
> Hi Eddie,
> 
> On Fri, Mar 07, 2014 at 11:21:45AM -0800, Eddie Wai wrote:
> > Hello Maurizio,
> > 
> > Thanks for looking into this.  The patch looks good, but I would like to
> > extend it with the following allocation failure portion to completely
> > remove the memory leak.  Please incorporate this into your next
> > submission.
> 
> Thanks for the patch you sent,
> 
> maybe it is even better if I modify bnx2fc_allocate_hash_table() in such a way
> that, in case of error, it frees all the memory it has allocated.
> 
> Note that your patch does not free the table if
> "hba->hash_tbl_pbl = dma_alloc_coherent(...)" fails (line 2058).
> 
> It just requires a very little change to your patch, I'll send it tomorrow.
You're right, the hash_tbl_segments[i] entries will also need to be
freed upon the hash_tbl_pbl allocation failure.  Thanks again!
> 
> Regards,
> Maurizio Lombardi
> 
> > 
> > Thanks,
> > Eddie
> > 
> > @@ -2020,7 +2026,7 @@ static int bnx2fc_allocate_hash_table(struct
> > bnx2fc_hba *hba)
> >         dma_segment_array = kzalloc(dma_segment_array_size, GFP_KERNEL);
> >         if (!dma_segment_array) {
> >                 printk(KERN_ERR PFX "hash table pointers (dma) alloc
> > failed\n");
> > -               return -ENOMEM;
> > +               goto free_hash_tbl_seg;
> >         }
> > 
> >         for (i = 0; i < segment_count; ++i) {
> > @@ -2039,7 +2045,7 @@ static int bnx2fc_allocate_hash_table(struct
> > bnx2fc_hba *hba)
> >                                 hba->hash_tbl_segments[i] = NULL;
> >                         }
> >                         kfree(dma_segment_array);
> > -                       return -ENOMEM;
> > +                       goto free_hash_tbl_seg;
> >                 }
> >                 memset(hba->hash_tbl_segments[i], 0,
> >                        BNX2FC_HASH_TBL_CHUNK_SIZE);
> > @@ -2077,6 +2083,11 @@ static int bnx2fc_allocate_hash_table(struct
> > bnx2fc_hba *hba)
> >         }
> >         kfree(dma_segment_array);
> >         return 0;
> > +
> > +free_hash_tbl_seg:
> > +       kfree(hba->hash_tbl_segments);
> > +       hba->hash_tbl_segments = NULL;
> > +       return -ENOMEM;
> >  }
> > 
> > 
> > On Fri, 2014-03-07 at 15:37 +0100, Maurizio Lombardi wrote:
> > > If bnx2fc_allocate_hash_table() for some reasons fails, it is possible 
> > > that the
> > > hash_tbl_segments or the hash_tbl_pbl pointers are NULL.
> > > In this case bnx2fc_free_hash_table() will panic the system.
> > > 
> > > this patch also fixes a memory leak, the hash_tbl_segments pointer was 
> > > never
> > > freed.
> > > 
> > > Signed-off-by: Maurizio Lombardi <[email protected]>
> > > ---
> > >  drivers/scsi/bnx2fc/bnx2fc_hwi.c | 34 ++++++++++++++++++++--------------
> > >  1 file changed, 20 insertions(+), 14 deletions(-)
> > > 
> > > diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c 
> > > b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
> > > index 261af2a..f83bae4 100644
> > > --- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
> > > +++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
> > > @@ -1968,21 +1968,27 @@ static void bnx2fc_free_hash_table(struct 
> > > bnx2fc_hba *hba)
> > >   int segment_count;
> > >   u32 *pbl;
> > >  
> > > - segment_count = hba->hash_tbl_segment_count;
> > > -
> > > - pbl = hba->hash_tbl_pbl;
> > > - for (i = 0; i < segment_count; ++i) {
> > > -         dma_addr_t dma_address;
> > > -
> > > -         dma_address = le32_to_cpu(*pbl);
> > > -         ++pbl;
> > > -         dma_address += ((u64)le32_to_cpu(*pbl)) << 32;
> > > -         ++pbl;
> > > -         dma_free_coherent(&hba->pcidev->dev,
> > > -                           BNX2FC_HASH_TBL_CHUNK_SIZE,
> > > -                           hba->hash_tbl_segments[i],
> > > -                           dma_address);
> > > + if (hba->hash_tbl_segments) {
> > > +
> > > +         pbl = hba->hash_tbl_pbl;
> > > +         if (pbl) {
> > > +                 segment_count = hba->hash_tbl_segment_count;
> > > +                 for (i = 0; i < segment_count; ++i) {
> > > +                         dma_addr_t dma_address;
> > > +
> > > +                         dma_address = le32_to_cpu(*pbl);
> > > +                         ++pbl;
> > > +                         dma_address += ((u64)le32_to_cpu(*pbl)) << 32;
> > > +                         ++pbl;
> > > +                         dma_free_coherent(&hba->pcidev->dev,
> > > +                                           BNX2FC_HASH_TBL_CHUNK_SIZE,
> > > +                                           hba->hash_tbl_segments[i],
> > > +                                           dma_address);
> > > +                 }
> > > +         }
> > >  
> > > +         kfree(hba->hash_tbl_segments);
> > > +         hba->hash_tbl_segments = NULL;
> > >   }
> > >  
> > >   if (hba->hash_tbl_pbl) {
> > 
> > 


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

Reply via email to