All of lore.kernel.org
 help / color / mirror / Atom feed
From: Muchun Song <muchun.song@linux.dev>
To: Li Zhe <lizhe.67@bytedance.com>, Balbir Singh <balbirs@nvidia.com>
Cc: osalvador@suse.de, david@kernel.org, akpm@linux-foundation.org,
	rppt@kernel.org, apopple@nvidia.com, linux-mm@kvack.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH 1/2] mm/mm_init: factor out memmap_init_page_from_template()
Date: Mon, 9 Nov 2026 10:57:35 +0800	[thread overview]
Message-ID: <f062d92e-a016-447f-926f-bd1b1ce7f106@linux.dev> (raw)
In-Reply-To: <25a188bf-05e4-4f0e-b670-a9dc88195b21@bytedance.com>



On 2026/11/9 10:51, Li Zhe wrote:
> On 11/6/26 6:34 PM, Balbir Singh wrote:
>> On Thu, Nov 05, 2026 at 08:06:14PM +0800, Li Zhe wrote:
>>> ZONE_DEVICE memmap initialization already uses a reusable struct page
>>> template when initializing compound tail pages.  The template mostly
>>> contains invariant state, but a few fields still depend on the target
>>> PFN and must be refreshed before copying the template into each
>>> destination struct page.
>>>
>>> Factor that operation into memmap_init_page_from_template() so other
>>> boot-time memmap initialization paths can reuse the same helper.
>>>
>>> No functional change intended.
>>>
>>> Signed-off-by: Li Zhe <lizhe.67@bytedance.com>
>>> ---
>>>    mm/mm_init.c | 29 +++++++++++++++--------------
>>>    mm/mm_init.h |  2 ++
>>>    2 files changed, 17 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/mm/mm_init.c b/mm/mm_init.c
>>> index 2a0e782a151d..495e20fbdec0 100644
>>> --- a/mm/mm_init.c
>>> +++ b/mm/mm_init.c
>>> @@ -625,6 +625,17 @@ void __meminit __init_single_page(struct page *page, unsigned long pfn,
>>>    	vmemmap_optimization_verify_zone(page);
>>>    }
>>>    
>>> +void __meminit memmap_init_page_from_template(struct page *page,
>>> +		unsigned long pfn, unsigned long zone, struct page *template)
>>> +{
>>> +	set_page_section_from_pfn(template, pfn);
>>> +#ifdef WANT_PAGE_VIRTUAL
>>> +	if (!is_highmem_idx(zone))
>>> +		set_page_address(template, __va(pfn << PAGE_SHIFT));
>>> +#endif
>>> +	memcpy_nontemporal(page, template, sizeof(*page));
>>> +}
>>> +
>> Can we make the template a const? Why can't we do
>>
>> void __meminit memmap_init_page_from_template(struct page *page,
>> 		unsigned long pfn, unsigned long zone,
>> 		const struct page *template)
>> {
>> 	memcpy_nontemporal(page, template, sizeof(*page));
>>
>> 	set_page_section_from_pfn(page, pfn);
>> #ifdef WANT_PAGE_VIRTUAL
>> 	if (!is_highmem_idx(zone))
>> 		set_page_address(page, __va(pfn << PAGE_SHIFT));
>> #endif
>>
>> That way we don't update template once it is set, if template is r/o,
>> then we don't need both first page and template in the caller to
>> be different.

I used to think that too.

> I kept it this way to preserve the memcpy_nontemporal() write pattern:
> update the PFN-dependent fields in the template first, then copy the
> final state to the destination page once.
>
> If we copy first and then update the destination page, the hot loop
> would do a non-temporal copy followed by normal stores to the same
> struct page. That is the pattern this helper avoids.

After thinking it through, that should be the reason. To prevent
similar confusion for others, I suggest adding a comment here
explaining why this specific order is used.

Thanks.

>
> Thanks,
> Zhe
>>>    #ifdef CONFIG_NUMA
>>>    /*
>>>     * During memory init memblocks map pfns to nids. The search is expensive and
>>> @@ -1073,17 +1084,6 @@ static void __ref __init_zone_device_page(struct page *page, unsigned long pfn,
>>>    	}
>>>    }
>>>    
>>> -static void zone_device_page_init_from_template(struct page *page,
>>> -		unsigned long pfn, struct page *template)
>>> -{
>>> -	set_page_section_from_pfn(template, pfn);
>>> -#ifdef WANT_PAGE_VIRTUAL
>>> -	if (!is_highmem_idx(ZONE_DEVICE))
>>> -		set_page_address(template, __va(pfn << PAGE_SHIFT));
>>> -#endif
>>> -	memcpy_nontemporal(page, template, sizeof(*page));
>>> -}
>>> -
>>>    /*
>>>     * With compound page geometry and when struct pages are stored in ram most
>>>     * tail pages are reused. Consequently, the amount of unique struct pages to
>>> @@ -1136,8 +1136,8 @@ static void __ref memmap_init_compound(struct page *head,
>>>    
>>>    	/* Initialize the remaining tail pages from template. */
>>>    	for (pfn = head_pfn + 2; pfn < end_pfn; pfn++)
>>> -		zone_device_page_init_from_template(pfn_to_page(pfn), pfn,
>>> -						    &template);
>>> +		memmap_init_page_from_template(pfn_to_page(pfn), pfn,
>>> +					       ZONE_DEVICE, &template);
>>>    	prep_compound_head(head, order);
>>>    }
>>>    
>>> @@ -1192,7 +1192,8 @@ void __ref memmap_init_zone_device(struct zone *zone,
>>>    	for (; pfn < end_pfn; pfn += pfns_per_compound) {
>>>    		page = pfn_to_page(pfn);
>>>    
>>> -		zone_device_page_init_from_template(page, pfn, &template);
>>> +		memmap_init_page_from_template(page, pfn, ZONE_DEVICE,
>>> +					       &template);
>>>    
>>>    		if (IS_ALIGNED(pfn, PAGES_PER_SECTION))
>>>    			cond_resched();
>>> diff --git a/mm/mm_init.h b/mm/mm_init.h
>>> index 0034e37dbabd..22c465122b47 100644
>>> --- a/mm/mm_init.h
>>> +++ b/mm/mm_init.h
>>> @@ -111,5 +111,7 @@ void memblock_free_all(void);
>>>    
>>>    void __meminit __init_single_page(struct page *page, unsigned long pfn,
>>>    				unsigned long zone, int nid);
>>> +void __meminit memmap_init_page_from_template(struct page *page,
>>> +		unsigned long pfn, unsigned long zone, struct page *template);
>>>    
>>>    #endif /* __MM_MM_INIT_H */
>>> -- 
>> Balbir



  reply	other threads:[~2026-11-09  2:57 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-05 12:06 [PATCH 0/2] mm: optimize HugeTLB bootmem hugepage init Li Zhe
2026-11-05 12:06 ` [PATCH 1/2] mm/mm_init: factor out memmap_init_page_from_template() Li Zhe
2026-11-06 10:34   ` Balbir Singh
2026-11-09  2:51     ` Li Zhe
2026-11-09  2:57       ` Muchun Song [this message]
2026-11-09  3:05         ` Li Zhe
2026-11-05 12:06 ` [PATCH 2/2] mm/hugetlb: optimize bootmem hugepage tail vmemmap init Li Zhe
2026-11-06 10:23   ` Balbir Singh
2026-11-09  3:01     ` Li Zhe
2026-11-09  9:22       ` Li Zhe
2026-11-09  9:41         ` Mike Rapoport
2026-11-09  9:52           ` Li Zhe
2026-11-09 11:33             ` Mike Rapoport
2026-11-10  2:15               ` Li Zhe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f062d92e-a016-447f-926f-bd1b1ce7f106@linux.dev \
    --to=muchun.song@linux.dev \
    --cc=akpm@linux-foundation.org \
    --cc=apopple@nvidia.com \
    --cc=balbirs@nvidia.com \
    --cc=david@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=lizhe.67@bytedance.com \
    --cc=osalvador@suse.de \
    --cc=rppt@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.