svn commit: r307488 - user/alc/PQ_LAUNDRY/sys/vm

Mark Johnston markj at FreeBSD.org
Mon Oct 17 07:23:08 UTC 2016


Author: markj
Date: Mon Oct 17 07:23:07 2016
New Revision: 307488
URL: https://svnweb.freebsd.org/changeset/base/307488

Log:
  Handle laundering run preemption properly.
  
  Shortfall can preempt a background laundering, but not a shortfall
  laundering. Therefore:
  - make sure we don't reset the shortfall target if a shortfall request
    arrives while the system is already in shortfall, and
  - make sure we acknowledge a shortfall request by resetting
    vm_laundry_request if it arrives during background laundering.
  
  Also ensure that we sleep uninterruptibly between laundry cycles, and
  rename "cycle" to make its use more clear.
  
  Reviewed by:	alc

Modified:
  user/alc/PQ_LAUNDRY/sys/vm/vm_pageout.c

Modified: user/alc/PQ_LAUNDRY/sys/vm/vm_pageout.c
==============================================================================
--- user/alc/PQ_LAUNDRY/sys/vm/vm_pageout.c	Mon Oct 17 07:20:01 2016	(r307487)
+++ user/alc/PQ_LAUNDRY/sys/vm/vm_pageout.c	Mon Oct 17 07:23:07 2016	(r307488)
@@ -1115,8 +1115,7 @@ vm_pageout_laundry_worker(void *arg)
 	struct vm_pagequeue *pq;
 	uint64_t nclean, ndirty;
 	u_int last_launder, wakeups;
-	int cycle, domidx, last_target, launder, shortfall;
-	int sleeptime, target;
+	int domidx, last_target, launder, shortfall, shortfall_cycle, target;
 	bool in_shortfall;
 
 	domidx = (uintptr_t)arg;
@@ -1127,8 +1126,8 @@ vm_pageout_laundry_worker(void *arg)
 
 	shortfall = 0;
 	in_shortfall = false;
+	shortfall_cycle = 0;
 	target = 0;
-	cycle = 0;
 	last_launder = 0;
 
 	/*
@@ -1136,7 +1135,8 @@ vm_pageout_laundry_worker(void *arg)
 	 */
 	for (;;) {
 		KASSERT(target >= 0, ("negative target %d", target));
-		KASSERT(cycle >= 0, ("negative cycle %d", cycle));
+		KASSERT(shortfall_cycle >= 0,
+		    ("negative cycle %d", shortfall_cycle));
 		launder = 0;
 		wakeups = VM_METER_PCPU_CNT(v_pdwakeups);
 
@@ -1146,11 +1146,11 @@ vm_pageout_laundry_worker(void *arg)
 		 */
 		if (shortfall > 0) {
 			in_shortfall = true;
+			shortfall_cycle = VM_LAUNDER_RATE;
 			target = shortfall;
-			cycle = VM_LAUNDER_RATE;
 		} else if (!in_shortfall)
 			goto trybackground;
-		else if (cycle == 0 || vm_laundry_target() <= 0) {
+		else if (shortfall_cycle == 0 || vm_laundry_target() <= 0) {
 			/*
 			 * We recently entered shortfall and began laundering
 			 * pages.  If we have completed that laundering run
@@ -1163,7 +1163,7 @@ vm_pageout_laundry_worker(void *arg)
 			goto trybackground;
 		}
 		last_launder = wakeups;
-		launder = target / cycle--;
+		launder = target / shortfall_cycle--;
 		goto dolaundry;
 
 		/*
@@ -1229,16 +1229,26 @@ dolaundry:
 		 * started.  Otherwise, wait for a kick from the pagedaemon.
 		 */
 		vm_pagequeue_lock(pq);
-		if (target > 0 || vm_laundry_request != VM_LAUNDRY_IDLE)
-			sleeptime = hz / VM_LAUNDER_INTERVAL;
-		else
-			sleeptime = 0;
-		(void)mtx_sleep(&vm_laundry_request, vm_pagequeue_lockptr(pq),
-		    PVM, "laundr", sleeptime);
-		if (vm_laundry_request == VM_LAUNDRY_SHORTFALL)
+		if (target > 0 || vm_laundry_request != VM_LAUNDRY_IDLE) {
+			vm_pagequeue_unlock(pq);
+			pause("laundr", hz / VM_LAUNDER_INTERVAL);
+			vm_pagequeue_lock(pq);
+		} else
+			(void)mtx_sleep(&vm_laundry_request,
+			    vm_pagequeue_lockptr(pq), PVM, "laundr", 0);
+
+		/*
+		 * If the pagedaemon has indicated that it's in shortfall, start
+		 * a shortfall laundering unless we're already in the middle of
+		 * one.  This may preempt a background laundering.
+		 */
+		if (vm_laundry_request == VM_LAUNDRY_SHORTFALL &&
+		    (!in_shortfall || shortfall_cycle == 0)) {
 			shortfall = vm_laundry_target() + vm_pageout_deficit;
-		else
+			target = 0;
+		} else
 			shortfall = 0;
+
 		if (target == 0)
 			vm_laundry_request = VM_LAUNDRY_IDLE;
 		vm_pagequeue_unlock(pq);


More information about the svn-src-user mailing list