diff options
author | asomers <asomers@FreeBSD.org> | 2017-10-25 14:45:56 +0000 |
---|---|---|
committer | asomers <asomers@FreeBSD.org> | 2017-10-25 14:45:56 +0000 |
commit | fe49fbe267d6f971964b5faf367f3c6a66b68458 (patch) | |
tree | cf30de8c2b7d4949a8388386fef193f2f40508f3 | |
parent | f919f1946d476558e28ea675dc0ac9da69bf506c (diff) | |
download | FreeBSD-src-fe49fbe267d6f971964b5faf367f3c6a66b68458.zip FreeBSD-src-fe49fbe267d6f971964b5faf367f3c6a66b68458.tar.gz |
MFC r324220:
MFV r316858 7280 Allow changing global libzpool variables in zdb
7280 Allow changing global libzpool variables in zdb and ztest through command line
illumos/illumos-gate@0e60744c982adecd0a1f146f5637475d07ab1069
https://github.com/illumos/illumos-gate/commit/0e60744c982adecd0a1f146f5637475d07ab1069
https://www.illumos.org/issues/7280
zdb is very handy for diagnosing problems with a pool in a safe and
quick way. When a pool is in a bad shape, we often want to disable some
fail-safes, or adjust some tunables in order to open them. In the
kernel, this is done by changing public variables in mdb. The goal of
this feature is to add the same capability to zdb and ztest, so that
they can change libzpool tuneables from the command line.
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Dan Kimmel <dan.kimmel@delphix.com>
Approved by: Robert Mustacchi <rm@joyent.com>
Author: Pavel Zakharov <pavel.zakharov@delphix.com>
-rw-r--r-- | cddl/contrib/opensolaris/cmd/zdb/zdb.8 | 5 | ||||
-rw-r--r-- | cddl/contrib/opensolaris/cmd/zdb/zdb.c | 12 | ||||
-rw-r--r-- | cddl/contrib/opensolaris/cmd/ztest/ztest.c | 8 | ||||
-rw-r--r-- | cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h | 3 | ||||
-rw-r--r-- | cddl/contrib/opensolaris/lib/libzpool/common/util.c | 57 |
5 files changed, 81 insertions, 4 deletions
diff --git a/cddl/contrib/opensolaris/cmd/zdb/zdb.8 b/cddl/contrib/opensolaris/cmd/zdb/zdb.8 index 6ae25c3..9d9ea94 100644 --- a/cddl/contrib/opensolaris/cmd/zdb/zdb.8 +++ b/cddl/contrib/opensolaris/cmd/zdb/zdb.8 @@ -33,6 +33,7 @@ .Op Fl U Ar cache .Op Fl I Ar inflight I/Os .Op Fl x Ar dumpdir +.Op Fl o Ar var=value .Ar poolname .Op Ar object ... .Nm @@ -252,6 +253,10 @@ Limit the number of outstanding checksum I/Os to the specified value. The default value is 200. This option affects the performance of the .Fl c option. +.It Fl o Ar var=value +Set the given global libzpool variable to the provided value. The value must be +an unsigned 32-bit integer. Currently only little-endian systems are supported +to avoid accidentally setting the high 32 bits of 64-bit variables. .It Fl P Print numbers in an unscaled form more amenable to parsing, eg. 1000000 rather than 1M. diff --git a/cddl/contrib/opensolaris/cmd/zdb/zdb.c b/cddl/contrib/opensolaris/cmd/zdb/zdb.c index 711377a..e9e2dd6 100644 --- a/cddl/contrib/opensolaris/cmd/zdb/zdb.c +++ b/cddl/contrib/opensolaris/cmd/zdb/zdb.c @@ -121,7 +121,8 @@ usage(void) { (void) fprintf(stderr, "Usage: %s [-CumMdibcsDvhLXFPAG] [-t txg] [-e [-p path...]] " - "[-U config] [-I inflight I/Os] [-x dumpdir] poolname [object...]\n" + "[-U config] [-I inflight I/Os] [-x dumpdir] [-o var=value] " + "poolname [object...]\n" " %s [-divPA] [-e -p path...] [-U config] dataset " "[object...]\n" " %s -mM [-LXFPA] [-t txg] [-e [-p path...]] [-U config] " @@ -183,6 +184,8 @@ usage(void) "checksumming I/Os [default is 200]\n"); (void) fprintf(stderr, " -G dump zfs_dbgmsg buffer before " "exiting\n"); + (void) fprintf(stderr, " -o <variable>=<value> set global " + "variable to an unsigned 32-bit integer value\n"); (void) fprintf(stderr, "Specify an option more than once (e.g. -bb) " "to make only that option verbose\n"); (void) fprintf(stderr, "Default is to dump everything non-verbosely\n"); @@ -3614,7 +3617,7 @@ main(int argc, char **argv) spa_config_path = spa_config_path_env; while ((c = getopt(argc, argv, - "bcdhilmMI:suCDRSAFLXx:evp:t:U:PG")) != -1) { + "bcdhilmMI:suCDRSAFLXx:evp:t:U:PGo:")) != -1) { switch (c) { case 'b': case 'c': @@ -3683,6 +3686,11 @@ main(int argc, char **argv) case 'x': vn_dumpdir = optarg; break; + case 'o': + error = set_global_var(optarg); + if (error != 0) + usage(); + break; default: usage(); break; diff --git a/cddl/contrib/opensolaris/cmd/ztest/ztest.c b/cddl/contrib/opensolaris/cmd/ztest/ztest.c index 2205c95..43e0269 100644 --- a/cddl/contrib/opensolaris/cmd/ztest/ztest.c +++ b/cddl/contrib/opensolaris/cmd/ztest/ztest.c @@ -583,6 +583,8 @@ usage(boolean_t requested) "\t[-F freezeloops (default: %llu)] max loops in spa_freeze()\n" "\t[-P passtime (default: %llu sec)] time per pass\n" "\t[-B alt_ztest (default: <none>)] alternate ztest path\n" + "\t[-o variable=value] ... set global variable to an unsigned\n" + "\t 32-bit integer value\n" "\t[-h] (print help)\n" "", zo->zo_pool, @@ -618,7 +620,7 @@ process_options(int argc, char **argv) bcopy(&ztest_opts_defaults, zo, sizeof (*zo)); while ((opt = getopt(argc, argv, - "v:s:a:m:r:R:d:t:g:i:k:p:f:VET:P:hF:B:")) != EOF) { + "v:s:a:m:r:R:d:t:g:i:k:p:f:VET:P:hF:B:o:")) != EOF) { value = 0; switch (opt) { case 'v': @@ -705,6 +707,10 @@ process_options(int argc, char **argv) case 'B': (void) strlcpy(altdir, optarg, sizeof (altdir)); break; + case 'o': + if (set_global_var(optarg) != 0) + usage(B_FALSE); + break; case 'h': usage(B_TRUE); break; diff --git a/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h b/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h index f11174f..b69aad2 100644 --- a/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h +++ b/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 by Delphix. All rights reserved. + * Copyright (c) 2012, 2016 by Delphix. All rights reserved. * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ /* @@ -581,6 +581,7 @@ extern void kernel_fini(void); struct spa; extern void nicenum(uint64_t num, char *buf); extern void show_pool_stats(struct spa *); +extern int set_global_var(char *arg); typedef struct callb_cpr { kmutex_t *cc_lockp; diff --git a/cddl/contrib/opensolaris/lib/libzpool/common/util.c b/cddl/contrib/opensolaris/lib/libzpool/common/util.c index 6257e2b..7cfc638 100644 --- a/cddl/contrib/opensolaris/lib/libzpool/common/util.c +++ b/cddl/contrib/opensolaris/lib/libzpool/common/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. @@ -153,3 +155,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", varname); + 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); +} |