Module Name: src Committed By: pooka Date: Tue Feb 22 20:17:38 UTC 2011
Modified Files: src/sys/rump/librump/rumpkern: vm.c src/sys/rump/librump/rumpvfs: vm_vfs.c Log Message: Shuffle the pagedaemon algorithm a bit to record the number of pageouts active and give up only if the pagedaemon could not free memory and there are no outstanding pageouts. This should fix the "out of memory" pauses reported by Mihai Chelaru and Taylor R Campbell. Tested by copying files to and from an ffs backed by /dev/wd0 (with and without -o log) using a 1MB rump kernel memory limit. To generate a diff of this commit: cvs rdiff -u -r1.112 -r1.113 src/sys/rump/librump/rumpkern/vm.c cvs rdiff -u -r1.24 -r1.25 src/sys/rump/librump/rumpvfs/vm_vfs.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/rump/librump/rumpkern/vm.c diff -u src/sys/rump/librump/rumpkern/vm.c:1.112 src/sys/rump/librump/rumpkern/vm.c:1.113 --- src/sys/rump/librump/rumpkern/vm.c:1.112 Tue Feb 22 18:43:20 2011 +++ src/sys/rump/librump/rumpkern/vm.c Tue Feb 22 20:17:38 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: vm.c,v 1.112 2011/02/22 18:43:20 pooka Exp $ */ +/* $NetBSD: vm.c,v 1.113 2011/02/22 20:17:38 pooka Exp $ */ /* * Copyright (c) 2007-2010 Antti Kantee. All Rights Reserved. @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vm.c,v 1.112 2011/02/22 18:43:20 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vm.c,v 1.113 2011/02/22 20:17:38 pooka Exp $"); #include <sys/param.h> #include <sys/atomic.h> @@ -923,14 +923,27 @@ uvm_pageout_start(int npages) { - /* we don't have the heuristics */ + mutex_enter(&pdaemonmtx); + uvmexp.paging += npages; + mutex_exit(&pdaemonmtx); } void uvm_pageout_done(int npages) { - /* could wakeup waiters, but just let the pagedaemon do it */ + if (!npages) + return; + + mutex_enter(&pdaemonmtx); + KASSERT(uvmexp.paging >= npages); + uvmexp.paging -= npages; + + if (pdaemon_waiters) { + pdaemon_waiters = 0; + cv_broadcast(&oomwait); + } + mutex_exit(&pdaemonmtx); } static bool @@ -969,6 +982,8 @@ /* * The Diabolical pageDaemon Director (DDD). + * + * This routine can always use better heuristics. */ void uvm_pageout(void *arg) @@ -976,35 +991,30 @@ struct vm_page *pg; struct pool *pp, *pp_first; uint64_t where; - int timo = 0; int cleaned, skip, skipped; - bool succ = false; + int waspaging; + bool succ; bool lockrunning; mutex_enter(&pdaemonmtx); for (;;) { - if (succ) { + if (!NEED_PAGEDAEMON()) { kernel_map->flags &= ~VM_MAP_WANTVA; kmem_map->flags &= ~VM_MAP_WANTVA; - timo = 0; - if (pdaemon_waiters) { - pdaemon_waiters = 0; - cv_broadcast(&oomwait); - } } - succ = false; - if (pdaemon_waiters == 0) { - cv_timedwait(&pdaemoncv, &pdaemonmtx, timo); - uvmexp.pdwoke++; + if (pdaemon_waiters) { + pdaemon_waiters = 0; + cv_broadcast(&oomwait); } + cv_wait(&pdaemoncv, &pdaemonmtx); + uvmexp.pdwoke++; + waspaging = uvmexp.paging; + /* tell the world that we are hungry */ kernel_map->flags |= VM_MAP_WANTVA; kmem_map->flags |= VM_MAP_WANTVA; - - if (pdaemon_waiters == 0 && !NEED_PAGEDAEMON()) - continue; mutex_exit(&pdaemonmtx); /* @@ -1014,7 +1024,6 @@ */ pool_cache_reclaim(&pagecache); if (!NEED_PAGEDAEMON()) { - succ = true; mutex_enter(&pdaemonmtx); continue; } @@ -1081,7 +1090,6 @@ */ pool_cache_reclaim(&pagecache); if (!NEED_PAGEDAEMON()) { - succ = true; mutex_enter(&pdaemonmtx); continue; } @@ -1118,13 +1126,14 @@ * Unfortunately, the wife just borrowed it. */ - if (!succ && cleaned == 0) { + mutex_enter(&pdaemonmtx); + if (!succ && cleaned == 0 && pdaemon_waiters && + uvmexp.paging == 0) { rumpuser_dprintf("pagedaemoness: failed to reclaim " "memory ... sleeping (deadlock?)\n"); - timo = hz; + cv_timedwait(&pdaemoncv, &pdaemonmtx, hz); + mutex_enter(&pdaemonmtx); } - - mutex_enter(&pdaemonmtx); } panic("you can swap out any time you like, but you can never leave"); Index: src/sys/rump/librump/rumpvfs/vm_vfs.c diff -u src/sys/rump/librump/rumpvfs/vm_vfs.c:1.24 src/sys/rump/librump/rumpvfs/vm_vfs.c:1.25 --- src/sys/rump/librump/rumpvfs/vm_vfs.c:1.24 Sat Dec 18 11:45:09 2010 +++ src/sys/rump/librump/rumpvfs/vm_vfs.c Tue Feb 22 20:17:37 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: vm_vfs.c,v 1.24 2010/12/18 11:45:09 pooka Exp $ */ +/* $NetBSD: vm_vfs.c,v 1.25 2011/02/22 20:17:37 pooka Exp $ */ /* * Copyright (c) 2008 Antti Kantee. All Rights Reserved. @@ -29,7 +29,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vm_vfs.c,v 1.24 2010/12/18 11:45:09 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vm_vfs.c,v 1.25 2011/02/22 20:17:37 pooka Exp $"); #include <sys/param.h> @@ -67,7 +67,6 @@ } uvm_pagermapout((vaddr_t)bp->b_data, npages); - uvm_pageout_done(pageout); /* get uobj because we need it after pages might be recycled */ uobj = pgs[0]->uobject; @@ -79,6 +78,8 @@ mutex_exit(&uvm_pageqlock); mutex_exit(&uobj->vmobjlock); + uvm_pageout_done(pageout); + if (BUF_ISWRITE(bp) && (bp->b_cflags & BC_AGE) != 0) { mutex_enter(bp->b_objlock); vwakeup(bp);