Commit 87134102 authored by Johannes Weiner's avatar Johannes Weiner Committed by Linus Torvalds

arch: mm: do not invoke OOM killer on kernel fault OOM

Kernel faults are expected to handle OOM conditions gracefully (gup,
uaccess etc.), so they should never invoke the OOM killer.  Reserve this
for faults triggered in user context when it is the only option.

Most architectures already do this, fix up the remaining few.
Signed-off-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
Reviewed-by: default avatarMichal Hocko <mhocko@suse.cz>
Acked-by: default avatarKOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: David Rientjes <rientjes@google.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: azurIt <azurit@pobox.sk>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 94bce453
...@@ -349,6 +349,13 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) ...@@ -349,6 +349,13 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
if (likely(!(fault & (VM_FAULT_ERROR | VM_FAULT_BADMAP | VM_FAULT_BADACCESS)))) if (likely(!(fault & (VM_FAULT_ERROR | VM_FAULT_BADMAP | VM_FAULT_BADACCESS))))
return 0; return 0;
/*
* If we are in kernel mode at this point, we
* have no context to handle this fault with.
*/
if (!user_mode(regs))
goto no_context;
if (fault & VM_FAULT_OOM) { if (fault & VM_FAULT_OOM) {
/* /*
* We ran out of memory, call the OOM killer, and return to * We ran out of memory, call the OOM killer, and return to
...@@ -359,13 +366,6 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) ...@@ -359,13 +366,6 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
return 0; return 0;
} }
/*
* If we are in kernel mode at this point, we
* have no context to handle this fault with.
*/
if (!user_mode(regs))
goto no_context;
if (fault & VM_FAULT_SIGBUS) { if (fault & VM_FAULT_SIGBUS) {
/* /*
* We had some memory, but were unable to * We had some memory, but were unable to
......
...@@ -288,6 +288,13 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, ...@@ -288,6 +288,13 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
VM_FAULT_BADACCESS)))) VM_FAULT_BADACCESS))))
return 0; return 0;
/*
* If we are in kernel mode at this point, we have no context to
* handle this fault with.
*/
if (!user_mode(regs))
goto no_context;
if (fault & VM_FAULT_OOM) { if (fault & VM_FAULT_OOM) {
/* /*
* We ran out of memory, call the OOM killer, and return to * We ran out of memory, call the OOM killer, and return to
...@@ -298,13 +305,6 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, ...@@ -298,13 +305,6 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
return 0; return 0;
} }
/*
* If we are in kernel mode at this point, we have no context to
* handle this fault with.
*/
if (!user_mode(regs))
goto no_context;
if (fault & VM_FAULT_SIGBUS) { if (fault & VM_FAULT_SIGBUS) {
/* /*
* We had some memory, but were unable to successfully fix up * We had some memory, but were unable to successfully fix up
......
...@@ -228,9 +228,9 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) ...@@ -228,9 +228,9 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
*/ */
out_of_memory: out_of_memory:
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
pagefault_out_of_memory();
if (!user_mode(regs)) if (!user_mode(regs))
goto no_context; goto no_context;
pagefault_out_of_memory();
return; return;
do_sigbus: do_sigbus:
......
...@@ -241,6 +241,8 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write, ...@@ -241,6 +241,8 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
* (which will retry the fault, or kill us if we got oom-killed). * (which will retry the fault, or kill us if we got oom-killed).
*/ */
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
if (!user_mode(regs))
goto no_context;
pagefault_out_of_memory(); pagefault_out_of_memory();
return; return;
......
...@@ -124,6 +124,8 @@ int handle_page_fault(unsigned long address, unsigned long ip, ...@@ -124,6 +124,8 @@ int handle_page_fault(unsigned long address, unsigned long ip,
* (which will retry the fault, or kill us if we got oom-killed). * (which will retry the fault, or kill us if we got oom-killed).
*/ */
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
if (!is_user)
goto out_nosemaphore;
pagefault_out_of_memory(); pagefault_out_of_memory();
return 0; return 0;
} }
......
...@@ -278,6 +278,13 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs) ...@@ -278,6 +278,13 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
(VM_FAULT_ERROR | VM_FAULT_BADMAP | VM_FAULT_BADACCESS)))) (VM_FAULT_ERROR | VM_FAULT_BADMAP | VM_FAULT_BADACCESS))))
return 0; return 0;
/*
* If we are in kernel mode at this point, we
* have no context to handle this fault with.
*/
if (!user_mode(regs))
goto no_context;
if (fault & VM_FAULT_OOM) { if (fault & VM_FAULT_OOM) {
/* /*
* We ran out of memory, call the OOM killer, and return to * We ran out of memory, call the OOM killer, and return to
...@@ -288,13 +295,6 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs) ...@@ -288,13 +295,6 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
return 0; return 0;
} }
/*
* If we are in kernel mode at this point, we
* have no context to handle this fault with.
*/
if (!user_mode(regs))
goto no_context;
if (fault & VM_FAULT_SIGBUS) { if (fault & VM_FAULT_SIGBUS) {
/* /*
* We had some memory, but were unable to * We had some memory, but were unable to
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment