diff options
author | LOLi <[email protected]> | 2017-10-11 00:22:05 +0200 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2017-10-10 15:22:05 -0700 |
commit | aee1dd4d983c64db3c3155290d48f05243e85709 (patch) | |
tree | ee30dfe67c6bf3263517eaca69390365e50e24c3 /lib/libzfs | |
parent | 70f02287f86db33950eba9ceeb4f4c07c23131e0 (diff) |
Fix intra-pool resumable 'zfs send -t <token>'
Because resuming from a token requires "guid" -> "snapshot" mapping
we have to walk the whole dataset hierarchy to find the right snapshot
to send; when both source and destination exists, for an incremental
resumable stream, libzfs gets confused and picks up the wrong snapshot
to send from: this results in attempting to send
"destination@snap1 -> source@snap2"
instead of
"source@snap1 -> source@snap2"
which fails with a "Invalid cross-device link" error (EXDEV).
Fix this by adjusting the logic behind dataset traversal in
zfs_iter_children() to pick the right snapshot to send from.
Additionally update dry-run 'zfs send -t' to print its output to
stderr: this is consistent with other dry-run commands.
Reviewed-by: George Melikov <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: loli10K <[email protected]>
Closes #6618
Closes #6619
Closes #6623
Diffstat (limited to 'lib/libzfs')
-rw-r--r-- | lib/libzfs/libzfs_iter.c | 4 | ||||
-rw-r--r-- | lib/libzfs/libzfs_sendrecv.c | 7 |
2 files changed, 6 insertions, 5 deletions
diff --git a/lib/libzfs/libzfs_iter.c b/lib/libzfs/libzfs_iter.c index 57ebdd89d..75267d053 100644 --- a/lib/libzfs/libzfs_iter.c +++ b/lib/libzfs/libzfs_iter.c @@ -428,10 +428,10 @@ zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data) { int ret; - if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0) + if ((ret = zfs_iter_snapshots(zhp, B_FALSE, func, data)) != 0) return (ret); - return (zfs_iter_snapshots(zhp, B_FALSE, func, data)); + return (zfs_iter_filesystems(zhp, func, data)); } diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index 857abda3d..855a297c9 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -1654,6 +1654,7 @@ zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *flags, int outfd, int error = 0; char name[ZFS_MAX_DATASET_NAME_LEN]; enum lzc_send_flags lzc_flags = 0; + FILE *fout = (flags->verbose && flags->dryrun) ? stdout : stderr; (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, "cannot resume send")); @@ -1668,9 +1669,9 @@ zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *flags, int outfd, return (zfs_error(hdl, EZFS_FAULT, errbuf)); } if (flags->verbose) { - (void) fprintf(stderr, dgettext(TEXT_DOMAIN, + (void) fprintf(fout, dgettext(TEXT_DOMAIN, "resume token contents:\n")); - nvlist_print(stderr, resume_nvl); + nvlist_print(fout, resume_nvl); } if (nvlist_lookup_string(resume_nvl, "toname", &toname) != 0 || @@ -1729,7 +1730,7 @@ zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *flags, int outfd, lzc_flags, &size); if (error == 0) size = MAX(0, (int64_t)(size - bytes)); - send_print_verbose(stderr, zhp->zfs_name, fromname, + send_print_verbose(fout, zhp->zfs_name, fromname, size, flags->parsable); } |