aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m32r/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/m32r/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/m32r/mm')
-rw-r--r--arch/m32r/mm/fault.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c
index 3cdfa9c1d091..e9c6a8014bd6 100644
--- a/arch/m32r/mm/fault.c
+++ b/arch/m32r/mm/fault.c
@@ -78,7 +78,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
78 struct mm_struct *mm; 78 struct mm_struct *mm;
79 struct vm_area_struct * vma; 79 struct vm_area_struct * vma;
80 unsigned long page, addr; 80 unsigned long page, addr;
81 int write; 81 unsigned long flags = 0;
82 int fault; 82 int fault;
83 siginfo_t info; 83 siginfo_t info;
84 84
@@ -117,6 +117,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
117 if (in_atomic() || !mm) 117 if (in_atomic() || !mm)
118 goto bad_area_nosemaphore; 118 goto bad_area_nosemaphore;
119 119
120 if (error_code & ACE_USERMODE)
121 flags |= FAULT_FLAG_USER;
122
120 /* When running in the kernel we expect faults to occur only to 123 /* When running in the kernel we expect faults to occur only to
121 * addresses in user space. All other faults represent errors in the 124 * addresses in user space. All other faults represent errors in the
122 * kernel and should generate an OOPS. Unfortunately, in the case of an 125 * kernel and should generate an OOPS. Unfortunately, in the case of an
@@ -166,14 +169,13 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
166 */ 169 */
167good_area: 170good_area:
168 info.si_code = SEGV_ACCERR; 171 info.si_code = SEGV_ACCERR;
169 write = 0;
170 switch (error_code & (ACE_WRITE|ACE_PROTECTION)) { 172 switch (error_code & (ACE_WRITE|ACE_PROTECTION)) {
171 default: /* 3: write, present */ 173 default: /* 3: write, present */
172 /* fall through */ 174 /* fall through */
173 case ACE_WRITE: /* write, not present */ 175 case ACE_WRITE: /* write, not present */
174 if (!(vma->vm_flags & VM_WRITE)) 176 if (!(vma->vm_flags & VM_WRITE))
175 goto bad_area; 177 goto bad_area;
176 write++; 178 flags |= FAULT_FLAG_WRITE;
177 break; 179 break;
178 case ACE_PROTECTION: /* read, present */ 180 case ACE_PROTECTION: /* read, present */
179 case 0: /* read, not present */ 181 case 0: /* read, not present */
@@ -194,7 +196,7 @@ good_area:
194 */ 196 */
195 addr = (address & PAGE_MASK); 197 addr = (address & PAGE_MASK);
196 set_thread_fault_code(error_code); 198 set_thread_fault_code(error_code);
197 fault = handle_mm_fault(mm, vma, addr, write ? FAULT_FLAG_WRITE : 0); 199 fault = handle_mm_fault(mm, vma, addr, flags);
198 if (unlikely(fault & VM_FAULT_ERROR)) { 200 if (unlikely(fault & VM_FAULT_ERROR)) {
199 if (fault & VM_FAULT_OOM) 201 if (fault & VM_FAULT_OOM)
200 goto out_of_memory; 202 goto out_of_memory;