svn commit: r337443 - head/sys/vm

Alan Cox alc at FreeBSD.org
Wed Aug 8 02:30:35 UTC 2018


Author: alc
Date: Wed Aug  8 02:30:34 2018
New Revision: 337443
URL: https://svnweb.freebsd.org/changeset/base/337443

Log:
  Defer and aggregate swap_pager_meta_build frees.
  
  Before swp_pager_meta_build replaces an old swapblk with an new one,
  it frees the old one.  To allow such freeing of blocks to be
  aggregated, have swp_pager_meta_build return the old swap block, and
  make the caller responsible for freeing it.
  
  Define a pair of short static functions, swp_pager_init_freerange and
  swp_pager_update_freerange, to do the initialization and updating of
  blk addresses and counters used in aggregating blocks to be freed.
  
  Submitted by:	Doug Moore <dougm at rice.edu>
  Reviewed by:	kib, markj (an earlier version)
  Tested by:	pho
  MFC after:	1 week
  Differential Revision:	https://reviews.freebsd.org/D13707

Modified:
  head/sys/vm/swap_pager.c

Modified: head/sys/vm/swap_pager.c
==============================================================================
--- head/sys/vm/swap_pager.c	Wed Aug  8 01:33:36 2018	(r337442)
+++ head/sys/vm/swap_pager.c	Wed Aug  8 02:30:34 2018	(r337443)
@@ -403,11 +403,32 @@ static daddr_t	swp_pager_getswapspace(int npages);
 /*
  * Metadata functions
  */
-static void swp_pager_meta_build(vm_object_t, vm_pindex_t, daddr_t);
+static daddr_t swp_pager_meta_build(vm_object_t, vm_pindex_t, daddr_t);
 static void swp_pager_meta_free(vm_object_t, vm_pindex_t, vm_pindex_t);
 static void swp_pager_meta_free_all(vm_object_t);
 static daddr_t swp_pager_meta_ctl(vm_object_t, vm_pindex_t, int);
 
+static void
+swp_pager_init_freerange(daddr_t *start, daddr_t *num)
+{
+
+	*start = SWAPBLK_NONE;
+	*num = 0;
+}
+
+static void
+swp_pager_update_freerange(daddr_t *start, daddr_t *num, daddr_t addr)
+{
+
+	if (*start + *num == addr) {
+		(*num)++;
+	} else {
+		swp_pager_freeswapspace(*start, *num);
+		*start = addr;
+		*num = 1;
+	}
+}
+
 static void *
 swblk_trie_alloc(struct pctrie *ptree)
 {
@@ -861,7 +882,9 @@ swap_pager_reserve(vm_object_t object, vm_pindex_t sta
 	int n = 0;
 	daddr_t blk = SWAPBLK_NONE;
 	vm_pindex_t beg = start;	/* save start index */
+	daddr_t addr, n_free, s_free;
 
+	swp_pager_init_freerange(&s_free, &n_free);
 	VM_OBJECT_WLOCK(object);
 	while (size) {
 		if (n == 0) {
@@ -875,12 +898,15 @@ swap_pager_reserve(vm_object_t object, vm_pindex_t sta
 				}
 			}
 		}
-		swp_pager_meta_build(object, start, blk);
+		addr = swp_pager_meta_build(object, start, blk);
+		if (addr != SWAPBLK_NONE)
+			swp_pager_update_freerange(&s_free, &n_free, addr);
 		--size;
 		++start;
 		++blk;
 		--n;
 	}
+	swp_pager_freeswapspace(s_free, n_free);
 	swp_pager_meta_free(object, start, n);
 	VM_OBJECT_WUNLOCK(object);
 	return (0);
@@ -910,7 +936,7 @@ swap_pager_copy(vm_object_t srcobject, vm_object_t dst
     vm_pindex_t offset, int destroysource)
 {
 	vm_pindex_t i;
-	daddr_t dstaddr, first_free, num_free, srcaddr;
+	daddr_t dstaddr, n_free, s_free, srcaddr;
 
 	VM_OBJECT_ASSERT_WLOCKED(srcobject);
 	VM_OBJECT_ASSERT_WLOCKED(dstobject);
@@ -937,42 +963,38 @@ swap_pager_copy(vm_object_t srcobject, vm_object_t dst
 	/*
 	 * Transfer source to destination.
 	 */
-	first_free = SWAPBLK_NONE;
-	num_free = 0;
+	swp_pager_init_freerange(&s_free, &n_free);
 	for (i = 0; i < dstobject->size; ++i) {
 		srcaddr = swp_pager_meta_ctl(srcobject, i + offset, SWM_POP);
 		if (srcaddr == SWAPBLK_NONE)
 			continue;
 		dstaddr = swp_pager_meta_ctl(dstobject, i, 0);
-		if (dstaddr == SWAPBLK_NONE) {
+		if (dstaddr != SWAPBLK_NONE) {
 			/*
-			 * Destination has no swapblk and is not resident,
-			 * copy source.
-			 *
-			 * swp_pager_meta_build() can sleep.
-			 */
-			vm_object_pip_add(srcobject, 1);
-			VM_OBJECT_WUNLOCK(srcobject);
-			vm_object_pip_add(dstobject, 1);
-			swp_pager_meta_build(dstobject, i, srcaddr);
-			vm_object_pip_wakeup(dstobject);
-			VM_OBJECT_WLOCK(srcobject);
-			vm_object_pip_wakeup(srcobject);
-		} else {
-			/*
 			 * Destination has valid swapblk or it is represented
-			 * by a resident page.  We destroy the sourceblock.
+			 * by a resident page.  We destroy the source block.
 			 */
-			if (first_free + num_free == srcaddr)
-				num_free++;
-			else {
-				swp_pager_freeswapspace(first_free, num_free);
-				first_free = srcaddr;
-				num_free = 1;
-			}
+			swp_pager_update_freerange(&s_free, &n_free, srcaddr);
+			continue;
 		}
+
+		/*
+		 * Destination has no swapblk and is not resident,
+		 * copy source.
+		 *
+		 * swp_pager_meta_build() can sleep.
+		 */
+		vm_object_pip_add(srcobject, 1);
+		VM_OBJECT_WUNLOCK(srcobject);
+		vm_object_pip_add(dstobject, 1);
+		dstaddr = swp_pager_meta_build(dstobject, i, srcaddr);
+		KASSERT(dstaddr == SWAPBLK_NONE,
+		    ("Unexpected destination swapblk"));
+		vm_object_pip_wakeup(dstobject);
+		VM_OBJECT_WLOCK(srcobject);
+		vm_object_pip_wakeup(srcobject);
 	}
-	swp_pager_freeswapspace(first_free, num_free);
+	swp_pager_freeswapspace(s_free, n_free);
 
 	/*
 	 * Free left over swap blocks in source.
@@ -1307,7 +1329,9 @@ swap_pager_putpages(vm_object_t object, vm_page_t *ma,
 {
 	int i, n;
 	boolean_t sync;
+	daddr_t addr, n_free, s_free;
 
+	swp_pager_init_freerange(&s_free, &n_free);
 	if (count && ma[0]->object != object) {
 		panic("swap_pager_putpages: object mismatch %p/%p",
 		    object,
@@ -1322,8 +1346,11 @@ swap_pager_putpages(vm_object_t object, vm_page_t *ma,
 	 * check for bogus sysops
 	 * force sync if not pageout process
 	 */
-	if (object->type != OBJT_SWAP)
-		swp_pager_meta_build(object, 0, SWAPBLK_NONE);
+	if (object->type != OBJT_SWAP) {
+		addr = swp_pager_meta_build(object, 0, SWAPBLK_NONE);
+		KASSERT(addr == SWAPBLK_NONE,
+		    ("unexpected object swap block"));
+	}
 	VM_OBJECT_WUNLOCK(object);
 
 	n = 0;
@@ -1391,11 +1418,11 @@ swap_pager_putpages(vm_object_t object, vm_page_t *ma,
 		for (j = 0; j < n; ++j) {
 			vm_page_t mreq = ma[i+j];
 
-			swp_pager_meta_build(
-			    mreq->object,
-			    mreq->pindex,
-			    blk + j
-			);
+			addr = swp_pager_meta_build(mreq->object, mreq->pindex,
+			    blk + j);
+			if (addr != SWAPBLK_NONE)
+				swp_pager_update_freerange(&s_free, &n_free,
+				    addr);
 			MPASS(mreq->dirty == VM_PAGE_BITS_ALL);
 			mreq->oflags |= VPO_SWAPINPROG;
 			bp->b_pages[j] = mreq;
@@ -1453,6 +1480,7 @@ swap_pager_putpages(vm_object_t object, vm_page_t *ma,
 		swp_pager_async_iodone(bp);
 	}
 	VM_OBJECT_WLOCK(object);
+	swp_pager_freeswapspace(s_free, n_free);
 }
 
 /*
@@ -1783,14 +1811,15 @@ swp_pager_swblk_empty(struct swblk *sb, int start, int
  *
  *	The specified swapblk is added to the object's swap metadata.  If
  *	the swapblk is not valid, it is freed instead.  Any previously
- *	assigned swapblk is freed.
+ *	assigned swapblk is returned.
  */
-static void
+static daddr_t
 swp_pager_meta_build(vm_object_t object, vm_pindex_t pindex, daddr_t swapblk)
 {
 	static volatile int swblk_zone_exhausted, swpctrie_zone_exhausted;
 	struct swblk *sb, *sb1;
 	vm_pindex_t modpi, rdpi;
+	daddr_t prev_swapblk;
 	int error, i;
 
 	VM_OBJECT_ASSERT_WLOCKED(object);
@@ -1815,7 +1844,7 @@ swp_pager_meta_build(vm_object_t object, vm_pindex_t p
 	sb = SWAP_PCTRIE_LOOKUP(&object->un_pager.swp.swp_blks, rdpi);
 	if (sb == NULL) {
 		if (swapblk == SWAPBLK_NONE)
-			return;
+			return (SWAPBLK_NONE);
 		for (;;) {
 			sb = uma_zalloc(swblk_zone, M_NOWAIT | (curproc ==
 			    pageproc ? M_USE_RESERVE : 0));
@@ -1882,9 +1911,8 @@ allocated:
 	MPASS(sb->p == rdpi);
 
 	modpi = pindex % SWAP_META_PAGES;
-	/* Delete prior contents of metadata. */
-	if (sb->d[modpi] != SWAPBLK_NONE)
-		swp_pager_freeswapspace(sb->d[modpi], 1);
+	/* Return prior contents of metadata. */
+	prev_swapblk = sb->d[modpi];
 	/* Enter block into metadata. */
 	sb->d[modpi] = swapblk;
 
@@ -1896,6 +1924,7 @@ allocated:
 		SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks, rdpi);
 		uma_zfree(swblk_zone, sb);
 	}
+	return (prev_swapblk);
 }
 
 /*
@@ -1912,7 +1941,7 @@ static void
 swp_pager_meta_free(vm_object_t object, vm_pindex_t pindex, vm_pindex_t count)
 {
 	struct swblk *sb;
-	daddr_t first_free, num_free;
+	daddr_t n_free, s_free;
 	vm_pindex_t last;
 	int i, limit, start;
 
@@ -1920,8 +1949,7 @@ swp_pager_meta_free(vm_object_t object, vm_pindex_t pi
 	if (object->type != OBJT_SWAP || count == 0)
 		return;
 
-	first_free = SWAPBLK_NONE;
-	num_free = 0;
+	swp_pager_init_freerange(&s_free, &n_free);
 	last = pindex + count;
 	for (;;) {
 		sb = SWAP_PCTRIE_LOOKUP_GE(&object->un_pager.swp.swp_blks,
@@ -1934,13 +1962,7 @@ swp_pager_meta_free(vm_object_t object, vm_pindex_t pi
 		for (i = start; i < limit; i++) {
 			if (sb->d[i] == SWAPBLK_NONE)
 				continue;
-			if (first_free + num_free == sb->d[i])
-				num_free++;
-			else {
-				swp_pager_freeswapspace(first_free, num_free);
-				first_free = sb->d[i];
-				num_free = 1;
-			}
+			swp_pager_update_freerange(&s_free, &n_free, sb->d[i]);
 			sb->d[i] = SWAPBLK_NONE;
 		}
 		if (swp_pager_swblk_empty(sb, 0, start) &&
@@ -1951,7 +1973,7 @@ swp_pager_meta_free(vm_object_t object, vm_pindex_t pi
 		}
 		pindex = sb->p + SWAP_META_PAGES;
 	}
-	swp_pager_freeswapspace(first_free, num_free);
+	swp_pager_freeswapspace(s_free, n_free);
 }
 
 /*
@@ -1964,7 +1986,7 @@ static void
 swp_pager_meta_free_all(vm_object_t object)
 {
 	struct swblk *sb;
-	daddr_t first_free, num_free;
+	daddr_t n_free, s_free;
 	vm_pindex_t pindex;
 	int i;
 
@@ -1972,26 +1994,19 @@ swp_pager_meta_free_all(vm_object_t object)
 	if (object->type != OBJT_SWAP)
 		return;
 
-	first_free = SWAPBLK_NONE;
-	num_free = 0;
+	swp_pager_init_freerange(&s_free, &n_free);
 	for (pindex = 0; (sb = SWAP_PCTRIE_LOOKUP_GE(
 	    &object->un_pager.swp.swp_blks, pindex)) != NULL;) {
 		pindex = sb->p + SWAP_META_PAGES;
 		for (i = 0; i < SWAP_META_PAGES; i++) {
 			if (sb->d[i] == SWAPBLK_NONE)
 				continue;
-			if (first_free + num_free == sb->d[i])
-				num_free++;
-			else {
-				swp_pager_freeswapspace(first_free, num_free);
-				first_free = sb->d[i];
-				num_free = 1;
-			}
+			swp_pager_update_freerange(&s_free, &n_free, sb->d[i]);
 		}
 		SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks, sb->p);
 		uma_zfree(swblk_zone, sb);
 	}
-	swp_pager_freeswapspace(first_free, num_free);
+	swp_pager_freeswapspace(s_free, n_free);
 }
 
 /*


More information about the svn-src-head mailing list