svn commit: r329807 - vendor/illumos/dist/lib/libzfs/common
Alexander Motin
mav at FreeBSD.org
Thu Feb 22 04:01:06 UTC 2018
Author: mav
Date: Thu Feb 22 04:01:05 2018
New Revision: 329807
URL: https://svnweb.freebsd.org/changeset/base/329807
Log:
8940 Sending an intra-pool resumable send stream may result in EXDEV
illumos/illumos-gate at 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 at snap1 -> source at snap2" stream instead of
"source at snap1 -> source at snap2": this fails with an "Invalid cross-device
link" (EXDEV) error.
Reviewed by: Paul Dagnelie <pcd at delphix.com>
Reviewed by: Matthew Ahrens <mahrens at delphix.com>
Approved by: Hans Rosenfeld <rosenfeld at grumpf.hope-2000.org>
Author: loli10K <ezomori.nozomu at gmail.com>
Modified:
vendor/illumos/dist/lib/libzfs/common/libzfs_iter.c
vendor/illumos/dist/lib/libzfs/common/libzfs_sendrecv.c
Modified: vendor/illumos/dist/lib/libzfs/common/libzfs_iter.c
==============================================================================
--- vendor/illumos/dist/lib/libzfs/common/libzfs_iter.c Thu Feb 22 03:55:02 2018 (r329806)
+++ vendor/illumos/dist/lib/libzfs/common/libzfs_iter.c Thu Feb 22 04:01:05 2018 (r329807)
@@ -424,16 +424,20 @@ zfs_iter_snapspec(zfs_handle_t *fs_zhp, const char *sp
/*
* 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));
}
Modified: vendor/illumos/dist/lib/libzfs/common/libzfs_sendrecv.c
==============================================================================
--- vendor/illumos/dist/lib/libzfs/common/libzfs_sendrecv.c Thu Feb 22 03:55:02 2018 (r329806)
+++ vendor/illumos/dist/lib/libzfs/common/libzfs_sendrecv.c Thu Feb 22 04:01:05 2018 (r329807)
@@ -1577,6 +1577,7 @@ zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *fla
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"));
@@ -1591,9 +1592,9 @@ zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *fla
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 ||
@@ -1650,7 +1651,7 @@ zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *fla
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);
}
More information about the svn-src-all
mailing list