* [PATCH v3 2/8] mm/hwpoison: don't need to hold compound lock for hugetlbfs page
2013-08-26 1:18 [PATCH v3 1/8] mm/hwpoison: fix lose PG_dirty flag for errors on mlocked pages Wanpeng Li
@ 2013-08-26 1:18 ` Wanpeng Li
2013-08-26 1:18 ` [PATCH v3 3/8] mm/hwpoison: fix race against poison thp Wanpeng Li
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Wanpeng Li @ 2013-08-26 1:18 UTC (permalink / raw)
To: Andrew Morton
Cc: Andi Kleen, Fengguang Wu, Naoya Horiguchi, Tony Luck, gong.chen,
linux-mm, linux-kernel, Wanpeng Li
v1 -> v2:
* drop compound_trans_order completely
compound lock is introduced by commit e9da73d67("thp: compound_lock."),
it is used to serialize put_page against __split_huge_page_refcount().
In addition, transparent hugepages will be splitted in hwpoison handler
and just one subpage will be poisoned. There is unnecessary to hold
compound lock for hugetlbfs page. This patch replace compound_trans_order
by compond_order in the place where the page is hugetlbfs page.
Reviewed-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Signed-off-by: Wanpeng Li <liwanp@linux.vnet.ibm.com>
---
include/linux/mm.h | 14 --------------
mm/memory-failure.c | 12 ++++++------
2 files changed, 6 insertions(+), 20 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index f022460..1745a2a 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -489,20 +489,6 @@ static inline int compound_order(struct page *page)
return (unsigned long)page[1].lru.prev;
}
-static inline int compound_trans_order(struct page *page)
-{
- int order;
- unsigned long flags;
-
- if (!PageHead(page))
- return 0;
-
- flags = compound_lock_irqsave(page);
- order = compound_order(page);
- compound_unlock_irqrestore(page, flags);
- return order;
-}
-
static inline void set_compound_order(struct page *page, unsigned long order)
{
page[1].lru.prev = (void *)order;
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 2c13aa7..efa6bd7 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -206,7 +206,7 @@ static int kill_proc(struct task_struct *t, unsigned long addr, int trapno,
#ifdef __ARCH_SI_TRAPNO
si.si_trapno = trapno;
#endif
- si.si_addr_lsb = compound_trans_order(compound_head(page)) + PAGE_SHIFT;
+ si.si_addr_lsb = compound_order(compound_head(page)) + PAGE_SHIFT;
if ((flags & MF_ACTION_REQUIRED) && t == current) {
si.si_code = BUS_MCEERR_AR;
@@ -983,7 +983,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
static void set_page_hwpoison_huge_page(struct page *hpage)
{
int i;
- int nr_pages = 1 << compound_trans_order(hpage);
+ int nr_pages = 1 << compound_order(hpage);
for (i = 0; i < nr_pages; i++)
SetPageHWPoison(hpage + i);
}
@@ -991,7 +991,7 @@ static void set_page_hwpoison_huge_page(struct page *hpage)
static void clear_page_hwpoison_huge_page(struct page *hpage)
{
int i;
- int nr_pages = 1 << compound_trans_order(hpage);
+ int nr_pages = 1 << compound_order(hpage);
for (i = 0; i < nr_pages; i++)
ClearPageHWPoison(hpage + i);
}
@@ -1336,7 +1336,7 @@ int unpoison_memory(unsigned long pfn)
return 0;
}
- nr_pages = 1 << compound_trans_order(page);
+ nr_pages = 1 << compound_order(page);
if (!get_page_unless_zero(page)) {
/*
@@ -1491,7 +1491,7 @@ static int soft_offline_huge_page(struct page *page, int flags)
} else {
set_page_hwpoison_huge_page(hpage);
dequeue_hwpoisoned_huge_page(hpage);
- atomic_long_add(1 << compound_trans_order(hpage),
+ atomic_long_add(1 << compound_order(hpage),
&num_poisoned_pages);
}
return ret;
@@ -1551,7 +1551,7 @@ int soft_offline_page(struct page *page, int flags)
if (PageHuge(page)) {
set_page_hwpoison_huge_page(hpage);
dequeue_hwpoisoned_huge_page(hpage);
- atomic_long_add(1 << compound_trans_order(hpage),
+ atomic_long_add(1 << compound_order(hpage),
&num_poisoned_pages);
} else {
SetPageHWPoison(page);
--
1.7.5.4
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 3/8] mm/hwpoison: fix race against poison thp
2013-08-26 1:18 [PATCH v3 1/8] mm/hwpoison: fix lose PG_dirty flag for errors on mlocked pages Wanpeng Li
2013-08-26 1:18 ` [PATCH v3 2/8] mm/hwpoison: don't need to hold compound lock for hugetlbfs page Wanpeng Li
@ 2013-08-26 1:18 ` Wanpeng Li
2013-08-26 1:18 ` [PATCH v3 4/8] mm/hwpoison: replacing atomic_long_sub() with atomic_long_dec() Wanpeng Li
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Wanpeng Li @ 2013-08-26 1:18 UTC (permalink / raw)
To: Andrew Morton
Cc: Andi Kleen, Fengguang Wu, Naoya Horiguchi, Tony Luck, gong.chen,
linux-mm, linux-kernel, Wanpeng Li
v1 -> v2:
* unpoison thp fail
There is a race between hwpoison page and unpoison page, memory_failure
set the page hwpoison and increase num_poisoned_pages without hold page
lock, and one page count will be accounted against thp for num_poisoned_pages.
However, unpoison can occur before memory_failure hold page lock and
split transparent hugepage, unpoison will decrease num_poisoned_pages
by 1 << compound_order since memory_failure has not yet split transparent
hugepage with page lock held. That means we account one page for hwpoison
and 1 << compound_order for unpoison. This patch fix it by inserting a
PageTransHuge check before doing TestClearPageHWPoison, unpoison failed
without clearing PageHWPoison and decreasing num_poisoned_pages.
A B
memory_failue
TestSetPageHWPoison(p);
if (PageHuge(p))
nr_pages = 1 << compound_order(hpage);
else
nr_pages = 1;
atomic_long_add(nr_pages, &num_poisoned_pages);
unpoison_memory
nr_pages = 1<< compound_trans_order(page);
if(TestClearPageHWPoison(p))
atomic_long_sub(nr_pages, &num_poisoned_pages);
lock page
if (!PageHWPoison(p))
unlock page and return
hwpoison_user_mappings
if (PageTransHuge(hpage))
split_huge_page(hpage);
Suggested-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Signed-off-by: Wanpeng Li <liwanp@linux.vnet.ibm.com>
---
mm/memory-failure.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 5a4f4d6..a6c4752 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1339,6 +1339,16 @@ int unpoison_memory(unsigned long pfn)
return 0;
}
+ /*
+ * unpoison_memory() can encounter thp only when the thp is being
+ * worked by memory_failure() and the page lock is not held yet.
+ * In such case, we yield to memory_failure() and make unpoison fail.
+ */
+ if (PageTransHuge(page)) {
+ pr_info("MCE: Memory failure is now running on %#lx\n", pfn);
+ return 0;
+ }
+
nr_pages = 1 << compound_order(page);
if (!get_page_unless_zero(page)) {
--
1.8.1.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 4/8] mm/hwpoison: replacing atomic_long_sub() with atomic_long_dec()
2013-08-26 1:18 [PATCH v3 1/8] mm/hwpoison: fix lose PG_dirty flag for errors on mlocked pages Wanpeng Li
2013-08-26 1:18 ` [PATCH v3 2/8] mm/hwpoison: don't need to hold compound lock for hugetlbfs page Wanpeng Li
2013-08-26 1:18 ` [PATCH v3 3/8] mm/hwpoison: fix race against poison thp Wanpeng Li
@ 2013-08-26 1:18 ` Wanpeng Li
2013-08-26 1:18 ` [PATCH v3 5/8] mm/hwpoison: don't set migration type twice to avoid hold heavy contend zone->lock Wanpeng Li
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Wanpeng Li @ 2013-08-26 1:18 UTC (permalink / raw)
To: Andrew Morton
Cc: Andi Kleen, Fengguang Wu, Naoya Horiguchi, Tony Luck, gong.chen,
linux-mm, linux-kernel, Wanpeng Li
Repalce atomic_long_sub() with atomic_long_dec() since the page is
normal page instead of hugetlbfs page or thp.
Reviewed-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Signed-off-by: Wanpeng Li <liwanp@linux.vnet.ibm.com>
---
mm/memory-failure.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index a6c4752..297965e 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1363,7 +1363,7 @@ int unpoison_memory(unsigned long pfn)
return 0;
}
if (TestClearPageHWPoison(p))
- atomic_long_sub(nr_pages, &num_poisoned_pages);
+ atomic_long_dec(&num_poisoned_pages);
pr_info("MCE: Software-unpoisoned free page %#lx\n", pfn);
return 0;
}
--
1.8.1.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 5/8] mm/hwpoison: don't set migration type twice to avoid hold heavy contend zone->lock
2013-08-26 1:18 [PATCH v3 1/8] mm/hwpoison: fix lose PG_dirty flag for errors on mlocked pages Wanpeng Li
` (2 preceding siblings ...)
2013-08-26 1:18 ` [PATCH v3 4/8] mm/hwpoison: replacing atomic_long_sub() with atomic_long_dec() Wanpeng Li
@ 2013-08-26 1:18 ` Wanpeng Li
2013-08-26 1:18 ` [PATCH v3 6/8] mm/hwpoison: drop forward reference declarations __soft_offline_page() Wanpeng Li
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Wanpeng Li @ 2013-08-26 1:18 UTC (permalink / raw)
To: Andrew Morton
Cc: Andi Kleen, Fengguang Wu, Naoya Horiguchi, Tony Luck, gong.chen,
linux-mm, linux-kernel, Wanpeng Li
v1 -> v2:
* add more explanation in patch description.
v2 -> v3:
* set MIGRATE_ISOLATE only if it's not set.
Set pageblock migration type will hold zone->lock which is heavy contended
in system to avoid race. However, soft offline page will set pageblock
migration type twice during get page if the page is in used, not hugetlbfs
page and not on lru list. There is unnecessary to set the pageblock migration
type and hold heavy contended zone->lock again if the first round get page
have already set the pageblock to right migration type.
The trick here is migration type is MIGRATE_ISOLATE. There are other two parts
can change MIGRATE_ISOLATE except hwpoison. One is memory hoplug, however, we
hold lock_memory_hotplug() which avoid race. The second is CMA which umovable
page allocation requst can't fallback to. So it's safe here.
Signed-off-by: Wanpeng Li <liwanp@linux.vnet.ibm.com>
---
mm/memory-failure.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 297965e..f357c91 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1426,7 +1426,8 @@ static int __get_any_page(struct page *p, unsigned long pfn, int flags)
* was free. This flag should be kept set until the source page
* is freed and PG_hwpoison on it is set.
*/
- set_migratetype_isolate(p, true);
+ if (get_pageblock_migratetype(p) != MIGRATE_ISOLATE)
+ set_migratetype_isolate(p, true);
/*
* When the target page is a free hugepage, just remove it
* from free hugepage list.
--
1.8.1.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 6/8] mm/hwpoison: drop forward reference declarations __soft_offline_page()
2013-08-26 1:18 [PATCH v3 1/8] mm/hwpoison: fix lose PG_dirty flag for errors on mlocked pages Wanpeng Li
` (3 preceding siblings ...)
2013-08-26 1:18 ` [PATCH v3 5/8] mm/hwpoison: don't set migration type twice to avoid hold heavy contend zone->lock Wanpeng Li
@ 2013-08-26 1:18 ` Wanpeng Li
2013-08-26 1:18 ` [PATCH v3 7/8] mm/hwpoison: add '#' to madvise_hwpoison Wanpeng Li
2013-08-26 1:18 ` [PATCH v3 8/8] mm/hwpoison: fix memory failure still hold reference count after unpoison empty zero page Wanpeng Li
6 siblings, 0 replies; 8+ messages in thread
From: Wanpeng Li @ 2013-08-26 1:18 UTC (permalink / raw)
To: Andrew Morton
Cc: Andi Kleen, Fengguang Wu, Naoya Horiguchi, Tony Luck, gong.chen,
linux-mm, linux-kernel, Wanpeng Li
Drop forward reference declarations __soft_offline_page.
Reviewed-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Signed-off-by: Wanpeng Li <liwanp@linux.vnet.ibm.com>
---
mm/memory-failure.c | 128 ++++++++++++++++++++++++++--------------------------
1 file changed, 63 insertions(+), 65 deletions(-)
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index f357c91..ca714ac 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1511,71 +1511,6 @@ static int soft_offline_huge_page(struct page *page, int flags)
return ret;
}
-static int __soft_offline_page(struct page *page, int flags);
-
-/**
- * soft_offline_page - Soft offline a page.
- * @page: page to offline
- * @flags: flags. Same as memory_failure().
- *
- * Returns 0 on success, otherwise negated errno.
- *
- * Soft offline a page, by migration or invalidation,
- * without killing anything. This is for the case when
- * a page is not corrupted yet (so it's still valid to access),
- * but has had a number of corrected errors and is better taken
- * out.
- *
- * The actual policy on when to do that is maintained by
- * user space.
- *
- * This should never impact any application or cause data loss,
- * however it might take some time.
- *
- * This is not a 100% solution for all memory, but tries to be
- * ``good enough'' for the majority of memory.
- */
-int soft_offline_page(struct page *page, int flags)
-{
- int ret;
- unsigned long pfn = page_to_pfn(page);
- struct page *hpage = compound_trans_head(page);
-
- if (PageHWPoison(page)) {
- pr_info("soft offline: %#lx page already poisoned\n", pfn);
- return -EBUSY;
- }
- if (!PageHuge(page) && PageTransHuge(hpage)) {
- if (PageAnon(hpage) && unlikely(split_huge_page(hpage))) {
- pr_info("soft offline: %#lx: failed to split THP\n",
- pfn);
- return -EBUSY;
- }
- }
-
- ret = get_any_page(page, pfn, flags);
- if (ret < 0)
- return ret;
- if (ret) { /* for in-use pages */
- if (PageHuge(page))
- ret = soft_offline_huge_page(page, flags);
- else
- ret = __soft_offline_page(page, flags);
- } else { /* for free pages */
- if (PageHuge(page)) {
- set_page_hwpoison_huge_page(hpage);
- dequeue_hwpoisoned_huge_page(hpage);
- atomic_long_add(1 << compound_order(hpage),
- &num_poisoned_pages);
- } else {
- SetPageHWPoison(page);
- atomic_long_inc(&num_poisoned_pages);
- }
- }
- unset_migratetype_isolate(page, MIGRATE_MOVABLE);
- return ret;
-}
-
static int __soft_offline_page(struct page *page, int flags)
{
int ret;
@@ -1662,3 +1597,66 @@ static int __soft_offline_page(struct page *page, int flags)
}
return ret;
}
+
+/**
+ * soft_offline_page - Soft offline a page.
+ * @page: page to offline
+ * @flags: flags. Same as memory_failure().
+ *
+ * Returns 0 on success, otherwise negated errno.
+ *
+ * Soft offline a page, by migration or invalidation,
+ * without killing anything. This is for the case when
+ * a page is not corrupted yet (so it's still valid to access),
+ * but has had a number of corrected errors and is better taken
+ * out.
+ *
+ * The actual policy on when to do that is maintained by
+ * user space.
+ *
+ * This should never impact any application or cause data loss,
+ * however it might take some time.
+ *
+ * This is not a 100% solution for all memory, but tries to be
+ * ``good enough'' for the majority of memory.
+ */
+int soft_offline_page(struct page *page, int flags)
+{
+ int ret;
+ unsigned long pfn = page_to_pfn(page);
+ struct page *hpage = compound_trans_head(page);
+
+ if (PageHWPoison(page)) {
+ pr_info("soft offline: %#lx page already poisoned\n", pfn);
+ return -EBUSY;
+ }
+ if (!PageHuge(page) && PageTransHuge(hpage)) {
+ if (PageAnon(hpage) && unlikely(split_huge_page(hpage))) {
+ pr_info("soft offline: %#lx: failed to split THP\n",
+ pfn);
+ return -EBUSY;
+ }
+ }
+
+ ret = get_any_page(page, pfn, flags);
+ if (ret < 0)
+ return ret;
+ if (ret) { /* for in-use pages */
+ if (PageHuge(page))
+ ret = soft_offline_huge_page(page, flags);
+ else
+ ret = __soft_offline_page(page, flags);
+ } else { /* for free pages */
+ if (PageHuge(page)) {
+ set_page_hwpoison_huge_page(hpage);
+ dequeue_hwpoisoned_huge_page(hpage);
+ atomic_long_add(1 << compound_order(hpage),
+ &num_poisoned_pages);
+ } else {
+ SetPageHWPoison(page);
+ atomic_long_inc(&num_poisoned_pages);
+ }
+ }
+ unset_migratetype_isolate(page, MIGRATE_MOVABLE);
+ return ret;
+}
--
1.8.1.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 7/8] mm/hwpoison: add '#' to madvise_hwpoison
2013-08-26 1:18 [PATCH v3 1/8] mm/hwpoison: fix lose PG_dirty flag for errors on mlocked pages Wanpeng Li
` (4 preceding siblings ...)
2013-08-26 1:18 ` [PATCH v3 6/8] mm/hwpoison: drop forward reference declarations __soft_offline_page() Wanpeng Li
@ 2013-08-26 1:18 ` Wanpeng Li
2013-08-26 1:18 ` [PATCH v3 8/8] mm/hwpoison: fix memory failure still hold reference count after unpoison empty zero page Wanpeng Li
6 siblings, 0 replies; 8+ messages in thread
From: Wanpeng Li @ 2013-08-26 1:18 UTC (permalink / raw)
To: Andrew Morton
Cc: Andi Kleen, Fengguang Wu, Naoya Horiguchi, Tony Luck, gong.chen,
linux-mm, linux-kernel, Wanpeng Li
Add '#' to madvise_hwpoison.
Before patch:
[ 95.892866] Injecting memory failure for page 19d0 at b7786000
[ 95.893151] MCE 0x19d0: non LRU page recovery: Ignored
After patch:
[ 95.892866] Injecting memory failure for page 0x19d0 at 0xb7786000
[ 95.893151] MCE 0x19d0: non LRU page recovery: Ignored
Reviewed-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Signed-off-by: Wanpeng Li <liwanp@linux.vnet.ibm.com>
---
mm/madvise.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mm/madvise.c b/mm/madvise.c
index 95795df..588bb19 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -353,14 +353,14 @@ static int madvise_hwpoison(int bhv, unsigned long start, unsigned long end)
if (ret != 1)
return ret;
if (bhv == MADV_SOFT_OFFLINE) {
- printk(KERN_INFO "Soft offlining page %lx at %lx\n",
+ pr_info("Soft offlining page %#lx at %#lx\n",
page_to_pfn(p), start);
ret = soft_offline_page(p, MF_COUNT_INCREASED);
if (ret)
break;
continue;
}
- printk(KERN_INFO "Injecting memory failure for page %lx at %lx\n",
+ pr_info("Injecting memory failure for page %#lx at %#lx\n",
page_to_pfn(p), start);
/* Ignore return value for now */
memory_failure(page_to_pfn(p), 0, MF_COUNT_INCREASED);
--
1.8.1.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 8/8] mm/hwpoison: fix memory failure still hold reference count after unpoison empty zero page
2013-08-26 1:18 [PATCH v3 1/8] mm/hwpoison: fix lose PG_dirty flag for errors on mlocked pages Wanpeng Li
` (5 preceding siblings ...)
2013-08-26 1:18 ` [PATCH v3 7/8] mm/hwpoison: add '#' to madvise_hwpoison Wanpeng Li
@ 2013-08-26 1:18 ` Wanpeng Li
6 siblings, 0 replies; 8+ messages in thread
From: Wanpeng Li @ 2013-08-26 1:18 UTC (permalink / raw)
To: Andrew Morton
Cc: Andi Kleen, Fengguang Wu, Naoya Horiguchi, Tony Luck, gong.chen,
linux-mm, linux-kernel, Wanpeng Li
madvise hwpoison inject will poison the read-only empty zero page if there is
no write access before poison. Empty zero page reference count will be increased
for hwpoison, subsequent poison zero page will return directly since page has
already been set PG_hwpoison, however, page reference count is still increased
by get_user_pages_fast. The unpoison process will unpoison the empty zero page
and decrease the reference count successfully for the fist time, however,
subsequent unpoison empty zero page will return directly since page has already
been unpoisoned and without decrease the page reference count of empty zero page.
This patch fix it by decrease page reference count for empty zero page which has
already been unpoisoned and page count > 1.
Testcase:
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <errno.h>
#define PAGES_TO_TEST 3
#define PAGE_SIZE 4096
int main(void)
{
char *mem;
int i;
mem = mmap(NULL, PAGES_TO_TEST * PAGE_SIZE,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
if (madvise(mem, PAGES_TO_TEST * PAGE_SIZE, MADV_HWPOISON) == -1)
return -1;
munmap(mem, PAGES_TO_TEST * PAGE_SIZE);
return 0;
}
Add printk to dump page reference count:
[ 93.075959] Injecting memory failure for page 0x19d0 at 0xb77d8000
[ 93.076207] MCE 0x19d0: non LRU page recovery: Ignored
[ 93.076209] pfn 0x19d0, page count = 1 after memory failure
[ 93.076220] Injecting memory failure for page 0x19d0 at 0xb77d9000
[ 93.076221] MCE 0x19d0: already hardware poisoned
[ 93.076222] pfn 0x19d0, page count = 2 after memory failure
[ 93.076224] Injecting memory failure for page 0x19d0 at 0xb77da000
[ 93.076224] MCE 0x19d0: already hardware poisoned
[ 93.076225] pfn 0x19d0, page count = 3 after memory failure
Before patch:
[ 139.197474] MCE: Software-unpoisoned page 0x19d0
[ 139.197479] pfn 0x19d0, page count = 2 after unpoison memory
[ 150.478130] MCE: Page was already unpoisoned 0x19d0
[ 150.478135] pfn 0x19d0, page count = 2 after unpoison memory
[ 151.548288] MCE: Page was already unpoisoned 0x19d0
[ 151.548292] pfn 0x19d0, page count = 2 after unpoison memory
After patch:
[ 116.022122] MCE: Software-unpoisoned page 0x19d0
[ 116.022127] pfn 0x19d0, page count = 2 after unpoison memory
[ 117.256163] MCE: Page was already unpoisoned 0x19d0
[ 117.256167] pfn 0x19d0, page count = 1 after unpoison memory
[ 117.917772] MCE: Page was already unpoisoned 0x19d0
[ 117.917777] pfn 0x19d0, page count = 1 after unpoison memory
Signed-off-by: Wanpeng Li <liwanp@linux.vnet.ibm.com>
---
mm/memory-failure.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index ca714ac..fb687fd 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1335,6 +1335,8 @@ int unpoison_memory(unsigned long pfn)
page = compound_head(p);
if (!PageHWPoison(p)) {
+ if (pfn == my_zero_pfn(0) && page_count(p) > 1)
+ put_page(p);
pr_info("MCE: Page was already unpoisoned %#lx\n", pfn);
return 0;
}
--
1.8.1.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 8+ messages in thread