Skip to content

Commit

Permalink
=> openzfs#2338: hybridcluster/zfs-send-p-fix-71011260 - zfs send -p …
Browse files Browse the repository at this point in the history
…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-src@4995789cde5 where ordered iteration was introduced
to fix a different problem.
We might want to pick up the complete fix eventually.
avg-I authored and FransUrbo committed Aug 29, 2014
1 parent 9fb7a02 commit 1593745
Showing 1 changed file with 26 additions and 5 deletions.
31 changes: 26 additions & 5 deletions lib/libzfs/libzfs_sendrecv.c
Original file line number Diff line number Diff line change
@@ -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);

0 comments on commit 1593745

Please sign in to comment.