From: Miaohe Lin <linmiaohe@huawei.com>
To: Breno Leitao <leitao@debian.org>
Cc: <linux-mm@kvack.org>, <linux-kernel@vger.kernel.org>,
<linux-doc@vger.kernel.org>, <linux-kselftest@vger.kernel.org>,
<linux-trace-kernel@vger.kernel.org>, <kernel-team@meta.com>,
Andrew Morton <akpm@linux-foundation.org>,
David Hildenbrand <david@kernel.org>,
"Lorenzo Stoakes" <ljs@kernel.org>,
Vlastimil Babka <vbabka@kernel.org>,
Mike Rapoport <rppt@kernel.org>,
Suren Baghdasaryan <surenb@google.com>,
Michal Hocko <mhocko@suse.com>, Shuah Khan <shuah@kernel.org>,
Naoya Horiguchi <nao.horiguchi@gmail.com>,
Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
"Liam R. Howlett" <liam@infradead.org>, <lance.yang@linux.dev>,
Steven Rostedt <rostedt@goodmis.org>,
"Masami Hiramatsu" <mhiramat@kernel.org>,
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Subject: Re: [PATCH v10 2/6] mm/memory-failure: surface unhandlable kernel pages as -ENOTRECOVERABLE
Date: Mon, 6 Jul 2026 20:22:12 +0800 [thread overview]
Message-ID: <157b0e23-9f1e-1af2-bb44-44f1f2cab8a5@huawei.com> (raw)
In-Reply-To: <20260630-ecc_panic-v10-2-c6ed5b62eea2@debian.org>
On 2026/6/30 20:46, Breno Leitao wrote:
> get_any_page() collapses every HWPoisonHandlable() rejection into a
> single -EIO via the __get_hwpoison_page() -> -EBUSY -> shake_page()
> -> retry path. That is correct for the transient case (a userspace
> folio briefly off LRU during migration or compaction, which a later
> shake can drag back), but wrong for stable kernel-owned pages: slab,
> page-table, large-kmalloc and PG_reserved pages will never become
> HWPoisonHandlable(), so the retry loop is wasted work and the final
> -EIO loses the "this is structurally unrecoverable" information.
> memory_failure() then maps -EIO into MF_MSG_GET_HWPOISON, which the
> panic-on-unrecoverable sysctl deliberately does not act on.
>
> Introduce is_kernel_owned_page(), a small predicate that positively
> identifies pages the hwpoison handler cannot recover from:
>
> is_kernel_owned_page(p) :=
> PageReserved(p) ||
> PageSlab(head) || PageTable(head) || PageLargeKmalloc(head)
>
> where head = compound_head(p).
>
> PG_reserved is a per-page flag (PF_NO_COMPOUND) and is tested on the
> page directly. The slab, page-table and large-kmalloc page-type bits
> are only stored on the head page, so those tests resolve the compound
> head first, then re-read compound_head(page) afterwards: a concurrent
> split or compound free that moves head invalidates the just-read flags
> and the loop retries. The lookup still takes no refcount, mirroring
> the rest of get_any_page(); the recheck closes the common split race,
> and a residual free->alloc->free in the same window can only mis-tag
> a genuinely poisoned page, never reclassify a handlable one.
>
> No MF_SOFT_OFFLINE / page_has_movable_ops() opt-out is needed: a
> movable_ops page is always PageOffline or PageZsmalloc, whose
> page_type is mutually exclusive with slab, page-table and
> large-kmalloc, and it never carries PG_reserved, so it can never
> match any of the checks above.
>
> The list is intentionally not exhaustive. vmalloc and kernel-stack
> pages, for example, do not carry a page_type bit and would need a
> different oracle; they keep going through the existing retry path
> unchanged. This is the smallest set we can identify with certainty
> by page type.
>
> Wire the helper into the top of get_any_page() to short-circuit
> those pages before the retry loop runs. On a hit, drop the caller's
> MF_COUNT_INCREASED reference (if any) and return -ENOTRECOVERABLE
> straight away. Pages outside the helper's positive list still take
> the existing retry path and return -EIO, leaving operator-visible
> behaviour for those cases unchanged.
>
> Extend the unhandlable-page pr_err() to fire for either errno and
> update the get_hwpoison_page() kerneldoc to document the new return.
>
> memory_failure() still folds every negative return into
> MF_MSG_GET_HWPOISON via its existing "else if (res < 0)" branch, so
> this patch on its own only changes the errno that soft_offline_page()
> can propagate to its callers. A follow-up wires -ENOTRECOVERABLE
> through memory_failure() and reports MF_MSG_KERNEL for the
> unrecoverable cases, which is what the
> panic_on_unrecoverable_memory_failure sysctl observes.
>
> Suggested-by: David Hildenbrand <david@kernel.org>
> Suggested-by: Lance Yang <lance.yang@linux.dev>
> Signed-off-by: Breno Leitao <leitao@debian.org>
> ---
> mm/memory-failure.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 50 insertions(+), 2 deletions(-)
>
> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> index f4d3e6e20e13f..087658484e242 100644
> --- a/mm/memory-failure.c
> +++ b/mm/memory-failure.c
> @@ -1325,6 +1325,38 @@ static inline bool HWPoisonHandlable(struct page *page, unsigned long flags)
> return PageLRU(page) || is_free_buddy_page(page);
> }
>
> +/*
> + * Positive identification of pages the hwpoison handler cannot recover:
> + * pages owned by kernel internals with no userspace mapping to unmap, no
> + * file mapping to invalidate, and no migration target.
> + */
> +static inline bool is_kernel_owned_page(struct page *page)
> +{
> + struct page *head;
> + bool kernel_owned;
> +
> + /* PG_reserved is a per-page flag, never set on a compound page. */
> + if (PageReserved(page))
> + return true;
> +
> + /*
> + * Page-type bits live only on the head page, so resolve any tail
> + * first. The check takes no refcount; recheck the head afterwards
> + * so a concurrent split or compound free cannot leave us trusting
> + * a stale view. A residual free->alloc->free cannot be closed here
> + * (frozen slab and large-kmalloc pages cannot be pinned), but is
> + * harmless: where a wrong verdict could panic, memory_failure() has
> + * already set PageHWPoison, which bars the page from the allocator.
> + */
> +retry:
> + head = compound_head(page);
It's irrelevant to this issue but should we use folio?
Anyway, this patch looks good to me.
Acked-by: Miaohe Lin <linmiaohe@huawei.com>
Thanks.
.
next prev parent reply other threads:[~2026-07-06 12:22 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-30 12:46 [PATCH v10 0/6] mm/memory-failure: add panic option for unrecoverable pages Breno Leitao
2026-06-30 12:46 ` [PATCH v10 1/6] mm/memory-failure: drop dead error_states[] entry for reserved pages Breno Leitao
2026-06-30 12:46 ` [PATCH v10 2/6] mm/memory-failure: surface unhandlable kernel pages as -ENOTRECOVERABLE Breno Leitao
2026-07-06 12:22 ` Miaohe Lin [this message]
2026-06-30 12:46 ` [PATCH v10 3/6] mm/memory-failure: report MF_MSG_KERNEL for unrecoverable kernel pages Breno Leitao
2026-06-30 12:46 ` [PATCH v10 4/6] mm/memory-failure: add panic option for unrecoverable pages Breno Leitao
2026-06-30 12:46 ` [PATCH v10 5/6] Documentation: document panic_on_unrecoverable_memory_failure sysctl Breno Leitao
2026-07-09 3:18 ` Miaohe Lin
2026-06-30 12:46 ` [PATCH v10 6/6] selftests/mm: add hwpoison-panic destructive test Breno Leitao
2026-07-04 9:31 ` Mike Rapoport
2026-07-06 16:14 ` Breno Leitao
2026-07-06 16:23 ` Mike Rapoport
2026-07-09 3:34 ` Miaohe Lin
2026-06-30 20:55 ` [PATCH v10 0/6] mm/memory-failure: add panic option for unrecoverable pages Andrew Morton
-- strict thread matches above, loose matches on Subject: below --
2026-06-26 15:33 Breno Leitao
2026-06-26 15:33 ` [PATCH v10 2/6] mm/memory-failure: surface unhandlable kernel pages as -ENOTRECOVERABLE Breno Leitao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=157b0e23-9f1e-1af2-bb44-44f1f2cab8a5@huawei.com \
--to=linmiaohe@huawei.com \
--cc=akpm@linux-foundation.org \
--cc=corbet@lwn.net \
--cc=david@kernel.org \
--cc=kernel-team@meta.com \
--cc=lance.yang@linux.dev \
--cc=leitao@debian.org \
--cc=liam@infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=ljs@kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mhiramat@kernel.org \
--cc=mhocko@suse.com \
--cc=nao.horiguchi@gmail.com \
--cc=rostedt@goodmis.org \
--cc=rppt@kernel.org \
--cc=shuah@kernel.org \
--cc=skhan@linuxfoundation.org \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.