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.h2
-rw-r--r--usr/src/lib/libzfs/common/libzfs_dataset.c20
-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.c7
-rw-r--r--usr/src/lib/libzfs/common/libzfs_util.c41
-rw-r--r--usr/src/lib/libzfs/common/mapfile-vers3
7 files changed, 88 insertions, 4 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h
index eb550f606f..ddb85646f7 100644
--- a/usr/src/lib/libzfs/common/libzfs.h
+++ b/usr/src/lib/libzfs/common/libzfs.h
@@ -64,6 +64,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 */
@@ -184,6 +185,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 *);
diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c
index e491a65c93..f240b6494f 100644
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c
@@ -329,6 +329,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) {
@@ -1988,6 +1992,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);
@@ -2228,6 +2237,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
@@ -2238,6 +2248,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;
diff --git a/usr/src/lib/libzfs/common/libzfs_impl.h b/usr/src/lib/libzfs/common/libzfs_impl.h
index ad4142da3f..9d98718dcb 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) 2013 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 5fdfe1d591..01c059fe61 100644
--- a/usr/src/lib/libzfs/common/libzfs_iter.c
+++ b/usr/src/lib/libzfs/common/libzfs_iter.c
@@ -23,6 +23,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
#include <stdio.h>
@@ -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);
@@ -147,15 +151,19 @@ zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data)
zhp->zfs_type == ZFS_TYPE_BOOKMARK)
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 0418091025..0c37c36257 100644
--- a/usr/src/lib/libzfs/common/libzfs_pool.c
+++ b/usr/src/lib/libzfs/common/libzfs_pool.c
@@ -270,6 +270,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:
@@ -334,6 +340,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:
diff --git a/usr/src/lib/libzfs/common/libzfs_util.c b/usr/src/lib/libzfs/common/libzfs_util.c
index 507a72ce02..59b978cf16 100644
--- a/usr/src/lib/libzfs/common/libzfs_util.c
+++ b/usr/src/lib/libzfs/common/libzfs_util.c
@@ -83,6 +83,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"));
@@ -611,6 +614,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)
{
@@ -646,6 +685,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 c46260717e..9ed5c461c0 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) 2011, 2014 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;
@@ -104,6 +106,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;