diff options
author | Mel Gorman <mgorman@suse.de> | 2015-08-06 18:46:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-08-06 21:39:40 -0400 |
commit | 7ace99170789bc53cbb7e9e352d7a3851208fbcf (patch) | |
tree | 8563a1e739a73bf29bf93154b88ac7ef52209d1c /mm/page_alloc.c | |
parent | de54b9ac253787c366bbfb28d901a31954eb3511 (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.c | 16 |
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 | |
985 | static struct mminit_pfnnid_cache early_pfnnid_cache __meminitdata; | 985 | static struct mminit_pfnnid_cache early_pfnnid_cache __meminitdata; |
986 | 986 | ||
987 | int __meminit early_pfn_to_nid(unsigned long pfn) | 987 | int __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 | ||