mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 10:37:35 +03:00
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 <pcd@delphix.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Pablo Correa Gómez <ablocorrea@hotmail.com> Closes #11710
This commit is contained in:
committed by
Brian Behlendorf
parent
f8631d0fe0
commit
07d64c07e0
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user