diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f6267ddc..6301369c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## v20.10: (Upcoming Release) +### bdev + +A new API was added `bdev_examine_bdev` that allows users to examine a +bdev explicitly. It can be used only if auto_examine is disabled. + ## v20.07: SPDK CSI driver, new accel_fw commands, I/O abort support ### accel diff --git a/include/spdk/bdev.h b/include/spdk/bdev.h index 0bb39c410..5fcbe71cc 100644 --- a/include/spdk/bdev.h +++ b/include/spdk/bdev.h @@ -193,6 +193,14 @@ void spdk_bdev_get_opts(struct spdk_bdev_opts *opts); int spdk_bdev_set_opts(struct spdk_bdev_opts *opts); +/** + * Examine a block device explicitly + * + * \param name the name or alias of the block device + * \return 0 if block device was examined successfully, suitable errno value otherwise + */ +int spdk_bdev_examine(const char *name); + /** * Block device initialization callback. * diff --git a/lib/bdev/Makefile b/lib/bdev/Makefile index ca0bf992a..497e4bb27 100644 --- a/lib/bdev/Makefile +++ b/lib/bdev/Makefile @@ -35,7 +35,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk SO_VER := 3 -SO_MINOR := 0 +SO_MINOR := 1 ifeq ($(CONFIG_VTUNE),y) CFLAGS += -I$(CONFIG_VTUNE_DIR)/include -I$(CONFIG_VTUNE_DIR)/sdk/src/ittnotify diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index 6c7bc8d4d..164ee4e30 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -484,6 +484,54 @@ bdev_examine(struct spdk_bdev *bdev) } } +int +spdk_bdev_examine(const char *name) +{ + struct spdk_bdev *bdev; + struct spdk_bdev_examine_item *item; + + if (g_bdev_opts.bdev_auto_examine) { + SPDK_ERRLOG("Manual examine is not allowed if auto examine is enabled"); + return -EINVAL; + } + + if (bdev_examine_allowlist_check(name)) { + SPDK_ERRLOG("Duplicate bdev name for manual examine: %s\n", name); + return -EEXIST; + } + + item = calloc(1, sizeof(*item)); + if (!item) { + return -ENOMEM; + } + item->name = strdup(name); + if (!item->name) { + free(item); + return -ENOMEM; + } + TAILQ_INSERT_TAIL(&g_bdev_examine_allowlist, item, link); + + bdev = spdk_bdev_get_by_name(name); + if (bdev) { + bdev_examine(bdev); + } + return 0; +} + +static inline void +bdev_examine_allowlist_config_json(struct spdk_json_write_ctx *w) +{ + struct spdk_bdev_examine_item *item; + TAILQ_FOREACH(item, &g_bdev_examine_allowlist, link) { + spdk_json_write_object_begin(w); + spdk_json_write_named_string(w, "method", "bdev_examine"); + spdk_json_write_named_object_begin(w, "params"); + spdk_json_write_named_string(w, "name", item->name); + spdk_json_write_object_end(w); + spdk_json_write_object_end(w); + } +} + struct spdk_bdev * spdk_bdev_first(void) { @@ -984,6 +1032,8 @@ spdk_bdev_subsystem_config_json(struct spdk_json_write_ctx *w) spdk_json_write_object_end(w); spdk_json_write_object_end(w); + bdev_examine_allowlist_config_json(w); + TAILQ_FOREACH(bdev_module, &g_bdev_mgr.bdev_modules, internal.tailq) { if (bdev_module->config_json) { bdev_module->config_json(w); diff --git a/lib/bdev/bdev_rpc.c b/lib/bdev/bdev_rpc.c index 6ce7136c4..5c8cfa469 100644 --- a/lib/bdev/bdev_rpc.c +++ b/lib/bdev/bdev_rpc.c @@ -96,3 +96,48 @@ 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) + +struct rpc_bdev_examine { + char *name; +}; + +static void +free_rpc_bdev_examine(struct rpc_bdev_examine *r) +{ + free(r->name); +} + +static const struct spdk_json_object_decoder rpc_examine_bdev_decoders[] = { + {"name", offsetof(struct rpc_bdev_examine, name), spdk_json_decode_string}, +}; + +static void +rpc_bdev_examine_bdev(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_bdev_examine req = {NULL}; + struct spdk_json_write_ctx *w; + int rc; + + if (spdk_json_decode_object(params, rpc_examine_bdev_decoders, + SPDK_COUNTOF(rpc_examine_bdev_decoders), + &req)) { + SPDK_ERRLOG("spdk_json_decode_object() failed\n"); + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "spdk_json_decode_object failed"); + goto cleanup; + } + + rc = spdk_bdev_examine(req.name); + if (rc != 0) { + spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); + goto cleanup; + } + w = spdk_jsonrpc_begin_result(request); + spdk_json_write_bool(w, true); + spdk_jsonrpc_end_result(request, w); + +cleanup: + free_rpc_bdev_examine(&req); +} +SPDK_RPC_REGISTER("bdev_examine", rpc_bdev_examine_bdev, SPDK_RPC_RUNTIME) diff --git a/lib/bdev/spdk_bdev.map b/lib/bdev/spdk_bdev.map index 9f9c3c7e5..80c3bb555 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_examine; spdk_bdev_initialize; spdk_bdev_finish; spdk_bdev_config_text; diff --git a/scripts/rpc.py b/scripts/rpc.py index aa6c54d8b..3ea8f3883 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -174,6 +174,15 @@ if __name__ == "__main__": p.set_defaults(bdev_auto_examine=True) p.set_defaults(func=bdev_set_options) + def bdev_examine(args): + rpc.bdev.bdev_examine(args.client, + name=args.name) + + p = subparsers.add_parser('bdev_examine', + help="""examine a bdev if it exists, or will examine it after it is created""") + p.add_argument('-b', '--name', help='Name or alias of the bdev') + p.set_defaults(func=bdev_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 fc4182aee..2bdd72e96 100644 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -22,6 +22,19 @@ def bdev_set_options(client, bdev_io_pool_size=None, bdev_io_cache_size=None, bd return client.call('bdev_set_options', params) +def bdev_examine(client, name): + """Examine a bdev manually. If the bdev does not exist yet when this RPC is called, + it will be examined when it is created + + Args: + name: name of the bdev + """ + params = { + 'name': name + } + return client.call('bdev_examine', params) + + @deprecated_alias('construct_compress_bdev') def bdev_compress_create(client, base_bdev_name, pm_path, lb_size): """Construct a compress virtual block device.