Skip to content

Commit

Permalink
m68k/mm: Port OOM changes to do_page_fault()
Browse files Browse the repository at this point in the history
Commit d065bd8
(mm: retry page fault when blocking on disk transfer) and
commit 37b23e0
(x86,mm: make pagefault killable)

The above commits introduced changes into the x86 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.

Port these changes to m68k.

Signed-off-by: Kautuk Consul <consul.kautuk@gmail.com>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
  • Loading branch information
Kautuk Consul authored and Geert Uytterhoeven committed Apr 22, 2012
1 parent 107b5d5 commit b637a6b
Showing 1 changed file with 34 additions and 8 deletions.
42 changes: 34 additions & 8 deletions arch/m68k/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
{
struct mm_struct *mm = current->mm;
struct vm_area_struct * vma;
int write, fault;
int fault;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;

#ifdef DEBUG
printk ("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
Expand All @@ -87,6 +88,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
if (in_atomic() || !mm)
goto no_context;

retry:
down_read(&mm->mmap_sem);

vma = find_vma(mm, address);
Expand Down Expand Up @@ -117,14 +119,13 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
#ifdef DEBUG
printk("do_page_fault: good_area\n");
#endif
write = 0;
switch (error_code & 3) {
default: /* 3: write, present */
/* fall through */
case 2: /* write, not present */
if (!(vma->vm_flags & VM_WRITE))
goto acc_err;
write++;
flags |= FAULT_FLAG_WRITE;
break;
case 1: /* read, present */
goto acc_err;
Expand All @@ -139,21 +140,46 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
* the fault.
*/

fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
fault = handle_mm_fault(mm, vma, address, flags);
#ifdef DEBUG
printk("handle_mm_fault returns %d\n",fault);
#endif

if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
return 0;

if (unlikely(fault & VM_FAULT_ERROR)) {
if (fault & VM_FAULT_OOM)
goto out_of_memory;
else if (fault & VM_FAULT_SIGBUS)
goto bus_err;
BUG();
}
if (fault & VM_FAULT_MAJOR)
current->maj_flt++;
else
current->min_flt++;

/*
* Major/minor page fault accounting is only done on the
* 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;

/*
* 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 0;
Expand Down

0 comments on commit b637a6b

Please sign in to comment.