diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2011-05-26 03:48:29 -0400 |
---|---|---|
committer | Heiko Carstens <heiko.carstens@de.ibm.com> | 2011-05-26 03:48:25 -0400 |
commit | 99583181cbf2252dd0554eef6f419a6b22cd33ea (patch) | |
tree | bb8ff8673b3415318236a6efe0a8c5081ef32815 /arch/s390 | |
parent | b396637841fff79e9520514e8dcbe769c20a2ea0 (diff) |
[S390] mm: handle kernel caused page fault oom situations
If e.g. copy_from_user() generates a page fault and the kernel runs
into an OOM situation the system might lock up.
If the OOM killer sends a SIG_KILL to the current process it can't
handle it since it is stuck in a copy_from_user() - page fault loop.
Fix this by adding the same fix as other architectures have.
E.g. the x86 variant f86268 "x86/mm: Handle mm_fault_error() in kernel
space"
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/mm/fault.c | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 105fa107143..b57723aee84 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -245,9 +245,12 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code, | |||
245 | do_no_context(regs, int_code, trans_exc_code); | 245 | do_no_context(regs, int_code, trans_exc_code); |
246 | break; | 246 | break; |
247 | default: /* fault & VM_FAULT_ERROR */ | 247 | default: /* fault & VM_FAULT_ERROR */ |
248 | if (fault & VM_FAULT_OOM) | 248 | if (fault & VM_FAULT_OOM) { |
249 | pagefault_out_of_memory(); | 249 | if (!(regs->psw.mask & PSW_MASK_PSTATE)) |
250 | else if (fault & VM_FAULT_SIGBUS) { | 250 | do_no_context(regs, int_code, trans_exc_code); |
251 | else | ||
252 | pagefault_out_of_memory(); | ||
253 | } else if (fault & VM_FAULT_SIGBUS) { | ||
251 | /* Kernel mode? Handle exceptions or die */ | 254 | /* Kernel mode? Handle exceptions or die */ |
252 | if (!(regs->psw.mask & PSW_MASK_PSTATE)) | 255 | if (!(regs->psw.mask & PSW_MASK_PSTATE)) |
253 | do_no_context(regs, int_code, trans_exc_code); | 256 | do_no_context(regs, int_code, trans_exc_code); |
@@ -429,10 +432,9 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write) | |||
429 | access = write ? VM_WRITE : VM_READ; | 432 | access = write ? VM_WRITE : VM_READ; |
430 | fault = do_exception(®s, access, uaddr | 2); | 433 | fault = do_exception(®s, access, uaddr | 2); |
431 | if (unlikely(fault)) { | 434 | if (unlikely(fault)) { |
432 | if (fault & VM_FAULT_OOM) { | 435 | if (fault & VM_FAULT_OOM) |
433 | pagefault_out_of_memory(); | 436 | return -EFAULT; |
434 | fault = 0; | 437 | else if (fault & VM_FAULT_SIGBUS) |
435 | } else if (fault & VM_FAULT_SIGBUS) | ||
436 | do_sigbus(®s, pgm_int_code, uaddr); | 438 | do_sigbus(®s, pgm_int_code, uaddr); |
437 | } | 439 | } |
438 | return fault ? -EFAULT : 0; | 440 | return fault ? -EFAULT : 0; |