提交 8295d535 编写于 作者: O Oscar Salvador 提交者: Linus Torvalds

mm,hwpoison: refactor get_any_page

Patch series "HWPoison: Refactor get page interface", v2.

This patch (of 3):

When we want to grab a refcount via get_any_page, we call __get_any_page
that calls get_hwpoison_page to get the actual refcount.

get_any_page() is only there because we have a sort of retry mechanism in
case the page we met is unknown to us or if we raced with an allocation.

Also __get_any_page() prints some messages about the page type in case the
page was a free page or the page type was unknown, but if anything, we
only need to print a message in case the pagetype was unknown, as that is
reporting an error down the chain.

Let us merge get_any_page() and __get_any_page(), and let the message be
printed in soft_offline_page.  While we are it, we can also remove the
'pfn' parameter as it is no longer used.

Link: https://lkml.kernel.org/r/20201204102558.31607-1-osalvador@suse.de
Link: https://lkml.kernel.org/r/20201204102558.31607-2-osalvador@suse.deSigned-off-by: NOscar Salvador <osalvador@suse.de>
Acked-by: NNaoya Horiguchi <naoya.horiguchi@nec.com>
Acked-by: NVlastimil Babka <Vbabka@suse.cz>
Cc: Qian Cai <qcai@redhat.com>
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 32409cba
...@@ -1707,70 +1707,51 @@ EXPORT_SYMBOL(unpoison_memory); ...@@ -1707,70 +1707,51 @@ EXPORT_SYMBOL(unpoison_memory);
/* /*
* Safely get reference count of an arbitrary page. * Safely get reference count of an arbitrary page.
* Returns 0 for a free page, -EIO for a zero refcount page * Returns 0 for a free page, 1 for an in-use page, -EIO for a page-type we
* that is not free, and 1 for any other page type. * cannot handle and -EBUSY if we raced with an allocation.
* For 1 the page is returned with increased page count, otherwise not. * We only incremented refcount in case the page was already in-use and it is
* a known type we can handle.
*/ */
static int __get_any_page(struct page *p, unsigned long pfn, int flags) static int get_any_page(struct page *p, int flags)
{ {
int ret; int ret = 0, pass = 0;
bool count_increased = false;
if (flags & MF_COUNT_INCREASED) if (flags & MF_COUNT_INCREASED)
return 1; count_increased = true;
/* try_again:
* When the target page is a free hugepage, just remove it if (!count_increased && !get_hwpoison_page(p)) {
* from free hugepage list. if (page_count(p)) {
*/ /* We raced with an allocation, retry. */
if (!get_hwpoison_page(p)) { if (pass++ < 3)
if (PageHuge(p)) { goto try_again;
pr_info("%s: %#lx free huge page\n", __func__, pfn);
ret = 0;
} 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; ret = -EBUSY;
} else { } else if (!PageHuge(p) && !is_free_buddy_page(p)) {
pr_info("%s: %#lx: unknown zero refcount page type %lx\n", /* We raced with put_page, retry. */
__func__, pfn, p->flags); if (pass++ < 3)
goto try_again;
ret = -EIO; ret = -EIO;
} }
} else { } else {
/* Not a free page */ if (PageHuge(p) || PageLRU(p) || __PageMovable(p)) {
ret = 1; ret = 1;
} } else {
return ret; /*
} * A page we cannot handle. Check whether we can turn
* it into something we can handle.
static int get_any_page(struct page *page, unsigned long pfn, int flags) */
{ if (pass++ < 3) {
int ret = __get_any_page(page, pfn, flags); put_page(p);
shake_page(p, 1);
if (ret == -EBUSY) count_increased = false;
ret = __get_any_page(page, pfn, flags); goto try_again;
}
if (ret == 1 && !PageHuge(page) && put_page(p);
!PageLRU(page) && !__PageMovable(page)) { ret = -EIO;
/*
* Try to free it.
*/
put_page(page);
shake_page(page, 1);
/*
* Did it turn free?
*/
ret = __get_any_page(page, pfn, 0);
if (ret == 1 && !PageLRU(page)) {
/* Drop page reference which is from __get_any_page() */
put_page(page);
pr_info("soft_offline: %#lx: unknown non LRU page type %lx (%pGp)\n",
pfn, page->flags, &page->flags);
return -EIO;
} }
} }
return ret; return ret;
} }
...@@ -1939,7 +1920,7 @@ int soft_offline_page(unsigned long pfn, int flags) ...@@ -1939,7 +1920,7 @@ int soft_offline_page(unsigned long pfn, int flags)
return -EIO; return -EIO;
if (PageHWPoison(page)) { if (PageHWPoison(page)) {
pr_info("soft offline: %#lx page already poisoned\n", pfn); pr_info("%s: %#lx page already poisoned\n", __func__, pfn);
if (flags & MF_COUNT_INCREASED) if (flags & MF_COUNT_INCREASED)
put_page(page); put_page(page);
return 0; return 0;
...@@ -1947,16 +1928,20 @@ int soft_offline_page(unsigned long pfn, int flags) ...@@ -1947,16 +1928,20 @@ int soft_offline_page(unsigned long pfn, int flags)
retry: retry:
get_online_mems(); get_online_mems();
ret = get_any_page(page, pfn, flags); ret = get_any_page(page, flags);
put_online_mems(); put_online_mems();
if (ret > 0) if (ret > 0) {
ret = soft_offline_in_use_page(page); ret = soft_offline_in_use_page(page);
else if (ret == 0) } else if (ret == 0) {
if (soft_offline_free_page(page) && try_again) { if (soft_offline_free_page(page) && try_again) {
try_again = false; try_again = false;
goto retry; goto retry;
} }
} else if (ret == -EIO) {
pr_info("%s: %#lx: unknown page type: %lx (%pGP)\n",
__func__, pfn, page->flags, &page->flags);
}
return ret; return ret;
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册