--- arch/x86_64/mm/fault.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) --- linux-2.6.23-rc6.orig/arch/x86_64/mm/fault.c +++ linux-2.6.23-rc6/arch/x86_64/mm/fault.c @@ -310,10 +310,10 @@ asmlinkage void __kprobes do_page_fault( int write, fault; unsigned long flags; siginfo_t info; + int locked = 0; tsk = current; mm = tsk->mm; - prefetchw(&mm->mmap_sem); /* get the address */ address = read_cr2(); @@ -390,14 +390,14 @@ asmlinkage void __kprobes do_page_fault( * source. If this is invalid we can skip the address space check, * thus avoiding the deadlock. */ - if (!down_read_trylock(&mm->mmap_sem)) { - if ((error_code & PF_USER) == 0 && - !search_exception_tables(regs->rip)) - goto bad_area_nosemaphore; + + if (likely(!locked)) { + vma = __find_get_vma(mm, address, &locked); + } else { down_read(&mm->mmap_sem); + vma = find_vma(mm, address); + get_vma(vma); } - - vma = find_vma(mm, address); if (!vma) goto bad_area; if (likely(vma->vm_start <= address)) @@ -411,6 +411,11 @@ asmlinkage void __kprobes do_page_fault( if (address + 65536 + 32 * sizeof(unsigned long) < regs->rsp) goto bad_area; } + if (!locked) { + put_vma(vma); + locked = 1; + goto again; + } if (expand_stack(vma, address)) goto bad_area; /* @@ -418,6 +423,11 @@ asmlinkage void __kprobes do_page_fault( * we can handle it.. */ good_area: + if (locked) { + up_read(&mm->mmap_sem); + locked = 0; + } + info.si_code = SEGV_ACCERR; write = 0; switch (error_code & (PF_PROT|PF_WRITE)) { @@ -452,7 +462,7 @@ good_area: tsk->maj_flt++; else tsk->min_flt++; - up_read(&mm->mmap_sem); + put_vma(vma); return; /* @@ -460,7 +470,11 @@ good_area: * Fix it, but check if it's kernel or user first.. */ bad_area: - up_read(&mm->mmap_sem); + if (locked) { + up_read(&mm->mmap_sem); + locked = 0; + } + put_vma(vma); bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ @@ -552,7 +566,7 @@ no_context: * us unable to handle the page fault gracefully. */ out_of_memory: - up_read(&mm->mmap_sem); + put_vma(vma); if (is_init(current)) { yield(); goto again; @@ -563,7 +577,7 @@ out_of_memory: goto no_context; do_sigbus: - up_read(&mm->mmap_sem); + put_vma(vma); /* Kernel mode? Handle exceptions or die */ if (!(error_code & PF_USER)) -- -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: email@kvack.org