Search code examples
copyzfs

How to copy the incremental parts of the cloned dataset to the original dataset(snapshot) in zfs?


zp1/tmp/origin@1  ==(clone & snapshot)==>  zp1/tmp/clone@1
                                             ...working...
                                             (snapshot)
                                                ||
                                                \/
zp1/tmp/origin@2   <====================   zp1/tmp/clone@2
                            ||
        $$copy the incremental parts between zp1/tmp/clone@1 
        and zp1/tmp/clone@2 to zp1/tmp/origin.$$

The $$copy ..$$ part is what I want, and I have tried the below test procedure but failed with does not match incremental source error. Please, note that it's not about backup.
Is it possible?

[test procedure]

# zfs create zp1/tmp/origin
# touch /zp1/tmp/origin/hi.txt
# zfs snapshot zp1/tmp/origin@1
# zfs clone zp1/tmp/origin@1 zp1/tmp/clone
# zfs snapshot zp1/tmp/clone@1
# touch /zp1/tmp/clone/bye.txt
# zfs snapshot zp1/tmp/clone@2

# zfs list -t all -r zp1/tmp
NAME               USED  AVAIL     REFER  MOUNTPOINT
zp1/tmp            256K   339G       96K  /zp1/tmp
zp1/tmp/clone       64K   339G       96K  /zp1/tmp/clone
zp1/tmp/clone@1      0B      -       96K  -
zp1/tmp/clone@2      0B      -       96K  -
zp1/tmp/origin      96K   339G       96K  /zp1/tmp/origin
zp1/tmp/origin@1     0B      -       96K  -

# zfs send -v -I zp1/tmp/clone@1 zp1/tmp/clone@2 | zfs receive -v zp1/tmp/origin@2
send from @1 to zp1/tmp/clone@2 estimated size is 32.6K
total estimated size is 32.6K
TIME        SENT   SNAPSHOT zp1/tmp/clone@2
receiving incremental stream of zp1/tmp/clone@2 into zp1/tmp/origin@2
cannot receive incremental stream: most recent snapshot of zp1/tmp/origin does not
match incremental source

Solution

  • The zfs send command compares a UUID of the source that it’s sending from and the destination that it’s sending to, to make sure you’re replaying the changes on top of a filesystem that had exactly the same data in it. In your case you’re skipping part of the timeline though, so this UUID doesn’t match.

    Your naming scheme for the snapshots on the clone is confusing — clone@1 is not the same snapshot as original-fs@1 even though they probably point at the same data, so I’m going to rename them slightly to make that clearer:

    1. original-fs@1 comes first
    2. clone comes next and has the same UUID as original-fs@1 at the start
    3. clone@2 comes next
    4. clone@3 comes next

    You’re trying to send the delta between clone@2 and clone@3 onto a filesystem which doesn’t have clone@2 on it yet. Instead, you should send from original-fs@1 to clone@3 to capture the whole timeline (or you could do two sends, from original-fs@1 to clone@2, then clone@2 to clone@3, if you want to recreate the full snapshot sequence on both versions of the data).

    That said, this is just copying a bunch of data around for no reason. Why not just zfs promote the clone so that it becomes the parent filesystem? (Then you can delete the old parent and rename the new one to take its place.)