Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: "Gregory Price (Meta)" <gourry@gourry.net>
To: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org, linux-cxl@vger.kernel.org,
	kernel-team@meta.com, akpm@linux-foundation.org,
	vbabka@kernel.org, surenb@google.com, mhocko@suse.com,
	brendan.jackman@linux.dev, hannes@cmpxchg.org, ziy@nvidia.com,
	linmiaohe@huawei.com, nao.horiguchi@gmail.com, david@kernel.org,
	ljs@kernel.org, liam@infradead.org, rppt@kernel.org,
	osalvador@suse.de, muchun.song@linux.dev, iamjoonsoo.kim@lge.com,
	anshuman.khandual@arm.com, stable@vger.kernel.org
Subject: [PATCH 3/6] mm/memory-failure: keep the page online while handling it
Date: Tue, 27 Oct 2026 00:22:01 -0400	[thread overview]
Message-ID: <20261027042204.3741307-4-gourry@gourry.net> (raw)
In-Reply-To: <20261027042204.3741307-1-gourry@gourry.net>

memory_failure(), soft_offline_page() and unpoison_memory() check that a
pfn is online, then sleep on mf_mutex before using its page.  If the
block goes offline meanwhile, a DEBUG_VM kernel faults on the poisoned
memmap, and removal frees it on any kernel:

  CPU 1 (soft_offline_page)           CPU 2 (offline_pages)
  pfn_to_online_page()
    page is online
  mutex_lock(&mf_mutex)
                                      offline_mem_sections()
                                      remove_pfn_range_from_zone()
                                        page_init_poison()
  get_hwpoison_page()
    zone_pcp_disable(page_zone(page))
      zone of a poisoned page

  Oops: general protection fault, probably for non-canonical address 0xdffffc000000069e: 0000 [#1] SMP KASAN
  RIP: 0010:__zone_set_pageset_high_and_batch+0x89/0x270
   zone_pcp_disable+0x28/0x40
   get_hwpoison_page+0xc2/0x1160
   soft_offline_page.part.0+0xe7/0xbf0

memory_failure() faults the same way.  unpoison_memory() does not fault,
but it clears flags on the poisoned page and returns success.

Hold get_online_mems() from before the online check to the last use of
the page.  soft_offline_page() took it only around get_hwpoison_page();
it now takes it once, earlier.

With a kprobe parking each entry point across the offline, base faults,
or for unpoison_memory() succeeds, in 3 of 3 runs each.  With this patch
all 9 runs wait and fail with -EIO or -ENXIO, and lockdep stays clean
over offline/online cycles mixed with error injection.

Fixes: 96c804a6ae8c ("mm/memory-failure.c: don't access uninitialized memmaps in memory_failure()")
Fixes: feec24a6139d ("mm, soft-offline: convert parameter to pfn")
Fixes: d613f53c83ec ("mm/memory-failure: fix VM_BUG_ON_PAGE(PagePoisoned(page)) when unpoison memory")
Cc: stable@vger.kernel.org
Signed-off-by: Gregory Price (Meta) <gourry@gourry.net>
---
 mm/memory-failure.c | 31 ++++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 0c96eb5119976..cdae2a1988bb8 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -2394,6 +2394,8 @@ int memory_failure(unsigned long pfn, int flags)
 	if (!sysctl_memory_failure_recovery)
 		panic("Memory failure on page %lx", pfn);
 
+	/* Keep the page online from the check below until we are done */
+	get_online_mems();
 	mutex_lock(&mf_mutex);
 
 	if (!(flags & MF_SW_SIMULATED))
@@ -2608,11 +2610,13 @@ int memory_failure(unsigned long pfn, int flags)
 identify_page_state:
 	res = identify_page_state(pfn, p, page_flags);
 	mutex_unlock(&mf_mutex);
+	put_online_mems();
 	return res;
 unlock_page:
 	folio_unlock(folio);
 unlock_mutex:
 	mutex_unlock(&mf_mutex);
+	put_online_mems();
 	return res;
 }
 EXPORT_SYMBOL_GPL(memory_failure);
@@ -2742,9 +2746,12 @@ int unpoison_memory(unsigned long pfn)
 	static DEFINE_RATELIMIT_STATE(unpoison_rs, DEFAULT_RATELIMIT_INTERVAL,
 					DEFAULT_RATELIMIT_BURST);
 
+	get_online_mems();
 	p = pfn_to_online_page(pfn);
-	if (!p)
+	if (!p) {
+		put_online_mems();
 		return -EIO;
+	}
 	folio = page_folio(p);
 
 	mutex_lock(&mf_mutex);
@@ -2833,6 +2840,7 @@ int unpoison_memory(unsigned long pfn)
 		unpoison_pr_info("%#lx: software-unpoisoned page\n",
 				 page_to_pfn(p), &unpoison_rs);
 	}
+	put_online_mems();
 	return ret;
 }
 EXPORT_SYMBOL(unpoison_memory);
@@ -2974,38 +2982,42 @@ int soft_offline_page(unsigned long pfn, int flags)
 		return -ENXIO;
 	}
 
+	if (!sysctl_enable_soft_offline) {
+		pr_info_once("disabled by /proc/sys/vm/enable_soft_offline\n");
+		put_ref_page(pfn, flags);
+		return -EOPNOTSUPP;
+	}
+
+	/* Keep the page online from the check below until we are done */
+	get_online_mems();
+
 	/* Only online pages can be soft-offlined (esp., not ZONE_DEVICE). */
 	page = pfn_to_online_page(pfn);
 	if (!page) {
+		put_online_mems();
 		put_ref_page(pfn, flags);
 		return -EIO;
 	}
 
-	if (!sysctl_enable_soft_offline) {
-		pr_info_once("disabled by /proc/sys/vm/enable_soft_offline\n");
-		put_ref_page(pfn, flags);
-		return -EOPNOTSUPP;
-	}
-
 	mutex_lock(&mf_mutex);
 
 	if (PageHWPoison(page)) {
 		pr_info("%#lx: page already poisoned\n", pfn);
 		put_ref_page(pfn, flags);
 		mutex_unlock(&mf_mutex);
+		put_online_mems();
 		return 0;
 	}
 
 retry:
-	get_online_mems();
 	ret = get_hwpoison_page(page, flags | MF_SOFT_OFFLINE);
-	put_online_mems();
 
 	if (hwpoison_filter(page)) {
 		if (ret > 0)
 			put_page(page);
 
 		mutex_unlock(&mf_mutex);
+		put_online_mems();
 		return -EOPNOTSUPP;
 	}
 
@@ -3023,6 +3035,7 @@ int soft_offline_page(unsigned long pfn, int flags)
 	}
 
 	mutex_unlock(&mf_mutex);
+	put_online_mems();
 
 	return ret;
 }
-- 
2.53.0-Meta



  parent reply	other threads:[~2026-10-27  4:22 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-27  4:21 [PATCH 0/6] mm: fix pfn walker races with memory offline Gregory Price (Meta)
2026-10-27  4:21 ` [PATCH 1/6] mm/compaction: wait for pfn walkers before poisoning offlined memmap Gregory Price (Meta)
2026-10-27 13:38   ` David Hildenbrand (Arm)
2026-10-28  4:22   ` sashiko-bot
2026-10-27  4:22 ` [PATCH 2/6] mm/page_owner: hold off memory offline while a page is read Gregory Price (Meta)
2026-10-28  4:22   ` sashiko-bot
2026-10-27  4:22 ` Gregory Price (Meta) [this message]
2026-10-27  4:22 ` [PATCH 4/6] mm/page_alloc: don't undo another isolation in alloc_contig_range Gregory Price (Meta)
2026-10-27 13:37   ` David Hildenbrand (Arm)
2026-10-27 14:06     ` Gregory Price (Meta)
2026-10-27 14:13       ` David Hildenbrand (Arm)
2026-10-27 18:53         ` Zi Yan
2026-10-27 18:58           ` David Hildenbrand (Arm)
2026-10-27 19:38             ` Gregory Price
2026-10-27  4:22 ` [PATCH 5/6] mm/page_alloc: keep the range online while alloc_contig isolates it Gregory Price (Meta)
2026-10-27  4:22 ` [PATCH 6/6] mm/hwpoison-inject: keep the page online while filtering it Gregory Price (Meta)
2026-10-27  8:57 ` [PATCH 0/6] mm: fix pfn walker races with memory offline David Hildenbrand (Arm)
2026-10-27 11:31   ` Gregory Price (Meta)
2026-10-27 12:51     ` David Hildenbrand (Arm)
2026-10-27 13:49       ` Gregory Price (Meta)
2026-10-27 14:25         ` David Hildenbrand (Arm)
2026-10-27 15:49           ` Gregory Price (Meta)

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=20261027042204.3741307-4-gourry@gourry.net \
    --to=gourry@gourry.net \
    --cc=akpm@linux-foundation.org \
    --cc=anshuman.khandual@arm.com \
    --cc=brendan.jackman@linux.dev \
    --cc=david@kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=iamjoonsoo.kim@lge.com \
    --cc=kernel-team@meta.com \
    --cc=liam@infradead.org \
    --cc=linmiaohe@huawei.com \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=mhocko@suse.com \
    --cc=muchun.song@linux.dev \
    --cc=nao.horiguchi@gmail.com \
    --cc=osalvador@suse.de \
    --cc=rppt@kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=surenb@google.com \
    --cc=vbabka@kernel.org \
    --cc=ziy@nvidia.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox