Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zfs recv -F: cannot restore to [...]: destination already exists (only if clone exist) #2739

Closed
seletskiy opened this issue Sep 25, 2014 · 6 comments
Milestone

Comments

@seletskiy
Copy link
Contributor

Steps to reproduce:

zfs create zroot/src
zfs snap zroot/src@1
zfs send zroot/src@1 | zfs recv zroot/dst
zfs snap zroot/dst@blah
zfs clone zroot/dst@blah zroot/dst-blah
zfs snap zroot/src@2
zfs send -i zroot/src@1 zroot/src@2 | zfs recv -F zroot/dst@2

Result:

cannot restore to zroot/dst@2: destination already exists

Expected: recv command successfully completes or correct error message is reported.

It's reproduceable in 100% of cases on 0.6.3.

If clone is not created or flag -F is not used issue will not reproduce.

@seletskiy
Copy link
Contributor Author

After digging in code I found, that it should destroy any snapshots that are above current sending state, so there is a code:

    error = dsl_destroy_snapshot_check_impl(
        snap, B_FALSE);

Which will return EEXIST if there are clones on the target fs. It will bubble from that call to the very surface (libzfs_sendrecv.c) where it will be switched to case:

case EEXIST:
    // ...
    zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
        "destination already exists"));
    (void) zfs_error_fmt(hdl, EZFS_EXISTS,
        dgettext(TEXT_DOMAIN, "cannot restore to %s"),
        zc.zc_value);

And we will see exactly that error message (but it's not correct).

So, my points is: a) zfs should check that stream can be received if rollback is forced prior to receiving all the stream; b) reported error message should clarify that stream can not be received because of children of target fs.

@behlendorf
Copy link
Contributor

@seletskiy Nice investigation and reproducer. A few comments:

a) zfs should check that stream can be received if rollback is forced prior to receiving all the stream;

In the case where there's a clone of a snapshot rollback can never succeed. The clone needs to be promoted, with zfs promote to sever its dependency on the snapshot.

b) reported error message should clarify that stream can not be received because of children of target fs.

Absolutely, for this case we should return a different unique errno and print a clear message describing the problem and better yet what could be done to resolve it. Could you propose a patch for this? I'm happy to review it.

@seletskiy
Copy link
Contributor Author

By (a) I mean that right now check, that will ensure that there is no children on the target fs, will run only after actual receive is done, and it's quite irritating to see error message about unexpected clone fs after receiveing 1TB stream... So, maybe it's better to set some kind of lock on the target fs so it will not possible to make clone of snapshot if parent fs is under receive?

@seletskiy
Copy link
Contributor Author

Regarding (b): yep, I'll prepare a patch.

@behlendorf behlendorf added this to the 0.8.0 milestone Oct 12, 2016
@behlendorf
Copy link
Contributor

This is still reproducible in master using the original test case above. Destroying the clone allows the stream to be received.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants
@behlendorf @seletskiy and others