Commit 14c02e41 authored by Laurent Dufour's avatar Laurent Dufour Committed by Michael Ellerman

powerpc/mm: Handle VM_FAULT_RETRY earlier

In do_page_fault() if handle_mm_fault() returns VM_FAULT_RETRY, retry
the page fault handling before anything else.

This would simplify the handling of the mmap_sem lock in this part of
the code.
Reviewed-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: default avatarLaurent Dufour <ldufour@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent c2294e0f
...@@ -458,6 +458,26 @@ int do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -458,6 +458,26 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
* the fault. * the fault.
*/ */
fault = handle_mm_fault(vma, address, flags); fault = handle_mm_fault(vma, address, flags);
/*
* Handle the retry right now, the mmap_sem has been released in that
* case.
*/
if (unlikely(fault & VM_FAULT_RETRY)) {
/* We retry only once */
if (flags & FAULT_FLAG_ALLOW_RETRY) {
/*
* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
* of starvation.
*/
flags &= ~FAULT_FLAG_ALLOW_RETRY;
flags |= FAULT_FLAG_TRIED;
if (!fatal_signal_pending(current))
goto retry;
}
/* We will enter mm_fault_error() below */
}
if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) { if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) {
if (fault & VM_FAULT_SIGSEGV) if (fault & VM_FAULT_SIGSEGV)
goto bad_area; goto bad_area;
...@@ -469,11 +489,8 @@ int do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -469,11 +489,8 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
} }
/* /*
* Major/minor page fault accounting is only done on the * Major/minor page fault accounting.
* initial attempt. If we go through a retry, it is extremely
* likely that the page will be found in page cache at that point.
*/ */
if (flags & FAULT_FLAG_ALLOW_RETRY) {
if (fault & VM_FAULT_MAJOR) { if (fault & VM_FAULT_MAJOR) {
current->maj_flt++; current->maj_flt++;
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
...@@ -494,14 +511,6 @@ int do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -494,14 +511,6 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
regs, address); regs, address);
} }
if (fault & VM_FAULT_RETRY) {
/* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
* of starvation. */
flags &= ~FAULT_FLAG_ALLOW_RETRY;
flags |= FAULT_FLAG_TRIED;
goto retry;
}
}
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
goto bail; goto bail;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment