@@ -1009,6 +1009,76 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
10091009 return unmap_success ;
10101010}
10111011
1012+ static int memory_failure_hugetlb (unsigned long pfn , int trapno , int flags )
1013+ {
1014+ struct page_state * ps ;
1015+ struct page * p = pfn_to_page (pfn );
1016+ struct page * head = compound_head (p );
1017+ int res ;
1018+ unsigned long page_flags ;
1019+
1020+ if (TestSetPageHWPoison (head )) {
1021+ pr_err ("Memory failure: %#lx: already hardware poisoned\n" ,
1022+ pfn );
1023+ return 0 ;
1024+ }
1025+
1026+ num_poisoned_pages_inc ();
1027+
1028+ if (!(flags & MF_COUNT_INCREASED ) && !get_hwpoison_page (p )) {
1029+ /*
1030+ * Check "filter hit" and "race with other subpage."
1031+ */
1032+ lock_page (head );
1033+ if (PageHWPoison (head )) {
1034+ if ((hwpoison_filter (p ) && TestClearPageHWPoison (p ))
1035+ || (p != head && TestSetPageHWPoison (head ))) {
1036+ num_poisoned_pages_dec ();
1037+ unlock_page (head );
1038+ return 0 ;
1039+ }
1040+ }
1041+ unlock_page (head );
1042+ dissolve_free_huge_page (p );
1043+ action_result (pfn , MF_MSG_FREE_HUGE , MF_DELAYED );
1044+ return 0 ;
1045+ }
1046+
1047+ lock_page (head );
1048+ page_flags = head -> flags ;
1049+
1050+ if (!PageHWPoison (head )) {
1051+ pr_err ("Memory failure: %#lx: just unpoisoned\n" , pfn );
1052+ num_poisoned_pages_dec ();
1053+ unlock_page (head );
1054+ put_hwpoison_page (head );
1055+ return 0 ;
1056+ }
1057+
1058+ if (!hwpoison_user_mappings (p , pfn , trapno , flags , & head )) {
1059+ action_result (pfn , MF_MSG_UNMAP_FAILED , MF_IGNORED );
1060+ res = - EBUSY ;
1061+ goto out ;
1062+ }
1063+
1064+ res = - EBUSY ;
1065+
1066+ for (ps = error_states ;; ps ++ )
1067+ if ((p -> flags & ps -> mask ) == ps -> res )
1068+ break ;
1069+
1070+ page_flags |= (p -> flags & (1UL << PG_dirty ));
1071+
1072+ if (!ps -> mask )
1073+ for (ps = error_states ;; ps ++ )
1074+ if ((page_flags & ps -> mask ) == ps -> res )
1075+ break ;
1076+ res = page_action (ps , p , pfn );
1077+ out :
1078+ unlock_page (head );
1079+ return res ;
1080+ }
1081+
10121082/**
10131083 * memory_failure - Handle memory failure of a page.
10141084 * @pfn: Page Number of the corrupted page
@@ -1046,33 +1116,22 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
10461116 }
10471117
10481118 p = pfn_to_page (pfn );
1049- orig_head = hpage = compound_head (p );
1050-
1051- /* tmporary check code, to be updated in later patches */
1052- if (PageHuge (p )) {
1053- if (TestSetPageHWPoison (hpage )) {
1054- pr_err ("Memory failure: %#lx: already hardware poisoned\n" , pfn );
1055- return 0 ;
1056- }
1057- goto tmp ;
1058- }
1119+ if (PageHuge (p ))
1120+ return memory_failure_hugetlb (pfn , trapno , flags );
10591121 if (TestSetPageHWPoison (p )) {
10601122 pr_err ("Memory failure: %#lx: already hardware poisoned\n" ,
10611123 pfn );
10621124 return 0 ;
10631125 }
10641126
1065- tmp :
1127+ orig_head = hpage = compound_head ( p );
10661128 num_poisoned_pages_inc ();
10671129
10681130 /*
10691131 * We need/can do nothing about count=0 pages.
10701132 * 1) it's a free page, and therefore in safe hand:
10711133 * prep_new_page() will be the gate keeper.
1072- * 2) it's a free hugepage, which is also safe:
1073- * an affected hugepage will be dequeued from hugepage freelist,
1074- * so there's no concern about reusing it ever after.
1075- * 3) it's part of a non-compound high order page.
1134+ * 2) it's part of a non-compound high order page.
10761135 * Implies some kernel user: cannot stop them from
10771136 * R/W the page; let's pray that the page has been
10781137 * used and will be freed some time later.
@@ -1083,31 +1142,13 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
10831142 if (is_free_buddy_page (p )) {
10841143 action_result (pfn , MF_MSG_BUDDY , MF_DELAYED );
10851144 return 0 ;
1086- } else if (PageHuge (hpage )) {
1087- /*
1088- * Check "filter hit" and "race with other subpage."
1089- */
1090- lock_page (hpage );
1091- if (PageHWPoison (hpage )) {
1092- if ((hwpoison_filter (p ) && TestClearPageHWPoison (p ))
1093- || (p != hpage && TestSetPageHWPoison (hpage ))) {
1094- num_poisoned_pages_dec ();
1095- unlock_page (hpage );
1096- return 0 ;
1097- }
1098- }
1099- res = dequeue_hwpoisoned_huge_page (hpage );
1100- action_result (pfn , MF_MSG_FREE_HUGE ,
1101- res ? MF_IGNORED : MF_DELAYED );
1102- unlock_page (hpage );
1103- return res ;
11041145 } else {
11051146 action_result (pfn , MF_MSG_KERNEL_HIGH_ORDER , MF_IGNORED );
11061147 return - EBUSY ;
11071148 }
11081149 }
11091150
1110- if (! PageHuge ( p ) && PageTransHuge (hpage )) {
1151+ if (PageTransHuge (hpage )) {
11111152 lock_page (p );
11121153 if (!PageAnon (p ) || unlikely (split_huge_page (p ))) {
11131154 unlock_page (p );
@@ -1145,7 +1186,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
11451186 return 0 ;
11461187 }
11471188
1148- lock_page (hpage );
1189+ lock_page (p );
11491190
11501191 /*
11511192 * The page could have changed compound pages during the locking.
@@ -1175,32 +1216,21 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
11751216 if (!PageHWPoison (p )) {
11761217 pr_err ("Memory failure: %#lx: just unpoisoned\n" , pfn );
11771218 num_poisoned_pages_dec ();
1178- unlock_page (hpage );
1179- put_hwpoison_page (hpage );
1219+ unlock_page (p );
1220+ put_hwpoison_page (p );
11801221 return 0 ;
11811222 }
11821223 if (hwpoison_filter (p )) {
11831224 if (TestClearPageHWPoison (p ))
11841225 num_poisoned_pages_dec ();
1185- unlock_page (hpage );
1186- put_hwpoison_page (hpage );
1226+ unlock_page (p );
1227+ put_hwpoison_page (p );
11871228 return 0 ;
11881229 }
11891230
1190- if (!PageHuge ( p ) && ! PageTransTail (p ) && !PageLRU (p ))
1231+ if (!PageTransTail (p ) && !PageLRU (p ))
11911232 goto identify_page_state ;
11921233
1193- /*
1194- * For error on the tail page, we should set PG_hwpoison
1195- * on the head page to show that the hugepage is hwpoisoned
1196- */
1197- if (PageHuge (p ) && PageTail (p ) && TestSetPageHWPoison (hpage )) {
1198- action_result (pfn , MF_MSG_POISONED_HUGE , MF_IGNORED );
1199- unlock_page (hpage );
1200- put_hwpoison_page (hpage );
1201- return 0 ;
1202- }
1203-
12041234 /*
12051235 * It's very difficult to mess with pages currently under IO
12061236 * and in many cases impossible, so we just avoid it here.
@@ -1248,7 +1278,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
12481278 break ;
12491279 res = page_action (ps , p , pfn );
12501280out :
1251- unlock_page (hpage );
1281+ unlock_page (p );
12521282 return res ;
12531283}
12541284EXPORT_SYMBOL_GPL (memory_failure );
0 commit comments