Skip to content

Commit

Permalink
mm,hwpoison: double-check page count in __get_any_page()
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
nhoriguchi authored and torvalds committed Oct 16, 2020
1 parent 5d1fd5d commit 1f2481d
Showing 1 changed file with 6 additions and 0 deletions.
6 changes: 6 additions & 0 deletions mm/memory-failure.c
Original file line number Diff line number Diff line change
Expand Up @@ -1707,6 +1707,9 @@ static int __get_any_page(struct page *p, unsigned long pfn, int flags)
} else if (is_free_buddy_page(p)) {
pr_info("%s: %#lx free buddy page\n", __func__, pfn);
ret = 0;
} else if (page_count(p)) {
/* raced with allocation */
ret = -EBUSY;
} else {
pr_info("%s: %#lx: unknown zero refcount page type %lx\n",
__func__, pfn, p->flags);
Expand All @@ -1723,6 +1726,9 @@ static int get_any_page(struct page *page, unsigned long pfn, int flags)
{
int ret = __get_any_page(page, pfn, flags);

if (ret == -EBUSY)
ret = __get_any_page(page, pfn, flags);

if (ret == 1 && !PageHuge(page) &&
!PageLRU(page) && !__PageMovable(page)) {
/*
Expand Down

0 comments on commit 1f2481d

Please sign in to comment.