aboutsummaryrefslogtreecommitdiff
path: root/cddl/contrib/opensolaris/lib/libzfs
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2018-02-22 04:01:55 +0000
committerAlexander Motin <mav@FreeBSD.org>2018-02-22 04:01:55 +0000
commit03d54eb339391b451a9625aef0b5c2e967bc30ab (patch)
treec27c574b89b8d18f848a3f50899d02942c3eff49 /cddl/contrib/opensolaris/lib/libzfs
parent011eae6c576481685784c6e0afec414c5af92e19 (diff)
parent34ff7cee7a460f9a00f0b1bd170b791a4840d83d (diff)
downloadsrc-03d54eb339391b451a9625aef0b5c2e967bc30ab.tar.gz
src-03d54eb339391b451a9625aef0b5c2e967bc30ab.zip
MFV r329807:
8940 Sending an intra-pool resumable send stream may result in EXDEV illumos/illumos-gate@544132fce3fa6583f01318f9559adc46614343a7 "zfs send -t <token>" for an incremental send should be able to resume successfully when sending to the same pool: a subtle issue in zfs_iter_children() doesn't currently allow this. Because resuming from a token requires "guid" -> "dataset" mapping (guid_to_name()), we have to walk the whole hierarchy to find the right snapshots to send. When resuming an incremental send both source and destination live in the same pool and have the same guid: this is where zfs_iter_children() gets confused and picks up the wrong snapshot, so we end up trying to send an incremental "destination@snap1 -> source@snap2" stream instead of "source@snap1 -> source@snap2": this fails with an "Invalid cross-device link" (EXDEV) error. Reviewed by: Paul Dagnelie <pcd@delphix.com> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Approved by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> Author: loli10K <ezomori.nozomu@gmail.com>
Notes
Notes: svn path=/head/; revision=329808
Diffstat (limited to 'cddl/contrib/opensolaris/lib/libzfs')
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c8
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c7
2 files changed, 10 insertions, 5 deletions
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c
index ae6173e8d8f2..433fea3ef51d 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c
@@ -424,16 +424,20 @@ zfs_iter_snapspec(zfs_handle_t *fs_zhp, const char *spec_orig,
/*
* Iterate over all children, snapshots and filesystems
+ * Process snapshots before filesystems because they are nearer the input
+ * handle: this is extremely important when used with zfs_iter_f functions
+ * looking for data, following the logic that we would like to find it as soon
+ * and as close as possible.
*/
int
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/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
index 39668027e2b5..4037eac686c7 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
@@ -1585,6 +1585,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"));
@@ -1599,9 +1600,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 ||
@@ -1658,7 +1659,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);
}