aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory-failure.c
diff options
context:
space:
mode:
authorNaoya Horiguchi <n-horiguchi@ah.jp.nec.com>2010-05-27 20:29:18 -0400
committerAndi Kleen <ak@linux.intel.com>2010-08-11 03:22:12 -0400
commit7013febc8940960eaaba039bac0f80910f679ce1 (patch)
tree27a61a69ae8c1df5149ba9ac98cc573e8bf19b95 /mm/memory-failure.c
parent7af446a841a264a1a9675001005b29ce01d1fc57 (diff)
HWPOISON, hugetlb: set/clear PG_hwpoison bits on hugepage
To avoid race condition between concurrent memory errors on identified hugepage, we atomically test and set PG_hwpoison bit on the head page. All pages in the error hugepage are considered as hwpoisoned for now, so set and clear all PG_hwpoison bits in the hugepage with page lock of the head page held. Dependency: "HWPOISON, hugetlb: enable error handling path for hugepage" Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Cc: Andrew Morton <akpm@linux-foundation.org> Acked-by: Fengguang Wu <fengguang.wu@intel.com> Signed-off-by: Andi Kleen <ak@linux.intel.com>
Diffstat (limited to 'mm/memory-failure.c')
-rw-r--r--mm/memory-failure.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 1ec68c80788..fee648b9d39 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -920,6 +920,22 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
920 return ret; 920 return ret;
921} 921}
922 922
923static void set_page_hwpoison_huge_page(struct page *hpage)
924{
925 int i;
926 int nr_pages = 1 << compound_order(hpage);
927 for (i = 0; i < nr_pages; i++)
928 SetPageHWPoison(hpage + i);
929}
930
931static void clear_page_hwpoison_huge_page(struct page *hpage)
932{
933 int i;
934 int nr_pages = 1 << compound_order(hpage);
935 for (i = 0; i < nr_pages; i++)
936 ClearPageHWPoison(hpage + i);
937}
938
923int __memory_failure(unsigned long pfn, int trapno, int flags) 939int __memory_failure(unsigned long pfn, int trapno, int flags)
924{ 940{
925 struct page_state *ps; 941 struct page_state *ps;
@@ -1014,6 +1030,26 @@ int __memory_failure(unsigned long pfn, int trapno, int flags)
1014 return 0; 1030 return 0;
1015 } 1031 }
1016 1032
1033 /*
1034 * For error on the tail page, we should set PG_hwpoison
1035 * on the head page to show that the hugepage is hwpoisoned
1036 */
1037 if (PageTail(p) && TestSetPageHWPoison(hpage)) {
1038 action_result(pfn, "hugepage already hardware poisoned",
1039 IGNORED);
1040 unlock_page(hpage);
1041 put_page(hpage);
1042 return 0;
1043 }
1044 /*
1045 * Set PG_hwpoison on all pages in an error hugepage,
1046 * because containment is done in hugepage unit for now.
1047 * Since we have done TestSetPageHWPoison() for the head page with
1048 * page lock held, we can safely set PG_hwpoison bits on tail pages.
1049 */
1050 if (PageHuge(p))
1051 set_page_hwpoison_huge_page(hpage);
1052
1017 wait_on_page_writeback(p); 1053 wait_on_page_writeback(p);
1018 1054
1019 /* 1055 /*
@@ -1118,6 +1154,8 @@ int unpoison_memory(unsigned long pfn)
1118 atomic_long_dec(&mce_bad_pages); 1154 atomic_long_dec(&mce_bad_pages);
1119 freeit = 1; 1155 freeit = 1;
1120 } 1156 }
1157 if (PageHuge(p))
1158 clear_page_hwpoison_huge_page(page);
1121 unlock_page(page); 1159 unlock_page(page);
1122 1160
1123 put_page(page); 1161 put_page(page);