[RFC PATCH v1 4/4] mm, memory_hotplug: fix inconsistent num_poisoned_pages on memory hotremove

From: Naoya Horiguchi
Date: Wed Apr 27 2022 - 00:29:29 EST


From: Naoya Horiguchi <naoya.horiguchi@xxxxxxx>

When offlining memory section with hwpoisoned pages, the hwpoisons are
canceled. But num_poisoned_pages is not updated for that event, so the
counter becomes inconsistent.

Add num_poisoned_pages_dec() in __offline_isolated_pages(). PageHWPoison
can be set on a tail page of some high order buddy page, so we need check
PageHWPoison on each subpage.

Signed-off-by: Naoya Horiguchi <naoya.horiguchi@xxxxxxx>
---
mm/page_alloc.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 6e5b4488a0c5..dcd962855617 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -9487,12 +9487,15 @@ void __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
zone = page_zone(pfn_to_page(pfn));
spin_lock_irqsave(&zone->lock, flags);
while (pfn < end_pfn) {
+ int i;
+
page = pfn_to_page(pfn);
/*
* The HWPoisoned page may be not in buddy system, and
* page_count() is not 0.
*/
if (unlikely(!PageBuddy(page) && PageHWPoison(page))) {
+ num_poisoned_pages_dec();
pfn++;
continue;
}
@@ -9510,6 +9513,9 @@ void __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
BUG_ON(page_count(page));
BUG_ON(!PageBuddy(page));
order = buddy_order(page);
+ for (i = 0; i < 1 << order; i++)
+ if (PageHWPoison(page + i))
+ num_poisoned_pages_dec();
del_page_from_free_list(page, zone, order);
pfn += (1 << order);
}
--
2.25.1