Skip to content

Commit

Permalink
ztest: fix -o by calling set_global_var in child processes
Browse files Browse the repository at this point in the history
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 openzfs#11602
  • Loading branch information
problame authored and RageLtMan committed May 31, 2021
1 parent 4ff647e commit 1c2e919
Showing 1 changed file with 51 additions and 2 deletions.
53 changes: 51 additions & 2 deletions cmd/ztest/ztest.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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 = {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -922,8 +928,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;
Expand Down Expand Up @@ -7933,6 +7952,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)
{
Expand Down Expand Up @@ -8049,7 +8089,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;

Expand Down Expand Up @@ -8116,6 +8156,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);
Expand Down

0 comments on commit 1c2e919

Please sign in to comment.