aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/mm
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2013-09-12 18:13:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-12 18:38:01 -0400
commit759496ba6407c6994d6a5ce3a5e74937d7816208 (patch)
treeaeff8de8af36f70f2591114cef58c9ae7df25565 /arch/sparc/mm
parent871341023c771ad233620b7a1fb3d9c7031c4e5c (diff)
arch: mm: pass userspace fault flag to generic fault handler
Unlike global OOM handling, memory cgroup code will invoke the OOM killer in any OOM situation because it has no way of telling faults occuring in kernel context - which could be handled more gracefully - from user-triggered faults. Pass a flag that identifies faults originating in user space from the architecture-specific fault handlers to generic code so that memcg OOM handling can be improved. Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Reviewed-by: Michal Hocko <mhocko@suse.cz> Cc: David Rientjes <rientjes@google.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: azurIt <azurit@pobox.sk> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/sparc/mm')
-rw-r--r--arch/sparc/mm/fault_32.c12
-rw-r--r--arch/sparc/mm/fault_64.c6
2 files changed, 13 insertions, 5 deletions
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index e98bfda205a2..59dbd4645725 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -177,8 +177,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
177 unsigned long g2; 177 unsigned long g2;
178 int from_user = !(regs->psr & PSR_PS); 178 int from_user = !(regs->psr & PSR_PS);
179 int fault, code; 179 int fault, code;
180 unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | 180 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
181 (write ? FAULT_FLAG_WRITE : 0));
182 181
183 if (text_fault) 182 if (text_fault)
184 address = regs->pc; 183 address = regs->pc;
@@ -235,6 +234,11 @@ good_area:
235 goto bad_area; 234 goto bad_area;
236 } 235 }
237 236
237 if (from_user)
238 flags |= FAULT_FLAG_USER;
239 if (write)
240 flags |= FAULT_FLAG_WRITE;
241
238 /* 242 /*
239 * If for any reason at all we couldn't handle the fault, 243 * If for any reason at all we couldn't handle the fault,
240 * make sure we exit gracefully rather than endlessly redo 244 * make sure we exit gracefully rather than endlessly redo
@@ -383,6 +387,7 @@ static void force_user_fault(unsigned long address, int write)
383 struct vm_area_struct *vma; 387 struct vm_area_struct *vma;
384 struct task_struct *tsk = current; 388 struct task_struct *tsk = current;
385 struct mm_struct *mm = tsk->mm; 389 struct mm_struct *mm = tsk->mm;
390 unsigned int flags = FAULT_FLAG_USER;
386 int code; 391 int code;
387 392
388 code = SEGV_MAPERR; 393 code = SEGV_MAPERR;
@@ -402,11 +407,12 @@ good_area:
402 if (write) { 407 if (write) {
403 if (!(vma->vm_flags & VM_WRITE)) 408 if (!(vma->vm_flags & VM_WRITE))
404 goto bad_area; 409 goto bad_area;
410 flags |= FAULT_FLAG_WRITE;
405 } else { 411 } else {
406 if (!(vma->vm_flags & (VM_READ | VM_EXEC))) 412 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
407 goto bad_area; 413 goto bad_area;
408 } 414 }
409 switch (handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0)) { 415 switch (handle_mm_fault(mm, vma, address, flags)) {
410 case VM_FAULT_SIGBUS: 416 case VM_FAULT_SIGBUS:
411 case VM_FAULT_OOM: 417 case VM_FAULT_OOM:
412 goto do_sigbus; 418 goto do_sigbus;
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index 5062ff389e83..2ebec263d685 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -315,7 +315,8 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
315 bad_kernel_pc(regs, address); 315 bad_kernel_pc(regs, address);
316 return; 316 return;
317 } 317 }
318 } 318 } else
319 flags |= FAULT_FLAG_USER;
319 320
320 /* 321 /*
321 * If we're in an interrupt or have no user 322 * If we're in an interrupt or have no user
@@ -418,13 +419,14 @@ good_area:
418 vma->vm_file != NULL) 419 vma->vm_file != NULL)
419 set_thread_fault_code(fault_code | 420 set_thread_fault_code(fault_code |
420 FAULT_CODE_BLKCOMMIT); 421 FAULT_CODE_BLKCOMMIT);
422
423 flags |= FAULT_FLAG_WRITE;
421 } else { 424 } else {
422 /* Allow reads even for write-only mappings */ 425 /* Allow reads even for write-only mappings */
423 if (!(vma->vm_flags & (VM_READ | VM_EXEC))) 426 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
424 goto bad_area; 427 goto bad_area;
425 } 428 }
426 429
427 flags |= ((fault_code & FAULT_CODE_WRITE) ? FAULT_FLAG_WRITE : 0);
428 fault = handle_mm_fault(mm, vma, address, flags); 430 fault = handle_mm_fault(mm, vma, address, flags);
429 431
430 if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) 432 if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))