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 jsai20 committed Mar 30, 2021
1 parent 3265998 commit e48d15b
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 e48d15b

Please sign in to comment.