Commit 6d4831c2 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

vfs: avoid large kmalloc()s for the fdtable

Azurit reports large increases in system time after 2.6.36 when running
Apache.  It was bisected down to a892e2d7 ("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: default avatarazurIt <azurit@pobox.sk>
Tested-by: default avatarazurIt <azurit@pobox.sk>
Acked-by: default avatarChangli Gao <xiaosuo@gmail.com>
Cc: Americo Wang <xiyou.wangcong@gmail.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Acked-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: <stable@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent e8dad694
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/mmzone.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -39,14 +40,17 @@ int sysctl_nr_open_max = 1024 * 1024; /* raised later */ ...@@ -39,14 +40,17 @@ int sysctl_nr_open_max = 1024 * 1024; /* raised later */
*/ */
static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list); 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; /*
* Very large allocations can stress page reclaim, so fall back to
data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN); * vmalloc() if the allocation size will be considered "large" by the VM.
if (data != NULL) */
return data; if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN);
if (data != NULL)
return data;
}
return vmalloc(size); return vmalloc(size);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment