From: Naoya Horiguchi <naoya.horiguchi@xxxxxxx> HWPoisonHandlable() introduced by patch "mm,hwpoison: fix race with hugetlb page allocation" filters error events by page type, and only limited events reach get_page_unless_zero() to avoid race. Actually this is too restictive because get_hwpoison_page always fails to take refcount for any types of kernel page, leading to MF_MSG_KERNEL_HIGH_ORDER. This is not critical (no panic), but less informative than MF_MSG_SLAB or MF_MSG_PAGETABLE, so extend HWPoisonHandlable() to some basic types of kernel pages (slab, pgtable, and reserved pages). The "handling" for these types are still primitive (just taking refcount and setting PG_hwpoison) and some more aggressive actions for memory error containment are possible and wanted. But compared to the older code, these cases never enter the code block of page locks (note that page locks is not well-defined on these pages), so it's a little safer for functions intended for user pages not to be called for kernel pages. Signed-off-by: Naoya Horiguchi <naoya.horiguchi@xxxxxxx> --- mm/memory-failure.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git v5.13-rc5/mm/memory-failure.c v5.13-rc5_patched/mm/memory-failure.c index b986936e50eb..0d51067f0129 100644 --- v5.13-rc5/mm/memory-failure.c +++ v5.13-rc5_patched/mm/memory-failure.c @@ -1113,7 +1113,8 @@ static int page_action(struct page_state *ps, struct page *p, */ static inline bool HWPoisonHandlable(struct page *page) { - return PageLRU(page) || __PageMovable(page); + return PageLRU(page) || __PageMovable(page) || + PageSlab(page) || PageTable(page) || PageReserved(page); } static int __get_hwpoison_page(struct page *page) @@ -1260,12 +1261,6 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn, struct page *hpage = *hpagep; bool mlocked = PageMlocked(hpage); - /* - * Here we are interested only in user-mapped pages, so skip any - * other types of pages. - */ - if (PageReserved(p) || PageSlab(p)) - return true; if (!(PageLRU(hpage) || PageHuge(p))) return true; @@ -1670,7 +1665,10 @@ int memory_failure(unsigned long pfn, int flags) action_result(pfn, MF_MSG_BUDDY, res); res = res == MF_RECOVERED ? 0 : -EBUSY; } else { - action_result(pfn, MF_MSG_KERNEL_HIGH_ORDER, MF_IGNORED); + if (PageCompound(p)) + action_result(pfn, MF_MSG_KERNEL_HIGH_ORDER, MF_IGNORED); + else + action_result(pfn, MF_MSG_KERNEL, MF_IGNORED); res = -EBUSY; } goto unlock_mutex; @@ -1681,6 +1679,20 @@ int memory_failure(unsigned long pfn, int flags) } } + if (PageSlab(p)) { + action_result(pfn, MF_MSG_SLAB, MF_IGNORED); + res = -EBUSY; + goto unlock_mutex; + } else if (PageTable(p)) { + action_result(pfn, MF_MSG_PAGETABLE, MF_IGNORED); + res = -EBUSY; + goto unlock_mutex; + } else if (PageReserved(p)) { + action_result(pfn, MF_MSG_KERNEL, MF_IGNORED); + res = -EBUSY; + goto unlock_mutex; + } + if (PageTransHuge(hpage)) { if (try_to_split_thp_page(p, "Memory Failure") < 0) { action_result(pfn, MF_MSG_UNSPLIT_THP, MF_IGNORED); -- 2.25.1