Re: [PATCH v7 01/13] memory-failure: Fix hardware poison check in unpoison_memory() again

[email protected] Thu, 30 Jul 2026 22:39:57 -0700
Newsgroups org.kernel.vger.linux-fsdevel,org.kernel.vger.stable,org.kvack.linux-mm
Message-ID <[email protected]>
On 7/28/2026 1:43 PM, Matthew Wilcox (Oracle) wrote:
> The earlier patch (6c54312f9689) that attempted to fix unpoison_memory() 
> was incorrect for hugetlb folios. Before a6fddef49eef, we checked the 
> head page for poison (which was correct for hugetlb and incorrect for 
> THP). We are currently incapable
> 
> 
> The earlier patch (6c54312f9689) that attempted to fix unpoison_memory()
> was incorrect for hugetlb folios.  Before a6fddef49eef, we checked
> the head page for poison (which was correct for hugetlb and incorrect
> for THP).  We are currently incapable of unpoisoning pages (other than
> the first page) in a hugetlb folio.
> 
> Use is_page_hwpoison() which handles hugetlb pages sufficiently well for
> this purpose.  This is racy as we don't have a reference on the folio at
> this point, but fixing that properly requires deeper surgery and this
> is a CAP_SYS_ADMIN path only so this will do for the moment and can be
> easily backported.  It's no worse than the situation before a6fddef49eef.
> 
> The other bug in a6fddef49eef is that we currently clear the HWPoison
> flag on the precise page, which is wrong for hugetlb.  Fix that too.
> 
> Fixes: a6fddef49eef ("mm/memory-failure: convert unpoison_memory() to folios")
> Cc: [email protected]
> Cc: Miaohe Lin <[email protected]>
> Signed-off-by: Matthew Wilcox (Oracle) <[email protected]>
> ---
>   mm/memory-failure.c | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> index 51508a55c405..944e6e1d4971 100644
> --- a/mm/memory-failure.c
> +++ b/mm/memory-failure.c
> @@ -2695,8 +2695,8 @@ int unpoison_memory(unsigned long pfn)
>   		goto unlock_mutex;
>   	}
>   
> -	if (!PageHWPoison(p)) {
> -		unpoison_pr_info("%#lx: page was already unpoisoned\n",
> +	if (!is_page_hwpoison(p)) {
> +		unpoison_pr_info("%#lx: page is not poisoned\n",
>   				 pfn, &unpoison_rs);
>   		goto unlock_mutex;
>   	}
> @@ -2748,6 +2748,7 @@ int unpoison_memory(unsigned long pfn)
>   				folio_put(folio);
>   				goto unlock_mutex;
>   			}
> +			p = &folio->page;
>   		}
>   
>   		folio_put(folio);
> -- 
> 2.47.3
> 

I think I spot another pre-existing issue in unpoison_memory():
the XXX line doesn't work for non-hugetlb free large folio because it'll
just try to clear PG_hwpoison in the folio->page, not the precise 'pfn' 
page.  Something like below could do.


diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 51508a55c405..14915718ace5 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -2730,8 +2730,10 @@ int unpoison_memory(unsigned long pfn)
                         count = folio_free_raw_hwp(folio, false);
                         if (count == 0)
                                 goto unlock_mutex;
+                       else
+                               ret = folio_test_clear_hwpoison(folio) ? 
0 : -EBUSY;
                 }
-               ret = folio_test_clear_hwpoison(folio) ? 0 : -EBUSY; 
<--- XXX
+               ret = TestClearPageHWPoison(p) ? 0 : -EBUSY;
         } else if (ghp < 0) {
                 if (ghp == -EHWPOISON) {
                         ret = put_page_back_buddy(p) ? 0 : -EBUSY;

thanks,
-jane