[RFC PATCH v3 1/2] memory-failure: export page_type and action result

From: Xie XiuQi
Date: Tue Apr 07 2015 - 07:19:19 EST


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 <xiexiuqi@xxxxxxxxxx>
---
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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/