changeset 11668:707c4515580e

6885979 zfs_send -R fails to send snapshots that get renamed during the operation 6926290 zfs_hold_range() should handle fromsnap == NULL 6926291 In zfs_send(), errno can get clobbered before we use it
author Chris Kirby <Chris.Kirby@sun.com>
date Wed, 17 Feb 2010 11:41:36 -0700
parents 57af99420adf
children 573bcdd6e9c2
files usr/src/lib/libzfs/common/libzfs_dataset.c usr/src/lib/libzfs/common/libzfs_sendrecv.c
diffstat 2 files changed, 19 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c	Tue Feb 16 23:03:39 2010 -0800
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c	Wed Feb 17 11:41:36 2010 -0700
@@ -4078,6 +4078,7 @@
 	arg.temphold = temphold;
 	arg.holding = B_TRUE;
 	arg.recursive = recursive;
+	arg.seenfrom = (fromsnap == NULL);
 
 	error = zfs_iter_snapshots_sorted(zhp, zfs_hold_range_one, &arg);
 
@@ -4147,6 +4148,7 @@
 	arg.tosnap = tosnap;
 	arg.tag = tag;
 	arg.recursive = recursive;
+	arg.seenfrom = (fromsnap == NULL);
 
 	return (zfs_iter_snapshots_sorted(zhp, zfs_hold_range_one, &arg));
 }
--- a/usr/src/lib/libzfs/common/libzfs_sendrecv.c	Tue Feb 16 23:03:39 2010 -0800
+++ b/usr/src/lib/libzfs/common/libzfs_sendrecv.c	Wed Feb 17 11:41:36 2010 -0700
@@ -848,7 +848,7 @@
  */
 static int
 dump_ioctl(zfs_handle_t *zhp, const char *fromsnap, boolean_t fromorigin,
-    int outfd)
+    int outfd, boolean_t enoent_ok, boolean_t *got_enoent)
 {
 	zfs_cmd_t zc = { 0 };
 	libzfs_handle_t *hdl = zhp->zfs_hdl;
@@ -862,6 +862,8 @@
 	zc.zc_cookie = outfd;
 	zc.zc_obj = fromorigin;
 
+	*got_enoent = B_FALSE;
+
 	if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SEND, &zc) != 0) {
 		char errbuf[1024];
 		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
@@ -875,6 +877,10 @@
 			return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
 
 		case ENOENT:
+			if (enoent_ok) {
+				*got_enoent = B_TRUE;
+				return (0);
+			}
 			if (zfs_dataset_exists(hdl, zc.zc_name,
 			    ZFS_TYPE_SNAPSHOT)) {
 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -911,6 +917,7 @@
 	send_dump_data_t *sdd = arg;
 	const char *thissnap;
 	int err;
+	boolean_t got_enoent;
 
 	thissnap = strchr(zhp->zfs_name, '@') + 1;
 
@@ -956,9 +963,12 @@
 
 	err = dump_ioctl(zhp, sdd->prevsnap,
 	    sdd->prevsnap[0] == '\0' && (sdd->fromorigin || sdd->replicate),
-	    sdd->outfd);
+	    sdd->outfd, B_TRUE, &got_enoent);
 
-	(void) strcpy(sdd->prevsnap, thissnap);
+	if (got_enoent)
+		err = 0;
+	else
+		(void) strcpy(sdd->prevsnap, thissnap);
 	zfs_close(zhp);
 	return (err);
 }
@@ -1038,10 +1048,12 @@
 			if (sdd->filter_cb == NULL ||
 			    sdd->filter_cb(snapzhp, sdd->filter_cb_arg) ==
 			    B_TRUE) {
+				boolean_t got_enoent;
+
 				rv = dump_ioctl(snapzhp,
 				    missingfrom ? NULL : sdd->fromsnap,
 				    sdd->fromorigin || missingfrom,
-				    sdd->outfd);
+				    sdd->outfd, B_FALSE, &got_enoent);
 			}
 			sdd->seento = B_TRUE;
 			zfs_close(snapzhp);
@@ -1267,11 +1279,11 @@
 			if (err == -1) {
 				fsavl_destroy(fsavl);
 				nvlist_free(fss);
+				err = errno;
 				if (holdsnaps) {
 					(void) zfs_release_range(zhp, fromsnap,
 					    tosnap, holdtag, flags.replicate);
 				}
-				err = errno;
 				goto stderr_out;
 			}
 		}