svn commit: r215866 - stable/8/sys/vm

Konstantin Belousov kib at FreeBSD.org
Fri Nov 26 15:30:03 UTC 2010


Author: kib
Date: Fri Nov 26 15:30:02 2010
New Revision: 215866
URL: http://svn.freebsd.org/changeset/base/215866

Log:
  MFC r215471:
  In vm_object_page_clean(), handle the pages that might be cached
  or not written by vm_pageout_flush().
  
  MFC r215574:
  The runlen returned from vm_pageout_flush() might be zero legitimately
  
  MCF r215610:
  Eliminate the mab, maf arrays and related variables.
  The change also fixes off-by-one error in the calculation of mreq.
  
  MFC r215796:
  After the sleep caused by encountering a busy page, relookup the page.

Modified:
  stable/8/sys/vm/vm_contig.c
  stable/8/sys/vm/vm_object.c
  stable/8/sys/vm/vm_pageout.c
  stable/8/sys/vm/vm_pageout.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)

Modified: stable/8/sys/vm/vm_contig.c
==============================================================================
--- stable/8/sys/vm/vm_contig.c	Fri Nov 26 14:50:42 2010	(r215865)
+++ stable/8/sys/vm/vm_contig.c	Fri Nov 26 15:30:02 2010	(r215866)
@@ -138,7 +138,7 @@ vm_contig_launder_page(vm_page_t m, vm_p
 		} else if (object->type == OBJT_SWAP ||
 			   object->type == OBJT_DEFAULT) {
 			m_tmp = m;
-			vm_pageout_flush(&m_tmp, 1, VM_PAGER_PUT_SYNC);
+			vm_pageout_flush(&m_tmp, 1, VM_PAGER_PUT_SYNC, 0, NULL);
 			VM_OBJECT_UNLOCK(object);
 			return (0);
 		}

Modified: stable/8/sys/vm/vm_object.c
==============================================================================
--- stable/8/sys/vm/vm_object.c	Fri Nov 26 14:50:42 2010	(r215865)
+++ stable/8/sys/vm/vm_object.c	Fri Nov 26 15:30:02 2010	(r215866)
@@ -809,10 +809,12 @@ rescan:
 		np = TAILQ_NEXT(p, listq);
 		if (p->valid == 0)
 			continue;
-		while (vm_page_sleep_if_busy(p, TRUE, "vpcwai")) {
+		if (vm_page_sleep_if_busy(p, TRUE, "vpcwai")) {
 			vm_page_lock_queues();
 			if (object->generation != curgeneration)
 				goto rescan;
+			np = vm_page_find_least(object, pi);
+			continue;
 		}
 		vm_page_test_dirty(p);
 		if (p->dirty == 0)
@@ -828,7 +830,6 @@ rescan:
 			continue;
 
 		n = vm_object_page_collect_flush(object, p, pagerflags);
-		KASSERT(n > 0, ("vm_object_page_collect_flush failed"));
 		if (object->generation != curgeneration)
 			goto rescan;
 		np = vm_page_find_least(object, pi + n);
@@ -844,77 +845,39 @@ rescan:
 static int
 vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int pagerflags)
 {
-	int runlen;
-	int maxf;
-	int chkb;
-	int maxb;
-	int i, index;
-	vm_pindex_t pi;
-	vm_page_t maf[vm_pageout_page_count];
-	vm_page_t mab[vm_pageout_page_count];
-	vm_page_t ma[vm_pageout_page_count];
-	vm_page_t tp, p1;
+	vm_page_t ma[vm_pageout_page_count], p_first, tp;
+	int count, i, mreq, runlen;
 
 	mtx_assert(&vm_page_queue_mtx, MA_OWNED);
-	pi = p->pindex;
-	maxf = 0;
-	for (i = 1, p1 = p; i < vm_pageout_page_count; i++) {
-		tp = vm_page_next(p1);
+
+	count = 1;
+	mreq = 0;
+
+	for (tp = p; count < vm_pageout_page_count; count++) {
+		tp = vm_page_next(tp);
 		if (tp == NULL || tp->busy != 0 || (tp->oflags & VPO_BUSY) != 0)
 			break;
 		vm_page_test_dirty(tp);
 		if (tp->dirty == 0)
 			break;
-		maf[i - 1] = p1 = tp;
-		maxf++;
 	}
 
-	maxb = 0;
-	chkb = vm_pageout_page_count -  maxf;
-	for (i = 1, p1 = p; i < chkb; i++) {
-		tp = vm_page_prev(p1);
+	for (p_first = p; count < vm_pageout_page_count; count++) {
+		tp = vm_page_prev(p_first);
 		if (tp == NULL || tp->busy != 0 || (tp->oflags & VPO_BUSY) != 0)
 			break;
 		vm_page_test_dirty(tp);
 		if (tp->dirty == 0)
 			break;
-		mab[i - 1] = p1 = tp;
-		maxb++;
+		p_first = tp;
+		mreq++;
 	}
 
-	for (i = 0; i < maxb; i++) {
-		index = (maxb - i) - 1;
-		ma[index] = mab[i];
-	}
-	ma[maxb] = p;
-	for (i = 0; i < maxf; i++) {
-		index = (maxb + i) + 1;
-		ma[index] = maf[i];
-	}
-	runlen = maxb + maxf + 1;
+	for (tp = p_first, i = 0; i < count; tp = TAILQ_NEXT(tp, listq), i++)
+		ma[i] = tp;
 
-	vm_pageout_flush(ma, runlen, pagerflags);
-	for (i = 0; i < runlen; i++) {
-		if (ma[i]->dirty != 0) {
-			KASSERT((ma[i]->flags & PG_WRITEABLE) == 0,
-	("vm_object_page_collect_flush: page %p is not write protected",
-			    ma[i]));
-		}
-	}
-	for (i = 0; i < maxf; i++) {
-		if (ma[i + maxb + 1]->dirty != 0) {
-			/*
-			 * maxf will end up being the actual number of pages
-			 * we wrote out contiguously, non-inclusive of the
-			 * first page.  We do not count look-behind pages.
-			 */
-			if (maxf > i) {
-				maxf = i;
-				break;
-			}
-		}
-	}
-	return (maxf + 1);
+	vm_pageout_flush(ma, count, pagerflags, mreq, &runlen);
+	return (runlen);
 }
 
 /*

Modified: stable/8/sys/vm/vm_pageout.c
==============================================================================
--- stable/8/sys/vm/vm_pageout.c	Fri Nov 26 14:50:42 2010	(r215865)
+++ stable/8/sys/vm/vm_pageout.c	Fri Nov 26 15:30:02 2010	(r215866)
@@ -391,7 +391,7 @@ more:
 	/*
 	 * we allow reads during pageouts...
 	 */
-	return (vm_pageout_flush(&mc[page_base], pageout_count, 0));
+	return (vm_pageout_flush(&mc[page_base], pageout_count, 0, 0, NULL));
 }
 
 /*
@@ -402,14 +402,17 @@ more:
  *	reference count all in here rather then in the parent.  If we want
  *	the parent to do more sophisticated things we may have to change
  *	the ordering.
+ *
+ *	Returned runlen is the count of pages between mreq and first
+ *	page after mreq with status VM_PAGER_AGAIN.
  */
 int
-vm_pageout_flush(vm_page_t *mc, int count, int flags)
+vm_pageout_flush(vm_page_t *mc, int count, int flags, int mreq, int *prunlen)
 {
 	vm_object_t object = mc[0]->object;
 	int pageout_status[count];
 	int numpagedout = 0;
-	int i;
+	int i, runlen;
 
 	mtx_assert(&vm_page_queue_mtx, MA_OWNED);
 	VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
@@ -435,6 +438,7 @@ vm_pageout_flush(vm_page_t *mc, int coun
 
 	vm_pager_put_pages(object, mc, count, flags, pageout_status);
 
+	runlen = count - mreq;
 	vm_page_lock_queues();
 	for (i = 0; i < count; i++) {
 		vm_page_t mt = mc[i];
@@ -465,6 +469,8 @@ vm_pageout_flush(vm_page_t *mc, int coun
 			vm_page_activate(mt);
 			break;
 		case VM_PAGER_AGAIN:
+			if (i >= mreq && i - mreq < runlen)
+				runlen = i - mreq;
 			break;
 		}
 
@@ -481,7 +487,9 @@ vm_pageout_flush(vm_page_t *mc, int coun
 				vm_page_try_to_cache(mt);
 		}
 	}
-	return numpagedout;
+	if (prunlen != NULL)
+		*prunlen = runlen;
+	return (numpagedout);
 }
 
 #if !defined(NO_SWAPPING)

Modified: stable/8/sys/vm/vm_pageout.h
==============================================================================
--- stable/8/sys/vm/vm_pageout.h	Fri Nov 26 14:50:42 2010	(r215865)
+++ stable/8/sys/vm/vm_pageout.h	Fri Nov 26 15:30:02 2010	(r215866)
@@ -102,7 +102,7 @@ extern void vm_waitpfault(void);
 
 #ifdef _KERNEL
 boolean_t vm_pageout_fallback_object_lock(vm_page_t, vm_page_t *);
-int vm_pageout_flush(vm_page_t *, int, int);
+int vm_pageout_flush(vm_page_t *, int, int, int, int *);
 void vm_pageout_oom(int shortage);
 #endif
 #endif	/* _VM_VM_PAGEOUT_H_ */


More information about the svn-src-all mailing list