diff --git a/CHANGELOG.md b/CHANGELOG.md index 67e4a2fb8..85d806743 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ parameter in spdk_bdev_get_opts function. Two fields `small_buf_pool_size` and `large_buf_pool_size` were added into spdk_bdev_opts, which were used to determine the small and large buffer pool size of the whole bdev module. +A new API `spdk_bdev_wait_for_examine` was added to allow for checking state of +examine process. Along with corresponding `bdev_wait_for_examine` RPC. + ### blob An `opts_size` element was added in the `spdk_bs_opts` structure to solve the diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index 5dadca1ce..df5a4e245 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -1320,6 +1320,40 @@ Example response: } ~~~ +## bdev_wait_for_examine {#rpc_bdev_wait_for_examine} + +Report when all bdevs have been examined by every bdev module. + +### Parameters + +None + +### Response + +The response is sent when all bdev modules had a chance to examine every bdev. + +### Example + +Example request: + +~~~ +{ + "jsonrpc": "2.0", + "method": "bdev_wait_for_examine", + "id": 1 +} +~~~ + +Example response: + +~~~ +{ + "jsonrpc": "2.0", + "id": 1, + "result": true +} +~~~ + ## bdev_get_iostat {#rpc_bdev_get_iostat} Get I/O statistics of block devices (bdevs). diff --git a/include/spdk/bdev.h b/include/spdk/bdev.h index 95366887e..3bf618cf3 100644 --- a/include/spdk/bdev.h +++ b/include/spdk/bdev.h @@ -209,6 +209,20 @@ void spdk_bdev_get_opts(struct spdk_bdev_opts *opts, size_t opts_size); int spdk_bdev_set_opts(struct spdk_bdev_opts *opts); +typedef void (*spdk_bdev_wait_for_examine_cb)(void *arg); + +/** + * Report when all bdevs finished the examine process. + * The registered cb_fn will be called just once. + * This function needs to be called again to receive + * further reports on examine process. + * + * \param cb_fn Callback function. + * \param cb_arg Callback argument. + * \return 0 if function was registered, suitable errno value otherwise + */ +int spdk_bdev_wait_for_examine(spdk_bdev_wait_for_examine_cb cb_fn, void *cb_arg); + /** * Examine a block device explicitly * diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index d92e140f1..63e38c834 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -462,6 +462,47 @@ spdk_bdev_set_opts(struct spdk_bdev_opts *opts) return 0; } +struct spdk_bdev_wait_for_examine_ctx { + struct spdk_poller *poller; + spdk_bdev_wait_for_examine_cb cb_fn; + void *cb_arg; +}; + +static bool +bdev_module_all_actions_completed(void); + +static int +bdev_wait_for_examine_cb(void *arg) +{ + struct spdk_bdev_wait_for_examine_ctx *ctx = arg; + + if (!bdev_module_all_actions_completed()) { + return SPDK_POLLER_IDLE; + } + + spdk_poller_unregister(&ctx->poller); + ctx->cb_fn(ctx->cb_arg); + free(ctx); + + return SPDK_POLLER_BUSY; +} + +int +spdk_bdev_wait_for_examine(spdk_bdev_wait_for_examine_cb cb_fn, void *cb_arg) +{ + struct spdk_bdev_wait_for_examine_ctx *ctx; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + return -ENOMEM; + } + ctx->cb_fn = cb_fn; + ctx->cb_arg = cb_arg; + ctx->poller = SPDK_POLLER_REGISTER(bdev_wait_for_examine_cb, ctx, 0); + + return 0; +} + struct spdk_bdev_examine_item { char *name; TAILQ_ENTRY(spdk_bdev_examine_item) link; diff --git a/lib/bdev/bdev_rpc.c b/lib/bdev/bdev_rpc.c index 666bf2627..9055c77dd 100644 --- a/lib/bdev/bdev_rpc.c +++ b/lib/bdev/bdev_rpc.c @@ -110,6 +110,33 @@ rpc_bdev_set_options(struct spdk_jsonrpc_request *request, const struct spdk_jso SPDK_RPC_REGISTER("bdev_set_options", rpc_bdev_set_options, SPDK_RPC_STARTUP) SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_set_options, set_bdev_options) +static void +rpc_bdev_wait_for_examine_cpl(void *arg) +{ + struct spdk_jsonrpc_request *request = arg; + + spdk_jsonrpc_send_bool_response(request, true); +} + +static void +rpc_bdev_wait_for_examine(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + int rc; + + if (params != NULL) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "bdev_wait_for_examine requires no parameters"); + return; + } + + rc = spdk_bdev_wait_for_examine(rpc_bdev_wait_for_examine_cpl, request); + if (rc != 0) { + spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); + } +} +SPDK_RPC_REGISTER("bdev_wait_for_examine", rpc_bdev_wait_for_examine, SPDK_RPC_RUNTIME) + struct rpc_bdev_examine { char *name; }; diff --git a/lib/bdev/spdk_bdev.map b/lib/bdev/spdk_bdev.map index d2b268715..b827f9d27 100644 --- a/lib/bdev/spdk_bdev.map +++ b/lib/bdev/spdk_bdev.map @@ -4,6 +4,7 @@ # Public functions in bdev.h spdk_bdev_get_opts; spdk_bdev_set_opts; + spdk_bdev_wait_for_examine; spdk_bdev_examine; spdk_bdev_initialize; spdk_bdev_finish; diff --git a/scripts/rpc.py b/scripts/rpc.py index d5efc29e9..ec9895594 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -198,6 +198,13 @@ if __name__ == "__main__": p.add_argument('-b', '--name', help='Name or alias of the bdev') p.set_defaults(func=bdev_examine) + def bdev_wait_for_examine(args): + rpc.bdev.bdev_wait_for_examine(args.client) + + p = subparsers.add_parser('bdev_wait_for_examine', + help="""Report when all bdevs have been examined""") + p.set_defaults(func=bdev_wait_for_examine) + def bdev_compress_create(args): print_json(rpc.bdev.bdev_compress_create(args.client, base_bdev_name=args.base_bdev_name, diff --git a/scripts/rpc/bdev.py b/scripts/rpc/bdev.py index d70df5999..4dd05377e 100644 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -41,6 +41,12 @@ def bdev_examine(client, name): return client.call('bdev_examine', params) +def bdev_wait_for_examine(client): + """Report when all bdevs have been examined + """ + return client.call('bdev_wait_for_examine') + + @deprecated_alias('construct_compress_bdev') def bdev_compress_create(client, base_bdev_name, pm_path, lb_size): """Construct a compress virtual block device. diff --git a/test/bdev/blockdev.sh b/test/bdev/blockdev.sh index 755f4da46..6799670bc 100755 --- a/test/bdev/blockdev.sh +++ b/test/bdev/blockdev.sh @@ -346,6 +346,8 @@ case "$test_type" in ;; esac +"$rpc_py" bdev_wait_for_examine + # Generate json config and use it throughout all the tests cat <<- CONF > "$conf_file" {"subsystems":[