diff options
author | Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> | 2015-04-15 19:13:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-15 19:35:16 -0400 |
commit | 64d37a2baf5e5c0f1009c0ef290a9027de721d66 (patch) | |
tree | 6d36f30d67e7a2bbf595248097ad5a75362aa611 | |
parent | 2564f683d1a6cb76893199ce68e6484725621e49 (diff) |
mm/memory-failure.c: define page types for action_result() in one place
This cleanup patch moves all strings passed to action_result() into a
singl= e array action_page_type so that a reader can easily find which
kind of actio= n results are possible. And this patch also fixes the
odd lines to be printed out, like "unknown page state page" or "free
buddy, 2nd try page".
[akpm@linux-foundation.org: rename messages, per David]
[akpm@linux-foundation.org: s/DIRTY_UNEVICTABLE_LRU/CLEAN_UNEVICTABLE_LRU', per Andi]
Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: "Xie XiuQi" <xiexiuqi@huawei.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Chen Gong <gong.chen@linux.intel.com>
Cc: David Rientjes <rientjes@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | mm/memory-failure.c | 108 |
1 files changed, 77 insertions, 31 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index d487f8dc6d39..5fd8931d8c31 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
@@ -521,6 +521,52 @@ static const char *action_name[] = { | |||
521 | [RECOVERED] = "Recovered", | 521 | [RECOVERED] = "Recovered", |
522 | }; | 522 | }; |
523 | 523 | ||
524 | enum action_page_type { | ||
525 | MSG_KERNEL, | ||
526 | MSG_KERNEL_HIGH_ORDER, | ||
527 | MSG_SLAB, | ||
528 | MSG_DIFFERENT_COMPOUND, | ||
529 | MSG_POISONED_HUGE, | ||
530 | MSG_HUGE, | ||
531 | MSG_FREE_HUGE, | ||
532 | MSG_UNMAP_FAILED, | ||
533 | MSG_DIRTY_SWAPCACHE, | ||
534 | MSG_CLEAN_SWAPCACHE, | ||
535 | MSG_DIRTY_MLOCKED_LRU, | ||
536 | MSG_CLEAN_MLOCKED_LRU, | ||
537 | MSG_DIRTY_UNEVICTABLE_LRU, | ||
538 | MSG_CLEAN_UNEVICTABLE_LRU, | ||
539 | MSG_DIRTY_LRU, | ||
540 | MSG_CLEAN_LRU, | ||
541 | MSG_TRUNCATED_LRU, | ||
542 | MSG_BUDDY, | ||
543 | MSG_BUDDY_2ND, | ||
544 | MSG_UNKNOWN, | ||
545 | }; | ||
546 | |||
547 | static const char * const action_page_types[] = { | ||
548 | [MSG_KERNEL] = "reserved kernel page", | ||
549 | [MSG_KERNEL_HIGH_ORDER] = "high-order kernel page", | ||
550 | [MSG_SLAB] = "kernel slab page", | ||
551 | [MSG_DIFFERENT_COMPOUND] = "different compound page after locking", | ||
552 | [MSG_POISONED_HUGE] = "huge page already hardware poisoned", | ||
553 | [MSG_HUGE] = "huge page", | ||
554 | [MSG_FREE_HUGE] = "free huge page", | ||
555 | [MSG_UNMAP_FAILED] = "unmapping failed page", | ||
556 | [MSG_DIRTY_SWAPCACHE] = "dirty swapcache page", | ||
557 | [MSG_CLEAN_SWAPCACHE] = "clean swapcache page", | ||
558 | [MSG_DIRTY_MLOCKED_LRU] = "dirty mlocked LRU page", | ||
559 | [MSG_CLEAN_MLOCKED_LRU] = "clean mlocked LRU page", | ||
560 | [MSG_DIRTY_UNEVICTABLE_LRU] = "dirty unevictable LRU page", | ||
561 | [MSG_CLEAN_UNEVICTABLE_LRU] = "clean unevictable LRU page", | ||
562 | [MSG_DIRTY_LRU] = "dirty LRU page", | ||
563 | [MSG_CLEAN_LRU] = "clean LRU page", | ||
564 | [MSG_TRUNCATED_LRU] = "already truncated LRU page", | ||
565 | [MSG_BUDDY] = "free buddy page", | ||
566 | [MSG_BUDDY_2ND] = "free buddy page (2nd try)", | ||
567 | [MSG_UNKNOWN] = "unknown page", | ||
568 | }; | ||
569 | |||
524 | /* | 570 | /* |
525 | * XXX: It is possible that a page is isolated from LRU cache, | 571 | * XXX: It is possible that a page is isolated from LRU cache, |
526 | * and then kept in swap cache or failed to remove from page cache. | 572 | * and then kept in swap cache or failed to remove from page cache. |
@@ -777,10 +823,10 @@ static int me_huge_page(struct page *p, unsigned long pfn) | |||
777 | static struct page_state { | 823 | static struct page_state { |
778 | unsigned long mask; | 824 | unsigned long mask; |
779 | unsigned long res; | 825 | unsigned long res; |
780 | char *msg; | 826 | enum action_page_type type; |
781 | int (*action)(struct page *p, unsigned long pfn); | 827 | int (*action)(struct page *p, unsigned long pfn); |
782 | } error_states[] = { | 828 | } error_states[] = { |
783 | { reserved, reserved, "reserved kernel", me_kernel }, | 829 | { reserved, reserved, MSG_KERNEL, me_kernel }, |
784 | /* | 830 | /* |
785 | * free pages are specially detected outside this table: | 831 | * free pages are specially detected outside this table: |
786 | * PG_buddy pages only make a small fraction of all free pages. | 832 | * PG_buddy pages only make a small fraction of all free pages. |
@@ -791,31 +837,31 @@ static struct page_state { | |||
791 | * currently unused objects without touching them. But just | 837 | * currently unused objects without touching them. But just |
792 | * treat it as standard kernel for now. | 838 | * treat it as standard kernel for now. |
793 | */ | 839 | */ |
794 | { slab, slab, "kernel slab", me_kernel }, | 840 | { slab, slab, MSG_SLAB, me_kernel }, |
795 | 841 | ||
796 | #ifdef CONFIG_PAGEFLAGS_EXTENDED | 842 | #ifdef CONFIG_PAGEFLAGS_EXTENDED |
797 | { head, head, "huge", me_huge_page }, | 843 | { head, head, MSG_HUGE, me_huge_page }, |
798 | { tail, tail, "huge", me_huge_page }, | 844 | { tail, tail, MSG_HUGE, me_huge_page }, |
799 | #else | 845 | #else |
800 | { compound, compound, "huge", me_huge_page }, | 846 | { compound, compound, MSG_HUGE, me_huge_page }, |
801 | #endif | 847 | #endif |
802 | 848 | ||
803 | { sc|dirty, sc|dirty, "dirty swapcache", me_swapcache_dirty }, | 849 | { sc|dirty, sc|dirty, MSG_DIRTY_SWAPCACHE, me_swapcache_dirty }, |
804 | { sc|dirty, sc, "clean swapcache", me_swapcache_clean }, | 850 | { sc|dirty, sc, MSG_CLEAN_SWAPCACHE, me_swapcache_clean }, |
805 | 851 | ||
806 | { mlock|dirty, mlock|dirty, "dirty mlocked LRU", me_pagecache_dirty }, | 852 | { mlock|dirty, mlock|dirty, MSG_DIRTY_MLOCKED_LRU, me_pagecache_dirty }, |
807 | { mlock|dirty, mlock, "clean mlocked LRU", me_pagecache_clean }, | 853 | { mlock|dirty, mlock, MSG_CLEAN_MLOCKED_LRU, me_pagecache_clean }, |
808 | 854 | ||
809 | { unevict|dirty, unevict|dirty, "dirty unevictable LRU", me_pagecache_dirty }, | 855 | { unevict|dirty, unevict|dirty, MSG_DIRTY_UNEVICTABLE_LRU, me_pagecache_dirty }, |
810 | { unevict|dirty, unevict, "clean unevictable LRU", me_pagecache_clean }, | 856 | { unevict|dirty, unevict, MSG_CLEAN_UNEVICTABLE_LRU, me_pagecache_clean }, |
811 | 857 | ||
812 | { lru|dirty, lru|dirty, "dirty LRU", me_pagecache_dirty }, | 858 | { lru|dirty, lru|dirty, MSG_DIRTY_LRU, me_pagecache_dirty }, |
813 | { lru|dirty, lru, "clean LRU", me_pagecache_clean }, | 859 | { lru|dirty, lru, MSG_CLEAN_LRU, me_pagecache_clean }, |
814 | 860 | ||
815 | /* | 861 | /* |
816 | * Catchall entry: must be at end. | 862 | * Catchall entry: must be at end. |
817 | */ | 863 | */ |
818 | { 0, 0, "unknown page state", me_unknown }, | 864 | { 0, 0, MSG_UNKNOWN, me_unknown }, |
819 | }; | 865 | }; |
820 | 866 | ||
821 | #undef dirty | 867 | #undef dirty |
@@ -835,10 +881,10 @@ static struct page_state { | |||
835 | * "Dirty/Clean" indication is not 100% accurate due to the possibility of | 881 | * "Dirty/Clean" indication is not 100% accurate due to the possibility of |
836 | * setting PG_dirty outside page lock. See also comment above set_page_dirty(). | 882 | * setting PG_dirty outside page lock. See also comment above set_page_dirty(). |
837 | */ | 883 | */ |
838 | static void action_result(unsigned long pfn, char *msg, int result) | 884 | static void action_result(unsigned long pfn, enum action_page_type type, int result) |
839 | { | 885 | { |
840 | pr_err("MCE %#lx: %s page recovery: %s\n", | 886 | pr_err("MCE %#lx: recovery action for %s: %s\n", |
841 | pfn, msg, action_name[result]); | 887 | pfn, action_page_types[type], action_name[result]); |
842 | } | 888 | } |
843 | 889 | ||
844 | static int page_action(struct page_state *ps, struct page *p, | 890 | static int page_action(struct page_state *ps, struct page *p, |
@@ -854,11 +900,11 @@ static int page_action(struct page_state *ps, struct page *p, | |||
854 | count--; | 900 | count--; |
855 | if (count != 0) { | 901 | if (count != 0) { |
856 | printk(KERN_ERR | 902 | printk(KERN_ERR |
857 | "MCE %#lx: %s page still referenced by %d users\n", | 903 | "MCE %#lx: %s still referenced by %d users\n", |
858 | pfn, ps->msg, count); | 904 | pfn, action_page_types[ps->type], count); |
859 | result = FAILED; | 905 | result = FAILED; |
860 | } | 906 | } |
861 | action_result(pfn, ps->msg, result); | 907 | action_result(pfn, ps->type, result); |
862 | 908 | ||
863 | /* Could do more checks here if page looks ok */ | 909 | /* Could do more checks here if page looks ok */ |
864 | /* | 910 | /* |
@@ -1106,7 +1152,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags) | |||
1106 | if (!(flags & MF_COUNT_INCREASED) && | 1152 | if (!(flags & MF_COUNT_INCREASED) && |
1107 | !get_page_unless_zero(hpage)) { | 1153 | !get_page_unless_zero(hpage)) { |
1108 | if (is_free_buddy_page(p)) { | 1154 | if (is_free_buddy_page(p)) { |
1109 | action_result(pfn, "free buddy", DELAYED); | 1155 | action_result(pfn, MSG_BUDDY, DELAYED); |
1110 | return 0; | 1156 | return 0; |
1111 | } else if (PageHuge(hpage)) { | 1157 | } else if (PageHuge(hpage)) { |
1112 | /* | 1158 | /* |
@@ -1123,12 +1169,12 @@ int memory_failure(unsigned long pfn, int trapno, int flags) | |||
1123 | } | 1169 | } |
1124 | set_page_hwpoison_huge_page(hpage); | 1170 | set_page_hwpoison_huge_page(hpage); |
1125 | res = dequeue_hwpoisoned_huge_page(hpage); | 1171 | res = dequeue_hwpoisoned_huge_page(hpage); |
1126 | action_result(pfn, "free huge", | 1172 | action_result(pfn, MSG_FREE_HUGE, |
1127 | res ? IGNORED : DELAYED); | 1173 | res ? IGNORED : DELAYED); |
1128 | unlock_page(hpage); | 1174 | unlock_page(hpage); |
1129 | return res; | 1175 | return res; |
1130 | } else { | 1176 | } else { |
1131 | action_result(pfn, "high order kernel", IGNORED); | 1177 | action_result(pfn, MSG_KERNEL_HIGH_ORDER, IGNORED); |
1132 | return -EBUSY; | 1178 | return -EBUSY; |
1133 | } | 1179 | } |
1134 | } | 1180 | } |
@@ -1150,9 +1196,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags) | |||
1150 | */ | 1196 | */ |
1151 | if (is_free_buddy_page(p)) { | 1197 | if (is_free_buddy_page(p)) { |
1152 | if (flags & MF_COUNT_INCREASED) | 1198 | if (flags & MF_COUNT_INCREASED) |
1153 | action_result(pfn, "free buddy", DELAYED); | 1199 | action_result(pfn, MSG_BUDDY, DELAYED); |
1154 | else | 1200 | else |
1155 | action_result(pfn, "free buddy, 2nd try", DELAYED); | 1201 | action_result(pfn, MSG_BUDDY_2ND, |
1202 | DELAYED); | ||
1156 | return 0; | 1203 | return 0; |
1157 | } | 1204 | } |
1158 | } | 1205 | } |
@@ -1165,7 +1212,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags) | |||
1165 | * If this happens just bail out. | 1212 | * If this happens just bail out. |
1166 | */ | 1213 | */ |
1167 | if (compound_head(p) != hpage) { | 1214 | if (compound_head(p) != hpage) { |
1168 | action_result(pfn, "different compound page after locking", IGNORED); | 1215 | action_result(pfn, MSG_DIFFERENT_COMPOUND, IGNORED); |
1169 | res = -EBUSY; | 1216 | res = -EBUSY; |
1170 | goto out; | 1217 | goto out; |
1171 | } | 1218 | } |
@@ -1205,8 +1252,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags) | |||
1205 | * on the head page to show that the hugepage is hwpoisoned | 1252 | * on the head page to show that the hugepage is hwpoisoned |
1206 | */ | 1253 | */ |
1207 | if (PageHuge(p) && PageTail(p) && TestSetPageHWPoison(hpage)) { | 1254 | if (PageHuge(p) && PageTail(p) && TestSetPageHWPoison(hpage)) { |
1208 | action_result(pfn, "hugepage already hardware poisoned", | 1255 | action_result(pfn, MSG_POISONED_HUGE, IGNORED); |
1209 | IGNORED); | ||
1210 | unlock_page(hpage); | 1256 | unlock_page(hpage); |
1211 | put_page(hpage); | 1257 | put_page(hpage); |
1212 | return 0; | 1258 | return 0; |
@@ -1235,7 +1281,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags) | |||
1235 | */ | 1281 | */ |
1236 | if (hwpoison_user_mappings(p, pfn, trapno, flags, &hpage) | 1282 | if (hwpoison_user_mappings(p, pfn, trapno, flags, &hpage) |
1237 | != SWAP_SUCCESS) { | 1283 | != SWAP_SUCCESS) { |
1238 | action_result(pfn, "unmapping failed", IGNORED); | 1284 | action_result(pfn, MSG_UNMAP_FAILED, IGNORED); |
1239 | res = -EBUSY; | 1285 | res = -EBUSY; |
1240 | goto out; | 1286 | goto out; |
1241 | } | 1287 | } |
@@ -1244,7 +1290,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags) | |||
1244 | * Torn down by someone else? | 1290 | * Torn down by someone else? |
1245 | */ | 1291 | */ |
1246 | if (PageLRU(p) && !PageSwapCache(p) && p->mapping == NULL) { | 1292 | if (PageLRU(p) && !PageSwapCache(p) && p->mapping == NULL) { |
1247 | action_result(pfn, "already truncated LRU", IGNORED); | 1293 | action_result(pfn, MSG_TRUNCATED_LRU, IGNORED); |
1248 | res = -EBUSY; | 1294 | res = -EBUSY; |
1249 | goto out; | 1295 | goto out; |
1250 | } | 1296 | } |