On 7/31/2026 1:07 PM, Matthew Wilcox (Oracle) wrote:
> 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
>
>
> 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.
>
> 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(-)
>
> 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));
> }
>
> +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 page *page)
> return true;
> folio = 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;
> };
>
> -/*
> - * 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;
>
> - if (!folio_test_has_hwpoisoned(folio))
> - return false;
> -
> spin_lock_irqsave(&hwp_page_lock, flags);
>
> /*
> @@ -1851,6 +1846,40 @@ bool hugetlb_page_hwpoison(const struct folio *folio, const struct page *page)
> return p != NULL;
> }
>
> +/*
> + * 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 = page_folio(page);
> + if (!folio_test_huge_poison(folio)) {
> + ret = PageHWPoison(page);
> + goto unlock;
> + }
> +
> + ret = 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 move_flag)
> {
> struct hwp_page *p, *next;
> --
> 2.47.3
>
Reviewed-by: Jane Chu <[email protected]>
thanks,
-jane
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.