Message ID | 20230614110324.3839354-1-yajun.deng@linux.dev |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp1159556vqr; Wed, 14 Jun 2023 04:11:05 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5B8xtTbsj95K96W0mr4TQWJDqU6+vk71FofiuBIhpMG58TvD0p3H0Auz07+QDqSrVw8SAl X-Received: by 2002:a05:6808:1909:b0:397:f1b3:f940 with SMTP id bf9-20020a056808190900b00397f1b3f940mr11396396oib.27.1686741065311; Wed, 14 Jun 2023 04:11:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1686741065; cv=none; d=google.com; s=arc-20160816; b=Ux/NdO5Uk9lGSUXZOT/uxs7MM8UOb0GVZxudscqEirkjqK0NlB334PSRhGQZFun+ye lwHfQqxf5wJjby2lRTYVd037BCoEC2rX5oPoA+m6/zJHTTeN58F8gQjRwSF1fIH71rB3 5zLjE7a9caN0djK2f4glkn3/b7cri7j+Wg+0sRFGKXOx92lKu+22HhMJarkbBOKCHGqA FuSJjCSdaSg9QsWCK6xGmHk75q64d7VqQiCIa/pFUbXEe400yH5oIZohuFHC8F5/K2Z2 mlDMn3ruuNgO5Mjuh7Ch8ernUiOkZT112RRFzbgQsn8q7nmbC06Y+iT7IqjPvvtPgbsh 7LFg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=JUAXO3nF4TYUh7G4bGQ31E/7+rub4uhiLNTBrM2ujC8=; b=eogMu5VWOWPy88rGiNuL7+G0GBiRlUv7eclGAUN9x50CQzDWsSCivAhpdbBcUZi0la ta0Equt1teNN5cp/+3DGawUUv6bmBlzycKG3xXOAYm1pqVduk/lnxlHJf8+7NqtXdtNH faLH9GziyISR7MTRdU0wXbvOlku1+usR33POrI0E7b4pE8MoQeRDW8aIrvOpT1rcdTAS QSqZkCDtzqp7VSCN7hZpbrp3GeV7nD7ZlbHQoZSwtcuoLZsnzFL0E7oODOOcJVTXWJeH kB0s6/jflxIpOMQT2kcdSK7N2Qfrn9ve2uFvShoKa+hE9Ie6p8OhbHU0CEh3Vrp20YJ8 2/fA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linux.dev header.s=key1 header.b=P06EKQSY; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.dev Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id c5-20020a621c05000000b0065d565b6b33si10616005pfc.33.2023.06.14.04.10.49; Wed, 14 Jun 2023 04:11:05 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linux.dev header.s=key1 header.b=P06EKQSY; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.dev Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243511AbjFNLD7 (ORCPT <rfc822;n2h9z4@gmail.com> + 99 others); Wed, 14 Jun 2023 07:03:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33008 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236214AbjFNLDo (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Wed, 14 Jun 2023 07:03:44 -0400 Received: from out-62.mta1.migadu.com (out-62.mta1.migadu.com [95.215.58.62]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8069A1BE5 for <linux-kernel@vger.kernel.org>; Wed, 14 Jun 2023 04:03:42 -0700 (PDT) X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1686740617; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=JUAXO3nF4TYUh7G4bGQ31E/7+rub4uhiLNTBrM2ujC8=; b=P06EKQSYiSzPJZCUwYNF5LhDGDRkWumiodO74KPIgoDsJrSSb2UrF6A7dqnDxkcI4mWLjI nb9+BJDG2syeWPi7IUgLgHswlfW/eBUTP6IOeABhyIBQQry9VGuTvpKhY+7YUZVYrZN8jH k9zNpZiJ+8Ve3g+BfGPpBFZezTn8LhM= From: Yajun Deng <yajun.deng@linux.dev> To: gregkh@linuxfoundation.org, rafael@kernel.org, rppt@kernel.org, akpm@linux-foundation.org Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, Yajun Deng <yajun.deng@linux.dev> Subject: [PATCH] mm/mm_init.c: remove spinlock in early_pfn_to_nid() Date: Wed, 14 Jun 2023 19:03:24 +0800 Message-Id: <20230614110324.3839354-1-yajun.deng@linux.dev> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1768676199273240410?= X-GMAIL-MSGID: =?utf-8?q?1768676199273240410?= |
Series |
mm/mm_init.c: remove spinlock in early_pfn_to_nid()
|
|
Commit Message
Yajun Deng
June 14, 2023, 11:03 a.m. UTC
When the system boots, only one cpu is enabled before smp_init().
So the spinlock is not needed in most cases, remove it.
Add spinlock in get_nid_for_pfn() because it is after smp_init().
Signed-off-by: Yajun Deng <yajun.deng@linux.dev>
---
drivers/base/node.c | 11 +++++++++--
mm/mm_init.c | 18 +++---------------
2 files changed, 12 insertions(+), 17 deletions(-)
Comments
On Wed, Jun 14, 2023 at 07:03:24PM +0800, Yajun Deng wrote: > When the system boots, only one cpu is enabled before smp_init(). > So the spinlock is not needed in most cases, remove it. > > Add spinlock in get_nid_for_pfn() because it is after smp_init(). So this is two different things at once in the same patch? Or are they the same problem and both need to go in to solve it? And if a spinlock is not needed at early boot, is it really causing any problems? > > Signed-off-by: Yajun Deng <yajun.deng@linux.dev> > --- > drivers/base/node.c | 11 +++++++++-- > mm/mm_init.c | 18 +++--------------- > 2 files changed, 12 insertions(+), 17 deletions(-) > > diff --git a/drivers/base/node.c b/drivers/base/node.c > index 9de524e56307..844102570ff2 100644 > --- a/drivers/base/node.c > +++ b/drivers/base/node.c > @@ -748,8 +748,15 @@ int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) > static int __ref get_nid_for_pfn(unsigned long pfn) > { > #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT > - if (system_state < SYSTEM_RUNNING) > - return early_pfn_to_nid(pfn); > + static DEFINE_SPINLOCK(early_pfn_lock); > + int nid; > + > + if (system_state < SYSTEM_RUNNING) { > + spin_lock(&early_pfn_lock); > + nid = early_pfn_to_nid(pfn); > + spin_unlock(&early_pfn_lock); Adding an external lock for when you call a function is VERY dangerous as you did not document this anywhere, and there's no way to enforce it properly at all. Does your change actually result in any boot time changes? How was this tested? thanks, greg k-h
June 14, 2023 7:09 PM, "Greg KH" <gregkh@linuxfoundation.org> wrote: > On Wed, Jun 14, 2023 at 07:03:24PM +0800, Yajun Deng wrote: > >> When the system boots, only one cpu is enabled before smp_init(). >> So the spinlock is not needed in most cases, remove it. >> >> Add spinlock in get_nid_for_pfn() because it is after smp_init(). > > So this is two different things at once in the same patch? > > Or are they the same problem and both need to go in to solve it? > > And if a spinlock is not needed at early boot, is it really causing any > problems? > They are the same problem. I added pr_info in early_pfn_to_nid(), found get_nid_for_pfn() is the only case need to add spinlock. This patch tested on my x86 system. >> Signed-off-by: Yajun Deng <yajun.deng@linux.dev> >> --- >> drivers/base/node.c | 11 +++++++++-- >> mm/mm_init.c | 18 +++--------------- >> 2 files changed, 12 insertions(+), 17 deletions(-) >> >> diff --git a/drivers/base/node.c b/drivers/base/node.c >> index 9de524e56307..844102570ff2 100644 >> --- a/drivers/base/node.c >> +++ b/drivers/base/node.c >> @@ -748,8 +748,15 @@ int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) >> static int __ref get_nid_for_pfn(unsigned long pfn) >> { >> #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT >> - if (system_state < SYSTEM_RUNNING) >> - return early_pfn_to_nid(pfn); >> + static DEFINE_SPINLOCK(early_pfn_lock); >> + int nid; >> + >> + if (system_state < SYSTEM_RUNNING) { >> + spin_lock(&early_pfn_lock); >> + nid = early_pfn_to_nid(pfn); >> + spin_unlock(&early_pfn_lock); > > Adding an external lock for when you call a function is VERY dangerous > as you did not document this anywhere, and there's no way to enforce it > properly at all. > I should add a comment before early_pfn_to_nid(). > Does your change actually result in any boot time changes? How was this > tested? > Just a bit. > thanks, > > greg k-h
Hi, On Wed, Jun 14, 2023 at 11:28:32AM +0000, Yajun Deng wrote: > June 14, 2023 7:09 PM, "Greg KH" <gregkh@linuxfoundation.org> wrote: > > > On Wed, Jun 14, 2023 at 07:03:24PM +0800, Yajun Deng wrote: > > > >> When the system boots, only one cpu is enabled before smp_init(). > >> So the spinlock is not needed in most cases, remove it. > >> > >> Add spinlock in get_nid_for_pfn() because it is after smp_init(). > > > > So this is two different things at once in the same patch? > > > > Or are they the same problem and both need to go in to solve it? > > > > And if a spinlock is not needed at early boot, is it really causing any > > problems? > > > > They are the same problem. > I added pr_info in early_pfn_to_nid(), found get_nid_for_pfn() is the only > case need to add spinlock. > This patch tested on my x86 system. Are you sure it'll work on !x86? > >> Signed-off-by: Yajun Deng <yajun.deng@linux.dev> > >> --- > >> drivers/base/node.c | 11 +++++++++-- > >> mm/mm_init.c | 18 +++--------------- > >> 2 files changed, 12 insertions(+), 17 deletions(-) > >> > >> diff --git a/drivers/base/node.c b/drivers/base/node.c > >> index 9de524e56307..844102570ff2 100644 > >> --- a/drivers/base/node.c > >> +++ b/drivers/base/node.c > >> @@ -748,8 +748,15 @@ int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) > >> static int __ref get_nid_for_pfn(unsigned long pfn) > >> { > >> #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT > >> - if (system_state < SYSTEM_RUNNING) > >> - return early_pfn_to_nid(pfn); > >> + static DEFINE_SPINLOCK(early_pfn_lock); > >> + int nid; > >> + > >> + if (system_state < SYSTEM_RUNNING) { > >> + spin_lock(&early_pfn_lock); > >> + nid = early_pfn_to_nid(pfn); > >> + spin_unlock(&early_pfn_lock); > > > > Adding an external lock for when you call a function is VERY dangerous > > as you did not document this anywhere, and there's no way to enforce it > > properly at all. > > > > I should add a comment before early_pfn_to_nid(). > > > Does your change actually result in any boot time changes? How was this > > tested? > > > > Just a bit. Just a bit tested? Or just a bit of boot time changes? For the latter, do you have numbers?
June 14, 2023 7:53 PM, "Mike Rapoport" <rppt@kernel.org> wrote: > Hi, > > On Wed, Jun 14, 2023 at 11:28:32AM +0000, Yajun Deng wrote: > >> June 14, 2023 7:09 PM, "Greg KH" <gregkh@linuxfoundation.org> wrote: >> >> On Wed, Jun 14, 2023 at 07:03:24PM +0800, Yajun Deng wrote: >> >> When the system boots, only one cpu is enabled before smp_init(). >> So the spinlock is not needed in most cases, remove it. >> >> Add spinlock in get_nid_for_pfn() because it is after smp_init(). >> >> So this is two different things at once in the same patch? >> >> Or are they the same problem and both need to go in to solve it? >> >> And if a spinlock is not needed at early boot, is it really causing any >> problems? >> >> They are the same problem. >> I added pr_info in early_pfn_to_nid(), found get_nid_for_pfn() is the only >> case need to add spinlock. >> This patch tested on my x86 system. > > Are you sure it'll work on !x86? > I'm probably sure of that, although I don't have a !x86 machine. early_pfn_to_nid() is called in smp_init() and kasan_init() on different architectures. If it works well on x86, it'll work on !x86. >> Signed-off-by: Yajun Deng <yajun.deng@linux.dev> >> --- >> drivers/base/node.c | 11 +++++++++-- >> mm/mm_init.c | 18 +++--------------- >> 2 files changed, 12 insertions(+), 17 deletions(-) >> >> diff --git a/drivers/base/node.c b/drivers/base/node.c >> index 9de524e56307..844102570ff2 100644 >> --- a/drivers/base/node.c >> +++ b/drivers/base/node.c >> @@ -748,8 +748,15 @@ int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) >> static int __ref get_nid_for_pfn(unsigned long pfn) >> { >> #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT >> - if (system_state < SYSTEM_RUNNING) >> - return early_pfn_to_nid(pfn); >> + static DEFINE_SPINLOCK(early_pfn_lock); >> + int nid; >> + >> + if (system_state < SYSTEM_RUNNING) { >> + spin_lock(&early_pfn_lock); >> + nid = early_pfn_to_nid(pfn); >> + spin_unlock(&early_pfn_lock); >> >> Adding an external lock for when you call a function is VERY dangerous >> as you did not document this anywhere, and there's no way to enforce it >> properly at all. >> >> I should add a comment before early_pfn_to_nid(). >> >> Does your change actually result in any boot time changes? How was this >> tested? >> >> Just a bit. > > Just a bit tested? Or just a bit of boot time changes? > For the latter, do you have numbers? > For the latter, the most beneficial function is memmap_init_reserved_pages(), the boot time changes depending on whether DEFERRED_STRUCT_PAGE_INIT is defined or not. -->memmap_init_reserved_pages() -->for_each_reserved_mem_range() reserve_bootmem_region() -->for() init_reserved_page() --> early_pfn_to_nid() If define CONFIG_DEFERRED_STRUCT_PAGE_INIT: before: memmap_init_reserved_pages() 1.87 seconds after: memmap_init_reserved_pages() 1.27 seconds 32% time reduction. If not define CONFIG_DEFERRED_STRUCT_PAGE_INIT: early_pfn_to_nid() is called by few, boot time didn't change. By the way, this machine has 190GB RAM. > -- > Sincerely yours, > Mike.
On Thu, Jun 15, 2023 at 03:02:58AM +0000, Yajun Deng wrote: > June 14, 2023 7:53 PM, "Mike Rapoport" <rppt@kernel.org> wrote: > > > Hi, > > > > On Wed, Jun 14, 2023 at 11:28:32AM +0000, Yajun Deng wrote: > > > >> June 14, 2023 7:09 PM, "Greg KH" <gregkh@linuxfoundation.org> wrote: > >> > >> On Wed, Jun 14, 2023 at 07:03:24PM +0800, Yajun Deng wrote: > >> > >> When the system boots, only one cpu is enabled before smp_init(). > >> So the spinlock is not needed in most cases, remove it. > >> > >> Add spinlock in get_nid_for_pfn() because it is after smp_init(). > >> > >> So this is two different things at once in the same patch? > >> > >> Or are they the same problem and both need to go in to solve it? > >> > >> And if a spinlock is not needed at early boot, is it really causing any > >> problems? > >> > >> They are the same problem. > >> I added pr_info in early_pfn_to_nid(), found get_nid_for_pfn() is the only > >> case need to add spinlock. > >> This patch tested on my x86 system. > > > > Are you sure it'll work on !x86? > > > > I'm probably sure of that, although I don't have a !x86 machine. > > early_pfn_to_nid() is called in smp_init() and kasan_init() on > different architectures. If it works well on x86, it'll work on > !x86. This is often not true. Please verify that other architectures do not call early_pfn_to_nid() after smp_init(). The explanation why it is safe should be a part of the changelog. > >> Signed-off-by: Yajun Deng <yajun.deng@linux.dev> > >> --- > >> drivers/base/node.c | 11 +++++++++-- > >> mm/mm_init.c | 18 +++--------------- > >> 2 files changed, 12 insertions(+), 17 deletions(-) > >> > >> diff --git a/drivers/base/node.c b/drivers/base/node.c > >> index 9de524e56307..844102570ff2 100644 > >> --- a/drivers/base/node.c > >> +++ b/drivers/base/node.c > >> @@ -748,8 +748,15 @@ int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) > >> static int __ref get_nid_for_pfn(unsigned long pfn) > >> { > >> #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT > >> - if (system_state < SYSTEM_RUNNING) > >> - return early_pfn_to_nid(pfn); > >> + static DEFINE_SPINLOCK(early_pfn_lock); > >> + int nid; > >> + > >> + if (system_state < SYSTEM_RUNNING) { > >> + spin_lock(&early_pfn_lock); > >> + nid = early_pfn_to_nid(pfn); > >> + spin_unlock(&early_pfn_lock); > >> > >> Adding an external lock for when you call a function is VERY dangerous > >> as you did not document this anywhere, and there's no way to enforce it > >> properly at all. > >> > >> I should add a comment before early_pfn_to_nid(). > >> > >> Does your change actually result in any boot time changes? How was this > >> tested? > >> > >> Just a bit. > > > > Just a bit tested? Or just a bit of boot time changes? > > For the latter, do you have numbers? > > > > For the latter, the most beneficial function is memmap_init_reserved_pages(), > the boot time changes depending on whether DEFERRED_STRUCT_PAGE_INIT > is defined or not. > > -->memmap_init_reserved_pages() > -->for_each_reserved_mem_range() > reserve_bootmem_region() > -->for() > init_reserved_page() > --> early_pfn_to_nid() A better solution would be to pass nid to reserve_bootmem_range() and drop the call to early_pfn_to_nid() in init_reserved_page(). Then there won't be lock contention and no need for fragile changes in the locking. > If define CONFIG_DEFERRED_STRUCT_PAGE_INIT: > > before: > memmap_init_reserved_pages() 1.87 seconds > after: > memmap_init_reserved_pages() 1.27 seconds > > 32% time reduction. These measurements should be part of the changelog. > If not define CONFIG_DEFERRED_STRUCT_PAGE_INIT: > > early_pfn_to_nid() is called by few, > boot time didn't change. > > > By the way, this machine has 190GB RAM. > > > -- > > Sincerely yours, > > Mike.
June 15, 2023 2:20 PM, "Mike Rapoport" <rppt@kernel.org> wrote: > On Thu, Jun 15, 2023 at 03:02:58AM +0000, Yajun Deng wrote: > >> June 14, 2023 7:53 PM, "Mike Rapoport" <rppt@kernel.org> wrote: >> >> Hi, >> >> On Wed, Jun 14, 2023 at 11:28:32AM +0000, Yajun Deng wrote: >> >> June 14, 2023 7:09 PM, "Greg KH" <gregkh@linuxfoundation.org> wrote: >> >> On Wed, Jun 14, 2023 at 07:03:24PM +0800, Yajun Deng wrote: >> >> When the system boots, only one cpu is enabled before smp_init(). >> So the spinlock is not needed in most cases, remove it. >> >> Add spinlock in get_nid_for_pfn() because it is after smp_init(). >> >> So this is two different things at once in the same patch? >> >> Or are they the same problem and both need to go in to solve it? >> >> And if a spinlock is not needed at early boot, is it really causing any >> problems? >> >> They are the same problem. >> I added pr_info in early_pfn_to_nid(), found get_nid_for_pfn() is the only >> case need to add spinlock. >> This patch tested on my x86 system. >> >> Are you sure it'll work on !x86? >> >> I'm probably sure of that, although I don't have a !x86 machine. >> >> early_pfn_to_nid() is called in smp_init() and kasan_init() on >> different architectures. If it works well on x86, it'll work on >> !x86. > > This is often not true. Please verify that other architectures do not call > early_pfn_to_nid() after smp_init(). The explanation why it is safe should > be a part of the changelog. > >> Signed-off-by: Yajun Deng <yajun.deng@linux.dev> >> --- >> drivers/base/node.c | 11 +++++++++-- >> mm/mm_init.c | 18 +++--------------- >> 2 files changed, 12 insertions(+), 17 deletions(-) >> >> diff --git a/drivers/base/node.c b/drivers/base/node.c >> index 9de524e56307..844102570ff2 100644 >> --- a/drivers/base/node.c >> +++ b/drivers/base/node.c >> @@ -748,8 +748,15 @@ int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) >> static int __ref get_nid_for_pfn(unsigned long pfn) >> { >> #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT >> - if (system_state < SYSTEM_RUNNING) >> - return early_pfn_to_nid(pfn); >> + static DEFINE_SPINLOCK(early_pfn_lock); >> + int nid; >> + >> + if (system_state < SYSTEM_RUNNING) { >> + spin_lock(&early_pfn_lock); >> + nid = early_pfn_to_nid(pfn); >> + spin_unlock(&early_pfn_lock); >> >> Adding an external lock for when you call a function is VERY dangerous >> as you did not document this anywhere, and there's no way to enforce it >> properly at all. >> >> I should add a comment before early_pfn_to_nid(). >> >> Does your change actually result in any boot time changes? How was this >> tested? >> >> Just a bit. >> >> Just a bit tested? Or just a bit of boot time changes? >> For the latter, do you have numbers? >> >> For the latter, the most beneficial function is memmap_init_reserved_pages(), >> the boot time changes depending on whether DEFERRED_STRUCT_PAGE_INIT >> is defined or not. >> >> -->memmap_init_reserved_pages() >> -->for_each_reserved_mem_range() >> reserve_bootmem_region() >> -->for() >> init_reserved_page() >> --> early_pfn_to_nid() > > A better solution would be to pass nid to reserve_bootmem_range() and drop > the call to early_pfn_to_nid() in init_reserved_page(). > > Then there won't be lock contention and no need for fragile changes in the > locking. > Great, I will try it. >> If define CONFIG_DEFERRED_STRUCT_PAGE_INIT: >> >> before: >> memmap_init_reserved_pages() 1.87 seconds >> after: >> memmap_init_reserved_pages() 1.27 seconds >> >> 32% time reduction. > > These measurements should be part of the changelog. > >> If not define CONFIG_DEFERRED_STRUCT_PAGE_INIT: >> >> early_pfn_to_nid() is called by few, >> boot time didn't change. >> >> By the way, this machine has 190GB RAM. >> >> -- >> Sincerely yours, >> Mike. > > -- > Sincerely yours, > Mike.
diff --git a/drivers/base/node.c b/drivers/base/node.c index 9de524e56307..844102570ff2 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -748,8 +748,15 @@ int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) static int __ref get_nid_for_pfn(unsigned long pfn) { #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT - if (system_state < SYSTEM_RUNNING) - return early_pfn_to_nid(pfn); + static DEFINE_SPINLOCK(early_pfn_lock); + int nid; + + if (system_state < SYSTEM_RUNNING) { + spin_lock(&early_pfn_lock); + nid = early_pfn_to_nid(pfn); + spin_unlock(&early_pfn_lock); + return nid; + } #endif return pfn_to_nid(pfn); } diff --git a/mm/mm_init.c b/mm/mm_init.c index d393631599a7..5895a30435ee 100644 --- a/mm/mm_init.c +++ b/mm/mm_init.c @@ -584,11 +584,11 @@ struct mminit_pfnnid_cache { static struct mminit_pfnnid_cache early_pfnnid_cache __meminitdata; /* - * Required by SPARSEMEM. Given a PFN, return what node the PFN is on. + * Given a PFN, return what node the PFN is on. */ -static int __meminit __early_pfn_to_nid(unsigned long pfn, - struct mminit_pfnnid_cache *state) +int __meminit early_pfn_to_nid(unsigned long pfn) { + struct mminit_pfnnid_cache *state = &early_pfnnid_cache; unsigned long start_pfn, end_pfn; int nid; @@ -601,20 +601,8 @@ static int __meminit __early_pfn_to_nid(unsigned long pfn, state->last_end = end_pfn; state->last_nid = nid; } - - return nid; -} - -int __meminit early_pfn_to_nid(unsigned long pfn) -{ - static DEFINE_SPINLOCK(early_pfn_lock); - int nid; - - spin_lock(&early_pfn_lock); - nid = __early_pfn_to_nid(pfn, &early_pfnnid_cache); if (nid < 0) nid = first_online_node; - spin_unlock(&early_pfn_lock); return nid; }