I have got a report, for FreeBSD, about a filesystem getting into a
weird state with respect to the resumable receive.
The filesystem has non-empty 'receive_resume_token' property.
But a send stream generated with that token cannot be received.
Also, the receive state cannot be cleared with zfs recv -A.
The filesystem's 'inconsistent' property is zero.
>From the above I conclude that there is no %recv child.

I was able to reproduce that condition -- again, on FreeBSD -- using the
following steps.

- create a full send stream and make a truncated copy of it (e.g. 50%)
- zfs recv -F -s the truncated copy into a new destination dataset
  - this creates the destination dataset
  - marks the dataset inconsistent
  - receives as much data as available in the truncated stream
  - sets up a partial receive state for the dataset (in its ZAP)
- repeat the same command with the same truncated stream again
  - because of -F, the command is allowed to proceed despite the
existing destination
  - because the destination exists, the stream is received into %recv
  - a partial receive state is set up on %recv
- create a resume stream with zfs send -t using the token from the
previous step
- zfs recv -F -s the resume stream
  - this finds %recv and the resume state recorded in it
  - this completes the receive into %recv
  - the clone swap is done to move the received objset into the parent
dataset
  - %recv is destroyed
  - the parent dataset is marked consistent

So, in the end we have a fully received dataset in a consistent state,
but it still has the partial receive state from the first receive.

I think that maybe dmu_recv_end_sync() should clear the resume state on
origin_head in the !drc->drc_newfs case like it does for ds in the other
case.

Or maybe, if we start a new full receive and the destination already
exists and it is inconsistent and it has the resume state, then we
should assert that the destination has no snapshots and then re-create
it, so that we can receive into it directly (without creating %recv).
I see two ways of re-creating the destination.  Either, we can destroy
and create it.  Or we can somehow discard all its data, e.g., roll back
to @$ORIGIN.

Maybe there are other options.

What do you think?

Thank you!

P.S.
I have not tried illumos or ZoL yet.
Could anyone please try to reproduce?
Thanks again.

-- 
Andriy Gapon

------------------------------------------
openzfs: openzfs-developer
Permalink: 
https://openzfs.topicbox.com/groups/developer/Tbb598d5972318c77-M2aaa54b879588765828c633d
Delivery options: https://openzfs.topicbox.com/groups/developer/subscription

Reply via email to