Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] mm/madvise: avoid skipping pages after splitting large folios
@ 2026-08-06  5:55 Yunhui Cui
  2026-08-06  6:29 ` Andrew Morton
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Yunhui Cui @ 2026-08-06  5:55 UTC (permalink / raw)
  To: akpm, liam, ljs, david, vbabka, jannh, 00moses.alexander00,
	linux-mm, linux-kernel
  Cc: Yunhui Cui, stable

madvise_inject_error() advances through the requested range using the
size of the page returned by get_user_pages_fast(). Saving the size
before error injection is required for hugetlb pages because successful
soft offlining can dissolve the source huge page.

That stride is incorrect for non-hugetlb large folios in system memory.
The memory failure handlers split such a folio and handle only the base
page for the supplied PFN. Advancing by the pre-split folio size then
skips the remaining pages in the requested range while madvise() still
reports success.

Advance by PAGE_SIZE for non-hugetlb folios in system memory. Retain
folio_size() for hugetlb and ZONE_DEVICE folios, as compound Device DAX
folios are handled as a whole.

Fixes: 19bfbe22f59a ("mm, hugetlb, soft_offline: save compound page order before page migration")
Cc: stable@vger.kernel.org
Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
---
 mm/madvise.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/mm/madvise.c b/mm/madvise.c
index 5a09cc24f04a0..e9d4c3bbc5290 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -1455,20 +1455,25 @@ static int madvise_inject_error(struct madvise_behavior *madv_behavior)
 
 	for (; start < end; start += size) {
 		unsigned long pfn;
+		struct folio *folio;
 		struct page *page;
 		int ret;
 
 		ret = get_user_pages_fast(start, 1, 0, &page);
 		if (ret != 1)
 			return ret;
+		folio = page_folio(page);
 		pfn = page_to_pfn(page);
 
 		/*
-		 * When soft offlining hugepages, after migrating the page
-		 * we dissolve it, therefore in the second loop "page" will
-		 * no longer be a compound page.
+		 * Non-hugetlb large folios in system memory are split and only
+		 * the addressed base page is handled. Hugetlb folios may be
+		 * dissolved and ZONE_DEVICE folios may be handled as a whole,
+		 * so save their size before error injection.
 		 */
-		size = page_size(compound_head(page));
+		size = PAGE_SIZE;
+		if (folio_test_hugetlb(folio) || folio_is_zone_device(folio))
+			size = folio_size(folio);
 
 		if (madv_behavior->behavior == MADV_SOFT_OFFLINE) {
 			pr_info("Soft offlining pfn %#lx at process virtual address %#lx\n",
-- 
2.39.5



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

* Re: [PATCH v2] mm/madvise: avoid skipping pages after splitting large folios
  2026-08-06  5:55 [PATCH v2] mm/madvise: avoid skipping pages after splitting large folios Yunhui Cui
@ 2026-08-06  6:29 ` Andrew Morton
  2026-08-06  8:19   ` [External] " yunhui cui
  2026-08-06  8:41 ` David Hildenbrand (Arm)
  2026-08-06  9:11 ` Lorenzo Stoakes (ARM)
  2 siblings, 1 reply; 10+ messages in thread
From: Andrew Morton @ 2026-08-06  6:29 UTC (permalink / raw)
  To: Yunhui Cui
  Cc: liam, ljs, david, vbabka, jannh, 00moses.alexander00, linux-mm,
	linux-kernel, stable

On Thu,  6 Aug 2026 13:55:01 +0800 Yunhui Cui <cuiyunhui@bytedance.com> wrote:

> madvise_inject_error() advances through the requested range using the
> size of the page returned by get_user_pages_fast(). Saving the size
> before error injection is required for hugetlb pages because successful
> soft offlining can dissolve the source huge page.
> 
> That stride is incorrect for non-hugetlb large folios in system memory.
> The memory failure handlers split such a folio and handle only the base
> page for the supplied PFN. Advancing by the pre-split folio size then
> skips the remaining pages in the requested range while madvise() still
> reports success.
> 
> Advance by PAGE_SIZE for non-hugetlb folios in system memory. Retain
> folio_size() for hugetlb and ZONE_DEVICE folios, as compound Device DAX
> folios are handled as a whole.

Thanks.

> Fixes: 19bfbe22f59a ("mm, hugetlb, soft_offline: save compound page order before page migration")
> Cc: stable@vger.kernel.org
> Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>

Should there be an Assisted-by: here?

When fixing a bug, please always describe the userspace-visible runtime
effects of that bug.  Especially when proposing a -stable backport.


I asked Gemini this question and then pasted in your email.  It told me
stuff, but I don't know if it's correct.  In this case it would be good
to hear that description in your own words, please.

And perhaps a means of reproducing the bug - clearly our selftests/
coverage here is poor.


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

* Re: [External] Re: [PATCH v2] mm/madvise: avoid skipping pages after splitting large folios
  2026-08-06  6:29 ` Andrew Morton
@ 2026-08-06  8:19   ` yunhui cui
  0 siblings, 0 replies; 10+ messages in thread
From: yunhui cui @ 2026-08-06  8:19 UTC (permalink / raw)
  To: Andrew Morton
  Cc: liam, ljs, david, vbabka, jannh, 00moses.alexander00, linux-mm,
	linux-kernel, stable

Hi Andrew,

On Thu, Aug 6, 2026 at 2:29 PM Andrew Morton <akpm@linux-foundation.org> wrote:
>
> On Thu,  6 Aug 2026 13:55:01 +0800 Yunhui Cui <cuiyunhui@bytedance.com> wrote:
>
> > madvise_inject_error() advances through the requested range using the
> > size of the page returned by get_user_pages_fast(). Saving the size
> > before error injection is required for hugetlb pages because successful
> > soft offlining can dissolve the source huge page.
> >
> > That stride is incorrect for non-hugetlb large folios in system memory.
> > The memory failure handlers split such a folio and handle only the base
> > page for the supplied PFN. Advancing by the pre-split folio size then
> > skips the remaining pages in the requested range while madvise() still
> > reports success.
> >
> > Advance by PAGE_SIZE for non-hugetlb folios in system memory. Retain
> > folio_size() for hugetlb and ZONE_DEVICE folios, as compound Device DAX
> > folios are handled as a whole.
>
> Thanks.
>
> > Fixes: 19bfbe22f59a ("mm, hugetlb, soft_offline: save compound page order before page migration")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
>
> Should there be an Assisted-by: here?
>
> When fixing a bug, please always describe the userspace-visible runtime
> effects of that bug.  Especially when proposing a -stable backport.
>
>
> I asked Gemini this question and then pasted in your email.  It told me
> stuff, but I don't know if it's correct.  In this case it would be good
> to hear that description in your own words, please.
>
> And perhaps a means of reproducing the bug - clearly our selftests/
> coverage here is poor.

The issue can be reproduced with the softoffline helper from
avocado-misc-tests. With 64K mTHP enabled:
./softoffline -m private -n 50
the test consistently failed with:
pfn matches, softoffline failed at 10

After temporarily disabling 64K mTHP:
echo never > /sys/kernel/mm/transparent_hugepage/hugepages-64kB/enabled
./softoffline -m private -n 50
the test passed in five consecutive runs:
Softoffline succeeded!

Thanks,
Yunhui


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

* Re: [PATCH v2] mm/madvise: avoid skipping pages after splitting large folios
  2026-08-06  5:55 [PATCH v2] mm/madvise: avoid skipping pages after splitting large folios Yunhui Cui
  2026-08-06  6:29 ` Andrew Morton
@ 2026-08-06  8:41 ` David Hildenbrand (Arm)
  2026-08-06  9:13   ` Lorenzo Stoakes (ARM)
  2026-08-06  9:11 ` Lorenzo Stoakes (ARM)
  2 siblings, 1 reply; 10+ messages in thread
From: David Hildenbrand (Arm) @ 2026-08-06  8:41 UTC (permalink / raw)
  To: Yunhui Cui, akpm, liam, ljs, vbabka, jannh, 00moses.alexander00,
	linux-mm, linux-kernel
  Cc: stable

On 8/6/26 07:55, Yunhui Cui wrote:
> madvise_inject_error() advances through the requested range using the
> size of the page returned by get_user_pages_fast(). Saving the size
> before error injection is required for hugetlb pages because successful
> soft offlining can dissolve the source huge page.
> 
> That stride is incorrect for non-hugetlb large folios in system memory.
> The memory failure handlers split such a folio and handle only the base
> page for the supplied PFN. Advancing by the pre-split folio size then
> skips the remaining pages in the requested range while madvise() still
> reports success.
> 
> Advance by PAGE_SIZE for non-hugetlb folios in system memory. Retain
> folio_size() for hugetlb and ZONE_DEVICE folios, as compound Device DAX
> folios are handled as a whole.
> 
> Fixes: 19bfbe22f59a ("mm, hugetlb, soft_offline: save compound page order before page migration")
> Cc: stable@vger.kernel.org
> Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
> ---
>  mm/madvise.c | 13 +++++++++----
>  1 file changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/mm/madvise.c b/mm/madvise.c
> index 5a09cc24f04a0..e9d4c3bbc5290 100644
> --- a/mm/madvise.c
> +++ b/mm/madvise.c
> @@ -1455,20 +1455,25 @@ static int madvise_inject_error(struct madvise_behavior *madv_behavior)
>  
>  	for (; start < end; start += size) {
>  		unsigned long pfn;
> +		struct folio *folio;
>  		struct page *page;
>  		int ret;
>  
>  		ret = get_user_pages_fast(start, 1, 0, &page);
>  		if (ret != 1)
>  			return ret;
> +		folio = page_folio(page);
>  		pfn = page_to_pfn(page);
>  
>  		/*
> -		 * When soft offlining hugepages, after migrating the page
> -		 * we dissolve it, therefore in the second loop "page" will
> -		 * no longer be a compound page.
> +		 * Non-hugetlb large folios in system memory are split and only
> +		 * the addressed base page is handled. Hugetlb folios may be
> +		 * dissolved and ZONE_DEVICE folios may be handled as a whole,
> +		 * so save their size before error injection.
>  		 */
> -		size = page_size(compound_head(page));
> +		size = PAGE_SIZE;
> +		if (folio_test_hugetlb(folio) || folio_is_zone_device(folio))
> +			size = folio_size(folio);


We should never ever try deferring "how much has been mapped" from a single PTE.

While this currently works for hugetlb, it's just an anti-pattern to throw
hugetlb checks and similar around.

So this is not the way to fix it.

-- 
Cheers,

David


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

* Re: [PATCH v2] mm/madvise: avoid skipping pages after splitting large folios
  2026-08-06  5:55 [PATCH v2] mm/madvise: avoid skipping pages after splitting large folios Yunhui Cui
  2026-08-06  6:29 ` Andrew Morton
  2026-08-06  8:41 ` David Hildenbrand (Arm)
@ 2026-08-06  9:11 ` Lorenzo Stoakes (ARM)
  2026-08-06 11:35   ` David Hildenbrand (Arm)
  2 siblings, 1 reply; 10+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-08-06  9:11 UTC (permalink / raw)
  To: Yunhui Cui
  Cc: akpm, liam, david, vbabka, jannh, 00moses.alexander00, linux-mm,
	linux-kernel, stable

As a newer contributor to mm please wait for feedback on a v1 from reviewers
before respinning, thanks :)

On Thu, Aug 06, 2026 at 01:55:01PM +0800, Yunhui Cui wrote:
> madvise_inject_error() advances through the requested range using the
> size of the page returned by get_user_pages_fast(). Saving the size
> before error injection is required for hugetlb pages because successful
> soft offlining can dissolve the source huge page.

But you're also changing the behaviour for MADV_HWPOISON not only
MADV_SOFT_OFFLINE? Explain?

Also mention the specific madvise flags...

>
> That stride is incorrect for non-hugetlb large folios in system memory.
> The memory failure handlers split such a folio and handle only the base
> page for the supplied PFN. Advancing by the pre-split folio size then
> skips the remaining pages in the requested range while madvise() still
> reports success.

As Andrew also asks:

How did you find out about this? Is this a theoretical issue?

Why? What? Who?...

>
> Advance by PAGE_SIZE for non-hugetlb folios in system memory. Retain
> folio_size() for hugetlb and ZONE_DEVICE folios, as compound Device DAX
> folios are handled as a whole.

You get a folio to check to see if it's DAX when you have the VMA that you can
check for DAX?...

>
> Fixes: 19bfbe22f59a ("mm, hugetlb, soft_offline: save compound page order before page migration")

4.14...!

> Cc: stable@vger.kernel.org

Stuff that touches folio and soft offline-adjacent THP is going to be tricky to
backport correctly.

And in madvise(2):

              This feature is intended for testing of memory error-
              handling code; it is available only if the kernel was
              configured with CONFIG_MEMORY_FAILURE.

For both MADV_SOFT_OFFLINE and MADV_HWPOISON.

So I don't see why this should be backported. You might accidentally not quite
offline/poison everything you intended in a test but that isn't a bug?

Given nobody's complained in nearly a decade I don't think this matters.

Also you're suggesting backporting to pre-folio ancient times which is going to
make this horrid and tricky there too.

> Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>

This could really do with a test to reproduce the issue. Mm selftests already
has memory failure stuff.

Please provide one to demonstrate the issue.

> ---
>  mm/madvise.c | 13 +++++++++----
>  1 file changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/mm/madvise.c b/mm/madvise.c
> index 5a09cc24f04a0..e9d4c3bbc5290 100644
> --- a/mm/madvise.c
> +++ b/mm/madvise.c
> @@ -1455,20 +1455,25 @@ static int madvise_inject_error(struct madvise_behavior *madv_behavior)
>
>  	for (; start < end; start += size) {
>  		unsigned long pfn;
> +		struct folio *folio;
>  		struct page *page;
>  		int ret;
>
>  		ret = get_user_pages_fast(start, 1, 0, &page);
>  		if (ret != 1)
>  			return ret;
> +		folio = page_folio(page);
>  		pfn = page_to_pfn(page);
>
>  		/*
> -		 * When soft offlining hugepages, after migrating the page
> -		 * we dissolve it, therefore in the second loop "page" will
> -		 * no longer be a compound page.
> +		 * Non-hugetlb large folios in system memory are split and only

'non-hugetlb large folios' is horrid. Large folios. And 'system memory' is
redundant.

> +		 * the addressed base page is handled. Hugetlb folios may be
> +		 * dissolved and ZONE_DEVICE folios may be handled as a whole,
> +		 * so save their size before error injection.
>  		 */

You're discarding the whole thing of the page no longer being the head. But I
guess with folios we don't need to mention that.

This whole thing can made more succinct like:

		/* DAX and hugetlb are consumed in folio chunks, everything else is split. */

> -		size = page_size(compound_head(page));

Yuck at this existing code.

> +		size = PAGE_SIZE;
> +		if (folio_test_hugetlb(folio) || folio_is_zone_device(folio))
> +			size = folio_size(folio);

It's really disgusting that hugetlb is treated differently with everything else
treated page-at-a-time.

Honestly I'd prefer to see a folio helper so the main loop can just assume
folio size stride.

But you can enter midway through a bloody folio. Ugh. So maybe that doesn't
work.

Let's at least split out the folio check into a helper to make things
clearer:

static bool poison_splits_folio(const struct folio *folio)
{
	/* Hugetlb is, as always, a world unto itself. */
	if (folio_test_hugetlb(folio))
		return false;
	/* Soft-offline errors out, hwpoison traverse DAX intact. */
	if (folio_is_zone_device(folio))
		return false;
	return true;
}

Then for your patch:

-		size = PAGE_SIZE;
-		if (folio_test_hugetlb(folio) || folio_is_zone_device(folio))
-			size = folio_size(folio);
+		size = poison_splits_folio(folio) ? PAGE_SIZE : folio_size(folio);

I tried writing something that was neater and nicer but AI kept pointing
out how it was totally broken and I really really hate this code (not your
fault :).

--
Cheers, Lorenzo


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

* Re: [PATCH v2] mm/madvise: avoid skipping pages after splitting large folios
  2026-08-06  8:41 ` David Hildenbrand (Arm)
@ 2026-08-06  9:13   ` Lorenzo Stoakes (ARM)
  0 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-08-06  9:13 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Yunhui Cui, akpm, liam, vbabka, jannh, 00moses.alexander00,
	linux-mm, linux-kernel, stable

On Thu, Aug 06, 2026 at 10:41:06AM +0200, David Hildenbrand (Arm) wrote:
> On 8/6/26 07:55, Yunhui Cui wrote:
> > madvise_inject_error() advances through the requested range using the
> > size of the page returned by get_user_pages_fast(). Saving the size
> > before error injection is required for hugetlb pages because successful
> > soft offlining can dissolve the source huge page.
> >
> > That stride is incorrect for non-hugetlb large folios in system memory.
> > The memory failure handlers split such a folio and handle only the base
> > page for the supplied PFN. Advancing by the pre-split folio size then
> > skips the remaining pages in the requested range while madvise() still
> > reports success.
> >
> > Advance by PAGE_SIZE for non-hugetlb folios in system memory. Retain
> > folio_size() for hugetlb and ZONE_DEVICE folios, as compound Device DAX
> > folios are handled as a whole.
> >
> > Fixes: 19bfbe22f59a ("mm, hugetlb, soft_offline: save compound page order before page migration")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
> > ---
> >  mm/madvise.c | 13 +++++++++----
> >  1 file changed, 9 insertions(+), 4 deletions(-)
> >
> > diff --git a/mm/madvise.c b/mm/madvise.c
> > index 5a09cc24f04a0..e9d4c3bbc5290 100644
> > --- a/mm/madvise.c
> > +++ b/mm/madvise.c
> > @@ -1455,20 +1455,25 @@ static int madvise_inject_error(struct madvise_behavior *madv_behavior)
> >
> >  	for (; start < end; start += size) {
> >  		unsigned long pfn;
> > +		struct folio *folio;
> >  		struct page *page;
> >  		int ret;
> >
> >  		ret = get_user_pages_fast(start, 1, 0, &page);
> >  		if (ret != 1)
> >  			return ret;
> > +		folio = page_folio(page);
> >  		pfn = page_to_pfn(page);
> >
> >  		/*
> > -		 * When soft offlining hugepages, after migrating the page
> > -		 * we dissolve it, therefore in the second loop "page" will
> > -		 * no longer be a compound page.
> > +		 * Non-hugetlb large folios in system memory are split and only
> > +		 * the addressed base page is handled. Hugetlb folios may be
> > +		 * dissolved and ZONE_DEVICE folios may be handled as a whole,
> > +		 * so save their size before error injection.
> >  		 */
> > -		size = page_size(compound_head(page));
> > +		size = PAGE_SIZE;
> > +		if (folio_test_hugetlb(folio) || folio_is_zone_device(folio))
> > +			size = folio_size(folio);
>
>
> We should never ever try deferring "how much has been mapped" from a single PTE.

Inferring? :)

>
> While this currently works for hugetlb, it's just an anti-pattern to throw
> hugetlb checks and similar around.
>
> So this is not the way to fix it.

All of this code is disgusting. Also what about an address range that is
partially inside a folio...? Then presumably the whole folio is discarded? Or
does it figure it out somehow and does the split for the rest of the range?

And what if end < the end of the hugetlb size?

Ugh god I hate all of this, it's so so bad. And hugetlb being the special
snowflake is the cherry on the s*** cake...

>
> --
> Cheers,
>
> David

--
Cheers, Lorenzo


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

* Re: [PATCH v2] mm/madvise: avoid skipping pages after splitting large folios
  2026-08-06  9:11 ` Lorenzo Stoakes (ARM)
@ 2026-08-06 11:35   ` David Hildenbrand (Arm)
  2026-08-06 14:34     ` Lorenzo Stoakes (ARM)
  0 siblings, 1 reply; 10+ messages in thread
From: David Hildenbrand (Arm) @ 2026-08-06 11:35 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM), Yunhui Cui
  Cc: akpm, liam, vbabka, jannh, 00moses.alexander00, linux-mm,
	linux-kernel, stable

> 
> Let's at least split out the folio check into a helper to make things
> clearer:
> 
> static bool poison_splits_folio(const struct folio *folio)
> {
> 	/* Hugetlb is, as always, a world unto itself. */
> 	if (folio_test_hugetlb(folio))
> 		return false;
> 	/* Soft-offline errors out, hwpoison traverse DAX intact. */
> 	if (folio_is_zone_device(folio))
> 		return false;
> 	return true;
> }
> 
> Then for your patch:
> 
> -		size = PAGE_SIZE;
> -		if (folio_test_hugetlb(folio) || folio_is_zone_device(folio))
> -			size = folio_size(folio);
> +		size = poison_splits_folio(folio) ? PAGE_SIZE : folio_size(folio);
> 
> I tried writing something that was neater and nicer but AI kept pointing
> out how it was totally broken and I really really hate this code (not your
> fault :).

No, I don't think any such special casing on folios is the right way to handle it.

-- 
Cheers,

David


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

* Re: [PATCH v2] mm/madvise: avoid skipping pages after splitting large folios
  2026-08-06 11:35   ` David Hildenbrand (Arm)
@ 2026-08-06 14:34     ` Lorenzo Stoakes (ARM)
  2026-08-06 14:46       ` David Hildenbrand (Arm)
  0 siblings, 1 reply; 10+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-08-06 14:34 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Yunhui Cui, akpm, liam, vbabka, jannh, 00moses.alexander00,
	linux-mm, linux-kernel, stable

On Thu, Aug 06, 2026 at 01:35:30PM +0200, David Hildenbrand (Arm) wrote:
> >
> > Let's at least split out the folio check into a helper to make things
> > clearer:
> >
> > static bool poison_splits_folio(const struct folio *folio)
> > {
> > 	/* Hugetlb is, as always, a world unto itself. */
> > 	if (folio_test_hugetlb(folio))
> > 		return false;
> > 	/* Soft-offline errors out, hwpoison traverse DAX intact. */
> > 	if (folio_is_zone_device(folio))
> > 		return false;
> > 	return true;
> > }
> >
> > Then for your patch:
> >
> > -		size = PAGE_SIZE;
> > -		if (folio_test_hugetlb(folio) || folio_is_zone_device(folio))
> > -			size = folio_size(folio);
> > +		size = poison_splits_folio(folio) ? PAGE_SIZE : folio_size(folio);
> >
> > I tried writing something that was neater and nicer but AI kept pointing
> > out how it was totally broken and I really really hate this code (not your
> > fault :).
>
> No, I don't think any such special casing on folios is the right way to handle it.

I mean the issue here is the stride varies depending on whether the thing is
hugetlb or not (and some weird DAX thing), and the poisoning causes a split
otherwise so if you want to poison a range you have to account for that.

But I agree there's something wrong here.

At first I thought 'handle at a folio granularity and assume folio slide' but
stupidly this code allows you to poison partial large folio ranges (I don't
think it should and given it's debug/testing crap I think it's fine to change
that).

But then maybe the answer is to change the interface in general? But at the same
time poisoning happens at a pfn level...

It's kinda weird to allow such an open-ended debug thing. I'd prefer we just
disallowed hugetlb, or did a split right away if THP or something.

Anyway hwpoison is a swamp of neglect and hackery regardless.

>
> --
> Cheers,
>
> David

--
Cheers, Lorenzo


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

* Re: [PATCH v2] mm/madvise: avoid skipping pages after splitting large folios
  2026-08-06 14:34     ` Lorenzo Stoakes (ARM)
@ 2026-08-06 14:46       ` David Hildenbrand (Arm)
  2026-08-06 15:40         ` Lorenzo Stoakes (ARM)
  0 siblings, 1 reply; 10+ messages in thread
From: David Hildenbrand (Arm) @ 2026-08-06 14:46 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Yunhui Cui, akpm, liam, vbabka, jannh, 00moses.alexander00,
	linux-mm, linux-kernel, stable

On 8/6/26 16:34, Lorenzo Stoakes (ARM) wrote:
> On Thu, Aug 06, 2026 at 01:35:30PM +0200, David Hildenbrand (Arm) wrote:
>>>
>>> Let's at least split out the folio check into a helper to make things
>>> clearer:
>>>
>>> static bool poison_splits_folio(const struct folio *folio)
>>> {
>>> 	/* Hugetlb is, as always, a world unto itself. */
>>> 	if (folio_test_hugetlb(folio))
>>> 		return false;
>>> 	/* Soft-offline errors out, hwpoison traverse DAX intact. */
>>> 	if (folio_is_zone_device(folio))
>>> 		return false;
>>> 	return true;
>>> }
>>>
>>> Then for your patch:
>>>
>>> -		size = PAGE_SIZE;
>>> -		if (folio_test_hugetlb(folio) || folio_is_zone_device(folio))
>>> -			size = folio_size(folio);
>>> +		size = poison_splits_folio(folio) ? PAGE_SIZE : folio_size(folio);
>>>
>>> I tried writing something that was neater and nicer but AI kept pointing
>>> out how it was totally broken and I really really hate this code (not your
>>> fault :).
>>
>> No, I don't think any such special casing on folios is the right way to handle it.
> 
> I mean the issue here is the stride varies depending on whether the thing is
> hugetlb or not (and some weird DAX thing), and the poisoning causes a split
> otherwise so if you want to poison a range you have to account for that.

We GUP'ed a single page and now try to be smart about which other pages we'd GUP
next.

That's just wrong, and hugetlb special-casing is just ugly.

The problem here is that, if we GUP'ed a page and poisoned it, the GUP'ing the
next page might fail and we'd return an error.

But maybe that error can simply be handled? We have FOLL_HWPOISON.

So maybe we can just use FOLL_HWPOISON and skip over the entries that already
return -EHWPOISON?

-- 
Cheers,

David


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

* Re: [PATCH v2] mm/madvise: avoid skipping pages after splitting large folios
  2026-08-06 14:46       ` David Hildenbrand (Arm)
@ 2026-08-06 15:40         ` Lorenzo Stoakes (ARM)
  0 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-08-06 15:40 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Yunhui Cui, akpm, liam, vbabka, jannh, 00moses.alexander00,
	linux-mm, linux-kernel, stable

On Thu, Aug 06, 2026 at 04:46:10PM +0200, David Hildenbrand (Arm) wrote:
> On 8/6/26 16:34, Lorenzo Stoakes (ARM) wrote:
> > On Thu, Aug 06, 2026 at 01:35:30PM +0200, David Hildenbrand (Arm) wrote:
> >>>
> >>> Let's at least split out the folio check into a helper to make things
> >>> clearer:
> >>>
> >>> static bool poison_splits_folio(const struct folio *folio)
> >>> {
> >>> 	/* Hugetlb is, as always, a world unto itself. */
> >>> 	if (folio_test_hugetlb(folio))
> >>> 		return false;
> >>> 	/* Soft-offline errors out, hwpoison traverse DAX intact. */
> >>> 	if (folio_is_zone_device(folio))
> >>> 		return false;
> >>> 	return true;
> >>> }
> >>>
> >>> Then for your patch:
> >>>
> >>> -		size = PAGE_SIZE;
> >>> -		if (folio_test_hugetlb(folio) || folio_is_zone_device(folio))
> >>> -			size = folio_size(folio);
> >>> +		size = poison_splits_folio(folio) ? PAGE_SIZE : folio_size(folio);
> >>>
> >>> I tried writing something that was neater and nicer but AI kept pointing
> >>> out how it was totally broken and I really really hate this code (not your
> >>> fault :).
> >>
> >> No, I don't think any such special casing on folios is the right way to handle it.
> >
> > I mean the issue here is the stride varies depending on whether the thing is
> > hugetlb or not (and some weird DAX thing), and the poisoning causes a split
> > otherwise so if you want to poison a range you have to account for that.
>
> We GUP'ed a single page and now try to be smart about which other pages we'd GUP
> next.
>
> That's just wrong, and hugetlb special-casing is just ugly.
>
> The problem here is that, if we GUP'ed a page and poisoned it, the GUP'ing the
> next page might fail and we'd return an error.
>
> But maybe that error can simply be handled? We have FOLL_HWPOISON.
>
> So maybe we can just use FOLL_HWPOISON and skip over the entries that already
> return -EHWPOISON?

Yup this is ugly debug code so that works for me.

>
> --
> Cheers,
>
> David

--
Cheers, Lorenzo


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

end of thread, other threads:[~2026-08-06 15:40 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-06  5:55 [PATCH v2] mm/madvise: avoid skipping pages after splitting large folios Yunhui Cui
2026-08-06  6:29 ` Andrew Morton
2026-08-06  8:19   ` [External] " yunhui cui
2026-08-06  8:41 ` David Hildenbrand (Arm)
2026-08-06  9:13   ` Lorenzo Stoakes (ARM)
2026-08-06  9:11 ` Lorenzo Stoakes (ARM)
2026-08-06 11:35   ` David Hildenbrand (Arm)
2026-08-06 14:34     ` Lorenzo Stoakes (ARM)
2026-08-06 14:46       ` David Hildenbrand (Arm)
2026-08-06 15:40         ` Lorenzo Stoakes (ARM)

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