aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/lib/libzpool/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/openzfs/lib/libzpool/util.c')
-rw-r--r--sys/contrib/openzfs/lib/libzpool/util.c198
1 files changed, 115 insertions, 83 deletions
diff --git a/sys/contrib/openzfs/lib/libzpool/util.c b/sys/contrib/openzfs/lib/libzpool/util.c
index a2bdfec1d173..66d6f43967d5 100644
--- a/sys/contrib/openzfs/lib/libzpool/util.c
+++ b/sys/contrib/openzfs/lib/libzpool/util.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: CDDL-1.0
/*
* CDDL HEADER START
*
@@ -6,7 +7,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -35,7 +36,7 @@
#include <sys/fs/zfs.h>
#include <sys/zfs_refcount.h>
#include <sys/zfs_ioctl.h>
-#include <dlfcn.h>
+#include <sys/tunables.h>
#include <libzutil.h>
/*
@@ -64,7 +65,8 @@ show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
}
if (desc != NULL) {
- char *suffix = "", *bias = NULL;
+ const char *suffix = "";
+ const char *bias = NULL;
char bias_suffix[32];
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG, &is_log);
@@ -112,7 +114,8 @@ show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
for (c = 0; c < children; c++) {
nvlist_t *cnv = child[c];
- char *cname = NULL, *tname;
+ const char *cname = NULL;
+ char *tname;
uint64_t np;
int len;
if (nvlist_lookup_string(cnv, ZPOOL_CONFIG_PATH, &cname) &&
@@ -132,14 +135,12 @@ void
show_pool_stats(spa_t *spa)
{
nvlist_t *config, *nvroot;
- char *name;
+ const char *name;
- VERIFY(spa_get_stats(spa_name(spa), &config, NULL, 0) == 0);
+ VERIFY0(spa_get_stats(spa_name(spa), &config, NULL, 0));
- VERIFY(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
- &nvroot) == 0);
- VERIFY(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
- &name) == 0);
+ VERIFY0(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvroot));
+ VERIFY0(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, &name));
show_vdev_stats(name, ZPOOL_CONFIG_CHILDREN, nvroot, 0);
show_vdev_stats(NULL, ZPOOL_CONFIG_L2CACHE, nvroot, 0);
@@ -148,100 +149,125 @@ show_pool_stats(spa_t *spa)
nvlist_free(config);
}
-/* *k_out must be freed by the caller */
+/*
+ * Common helper for working with libzpool tunables from the command line.
+ *
+ * Valid inputs:
+ *
+ * <name> show named tunable and value
+ * <name>=<value> set tunable value
+ *
+ * show show all tunables and values
+ * show=<name> show named tunable and value
+ * info show info about all tunables
+ * info=<name> show info about named tunable
+ */
+
+typedef enum { SHOW, INFO, SET } tunable_mode_t;
+
static int
-set_global_var_parse_kv(const char *arg, char **k_out, u_longlong_t *v_out)
+list_tunables_cb(const zfs_tunable_t *tunable, void *arg)
{
- int err;
- VERIFY(arg);
- char *d = strdup(arg);
-
- char *save = NULL;
- char *k = strtok_r(d, "=", &save);
- char *v_str = strtok_r(NULL, "=", &save);
- char *follow = strtok_r(NULL, "=", &save);
- if (k == NULL || v_str == NULL || follow != NULL) {
- err = EINVAL;
- goto err_free;
- }
-
- u_longlong_t val = strtoull(v_str, NULL, 0);
- if (val > UINT32_MAX) {
- fprintf(stderr, "Value for global variable '%s' must "
- "be a 32-bit unsigned integer, got '%s'\n", k, v_str);
- err = EOVERFLOW;
- goto err_free;
+ const tunable_mode_t *mode = arg;
+
+ static const char *type[] = {
+ "int", "uint", "ulong", "u64", "str",
+ };
+ static const char *perm[] = {
+ "rw", "rd",
+ };
+
+ if (*mode == SHOW) {
+ char val[64];
+ int err = zfs_tunable_get(tunable, val, sizeof (val));
+ if (err == 0)
+ printf("%s: %s\n", tunable->zt_name, val);
+ else
+ printf("%s: [error getting tunable value: %s]\n",
+ tunable->zt_name, strerror(err));
+ } else {
+ printf("%s [%s %s]: %s\n", tunable->zt_name,
+ type[tunable->zt_type], perm[tunable->zt_perm],
+ tunable->zt_desc);
}
- *k_out = k;
- *v_out = val;
return (0);
-
-err_free:
- free(k);
-
- return (err);
}
-
-/*
- * Sets given global variable in libzpool to given unsigned 32-bit value.
- * arg: "<variable>=<value>"
- */
int
-set_global_var(char const *arg)
+handle_tunable_option(const char *_arg, boolean_t quiet)
{
- void *zpoolhdl;
- char *varname;
- u_longlong_t val;
- int ret;
-
-#ifndef _ZFS_LITTLE_ENDIAN
- /*
- * On big endian systems changing a 64-bit variable would set the high
- * 32 bits instead of the low 32 bits, which could cause unexpected
- * results.
- */
- fprintf(stderr, "Setting global variables is only supported on "
- "little-endian systems\n");
- ret = ENOTSUP;
- goto out_ret;
-#endif
+ int err = 0;
+ char *arg = strdup(_arg);
+ char *k, *v;
+
+ v = arg;
+ k = strsep(&v, "=");
+
+ tunable_mode_t mode;
+
+ if (strcmp(k, "show") == 0) {
+ mode = SHOW;
+ k = v;
+ } else if (strcmp(k, "info") == 0) {
+ mode = INFO;
+ k = v;
+ } else if (v == NULL) {
+ mode = SHOW;
+ } else {
+ mode = SET;
+ }
- if ((ret = set_global_var_parse_kv(arg, &varname, &val)) != 0) {
- goto out_ret;
+ if (quiet && mode != SET) {
+ err = EINVAL;
+ goto out;
}
- zpoolhdl = dlopen("libzpool.so", RTLD_LAZY);
- if (zpoolhdl != NULL) {
- uint32_t *var;
- var = dlsym(zpoolhdl, varname);
- if (var == NULL) {
- fprintf(stderr, "Global variable '%s' does not exist "
- "in libzpool.so\n", varname);
- ret = EINVAL;
- goto out_dlclose;
+ if (mode == SET) {
+ const zfs_tunable_t *tunable = zfs_tunable_lookup(k);
+ if (tunable == NULL) {
+ err = ENOENT;
+ goto out;
}
- *var = (uint32_t)val;
+ char vold[256], vnew[256];
+ if (zfs_tunable_get(tunable, vold, sizeof (vold)) != 0)
+ strcpy(vold, "???");
+ err = zfs_tunable_set(tunable, v);
+ if (err != 0)
+ goto out;
+ if (zfs_tunable_get(tunable, vnew, sizeof (vnew)) != 0)
+ strcpy(vnew, "???");
+
+ if (!quiet)
+ printf("%s: %s -> %s\n", k, vold, vnew);
+ } else if (k != NULL) {
+ const zfs_tunable_t *tunable = zfs_tunable_lookup(k);
+ if (tunable == NULL) {
+ err = ENOENT;
+ goto out;
+ }
+ list_tunables_cb(tunable, &mode);
} else {
- fprintf(stderr, "Failed to open libzpool.so to set global "
- "variable\n");
- ret = EIO;
- goto out_dlclose;
+ zfs_tunable_iter(list_tunables_cb, &mode);
}
- ret = 0;
+out:
+ if (!quiet) {
+ if (err == ENOENT)
+ fprintf(stderr, "no such tunable: %s\n", k);
+ else if (err != 0)
+ fprintf(stderr, "couldn't set tunable '%s': %s\n",
+ k, strerror(err));
+ }
-out_dlclose:
- dlclose(zpoolhdl);
- free(varname);
-out_ret:
- return (ret);
+ free(arg);
+ return (err);
}
static nvlist_t *
refresh_config(void *unused, nvlist_t *tryconfig)
{
+ (void) unused;
return (spa_tryimport(tryconfig));
}
@@ -254,9 +280,12 @@ refresh_config(void *unused, nvlist_t *tryconfig)
static int
pool_active(void *unused, const char *name, uint64_t guid, boolean_t *isactive)
{
+ (void) unused, (void) guid;
zfs_iocparm_t zp;
zfs_cmd_t *zc = NULL;
+#ifdef ZFS_LEGACY_SUPPORT
zfs_cmd_legacy_t *zcl = NULL;
+#endif
unsigned long request;
int ret;
@@ -291,6 +320,7 @@ pool_active(void *unused, const char *name, uint64_t guid, boolean_t *isactive)
umem_free(zc, sizeof (zfs_cmd_t));
break;
+#ifdef ZFS_LEGACY_SUPPORT
case ZFS_IOCVER_LEGACY:
zcl = umem_zalloc(sizeof (zfs_cmd_legacy_t), UMEM_NOFAIL);
@@ -306,6 +336,7 @@ pool_active(void *unused, const char *name, uint64_t guid, boolean_t *isactive)
umem_free(zcl, sizeof (zfs_cmd_legacy_t));
break;
+#endif
default:
fprintf(stderr, "unrecognized zfs ioctl version %d", ver);
exit(1);
@@ -322,6 +353,7 @@ static int
pool_active(void *unused, const char *name, uint64_t guid,
boolean_t *isactive)
{
+ (void) unused, (void) guid;
int fd = open(ZFS_DEV, O_RDWR | O_CLOEXEC);
if (fd < 0)
return (-1);
@@ -345,7 +377,7 @@ pool_active(void *unused, const char *name, uint64_t guid,
}
#endif
-const pool_config_ops_t libzpool_config_ops = {
+pool_config_ops_t libzpool_config_ops = {
.pco_refresh_config = refresh_config,
.pco_pool_active = pool_active,
};