On Thu, Oct 17, 2019 at 08:27:59PM +0200, Michal Hocko wrote:
On Thu 17-10-19 14:07:13, Qian Cai wrote:
On Thu, 2019-10-17 at 12:01 +0200, Michal Hocko wrote:
On Thu 17-10-19 09:34:10, Naoya Horiguchi wrote:
On Mon, Oct 14, 2019 at 10:39:14AM +0200, Michal Hocko wrote:
[...]
diff --git a/mm/page_isolation.c b/mm/page_isolation.c
index 89c19c0feadb..5fb3fee16fde 100644
--- a/mm/page_isolation.c
+++ b/mm/page_isolation.c
@@ -274,7 +274,7 @@ __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn,
* simple way to verify that as VM_BUG_ON(), though.
*/
pfn += 1 << page_order(page);
- else if (skip_hwpoisoned_pages && PageHWPoison(page))
+ else if (skip_hwpoisoned_pages && PageHWPoison(compound_head(page)))
/* A HWPoisoned page cannot be also PageBuddy */
pfn++;
else
This fix looks good to me. The original code only addresses hwpoisoned 4kB-page,
we seem to have this issue since the following commit,
Thanks a lot for double checking Naoya!
commit b023f46813cde6e3b8a8c24f432ff9c1fd8e9a64
Author: Wen Congyang <wency@xxxxxxxxxxxxxx>
Date: Tue Dec 11 16:00:45 2012 -0800
memory-hotplug: skip HWPoisoned page when offlining pages
and extension of LTP coverage finally discovered this.
Qian, could you give the patch some testing?
Unfortunately, this does not solve the problem.ÂIt looks to me that in
soft_offline_huge_page(), set_hwpoison_free_buddy_page() will only set
PG_hwpoison for buddy pages, so the even the compound_head() has no PG_hwpoison
set.
if (PageBuddy(page_head) && page_order(page_head) >= order) {
if (!TestSetPageHWPoison(page))
hwpoisoned = true;
This is more than unexpected. How are we supposed to find out that the
page is poisoned? Any idea Naoya?
# sorry for my poor review...
We set PG_hwpoison bit only on the head page for hugetlb, that's because
we handle multiple pages as a single one for hugetlb. So it's enough
to check isolation only on the head page. Simply skipping pfn cursor to
the page after the hugepage should avoid the infinite loop:
@@ -274,9 +274,13 @@ __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn,
* simple way to verify that as VM_BUG_ON(), though.
*/
pfn += 1 << page_order(page);
- else if (skip_hwpoisoned_pages && PageHWPoison(page))
- /* A HWPoisoned page cannot be also PageBuddy */
- pfn++;
+ else if (skip_hwpoisoned_pages && PageHWPoison(compound_head(page)))
+ /*
+ * A HWPoisoned page cannot be also PageBuddy.
+ * PG_hwpoison could be set only on the head page in
+ * hugetlb case, so no need to check tail pages.
+ */
+ pfn += 1 << compound_order(page);
else
break;
}
Qian, could you please try this?