mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Qi Zheng <qi.zheng@linux.dev>
To: Muchun Song <songmuchun@bytedance.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	David Hildenbrand <david@kernel.org>,
	Oscar Salvador <osalvador@suse.de>,
	Madhavan Srinivasan <maddy@linux.ibm.com>,
	Michael Ellerman <mpe@ellerman.id.au>,
	Jonathan Corbet <corbet@lwn.net>
Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	linuxppc-dev@lists.ozlabs.org, linux-doc@vger.kernel.org,
	Muchun Song <muchun.song@linux.dev>,
	Lorenzo Stoakes <ljs@kernel.org>, Mike Rapoport <rppt@kernel.org>,
	Nicholas Piggin <npiggin@gmail.com>,
	Christophe Leroy <chleroy@kernel.org>,
	Randy Dunlap <rdunlap@infradead.org>
Subject: Re: [PATCH v2 09/11] mm/sparse-vmemmap: drop the extra tail page from device DAX reservation
Date: Tue, 8 Sep 2026 17:09:58 +0800	[thread overview]
Message-ID: <f2f1f7e4-539f-4385-a28b-1fde074cdeca@linux.dev> (raw)
In-Reply-To: <20260908030335.96549-10-songmuchun@bytedance.com>



On 9/8/26 11:03 AM, Muchun Song wrote:
> The device DAX vmemmap population still reserves one extra tail vmemmap
> page after the head page.
> 
> Drop that extra reservation and let the shared tail page cover all tail
> vmemmap pages after the head page, so DAX follows the same reservation
> model as HugeTLB.
> 
> This reduces the reserved vmemmap pages for optimized DAX mappings to
> one and removes the now-unneeded first-tail population from the generic
> and powerpc paths to simplify the code as well.
> 
> Signed-off-by: Muchun Song <songmuchun@bytedance.com>
> ---
>   arch/powerpc/mm/book3s64/radix_pgtable.c | 46 ++----------------------
>   include/linux/mm.h                       |  3 +-
>   mm/mm_init.c                             |  2 +-
>   mm/sparse-vmemmap.c                      | 13 ++-----
>   4 files changed, 7 insertions(+), 57 deletions(-)

Looks like sashiko's response [1] is a false positive.

[1]. 
https://sashiko.dev/#/patchset/20260908030335.96549-1-songmuchun%40bytedance.com

__SetPageReserved() in vmemmap_shared_tail_page() marks the struct page
entries stored inside the shared vmemmap backing page, i.e. the metadata
templates that later represent DEV-DAX tail pages. It does not mark the
struct page of the backing page itself.

On hot-remove, free_vmemmap_pages() is called with pte_page(*pte), which
is the backing page. That page is not reserved, so the teardown goes
through __free_pages(), not free_reserved_pages().

Right?

If so:

Acked-by: Qi Zheng <qi.zheng@linux.dev>

Thanks,
Qi

> 
> diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c
> index 831c231a4a18..e7e751c48dd2 100644
> --- a/arch/powerpc/mm/book3s64/radix_pgtable.c
> +++ b/arch/powerpc/mm/book3s64/radix_pgtable.c
> @@ -1218,39 +1218,6 @@ int __meminit radix__vmemmap_populate(unsigned long start, unsigned long end, in
>   	return 0;
>   }
>   
> -static pte_t * __meminit radix__vmemmap_populate_address(unsigned long addr, int node,
> -							 struct vmem_altmap *altmap,
> -							 struct page *reuse)
> -{
> -	pgd_t *pgd;
> -	p4d_t *p4d;
> -	pud_t *pud;
> -	pmd_t *pmd;
> -	pte_t *pte;
> -
> -	pgd = pgd_offset_k(addr);
> -	p4d = p4d_offset(pgd, addr);
> -	pud = vmemmap_pud_alloc(p4d, node, addr);
> -	if (!pud)
> -		return NULL;
> -	pmd = vmemmap_pmd_alloc(pud, node, addr);
> -	if (!pmd)
> -		return NULL;
> -	if (pmd_leaf(*pmd))
> -		/*
> -		 * The second page is mapped as a hugepage due to a nearby request.
> -		 * Force our mapping to page size without deduplication
> -		 */
> -		return NULL;
> -	pte = vmemmap_pte_alloc(pmd, node, addr);
> -	if (!pte)
> -		return NULL;
> -	radix__vmemmap_pte_populate(pmd, addr, node, NULL, NULL);
> -	vmemmap_verify(pte, node, addr, addr + PAGE_SIZE);
> -
> -	return pte;
> -}
> -
>   int __meminit vmemmap_populate_compound_pages(unsigned long start_pfn,
>   					      unsigned long start,
>   					      unsigned long end, int node,
> @@ -1297,7 +1264,7 @@ int __meminit vmemmap_populate_compound_pages(unsigned long start_pfn,
>   		if (!pte_none(*pte)) {
>   			/*
>   			 * This could be because we already have a compound
> -			 * page whose VMEMMAP_RESERVE_NR pages were mapped and
> +			 * page whose retained vmemmap page was mapped and
>   			 * this request fall in those pages.
>   			 */
>   			next = addr + PAGE_SIZE;
> @@ -1318,16 +1285,7 @@ int __meminit vmemmap_populate_compound_pages(unsigned long start_pfn,
>   					return -ENOMEM;
>   				vmemmap_verify(pte, node, addr, addr + PAGE_SIZE);
>   
> -				/*
> -				 * Populate the tail pages vmemmap page
> -				 * It can fall in different pmd, hence
> -				 * vmemmap_populate_address()
> -				 */
> -				pte = radix__vmemmap_populate_address(addr + PAGE_SIZE, node, NULL, NULL);
> -				if (!pte)
> -					return -ENOMEM;
> -
> -				next = addr + 2 * PAGE_SIZE;
> +				next = addr + PAGE_SIZE;
>   				continue;
>   			}
>   
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index a2ebe87e7654..969594074fd2 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -5167,7 +5167,6 @@ static inline void vmem_altmap_free(struct vmem_altmap *altmap,
>   }
>   #endif
>   
> -#define VMEMMAP_RESERVE_NR	2
>   #ifdef CONFIG_ARCH_WANT_OPTIMIZE_DAX_VMEMMAP
>   static inline bool __vmemmap_can_optimize(struct vmem_altmap *altmap,
>   					  struct dev_pagemap *pgmap)
> @@ -5187,7 +5186,7 @@ static inline bool __vmemmap_can_optimize(struct vmem_altmap *altmap,
>   	 * For vmemmap optimization with DAX we need minimum 2 vmemmap
>   	 * pages. See layout diagram in Documentation/mm/vmemmap_dedup.rst
>   	 */
> -	return !altmap && (nr_vmemmap_pages > VMEMMAP_RESERVE_NR);
> +	return !altmap && (nr_vmemmap_pages > VMEMMAP_OPTIMIZATION_PAGES);
>   }
>   /*
>    * If we don't have an architecture override, use the generic rule
> diff --git a/mm/mm_init.c b/mm/mm_init.c
> index 7a2e58d631c2..629420a83891 100644
> --- a/mm/mm_init.c
> +++ b/mm/mm_init.c
> @@ -1056,7 +1056,7 @@ static inline unsigned long compound_nr_pages(unsigned long pfn,
>   	if (!section_vmemmap_optimizable(ms))
>   		return pgmap_vmemmap_nr(pgmap);
>   
> -	return VMEMMAP_RESERVE_NR * (PAGE_SIZE / sizeof(struct page));
> +	return VMEMMAP_OPTIMIZATION_PAGES * (PAGE_SIZE / sizeof(struct page));
>   }
>   
>   static void __ref memmap_init_compound(struct page *head,
> diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
> index 0201877a7f80..e655d9d1348f 100644
> --- a/mm/sparse-vmemmap.c
> +++ b/mm/sparse-vmemmap.c
> @@ -136,7 +136,6 @@ int __meminit section_nr_vmemmap_pages(unsigned long pfn, unsigned long nr_pages
>   {
>   	const struct mem_section *ms = __pfn_to_section(pfn);
>   	const int order = section_order(ms);
> -	const int vmemmap_pages = pgmap ? VMEMMAP_RESERVE_NR : VMEMMAP_OPTIMIZATION_PAGES;
>   	const unsigned long pages_per_compound = 1UL << order;
>   
>   	VM_WARN_ON_ONCE(!IS_ALIGNED(pfn | nr_pages, PAGES_PER_SUBSECTION));
> @@ -147,13 +146,13 @@ int __meminit section_nr_vmemmap_pages(unsigned long pfn, unsigned long nr_pages
>   
>   	if (order < PFN_SECTION_SHIFT) {
>   		VM_WARN_ON_ONCE(!IS_ALIGNED(pfn | nr_pages, pages_per_compound));
> -		return vmemmap_pages * nr_pages / pages_per_compound;
> +		return VMEMMAP_OPTIMIZATION_PAGES * nr_pages / pages_per_compound;
>   	}
>   
>   	VM_WARN_ON_ONCE(!IS_ALIGNED(pfn | nr_pages, PAGES_PER_SECTION));
>   
>   	if (IS_ALIGNED(pfn, pages_per_compound))
> -		return vmemmap_pages;
> +		return VMEMMAP_OPTIMIZATION_PAGES;
>   
>   	return 0;
>   }
> @@ -521,17 +520,11 @@ static int __meminit vmemmap_populate_compound_pages(unsigned long start_pfn,
>   		if (!pte)
>   			return -ENOMEM;
>   
> -		/* Populate the tail pages vmemmap page */
> -		next = addr + PAGE_SIZE;
> -		pte = vmemmap_populate_address(next, node, NULL, -1, flags);
> -		if (!pte)
> -			return -ENOMEM;
> -
>   		/*
>   		 * Reuse the shared page for the rest of tail pages
>   		 * See layout diagram in Documentation/mm/vmemmap_dedup.rst
>   		 */
> -		next += PAGE_SIZE;
> +		next = addr + PAGE_SIZE;
>   		rc = vmemmap_populate_range(next, last, node, NULL,
>   					    page_to_pfn(page), flags);
>   		if (rc)


  reply	other threads:[~2026-09-08  9:10 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-08  3:03 [PATCH v2 00/11] mm: Switch device DAX to section-based vmemmap optimization Muchun Song
2026-09-08  3:03 ` [PATCH v2 01/11] mm/sparse-vmemmap: introduce CONFIG_SPARSEMEM_VMEMMAP_OPTIMIZATION Muchun Song
2026-09-08  3:03 ` [PATCH v2 02/11] mm/sparse-vmemmap: factor out shared vmemmap tail page allocation Muchun Song
2026-09-08  3:03 ` [PATCH v2 03/11] mm/sparse-vmemmap: open-code init_compound_tail() Muchun Song
2026-09-10  7:50   ` David Hildenbrand (Arm)
2026-09-08  3:03 ` [PATCH v2 04/11] mm/sparse-vmemmap: prepare DAX vmemmap population for section orders Muchun Song
2026-09-08  3:03 ` [PATCH v2 05/11] mm/sparse-vmemmap: set section order for device DAX Muchun Song
2026-09-08  3:03 ` [PATCH v2 06/11] mm/sparse-vmemmap: switch device DAX to shared tail vmemmap pages Muchun Song
2026-09-08  4:09   ` Muchun Song
2026-09-08  7:46   ` Qi Zheng
2026-09-08  8:34     ` Muchun Song
2026-09-08  3:03 ` [PATCH v2 07/11] mm/sparse-vmemmap: move HVO helpers to a public header Muchun Song
2026-09-08  8:19   ` Qi Zheng
2026-09-08  3:03 ` [PATCH v2 08/11] powerpc/mm: switch device DAX to shared tail vmemmap pages Muchun Song
2026-09-08  3:03 ` [PATCH v2 09/11] mm/sparse-vmemmap: drop the extra tail page from device DAX reservation Muchun Song
2026-09-08  9:09   ` Qi Zheng [this message]
2026-09-08  9:12     ` Muchun Song
2026-09-08  3:03 ` [PATCH v2 10/11] mm/sparse-vmemmap: drop unused section_nr_vmemmap_pages() arguments Muchun Song
2026-09-08  9:23   ` Qi Zheng
2026-09-08  3:03 ` [PATCH v2 11/11] Documentation/mm: update DAX vmemmap deduplication docs Muchun Song
2026-09-08  9:29   ` Qi Zheng
2026-09-09  1:45 ` [PATCH v2 00/11] mm: Switch device DAX to section-based vmemmap optimization Andrew Morton
2026-09-10  6:48   ` Muchun Song

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=f2f1f7e4-539f-4385-a28b-1fde074cdeca@linux.dev \
    --to=qi.zheng@linux.dev \
    --cc=akpm@linux-foundation.org \
    --cc=chleroy@kernel.org \
    --cc=corbet@lwn.net \
    --cc=david@kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=ljs@kernel.org \
    --cc=maddy@linux.ibm.com \
    --cc=mpe@ellerman.id.au \
    --cc=muchun.song@linux.dev \
    --cc=npiggin@gmail.com \
    --cc=osalvador@suse.de \
    --cc=rdunlap@infradead.org \
    --cc=rppt@kernel.org \
    --cc=songmuchun@bytedance.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®