Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mm/memory-failure.c: don't let collect_procs() skip over processes for MF_ACTION_REQUIRED

When Linux sees an "action optional" machine check (where h/w has reported
an error that is not in the current execution path) we generally do not
want to signal a process, since most processes do not have a SIGBUS
handler - we'd just prematurely terminate the process for a problem that
they might never actually see.

task_early_kill() decides whether to consider a process - and it checks
whether this specific process has been marked for early signals with
"prctl", or if the system administrator has requested early signals for
all processes using /proc/sys/vm/memory_failure_early_kill.

But for MF_ACTION_REQUIRED case we must not defer. The error is in the
execution path of the current thread so we must send the SIGBUS
immediatley.

Fix by passing a flag argument through collect_procs*() to
task_early_kill() so it knows whether we can defer or must take action.

Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Borislav Petkov <bp@suse.de>
Cc: Chen Gong <gong.chen@linux.jf.intel.com>
Cc: <stable@vger.kernel.org> [3.2+]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Tony Luck and committed by
Linus Torvalds
74614de1 a70ffcac

+12 -9
+12 -9
mm/memory-failure.c
··· 380 380 } 381 381 } 382 382 383 - static int task_early_kill(struct task_struct *tsk) 383 + static int task_early_kill(struct task_struct *tsk, int force_early) 384 384 { 385 385 if (!tsk->mm) 386 386 return 0; 387 + if (force_early) 388 + return 1; 387 389 if (tsk->flags & PF_MCE_PROCESS) 388 390 return !!(tsk->flags & PF_MCE_EARLY); 389 391 return sysctl_memory_failure_early_kill; ··· 395 393 * Collect processes when the error hit an anonymous page. 396 394 */ 397 395 static void collect_procs_anon(struct page *page, struct list_head *to_kill, 398 - struct to_kill **tkc) 396 + struct to_kill **tkc, int force_early) 399 397 { 400 398 struct vm_area_struct *vma; 401 399 struct task_struct *tsk; ··· 411 409 for_each_process (tsk) { 412 410 struct anon_vma_chain *vmac; 413 411 414 - if (!task_early_kill(tsk)) 412 + if (!task_early_kill(tsk, force_early)) 415 413 continue; 416 414 anon_vma_interval_tree_foreach(vmac, &av->rb_root, 417 415 pgoff, pgoff) { ··· 430 428 * Collect processes when the error hit a file mapped page. 431 429 */ 432 430 static void collect_procs_file(struct page *page, struct list_head *to_kill, 433 - struct to_kill **tkc) 431 + struct to_kill **tkc, int force_early) 434 432 { 435 433 struct vm_area_struct *vma; 436 434 struct task_struct *tsk; ··· 441 439 for_each_process(tsk) { 442 440 pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); 443 441 444 - if (!task_early_kill(tsk)) 442 + if (!task_early_kill(tsk, force_early)) 445 443 continue; 446 444 447 445 vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, ··· 467 465 * First preallocate one tokill structure outside the spin locks, 468 466 * so that we can kill at least one process reasonably reliable. 469 467 */ 470 - static void collect_procs(struct page *page, struct list_head *tokill) 468 + static void collect_procs(struct page *page, struct list_head *tokill, 469 + int force_early) 471 470 { 472 471 struct to_kill *tk; 473 472 ··· 479 476 if (!tk) 480 477 return; 481 478 if (PageAnon(page)) 482 - collect_procs_anon(page, tokill, &tk); 479 + collect_procs_anon(page, tokill, &tk, force_early); 483 480 else 484 - collect_procs_file(page, tokill, &tk); 481 + collect_procs_file(page, tokill, &tk, force_early); 485 482 kfree(tk); 486 483 } 487 484 ··· 966 963 * there's nothing that can be done. 967 964 */ 968 965 if (kill) 969 - collect_procs(ppage, &tokill); 966 + collect_procs(ppage, &tokill, flags & MF_ACTION_REQUIRED); 970 967 971 968 ret = try_to_unmap(ppage, ttu); 972 969 if (ret != SWAP_SUCCESS)