Project

General

Profile

Actions

Bug #4671

open

incremental "zfs send" fails from origin's origin snapshot

Added by David Pacheco about 8 years ago.

Status:
New
Priority:
Normal
Assignee:
-
Category:
-
Start date:
2014-03-06
Due date:
% Done:

0%

Estimated time:
Difficulty:
Medium
Tags:
needs-triage
Gerrit CR:

Description

"zfs send" doesn't seem to support an incremental send from an origin snapshot to a clone's clone. Here's the setup:

# zfs create zones/foo0
# zfs snapshot zones/foo0@foo0
# zfs clone zones/foo0@foo0 zones/foo1
# zfs snapshot zones/foo1@foo1
# zfs clone zones/foo1@foo1 zones/foo2
# zfs snapshot zones/foo2@foo2

Now, incremental sends work from foo0 (the original, non-clone filesystem) to foo1 (the first clone) and from foo1 to foo2 (the second clone):

# zfs send -i zones/foo0@foo0 zones/foo1@foo1 > /dev/null
# zfs send -i zones/foo1@foo1 zones/foo2@foo2 > /dev/null

but not from foo0 to foo2:

# zfs send -i zones/foo0@foo0 zones/foo2@foo2 > /dev/null
incremental source must be in same filesystem
usage:
        send [-DnPpRv] [-[iI] snapshot] <snapshot>
        send [-i snapshot|bookmark] <filesystem|volume|snapshot>

For the property list, run: zfs set|get

For the delegated permission list, run: zfs allow|unallow

I assume this is technically possible, since it works when all of the snapshots are part of the same filesystem. In fact, if you promote zones/foo2, it does work:

# zfs promote zones/foo2
# zfs send -i zones/foo0@foo0 zones/foo2@foo2 > /dev/null
#

The problem appears to be this code in zfs_do_send:
https://github.com/illumos/illumos-gate/blob/master/usr/src/cmd/zfs/zfs_main.c#L3764-L3781

  3764                  if (strcmp(origin, fromname) == 0) {
  3765                          fromname = NULL;
  3766                          flags.fromorigin = B_TRUE;
  3767                  } else {
  3768                          *cp = '\\0';
  3769                          if (cp != fromname && strcmp(argv[0], fromname)) {
  3770                                  (void) fprintf(stderr,
  3771                                      gettext("incremental source must be " 
  3772                                      "in same filesystem\\n"));
  3773                                  usage(B_FALSE);
  3774                          }
  3775                          fromname = cp + 1;
  3776                          if (strchr(fromname, '@') || strchr(fromname, '/')) {
  3777                                  (void) fprintf(stderr,
  3778                                      gettext("invalid incremental source\\n"));
  3779                                  usage(B_FALSE);
  3780                          }
  3781                  }

It looks like the code generally only allows incremental sends from the exact same filesystem (as the error message suggests), with an explicit exception for the origin of the destination dataset. That is, the only reason the first two "zfs send"s above work at all is that they're each sending from the origin snapshot of the dataset.

It seems like this code should follow the whole chain of origins. In other words, it should keep looking at the next origin until either it finds one that matches "fromname" (in which case it should be allowed) or it finds a non-clone dataset.

I haven't looked to see if there's a similar problem in the kernel, but at least we know it's technically possible to generate a send stream between these two snapshots.

No data to display

Actions

Also available in: Atom PDF