diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index d6bb169b1..27254b2d3 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -5208,6 +5208,7 @@ Construct error bdev. Name | Optional | Type | Description ----------------------- | -------- | ----------- | ----------- base_name | Required | string | Base bdev name +uuid | Optional | string | UUID for this bdev #### Example diff --git a/module/bdev/error/vbdev_error.c b/module/bdev/error/vbdev_error.c index a3dee0525..b49038f52 100644 --- a/module/bdev/error/vbdev_error.c +++ b/module/bdev/error/vbdev_error.c @@ -21,6 +21,7 @@ struct spdk_vbdev_error_config { char *base_bdev; + struct spdk_uuid uuid; TAILQ_ENTRY(spdk_vbdev_error_config) tailq; }; @@ -54,7 +55,7 @@ static void vbdev_error_fini(void); static void vbdev_error_examine(struct spdk_bdev *bdev); static int vbdev_error_config_json(struct spdk_json_write_ctx *w); -static int vbdev_error_config_add(const char *base_bdev_name); +static int vbdev_error_config_add(const char *base_bdev_name, const struct spdk_uuid *uuid); static int vbdev_error_config_remove(const char *base_bdev_name); static struct spdk_bdev_module error_if = { @@ -314,11 +315,11 @@ vbdev_error_base_bdev_hotremove_cb(void *_part_base) } static int -_vbdev_error_create(const char *base_bdev_name) +_vbdev_error_create(const char *base_bdev_name, const struct spdk_uuid *uuid) { struct spdk_bdev_part_base *base = NULL; struct error_disk *disk = NULL; - struct spdk_bdev *base_bdev; + struct spdk_bdev *base_bdev, *bdev; char *name; int rc; @@ -351,6 +352,11 @@ _vbdev_error_create(const char *base_bdev_name) return -ENOMEM; } + if (uuid) { + bdev = spdk_bdev_part_get_bdev(&disk->part); + spdk_uuid_copy(&bdev->uuid, uuid); + } + rc = spdk_bdev_part_construct(&disk->part, base, name, 0, base_bdev->blockcnt, "Error Injection Disk"); free(name); @@ -368,18 +374,18 @@ _vbdev_error_create(const char *base_bdev_name) } int -vbdev_error_create(const char *base_bdev_name) +vbdev_error_create(const char *base_bdev_name, const struct spdk_uuid *uuid) { int rc; - rc = vbdev_error_config_add(base_bdev_name); + rc = vbdev_error_config_add(base_bdev_name, uuid); if (rc != 0) { SPDK_ERRLOG("Adding config for ErrorInjection bdev %s failed (rc=%d)\n", base_bdev_name, rc); return rc; } - rc = _vbdev_error_create(base_bdev_name); + rc = _vbdev_error_create(base_bdev_name, uuid); if (rc == -ENODEV) { rc = 0; } else if (rc != 0) { @@ -429,7 +435,7 @@ vbdev_error_config_find_by_base_name(const char *base_bdev_name) } static int -vbdev_error_config_add(const char *base_bdev_name) +vbdev_error_config_add(const char *base_bdev_name, const struct spdk_uuid *uuid) { struct spdk_vbdev_error_config *cfg; @@ -453,6 +459,10 @@ vbdev_error_config_add(const char *base_bdev_name) return -ENOMEM; } + if (uuid) { + spdk_uuid_copy(&cfg->uuid, uuid); + } + TAILQ_INSERT_TAIL(&g_error_config, cfg, tailq); return 0; @@ -494,7 +504,7 @@ vbdev_error_examine(struct spdk_bdev *bdev) cfg = vbdev_error_config_find_by_base_name(bdev->name); if (cfg != NULL) { - rc = _vbdev_error_create(bdev->name); + rc = _vbdev_error_create(bdev->name, &cfg->uuid); if (rc != 0) { SPDK_ERRLOG("could not create error vbdev for bdev %s at examine\n", bdev->name); @@ -508,6 +518,7 @@ static int vbdev_error_config_json(struct spdk_json_write_ctx *w) { struct spdk_vbdev_error_config *cfg; + char uuid_str[SPDK_UUID_STRING_LEN]; TAILQ_FOREACH(cfg, &g_error_config, tailq) { spdk_json_write_object_begin(w); @@ -515,6 +526,10 @@ vbdev_error_config_json(struct spdk_json_write_ctx *w) spdk_json_write_named_string(w, "method", "bdev_error_create"); spdk_json_write_named_object_begin(w, "params"); spdk_json_write_named_string(w, "base_name", cfg->base_bdev); + if (!spdk_mem_all_zero(&cfg->uuid, sizeof(struct spdk_uuid))) { + spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &cfg->uuid); + spdk_json_write_named_string(w, "uuid", uuid_str); + } spdk_json_write_object_end(w); spdk_json_write_object_end(w); diff --git a/module/bdev/error/vbdev_error.h b/module/bdev/error/vbdev_error.h index 943a207af..38b5b67d1 100644 --- a/module/bdev/error/vbdev_error.h +++ b/module/bdev/error/vbdev_error.h @@ -8,6 +8,7 @@ #include "spdk/stdinc.h" #include "spdk/bdev.h" +#include "spdk/uuid.h" enum vbdev_error_type { VBDEV_IO_FAILURE = 1, @@ -21,9 +22,10 @@ typedef void (*spdk_delete_error_complete)(void *cb_arg, int bdeverrno); * Create a vbdev on the base bdev to inject error into it. * * \param base_bdev_name Name of the base bdev. + * \param uuid Optional UUID to assign to the bdev. * \return 0 on success or negative on failure. */ -int vbdev_error_create(const char *base_bdev_name); +int vbdev_error_create(const char *base_bdev_name, const struct spdk_uuid *uuid); /** * Delete vbdev used to inject errors. diff --git a/module/bdev/error/vbdev_error_rpc.c b/module/bdev/error/vbdev_error_rpc.c index add4c40d2..0db29871b 100644 --- a/module/bdev/error/vbdev_error_rpc.c +++ b/module/bdev/error/vbdev_error_rpc.c @@ -57,16 +57,19 @@ rpc_error_bdev_decode_error_type(const struct spdk_json_val *val, void *out) struct rpc_bdev_error_create { char *base_name; + char *uuid; }; static void free_rpc_bdev_error_create(struct rpc_bdev_error_create *req) { free(req->base_name); + free(req->uuid); } static const struct spdk_json_object_decoder rpc_bdev_error_create_decoders[] = { {"base_name", offsetof(struct rpc_bdev_error_create, base_name), spdk_json_decode_string}, + {"uuid", offsetof(struct rpc_bdev_error_create, uuid), spdk_json_decode_string, true}, }; static void @@ -74,6 +77,8 @@ rpc_bdev_error_create(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) { struct rpc_bdev_error_create req = {}; + struct spdk_uuid *uuid = NULL; + struct spdk_uuid decoded_uuid; int rc = 0; if (spdk_json_decode_object(params, rpc_bdev_error_create_decoders, @@ -85,7 +90,16 @@ rpc_bdev_error_create(struct spdk_jsonrpc_request *request, goto cleanup; } - rc = vbdev_error_create(req.base_name); + if (req.uuid) { + if (spdk_uuid_parse(&decoded_uuid, req.uuid)) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "Failed to parse bdev UUID"); + goto cleanup; + } + uuid = &decoded_uuid; + } + + rc = vbdev_error_create(req.base_name, uuid); if (rc) { spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); goto cleanup; diff --git a/python/spdk/rpc/bdev.py b/python/spdk/rpc/bdev.py index 91b46958f..9bfbd201d 100644 --- a/python/spdk/rpc/bdev.py +++ b/python/spdk/rpc/bdev.py @@ -1152,13 +1152,16 @@ def bdev_rbd_resize(client, name, new_size): return client.call('bdev_rbd_resize', params) -def bdev_error_create(client, base_name): +def bdev_error_create(client, base_name, uuid=None): """Construct an error injection block device. Args: base_name: base bdev name + uuid: UUID for this bdev (optional) """ params = {'base_name': base_name} + if uuid is not None: + params['uuid'] = uuid return client.call('bdev_error_create', params) diff --git a/scripts/rpc.py b/scripts/rpc.py index 96de005dd..3fcb02552 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -1069,10 +1069,12 @@ if __name__ == "__main__": def bdev_error_create(args): print_json(rpc.bdev.bdev_error_create(args.client, - base_name=args.base_name)) + base_name=args.base_name, + uuid=args.uuid)) p = subparsers.add_parser('bdev_error_create', help='Add bdev with error injection backend') p.add_argument('base_name', help='base bdev name') + p.add_argument('--uuid', help='UUID for this bdev', required=False) p.set_defaults(func=bdev_error_create) def bdev_error_delete(args):