summaryrefslogtreecommitdiffstats
path: root/mm/memory-failure.c
diff options
context:
space:
mode:
authorXie XiuQi <xiexiuqi@huawei.com>2015-06-24 19:57:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-24 20:49:43 -0400
commitcc637b1704d78b068c2eb700eec384c69ea56cdf (patch)
tree3a406d52580aa7ce7b834a580922742bd3d665d4 /mm/memory-failure.c
parenteb3c24f305e56caaf5c4bd34d2923839688d470e (diff)
memory-failure: export page_type and action result
Export 'outcome' and 'action_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@huawei.com> Acked-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Cc: Chen Gong <gong.chen@linux.intel.com> Cc: Jim Davis <jim.epost@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Tony Luck <tony.luck@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memory-failure.c')
-rw-r--r--mm/memory-failure.c168
1 files changed, 67 insertions, 101 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index c72f41bfbaaf..b71a3cd3d0b0 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -504,68 +504,34 @@ static void collect_procs(struct page *page, struct list_head *tokill,
504 kfree(tk); 504 kfree(tk);
505} 505}
506 506
507/*
508 * Error handlers for various types of pages.
509 */
510
511enum outcome {
512 IGNORED, /* Error: cannot be handled */
513 FAILED, /* Error: handling failed */
514 DELAYED, /* Will be handled later */
515 RECOVERED, /* Successfully recovered */
516};
517
518static const char *action_name[] = { 507static const char *action_name[] = {
519 [IGNORED] = "Ignored", 508 [MF_IGNORED] = "Ignored",
520 [FAILED] = "Failed", 509 [MF_FAILED] = "Failed",
521 [DELAYED] = "Delayed", 510 [MF_DELAYED] = "Delayed",
522 [RECOVERED] = "Recovered", 511 [MF_RECOVERED] = "Recovered",
523};
524
525enum action_page_type {
526 MSG_KERNEL,
527 MSG_KERNEL_HIGH_ORDER,
528 MSG_SLAB,
529 MSG_DIFFERENT_COMPOUND,
530 MSG_POISONED_HUGE,
531 MSG_HUGE,
532 MSG_FREE_HUGE,
533 MSG_UNMAP_FAILED,
534 MSG_DIRTY_SWAPCACHE,
535 MSG_CLEAN_SWAPCACHE,
536 MSG_DIRTY_MLOCKED_LRU,
537 MSG_CLEAN_MLOCKED_LRU,
538 MSG_DIRTY_UNEVICTABLE_LRU,
539 MSG_CLEAN_UNEVICTABLE_LRU,
540 MSG_DIRTY_LRU,
541 MSG_CLEAN_LRU,
542 MSG_TRUNCATED_LRU,
543 MSG_BUDDY,
544 MSG_BUDDY_2ND,
545 MSG_UNKNOWN,
546}; 512};
547 513
548static const char * const action_page_types[] = { 514static const char * const action_page_types[] = {
549 [MSG_KERNEL] = "reserved kernel page", 515 [MF_MSG_KERNEL] = "reserved kernel page",
550 [MSG_KERNEL_HIGH_ORDER] = "high-order kernel page", 516 [MF_MSG_KERNEL_HIGH_ORDER] = "high-order kernel page",
551 [MSG_SLAB] = "kernel slab page", 517 [MF_MSG_SLAB] = "kernel slab page",
552 [MSG_DIFFERENT_COMPOUND] = "different compound page after locking", 518 [MF_MSG_DIFFERENT_COMPOUND] = "different compound page after locking",
553 [MSG_POISONED_HUGE] = "huge page already hardware poisoned", 519 [MF_MSG_POISONED_HUGE] = "huge page already hardware poisoned",
554 [MSG_HUGE] = "huge page", 520 [MF_MSG_HUGE] = "huge page",
555 [MSG_FREE_HUGE] = "free huge page", 521 [MF_MSG_FREE_HUGE] = "free huge page",
556 [MSG_UNMAP_FAILED] = "unmapping failed page", 522 [MF_MSG_UNMAP_FAILED] = "unmapping failed page",
557 [MSG_DIRTY_SWAPCACHE] = "dirty swapcache page", 523 [MF_MSG_DIRTY_SWAPCACHE] = "dirty swapcache page",
558 [MSG_CLEAN_SWAPCACHE] = "clean swapcache page", 524 [MF_MSG_CLEAN_SWAPCACHE] = "clean swapcache page",
559 [MSG_DIRTY_MLOCKED_LRU] = "dirty mlocked LRU page", 525 [MF_MSG_DIRTY_MLOCKED_LRU] = "dirty mlocked LRU page",
560 [MSG_CLEAN_MLOCKED_LRU] = "clean mlocked LRU page", 526 [MF_MSG_CLEAN_MLOCKED_LRU] = "clean mlocked LRU page",
561 [MSG_DIRTY_UNEVICTABLE_LRU] = "dirty unevictable LRU page", 527 [MF_MSG_DIRTY_UNEVICTABLE_LRU] = "dirty unevictable LRU page",
562 [MSG_CLEAN_UNEVICTABLE_LRU] = "clean unevictable LRU page", 528 [MF_MSG_CLEAN_UNEVICTABLE_LRU] = "clean unevictable LRU page",
563 [MSG_DIRTY_LRU] = "dirty LRU page", 529 [MF_MSG_DIRTY_LRU] = "dirty LRU page",
564 [MSG_CLEAN_LRU] = "clean LRU page", 530 [MF_MSG_CLEAN_LRU] = "clean LRU page",
565 [MSG_TRUNCATED_LRU] = "already truncated LRU page", 531 [MF_MSG_TRUNCATED_LRU] = "already truncated LRU page",
566 [MSG_BUDDY] = "free buddy page", 532 [MF_MSG_BUDDY] = "free buddy page",
567 [MSG_BUDDY_2ND] = "free buddy page (2nd try)", 533 [MF_MSG_BUDDY_2ND] = "free buddy page (2nd try)",
568 [MSG_UNKNOWN] = "unknown page", 534 [MF_MSG_UNKNOWN] = "unknown page",
569}; 535};
570 536
571/* 537/*
@@ -599,7 +565,7 @@ static int delete_from_lru_cache(struct page *p)
599 */ 565 */
600static int me_kernel(struct page *p, unsigned long pfn) 566static int me_kernel(struct page *p, unsigned long pfn)
601{ 567{
602 return IGNORED; 568 return MF_IGNORED;
603} 569}
604 570
605/* 571/*
@@ -608,7 +574,7 @@ static int me_kernel(struct page *p, unsigned long pfn)
608static int me_unknown(struct page *p, unsigned long pfn) 574static int me_unknown(struct page *p, unsigned long pfn)
609{ 575{
610 printk(KERN_ERR "MCE %#lx: Unknown page state\n", pfn); 576 printk(KERN_ERR "MCE %#lx: Unknown page state\n", pfn);
611 return FAILED; 577 return MF_FAILED;
612} 578}
613 579
614/* 580/*
@@ -617,7 +583,7 @@ static int me_unknown(struct page *p, unsigned long pfn)
617static int me_pagecache_clean(struct page *p, unsigned long pfn) 583static int me_pagecache_clean(struct page *p, unsigned long pfn)
618{ 584{
619 int err; 585 int err;
620 int ret = FAILED; 586 int ret = MF_FAILED;
621 struct address_space *mapping; 587 struct address_space *mapping;
622 588
623 delete_from_lru_cache(p); 589 delete_from_lru_cache(p);
@@ -627,7 +593,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
627 * should be the one m_f() holds. 593 * should be the one m_f() holds.
628 */ 594 */
629 if (PageAnon(p)) 595 if (PageAnon(p))
630 return RECOVERED; 596 return MF_RECOVERED;
631 597
632 /* 598 /*
633 * Now truncate the page in the page cache. This is really 599 * Now truncate the page in the page cache. This is really
@@ -641,7 +607,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
641 /* 607 /*
642 * Page has been teared down in the meanwhile 608 * Page has been teared down in the meanwhile
643 */ 609 */
644 return FAILED; 610 return MF_FAILED;
645 } 611 }
646 612
647 /* 613 /*
@@ -658,7 +624,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
658 !try_to_release_page(p, GFP_NOIO)) { 624 !try_to_release_page(p, GFP_NOIO)) {
659 pr_info("MCE %#lx: failed to release buffers\n", pfn); 625 pr_info("MCE %#lx: failed to release buffers\n", pfn);
660 } else { 626 } else {
661 ret = RECOVERED; 627 ret = MF_RECOVERED;
662 } 628 }
663 } else { 629 } else {
664 /* 630 /*
@@ -666,7 +632,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
666 * This fails on dirty or anything with private pages 632 * This fails on dirty or anything with private pages
667 */ 633 */
668 if (invalidate_inode_page(p)) 634 if (invalidate_inode_page(p))
669 ret = RECOVERED; 635 ret = MF_RECOVERED;
670 else 636 else
671 printk(KERN_INFO "MCE %#lx: Failed to invalidate\n", 637 printk(KERN_INFO "MCE %#lx: Failed to invalidate\n",
672 pfn); 638 pfn);
@@ -752,9 +718,9 @@ static int me_swapcache_dirty(struct page *p, unsigned long pfn)
752 ClearPageUptodate(p); 718 ClearPageUptodate(p);
753 719
754 if (!delete_from_lru_cache(p)) 720 if (!delete_from_lru_cache(p))
755 return DELAYED; 721 return MF_DELAYED;
756 else 722 else
757 return FAILED; 723 return MF_FAILED;
758} 724}
759 725
760static int me_swapcache_clean(struct page *p, unsigned long pfn) 726static int me_swapcache_clean(struct page *p, unsigned long pfn)
@@ -762,9 +728,9 @@ static int me_swapcache_clean(struct page *p, unsigned long pfn)
762 delete_from_swap_cache(p); 728 delete_from_swap_cache(p);
763 729
764 if (!delete_from_lru_cache(p)) 730 if (!delete_from_lru_cache(p))
765 return RECOVERED; 731 return MF_RECOVERED;
766 else 732 else
767 return FAILED; 733 return MF_FAILED;
768} 734}
769 735
770/* 736/*
@@ -794,9 +760,9 @@ static int me_huge_page(struct page *p, unsigned long pfn)
794 if (!(page_mapping(hpage) || PageAnon(hpage))) { 760 if (!(page_mapping(hpage) || PageAnon(hpage))) {
795 res = dequeue_hwpoisoned_huge_page(hpage); 761 res = dequeue_hwpoisoned_huge_page(hpage);
796 if (!res) 762 if (!res)
797 return RECOVERED; 763 return MF_RECOVERED;
798 } 764 }
799 return DELAYED; 765 return MF_DELAYED;
800} 766}
801 767
802/* 768/*
@@ -828,10 +794,10 @@ static int me_huge_page(struct page *p, unsigned long pfn)
828static struct page_state { 794static struct page_state {
829 unsigned long mask; 795 unsigned long mask;
830 unsigned long res; 796 unsigned long res;
831 enum action_page_type type; 797 enum mf_action_page_type type;
832 int (*action)(struct page *p, unsigned long pfn); 798 int (*action)(struct page *p, unsigned long pfn);
833} error_states[] = { 799} error_states[] = {
834 { reserved, reserved, MSG_KERNEL, me_kernel }, 800 { reserved, reserved, MF_MSG_KERNEL, me_kernel },
835 /* 801 /*
836 * free pages are specially detected outside this table: 802 * free pages are specially detected outside this table:
837 * PG_buddy pages only make a small fraction of all free pages. 803 * PG_buddy pages only make a small fraction of all free pages.
@@ -842,31 +808,31 @@ static struct page_state {
842 * currently unused objects without touching them. But just 808 * currently unused objects without touching them. But just
843 * treat it as standard kernel for now. 809 * treat it as standard kernel for now.
844 */ 810 */
845 { slab, slab, MSG_SLAB, me_kernel }, 811 { slab, slab, MF_MSG_SLAB, me_kernel },
846 812
847#ifdef CONFIG_PAGEFLAGS_EXTENDED 813#ifdef CONFIG_PAGEFLAGS_EXTENDED
848 { head, head, MSG_HUGE, me_huge_page }, 814 { head, head, MF_MSG_HUGE, me_huge_page },
849 { tail, tail, MSG_HUGE, me_huge_page }, 815 { tail, tail, MF_MSG_HUGE, me_huge_page },
850#else 816#else
851 { compound, compound, MSG_HUGE, me_huge_page }, 817 { compound, compound, MF_MSG_HUGE, me_huge_page },
852#endif 818#endif
853 819
854 { sc|dirty, sc|dirty, MSG_DIRTY_SWAPCACHE, me_swapcache_dirty }, 820 { sc|dirty, sc|dirty, MF_MSG_DIRTY_SWAPCACHE, me_swapcache_dirty },
855 { sc|dirty, sc, MSG_CLEAN_SWAPCACHE, me_swapcache_clean }, 821 { sc|dirty, sc, MF_MSG_CLEAN_SWAPCACHE, me_swapcache_clean },
856 822
857 { mlock|dirty, mlock|dirty, MSG_DIRTY_MLOCKED_LRU, me_pagecache_dirty }, 823 { mlock|dirty, mlock|dirty, MF_MSG_DIRTY_MLOCKED_LRU, me_pagecache_dirty },
858 { mlock|dirty, mlock, MSG_CLEAN_MLOCKED_LRU, me_pagecache_clean }, 824 { mlock|dirty, mlock, MF_MSG_CLEAN_MLOCKED_LRU, me_pagecache_clean },
859 825
860 { unevict|dirty, unevict|dirty, MSG_DIRTY_UNEVICTABLE_LRU, me_pagecache_dirty }, 826 { unevict|dirty, unevict|dirty, MF_MSG_DIRTY_UNEVICTABLE_LRU, me_pagecache_dirty },
861 { unevict|dirty, unevict, MSG_CLEAN_UNEVICTABLE_LRU, me_pagecache_clean }, 827 { unevict|dirty, unevict, MF_MSG_CLEAN_UNEVICTABLE_LRU, me_pagecache_clean },
862 828
863 { lru|dirty, lru|dirty, MSG_DIRTY_LRU, me_pagecache_dirty }, 829 { lru|dirty, lru|dirty, MF_MSG_DIRTY_LRU, me_pagecache_dirty },
864 { lru|dirty, lru, MSG_CLEAN_LRU, me_pagecache_clean }, 830 { lru|dirty, lru, MF_MSG_CLEAN_LRU, me_pagecache_clean },
865 831
866 /* 832 /*
867 * Catchall entry: must be at end. 833 * Catchall entry: must be at end.
868 */ 834 */
869 { 0, 0, MSG_UNKNOWN, me_unknown }, 835 { 0, 0, MF_MSG_UNKNOWN, me_unknown },
870}; 836};
871 837
872#undef dirty 838#undef dirty
@@ -886,7 +852,7 @@ static struct page_state {
886 * "Dirty/Clean" indication is not 100% accurate due to the possibility of 852 * "Dirty/Clean" indication is not 100% accurate due to the possibility of
887 * setting PG_dirty outside page lock. See also comment above set_page_dirty(). 853 * setting PG_dirty outside page lock. See also comment above set_page_dirty().
888 */ 854 */
889static void action_result(unsigned long pfn, enum action_page_type type, int result) 855static void action_result(unsigned long pfn, enum mf_action_page_type type, int result)
890{ 856{
891 pr_err("MCE %#lx: recovery action for %s: %s\n", 857 pr_err("MCE %#lx: recovery action for %s: %s\n",
892 pfn, action_page_types[type], action_name[result]); 858 pfn, action_page_types[type], action_name[result]);
@@ -901,13 +867,13 @@ static int page_action(struct page_state *ps, struct page *p,
901 result = ps->action(p, pfn); 867 result = ps->action(p, pfn);
902 868
903 count = page_count(p) - 1; 869 count = page_count(p) - 1;
904 if (ps->action == me_swapcache_dirty && result == DELAYED) 870 if (ps->action == me_swapcache_dirty && result == MF_DELAYED)
905 count--; 871 count--;
906 if (count != 0) { 872 if (count != 0) {
907 printk(KERN_ERR 873 printk(KERN_ERR
908 "MCE %#lx: %s still referenced by %d users\n", 874 "MCE %#lx: %s still referenced by %d users\n",
909 pfn, action_page_types[ps->type], count); 875 pfn, action_page_types[ps->type], count);
910 result = FAILED; 876 result = MF_FAILED;
911 } 877 }
912 action_result(pfn, ps->type, result); 878 action_result(pfn, ps->type, result);
913 879
@@ -916,7 +882,7 @@ static int page_action(struct page_state *ps, struct page *p,
916 * Could adjust zone counters here to correct for the missing page. 882 * Could adjust zone counters here to correct for the missing page.
917 */ 883 */
918 884
919 return (result == RECOVERED || result == DELAYED) ? 0 : -EBUSY; 885 return (result == MF_RECOVERED || result == MF_DELAYED) ? 0 : -EBUSY;
920} 886}
921 887
922/** 888/**
@@ -1136,7 +1102,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1136 */ 1102 */
1137 if (!(flags & MF_COUNT_INCREASED) && !get_hwpoison_page(p)) { 1103 if (!(flags & MF_COUNT_INCREASED) && !get_hwpoison_page(p)) {
1138 if (is_free_buddy_page(p)) { 1104 if (is_free_buddy_page(p)) {
1139 action_result(pfn, MSG_BUDDY, DELAYED); 1105 action_result(pfn, MF_MSG_BUDDY, MF_DELAYED);
1140 return 0; 1106 return 0;
1141 } else if (PageHuge(hpage)) { 1107 } else if (PageHuge(hpage)) {
1142 /* 1108 /*
@@ -1153,12 +1119,12 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1153 } 1119 }
1154 set_page_hwpoison_huge_page(hpage); 1120 set_page_hwpoison_huge_page(hpage);
1155 res = dequeue_hwpoisoned_huge_page(hpage); 1121 res = dequeue_hwpoisoned_huge_page(hpage);
1156 action_result(pfn, MSG_FREE_HUGE, 1122 action_result(pfn, MF_MSG_FREE_HUGE,
1157 res ? IGNORED : DELAYED); 1123 res ? MF_IGNORED : MF_DELAYED);
1158 unlock_page(hpage); 1124 unlock_page(hpage);
1159 return res; 1125 return res;
1160 } else { 1126 } else {
1161 action_result(pfn, MSG_KERNEL_HIGH_ORDER, IGNORED); 1127 action_result(pfn, MF_MSG_KERNEL_HIGH_ORDER, MF_IGNORED);
1162 return -EBUSY; 1128 return -EBUSY;
1163 } 1129 }
1164 } 1130 }
@@ -1203,10 +1169,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1203 */ 1169 */
1204 if (is_free_buddy_page(p)) { 1170 if (is_free_buddy_page(p)) {
1205 if (flags & MF_COUNT_INCREASED) 1171 if (flags & MF_COUNT_INCREASED)
1206 action_result(pfn, MSG_BUDDY, DELAYED); 1172 action_result(pfn, MF_MSG_BUDDY, MF_DELAYED);
1207 else 1173 else
1208 action_result(pfn, MSG_BUDDY_2ND, 1174 action_result(pfn, MF_MSG_BUDDY_2ND,
1209 DELAYED); 1175 MF_DELAYED);
1210 return 0; 1176 return 0;
1211 } 1177 }
1212 } 1178 }
@@ -1219,7 +1185,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1219 * If this happens just bail out. 1185 * If this happens just bail out.
1220 */ 1186 */
1221 if (PageCompound(p) && compound_head(p) != orig_head) { 1187 if (PageCompound(p) && compound_head(p) != orig_head) {
1222 action_result(pfn, MSG_DIFFERENT_COMPOUND, IGNORED); 1188 action_result(pfn, MF_MSG_DIFFERENT_COMPOUND, MF_IGNORED);
1223 res = -EBUSY; 1189 res = -EBUSY;
1224 goto out; 1190 goto out;
1225 } 1191 }
@@ -1259,7 +1225,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1259 * on the head page to show that the hugepage is hwpoisoned 1225 * on the head page to show that the hugepage is hwpoisoned
1260 */ 1226 */
1261 if (PageHuge(p) && PageTail(p) && TestSetPageHWPoison(hpage)) { 1227 if (PageHuge(p) && PageTail(p) && TestSetPageHWPoison(hpage)) {
1262 action_result(pfn, MSG_POISONED_HUGE, IGNORED); 1228 action_result(pfn, MF_MSG_POISONED_HUGE, MF_IGNORED);
1263 unlock_page(hpage); 1229 unlock_page(hpage);
1264 put_page(hpage); 1230 put_page(hpage);
1265 return 0; 1231 return 0;
@@ -1288,7 +1254,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1288 */ 1254 */
1289 if (hwpoison_user_mappings(p, pfn, trapno, flags, &hpage) 1255 if (hwpoison_user_mappings(p, pfn, trapno, flags, &hpage)
1290 != SWAP_SUCCESS) { 1256 != SWAP_SUCCESS) {
1291 action_result(pfn, MSG_UNMAP_FAILED, IGNORED); 1257 action_result(pfn, MF_MSG_UNMAP_FAILED, MF_IGNORED);
1292 res = -EBUSY; 1258 res = -EBUSY;
1293 goto out; 1259 goto out;
1294 } 1260 }
@@ -1297,7 +1263,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1297 * Torn down by someone else? 1263 * Torn down by someone else?
1298 */ 1264 */
1299 if (PageLRU(p) && !PageSwapCache(p) && p->mapping == NULL) { 1265 if (PageLRU(p) && !PageSwapCache(p) && p->mapping == NULL) {
1300 action_result(pfn, MSG_TRUNCATED_LRU, IGNORED); 1266 action_result(pfn, MF_MSG_TRUNCATED_LRU, MF_IGNORED);
1301 res = -EBUSY; 1267 res = -EBUSY;
1302 goto out; 1268 goto out;
1303 } 1269 }