diff options
author | Kautuk Consul <consul.kautuk@gmail.com> | 2012-03-20 09:24:05 -0400 |
---|---|---|
committer | Jesper Nilsson <jespern@axis.com> | 2012-04-04 11:50:30 -0400 |
commit | 4d5914d628360c607dc426ccb1acaf23909ac546 (patch) | |
tree | 711cce67064eabd0d3347fb90ff80c55d59667ed /arch/cris/mm/fault.c | |
parent | dfb73a071f0259ba81ceea7b7f312f63dd18c73c (diff) |
cris/mm/fault.c: Port OOM changes to do_page_fault
Commit d065bd810b6deb67d4897a14bfe21f8eb526ba99
(mm: retry page fault when blocking on disk transfer) and
commit 37b23e0525d393d48a7d59f870b3bc061a30ccdb
(x86,mm: make pagefault killable)
The above commits 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 CRIS.
Signed-off-by: Kautuk Consul <consul.kautuk@gmail.com>
Signed-off-by: Jesper Nilsson <jesper.nilsson@axis.com>
Diffstat (limited to 'arch/cris/mm/fault.c')
-rw-r--r-- | arch/cris/mm/fault.c | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c index b4760d86e1bb..45fd542cf173 100644 --- a/arch/cris/mm/fault.c +++ b/arch/cris/mm/fault.c | |||
@@ -58,6 +58,8 @@ do_page_fault(unsigned long address, struct pt_regs *regs, | |||
58 | struct vm_area_struct * vma; | 58 | struct vm_area_struct * vma; |
59 | siginfo_t info; | 59 | siginfo_t info; |
60 | int fault; | 60 | int fault; |
61 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | | ||
62 | ((writeaccess & 1) ? FAULT_FLAG_WRITE : 0); | ||
61 | 63 | ||
62 | D(printk(KERN_DEBUG | 64 | D(printk(KERN_DEBUG |
63 | "Page fault for %lX on %X at %lX, prot %d write %d\n", | 65 | "Page fault for %lX on %X at %lX, prot %d write %d\n", |
@@ -115,6 +117,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs, | |||
115 | if (in_atomic() || !mm) | 117 | if (in_atomic() || !mm) |
116 | goto no_context; | 118 | goto no_context; |
117 | 119 | ||
120 | retry: | ||
118 | down_read(&mm->mmap_sem); | 121 | down_read(&mm->mmap_sem); |
119 | vma = find_vma(mm, address); | 122 | vma = find_vma(mm, address); |
120 | if (!vma) | 123 | if (!vma) |
@@ -163,7 +166,11 @@ do_page_fault(unsigned long address, struct pt_regs *regs, | |||
163 | * the fault. | 166 | * the fault. |
164 | */ | 167 | */ |
165 | 168 | ||
166 | fault = handle_mm_fault(mm, vma, address, (writeaccess & 1) ? FAULT_FLAG_WRITE : 0); | 169 | fault = handle_mm_fault(mm, vma, address, flags); |
170 | |||
171 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) | ||
172 | return; | ||
173 | |||
167 | if (unlikely(fault & VM_FAULT_ERROR)) { | 174 | if (unlikely(fault & VM_FAULT_ERROR)) { |
168 | if (fault & VM_FAULT_OOM) | 175 | if (fault & VM_FAULT_OOM) |
169 | goto out_of_memory; | 176 | goto out_of_memory; |
@@ -171,10 +178,24 @@ do_page_fault(unsigned long address, struct pt_regs *regs, | |||
171 | goto do_sigbus; | 178 | goto do_sigbus; |
172 | BUG(); | 179 | BUG(); |
173 | } | 180 | } |
174 | if (fault & VM_FAULT_MAJOR) | 181 | |
175 | tsk->maj_flt++; | 182 | if (flags & FAULT_FLAG_ALLOW_RETRY) { |
176 | else | 183 | if (fault & VM_FAULT_MAJOR) |
177 | tsk->min_flt++; | 184 | tsk->maj_flt++; |
185 | else | ||
186 | tsk->min_flt++; | ||
187 | if (fault & VM_FAULT_RETRY) { | ||
188 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | ||
189 | |||
190 | /* | ||
191 | * No need to up_read(&mm->mmap_sem) as we would | ||
192 | * have already released it in __lock_page_or_retry | ||
193 | * in mm/filemap.c. | ||
194 | */ | ||
195 | |||
196 | goto retry; | ||
197 | } | ||
198 | } | ||
178 | 199 | ||
179 | up_read(&mm->mmap_sem); | 200 | up_read(&mm->mmap_sem); |
180 | return; | 201 | return; |