diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index f6ec2cf1f..bee750c00 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -164,6 +164,39 @@ Example response: } ~~~ +## wait_subsystem_init {#rpc_wait_subsystem_init} + +Do not return until all subsystems have been initialized and the RPC system state is running. +If the application is already running, this call will return immediately. This RPC can be called at any time. + +### Parameters + +This method has no parameters. + +### Response + +Returns True when subsystems have been initialized. + +### Example + +Example request: +~~~ +{ + "jsonrpc": "2.0", + "id": 1, + "method": "wait_subsystem_init" +} +~~~ + +Example response: +~~~ +{ + "jsonrpc": "2.0", + "id": 1, + "result": true +} +~~~ + ## get_rpc_methods {#rpc_get_rpc_methods} Get an array of supported RPC methods. diff --git a/lib/event/app.c b/lib/event/app.c index afd639fc5..519604e89 100644 --- a/lib/event/app.c +++ b/lib/event/app.c @@ -1007,3 +1007,57 @@ spdk_rpc_start_subsystem_init(struct spdk_jsonrpc_request *request, spdk_subsystem_init(cb_event); } SPDK_RPC_REGISTER("start_subsystem_init", spdk_rpc_start_subsystem_init, SPDK_RPC_STARTUP) + +struct subsystem_init_poller_ctx { + struct spdk_poller *init_poller; + struct spdk_jsonrpc_request *request; +}; + +static int +spdk_rpc_subsystem_init_poller_ctx(void *ctx) +{ + struct spdk_json_write_ctx *w; + struct subsystem_init_poller_ctx *poller_ctx = ctx; + + if (spdk_rpc_get_state() == SPDK_RPC_RUNTIME) { + w = spdk_jsonrpc_begin_result(poller_ctx->request); + if (w == NULL) { + SPDK_ERRLOG("Unable to allocate memory for RPC response\n"); + } else { + spdk_json_write_bool(w, true); + } + spdk_jsonrpc_end_result(poller_ctx->request, w); + spdk_poller_unregister(&poller_ctx->init_poller); + free(poller_ctx); + } + + return 1; +} + +static void +spdk_rpc_wait_subsystem_init(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct spdk_json_write_ctx *w; + struct subsystem_init_poller_ctx *ctx; + + if (spdk_rpc_get_state() == SPDK_RPC_RUNTIME) { + w = spdk_jsonrpc_begin_result(request); + if (w == NULL) { + return; + } + spdk_json_write_bool(w, true); + spdk_jsonrpc_end_result(request, w); + } else { + ctx = malloc(sizeof(struct subsystem_init_poller_ctx)); + if (ctx == NULL) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, + "Unable to allocate memory for the request context\n"); + return; + } + ctx->request = request; + ctx->init_poller = spdk_poller_register(spdk_rpc_subsystem_init_poller_ctx, ctx, 0); + } +} +SPDK_RPC_REGISTER("wait_subsystem_init", spdk_rpc_wait_subsystem_init, + SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME) diff --git a/scripts/rpc.py b/scripts/rpc.py index 6151a8587..7c7241730 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -48,6 +48,13 @@ if __name__ == "__main__": p = subparsers.add_parser('start_subsystem_init', help='Start initialization of subsystems') p.set_defaults(func=start_subsystem_init) + @call_cmd + def wait_subsystem_init(args): + rpc.wait_subsystem_init(args.client) + + p = subparsers.add_parser('wait_subsystem_init', help='Block until subsystems have been initialized') + p.set_defaults(func=wait_subsystem_init) + @call_cmd def get_rpc_methods(args): print_dict(rpc.get_rpc_methods(args.client, diff --git a/scripts/rpc/__init__.py b/scripts/rpc/__init__.py index 9a4dbb58c..7601a206f 100644 --- a/scripts/rpc/__init__.py +++ b/scripts/rpc/__init__.py @@ -22,6 +22,11 @@ def start_subsystem_init(client): return client.call('start_subsystem_init') +def wait_subsystem_init(client): + """Block until subsystems have been initialized""" + return client.call('wait_subsystem_init') + + def get_rpc_methods(client, current=None): """Get list of supported RPC methods. Args: