On Thu, Sep 17, 2020 at 03:09:52PM +0200, Oscar Salvador wrote: > static bool page_handle_poison(struct page *page, bool hugepage_or_freepage, bool release) > { > if (release) { > put_page(page); > drain_all_pages(page_zone(page)); > } > > ... > SetPageHWPoison(page); > page_ref_inc(page); > > 1) You are freeing the page first, which means it goes to buddy > 2) Then you set it as poisoned and you update its refcount. > > Now we have a page sitting in Buddy with a refcount = 1 and poisoned, and that is quite wrong. Hi Naoya, Ok, I tested it and with the following changes on top I cannot reproduce the issue: diff --git a/mm/memory-failure.c b/mm/memory-failure.c index f68cb5e3b320..4ffaaa5c2603 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -67,11 +67,6 @@ atomic_long_t num_poisoned_pages __read_mostly = ATOMIC_LONG_INIT(0); static bool page_handle_poison(struct page *page, bool hugepage_or_freepage, bool release) { - if (release) { - put_page(page); - drain_all_pages(page_zone(page)); - } - if (hugepage_or_freepage) { /* * Doing this check for free pages is also fine since dissolve_free_huge_page @@ -89,6 +84,12 @@ static bool page_handle_poison(struct page *page, bool hugepage_or_freepage, boo } SetPageHWPoison(page); + + if (release) { + put_page(page); + drain_all_pages(page_zone(page)); + } + page_ref_inc(page); num_poisoned_pages_inc(); return true; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 0d9f9bd0e06c..8a6ab05f074c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1173,6 +1173,16 @@ static __always_inline bool free_pages_prepare(struct page *page, trace_mm_page_free(page, order); + if (unlikely(PageHWPoison(page)) && !order) { + /* + * Untie memcg state and reset page's owner + */ + if (memcg_kmem_enabled() && PageKmemcg(page)) + __memcg_kmem_uncharge_page(page, order); + reset_page_owner(page, order); + return false; + } + /* * Check tail pages before head page information is cleared to * avoid checking PageCompound for order-0 pages. # sh tmp_run_ksm_madv.sh p1 0x7f6b6b08e000 p2 0x7f6b529ee000 madvise(p1) 0 madvise(p2) 0 writing p1 ... done writing p2 ... done soft offline soft offline returns 0 OK Can you try to re-run your tests and see if they come clean? If they do, I will try to see if Andrew can squezee above changes into [1], where they belong to. Otherwise I will craft a v5 containing all fixups (pretty unfortunate). [1] https://patchwork.kernel.org/patch/11704099/ -- Oscar Salvador SUSE L3