summaryrefslogtreecommitdiffstats
path: root/lib/libzpool/util.c
diff options
context:
space:
mode:
authorGeorge Melikov <[email protected]>2017-01-31 21:13:10 +0300
committerBrian Behlendorf <[email protected]>2017-01-31 10:13:10 -0800
commited828c0c375477ff27d5fa9a7bf46ae6b6f2e57a (patch)
tree09347b9e65fb56cd28afbe2ac3b1e29f0d175bc0 /lib/libzpool/util.c
parent41425f79dabc58e5ddb16cc701cc435a5480e56a (diff)
OpenZFS 7280 - Allow changing global libzpool variables in zdb and ztest through command line
Authored by: Pavel Zakharov <[email protected]> Reviewed by: Matthew Ahrens <[email protected]> Reviewed by: Dan Kimmel <[email protected]> Approved by: Robert Mustacchi <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Ported-by: George Melikov <[email protected]> OpenZFS-issue: https://www.illumos.org/issues/7280 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/0e60744 Closes #5676
Diffstat (limited to 'lib/libzpool/util.c')
-rw-r--r--lib/libzpool/util.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/lib/libzpool/util.c b/lib/libzpool/util.c
index bc3bcbe78..3bdc31722 100644
--- a/lib/libzpool/util.c
+++ b/lib/libzpool/util.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016 by Delphix. All rights reserved.
*/
#include <assert.h>
@@ -31,6 +32,7 @@
#include <sys/spa.h>
#include <sys/fs/zfs.h>
#include <sys/refcount.h>
+#include <dlfcn.h>
/*
* Routines needed by more than one client of libzpool.
@@ -158,3 +160,58 @@ show_pool_stats(spa_t *spa)
nvlist_free(config);
}
+
+/*
+ * Sets given global variable in libzpool to given unsigned 32-bit value.
+ * arg: "<variable>=<value>"
+ */
+int
+set_global_var(char *arg)
+{
+ void *zpoolhdl;
+ char *varname = arg, *varval;
+ u_longlong_t val;
+
+#ifndef _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");
+ return (ENOTSUP);
+#endif
+ if ((varval = strchr(arg, '=')) != NULL) {
+ *varval = '\0';
+ varval++;
+ val = strtoull(varval, NULL, 0);
+ if (val > UINT32_MAX) {
+ fprintf(stderr, "Value for global variable '%s' must "
+ "be a 32-bit unsigned integer\n", varname);
+ return (EOVERFLOW);
+ }
+ } else {
+ return (EINVAL);
+ }
+
+ 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);
+ return (EINVAL);
+ }
+ *var = (uint32_t)val;
+
+ dlclose(zpoolhdl);
+ } else {
+ fprintf(stderr, "Failed to open libzpool.so to set global "
+ "variable\n");
+ return (EIO);
+ }
+
+ return (0);
+}