summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2015-09-20 19:20:03 +0000
committeralc <alc@FreeBSD.org>2015-09-20 19:20:03 +0000
commit57be559e4abf337edf211ba16a09c41aa227d270 (patch)
tree2fbf814e246a1f70e7c5146bab44e4a5ad1a1d3d
parent058e1a61ea26c02b092c4ad3659ac1a3d0f57c45 (diff)
downloadFreeBSD-src-57be559e4abf337edf211ba16a09c41aa227d270.zip
FreeBSD-src-57be559e4abf337edf211ba16a09c41aa227d270.tar.gz
Correct a non-fatal error in vm_pageout_worker(). vm_pageout_worker()
should not assume that vm_pages_needed will remain set while it sleeps. Other threads can clear vm_pages_needed by performing a sufficient number of vm_page_free() calls, e.g., process termination. The effect of this error was that vm_pageout_worker() would free and/or launder pages when, in fact, there was no shortage of free pages. Rewrite a nearby comment to describe all of the possible cases and not just the most common case. The problem being that the comment made the most common case seem like the only case. Reviewed by: kib MFC after: 1 week Sponsored by: EMC / Isilon Storage Division
-rw-r--r--sys/vm/vm_pageout.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 6641193..0a18e6d 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -1638,9 +1638,15 @@ vm_pageout_worker(void *arg)
}
if (vm_pages_needed) {
/*
- * Still not done, take a second pass without waiting
- * (unlimited dirty cleaning), otherwise sleep a bit
- * and try again.
+ * We're still not done. Either vm_pages_needed was
+ * set by another thread during the previous scan
+ * (typically, this happens during a level 0 scan) or
+ * vm_pages_needed was already set and the scan failed
+ * to free enough pages. If we haven't yet performed
+ * a level >= 2 scan (unlimited dirty cleaning), then
+ * upgrade the level and scan again now. Otherwise,
+ * sleep a bit and try again later. While sleeping,
+ * vm_pages_needed can be cleared.
*/
if (domain->vmd_pass > 1)
msleep(&vm_pages_needed,
@@ -1651,15 +1657,14 @@ vm_pageout_worker(void *arg)
* Good enough, sleep until required to refresh
* stats.
*/
- domain->vmd_pass = 0;
msleep(&vm_pages_needed, &vm_page_queue_free_mtx,
PVM, "psleep", hz);
-
}
if (vm_pages_needed) {
vm_cnt.v_pdwakeups++;
domain->vmd_pass++;
- }
+ } else
+ domain->vmd_pass = 0;
mtx_unlock(&vm_page_queue_free_mtx);
vm_pageout_scan(domain, domain->vmd_pass);
}
OpenPOWER on IntegriCloud