提交 9eb1ae72 编写于 作者: N Naoya Horiguchi 提交者: Yang Yingliang

mm, hwpoison: double-check page count in __get_any_page()

mainline inclusion
from mainline-v5.10-rc1
commit 1f2481dd
category: bugfix
bugzilla: 44803
CVE: NA

-------------------------------------------------

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: NQian Cai <cai@lca.pw>
Signed-off-by: NNaoya Horiguchi <naoya.horiguchi@nec.com>
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Cc: Aristeu Rozanski <aris@ruivo.org>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: Dmitry Yakunin <zeil@yandex-team.ru>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Mike Kravetz <mike.kravetz@oracle.com>
Cc: Oscar Salvador <osalvador@suse.com>
Cc: Tony Luck <tony.luck@intel.com>
Link: https://lkml.kernel.org/r/20200922135650.1634-14-osalvador@suse.deSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: NLiu Shixin <liushixin2@huawei.com>
Reviewed-by: NKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: NCheng Jian <cj.chengjian@huawei.com>
上级 c5e3a0ed
...@@ -1646,6 +1646,9 @@ static int __get_any_page(struct page *p, unsigned long pfn, int flags) ...@@ -1646,6 +1646,9 @@ static int __get_any_page(struct page *p, unsigned long pfn, int flags)
} else if (is_free_buddy_page(p)) { } else if (is_free_buddy_page(p)) {
pr_info("%s: %#lx free buddy page\n", __func__, pfn); pr_info("%s: %#lx free buddy page\n", __func__, pfn);
ret = 0; ret = 0;
} else if (page_count(p)) {
/* raced with allocation */
ret = -EBUSY;
} else { } else {
pr_info("%s: %#lx: unknown zero refcount page type %lx\n", pr_info("%s: %#lx: unknown zero refcount page type %lx\n",
__func__, pfn, p->flags); __func__, pfn, p->flags);
...@@ -1662,6 +1665,9 @@ static int get_any_page(struct page *page, unsigned long pfn, int flags) ...@@ -1662,6 +1665,9 @@ static int get_any_page(struct page *page, unsigned long pfn, int flags)
{ {
int ret = __get_any_page(page, pfn, flags); int ret = __get_any_page(page, pfn, flags);
if (ret == -EBUSY)
ret = __get_any_page(page, pfn, flags);
if (ret == 1 && !PageHuge(page) && if (ret == 1 && !PageHuge(page) &&
!PageLRU(page) && !__PageMovable(page)) { !PageLRU(page) && !__PageMovable(page)) {
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册