diff options
Diffstat (limited to 'sys/contrib/openzfs/lib/libzpool/util.c')
-rw-r--r-- | sys/contrib/openzfs/lib/libzpool/util.c | 198 |
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, }; |