Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/5] Keep tail page private zero at free and folio split time
@ 2026-07-09 18:06 Zi Yan
  2026-07-09 18:06 ` [PATCH v3 1/5] mm/percpu-km: clear page->private before free them Zi Yan
                   ` (5 more replies)
  0 siblings, 6 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

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.

It is based on commit c7bf81a726b51 ("samples/damon/prcl: do not stop DAMON
for damon_call() failure") in mm-everything-2026-07-09-05-55, since v2 is
on top of it. I also replaced v2 in mm-everything-2026-07-09-05-55 locally
and find no conflict.

Note on ZONE_DEVICE and DAX page/folio
===
ZONE_DEVICE and DAX use prep_compound_tail() to reinitialize folios, so
tail_page->private was reset before this patchset. There was a concern that
after this patchset stale ->private can appear after ZONE_DEVICE/DAX folio
initialization. My reasoning is that no code sets ZONE_DEVICE/DAX
page->private, so their page->private stays zero all the time.
ZONE_DEVICE_PRIVATE page migration only supports anonymous memory without
swapcache, so after the migration ->private remains zero.

But let me know if my reasoning is wrong. It can be fixed by adding
->private zeroing code in ZONE_DEVICE/DAX folio initialization code.

Motivation
===

page->private is zeroed at page free time since commit ac1ea219590c0
("mm/page_alloc: clear page->private in free_pages_prepare()"), since we
concluded that it might be too much to ask every page user to free a page
with ->private zeroed. The holder of the last page reference might not know
whether ->private needs to be cleared.

For compound and high-order pages, tail_page->private can also leak to
later users if it is left uncleared. The page allocation path does not zero
every tail_page->private field, so they can be seen by new users and cause
unexpected issues[1].

Check tail_page->private at page free time, and check tail pages that
become new folio heads during large folio split. With those checks in
place, prep_compound_tail() no longer needs to clear tail_page->private
when preparing compound page metadata.

Overview
===

1. Patch 1 clears all pages ->private before percpu-km frees them.
2. Patch 2 removes setting page->private in compaction code when a free
   page is taken out of the buddy allocator. cc->freepages is indexed by
   page order, so storing the free page order in page->private is
   redundant. In alloc_contig_frozen_range_noprof(),
   isolate_freepages_range() is used to grab free pages from buddy
   allocator and it leaves the aforementioned page->private set until
   either split_free_frozen_pages() or prep_new_page() is called. That
   stale value without resetting triggers the tail_page->private nonzero
   check once set_page_private(0) is removed from prep_compound_tail().

3. Patch 3 adds back the page->private check for tail pages promoted to new
   folio heads in __split_folio_to_order().
4. Patch 4 adds a tail_page->private check in the page free path.
5. Patch 5 removes tail_page->private zeroing from prep_compound_tail().

Link: https://lore.kernel.org/all/20260206174017.128673-1-mikhail.v.gavrilov@gmail.com/ [1]

Signed-off-by: Zi Yan <ziy@nvidia.com>
---
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

Changes in v2:
1. added reset page->private when percpu-km frees pages
2. replaced subpage with tail page/tail_page in all patches
3. moved implementation details from cc->freepages patch message to cover
   letter, since it is too much for a patch description.
4. used VM_WARN_ON_ONCE_PAGE() in __split_folio_to_order() patch without
   fixup. The expectation is to catch any violation during development
   phase.
5. guarded tail_page->private check behind is_check_pages_enabled().
6. replaced tail_page->private reset code with VM_WARN_ON_ONCE() instead of
   deletion in prep_compound_tail
7. the pre-existing issue in alloc_contig_frozen_range_noprof() is under
   discussion and might not be worth fixing.
   - Link: https://lore.kernel.org/all/d44ae8a5-ec70-456b-92a0-ce7ccabf6917@kernel.org/
- Link to v1: https://lore.kernel.org/r/20260628-keep-subpage-private-zero-at-free-v1-0-f4ce3930d10f@nvidia.com

---
Zi Yan (5):
      mm/percpu-km: clear page->private before free them
      mm/compaction: stop recording free page order in page->private
      mm/huge_memory: add page->private check back in __split_folio_to_order()
      mm/page_alloc: make sure tail_page->private is zero at page free time
      mm/page_alloc: remove set_page_private() in prep_compound_tail()

 mm/compaction.c  |  3 ---
 mm/huge_memory.c |  7 +++++++
 mm/internal.h    |  2 +-
 mm/page_alloc.c  | 14 +++++++++++---
 mm/percpu-km.c   |  9 ++++++++-
 5 files changed, 27 insertions(+), 8 deletions(-)
---
base-commit: c7bf81a726b51f1ba9f197491e1e4c8fdf317326
change-id: 20260603-keep-subpage-private-zero-at-free-a1e1435025dc

Best regards,
-- 
Yan, Zi



^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-07-10 12:51 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH v3 3/5] mm/huge_memory: add page->private check back in __split_folio_to_order() 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
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox