summaryrefslogtreecommitdiff
path: root/usr/src/lib/libzfs
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2015-04-09 11:45:19 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2015-04-09 11:45:19 +0000
commit2b223b8361851779edb84f2c1e0b6eb6be89cebe (patch)
tree5aa00d1bdfee7bd8c537449a78f1ab93044f3a12 /usr/src/lib/libzfs
parent52d1e941a3244efb8ae46e42c7d2d6ec9ec3f188 (diff)
parent30925561c223021e91d15899cbe75f80e54d8889 (diff)
downloadillumos-joyent-2b223b8361851779edb84f2c1e0b6eb6be89cebe.tar.gz
[illumos-gate merge]
commit 30925561c223021e91d15899cbe75f80e54d8889 5745 zfs set allows only one dataset property to be set at a time commit 643da460c8ca583e39ce053081754e24087f84c8 5765 add support for estimating send stream size with lzc_send_space when source is a bookmark commit dc5f28a3c341db7c241bba77ddc109c141072f27 5764 "zfs send -nv" directs output to stderr commit 1c445679611e2f17e31e163f4eeb49f65c99d191 5794 Add reference to RFC 5903 to ike.config(4) commit 4bc492d2bb45bc1a51b553ae441cfee4289cb3ee 5775 mr_sas initialisation pauses unecessarily for 60 seconds.
Diffstat (limited to 'usr/src/lib/libzfs')
-rw-r--r--usr/src/lib/libzfs/common/libzfs.h3
-rw-r--r--usr/src/lib/libzfs/common/libzfs_dataset.c157
-rw-r--r--usr/src/lib/libzfs/common/libzfs_sendrecv.c24
-rw-r--r--usr/src/lib/libzfs/common/libzfs_util.c16
-rw-r--r--usr/src/lib/libzfs/common/mapfile-vers3
5 files changed, 144 insertions, 59 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h
index 531ee14d61..ddb85646f7 100644
--- a/usr/src/lib/libzfs/common/libzfs.h
+++ b/usr/src/lib/libzfs/common/libzfs.h
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
@@ -427,6 +427,7 @@ extern nvlist_t *zfs_valid_proplist(libzfs_handle_t *, zfs_type_t,
extern const char *zfs_prop_to_name(zfs_prop_t);
extern int zfs_prop_set(zfs_handle_t *, const char *, const char *);
+extern int zfs_prop_set_list(zfs_handle_t *, nvlist_t *);
extern int zfs_prop_get(zfs_handle_t *, zfs_prop_t, char *, size_t,
zprop_source_t *, char *, size_t, boolean_t);
extern int zfs_prop_get_recvd(zfs_handle_t *, const char *, char *, size_t,
diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c
index f2dd13f1af..c69fad8174 100644
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c
@@ -1497,15 +1497,10 @@ zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err,
int
zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
{
- zfs_cmd_t zc = { 0 };
int ret = -1;
- prop_changelist_t *cl = NULL;
char errbuf[1024];
libzfs_handle_t *hdl = zhp->zfs_hdl;
- nvlist_t *nvl = NULL, *realprops;
- zfs_prop_t prop;
- boolean_t do_prefix = B_TRUE;
- int added_resv;
+ nvlist_t *nvl = NULL;
(void) snprintf(errbuf, sizeof (errbuf),
dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
@@ -1517,65 +1512,133 @@ zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
goto error;
}
- if ((realprops = zfs_valid_proplist(hdl, zhp->zfs_type, nvl,
- zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL)
- goto error;
+ ret = zfs_prop_set_list(zhp, nvl);
+error:
nvlist_free(nvl);
- nvl = realprops;
+ return (ret);
+}
- prop = zfs_name_to_prop(propname);
- if (prop == ZFS_PROP_VOLSIZE) {
- if ((added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1)
- goto error;
- }
- if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL)
- goto error;
+/*
+ * Given an nvlist of property names and values, set the properties for the
+ * given dataset.
+ */
+int
+zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
+{
+ zfs_cmd_t zc = { 0 };
+ int ret = -1;
+ prop_changelist_t **cls = NULL;
+ int cl_idx;
+ char errbuf[1024];
+ libzfs_handle_t *hdl = zhp->zfs_hdl;
+ nvlist_t *nvl;
+ int nvl_len;
+ int added_resv;
- if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "child dataset with inherited mountpoint is used "
- "in a non-global zone"));
- ret = zfs_error(hdl, EZFS_ZONED, errbuf);
+ (void) snprintf(errbuf, sizeof (errbuf),
+ dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
+ zhp->zfs_name);
+
+ if ((nvl = zfs_valid_proplist(hdl, zhp->zfs_type, props,
+ zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL)
goto error;
- }
/*
- * We don't want to unmount & remount the dataset when changing
- * its canmount property to 'on' or 'noauto'. We only use
- * the changelist logic to unmount when setting canmount=off.
+ * We have to check for any extra properties which need to be added
+ * before computing the length of the nvlist.
*/
- if (prop == ZFS_PROP_CANMOUNT) {
- uint64_t idx;
- int err = zprop_string_to_index(prop, propval, &idx,
- ZFS_TYPE_DATASET);
- if (err == 0 && idx != ZFS_CANMOUNT_OFF)
- do_prefix = B_FALSE;
+ for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
+ elem != NULL;
+ elem = nvlist_next_nvpair(nvl, elem)) {
+ if (zfs_name_to_prop(nvpair_name(elem)) == ZFS_PROP_VOLSIZE &&
+ (added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1) {
+ goto error;
+ }
}
-
- if (do_prefix && (ret = changelist_prefix(cl)) != 0)
+ /*
+ * Check how many properties we're setting and allocate an array to
+ * store changelist pointers for postfix().
+ */
+ nvl_len = 0;
+ for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
+ elem != NULL;
+ elem = nvlist_next_nvpair(nvl, elem))
+ nvl_len++;
+ if ((cls = calloc(nvl_len, sizeof (prop_changelist_t *))) == NULL)
goto error;
+ cl_idx = 0;
+ for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
+ elem != NULL;
+ elem = nvlist_next_nvpair(nvl, elem)) {
+
+ zfs_prop_t prop = zfs_name_to_prop(nvpair_name(elem));
+
+ assert(cl_idx < nvl_len);
+ /*
+ * We don't want to unmount & remount the dataset when changing
+ * its canmount property to 'on' or 'noauto'. We only use
+ * the changelist logic to unmount when setting canmount=off.
+ */
+ if (!(prop == ZFS_PROP_CANMOUNT &&
+ fnvpair_value_uint64(elem) != ZFS_CANMOUNT_OFF)) {
+ cls[cl_idx] = changelist_gather(zhp, prop, 0, 0);
+ if (cls[cl_idx] == NULL)
+ goto error;
+ }
+
+ if (prop == ZFS_PROP_MOUNTPOINT &&
+ changelist_haszonedchild(cls[cl_idx])) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "child dataset with inherited mountpoint is used "
+ "in a non-global zone"));
+ ret = zfs_error(hdl, EZFS_ZONED, errbuf);
+ goto error;
+ }
+
+ if (cls[cl_idx] != NULL &&
+ (ret = changelist_prefix(cls[cl_idx])) != 0)
+ goto error;
+
+ cl_idx++;
+ }
+ assert(cl_idx == nvl_len);
+
/*
- * Execute the corresponding ioctl() to set this property.
+ * Execute the corresponding ioctl() to set this list of properties.
*/
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
- if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0)
+ if ((ret = zcmd_write_src_nvlist(hdl, &zc, nvl)) != 0 ||
+ (ret = zcmd_alloc_dst_nvlist(hdl, &zc, 0)) != 0)
goto error;
ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
if (ret != 0) {
- zfs_setprop_error(hdl, prop, errno, errbuf);
+ /* Get the list of unset properties back and report them. */
+ nvlist_t *errorprops = NULL;
+ if (zcmd_read_dst_nvlist(hdl, &zc, &errorprops) != 0)
+ goto error;
+ for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
+ elem != NULL;
+ elem = nvlist_next_nvpair(nvl, elem)) {
+ zfs_prop_t prop = zfs_name_to_prop(nvpair_name(elem));
+ zfs_setprop_error(hdl, prop, errno, errbuf);
+ }
+ nvlist_free(errorprops);
+
if (added_resv && errno == ENOSPC) {
/* clean up the volsize property we tried to set */
uint64_t old_volsize = zfs_prop_get_int(zhp,
ZFS_PROP_VOLSIZE);
nvlist_free(nvl);
+ nvl = NULL;
zcmd_free_nvlists(&zc);
+
if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
goto error;
if (nvlist_add_uint64(nvl,
@@ -1587,8 +1650,13 @@ zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
(void) zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
}
} else {
- if (do_prefix)
- ret = changelist_postfix(cl);
+ for (cl_idx = 0; cl_idx < nvl_len; cl_idx++) {
+ if (cls[cl_idx] != NULL) {
+ int clp_err = changelist_postfix(cls[cl_idx]);
+ if (clp_err != 0)
+ ret = clp_err;
+ }
+ }
/*
* Refresh the statistics so the new property value
@@ -1601,8 +1669,13 @@ zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
error:
nvlist_free(nvl);
zcmd_free_nvlists(&zc);
- if (cl)
- changelist_free(cl);
+ if (cls != NULL) {
+ for (cl_idx = 0; cl_idx < nvl_len; cl_idx++) {
+ if (cls[cl_idx] != NULL)
+ changelist_free(cls[cl_idx]);
+ }
+ free(cls);
+ }
return (ret);
}
@@ -4127,7 +4200,7 @@ zfs_smb_acl_mgmt(libzfs_handle_t *hdl, char *dataset, char *path,
if (cmd == ZFS_SMB_ACL_RENAME) {
if (nvlist_alloc(&nvlist, NV_UNIQUE_NAME, 0) != 0) {
(void) no_memory(hdl);
- return (NULL);
+ return (0);
}
}
diff --git a/usr/src/lib/libzfs/common/libzfs_sendrecv.c b/usr/src/lib/libzfs/common/libzfs_sendrecv.c
index c4944438aa..9a34fb32ea 100644
--- a/usr/src/lib/libzfs/common/libzfs_sendrecv.c
+++ b/usr/src/lib/libzfs/common/libzfs_sendrecv.c
@@ -806,7 +806,8 @@ typedef struct send_dump_data {
char prevsnap[ZFS_MAXNAMELEN];
uint64_t prevsnap_obj;
boolean_t seenfrom, seento, replicate, doall, fromorigin;
- boolean_t verbose, dryrun, parsable, progress, embed_data, large_block;
+ boolean_t verbose, dryrun, parsable, progress, embed_data, std_out;
+ boolean_t large_block;
int outfd;
boolean_t err;
nvlist_t *fss;
@@ -1034,6 +1035,7 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
int err;
boolean_t isfromsnap, istosnap, fromorigin;
boolean_t exclude = B_FALSE;
+ FILE *fout = sdd->std_out ? stdout : stderr;
err = 0;
thissnap = strchr(zhp->zfs_name, '@') + 1;
@@ -1108,30 +1110,30 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
if (sdd->parsable) {
if (sdd->prevsnap[0] != '\0') {
- (void) fprintf(stderr, "incremental\t%s\t%s",
+ (void) fprintf(fout, "incremental\t%s\t%s",
sdd->prevsnap, zhp->zfs_name);
} else {
- (void) fprintf(stderr, "full\t%s",
+ (void) fprintf(fout, "full\t%s",
zhp->zfs_name);
}
} else {
- (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
+ (void) fprintf(fout, dgettext(TEXT_DOMAIN,
"send from @%s to %s"),
sdd->prevsnap, zhp->zfs_name);
}
if (err == 0) {
if (sdd->parsable) {
- (void) fprintf(stderr, "\t%llu\n",
+ (void) fprintf(fout, "\t%llu\n",
(longlong_t)size);
} else {
char buf[16];
zfs_nicenum(size, buf, sizeof (buf));
- (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
+ (void) fprintf(fout, dgettext(TEXT_DOMAIN,
" estimated size is %s\n"), buf);
}
sdd->size += size;
} else {
- (void) fprintf(stderr, "\n");
+ (void) fprintf(fout, "\n");
}
}
@@ -1375,6 +1377,7 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
int pipefd[2];
dedup_arg_t dda = { 0 };
int featureflags = 0;
+ FILE *fout;
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot send '%s'"), zhp->zfs_name);
@@ -1509,6 +1512,9 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
sdd.filter_cb_arg = cb_arg;
if (debugnvp)
sdd.debugnv = *debugnvp;
+ if (sdd.verbose && sdd.dryrun)
+ sdd.std_out = B_TRUE;
+ fout = sdd.std_out ? stdout : stderr;
/*
* Some flags require that we place user holds on the datasets that are
@@ -1548,12 +1554,12 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
if (flags->verbose) {
if (flags->parsable) {
- (void) fprintf(stderr, "size\t%llu\n",
+ (void) fprintf(fout, "size\t%llu\n",
(longlong_t)sdd.size);
} else {
char buf[16];
zfs_nicenum(sdd.size, buf, sizeof (buf));
- (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
+ (void) fprintf(fout, dgettext(TEXT_DOMAIN,
"total estimated size is %s\n"), buf);
}
}
diff --git a/usr/src/lib/libzfs/common/libzfs_util.c b/usr/src/lib/libzfs/common/libzfs_util.c
index 2dff496454..59b978cf16 100644
--- a/usr/src/lib/libzfs/common/libzfs_util.c
+++ b/usr/src/lib/libzfs/common/libzfs_util.c
@@ -22,7 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
- * Copyright (c) 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
*/
/*
@@ -780,8 +780,9 @@ zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
if (len == 0)
len = 16 * 1024;
zc->zc_nvlist_dst_size = len;
- if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
- zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == NULL)
+ zc->zc_nvlist_dst =
+ (uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size);
+ if (zc->zc_nvlist_dst == 0)
return (-1);
return (0);
@@ -796,9 +797,9 @@ int
zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
{
free((void *)(uintptr_t)zc->zc_nvlist_dst);
- if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
- zfs_alloc(hdl, zc->zc_nvlist_dst_size))
- == NULL)
+ zc->zc_nvlist_dst =
+ (uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size);
+ if (zc->zc_nvlist_dst == 0)
return (-1);
return (0);
@@ -813,6 +814,9 @@ zcmd_free_nvlists(zfs_cmd_t *zc)
free((void *)(uintptr_t)zc->zc_nvlist_conf);
free((void *)(uintptr_t)zc->zc_nvlist_src);
free((void *)(uintptr_t)zc->zc_nvlist_dst);
+ zc->zc_nvlist_conf = NULL;
+ zc->zc_nvlist_src = NULL;
+ zc->zc_nvlist_dst = NULL;
}
static int
diff --git a/usr/src/lib/libzfs/common/mapfile-vers b/usr/src/lib/libzfs/common/mapfile-vers
index da1d82a67c..9ed5c461c0 100644
--- a/usr/src/lib/libzfs/common/mapfile-vers
+++ b/usr/src/lib/libzfs/common/mapfile-vers
@@ -20,7 +20,7 @@
#
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright 2011 Nexenta Systems, Inc. All rights reserved.
-# Copyright (c) 2013 by Delphix. All rights reserved.
+# Copyright (c) 2011, 2014 by Delphix. All rights reserved.
# Copyright (c) 2012, Joyent, Inc. All rights reserved.
#
# MAPFILE HEADER START
@@ -125,6 +125,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zfs_prop_is_string;
zfs_prop_readonly;
zfs_prop_set;
+ zfs_prop_set_list;
zfs_prop_string_to_index;
zfs_prop_to_name;
zfs_prop_user;