* [PATCH v3 1/5] mm/percpu-km: clear page->private before free them
2026-07-09 18:06 [PATCH v3 0/5] Keep tail page private zero at free and folio split time Zi Yan
@ 2026-07-09 18:06 ` Zi Yan
2026-07-09 18:06 ` [PATCH v3 2/5] mm/compaction: stop recording free page order in page->private Zi Yan
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Zi Yan @ 2026-07-09 18:06 UTC (permalink / raw)
To: Andrew Morton, Vlastimil Babka, Suren Baghdasaryan, Michal Hocko,
Brendan Jackman, Johannes Weiner, David Hildenbrand,
Lorenzo Stoakes, Baolin Wang, Liam R. Howlett, Nico Pache,
Ryan Roberts, Dev Jain, Barry Song, Lance Yang, Mike Rapoport,
Dennis Zhou, Tejun Heo, Christoph Lameter, Alistair Popple,
Usama Arif
Cc: linux-mm, linux-kernel, Zi Yan
page->private is cleared in free page path. In a subsequent commit,
tail_page->private will be checked and ensured to be zero. Clearing
percpu-km allocated pages' ->private to prevent triggering warnings later,
namely undo what we did in pcpu_create_chunk().
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Reviewed-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
mm/percpu-km.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/mm/percpu-km.c b/mm/percpu-km.c
index 4efa74a495cb6..7ffe84adadb9d 100644
--- a/mm/percpu-km.c
+++ b/mm/percpu-km.c
@@ -94,8 +94,15 @@ static void pcpu_destroy_chunk(struct pcpu_chunk *chunk)
pcpu_stats_chunk_dealloc();
trace_percpu_destroy_chunk(chunk->base_addr);
- if (chunk->data)
+ if (chunk->data) {
+ struct page *pages = (struct page *)chunk->data;
+ int i;
+
+ /* clear chunk info from each page before free them */
+ for (i = 0; i < nr_pages; i++)
+ pcpu_set_page_chunk(pages + i, NULL);
__free_pages(chunk->data, order_base_2(nr_pages));
+ }
pcpu_free_chunk(chunk);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v3 2/5] mm/compaction: stop recording free page order in page->private
2026-07-09 18:06 [PATCH v3 0/5] Keep tail page private zero at free and folio split time Zi Yan
2026-07-09 18:06 ` [PATCH v3 1/5] mm/percpu-km: clear page->private before free them Zi Yan
@ 2026-07-09 18:06 ` Zi Yan
2026-07-09 18:06 ` [PATCH v3 3/5] mm/huge_memory: add page->private check back in __split_folio_to_order() Zi Yan
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Zi Yan @ 2026-07-09 18:06 UTC (permalink / raw)
To: Andrew Morton, Vlastimil Babka, Suren Baghdasaryan, Michal Hocko,
Brendan Jackman, Johannes Weiner, David Hildenbrand,
Lorenzo Stoakes, Baolin Wang, Liam R. Howlett, Nico Pache,
Ryan Roberts, Dev Jain, Barry Song, Lance Yang, Mike Rapoport,
Dennis Zhou, Tejun Heo, Christoph Lameter, Alistair Popple,
Usama Arif
Cc: linux-mm, linux-kernel, Zi Yan
Commit 733aea0b3a7bb ("mm/compaction: add support for >0 order folio
memory compaction.") stores isolated free pages in an array indexed by free
page orders, it is no longer needed to store the order in each page's
->private field. And there is no code using the stored order. Stop doing
that.
It also prepares for an upcoming change that ensures subpage->private is
zero at page free time and the removal of set_page_private(0) from
prep_compound_tail().
Reviewed-by: David Hildenbrand (Arm) <david@kernel.org>
Reviewed-by: Lance Yang <lance.yang@linux.dev>
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
Reviewed-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
mm/compaction.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/mm/compaction.c b/mm/compaction.c
index 4b2318fad4eb5..9f81055a358ed 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -645,7 +645,6 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
isolated = __isolate_free_page(page, order);
if (!isolated)
break;
- set_page_private(page, order);
nr_scanned += isolated - 1;
total_isolated += isolated;
@@ -1618,7 +1617,6 @@ static void fast_isolate_freepages(struct compact_control *cc)
/* Isolate the page if available */
if (page) {
if (__isolate_free_page(page, order)) {
- set_page_private(page, order);
nr_isolated = 1 << order;
nr_scanned += nr_isolated - 1;
total_isolated += nr_isolated;
@@ -1847,7 +1845,6 @@ static struct folio *compaction_alloc_noprof(struct folio *src, unsigned long da
size >>= 1;
list_add(&freepage[size].lru, &cc->freepages[start_order]);
- set_page_private(&freepage[size], start_order);
}
dst = (struct folio *)freepage;
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v3 3/5] mm/huge_memory: add page->private check back in __split_folio_to_order()
2026-07-09 18:06 [PATCH v3 0/5] Keep tail page private zero at free and folio split time Zi Yan
2026-07-09 18:06 ` [PATCH v3 1/5] mm/percpu-km: clear page->private before free them Zi Yan
2026-07-09 18:06 ` [PATCH v3 2/5] mm/compaction: stop recording free page order in page->private Zi Yan
@ 2026-07-09 18:06 ` Zi Yan
2026-07-09 18:06 ` [PATCH v3 4/5] mm/page_alloc: make sure tail_page->private is zero at page free time Zi Yan
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Zi Yan @ 2026-07-09 18:06 UTC (permalink / raw)
To: Andrew Morton, Vlastimil Babka, Suren Baghdasaryan, Michal Hocko,
Brendan Jackman, Johannes Weiner, David Hildenbrand,
Lorenzo Stoakes, Baolin Wang, Liam R. Howlett, Nico Pache,
Ryan Roberts, Dev Jain, Barry Song, Lance Yang, Mike Rapoport,
Dennis Zhou, Tejun Heo, Christoph Lameter, Alistair Popple,
Usama Arif
Cc: linux-mm, linux-kernel, Zi Yan
page->private should not be set in tail pages. Commit 4265d67e405a
("mm/migrate_device: add THP splitting during migration") removed a
DEBUG_VM check without a proper reason[1]. Add it back.
Link: https://lore.kernel.org/all/13f3fcda-7328-4aa5-afc6-75a294a82b2a@nvidia.com/ [1]
Reviewed-by: Lance Yang <lance.yang@linux.dev>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
Reviewed-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
mm/huge_memory.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index fb2d7dd17de0c..ea0445d6c17f0 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -3591,6 +3591,13 @@ static void __split_folio_to_order(struct folio *folio, int old_order,
new_folio->mapping = folio->mapping;
new_folio->index = folio->index + i;
+ /*
+ * page->private should not be set in tail pages. Warn once
+ * if private is unexpectedly set. Do it before swap.val assignment
+ * since private overlaps with swap.val.
+ */
+ VM_WARN_ON_ONCE_PAGE(new_folio->private, new_head);
+
if (folio_test_swapcache(folio))
new_folio->swap.val = folio->swap.val + i;
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v3 4/5] mm/page_alloc: make sure tail_page->private is zero at page free time
2026-07-09 18:06 [PATCH v3 0/5] Keep tail page private zero at free and folio split time Zi Yan
` (2 preceding siblings ...)
2026-07-09 18:06 ` [PATCH v3 3/5] mm/huge_memory: add page->private check back in __split_folio_to_order() Zi Yan
@ 2026-07-09 18:06 ` Zi Yan
2026-07-10 12:51 ` David Hildenbrand (Arm)
2026-07-09 18:06 ` [PATCH v3 5/5] mm/page_alloc: remove set_page_private() in prep_compound_tail() Zi Yan
2026-07-09 18:40 ` [PATCH v3 0/5] Keep tail page private zero at free and folio split time Andrew Morton
5 siblings, 1 reply; 8+ messages in thread
From: Zi Yan @ 2026-07-09 18:06 UTC (permalink / raw)
To: Andrew Morton, Vlastimil Babka, Suren Baghdasaryan, Michal Hocko,
Brendan Jackman, Johannes Weiner, David Hildenbrand,
Lorenzo Stoakes, Baolin Wang, Liam R. Howlett, Nico Pache,
Ryan Roberts, Dev Jain, Barry Song, Lance Yang, Mike Rapoport,
Dennis Zhou, Tejun Heo, Christoph Lameter, Alistair Popple,
Usama Arif
Cc: linux-mm, linux-kernel, Zi Yan
Any code using tail_page->private of a folio, a compound page or a
high-order page is supposed to reset it after use, otherwise ->private data
can leak to new page user and cause unexpected issues. Add a bad_page()
check at page free path for it.
Reviewed-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
mm/page_alloc.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index a63733dac659e..cc45dfe89c76b 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1377,15 +1377,23 @@ static __always_inline bool __free_pages_prepare(struct page *page,
#endif
}
for (i = 1; i < (1 << order); i++) {
+ struct page *tail_page = page + i;
+
if (compound)
- bad += free_tail_page_prepare(page, page + i);
+ bad += free_tail_page_prepare(page, tail_page);
if (is_check_pages_enabled()) {
- if (free_page_is_bad(page + i)) {
+ if (free_page_is_bad(tail_page)) {
+ bad++;
+ continue;
+ }
+
+ if (tail_page->private) {
+ bad_page(tail_page, "nonzero private");
bad++;
continue;
}
}
- (page + i)->flags.f &= ~PAGE_FLAGS_CHECK_AT_PREP;
+ tail_page->flags.f &= ~PAGE_FLAGS_CHECK_AT_PREP;
}
}
if (folio_test_anon(folio)) {
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v3 4/5] mm/page_alloc: make sure tail_page->private is zero at page free time
2026-07-09 18:06 ` [PATCH v3 4/5] mm/page_alloc: make sure tail_page->private is zero at page free time Zi Yan
@ 2026-07-10 12:51 ` David Hildenbrand (Arm)
0 siblings, 0 replies; 8+ messages in thread
From: David Hildenbrand (Arm) @ 2026-07-10 12:51 UTC (permalink / raw)
To: Zi Yan, Andrew Morton, Vlastimil Babka, Suren Baghdasaryan,
Michal Hocko, Brendan Jackman, Johannes Weiner, Lorenzo Stoakes,
Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
Barry Song, Lance Yang, Mike Rapoport, Dennis Zhou, Tejun Heo,
Christoph Lameter, Alistair Popple, Usama Arif
Cc: linux-mm, linux-kernel
On 7/9/26 20:06, Zi Yan wrote:
> Any code using tail_page->private of a folio, a compound page or a
> high-order page is supposed to reset it after use, otherwise ->private data
> can leak to new page user and cause unexpected issues. Add a bad_page()
> check at page free path for it.
>
> Reviewed-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
> Signed-off-by: Zi Yan <ziy@nvidia.com>
> ---
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
--
Cheers,
David
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 5/5] mm/page_alloc: remove set_page_private() in prep_compound_tail()
2026-07-09 18:06 [PATCH v3 0/5] Keep tail page private zero at free and folio split time Zi Yan
` (3 preceding siblings ...)
2026-07-09 18:06 ` [PATCH v3 4/5] mm/page_alloc: make sure tail_page->private is zero at page free time Zi Yan
@ 2026-07-09 18:06 ` Zi Yan
2026-07-09 18:40 ` [PATCH v3 0/5] Keep tail page private zero at free and folio split time Andrew Morton
5 siblings, 0 replies; 8+ messages in thread
From: Zi Yan @ 2026-07-09 18:06 UTC (permalink / raw)
To: Andrew Morton, Vlastimil Babka, Suren Baghdasaryan, Michal Hocko,
Brendan Jackman, Johannes Weiner, David Hildenbrand,
Lorenzo Stoakes, Baolin Wang, Liam R. Howlett, Nico Pache,
Ryan Roberts, Dev Jain, Barry Song, Lance Yang, Mike Rapoport,
Dennis Zhou, Tejun Heo, Christoph Lameter, Alistair Popple,
Usama Arif
Cc: linux-mm, linux-kernel, Zi Yan
Tail pages are expected to have (and optionally be checked) zeroed
->private when they are freed. It stays true during subsequent
reallocation, so replace the tail_page->private initialization with a
VM_WARN_ON_ONCE() in compound page preparation.
Acked-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Reviewed-by: Lance Yang <lance.yang@linux.dev>
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
mm/internal.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/internal.h b/mm/internal.h
index 841c27611627e..398741a8ab092 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -741,7 +741,7 @@ static inline void prep_compound_tail(struct page *tail,
{
tail->mapping = TAIL_MAPPING;
set_compound_head(tail, head, order);
- set_page_private(tail, 0);
+ VM_WARN_ON_ONCE(tail->private);
}
static inline void init_compound_tail(struct page *tail,
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v3 0/5] Keep tail page private zero at free and folio split time
2026-07-09 18:06 [PATCH v3 0/5] Keep tail page private zero at free and folio split time Zi Yan
` (4 preceding siblings ...)
2026-07-09 18:06 ` [PATCH v3 5/5] mm/page_alloc: remove set_page_private() in prep_compound_tail() Zi Yan
@ 2026-07-09 18:40 ` Andrew Morton
5 siblings, 0 replies; 8+ messages in thread
From: Andrew Morton @ 2026-07-09 18:40 UTC (permalink / raw)
To: Zi Yan
Cc: Vlastimil Babka, Suren Baghdasaryan, Michal Hocko,
Brendan Jackman, Johannes Weiner, David Hildenbrand,
Lorenzo Stoakes, Baolin Wang, Liam R. Howlett, Nico Pache,
Ryan Roberts, Dev Jain, Barry Song, Lance Yang, Mike Rapoport,
Dennis Zhou, Tejun Heo, Christoph Lameter, Alistair Popple,
Usama Arif, linux-mm, linux-kernel
On Thu, 09 Jul 2026 14:06:00 -0400 Zi Yan <ziy@nvidia.com> wrote:
> Hi all,
>
> This patchset makes sure tail_page->private is zero before compound or
> high-order pages are returned to the allocator. It also checks tail pages
> that become new folio heads during large folio split, before their private
> fields are used by new folios.
Updated, thanks.
> Changes in v3:
> 1. replaced "it" with "a DEBUG_VM check" in Patch 3 commit message
> 2. moved tail_page->private bad_page() code up to the existing
> is_check_pages_enabled() block in Patch 4.
> - Link to v2: https://lore.kernel.org/r/20260703-keep-subpage-private-zero-at-free-v2-0-2970fe777dd6@nvidia.com
Here's how v3 altered mm.git:
mm/page_alloc.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
--- a/mm/page_alloc.c~b
+++ a/mm/page_alloc.c
@@ -1386,13 +1386,14 @@ static __always_inline bool __free_pages
bad++;
continue;
}
+
+ if (tail_page->private) {
+ bad_page(tail_page, "nonzero private");
+ bad++;
+ continue;
+ }
}
tail_page->flags.f &= ~PAGE_FLAGS_CHECK_AT_PREP;
- if (is_check_pages_enabled() && tail_page->private) {
- bad_page(tail_page, "nonzero private");
- bad++;
- continue;
- }
}
}
if (folio_test_anon(folio)) {
_
^ permalink raw reply [flat|nested] 8+ messages in thread