@@ -173,23 +173,52 @@ int hwpoison_filter(struct page *p)
173
173
174
174
EXPORT_SYMBOL_GPL (hwpoison_filter );
175
175
176
+ /*
177
+ * Kill all processes that have a poisoned page mapped and then isolate
178
+ * the page.
179
+ *
180
+ * General strategy:
181
+ * Find all processes having the page mapped and kill them.
182
+ * But we keep a page reference around so that the page is not
183
+ * actually freed yet.
184
+ * Then stash the page away
185
+ *
186
+ * There's no convenient way to get back to mapped processes
187
+ * from the VMAs. So do a brute-force search over all
188
+ * running processes.
189
+ *
190
+ * Remember that machine checks are not common (or rather
191
+ * if they are common you have other problems), so this shouldn't
192
+ * be a performance issue.
193
+ *
194
+ * Also there are some races possible while we get from the
195
+ * error detection to actually handle it.
196
+ */
197
+
198
+ struct to_kill {
199
+ struct list_head nd ;
200
+ struct task_struct * tsk ;
201
+ unsigned long addr ;
202
+ short size_shift ;
203
+ char addr_valid ;
204
+ };
205
+
176
206
/*
177
207
* Send all the processes who have the page mapped a signal.
178
208
* ``action optional'' if they are not immediately affected by the error
179
209
* ``action required'' if error happened in current execution context
180
210
*/
181
- static int kill_proc (struct task_struct * t , unsigned long addr ,
182
- unsigned long pfn , struct page * page , int flags )
211
+ static int kill_proc (struct to_kill * tk , unsigned long pfn , int flags )
183
212
{
184
- short addr_lsb ;
213
+ struct task_struct * t = tk -> tsk ;
214
+ short addr_lsb = tk -> size_shift ;
185
215
int ret ;
186
216
187
217
pr_err ("Memory failure: %#lx: Killing %s:%d due to hardware memory corruption\n" ,
188
218
pfn , t -> comm , t -> pid );
189
- addr_lsb = compound_order (compound_head (page )) + PAGE_SHIFT ;
190
219
191
220
if ((flags & MF_ACTION_REQUIRED ) && t -> mm == current -> mm ) {
192
- ret = force_sig_mceerr (BUS_MCEERR_AR , (void __user * )addr ,
221
+ ret = force_sig_mceerr (BUS_MCEERR_AR , (void __user * )tk -> addr ,
193
222
addr_lsb , current );
194
223
} else {
195
224
/*
@@ -198,7 +227,7 @@ static int kill_proc(struct task_struct *t, unsigned long addr,
198
227
* This could cause a loop when the user sets SIGBUS
199
228
* to SIG_IGN, but hopefully no one will do that?
200
229
*/
201
- ret = send_sig_mceerr (BUS_MCEERR_AO , (void __user * )addr ,
230
+ ret = send_sig_mceerr (BUS_MCEERR_AO , (void __user * )tk -> addr ,
202
231
addr_lsb , t ); /* synchronous? */
203
232
}
204
233
if (ret < 0 )
@@ -234,35 +263,6 @@ void shake_page(struct page *p, int access)
234
263
}
235
264
EXPORT_SYMBOL_GPL (shake_page );
236
265
237
- /*
238
- * Kill all processes that have a poisoned page mapped and then isolate
239
- * the page.
240
- *
241
- * General strategy:
242
- * Find all processes having the page mapped and kill them.
243
- * But we keep a page reference around so that the page is not
244
- * actually freed yet.
245
- * Then stash the page away
246
- *
247
- * There's no convenient way to get back to mapped processes
248
- * from the VMAs. So do a brute-force search over all
249
- * running processes.
250
- *
251
- * Remember that machine checks are not common (or rather
252
- * if they are common you have other problems), so this shouldn't
253
- * be a performance issue.
254
- *
255
- * Also there are some races possible while we get from the
256
- * error detection to actually handle it.
257
- */
258
-
259
- struct to_kill {
260
- struct list_head nd ;
261
- struct task_struct * tsk ;
262
- unsigned long addr ;
263
- char addr_valid ;
264
- };
265
-
266
266
/*
267
267
* Failure handling: if we can't find or can't kill a process there's
268
268
* not much we can do. We just print a message and ignore otherwise.
@@ -292,6 +292,7 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
292
292
}
293
293
tk -> addr = page_address_in_vma (p , vma );
294
294
tk -> addr_valid = 1 ;
295
+ tk -> size_shift = compound_order (compound_head (p )) + PAGE_SHIFT ;
295
296
296
297
/*
297
298
* In theory we don't have to kill when the page was
@@ -317,9 +318,8 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
317
318
* Also when FAIL is set do a force kill because something went
318
319
* wrong earlier.
319
320
*/
320
- static void kill_procs (struct list_head * to_kill , int forcekill ,
321
- bool fail , struct page * page , unsigned long pfn ,
322
- int flags )
321
+ static void kill_procs (struct list_head * to_kill , int forcekill , bool fail ,
322
+ unsigned long pfn , int flags )
323
323
{
324
324
struct to_kill * tk , * next ;
325
325
@@ -342,8 +342,7 @@ static void kill_procs(struct list_head *to_kill, int forcekill,
342
342
* check for that, but we need to tell the
343
343
* process anyways.
344
344
*/
345
- else if (kill_proc (tk -> tsk , tk -> addr ,
346
- pfn , page , flags ) < 0 )
345
+ else if (kill_proc (tk , pfn , flags ) < 0 )
347
346
pr_err ("Memory failure: %#lx: Cannot send advisory machine check signal to %s:%d\n" ,
348
347
pfn , tk -> tsk -> comm , tk -> tsk -> pid );
349
348
}
@@ -1012,7 +1011,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
1012
1011
* any accesses to the poisoned memory.
1013
1012
*/
1014
1013
forcekill = PageDirty (hpage ) || (flags & MF_MUST_KILL );
1015
- kill_procs (& tokill , forcekill , !unmap_success , p , pfn , flags );
1014
+ kill_procs (& tokill , forcekill , !unmap_success , pfn , flags );
1016
1015
1017
1016
return unmap_success ;
1018
1017
}
0 commit comments