summaryrefslogtreecommitdiff
path: root/usr/src/cmd/zfs
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2019-08-01 11:34:42 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2019-08-01 11:34:42 +0000
commit7f874eb65f07035e3f808d58a70ad712248fde0a (patch)
treecf9ef0b9e1cc37c48c49f4cafe18d7ad105d5ce6 /usr/src/cmd/zfs
parentec6335ff2d187135730376f34f2fe1cae4189572 (diff)
parent6ccda740e007c01cb5d1436fe337851ff8c5d422 (diff)
downloadillumos-joyent-7f874eb65f07035e3f808d58a70ad712248fde0a.tar.gz
[illumos-gate merge]
commit 6ccda740e007c01cb5d1436fe337851ff8c5d422 11282 port ZoL send/recv fixes
Diffstat (limited to 'usr/src/cmd/zfs')
-rw-r--r--usr/src/cmd/zfs/zfs_main.c109
1 files changed, 75 insertions, 34 deletions
diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c
index dc14a2c609..9ca6c03be7 100644
--- a/usr/src/cmd/zfs/zfs_main.c
+++ b/usr/src/cmd/zfs/zfs_main.c
@@ -269,10 +269,12 @@ get_usage(zfs_help_t idx)
case HELP_PROMOTE:
return (gettext("\tpromote <clone-filesystem>\n"));
case HELP_RECEIVE:
- return (gettext("\treceive [-vnsFu] <filesystem|volume|"
- "snapshot>\n"
- "\treceive [-vnsFu] [-o origin=<snapshot>] [-d | -e] "
- "<filesystem>\n"
+ return (gettext("\treceive [-vnsFhu] "
+ "[-o <property>=<value>] ... [-x <property>] ...\n"
+ "\t <filesystem|volume|snapshot>\n"
+ "\treceive [-vnsFhu] [-o <property>=<value>] ... "
+ "[-x <property>] ... \n"
+ "\t [-d | -e] <filesystem>\n"
"\treceive -A <filesystem|volume>\n"));
case HELP_RENAME:
return (gettext("\trename [-f] <filesystem|volume|snapshot> "
@@ -282,9 +284,9 @@ get_usage(zfs_help_t idx)
case HELP_ROLLBACK:
return (gettext("\trollback [-rRf] <snapshot>\n"));
case HELP_SEND:
- return (gettext("\tsend [-DnPpRvLecr] [-[iI] snapshot] "
+ return (gettext("\tsend [-DnPpRvLecwhb] [-[iI] snapshot] "
"<snapshot>\n"
- "\tsend [-Lecr] [-i snapshot|bookmark] "
+ "\tsend [-nvPLecw] [-i snapshot|bookmark] "
"<filesystem|volume|snapshot>\n"
"\tsend [-nvPe] -t <receive_resume_token>\n"));
case HELP_SET:
@@ -536,26 +538,48 @@ usage(boolean_t requested)
* Take a property=value argument string and add it to the given nvlist.
* Modifies the argument inplace.
*/
-static int
+static boolean_t
parseprop(nvlist_t *props, char *propname)
{
- char *propval, *strval;
+ char *propval;
if ((propval = strchr(propname, '=')) == NULL) {
(void) fprintf(stderr, gettext("missing "
"'=' for property=value argument\n"));
- return (-1);
+ return (B_FALSE);
}
*propval = '\0';
propval++;
- if (nvlist_lookup_string(props, propname, &strval) == 0) {
+ if (nvlist_exists(props, propname)) {
(void) fprintf(stderr, gettext("property '%s' "
"specified multiple times\n"), propname);
- return (-1);
+ return (B_FALSE);
}
if (nvlist_add_string(props, propname, propval) != 0)
nomem();
- return (0);
+ return (B_TRUE);
+}
+
+/*
+ * Take a property name argument and add it to the given nvlist.
+ * Modifies the argument inplace.
+ */
+static boolean_t
+parsepropname(nvlist_t *props, char *propname)
+{
+ if (strchr(propname, '=') != NULL) {
+ (void) fprintf(stderr, gettext("invalid character "
+ "'=' in property argument\n"));
+ return (B_FALSE);
+ }
+ if (nvlist_exists(props, propname)) {
+ (void) fprintf(stderr, gettext("property '%s' "
+ "specified multiple times\n"), propname);
+ return (B_FALSE);
+ }
+ if (nvlist_add_boolean(props, propname) != 0)
+ nomem();
+ return (B_TRUE);
}
static int
@@ -679,8 +703,10 @@ zfs_do_clone(int argc, char **argv)
keeptrying = B_TRUE;
break;
case 'o':
- if (parseprop(props, optarg) != 0)
+ if (!parseprop(props, optarg)) {
+ nvlist_free(props);
return (1);
+ }
break;
case 'p':
parents = B_TRUE;
@@ -863,7 +889,7 @@ zfs_do_create(int argc, char **argv)
dryrun = B_TRUE;
break;
case 'o':
- if (parseprop(props, optarg) != 0)
+ if (!parseprop(props, optarg))
goto error;
break;
case 's':
@@ -3764,8 +3790,10 @@ zfs_do_set(int argc, char **argv)
if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
nomem();
for (int i = 1; i < ds_start; i++) {
- if ((ret = parseprop(props, argv[i])) != 0)
+ if (!parseprop(props, argv[i])) {
+ ret = -1;
goto error;
+ }
}
ret = zfs_for_each(argc - ds_start, argv + ds_start, 0,
@@ -3832,8 +3860,11 @@ zfs_do_snapshot(int argc, char **argv)
while ((c = getopt(argc, argv, "ro:")) != -1) {
switch (c) {
case 'o':
- if (parseprop(props, optarg) != 0)
+ if (!parseprop(props, optarg)) {
+ nvlist_free(sd.sd_nvl);
+ nvlist_free(props);
return (1);
+ }
break;
case 'r':
sd.sd_recursive = B_TRUE;
@@ -3916,11 +3947,13 @@ zfs_do_send(int argc, char **argv)
{"resume", required_argument, NULL, 't'},
{"compressed", no_argument, NULL, 'c'},
{"raw", no_argument, NULL, 'w'},
+ {"backup", no_argument, NULL, 'b'},
+ {"holds", no_argument, NULL, 'h'},
{0, 0, 0, 0}
};
/* check options */
- while ((c = getopt_long(argc, argv, ":i:I:RbDpvnPLet:cw", long_options,
+ while ((c = getopt_long(argc, argv, ":i:I:RDpvnPLeht:cwb", long_options,
NULL)) != -1) {
switch (c) {
case 'i':
@@ -3940,6 +3973,12 @@ zfs_do_send(int argc, char **argv)
case 'p':
flags.props = B_TRUE;
break;
+ case 'b':
+ flags.backup = B_TRUE;
+ break;
+ case 'h':
+ flags.holds = B_TRUE;
+ break;
case 'P':
flags.parsable = B_TRUE;
flags.verbose = B_TRUE;
@@ -4020,7 +4059,7 @@ zfs_do_send(int argc, char **argv)
if (resume_token != NULL) {
if (fromname != NULL || flags.replicate || flags.props ||
- flags.dedup) {
+ flags.backup || flags.dedup) {
(void) fprintf(stderr,
gettext("invalid flags combined with -t\n"));
usage(B_FALSE);
@@ -4063,8 +4102,8 @@ zfs_do_send(int argc, char **argv)
enum lzc_send_flags lzc_flags = 0;
if (flags.replicate || flags.doall || flags.props ||
- flags.dedup || flags.dryrun || flags.verbose ||
- flags.progress) {
+ flags.backup || flags.dedup || flags.holds ||
+ flags.dryrun || flags.verbose || flags.progress) {
(void) fprintf(stderr,
gettext("Error: "
"Unsupported flag with filesystem or bookmark.\n"));
@@ -4171,19 +4210,25 @@ zfs_do_receive(int argc, char **argv)
int c, err = 0;
recvflags_t flags = { 0 };
boolean_t abort_resumable = B_FALSE;
-
nvlist_t *props;
- nvpair_t *nvp = NULL;
if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
nomem();
/* check options */
- while ((c = getopt(argc, argv, ":o:denuvFsA")) != -1) {
+ while ((c = getopt(argc, argv, ":o:x:dehnuvFsA")) != -1) {
switch (c) {
case 'o':
- if (parseprop(props, optarg) != 0)
- return (1);
+ if (!parseprop(props, optarg)) {
+ nvlist_free(props);
+ usage(B_FALSE);
+ }
+ break;
+ case 'x':
+ if (!parsepropname(props, optarg)) {
+ nvlist_free(props);
+ usage(B_FALSE);
+ }
break;
case 'd':
flags.isprefix = B_TRUE;
@@ -4192,6 +4237,9 @@ zfs_do_receive(int argc, char **argv)
flags.isprefix = B_TRUE;
flags.istail = B_TRUE;
break;
+ case 'h':
+ flags.skipholds = B_TRUE;
+ break;
case 'n':
flags.dryrun = B_TRUE;
break;
@@ -4235,13 +4283,6 @@ zfs_do_receive(int argc, char **argv)
usage(B_FALSE);
}
- while ((nvp = nvlist_next_nvpair(props, nvp))) {
- if (strcmp(nvpair_name(nvp), "origin") != 0) {
- (void) fprintf(stderr, gettext("invalid option"));
- usage(B_FALSE);
- }
- }
-
if (abort_resumable) {
if (flags.isprefix || flags.istail || flags.dryrun ||
flags.resumable || flags.nomount) {
@@ -6179,7 +6220,7 @@ share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol,
(void) fprintf(stderr, gettext("cannot %s '%s': "
"Contains partially-completed state from "
- "\"zfs receive -r\", which can be resumed with "
+ "\"zfs receive -s\", which can be resumed with "
"\"zfs send -t\"\n"),
cmdname, zfs_get_name(zhp));
return (1);
@@ -7657,7 +7698,7 @@ zfs_do_change_key(int argc, char **argv)
inheritkey = B_TRUE;
break;
case 'o':
- if (parseprop(props, optarg) != 0) {
+ if (!parseprop(props, optarg)) {
nvlist_free(props);
return (1);
}