2015-04-20 08:47:45

by Xie XiuQi

[permalink] [raw]
Subject: [PATCH v4 0/3] tracing: add trace event for memory-failure

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 patchset 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

--
v3->v4:
- rebase on top of latest linux-next
- update comments as Naoya's suggestion
- add #ifdef CONFIG_MEMORY_FAILURE for this trace event
- change type of action_result's param 3 to enum

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 (3):
memory-failure: export page_type and action result
memory-failure: change type of action_result's param 3 to enum
tracing: add trace event for memory-failure

include/linux/mm.h | 34 ++++++++++
include/ras/ras_event.h | 85 ++++++++++++++++++++++++
mm/memory-failure.c | 172 ++++++++++++++++++++----------------------------
3 files changed, 190 insertions(+), 101 deletions(-)

--
1.8.3.1


2015-04-20 08:48:48

by Xie XiuQi

[permalink] [raw]
Subject: [PATCH v4 1/3] memory-failure: export page_type and action result

Export 'outcome' and 'action_page_type' to mm.h, so we could use
this enums 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 | 168 +++++++++++++++++++++-------------------------------
2 files changed, 101 insertions(+), 101 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 8b08607..8413615 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2152,6 +2152,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_action_page_type {
+ MF_MSG_KERNEL,
+ MF_MSG_KERNEL_HIGH_ORDER,
+ MF_MSG_SLAB,
+ MF_MSG_DIFFERENT_COMPOUND,
+ MF_MSG_POISONED_HUGE,
+ MF_MSG_HUGE,
+ MF_MSG_FREE_HUGE,
+ MF_MSG_UNMAP_FAILED,
+ MF_MSG_DIRTY_SWAPCACHE,
+ MF_MSG_CLEAN_SWAPCACHE,
+ MF_MSG_DIRTY_MLOCKED_LRU,
+ MF_MSG_CLEAN_MLOCKED_LRU,
+ MF_MSG_DIRTY_UNEVICTABLE_LRU,
+ MF_MSG_CLEAN_UNEVICTABLE_LRU,
+ MF_MSG_DIRTY_LRU,
+ MF_MSG_CLEAN_LRU,
+ MF_MSG_TRUNCATED_LRU,
+ MF_MSG_BUDDY,
+ MF_MSG_BUDDY_2ND,
+ MF_MSG_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 d9359b7..6f5748d 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -503,68 +503,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 action_page_type {
- MSG_KERNEL,
- MSG_KERNEL_HIGH_ORDER,
- MSG_SLAB,
- MSG_DIFFERENT_COMPOUND,
- MSG_POISONED_HUGE,
- MSG_HUGE,
- MSG_FREE_HUGE,
- MSG_UNMAP_FAILED,
- MSG_DIRTY_SWAPCACHE,
- MSG_CLEAN_SWAPCACHE,
- MSG_DIRTY_MLOCKED_LRU,
- MSG_CLEAN_MLOCKED_LRU,
- MSG_DIRTY_UNEVICTABLE_LRU,
- MSG_CLEAN_UNEVICTABLE_LRU,
- MSG_DIRTY_LRU,
- MSG_CLEAN_LRU,
- MSG_TRUNCATED_LRU,
- MSG_BUDDY,
- MSG_BUDDY_2ND,
- MSG_UNKNOWN,
+ [MF_IGNORED] = "Ignored",
+ [MF_FAILED] = "Failed",
+ [MF_DELAYED] = "Delayed",
+ [MF_RECOVERED] = "Recovered",
};

static const char * const action_page_types[] = {
- [MSG_KERNEL] = "reserved kernel page",
- [MSG_KERNEL_HIGH_ORDER] = "high-order kernel page",
- [MSG_SLAB] = "kernel slab page",
- [MSG_DIFFERENT_COMPOUND] = "different compound page after locking",
- [MSG_POISONED_HUGE] = "huge page already hardware poisoned",
- [MSG_HUGE] = "huge page",
- [MSG_FREE_HUGE] = "free huge page",
- [MSG_UNMAP_FAILED] = "unmapping failed page",
- [MSG_DIRTY_SWAPCACHE] = "dirty swapcache page",
- [MSG_CLEAN_SWAPCACHE] = "clean swapcache page",
- [MSG_DIRTY_MLOCKED_LRU] = "dirty mlocked LRU page",
- [MSG_CLEAN_MLOCKED_LRU] = "clean mlocked LRU page",
- [MSG_DIRTY_UNEVICTABLE_LRU] = "dirty unevictable LRU page",
- [MSG_CLEAN_UNEVICTABLE_LRU] = "clean unevictable LRU page",
- [MSG_DIRTY_LRU] = "dirty LRU page",
- [MSG_CLEAN_LRU] = "clean LRU page",
- [MSG_TRUNCATED_LRU] = "already truncated LRU page",
- [MSG_BUDDY] = "free buddy page",
- [MSG_BUDDY_2ND] = "free buddy page (2nd try)",
- [MSG_UNKNOWN] = "unknown page",
+ [MF_MSG_KERNEL] = "reserved kernel page",
+ [MF_MSG_KERNEL_HIGH_ORDER] = "high-order kernel page",
+ [MF_MSG_SLAB] = "kernel slab page",
+ [MF_MSG_DIFFERENT_COMPOUND] = "different compound page after locking",
+ [MF_MSG_POISONED_HUGE] = "huge page already hardware poisoned",
+ [MF_MSG_HUGE] = "huge page",
+ [MF_MSG_FREE_HUGE] = "free huge page",
+ [MF_MSG_UNMAP_FAILED] = "unmapping failed page",
+ [MF_MSG_DIRTY_SWAPCACHE] = "dirty swapcache page",
+ [MF_MSG_CLEAN_SWAPCACHE] = "clean swapcache page",
+ [MF_MSG_DIRTY_MLOCKED_LRU] = "dirty mlocked LRU page",
+ [MF_MSG_CLEAN_MLOCKED_LRU] = "clean mlocked LRU page",
+ [MF_MSG_DIRTY_UNEVICTABLE_LRU] = "dirty unevictable LRU page",
+ [MF_MSG_CLEAN_UNEVICTABLE_LRU] = "clean unevictable LRU page",
+ [MF_MSG_DIRTY_LRU] = "dirty LRU page",
+ [MF_MSG_CLEAN_LRU] = "clean LRU page",
+ [MF_MSG_TRUNCATED_LRU] = "already truncated LRU page",
+ [MF_MSG_BUDDY] = "free buddy page",
+ [MF_MSG_BUDDY_2ND] = "free buddy page (2nd try)",
+ [MF_MSG_UNKNOWN] = "unknown page",
};

/*
@@ -598,7 +564,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 +573,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 +582,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 +592,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 +606,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 +623,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 +631,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 +717,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 +727,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 +755,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;
}

/*
@@ -823,10 +789,10 @@ static int me_huge_page(struct page *p, unsigned long pfn)
static struct page_state {
unsigned long mask;
unsigned long res;
- enum action_page_type type;
+ enum mf_action_page_type type;
int (*action)(struct page *p, unsigned long pfn);
} error_states[] = {
- { reserved, reserved, MSG_KERNEL, me_kernel },
+ { reserved, reserved, MF_MSG_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 +803,31 @@ static struct page_state {
* currently unused objects without touching them. But just
* treat it as standard kernel for now.
*/
- { slab, slab, MSG_SLAB, me_kernel },
+ { slab, slab, MF_MSG_SLAB, me_kernel },

#ifdef CONFIG_PAGEFLAGS_EXTENDED
- { head, head, MSG_HUGE, me_huge_page },
- { tail, tail, MSG_HUGE, me_huge_page },
+ { head, head, MF_MSG_HUGE, me_huge_page },
+ { tail, tail, MF_MSG_HUGE, me_huge_page },
#else
- { compound, compound, MSG_HUGE, me_huge_page },
+ { compound, compound, MF_MSG_HUGE, me_huge_page },
#endif

- { sc|dirty, sc|dirty, MSG_DIRTY_SWAPCACHE, me_swapcache_dirty },
- { sc|dirty, sc, MSG_CLEAN_SWAPCACHE, me_swapcache_clean },
+ { sc|dirty, sc|dirty, MF_MSG_DIRTY_SWAPCACHE, me_swapcache_dirty },
+ { sc|dirty, sc, MF_MSG_CLEAN_SWAPCACHE, me_swapcache_clean },

- { mlock|dirty, mlock|dirty, MSG_DIRTY_MLOCKED_LRU, me_pagecache_dirty },
- { mlock|dirty, mlock, MSG_CLEAN_MLOCKED_LRU, me_pagecache_clean },
+ { mlock|dirty, mlock|dirty, MF_MSG_DIRTY_MLOCKED_LRU, me_pagecache_dirty },
+ { mlock|dirty, mlock, MF_MSG_CLEAN_MLOCKED_LRU, me_pagecache_clean },

- { unevict|dirty, unevict|dirty, MSG_DIRTY_UNEVICTABLE_LRU, me_pagecache_dirty },
- { unevict|dirty, unevict, MSG_CLEAN_UNEVICTABLE_LRU, me_pagecache_clean },
+ { unevict|dirty, unevict|dirty, MF_MSG_DIRTY_UNEVICTABLE_LRU, me_pagecache_dirty },
+ { unevict|dirty, unevict, MF_MSG_CLEAN_UNEVICTABLE_LRU, me_pagecache_clean },

- { lru|dirty, lru|dirty, MSG_DIRTY_LRU, me_pagecache_dirty },
- { lru|dirty, lru, MSG_CLEAN_LRU, me_pagecache_clean },
+ { lru|dirty, lru|dirty, MF_MSG_DIRTY_LRU, me_pagecache_dirty },
+ { lru|dirty, lru, MF_MSG_CLEAN_LRU, me_pagecache_clean },

/*
* Catchall entry: must be at end.
*/
- { 0, 0, MSG_UNKNOWN, me_unknown },
+ { 0, 0, MF_MSG_UNKNOWN, me_unknown },
};

#undef dirty
@@ -881,7 +847,7 @@ static struct page_state {
* "Dirty/Clean" indication is not 100% accurate due to the possibility of
* setting PG_dirty outside page lock. See also comment above set_page_dirty().
*/
-static void action_result(unsigned long pfn, enum action_page_type type, int result)
+static void action_result(unsigned long pfn, enum mf_action_page_type type, int result)
{
pr_err("MCE %#lx: recovery action for %s: %s\n",
pfn, action_page_types[type], action_name[result]);
@@ -896,13 +862,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_types[ps->type], count);
- result = FAILED;
+ result = MF_FAILED;
}
action_result(pfn, ps->type, result);

@@ -911,7 +877,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 +1118,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, MSG_BUDDY, DELAYED);
+ action_result(pfn, MF_MSG_BUDDY, MF_DELAYED);
return 0;
} else if (PageHuge(hpage)) {
/*
@@ -1169,12 +1135,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, MSG_FREE_HUGE,
- res ? IGNORED : DELAYED);
+ action_result(pfn, MF_MSG_FREE_HUGE,
+ res ? MF_IGNORED : MF_DELAYED);
unlock_page(hpage);
return res;
} else {
- action_result(pfn, MSG_KERNEL_HIGH_ORDER, IGNORED);
+ action_result(pfn, MF_MSG_KERNEL_HIGH_ORDER, MF_IGNORED);
return -EBUSY;
}
}
@@ -1196,10 +1162,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
*/
if (is_free_buddy_page(p)) {
if (flags & MF_COUNT_INCREASED)
- action_result(pfn, MSG_BUDDY, DELAYED);
+ action_result(pfn, MF_MSG_BUDDY, MF_DELAYED);
else
- action_result(pfn, MSG_BUDDY_2ND,
- DELAYED);
+ action_result(pfn, MF_MSG_BUDDY_2ND,
+ MF_DELAYED);
return 0;
}
}
@@ -1212,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, MSG_DIFFERENT_COMPOUND, IGNORED);
+ action_result(pfn, MF_MSG_DIFFERENT_COMPOUND, MF_IGNORED);
res = -EBUSY;
goto out;
}
@@ -1252,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, MSG_POISONED_HUGE, IGNORED);
+ action_result(pfn, MF_MSG_POISONED_HUGE, MF_IGNORED);
unlock_page(hpage);
put_page(hpage);
return 0;
@@ -1281,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, MSG_UNMAP_FAILED, IGNORED);
+ action_result(pfn, MF_MSG_UNMAP_FAILED, MF_IGNORED);
res = -EBUSY;
goto out;
}
@@ -1290,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, MSG_TRUNCATED_LRU, IGNORED);
+ action_result(pfn, MF_MSG_TRUNCATED_LRU, MF_IGNORED);
res = -EBUSY;
goto out;
}
--
1.8.3.1

2015-04-20 08:47:47

by Xie XiuQi

[permalink] [raw]
Subject: [PATCH v4 2/3] memory-failure: change type of action_result's param 3 to enum

Change type of action_result's param 3 to enum for type consistency,
and rename mf_outcome to mf_result for clearly.

Signed-off-by: Xie XiuQi <[email protected]>
---
include/linux/mm.h | 2 +-
mm/memory-failure.c | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 8413615..93c4a00 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2156,7 +2156,7 @@ extern int soft_offline_page(struct page *page, int flags);
/*
* Error handlers for various types of pages.
*/
-enum mf_outcome {
+enum mf_result {
MF_IGNORED, /* Error: cannot be handled */
MF_FAILED, /* Error: handling failed */
MF_DELAYED, /* Will be handled later */
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 6f5748d..f074f8e 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -847,7 +847,8 @@ static struct page_state {
* "Dirty/Clean" indication is not 100% accurate due to the possibility of
* setting PG_dirty outside page lock. See also comment above set_page_dirty().
*/
-static void action_result(unsigned long pfn, enum mf_action_page_type type, int result)
+static void action_result(unsigned long pfn, enum mf_action_page_type type,
+ enum mf_result result)
{
pr_err("MCE %#lx: recovery action for %s: %s\n",
pfn, action_page_types[type], action_name[result]);
--
1.8.3.1

2015-04-20 08:48:04

by Xie XiuQi

[permalink] [raw]
Subject: [PATCH v4 3/3] tracing: add trace event for memory-failure

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 | 85 +++++++++++++++++++++++++++++++++++++++++++++++++
mm/memory-failure.c | 3 ++
2 files changed, 88 insertions(+)

diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
index 79abb9c..258ed89 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,90 @@ TRACE_EVENT(aer_event,
__print_flags(__entry->status, "|", aer_uncorrectable_errors))
);

+/*
+ * memory-failure recovery action result event
+ *
+ * unsigned long pfn - Page Frame Number of the corrupted page
+ * int type - Page types of the corrupted page
+ * int result - Result of recovery action
+ */
+
+#ifdef CONFIG_MEMORY_FAILURE
+#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_MSG_KERNEL, "reserved kernel page" ) \
+ EM ( MF_MSG_KERNEL_HIGH_ORDER, "high-order kernel page" ) \
+ EM ( MF_MSG_SLAB, "kernel slab page" ) \
+ EM ( MF_MSG_DIFFERENT_COMPOUND, "different compound page after locking" ) \
+ EM ( MF_MSG_POISONED_HUGE, "huge page already hardware poisoned" ) \
+ EM ( MF_MSG_HUGE, "huge page" ) \
+ EM ( MF_MSG_FREE_HUGE, "free huge page" ) \
+ EM ( MF_MSG_UNMAP_FAILED, "unmapping failed page" ) \
+ EM ( MF_MSG_DIRTY_SWAPCACHE, "dirty swapcache page" ) \
+ EM ( MF_MSG_CLEAN_SWAPCACHE, "clean swapcache page" ) \
+ EM ( MF_MSG_DIRTY_MLOCKED_LRU, "dirty mlocked LRU page" ) \
+ EM ( MF_MSG_CLEAN_MLOCKED_LRU, "clean mlocked LRU page" ) \
+ EM ( MF_MSG_DIRTY_UNEVICTABLE_LRU, "dirty unevictable LRU page" ) \
+ EM ( MF_MSG_CLEAN_UNEVICTABLE_LRU, "clean unevictable LRU page" ) \
+ EM ( MF_MSG_DIRTY_LRU, "dirty LRU page" ) \
+ EM ( MF_MSG_CLEAN_LRU, "clean LRU page" ) \
+ EM ( MF_MSG_TRUNCATED_LRU, "already truncated LRU page" ) \
+ EM ( MF_MSG_BUDDY, "free buddy page" ) \
+ EM ( MF_MSG_BUDDY_2ND, "free buddy page (2nd try)" ) \
+ EMe ( MF_MSG_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 /* CONFIG_MEMORY_FAILURE */
#endif /* _TRACE_HW_EVENT_MC_H */

/* This part must be outside protection */
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index f074f8e..42c5981 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;

@@ -850,6 +851,8 @@ static struct page_state {
static void action_result(unsigned long pfn, enum mf_action_page_type type,
enum mf_result result)
{
+ trace_memory_failure_event(pfn, type, result);
+
pr_err("MCE %#lx: recovery action for %s: %s\n",
pfn, action_page_types[type], action_name[result]);
}
--
1.8.3.1

2015-04-20 19:53:53

by Steven Rostedt

[permalink] [raw]
Subject: Re: [PATCH v4 3/3] tracing: add trace event for memory-failure

On Mon, 20 Apr 2015 16:44:40 +0800
Xie XiuQi <[email protected]> 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]>

Looks good to me.

Acked-by: Steven Rostedt <[email protected]>

-- Steve

2015-04-29 11:15:42

by Xie XiuQi

[permalink] [raw]
Subject: Re: [PATCH v4 0/3] tracing: add trace event for memory-failure

Hi Naoya,

Could you help to review and applied this series if possible.

Thanks,
Xie XiuQi

On 2015/4/20 16:44, 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 patchset 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
>
> --
> v3->v4:
> - rebase on top of latest linux-next
> - update comments as Naoya's suggestion
> - add #ifdef CONFIG_MEMORY_FAILURE for this trace event
> - change type of action_result's param 3 to enum
>
> 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 (3):
> memory-failure: export page_type and action result
> memory-failure: change type of action_result's param 3 to enum
> tracing: add trace event for memory-failure
>
> include/linux/mm.h | 34 ++++++++++
> include/ras/ras_event.h | 85 ++++++++++++++++++++++++
> mm/memory-failure.c | 172 ++++++++++++++++++++----------------------------
> 3 files changed, 190 insertions(+), 101 deletions(-)
>

2015-05-07 01:13:23

by Naoya Horiguchi

[permalink] [raw]
Subject: Re: [PATCH v4 2/3] memory-failure: change type of action_result's param 3 to enum

On Mon, Apr 20, 2015 at 04:44:39PM +0800, Xie XiuQi wrote:
> Change type of action_result's param 3 to enum for type consistency,
> and rename mf_outcome to mf_result for clearly.
>
> Signed-off-by: Xie XiuQi <[email protected]>

Acked-by: Naoya Horiguchi <[email protected]>

> ---
> include/linux/mm.h | 2 +-
> mm/memory-failure.c | 3 ++-
> 2 files changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 8413615..93c4a00 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -2156,7 +2156,7 @@ extern int soft_offline_page(struct page *page, int flags);
> /*
> * Error handlers for various types of pages.
> */
> -enum mf_outcome {
> +enum mf_result {
> MF_IGNORED, /* Error: cannot be handled */
> MF_FAILED, /* Error: handling failed */
> MF_DELAYED, /* Will be handled later */
> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> index 6f5748d..f074f8e 100644
> --- a/mm/memory-failure.c
> +++ b/mm/memory-failure.c
> @@ -847,7 +847,8 @@ static struct page_state {
> * "Dirty/Clean" indication is not 100% accurate due to the possibility of
> * setting PG_dirty outside page lock. See also comment above set_page_dirty().
> */
> -static void action_result(unsigned long pfn, enum mf_action_page_type type, int result)
> +static void action_result(unsigned long pfn, enum mf_action_page_type type,
> + enum mf_result result)
> {
> pr_err("MCE %#lx: recovery action for %s: %s\n",
> pfn, action_page_types[type], action_name[result]);
> --
> 1.8.3.1
> -

2015-05-07 01:13:18

by Naoya Horiguchi

[permalink] [raw]
Subject: Re: [PATCH v4 1/3] memory-failure: export page_type and action result

On Mon, Apr 20, 2015 at 04:44:38PM +0800, Xie XiuQi wrote:
> Export 'outcome' and 'action_page_type' to mm.h, so we could use
> this enums outside.
>
> This patch is preparation for adding trace events for memory-failure
> recovery action.
>
> Signed-off-by: Xie XiuQi <[email protected]>

Acked-by: Naoya Horiguchi <[email protected]>

> ---
> include/linux/mm.h | 34 +++++++++++
> mm/memory-failure.c | 168 +++++++++++++++++++++-------------------------------
> 2 files changed, 101 insertions(+), 101 deletions(-)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 8b08607..8413615 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -2152,6 +2152,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_action_page_type {
> + MF_MSG_KERNEL,
> + MF_MSG_KERNEL_HIGH_ORDER,
> + MF_MSG_SLAB,
> + MF_MSG_DIFFERENT_COMPOUND,
> + MF_MSG_POISONED_HUGE,
> + MF_MSG_HUGE,
> + MF_MSG_FREE_HUGE,
> + MF_MSG_UNMAP_FAILED,
> + MF_MSG_DIRTY_SWAPCACHE,
> + MF_MSG_CLEAN_SWAPCACHE,
> + MF_MSG_DIRTY_MLOCKED_LRU,
> + MF_MSG_CLEAN_MLOCKED_LRU,
> + MF_MSG_DIRTY_UNEVICTABLE_LRU,
> + MF_MSG_CLEAN_UNEVICTABLE_LRU,
> + MF_MSG_DIRTY_LRU,
> + MF_MSG_CLEAN_LRU,
> + MF_MSG_TRUNCATED_LRU,
> + MF_MSG_BUDDY,
> + MF_MSG_BUDDY_2ND,
> + MF_MSG_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 d9359b7..6f5748d 100644
> --- a/mm/memory-failure.c
> +++ b/mm/memory-failure.c
> @@ -503,68 +503,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 action_page_type {
> - MSG_KERNEL,
> - MSG_KERNEL_HIGH_ORDER,
> - MSG_SLAB,
> - MSG_DIFFERENT_COMPOUND,
> - MSG_POISONED_HUGE,
> - MSG_HUGE,
> - MSG_FREE_HUGE,
> - MSG_UNMAP_FAILED,
> - MSG_DIRTY_SWAPCACHE,
> - MSG_CLEAN_SWAPCACHE,
> - MSG_DIRTY_MLOCKED_LRU,
> - MSG_CLEAN_MLOCKED_LRU,
> - MSG_DIRTY_UNEVICTABLE_LRU,
> - MSG_CLEAN_UNEVICTABLE_LRU,
> - MSG_DIRTY_LRU,
> - MSG_CLEAN_LRU,
> - MSG_TRUNCATED_LRU,
> - MSG_BUDDY,
> - MSG_BUDDY_2ND,
> - MSG_UNKNOWN,
> + [MF_IGNORED] = "Ignored",
> + [MF_FAILED] = "Failed",
> + [MF_DELAYED] = "Delayed",
> + [MF_RECOVERED] = "Recovered",
> };
>
> static const char * const action_page_types[] = {
> - [MSG_KERNEL] = "reserved kernel page",
> - [MSG_KERNEL_HIGH_ORDER] = "high-order kernel page",
> - [MSG_SLAB] = "kernel slab page",
> - [MSG_DIFFERENT_COMPOUND] = "different compound page after locking",
> - [MSG_POISONED_HUGE] = "huge page already hardware poisoned",
> - [MSG_HUGE] = "huge page",
> - [MSG_FREE_HUGE] = "free huge page",
> - [MSG_UNMAP_FAILED] = "unmapping failed page",
> - [MSG_DIRTY_SWAPCACHE] = "dirty swapcache page",
> - [MSG_CLEAN_SWAPCACHE] = "clean swapcache page",
> - [MSG_DIRTY_MLOCKED_LRU] = "dirty mlocked LRU page",
> - [MSG_CLEAN_MLOCKED_LRU] = "clean mlocked LRU page",
> - [MSG_DIRTY_UNEVICTABLE_LRU] = "dirty unevictable LRU page",
> - [MSG_CLEAN_UNEVICTABLE_LRU] = "clean unevictable LRU page",
> - [MSG_DIRTY_LRU] = "dirty LRU page",
> - [MSG_CLEAN_LRU] = "clean LRU page",
> - [MSG_TRUNCATED_LRU] = "already truncated LRU page",
> - [MSG_BUDDY] = "free buddy page",
> - [MSG_BUDDY_2ND] = "free buddy page (2nd try)",
> - [MSG_UNKNOWN] = "unknown page",
> + [MF_MSG_KERNEL] = "reserved kernel page",
> + [MF_MSG_KERNEL_HIGH_ORDER] = "high-order kernel page",
> + [MF_MSG_SLAB] = "kernel slab page",
> + [MF_MSG_DIFFERENT_COMPOUND] = "different compound page after locking",
> + [MF_MSG_POISONED_HUGE] = "huge page already hardware poisoned",
> + [MF_MSG_HUGE] = "huge page",
> + [MF_MSG_FREE_HUGE] = "free huge page",
> + [MF_MSG_UNMAP_FAILED] = "unmapping failed page",
> + [MF_MSG_DIRTY_SWAPCACHE] = "dirty swapcache page",
> + [MF_MSG_CLEAN_SWAPCACHE] = "clean swapcache page",
> + [MF_MSG_DIRTY_MLOCKED_LRU] = "dirty mlocked LRU page",
> + [MF_MSG_CLEAN_MLOCKED_LRU] = "clean mlocked LRU page",
> + [MF_MSG_DIRTY_UNEVICTABLE_LRU] = "dirty unevictable LRU page",
> + [MF_MSG_CLEAN_UNEVICTABLE_LRU] = "clean unevictable LRU page",
> + [MF_MSG_DIRTY_LRU] = "dirty LRU page",
> + [MF_MSG_CLEAN_LRU] = "clean LRU page",
> + [MF_MSG_TRUNCATED_LRU] = "already truncated LRU page",
> + [MF_MSG_BUDDY] = "free buddy page",
> + [MF_MSG_BUDDY_2ND] = "free buddy page (2nd try)",
> + [MF_MSG_UNKNOWN] = "unknown page",
> };
>
> /*
> @@ -598,7 +564,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 +573,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 +582,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 +592,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 +606,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 +623,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 +631,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 +717,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 +727,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 +755,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;
> }
>
> /*
> @@ -823,10 +789,10 @@ static int me_huge_page(struct page *p, unsigned long pfn)
> static struct page_state {
> unsigned long mask;
> unsigned long res;
> - enum action_page_type type;
> + enum mf_action_page_type type;
> int (*action)(struct page *p, unsigned long pfn);
> } error_states[] = {
> - { reserved, reserved, MSG_KERNEL, me_kernel },
> + { reserved, reserved, MF_MSG_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 +803,31 @@ static struct page_state {
> * currently unused objects without touching them. But just
> * treat it as standard kernel for now.
> */
> - { slab, slab, MSG_SLAB, me_kernel },
> + { slab, slab, MF_MSG_SLAB, me_kernel },
>
> #ifdef CONFIG_PAGEFLAGS_EXTENDED
> - { head, head, MSG_HUGE, me_huge_page },
> - { tail, tail, MSG_HUGE, me_huge_page },
> + { head, head, MF_MSG_HUGE, me_huge_page },
> + { tail, tail, MF_MSG_HUGE, me_huge_page },
> #else
> - { compound, compound, MSG_HUGE, me_huge_page },
> + { compound, compound, MF_MSG_HUGE, me_huge_page },
> #endif
>
> - { sc|dirty, sc|dirty, MSG_DIRTY_SWAPCACHE, me_swapcache_dirty },
> - { sc|dirty, sc, MSG_CLEAN_SWAPCACHE, me_swapcache_clean },
> + { sc|dirty, sc|dirty, MF_MSG_DIRTY_SWAPCACHE, me_swapcache_dirty },
> + { sc|dirty, sc, MF_MSG_CLEAN_SWAPCACHE, me_swapcache_clean },
>
> - { mlock|dirty, mlock|dirty, MSG_DIRTY_MLOCKED_LRU, me_pagecache_dirty },
> - { mlock|dirty, mlock, MSG_CLEAN_MLOCKED_LRU, me_pagecache_clean },
> + { mlock|dirty, mlock|dirty, MF_MSG_DIRTY_MLOCKED_LRU, me_pagecache_dirty },
> + { mlock|dirty, mlock, MF_MSG_CLEAN_MLOCKED_LRU, me_pagecache_clean },
>
> - { unevict|dirty, unevict|dirty, MSG_DIRTY_UNEVICTABLE_LRU, me_pagecache_dirty },
> - { unevict|dirty, unevict, MSG_CLEAN_UNEVICTABLE_LRU, me_pagecache_clean },
> + { unevict|dirty, unevict|dirty, MF_MSG_DIRTY_UNEVICTABLE_LRU, me_pagecache_dirty },
> + { unevict|dirty, unevict, MF_MSG_CLEAN_UNEVICTABLE_LRU, me_pagecache_clean },
>
> - { lru|dirty, lru|dirty, MSG_DIRTY_LRU, me_pagecache_dirty },
> - { lru|dirty, lru, MSG_CLEAN_LRU, me_pagecache_clean },
> + { lru|dirty, lru|dirty, MF_MSG_DIRTY_LRU, me_pagecache_dirty },
> + { lru|dirty, lru, MF_MSG_CLEAN_LRU, me_pagecache_clean },
>
> /*
> * Catchall entry: must be at end.
> */
> - { 0, 0, MSG_UNKNOWN, me_unknown },
> + { 0, 0, MF_MSG_UNKNOWN, me_unknown },
> };
>
> #undef dirty
> @@ -881,7 +847,7 @@ static struct page_state {
> * "Dirty/Clean" indication is not 100% accurate due to the possibility of
> * setting PG_dirty outside page lock. See also comment above set_page_dirty().
> */
> -static void action_result(unsigned long pfn, enum action_page_type type, int result)
> +static void action_result(unsigned long pfn, enum mf_action_page_type type, int result)
> {
> pr_err("MCE %#lx: recovery action for %s: %s\n",
> pfn, action_page_types[type], action_name[result]);
> @@ -896,13 +862,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_types[ps->type], count);
> - result = FAILED;
> + result = MF_FAILED;
> }
> action_result(pfn, ps->type, result);
>
> @@ -911,7 +877,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 +1118,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, MSG_BUDDY, DELAYED);
> + action_result(pfn, MF_MSG_BUDDY, MF_DELAYED);
> return 0;
> } else if (PageHuge(hpage)) {
> /*
> @@ -1169,12 +1135,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, MSG_FREE_HUGE,
> - res ? IGNORED : DELAYED);
> + action_result(pfn, MF_MSG_FREE_HUGE,
> + res ? MF_IGNORED : MF_DELAYED);
> unlock_page(hpage);
> return res;
> } else {
> - action_result(pfn, MSG_KERNEL_HIGH_ORDER, IGNORED);
> + action_result(pfn, MF_MSG_KERNEL_HIGH_ORDER, MF_IGNORED);
> return -EBUSY;
> }
> }
> @@ -1196,10 +1162,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
> */
> if (is_free_buddy_page(p)) {
> if (flags & MF_COUNT_INCREASED)
> - action_result(pfn, MSG_BUDDY, DELAYED);
> + action_result(pfn, MF_MSG_BUDDY, MF_DELAYED);
> else
> - action_result(pfn, MSG_BUDDY_2ND,
> - DELAYED);
> + action_result(pfn, MF_MSG_BUDDY_2ND,
> + MF_DELAYED);
> return 0;
> }
> }
> @@ -1212,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, MSG_DIFFERENT_COMPOUND, IGNORED);
> + action_result(pfn, MF_MSG_DIFFERENT_COMPOUND, MF_IGNORED);
> res = -EBUSY;
> goto out;
> }
> @@ -1252,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, MSG_POISONED_HUGE, IGNORED);
> + action_result(pfn, MF_MSG_POISONED_HUGE, MF_IGNORED);
> unlock_page(hpage);
> put_page(hpage);
> return 0;
> @@ -1281,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, MSG_UNMAP_FAILED, IGNORED);
> + action_result(pfn, MF_MSG_UNMAP_FAILED, MF_IGNORED);
> res = -EBUSY;
> goto out;
> }
> @@ -1290,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, MSG_TRUNCATED_LRU, IGNORED);
> + action_result(pfn, MF_MSG_TRUNCATED_LRU, MF_IGNORED);
> res = -EBUSY;
> goto out;
> }
> --
> 1.8.3.1
> -

2015-05-07 01:13:26

by Naoya Horiguchi

[permalink] [raw]
Subject: Re: [PATCH v4 3/3] tracing: add trace event for memory-failure

On Mon, Apr 20, 2015 at 04:44:40PM +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]>

Reviewed-by: Naoya Horiguchi <[email protected]>

> ---
> include/ras/ras_event.h | 85 +++++++++++++++++++++++++++++++++++++++++++++++++
> mm/memory-failure.c | 3 ++
> 2 files changed, 88 insertions(+)
>
> diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
> index 79abb9c..258ed89 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,90 @@ TRACE_EVENT(aer_event,
> __print_flags(__entry->status, "|", aer_uncorrectable_errors))
> );
>
> +/*
> + * memory-failure recovery action result event
> + *
> + * unsigned long pfn - Page Frame Number of the corrupted page
> + * int type - Page types of the corrupted page
> + * int result - Result of recovery action
> + */
> +
> +#ifdef CONFIG_MEMORY_FAILURE
> +#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_MSG_KERNEL, "reserved kernel page" ) \
> + EM ( MF_MSG_KERNEL_HIGH_ORDER, "high-order kernel page" ) \
> + EM ( MF_MSG_SLAB, "kernel slab page" ) \
> + EM ( MF_MSG_DIFFERENT_COMPOUND, "different compound page after locking" ) \
> + EM ( MF_MSG_POISONED_HUGE, "huge page already hardware poisoned" ) \
> + EM ( MF_MSG_HUGE, "huge page" ) \
> + EM ( MF_MSG_FREE_HUGE, "free huge page" ) \
> + EM ( MF_MSG_UNMAP_FAILED, "unmapping failed page" ) \
> + EM ( MF_MSG_DIRTY_SWAPCACHE, "dirty swapcache page" ) \
> + EM ( MF_MSG_CLEAN_SWAPCACHE, "clean swapcache page" ) \
> + EM ( MF_MSG_DIRTY_MLOCKED_LRU, "dirty mlocked LRU page" ) \
> + EM ( MF_MSG_CLEAN_MLOCKED_LRU, "clean mlocked LRU page" ) \
> + EM ( MF_MSG_DIRTY_UNEVICTABLE_LRU, "dirty unevictable LRU page" ) \
> + EM ( MF_MSG_CLEAN_UNEVICTABLE_LRU, "clean unevictable LRU page" ) \
> + EM ( MF_MSG_DIRTY_LRU, "dirty LRU page" ) \
> + EM ( MF_MSG_CLEAN_LRU, "clean LRU page" ) \
> + EM ( MF_MSG_TRUNCATED_LRU, "already truncated LRU page" ) \
> + EM ( MF_MSG_BUDDY, "free buddy page" ) \
> + EM ( MF_MSG_BUDDY_2ND, "free buddy page (2nd try)" ) \
> + EMe ( MF_MSG_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 /* CONFIG_MEMORY_FAILURE */
> #endif /* _TRACE_HW_EVENT_MC_H */
>
> /* This part must be outside protection */
> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> index f074f8e..42c5981 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;
>
> @@ -850,6 +851,8 @@ static struct page_state {
> static void action_result(unsigned long pfn, enum mf_action_page_type type,
> enum mf_result result)
> {
> + trace_memory_failure_event(pfn, type, result);
> +
> pr_err("MCE %#lx: recovery action for %s: %s\n",
> pfn, action_page_types[type], action_name[result]);
> }
> --
> 1.8.3.1
> -

2015-05-07 01:13:07

by Naoya Horiguchi

[permalink] [raw]
Subject: Re: [PATCH v4 0/3] tracing: add trace event for memory-failure

On Wed, Apr 29, 2015 at 07:14:27PM +0800, Xie XiuQi wrote:
> Hi Naoya,
>
> Could you help to review and applied this series if possible.

Sorry for late response, I was offline for several days due to national
holidays.

This patchset is good to me, but I'm not sure which path it should go through.
Ordinarily, memory-failure patches go to linux-mm, but patch 3 depends on
TRACE_DEFINE_ENUM patches, so this can go to linux-next directly, or go to
linux-mm with depending patches.

Steven, Andrew, which way do you like?

Thanks,
Naoya Horiguchi

> Thanks,
> Xie XiuQi
>
> On 2015/4/20 16:44, 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 patchset 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
> >
> > --
> > v3->v4:
> > - rebase on top of latest linux-next
> > - update comments as Naoya's suggestion
> > - add #ifdef CONFIG_MEMORY_FAILURE for this trace event
> > - change type of action_result's param 3 to enum
> >
> > 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 (3):
> > memory-failure: export page_type and action result
> > memory-failure: change type of action_result's param 3 to enum
> > tracing: add trace event for memory-failure
> >
> > include/linux/mm.h | 34 ++++++++++
> > include/ras/ras_event.h | 85 ++++++++++++++++++++++++
> > mm/memory-failure.c | 172 ++++++++++++++++++++----------------------------
> > 3 files changed, 190 insertions(+), 101 deletions(-)
> >
>
> -

2015-05-07 02:17:38

by Steven Rostedt

[permalink] [raw]
Subject: Re: [PATCH v4 0/3] tracing: add trace event for memory-failure

On Thu, 7 May 2015 01:12:07 +0000
Naoya Horiguchi <[email protected]> wrote:

> On Wed, Apr 29, 2015 at 07:14:27PM +0800, Xie XiuQi wrote:
> > Hi Naoya,
> >
> > Could you help to review and applied this series if possible.
>
> Sorry for late response, I was offline for several days due to national
> holidays.
>
> This patchset is good to me, but I'm not sure which path it should go through.
> Ordinarily, memory-failure patches go to linux-mm, but patch 3 depends on
> TRACE_DEFINE_ENUM patches, so this can go to linux-next directly, or go to
> linux-mm with depending patches.
>
> Steven, Andrew, which way do you like?
>

The TRACE_DEFINE_ENUM() patch set went into the 4.1 merge window. It
should be fine to base off of any of Linus's tags after or including
4.1-rc1.

I need to start converting other trace events for 4.2.

-- Steve

2015-05-07 02:25:45

by Steven Rostedt

[permalink] [raw]
Subject: Re: [PATCH v4 3/3] tracing: add trace event for memory-failure

On Mon, 20 Apr 2015 16:44:40 +0800
Xie XiuQi <[email protected]> wrote:

> --- 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,90 @@ TRACE_EVENT(aer_event,
> __print_flags(__entry->status, "|", aer_uncorrectable_errors))
> );
>
> +/*
> + * memory-failure recovery action result event
> + *
> + * unsigned long pfn - Page Frame Number of the corrupted page
> + * int type - Page types of the corrupted page
> + * int result - Result of recovery action
> + */
> +
> +#ifdef CONFIG_MEMORY_FAILURE
> +#define MF_ACTION_RESULT \
> + EM ( MF_IGNORED, "Ignord" ) \

"Ignored" ?

> + EM ( MF_FAILED, "Failed" ) \
> + EM ( MF_DELAYED, "Delayed" ) \
> + EMe ( MF_RECOVERED, "Recovered" )
> +
> +#define MF_PAGE_TYPE \
> + EM ( MF_MSG_KERNEL, "reserved kernel page" ) \
> + EM ( MF_MSG_KERNEL_HIGH_ORDER, "high-order kernel page" ) \
> + EM ( MF_MSG_SLAB, "kernel slab page" ) \
> + EM ( MF_MSG_DIFFERENT_COMPOUND, "different compound page after locking" ) \
> + EM ( MF_MSG_POISONED_HUGE, "huge page already hardware poisoned" ) \
> + EM ( MF_MSG_HUGE, "huge page" ) \
> + EM ( MF_MSG_FREE_HUGE, "free huge page" ) \
> + EM ( MF_MSG_UNMAP_FAILED, "unmapping failed page" ) \
> + EM ( MF_MSG_DIRTY_SWAPCACHE, "dirty swapcache page" ) \
> + EM ( MF_MSG_CLEAN_SWAPCACHE, "clean swapcache page" ) \
> + EM ( MF_MSG_DIRTY_MLOCKED_LRU, "dirty mlocked LRU page" ) \
> + EM ( MF_MSG_CLEAN_MLOCKED_LRU, "clean mlocked LRU page" ) \
> + EM ( MF_MSG_DIRTY_UNEVICTABLE_LRU, "dirty unevictable LRU page" ) \
> + EM ( MF_MSG_CLEAN_UNEVICTABLE_LRU, "clean unevictable LRU page" ) \
> + EM ( MF_MSG_DIRTY_LRU, "dirty LRU page" ) \
> + EM ( MF_MSG_CLEAN_LRU, "clean LRU page" ) \
> + EM ( MF_MSG_TRUNCATED_LRU, "already truncated LRU page" ) \
> + EM ( MF_MSG_BUDDY, "free buddy page" ) \
> + EM ( MF_MSG_BUDDY_2ND, "free buddy page (2nd try)" ) \
> + EMe ( MF_MSG_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",

Hmm, "%#" is new to me. I'm not sure libtraceevent handles that.

Not your problem, I need to make sure that it does, and if it does not,
I need to fix it.

I'm not even sure what %# does.

Other than the typo,

Acked-by: Steven Rostedt <[email protected]>

-- Steve


> + __entry->pfn,
> + __print_symbolic(__entry->type, MF_PAGE_TYPE),
> + __print_symbolic(__entry->result, MF_ACTION_RESULT)
> + )
> +);
> +#endif /* CONFIG_MEMORY_FAILURE */
> #endif /* _TRACE_HW_EVENT_MC_H */
>
> /* This part must be outside protection */
> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> index f074f8e..42c5981 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;
>
> @@ -850,6 +851,8 @@ static struct page_state {
> static void action_result(unsigned long pfn, enum mf_action_page_type type,
> enum mf_result result)
> {
> + trace_memory_failure_event(pfn, type, result);
> +
> pr_err("MCE %#lx: recovery action for %s: %s\n",
> pfn, action_page_types[type], action_name[result]);
> }

2015-05-07 05:59:27

by Xie XiuQi

[permalink] [raw]
Subject: Re: [PATCH v4 0/3] tracing: add trace event for memory-failure

On 2015/5/7 9:12, Naoya Horiguchi wrote:
> On Wed, Apr 29, 2015 at 07:14:27PM +0800, Xie XiuQi wrote:
>> Hi Naoya,
>>
>> Could you help to review and applied this series if possible.
>
> Sorry for late response, I was offline for several days due to national
> holidays.

It doesn't matter, wish you have a good holiday ;-)

>
> This patchset is good to me, but I'm not sure which path it should go through.
> Ordinarily, memory-failure patches go to linux-mm, but patch 3 depends on
> TRACE_DEFINE_ENUM patches, so this can go to linux-next directly, or go to
> linux-mm with depending patches.

TRACE_DEFINE_ENUM patches has been merged into mainline. I'll correct patch 3's typo
and rebase them on top of latest mainline in v5.

Thanks,
Xie XiuQi

>
> Steven, Andrew, which way do you like?
>
> Thanks,
> Naoya Horiguchi
>
>> Thanks,
>> Xie XiuQi
>>
>> On 2015/4/20 16:44, 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 patchset 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
>>>
>>> --
>>> v3->v4:
>>> - rebase on top of latest linux-next
>>> - update comments as Naoya's suggestion
>>> - add #ifdef CONFIG_MEMORY_FAILURE for this trace event
>>> - change type of action_result's param 3 to enum
>>>
>>> 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 (3):
>>> memory-failure: export page_type and action result
>>> memory-failure: change type of action_result's param 3 to enum
>>> tracing: add trace event for memory-failure
>>>
>>> include/linux/mm.h | 34 ++++++++++
>>> include/ras/ras_event.h | 85 ++++++++++++++++++++++++
>>> mm/memory-failure.c | 172 ++++++++++++++++++++----------------------------
>>> 3 files changed, 190 insertions(+), 101 deletions(-)
>>>
>>
>> --
> 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/
>
> .
>

2015-05-07 06:04:54

by Xie XiuQi

[permalink] [raw]
Subject: Re: [PATCH v4 3/3] tracing: add trace event for memory-failure

On 2015/5/7 10:25, Steven Rostedt wrote:
> On Mon, 20 Apr 2015 16:44:40 +0800
> Xie XiuQi <[email protected]> wrote:
>

...

>> + *
>> + * unsigned long pfn - Page Frame Number of the corrupted page
>> + * int type - Page types of the corrupted page
>> + * int result - Result of recovery action
>> + */
>> +
>> +#ifdef CONFIG_MEMORY_FAILURE
>> +#define MF_ACTION_RESULT \
>> + EM ( MF_IGNORED, "Ignord" ) \
>
> "Ignored" ?

My fault, I'll correct it, thanks.

>
>> + EM ( MF_FAILED, "Failed" ) \
>> + EM ( MF_DELAYED, "Delayed" ) \
>> + EMe ( MF_RECOVERED, "Recovered" )
>> +
>> +#define MF_PAGE_TYPE \
>> + EM ( MF_MSG_KERNEL, "reserved kernel page" ) \
>> + EM ( MF_MSG_KERNEL_HIGH_ORDER, "high-order kernel page" ) \
...
>> + ),
>> +
>> + TP_fast_assign(
>> + __entry->pfn = pfn;
>> + __entry->type = type;
>> + __entry->result = result;
>> + ),
>> +
>> + TP_printk("pfn %#lx: recovery action for %s: %s",
>
> Hmm, "%#" is new to me. I'm not sure libtraceevent handles that.
>
> Not your problem, I need to make sure that it does, and if it does not,
> I need to fix it.
>
> I'm not even sure what %# does.
>
> Other than the typo,
>
> Acked-by: Steven Rostedt <[email protected]>

Thanks,
Xie XiuQi

>
> -- Steve
>
>
>> + __entry->pfn,
>> + __print_symbolic(__entry->type, MF_PAGE_TYPE),
>> + __print_symbolic(__entry->result, MF_ACTION_RESULT)
>> + )
>> +);
>> +#endif /* CONFIG_MEMORY_FAILURE */
>> #endif /* _TRACE_HW_EVENT_MC_H */
>>
>> /* This part must be outside protection */
>> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
>> index f074f8e..42c5981 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;
>>
>> @@ -850,6 +851,8 @@ static struct page_state {
>> static void action_result(unsigned long pfn, enum mf_action_page_type type,
>> enum mf_result result)
>> {
>> + trace_memory_failure_event(pfn, type, result);
>> +
>> pr_err("MCE %#lx: recovery action for %s: %s\n",
>> pfn, action_page_types[type], action_name[result]);
>> }
>
>
> .
>