microblaze: Port OOM changes to do_page_fault
authorKautuk Consul <consul.kautuk@gmail.com>
Tue, 20 Mar 2012 13:21:40 +0000 (09:21 -0400)
committerMichal Simek <monstr@monstr.eu>
Fri, 25 May 2012 04:34:34 +0000 (06:34 +0200)
Commit d065bd810b6deb67d4897a14bfe21f8eb526ba99
(mm: retry page fault when blocking on disk transfer) and
commit 37b23e0525d393d48a7d59f870b3bc061a30ccdb
(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 microblaze.

Signed-off-by: Kautuk Consul <consul.kautuk@gmail.com>
arch/microblaze/mm/fault.c

index c38a265846dec68c427398834e9833ceced31753..eb365d6795fa80448fbe4fe391b8b3211c0f4156 100644 (file)
@@ -92,6 +92,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
        int code = SEGV_MAPERR;
        int is_write = error_code & ESR_S;
        int fault;
+       unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
+                                        (is_write ? FAULT_FLAG_WRITE : 0);
 
        regs->ear = address;
        regs->esr = error_code;
@@ -138,6 +140,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
                if (kernel_mode(regs) && !search_exception_tables(regs->pc))
                        goto bad_area_nosemaphore;
 
+retry:
                down_read(&mm->mmap_sem);
        }
 
@@ -210,7 +213,11 @@ good_area:
         * make sure we exit gracefully rather than endlessly redo
         * the fault.
         */
-       fault = handle_mm_fault(mm, vma, address, is_write ? 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;
@@ -218,11 +225,27 @@ good_area:
                        goto do_sigbus;
                BUG();
        }
-       if (unlikely(fault & VM_FAULT_MAJOR))
-               current->maj_flt++;
-       else
-               current->min_flt++;
+
+       if (flags & FAULT_FLAG_ALLOW_RETRY) {
+               if (unlikely(fault & VM_FAULT_MAJOR))
+                       current->maj_flt++;
+               else
+                       current->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);
+
        /*
         * keep track of tlb+htab misses that are good addrs but
         * just need pte's created via handle_mm_fault()