From owner-svn-src-stable@FreeBSD.ORG Fri Mar 19 22:39:27 2010 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DB909106566B; Fri, 19 Mar 2010 22:39:27 +0000 (UTC) (envelope-from attilio@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id C8B2F8FC0A; Fri, 19 Mar 2010 22:39:27 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o2JMdRsU085364; Fri, 19 Mar 2010 22:39:27 GMT (envelope-from attilio@svn.freebsd.org) Received: (from attilio@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o2JMdRQs085360; Fri, 19 Mar 2010 22:39:27 GMT (envelope-from attilio@svn.freebsd.org) Message-Id: <201003192239.o2JMdRQs085360@svn.freebsd.org> From: Attilio Rao Date: Fri, 19 Mar 2010 22:39:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-6@freebsd.org X-SVN-Group: stable-6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r205349 - stable/6/sys/vm X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 19 Mar 2010 22:39:28 -0000 Author: attilio Date: Fri Mar 19 22:39:27 2010 New Revision: 205349 URL: http://svn.freebsd.org/changeset/base/205349 Log: MFC 181019, 183474, 191277, and 191626: - Move the code for doing out-of-memory grass from vm_pageout_scan() into the separate function vm_pageout_oom(). Supply a parameter for vm_pageout_oom() describing a reason for the call. - Call vm_pageout_oom() from the swp_pager_meta_build() when swap zone is exhausted. - In both pageout oom handler and vm_daemon, acquire the reference to the vmspace of the examined process instead of directly accessing its vmspace, that may change. Also, as an optimization, check for P_INEXEC flag before examining the process. Sponsored by: Sandvine Incorporated Reviewed by: emaste Modified: stable/6/sys/vm/swap_pager.c stable/6/sys/vm/vm_pageout.c stable/6/sys/vm/vm_pageout.h Directory Properties: stable/6/sys/ (props changed) stable/6/sys/contrib/pf/ (props changed) stable/6/sys/dev/cxgb/ (props changed) Modified: stable/6/sys/vm/swap_pager.c ============================================================================== --- stable/6/sys/vm/swap_pager.c Fri Mar 19 21:29:30 2010 (r205348) +++ stable/6/sys/vm/swap_pager.c Fri Mar 19 22:39:27 2010 (r205349) @@ -1680,7 +1680,7 @@ swp_pager_meta_build(vm_object_t object, { struct swblock *swap; struct swblock **pswap; - int idx; + int dummy, idx; VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); /* @@ -1720,9 +1720,12 @@ retry: if (swap == NULL) { mtx_unlock(&swhash_mtx); VM_OBJECT_UNLOCK(object); - if (uma_zone_exhausted(swap_zone)) + if (uma_zone_exhausted(swap_zone)) { printf("swap zone exhausted, increase kern.maxswzone\n"); - VM_WAIT; + vm_pageout_oom(VM_OOM_SWAPZ); + tsleep(&dummy, PVM, "swzonex", 10); + } else + VM_WAIT; VM_OBJECT_LOCK(object); goto retry; } Modified: stable/6/sys/vm/vm_pageout.c ============================================================================== --- stable/6/sys/vm/vm_pageout.c Fri Mar 19 21:29:30 2010 (r205348) +++ stable/6/sys/vm/vm_pageout.c Fri Mar 19 22:39:27 2010 (r205349) @@ -711,9 +711,6 @@ vm_pageout_scan(int pass) struct vm_page marker; int page_shortage, maxscan, pcount; int addl_page_shortage, addl_page_shortage_init; - struct proc *p, *bigproc; - struct thread *td; - vm_offset_t size, bigsize; vm_object_t object; int actcount, cache_cur, cache_first_failure; static int cache_last_free; @@ -1246,7 +1243,23 @@ unlock_and_continue: * doing this on the first pass in order to give ourselves a * chance to flush out dirty vnode-backed pages and to allow * active pages to be moved to the inactive queue and reclaimed. - * + */ + if (pass != 0 && + ((swap_pager_avail < 64 && vm_page_count_min()) || + (swap_pager_full && vm_paging_target() > 0))) + vm_pageout_oom(VM_OOM_MEM); +} + + +void +vm_pageout_oom(int shortage) +{ + struct proc *p, *bigproc; + vm_offset_t size, bigsize; + struct thread *td; + struct vmspace *vm; + + /* * We keep the process bigproc locked once we find it to keep anyone * from messing with it; however, there is a possibility of * deadlock if process B is bigproc and one of it's child processes @@ -1254,77 +1267,81 @@ unlock_and_continue: * lock while walking this list. To avoid this, we don't block on * the process lock but just skip a process if it is already locked. */ - if (pass != 0 && - ((swap_pager_avail < 64 && vm_page_count_min()) || - (swap_pager_full && vm_paging_target() > 0))) { - bigproc = NULL; - bigsize = 0; - sx_slock(&allproc_lock); - FOREACH_PROC_IN_SYSTEM(p) { - int breakout; + bigproc = NULL; + bigsize = 0; + sx_slock(&allproc_lock); + FOREACH_PROC_IN_SYSTEM(p) { + int breakout; - if (PROC_TRYLOCK(p) == 0) - continue; - /* - * If this is a system or protected process, skip it. - */ - if ((p->p_flag & P_SYSTEM) || (p->p_pid == 1) || - (p->p_flag & P_PROTECTED) || - ((p->p_pid < 48) && (swap_pager_avail != 0))) { - PROC_UNLOCK(p); - continue; - } - /* - * If the process is in a non-running type state, - * don't touch it. Check all the threads individually. - */ - mtx_lock_spin(&sched_lock); - breakout = 0; - FOREACH_THREAD_IN_PROC(p, td) { - if (!TD_ON_RUNQ(td) && - !TD_IS_RUNNING(td) && - !TD_IS_SLEEPING(td)) { - breakout = 1; - break; - } - } - if (breakout) { - mtx_unlock_spin(&sched_lock); - PROC_UNLOCK(p); - continue; - } - mtx_unlock_spin(&sched_lock); - /* - * get the process size - */ - if (!vm_map_trylock_read(&p->p_vmspace->vm_map)) { - PROC_UNLOCK(p); - continue; + if (PROC_TRYLOCK(p) == 0) + continue; + /* + * If this is a system or protected process, skip it. + */ + if ((p->p_flag & (P_INEXEC | P_PROTECTED | P_SYSTEM)) || + (p->p_pid == 1) || + ((p->p_pid < 48) && (swap_pager_avail != 0))) { + PROC_UNLOCK(p); + continue; + } + /* + * If the process is in a non-running type state, + * don't touch it. Check all the threads individually. + */ + mtx_lock_spin(&sched_lock); + breakout = 0; + FOREACH_THREAD_IN_PROC(p, td) { + if (!TD_ON_RUNQ(td) && + !TD_IS_RUNNING(td) && + !TD_IS_SLEEPING(td)) { + breakout = 1; + break; } - size = vmspace_swap_count(p->p_vmspace); - vm_map_unlock_read(&p->p_vmspace->vm_map); - size += vmspace_resident_count(p->p_vmspace); - /* - * if the this process is bigger than the biggest one - * remember it. - */ - if (size > bigsize) { - if (bigproc != NULL) - PROC_UNLOCK(bigproc); - bigproc = p; - bigsize = size; - } else - PROC_UNLOCK(p); } - sx_sunlock(&allproc_lock); - if (bigproc != NULL) { - killproc(bigproc, "out of swap space"); - mtx_lock_spin(&sched_lock); - sched_nice(bigproc, PRIO_MIN); + if (breakout) { mtx_unlock_spin(&sched_lock); - PROC_UNLOCK(bigproc); - wakeup(&cnt.v_free_count); + PROC_UNLOCK(p); + continue; + } + mtx_unlock_spin(&sched_lock); + /* + * get the process size + */ + vm = vmspace_acquire_ref(p); + if (vm == NULL) { + PROC_UNLOCK(p); + continue; } + if (!vm_map_trylock_read(&vm->vm_map)) { + vmspace_free(vm); + PROC_UNLOCK(p); + continue; + } + size = vmspace_swap_count(vm); + vm_map_unlock_read(&vm->vm_map); + if (shortage == VM_OOM_MEM) + size += vmspace_resident_count(vm); + vmspace_free(vm); + /* + * if the this process is bigger than the biggest one + * remember it. + */ + if (size > bigsize) { + if (bigproc != NULL) + PROC_UNLOCK(bigproc); + bigproc = p; + bigsize = size; + } else + PROC_UNLOCK(p); + } + sx_sunlock(&allproc_lock); + if (bigproc != NULL) { + killproc(bigproc, "out of swap space"); + mtx_lock_spin(&sched_lock); + sched_nice(bigproc, PRIO_MIN); + mtx_unlock_spin(&sched_lock); + PROC_UNLOCK(bigproc); + wakeup(&cnt.v_free_count); } } @@ -1595,6 +1612,7 @@ vm_daemon() struct rlimit rsslim; struct proc *p; struct thread *td; + struct vmspace *vm; int breakout, swapout_flags; while (TRUE) { @@ -1619,7 +1637,7 @@ vm_daemon() * looked at this process, skip it. */ PROC_LOCK(p); - if (p->p_flag & (P_SYSTEM | P_WEXIT)) { + if (p->p_flag & (P_INEXEC | P_SYSTEM | P_WEXIT)) { PROC_UNLOCK(p); continue; } @@ -1656,13 +1674,17 @@ vm_daemon() */ if ((p->p_sflag & PS_INMEM) == 0) limit = 0; /* XXX */ + vm = vmspace_acquire_ref(p); PROC_UNLOCK(p); + if (vm == NULL) + continue; - size = vmspace_resident_count(p->p_vmspace); + size = vmspace_resident_count(vm); if (limit >= 0 && size >= limit) { vm_pageout_map_deactivate_pages( - &p->p_vmspace->vm_map, limit); + &vm->vm_map, limit); } + vmspace_free(vm); } sx_sunlock(&allproc_lock); } Modified: stable/6/sys/vm/vm_pageout.h ============================================================================== --- stable/6/sys/vm/vm_pageout.h Fri Mar 19 21:29:30 2010 (r205348) +++ stable/6/sys/vm/vm_pageout.h Fri Mar 19 22:39:27 2010 (r205349) @@ -83,6 +83,9 @@ extern int vm_pageout_page_count; #define VM_SWAP_NORMAL 1 #define VM_SWAP_IDLE 2 +#define VM_OOM_MEM 1 +#define VM_OOM_SWAPZ 2 + /* * Exported routines. */ @@ -99,5 +102,6 @@ extern void vm_waitpfault(void); #ifdef _KERNEL int vm_pageout_flush(vm_page_t *, int, int); +void vm_pageout_oom(int shortage); #endif #endif /* _VM_VM_PAGEOUT_H_ */