--- old/usr/src/cmd/zfs/zfs_main.c	Tue Aug  7 18:11:16 2012
+++ new/usr/src/cmd/zfs/zfs_main.c	Tue Aug  7 18:11:15 2012
@@ -252,7 +252,7 @@
 	case HELP_ROLLBACK:
 		return (gettext("\trollback [-rRf] <snapshot>\n"));
 	case HELP_SEND:
-		return (gettext("\tsend [-DnPpRrv] [-[iI] snapshot] "
+		return (gettext("\tsend [-DnPpRrvs] [-[iI] snapshot] "
 		    "<snapshot>\n"));
 	case HELP_SET:
 		return (gettext("\tset <property=value> "
@@ -3552,7 +3552,7 @@
 	boolean_t extraverbose = B_FALSE;
 
 	/* check options */
-	while ((c = getopt(argc, argv, ":i:I:RDpvnP")) != -1) {
+	while ((c = getopt(argc, argv, ":i:I:RDpvnPs")) != -1) {
 		switch (c) {
 		case 'i':
 			if (fromname)
@@ -3587,6 +3587,9 @@
 		case 'n':
 			flags.dryrun = B_TRUE;
 			break;
+		case 's':
+			flags.sendsize = B_TRUE;
+			break;
 		case ':':
 			(void) fprintf(stderr, gettext("missing argument for "
 			    "'%c' option\n"), optopt);
@@ -3612,7 +3615,10 @@
 		usage(B_FALSE);
 	}
 
-	if (!flags.dryrun && isatty(STDOUT_FILENO)) {
+	if (flags.sendsize) {
+		(void) close(STDOUT_FILENO);
+		(void) open("/dev/null", O_WRONLY|O_LARGEFILE);
+	} else if (!flags.dryrun && isatty(STDOUT_FILENO)) {
 		(void) fprintf(stderr,
 		    gettext("Error: Stream can not be written to a terminal.\n"
 		    "You must redirect standard output.\n"));
--- old/usr/src/lib/libzfs/common/libzfs.h	Tue Aug  7 18:11:25 2012
+++ new/usr/src/lib/libzfs/common/libzfs.h	Tue Aug  7 18:11:23 2012
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2012 by Delphix. All rights reserved.
  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  */
@@ -580,6 +580,9 @@
 	/* do not send (no-op, ie. -n) */
 	boolean_t dryrun;
 
+	/* do not send (just calculate exact send stream size, ie. -s */
+	boolean_t sendsize;
+
 	/* parsable verbose output (ie. -P) */
 	boolean_t parsable;
 
--- old/usr/src/lib/libzfs/common/libzfs_sendrecv.c	Tue Aug  7 18:11:36 2012
+++ new/usr/src/lib/libzfs/common/libzfs_sendrecv.c	Tue Aug  7 18:11:29 2012
@@ -23,6 +23,7 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012 by Delphix. All rights reserved.
  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  */
 
 #include <assert.h>
@@ -61,6 +62,8 @@
 typedef struct dedup_arg {
 	int	inputfd;
 	int	outputfd;
+	uint64_t	dedup_data_sz;
+	boolean_t	sendsize;
 	libzfs_handle_t  *dedup_hdl;
 } dedup_arg_t;
 
@@ -184,6 +187,24 @@
 }
 
 /*
+ * the function used by the cksummer thread that needs to know
+ * about the sendsize flag
+ */
+static int
+dedup_cksum_and_write(dedup_arg_t *dda, const void *buf, uint64_t len,
+    zio_cksum_t *zc, int outfd)
+{
+	int ret = len;
+
+	dda->dedup_data_sz += len;
+	fletcher_4_incremental_native(buf, len, zc);
+	if (!dda->sendsize)
+		ret = (write(outfd, buf, len));
+
+	return (ret);
+}
+
+/*
  * This function is started in a separate thread when the dedup option
  * has been requested.  The main send thread determines the list of
  * snapshots to be included in the send stream and makes the ioctl calls
@@ -261,7 +282,8 @@
 			    DMU_BACKUP_FEATURE_DEDUPPROPS);
 			DMU_SET_FEATUREFLAGS(drrb->drr_versioninfo, fflags);
 
-			if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
+			if (dedup_cksum_and_write(dda, drr,
+			    sizeof (dmu_replay_record_t),
 			    &stream_cksum, outfd) == -1)
 				goto out;
 			if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
@@ -275,8 +297,8 @@
 				(void) ssread(buf, sz, ofp);
 				if (ferror(stdin))
 					perror("fread");
-				if (cksum_and_write(buf, sz, &stream_cksum,
-				    outfd) == -1)
+				if (dedup_cksum_and_write(dda, buf, sz,
+				    &stream_cksum, outfd) == -1)
 					goto out;
 			}
 			break;
@@ -291,12 +313,14 @@
 			if ((write(outfd, drr,
 			    sizeof (dmu_replay_record_t))) == -1)
 				goto out;
+			dda->dedup_data_sz += sizeof (dmu_replay_record_t);
 			break;
 		}
 
 		case DRR_OBJECT:
 		{
-			if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
+			if (dedup_cksum_and_write(dda, drr,
+			    sizeof (dmu_replay_record_t),
 			    &stream_cksum, outfd) == -1)
 				goto out;
 			if (drro->drr_bonuslen > 0) {
@@ -303,7 +327,7 @@
 				(void) ssread(buf,
 				    P2ROUNDUP((uint64_t)drro->drr_bonuslen, 8),
 				    ofp);
-				if (cksum_and_write(buf,
+				if (dedup_cksum_and_write(dda, buf,
 				    P2ROUNDUP((uint64_t)drro->drr_bonuslen, 8),
 				    &stream_cksum, outfd) == -1)
 					goto out;
@@ -313,11 +337,12 @@
 
 		case DRR_SPILL:
 		{
-			if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
+			if (dedup_cksum_and_write(dda, drr,
+			    sizeof (dmu_replay_record_t),
 			    &stream_cksum, outfd) == -1)
 				goto out;
 			(void) ssread(buf, drrs->drr_length, ofp);
-			if (cksum_and_write(buf, drrs->drr_length,
+			if (dedup_cksum_and_write(dda, buf, drrs->drr_length,
 			    &stream_cksum, outfd) == -1)
 				goto out;
 			break;
@@ -325,7 +350,8 @@
 
 		case DRR_FREEOBJECTS:
 		{
-			if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
+			if (dedup_cksum_and_write(dda, drr,
+			    sizeof (dmu_replay_record_t),
 			    &stream_cksum, outfd) == -1)
 				goto out;
 			break;
@@ -390,17 +416,17 @@
 				wbr_drrr->drr_key.ddk_prop =
 				    drrw->drr_key.ddk_prop;
 
-				if (cksum_and_write(&wbr_drr,
+				if (dedup_cksum_and_write(dda, &wbr_drr,
 				    sizeof (dmu_replay_record_t), &stream_cksum,
 				    outfd) == -1)
 					goto out;
 			} else {
 				/* block not previously seen */
-				if (cksum_and_write(drr,
+				if (dedup_cksum_and_write(dda, drr,
 				    sizeof (dmu_replay_record_t), &stream_cksum,
 				    outfd) == -1)
 					goto out;
-				if (cksum_and_write(buf,
+				if (dedup_cksum_and_write(dda, buf,
 				    drrw->drr_length,
 				    &stream_cksum, outfd) == -1)
 					goto out;
@@ -410,7 +436,8 @@
 
 		case DRR_FREE:
 		{
-			if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
+			if (dedup_cksum_and_write(dda, drr,
+			    sizeof (dmu_replay_record_t),
 			    &stream_cksum, outfd) == -1)
 				goto out;
 			break;
@@ -789,7 +816,10 @@
 	char prevsnap[ZFS_MAXNAMELEN];
 	uint64_t prevsnap_obj;
 	boolean_t seenfrom, seento, replicate, doall, fromorigin;
-	boolean_t verbose, dryrun, parsable, progress;
+	boolean_t verbose, dryrun, dedup, parsable, progress;
+	boolean_t sendsize;
+	uint32_t hdr_send_sz;
+	uint64_t send_sz;
 	int outfd;
 	boolean_t err;
 	nvlist_t *fss;
@@ -868,7 +898,8 @@
  */
 static int
 dump_ioctl(zfs_handle_t *zhp, const char *fromsnap, uint64_t fromsnap_obj,
-    boolean_t fromorigin, int outfd, nvlist_t *debugnv)
+    boolean_t fromorigin, int outfd, nvlist_t *debugnv,
+    boolean_t sendsize, uint64_t *sendcounter)
 {
 	zfs_cmd_t zc = { 0 };
 	libzfs_handle_t *hdl = zhp->zfs_hdl;
@@ -882,6 +913,8 @@
 	zc.zc_obj = fromorigin;
 	zc.zc_sendobj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID);
 	zc.zc_fromobj = fromsnap_obj;
+	zc.zc_sendsize = sendsize;
+	zc.zc_sendcounter = 0;
 
 	VERIFY(0 == nvlist_alloc(&thisdbg, NV_UNIQUE_NAME, 0));
 	if (fromsnap && fromsnap[0] != '\0') {
@@ -935,6 +968,7 @@
 		}
 	}
 
+	*sendcounter = (uint64_t)zc.zc_sendcounter;
 	if (debugnv)
 		VERIFY(0 == nvlist_add_nvlist(debugnv, zhp->zfs_name, thisdbg));
 	nvlist_free(thisdbg);
@@ -1117,11 +1151,9 @@
 	fromorigin = sdd->prevsnap[0] == '\0' &&
 	    (sdd->fromorigin || sdd->replicate);
 
+	/* print out to-from and approximate size in verbose mode */
 	if (sdd->verbose) {
-		uint64_t size;
-		err = estimate_ioctl(zhp, sdd->prevsnap_obj,
-		    fromorigin, &size);
-
+		/* print preamble */
 		if (sdd->parsable) {
 			if (sdd->prevsnap[0] != '\0') {
 				(void) fprintf(stderr, "incremental\t%s\t%s",
@@ -1135,28 +1167,50 @@
 			    "send from @%s to %s"),
 			    sdd->prevsnap, zhp->zfs_name);
 		}
-		if (err == 0) {
-			if (sdd->parsable) {
-				(void) fprintf(stderr, "\t%llu\n",
-				    (longlong_t)size);
+
+		if (sdd->sendsize) {
+			/*
+			 * we are going to print out the exact stream size info,
+			 * so skip the estimate
+			 */
+			(void) fprintf(stderr, "\n");
+		} else {
+			/*
+			 * provide stream size estimate otherwise
+			 */
+			uint64_t size;
+			err = estimate_ioctl(zhp, sdd->prevsnap_obj,
+			    fromorigin, &size);
+
+			if (err == 0) {
+				if (sdd->parsable) {
+					(void) fprintf(stderr, "\t%llu\n",
+					    (longlong_t)size);
+				} else {
+					char buf[16];
+					zfs_nicenum(size, buf, sizeof (buf));
+					(void) fprintf(stderr,
+					    dgettext(TEXT_DOMAIN,
+					    " estimated size is %s\n"),
+					    buf);
+				}
+				sdd->size += size;
 			} else {
-				char buf[16];
-				zfs_nicenum(size, buf, sizeof (buf));
-				(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
-				    " estimated size is %s\n"), buf);
+				/* could not estimate */
+				(void) fprintf(stderr, "\n");
 			}
-			sdd->size += size;
-		} else {
-			(void) fprintf(stderr, "\n");
 		}
 	}
 
 	if (!sdd->dryrun) {
+		uint64_t sendcounter = 0;
+		boolean_t track_progress = (sdd->progress && !sdd->sendsize);
+		boolean_t sendsize = B_FALSE;
 		/*
 		 * If progress reporting is requested, spawn a new thread to
 		 * poll ZFS_IOC_SEND_PROGRESS at a regular interval.
 		 */
-		if (sdd->progress) {
+		if (track_progress) {
 			pa.pa_zhp = zhp;
 			pa.pa_fd = sdd->outfd;
 			pa.pa_parsable = sdd->parsable;
@@ -1168,10 +1222,26 @@
 			}
 		}
 
+
+		/*
+		 * We need to reset the sendsize flag being sent to
+		 * kernel if sdd->dedup is set. With dedup, the file
+		 * descriptor sent to kernel is one end of the pipe,
+		 * and we would want the data back in the pipe for
+		 * cksummer() to calculate the exact size of the dedup-ed
+		 * stream. So reset the sendsize flag such that
+		 * kernel writes to the pipe.
+		 */
+
+		sendsize = sdd->dedup ? B_FALSE : sdd->sendsize;
+
 		err = dump_ioctl(zhp, sdd->prevsnap, sdd->prevsnap_obj,
-		    fromorigin, sdd->outfd, sdd->debugnv);
+		    fromorigin, sdd->outfd, sdd->debugnv,
+		    sendsize, &sendcounter);
 
-		if (sdd->progress) {
+		sdd->send_sz += sendcounter;
+
+		if (track_progress) {
 			(void) pthread_cancel(tid);
 			(void) pthread_join(tid, NULL);
 		}
@@ -1414,6 +1484,7 @@
 		dda.outputfd = outfd;
 		dda.inputfd = pipefd[1];
 		dda.dedup_hdl = zhp->zfs_hdl;
+		dda.sendsize = flags->sendsize;
 		if (err = pthread_create(&tid, NULL, cksummer, &dda)) {
 			(void) close(pipefd[0]);
 			(void) close(pipefd[1]);
@@ -1474,11 +1545,13 @@
 			    "%s@%s", zhp->zfs_name, tosnap);
 			drr.drr_payloadlen = buflen;
 			err = cksum_and_write(&drr, sizeof (drr), &zc, outfd);
+			sdd.hdr_send_sz += sizeof (drr);
 
 			/* write header nvlist */
 			if (err != -1 && packbuf != NULL) {
 				err = cksum_and_write(packbuf, buflen, &zc,
 				    outfd);
+				sdd.hdr_send_sz += buflen;
 			}
 			free(packbuf);
 			if (err == -1) {
@@ -1493,6 +1566,7 @@
 			drr.drr_type = DRR_END;
 			drr.drr_u.drr_end.drr_checksum = zc;
 			err = write(outfd, &drr, sizeof (drr));
+			sdd.hdr_send_sz += sizeof (drr);
 			if (err == -1) {
 				fsavl_destroy(fsavl);
 				nvlist_free(fss);
@@ -1517,6 +1591,8 @@
 	sdd.fss = fss;
 	sdd.fsavl = fsavl;
 	sdd.verbose = flags->verbose;
+	sdd.dedup = flags->dedup;
+	sdd.sendsize = flags->sendsize;
 	sdd.parsable = flags->parsable;
 	sdd.progress = flags->progress;
 	sdd.dryrun = flags->dryrun;
@@ -1547,7 +1623,7 @@
 	} else {
 		sdd.cleanup_fd = -1;
 	}
-	if (flags->verbose) {
+	if (flags->verbose && !flags->sendsize) {
 		/*
 		 * Do a verbose no-op dry run to get all the verbose output
 		 * before generating any data.  Then do a non-verbose real
@@ -1574,6 +1650,7 @@
 	if (flags->dedup) {
 		(void) close(pipefd[0]);
 		(void) pthread_join(tid, NULL);
+		sdd.send_sz = dda.dedup_data_sz;
 	}
 
 	if (sdd.cleanup_fd != -1) {
@@ -1594,7 +1671,22 @@
 			return (zfs_standard_error(zhp->zfs_hdl,
 			    errno, errbuf));
 		}
+		sdd.hdr_send_sz += sizeof (drr);
 	}
+
+	if (flags->sendsize) {
+		if (flags->verbose) {
+			fprintf(stderr, "Send stream header size (bytes): "
+			    "%u\n", sdd.hdr_send_sz);
+			fprintf(stderr, "Send stream data size (bytes):	 "
+			    "%llu\n", sdd.send_sz);
+			fprintf(stderr, "Total send stream size (bytes):  "
+			    "%llu\n", sdd.send_sz + (uint64_t)sdd.hdr_send_sz);
+		} else {
+			fprintf(stderr, "Total send stream size (bytes):  "
+			    "%llu\n", sdd.send_sz + (uint64_t)sdd.hdr_send_sz);
+		}
+	}
 
 	return (err || sdd.err);
 
--- old/usr/src/man/man1m/zfs.1m	Tue Aug  7 18:11:48 2012
+++ new/usr/src/man/man1m/zfs.1m	Tue Aug  7 18:11:43 2012
@@ -1,7 +1,7 @@
 '\" te
 .\" Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
 .\" Copyright (c) 2012 by Delphix. All rights reserved.
-.\" Copyright (c) 2012 Nexenta Systems, Inc. All Rights Reserved.
+.\" Copyright 2012 Nexenta Systems, Inc. All Rights Reserved.
 .\" Copyright (c) 2012, Joyent, Inc. All rights reserved.
 .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.
 .\"  See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with
@@ -144,7 +144,7 @@
 
 .LP
 .nf
-\fBzfs\fR \fBsend\fR [\fB-DnPpRrv\fR] [\fB-\fR[\fBiI\fR] \fIsnapshot\fR] \fIsnapshot\fR
+\fBzfs\fR \fBsend\fR [\fB-DnPpRrvs\fR] [\fB-\fR[\fBiI\fR] \fIsnapshot\fR] \fIsnapshot\fR
 .fi
 
 .LP
@@ -2720,7 +2720,7 @@
 .sp
 .ne 2
 .na
-\fBzfs send\fR [\fB-DnPpRrv\fR] [\fB-\fR[\fBiI\fR] \fIsnapshot\fR] \fIsnapshot\fR
+\fBzfs send\fR [\fB-DnPpRrvs\fR] [\fB-\fR[\fBiI\fR] \fIsnapshot\fR] \fIsnapshot\fR
 .ad
 .sp .6
 .RS 4n
@@ -2828,6 +2828,19 @@
 data will be sent.
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fB-s\fR\fR
+.ad
+.sp .6
+.RS 4n
+Calculate send stream size.  Do not generate any actual send data.  This is
+useful when one needs to know stream size in order to store the stream externally. 
+With \fB-v\fR specified, provides info on stream header and stream data portion 
+sizes, in addition to the total stream size.
+.RE
+
 .sp
 .ne 2
 .na
--- old/usr/src/uts/common/fs/zfs/dmu_send.c	Tue Aug  7 18:11:53 2012
+++ new/usr/src/uts/common/fs/zfs/dmu_send.c	Tue Aug  7 18:11:52 2012
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2012 by Delphix. All rights reserved.
  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  */
@@ -59,11 +59,14 @@
 	ssize_t resid; /* have to get resid to get detailed errno */
 	ASSERT3U(len % 8, ==, 0);
 
-	fletcher_4_incremental_native(buf, len, &dsp->dsa_zc);
-	dsp->dsa_err = vn_rdwr(UIO_WRITE, dsp->dsa_vp,
-	    (caddr_t)buf, len,
-	    0, UIO_SYSSPACE, FAPPEND, RLIM64_INFINITY, CRED(), &resid);
-
+	dsp->dsa_err = 0;
+	if (!dsp->sendsize) {
+		fletcher_4_incremental_native(buf, len, &dsp->dsa_zc);
+		dsp->dsa_err = vn_rdwr(UIO_WRITE, dsp->dsa_vp,
+		    (caddr_t)buf, len,
+		    0, UIO_SYSSPACE, FAPPEND, RLIM64_INFINITY,
+		    CRED(), &resid);
+	}
 	mutex_enter(&ds->ds_sendstream_lock);
 	*dsp->dsa_off += len;
 	mutex_exit(&ds->ds_sendstream_lock);
@@ -358,29 +361,36 @@
 		(void) arc_buf_remove_ref(abuf, &abuf);
 	} else { /* it's a level-0 block of a regular object */
 		uint32_t aflags = ARC_WAIT;
-		arc_buf_t *abuf;
+		arc_buf_t *abuf = NULL;
+		void *buf = NULL;
 		int blksz = BP_GET_LSIZE(bp);
 
-		if (dsl_read(NULL, spa, bp, pbuf,
-		    arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
-		    ZIO_FLAG_CANFAIL, &aflags, zb) != 0) {
-			if (zfs_send_corrupt_data) {
+		if (!dsp->sendsize) {
+			if (dsl_read(NULL, spa, bp, pbuf,
+			    arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
+			    ZIO_FLAG_CANFAIL, &aflags, zb) != 0) {
+				if (zfs_send_corrupt_data) {
 				/* Send a block filled with 0x"zfs badd bloc" */
-				abuf = arc_buf_alloc(spa, blksz, &abuf,
-				    ARC_BUFC_DATA);
-				uint64_t *ptr;
-				for (ptr = abuf->b_data;
-				    (char *)ptr < (char *)abuf->b_data + blksz;
-				    ptr++)
-					*ptr = 0x2f5baddb10c;
-			} else {
-				return (EIO);
+					abuf = arc_buf_alloc(spa, blksz, &abuf,
+					    ARC_BUFC_DATA);
+					uint64_t *ptr;
+					for (ptr = abuf->b_data;
+					    (char *)ptr <
+					    (char *)abuf->b_data + blksz;
+					    ptr++)
+						*ptr = 0x2f5baddb10c;
+				} else {
+					return (EIO);
+				}
 			}
+			buf = abuf->b_data;
 		}
 
 		err = dump_data(dsp, type, zb->zb_object, zb->zb_blkid * blksz,
-		    blksz, bp, abuf->b_data);
-		(void) arc_buf_remove_ref(abuf, &abuf);
+		    blksz, bp, buf);
+		if (!dsp->sendsize) {
+			(void) arc_buf_remove_ref(abuf, &abuf);
+		}
 	}
 
 	ASSERT(err == 0 || err == EINTR);
@@ -426,9 +436,10 @@
 	return (ret);
 }
 
+
 int
 dmu_send(objset_t *tosnap, objset_t *fromsnap, int outfd, vnode_t *vp,
-    offset_t *off)
+    offset_t *off, boolean_t sendsize)
 {
 	dsl_dataset_t *ds = tosnap->os_dsl_dataset;
 	dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;
@@ -496,6 +507,7 @@
 	dsp->dsa_toguid = ds->ds_phys->ds_guid;
 	ZIO_SET_CHECKSUM(&dsp->dsa_zc, 0, 0, 0, 0);
 	dsp->dsa_pending_op = PENDING_NONE;
+	dsp->sendsize = sendsize;
 
 	mutex_enter(&ds->ds_sendstream_lock);
 	list_insert_head(&ds->ds_sendstreams, dsp);
@@ -506,8 +518,15 @@
 		goto out;
 	}
 
-	err = traverse_dataset(ds, fromtxg, TRAVERSE_PRE | TRAVERSE_PREFETCH,
-	    backup_cb, dsp);
+	if (dsp->sendsize) {
+		err = traverse_dataset(ds, fromtxg,
+		    TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA,
+		    backup_cb, dsp);
+	} else {
+		err = traverse_dataset(ds,
+		    fromtxg, TRAVERSE_PRE | TRAVERSE_PREFETCH,
+		    backup_cb, dsp);
+	}
 
 	if (dsp->dsa_pending_op != PENDING_NONE)
 		if (dump_bytes(dsp, drr, sizeof (dmu_replay_record_t)) != 0)
--- old/usr/src/uts/common/fs/zfs/sys/dmu.h	Tue Aug  7 18:11:57 2012
+++ new/usr/src/uts/common/fs/zfs/sys/dmu.h	Tue Aug  7 18:11:54 2012
@@ -22,7 +22,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012 by Delphix. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  */
 
@@ -783,7 +783,7 @@
     dmu_traverse_cb_t cb, void *arg);
 
 int dmu_send(objset_t *tosnap, objset_t *fromsnap,
-    int outfd, struct vnode *vp, offset_t *off);
+    int outfd, struct vnode *vp, offset_t *off, boolean_t sendsize);
 int dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, uint64_t *sizep);
 
 typedef struct dmu_recv_cookie {
--- old/usr/src/uts/common/fs/zfs/sys/dmu_impl.h	Tue Aug  7 18:12:01 2012
+++ new/usr/src/uts/common/fs/zfs/sys/dmu_impl.h	Tue Aug  7 18:12:00 2012
@@ -22,6 +22,7 @@
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  */
 
 #ifndef _SYS_DMU_IMPL_H
@@ -290,6 +291,7 @@
 	uint64_t dsa_toguid;
 	int dsa_err;
 	dmu_pendop_t dsa_pending_op;
+	boolean_t sendsize;
 } dmu_sendarg_t;
 
 
--- old/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h	Tue Aug  7 18:12:07 2012
+++ new/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h	Tue Aug  7 18:12:03 2012
@@ -21,6 +21,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright 2012, Nexenta Systems Inc. All rights reserved.
  */
 
 #ifndef	_SYS_ZFS_IOCTL_H
@@ -305,6 +306,8 @@
 	uint64_t	zc_fromobj;
 	uint64_t	zc_createtxg;
 	zfs_stat_t	zc_stat;
+	uint64_t	zc_sendcounter;
+	boolean_t	zc_sendsize;
 } zfs_cmd_t;
 
 typedef struct zfs_useracct {
--- old/usr/src/uts/common/fs/zfs/zfs_ioctl.c	Tue Aug  7 18:12:12 2012
+++ new/usr/src/uts/common/fs/zfs/zfs_ioctl.c	Tue Aug  7 18:12:11 2012
@@ -22,7 +22,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Portions Copyright 2011 Martin Matuska
- * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  * Copyright (c) 2012 by Delphix. All rights reserved.
  */
@@ -3172,7 +3172,7 @@
 	if (cbfunc == NULL)
 		return (EINVAL);
 
-	if (zfs_get_parent(name, parent, MAXNAMELEN) == 0 &&
+	if (zfs_get_parent(fsname, parent, MAXNAMELEN) == 0 &&
 	    zfs_is_wormed(parent)) {
 		return (EPERM);
 	}
@@ -4188,6 +4188,7 @@
 		error = dmu_send_estimate(tosnap, fromsnap,
 		    &zc->zc_objset_type);
 	} else {
+		offset_t off_starting;
 		file_t *fp = getf(zc->zc_cookie);
 		if (fp == NULL) {
 			dsl_dataset_rele(ds, FTAG);
@@ -4197,9 +4198,11 @@
 		}
 
 		off = fp->f_offset;
-		error = dmu_send(tosnap, fromsnap,
-		    zc->zc_cookie, fp->f_vnode, &off);
+		off_starting = off;
+		error = dmu_send(tosnap, fromsnap, zc->zc_cookie, fp->f_vnode,
+		    &off, zc->zc_sendsize);
 
+		zc->zc_sendcounter = off - off_starting;
 		if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
 			fp->f_offset = off;
 		releasef(zc->zc_cookie);
@@ -5172,7 +5175,7 @@
 	}
 
 	off = fp->f_offset;
-	error = dmu_send(tosnap, fromsnap, fd, fp->f_vnode, &off);
+	error = dmu_send(tosnap, fromsnap, fd, fp->f_vnode, &off, B_FALSE);
 
 	if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
 		fp->f_offset = off;
