Author: kib
Date: Tue Apr  6 10:43:01 2010
New Revision: 206264
URL: http://svn.freebsd.org/changeset/base/206264

Log:
  When OOM searches for a process to kill, ignore the processes already
  killed by OOM. When killed process waits for a page allocation, try to
  satisfy the request as fast as possible.
  
  This removes the often encountered deadlock, where OOM continously
  selects the same victim process, that sleeps uninterruptibly waiting
  for a page. The killed process may still sleep if page cannot be
  obtained immediately, but testing has shown that system has much
  higher chance to survive in OOM situation with the patch.
  
  In collaboration with:        pho
  Reviewed by:  alc
  MFC after:    4 weeks

Modified:
  head/sys/kern/kern_sig.c
  head/sys/sys/proc.h
  head/sys/vm/vm_fault.c
  head/sys/vm/vm_pageout.c

Modified: head/sys/kern/kern_sig.c
==============================================================================
--- head/sys/kern/kern_sig.c    Tue Apr  6 10:34:15 2010        (r206263)
+++ head/sys/kern/kern_sig.c    Tue Apr  6 10:43:01 2010        (r206264)
@@ -2809,6 +2809,7 @@ killproc(p, why)
                p, p->p_pid, p->p_comm);
        log(LOG_ERR, "pid %d (%s), uid %d, was killed: %s\n", p->p_pid, 
p->p_comm,
                p->p_ucred ? p->p_ucred->cr_uid : -1, why);
+       p->p_flag |= P_WKILLED;
        psignal(p, SIGKILL);
 }
 

Modified: head/sys/sys/proc.h
==============================================================================
--- head/sys/sys/proc.h Tue Apr  6 10:34:15 2010        (r206263)
+++ head/sys/sys/proc.h Tue Apr  6 10:43:01 2010        (r206264)
@@ -573,7 +573,7 @@ struct proc {
 #define        P_WAITED        0x01000 /* Someone is waiting for us. */
 #define        P_WEXIT         0x02000 /* Working on exiting. */
 #define        P_EXEC          0x04000 /* Process called exec. */
-#define        P_UNUSED8000    0x08000 /* available. */
+#define        P_WKILLED       0x08000 /* Killed, go to kernel/user boundary 
ASAP. */
 #define        P_CONTINUED     0x10000 /* Proc has continued from a stopped 
state. */
 #define        P_STOPPED_SIG   0x20000 /* Stopped due to SIGSTOP/SIGTSTP. */
 #define        P_STOPPED_TRACE 0x40000 /* Stopped because of tracing. */
@@ -592,6 +592,7 @@ struct proc {
 
 #define        P_STOPPED       (P_STOPPED_SIG|P_STOPPED_SINGLE|P_STOPPED_TRACE)
 #define        P_SHOULDSTOP(p) ((p)->p_flag & P_STOPPED)
+#define        P_KILLED(p)     ((p)->p_flag & P_WKILLED)
 
 /*
  * These were process status values (p_stat), now they are only used in

Modified: head/sys/vm/vm_fault.c
==============================================================================
--- head/sys/vm/vm_fault.c      Tue Apr  6 10:34:15 2010        (r206263)
+++ head/sys/vm/vm_fault.c      Tue Apr  6 10:43:01 2010        (r206264)
@@ -216,7 +216,7 @@ vm_fault(vm_map_t map, vm_offset_t vaddr
        vm_object_t next_object;
        vm_page_t marray[VM_FAULT_READ];
        int hardfault;
-       int faultcount, ahead, behind;
+       int faultcount, ahead, behind, alloc_req;
        struct faultstate fs;
        struct vnode *vp;
        int locked, error;
@@ -386,9 +386,14 @@ RetryFault:;
 
                        /*
                         * Allocate a new page for this object/offset pair.
+                        *
+                        * Unlocked read of the p_flag is harmless. At
+                        * worst, the P_KILLED might be not observed
+                        * there, and allocation can fail, causing
+                        * restart and new reading of the p_flag.
                         */
                        fs.m = NULL;
-                       if (!vm_page_count_severe()) {
+                       if (!vm_page_count_severe() || P_KILLED(curproc)) {
 #if VM_NRESERVLEVEL > 0
                                if ((fs.object->flags & OBJ_COLORED) == 0) {
                                        fs.object->flags |= OBJ_COLORED;
@@ -396,10 +401,13 @@ RetryFault:;
                                            fs.pindex;
                                }
 #endif
+                               alloc_req = P_KILLED(curproc) ?
+                                   VM_ALLOC_SYSTEM : VM_ALLOC_NORMAL;
+                               if (fs.object->type != OBJT_VNODE &&
+                                   fs.object->backing_object == NULL)
+                                       alloc_req |= VM_ALLOC_ZERO;
                                fs.m = vm_page_alloc(fs.object, fs.pindex,
-                                   (fs.object->type == OBJT_VNODE ||
-                                    fs.object->backing_object != NULL) ?
-                                   VM_ALLOC_NORMAL : VM_ALLOC_ZERO);
+                                   alloc_req);
                        }
                        if (fs.m == NULL) {
                                unlock_and_deallocate(&fs);
@@ -424,7 +432,8 @@ readrest:
                        int reqpage = 0;
                        u_char behavior = vm_map_entry_behavior(fs.entry);
 
-                       if (behavior == MAP_ENTRY_BEHAV_RANDOM) {
+                       if (behavior == MAP_ENTRY_BEHAV_RANDOM ||
+                           P_KILLED(curproc)) {
                                ahead = 0;
                                behind = 0;
                        } else {

Modified: head/sys/vm/vm_pageout.c
==============================================================================
--- head/sys/vm/vm_pageout.c    Tue Apr  6 10:34:15 2010        (r206263)
+++ head/sys/vm/vm_pageout.c    Tue Apr  6 10:43:01 2010        (r206264)
@@ -1206,10 +1206,10 @@ vm_pageout_oom(int shortage)
                if (PROC_TRYLOCK(p) == 0)
                        continue;
                /*
-                * If this is a system or protected process, skip it.
+                * If this is a system, protected or killed process, skip it.
                 */
                if ((p->p_flag & (P_INEXEC | P_PROTECTED | P_SYSTEM)) ||
-                   (p->p_pid == 1) ||
+                   (p->p_pid == 1) || P_KILLED(p) ||
                    ((p->p_pid < 48) && (swap_pager_avail != 0))) {
                        PROC_UNLOCK(p);
                        continue;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to