From e48d15bdeab78f569bc59acc3cbed17a45868939 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Fri, 2 Oct 2020 18:47:09 -0600 Subject: [PATCH] Fix EIO after resuming receive of new dataset over an existing one 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 Reviewed-by: Ryan Moeller Signed-off-by: Alan Somers External-issue: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=249579 Closes #10995 Closes #10999 --- lib/libzfs/libzfs_sendrecv.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index b46a4f122c47..eb300f97c804 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -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; @@ -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) { /* @@ -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);