Re: Rare memory leakage

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

 



On Tue, Sep 22, 2020 at 02:12:19PM +0100, Matthew Wilcox wrote:
> On Tue, Sep 22, 2020 at 12:44:51PM +0100, Matthew Wilcox wrote:
> > I've just kicked off a test run using this:
> > 
> > +/*
> > + * Have to be careful when freeing a non-compound allocation in case somebody
> > + * else takes a temporary reference on the first page and then calls put_page()
> > + */
> >  void __free_pages(struct page *page, unsigned int order)
> >  {
> > -       if (put_page_testzero(page))
> > -               free_the_page(page, order);
> > +       if (likely(page_ref_freeze(page, 1)))
> > +               goto free;
> > +       if (likely(order == 0 || PageHead(page))) {
> > +               if (put_page_testzero(page))
> > +                       goto free;
> > +               return;
> > +       }
> > +
> > +       prep_compound_page(page, order);
> > +       put_page(page);
> > +       return;
> > +free:
> > +       free_the_page(page, order);
> >  }
> >  EXPORT_SYMBOL(__free_pages);
> > 
> > > > Better ideas?
> > > 
> > > IMHO, alloc_pages() with order > 0 and without __GFP_COMP is a weird beast. In
> > > that case it would be probably best to refcount each base page separately. I
> > > don't know how many assumptions this would break :/
> > 
> > You sound like a man who's never dealt with device drivers.  Multiorder,
> > non-compound allocations are the norm in that world.
> 
> This seems easier to reason about:
> 
> +/*
> + * If we free a non-compound allocation, another thread may have a
> + * transient reference to the first page.  It has no way of knowing
> + * about the rest of the allocation, so we have to free all but the
> + * first page here.
> + */
>  void __free_pages(struct page *page, unsigned int order)
>  {
>         if (put_page_testzero(page))
>                 free_the_page(page, order);
> +       else
> +               while (order-- > 0)
> +                       free_the_page(page + 1 << order, order);
>  }
>  EXPORT_SYMBOL(__free_pages);

To be honest, I have not dealt with device drivers much myself, but this
looks bogus. We free pages beynd the first one if the first is pinned.
How is it correct?

-- 
 Kirill A. Shutemov




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux