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

From: Xie XiuQi
Date: Sat Apr 11 2015 - 06:42:57 EST


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


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