app: added --json-ignore-init-errors

If set, SPDK will continue loading the JSON config even if
some commands caused an error. This can be useful when loading
RPC config from spdk_tgt into e.g. bdevperf, which supports
only a subset of RPC commands and would usually fail with
"Method not found" message.

Resolves #840

Change-Id: I070fea862fd99e5882d870e11e6a28dc9d0c8ba6
Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/620
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Darek Stojaczyk 2020-02-06 13:38:46 +01:00 committed by Tomasz Zawadzki
parent 7745383ab2
commit 8e7d6e1b0c
7 changed files with 28 additions and 7 deletions

View File

@ -6,6 +6,11 @@
A new function, `spdk_vmd_fini`, has been added. It releases all resources acquired by the VMD A new function, `spdk_vmd_fini`, has been added. It releases all resources acquired by the VMD
library through the `spdk_vmd_init` call. library through the `spdk_vmd_init` call.
### Miscellaneous
`--json-ignore-init-errors` command line param has been added to ignore initialization errors
on JSON config load.
## v20.01 ## v20.01
### bdev ### bdev

View File

@ -204,7 +204,7 @@ spdk_fio_bdev_init_start(void *arg)
if (g_json_config_file != NULL) { if (g_json_config_file != NULL) {
spdk_app_json_config_load(g_json_config_file, SPDK_DEFAULT_RPC_ADDR, spdk_app_json_config_load(g_json_config_file, SPDK_DEFAULT_RPC_ADDR,
spdk_fio_bdev_init_done, done); spdk_fio_bdev_init_done, done, true);
} else { } else {
spdk_subsystem_init(spdk_fio_bdev_init_done, done); spdk_subsystem_init(spdk_fio_bdev_init_done, done);
} }

View File

@ -91,6 +91,7 @@ struct spdk_app_opts {
const char *name; const char *name;
const char *config_file; const char *config_file;
const char *json_config_file; const char *json_config_file;
bool json_config_ignore_errors;
const char *rpc_addr; /* Can be UNIX domain socket path or IP address + TCP port */ const char *rpc_addr; /* Can be UNIX domain socket path or IP address + TCP port */
const char *reactor_mask; const char *reactor_mask;
const char *tpoint_group_mask; const char *tpoint_group_mask;

View File

@ -144,7 +144,8 @@ void spdk_subsystem_init_next(int rc);
void spdk_subsystem_fini_next(void); void spdk_subsystem_fini_next(void);
void spdk_subsystem_config(FILE *fp); void spdk_subsystem_config(FILE *fp);
void spdk_app_json_config_load(const char *json_config_file, const char *rpc_addr, void spdk_app_json_config_load(const char *json_config_file, const char *rpc_addr,
spdk_subsystem_init_fn cb_fn, void *cb_arg); spdk_subsystem_init_fn cb_fn, void *cb_arg,
bool stop_on_error);
/** /**
* Save pointed \c subsystem configuration to the JSON write context \c w. In case of * Save pointed \c subsystem configuration to the JSON write context \c w. In case of

View File

@ -59,6 +59,7 @@
struct spdk_app { struct spdk_app {
struct spdk_conf *config; struct spdk_conf *config;
const char *json_config_file; const char *json_config_file;
bool json_config_ignore_errors;
const char *rpc_addr; const char *rpc_addr;
int shm_id; int shm_id;
spdk_app_shutdown_cb shutdown_cb; spdk_app_shutdown_cb shutdown_cb;
@ -128,6 +129,8 @@ static const struct option g_cmdline_options[] = {
{"max-delay", required_argument, NULL, MAX_REACTOR_DELAY_OPT_IDX}, {"max-delay", required_argument, NULL, MAX_REACTOR_DELAY_OPT_IDX},
#define JSON_CONFIG_OPT_IDX 262 #define JSON_CONFIG_OPT_IDX 262
{"json", required_argument, NULL, JSON_CONFIG_OPT_IDX}, {"json", required_argument, NULL, JSON_CONFIG_OPT_IDX},
#define JSON_CONFIG_IGNORE_INIT_ERRORS_IDX 263
{"json-ignore-init-errors", no_argument, NULL, JSON_CONFIG_IGNORE_INIT_ERRORS_IDX},
}; };
/* Global section */ /* Global section */
@ -561,7 +564,7 @@ bootstrap_fn(void *arg1)
if (g_spdk_app.json_config_file) { if (g_spdk_app.json_config_file) {
g_delay_subsystem_init = false; g_delay_subsystem_init = false;
spdk_app_json_config_load(g_spdk_app.json_config_file, g_spdk_app.rpc_addr, spdk_app_start_rpc, spdk_app_json_config_load(g_spdk_app.json_config_file, g_spdk_app.rpc_addr, spdk_app_start_rpc,
NULL); NULL, !g_spdk_app.json_config_ignore_errors);
} else { } else {
if (!g_delay_subsystem_init) { if (!g_delay_subsystem_init) {
spdk_subsystem_init(spdk_app_start_rpc, NULL); spdk_subsystem_init(spdk_app_start_rpc, NULL);
@ -626,6 +629,7 @@ spdk_app_start(struct spdk_app_opts *opts, spdk_msg_fn start_fn,
memset(&g_spdk_app, 0, sizeof(g_spdk_app)); memset(&g_spdk_app, 0, sizeof(g_spdk_app));
g_spdk_app.config = config; g_spdk_app.config = config;
g_spdk_app.json_config_file = opts->json_config_file; g_spdk_app.json_config_file = opts->json_config_file;
g_spdk_app.json_config_ignore_errors = opts->json_config_ignore_errors;
g_spdk_app.rpc_addr = opts->rpc_addr; g_spdk_app.rpc_addr = opts->rpc_addr;
g_spdk_app.shm_id = opts->shm_id; g_spdk_app.shm_id = opts->shm_id;
g_spdk_app.shutdown_cb = opts->shutdown_cb; g_spdk_app.shutdown_cb = opts->shutdown_cb;
@ -728,6 +732,8 @@ usage(void (*app_usage)(void))
g_default_opts.config_file != NULL ? g_default_opts.config_file : "none"); g_default_opts.config_file != NULL ? g_default_opts.config_file : "none");
printf(" --json <config> JSON config file (default %s)\n", printf(" --json <config> JSON config file (default %s)\n",
g_default_opts.json_config_file != NULL ? g_default_opts.json_config_file : "none"); g_default_opts.json_config_file != NULL ? g_default_opts.json_config_file : "none");
printf(" --json-ignore-init-errors\n");
printf(" don't exit on invalid config entry\n");
printf(" -d, --limit-coredump do not set max coredump size to RLIM_INFINITY\n"); printf(" -d, --limit-coredump do not set max coredump size to RLIM_INFINITY\n");
printf(" -g, --single-file-segments\n"); printf(" -g, --single-file-segments\n");
printf(" force creating just one hugetlbfs file\n"); printf(" force creating just one hugetlbfs file\n");
@ -837,6 +843,9 @@ spdk_app_parse_args(int argc, char **argv, struct spdk_app_opts *opts,
case JSON_CONFIG_OPT_IDX: case JSON_CONFIG_OPT_IDX:
opts->json_config_file = optarg; opts->json_config_file = optarg;
break; break;
case JSON_CONFIG_IGNORE_INIT_ERRORS_IDX:
opts->json_config_ignore_errors = true;
break;
case LIMIT_COREDUMP_OPT_IDX: case LIMIT_COREDUMP_OPT_IDX:
opts->enable_coredump = false; opts->enable_coredump = false;
break; break;

View File

@ -88,6 +88,7 @@ struct load_json_config_ctx {
struct spdk_thread *thread; struct spdk_thread *thread;
spdk_subsystem_init_fn cb_fn; spdk_subsystem_init_fn cb_fn;
void *cb_arg; void *cb_arg;
bool stop_on_error;
/* Current subsystem */ /* Current subsystem */
struct spdk_json_val *subsystems; /* "subsystems" array */ struct spdk_json_val *subsystems; /* "subsystems" array */
@ -189,6 +190,9 @@ rpc_client_poller(void *arg)
if (resp->error) { if (resp->error) {
SPDK_ERRLOG("error response: %*s", (int)resp->error->len, (char *)resp->error->start); SPDK_ERRLOG("error response: %*s", (int)resp->error->len, (char *)resp->error->start);
}
if (resp->error && ctx->stop_on_error) {
spdk_jsonrpc_client_free_response(resp); spdk_jsonrpc_client_free_response(resp);
spdk_app_json_config_load_done(ctx, -EINVAL); spdk_app_json_config_load_done(ctx, -EINVAL);
} else { } else {
@ -302,8 +306,7 @@ static void
spdk_app_json_config_load_subsystem_config_entry_next(struct load_json_config_ctx *ctx, spdk_app_json_config_load_subsystem_config_entry_next(struct load_json_config_ctx *ctx,
struct spdk_jsonrpc_client_response *resp) struct spdk_jsonrpc_client_response *resp)
{ {
/* Don't care about the response as long it is not /* Don't care about the response */
* an error (which is validated by poller) */
spdk_jsonrpc_client_free_response(resp); spdk_jsonrpc_client_free_response(resp);
ctx->config_it = spdk_json_next(ctx->config_it); ctx->config_it = spdk_json_next(ctx->config_it);
@ -530,7 +533,8 @@ err:
void void
spdk_app_json_config_load(const char *json_config_file, const char *rpc_addr, spdk_app_json_config_load(const char *json_config_file, const char *rpc_addr,
spdk_subsystem_init_fn cb_fn, void *cb_arg) spdk_subsystem_init_fn cb_fn, void *cb_arg,
bool stop_on_error)
{ {
struct load_json_config_ctx *ctx = calloc(1, sizeof(*ctx)); struct load_json_config_ctx *ctx = calloc(1, sizeof(*ctx));
int rc; int rc;
@ -543,6 +547,7 @@ spdk_app_json_config_load(const char *json_config_file, const char *rpc_addr,
ctx->cb_fn = cb_fn; ctx->cb_fn = cb_fn;
ctx->cb_arg = cb_arg; ctx->cb_arg = cb_arg;
ctx->stop_on_error = stop_on_error;
ctx->thread = spdk_get_thread(); ctx->thread = spdk_get_thread();
rc = spdk_app_json_config_read(json_config_file, ctx); rc = spdk_app_json_config_read(json_config_file, ctx);

View File

@ -49,7 +49,7 @@ DEFINE_STUB_V(spdk_rpc_register_alias_deprecated, (const char *method, const cha
DEFINE_STUB_V(spdk_rpc_set_state, (uint32_t state)); DEFINE_STUB_V(spdk_rpc_set_state, (uint32_t state));
DEFINE_STUB(spdk_rpc_get_state, uint32_t, (void), SPDK_RPC_RUNTIME); DEFINE_STUB(spdk_rpc_get_state, uint32_t, (void), SPDK_RPC_RUNTIME);
DEFINE_STUB_V(spdk_app_json_config_load, (const char *json_config_file, const char *rpc_addr, DEFINE_STUB_V(spdk_app_json_config_load, (const char *json_config_file, const char *rpc_addr,
spdk_subsystem_init_fn cb_fn, void *cb_arg)); spdk_subsystem_init_fn cb_fn, void *cb_arg, bool stop_on_error));
static void static void
unittest_usage(void) unittest_usage(void)