From: Johannes Weiner Date: Mon, 29 Apr 2013 22:07:56 +0000 (-0700) Subject: x86-64: fall back to regular page vmemmap on allocation failure X-Git-Tag: upstream/snapshot3+hdmi~5281^2~47 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8e2cdbcb86b0abefc3d07922c48edb01fece3c56;p=platform%2Fadaptation%2Frenesas_rcar%2Frenesas_kernel.git x86-64: fall back to regular page vmemmap on allocation failure Memory hotplug can happen on a machine under load, memory shortness and fragmentation, so huge page allocations for the vmemmap are not guaranteed to succeed. Try to fall back to regular pages before failing the hotplug event completely. Signed-off-by: Johannes Weiner Cc: Ben Hutchings Cc: Bernhard Schmidt Cc: Johannes Weiner Cc: Russell King Cc: Ingo Molnar Cc: Thomas Gleixner Cc: "H. Peter Anvin" Cc: Benjamin Herrenschmidt Cc: "Luck, Tony" Cc: Heiko Carstens Cc: David Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 9f6347c..71ff55a 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -1303,31 +1303,37 @@ static int __meminit vmemmap_populate_hugepages(unsigned long start, pmd = pmd_offset(pud, addr); if (pmd_none(*pmd)) { - pte_t entry; void *p; p = vmemmap_alloc_block_buf(PMD_SIZE, node); - if (!p) - return -ENOMEM; - - entry = pfn_pte(__pa(p) >> PAGE_SHIFT, - PAGE_KERNEL_LARGE); - set_pmd(pmd, __pmd(pte_val(entry))); - - /* check to see if we have contiguous blocks */ - if (p_end != p || node_start != node) { - if (p_start) - printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n", - addr_start, addr_end-1, p_start, p_end-1, node_start); - addr_start = addr; - node_start = node; - p_start = p; - } + if (p) { + pte_t entry; + + entry = pfn_pte(__pa(p) >> PAGE_SHIFT, + PAGE_KERNEL_LARGE); + set_pmd(pmd, __pmd(pte_val(entry))); + + /* check to see if we have contiguous blocks */ + if (p_end != p || node_start != node) { + if (p_start) + printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n", + addr_start, addr_end-1, p_start, p_end-1, node_start); + addr_start = addr; + node_start = node; + p_start = p; + } - addr_end = addr + PMD_SIZE; - p_end = p + PMD_SIZE; - } else + addr_end = addr + PMD_SIZE; + p_end = p + PMD_SIZE; + continue; + } + } else if (pmd_large(*pmd)) { vmemmap_verify((pte_t *)pmd, node, addr, next); + continue; + } + pr_warn_once("vmemmap: falling back to regular page backing\n"); + if (vmemmap_populate_basepages(addr, next, node)) + return -ENOMEM; } return 0; }