the fault.  */
        fault = handle_mm_fault(mm, vma, address, cause > 0);
        up_read(&mm->mmap_sem);
-
-       switch (fault) {
-             case VM_FAULT_MINOR:
-               current->min_flt++;
-               break;
-             case VM_FAULT_MAJOR:
-               current->maj_flt++;
-               break;
-             case VM_FAULT_SIGBUS:
-               goto do_sigbus;
-             case VM_FAULT_OOM:
-               goto out_of_memory;
-             default:
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
                BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               current->maj_flt++;
+       else
+               current->min_flt++;
        return;
 
        /* Something tried to access memory that isn't in our memory map.
 
         */
 survive:
        fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, fsr & (1 << 11));
-
-       /*
-        * Handle the "normal" cases first - successful and sigbus
-        */
-       switch (fault) {
-       case VM_FAULT_MAJOR:
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       return fault;
+               BUG();
+       }
+       if (fault & VM_FAULT_MAJOR)
                tsk->maj_flt++;
-               return fault;
-       case VM_FAULT_MINOR:
+       else
                tsk->min_flt++;
-       case VM_FAULT_SIGBUS:
-               return fault;
-       }
+       return fault;
 
+out_of_memory:
        if (!is_init(tsk))
                goto out;
 
        /*
         * Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR
         */
-       if (fault >= VM_FAULT_MINOR)
+       if (likely(!(fault & VM_FAULT_ERROR)))
                return 0;
 
        /*
        if (!user_mode(regs))
                goto no_context;
 
-       switch (fault) {
-       case VM_FAULT_OOM:
+       if (fault & VM_FAULT_OOM) {
                /*
                 * We ran out of memory, or some other thing
                 * happened to us that made us unable to handle
                printk("VM: killing process %s\n", tsk->comm);
                do_exit(SIGKILL);
                return 0;
-
-       case VM_FAULT_SIGBUS:
+       }
+       if (fault & VM_FAULT_SIGBUS) {
                /*
                 * We had some memory, but were unable to
                 * successfully fix up this page fault.
                 */
                sig = SIGBUS;
                code = BUS_ADRERR;
-               break;
-
-       default:
+       } else {
                /*
                 * Something tried to access memory that
                 * isn't in our memory map..
                sig = SIGSEGV;
                code = fault == VM_FAULT_BADACCESS ?
                        SEGV_ACCERR : SEGV_MAPERR;
-               break;
        }
 
        __do_user_fault(tsk, addr, fsr, sig, code, regs);
 
         */
 survive:
        fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(fsr));
-
-       /*
-        * Handle the "normal" cases first - successful and sigbus
-        */
-       switch (fault) {
-       case VM_FAULT_MAJOR:
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       return fault;
+               BUG();
+       }
+       if (fault & VM_FAULT_MAJOR)
                tsk->maj_flt++;
-               return fault;
-       case VM_FAULT_MINOR:
+       else
                tsk->min_flt++;
-       case VM_FAULT_SIGBUS:
-               return fault;
-       }
+       return fault;
 
+out_of_memory:
        fault = -3; /* out of memory */
        if (!is_init(tsk))
                goto out;
        /*
         * Handle the "normal" case first
         */
-       switch (fault) {
-       case VM_FAULT_MINOR:
-       case VM_FAULT_MAJOR:
+       if (likely(!(fault & VM_FAULT_ERROR)))
                return 0;
-       case VM_FAULT_SIGBUS:
+       if (fault & VM_FAULT_SIGBUS)
                goto do_sigbus;
-       }
+       /* else VM_FAULT_OOM */
 
        /*
         * If we are in kernel mode at this point, we
 
        int writeaccess;
        long signr;
        int code;
+       int fault;
 
        if (notify_page_fault(regs, ecr))
                return;
         * fault.
         */
 survive:
-       switch (handle_mm_fault(mm, vma, address, writeaccess)) {
-       case VM_FAULT_MINOR:
-               tsk->min_flt++;
-               break;
-       case VM_FAULT_MAJOR:
-               tsk->maj_flt++;
-               break;
-       case VM_FAULT_SIGBUS:
-               goto do_sigbus;
-       case VM_FAULT_OOM:
-               goto out_of_memory;
-       default:
+       fault = handle_mm_fault(mm, vma, address, writeaccess);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
                BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               tsk->maj_flt++;
+       else
+               tsk->min_flt++;
 
        up_read(&mm->mmap_sem);
        return;
 
        struct mm_struct *mm;
        struct vm_area_struct * vma;
        siginfo_t info;
+       int fault;
 
         D(printk("Page fault for %lX on %X at %lX, prot %d write %d\n",
                  address, smp_processor_id(), instruction_pointer(regs),
         * the fault.
         */
 
-       switch (handle_mm_fault(mm, vma, address, writeaccess & 1)) {
-       case VM_FAULT_MINOR:
-               tsk->min_flt++;
-               break;
-       case VM_FAULT_MAJOR:
-               tsk->maj_flt++;
-               break;
-       case VM_FAULT_SIGBUS:
-               goto do_sigbus;
-       default:
-               goto out_of_memory;
+       fault = handle_mm_fault(mm, vma, address, writeaccess & 1);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
+               BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               tsk->maj_flt++;
+       else
+               tsk->min_flt++;
 
        up_read(&mm->mmap_sem);
        return;
 
        pud_t *pue;
        pte_t *pte;
        int write;
+       int fault;
 
 #if 0
        const char *atxc[16] = {
         * make sure we exit gracefully rather than endlessly redo
         * the fault.
         */
-       switch (handle_mm_fault(mm, vma, ear0, write)) {
-       case VM_FAULT_MINOR:
-               current->min_flt++;
-               break;
-       case VM_FAULT_MAJOR:
-               current->maj_flt++;
-               break;
-       case VM_FAULT_SIGBUS:
-               goto do_sigbus;
-       default:
-               goto out_of_memory;
+       fault = handle_mm_fault(mm, vma, ear0, write);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
+               BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               current->maj_flt++;
+       else
+               current->min_flt++;
 
        up_read(&mm->mmap_sem);
        return;
 
        struct vm_area_struct * vma;
        unsigned long address;
        int write, si_code;
+       int fault;
 
        /* get the address */
         address = read_cr2();
         * make sure we exit gracefully rather than endlessly redo
         * the fault.
         */
-       switch (handle_mm_fault(mm, vma, address, write)) {
-               case VM_FAULT_MINOR:
-                       tsk->min_flt++;
-                       break;
-               case VM_FAULT_MAJOR:
-                       tsk->maj_flt++;
-                       break;
-               case VM_FAULT_SIGBUS:
-                       goto do_sigbus;
-               case VM_FAULT_OOM:
+       fault = handle_mm_fault(mm, vma, address, write);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
-               default:
-                       BUG();
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
+               BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               tsk->maj_flt++;
+       else
+               tsk->min_flt++;
 
        /*
         * Did it hit the DOS screen memory VA from vm86 mode?
 
        struct mm_struct *mm = current->mm;
        struct siginfo si;
        unsigned long mask;
+       int fault;
 
        /* mmap_sem is performance critical.... */
        prefetchw(&mm->mmap_sem);
         * sure we exit gracefully rather than endlessly redo the
         * fault.
         */
-       switch (handle_mm_fault(mm, vma, address, (mask & VM_WRITE) != 0)) {
-             case VM_FAULT_MINOR:
-               ++current->min_flt;
-               break;
-             case VM_FAULT_MAJOR:
-               ++current->maj_flt;
-               break;
-             case VM_FAULT_SIGBUS:
+       fault = handle_mm_fault(mm, vma, address, (mask & VM_WRITE) != 0);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
                /*
                 * We ran out of memory, or some other thing happened
                 * to us that made us unable to handle the page fault
                 * gracefully.
                 */
-               signal = SIGBUS;
-               goto bad_area;
-             case VM_FAULT_OOM:
-               goto out_of_memory;
-             default:
+               if (fault & VM_FAULT_OOM) {
+                       goto out_of_memory;
+               } else if (fault & VM_FAULT_SIGBUS) {
+                       signal = SIGBUS;
+                       goto bad_area;
+               }
                BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               current->maj_flt++;
+       else
+               current->min_flt++;
        up_read(&mm->mmap_sem);
        return;
 
 
        struct vm_area_struct * vma;
        unsigned long page, addr;
        int write;
+       int fault;
        siginfo_t info;
 
        /*
         */
        addr = (address & PAGE_MASK);
        set_thread_fault_code(error_code);
-       switch (handle_mm_fault(mm, vma, addr, write)) {
-               case VM_FAULT_MINOR:
-                       tsk->min_flt++;
-                       break;
-               case VM_FAULT_MAJOR:
-                       tsk->maj_flt++;
-                       break;
-               case VM_FAULT_SIGBUS:
-                       goto do_sigbus;
-               case VM_FAULT_OOM:
+       fault = handle_mm_fault(mm, vma, addr, write);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
-               default:
-                       BUG();
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
+               BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               tsk->maj_flt++;
+       else
+               tsk->min_flt++;
        set_thread_fault_code(0);
        up_read(&mm->mmap_sem);
        return;
 
 #ifdef DEBUG
        printk("handle_mm_fault returns %d\n",fault);
 #endif
-       switch (fault) {
-       case VM_FAULT_MINOR:
-               current->min_flt++;
-               break;
-       case VM_FAULT_MAJOR:
-               current->maj_flt++;
-               break;
-       case VM_FAULT_SIGBUS:
-               goto bus_err;
-       default:
-               goto out_of_memory;
+       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++;
 
        up_read(&mm->mmap_sem);
        return 0;
 
        struct mm_struct *mm = tsk->mm;
        const int field = sizeof(unsigned long) * 2;
        siginfo_t info;
+       int fault;
 
 #if 0
        printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", raw_smp_processor_id(),
         * make sure we exit gracefully rather than endlessly redo
         * the fault.
         */
-       switch (handle_mm_fault(mm, vma, address, write)) {
-       case VM_FAULT_MINOR:
-               tsk->min_flt++;
-               break;
-       case VM_FAULT_MAJOR:
-               tsk->maj_flt++;
-               break;
-       case VM_FAULT_SIGBUS:
-               goto do_sigbus;
-       case VM_FAULT_OOM:
-               goto out_of_memory;
-       default:
+       fault = handle_mm_fault(mm, vma, address, write);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
                BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               tsk->maj_flt++;
+       else
+               tsk->min_flt++;
 
        up_read(&mm->mmap_sem);
        return;
 
        struct mm_struct *mm = tsk->mm;
        const struct exception_table_entry *fix;
        unsigned long acc_type;
+       int fault;
 
        if (in_atomic() || !mm)
                goto no_context;
         * fault.
         */
 
-       switch (handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) != 0)) {
-             case VM_FAULT_MINOR:
-               ++current->min_flt;
-               break;
-             case VM_FAULT_MAJOR:
-               ++current->maj_flt;
-               break;
-             case VM_FAULT_SIGBUS:
+       fault = handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) != 0);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
                /*
                 * We hit a shared mapping outside of the file, or some
                 * other thing happened to us that made us unable to
                 * handle the page fault gracefully.
                 */
-               goto bad_area;
-             default:
-               goto out_of_memory;
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto bad_area;
+               BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               current->maj_flt++;
+       else
+               current->min_flt++;
        up_read(&mm->mmap_sem);
        return;
 
 
        struct mm_struct *mm = current->mm;
        siginfo_t info;
        int code = SEGV_MAPERR;
-       int is_write = 0;
+       int is_write = 0, ret;
        int trap = TRAP(regs);
        int is_exec = trap == 0x400;
 
         * the fault.
         */
  survive:
-       switch (handle_mm_fault(mm, vma, address, is_write)) {
-
-       case VM_FAULT_MINOR:
-               current->min_flt++;
-               break;
-       case VM_FAULT_MAJOR:
-               current->maj_flt++;
-               break;
-       case VM_FAULT_SIGBUS:
-               goto do_sigbus;
-       case VM_FAULT_OOM:
-               goto out_of_memory;
-       default:
+       ret = handle_mm_fault(mm, vma, address, is_write);
+       if (unlikely(ret & VM_FAULT_ERROR)) {
+               if (ret & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (ret & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
                BUG();
        }
-
+       if (ret & VM_FAULT_MAJOR)
+               current->maj_flt++;
+       else
+               current->min_flt++;
        up_read(&mm->mmap_sem);
        return 0;
 
 
                        goto bad_area;
        }
        ret = 0;
-       *flt = handle_mm_fault(mm, vma, ea, is_write);
-       switch (*flt) {
-       case VM_FAULT_MINOR:
-               current->min_flt++;
-               break;
-       case VM_FAULT_MAJOR:
-               current->maj_flt++;
-               break;
-       case VM_FAULT_SIGBUS:
-               ret = -EFAULT;
-               goto bad_area;
-       case VM_FAULT_OOM:
-               ret = -ENOMEM;
-               goto bad_area;
-       default:
+       fault = handle_mm_fault(mm, vma, ea, is_write);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM) {
+                       ret = -ENOMEM;
+                       goto bad_area;
+               } else if (fault & VM_FAULT_SIGBUS) {
+                       ret = -EFAULT;
+                       goto bad_area;
+               }
                BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               current->maj_flt++;
+       else
+               current->min_flt++;
        up_read(&mm->mmap_sem);
        return ret;
 
 
        struct mm_struct *mm = current->mm;
        siginfo_t info;
        int code = SEGV_MAPERR;
+       int fault;
 #if defined(CONFIG_4xx) || defined (CONFIG_BOOKE)
        int is_write = error_code & ESR_DST;
 #else
         * the fault.
         */
  survive:
-        switch (handle_mm_fault(mm, vma, address, is_write)) {
-        case VM_FAULT_MINOR:
-                current->min_flt++;
-                break;
-        case VM_FAULT_MAJOR:
-                current->maj_flt++;
-                break;
-        case VM_FAULT_SIGBUS:
-                goto do_sigbus;
-        case VM_FAULT_OOM:
-                goto out_of_memory;
-       default:
+       fault = handle_mm_fault(mm, vma, address, is_write);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
                BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               current->maj_flt++;
+       else
+               current->min_flt++;
 
        up_read(&mm->mmap_sem);
        /*
 
 {
        struct vm_area_struct *vma;
        int ret = -EFAULT;
+       int fault;
 
        if (in_atomic())
                return ret;
        }
 
 survive:
-       switch (handle_mm_fault(mm, vma, address, write_access)) {
-       case VM_FAULT_MINOR:
-               current->min_flt++;
-               break;
-       case VM_FAULT_MAJOR:
-               current->maj_flt++;
-               break;
-       case VM_FAULT_SIGBUS:
-               goto out_sigbus;
-       case VM_FAULT_OOM:
-               goto out_of_memory;
-       default:
+       fault = handle_mm_fault(mm, vma, address, write_access);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto out_sigbus;
                BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               current->maj_flt++;
+       else
+               current->min_flt++;
        ret = 0;
 out:
        up_read(&mm->mmap_sem);
 
        unsigned long address;
        int space;
        int si_code;
+       int fault;
 
        if (notify_page_fault(regs, error_code))
                return;
         * make sure we exit gracefully rather than endlessly redo
         * the fault.
         */
-       switch (handle_mm_fault(mm, vma, address, write)) {
-       case VM_FAULT_MINOR:
-               tsk->min_flt++;
-               break;
-       case VM_FAULT_MAJOR:
-               tsk->maj_flt++;
-               break;
-       case VM_FAULT_SIGBUS:
-               do_sigbus(regs, error_code, address);
-               return;
-       case VM_FAULT_OOM:
-               if (do_out_of_memory(regs, error_code, address))
-                       goto survive;
-               return;
-       default:
+       fault = handle_mm_fault(mm, vma, address, write);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM) {
+                       if (do_out_of_memory(regs, error_code, address))
+                               goto survive;
+                       return;
+               } else if (fault & VM_FAULT_SIGBUS) {
+                       do_sigbus(regs, error_code, address);
+                       return;
+               }
                BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               tsk->maj_flt++;
+       else
+               tsk->min_flt++;
 
         up_read(&mm->mmap_sem);
        /*
 
        struct mm_struct *mm;
        struct vm_area_struct * vma;
        int si_code;
+       int fault;
        siginfo_t info;
 
        trace_hardirqs_on();
         * the fault.
         */
 survive:
-       switch (handle_mm_fault(mm, vma, address, writeaccess)) {
-               case VM_FAULT_MINOR:
-                       tsk->min_flt++;
-                       break;
-               case VM_FAULT_MAJOR:
-                       tsk->maj_flt++;
-                       break;
-               case VM_FAULT_SIGBUS:
-                       goto do_sigbus;
-               case VM_FAULT_OOM:
+       fault = handle_mm_fault(mm, vma, address, writeaccess);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
-               default:
-                       BUG();
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
+               BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               tsk->maj_flt++;
+       else
+               tsk->min_flt++;
 
        up_read(&mm->mmap_sem);
        return;
 
        struct vm_area_struct * vma;
        const struct exception_table_entry *fixup;
        pte_t *pte;
+       int fault;
 
 #if defined(CONFIG_SH64_PROC_TLB)
         ++calls_to_do_slow_page_fault;
         * the fault.
         */
 survive:
-       switch (handle_mm_fault(mm, vma, address, writeaccess)) {
-       case VM_FAULT_MINOR:
-               tsk->min_flt++;
-               break;
-       case VM_FAULT_MAJOR:
-               tsk->maj_flt++;
-               break;
-       case VM_FAULT_SIGBUS:
-               goto do_sigbus;
-       default:
-               goto out_of_memory;
+       fault = handle_mm_fault(mm, vma, address, writeaccess);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
+               BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               tsk->maj_flt++;
+       else
+               tsk->min_flt++;
+
        /* If we get here, the page fault has been handled.  Do the TLB refill
           now from the newly-setup PTE, to avoid having to fault again right
           away on the same instruction. */
 
        unsigned long g2;
        siginfo_t info;
        int from_user = !(regs->psr & PSR_PS);
+       int fault;
 
        if(text_fault)
                address = regs->pc;
         * make sure we exit gracefully rather than endlessly redo
         * the fault.
         */
-       switch (handle_mm_fault(mm, vma, address, write)) {
-       case VM_FAULT_SIGBUS:
-               goto do_sigbus;
-       case VM_FAULT_OOM:
-               goto out_of_memory;
-       case VM_FAULT_MAJOR:
+       fault = handle_mm_fault(mm, vma, address, write);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
+               BUG();
+       }
+       if (fault & VM_FAULT_MAJOR)
                current->maj_flt++;
-               break;
-       case VM_FAULT_MINOR:
-       default:
+       else
                current->min_flt++;
-               break;
-       }
        up_read(&mm->mmap_sem);
        return;
 
 
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
        unsigned int insn = 0;
-       int si_code, fault_code;
+       int si_code, fault_code, fault;
        unsigned long address, mm_rss;
 
        fault_code = get_thread_fault_code();
                        goto bad_area;
        }
 
-       switch (handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE))) {
-       case VM_FAULT_MINOR:
-               current->min_flt++;
-               break;
-       case VM_FAULT_MAJOR:
-               current->maj_flt++;
-               break;
-       case VM_FAULT_SIGBUS:
-               goto do_sigbus;
-       case VM_FAULT_OOM:
-               goto out_of_memory;
-       default:
+       fault = handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE));
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
                BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               current->maj_flt++;
+       else
+               current->min_flt++;
 
        up_read(&mm->mmap_sem);
 
 
                goto out;
 
        do {
+               int fault;
 survive:
-               switch (handle_mm_fault(mm, vma, address, is_write)){
-               case VM_FAULT_MINOR:
-                       current->min_flt++;
-                       break;
-               case VM_FAULT_MAJOR:
-                       current->maj_flt++;
-                       break;
-               case VM_FAULT_SIGBUS:
-                       err = -EACCES;
-                       goto out;
-               case VM_FAULT_OOM:
-                       err = -ENOMEM;
-                       goto out_of_memory;
-               default:
+               fault = handle_mm_fault(mm, vma, address, is_write);
+               if (unlikely(fault & VM_FAULT_ERROR)) {
+                       if (fault & VM_FAULT_OOM) {
+                               err = -ENOMEM;
+                               goto out_of_memory;
+                       } else if (fault & VM_FAULT_SIGBUS) {
+                               err = -EACCES;
+                               goto out;
+                       }
                        BUG();
                }
+               if (fault & VM_FAULT_MAJOR)
+                       current->maj_flt++;
+               else
+                       current->min_flt++;
+
                pgd = pgd_offset(mm, address);
                pud = pud_offset(pgd, address);
                pmd = pmd_offset(pud, address);
 
        struct vm_area_struct * vma;
        unsigned long address;
        const struct exception_table_entry *fixup;
-       int write;
+       int write, fault;
        unsigned long flags;
        siginfo_t info;
 
         * make sure we exit gracefully rather than endlessly redo
         * the fault.
         */
-       switch (handle_mm_fault(mm, vma, address, write)) {
-       case VM_FAULT_MINOR:
-               tsk->min_flt++;
-               break;
-       case VM_FAULT_MAJOR:
-               tsk->maj_flt++;
-               break;
-       case VM_FAULT_SIGBUS:
-               goto do_sigbus;
-       default:
-               goto out_of_memory;
+       fault = handle_mm_fault(mm, vma, address, write);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
+               BUG();
        }
-
+       if (fault & VM_FAULT_MAJOR)
+               tsk->maj_flt++;
+       else
+               tsk->min_flt++;
        up_read(&mm->mmap_sem);
        return;
 
 
        siginfo_t info;
 
        int is_write, is_exec;
+       int fault;
 
        info.si_code = SEGV_MAPERR;
 
         * the fault.
         */
 survive:
-       switch (handle_mm_fault(mm, vma, address, is_write)) {
-       case VM_FAULT_MINOR:
-               current->min_flt++;
-               break;
-       case VM_FAULT_MAJOR:
-               current->maj_flt++;
-               break;
-       case VM_FAULT_SIGBUS:
-               goto do_sigbus;
-       case VM_FAULT_OOM:
-               goto out_of_memory;
-       default:
+       fault = handle_mm_fault(mm, vma, address, is_write);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
                BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               current->maj_flt++;
+       else
+               current->min_flt++;
 
        up_read(&mm->mmap_sem);
        return;
 
        struct gfs2_holder i_gh;
        int alloc_required;
        int error;
-       int ret = VM_FAULT_MINOR;
+       int ret = 0;
 
        error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
        if (error)
        set_bit(GFF_EXLOCK, &gf->f_flags);
        ret = filemap_fault(vma, vmf);
        clear_bit(GFF_EXLOCK, &gf->f_flags);
-       if (ret & (VM_FAULT_ERROR | FAULT_RET_NOPAGE))
+       if (ret & VM_FAULT_ERROR)
                goto out_unlock;
 
        if (alloc_required) {
                /* XXX: do we need to drop page lock around alloc_page_backing?*/
                error = alloc_page_backing(ip, vmf->page);
                if (error) {
-                       if (ret & FAULT_RET_LOCKED)
+                       /*
+                        * VM_FAULT_LOCKED should always be the case for
+                        * filemap_fault, but it may not be in a future
+                        * implementation.
+                        */
+                       if (ret & VM_FAULT_LOCKED)
                                unlock_page(vmf->page);
                        page_cache_release(vmf->page);
                        ret = VM_FAULT_OOM;
 
 #define FAULT_FLAG_NONLINEAR   0x02    /* Fault was via a nonlinear mapping */
 
 
-#define FAULT_RET_NOPAGE       0x0100  /* ->fault did not return a page. This
-                                        * can be used if the handler installs
-                                        * their own pte.
-                                        */
-#define FAULT_RET_LOCKED       0x0200  /* ->fault locked the page, caller must
-                                        * unlock after installing the mapping.
-                                        * This is used by pagecache in
-                                        * particular, where the page lock is
-                                        * used to synchronise against truncate
-                                        * and invalidate. Mutually exclusive
-                                        * with FAULT_RET_NOPAGE.
-                                        */
-
 /*
  * vm_fault is filled by the the pagefault handler and passed to the vma's
- * ->fault function. The vma's ->fault is responsible for returning the
- * VM_FAULT_xxx type which occupies the lowest byte of the return code, ORed
- * with FAULT_RET_ flags that occupy the next byte and give details about
- * how the fault was handled.
+ * ->fault function. The vma's ->fault is responsible for returning a bitmask
+ * of VM_FAULT_xxx flags that give details about how the fault was handled.
  *
  * pgoff should be used in favour of virtual_address, if possible. If pgoff
  * is used, one may set VM_CAN_NONLINEAR in the vma->vm_flags to get nonlinear
        void __user *virtual_address;   /* Faulting virtual address */
 
        struct page *page;              /* ->fault handlers should return a
-                                        * page here, unless FAULT_RET_NOPAGE
+                                        * page here, unless VM_FAULT_NOPAGE
                                         * is set (which is also implied by
-                                        * VM_FAULT_OOM or SIGBUS).
+                                        * VM_FAULT_ERROR).
                                         */
 };
 
  * just gets major/minor fault counters bumped up.
  */
 
-/*
- * VM_FAULT_ERROR is set for the error cases, to make some tests simpler.
- */
-#define VM_FAULT_ERROR 0x20
+#define VM_FAULT_MINOR 0 /* For backwards compat. Remove me quickly. */
 
-#define VM_FAULT_OOM   (0x00 | VM_FAULT_ERROR)
-#define VM_FAULT_SIGBUS        (0x01 | VM_FAULT_ERROR)
-#define VM_FAULT_MINOR 0x02
-#define VM_FAULT_MAJOR 0x03
+#define VM_FAULT_OOM   0x0001
+#define VM_FAULT_SIGBUS        0x0002
+#define VM_FAULT_MAJOR 0x0004
+#define VM_FAULT_WRITE 0x0008  /* Special case for get_user_pages */
 
-/* 
- * Special case for get_user_pages.
- * Must be in a distinct bit from the above VM_FAULT_ flags.
- */
-#define VM_FAULT_WRITE 0x10
+#define VM_FAULT_NOPAGE        0x0100  /* ->fault installed the pte, not return page */
+#define VM_FAULT_LOCKED        0x0200  /* ->fault locked the returned page */
 
-/*
- * Mask of VM_FAULT_ flags
- */
-#define VM_FAULT_MASK  0xff
+#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS)
 
 #define offset_in_page(p)      ((unsigned long)(p) & ~PAGE_MASK)
 
 extern int vmtruncate_range(struct inode * inode, loff_t offset, loff_t end);
 
 #ifdef CONFIG_MMU
-extern int __handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma,
+extern int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                        unsigned long address, int write_access);
-
-static inline int handle_mm_fault(struct mm_struct *mm,
-                       struct vm_area_struct *vma, unsigned long address,
-                       int write_access)
-{
-       return __handle_mm_fault(mm, vma, address, write_access) &
-                               (~VM_FAULT_WRITE);
-}
 #else
 static inline int handle_mm_fault(struct mm_struct *mm,
                        struct vm_area_struct *vma, unsigned long address,
 
        vma = find_vma(mm, address);
        if (vma && address >= vma->vm_start &&
            (vma->vm_flags & VM_WRITE)) {
-               switch (handle_mm_fault(mm, vma, address, 1)) {
-               case VM_FAULT_MINOR:
-                       ret = 0;
-                       current->min_flt++;
-                       break;
-               case VM_FAULT_MAJOR:
+               int fault;
+               fault = handle_mm_fault(mm, vma, address, 1);
+               if (unlikely((fault & VM_FAULT_ERROR))) {
+#if 0
+                       /* XXX: let's do this when we verify it is OK */
+                       if (ret & VM_FAULT_OOM)
+                               ret = -ENOMEM;
+#endif
+               } else {
                        ret = 0;
-                       current->maj_flt++;
-                       break;
+                       if (fault & VM_FAULT_MAJOR)
+                               current->maj_flt++;
+                       else
+                               current->min_flt++;
                }
        }
        if (!fshared)
 
        struct page *page;
        unsigned long size;
        int did_readaround = 0;
-       int ret;
-
-       ret = VM_FAULT_MINOR;
+       int ret = 0;
 
        size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
        if (vmf->pgoff >= size)
         */
        mark_page_accessed(page);
        vmf->page = page;
-       return ret | FAULT_RET_LOCKED;
+       return ret | VM_FAULT_LOCKED;
 
 outside_data_content:
        /*
 
 out:
        page_cache_get(page);
        vmf->page = page;
-       return VM_FAULT_MINOR;
+       return 0;
 }
 
 static struct vm_operations_struct xip_file_vm_ops = {
 
        avoidcopy = (page_count(old_page) == 1);
        if (avoidcopy) {
                set_huge_ptep_writable(vma, address, ptep);
-               return VM_FAULT_MINOR;
+               return 0;
        }
 
        page_cache_get(old_page);
        }
        page_cache_release(new_page);
        page_cache_release(old_page);
-       return VM_FAULT_MINOR;
+       return 0;
 }
 
 static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
        if (idx >= size)
                goto backout;
 
-       ret = VM_FAULT_MINOR;
+       ret = 0;
        if (!pte_none(*ptep))
                goto backout;
 
                return ret;
        }
 
-       ret = VM_FAULT_MINOR;
+       ret = 0;
 
        spin_lock(&mm->page_table_lock);
        /* Check for a racing update before calling hugetlb_cow */
                        spin_unlock(&mm->page_table_lock);
                        ret = hugetlb_fault(mm, vma, vaddr, 0);
                        spin_lock(&mm->page_table_lock);
-                       if (ret == VM_FAULT_MINOR)
+                       if (!(ret & VM_FAULT_MAJOR))
                                continue;
 
                        remainder = 0;
 
                        cond_resched();
                        while (!(page = follow_page(vma, start, foll_flags))) {
                                int ret;
-                               ret = __handle_mm_fault(mm, vma, start,
+                               ret = handle_mm_fault(mm, vma, start,
                                                foll_flags & FOLL_WRITE);
+                               if (ret & VM_FAULT_ERROR) {
+                                       if (ret & VM_FAULT_OOM)
+                                               return i ? i : -ENOMEM;
+                                       else if (ret & VM_FAULT_SIGBUS)
+                                               return i ? i : -EFAULT;
+                                       BUG();
+                               }
+                               if (ret & VM_FAULT_MAJOR)
+                                       tsk->maj_flt++;
+                               else
+                                       tsk->min_flt++;
+
                                /*
-                                * The VM_FAULT_WRITE bit tells us that do_wp_page has
-                                * broken COW when necessary, even if maybe_mkwrite
-                                * decided not to set pte_write. We can thus safely do
-                                * subsequent page lookups as if they were reads.
+                                * The VM_FAULT_WRITE bit tells us that
+                                * do_wp_page has broken COW when necessary,
+                                * even if maybe_mkwrite decided not to set
+                                * pte_write. We can thus safely do subsequent
+                                * page lookups as if they were reads.
                                 */
                                if (ret & VM_FAULT_WRITE)
                                        foll_flags &= ~FOLL_WRITE;
-                               
-                               switch (ret & ~VM_FAULT_WRITE) {
-                               case VM_FAULT_MINOR:
-                                       tsk->min_flt++;
-                                       break;
-                               case VM_FAULT_MAJOR:
-                                       tsk->maj_flt++;
-                                       break;
-                               case VM_FAULT_SIGBUS:
-                                       return i ? i : -EFAULT;
-                               case VM_FAULT_OOM:
-                                       return i ? i : -ENOMEM;
-                               default:
-                                       BUG();
-                               }
+
                                cond_resched();
                        }
                        if (pages) {
 {
        struct page *old_page, *new_page;
        pte_t entry;
-       int reuse = 0, ret = VM_FAULT_MINOR;
+       int reuse = 0, ret = 0;
        struct page *dirty_page = NULL;
 
        old_page = vm_normal_page(vma, address, orig_pte);
        /*
         * files that support invalidating or truncating portions of the
         * file from under mmaped areas must have their ->fault function
-        * return a locked page (and FAULT_RET_LOCKED code). This provides
-        * synchronisation against concurrent unmapping here.
+        * return a locked page (and set VM_FAULT_LOCKED in the return).
+        * This provides synchronisation against concurrent unmapping here.
         */
 
 again:
        struct page *page;
        swp_entry_t entry;
        pte_t pte;
-       int ret = VM_FAULT_MINOR;
+       int ret = 0;
 
        if (!pte_unmap_same(mm, pmd, page_table, orig_pte))
                goto out;
        unlock_page(page);
 
        if (write_access) {
+               /* XXX: We could OR the do_wp_page code with this one? */
                if (do_wp_page(mm, vma, address,
-                               page_table, pmd, ptl, pte) == VM_FAULT_OOM)
+                               page_table, pmd, ptl, pte) & VM_FAULT_OOM)
                        ret = VM_FAULT_OOM;
                goto out;
        }
        lazy_mmu_prot_update(entry);
 unlock:
        pte_unmap_unlock(page_table, ptl);
-       return VM_FAULT_MINOR;
+       return 0;
 release:
        page_cache_release(page);
        goto unlock;
 
        if (likely(vma->vm_ops->fault)) {
                ret = vma->vm_ops->fault(vma, &vmf);
-               if (unlikely(ret & (VM_FAULT_ERROR | FAULT_RET_NOPAGE)))
-                       return (ret & VM_FAULT_MASK);
+               if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE)))
+                       return ret;
        } else {
                /* Legacy ->nopage path */
-               ret = VM_FAULT_MINOR;
+               ret = 0;
                vmf.page = vma->vm_ops->nopage(vma, address & PAGE_MASK, &ret);
                /* no page was available -- either SIGBUS or OOM */
                if (unlikely(vmf.page == NOPAGE_SIGBUS))
         * For consistency in subsequent calls, make the faulted page always
         * locked.
         */
-       if (unlikely(!(ret & FAULT_RET_LOCKED)))
+       if (unlikely(!(ret & VM_FAULT_LOCKED)))
                lock_page(vmf.page);
        else
                VM_BUG_ON(!PageLocked(vmf.page));
                                ret = VM_FAULT_OOM;
                                goto out;
                        }
-                       page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
+                       page = alloc_page_vma(GFP_HIGHUSER_MOVABLE,
+                                               vma, address);
                        if (!page) {
                                ret = VM_FAULT_OOM;
                                goto out;
                                 * is better done later.
                                 */
                                if (!page->mapping) {
-                                       ret = VM_FAULT_MINOR;
+                                       ret = 0;
                                        anon = 1; /* no anon but release vmf.page */
                                        goto out;
                                }
                put_page(dirty_page);
        }
 
-       return (ret & VM_FAULT_MASK);
+       return ret;
 }
 
 static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        spinlock_t *ptl;
        pte_t entry;
        unsigned long pfn;
-       int ret = VM_FAULT_MINOR;
 
        pte_unmap(page_table);
        BUG_ON(!(vma->vm_flags & VM_PFNMAP));
        else if (unlikely(pfn == NOPFN_SIGBUS))
                return VM_FAULT_SIGBUS;
        else if (unlikely(pfn == NOPFN_REFAULT))
-               return VM_FAULT_MINOR;
+               return 0;
 
        page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
 
                set_pte_at(mm, address, page_table, entry);
        }
        pte_unmap_unlock(page_table, ptl);
-       return ret;
+       return 0;
 }
 
 /*
        pgoff_t pgoff;
 
        if (!pte_unmap_same(mm, pmd, page_table, orig_pte))
-               return VM_FAULT_MINOR;
+               return 0;
 
        if (unlikely(!(vma->vm_flags & VM_NONLINEAR) ||
                        !(vma->vm_flags & VM_CAN_NONLINEAR))) {
        }
 unlock:
        pte_unmap_unlock(pte, ptl);
-       return VM_FAULT_MINOR;
+       return 0;
 }
 
 /*
  * By the time we get here, we already hold the mm semaphore
  */
-int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
+int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                unsigned long address, int write_access)
 {
        pgd_t *pgd;
        return handle_pte_fault(mm, vma, address, pte, pmd, write_access);
 }
 
-EXPORT_SYMBOL_GPL(__handle_mm_fault);
+EXPORT_SYMBOL_GPL(handle_mm_fault);
 
 #ifndef __PAGETABLE_PUD_FOLDED
 /*
 
                return -EFBIG;
 
        if (type)
-               *type = VM_FAULT_MINOR;
+               *type = 0;
 
        /*
         * Normally, filepage is NULL on entry, and either found
                if (!swappage) {
                        shmem_swp_unmap(entry);
                        /* here we actually do the io */
-                       if (type && *type == VM_FAULT_MINOR) {
+                       if (type && !(*type & VM_FAULT_MAJOR)) {
                                __count_vm_event(PGMAJFAULT);
-                               *type = VM_FAULT_MAJOR;
+                               *type |= VM_FAULT_MAJOR;
                        }
                        spin_unlock(&info->lock);
                        swappage = shmem_swapin(info, swap, idx);
                return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS);
 
        mark_page_accessed(vmf->page);
-       return ret | FAULT_RET_LOCKED;
+       return ret | VM_FAULT_LOCKED;
 }
 
 #ifdef CONFIG_NUMA