aboutsummaryrefslogtreecommitdiffstats
path: root/cmd/ztest/ztest.c
diff options
context:
space:
mode:
authorChristian Schwarz <[email protected]>2021-02-16 11:14:44 +0100
committerBrian Behlendorf <[email protected]>2021-02-19 22:45:10 -0800
commit2801e68d1bedaedd76c433a7cf6eafd304bc7ccf (patch)
tree967c3e3f65e895e8f64eff26161b3ae42d50deb4 /cmd/ztest/ztest.c
parentedc508ac0b80996d872f3c5d86c2ee49b519a661 (diff)
ztest: fix -o by calling set_global_var in child processes
Without set_global_var() in the child processes the -o option provides little use. Before this change set_global_var() was called as a side-effect of getopt processing which only happens for the parent ztest process. This change limits the set of options that can be set and makes them available to the child through ztest_shared_opts_t. Future work: support arbitrary option count and length. Reviewed-by: Matthew Ahrens <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Pavel Zakharov <[email protected]> Signed-off-by: Christian Schwarz <[email protected]> Closes #11602
Diffstat (limited to 'cmd/ztest/ztest.c')
-rw-r--r--cmd/ztest/ztest.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c
index d2bf01019..51952be33 100644
--- a/cmd/ztest/ztest.c
+++ b/cmd/ztest/ztest.c
@@ -158,6 +158,9 @@ enum ztest_class_state {
ZTEST_VDEV_CLASS_RND
};
+#define ZO_GVARS_MAX_ARGLEN ((size_t)64)
+#define ZO_GVARS_MAX_COUNT ((size_t)10)
+
typedef struct ztest_shared_opts {
char zo_pool[ZFS_MAX_DATASET_NAME_LEN];
char zo_dir[ZFS_MAX_DATASET_NAME_LEN];
@@ -185,6 +188,8 @@ typedef struct ztest_shared_opts {
int zo_mmp_test;
int zo_special_vdevs;
int zo_dump_dbgmsg;
+ int zo_gvars_count;
+ char zo_gvars[ZO_GVARS_MAX_COUNT][ZO_GVARS_MAX_ARGLEN];
} ztest_shared_opts_t;
static const ztest_shared_opts_t ztest_opts_defaults = {
@@ -212,6 +217,7 @@ static const ztest_shared_opts_t ztest_opts_defaults = {
.zo_maxloops = 50, /* max loops during spa_freeze() */
.zo_metaslab_force_ganging = 64 << 10,
.zo_special_vdevs = ZTEST_VDEV_CLASS_RND,
+ .zo_gvars_count = 0,
};
extern uint64_t metaslab_force_ganging;
@@ -918,8 +924,21 @@ process_options(int argc, char **argv)
ztest_parse_name_value(optarg, zo);
break;
case 'o':
- if (set_global_var(optarg) != 0)
+ if (zo->zo_gvars_count >= ZO_GVARS_MAX_COUNT) {
+ (void) fprintf(stderr,
+ "max global var count (%zu) exceeded\n",
+ ZO_GVARS_MAX_COUNT);
+ usage(B_FALSE);
+ }
+ char *v = zo->zo_gvars[zo->zo_gvars_count];
+ if (strlcpy(v, optarg, ZO_GVARS_MAX_ARGLEN) >=
+ ZO_GVARS_MAX_ARGLEN) {
+ (void) fprintf(stderr,
+ "global var option '%s' is too long\n",
+ optarg);
usage(B_FALSE);
+ }
+ zo->zo_gvars_count++;
break;
case 'G':
zo->zo_dump_dbgmsg = 1;
@@ -7611,6 +7630,27 @@ setup_data(void)
ztest_shared_ds = (void *)&buf[offset];
}
+static int
+ztest_set_global_vars(void)
+{
+ for (size_t i = 0; i < ztest_opts.zo_gvars_count; i++) {
+ char *kv = ztest_opts.zo_gvars[i];
+ VERIFY3U(strlen(kv), <=, ZO_GVARS_MAX_ARGLEN);
+ VERIFY3U(strlen(kv), >, 0);
+ int err = set_global_var(kv);
+ if (ztest_opts.zo_verbose > 0) {
+ (void) printf("setting global var %s ... %s\n", kv,
+ err ? "failed" : "ok");
+ }
+ if (err != 0) {
+ (void) fprintf(stderr,
+ "failed to set global var '%s'\n", kv);
+ return (err);
+ }
+ }
+ return (0);
+}
+
static boolean_t
exec_child(char *cmd, char *libpath, boolean_t ignorekill, int *statusp)
{
@@ -7727,7 +7767,7 @@ main(int argc, char **argv)
char numbuf[NN_NUMBUF_SZ];
char *cmd;
boolean_t hasalt;
- int f;
+ int f, err;
char *fd_data_str = getenv("ZTEST_FD_DATA");
struct sigaction action;
@@ -7794,6 +7834,15 @@ main(int argc, char **argv)
}
ASSERT3U(ztest_opts.zo_datasets, ==, ztest_shared_hdr->zh_ds_count);
+ err = ztest_set_global_vars();
+ if (err != 0 && !fd_data_str) {
+ /* error message done by ztest_set_global_vars */
+ exit(EXIT_FAILURE);
+ } else {
+ /* children should not be spawned if setting gvars fails */
+ VERIFY3S(err, ==, 0);
+ }
+
/* Override location of zpool.cache */
VERIFY3S(asprintf((char **)&spa_config_path, "%s/zpool.cache",
ztest_opts.zo_dir), !=, -1);