RAS user space tools like rasdaemon which base on trace event, could
receive mce error event, but no memory recovery result event. So, I
want to add this event to make this scenario complete.
This patch add a event at ras group for memory-failure.
The output like below:
# tracer: nop
#
# entries-in-buffer/entries-written: 2/2 #P:24
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
mce-inject-13150 [001] .... 277.019359: memory_failure_event: pfn 0x19869: recovery action for free buddy page: Delayed
--
v2->v3:
- rebase on top of linux-next
- based on Steven Rostedt's "tracing: Add TRACE_DEFINE_ENUM() macro
to map enums to their values" patch set v1.
v1->v2:
- Comment update
- Just passing 'result' instead of 'action_name[result]',
suggested by Steve. And hard coded there because trace-cmd
and perf do not have a way to process enums.
Xie XiuQi (2):
memory-failure: export page_type and action result
tracing: add trace event for memory-failure
include/linux/mm.h | 34 ++++++++++
include/ras/ras_event.h | 83 ++++++++++++++++++++++++
kernel/trace/trace.c | 2 +-
mm/memory-failure.c | 165 ++++++++++++++++++++----------------------------
4 files changed, 185 insertions(+), 99 deletions(-)
--
1.8.3.1
Export 'outcome' and 'page_type' to mm.h, so we could use this emnus
outside.
This patch is preparation for adding trace events for memory-failure
recovery action.
Signed-off-by: Xie XiuQi <[email protected]>
---
include/linux/mm.h | 34 +++++++++++
mm/memory-failure.c | 163 +++++++++++++++++++++-------------------------------
2 files changed, 99 insertions(+), 98 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 4a3a385..5d812b0 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2114,6 +2114,40 @@ extern void shake_page(struct page *p, int access);
extern atomic_long_t num_poisoned_pages;
extern int soft_offline_page(struct page *page, int flags);
+
+/*
+ * Error handlers for various types of pages.
+ */
+enum mf_outcome {
+ MF_IGNORED, /* Error: cannot be handled */
+ MF_FAILED, /* Error: handling failed */
+ MF_DELAYED, /* Will be handled later */
+ MF_RECOVERED, /* Successfully recovered */
+};
+
+enum mf_page_type {
+ MF_KERNEL,
+ MF_KERNEL_HIGH_ORDER,
+ MF_SLAB,
+ MF_DIFFERENT_COMPOUND,
+ MF_POISONED_HUGE,
+ MF_HUGE,
+ MF_FREE_HUGE,
+ MF_UNMAP_FAILED,
+ MF_DIRTY_SWAPCACHE,
+ MF_CLEAN_SWAPCACHE,
+ MF_DIRTY_MLOCKED_LRU,
+ MF_CLEAN_MLOCKED_LRU,
+ MF_DIRTY_UNEVICTABLE_LRU,
+ MF_CLEAN_UNEVICTABLE_LRU,
+ MF_DIRTY_LRU,
+ MF_CLEAN_LRU,
+ MF_TRUNCATED_LRU,
+ MF_BUDDY,
+ MF_BUDDY_2ND,
+ MF_UNKNOWN,
+};
+
#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLBFS)
extern void clear_huge_page(struct page *page,
unsigned long addr,
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 5074998..34e9c65 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -56,6 +56,7 @@
#include <linux/mm_inline.h>
#include <linux/kfifo.h>
#include "internal.h"
+#include "ras/ras_event.h"
int sysctl_memory_failure_early_kill __read_mostly = 0;
@@ -503,68 +504,34 @@ static void collect_procs(struct page *page, struct list_head *tokill,
kfree(tk);
}
-/*
- * Error handlers for various types of pages.
- */
-
-enum outcome {
- IGNORED, /* Error: cannot be handled */
- FAILED, /* Error: handling failed */
- DELAYED, /* Will be handled later */
- RECOVERED, /* Successfully recovered */
-};
-
static const char *action_name[] = {
- [IGNORED] = "Ignored",
- [FAILED] = "Failed",
- [DELAYED] = "Delayed",
- [RECOVERED] = "Recovered",
-};
-
-enum page_type {
- KERNEL,
- KERNEL_HIGH_ORDER,
- SLAB,
- DIFFERENT_COMPOUND,
- POISONED_HUGE,
- HUGE,
- FREE_HUGE,
- UNMAP_FAILED,
- DIRTY_SWAPCACHE,
- CLEAN_SWAPCACHE,
- DIRTY_MLOCKED_LRU,
- CLEAN_MLOCKED_LRU,
- DIRTY_UNEVICTABLE_LRU,
- CLEAN_UNEVICTABLE_LRU,
- DIRTY_LRU,
- CLEAN_LRU,
- TRUNCATED_LRU,
- BUDDY,
- BUDDY_2ND,
- UNKNOWN,
+ [MF_IGNORED] = "Ignored",
+ [MF_FAILED] = "Failed",
+ [MF_DELAYED] = "Delayed",
+ [MF_RECOVERED] = "Recovered",
};
static const char *action_page_type[] = {
- [KERNEL] = "reserved kernel page",
- [KERNEL_HIGH_ORDER] = "high-order kernel page",
- [SLAB] = "kernel slab page",
- [DIFFERENT_COMPOUND] = "different compound page after locking",
- [POISONED_HUGE] = "huge page already hardware poisoned",
- [HUGE] = "huge page",
- [FREE_HUGE] = "free huge page",
- [UNMAP_FAILED] = "unmapping failed page",
- [DIRTY_SWAPCACHE] = "dirty swapcache page",
- [CLEAN_SWAPCACHE] = "clean swapcache page",
- [DIRTY_MLOCKED_LRU] = "dirty mlocked LRU page",
- [CLEAN_MLOCKED_LRU] = "clean mlocked LRU page",
- [DIRTY_UNEVICTABLE_LRU] = "dirty unevictable LRU page",
- [CLEAN_UNEVICTABLE_LRU] = "clean unevictable LRU page",
- [DIRTY_LRU] = "dirty LRU page",
- [CLEAN_LRU] = "clean LRU page",
- [TRUNCATED_LRU] = "already truncated LRU page",
- [BUDDY] = "free buddy page",
- [BUDDY_2ND] = "free buddy page (2nd try)",
- [UNKNOWN] = "unknown page",
+ [MF_KERNEL] = "reserved kernel page",
+ [MF_KERNEL_HIGH_ORDER] = "high-order kernel page",
+ [MF_SLAB] = "kernel slab page",
+ [MF_DIFFERENT_COMPOUND] = "different compound page after locking",
+ [MF_POISONED_HUGE] = "huge page already hardware poisoned",
+ [MF_HUGE] = "huge page",
+ [MF_FREE_HUGE] = "free huge page",
+ [MF_UNMAP_FAILED] = "unmapping failed page",
+ [MF_DIRTY_SWAPCACHE] = "dirty swapcache page",
+ [MF_CLEAN_SWAPCACHE] = "clean swapcache page",
+ [MF_DIRTY_MLOCKED_LRU] = "dirty mlocked LRU page",
+ [MF_CLEAN_MLOCKED_LRU] = "clean mlocked LRU page",
+ [MF_DIRTY_UNEVICTABLE_LRU] = "dirty unevictable LRU page",
+ [MF_CLEAN_UNEVICTABLE_LRU] = "clean unevictable LRU page",
+ [MF_DIRTY_LRU] = "dirty LRU page",
+ [MF_CLEAN_LRU] = "clean LRU page",
+ [MF_TRUNCATED_LRU] = "already truncated LRU page",
+ [MF_BUDDY] = "free buddy page",
+ [MF_BUDDY_2ND] = "free buddy page (2nd try)",
+ [MF_UNKNOWN] = "unknown page",
};
/*
@@ -598,7 +565,7 @@ static int delete_from_lru_cache(struct page *p)
*/
static int me_kernel(struct page *p, unsigned long pfn)
{
- return IGNORED;
+ return MF_IGNORED;
}
/*
@@ -607,7 +574,7 @@ static int me_kernel(struct page *p, unsigned long pfn)
static int me_unknown(struct page *p, unsigned long pfn)
{
printk(KERN_ERR "MCE %#lx: Unknown page state\n", pfn);
- return FAILED;
+ return MF_FAILED;
}
/*
@@ -616,7 +583,7 @@ static int me_unknown(struct page *p, unsigned long pfn)
static int me_pagecache_clean(struct page *p, unsigned long pfn)
{
int err;
- int ret = FAILED;
+ int ret = MF_FAILED;
struct address_space *mapping;
delete_from_lru_cache(p);
@@ -626,7 +593,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
* should be the one m_f() holds.
*/
if (PageAnon(p))
- return RECOVERED;
+ return MF_RECOVERED;
/*
* Now truncate the page in the page cache. This is really
@@ -640,7 +607,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
/*
* Page has been teared down in the meanwhile
*/
- return FAILED;
+ return MF_FAILED;
}
/*
@@ -657,7 +624,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
!try_to_release_page(p, GFP_NOIO)) {
pr_info("MCE %#lx: failed to release buffers\n", pfn);
} else {
- ret = RECOVERED;
+ ret = MF_RECOVERED;
}
} else {
/*
@@ -665,7 +632,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
* This fails on dirty or anything with private pages
*/
if (invalidate_inode_page(p))
- ret = RECOVERED;
+ ret = MF_RECOVERED;
else
printk(KERN_INFO "MCE %#lx: Failed to invalidate\n",
pfn);
@@ -751,9 +718,9 @@ static int me_swapcache_dirty(struct page *p, unsigned long pfn)
ClearPageUptodate(p);
if (!delete_from_lru_cache(p))
- return DELAYED;
+ return MF_DELAYED;
else
- return FAILED;
+ return MF_FAILED;
}
static int me_swapcache_clean(struct page *p, unsigned long pfn)
@@ -761,9 +728,9 @@ static int me_swapcache_clean(struct page *p, unsigned long pfn)
delete_from_swap_cache(p);
if (!delete_from_lru_cache(p))
- return RECOVERED;
+ return MF_RECOVERED;
else
- return FAILED;
+ return MF_FAILED;
}
/*
@@ -789,9 +756,9 @@ static int me_huge_page(struct page *p, unsigned long pfn)
if (!(page_mapping(hpage) || PageAnon(hpage))) {
res = dequeue_hwpoisoned_huge_page(hpage);
if (!res)
- return RECOVERED;
+ return MF_RECOVERED;
}
- return DELAYED;
+ return MF_DELAYED;
}
/*
@@ -826,7 +793,7 @@ static struct page_state {
int type;
int (*action)(struct page *p, unsigned long pfn);
} error_states[] = {
- { reserved, reserved, KERNEL, me_kernel },
+ { reserved, reserved, MF_KERNEL, me_kernel },
/*
* free pages are specially detected outside this table:
* PG_buddy pages only make a small fraction of all free pages.
@@ -837,31 +804,31 @@ static struct page_state {
* currently unused objects without touching them. But just
* treat it as standard kernel for now.
*/
- { slab, slab, SLAB, me_kernel },
+ { slab, slab, MF_SLAB, me_kernel },
#ifdef CONFIG_PAGEFLAGS_EXTENDED
- { head, head, HUGE, me_huge_page },
- { tail, tail, HUGE, me_huge_page },
+ { head, head, MF_HUGE, me_huge_page },
+ { tail, tail, MF_HUGE, me_huge_page },
#else
- { compound, compound, HUGE, me_huge_page },
+ { compound, compound, MF_HUGE, me_huge_page },
#endif
- { sc|dirty, sc|dirty, DIRTY_SWAPCACHE, me_swapcache_dirty },
- { sc|dirty, sc, CLEAN_SWAPCACHE, me_swapcache_clean },
+ { sc|dirty, sc|dirty, MF_DIRTY_SWAPCACHE, me_swapcache_dirty },
+ { sc|dirty, sc, MF_CLEAN_SWAPCACHE, me_swapcache_clean },
- { mlock|dirty, mlock|dirty, DIRTY_MLOCKED_LRU, me_pagecache_dirty },
- { mlock|dirty, mlock, CLEAN_MLOCKED_LRU, me_pagecache_clean },
+ { mlock|dirty, mlock|dirty, MF_DIRTY_MLOCKED_LRU, me_pagecache_dirty },
+ { mlock|dirty, mlock, MF_CLEAN_MLOCKED_LRU, me_pagecache_clean },
- { unevict|dirty, unevict|dirty, DIRTY_UNEVICTABLE_LRU, me_pagecache_dirty },
- { unevict|dirty, unevict, CLEAN_UNEVICTABLE_LRU, me_pagecache_clean },
+ { unevict|dirty, unevict|dirty, MF_DIRTY_UNEVICTABLE_LRU, me_pagecache_dirty },
+ { unevict|dirty, unevict, MF_CLEAN_UNEVICTABLE_LRU, me_pagecache_clean },
- { lru|dirty, lru|dirty, DIRTY_LRU, me_pagecache_dirty },
- { lru|dirty, lru, CLEAN_LRU, me_pagecache_clean },
+ { lru|dirty, lru|dirty, MF_DIRTY_LRU, me_pagecache_dirty },
+ { lru|dirty, lru, MF_CLEAN_LRU, me_pagecache_clean },
/*
* Catchall entry: must be at end.
*/
- { 0, 0, UNKNOWN, me_unknown },
+ { 0, 0, MF_UNKNOWN, me_unknown },
};
#undef dirty
@@ -896,13 +863,13 @@ static int page_action(struct page_state *ps, struct page *p,
result = ps->action(p, pfn);
count = page_count(p) - 1;
- if (ps->action == me_swapcache_dirty && result == DELAYED)
+ if (ps->action == me_swapcache_dirty && result == MF_DELAYED)
count--;
if (count != 0) {
printk(KERN_ERR
"MCE %#lx: %s still referenced by %d users\n",
pfn, action_page_type[ps->type], count);
- result = FAILED;
+ result = MF_FAILED;
}
action_result(pfn, ps->type, result);
@@ -911,7 +878,7 @@ static int page_action(struct page_state *ps, struct page *p,
* Could adjust zone counters here to correct for the missing page.
*/
- return (result == RECOVERED || result == DELAYED) ? 0 : -EBUSY;
+ return (result == MF_RECOVERED || result == MF_DELAYED) ? 0 : -EBUSY;
}
/*
@@ -1152,7 +1119,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
if (!(flags & MF_COUNT_INCREASED) &&
!get_page_unless_zero(hpage)) {
if (is_free_buddy_page(p)) {
- action_result(pfn, BUDDY, DELAYED);
+ action_result(pfn, MF_BUDDY, MF_DELAYED);
return 0;
} else if (PageHuge(hpage)) {
/*
@@ -1169,12 +1136,12 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
}
set_page_hwpoison_huge_page(hpage);
res = dequeue_hwpoisoned_huge_page(hpage);
- action_result(pfn, FREE_HUGE,
- res ? IGNORED : DELAYED);
+ action_result(pfn, MF_FREE_HUGE,
+ res ? MF_IGNORED : MF_DELAYED);
unlock_page(hpage);
return res;
} else {
- action_result(pfn, KERNEL_HIGH_ORDER, IGNORED);
+ action_result(pfn, MF_KERNEL_HIGH_ORDER, MF_IGNORED);
return -EBUSY;
}
}
@@ -1196,9 +1163,9 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
*/
if (is_free_buddy_page(p)) {
if (flags & MF_COUNT_INCREASED)
- action_result(pfn, BUDDY, DELAYED);
+ action_result(pfn, MF_BUDDY, MF_DELAYED);
else
- action_result(pfn, BUDDY_2ND, DELAYED);
+ action_result(pfn, MF_BUDDY_2ND, MF_DELAYED);
return 0;
}
}
@@ -1211,7 +1178,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
* If this happens just bail out.
*/
if (compound_head(p) != hpage) {
- action_result(pfn, DIFFERENT_COMPOUND, IGNORED);
+ action_result(pfn, MF_DIFFERENT_COMPOUND, MF_IGNORED);
res = -EBUSY;
goto out;
}
@@ -1251,7 +1218,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
* on the head page to show that the hugepage is hwpoisoned
*/
if (PageHuge(p) && PageTail(p) && TestSetPageHWPoison(hpage)) {
- action_result(pfn, POISONED_HUGE, IGNORED);
+ action_result(pfn, MF_POISONED_HUGE, MF_IGNORED);
unlock_page(hpage);
put_page(hpage);
return 0;
@@ -1280,7 +1247,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
*/
if (hwpoison_user_mappings(p, pfn, trapno, flags, &hpage)
!= SWAP_SUCCESS) {
- action_result(pfn, UNMAP_FAILED, IGNORED);
+ action_result(pfn, MF_UNMAP_FAILED, MF_IGNORED);
res = -EBUSY;
goto out;
}
@@ -1289,7 +1256,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
* Torn down by someone else?
*/
if (PageLRU(p) && !PageSwapCache(p) && p->mapping == NULL) {
- action_result(pfn, TRUNCATED_LRU, IGNORED);
+ action_result(pfn, MF_TRUNCATED_LRU, MF_IGNORED);
res = -EBUSY;
goto out;
}
--
1.8.3.1
RAS user space tools like rasdaemon which base on trace event, could
receive mce error event, but no memory recovery result event. So, I
want to add this event to make this scenario complete.
This patch add a event at ras group for memory-failure.
The output like below:
# tracer: nop
#
# entries-in-buffer/entries-written: 2/2 #P:24
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
mce-inject-13150 [001] .... 277.019359: memory_failure_event: pfn 0x19869: recovery action for free buddy page: Delayed
Cc: Tony Luck <[email protected]>
Cc: Steven Rostedt <[email protected]>
Signed-off-by: Xie XiuQi <[email protected]>
---
include/ras/ras_event.h | 83 +++++++++++++++++++++++++++++++++++++++++++++++++
kernel/trace/trace.c | 2 +-
mm/memory-failure.c | 2 ++
3 files changed, 86 insertions(+), 1 deletion(-)
diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
index 79abb9c..52c75f2 100644
--- a/include/ras/ras_event.h
+++ b/include/ras/ras_event.h
@@ -11,6 +11,7 @@
#include <linux/pci.h>
#include <linux/aer.h>
#include <linux/cper.h>
+#include <linux/mm.h>
/*
* MCE Extended Error Log trace event
@@ -232,6 +233,88 @@ TRACE_EVENT(aer_event,
__print_flags(__entry->status, "|", aer_uncorrectable_errors))
);
+/*
+ * memory-failure recovery action result event
+ *
+ * unsigned long pfn - Page Number of the corrupted page
+ * int type - Page types of the corrupted page
+ * int result - Result of recovery action
+ */
+
+#define MF_ACTION_RESULT \
+ EM ( MF_IGNORED, "Ignord" ) \
+ EM ( MF_FAILED, "Failed" ) \
+ EM ( MF_DELAYED, "Delayed" ) \
+ EMe ( MF_RECOVERED, "Recovered" )
+
+#define MF_PAGE_TYPE \
+ EM ( MF_KERNEL, "reserved kernel page" ) \
+ EM ( MF_KERNEL_HIGH_ORDER, "high-order kernel page" ) \
+ EM ( MF_SLAB, "kernel slab page" ) \
+ EM ( MF_DIFFERENT_COMPOUND, "different compound page after locking" ) \
+ EM ( MF_POISONED_HUGE, "huge page already hardware poisoned" ) \
+ EM ( MF_HUGE, "huge page" ) \
+ EM ( MF_FREE_HUGE, "free huge page" ) \
+ EM ( MF_UNMAP_FAILED, "unmapping failed page" ) \
+ EM ( MF_DIRTY_SWAPCACHE, "dirty swapcache page" ) \
+ EM ( MF_CLEAN_SWAPCACHE, "clean swapcache page" ) \
+ EM ( MF_DIRTY_MLOCKED_LRU, "dirty mlocked LRU page" ) \
+ EM ( MF_CLEAN_MLOCKED_LRU, "clean mlocked LRU page" ) \
+ EM ( MF_DIRTY_UNEVICTABLE_LRU, "dirty unevictable LRU page" ) \
+ EM ( MF_CLEAN_UNEVICTABLE_LRU, "clean unevictable LRU page" ) \
+ EM ( MF_DIRTY_LRU, "dirty LRU page" ) \
+ EM ( MF_CLEAN_LRU, "clean LRU page" ) \
+ EM ( MF_TRUNCATED_LRU, "already truncated LRU page" ) \
+ EM ( MF_BUDDY, "free buddy page" ) \
+ EM ( MF_BUDDY_2ND, "free buddy page (2nd try)" ) \
+ EMe ( MF_UNKNOWN, "unknown page" )
+
+/*
+ * First define the enums in MM_ACTION_RESULT to be exported to userspace
+ * via TRACE_DEFINE_ENUM().
+ */
+#undef EM
+#undef EMe
+#define EM(a,b) TRACE_DEFINE_ENUM(a);
+#define EMe(a,b) TRACE_DEFINE_ENUM(a);
+
+MF_ACTION_RESULT
+MF_PAGE_TYPE
+
+/*
+ * Now redefine the EM() and EMe() macros to map the enums to the strings
+ * that will be printed in the output.
+ */
+#undef EM
+#undef EMe
+#define EM(a,b) { a, b },
+#define EMe(a,b) { a, b }
+
+TRACE_EVENT(memory_failure_event,
+ TP_PROTO(unsigned long pfn,
+ int type,
+ int result),
+
+ TP_ARGS(pfn, type, result),
+
+ TP_STRUCT__entry(
+ __field(unsigned long, pfn)
+ __field(int, type)
+ __field(int, result)
+ ),
+
+ TP_fast_assign(
+ __entry->pfn = pfn;
+ __entry->type = type;
+ __entry->result = result;
+ ),
+
+ TP_printk("pfn %#lx: recovery action for %s: %s",
+ __entry->pfn,
+ __print_symbolic(__entry->type, MF_PAGE_TYPE),
+ __print_symbolic(__entry->result, MF_ACTION_RESULT)
+ )
+);
#endif /* _TRACE_HW_EVENT_MC_H */
/* This part must be outside protection */
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 25334e7..f5e8856 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -6776,7 +6776,7 @@ static struct notifier_block trace_module_nb = {
};
#endif
-static __init int tracer_init_debugfs(void)
+static __init int tracer_init_tracefs(void)
{
struct dentry *d_tracer;
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 34e9c65..d118af8 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -850,6 +850,8 @@ static struct page_state {
*/
static void action_result(unsigned long pfn, int type, int result)
{
+ trace_memory_failure_event(pfn, type, result);
+
pr_err("MCE %#lx: recovery action for %s: %s\n",
pfn, action_page_type[type], action_name[result]);
}
--
1.8.3.1
On Tue, Apr 07, 2015 at 07:05:31PM +0800, Xie XiuQi wrote:
> RAS user space tools like rasdaemon which base on trace event, could
> receive mce error event, but no memory recovery result event. So, I
> want to add this event to make this scenario complete.
>
> This patch add a event at ras group for memory-failure.
>
> The output like below:
> # tracer: nop
> #
> # entries-in-buffer/entries-written: 2/2 #P:24
> #
> # _-----=> irqs-off
> # / _----=> need-resched
> # | / _---=> hardirq/softirq
> # || / _--=> preempt-depth
> # ||| / delay
> # TASK-PID CPU# |||| TIMESTAMP FUNCTION
> # | | | |||| | |
> mce-inject-13150 [001] .... 277.019359: memory_failure_event: pfn 0x19869: recovery action for free buddy page: Delayed
>
>
> Cc: Tony Luck <[email protected]>
> Cc: Steven Rostedt <[email protected]>
> Signed-off-by: Xie XiuQi <[email protected]>
> ---
> include/ras/ras_event.h | 83 +++++++++++++++++++++++++++++++++++++++++++++++++
> kernel/trace/trace.c | 2 +-
> mm/memory-failure.c | 2 ++
> 3 files changed, 86 insertions(+), 1 deletion(-)
>
> diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
> index 79abb9c..52c75f2 100644
> --- a/include/ras/ras_event.h
> +++ b/include/ras/ras_event.h
> @@ -11,6 +11,7 @@
> #include <linux/pci.h>
> #include <linux/aer.h>
> #include <linux/cper.h>
> +#include <linux/mm.h>
>
> /*
> * MCE Extended Error Log trace event
> @@ -232,6 +233,88 @@ TRACE_EVENT(aer_event,
> __print_flags(__entry->status, "|", aer_uncorrectable_errors))
> );
>
> +/*
> + * memory-failure recovery action result event
> + *
> + * unsigned long pfn - Page Number of the corrupted page
Hi XiuQi,
I think "Page Frame Number" is better.
And embracing these definition code with #ifdef CONFIG_MEMORY_FAILURE might
be helpful if it reduces binary size for !CONFIG_MEMORY_FAILURE build?
Thanks,
Naoya Horiguchi
> + * int type - Page types of the corrupted page
> + * int result - Result of recovery action
> + */
> +
> +#define MF_ACTION_RESULT \
> + EM ( MF_IGNORED, "Ignord" ) \
> + EM ( MF_FAILED, "Failed" ) \
> + EM ( MF_DELAYED, "Delayed" ) \
> + EMe ( MF_RECOVERED, "Recovered" )
> +
> +#define MF_PAGE_TYPE \
> + EM ( MF_KERNEL, "reserved kernel page" ) \
> + EM ( MF_KERNEL_HIGH_ORDER, "high-order kernel page" ) \
> + EM ( MF_SLAB, "kernel slab page" ) \
> + EM ( MF_DIFFERENT_COMPOUND, "different compound page after locking" ) \
> + EM ( MF_POISONED_HUGE, "huge page already hardware poisoned" ) \
> + EM ( MF_HUGE, "huge page" ) \
> + EM ( MF_FREE_HUGE, "free huge page" ) \
> + EM ( MF_UNMAP_FAILED, "unmapping failed page" ) \
> + EM ( MF_DIRTY_SWAPCACHE, "dirty swapcache page" ) \
> + EM ( MF_CLEAN_SWAPCACHE, "clean swapcache page" ) \
> + EM ( MF_DIRTY_MLOCKED_LRU, "dirty mlocked LRU page" ) \
> + EM ( MF_CLEAN_MLOCKED_LRU, "clean mlocked LRU page" ) \
> + EM ( MF_DIRTY_UNEVICTABLE_LRU, "dirty unevictable LRU page" ) \
> + EM ( MF_CLEAN_UNEVICTABLE_LRU, "clean unevictable LRU page" ) \
> + EM ( MF_DIRTY_LRU, "dirty LRU page" ) \
> + EM ( MF_CLEAN_LRU, "clean LRU page" ) \
> + EM ( MF_TRUNCATED_LRU, "already truncated LRU page" ) \
> + EM ( MF_BUDDY, "free buddy page" ) \
> + EM ( MF_BUDDY_2ND, "free buddy page (2nd try)" ) \
> + EMe ( MF_UNKNOWN, "unknown page" )
> +
> +/*
> + * First define the enums in MM_ACTION_RESULT to be exported to userspace
> + * via TRACE_DEFINE_ENUM().
> + */
> +#undef EM
> +#undef EMe
> +#define EM(a,b) TRACE_DEFINE_ENUM(a);
> +#define EMe(a,b) TRACE_DEFINE_ENUM(a);
> +
> +MF_ACTION_RESULT
> +MF_PAGE_TYPE
> +
> +/*
> + * Now redefine the EM() and EMe() macros to map the enums to the strings
> + * that will be printed in the output.
> + */
> +#undef EM
> +#undef EMe
> +#define EM(a,b) { a, b },
> +#define EMe(a,b) { a, b }
> +
> +TRACE_EVENT(memory_failure_event,
> + TP_PROTO(unsigned long pfn,
> + int type,
> + int result),
> +
> + TP_ARGS(pfn, type, result),
> +
> + TP_STRUCT__entry(
> + __field(unsigned long, pfn)
> + __field(int, type)
> + __field(int, result)
> + ),
> +
> + TP_fast_assign(
> + __entry->pfn = pfn;
> + __entry->type = type;
> + __entry->result = result;
> + ),
> +
> + TP_printk("pfn %#lx: recovery action for %s: %s",
> + __entry->pfn,
> + __print_symbolic(__entry->type, MF_PAGE_TYPE),
> + __print_symbolic(__entry->result, MF_ACTION_RESULT)
> + )
> +);
> #endif /* _TRACE_HW_EVENT_MC_H */
>
> /* This part must be outside protection */
> diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
> index 25334e7..f5e8856 100644
> --- a/kernel/trace/trace.c
> +++ b/kernel/trace/trace.c
> @@ -6776,7 +6776,7 @@ static struct notifier_block trace_module_nb = {
> };
> #endif
>
> -static __init int tracer_init_debugfs(void)
> +static __init int tracer_init_tracefs(void)
> {
> struct dentry *d_tracer;
>
> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> index 34e9c65..d118af8 100644
> --- a/mm/memory-failure.c
> +++ b/mm/memory-failure.c
> @@ -850,6 +850,8 @@ static struct page_state {
> */
> static void action_result(unsigned long pfn, int type, int result)
> {
> + trace_memory_failure_event(pfn, type, result);
> +
> pr_err("MCE %#lx: recovery action for %s: %s\n",
> pfn, action_page_type[type], action_name[result]);
> }
> --
> 1.8.3.1
> -
On Tue, Apr 07, 2015 at 07:05:30PM +0800, Xie XiuQi wrote:
> Export 'outcome' and 'page_type' to mm.h, so we could use this emnus
> outside.
>
> This patch is preparation for adding trace events for memory-failure
> recovery action.
>
> Signed-off-by: Xie XiuQi <[email protected]>
I made some update on mm/memory-failure.c, so some more rebasing is needed.
Please see mm-memory-failurec-define-page-types-for-action_result-in-one-place-v3
in latest linux-mmotm.
Other than that, this patch looks good to me.
Thanks,
Naoya Horiguchi
> ---
> include/linux/mm.h | 34 +++++++++++
> mm/memory-failure.c | 163 +++++++++++++++++++++-------------------------------
> 2 files changed, 99 insertions(+), 98 deletions(-)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 4a3a385..5d812b0 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -2114,6 +2114,40 @@ extern void shake_page(struct page *p, int access);
> extern atomic_long_t num_poisoned_pages;
> extern int soft_offline_page(struct page *page, int flags);
>
> +
> +/*
> + * Error handlers for various types of pages.
> + */
> +enum mf_outcome {
> + MF_IGNORED, /* Error: cannot be handled */
> + MF_FAILED, /* Error: handling failed */
> + MF_DELAYED, /* Will be handled later */
> + MF_RECOVERED, /* Successfully recovered */
> +};
> +
> +enum mf_page_type {
> + MF_KERNEL,
> + MF_KERNEL_HIGH_ORDER,
> + MF_SLAB,
> + MF_DIFFERENT_COMPOUND,
> + MF_POISONED_HUGE,
> + MF_HUGE,
> + MF_FREE_HUGE,
> + MF_UNMAP_FAILED,
> + MF_DIRTY_SWAPCACHE,
> + MF_CLEAN_SWAPCACHE,
> + MF_DIRTY_MLOCKED_LRU,
> + MF_CLEAN_MLOCKED_LRU,
> + MF_DIRTY_UNEVICTABLE_LRU,
> + MF_CLEAN_UNEVICTABLE_LRU,
> + MF_DIRTY_LRU,
> + MF_CLEAN_LRU,
> + MF_TRUNCATED_LRU,
> + MF_BUDDY,
> + MF_BUDDY_2ND,
> + MF_UNKNOWN,
> +};
> +
> #if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLBFS)
> extern void clear_huge_page(struct page *page,
> unsigned long addr,
> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> index 5074998..34e9c65 100644
> --- a/mm/memory-failure.c
> +++ b/mm/memory-failure.c
> @@ -56,6 +56,7 @@
> #include <linux/mm_inline.h>
> #include <linux/kfifo.h>
> #include "internal.h"
> +#include "ras/ras_event.h"
>
> int sysctl_memory_failure_early_kill __read_mostly = 0;
>
> @@ -503,68 +504,34 @@ static void collect_procs(struct page *page, struct list_head *tokill,
> kfree(tk);
> }
>
> -/*
> - * Error handlers for various types of pages.
> - */
> -
> -enum outcome {
> - IGNORED, /* Error: cannot be handled */
> - FAILED, /* Error: handling failed */
> - DELAYED, /* Will be handled later */
> - RECOVERED, /* Successfully recovered */
> -};
> -
> static const char *action_name[] = {
> - [IGNORED] = "Ignored",
> - [FAILED] = "Failed",
> - [DELAYED] = "Delayed",
> - [RECOVERED] = "Recovered",
> -};
> -
> -enum page_type {
> - KERNEL,
> - KERNEL_HIGH_ORDER,
> - SLAB,
> - DIFFERENT_COMPOUND,
> - POISONED_HUGE,
> - HUGE,
> - FREE_HUGE,
> - UNMAP_FAILED,
> - DIRTY_SWAPCACHE,
> - CLEAN_SWAPCACHE,
> - DIRTY_MLOCKED_LRU,
> - CLEAN_MLOCKED_LRU,
> - DIRTY_UNEVICTABLE_LRU,
> - CLEAN_UNEVICTABLE_LRU,
> - DIRTY_LRU,
> - CLEAN_LRU,
> - TRUNCATED_LRU,
> - BUDDY,
> - BUDDY_2ND,
> - UNKNOWN,
> + [MF_IGNORED] = "Ignored",
> + [MF_FAILED] = "Failed",
> + [MF_DELAYED] = "Delayed",
> + [MF_RECOVERED] = "Recovered",
> };
>
> static const char *action_page_type[] = {
> - [KERNEL] = "reserved kernel page",
> - [KERNEL_HIGH_ORDER] = "high-order kernel page",
> - [SLAB] = "kernel slab page",
> - [DIFFERENT_COMPOUND] = "different compound page after locking",
> - [POISONED_HUGE] = "huge page already hardware poisoned",
> - [HUGE] = "huge page",
> - [FREE_HUGE] = "free huge page",
> - [UNMAP_FAILED] = "unmapping failed page",
> - [DIRTY_SWAPCACHE] = "dirty swapcache page",
> - [CLEAN_SWAPCACHE] = "clean swapcache page",
> - [DIRTY_MLOCKED_LRU] = "dirty mlocked LRU page",
> - [CLEAN_MLOCKED_LRU] = "clean mlocked LRU page",
> - [DIRTY_UNEVICTABLE_LRU] = "dirty unevictable LRU page",
> - [CLEAN_UNEVICTABLE_LRU] = "clean unevictable LRU page",
> - [DIRTY_LRU] = "dirty LRU page",
> - [CLEAN_LRU] = "clean LRU page",
> - [TRUNCATED_LRU] = "already truncated LRU page",
> - [BUDDY] = "free buddy page",
> - [BUDDY_2ND] = "free buddy page (2nd try)",
> - [UNKNOWN] = "unknown page",
> + [MF_KERNEL] = "reserved kernel page",
> + [MF_KERNEL_HIGH_ORDER] = "high-order kernel page",
> + [MF_SLAB] = "kernel slab page",
> + [MF_DIFFERENT_COMPOUND] = "different compound page after locking",
> + [MF_POISONED_HUGE] = "huge page already hardware poisoned",
> + [MF_HUGE] = "huge page",
> + [MF_FREE_HUGE] = "free huge page",
> + [MF_UNMAP_FAILED] = "unmapping failed page",
> + [MF_DIRTY_SWAPCACHE] = "dirty swapcache page",
> + [MF_CLEAN_SWAPCACHE] = "clean swapcache page",
> + [MF_DIRTY_MLOCKED_LRU] = "dirty mlocked LRU page",
> + [MF_CLEAN_MLOCKED_LRU] = "clean mlocked LRU page",
> + [MF_DIRTY_UNEVICTABLE_LRU] = "dirty unevictable LRU page",
> + [MF_CLEAN_UNEVICTABLE_LRU] = "clean unevictable LRU page",
> + [MF_DIRTY_LRU] = "dirty LRU page",
> + [MF_CLEAN_LRU] = "clean LRU page",
> + [MF_TRUNCATED_LRU] = "already truncated LRU page",
> + [MF_BUDDY] = "free buddy page",
> + [MF_BUDDY_2ND] = "free buddy page (2nd try)",
> + [MF_UNKNOWN] = "unknown page",
> };
>
> /*
> @@ -598,7 +565,7 @@ static int delete_from_lru_cache(struct page *p)
> */
> static int me_kernel(struct page *p, unsigned long pfn)
> {
> - return IGNORED;
> + return MF_IGNORED;
> }
>
> /*
> @@ -607,7 +574,7 @@ static int me_kernel(struct page *p, unsigned long pfn)
> static int me_unknown(struct page *p, unsigned long pfn)
> {
> printk(KERN_ERR "MCE %#lx: Unknown page state\n", pfn);
> - return FAILED;
> + return MF_FAILED;
> }
>
> /*
> @@ -616,7 +583,7 @@ static int me_unknown(struct page *p, unsigned long pfn)
> static int me_pagecache_clean(struct page *p, unsigned long pfn)
> {
> int err;
> - int ret = FAILED;
> + int ret = MF_FAILED;
> struct address_space *mapping;
>
> delete_from_lru_cache(p);
> @@ -626,7 +593,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
> * should be the one m_f() holds.
> */
> if (PageAnon(p))
> - return RECOVERED;
> + return MF_RECOVERED;
>
> /*
> * Now truncate the page in the page cache. This is really
> @@ -640,7 +607,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
> /*
> * Page has been teared down in the meanwhile
> */
> - return FAILED;
> + return MF_FAILED;
> }
>
> /*
> @@ -657,7 +624,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
> !try_to_release_page(p, GFP_NOIO)) {
> pr_info("MCE %#lx: failed to release buffers\n", pfn);
> } else {
> - ret = RECOVERED;
> + ret = MF_RECOVERED;
> }
> } else {
> /*
> @@ -665,7 +632,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
> * This fails on dirty or anything with private pages
> */
> if (invalidate_inode_page(p))
> - ret = RECOVERED;
> + ret = MF_RECOVERED;
> else
> printk(KERN_INFO "MCE %#lx: Failed to invalidate\n",
> pfn);
> @@ -751,9 +718,9 @@ static int me_swapcache_dirty(struct page *p, unsigned long pfn)
> ClearPageUptodate(p);
>
> if (!delete_from_lru_cache(p))
> - return DELAYED;
> + return MF_DELAYED;
> else
> - return FAILED;
> + return MF_FAILED;
> }
>
> static int me_swapcache_clean(struct page *p, unsigned long pfn)
> @@ -761,9 +728,9 @@ static int me_swapcache_clean(struct page *p, unsigned long pfn)
> delete_from_swap_cache(p);
>
> if (!delete_from_lru_cache(p))
> - return RECOVERED;
> + return MF_RECOVERED;
> else
> - return FAILED;
> + return MF_FAILED;
> }
>
> /*
> @@ -789,9 +756,9 @@ static int me_huge_page(struct page *p, unsigned long pfn)
> if (!(page_mapping(hpage) || PageAnon(hpage))) {
> res = dequeue_hwpoisoned_huge_page(hpage);
> if (!res)
> - return RECOVERED;
> + return MF_RECOVERED;
> }
> - return DELAYED;
> + return MF_DELAYED;
> }
>
> /*
> @@ -826,7 +793,7 @@ static struct page_state {
> int type;
> int (*action)(struct page *p, unsigned long pfn);
> } error_states[] = {
> - { reserved, reserved, KERNEL, me_kernel },
> + { reserved, reserved, MF_KERNEL, me_kernel },
> /*
> * free pages are specially detected outside this table:
> * PG_buddy pages only make a small fraction of all free pages.
> @@ -837,31 +804,31 @@ static struct page_state {
> * currently unused objects without touching them. But just
> * treat it as standard kernel for now.
> */
> - { slab, slab, SLAB, me_kernel },
> + { slab, slab, MF_SLAB, me_kernel },
>
> #ifdef CONFIG_PAGEFLAGS_EXTENDED
> - { head, head, HUGE, me_huge_page },
> - { tail, tail, HUGE, me_huge_page },
> + { head, head, MF_HUGE, me_huge_page },
> + { tail, tail, MF_HUGE, me_huge_page },
> #else
> - { compound, compound, HUGE, me_huge_page },
> + { compound, compound, MF_HUGE, me_huge_page },
> #endif
>
> - { sc|dirty, sc|dirty, DIRTY_SWAPCACHE, me_swapcache_dirty },
> - { sc|dirty, sc, CLEAN_SWAPCACHE, me_swapcache_clean },
> + { sc|dirty, sc|dirty, MF_DIRTY_SWAPCACHE, me_swapcache_dirty },
> + { sc|dirty, sc, MF_CLEAN_SWAPCACHE, me_swapcache_clean },
>
> - { mlock|dirty, mlock|dirty, DIRTY_MLOCKED_LRU, me_pagecache_dirty },
> - { mlock|dirty, mlock, CLEAN_MLOCKED_LRU, me_pagecache_clean },
> + { mlock|dirty, mlock|dirty, MF_DIRTY_MLOCKED_LRU, me_pagecache_dirty },
> + { mlock|dirty, mlock, MF_CLEAN_MLOCKED_LRU, me_pagecache_clean },
>
> - { unevict|dirty, unevict|dirty, DIRTY_UNEVICTABLE_LRU, me_pagecache_dirty },
> - { unevict|dirty, unevict, CLEAN_UNEVICTABLE_LRU, me_pagecache_clean },
> + { unevict|dirty, unevict|dirty, MF_DIRTY_UNEVICTABLE_LRU, me_pagecache_dirty },
> + { unevict|dirty, unevict, MF_CLEAN_UNEVICTABLE_LRU, me_pagecache_clean },
>
> - { lru|dirty, lru|dirty, DIRTY_LRU, me_pagecache_dirty },
> - { lru|dirty, lru, CLEAN_LRU, me_pagecache_clean },
> + { lru|dirty, lru|dirty, MF_DIRTY_LRU, me_pagecache_dirty },
> + { lru|dirty, lru, MF_CLEAN_LRU, me_pagecache_clean },
>
> /*
> * Catchall entry: must be at end.
> */
> - { 0, 0, UNKNOWN, me_unknown },
> + { 0, 0, MF_UNKNOWN, me_unknown },
> };
>
> #undef dirty
> @@ -896,13 +863,13 @@ static int page_action(struct page_state *ps, struct page *p,
> result = ps->action(p, pfn);
>
> count = page_count(p) - 1;
> - if (ps->action == me_swapcache_dirty && result == DELAYED)
> + if (ps->action == me_swapcache_dirty && result == MF_DELAYED)
> count--;
> if (count != 0) {
> printk(KERN_ERR
> "MCE %#lx: %s still referenced by %d users\n",
> pfn, action_page_type[ps->type], count);
> - result = FAILED;
> + result = MF_FAILED;
> }
> action_result(pfn, ps->type, result);
>
> @@ -911,7 +878,7 @@ static int page_action(struct page_state *ps, struct page *p,
> * Could adjust zone counters here to correct for the missing page.
> */
>
> - return (result == RECOVERED || result == DELAYED) ? 0 : -EBUSY;
> + return (result == MF_RECOVERED || result == MF_DELAYED) ? 0 : -EBUSY;
> }
>
> /*
> @@ -1152,7 +1119,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
> if (!(flags & MF_COUNT_INCREASED) &&
> !get_page_unless_zero(hpage)) {
> if (is_free_buddy_page(p)) {
> - action_result(pfn, BUDDY, DELAYED);
> + action_result(pfn, MF_BUDDY, MF_DELAYED);
> return 0;
> } else if (PageHuge(hpage)) {
> /*
> @@ -1169,12 +1136,12 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
> }
> set_page_hwpoison_huge_page(hpage);
> res = dequeue_hwpoisoned_huge_page(hpage);
> - action_result(pfn, FREE_HUGE,
> - res ? IGNORED : DELAYED);
> + action_result(pfn, MF_FREE_HUGE,
> + res ? MF_IGNORED : MF_DELAYED);
> unlock_page(hpage);
> return res;
> } else {
> - action_result(pfn, KERNEL_HIGH_ORDER, IGNORED);
> + action_result(pfn, MF_KERNEL_HIGH_ORDER, MF_IGNORED);
> return -EBUSY;
> }
> }
> @@ -1196,9 +1163,9 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
> */
> if (is_free_buddy_page(p)) {
> if (flags & MF_COUNT_INCREASED)
> - action_result(pfn, BUDDY, DELAYED);
> + action_result(pfn, MF_BUDDY, MF_DELAYED);
> else
> - action_result(pfn, BUDDY_2ND, DELAYED);
> + action_result(pfn, MF_BUDDY_2ND, MF_DELAYED);
> return 0;
> }
> }
> @@ -1211,7 +1178,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
> * If this happens just bail out.
> */
> if (compound_head(p) != hpage) {
> - action_result(pfn, DIFFERENT_COMPOUND, IGNORED);
> + action_result(pfn, MF_DIFFERENT_COMPOUND, MF_IGNORED);
> res = -EBUSY;
> goto out;
> }
> @@ -1251,7 +1218,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
> * on the head page to show that the hugepage is hwpoisoned
> */
> if (PageHuge(p) && PageTail(p) && TestSetPageHWPoison(hpage)) {
> - action_result(pfn, POISONED_HUGE, IGNORED);
> + action_result(pfn, MF_POISONED_HUGE, MF_IGNORED);
> unlock_page(hpage);
> put_page(hpage);
> return 0;
> @@ -1280,7 +1247,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
> */
> if (hwpoison_user_mappings(p, pfn, trapno, flags, &hpage)
> != SWAP_SUCCESS) {
> - action_result(pfn, UNMAP_FAILED, IGNORED);
> + action_result(pfn, MF_UNMAP_FAILED, MF_IGNORED);
> res = -EBUSY;
> goto out;
> }
> @@ -1289,7 +1256,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
> * Torn down by someone else?
> */
> if (PageLRU(p) && !PageSwapCache(p) && p->mapping == NULL) {
> - action_result(pfn, TRUNCATED_LRU, IGNORED);
> + action_result(pfn, MF_TRUNCATED_LRU, MF_IGNORED);
> res = -EBUSY;
> goto out;
> }
> --
> 1.8.3.1
> -
On 2015/4/8 9:35, Naoya Horiguchi wrote:
> On Tue, Apr 07, 2015 at 07:05:31PM +0800, Xie XiuQi wrote:
>> RAS user space tools like rasdaemon which base on trace event, could
>> receive mce error event, but no memory recovery result event. So, I
>> want to add this event to make this scenario complete.
>>
>> This patch add a event at ras group for memory-failure.
>>
>> The output like below:
>> # tracer: nop
>> #
>> # entries-in-buffer/entries-written: 2/2 #P:24
>> #
>> # _-----=> irqs-off
>> # / _----=> need-resched
>> # | / _---=> hardirq/softirq
>> # || / _--=> preempt-depth
>> # ||| / delay
>> # TASK-PID CPU# |||| TIMESTAMP FUNCTION
>> # | | | |||| | |
>> mce-inject-13150 [001] .... 277.019359: memory_failure_event: pfn 0x19869: recovery action for free buddy page: Delayed
>>
>>
>> Cc: Tony Luck <[email protected]>
>> Cc: Steven Rostedt <[email protected]>
>> Signed-off-by: Xie XiuQi <[email protected]>
>> ---
>> include/ras/ras_event.h | 83 +++++++++++++++++++++++++++++++++++++++++++++++++
>> kernel/trace/trace.c | 2 +-
>> mm/memory-failure.c | 2 ++
>> 3 files changed, 86 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
>> index 79abb9c..52c75f2 100644
>> --- a/include/ras/ras_event.h
>> +++ b/include/ras/ras_event.h
>> @@ -11,6 +11,7 @@
>> #include <linux/pci.h>
>> #include <linux/aer.h>
>> #include <linux/cper.h>
>> +#include <linux/mm.h>
>>
>> /*
>> * MCE Extended Error Log trace event
>> @@ -232,6 +233,88 @@ TRACE_EVENT(aer_event,
>> __print_flags(__entry->status, "|", aer_uncorrectable_errors))
>> );
>>
>> +/*
>> + * memory-failure recovery action result event
>> + *
>> + * unsigned long pfn - Page Number of the corrupted page
>
> Hi XiuQi,
>
> I think "Page Frame Number" is better.
OK, I will
>
> And embracing these definition code with #ifdef CONFIG_MEMORY_FAILURE might
> be helpful if it reduces binary size for !CONFIG_MEMORY_FAILURE build?
Sorry for reply late.
I'll do it at next version.
Thanks,
Xie XiuQi
>
> Thanks,
> Naoya Horiguchi
>
>> + * int type - Page types of the corrupted page
>> + * int result - Result of recovery action
>> + */
>> +
>> +#define MF_ACTION_RESULT \
>> + EM ( MF_IGNORED, "Ignord" ) \
>> + EM ( MF_FAILED, "Failed" ) \
>> + EM ( MF_DELAYED, "Delayed" ) \
>> + EMe ( MF_RECOVERED, "Recovered" )
>> +
>> +#define MF_PAGE_TYPE \
>> + EM ( MF_KERNEL, "reserved kernel page" ) \
>> + EM ( MF_KERNEL_HIGH_ORDER, "high-order kernel page" ) \
>> + EM ( MF_SLAB, "kernel slab page" ) \
>> + EM ( MF_DIFFERENT_COMPOUND, "different compound page after locking" ) \
>> + EM ( MF_POISONED_HUGE, "huge page already hardware poisoned" ) \
>> + EM ( MF_HUGE, "huge page" ) \
>> + EM ( MF_FREE_HUGE, "free huge page" ) \
>> + EM ( MF_UNMAP_FAILED, "unmapping failed page" ) \
>> + EM ( MF_DIRTY_SWAPCACHE, "dirty swapcache page" ) \
>> + EM ( MF_CLEAN_SWAPCACHE, "clean swapcache page" ) \
>> + EM ( MF_DIRTY_MLOCKED_LRU, "dirty mlocked LRU page" ) \
>> + EM ( MF_CLEAN_MLOCKED_LRU, "clean mlocked LRU page" ) \
>> + EM ( MF_DIRTY_UNEVICTABLE_LRU, "dirty unevictable LRU page" ) \
>> + EM ( MF_CLEAN_UNEVICTABLE_LRU, "clean unevictable LRU page" ) \
>> + EM ( MF_DIRTY_LRU, "dirty LRU page" ) \
>> + EM ( MF_CLEAN_LRU, "clean LRU page" ) \
>> + EM ( MF_TRUNCATED_LRU, "already truncated LRU page" ) \
>> + EM ( MF_BUDDY, "free buddy page" ) \
>> + EM ( MF_BUDDY_2ND, "free buddy page (2nd try)" ) \
>> + EMe ( MF_UNKNOWN, "unknown page" )
>> +
>> +/*
>> + * First define the enums in MM_ACTION_RESULT to be exported to userspace
>> + * via TRACE_DEFINE_ENUM().
>> + */
>> +#undef EM
>> +#undef EMe
>> +#define EM(a,b) TRACE_DEFINE_ENUM(a);
>> +#define EMe(a,b) TRACE_DEFINE_ENUM(a);
>> +
>> +MF_ACTION_RESULT
>> +MF_PAGE_TYPE
>> +
>> +/*
>> + * Now redefine the EM() and EMe() macros to map the enums to the strings
>> + * that will be printed in the output.
>> + */
>> +#undef EM
>> +#undef EMe
>> +#define EM(a,b) { a, b },
>> +#define EMe(a,b) { a, b }
>> +
>> +TRACE_EVENT(memory_failure_event,
>> + TP_PROTO(unsigned long pfn,
>> + int type,
>> + int result),
>> +
>> + TP_ARGS(pfn, type, result),
>> +
>> + TP_STRUCT__entry(
>> + __field(unsigned long, pfn)
>> + __field(int, type)
>> + __field(int, result)
>> + ),
>> +
>> + TP_fast_assign(
>> + __entry->pfn = pfn;
>> + __entry->type = type;
>> + __entry->result = result;
>> + ),
>> +
>> + TP_printk("pfn %#lx: recovery action for %s: %s",
>> + __entry->pfn,
>> + __print_symbolic(__entry->type, MF_PAGE_TYPE),
>> + __print_symbolic(__entry->result, MF_ACTION_RESULT)
>> + )
>> +);
>> #endif /* _TRACE_HW_EVENT_MC_H */
>>
>> /* This part must be outside protection */
>> diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
>> index 25334e7..f5e8856 100644
>> --- a/kernel/trace/trace.c
>> +++ b/kernel/trace/trace.c
>> @@ -6776,7 +6776,7 @@ static struct notifier_block trace_module_nb = {
>> };
>> #endif
>>
>> -static __init int tracer_init_debugfs(void)
>> +static __init int tracer_init_tracefs(void)
>> {
>> struct dentry *d_tracer;
>>
>> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
>> index 34e9c65..d118af8 100644
>> --- a/mm/memory-failure.c
>> +++ b/mm/memory-failure.c
>> @@ -850,6 +850,8 @@ static struct page_state {
>> */
>> static void action_result(unsigned long pfn, int type, int result)
>> {
>> + trace_memory_failure_event(pfn, type, result);
>> +
>> pr_err("MCE %#lx: recovery action for %s: %s\n",
>> pfn, action_page_type[type], action_name[result]);
>> }
>> --
>> 1.8.3.1
>> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
> .
>
On 2015/4/8 9:45, Naoya Horiguchi wrote:
> On Tue, Apr 07, 2015 at 07:05:30PM +0800, Xie XiuQi wrote:
>> Export 'outcome' and 'page_type' to mm.h, so we could use this emnus
>> outside.
>>
>> This patch is preparation for adding trace events for memory-failure
>> recovery action.
>>
>> Signed-off-by: Xie XiuQi <[email protected]>
>
> I made some update on mm/memory-failure.c, so some more rebasing is needed.
> Please see mm-memory-failurec-define-page-types-for-action_result-in-one-place-v3
> in latest linux-mmotm.
OK, I will
>
> Other than that, this patch looks good to me.
Thanks!
>
> Thanks,
> Naoya Horiguchi
>
>> ---
>> include/linux/mm.h | 34 +++++++++++
>> mm/memory-failure.c | 163 +++++++++++++++++++++-------------------------------
>> 2 files changed, 99 insertions(+), 98 deletions(-)
>>
>> diff --git a/include/linux/mm.h b/include/linux/mm.h
>> index 4a3a385..5d812b0 100644
>> --- a/include/linux/mm.h
>> +++ b/include/linux/mm.h
>> @@ -2114,6 +2114,40 @@ extern void shake_page(struct page *p, int access);
>> extern atomic_long_t num_poisoned_pages;
>> extern int soft_offline_page(struct page *page, int flags);
>>
>> +
>> +/*
>> + * Error handlers for various types of pages.
>> + */
>> +enum mf_outcome {
>> + MF_IGNORED, /* Error: cannot be handled */
>> + MF_FAILED, /* Error: handling failed */
>> + MF_DELAYED, /* Will be handled later */
>> + MF_RECOVERED, /* Successfully recovered */
>> +};
>> +
>> +enum mf_page_type {
>> + MF_KERNEL,
>> + MF_KERNEL_HIGH_ORDER,
>> + MF_SLAB,
>> + MF_DIFFERENT_COMPOUND,
>> + MF_POISONED_HUGE,
>> + MF_HUGE,
>> + MF_FREE_HUGE,
>> + MF_UNMAP_FAILED,
>> + MF_DIRTY_SWAPCACHE,
>> + MF_CLEAN_SWAPCACHE,
>> + MF_DIRTY_MLOCKED_LRU,
>> + MF_CLEAN_MLOCKED_LRU,
>> + MF_DIRTY_UNEVICTABLE_LRU,
>> + MF_CLEAN_UNEVICTABLE_LRU,
>> + MF_DIRTY_LRU,
>> + MF_CLEAN_LRU,
>> + MF_TRUNCATED_LRU,
>> + MF_BUDDY,
>> + MF_BUDDY_2ND,
>> + MF_UNKNOWN,
>> +};
>> +
>> #if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLBFS)
>> extern void clear_huge_page(struct page *page,
>> unsigned long addr,
>> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
>> index 5074998..34e9c65 100644
>> --- a/mm/memory-failure.c
>> +++ b/mm/memory-failure.c
>> @@ -56,6 +56,7 @@
>> #include <linux/mm_inline.h>
>> #include <linux/kfifo.h>
>> #include "internal.h"
>> +#include "ras/ras_event.h"
>>
>> int sysctl_memory_failure_early_kill __read_mostly = 0;
>>
>> @@ -503,68 +504,34 @@ static void collect_procs(struct page *page, struct list_head *tokill,
>> kfree(tk);
>> }
>>
>> -/*
>> - * Error handlers for various types of pages.
>> - */
>> -
>> -enum outcome {
>> - IGNORED, /* Error: cannot be handled */
>> - FAILED, /* Error: handling failed */
>> - DELAYED, /* Will be handled later */
>> - RECOVERED, /* Successfully recovered */
>> -};
>> -
>> static const char *action_name[] = {
>> - [IGNORED] = "Ignored",
>> - [FAILED] = "Failed",
>> - [DELAYED] = "Delayed",
>> - [RECOVERED] = "Recovered",
>> -};
>> -
>> -enum page_type {
>> - KERNEL,
>> - KERNEL_HIGH_ORDER,
>> - SLAB,
>> - DIFFERENT_COMPOUND,
>> - POISONED_HUGE,
>> - HUGE,
>> - FREE_HUGE,
>> - UNMAP_FAILED,
>> - DIRTY_SWAPCACHE,
>> - CLEAN_SWAPCACHE,
>> - DIRTY_MLOCKED_LRU,
>> - CLEAN_MLOCKED_LRU,
>> - DIRTY_UNEVICTABLE_LRU,
>> - CLEAN_UNEVICTABLE_LRU,
>> - DIRTY_LRU,
>> - CLEAN_LRU,
>> - TRUNCATED_LRU,
>> - BUDDY,
>> - BUDDY_2ND,
>> - UNKNOWN,
>> + [MF_IGNORED] = "Ignored",
>> + [MF_FAILED] = "Failed",
>> + [MF_DELAYED] = "Delayed",
>> + [MF_RECOVERED] = "Recovered",
>> };
>>
>> static const char *action_page_type[] = {
>> - [KERNEL] = "reserved kernel page",
>> - [KERNEL_HIGH_ORDER] = "high-order kernel page",
>> - [SLAB] = "kernel slab page",
>> - [DIFFERENT_COMPOUND] = "different compound page after locking",
>> - [POISONED_HUGE] = "huge page already hardware poisoned",
>> - [HUGE] = "huge page",
>> - [FREE_HUGE] = "free huge page",
>> - [UNMAP_FAILED] = "unmapping failed page",
>> - [DIRTY_SWAPCACHE] = "dirty swapcache page",
>> - [CLEAN_SWAPCACHE] = "clean swapcache page",
>> - [DIRTY_MLOCKED_LRU] = "dirty mlocked LRU page",
>> - [CLEAN_MLOCKED_LRU] = "clean mlocked LRU page",
>> - [DIRTY_UNEVICTABLE_LRU] = "dirty unevictable LRU page",
>> - [CLEAN_UNEVICTABLE_LRU] = "clean unevictable LRU page",
>> - [DIRTY_LRU] = "dirty LRU page",
>> - [CLEAN_LRU] = "clean LRU page",
>> - [TRUNCATED_LRU] = "already truncated LRU page",
>> - [BUDDY] = "free buddy page",
>> - [BUDDY_2ND] = "free buddy page (2nd try)",
>> - [UNKNOWN] = "unknown page",
>> + [MF_KERNEL] = "reserved kernel page",
>> + [MF_KERNEL_HIGH_ORDER] = "high-order kernel page",
>> + [MF_SLAB] = "kernel slab page",
>> + [MF_DIFFERENT_COMPOUND] = "different compound page after locking",
>> + [MF_POISONED_HUGE] = "huge page already hardware poisoned",
>> + [MF_HUGE] = "huge page",
>> + [MF_FREE_HUGE] = "free huge page",
>> + [MF_UNMAP_FAILED] = "unmapping failed page",
>> + [MF_DIRTY_SWAPCACHE] = "dirty swapcache page",
>> + [MF_CLEAN_SWAPCACHE] = "clean swapcache page",
>> + [MF_DIRTY_MLOCKED_LRU] = "dirty mlocked LRU page",
>> + [MF_CLEAN_MLOCKED_LRU] = "clean mlocked LRU page",
>> + [MF_DIRTY_UNEVICTABLE_LRU] = "dirty unevictable LRU page",
>> + [MF_CLEAN_UNEVICTABLE_LRU] = "clean unevictable LRU page",
>> + [MF_DIRTY_LRU] = "dirty LRU page",
>> + [MF_CLEAN_LRU] = "clean LRU page",
>> + [MF_TRUNCATED_LRU] = "already truncated LRU page",
>> + [MF_BUDDY] = "free buddy page",
>> + [MF_BUDDY_2ND] = "free buddy page (2nd try)",
>> + [MF_UNKNOWN] = "unknown page",
>> };
>>
>> /*
>> @@ -598,7 +565,7 @@ static int delete_from_lru_cache(struct page *p)
>> */
>> static int me_kernel(struct page *p, unsigned long pfn)
>> {
>> - return IGNORED;
>> + return MF_IGNORED;
>> }
>>
>> /*
>> @@ -607,7 +574,7 @@ static int me_kernel(struct page *p, unsigned long pfn)
>> static int me_unknown(struct page *p, unsigned long pfn)
>> {
>> printk(KERN_ERR "MCE %#lx: Unknown page state\n", pfn);
>> - return FAILED;
>> + return MF_FAILED;
>> }
>>
>> /*
>> @@ -616,7 +583,7 @@ static int me_unknown(struct page *p, unsigned long pfn)
>> static int me_pagecache_clean(struct page *p, unsigned long pfn)
>> {
>> int err;
>> - int ret = FAILED;
>> + int ret = MF_FAILED;
>> struct address_space *mapping;
>>
>> delete_from_lru_cache(p);
>> @@ -626,7 +593,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
>> * should be the one m_f() holds.
>> */
>> if (PageAnon(p))
>> - return RECOVERED;
>> + return MF_RECOVERED;
>>
>> /*
>> * Now truncate the page in the page cache. This is really
>> @@ -640,7 +607,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
>> /*
>> * Page has been teared down in the meanwhile
>> */
>> - return FAILED;
>> + return MF_FAILED;
>> }
>>
>> /*
>> @@ -657,7 +624,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
>> !try_to_release_page(p, GFP_NOIO)) {
>> pr_info("MCE %#lx: failed to release buffers\n", pfn);
>> } else {
>> - ret = RECOVERED;
>> + ret = MF_RECOVERED;
>> }
>> } else {
>> /*
>> @@ -665,7 +632,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
>> * This fails on dirty or anything with private pages
>> */
>> if (invalidate_inode_page(p))
>> - ret = RECOVERED;
>> + ret = MF_RECOVERED;
>> else
>> printk(KERN_INFO "MCE %#lx: Failed to invalidate\n",
>> pfn);
>> @@ -751,9 +718,9 @@ static int me_swapcache_dirty(struct page *p, unsigned long pfn)
>> ClearPageUptodate(p);
>>
>> if (!delete_from_lru_cache(p))
>> - return DELAYED;
>> + return MF_DELAYED;
>> else
>> - return FAILED;
>> + return MF_FAILED;
>> }
>>
>> static int me_swapcache_clean(struct page *p, unsigned long pfn)
>> @@ -761,9 +728,9 @@ static int me_swapcache_clean(struct page *p, unsigned long pfn)
>> delete_from_swap_cache(p);
>>
>> if (!delete_from_lru_cache(p))
>> - return RECOVERED;
>> + return MF_RECOVERED;
>> else
>> - return FAILED;
>> + return MF_FAILED;
>> }
>>
>> /*
>> @@ -789,9 +756,9 @@ static int me_huge_page(struct page *p, unsigned long pfn)
>> if (!(page_mapping(hpage) || PageAnon(hpage))) {
>> res = dequeue_hwpoisoned_huge_page(hpage);
>> if (!res)
>> - return RECOVERED;
>> + return MF_RECOVERED;
>> }
>> - return DELAYED;
>> + return MF_DELAYED;
>> }
>>
>> /*
>> @@ -826,7 +793,7 @@ static struct page_state {
>> int type;
>> int (*action)(struct page *p, unsigned long pfn);
>> } error_states[] = {
>> - { reserved, reserved, KERNEL, me_kernel },
>> + { reserved, reserved, MF_KERNEL, me_kernel },
>> /*
>> * free pages are specially detected outside this table:
>> * PG_buddy pages only make a small fraction of all free pages.
>> @@ -837,31 +804,31 @@ static struct page_state {
>> * currently unused objects without touching them. But just
>> * treat it as standard kernel for now.
>> */
>> - { slab, slab, SLAB, me_kernel },
>> + { slab, slab, MF_SLAB, me_kernel },
>>
>> #ifdef CONFIG_PAGEFLAGS_EXTENDED
>> - { head, head, HUGE, me_huge_page },
>> - { tail, tail, HUGE, me_huge_page },
>> + { head, head, MF_HUGE, me_huge_page },
>> + { tail, tail, MF_HUGE, me_huge_page },
>> #else
>> - { compound, compound, HUGE, me_huge_page },
>> + { compound, compound, MF_HUGE, me_huge_page },
>> #endif
>>
>> - { sc|dirty, sc|dirty, DIRTY_SWAPCACHE, me_swapcache_dirty },
>> - { sc|dirty, sc, CLEAN_SWAPCACHE, me_swapcache_clean },
>> + { sc|dirty, sc|dirty, MF_DIRTY_SWAPCACHE, me_swapcache_dirty },
>> + { sc|dirty, sc, MF_CLEAN_SWAPCACHE, me_swapcache_clean },
>>
>> - { mlock|dirty, mlock|dirty, DIRTY_MLOCKED_LRU, me_pagecache_dirty },
>> - { mlock|dirty, mlock, CLEAN_MLOCKED_LRU, me_pagecache_clean },
>> + { mlock|dirty, mlock|dirty, MF_DIRTY_MLOCKED_LRU, me_pagecache_dirty },
>> + { mlock|dirty, mlock, MF_CLEAN_MLOCKED_LRU, me_pagecache_clean },
>>
>> - { unevict|dirty, unevict|dirty, DIRTY_UNEVICTABLE_LRU, me_pagecache_dirty },
>> - { unevict|dirty, unevict, CLEAN_UNEVICTABLE_LRU, me_pagecache_clean },
>> + { unevict|dirty, unevict|dirty, MF_DIRTY_UNEVICTABLE_LRU, me_pagecache_dirty },
>> + { unevict|dirty, unevict, MF_CLEAN_UNEVICTABLE_LRU, me_pagecache_clean },
>>
>> - { lru|dirty, lru|dirty, DIRTY_LRU, me_pagecache_dirty },
>> - { lru|dirty, lru, CLEAN_LRU, me_pagecache_clean },
>> + { lru|dirty, lru|dirty, MF_DIRTY_LRU, me_pagecache_dirty },
>> + { lru|dirty, lru, MF_CLEAN_LRU, me_pagecache_clean },
>>
>> /*
>> * Catchall entry: must be at end.
>> */
>> - { 0, 0, UNKNOWN, me_unknown },
>> + { 0, 0, MF_UNKNOWN, me_unknown },
>> };
>>
>> #undef dirty
>> @@ -896,13 +863,13 @@ static int page_action(struct page_state *ps, struct page *p,
>> result = ps->action(p, pfn);
>>
>> count = page_count(p) - 1;
>> - if (ps->action == me_swapcache_dirty && result == DELAYED)
>> + if (ps->action == me_swapcache_dirty && result == MF_DELAYED)
>> count--;
>> if (count != 0) {
>> printk(KERN_ERR
>> "MCE %#lx: %s still referenced by %d users\n",
>> pfn, action_page_type[ps->type], count);
>> - result = FAILED;
>> + result = MF_FAILED;
>> }
>> action_result(pfn, ps->type, result);
>>
>> @@ -911,7 +878,7 @@ static int page_action(struct page_state *ps, struct page *p,
>> * Could adjust zone counters here to correct for the missing page.
>> */
>>
>> - return (result == RECOVERED || result == DELAYED) ? 0 : -EBUSY;
>> + return (result == MF_RECOVERED || result == MF_DELAYED) ? 0 : -EBUSY;
>> }
>>
>> /*
>> @@ -1152,7 +1119,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
>> if (!(flags & MF_COUNT_INCREASED) &&
>> !get_page_unless_zero(hpage)) {
>> if (is_free_buddy_page(p)) {
>> - action_result(pfn, BUDDY, DELAYED);
>> + action_result(pfn, MF_BUDDY, MF_DELAYED);
>> return 0;
>> } else if (PageHuge(hpage)) {
>> /*
>> @@ -1169,12 +1136,12 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
>> }
>> set_page_hwpoison_huge_page(hpage);
>> res = dequeue_hwpoisoned_huge_page(hpage);
>> - action_result(pfn, FREE_HUGE,
>> - res ? IGNORED : DELAYED);
>> + action_result(pfn, MF_FREE_HUGE,
>> + res ? MF_IGNORED : MF_DELAYED);
>> unlock_page(hpage);
>> return res;
>> } else {
>> - action_result(pfn, KERNEL_HIGH_ORDER, IGNORED);
>> + action_result(pfn, MF_KERNEL_HIGH_ORDER, MF_IGNORED);
>> return -EBUSY;
>> }
>> }
>> @@ -1196,9 +1163,9 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
>> */
>> if (is_free_buddy_page(p)) {
>> if (flags & MF_COUNT_INCREASED)
>> - action_result(pfn, BUDDY, DELAYED);
>> + action_result(pfn, MF_BUDDY, MF_DELAYED);
>> else
>> - action_result(pfn, BUDDY_2ND, DELAYED);
>> + action_result(pfn, MF_BUDDY_2ND, MF_DELAYED);
>> return 0;
>> }
>> }
>> @@ -1211,7 +1178,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
>> * If this happens just bail out.
>> */
>> if (compound_head(p) != hpage) {
>> - action_result(pfn, DIFFERENT_COMPOUND, IGNORED);
>> + action_result(pfn, MF_DIFFERENT_COMPOUND, MF_IGNORED);
>> res = -EBUSY;
>> goto out;
>> }
>> @@ -1251,7 +1218,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
>> * on the head page to show that the hugepage is hwpoisoned
>> */
>> if (PageHuge(p) && PageTail(p) && TestSetPageHWPoison(hpage)) {
>> - action_result(pfn, POISONED_HUGE, IGNORED);
>> + action_result(pfn, MF_POISONED_HUGE, MF_IGNORED);
>> unlock_page(hpage);
>> put_page(hpage);
>> return 0;
>> @@ -1280,7 +1247,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
>> */
>> if (hwpoison_user_mappings(p, pfn, trapno, flags, &hpage)
>> != SWAP_SUCCESS) {
>> - action_result(pfn, UNMAP_FAILED, IGNORED);
>> + action_result(pfn, MF_UNMAP_FAILED, MF_IGNORED);
>> res = -EBUSY;
>> goto out;
>> }
>> @@ -1289,7 +1256,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
>> * Torn down by someone else?
>> */
>> if (PageLRU(p) && !PageSwapCache(p) && p->mapping == NULL) {
>> - action_result(pfn, TRUNCATED_LRU, IGNORED);
>> + action_result(pfn, MF_TRUNCATED_LRU, MF_IGNORED);
>> res = -EBUSY;
>> goto out;
>> }
>> --
>> 1.8.3.1
>>
> .
>