From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1945958AbbGQMWQ (ORCPT ); Fri, 17 Jul 2015 08:22:16 -0400 Received: from cantor2.suse.de ([195.135.220.15]:52552 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1945919AbbGQMWN (ORCPT ); Fri, 17 Jul 2015 08:22:13 -0400 From: Mel Gorman To: Andrew Morton Cc: Nicolai Stange , Peter Zijlstra , Dave Hansen , Alex Ng , Fengguang Wu , Linux-MM , LKML , Mel Gorman Subject: [PATCH 3/3] mm, meminit: Allow early_pfn_to_nid to be used during runtime Date: Fri, 17 Jul 2015 13:22:04 +0100 Message-Id: <1437135724-20110-4-git-send-email-mgorman@suse.de> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1437135724-20110-1-git-send-email-mgorman@suse.de> References: <1437135724-20110-1-git-send-email-mgorman@suse.de> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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. Reported-and-tested-by: Alex Ng Signed-off-by: Mel Gorman --- mm/page_alloc.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 94e2599830c2..f1e841c67b7a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -982,21 +982,26 @@ static void __init __free_pages_boot_core(struct page *page, #if defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) || \ defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) -/* Only safe to use early in boot when initialisation is single-threaded */ + static struct mminit_pfnnid_cache early_pfnnid_cache __meminitdata; int __meminit early_pfn_to_nid(unsigned long pfn) { + static DEFINE_SPINLOCK(early_pfn_lock); int nid; - /* The system will behave unpredictably otherwise */ - BUG_ON(system_state != SYSTEM_BOOTING); + /* Avoid locking overhead during boot but hotplug must lock */ + if (system_state != SYSTEM_BOOTING) + spin_lock(&early_pfn_lock); nid = __early_pfn_to_nid(pfn, &early_pfnnid_cache); - if (nid >= 0) - return nid; - /* just returns 0 */ - return 0; + if (nid < 0) + nid = 0; + + if (system_state != SYSTEM_BOOTING) + spin_unlock(&early_pfn_lock); + + return nid; } #endif -- 2.4.3