aboutsummaryrefslogtreecommitdiff
path: root/cddl
diff options
context:
space:
mode:
authorMariusz Zaborski <oshogbo@FreeBSD.org>2020-04-11 17:54:35 +0000
committerMariusz Zaborski <oshogbo@FreeBSD.org>2020-04-11 17:54:35 +0000
commit23ee238fe5e3971569b3bd2ed2a2930110550466 (patch)
treed86f4ab8d193d4922ae377273be7ba1132f83c12 /cddl
parenteec362ef5816b61b79a98d28830c5ff1d757b3ae (diff)
downloadsrc-23ee238fe5e3971569b3bd2ed2a2930110550466.tar.gz
src-23ee238fe5e3971569b3bd2ed2a2930110550466.zip
zfs: Add option for forcible unmounting dataset while receiving snapshot.
Currently when the dataset is in use we can't receive snapshots. zfs send test/1@asd | zfs recv -FM test/2 cannot unmount '/test/2': Device busy This commits add option 'M' which attempts to forcibly unmount the dataset. Thanks to this we can enforce receiving snapshots in a single step. Note that this functionality is not supported on Linux because the VFS will prevent active mounted filesystems from being unmounted, even with the force option. This is the intended VFS behavior. Discussed-with: Pawel Jakub Dawidek <pjd@FreeBSD.org> Reviewed-by: Ryan Moeller <ryan@iXsystems.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Allan Jude <allanjude@freebsd.org> Differential Revision: https://reviews.freebsd.org/D22306 openzfs/zfs@a57d3d45d6efdff935421e2ef3f97e3dc089d93d
Notes
Notes: svn path=/head/; revision=359808
Diffstat (limited to 'cddl')
-rw-r--r--cddl/contrib/opensolaris/cmd/zfs/zfs.813
-rw-r--r--cddl/contrib/opensolaris/cmd/zfs/zfs_main.c9
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h3
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c10
4 files changed, 24 insertions, 11 deletions
diff --git a/cddl/contrib/opensolaris/cmd/zfs/zfs.8 b/cddl/contrib/opensolaris/cmd/zfs/zfs.8
index e060db67867c..74b94881a64a 100644
--- a/cddl/contrib/opensolaris/cmd/zfs/zfs.8
+++ b/cddl/contrib/opensolaris/cmd/zfs/zfs.8
@@ -32,7 +32,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 16, 2019
+.Dd February 16, 2020
.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
@@ -2909,14 +2909,14 @@ for more details.
.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
@@ -3016,6 +3016,9 @@ performing the receive operation. If receiving an incremental replication
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.
+This option is not supported on Linux.
.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
diff --git a/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c b/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
index 3f389d1a51ff..851ba3f9523f 100644
--- a/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
+++ b/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
@@ -274,9 +274,9 @@ get_usage(zfs_help_t idx)
case HELP_PROMOTE:
return (gettext("\tpromote <clone-filesystem>\n"));
case HELP_RECEIVE:
- return (gettext("\treceive|recv [-vnsFu] <filesystem|volume|"
+ return (gettext("\treceive|recv [-vnsFMu] <filesystem|volume|"
"snapshot>\n"
- "\treceive|recv [-vnsFu] [-o origin=<snapshot>] [-d | -e] "
+ "\treceive|recv [-vnsFMu] [-o origin=<snapshot>] [-d | -e] "
"<filesystem>\n"
"\treceive|recv -A <filesystem|volume>\n"));
case HELP_RENAME:
@@ -4078,7 +4078,7 @@ zfs_do_receive(int argc, char **argv)
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)
@@ -4106,6 +4106,9 @@ zfs_do_receive(int argc, char **argv)
case 'F':
flags.force = B_TRUE;
break;
+ case 'M':
+ flags.forceunmount = B_TRUE;
+ break;
case 'A':
abort_resumable = B_TRUE;
break;
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
index f5dbe7209db6..7d67f9463a1f 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
@@ -737,6 +737,9 @@ typedef struct recvflags {
/* 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 *,
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
index e6f654b25b5f..71a951027b30 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
@@ -2913,7 +2913,8 @@ zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
ZFS_TYPE_FILESYSTEM);
if (zhp != NULL) {
clp = changelist_gather(zhp,
- ZFS_PROP_MOUNTPOINT, 0, 0);
+ ZFS_PROP_MOUNTPOINT, 0,
+ flags->forceunmount ? MS_FORCE : 0);
zfs_close(zhp);
if (clp != NULL) {
softerr |=
@@ -3435,7 +3436,8 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
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);
@@ -3881,6 +3883,7 @@ zfs_receive(libzfs_handle_t *hdl, const char *tosnap, nvlist_t *props,
int cleanup_fd;
uint64_t action_handle = 0;
char *originsnap = NULL;
+
if (props) {
err = nvlist_lookup_string(props, "origin", &originsnap);
if (err && err != ENOENT)
@@ -3902,7 +3905,8 @@ zfs_receive(libzfs_handle_t *hdl, const char *tosnap, nvlist_t *props,
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 */