svn commit: r311008 - stable/11/sys/vm

Konstantin Belousov kib at FreeBSD.org
Sun Jan 1 11:38:36 UTC 2017


Author: kib
Date: Sun Jan  1 11:38:34 2017
New Revision: 311008
URL: https://svnweb.freebsd.org/changeset/base/311008

Log:
  MFC r310234:
  Improve vm_object_scan_all_shadowed() to also check swap backing objects.

Modified:
  stable/11/sys/vm/swap_pager.c
  stable/11/sys/vm/swap_pager.h
  stable/11/sys/vm/vm_object.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/vm/swap_pager.c
==============================================================================
--- stable/11/sys/vm/swap_pager.c	Sun Jan  1 11:19:17 2017	(r311007)
+++ stable/11/sys/vm/swap_pager.c	Sun Jan  1 11:38:34 2017	(r311008)
@@ -2010,6 +2010,44 @@ swp_pager_meta_ctl(vm_object_t object, v
 }
 
 /*
+ * Returns the least page index which is greater than or equal to the
+ * parameter pindex and for which there is a swap block allocated.
+ * Returns object's size if the object's type is not swap or if there
+ * are no allocated swap blocks for the object after the requested
+ * pindex.
+ */
+vm_pindex_t
+swap_pager_find_least(vm_object_t object, vm_pindex_t pindex)
+{
+	struct swblock **pswap, *swap;
+	vm_pindex_t i, j, lim;
+	int idx;
+
+	VM_OBJECT_ASSERT_LOCKED(object);
+	if (object->type != OBJT_SWAP || object->un_pager.swp.swp_bcount == 0)
+		return (object->size);
+
+	mtx_lock(&swhash_mtx);
+	for (j = pindex; j < object->size; j = lim) {
+		pswap = swp_pager_hash(object, j);
+		lim = rounddown2(j + SWAP_META_PAGES, SWAP_META_PAGES);
+		if (lim > object->size)
+			lim = object->size;
+		if ((swap = *pswap) != NULL) {
+			for (idx = j & SWAP_META_MASK, i = j; i < lim;
+			    i++, idx++) {
+				if (swap->swb_pages[idx] != SWAPBLK_NONE)
+					goto found;
+			}
+		}
+	}
+	i = object->size;
+found:
+	mtx_unlock(&swhash_mtx);
+	return (i);
+}
+
+/*
  * System call swapon(name) enables swapping on device name,
  * which must be in the swdevsw.  Return EBUSY
  * if already swapping on this device.

Modified: stable/11/sys/vm/swap_pager.h
==============================================================================
--- stable/11/sys/vm/swap_pager.h	Sun Jan  1 11:19:17 2017	(r311007)
+++ stable/11/sys/vm/swap_pager.h	Sun Jan  1 11:38:34 2017	(r311008)
@@ -79,6 +79,7 @@ extern int swap_pager_avail;
 struct xswdev;
 int swap_dev_info(int name, struct xswdev *xs, char *devname, size_t len);
 void swap_pager_copy(vm_object_t, vm_object_t, vm_pindex_t, int);
+vm_pindex_t swap_pager_find_least(vm_object_t object, vm_pindex_t pindex);
 void swap_pager_freespace(vm_object_t, vm_pindex_t, vm_size_t);
 void swap_pager_swap_init(void);
 int swap_pager_isswapped(vm_object_t, struct swdevt *);

Modified: stable/11/sys/vm/vm_object.c
==============================================================================
--- stable/11/sys/vm/vm_object.c	Sun Jan  1 11:19:17 2017	(r311007)
+++ stable/11/sys/vm/vm_object.c	Sun Jan  1 11:38:34 2017	(r311008)
@@ -1464,36 +1464,40 @@ vm_object_scan_all_shadowed(vm_object_t 
 {
 	vm_object_t backing_object;
 	vm_page_t p, pp;
-	vm_pindex_t backing_offset_index, new_pindex;
+	vm_pindex_t backing_offset_index, new_pindex, pi, ps;
 
 	VM_OBJECT_ASSERT_WLOCKED(object);
 	VM_OBJECT_ASSERT_WLOCKED(object->backing_object);
 
 	backing_object = object->backing_object;
 
-	/*
-	 * Initial conditions:
-	 *
-	 * We do not want to have to test for the existence of cache or swap
-	 * pages in the backing object.  XXX but with the new swapper this
-	 * would be pretty easy to do.
-	 */
-	if (backing_object->type != OBJT_DEFAULT)
+	if (backing_object->type != OBJT_DEFAULT &&
+	    backing_object->type != OBJT_SWAP)
 		return (false);
 
-	backing_offset_index = OFF_TO_IDX(object->backing_object_offset);
+	pi = backing_offset_index = OFF_TO_IDX(object->backing_object_offset);
+	p = vm_page_find_least(backing_object, pi);
+	ps = swap_pager_find_least(backing_object, pi);
 
-	for (p = TAILQ_FIRST(&backing_object->memq); p != NULL;
-	    p = TAILQ_NEXT(p, listq)) {
-		new_pindex = p->pindex - backing_offset_index;
+	/*
+	 * Only check pages inside the parent object's range and
+	 * inside the parent object's mapping of the backing object.
+	 */
+	for (;; pi++) {
+		if (p != NULL && p->pindex < pi)
+			p = TAILQ_NEXT(p, listq);
+		if (ps < pi)
+			ps = swap_pager_find_least(backing_object, pi);
+		if (p == NULL && ps >= backing_object->size)
+			break;
+		else if (p == NULL)
+			pi = ps;
+		else
+			pi = MIN(p->pindex, ps);
 
-		/*
-		 * Ignore pages outside the parent object's range and outside
-		 * the parent object's mapping of the backing object.
-		 */
-		if (p->pindex < backing_offset_index ||
-		    new_pindex >= object->size)
-			continue;
+		new_pindex = pi - backing_offset_index;
+		if (new_pindex >= object->size)
+			break;
 
 		/*
 		 * See if the parent has the page or if the parent's object


More information about the svn-src-all mailing list