Index: cddl/contrib/opensolaris/cmd/zfs/zfs.8 =================================================================== --- cddl/contrib/opensolaris/cmd/zfs/zfs.8 +++ cddl/contrib/opensolaris/cmd/zfs/zfs.8 @@ -32,7 +32,7 @@ .\" .\" $FreeBSD$ .\" -.Dd Octover 16, 2019 +.Dd November 9, 2019 .Dt ZFS 8 .Os .Sh NAME @@ -201,12 +201,12 @@ .Fl t Ar receive_resume_token .Nm .Cm receive Ns | Ns Cm recv -.Op Fl vnsFu +.Op Fl vnsFMu .Op Fl o Sy origin Ns = Ns Ar snapshot .Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot .Nm .Cm receive Ns | Ns Cm recv -.Op Fl vnsFu +.Op Fl vnsFMu .Op Fl d | e .Op Fl o Sy origin Ns = Ns Ar snapshot .Ar filesystem @@ -2894,14 +2894,14 @@ .It Xo .Nm .Cm receive Ns | Ns Cm recv -.Op Fl vnsFu +.Op Fl vnsFMu .Op Fl o Sy origin Ns = Ns Ar snapshot .Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot .Xc .It Xo .Nm .Cm receive Ns | Ns Cm recv -.Op Fl vnsFu +.Op Fl vnsFMu .Op Fl d | e .Op Fl o Sy origin Ns = Ns Ar snapshot .Ar filesystem @@ -3001,6 +3001,8 @@ stream (for example, one generated by .Qq Nm Cm send Fl R Bro Fl i | Fl I Brc ) , destroy snapshots and file systems that do not exist on the sending side. +.It Fl M +Force an unmount of the file system while receiving a snapshot. .It Fl s If the receive is interrupted, save the partially received state, rather than deleting it. Interruption may be due to premature termination of Index: cddl/contrib/opensolaris/cmd/zfs/zfs_main.c =================================================================== --- cddl/contrib/opensolaris/cmd/zfs/zfs_main.c +++ cddl/contrib/opensolaris/cmd/zfs/zfs_main.c @@ -274,9 +274,9 @@ case HELP_PROMOTE: return (gettext("\tpromote \n")); case HELP_RECEIVE: - return (gettext("\treceive|recv [-vnsFu] \n" - "\treceive|recv [-vnsFu] [-o origin=] [-d | -e] " + "\treceive|recv [-vnsFMu] [-o origin=] [-d | -e] " "\n" "\treceive|recv -A \n")); case HELP_RENAME: @@ -4051,7 +4051,7 @@ nomem(); /* check options */ - while ((c = getopt(argc, argv, ":o:denuvFsA")) != -1) { + while ((c = getopt(argc, argv, ":o:denuvMFsA")) != -1) { switch (c) { case 'o': if (parseprop(props, optarg) != 0) @@ -4079,6 +4079,9 @@ case 'F': flags.force = B_TRUE; break; + case 'M': + flags.forceunmount = B_TRUE; + break; case 'A': abort_resumable = B_TRUE; break; Index: cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h =================================================================== --- cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h +++ cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h @@ -716,6 +716,9 @@ /* do not mount file systems as they are extracted (private) */ boolean_t nomount; + + /* force unmount while recv snapshot (private) */ + boolean_t forceunmount; } recvflags_t; extern int zfs_receive(libzfs_handle_t *, const char *, nvlist_t *, Index: cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c =================================================================== --- cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c +++ cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c @@ -2893,7 +2893,8 @@ ZFS_TYPE_FILESYSTEM); if (zhp != NULL) { clp = changelist_gather(zhp, - ZFS_PROP_MOUNTPOINT, 0, 0); + ZFS_PROP_MOUNTPOINT, 0, + flags->force ? MS_FORCE : 0); zfs_close(zhp); if (clp != NULL) { softerr |= @@ -3395,7 +3396,8 @@ if (!flags->dryrun && zhp->zfs_type == ZFS_TYPE_FILESYSTEM && stream_wantsnewfs) { /* We can't do online recv in this case */ - clp = changelist_gather(zhp, ZFS_PROP_NAME, 0, 0); + clp = changelist_gather(zhp, ZFS_PROP_NAME, 0, + flags->forceunmount ? MS_FORCE : 0); if (clp == NULL) { zfs_close(zhp); zcmd_free_nvlists(&zc); @@ -3824,6 +3826,8 @@ int cleanup_fd; uint64_t action_handle = 0; char *originsnap = NULL; + int mflags = 0; + if (props) { err = nvlist_lookup_string(props, "origin", &originsnap); if (err && err != ENOENT) @@ -3838,6 +3842,10 @@ VERIFY(0 == close(cleanup_fd)); + if (flags->forceunmount) { + mflags = MS_FORCE; + } + if (err == 0 && !flags->nomount && top_zfs) { zfs_handle_t *zhp; prop_changelist_t *clp; @@ -3845,7 +3853,8 @@ zhp = zfs_open(hdl, top_zfs, ZFS_TYPE_FILESYSTEM); if (zhp != NULL) { clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT, - CL_GATHER_MOUNT_ALWAYS, 0); + CL_GATHER_MOUNT_ALWAYS, + flags->forceunmount ? MS_FORCE : 0); zfs_close(zhp); if (clp != NULL) { /* mount and share received datasets */