From 8a154b2c0d4b371c09b14cf5ffb3372995d155e1 Mon Sep 17 00:00:00 2001 From: tanlong <948985618@qq.com> Date: Tue, 19 Oct 2021 04:56:18 -0400 Subject: [PATCH] bdev/rbd:Add uuid to bdev_rbd_create to support multipath when rbd used as ns of nvmf target This patch is to solve the issue that two nvmf target connect the same rbd image and used for multipath. The scenario is host wants to access the same rbd image via two gateways, host and gateways are working as nvmf ini and tgt, and two gateways connect with the rbd image, io can switch to another gateway once one is broken. The targets of multipath must have the same uuid, so this patch add a new argument for bdev_rbd_create, like malloc dev. Signed-off-by: tanlong <948985618@qq.com> Change-Id: I593fedb6c5d94f625f1b331fdc40e2db488f7fb7 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9935 Community-CI: Broadcom CI Tested-by: SPDK CI Jenkins Reviewed-by: Aleksey Marchuk Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- doc/jsonrpc.md | 4 +++- module/bdev/rbd/bdev_rbd.c | 13 ++++++++++++- module/bdev/rbd/bdev_rbd.h | 2 +- module/bdev/rbd/bdev_rbd_rpc.c | 19 +++++++++++++++++-- scripts/rpc.py | 4 +++- scripts/rpc/bdev.py | 5 ++++- 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index f05c8262e..9fd29af8a 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -3569,6 +3569,7 @@ rbd_name | Required | string | Image name block_size | Required | number | Block size config | Optional | string map | Explicit librados configuration cluster_name | Optional | string | Rados cluster object name created in this module. +uuid | Optional | string | UUID of new bdev If no config is specified, Ceph configuration files must exist with all relevant settings for accessing the pool. If a config map is @@ -3601,7 +3602,8 @@ Example request with `key` from `/etc/ceph/ceph.client.admin.keyring`: "mon_host": "192.168.7.1:6789,192.168.7.2:6789", "key": "AQDwf8db7zR1GRAA5k7NKXjS5S5V4mntwUDnGQ==", } - "block_size": 4096 + "block_size": 4096, + "uuid": "76210ea4-7920-40a0-a07b-8992a7443c76" }, "jsonrpc": "2.0", "method": "bdev_rbd_create", diff --git a/module/bdev/rbd/bdev_rbd.c b/module/bdev/rbd/bdev_rbd.c index 918020c4c..791966b11 100644 --- a/module/bdev/rbd/bdev_rbd.c +++ b/module/bdev/rbd/bdev_rbd.c @@ -852,6 +852,7 @@ static void bdev_rbd_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w) { struct bdev_rbd *rbd = bdev->ctxt; + char uuid_str[SPDK_UUID_STRING_LEN]; spdk_json_write_object_begin(w); @@ -877,6 +878,9 @@ bdev_rbd_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w spdk_json_write_object_end(w); } + spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &bdev->uuid); + spdk_json_write_named_string(w, "uuid", uuid_str); + spdk_json_write_object_end(w); spdk_json_write_object_end(w); @@ -1128,7 +1132,8 @@ bdev_rbd_create(struct spdk_bdev **bdev, const char *name, const char *user_id, const char *const *config, const char *rbd_name, uint32_t block_size, - const char *cluster_name) + const char *cluster_name, + const struct spdk_uuid *uuid) { struct bdev_rbd *rbd; int ret; @@ -1189,6 +1194,12 @@ bdev_rbd_create(struct spdk_bdev **bdev, const char *name, const char *user_id, return ret; } + if (uuid) { + rbd->disk.uuid = *uuid; + } else { + spdk_uuid_generate(&rbd->disk.uuid); + } + if (name) { rbd->disk.name = strdup(name); } else { diff --git a/module/bdev/rbd/bdev_rbd.h b/module/bdev/rbd/bdev_rbd.h index c7399251c..1deef34cc 100644 --- a/module/bdev/rbd/bdev_rbd.h +++ b/module/bdev/rbd/bdev_rbd.h @@ -54,7 +54,7 @@ typedef void (*spdk_delete_rbd_complete)(void *cb_arg, int bdeverrno); int bdev_rbd_create(struct spdk_bdev **bdev, const char *name, const char *user_id, const char *pool_name, const char *const *config, - const char *rbd_name, uint32_t block_size, const char *cluster_name); + const char *rbd_name, uint32_t block_size, const char *cluster_name, const struct spdk_uuid *uuid); /** * Delete rbd bdev. * diff --git a/module/bdev/rbd/bdev_rbd_rpc.c b/module/bdev/rbd/bdev_rbd_rpc.c index b066c1ee9..acc16e845 100644 --- a/module/bdev/rbd/bdev_rbd_rpc.c +++ b/module/bdev/rbd/bdev_rbd_rpc.c @@ -33,6 +33,7 @@ #include "bdev_rbd.h" #include "spdk/util.h" +#include "spdk/uuid.h" #include "spdk/string.h" #include "spdk/log.h" @@ -44,6 +45,7 @@ struct rpc_create_rbd { uint32_t block_size; char **config; char *cluster_name; + char *uuid; }; static void @@ -55,6 +57,7 @@ free_rpc_create_rbd(struct rpc_create_rbd *req) free(req->rbd_name); bdev_rbd_free_config(req->config); free(req->cluster_name); + free(req->uuid); } static int @@ -106,7 +109,8 @@ static const struct spdk_json_object_decoder rpc_create_rbd_decoders[] = { {"rbd_name", offsetof(struct rpc_create_rbd, rbd_name), spdk_json_decode_string}, {"block_size", offsetof(struct rpc_create_rbd, block_size), spdk_json_decode_uint32}, {"config", offsetof(struct rpc_create_rbd, config), bdev_rbd_decode_config, true}, - {"cluster_name", offsetof(struct rpc_create_rbd, cluster_name), spdk_json_decode_string, true} + {"cluster_name", offsetof(struct rpc_create_rbd, cluster_name), spdk_json_decode_string, true}, + {"uuid", offsetof(struct rpc_create_rbd, uuid), spdk_json_decode_string, true} }; static void @@ -117,6 +121,8 @@ rpc_bdev_rbd_create(struct spdk_jsonrpc_request *request, struct spdk_json_write_ctx *w; struct spdk_bdev *bdev; int rc = 0; + struct spdk_uuid *uuid = NULL; + struct spdk_uuid decoded_uuid; if (spdk_json_decode_object(params, rpc_create_rbd_decoders, SPDK_COUNTOF(rpc_create_rbd_decoders), @@ -127,10 +133,19 @@ rpc_bdev_rbd_create(struct spdk_jsonrpc_request *request, goto cleanup; } + if (req.uuid) { + if (spdk_uuid_parse(&decoded_uuid, req.uuid)) { + spdk_jsonrpc_send_error_response(request, -EINVAL, + "Failed to parse bdev UUID"); + goto cleanup; + } + uuid = &decoded_uuid; + } + rc = bdev_rbd_create(&bdev, req.name, req.user_id, req.pool_name, (const char *const *)req.config, req.rbd_name, - req.block_size, req.cluster_name); + req.block_size, req.cluster_name, uuid); if (rc) { spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); goto cleanup; diff --git a/scripts/rpc.py b/scripts/rpc.py index 235923b67..228907915 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -700,7 +700,8 @@ if __name__ == "__main__": pool_name=args.pool_name, rbd_name=args.rbd_name, block_size=args.block_size, - cluster_name=args.cluster_name)) + cluster_name=args.cluster_name, + uuid=args.uuid)) p = subparsers.add_parser('bdev_rbd_create', aliases=['construct_rbd_bdev'], help='Add a bdev with ceph rbd backend') @@ -712,6 +713,7 @@ if __name__ == "__main__": p.add_argument('rbd_name', help='rbd image name') p.add_argument('block_size', help='rbd block size', type=int) p.add_argument('-c', '--cluster-name', help="cluster name to identify the Rados cluster", required=False) + p.add_argument('-u', '--uuid', help="UUID of the bdev") p.set_defaults(func=bdev_rbd_create) def bdev_rbd_delete(args): diff --git a/scripts/rpc/bdev.py b/scripts/rpc/bdev.py index a8684ffaa..87fde800b 100644 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -733,7 +733,7 @@ def bdev_rbd_get_clusters_info(client, name): @deprecated_alias('construct_rbd_bdev') -def bdev_rbd_create(client, pool_name, rbd_name, block_size, name=None, user=None, config=None, cluster_name=None): +def bdev_rbd_create(client, pool_name, rbd_name, block_size, name=None, user=None, config=None, cluster_name=None, uuid=None): """Create a Ceph RBD block device. Args: @@ -744,6 +744,7 @@ def bdev_rbd_create(client, pool_name, rbd_name, block_size, name=None, user=Non user: Ceph user name (optional) config: map of config keys to values (optional) cluster_name: Name to identify Rados cluster (optional) + uuid: UUID of block device (optional) Returns: Name of created block device. @@ -762,6 +763,8 @@ def bdev_rbd_create(client, pool_name, rbd_name, block_size, name=None, user=Non params['config'] = config if cluster_name is not None: params['cluster_name'] = cluster_name + if uuid is not None: + params['uuid'] = uuid return client.call('bdev_rbd_create', params)