svn commit: r205349 - stable/6/sys/vm
Attilio Rao
attilio at FreeBSD.org
Fri Mar 19 22:39:28 UTC 2010
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_ */
More information about the svn-src-stable-6
mailing list