From e890dd85a7522730ad46daf68150aafd3952d0c1 Mon Sep 17 00:00:00 2001 From: Tim Chase Date: Sun, 16 Nov 2014 22:27:58 -0600 Subject: [PATCH] Produce a full snapshot list for zfs send -p In order to accelerate zfs receive operations in the face of many property-containing snapshots, commit 0574855 changed the header nvlist ("fss") of a send stream to exclude snapshots which aren't part of the stream. This, however, would cause zfs receive -F to erroneously remove snapshots; it would remove any snapshot which wasn't listed in the header nvlist. This patch restores the full list of snapshots in fss[[snaps]] but still suppresses the properties of non-sent snapshots and also removes a consistency check in which an error is raised if a listed snapshot does not have any properties in fss[[snapprops]]. The 0574855 commit also introduced a bug in which zfs send -p of a complete stream (zfs send -p pool/fs@snap) would exclude the snapshot properties in fss[[snapprops]]. This patch detects the last snapshot in a series when no "from" snapshot has been specified and includes its properties. Signed-off-by: Tim Chase Signed-off-by: Brian Behlendorf Closes #2907 --- lib/libzfs/libzfs_sendrecv.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index ef5747f64..e3572914c 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -613,13 +613,15 @@ send_iterate_snap(zfs_handle_t *zhp, void *arg) uint64_t guid = zhp->zfs_dmustats.dds_guid; char *snapname; nvlist_t *nv; - boolean_t isfromsnap, istosnap; + boolean_t isfromsnap, istosnap, istosnapwithnofrom; snapname = strrchr(zhp->zfs_name, '@')+1; isfromsnap = (sd->fromsnap != NULL && strcmp(sd->fromsnap, snapname) == 0); istosnap = (sd->tosnap != NULL && (strcmp(sd->tosnap, snapname) == 0)); + istosnapwithnofrom = (istosnap && sd->fromsnap == NULL); + VERIFY(0 == nvlist_add_uint64(sd->parent_snaps, snapname, guid)); /* * NB: if there is no fromsnap here (it's a newly created fs in * an incremental replication), we will substitute the tosnap. @@ -635,7 +637,7 @@ send_iterate_snap(zfs_handle_t *zhp, void *arg) return (0); } - if (sd->seento || !sd->seenfrom) { + if ((sd->seento || !sd->seenfrom) && !istosnapwithnofrom) { zfs_close(zhp); return (0); } @@ -644,8 +646,6 @@ send_iterate_snap(zfs_handle_t *zhp, void *arg) sd->seento = B_TRUE; } - VERIFY(0 == nvlist_add_uint64(sd->parent_snaps, snapname, guid)); - VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0)); send_iterate_prop(zhp, nv); VERIFY(0 == nvlist_add_nvlist(sd->snapprops, snapname, nv)); @@ -2695,12 +2695,6 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, ret = zcmd_write_src_nvlist(hdl, &zc, props); if (err) nvlist_free(props); - - if (0 == nvlist_lookup_nvlist(fs, "snapprops", &props)) { - VERIFY(0 == nvlist_lookup_nvlist(props, - snapname, &snapprops_nvlist)); - } - if (ret != 0) return (-1); }