Add a new gfp flag
__GFP_VFALLBACK
If specified during a higher order allocation then the system will fall
back to vmap if no physically contiguous pages can be found. This will
create a virtually contiguous area instead of a physically contiguous area.
In many cases the virtually contiguous area can stand in for the physically
contiguous area (with some loss of performance).
Signed-off-by: Christoph Lameter <clameter@sgi.com>
---
include/linux/gfp.h | 5 +
mm/page_alloc.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 139 insertions(+), 5 deletions(-)
Index: linux-2.6/mm/page_alloc.c
===================================================================
--- linux-2.6.orig/mm/page_alloc.c 2007-10-03 19:44:07.000000000 -0700
+++ linux-2.6/mm/page_alloc.c 2007-10-03 19:44:08.000000000 -0700
@@ -60,6 +60,9 @@ long nr_swap_pages;
int percpu_pagelist_fraction;
static void __free_pages_ok(struct page *page, unsigned int order);
+static struct page *alloc_vcompound(gfp_t, int,
+ struct zonelist *, unsigned long);
+static void destroy_compound_page(struct page *page, unsigned long order);
/*
* results with 256, 32 in the lowmem_reserve sysctl:
@@ -260,9 +263,51 @@ static void bad_page(struct page *page)
* This usage means that zero-order pages may not be compound.
*/
+static void __free_vcompound(void *addr)
+{
+ struct page **pages;
+ int i;
+ struct page *page = vmalloc_to_page(addr);
+ int order = compound_order(page);
+ int nr_pages = 1 << order;
+
+ if (!PageVcompound(page) || !PageHead(page)) {
+ bad_page(page);
+ return;
+ }
+ destroy_compound_page(page, order);
+ pages = vunmap(addr);
+ /*
+ * First page will have zero refcount since it maintains state
+ * for the compound and was decremented before we got here.
+ */
+ set_page_address(page, NULL);
+ __ClearPageVcompound(page);
+ free_hot_page(page);
+
+ for (i = 1; i < nr_pages; i++) {
+ page = pages[i];
+ set_page_address(page, ...