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.
  • Loading branch information
avg-I authored and FransUrbo committed Sep 5, 2014
1 parent 7858804 commit c09a4c2
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
Expand Up @@ -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:
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit c09a4c2

Please sign in to comment.