Skip to content

Commit

Permalink
Fix EIO after resuming receive of new dataset over an existing one
Browse files Browse the repository at this point in the history
When resuming an interrupted ZFS send stream that creates a new dataset
with the same name as an existing dataset, if the existing dataset is
accessed after the failed receive, then after the subsequent successful
receive it will return EIO. This happens because nothing mounts the new
dataset, leaving the old, no longer valid dataset still mounted.

This commit fixes zfs receive to always unmount and remount the
destination, regardless of whether the stream is a new stream or a
resumed stream.

Sponsored by: Axcient
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Ryan Moeller <[email protected]>
Signed-off-by: Alan Somers <[email protected]>
External-issue: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=249579
Closes openzfs#10995
Closes openzfs#10999
  • Loading branch information
asomers authored and RageLtMan committed May 31, 2021
1 parent 74a286f commit 47641ad
Showing 1 changed file with 4 additions and 2 deletions.
6 changes: 4 additions & 2 deletions lib/libzfs/libzfs_sendrecv.c
Original file line number Diff line number Diff line change
Expand Up @@ -4108,7 +4108,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
char errbuf[1024];
const char *chopprefix;
boolean_t newfs = B_FALSE;
boolean_t stream_wantsnewfs;
boolean_t stream_wantsnewfs, stream_resumingnewfs;
boolean_t newprops = B_FALSE;
uint64_t read_bytes = 0;
uint64_t errflags = 0;
Expand Down Expand Up @@ -4329,6 +4329,8 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
DMU_BACKUP_FEATURE_EMBED_DATA;
stream_wantsnewfs = (drrb->drr_fromguid == 0 ||
(drrb->drr_flags & DRR_FLAG_CLONE) || originsnap) && !resuming;
stream_resumingnewfs = (drrb->drr_fromguid == 0 ||
(drrb->drr_flags & DRR_FLAG_CLONE) || originsnap) && resuming;

if (stream_wantsnewfs) {
/*
Expand Down Expand Up @@ -4496,7 +4498,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
}

if (!flags->dryrun && zhp->zfs_type == ZFS_TYPE_FILESYSTEM &&
stream_wantsnewfs) {
(stream_wantsnewfs || stream_resumingnewfs)) {
/* We can't do online recv in this case */
clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
flags->forceunmount ? MS_FORCE : 0);
Expand Down

0 comments on commit 47641ad

Please sign in to comment.