aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/mm/fault_32.c
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/fault_32.c
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/fault_32.c')
-rw-r--r--arch/sparc/mm/fault_32.c12
1 files changed, 9 insertions, 3 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;