Re: [PATCH v6 3/5] mm/memory-failure: set has_hwpoisoned flags on dissolved HugeTLB folio
From: Jiaqi Yan
Date: Fri Jul 24 2026 - 23:06:56 EST
On Sun, Jul 5, 2026 at 11:07 AM Jiaqi Yan <jiaqiyan@xxxxxxxxxx> wrote:
>
> When a free HWPoison HugeTLB folio is dissolved, it becomes
> non-HugeTLB and is released to buddy allocator as a high-order
> folio.
>
> Set has_hwpoisoned flags on the high-order folio so that buddy
> allocator can tell that it contains certain HWPoison page(s),
> and can handle it specially with free_has_hwpoisoned().
>
> Signed-off-by: Jiaqi Yan <jiaqiyan@xxxxxxxxxx>
> Acked-by: Miaohe Lin <linmiaohe@xxxxxxxxxx>
> ---
> include/linux/page-flags.h | 2 +-
> mm/memory-failure.c | 1 +
> 2 files changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> index 7a863572adce..3cd524e04a30 100644
> --- a/include/linux/page-flags.h
> +++ b/include/linux/page-flags.h
> @@ -879,7 +879,7 @@ FOLIO_FLAG_FALSE(partially_mapped)
>
> #define PG_head_mask ((1UL << PG_head))
>
> -#if defined(CONFIG_MEMORY_FAILURE) && defined(CONFIG_TRANSPARENT_HUGEPAGE)
> +#if defined(CONFIG_MEMORY_FAILURE) && (defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLB_PAGE))
> /*
> * PageHasHWPoisoned indicates that at least one subpage is hwpoisoned in the
> * compound page.
> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> index 4916ab145325..3d15b4c1b694 100644
> --- a/mm/memory-failure.c
> +++ b/mm/memory-failure.c
> @@ -2008,6 +2008,7 @@ void folio_clear_hugetlb_hwpoison(struct folio *folio)
> if (folio_test_hugetlb_vmemmap_optimized(folio))
> return;
> folio_clear_hwpoison(folio);
> + folio_set_has_hwpoisoned(folio);
>From Sashiko [1]:
> Does setting this flag and relying on free_has_hwpoisoned() to skip the
> poisoned subpages introduce a permanent memory leak if unpoison_memory() is
> later called?
> Since the subpages are isolated without using take_page_off_buddy(), they
> are left with a refcount of 0 and without the MAGIC_HWPOISON
> (PageHWPoisonTakenOff) tag.
> If an administrator later runs unpoison_memory() on these pages,
> __get_unpoison_page() checks PageHWPoisonTakenOff() (which is false) and
> evaluates get_page_unless_zero() (which returns 0 because refcount is 0).
> unpoison_memory() observes ghp == 0:
> unpoison_memory() {
> ...
> ghp = get_hwpoison_page(p, MF_UNPOISON);
> if (!ghp) {
> ...
> ret = folio_test_clear_hwpoison(folio) ? 0 : -EBUSY;
> } else if (ghp < 0) {
> ...
> }
> Will this cause unpoison_memory() to clear the poison flag and return success
> without ever calling put_page_back_buddy(), permanently leaking the memory?
I believe so, the software-poisoned page will leak.
To prevent that, free_has_hwpoisoned() can just do
SetPageHWPoisonTakenOff() for each page it found HWPoison. That should
be enough in my test, and no need to do take_page_off_buddy().
me_huge_page() will page_ref_inc(). Later during unpoison, ghp will
become -EHWPOISON and page's refcount will be 1 when it is invoked
with put_page_back_buddy().
[1] https://sashiko.dev/#/patchset/20260705180714.3708947-1-jiaqiyan@xxxxxxxxxx
> folio_free_raw_hwp(folio, true);
> }
>
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>