[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200917133959.GA2504@linux>
Date: Thu, 17 Sep 2020 15:40:06 +0200
From: Oscar Salvador <osalvador@...e.de>
To: HORIGUCHI NAOYA(堀口 直也)
<naoya.horiguchi@....com>
Cc: "akpm@...ux-foundation.org" <akpm@...ux-foundation.org>,
"aris@...vo.org" <aris@...vo.org>,
"mhocko@...nel.org" <mhocko@...nel.org>,
"tony.luck@...el.com" <tony.luck@...el.com>,
"cai@....pw" <cai@....pw>,
"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
"linux-mm@...ck.org" <linux-mm@...ck.org>
Subject: Re: [PATCH v4 0/7] HWpoison: further fixes and cleanups
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
Powered by blists - more mailing lists