@@ -1009,6 +1009,76 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
1009
1009
return unmap_success ;
1010
1010
}
1011
1011
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
+
1012
1082
/**
1013
1083
* memory_failure - Handle memory failure of a page.
1014
1084
* @pfn: Page Number of the corrupted page
@@ -1046,33 +1116,22 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1046
1116
}
1047
1117
1048
1118
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 );
1059
1121
if (TestSetPageHWPoison (p )) {
1060
1122
pr_err ("Memory failure: %#lx: already hardware poisoned\n" ,
1061
1123
pfn );
1062
1124
return 0 ;
1063
1125
}
1064
1126
1065
- tmp :
1127
+ orig_head = hpage = compound_head ( p );
1066
1128
num_poisoned_pages_inc ();
1067
1129
1068
1130
/*
1069
1131
* We need/can do nothing about count=0 pages.
1070
1132
* 1) it's a free page, and therefore in safe hand:
1071
1133
* 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.
1076
1135
* Implies some kernel user: cannot stop them from
1077
1136
* R/W the page; let's pray that the page has been
1078
1137
* used and will be freed some time later.
@@ -1083,31 +1142,13 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1083
1142
if (is_free_buddy_page (p )) {
1084
1143
action_result (pfn , MF_MSG_BUDDY , MF_DELAYED );
1085
1144
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 ;
1104
1145
} else {
1105
1146
action_result (pfn , MF_MSG_KERNEL_HIGH_ORDER , MF_IGNORED );
1106
1147
return - EBUSY ;
1107
1148
}
1108
1149
}
1109
1150
1110
- if (! PageHuge ( p ) && PageTransHuge (hpage )) {
1151
+ if (PageTransHuge (hpage )) {
1111
1152
lock_page (p );
1112
1153
if (!PageAnon (p ) || unlikely (split_huge_page (p ))) {
1113
1154
unlock_page (p );
@@ -1145,7 +1186,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1145
1186
return 0 ;
1146
1187
}
1147
1188
1148
- lock_page (hpage );
1189
+ lock_page (p );
1149
1190
1150
1191
/*
1151
1192
* The page could have changed compound pages during the locking.
@@ -1175,32 +1216,21 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1175
1216
if (!PageHWPoison (p )) {
1176
1217
pr_err ("Memory failure: %#lx: just unpoisoned\n" , pfn );
1177
1218
num_poisoned_pages_dec ();
1178
- unlock_page (hpage );
1179
- put_hwpoison_page (hpage );
1219
+ unlock_page (p );
1220
+ put_hwpoison_page (p );
1180
1221
return 0 ;
1181
1222
}
1182
1223
if (hwpoison_filter (p )) {
1183
1224
if (TestClearPageHWPoison (p ))
1184
1225
num_poisoned_pages_dec ();
1185
- unlock_page (hpage );
1186
- put_hwpoison_page (hpage );
1226
+ unlock_page (p );
1227
+ put_hwpoison_page (p );
1187
1228
return 0 ;
1188
1229
}
1189
1230
1190
- if (!PageHuge ( p ) && ! PageTransTail (p ) && !PageLRU (p ))
1231
+ if (!PageTransTail (p ) && !PageLRU (p ))
1191
1232
goto identify_page_state ;
1192
1233
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
-
1204
1234
/*
1205
1235
* It's very difficult to mess with pages currently under IO
1206
1236
* 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)
1248
1278
break ;
1249
1279
res = page_action (ps , p , pfn );
1250
1280
out :
1251
- unlock_page (hpage );
1281
+ unlock_page (p );
1252
1282
return res ;
1253
1283
}
1254
1284
EXPORT_SYMBOL_GPL (memory_failure );
0 commit comments