From: Oscar Salvador osalvador@suse.de
mainline inclusion from linux-v5.10-rc1 commit 694bf0b0cdf91be50e6f037ca93733ed83ca1187 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4LE22 CVE: NA
--------------------------------
Place the THP's page handling in a helper and use it from both hard and soft-offline machinery, so we get rid of some duplicated code.
Signed-off-by: Oscar Salvador osalvador@suse.de Acked-by: Naoya Horiguchi naoya.horiguchi@nec.com Signed-off-by: Ma Wupeng mawupeng1@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- mm/memory-failure.c | 51 ++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 28 deletions(-)
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index fb328fcac431a..40fdc743b5e90 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1085,6 +1085,25 @@ static int identify_page_state(unsigned long pfn, struct page *p, return page_action(ps, p, pfn); }
+static int try_to_split_thp_page(struct page *page, const char *msg) +{ + lock_page(page); + if (!PageAnon(page) || unlikely(split_huge_page(page))) { + unsigned long pfn = page_to_pfn(page); + + unlock_page(page); + if (!PageAnon(page)) + pr_info("%s: %#lx: non anonymous thp\n", msg, pfn); + else + pr_info("%s: %#lx: thp split failed\n", msg, pfn); + put_page(page); + return -EBUSY; + } + unlock_page(page); + + return 0; +} + static int memory_failure_hugetlb(unsigned long pfn, int flags) { struct page *p = pfn_to_page(pfn); @@ -1316,22 +1335,8 @@ int memory_failure(unsigned long pfn, int flags) }
if (PageTransHuge(hpage)) { - lock_page(p); - if (!PageAnon(p) || unlikely(split_huge_page(p))) { - unlock_page(p); - if (!PageAnon(p)) - pr_err("Memory failure: %#lx: non anonymous thp\n", - pfn); - else - pr_err("Memory failure: %#lx: thp split failed\n", - pfn); - if (TestClearPageHWPoison(p)) - num_poisoned_pages_dec(); - put_page(p); - res = -EBUSY; - goto unlock_mutex; - } - unlock_page(p); + if (try_to_split_thp_page(p, "Memory Failure") < 0) + return -EBUSY; VM_BUG_ON_PAGE(!page_count(p), p); }
@@ -1852,19 +1857,9 @@ static int soft_offline_in_use_page(struct page *page, int flags) int mt; struct page *hpage = compound_head(page);
- if (!PageHuge(page) && PageTransHuge(hpage)) { - lock_page(page); - if (!PageAnon(page) || unlikely(split_huge_page(page))) { - unlock_page(page); - if (!PageAnon(page)) - pr_info("soft offline: %#lx: non anonymous thp\n", page_to_pfn(page)); - else - pr_info("soft offline: %#lx: thp split failed\n", page_to_pfn(page)); - put_page(page); + if (!PageHuge(page) && PageTransHuge(hpage)) + if (try_to_split_thp_page(page, "soft offline") < 0) return -EBUSY; - } - unlock_page(page); - }
/* * Setting MIGRATE_ISOLATE here ensures that the page will be linked