Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: "David Hildenbrand (Arm)" <david@kernel.org>
To: Matthew Wilcox <willy@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	Jane Chu <jane.chu@oracle.com>,
	linux-mm@kvack.org, Muchun Song <muchun.song@linux.dev>,
	Oscar Salvador <osalvador@suse.de>,
	Miaohe Lin <linmiaohe@huawei.com>,
	Naoya Horiguchi <nao.horiguchi@gmail.com>,
	Jan Kara <jack@suse.cz>,
	linux-fsdevel@vger.kernel.org,
	Christian Brauner <christian@brauner.io>,
	Jiaqi Yan <jiaqiyan@google.com>,
	"Gregory Price (Meta)" <gourry@gourry.net>
Subject: Re: [PATCH v9 08/15] hugetlb: Use the has_hwpoisoned flag
Date: Thu, 24 Sep 2026 12:32:13 +0200	[thread overview]
Message-ID: <6121136c-de9d-4577-a30d-f00dbe244e5d@kernel.org> (raw)
In-Reply-To: <arQkP2uEzog8ChN0@casper.infradead.org>

On 9/23/26 21:10, Matthew Wilcox wrote:
> On Wed, Sep 23, 2026 at 01:40:24PM +0200, David Hildenbrand (Arm) wrote:
>> On 9/21/26 23:32, Matthew Wilcox wrote:
>>>
>>> We might be able to split this into two series at this point.  
>>
>> That would be good, because I suspect the "generic_file_read_iter() in
>> hugetlbfs" part is less controversial than the hugetlb cleanup and we can just
>> merge that easily without touching too much other code.
> 
> Oh, no, it's awful and complicated.  We could strip out the two bugfixes
> which are at the start of the series, but why would we want to do that?

Andrew usually wants us to separate bugfixes (especially stable ones) from
other work. Unless we all agree that they are not urgent and can go in in
the next cycle. I assume that's the case here.

> 
> It has to do with hugetlb not using the has_hwpoisoned() flag today,
> and to do that we need to do all the other cleanup first.  You don't
> need to read + understand those earlier patches; they have enough 
> review from people familiar with this area.  And sashiko ...

I think I reviewed most of them? Also, I like to understand code that touches
files I maintain. Independent of who (or what) else reviewed it.

Taking another look, most of the hwpoison patches are fine and I fully agree
that using has_hwpoisoned is much better. And if it helps to implement support
for the generic iterator, good.

Figuring out the actual hwpoisoned page for hugetlb looks like the right thing
to do.

I am not convinced about the huge_poison thing though, that originally caught my
attention.

So trying to understand the race we are trying to solve (that is independent of
the original idea of the patch set), I realize that these races are only on some 
slow paths we don't particularly care about for performance.


I'd just do the following to avoid that huge_poison thing and keep it simple:

From 9f175684aea7e1cebb1d4070c217a20c9e847294 Mon Sep 17 00:00:00 2001
From: "David Hildenbrand (Arm)" <david@kernel.org>
Date: Thu, 24 Sep 2026 12:12:17 +0200
Subject: [PATCH] tmp

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
 include/linux/page-flags.h | 40 ++++++++++++++++----------------------
 mm/memory-failure.c        | 37 ++++++-----------------------------
 2 files changed, 23 insertions(+), 54 deletions(-)

diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index f75d66c425095..c7f6ce68c6d15 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -909,6 +909,7 @@ FOLIO_TEST_SET_FLAG(has_hwpoisoned, FOLIO_SECOND_PAGE)
 FOLIO_TEST_CLEAR_FLAG(has_hwpoisoned, FOLIO_SECOND_PAGE)
 #else
 FOLIO_FLAG_FALSE(has_hwpoisoned)
+FOLIO_TEST_CLEAR_FLAG_FALSE(has_hwpoisoned)
 #endif
 
 /*
@@ -1047,29 +1048,8 @@ PAGE_TYPE_OPS(Slab, slab, slab)
 
 #ifdef CONFIG_HUGETLB_PAGE
 FOLIO_TYPE_OPS(hugetlb, hugetlb)
-
-#ifdef CONFIG_MEMORY_FAILURE
-static inline bool folio_test_huge_poison(const struct folio *folio)
-{
-	return (READ_ONCE(folio->page.page_type) >> 23) ==
-		((PGTY_hugetlb << 1) | 1);
-}
-
-static inline void folio_set_huge_poison(struct folio *folio)
-{
-	folio->page.page_type |= (1 << 23);
-}
-
-static inline void folio_clear_huge_poison(struct folio *folio)
-{
-	folio->page.page_type &= ~(1 << 23);
-}
-#else
-FOLIO_TEST_FLAG_FALSE(huge_poison)
-#endif
 #else
 FOLIO_TEST_FLAG_FALSE(hugetlb)
-FOLIO_TEST_FLAG_FALSE(huge_poison)
 #endif
 
 PAGE_TYPE_OPS(Zsmalloc, zsmalloc, zsmalloc)
@@ -1096,7 +1076,14 @@ static inline bool PageHuge(const struct page *page)
 }
 
 bool hugetlb_page_hwpoison(const struct folio *folio, const struct page *page);
+#ifdef CONFIG_MEMORY_FAILURE
 bool hugetlb_unref_page_hwpoison(const struct page *page);
+#else
+static inline bool hugetlb_unref_page_hwpoison(const struct page *page)
+{
+	return false;
+}
+#endif
 
 /*
  * Check if a page is currently marked HWPoisoned.  This check is best
@@ -1111,8 +1098,15 @@ static inline bool is_page_hwpoison(const struct page *page)
 	if (PageHWPoison(page))
 		return true;
 	folio = page_folio(page);
-	if (folio_test_huge_poison(folio))
-		return hugetlb_unref_page_hwpoison(page);
+
+	/*
+	 * It's not safe to query folio_test_has_hwpoisoned() due to concurrent
+	 * splitting.  As we don't expect to be called on any hot paths, simply
+	 * always take the slow path for hugetlb folios, whose per-page poison
+	 * state may be tracked out-of-line.
+	 */
+	if (folio_test_hugetlb(folio) && hugetlb_unref_page_hwpoison(page))
+		return true;
 	/* In case we raced with hugetlb transferring flags */
 	return PageHWPoison(page);
 }
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index c0a402522c216..d713eddf47640 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1869,13 +1869,8 @@ bool hugetlb_unref_page_hwpoison(const struct page *page)
 
 	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:
+	ret = folio_test_hugetlb(folio) &&
+	      hugetlb_page_hwpoison(folio, page);
 	spin_unlock_irqrestore(&hugetlb_lock, flags);
 	return ret;
 }
@@ -1908,23 +1903,6 @@ static unsigned long __folio_free_raw_hwp(struct folio *folio, bool move_flag)
 #define	MF_HUGETLB_PAGE_PRE_POISONED	4	/* exact page already poisoned */
 #define	MF_HUGETLB_RETRY		5	/* hugepage is busy, retry */
 
-static inline int hugetlb_set_poison(struct folio *folio)
-{
-	if (folio_test_set_has_hwpoisoned(folio))
-		return MF_HUGETLB_FOLIO_PRE_POISONED;
-	folio_set_huge_poison(folio);
-	return 0;
-}
-
-static inline int hugetlb_clear_poison(struct folio *folio)
-{
-	if (!folio_test_has_hwpoisoned(folio))
-		return -EBUSY;
-	folio_clear_huge_poison(folio);
-	folio_clear_has_hwpoisoned(folio);
-	return 0;
-}
-
 /*
  * Set hugetlb folio as hwpoisoned, update folio private raw hwpoison list
  * to keep track of the poisoned pages.
@@ -1933,7 +1911,8 @@ static int hugetlb_update_hwpoison(struct folio *folio, struct page *page)
 {
 	struct hwp_page *p;
 	unsigned long flags;
-	int ret = hugetlb_set_poison(folio);
+	int ret = folio_test_set_has_hwpoisoned(folio) ?
+		  MF_HUGETLB_FOLIO_PRE_POISONED : 0;
 
 	/*
 	 * Once the hwpoison hugepage has lost reliable raw error info,
@@ -2163,10 +2142,6 @@ static inline unsigned long folio_free_raw_hwp(struct folio *folio, bool flag)
 	return 0;
 }
 
-static inline int hugetlb_clear_poison(struct folio *folio)
-{
-	return 0;
-}
 #endif	/* CONFIG_HUGETLB_PAGE */
 
 /* Drop the extra refcount in case we come from madvise() */
@@ -2796,7 +2771,7 @@ int unpoison_memory(unsigned long pfn)
 				hugetlb_unlock_irq();
 				goto unlock_mutex;
 			}
-			ret = hugetlb_clear_poison(folio);
+			ret = folio_test_clear_has_hwpoisoned(folio) ? 0 : -EBUSY;
 		} else {
 			ret = TestClearPageHWPoison(p) ? 0 : -EBUSY;
 		}
@@ -2816,7 +2791,7 @@ int unpoison_memory(unsigned long pfn)
 			folio_put(folio);
 			goto unlock_mutex;
 		}
-		ret = hugetlb_clear_poison(folio);
+		ret = folio_test_clear_has_hwpoisoned(folio) ? 0 : -EBUSY;
 		folio_put(folio);
 		if (!ret)
 			folio_put(folio);
-- 
2.43.0



Makes /proc/kpageflags scanning slower with hugetlb folios, I don't think
sure anybody cares, really. We could add a way to safely check in a racy
way the has_hwpoison flag, but I don't really see the need to right now for some
debug infrastructure that does these racy things.

-- 
Cheers,

David


  reply	other threads:[~2026-09-24 10:55 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-05 21:05 [PATCH v9 00/15] Use generic_file_read_iter() in hugetlbfs Matthew Wilcox (Oracle)
2026-08-05 21:05 ` [PATCH v9 01/15] memory-failure: Fix hardware poison check in unpoison_memory() again Matthew Wilcox (Oracle)
2026-08-05 21:05 ` [PATCH v9 02/15] memory-failure: Prevent hugetlb freeing during unpoisoning Matthew Wilcox (Oracle)
2026-09-04  3:38   ` Miaohe Lin
2026-08-05 21:05 ` [PATCH v9 03/15] mm: Rename folio_contain_hwpoison_page() to folio_has_hwpoison_page() Matthew Wilcox (Oracle)
2026-08-13  7:20   ` David Hildenbrand (Arm)
2026-08-05 21:05 ` [PATCH v9 04/15] hugetlb: Mark some function arguments as const Matthew Wilcox (Oracle)
2026-08-05 21:05 ` [PATCH v9 05/15] guest_memfd: Use folio_has_hwpoisoned_page() Matthew Wilcox (Oracle)
2026-08-13  7:20   ` David Hildenbrand (Arm)
2026-08-13 11:50     ` Matthew Wilcox
2026-08-25 18:41       ` David Hildenbrand (Arm)
2026-08-05 21:05 ` [PATCH v9 06/15] kpageflags: Use is_page_hwpoison() to set KPF_HWPOISON Matthew Wilcox (Oracle)
2026-08-13  7:25   ` David Hildenbrand (Arm)
2026-08-13  9:01     ` David Hildenbrand (Arm)
2026-09-23 18:59       ` Matthew Wilcox
2026-08-05 21:05 ` [PATCH v9 07/15] hugetlb: Move poison to pages before clearing hugetlb page type Matthew Wilcox (Oracle)
2026-08-05 21:05 ` [PATCH v9 08/15] hugetlb: Use the has_hwpoisoned flag Matthew Wilcox (Oracle)
2026-08-13  8:29   ` David Hildenbrand (Arm)
2026-08-13 16:17     ` Matthew Wilcox
2026-09-18 13:44       ` David Hildenbrand (Arm)
2026-09-21 21:32         ` Matthew Wilcox
2026-09-23 11:40           ` David Hildenbrand (Arm)
2026-09-23 19:10             ` Matthew Wilcox
2026-09-24 10:32               ` David Hildenbrand (Arm) [this message]
2026-09-24 18:53                 ` Matthew Wilcox
2026-09-24 19:21                   ` David Hildenbrand (Arm)
2026-09-24 21:28                   ` Andrew Morton
2026-08-13 11:12   ` Pedro Falcato
2026-09-04  3:46   ` Miaohe Lin
2026-09-23 19:33     ` Matthew Wilcox
2026-08-05 21:05 ` [PATCH v9 09/15] mm: Remove locking mf_mutex in is_raw_hwpoison_page_in_hugepage() Matthew Wilcox (Oracle)
2026-09-04  6:35   ` Miaohe Lin
2026-09-23 19:34     ` Matthew Wilcox
2026-08-05 21:05 ` [PATCH v9 10/15] mm: Check individual hugetlb pages for poison Matthew Wilcox (Oracle)
2026-09-04  6:37   ` Miaohe Lin
2026-08-05 21:05 ` [PATCH v9 11/15] filemap: Add hwpoison handling to filemap_read() Matthew Wilcox (Oracle)
2026-08-13 10:55   ` Pedro Falcato
2026-08-13 16:33     ` Matthew Wilcox
2026-09-18 13:47       ` David Hildenbrand (Arm)
2026-09-21 20:08         ` Matthew Wilcox
2026-08-05 21:05 ` [PATCH v9 12/15] filemap: Remove checks in mapping_set_folio_order_range() Matthew Wilcox (Oracle)
2026-08-13 11:05   ` Pedro Falcato
2026-08-05 21:05 ` [PATCH v9 13/15] hugetlb: Set mapping folio order Matthew Wilcox (Oracle)
2026-08-13 11:06   ` Pedro Falcato
2026-09-18 13:47   ` David Hildenbrand (Arm)
2026-08-05 21:05 ` [PATCH v9 14/15] filemap: Add support for authoritative mappings Matthew Wilcox (Oracle)
2026-08-13 11:10   ` Pedro Falcato
2026-09-18 13:51   ` David Hildenbrand (Arm)
2026-09-21 21:19     ` Matthew Wilcox
2026-09-23 13:55       ` David Hildenbrand (Arm)
2026-08-05 21:05 ` [PATCH v9 15/15] hugetlb: replace hugetlbfs_read_iter() with generic_file_read_iter() Matthew Wilcox (Oracle)
2026-08-13 11:10   ` Pedro Falcato
2026-08-06 19:47 ` [PATCH v9 00/15] Use generic_file_read_iter() in hugetlbfs jane.chu
2026-08-13  8:37 ` Lorenzo Stoakes (ARM)

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=6121136c-de9d-4577-a30d-f00dbe244e5d@kernel.org \
    --to=david@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=christian@brauner.io \
    --cc=gourry@gourry.net \
    --cc=jack@suse.cz \
    --cc=jane.chu@oracle.com \
    --cc=jiaqiyan@google.com \
    --cc=linmiaohe@huawei.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=muchun.song@linux.dev \
    --cc=nao.horiguchi@gmail.com \
    --cc=osalvador@suse.de \
    --cc=willy@infradead.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox