diff options
author | Kautuk Consul <consul.kautuk@gmail.com> | 2012-08-18 22:41:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-08-19 11:41:19 -0400 |
commit | 0bcc426b1defa6b629dfa722537cab38876a3ce4 (patch) | |
tree | e545cca77bcafdf9071e0eb7647051e391f4436b /arch | |
parent | 28d353d9891c28496e366bebe4e65233f59ad1f6 (diff) |
alpha/mm/fault.c: Port OOM changes to do_page_fault
Commit d065bd810b6d ("mm: retry page fault when blocking on disk
transfer") and 37b23e0525d3 ("x86,mm: make pagefault killable")
introduced changes into the x86 pagefault handler for making the page
fault handler retryable as well as killable.
These changes reduce the mmap_sem hold time, which is crucial during OOM
killer invocation.
Port these changes to ALPHA.
Signed-off-by: Mohd. Faris <mohdfarisq2010@gmail.com>
Signed-off-by: Kautuk Consul <consul.kautuk@gmail.com>
Acked-by: Matt Turner <mattst88@gmail.com>
Signed-off-by: Michael Cree <mcree@orcon.net.nz>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/alpha/mm/fault.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c index 5eecab1a84ef..0c4132dd3507 100644 --- a/arch/alpha/mm/fault.c +++ b/arch/alpha/mm/fault.c | |||
@@ -89,6 +89,8 @@ do_page_fault(unsigned long address, unsigned long mmcsr, | |||
89 | const struct exception_table_entry *fixup; | 89 | const struct exception_table_entry *fixup; |
90 | int fault, si_code = SEGV_MAPERR; | 90 | int fault, si_code = SEGV_MAPERR; |
91 | siginfo_t info; | 91 | siginfo_t info; |
92 | unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | | ||
93 | (cause > 0 ? FAULT_FLAG_WRITE : 0)); | ||
92 | 94 | ||
93 | /* As of EV6, a load into $31/$f31 is a prefetch, and never faults | 95 | /* As of EV6, a load into $31/$f31 is a prefetch, and never faults |
94 | (or is suppressed by the PALcode). Support that for older CPUs | 96 | (or is suppressed by the PALcode). Support that for older CPUs |
@@ -114,6 +116,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, | |||
114 | goto vmalloc_fault; | 116 | goto vmalloc_fault; |
115 | #endif | 117 | #endif |
116 | 118 | ||
119 | retry: | ||
117 | down_read(&mm->mmap_sem); | 120 | down_read(&mm->mmap_sem); |
118 | vma = find_vma(mm, address); | 121 | vma = find_vma(mm, address); |
119 | if (!vma) | 122 | if (!vma) |
@@ -144,8 +147,11 @@ do_page_fault(unsigned long address, unsigned long mmcsr, | |||
144 | /* If for any reason at all we couldn't handle the fault, | 147 | /* If for any reason at all we couldn't handle the fault, |
145 | make sure we exit gracefully rather than endlessly redo | 148 | make sure we exit gracefully rather than endlessly redo |
146 | the fault. */ | 149 | the fault. */ |
147 | fault = handle_mm_fault(mm, vma, address, cause > 0 ? FAULT_FLAG_WRITE : 0); | 150 | fault = handle_mm_fault(mm, vma, address, flags); |
148 | up_read(&mm->mmap_sem); | 151 | |
152 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) | ||
153 | return; | ||
154 | |||
149 | if (unlikely(fault & VM_FAULT_ERROR)) { | 155 | if (unlikely(fault & VM_FAULT_ERROR)) { |
150 | if (fault & VM_FAULT_OOM) | 156 | if (fault & VM_FAULT_OOM) |
151 | goto out_of_memory; | 157 | goto out_of_memory; |
@@ -153,10 +159,26 @@ do_page_fault(unsigned long address, unsigned long mmcsr, | |||
153 | goto do_sigbus; | 159 | goto do_sigbus; |
154 | BUG(); | 160 | BUG(); |
155 | } | 161 | } |
156 | if (fault & VM_FAULT_MAJOR) | 162 | |
157 | current->maj_flt++; | 163 | if (flags & FAULT_FLAG_ALLOW_RETRY) { |
158 | else | 164 | if (fault & VM_FAULT_MAJOR) |
159 | current->min_flt++; | 165 | current->maj_flt++; |
166 | else | ||
167 | current->min_flt++; | ||
168 | if (fault & VM_FAULT_RETRY) { | ||
169 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | ||
170 | |||
171 | /* No need to up_read(&mm->mmap_sem) as we would | ||
172 | * have already released it in __lock_page_or_retry | ||
173 | * in mm/filemap.c. | ||
174 | */ | ||
175 | |||
176 | goto retry; | ||
177 | } | ||
178 | } | ||
179 | |||
180 | up_read(&mm->mmap_sem); | ||
181 | |||
160 | return; | 182 | return; |
161 | 183 | ||
162 | /* Something tried to access memory that isn't in our memory map. | 184 | /* Something tried to access memory that isn't in our memory map. |
@@ -186,12 +208,14 @@ do_page_fault(unsigned long address, unsigned long mmcsr, | |||
186 | /* We ran out of memory, or some other thing happened to us that | 208 | /* We ran out of memory, or some other thing happened to us that |
187 | made us unable to handle the page fault gracefully. */ | 209 | made us unable to handle the page fault gracefully. */ |
188 | out_of_memory: | 210 | out_of_memory: |
211 | up_read(&mm->mmap_sem); | ||
189 | if (!user_mode(regs)) | 212 | if (!user_mode(regs)) |
190 | goto no_context; | 213 | goto no_context; |
191 | pagefault_out_of_memory(); | 214 | pagefault_out_of_memory(); |
192 | return; | 215 | return; |
193 | 216 | ||
194 | do_sigbus: | 217 | do_sigbus: |
218 | up_read(&mm->mmap_sem); | ||
195 | /* Send a sigbus, regardless of whether we were in kernel | 219 | /* Send a sigbus, regardless of whether we were in kernel |
196 | or user mode. */ | 220 | or user mode. */ |
197 | info.si_signo = SIGBUS; | 221 | info.si_signo = SIGBUS; |