aboutsummaryrefslogtreecommitdiffstats
path: root/lib/libzfs/libzfs_sendrecv.c
diff options
context:
space:
mode:
authorLOLi <[email protected]>2018-02-21 21:32:06 +0100
committerBrian Behlendorf <[email protected]>2018-02-21 12:32:06 -0800
commitfaa97c1619e5d7b51b2077db18fb92c5279b9db3 (patch)
tree008822d20f9ce2c832fff79b89564c0cb76806a8 /lib/libzfs/libzfs_sendrecv.c
parentb0918402dc9a0f81dd52880fbd4e4f4f2133764b (diff)
Want 'zfs send -b'
This change implements 'zfs send -b' which can be used to send only received property values whether or not they are overridden by local settings. This can be very useful during "restore" operations from a backup pool because it allows to send only the property values originally sent from the backup source, even though they were later modified on the destination either by a 'zfs set' operation, explicit 'zfs inherit' or overridden during the receive process via 'zfs receive -o|-x'. Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: loli10K <[email protected]> Closes #7156
Diffstat (limited to 'lib/libzfs/libzfs_sendrecv.c')
-rw-r--r--lib/libzfs/libzfs_sendrecv.c33
1 files changed, 21 insertions, 12 deletions
diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c
index c850c8ba6..1623a75b4 100644
--- a/lib/libzfs/libzfs_sendrecv.c
+++ b/lib/libzfs/libzfs_sendrecv.c
@@ -621,6 +621,7 @@ typedef struct send_data {
const char *fromsnap;
const char *tosnap;
boolean_t raw;
+ boolean_t backup;
boolean_t recursive;
boolean_t verbose;
boolean_t seenfrom;
@@ -651,7 +652,8 @@ typedef struct send_data {
*/
} send_data_t;
-static void send_iterate_prop(zfs_handle_t *zhp, nvlist_t *nv);
+static void
+send_iterate_prop(zfs_handle_t *zhp, boolean_t received_only, nvlist_t *nv);
static int
send_iterate_snap(zfs_handle_t *zhp, void *arg)
@@ -706,7 +708,7 @@ send_iterate_snap(zfs_handle_t *zhp, void *arg)
}
VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0));
- send_iterate_prop(zhp, nv);
+ send_iterate_prop(zhp, sd->backup, nv);
VERIFY(0 == nvlist_add_nvlist(sd->snapprops, snapname, nv));
nvlist_free(nv);
@@ -715,11 +717,17 @@ send_iterate_snap(zfs_handle_t *zhp, void *arg)
}
static void
-send_iterate_prop(zfs_handle_t *zhp, nvlist_t *nv)
+send_iterate_prop(zfs_handle_t *zhp, boolean_t received_only, nvlist_t *nv)
{
+ nvlist_t *props = NULL;
nvpair_t *elem = NULL;
- while ((elem = nvlist_next_nvpair(zhp->zfs_props, elem)) != NULL) {
+ if (received_only)
+ props = zfs_get_recvd_props(zhp);
+ else
+ props = zhp->zfs_props;
+
+ while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
char *propname = nvpair_name(elem);
zfs_prop_t prop = zfs_name_to_prop(propname);
nvlist_t *propnv;
@@ -885,7 +893,7 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg)
/* iterate over props */
VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0));
- send_iterate_prop(zhp, nv);
+ send_iterate_prop(zhp, sd->backup, nv);
if (zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) != ZIO_CRYPT_OFF) {
boolean_t encroot;
@@ -951,7 +959,7 @@ out:
static int
gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap,
const char *tosnap, boolean_t recursive, boolean_t raw, boolean_t verbose,
- nvlist_t **nvlp, avl_tree_t **avlp)
+ boolean_t backup, nvlist_t **nvlp, avl_tree_t **avlp)
{
zfs_handle_t *zhp;
send_data_t sd = { 0 };
@@ -968,6 +976,7 @@ gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap,
sd.recursive = recursive;
sd.raw = raw;
sd.verbose = verbose;
+ sd.backup = backup;
if ((error = send_iterate_fs(zhp, &sd)) != 0) {
nvlist_free(sd.fss);
@@ -1881,7 +1890,7 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
}
}
- if (flags->replicate || flags->doall || flags->props) {
+ if (flags->replicate || flags->doall || flags->props || flags->backup) {
dmu_replay_record_t drr = { 0 };
char *packbuf = NULL;
size_t buflen = 0;
@@ -1889,7 +1898,7 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
ZIO_SET_CHECKSUM(&zc, 0, 0, 0, 0);
- if (flags->replicate || flags->props) {
+ if (flags->replicate || flags->props || flags->backup) {
nvlist_t *hdrnv;
VERIFY(0 == nvlist_alloc(&hdrnv, NV_UNIQUE_NAME, 0));
@@ -1908,7 +1917,7 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
err = gather_nvlist(zhp->zfs_hdl, zhp->zfs_name,
fromsnap, tosnap, flags->replicate, flags->raw,
- flags->verbose, &fss, &fsavl);
+ flags->verbose, flags->backup, &fss, &fsavl);
if (err)
goto err_out;
VERIFY(0 == nvlist_add_nvlist(hdrnv, "fss", fss));
@@ -2078,7 +2087,7 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
}
if (!flags->dryrun && (flags->replicate || flags->doall ||
- flags->props)) {
+ flags->props || flags->backup)) {
/*
* write final end record. NB: want to do this even if
* there was some error, because it might not be totally
@@ -2816,7 +2825,7 @@ again:
VERIFY(0 == nvlist_alloc(&deleted, NV_UNIQUE_NAME, 0));
if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL,
- recursive, B_TRUE, B_FALSE, &local_nv, &local_avl)) != 0)
+ recursive, B_TRUE, B_FALSE, B_FALSE, &local_nv, &local_avl)) != 0)
return (error);
/*
@@ -4121,7 +4130,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
*/
*cp = '\0';
if (gather_nvlist(hdl, destsnap, NULL, NULL, B_FALSE, B_TRUE,
- B_FALSE, &local_nv, &local_avl) == 0) {
+ B_FALSE, B_FALSE, &local_nv, &local_avl) == 0) {
*cp = '@';
fs = fsavl_find(local_avl, drrb->drr_toguid, NULL);
fsavl_destroy(local_avl);