summaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorMel Gorman <mgorman@suse.de>2015-08-06 18:46:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-08-06 21:39:40 -0400
commit7ace99170789bc53cbb7e9e352d7a3851208fbcf (patch)
tree8563a1e739a73bf29bf93154b88ac7ef52209d1c /mm/page_alloc.c
parentde54b9ac253787c366bbfb28d901a31954eb3511 (diff)
mm, meminit: allow early_pfn_to_nid to be used during runtime
early_pfn_to_nid() historically was inherently not SMP safe but only used during boot which is inherently single threaded or during hotplug which is protected by a giant mutex. With deferred memory initialisation there was a thread-safe version introduced and the early_pfn_to_nid would trigger a BUG_ON if used unsafely. Memory hotplug hit that check. This patch makes early_pfn_to_nid introduces a lock to make it safe to use during hotplug. Signed-off-by: Mel Gorman <mgorman@suse.de> Reported-by: Alex Ng <alexng@microsoft.com> Tested-by: Alex Ng <alexng@microsoft.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Nicolai Stange <nicstange@gmail.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Fengguang Wu <fengguang.wu@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index ef19f22b2b7d..ea0e6a6e7a11 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -981,21 +981,21 @@ static void __init __free_pages_boot_core(struct page *page,
981 981
982#if defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) || \ 982#if defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) || \
983 defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) 983 defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP)
984/* Only safe to use early in boot when initialisation is single-threaded */ 984
985static struct mminit_pfnnid_cache early_pfnnid_cache __meminitdata; 985static struct mminit_pfnnid_cache early_pfnnid_cache __meminitdata;
986 986
987int __meminit early_pfn_to_nid(unsigned long pfn) 987int __meminit early_pfn_to_nid(unsigned long pfn)
988{ 988{
989 static DEFINE_SPINLOCK(early_pfn_lock);
989 int nid; 990 int nid;
990 991
991 /* The system will behave unpredictably otherwise */ 992 spin_lock(&early_pfn_lock);
992 BUG_ON(system_state != SYSTEM_BOOTING);
993
994 nid = __early_pfn_to_nid(pfn, &early_pfnnid_cache); 993 nid = __early_pfn_to_nid(pfn, &early_pfnnid_cache);
995 if (nid >= 0) 994 if (nid < 0)
996 return nid; 995 nid = 0;
997 /* just returns 0 */ 996 spin_unlock(&early_pfn_lock);
998 return 0; 997
998 return nid;
999} 999}
1000#endif 1000#endif
1001 1001