summaryrefslogtreecommitdiff
path: root/usr/src/lib/libzfs
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libzfs')
-rw-r--r--usr/src/lib/libzfs/common/libzfs.h4
-rw-r--r--usr/src/lib/libzfs/common/libzfs_dataset.c25
-rw-r--r--usr/src/lib/libzfs/common/libzfs_impl.h3
-rw-r--r--usr/src/lib/libzfs/common/libzfs_iter.c16
-rw-r--r--usr/src/lib/libzfs/common/libzfs_pool.c32
-rw-r--r--usr/src/lib/libzfs/common/libzfs_util.c42
-rw-r--r--usr/src/lib/libzfs/common/mapfile-vers3
7 files changed, 104 insertions, 21 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h
index 49c86dd18f..bcb99b7758 100644
--- a/usr/src/lib/libzfs/common/libzfs.h
+++ b/usr/src/lib/libzfs/common/libzfs.h
@@ -62,6 +62,7 @@ typedef enum zfs_error {
EZFS_PROPTYPE, /* property does not apply to dataset type */
EZFS_PROPNONINHERIT, /* property is not inheritable */
EZFS_PROPSPACE, /* bad quota or reservation */
+ EZFS_PROPCACHED, /* prop unavail since cachedprops flag set */
EZFS_BADTYPE, /* dataset is not of appropriate type */
EZFS_BUSY, /* pool or dataset is busy */
EZFS_EXISTS, /* pool or dataset already exists */
@@ -182,6 +183,7 @@ extern libzfs_handle_t *zpool_get_handle(zpool_handle_t *);
extern libzfs_handle_t *zfs_get_handle(zfs_handle_t *);
extern void libzfs_print_on_error(libzfs_handle_t *, boolean_t);
+extern void libzfs_set_cachedprops(libzfs_handle_t *, boolean_t);
extern void zfs_save_arguments(int argc, char **, char *, int);
extern int zpool_log_history(libzfs_handle_t *, const char *);
@@ -264,7 +266,7 @@ extern int zpool_label_disk(libzfs_handle_t *, zpool_handle_t *, char *);
*/
extern int zpool_set_prop(zpool_handle_t *, const char *, const char *);
extern int zpool_get_prop(zpool_handle_t *, zpool_prop_t, char *,
- size_t proplen, zprop_source_t *);
+ size_t proplen, zprop_source_t *, boolean_t);
extern uint64_t zpool_get_prop_int(zpool_handle_t *, zpool_prop_t,
zprop_source_t *);
diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c
index 35d27d9d1f..2d444dcb4b 100644
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright 2012 Nexenta Systems, Inc. All rights reserved.
@@ -326,6 +327,10 @@ get_stats_ioctl(zfs_handle_t *zhp, zfs_cmd_t *zc)
{
libzfs_handle_t *hdl = zhp->zfs_hdl;
+ if (hdl->libzfs_cachedprops &&
+ libzfs_cmd_set_cachedprops(hdl, zc) != 0)
+ return (-1);
+
(void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name));
while (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, zc) != 0) {
@@ -1812,6 +1817,11 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
case ZFS_PROP_NORMALIZE:
case ZFS_PROP_UTF8ONLY:
case ZFS_PROP_CASE:
+ if (zhp->zfs_hdl->libzfs_cachedprops) {
+ return (zfs_error(zhp->zfs_hdl, EZFS_PROPCACHED,
+ "property unavailable since not cached"));
+ }
+
if (!zfs_prop_valid_for_type(prop, zhp->zfs_head_type) ||
zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
return (-1);
@@ -2051,6 +2061,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
char *str;
const char *strval;
boolean_t received = zfs_is_recvd_props_mode(zhp);
+ boolean_t printerr;
/*
* Check to see if this property applies to our object
@@ -2061,6 +2072,16 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
if (received && zfs_prop_readonly(prop))
return (-1);
+ if (zhp->zfs_hdl->libzfs_cachedprops &&
+ zfs_prop_cacheable(prop)) {
+ printerr = zhp->zfs_hdl->libzfs_printerr;
+ libzfs_print_on_error(zhp->zfs_hdl, B_FALSE);
+ (void) zfs_error(zhp->zfs_hdl, EZFS_PROPCACHED,
+ "property unavailable since not cached");
+ libzfs_print_on_error(zhp->zfs_hdl, printerr);
+ return (-1);
+ }
+
if (src)
*src = ZPROP_SRC_NONE;
@@ -2118,8 +2139,8 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
}
if ((zpool_get_prop(zhp->zpool_hdl,
- ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL)) ||
- (strcmp(root, "-") == 0))
+ ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL,
+ B_FALSE)) || (strcmp(root, "-") == 0))
root[0] = '\0';
/*
* Special case an alternate root of '/'. This will
diff --git a/usr/src/lib/libzfs/common/libzfs_impl.h b/usr/src/lib/libzfs/common/libzfs_impl.h
index 576b2af5d2..62793dcda1 100644
--- a/usr/src/lib/libzfs/common/libzfs_impl.h
+++ b/usr/src/lib/libzfs/common/libzfs_impl.h
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@@ -79,6 +80,7 @@ struct libzfs_handle {
libzfs_fru_t **libzfs_fru_hash;
libzfs_fru_t *libzfs_fru_list;
char libzfs_chassis_id[256];
+ boolean_t libzfs_cachedprops;
};
#define ZFSSHARE_MISS 0x01 /* Didn't find entry in cache */
@@ -149,6 +151,7 @@ int zpool_standard_error_fmt(libzfs_handle_t *, int, const char *, ...);
int get_dependents(libzfs_handle_t *, boolean_t, const char *, char ***,
size_t *);
zfs_handle_t *make_dataset_handle_zc(libzfs_handle_t *, zfs_cmd_t *);
+int libzfs_cmd_set_cachedprops(libzfs_handle_t *, zfs_cmd_t *);
int zprop_parse_value(libzfs_handle_t *, nvpair_t *, int, zfs_type_t,
diff --git a/usr/src/lib/libzfs/common/libzfs_iter.c b/usr/src/lib/libzfs/common/libzfs_iter.c
index be5767f542..48333df7d9 100644
--- a/usr/src/lib/libzfs/common/libzfs_iter.c
+++ b/usr/src/lib/libzfs/common/libzfs_iter.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@@ -110,6 +111,10 @@ zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data)
if (zhp->zfs_type != ZFS_TYPE_FILESYSTEM)
return (0);
+ if (zhp->zfs_hdl->libzfs_cachedprops &&
+ libzfs_cmd_set_cachedprops(zhp->zfs_hdl, &zc) != 0)
+ return (-1);
+
if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
return (-1);
@@ -120,9 +125,8 @@ zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data)
* that the pool has since been removed.
*/
if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl,
- &zc)) == NULL) {
+ &zc)) == NULL)
continue;
- }
if ((ret = func(nzhp, data)) != 0) {
zcmd_free_nvlists(&zc);
@@ -146,15 +150,19 @@ zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data)
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT)
return (0);
+ if (zhp->zfs_hdl->libzfs_cachedprops &&
+ libzfs_cmd_set_cachedprops(zhp->zfs_hdl, &zc) != 0)
+ return (-1);
+
if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
return (-1);
+
while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_SNAPSHOT_LIST_NEXT,
&zc)) == 0) {
if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl,
- &zc)) == NULL) {
+ &zc)) == NULL)
continue;
- }
if ((ret = func(nzhp, data)) != 0) {
zcmd_free_nvlists(&zc);
diff --git a/usr/src/lib/libzfs/common/libzfs_pool.c b/usr/src/lib/libzfs/common/libzfs_pool.c
index 1c6fb371e3..8315e1404b 100644
--- a/usr/src/lib/libzfs/common/libzfs_pool.c
+++ b/usr/src/lib/libzfs/common/libzfs_pool.c
@@ -23,6 +23,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
#include <ctype.h>
@@ -211,7 +212,7 @@ zpool_state_to_name(vdev_state_t state, vdev_aux_t aux)
*/
int
zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
- zprop_source_t *srctype)
+ zprop_source_t *srctype, boolean_t literal)
{
uint64_t intval;
const char *strval;
@@ -271,6 +272,12 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
case PROP_TYPE_NUMBER:
intval = zpool_get_prop_int(zhp, prop, &src);
+ if (literal && prop != ZPOOL_PROP_HEALTH) {
+ (void) snprintf(buf, len, "%llu",
+ (u_longlong_t)intval);
+ break;
+ }
+
switch (prop) {
case ZPOOL_PROP_SIZE:
case ZPOOL_PROP_ALLOCATED:
@@ -310,6 +317,7 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
default:
(void) snprintf(buf, len, "%llu", intval);
}
+
break;
case PROP_TYPE_INDEX:
@@ -376,7 +384,7 @@ zpool_is_bootable(zpool_handle_t *zhp)
char bootfs[ZPOOL_MAXNAMELEN];
return (zpool_get_prop(zhp, ZPOOL_PROP_BOOTFS, bootfs,
- sizeof (bootfs), NULL) == 0 && strncmp(bootfs, "-",
+ sizeof (bootfs), NULL, B_FALSE) == 0 && strncmp(bootfs, "-",
sizeof (bootfs)) != 0);
}
@@ -774,7 +782,7 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
if (entry->pl_prop != ZPROP_INVAL &&
zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf),
- NULL) == 0) {
+ NULL, B_FALSE) == 0) {
if (strlen(buf) > entry->pl_width)
entry->pl_width = strlen(buf);
}
@@ -3974,9 +3982,7 @@ supported_dump_vdev_type(libzfs_handle_t *hdl, nvlist_t *config, char *errbuf)
uint_t children, c;
verify(nvlist_lookup_string(config, ZPOOL_CONFIG_TYPE, &type) == 0);
- if (strcmp(type, VDEV_TYPE_RAIDZ) == 0 ||
- strcmp(type, VDEV_TYPE_FILE) == 0 ||
- strcmp(type, VDEV_TYPE_LOG) == 0 ||
+ if (strcmp(type, VDEV_TYPE_FILE) == 0 ||
strcmp(type, VDEV_TYPE_HOLE) == 0 ||
strcmp(type, VDEV_TYPE_MISSING) == 0) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -3995,8 +4001,12 @@ supported_dump_vdev_type(libzfs_handle_t *hdl, nvlist_t *config, char *errbuf)
}
/*
- * check if this zvol is allowable for use as a dump device; zero if
- * it is, > 0 if it isn't, < 0 if it isn't a zvol
+ * Check if this zvol is allowable for use as a dump device; zero if
+ * it is, > 0 if it isn't, < 0 if it isn't a zvol.
+ *
+ * Allowable storage configurations include mirrors, all raidz variants, and
+ * pools with log, cache, and spare devices. Pools which are backed by files or
+ * have missing/hole vdevs are not suitable.
*/
int
zvol_check_dump_config(char *arg)
@@ -4058,12 +4068,6 @@ zvol_check_dump_config(char *arg)
verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
&top, &toplevels) == 0);
- if (toplevels != 1) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "'%s' has multiple top level vdevs"), poolname);
- (void) zfs_error(hdl, EZFS_DEVOVERFLOW, errbuf);
- goto out;
- }
if (!supported_dump_vdev_type(hdl, top[0], errbuf)) {
goto out;
diff --git a/usr/src/lib/libzfs/common/libzfs_util.c b/usr/src/lib/libzfs/common/libzfs_util.c
index 41e25e9100..8706a6fdbb 100644
--- a/usr/src/lib/libzfs/common/libzfs_util.c
+++ b/usr/src/lib/libzfs/common/libzfs_util.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@@ -81,6 +82,9 @@ libzfs_error_description(libzfs_handle_t *hdl)
return (dgettext(TEXT_DOMAIN, "property cannot be inherited"));
case EZFS_PROPSPACE:
return (dgettext(TEXT_DOMAIN, "invalid quota or reservation"));
+ case EZFS_PROPCACHED:
+ return (dgettext(TEXT_DOMAIN, "property unavailable since "
+ "cachedprops flag set"));
case EZFS_BADTYPE:
return (dgettext(TEXT_DOMAIN, "operation not applicable to "
"datasets of this type"));
@@ -609,6 +613,42 @@ libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
hdl->libzfs_printerr = printerr;
}
+/*
+ * Set the value of the cachedprops flag. If the cachedprops flag is set,
+ * operations which get ZFS properties will only retrieve a property if the
+ * property is cached somewhere in memory.
+ *
+ * Consumers of libzfs should take care when setting this flag, as they will
+ * prevent themselves from listing the full set of ZFS properties.
+ *
+ * ZFS properties which always require disk I/O are ZPL properties (utf8only,
+ * normalization, etc.) and the volsize and volblocksize properties for volumes.
+ */
+void
+libzfs_set_cachedprops(libzfs_handle_t *hdl, boolean_t cachedprops)
+{
+ hdl->libzfs_cachedprops = cachedprops;
+}
+
+/*
+ * Adds a src nvlist to a zfs_cmd_t which specifies that only cached (i.e., will
+ * not require a disk access) properties should be retrieved.
+ */
+int
+libzfs_cmd_set_cachedprops(libzfs_handle_t *hdl, zfs_cmd_t *zc)
+{
+ nvlist_t *nvl;
+ int ret;
+
+ if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 ||
+ nvlist_add_boolean_value(nvl, "cachedpropsonly", B_TRUE) != 0)
+ return (no_memory(hdl));
+
+ ret = zcmd_write_src_nvlist(hdl, zc, nvl);
+ nvlist_free(nvl);
+ return (ret);
+}
+
libzfs_handle_t *
libzfs_init(void)
{
@@ -644,6 +684,8 @@ libzfs_init(void)
zpool_feature_init();
libzfs_mnttab_init(hdl);
+ hdl->libzfs_cachedprops = B_FALSE;
+
return (hdl);
}
diff --git a/usr/src/lib/libzfs/common/mapfile-vers b/usr/src/lib/libzfs/common/mapfile-vers
index 15075e3bb5..cff2c0dc9a 100644
--- a/usr/src/lib/libzfs/common/mapfile-vers
+++ b/usr/src/lib/libzfs/common/mapfile-vers
@@ -21,6 +21,7 @@
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright 2011 Nexenta Systems, Inc. All rights reserved.
# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright (c) 2012, Joyent, Inc. All rights reserved.
#
# MAPFILE HEADER START
#
@@ -59,6 +60,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
libzfs_init;
libzfs_mnttab_cache;
libzfs_print_on_error;
+ libzfs_set_cachedprops;
spa_feature_table;
zfs_allocatable_devs;
zfs_asprintf;
@@ -101,6 +103,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zfs_path_to_zhandle;
zfs_promote;
zfs_prop_align_right;
+ zfs_prop_cacheable;
zfs_prop_column_name;
zfs_prop_default_numeric;
zfs_prop_default_string;