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