Date: Tue, 6 Apr 2010 10:43:01 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r206264 - in head/sys: kern sys vm Message-ID: <201004061043.o36Ah1qo037088@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201004061043.o36Ah1qo037088>