summaryrefslogtreecommitdiffstats
path: root/sys/vm/vm_pageout.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2012-07-26 09:06:48 +0000
committerkib <kib@FreeBSD.org>2012-07-26 09:06:48 +0000
commit4f8212948b54915e36ecbd960fbc2a55b56eab59 (patch)
treec06c2b59d2508e95541f6f753da32a41d3dfe466 /sys/vm/vm_pageout.c
parentdf16a3505fa26d5c757f4cf372fa3f6bd6ed7652 (diff)
downloadFreeBSD-src-4f8212948b54915e36ecbd960fbc2a55b56eab59.zip
FreeBSD-src-4f8212948b54915e36ecbd960fbc2a55b56eab59.tar.gz
Do not requeue held page or page for which locking failed, just leave
them alone. Process the act_count updates for the held pages in the vm_pageout loop over the inactive queue, instead of refusing to do anything with such page. Clarify the intent of the addl_page_shortage counter and change its use for pages which are not processed in the loop according to the description. Reviewed by: alc MFC after: 2 weeks
Diffstat (limited to 'sys/vm/vm_pageout.c')
-rw-r--r--sys/vm/vm_pageout.c56
1 files changed, 35 insertions, 21 deletions
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 6ac0acb..3994ce1 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -889,6 +889,12 @@ vm_pageout_scan(int pass)
*/
uma_reclaim();
+ /*
+ * The addl_page_shortage is the the number of temporarily
+ * stuck pages in the inactive queue. In other words, the
+ * number of pages from cnt.v_inactive_count that should be
+ * discounted in setting the target for the active queue scan.
+ */
addl_page_shortage = atomic_readandclear_int(&vm_pageout_deficit);
/*
@@ -945,38 +951,31 @@ vm_pageout_scan(int pass)
("Unmanaged page %p cannot be in inactive queue", m));
/*
- * Lock the page.
+ * The page or object lock acquisitions fail if the
+ * page was removed from the queue or moved to a
+ * different position within the queue. In either
+ * case, addl_page_shortage should not be incremented.
*/
if (!vm_pageout_page_lock(m, &next)) {
vm_page_unlock(m);
- addl_page_shortage++;
continue;
}
-
- /*
- * A held page may be undergoing I/O, so skip it.
- */
- if (m->hold_count) {
+ object = m->object;
+ if (!VM_OBJECT_TRYLOCK(object) &&
+ !vm_pageout_fallback_object_lock(m, &next)) {
vm_page_unlock(m);
- vm_page_requeue(m);
- addl_page_shortage++;
+ VM_OBJECT_UNLOCK(object);
continue;
}
/*
- * Don't mess with busy pages, keep in the front of the
- * queue, most likely are being paged out.
+ * Don't mess with busy pages, keep them at at the
+ * front of the queue, most likely they are being
+ * paged out. Increment addl_page_shortage for busy
+ * pages, because they may leave the inactive queue
+ * shortly after page scan is finished.
*/
- object = m->object;
- if (!VM_OBJECT_TRYLOCK(object) &&
- (!vm_pageout_fallback_object_lock(m, &next) ||
- m->hold_count != 0)) {
- VM_OBJECT_UNLOCK(object);
- vm_page_unlock(m);
- addl_page_shortage++;
- continue;
- }
- if (m->busy || (m->oflags & VPO_BUSY)) {
+ if (m->busy != 0 || (m->oflags & VPO_BUSY) != 0) {
vm_page_unlock(m);
VM_OBJECT_UNLOCK(object);
addl_page_shortage++;
@@ -1036,6 +1035,21 @@ vm_pageout_scan(int pass)
goto relock_queues;
}
+ if (m->hold_count != 0) {
+ vm_page_unlock(m);
+ VM_OBJECT_UNLOCK(object);
+
+ /*
+ * Held pages are essentially stuck in the
+ * queue. So, they ought to be discounted
+ * from cnt.v_inactive_count. See the
+ * calculation of the page_shortage for the
+ * loop over the active queue below.
+ */
+ addl_page_shortage++;
+ goto relock_queues;
+ }
+
/*
* If the upper level VM system does not believe that the page
* is fully dirty, but it is mapped for write access, then we
OpenPOWER on IntegriCloud