From: Lance Yang <lance.yang@linux.dev>
To: david@kernel.org, ziy@nvidia.com
Cc: vbabka@kernel.org, akpm@linux-foundation.org, surenb@google.com,
mhocko@suse.com, jackmanb@google.com, hannes@cmpxchg.org,
ljs@kernel.org, baolin.wang@linux.alibaba.com,
liam@infradead.org, npache@redhat.com, ryan.roberts@arm.com,
dev.jain@arm.com, baohua@kernel.org, lance.yang@linux.dev,
rppt@kernel.org, linux-mm@kvack.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH 2/4] mm/huge_memory: add page->private check back in __split_folio_to_order()
Date: Wed, 1 Jul 2026 19:01:51 +0800 [thread overview]
Message-ID: <20260701110151.77453-1-lance.yang@linux.dev> (raw)
In-Reply-To: <98cf3340-1a2f-4d50-8410-6e9d6d3a5308@kernel.org>
On Wed, Jul 01, 2026 at 10:56:47AM +0200, David Hildenbrand (Arm) wrote:
>On 6/29/26 16:39, Vlastimil Babka (SUSE) wrote:
>> On 6/29/26 04:56, Zi Yan wrote:
>
>s/add/readd/
>
>>> page->private should not be set in tail pages. Commit 4265d67e405a
>>> ("mm/migrate_device: add THP splitting during migration") removed it
>>> without a proper reason. Add it back.
>
>You can link to the discussion where we clarified that this was not intentional.
Probably this one?
https://lore.kernel.org/all/13f3fcda-7328-4aa5-afc6-75a294a82b2a@nvidia.com/
>>>
>>> Signed-off-by: Zi Yan <ziy@nvidia.com>
>>> ---
>>> mm/huge_memory.c | 10 ++++++++++
>>> 1 file changed, 10 insertions(+)
>>>
>>> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
>>> index 2bccb0a53a0a..037d67fbec6e 100644
>>> --- a/mm/huge_memory.c
>>> +++ b/mm/huge_memory.c
>>> @@ -3594,6 +3594,16 @@ 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. Fix up and warn once
>>> + * if private is unexpectedly set. Do it before swap.val assignment
>>> + * since private overlaps with swap.val.
>>> + */
>>> + if (unlikely(new_folio->private)) {
>>> + VM_WARN_ON_ONCE_PAGE(true, new_head);
>>> + new_folio->private = NULL;
>>> + }
>>
>> The unconditional warning means this is not expected to happen. In that case
>> it's odd to check and fixup always, but only warn with CONFIG_DEBUG_VM.
>>
>> If we are reasonably sure the current code is OK, and only want to catch new
>> mistakes in development, we could just VM_WARN_ON_ONCE_PAGE() without fixup.
>>
>> If we are paranoid, leave it as it is, but drop the "VM_" ?
>
>Agreed, either "if (WARN_ON_ONCE(new_folio->private))" + fixup, or no fixup.
>
>I'd prefer VM_WARN_ON_ONCE_PAGE().
>
>(I was only able to trigger this once while testing my own patches)
Looking at the history a bit, that check has been around for a while :)
b653db77350c ("mm: Clear page->private when splitting or migrating a
page") first started clearing tail page->private during THP split:
static void __split_huge_page_tail(struct page *head, int tail,
struct lruvec *lruvec, struct list_head *list)
{
struct page *page_tail = head + tail;
...
page_tail->private = 0;
...
}
That was too broad for THP swapcache, tail page->private still carried
swap_entry_t there ...
71e2d666ef85 ("mm/huge_memory: do not clobber swp_entry_t during THP
split") kept that swapcache exception, and made that tail page check
explict:
static void __split_huge_page_tail(struct page *head, int tail,
struct lruvec *lruvec, struct list_head *list)
{
struct page *page_tail = head + tail;
...
/*
* page->private should not be set in tail pages with the exception
* of swap cache pages that store the swp_entry_t in tail pages.
* Fix up and warn once if private is unexpectedly set.
*/
if (!folio_test_swapcache(page_folio(head))) {
VM_WARN_ON_ONCE_PAGE(page_tail->private != 0, head);
page_tail->private = 0;
}
...
}
5aae9265ee1a ("mm: prep_compound_tail() clear page->private") followd
the same rule. Changelog says the warning had already caught real
non-zero tail page-private values:
"
Change that warning to dump page_tail (which also dumps head), instead of
just the head: so far we have seen dead000000000122, dead000000000003,
dead000000000001 or 0000000000000002 in the raw output for tail private.
"
So prep_compound_tail() clears tail page->private for tail pages:
static void prep_compound_tail(struct page *head, int tail_idx)
{
struct page *p = head + tail_idx;
...
set_page_private(p, 0);
}
cfeed8ffe55b ("mm/swap: stop using page->private on tail pages for
THP_SWAP") stopped keeping THP swap entries in tail page->privata.
So split code started warning and clearing old tail page->private before
setting the swap entry:
static void __split_huge_page_tail(struct page *head, int tail,
struct lruvec *lruvec, struct list_head *list)
{
struct page *page_tail = head + tail;
...
/*
* page->private should not be set in tail pages. Fix up and warn once
* if private is unexpectedly set.
*/
if (unlikely(page_tail->private)) {
VM_WARN_ON_ONCE_PAGE(true, page_tail);
page_tail->private = 0;
}
if (PageSwapCache(head))
set_page_private(page_tail, (unsigned long)head->private + tail);
...
}
00527733d0dc ("mm/huge_memory: add two new (not yet used) functions for
folio_split()") added the same check to __split_folio_to_order():
static void __split_folio_to_order(struct folio *folio, int old_order,
int new_order)
{
...
/*
* page->private should not be set in tail pages. Fix up and warn once
* if private is unexpectedly set.
*/
if (unlikely(new_folio->private)) {
VM_WARN_ON_ONCE_PAGE(true, new_head);
new_folio->private = NULL;
}
if (folio_test_swapcache(folio))
new_folio->swap.val = folio->swap.val + i;
...
}
4265d67e405a ("mm/migrate_device: add THP splitting during migration")
removed that check ... Worth noting, David pointed out in the thread that
the check had caught bugs before. Guess nobody really noticed at the time.
https://lore.kernel.org/all/76750d20-cdfe-41bb-a228-9b3f171675ec@kernel.org/
So adding it back makes sense to me. Just in case it's useful later, feel
free to add:
Reviewed-by: Lance Yang <lance.yang@linux.dev>
next prev parent reply other threads:[~2026-07-01 11:02 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-29 2:56 [PATCH 0/4] Keep subpage private zero at free and folio split time Zi Yan
2026-06-29 2:56 ` [PATCH 1/4] mm/compaction: stop recording free page order in page->private Zi Yan
2026-06-29 14:28 ` Vlastimil Babka (SUSE)
2026-06-29 15:03 ` Zi Yan
2026-06-30 1:32 ` Baolin Wang
2026-06-30 1:37 ` Zi Yan
2026-07-01 8:54 ` David Hildenbrand (Arm)
2026-07-01 6:49 ` Lance Yang
2026-06-29 2:56 ` [PATCH 2/4] mm/huge_memory: add page->private check back in __split_folio_to_order() Zi Yan
2026-06-29 14:39 ` Vlastimil Babka (SUSE)
2026-06-29 15:05 ` Zi Yan
2026-07-01 8:56 ` David Hildenbrand (Arm)
2026-07-01 11:01 ` Lance Yang [this message]
2026-07-01 11:08 ` David Hildenbrand (Arm)
2026-07-01 13:32 ` Zi Yan
2026-06-29 2:56 ` [PATCH 3/4] mm/page_alloc: make sure subpage->private is zero at page free time Zi Yan
2026-06-29 14:53 ` Vlastimil Babka (SUSE)
2026-06-29 15:07 ` Zi Yan
2026-06-29 2:56 ` [PATCH 4/4] mm/page_alloc: remove set_page_private() in prep_compound_tail() Zi Yan
2026-06-29 15:45 ` Vlastimil Babka (SUSE)
2026-06-29 16:50 ` Zi Yan
2026-07-01 8:58 ` David Hildenbrand (Arm)
2026-07-01 12:25 ` Lance Yang
2026-07-01 13:33 ` Zi Yan
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=20260701110151.77453-1-lance.yang@linux.dev \
--to=lance.yang@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=david@kernel.org \
--cc=dev.jain@arm.com \
--cc=hannes@cmpxchg.org \
--cc=jackmanb@google.com \
--cc=liam@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mhocko@suse.com \
--cc=npache@redhat.com \
--cc=rppt@kernel.org \
--cc=ryan.roberts@arm.com \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
--cc=ziy@nvidia.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