diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 63b26a9cca33553d2fe83e3150d85e56c8efbd16..7a69a295fc3ef0b1c14b7e4c77435908d909ce51 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -953,13 +953,13 @@ static int page_action(struct page_state *ps, struct page *p, } /** - * get_hwpoison_page() - Get refcount for memory error handling: + * __get_hwpoison_page() - Get refcount for memory error handling: * @page: raw error page (hit by memory error) * * Return: return 0 if failed to grab the refcount, otherwise true (some * non-zero value.) */ -int get_hwpoison_page(struct page *page) +static int __get_hwpoison_page(struct page *page) { struct page *head = compound_head(page); @@ -988,6 +988,26 @@ int get_hwpoison_page(struct page *page) return 0; } + +int get_hwpoison_page(struct page *p) +{ + int ret; + bool drained = false; + +retry: + ret = __get_hwpoison_page(p); + if (!ret && !is_free_buddy_page(p) && !page_count(p) && !drained) { + /* + * The page might be in a pcplist, so try to drain those + * and see if we are lucky. + */ + drain_all_pages(page_zone(p)); + drained = true; + goto retry; + } + + return ret; +} EXPORT_SYMBOL_GPL(get_hwpoison_page); /*