diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index 633a935cc..e3a0da070 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -5982,6 +5982,7 @@ Name | Optional | Type | Description ----------------------- | -------- | ----------- | ----------- name | Required | string | Bdev name base_bdev_name | Required | string | Base bdev name +uuid | Optional | string | UUID of new bdev #### Result diff --git a/module/bdev/passthru/vbdev_passthru.c b/module/bdev/passthru/vbdev_passthru.c index 09ab1513b..5abe67357 100644 --- a/module/bdev/passthru/vbdev_passthru.c +++ b/module/bdev/passthru/vbdev_passthru.c @@ -46,6 +46,7 @@ SPDK_BDEV_MODULE_REGISTER(passthru, &passthru_if) struct bdev_names { char *vbdev_name; char *bdev_name; + struct spdk_uuid uuid; TAILQ_ENTRY(bdev_names) link; }; static TAILQ_HEAD(, bdev_names) g_bdev_names = TAILQ_HEAD_INITIALIZER(g_bdev_names); @@ -404,11 +405,19 @@ vbdev_passthru_config_json(struct spdk_json_write_ctx *w) struct vbdev_passthru *pt_node; TAILQ_FOREACH(pt_node, &g_pt_nodes, link) { + const struct spdk_uuid *uuid = spdk_bdev_get_uuid(&pt_node->pt_bdev); + spdk_json_write_object_begin(w); spdk_json_write_named_string(w, "method", "bdev_passthru_create"); spdk_json_write_named_object_begin(w, "params"); spdk_json_write_named_string(w, "base_bdev_name", spdk_bdev_get_name(pt_node->base_bdev)); spdk_json_write_named_string(w, "name", spdk_bdev_get_name(&pt_node->pt_bdev)); + if (!spdk_uuid_is_null(uuid)) { + char uuid_str[SPDK_UUID_STRING_LEN]; + + spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), uuid); + spdk_json_write_named_string(w, "uuid", uuid_str); + } spdk_json_write_object_end(w); spdk_json_write_object_end(w); } @@ -447,7 +456,8 @@ pt_bdev_ch_destroy_cb(void *io_device, void *ctx_buf) /* Create the passthru association from the bdev and vbdev name and insert * on the global list. */ static int -vbdev_passthru_insert_name(const char *bdev_name, const char *vbdev_name) +vbdev_passthru_insert_name(const char *bdev_name, const char *vbdev_name, + const struct spdk_uuid *uuid) { struct bdev_names *name; @@ -479,6 +489,10 @@ vbdev_passthru_insert_name(const char *bdev_name, const char *vbdev_name) return -ENOMEM; } + if (uuid) { + spdk_uuid_copy(&name->uuid, uuid); + } + TAILQ_INSERT_TAIL(&g_bdev_names, name, link); return 0; @@ -607,6 +621,7 @@ vbdev_passthru_register(const char *bdev_name) break; } pt_node->pt_bdev.product_name = "passthru"; + spdk_uuid_copy(&pt_node->pt_bdev.uuid, &name->uuid); /* The base bdev that we're attaching to. */ rc = spdk_bdev_open_ext(bdev_name, true, vbdev_passthru_base_bdev_event_cb, @@ -685,14 +700,15 @@ vbdev_passthru_register(const char *bdev_name) /* Create the passthru disk from the given bdev and vbdev name. */ int -bdev_passthru_create_disk(const char *bdev_name, const char *vbdev_name) +bdev_passthru_create_disk(const char *bdev_name, const char *vbdev_name, + const struct spdk_uuid *uuid) { int rc; /* Insert the bdev name into our global name list even if it doesn't exist yet, * it may show up soon... */ - rc = vbdev_passthru_insert_name(bdev_name, vbdev_name); + rc = vbdev_passthru_insert_name(bdev_name, vbdev_name, uuid); if (rc) { return rc; } diff --git a/module/bdev/passthru/vbdev_passthru.h b/module/bdev/passthru/vbdev_passthru.h index 5450fbb14..076077f9e 100644 --- a/module/bdev/passthru/vbdev_passthru.h +++ b/module/bdev/passthru/vbdev_passthru.h @@ -16,9 +16,11 @@ * * \param bdev_name Bdev on which pass through vbdev will be created. * \param vbdev_name Name of the pass through bdev. + * \param uuid Optional UUID to assign to the pass through bdev. * \return 0 on success, other on failure. */ -int bdev_passthru_create_disk(const char *bdev_name, const char *vbdev_name); +int bdev_passthru_create_disk(const char *bdev_name, const char *vbdev_name, + const struct spdk_uuid *uuid); /** * Delete passthru bdev. diff --git a/module/bdev/passthru/vbdev_passthru_rpc.c b/module/bdev/passthru/vbdev_passthru_rpc.c index 82560199c..68e614a0b 100644 --- a/module/bdev/passthru/vbdev_passthru_rpc.c +++ b/module/bdev/passthru/vbdev_passthru_rpc.c @@ -14,6 +14,7 @@ struct rpc_bdev_passthru_create { char *base_bdev_name; char *name; + char *uuid; }; /* Free the allocated memory resource after the RPC handling. */ @@ -22,12 +23,14 @@ free_rpc_bdev_passthru_create(struct rpc_bdev_passthru_create *r) { free(r->base_bdev_name); free(r->name); + free(r->uuid); } /* Structure to decode the input parameters for this RPC method. */ static const struct spdk_json_object_decoder rpc_bdev_passthru_create_decoders[] = { {"base_bdev_name", offsetof(struct rpc_bdev_passthru_create, base_bdev_name), spdk_json_decode_string}, {"name", offsetof(struct rpc_bdev_passthru_create, name), spdk_json_decode_string}, + {"uuid", offsetof(struct rpc_bdev_passthru_create, uuid), spdk_json_decode_string, true}, }; /* Decode the parameters for this RPC method and properly construct the passthru @@ -39,6 +42,8 @@ rpc_bdev_passthru_create(struct spdk_jsonrpc_request *request, { struct rpc_bdev_passthru_create req = {NULL}; struct spdk_json_write_ctx *w; + struct spdk_uuid *uuid = NULL; + struct spdk_uuid decoded_uuid; int rc; if (spdk_json_decode_object(params, rpc_bdev_passthru_create_decoders, @@ -50,7 +55,16 @@ rpc_bdev_passthru_create(struct spdk_jsonrpc_request *request, goto cleanup; } - rc = bdev_passthru_create_disk(req.base_bdev_name, req.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 = bdev_passthru_create_disk(req.base_bdev_name, req.name, uuid); if (rc != 0) { 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 c7811105b..6206f497c 100644 --- a/python/spdk/rpc/bdev.py +++ b/python/spdk/rpc/bdev.py @@ -1312,12 +1312,13 @@ def bdev_iscsi_delete(client, name): return client.call('bdev_iscsi_delete', params) -def bdev_passthru_create(client, base_bdev_name, name): +def bdev_passthru_create(client, base_bdev_name, name, uuid=None): """Construct a pass-through block device. Args: base_bdev_name: name of the existing bdev name: name of block device + uuid: UUID of block device (optional) Returns: Name of created block device. @@ -1326,6 +1327,8 @@ def bdev_passthru_create(client, base_bdev_name, name): 'base_bdev_name': base_bdev_name, 'name': name, } + if uuid: + params['uuid'] = uuid return client.call('bdev_passthru_create', params) diff --git a/scripts/rpc.py b/scripts/rpc.py index 80b4a405a..2870d3e33 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -1129,11 +1129,13 @@ if __name__ == "__main__": def bdev_passthru_create(args): print_json(rpc.bdev.bdev_passthru_create(args.client, base_bdev_name=args.base_bdev_name, - name=args.name)) + name=args.name, + uuid=args.uuid)) p = subparsers.add_parser('bdev_passthru_create', help='Add a pass through bdev on existing bdev') p.add_argument('-b', '--base-bdev-name', help="Name of the existing bdev", required=True) p.add_argument('-p', '--name', help="Name of the pass through bdev", required=True) + p.add_argument('-u', '--uuid', help="UUID of the bdev") p.set_defaults(func=bdev_passthru_create) def bdev_passthru_delete(args):