Commit 96f3a5cc authored by Ley Foon Tan's avatar Ley Foon Tan

nios2: Port OOM changes to do_page_fault()

Commit d065bd81 ("mm: retry page fault when blocking on disk transfer") and
and commit 37b23e05 ("x86,mm: make pagefault killable")

The above commits introduced changes into the nios2 pagefault handler
for making the page fault handler retryable as well as killable.

These changes reduce the mmap_sem hold time, which is crucial
during OOM killer invocation.
Signed-off-by: default avatarLey Foon Tan <lftan@altera.com>
parent ad7ef26d
...@@ -47,7 +47,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause, ...@@ -47,7 +47,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause,
struct mm_struct *mm = tsk->mm; struct mm_struct *mm = tsk->mm;
int code = SEGV_MAPERR; int code = SEGV_MAPERR;
int fault; int fault;
unsigned int flags = 0; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
cause >>= 2; cause >>= 2;
...@@ -86,6 +86,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause, ...@@ -86,6 +86,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause,
if (!down_read_trylock(&mm->mmap_sem)) { if (!down_read_trylock(&mm->mmap_sem)) {
if (!user_mode(regs) && !search_exception_tables(regs->ea)) if (!user_mode(regs) && !search_exception_tables(regs->ea))
goto bad_area_nosemaphore; goto bad_area_nosemaphore;
retry:
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem);
} }
...@@ -132,6 +133,10 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause, ...@@ -132,6 +133,10 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause,
* the fault. * the fault.
*/ */
fault = handle_mm_fault(mm, vma, address, flags); 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 (unlikely(fault & VM_FAULT_ERROR)) {
if (fault & VM_FAULT_OOM) if (fault & VM_FAULT_OOM)
goto out_of_memory; goto out_of_memory;
...@@ -141,10 +146,32 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause, ...@@ -141,10 +146,32 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause,
goto do_sigbus; goto do_sigbus;
BUG(); BUG();
} }
if (fault & VM_FAULT_MAJOR)
tsk->maj_flt++; /*
else * Major/minor page fault accounting is only done on the
tsk->min_flt++; * 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)
current->maj_flt++;
else
current->min_flt++;
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;
/*
* 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); up_read(&mm->mmap_sem);
return; return;
......
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