summaryrefslogtreecommitdiffstats
path: root/arch/cris/mm/fault.c
diff options
context:
space:
mode:
authorLinus Torvalds2012-05-25 17:30:35 +0200
committerLinus Torvalds2012-05-25 17:30:35 +0200
commit4b7eba49c5912cbd7c70bbebec38d8cd54c2ef85 (patch)
tree99cc41c06ade46f9925268728417c9529ce5041e /arch/cris/mm/fault.c
parentMerge tag 'mmc-merge-for-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kerne... (diff)
parentcris: Remove old legacy "-traditional" flag from arch-v10/lib/Makefile (diff)
downloadkernel-qcow2-linux-4b7eba49c5912cbd7c70bbebec38d8cd54c2ef85.tar.gz
kernel-qcow2-linux-4b7eba49c5912cbd7c70bbebec38d8cd54c2ef85.tar.xz
kernel-qcow2-linux-4b7eba49c5912cbd7c70bbebec38d8cd54c2ef85.zip
Merge tag 'cris-for-linus' of git://jni.nu/cris
Pull CRIS changes from Jesper Nilsson: "No major changes here, but fixes some compile errors for CRIS, some small style issues, some documentation and as a bonus nukes a couple of obsolete rtc-files and related code." * tag 'cris-for-linus' of git://jni.nu/cris: cris: Remove old legacy "-traditional" flag from arch-v10/lib/Makefile CRIS: Remove legacy RTC drivers cris/mm/fault.c: Port OOM changes to do_page_fault cris:fix the wrong function declear CRIS: Add _sdata to vmlinux.lds.S cris: posix_types.h, include asm-generic/posix_types.h CRIS: Update documentation cris/arch-v32: cryptocop: Use kzalloc net:removed the unused variable cris:removed the unused variable CRISv32: Correct name of read_mostly section.
Diffstat (limited to 'arch/cris/mm/fault.c')
-rw-r--r--arch/cris/mm/fault.c31
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,
struct vm_area_struct * vma;
siginfo_t info;
int fault;
+ unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
+ ((writeaccess & 1) ? FAULT_FLAG_WRITE : 0);
D(printk(KERN_DEBUG
"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,
if (in_atomic() || !mm)
goto no_context;
+retry:
down_read(&mm->mmap_sem);
vma = find_vma(mm, address);
if (!vma)
@@ -163,7 +166,11 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
* the fault.
*/
- fault = handle_mm_fault(mm, vma, address, (writeaccess & 1) ? FAULT_FLAG_WRITE : 0);
+ fault = handle_mm_fault(mm, vma, address, flags);
+
+ if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+ return;
+
if (unlikely(fault & VM_FAULT_ERROR)) {
if (fault & VM_FAULT_OOM)
goto out_of_memory;
@@ -171,10 +178,24 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
goto do_sigbus;
BUG();
}
- if (fault & VM_FAULT_MAJOR)
- tsk->maj_flt++;
- else
- tsk->min_flt++;
+
+ if (flags & FAULT_FLAG_ALLOW_RETRY) {
+ if (fault & VM_FAULT_MAJOR)
+ tsk->maj_flt++;
+ else
+ tsk->min_flt++;
+ if (fault & VM_FAULT_RETRY) {
+ flags &= ~FAULT_FLAG_ALLOW_RETRY;
+
+ /*
+ * No need to up_read(&mm->mmap_sem) as we would
+ * have already released it in __lock_page_or_retry
+ * in mm/filemap.c.
+ */
+
+ goto retry;
+ }
+ }
up_read(&mm->mmap_sem);
return;