aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSrikar Dronamraju <[email protected]>2016-10-07 16:59:15 -0700
committerLinus Torvalds <[email protected]>2016-10-07 18:46:28 -0700
commitf6f34b4387d9e18304451a131b35d7c4f27a0b5a (patch)
treeb5098f74ab735fbac404c4acab5d6c5cd2fe54e4
parentc9634cf012321243ee8e4ea0fb0709904cd58395 (diff)
mm: introduce arch_reserved_kernel_pages()
Currently arch specific code can reserve memory blocks but alloc_large_system_hash() may not take it into consideration when sizing the hashes. This can lead to bigger hash than required and lead to no available memory for other purposes. This is specifically true for systems with CONFIG_DEFERRED_STRUCT_PAGE_INIT enabled. One approach to solve this problem would be to walk through the memblock regions and calculate the available memory and base the size of hash system on the available memory. The other approach would be to depend on the architecture to provide the number of pages that are reserved. This change provides hooks to allow the architecture to provide the required info. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Srikar Dronamraju <[email protected]> Suggested-by: Mel Gorman <[email protected]> Cc: Vlastimil Babka <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Michael Ellerman <[email protected]> Cc: Mahesh Salgaonkar <[email protected]> Cc: Hari Bathini <[email protected]> Cc: Dave Hansen <[email protected]> Cc: Balbir Singh <[email protected]> Cc: Benjamin Herrenschmidt <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
-rw-r--r--include/linux/mm.h3
-rw-r--r--mm/page_alloc.c12
2 files changed, 15 insertions, 0 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 0a063b4e4456..046077b4209d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1924,6 +1924,9 @@ extern void show_mem(unsigned int flags);
extern long si_mem_available(void);
extern void si_meminfo(struct sysinfo * val);
extern void si_meminfo_node(struct sysinfo *val, int nid);
+#ifdef __HAVE_ARCH_RESERVED_KERNEL_PAGES
+extern unsigned long arch_reserved_kernel_pages(void);
+#endif
extern __printf(3, 4)
void warn_alloc_failed(gfp_t gfp_mask, unsigned int order,
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index f6a5a221496a..e00f545c2398 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -6940,6 +6940,17 @@ static int __init set_hashdist(char *str)
__setup("hashdist=", set_hashdist);
#endif
+#ifndef __HAVE_ARCH_RESERVED_KERNEL_PAGES
+/*
+ * Returns the number of pages that arch has reserved but
+ * is not known to alloc_large_system_hash().
+ */
+static unsigned long __init arch_reserved_kernel_pages(void)
+{
+ return 0;
+}
+#endif
+
/*
* allocate a large system hash table from bootmem
* - it is assumed that the hash table must contain an exact power-of-2
@@ -6964,6 +6975,7 @@ void *__init alloc_large_system_hash(const char *tablename,
if (!numentries) {
/* round applicable memory size up to nearest megabyte */
numentries = nr_kernel_pages;
+ numentries -= arch_reserved_kernel_pages();
/* It isn't necessary when PAGE_SIZE >= 1MB */
if (PAGE_SHIFT < 20)