From 44ec21716abc5e7ebe50044bb7f90001e84a8d69 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Wed, 11 Jul 2012 14:02:53 -0700 Subject: [PATCH] --- yaml --- r: 311842 b: refs/heads/master c: 99ab7b19440a72ebdf225f99b20f8ef40decee86 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/linux/bootmem.h | 5 +++++ trunk/mm/bootmem.c | 2 +- trunk/mm/nobootmem.c | 2 +- trunk/mm/sparse.c | 18 +++++++++++++----- 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/[refs] b/[refs] index 0c217310d2aa..56693f757339 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 07b4e2bc9c35ea88cbd36d806fcd5e3bcbf022be +refs/heads/master: 99ab7b19440a72ebdf225f99b20f8ef40decee86 diff --git a/trunk/include/linux/bootmem.h b/trunk/include/linux/bootmem.h index 324fe08ea3b1..6d6795d46a75 100644 --- a/trunk/include/linux/bootmem.h +++ b/trunk/include/linux/bootmem.h @@ -91,6 +91,11 @@ extern void *__alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal); +void *___alloc_bootmem_node_nopanic(pg_data_t *pgdat, + unsigned long size, + unsigned long align, + unsigned long goal, + unsigned long limit); extern void *__alloc_bootmem_low(unsigned long size, unsigned long align, unsigned long goal); diff --git a/trunk/mm/bootmem.c b/trunk/mm/bootmem.c index ec4fcb7a56c8..73096630cb35 100644 --- a/trunk/mm/bootmem.c +++ b/trunk/mm/bootmem.c @@ -698,7 +698,7 @@ void * __init __alloc_bootmem(unsigned long size, unsigned long align, return ___alloc_bootmem(size, align, goal, limit); } -static void * __init ___alloc_bootmem_node_nopanic(pg_data_t *pgdat, +void * __init ___alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal, unsigned long limit) { diff --git a/trunk/mm/nobootmem.c b/trunk/mm/nobootmem.c index d23415c001bc..0900b3910cda 100644 --- a/trunk/mm/nobootmem.c +++ b/trunk/mm/nobootmem.c @@ -274,7 +274,7 @@ void * __init __alloc_bootmem(unsigned long size, unsigned long align, return ___alloc_bootmem(size, align, goal, limit); } -static void * __init ___alloc_bootmem_node_nopanic(pg_data_t *pgdat, +void * __init ___alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal, diff --git a/trunk/mm/sparse.c b/trunk/mm/sparse.c index e861397016a9..c7bb952400c8 100644 --- a/trunk/mm/sparse.c +++ b/trunk/mm/sparse.c @@ -275,8 +275,9 @@ static unsigned long * __init sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat, unsigned long size) { - pg_data_t *host_pgdat; - unsigned long goal; + unsigned long goal, limit; + unsigned long *p; + int nid; /* * A page may contain usemaps for other sections preventing the * page being freed and making a section unremovable while @@ -288,9 +289,16 @@ sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat, * this problem. */ goal = __pa(pgdat) & (PAGE_SECTION_MASK << PAGE_SHIFT); - host_pgdat = NODE_DATA(early_pfn_to_nid(goal >> PAGE_SHIFT)); - return __alloc_bootmem_node_nopanic(host_pgdat, size, - SMP_CACHE_BYTES, goal); + limit = goal + (1UL << PA_SECTION_SHIFT); + nid = early_pfn_to_nid(goal >> PAGE_SHIFT); +again: + p = ___alloc_bootmem_node_nopanic(NODE_DATA(nid), size, + SMP_CACHE_BYTES, goal, limit); + if (!p && limit) { + limit = 0; + goto again; + } + return p; } static void __init check_usemap_section_nr(int nid, unsigned long *usemap)