Re: [PATCH v8 10/15] mm: Check individual hugetlb pages for poison

[email protected] Mon, 3 Aug 2026 23:59:25 -0700
Newsgroups gmane.linux.file-systems,gmane.linux.kernel.mm
Message-ID <[email protected]>

On 7/31/2026 1:07 PM, Matthew Wilcox (Oracle) wrote:
> So far, is_page_hwpoison() has returned true for the entire poisoned=20
> hugetlb folio, but we can usually allow access to the pages which aren't=
=20
> poisoned. It's slightly tricky due to not having a reference to the=20
> folio, but the hugetlb lock can
>=20
>=20
> So far, is_page_hwpoison() has returned true for the entire poisoned
> hugetlb folio, but we can usually allow access to the pages which
> aren't poisoned.  It's slightly tricky due to not having a reference
> to the folio, but the hugetlb lock can save us here.
>=20
> Signed-off-by: Matthew Wilcox (Oracle) <[email protected]>
> ---
>   include/linux/page-flags.h |  4 +++-
>   mm/memory-failure.c        | 43 +++++++++++++++++++++++++++++++-------
>   2 files changed, 39 insertions(+), 8 deletions(-)
>=20
> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> index 4fab3fbfd430..ee026ba9b0b5 100644
> --- a/include/linux/page-flags.h
> +++ b/include/linux/page-flags.h
> @@ -1094,6 +1094,8 @@ static inline bool PageHuge(const struct page *page)
>   	return folio_test_hugetlb(page_folio(page));
>   }
>  =20
> +bool hugetlb_unref_page_hwpoison(const struct page *page);
> +
>   /*
>    * Check if a page is currently marked HWPoisoned.  This check is best
>    * effort only and inherently racy: there is no way to synchronize with
> @@ -1108,7 +1110,7 @@ static inline bool is_page_hwpoison(const struct pa=
ge *page)
>   		return true;
>   	folio =3D page_folio(page);
>   	if (folio_test_huge_poison(folio))
> -		return true;
> +		return hugetlb_unref_page_hwpoison(page);
>   	/* In case we raced with hugetlb transferring flags */
>   	return PageHWPoison(page);
>   }
> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> index 437a2be6c58c..c0a402522c21 100644
> --- a/mm/memory-failure.c
> +++ b/mm/memory-failure.c
> @@ -1820,17 +1820,12 @@ struct hwp_page {
>   	struct page *page;
>   };
>  =20
> -/*
> - * Check if a given @page in a hugetlb folio is HWPOISON.
> - */
> -bool hugetlb_page_hwpoison(const struct folio *folio, const struct page =
*page)
> +static bool precise_page_poisoned(const struct folio *folio,
> +		const struct page *page)
>   {
>   	const struct hwp_page *p;
>   	unsigned long flags;
>  =20
> -	if (!folio_test_has_hwpoisoned(folio))
> -		return false;
> -
>   	spin_lock_irqsave(&hwp_page_lock, flags);
>  =20
>   	/*
> @@ -1851,6 +1846,40 @@ bool hugetlb_page_hwpoison(const struct folio *fol=
io, const struct page *page)
>   	return p !=3D NULL;
>   }
>  =20
> +/*
> + * Check if a given @page in a hugetlb folio is HWPOISON.
> + */
> +bool hugetlb_page_hwpoison(const struct folio *folio, const struct page =
*page)
> +{
> +	if (!folio_test_has_hwpoisoned(folio))
> +		return false;
> +
> +	return precise_page_poisoned(folio, page);
> +}
> +
> +/*
> + * We have no reference on the folio containing this page.
> + * The hugetlb_lock keeps hugetlb folios from being freed.
> + */
> +bool hugetlb_unref_page_hwpoison(const struct page *page)
> +{
> +	const struct folio *folio;
> +	unsigned long flags;
> +	bool ret;
> +
> +	spin_lock_irqsave(&hugetlb_lock, flags);
> +	folio =3D page_folio(page);
> +	if (!folio_test_huge_poison(folio)) {
> +		ret =3D PageHWPoison(page);
> +		goto unlock;
> +	}
> +
> +	ret =3D precise_page_poisoned(folio, page);
> +unlock:
> +	spin_unlock_irqrestore(&hugetlb_lock, flags);
> +	return ret;
> +}
> +
>   static unsigned long __folio_free_raw_hwp(struct folio *folio, bool mov=
e_flag)
>   {
>   	struct hwp_page *p, *next;
> --=20
> 2.47.3
>=20

Reviewed-by: Jane Chu <[email protected]>

thanks,
-jane