From b52470bffb6cffffc690e98f7315365470d8f2a8 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Thu, 15 May 2014 11:42:19 +0300 Subject: [PATCH] => #2338: hybridcluster/zfs-send-p-fix-71011260 - zfs send -p send properties only for snapshots that are actually sent. zfs send -p send properties only for snapshots that are actually sent ... as opposed to sending properties of all snapshots of the relevant filesystem. The previous behavior results in properties being set on all snapshots on the receiving side, which is quite slow. More details are here: http://thread.gmane.org/gmane.comp.file-systems.openzfs.devel/346 Behavior of zfs send -R is not changed. send_iterate_fs: orderly iterate snapshots The previous commit depends on ordered iteration of the snapshots, otherwise the code won't be able to correctly detect snapshots that fall into the requested snapshot range. This commit can be considered a partial cherry-pick of commit freebsd/freebsd@4995789cde5 where ordered iteration was introduced to fix a different problem. We might want to pick up the complete fix eventually. --- lib/libzfs/libzfs_sendrecv.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index 9edbe724b4f5..6b41a8e14341 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -578,6 +578,8 @@ typedef struct send_data { const char *fromsnap; const char *tosnap; boolean_t recursive; + boolean_t seenfrom; + boolean_t seento; /* * The header nvlist is of the following format: @@ -612,20 +614,39 @@ 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; snapname = strrchr(zhp->zfs_name, '@')+1; + isfromsnap = (sd->fromsnap != NULL && + strcmp(sd->fromsnap, snapname) == 0); + istosnap = (sd->tosnap != NULL && (strcmp(sd->tosnap, snapname) == 0)); - 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. */ - if ((sd->fromsnap && strcmp(snapname, sd->fromsnap) == 0) || - (sd->parent_fromsnap_guid == 0 && sd->tosnap && - strcmp(snapname, sd->tosnap) == 0)) { + if (isfromsnap || (sd->parent_fromsnap_guid == 0 && istosnap)) { sd->parent_fromsnap_guid = guid; } + if (!sd->recursive) { + if (!sd->seenfrom && isfromsnap) { + sd->seenfrom = B_TRUE; + zfs_close(zhp); + return (0); + } + + if (sd->seento || !sd->seenfrom) { + zfs_close(zhp); + return (0); + } + + if (istosnap) + 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)); @@ -746,7 +767,7 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg) sd->parent_fromsnap_guid = 0; VERIFY(0 == nvlist_alloc(&sd->parent_snaps, NV_UNIQUE_NAME, 0)); VERIFY(0 == nvlist_alloc(&sd->snapprops, NV_UNIQUE_NAME, 0)); - (void) zfs_iter_snapshots(zhp, B_FALSE, send_iterate_snap, sd); + (void) zfs_iter_snapshots_sorted(zhp, send_iterate_snap, sd); VERIFY(0 == nvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps)); VERIFY(0 == nvlist_add_nvlist(nvfs, "snapprops", sd->snapprops)); nvlist_free(sd->parent_snaps);