Produce a full snapshot list for zfs send -p
In order to accelerate zfs receive operations in the face of many property-containing snapshots, commit0574855
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[<id>[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[<id>[snapprops]]. The0574855
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[<id>[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 <tim@chase2k.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #2907
This commit is contained in:
parent
7fc8c33ede
commit
e890dd85a7
|
@ -613,13 +613,15 @@ send_iterate_snap(zfs_handle_t *zhp, void *arg)
|
||||||
uint64_t guid = zhp->zfs_dmustats.dds_guid;
|
uint64_t guid = zhp->zfs_dmustats.dds_guid;
|
||||||
char *snapname;
|
char *snapname;
|
||||||
nvlist_t *nv;
|
nvlist_t *nv;
|
||||||
boolean_t isfromsnap, istosnap;
|
boolean_t isfromsnap, istosnap, istosnapwithnofrom;
|
||||||
|
|
||||||
snapname = strrchr(zhp->zfs_name, '@')+1;
|
snapname = strrchr(zhp->zfs_name, '@')+1;
|
||||||
isfromsnap = (sd->fromsnap != NULL &&
|
isfromsnap = (sd->fromsnap != NULL &&
|
||||||
strcmp(sd->fromsnap, snapname) == 0);
|
strcmp(sd->fromsnap, snapname) == 0);
|
||||||
istosnap = (sd->tosnap != NULL && (strcmp(sd->tosnap, 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
|
* NB: if there is no fromsnap here (it's a newly created fs in
|
||||||
* an incremental replication), we will substitute the tosnap.
|
* an incremental replication), we will substitute the tosnap.
|
||||||
|
@ -635,7 +637,7 @@ send_iterate_snap(zfs_handle_t *zhp, void *arg)
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sd->seento || !sd->seenfrom) {
|
if ((sd->seento || !sd->seenfrom) && !istosnapwithnofrom) {
|
||||||
zfs_close(zhp);
|
zfs_close(zhp);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
@ -644,8 +646,6 @@ send_iterate_snap(zfs_handle_t *zhp, void *arg)
|
||||||
sd->seento = B_TRUE;
|
sd->seento = B_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VERIFY(0 == nvlist_add_uint64(sd->parent_snaps, snapname, guid));
|
|
||||||
|
|
||||||
VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0));
|
VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0));
|
||||||
send_iterate_prop(zhp, nv);
|
send_iterate_prop(zhp, nv);
|
||||||
VERIFY(0 == nvlist_add_nvlist(sd->snapprops, snapname, 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);
|
ret = zcmd_write_src_nvlist(hdl, &zc, props);
|
||||||
if (err)
|
if (err)
|
||||||
nvlist_free(props);
|
nvlist_free(props);
|
||||||
|
|
||||||
if (0 == nvlist_lookup_nvlist(fs, "snapprops", &props)) {
|
|
||||||
VERIFY(0 == nvlist_lookup_nvlist(props,
|
|
||||||
snapname, &snapprops_nvlist));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue