diff options
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; |