Skip to content

Commit 1f2481d

Browse files
nhoriguchitorvalds
authored andcommitted
mm,hwpoison: double-check page count in __get_any_page()
Soft offlining could fail with EIO due to the race condition with hugepage migration. This issuse became visible due to the change by previous patch that makes soft offline handler take page refcount by its own. We have no way to directly pin zero refcount page, and the page considered as a zero refcount page could be allocated just after the first check. This patch adds the second check to find the race and gives us chance to handle it more reliably. Reported-by: Qian Cai <[email protected]> Signed-off-by: Naoya Horiguchi <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Cc: "Aneesh Kumar K.V" <[email protected]> Cc: Aneesh Kumar K.V <[email protected]> Cc: Aristeu Rozanski <[email protected]> Cc: Dave Hansen <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Dmitry Yakunin <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Mike Kravetz <[email protected]> Cc: Oscar Salvador <[email protected]> Cc: Tony Luck <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Linus Torvalds <[email protected]>
1 parent 5d1fd5d commit 1f2481d

File tree

1 file changed

+6
-0
lines changed

1 file changed

+6
-0
lines changed

mm/memory-failure.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,6 +1707,9 @@ static int __get_any_page(struct page *p, unsigned long pfn, int flags)
17071707
} else if (is_free_buddy_page(p)) {
17081708
pr_info("%s: %#lx free buddy page\n", __func__, pfn);
17091709
ret = 0;
1710+
} else if (page_count(p)) {
1711+
/* raced with allocation */
1712+
ret = -EBUSY;
17101713
} else {
17111714
pr_info("%s: %#lx: unknown zero refcount page type %lx\n",
17121715
__func__, pfn, p->flags);
@@ -1723,6 +1726,9 @@ static int get_any_page(struct page *page, unsigned long pfn, int flags)
17231726
{
17241727
int ret = __get_any_page(page, pfn, flags);
17251728

1729+
if (ret == -EBUSY)
1730+
ret = __get_any_page(page, pfn, flags);
1731+
17261732
if (ret == 1 && !PageHuge(page) &&
17271733
!PageLRU(page) && !__PageMovable(page)) {
17281734
/*

0 commit comments

Comments
 (0)