lkml.org 
[lkml]   [2011]   [Apr]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: Regression from 2.6.36
    On Wed, 13 Apr 2011, Andrew Morton wrote:

    > Azurit reports large increases in system time after 2.6.36 when running
    > Apache. It was bisected down to a892e2d7dcdfa6c76e6 ("vfs: use kmalloc()
    > to allocate fdmem if possible").
    >
    > That patch caused the vfs to use kmalloc() for very large allocations and
    > this is causing excessive work (and presumably excessive reclaim) within
    > the page allocator.
    >
    > Fix it by falling back to vmalloc() earlier - when the allocation attempt
    > would have been considered "costly" by reclaim.
    >
    > Reported-by: azurIt <azurit@pobox.sk>
    > Cc: Changli Gao <xiaosuo@gmail.com>
    > Cc: Americo Wang <xiyou.wangcong@gmail.com>
    > Cc: Jiri Slaby <jslaby@suse.cz>
    > Cc: Eric Dumazet <eric.dumazet@gmail.com>
    > Cc: Mel Gorman <mel@csn.ul.ie>
    > Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    > ---
    >
    > fs/file.c | 17 ++++++++++-------
    > 1 file changed, 10 insertions(+), 7 deletions(-)
    >
    > diff -puN fs/file.c~a fs/file.c
    > --- a/fs/file.c~a
    > +++ a/fs/file.c
    > @@ -39,14 +39,17 @@ int sysctl_nr_open_max = 1024 * 1024; /*
    > */
    > static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list);
    >
    > -static inline void *alloc_fdmem(unsigned int size)
    > +static void *alloc_fdmem(unsigned int size)
    > {
    > - void *data;
    > -
    > - data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN);
    > - if (data != NULL)
    > - return data;
    > -
    > + /*
    > + * Very large allocations can stress page reclaim, so fall back to
    > + * vmalloc() if the allocation size will be considered "large" by the VM.
    > + */
    > + if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER) {
    > + void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN);
    > + if (data != NULL)
    > + return data;
    > + }
    > return vmalloc(size);
    > }
    >

    It's a shame that we can't at least try kmalloc() with sufficiently large
    sizes by doing something like

    gfp_t flags = GFP_NOWAIT | __GFP_NOWARN;

    if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER))
    flags |= GFP_KERNEL;
    data = kmalloc(size, flags);
    if (data)
    return data;
    return vmalloc(size);

    which would at least attempt to use the slab allocator.


    \
     
     \ /
      Last update: 2011-04-13 23:47    [W:4.021 / U:53.172 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site