Commit 2e1c49db4c640b35df13889b86b9d62215ade4b6

Authored by Zou Nan hai
Committed by Linus Torvalds
1 parent fa0aa866c8

x86_64: allocate sparsemem memmap above 4G

On systems with huge amount of physical memory, VFS cache and memory memmap
may eat all available system memory under 4G, then the system may fail to
allocate swiotlb bounce buffer.

There was a fix for this issue in arch/x86_64/mm/numa.c, but that fix dose
not cover sparsemem model.

This patch add fix to sparsemem model by first try to allocate memmap above
4G.

Signed-off-by: Zou Nan hai <nanhai.zou@intel.com>
Acked-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: Andi Kleen <ak@suse.de>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 3 changed files with 18 additions and 0 deletions Side-by-side Diff

arch/x86_64/mm/init.c
... ... @@ -761,4 +761,10 @@
761 761 {
762 762 return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END);
763 763 }
  764 +
  765 +void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
  766 +{
  767 + return __alloc_bootmem_core(pgdat->bdata, size,
  768 + SMP_CACHE_BYTES, (4UL*1024*1024*1024), 0);
  769 +}
include/linux/bootmem.h
... ... @@ -59,6 +59,7 @@
59 59 unsigned long align,
60 60 unsigned long goal,
61 61 unsigned long limit);
  62 +extern void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size);
62 63  
63 64 #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
64 65 extern void reserve_bootmem(unsigned long addr, unsigned long size);
... ... @@ -209,6 +209,12 @@
209 209 return 1;
210 210 }
211 211  
  212 +__attribute__((weak))
  213 +void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
  214 +{
  215 + return NULL;
  216 +}
  217 +
212 218 static struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
213 219 {
214 220 struct page *map;
... ... @@ -216,6 +222,11 @@
216 222 int nid = sparse_early_nid(ms);
217 223  
218 224 map = alloc_remap(nid, sizeof(struct page) * PAGES_PER_SECTION);
  225 + if (map)
  226 + return map;
  227 +
  228 + map = alloc_bootmem_high_node(NODE_DATA(nid),
  229 + sizeof(struct page) * PAGES_PER_SECTION);
219 230 if (map)
220 231 return map;
221 232