]> granicus.if.org Git - zfs/commitdiff
OpenZFS 8940 - Sending an intra-pool resumable send stream may result in EXDEV
authorloli10K <ezomori.nozomu@gmail.com>
Sat, 30 Dec 2017 23:25:56 +0000 (00:25 +0100)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 14 Feb 2018 22:35:04 +0000 (14:35 -0800)
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.

Patch Notes:
Reconciled differences between OpenZFS and
aee1dd4d983c64db3c3155290d48f05243e85709.

Authored by: loli10K <ezomori.nozomu@gmail.com>
Reviewed by: Paul Dagnelie <pcd@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov>
Approved by: Hans Rosenfeld <rosenfeld@grumpf.home-2000.org>
Ported-by: Giuseppe Di Natale <dinatale2@llnl.gov>
OpenZFS-issue: https://www.illumos.org/issues/8940
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/9f7867c206
Closes #7171

lib/libzfs/libzfs_iter.c

index 75267d05368c83ac84eda1ec895abdc6545e7439..6f9b3f465785b5399ff08b1866c347990e21541d 100644 (file)
@@ -422,6 +422,10 @@ 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)