From 526cd580033dbb41cf1c4e949080332509a02b08 Mon Sep 17 00:00:00 2001 From: Sebastian Basierski Date: Wed, 10 Jan 2018 11:02:27 +0100 Subject: [PATCH] bdev: Added functions allowing logical volume rename. Change-Id: Ice343afdc84c2a11cd9026d128a35f7a62aa7125 Signed-off-by: Sebastian Basierski Reviewed-on: https://review.gerrithub.io/398933 Reviewed-by: Jim Harris Reviewed-by: Daniel Verkamp Reviewed-by: Tomasz Zawadzki Tested-by: SPDK Automated Test System --- include/spdk/lvol.h | 11 + include/spdk_internal/lvolstore.h | 3 +- lib/bdev/lvol/vbdev_lvol.c | 120 +++++++++- lib/bdev/lvol/vbdev_lvol.h | 3 + lib/bdev/lvol/vbdev_lvol_rpc.c | 86 +++++++ lib/lvol/lvol.c | 61 +++++ scripts/rpc.py | 5 + scripts/rpc/lvol.py | 8 + .../lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c | 213 +++++++++++++++++- test/unit/lib/lvol/lvol.c/lvol_ut.c | 77 ++++++- test/vhost/lvol/lvol_test.sh | 4 +- 11 files changed, 581 insertions(+), 10 deletions(-) diff --git a/include/spdk/lvol.h b/include/spdk/lvol.h index 36de87010..991d63e6e 100644 --- a/include/spdk/lvol.h +++ b/include/spdk/lvol.h @@ -151,6 +151,17 @@ int spdk_lvs_destroy(struct spdk_lvol_store *lvol_store, int spdk_lvol_create(struct spdk_lvol_store *lvs, const char *name, uint64_t sz, bool thin_provisioned, spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg); +/** + * \brief Renames lvol with new_name. + * \param lvol Handle to lvol + * \param new_name new name for lvol + * \param cb_fn Completion callback + * \param cb_arg Completion callback custom arguments + */ +void +spdk_lvol_rename(struct spdk_lvol *lvol, const char *new_name, + spdk_lvol_op_complete cb_fn, void *cb_arg); + /** * \brief Closes lvol and removes information about lvol from its lvolstore. * \param lvol Handle to lvol diff --git a/include/spdk_internal/lvolstore.h b/include/spdk_internal/lvolstore.h index 64cfd6d45..2838e7cd7 100644 --- a/include/spdk_internal/lvolstore.h +++ b/include/spdk_internal/lvolstore.h @@ -52,9 +52,10 @@ struct spdk_lvs_req { }; struct spdk_lvol_req { - spdk_lvol_op_complete cb_fn; + spdk_lvol_op_complete cb_fn; void *cb_arg; struct spdk_lvol *lvol; + char name[SPDK_LVOL_NAME_MAX]; }; struct spdk_lvs_with_handle_req { diff --git a/lib/bdev/lvol/vbdev_lvol.c b/lib/bdev/lvol/vbdev_lvol.c index 8be2dfa87..6df9d506f 100644 --- a/lib/bdev/lvol/vbdev_lvol.c +++ b/lib/bdev/lvol/vbdev_lvol.c @@ -66,6 +66,56 @@ vbdev_get_lvs_bdev_by_lvs(struct spdk_lvol_store *lvs_orig) return NULL; } +static int +_vbdev_lvol_change_bdev_alias(struct spdk_lvol *lvol, const char *new_lvol_name) +{ + struct spdk_bdev_alias *tmp; + char *old_alias; + char *alias; + int rc; + int alias_number = 0; + + /* bdev representing lvols have only one alias, + * while we changed lvs name earlier, we have to iterate alias list to get one, + * and check if there is only one alias */ + + TAILQ_FOREACH(tmp, &lvol->bdev->aliases, tailq) { + if (++alias_number > 1) { + SPDK_ERRLOG("There is more than 1 alias in bdev %s\n", lvol->bdev->name); + return -EINVAL; + } + + old_alias = tmp->alias; + } + + if (alias_number == 0) { + SPDK_ERRLOG("There are no aliases in bdev %s\n", lvol->bdev->name); + return -EINVAL; + } + + alias = spdk_sprintf_alloc("%s/%s", lvol->lvol_store->name, new_lvol_name); + if (alias == NULL) { + SPDK_ERRLOG("Cannot alloc memory for alias\n"); + return -ENOMEM; + } + + rc = spdk_bdev_alias_add(lvol->bdev, alias); + if (rc != 0) { + SPDK_ERRLOG("cannot add alias '%s'\n", alias); + free(alias); + return rc; + } + free(alias); + + rc = spdk_bdev_alias_del(lvol->bdev, old_alias); + if (rc != 0) { + SPDK_ERRLOG("cannot remove alias '%s'\n", old_alias); + return rc; + } + + return 0; +} + static struct lvol_store_bdev * vbdev_get_lvs_bdev_by_bdev(struct spdk_bdev *bdev_orig) { @@ -442,9 +492,18 @@ static int vbdev_lvol_destruct(void *ctx) { struct spdk_lvol *lvol = ctx; + char *alias; assert(lvol != NULL); + alias = spdk_sprintf_alloc("%s/%s", lvol->lvol_store->name, lvol->name); + if (alias != NULL) { + spdk_bdev_alias_del(lvol->bdev, alias); + free(alias); + } else { + SPDK_ERRLOG("Cannot alloc memory for alias\n"); + } + if (lvol->close_only) { free(lvol->bdev->name); free(lvol->bdev); @@ -660,6 +719,7 @@ _create_lvol_disk(struct spdk_lvol *lvol) struct spdk_bdev *bdev; struct lvol_store_bdev *lvs_bdev; uint64_t total_size; + unsigned char *alias; int rc; if (!lvol->unique_id) { @@ -678,8 +738,8 @@ _create_lvol_disk(struct spdk_lvol *lvol) return NULL; } - bdev->name = spdk_sprintf_alloc("%s/%s", lvs_bdev->lvs->name, lvol->name); - if (bdev->name == NULL) { + bdev->name = strdup(lvol->unique_id); + if (!bdev->name) { SPDK_ERRLOG("Cannot alloc memory for bdev name\n"); free(bdev); return NULL; @@ -701,6 +761,24 @@ _create_lvol_disk(struct spdk_lvol *lvol) return NULL; } + alias = spdk_sprintf_alloc("%s/%s", lvs_bdev->lvs->name, lvol->name); + if (alias == NULL) { + SPDK_ERRLOG("Cannot alloc memory for alias\n"); + free(bdev->name); + free(bdev); + return NULL; + } + + rc = spdk_bdev_alias_add(bdev, alias); + if (rc != 0) { + SPDK_ERRLOG("Cannot add alias to lvol bdev\n"); + free(bdev->name); + free(bdev); + free(alias); + return NULL; + } + free(alias); + return bdev; } @@ -748,6 +826,44 @@ vbdev_lvol_create(struct spdk_lvol_store *lvs, const char *name, size_t sz, return rc; } +static void +_vbdev_lvol_rename_cb(void *cb_arg, int lvolerrno) +{ + struct spdk_lvol_req *req = cb_arg; + + if (lvolerrno != 0) { + SPDK_ERRLOG("Renaming lvol failed\n"); + } + + req->cb_fn(req->cb_arg, lvolerrno); + free(req); +} + +void +vbdev_lvol_rename(struct spdk_lvol *lvol, const char *new_lvol_name, + spdk_lvol_op_complete cb_fn, void *cb_arg) +{ + struct spdk_lvol_req *req; + int rc; + + rc = _vbdev_lvol_change_bdev_alias(lvol, new_lvol_name); + if (rc != 0) { + SPDK_ERRLOG("renaming lvol to '%s' does not succeed\n", new_lvol_name); + cb_fn(cb_arg, rc); + return; + } + + req = calloc(1, sizeof(*req)); + if (req == NULL) { + cb_fn(cb_arg, -ENOMEM); + return; + } + req->cb_fn = cb_fn; + req->cb_arg = cb_arg; + + spdk_lvol_rename(lvol, new_lvol_name, _vbdev_lvol_rename_cb, req); +} + static void _vbdev_lvol_resize_cb(void *cb_arg, int lvolerrno) { diff --git a/lib/bdev/lvol/vbdev_lvol.h b/lib/bdev/lvol/vbdev_lvol.h index c543a8a4b..f599db504 100644 --- a/lib/bdev/lvol/vbdev_lvol.h +++ b/lib/bdev/lvol/vbdev_lvol.h @@ -57,6 +57,9 @@ int vbdev_lvol_create(struct spdk_lvol_store *lvs, const char *name, size_t sz, int vbdev_lvol_resize(char *name, size_t sz, spdk_lvol_op_complete cb_fn, void *cb_arg); +void vbdev_lvol_rename(struct spdk_lvol *lvol, const char *new_lvol_name, + spdk_lvol_op_complete cb_fn, void *cb_arg); + /** * \brief Search for handle lvolstore * \param uuid_str UUID of lvolstore diff --git a/lib/bdev/lvol/vbdev_lvol_rpc.c b/lib/bdev/lvol/vbdev_lvol_rpc.c index 5ca39c9fa..df3ed08f3 100644 --- a/lib/bdev/lvol/vbdev_lvol_rpc.c +++ b/lib/bdev/lvol/vbdev_lvol_rpc.c @@ -342,6 +342,92 @@ invalid: SPDK_RPC_REGISTER("construct_lvol_bdev", spdk_rpc_construct_lvol_bdev) +struct rpc_rename_lvol_bdev { + char *old_name; + char *new_name; +}; + +static void +free_rpc_rename_lvol_bdev(struct rpc_rename_lvol_bdev *req) +{ + free(req->old_name); + free(req->new_name); +} + +static const struct spdk_json_object_decoder rpc_rename_lvol_bdev_decoders[] = { + {"old_name", offsetof(struct rpc_rename_lvol_bdev, old_name), spdk_json_decode_string, true}, + {"new_name", offsetof(struct rpc_rename_lvol_bdev, new_name), spdk_json_decode_string, true}, +}; + +static void +_spdk_rpc_rename_lvol_bdev_cb(void *cb_arg, int lvolerrno) +{ + struct spdk_json_write_ctx *w; + struct spdk_jsonrpc_request *request = cb_arg; + + if (lvolerrno != 0) { + goto invalid; + } + + w = spdk_jsonrpc_begin_result(request); + if (w == NULL) { + return; + } + + spdk_json_write_bool(w, true); + spdk_jsonrpc_end_result(request, w); + return; + +invalid: + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + spdk_strerror(-lvolerrno)); +} + +static void +spdk_rpc_rename_lvol_bdev(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_rename_lvol_bdev req = {}; + struct spdk_bdev *bdev; + struct spdk_lvol *lvol; + int rc = 0; + + SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Renaming lvol\n"); + + if (spdk_json_decode_object(params, rpc_rename_lvol_bdev_decoders, + SPDK_COUNTOF(rpc_rename_lvol_bdev_decoders), + &req)) { + SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n"); + rc = -EINVAL; + goto invalid; + } + + bdev = spdk_bdev_get_by_name(req.old_name); + if (bdev == NULL) { + SPDK_ERRLOG("bdev '%s' does not exist\n", req.old_name); + rc = -ENODEV; + goto invalid; + } + + lvol = vbdev_lvol_get_from_bdev(bdev); + if (lvol == NULL) { + SPDK_ERRLOG("lvol does not exist\n"); + rc = -ENODEV; + goto invalid; + } + + vbdev_lvol_rename(lvol, req.new_name, _spdk_rpc_rename_lvol_bdev_cb, request); + + free_rpc_rename_lvol_bdev(&req); + return; + +invalid: + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc)); + free_rpc_rename_lvol_bdev(&req); +} + +SPDK_RPC_REGISTER("rename_lvol_bdev", spdk_rpc_rename_lvol_bdev) + struct rpc_resize_lvol_bdev { char *name; uint64_t size; diff --git a/lib/lvol/lvol.c b/lib/lvol/lvol.c index 9def3a063..b8e1e1e6a 100644 --- a/lib/lvol/lvol.c +++ b/lib/lvol/lvol.c @@ -1038,6 +1038,67 @@ invalid: return rc; } +static void +_spdk_lvol_rename_cb(void *cb_arg, int lvolerrno) +{ + struct spdk_lvol_req *req = cb_arg; + + if (lvolerrno != 0) { + SPDK_ERRLOG("Lvol rename operation failed\n"); + } else { + strncpy(req->lvol->name, req->name, SPDK_LVOL_NAME_MAX); + } + + req->cb_fn(req->cb_arg, lvolerrno); + free(req); +} + +void +spdk_lvol_rename(struct spdk_lvol *lvol, const char *new_name, + spdk_lvol_op_complete cb_fn, void *cb_arg) +{ + struct spdk_lvol *tmp; + struct spdk_blob *blob = lvol->blob; + struct spdk_lvol_req *req; + int rc; + + /* Check if new name is current lvol name. + * If so, return success immediately */ + if (strncmp(lvol->name, new_name, SPDK_LVOL_NAME_MAX) == 0) { + cb_fn(cb_arg, 0); + return; + } + + /* Check if lvol with 'new_name' already exists in lvolstore */ + TAILQ_FOREACH(tmp, &lvol->lvol_store->lvols, link) { + if (strncmp(tmp->name, new_name, SPDK_LVOL_NAME_MAX) == 0) { + SPDK_ERRLOG("Lvol %s already exists in lvol store %s\n", new_name, lvol->lvol_store->name); + cb_fn(cb_arg, -EEXIST); + return; + } + } + + req = calloc(1, sizeof(*req)); + if (!req) { + SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n"); + cb_fn(cb_arg, -ENOMEM); + return; + } + req->cb_fn = cb_fn; + req->cb_arg = cb_arg; + req->lvol = lvol; + strncpy(req->name, new_name, SPDK_LVOL_NAME_MAX); + + rc = spdk_blob_set_xattr(blob, "name", new_name, strlen(new_name) + 1); + if (rc < 0) { + free(req); + cb_fn(cb_arg, rc); + return; + } + + spdk_blob_sync_md(blob, _spdk_lvol_rename_cb, req); +} + void spdk_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg) { diff --git a/scripts/rpc.py b/scripts/rpc.py index 19ecadad8..bd07c2cf5 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -283,6 +283,11 @@ if __name__ == "__main__": p.add_argument('size', help='size in MiB for this bdev', type=int) p.set_defaults(func=rpc.lvol.construct_lvol_bdev) + p = subparsers.add_parser('rename_lvol_bdev', help='Change lvol bdev name') + p.add_argument('old_name', help='lvol bdev name') + p.add_argument('new_name', help='new lvol name') + p.set_defaults(func=rpc.lvol.rename_lvol_bdev) + # Logical volume resize feature is disabled, as it is currently work in progress # p = subparsers.add_parser('resize_lvol_bdev', help='Resize existing lvol bdev') # p.add_argument('name', help='lvol bdev name') diff --git a/scripts/rpc/lvol.py b/scripts/rpc/lvol.py index 564dfa92b..801caeb29 100755 --- a/scripts/rpc/lvol.py +++ b/scripts/rpc/lvol.py @@ -23,6 +23,14 @@ def construct_lvol_bdev(args): print_array(args.client.call('construct_lvol_bdev', params)) +def rename_lvol_bdev(args): + params = { + 'old_name': args.old_name, + 'new_name': args.new_name + } + args.client.call('rename_lvol_bdev', params) + + # Logical volume resize feature is disabled, as it is currently work in progress # # def resize_lvol_bdev(args): diff --git a/test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c b/test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c index 5893588af..4f99d8a3c 100644 --- a/test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c +++ b/test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c @@ -58,12 +58,79 @@ bool lvol_store_initialize_fail = false; bool lvol_store_initialize_cb_fail = false; bool lvol_already_opened = false; bool g_examine_done = false; +bool g_bdev_alias_already_exists = false; + +int +spdk_bdev_alias_add(struct spdk_bdev *bdev, const char *alias) +{ + struct spdk_bdev_alias *tmp; + + CU_ASSERT(alias != NULL); + CU_ASSERT(bdev != NULL); + if (g_bdev_alias_already_exists) { + return -EEXIST; + } + + tmp = calloc(1, sizeof(*tmp)); + SPDK_CU_ASSERT_FATAL(tmp != NULL); + + tmp->alias = strdup(alias); + SPDK_CU_ASSERT_FATAL(tmp->alias != NULL); + + TAILQ_INSERT_TAIL(&bdev->aliases, tmp, tailq); + + return 0; +} + +int +spdk_bdev_alias_del(struct spdk_bdev *bdev, const char *alias) +{ + struct spdk_bdev_alias *tmp; + + CU_ASSERT(alias != NULL); + CU_ASSERT(bdev != NULL); + + TAILQ_FOREACH(tmp, &bdev->aliases, tailq) { + if (strncmp(alias, tmp->alias, SPDK_LVOL_NAME_MAX) == 0) { + TAILQ_REMOVE(&bdev->aliases, tmp, tailq); + free(tmp->alias); + free(tmp); + return 0; + } + } + + return -ENOENT; +} void spdk_bdev_unregister_done(struct spdk_bdev *bdev, int bdeverrno) { } +void +spdk_lvol_rename(struct spdk_lvol *lvol, const char *new_name, + spdk_lvol_op_complete cb_fn, void *cb_arg) +{ + struct spdk_lvol *tmp; + + if (strncmp(lvol->name, new_name, SPDK_LVOL_NAME_MAX) == 0) { + cb_fn(cb_arg, 0); + return; + } + + TAILQ_FOREACH(tmp, &lvol->lvol_store->lvols, link) { + if (strncmp(tmp->name, new_name, SPDK_LVOL_NAME_MAX) == 0) { + SPDK_ERRLOG("Lvol %s already exists in lvol store %s\n", new_name, lvol->lvol_store->name); + cb_fn(cb_arg, -EEXIST); + return; + } + } + + strncpy(lvol->name, new_name, SPDK_LVOL_NAME_MAX); + + cb_fn(cb_arg, g_lvolerrno); +} + void spdk_lvol_open(struct spdk_lvol *lvol, spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg) { @@ -216,9 +283,19 @@ spdk_lvs_destroy(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, void *cb_arg) { struct spdk_lvol *lvol, *tmp; + char *alias; TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) { TAILQ_REMOVE(&lvs->lvols, lvol, link); + + alias = spdk_sprintf_alloc("%s/%s", lvs->name, lvol->name); + if (alias == NULL) { + SPDK_ERRLOG("Cannot alloc memory for alias\n"); + return -1; + } + spdk_bdev_alias_del(lvol->bdev, alias); + + free(alias); free(lvol->unique_id); free(lvol); } @@ -437,6 +514,8 @@ spdk_bdev_get_name(const struct spdk_bdev *bdev) int spdk_vbdev_register(struct spdk_bdev *vbdev, struct spdk_bdev **base_bdevs, int base_bdev_count) { + TAILQ_INIT(&vbdev->aliases); + g_registered_bdevs++; return 0; } @@ -471,6 +550,7 @@ spdk_lvol_create(struct spdk_lvol_store *lvs, const char *name, size_t sz, struct spdk_lvol *lvol; lvol = _lvol_create(lvs); + strncpy(lvol->name, name, SPDK_LVS_NAME_MAX); cb_fn(cb_arg, lvol, 0); return 0; @@ -504,6 +584,12 @@ vbdev_lvol_resize_complete(void *cb_arg, int lvolerrno) g_lvolerrno = lvolerrno; } +static void +vbdev_lvol_rename_complete(void *cb_arg, int lvolerrno) +{ + g_lvolerrno = lvolerrno; +} + static void ut_lvs_destroy(void) { @@ -518,6 +604,13 @@ ut_lvs_destroy(void) SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL); CU_ASSERT(g_bs_dev != NULL); + /* Create g_base_dev */ + g_lvs_bdev = calloc(1, sizeof(*g_lvs_bdev)); + SPDK_CU_ASSERT_FATAL(g_lvs_bdev != NULL); + g_base_bdev = calloc(1, sizeof(*g_base_bdev)); + SPDK_CU_ASSERT_FATAL(g_base_bdev != NULL); + g_lvs_bdev->bdev = g_base_bdev; + lvs = g_lvol_store; g_lvol_store = NULL; @@ -534,6 +627,9 @@ ut_lvs_destroy(void) vbdev_lvs_destruct(lvs, lvol_store_op_complete, NULL); CU_ASSERT(g_lvserrno == 0); CU_ASSERT(g_lvol_store == NULL); + + free(g_lvs_bdev); + free(g_base_bdev); } static void @@ -550,6 +646,10 @@ ut_lvol_init(void) g_base_bdev = calloc(1, sizeof(*g_base_bdev)); SPDK_CU_ASSERT_FATAL(g_base_bdev != NULL); + /* Assign name to lvs */ + strncpy(g_lvs->name, "UNIT_TEST_LVS_NAME", SPDK_LVS_NAME_MAX); + SPDK_CU_ASSERT_FATAL(g_lvs->name != NULL); + g_lvs_bdev->lvs = g_lvs; g_lvs_bdev->bdev = g_base_bdev; @@ -573,8 +673,6 @@ ut_lvol_init(void) free(g_lvs); free(g_lvs_bdev); free(g_base_bdev); - - } static void @@ -662,6 +760,18 @@ ut_lvol_examine(void) free(g_bs_dev); /* Examine succesfully */ + g_lvs = calloc(1, sizeof(*g_lvs)); + SPDK_CU_ASSERT_FATAL(g_lvs != NULL); + TAILQ_INIT(&g_lvs->lvols); + g_lvs_bdev = calloc(1, sizeof(*g_lvs_bdev)); + SPDK_CU_ASSERT_FATAL(g_lvs_bdev != NULL); + g_base_bdev = calloc(1, sizeof(*g_base_bdev)); + SPDK_CU_ASSERT_FATAL(g_base_bdev != NULL); + + /* Assign name to lvs */ + strncpy(g_lvs->name, "UNIT_TEST_LVS_NAME", SPDK_LVS_NAME_MAX); + SPDK_CU_ASSERT_FATAL(g_lvs->name != NULL); + g_bs_dev = NULL; g_lvserrno = 0; g_lvolerrno = 0; @@ -682,6 +792,85 @@ ut_lvol_examine(void) free(bdev); free(g_bs_dev); free(g_lvol_store); + + free(g_lvs); + free(g_lvs_bdev); + free(g_base_bdev); +} + +static void +ut_lvol_rename(void) +{ + struct spdk_lvol *lvol; + struct spdk_lvol *lvol2; + int sz = 10; + int rc; + + g_lvs = calloc(1, sizeof(*g_lvs)); + SPDK_CU_ASSERT_FATAL(g_lvs != NULL); + TAILQ_INIT(&g_lvs->lvols); + g_lvs_bdev = calloc(1, sizeof(*g_lvs_bdev)); + SPDK_CU_ASSERT_FATAL(g_lvs_bdev != NULL); + g_base_bdev = calloc(1, sizeof(*g_base_bdev)); + SPDK_CU_ASSERT_FATAL(g_base_bdev != NULL); + + /* Assign name to lvs */ + strncpy(g_lvs->name, "UNIT_TEST_LVS_NAME", SPDK_LVS_NAME_MAX); + SPDK_CU_ASSERT_FATAL(g_lvs->name != NULL); + + g_lvs_bdev->lvs = g_lvs; + g_lvs_bdev->bdev = g_base_bdev; + + uuid_generate_time(g_lvs->uuid); + + TAILQ_INSERT_TAIL(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores); + + /* Successful lvols create */ + g_lvolerrno = -1; + rc = vbdev_lvol_create(g_lvs, "lvol", sz, false, vbdev_lvol_create_complete, NULL); + SPDK_CU_ASSERT_FATAL(rc == 0); + CU_ASSERT(g_lvol != NULL); + CU_ASSERT(g_lvolerrno == 0); + lvol = g_lvol; + + g_lvolerrno = -1; + rc = vbdev_lvol_create(g_lvs, "lvol2", sz, false, vbdev_lvol_create_complete, NULL); + SPDK_CU_ASSERT_FATAL(rc == 0); + CU_ASSERT(g_lvol != NULL); + CU_ASSERT(g_lvolerrno == 0); + lvol2 = g_lvol; + + /* Successful rename lvol */ + vbdev_lvol_rename(lvol, "new_lvol_name", vbdev_lvol_rename_complete, NULL); + SPDK_CU_ASSERT_FATAL(g_lvolerrno == 0); + CU_ASSERT_STRING_EQUAL(lvol->name, "new_lvol_name"); + + /* Renaming lvol with name already existing */ + g_bdev_alias_already_exists = true; + vbdev_lvol_rename(lvol2, "new_lvol_name", vbdev_lvol_rename_complete, NULL); + g_bdev_alias_already_exists = false; + SPDK_CU_ASSERT_FATAL(g_lvolerrno != 0); + CU_ASSERT_STRING_NOT_EQUAL(lvol2->name, "new_lvol_name"); + + /* Renaming lvol with it's own name */ + vbdev_lvol_rename(lvol, "new_lvol_name", vbdev_lvol_rename_complete, NULL); + SPDK_CU_ASSERT_FATAL(g_lvolerrno == 0); + CU_ASSERT_STRING_EQUAL(lvol->name, "new_lvol_name"); + + /* Successful lvols destruct */ + g_lvol = lvol; + vbdev_lvol_destruct(g_lvol); + CU_ASSERT(g_lvol == NULL); + + g_lvol = lvol2; + vbdev_lvol_destruct(g_lvol); + CU_ASSERT(g_lvol == NULL); + + TAILQ_REMOVE(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores); + + free(g_lvs); + free(g_lvs_bdev); + free(g_base_bdev); } static void @@ -699,10 +888,14 @@ ut_lvol_resize(void) SPDK_CU_ASSERT_FATAL(g_lvs_bdev != NULL); g_base_bdev = calloc(1, sizeof(*g_base_bdev)); SPDK_CU_ASSERT_FATAL(g_base_bdev != NULL); + + /* Assign name to bdev */ + g_base_bdev->name = strdup("UNIT_TEST_LVS_NAME/old_lvol"); + SPDK_CU_ASSERT_FATAL(g_base_bdev->name != NULL); + g_lvs_bdev->lvs = g_lvs; g_lvs_bdev->bdev = g_base_bdev; - uuid_generate_time(g_lvs->uuid); g_base_bdev->blocklen = 4096; TAILQ_INSERT_TAIL(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores); @@ -716,6 +909,7 @@ ut_lvol_resize(void) g_base_bdev->ctxt = g_lvol; + free(g_base_bdev->name); g_base_bdev->name = spdk_sprintf_alloc("%s", g_lvol->unique_id); SPDK_CU_ASSERT_FATAL(g_base_bdev->name != NULL); @@ -760,6 +954,13 @@ ut_lvs_unload(void) SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL); CU_ASSERT(g_bs_dev != NULL); + /* Create g_base_dev */ + g_lvs_bdev = calloc(1, sizeof(*g_lvs_bdev)); + SPDK_CU_ASSERT_FATAL(g_lvs_bdev != NULL); + g_base_bdev = calloc(1, sizeof(*g_base_bdev)); + SPDK_CU_ASSERT_FATAL(g_base_bdev != NULL); + g_lvs_bdev->bdev = g_base_bdev; + lvs = g_lvol_store; g_lvol_store = NULL; @@ -777,6 +978,9 @@ ut_lvs_unload(void) CU_ASSERT(g_lvserrno == 0); CU_ASSERT(g_lvol_store == NULL); CU_ASSERT(g_lvol != NULL); + + free(g_lvs_bdev); + free(g_base_bdev); } static void @@ -960,7 +1164,8 @@ int main(int argc, char **argv) CU_add_test(suite, "ut_lvol_op_comp", ut_lvol_op_comp) == NULL || CU_add_test(suite, "ut_lvol_read_write", ut_lvol_read_write) == NULL || CU_add_test(suite, "ut_vbdev_lvol_submit_request", ut_vbdev_lvol_submit_request) == NULL || - CU_add_test(suite, "lvol_examine", ut_lvol_examine) == NULL + CU_add_test(suite, "lvol_examine", ut_lvol_examine) == NULL || + CU_add_test(suite, "ut_lvol_rename", ut_lvol_rename) == NULL ) { CU_cleanup_registry(); return CU_get_error(); diff --git a/test/unit/lib/lvol/lvol.c/lvol_ut.c b/test/unit/lib/lvol/lvol.c/lvol_ut.c index d14b382f9..7f82b4506 100644 --- a/test/unit/lib/lvol/lvol.c/lvol_ut.c +++ b/test/unit/lib/lvol/lvol.c/lvol_ut.c @@ -1359,6 +1359,80 @@ lvol_names(void) spdk_free_thread(); } + +static void +lvol_rename(void) +{ + struct lvol_ut_bs_dev dev; + struct spdk_lvs_opts opts; + struct spdk_lvol_store *lvs; + struct spdk_lvol *lvol, *lvol2; + int rc = 0; + + init_dev(&dev); + + spdk_allocate_thread(_lvol_send_msg, NULL, NULL, NULL, NULL); + + spdk_lvs_opts_init(&opts); + strncpy(opts.name, "lvs", sizeof(opts.name)); + + g_lvserrno = -1; + g_lvol_store = NULL; + rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL); + CU_ASSERT(rc == 0); + CU_ASSERT(g_lvserrno == 0); + SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL); + lvs = g_lvol_store; + + /* Trying to create new lvol */ + g_lvserrno = -1; + rc = spdk_lvol_create(lvs, "lvol", 1, false, lvol_op_with_handle_complete, NULL); + CU_ASSERT(rc == 0); + CU_ASSERT(g_lvserrno == 0); + SPDK_CU_ASSERT_FATAL(g_lvol != NULL); + lvol = g_lvol; + + /* Trying to create second lvol with existing lvol name */ + g_lvserrno = -1; + g_lvol = NULL; + rc = spdk_lvol_create(lvs, "lvol", 1, false, lvol_op_with_handle_complete, NULL); + CU_ASSERT(rc == -EINVAL); + CU_ASSERT(g_lvserrno == -1); + SPDK_CU_ASSERT_FATAL(g_lvol == NULL); + + /* Trying to create second lvol with non existing name */ + g_lvserrno = -1; + rc = spdk_lvol_create(lvs, "lvol2", 1, false, lvol_op_with_handle_complete, NULL); + CU_ASSERT(rc == 0); + CU_ASSERT(g_lvserrno == 0); + SPDK_CU_ASSERT_FATAL(g_lvol != NULL); + lvol2 = g_lvol; + + /* Trying to rename lvol with not existing name */ + spdk_lvol_rename(lvol, "lvol_new", lvol_op_complete, NULL); + CU_ASSERT(g_lvolerrno == 0); + CU_ASSERT_STRING_EQUAL(lvol->name, "lvol_new"); + + /* Trying to rename lvol with other lvol name */ + spdk_lvol_rename(lvol2, "lvol_new", lvol_op_complete, NULL); + CU_ASSERT(g_lvolerrno == -EEXIST); + CU_ASSERT_STRING_NOT_EQUAL(lvol2->name, "lvol_new"); + + spdk_lvol_close(lvol, close_cb, NULL); + spdk_lvol_destroy(lvol, lvol_op_complete, NULL); + + spdk_lvol_close(lvol2, close_cb, NULL); + spdk_lvol_destroy(lvol2, lvol_op_complete, NULL); + + g_lvserrno = -1; + rc = spdk_lvs_destroy(lvs, lvol_store_op_complete, NULL); + CU_ASSERT(rc == 0); + CU_ASSERT(g_lvserrno == 0); + g_lvol_store = NULL; + + spdk_free_thread(); +} + static void lvol_refcnt(void) { struct lvol_ut_bs_dev dev; @@ -1507,7 +1581,8 @@ int main(int argc, char **argv) CU_add_test(suite, "lvol_open", lvol_open) == NULL || CU_add_test(suite, "lvol_refcnt", lvol_refcnt) == NULL || CU_add_test(suite, "lvol_names", lvol_names) == NULL || - CU_add_test(suite, "lvol_create_thin_provisioned", lvol_create_thin_provisioned) == NULL + CU_add_test(suite, "lvol_create_thin_provisioned", lvol_create_thin_provisioned) == NULL || + CU_add_test(suite, "lvol_rename", lvol_rename) == NULL ) { CU_cleanup_registry(); return CU_get_error(); diff --git a/test/vhost/lvol/lvol_test.sh b/test/vhost/lvol/lvol_test.sh index ea46b596e..637d8fd1d 100755 --- a/test/vhost/lvol/lvol_test.sh +++ b/test/vhost/lvol/lvol_test.sh @@ -180,8 +180,8 @@ for (( i=0; i<$vm_count; i++)); do vm="vm_$i" # Get all lvol bdevs associated with this VM number - bdevs=$(jq -r "map(select(.product_name==\"Logical Volume\") | - select(.name | contains(\"$vm\")) | .name) | join(\" \")" <<< "$bdev_info") + bdevs=$(jq -r "map(select(.aliases[] | contains(\"$vm\")) | \ + .aliases[]) | join(\" \")" <<< "$bdev_info") bdevs=($bdevs) setup_cmd="vm_setup --disk-type=$ctrl_type --force=$i"