From e0170cab2bf4e40d360d8e7cc45a65594a631667 Mon Sep 17 00:00:00 2001 From: Kautuk Consul Date: Mon, 30 Jul 2012 14:39:25 -0700 Subject: [PATCH] --- yaml --- r: 319879 b: refs/heads/master c: bf7c27e9887af48952743753916f9cfbe900d0e9 h: refs/heads/master i: 319877: dfd9fe417213173e800bf827ea3dd2a91faae19f 319875: 0dd2a1447cd6a7a857451b1c69428c1758d84751 319871: d1f6efdb5ca123a0a8c1809810b48db3eee376e6 v: v3 --- [refs] | 2 +- trunk/arch/avr32/mm/fault.c | 33 +++++++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/[refs] b/[refs] index 9222490f7f0a..4db77938aabc 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 7eafef6d1d712aa9973c3cbd0013a5b66d5a6604 +refs/heads/master: bf7c27e9887af48952743753916f9cfbe900d0e9 diff --git a/trunk/arch/avr32/mm/fault.c b/trunk/arch/avr32/mm/fault.c index f7040a1e399f..b92e60958617 100644 --- a/trunk/arch/avr32/mm/fault.c +++ b/trunk/arch/avr32/mm/fault.c @@ -61,10 +61,10 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) const struct exception_table_entry *fixup; unsigned long address; unsigned long page; - int writeaccess; long signr; int code; int fault; + unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; if (notify_page_fault(regs, ecr)) return; @@ -86,6 +86,7 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) local_irq_enable(); +retry: down_read(&mm->mmap_sem); vma = find_vma(mm, address); @@ -104,7 +105,6 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) */ good_area: code = SEGV_ACCERR; - writeaccess = 0; switch (ecr) { case ECR_PROTECTION_X: @@ -121,7 +121,7 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) case ECR_TLB_MISS_W: if (!(vma->vm_flags & VM_WRITE)) goto bad_area; - writeaccess = 1; + flags |= FAULT_FLAG_WRITE; break; default: panic("Unhandled case %lu in do_page_fault!", ecr); @@ -132,7 +132,11 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) * sure we exit gracefully rather than endlessly redo the * fault. */ - fault = handle_mm_fault(mm, vma, address, writeaccess ? 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; @@ -140,10 +144,23 @@ asmlinkage void do_page_fault(unsigned long ecr, 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;