aboutsummaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/zfs/zfs_main.c120
-rw-r--r--cmd/zstreamdump/zstreamdump.c5
2 files changed, 105 insertions, 20 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
diff --git a/cmd/zstreamdump/zstreamdump.c b/cmd/zstreamdump/zstreamdump.c
index f288d148e..08d52bb37 100644
--- a/cmd/zstreamdump/zstreamdump.c
+++ b/cmd/zstreamdump/zstreamdump.c
@@ -127,7 +127,7 @@ read_hdr(dmu_replay_record_t *drr, zio_cksum_t *cksum)
(longlong_t)saved_cksum.zc_word[1],
(longlong_t)saved_cksum.zc_word[2],
(longlong_t)saved_cksum.zc_word[3]);
- exit(1);
+ return (0);
}
return (sizeof (*drr));
}
@@ -347,8 +347,7 @@ main(int argc, char *argv[])
if (verbose)
(void) printf("\n");
- if ((DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
- DMU_COMPOUNDSTREAM) && drr->drr_payloadlen != 0) {
+ if (drr->drr_payloadlen != 0) {
nvlist_t *nv;
int sz = drr->drr_payloadlen;