summaryrefslogtreecommitdiffstats
path: root/cmd/zfs
diff options
context:
space:
mode:
authorMatthew Ahrens <[email protected]>2016-01-06 22:22:48 +0100
committerBrian Behlendorf <[email protected]>2016-06-28 13:47:02 -0700
commit47dfff3b86c67c6ae184c2b7166eaa529590c2d2 (patch)
treeea731650ffe4a016c08fb83d2a6f00e6bd6738d4 /cmd/zfs
parent669cf0ab298dd66e512b37f6c4a42aee2d767b80 (diff)
OpenZFS 2605, 6980, 6902
2605 want to resume interrupted zfs send Reviewed by: George Wilson <[email protected]> Reviewed by: Paul Dagnelie <[email protected]> Reviewed by: Richard Elling <[email protected]> Reviewed by: Xin Li <[email protected]> Reviewed by: Arne Jansen <[email protected]> Approved by: Dan McDonald <[email protected]> Ported-by: kernelOfTruth <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> OpenZFS-issue: https://www.illumos.org/issues/2605 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/9c3fd12 6980 6902 causes zfs send to break due to 32-bit/64-bit struct mismatch Reviewed by: Paul Dagnelie <[email protected]> Reviewed by: George Wilson <[email protected]> Approved by: Robert Mustacchi <[email protected]> Ported by: Brian Behlendorf <[email protected]> OpenZFS-issue: https://www.illumos.org/issues/6980 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/ea4a67f Porting notes: - All rsend and snapshop tests enabled and updated for Linux. - Fix misuse of input argument in traverse_visitbp(). - Fix ISO C90 warnings and errors. - Fix gcc 'missing braces around initializer' in 'struct send_thread_arg to_arg =' warning. - Replace 4 argument fletcher_4_native() with 3 argument version, this change was made in OpenZFS 4185 which has not been ported. - Part of the sections for 'zfs receive' and 'zfs send' was rewritten and reordered to approximate upstream. - Fix mktree xattr creation, 'user.' prefix required. - Minor fixes to newly enabled test cases - Long holds for volumes allowed during receive for minor registration.
Diffstat (limited to 'cmd/zfs')
-rw-r--r--cmd/zfs/zfs_main.c120
1 files changed, 103 insertions, 17 deletions
diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c
index 8bcff2dba..3d20973a2 100644
--- a/cmd/zfs/zfs_main.c
+++ b/cmd/zfs/zfs_main.c
@@ -248,10 +248,11 @@ get_usage(zfs_help_t idx)
case HELP_PROMOTE:
return (gettext("\tpromote <clone-filesystem>\n"));
case HELP_RECEIVE:
- return (gettext("\treceive [-vnFu] <filesystem|volume|"
+ return (gettext("\treceive [-vnsFu] <filesystem|volume|"
"snapshot>\n"
- "\treceive [-vnFu] [-o origin=<snapshot>] [-d | -e] "
- "<filesystem>\n"));
+ "\treceive [-vnsFu] [-o origin=<snapshot>] [-d | -e] "
+ "<filesystem>\n"
+ "\treceive -A <filesystem|volume>\n"));
case HELP_RENAME:
return (gettext("\trename [-f] <filesystem|volume|snapshot> "
"<filesystem|volume|snapshot>\n"
@@ -263,7 +264,8 @@ get_usage(zfs_help_t idx)
return (gettext("\tsend [-DnPpRvLe] [-[iI] snapshot] "
"<snapshot>\n"
"\tsend [-Le] [-i snapshot|bookmark] "
- "<filesystem|volume|snapshot>\n"));
+ "<filesystem|volume|snapshot>\n"
+ "\tsend [-nvPe] -t <receive_resume_token>\n"));
case HELP_SET:
return (gettext("\tset <property=value> ... "
"<filesystem|volume|snapshot> ...\n"));
@@ -3707,6 +3709,7 @@ zfs_do_send(int argc, char **argv)
{
char *fromname = NULL;
char *toname = NULL;
+ char *resume_token = NULL;
char *cp;
zfs_handle_t *zhp;
sendflags_t flags = { 0 };
@@ -3715,7 +3718,7 @@ zfs_do_send(int argc, char **argv)
boolean_t extraverbose = B_FALSE;
/* check options */
- while ((c = getopt(argc, argv, ":i:I:RDpvnPLe")) != -1) {
+ while ((c = getopt(argc, argv, ":i:I:RDpvnPLet:")) != -1) {
switch (c) {
case 'i':
if (fromname)
@@ -3756,6 +3759,9 @@ zfs_do_send(int argc, char **argv)
case 'e':
flags.embed_data = B_TRUE;
break;
+ case 't':
+ resume_token = optarg;
+ break;
case ':':
(void) fprintf(stderr, gettext("missing argument for "
"'%c' option\n"), optopt);
@@ -3771,14 +3777,28 @@ zfs_do_send(int argc, char **argv)
argc -= optind;
argv += optind;
- /* check number of arguments */
- if (argc < 1) {
- (void) fprintf(stderr, gettext("missing snapshot argument\n"));
- usage(B_FALSE);
- }
- if (argc > 1) {
- (void) fprintf(stderr, gettext("too many arguments\n"));
- usage(B_FALSE);
+ if (resume_token != NULL) {
+ if (fromname != NULL || flags.replicate || flags.props ||
+ flags.dedup) {
+ (void) fprintf(stderr,
+ gettext("invalid flags combined with -t\n"));
+ usage(B_FALSE);
+ }
+ if (argc != 0) {
+ (void) fprintf(stderr, gettext("no additional "
+ "arguments are permitted with -t\n"));
+ usage(B_FALSE);
+ }
+ } else {
+ if (argc < 1) {
+ (void) fprintf(stderr,
+ gettext("missing snapshot argument\n"));
+ usage(B_FALSE);
+ }
+ if (argc > 1) {
+ (void) fprintf(stderr, gettext("too many arguments\n"));
+ usage(B_FALSE);
+ }
}
if (!flags.dryrun && isatty(STDOUT_FILENO)) {
@@ -3788,6 +3808,11 @@ zfs_do_send(int argc, char **argv)
return (1);
}
+ if (resume_token != NULL) {
+ return (zfs_send_resume(g_zfs, &flags, STDOUT_FILENO,
+ resume_token));
+ }
+
/*
* Special case sending a filesystem, or from a bookmark.
*/
@@ -3893,8 +3918,6 @@ zfs_do_send(int argc, char **argv)
}
/*
- * zfs receive [-vnFu] [-d | -e] <fs@snap>
- *
* Restore a backup stream from stdin.
*/
static int
@@ -3902,6 +3925,8 @@ zfs_do_receive(int argc, char **argv)
{
int c, err;
recvflags_t flags = { 0 };
+ boolean_t abort_resumable = B_FALSE;
+
nvlist_t *props;
nvpair_t *nvp = NULL;
@@ -3909,7 +3934,7 @@ zfs_do_receive(int argc, char **argv)
nomem();
/* check options */
- while ((c = getopt(argc, argv, ":o:denuvF")) != -1) {
+ while ((c = getopt(argc, argv, ":o:denuvFsA")) != -1) {
switch (c) {
case 'o':
if (parseprop(props, optarg) != 0)
@@ -3931,9 +3956,15 @@ zfs_do_receive(int argc, char **argv)
case 'v':
flags.verbose = B_TRUE;
break;
+ case 's':
+ flags.resumable = B_TRUE;
+ break;
case 'F':
flags.force = B_TRUE;
break;
+ case 'A':
+ abort_resumable = B_TRUE;
+ break;
case ':':
(void) fprintf(stderr, gettext("missing argument for "
"'%c' option\n"), optopt);
@@ -3966,6 +3997,44 @@ zfs_do_receive(int argc, char **argv)
}
}
+ if (abort_resumable) {
+ if (flags.isprefix || flags.istail || flags.dryrun ||
+ flags.resumable || flags.nomount) {
+ (void) fprintf(stderr, gettext("invalid option"));
+ usage(B_FALSE);
+ }
+
+ char namebuf[ZFS_MAXNAMELEN];
+ (void) snprintf(namebuf, sizeof (namebuf),
+ "%s/%%recv", argv[0]);
+
+ if (zfs_dataset_exists(g_zfs, namebuf,
+ ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) {
+ zfs_handle_t *zhp = zfs_open(g_zfs,
+ namebuf, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
+ if (zhp == NULL)
+ return (1);
+ err = zfs_destroy(zhp, B_FALSE);
+ } else {
+ zfs_handle_t *zhp = zfs_open(g_zfs,
+ argv[0], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
+ if (zhp == NULL)
+ usage(B_FALSE);
+ if (!zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) ||
+ zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN,
+ NULL, 0, NULL, NULL, 0, B_TRUE) == -1) {
+ (void) fprintf(stderr,
+ gettext("'%s' does not have any "
+ "resumable receive state to abort\n"),
+ argv[0]);
+ return (1);
+ }
+ err = zfs_destroy(zhp, B_FALSE);
+ }
+
+ return (err != 0);
+ }
+
if (isatty(STDIN_FILENO)) {
(void) fprintf(stderr,
gettext("Error: Backup stream can not be read "
@@ -3973,7 +4042,6 @@ zfs_do_receive(int argc, char **argv)
"You must redirect standard input.\n"));
return (1);
}
-
err = zfs_receive(g_zfs, argv[0], props, &flags, STDIN_FILENO, NULL);
return (err != 0);
@@ -5804,6 +5872,24 @@ share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol,
}
/*
+ * If this filesystem is inconsistent and has a receive resume
+ * token, we can not mount it.
+ */
+ if (zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) &&
+ zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN,
+ NULL, 0, NULL, NULL, 0, B_TRUE) == 0) {
+ if (!explicit)
+ return (0);
+
+ (void) fprintf(stderr, gettext("cannot %s '%s': "
+ "Contains partially-completed state from "
+ "\"zfs receive -r\", which can be resumed with "
+ "\"zfs send -t\"\n"),
+ cmdname, zfs_get_name(zhp));
+ return (1);
+ }
+
+ /*
* At this point, we have verified that the mountpoint and/or
* shareopts are appropriate for auto management. If the
* filesystem is already mounted or shared, return (failing