x86_64: During VM oom condition, kill all threads in process group
[powerpc.git] / arch / x86_64 / mm / fault.c
index de99dba..2074bdd 100644 (file)
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/tty.h>
 #include <linux/vt_kern.h>             /* For unblank_screen() */
 #include <linux/compiler.h>
+#include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/kprobes.h>
 #include <linux/uaccess.h>
+#include <linux/kdebug.h>
 
 #include <asm/system.h>
 #include <asm/pgalloc.h>
 #include <asm/smp.h>
 #include <asm/tlbflush.h>
 #include <asm/proto.h>
-#include <asm/kdebug.h>
 #include <asm-generic/sections.h>
 
 /* Page fault error code bits */
@@ -301,7 +301,7 @@ static int vmalloc_fault(unsigned long address)
        return 0;
 }
 
-int page_fault_trace = 0;
+static int page_fault_trace;
 int exception_trace = 1;
 
 /*
@@ -317,7 +317,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
        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;
 
@@ -450,19 +450,18 @@ good_area:
         * 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;
 
@@ -476,6 +475,12 @@ bad_area:
 bad_area_nosemaphore:
        /* User mode accesses just cause a SIGSEGV */
        if (error_code & PF_USER) {
+
+               /*
+                * It's possible to have interrupts off here.
+                */
+               local_irq_enable();
+
                if (is_prefetch(regs, address, error_code))
                        return;
 
@@ -563,7 +568,7 @@ out_of_memory:
        }
        printk("VM: killing process %s\n", tsk->comm);
        if (error_code & 4)
-               do_exit(SIGKILL);
+               do_group_exit(SIGKILL);
        goto no_context;
 
 do_sigbus: