From 8e7d6e1b0c381a8dae09147a613bc5e5e2b9a697 Mon Sep 17 00:00:00 2001 From: Darek Stojaczyk Date: Thu, 6 Feb 2020 13:38:46 +0100 Subject: [PATCH] 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 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/620 Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Tomasz Zawadzki Reviewed-by: Ben Walker --- CHANGELOG.md | 5 +++++ examples/bdev/fio_plugin/fio_plugin.c | 2 +- include/spdk/event.h | 1 + include/spdk_internal/event.h | 3 ++- lib/event/app.c | 11 ++++++++++- lib/event/json_config.c | 11 ++++++++--- test/unit/lib/event/app.c/app_ut.c | 2 +- 7 files changed, 28 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f717c845..0d028fb92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ A new function, `spdk_vmd_fini`, has been added. It releases all resources acquired by the VMD 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 ### bdev diff --git a/examples/bdev/fio_plugin/fio_plugin.c b/examples/bdev/fio_plugin/fio_plugin.c index b29f4a68f..566403f44 100644 --- a/examples/bdev/fio_plugin/fio_plugin.c +++ b/examples/bdev/fio_plugin/fio_plugin.c @@ -204,7 +204,7 @@ spdk_fio_bdev_init_start(void *arg) if (g_json_config_file != NULL) { 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 { spdk_subsystem_init(spdk_fio_bdev_init_done, done); } diff --git a/include/spdk/event.h b/include/spdk/event.h index 03ce1fad4..484bfccca 100644 --- a/include/spdk/event.h +++ b/include/spdk/event.h @@ -91,6 +91,7 @@ struct spdk_app_opts { const char *name; const char *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 *reactor_mask; const char *tpoint_group_mask; diff --git a/include/spdk_internal/event.h b/include/spdk_internal/event.h index 5d4d774a9..154c997d3 100644 --- a/include/spdk_internal/event.h +++ b/include/spdk_internal/event.h @@ -144,7 +144,8 @@ void spdk_subsystem_init_next(int rc); void spdk_subsystem_fini_next(void); void spdk_subsystem_config(FILE *fp); 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 diff --git a/lib/event/app.c b/lib/event/app.c index 404b88176..7b06e6447 100644 --- a/lib/event/app.c +++ b/lib/event/app.c @@ -59,6 +59,7 @@ struct spdk_app { struct spdk_conf *config; const char *json_config_file; + bool json_config_ignore_errors; const char *rpc_addr; int shm_id; 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}, #define JSON_CONFIG_OPT_IDX 262 {"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 */ @@ -561,7 +564,7 @@ bootstrap_fn(void *arg1) if (g_spdk_app.json_config_file) { 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, - NULL); + NULL, !g_spdk_app.json_config_ignore_errors); } else { if (!g_delay_subsystem_init) { 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)); g_spdk_app.config = config; 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.shm_id = opts->shm_id; 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"); printf(" --json JSON config file (default %s)\n", 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(" -g, --single-file-segments\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: opts->json_config_file = optarg; break; + case JSON_CONFIG_IGNORE_INIT_ERRORS_IDX: + opts->json_config_ignore_errors = true; + break; case LIMIT_COREDUMP_OPT_IDX: opts->enable_coredump = false; break; diff --git a/lib/event/json_config.c b/lib/event/json_config.c index 58e69b9c2..ba8d2bc19 100644 --- a/lib/event/json_config.c +++ b/lib/event/json_config.c @@ -88,6 +88,7 @@ struct load_json_config_ctx { struct spdk_thread *thread; spdk_subsystem_init_fn cb_fn; void *cb_arg; + bool stop_on_error; /* Current subsystem */ struct spdk_json_val *subsystems; /* "subsystems" array */ @@ -189,6 +190,9 @@ rpc_client_poller(void *arg) if (resp->error) { 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_app_json_config_load_done(ctx, -EINVAL); } else { @@ -302,8 +306,7 @@ static void spdk_app_json_config_load_subsystem_config_entry_next(struct load_json_config_ctx *ctx, struct spdk_jsonrpc_client_response *resp) { - /* Don't care about the response as long it is not - * an error (which is validated by poller) */ + /* Don't care about the response */ spdk_jsonrpc_client_free_response(resp); ctx->config_it = spdk_json_next(ctx->config_it); @@ -530,7 +533,8 @@ err: 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) { struct load_json_config_ctx *ctx = calloc(1, sizeof(*ctx)); 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_arg = cb_arg; + ctx->stop_on_error = stop_on_error; ctx->thread = spdk_get_thread(); rc = spdk_app_json_config_read(json_config_file, ctx); diff --git a/test/unit/lib/event/app.c/app_ut.c b/test/unit/lib/event/app.c/app_ut.c index ece0752f4..4208773ea 100644 --- a/test/unit/lib/event/app.c/app_ut.c +++ b/test/unit/lib/event/app.c/app_ut.c @@ -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(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, - spdk_subsystem_init_fn cb_fn, void *cb_arg)); + spdk_subsystem_init_fn cb_fn, void *cb_arg, bool stop_on_error)); static void unittest_usage(void)