Index: sys/vm/swap_pager.c
===================================================================
--- sys/vm/swap_pager.c
+++ sys/vm/swap_pager.c
@@ -2216,33 +2216,62 @@
 	start = (sb != NULL && sb->p < pindex) ? pindex - sb->p : 0;
 	for (; sb != NULL;
 	    sb = swblk_start_limit(srcobject, pindex, last), start = 0) {
-		limit = MIN(last - sb->p, SWAP_META_PAGES);
-		for (i = start; i < limit; i++) {
+		daddr_t	d[SWAP_META_PAGES];
+		int d_mask = 0;
+
+		pindex = sb->p;
+		limit = MIN(last - pindex, SWAP_META_PAGES);
+		for (i = start; i < limit; i++, pindex += SWAP_META_PAGES) {
 			if (sb->d[i] == SWAPBLK_NONE)
 				continue;
 			blk = swp_pager_meta_build(dstobject,
-			    sb->p + i - offset, sb->d[i], true);
+			    pindex + i - offset, sb->d[i], true);
 			if (blk == sb->d[i]) {
 				/*
 				 * Destination has no swapblk and is not
-				 * resident, so transfer source.
+				 * resident, so transfer source.  But
 				 * swp_pager_meta_build() failed memory
 				 * allocation already, likely to sleep in retry.
 				 */
-				VM_OBJECT_WUNLOCK(srcobject);
-				swp_pager_meta_build(dstobject,
-				    sb->p + i - offset, sb->d[i], false);
-				VM_OBJECT_WLOCK(srcobject);
+				d[i] = blk;
+				d_mask |= 1 << i;
 			} else if (blk != SWAPBLK_NONE)
 				swp_pager_update_freerange(&range, sb->d[i]);
 			sb->d[i] = SWAPBLK_NONE;
 		}
-		pindex = sb->p + SWAP_META_PAGES;
 		if (swp_pager_swblk_empty(sb, 0, start) &&
 		    swp_pager_swblk_empty(sb, limit, SWAP_META_PAGES)) {
 			swblk_lookup_remove(srcobject, sb);
 			uma_zfree(swblk_zone, sb);
 		}
+
+		/*
+		 * Try transferring  un-transferred blocks again, since it's
+		 * likely that just-freed memory will allow success this time,
+		 * without releasing the write lock.
+		 */
+		while (d_mask != 0) {
+			i = ffs(d_mask) - 1;
+			blk = swp_pager_meta_build(dstobject,
+			    pindex + i - offset, d[i], true);
+			if (blk == d[i])
+				break;
+			d_mask ^= 1 << i;
+		}
+		if (d_mask == 0)
+			continue;
+
+		/*
+		 * Finish transferring, with the lock released.
+		 */
+		VM_OBJECT_WUNLOCK(srcobject);
+		do {
+			i = ffs(d_mask) - 1;
+			swp_pager_meta_build(dstobject,
+			    pindex + i - offset, d[i], false);
+			d_mask ^= 1 << i;
+		} while (d_mask != 0);
+		VM_OBJECT_WLOCK(srcobject);
 	}
 	swp_pager_freeswapspace(&range);
 }