diff options
author | pablofsf <[email protected]> | 2021-04-11 21:05:35 +0200 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2021-04-14 13:19:50 -0700 |
commit | 07d64c07e06e558219f645b304d891bed9ff652f (patch) | |
tree | 462e399ee5c23da0273ed546e3c3912d02df16d7 /lib | |
parent | f8631d0fe065c2211fa3527d4b9f5e04725382fb (diff) |
Allow zfs to send replication streams with missing snapshots
A tentative implementation and discussion was done in #5285.
According to it a send --skip-missing|-s flag has been added.
In a replication stream, when there are snapshots missing in
the hierarchy, if -s is provided print a warning and ignore
dataset (and its children) instead of throwing an error
Reviewed-by: Paul Dagnelie <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Pablo Correa Gómez <[email protected]>
Closes #11710
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libzfs/libzfs_sendrecv.c | 36 |
1 files changed, 23 insertions, 13 deletions
diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index bc887e72a..ee593f8db 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -247,6 +247,7 @@ typedef struct send_data { boolean_t raw; boolean_t doall; boolean_t replicate; + boolean_t skipmissing; boolean_t verbose; boolean_t backup; boolean_t seenfrom; @@ -497,7 +498,8 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg) * - skip sending the current dataset if it was created later than * the parent tosnap * - return error if the current dataset was created earlier than - * the parent tosnap + * the parent tosnap, unless --skip-missing specified. Then + * just print a warning */ if (sd->tosnap != NULL && tosnap_txg == 0) { if (sd->tosnap_txg != 0 && txg > sd->tosnap_txg) { @@ -506,6 +508,11 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg) "skipping dataset %s: snapshot %s does " "not exist\n"), zhp->zfs_name, sd->tosnap); } + } else if (sd->skipmissing) { + (void) fprintf(stderr, dgettext(TEXT_DOMAIN, + "WARNING: skipping dataset %s and its children:" + " snapshot %s does not exist\n"), + zhp->zfs_name, sd->tosnap); } else { (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "cannot send %s@%s%s: snapshot %s@%s does not " @@ -649,8 +656,9 @@ 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 doall, - boolean_t replicate, boolean_t verbose, boolean_t backup, boolean_t holds, - boolean_t props, nvlist_t **nvlp, avl_tree_t **avlp) + boolean_t replicate, boolean_t skipmissing, boolean_t verbose, + boolean_t backup, boolean_t holds, boolean_t props, nvlist_t **nvlp, + avl_tree_t **avlp) { zfs_handle_t *zhp; send_data_t sd = { 0 }; @@ -668,6 +676,7 @@ gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap, sd.raw = raw; sd.doall = doall; sd.replicate = replicate; + sd.skipmissing = skipmissing; sd.verbose = verbose; sd.backup = backup; sd.holds = holds; @@ -1975,8 +1984,8 @@ send_conclusion_record(int fd, zio_cksum_t *zc) static int send_prelim_records(zfs_handle_t *zhp, const char *from, int fd, boolean_t gather_props, boolean_t recursive, boolean_t verbose, - boolean_t dryrun, boolean_t raw, boolean_t replicate, boolean_t backup, - boolean_t holds, boolean_t props, boolean_t doall, + boolean_t dryrun, boolean_t raw, boolean_t replicate, boolean_t skipmissing, + boolean_t backup, boolean_t holds, boolean_t props, boolean_t doall, nvlist_t **fssp, avl_tree_t **fsavlp) { int err = 0; @@ -2022,8 +2031,8 @@ send_prelim_records(zfs_handle_t *zhp, const char *from, int fd, } if ((err = gather_nvlist(zhp->zfs_hdl, tofs, - from, tosnap, recursive, raw, doall, replicate, verbose, - backup, holds, props, &fss, fsavlp)) != 0) { + from, tosnap, recursive, raw, doall, replicate, skipmissing, + verbose, backup, holds, props, &fss, fsavlp)) != 0) { return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP, errbuf)); } @@ -2160,8 +2169,9 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, err = send_prelim_records(tosnap, fromsnap, outfd, flags->replicate || flags->props || flags->holds, flags->replicate, flags->verbosity > 0, flags->dryrun, - flags->raw, flags->replicate, flags->backup, flags->holds, - flags->props, flags->doall, &fss, &fsavl); + flags->raw, flags->replicate, flags->skipmissing, + flags->backup, flags->holds, flags->props, flags->doall, + &fss, &fsavl); zfs_close(tosnap); if (err != 0) goto err_out; @@ -2464,7 +2474,7 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags, */ err = send_prelim_records(zhp, NULL, fd, B_TRUE, B_FALSE, flags->verbosity > 0, flags->dryrun, flags->raw, - flags->replicate, flags->backup, flags->holds, + flags->replicate, B_FALSE, flags->backup, flags->holds, flags->props, flags->doall, NULL, NULL); if (err != 0) return (err); @@ -3236,7 +3246,7 @@ again: deleted = fnvlist_alloc(); if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL, - recursive, B_TRUE, B_FALSE, recursive, B_FALSE, B_FALSE, + recursive, B_TRUE, B_FALSE, recursive, B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_TRUE, &local_nv, &local_avl)) != 0) return (error); @@ -4729,8 +4739,8 @@ 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, B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_TRUE, - &local_nv, &local_avl) == 0) { + B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_FALSE, + B_TRUE, &local_nv, &local_avl) == 0) { *cp = '@'; fs = fsavl_find(local_avl, drrb->drr_toguid, NULL); fsavl_destroy(local_avl); |