From 4219407a93dcf4d2d593fa23f1e1f74393405836 Mon Sep 17 00:00:00 2001 From: Tomasz Zawadzki Date: Mon, 23 Jul 2018 09:57:02 -0400 Subject: [PATCH] lvol: destroy_lvol_bdev implementation This patch fixes lvol delete behaviour. First, we look if there are any dependencies that disallow lvol deletion. If there are any (i.e. dependent clones) we fail. Otherwise we delete lvol and unregister associated bdev. destroy_bdev no longer deletes lvol. Fixes #345 Signed-off-by: Piotr Pelplinski Signed-off-by: Tomasz Zawadzki Change-Id: I99e6abded2ed3ae2742103f81fc7eb937ad1cab4 Reviewed-on: https://review.gerrithub.io/407402 Tested-by: SPDK CI Jenkins Chandler-Test-Pool: SPDK Automated Test System Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- include/spdk/lvol.h | 6 + include/spdk_internal/lvolstore.h | 1 - lib/bdev/lvol/vbdev_lvol.c | 184 +++++++++++------- lib/lvol/lvol.c | 37 ++-- test/iscsi_tgt/filesystem/filesystem.sh | 2 +- .../multiconnection/multiconnection.sh | 2 +- test/lvol/test_cases.py | 4 +- test/nvmf/host/perf.sh | 4 +- .../lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c | 116 ++++++++--- test/unit/lib/lvol/lvol.c/lvol_ut.c | 7 + 10 files changed, 249 insertions(+), 114 deletions(-) diff --git a/include/spdk/lvol.h b/include/spdk/lvol.h index d14a38496..279b4dfd3 100644 --- a/include/spdk/lvol.h +++ b/include/spdk/lvol.h @@ -205,6 +205,12 @@ void spdk_lvol_rename(struct spdk_lvol *lvol, const char *new_name, spdk_lvol_op_complete cb_fn, void *cb_arg); +/** + * \brief Returns if it is possible to delete an lvol (i.e. lvol is not a snapshot that have at least one clone). + * \param lvol Handle to lvol + */ +bool spdk_lvol_deletable(struct spdk_lvol *lvol); + /** * Close lvol and remove information about lvol from its lvolstore. * diff --git a/include/spdk_internal/lvolstore.h b/include/spdk_internal/lvolstore.h index cbe1d05c2..b46069783 100644 --- a/include/spdk_internal/lvolstore.h +++ b/include/spdk_internal/lvolstore.h @@ -105,7 +105,6 @@ struct spdk_lvol { char name[SPDK_LVOL_NAME_MAX]; struct spdk_uuid uuid; char uuid_str[SPDK_UUID_STRING_LEN]; - bool close_only; bool thin_provision; struct spdk_bdev *bdev; int ref_count; diff --git a/lib/bdev/lvol/vbdev_lvol.c b/lib/bdev/lvol/vbdev_lvol.c index b68986ef3..11db6d6a5 100644 --- a/lib/bdev/lvol/vbdev_lvol.c +++ b/lib/bdev/lvol/vbdev_lvol.c @@ -330,6 +330,41 @@ _vbdev_lvs_remove_cb(void *cb_arg, int lvserrno) free(req); } +static void +_vbdev_lvs_remove_lvol_cb(void *cb_arg, int lvolerrno) +{ + struct lvol_store_bdev *lvs_bdev = cb_arg; + struct spdk_lvol_store *lvs = lvs_bdev->lvs; + struct spdk_lvol *lvol; + + if (lvolerrno != 0) { + SPDK_DEBUGLOG(SPDK_LOG_VBDEV_LVOL, "Lvol removed with errno %d\n", lvolerrno); + } + + if (TAILQ_EMPTY(&lvs->lvols)) { + return; + } + + lvol = TAILQ_FIRST(&lvs->lvols); + while (lvol != NULL) { + if (spdk_lvol_deletable(lvol)) { + vbdev_lvol_destroy(lvol, _vbdev_lvs_remove_lvol_cb, lvs_bdev); + return; + } + lvol = TAILQ_NEXT(lvol, link); + } + + /* If no lvol is deletable, that means there is circular dependency. */ + SPDK_ERRLOG("Lvols left in lvs, but unable to delete.\n"); + assert(false); +} + +static void +_vbdev_lvs_unregister_empty_cb(void *cb_arg, int bdeverrno) +{ + SPDK_DEBUGLOG(SPDK_LOG_VBDEV_LVOL, "Lvol unregistered with errno %d\n", bdeverrno); +} + static void _vbdev_lvs_remove(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, void *cb_arg, bool destroy) @@ -383,9 +418,12 @@ _vbdev_lvs_remove(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, void lvs->destruct_req->cb_fn = _vbdev_lvs_remove_cb; lvs->destruct_req->cb_arg = lvs_bdev; lvs->destruct = destroy; - TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) { - lvol->close_only = !destroy; - spdk_bdev_unregister(lvol->bdev, NULL, NULL); + if (destroy) { + _vbdev_lvs_remove_lvol_cb(lvs_bdev, 0); + } else { + TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) { + spdk_bdev_unregister(lvol->bdev, _vbdev_lvs_unregister_empty_cb, NULL); + } } } } @@ -477,63 +515,24 @@ vbdev_get_lvol_store_by_name(const char *name) return NULL; } -static void -_vbdev_lvol_close_cb(void *cb_arg, int lvserrno) -{ - struct spdk_lvol_store *lvs; - - if (cb_arg == NULL) { - /* - * This close cb is from unload/destruct - so do not continue to check - * the lvol open counts. - */ - return; - } - - lvs = cb_arg; - - if (lvs->lvols_opened >= lvs->lvol_count) { - SPDK_INFOLOG(SPDK_LOG_VBDEV_LVOL, "Opening lvols finished\n"); - spdk_bdev_module_examine_done(&g_lvol_if); - } -} +struct vbdev_lvol_destroy_ctx { + struct spdk_lvol *lvol; + spdk_lvol_op_complete cb_fn; + void *cb_arg; +}; static void -_vbdev_lvol_destroy_cb(void *cb_arg, int lvserrno) +_vbdev_lvol_unregister_cb(void *ctx, int lvolerrno) { - struct spdk_bdev *bdev = cb_arg; + struct spdk_bdev *bdev = ctx; - if (lvserrno == -EBUSY) { - /* TODO: Handle reporting error to spdk_bdev_unregister */ - } - - SPDK_INFOLOG(SPDK_LOG_VBDEV_LVOL, "Lvol destroyed\n"); - - spdk_bdev_destruct_done(bdev, lvserrno); + spdk_bdev_destruct_done(bdev, lvolerrno); free(bdev->name); free(bdev); } -static void -_vbdev_lvol_destroy_after_close_cb(void *cb_arg, int lvserrno) -{ - struct spdk_lvol *lvol = cb_arg; - struct spdk_bdev *bdev = lvol->bdev; - - if (lvserrno != 0) { - SPDK_INFOLOG(SPDK_LOG_VBDEV_LVOL, "Could not close Lvol %s\n", lvol->unique_id); - spdk_bdev_destruct_done(bdev, lvserrno); - free(bdev->name); - free(bdev); - return; - } - - SPDK_INFOLOG(SPDK_LOG_VBDEV_LVOL, "Lvol %s closed, begin destroying\n", lvol->unique_id); - spdk_lvol_destroy(lvol, _vbdev_lvol_destroy_cb, bdev); -} - static int -vbdev_lvol_destruct(void *ctx) +vbdev_lvol_unregister(void *ctx) { struct spdk_lvol *lvol = ctx; char *alias; @@ -547,14 +546,7 @@ vbdev_lvol_destruct(void *ctx) } else { SPDK_ERRLOG("Cannot alloc memory for alias\n"); } - - if (lvol->close_only) { - free(lvol->bdev->name); - free(lvol->bdev); - spdk_lvol_close(lvol, _vbdev_lvol_close_cb, NULL); - } else { - spdk_lvol_close(lvol, _vbdev_lvol_destroy_after_close_cb, lvol); - } + spdk_lvol_close(lvol, _vbdev_lvol_unregister_cb, lvol->bdev); /* return 1 to indicate we have an operation that must finish asynchronously before the * lvol is closed @@ -562,14 +554,63 @@ vbdev_lvol_destruct(void *ctx) return 1; } +static void +_vbdev_lvol_destroy_cb(void *cb_arg, int bdeverrno) +{ + struct vbdev_lvol_destroy_ctx *ctx = cb_arg; + struct spdk_lvol *lvol = ctx->lvol; + + if (bdeverrno < 0) { + SPDK_INFOLOG(SPDK_LOG_VBDEV_LVOL, "Could not unregister bdev during lvol (%s) destroy\n", + lvol->unique_id); + ctx->cb_fn(ctx->cb_arg, bdeverrno); + free(ctx); + return; + } + + spdk_lvol_destroy(lvol, ctx->cb_fn, ctx->cb_arg); + free(ctx); +} + void vbdev_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg) { - /* - * TODO: This should call spdk_lvol_destroy() directly, and the bdev unregister path - * should be changed so that it does not destroy the lvol. - */ - spdk_bdev_unregister(lvol->bdev, cb_fn, cb_arg); + struct vbdev_lvol_destroy_ctx *ctx; + char *alias; + + assert(lvol != NULL); + assert(cb_fn != NULL); + + /* Check if it is possible to delete lvol */ + if (spdk_lvol_deletable(lvol) == false) { + /* throw an error */ + SPDK_ERRLOG("Cannot delete lvol\n"); + cb_fn(cb_arg, -EPERM); + return; + } + + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) { + cb_fn(cb_arg, -ENOMEM); + return; + } + + ctx->lvol = lvol; + ctx->cb_fn = cb_fn; + ctx->cb_arg = cb_arg; + + 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"); + cb_fn(cb_arg, -ENOMEM); + free(ctx); + return; + } + + spdk_bdev_unregister(lvol->bdev, _vbdev_lvol_destroy_cb, ctx); } static char * @@ -853,7 +894,7 @@ vbdev_lvol_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_ } static struct spdk_bdev_fn_table vbdev_lvol_fn_table = { - .destruct = vbdev_lvol_destruct, + .destruct = vbdev_lvol_unregister, .io_type_supported = vbdev_lvol_io_type_supported, .submit_request = vbdev_lvol_submit_request, .get_io_channel = vbdev_lvol_get_io_channel, @@ -1124,6 +1165,17 @@ _vbdev_lvs_examine_failed(void *cb_arg, int lvserrno) spdk_bdev_module_examine_done(&g_lvol_if); } +static void +_vbdev_lvol_examine_close_cb(void *cb_arg, int lvserrno) +{ + struct spdk_lvol_store *lvs = cb_arg; + + if (lvs->lvols_opened >= lvs->lvol_count) { + SPDK_INFOLOG(SPDK_LOG_VBDEV_LVOL, "Opening lvols finished\n"); + spdk_bdev_module_examine_done(&g_lvol_if); + } +} + static void _vbdev_lvs_examine_finish(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno) { @@ -1144,7 +1196,7 @@ _vbdev_lvs_examine_finish(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno) SPDK_ERRLOG("Cannot create bdev for lvol %s\n", lvol->unique_id); TAILQ_REMOVE(&lvs->lvols, lvol, link); lvs->lvol_count--; - spdk_lvol_close(lvol, _vbdev_lvol_close_cb, lvs); + spdk_lvol_close(lvol, _vbdev_lvol_examine_close_cb, lvs); SPDK_INFOLOG(SPDK_LOG_VBDEV_LVOL, "Opening lvol %s failed\n", lvol->unique_id); return; } diff --git a/lib/lvol/lvol.c b/lib/lvol/lvol.c index a0857ab1d..90e848aa8 100644 --- a/lib/lvol/lvol.c +++ b/lib/lvol/lvol.c @@ -84,6 +84,13 @@ _spdk_lvs_free(struct spdk_lvol_store *lvs) free(lvs); } +static void +_spdk_lvol_free(struct spdk_lvol *lvol) +{ + free(lvol->unique_id); + free(lvol); +} + static void _spdk_lvol_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno) { @@ -192,7 +199,6 @@ _spdk_load_next_lvol(void *cb_arg, struct spdk_blob *blob, int lvolerrno) lvol->blob = blob; lvol->blob_id = blob_id; lvol->lvol_store = lvs; - lvol->close_only = false; rc = spdk_blob_get_xattr_value(blob, "uuid", (const void **)&attr, &value_len); if (rc != 0 || value_len != SPDK_UUID_STRING_LEN || attr[SPDK_UUID_STRING_LEN - 1] != '\0' || @@ -218,8 +224,7 @@ _spdk_load_next_lvol(void *cb_arg, struct spdk_blob *blob, int lvolerrno) rc = spdk_blob_get_xattr_value(blob, "name", (const void **)&attr, &value_len); if (rc != 0 || value_len > SPDK_LVOL_NAME_MAX) { SPDK_ERRLOG("Cannot assign lvol name\n"); - free(lvol->unique_id); - free(lvol); + _spdk_lvol_free(lvol); req->lvserrno = -EINVAL; goto invalid; } @@ -765,8 +770,7 @@ spdk_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) { TAILQ_REMOVE(&lvs->lvols, lvol, link); - free(lvol->unique_id); - free(lvol); + _spdk_lvol_free(lvol); } lvs_req = calloc(1, sizeof(*lvs_req)); @@ -877,8 +881,7 @@ _spdk_lvol_close_blob_cb(void *cb_arg, int lvolerrno) if (lvolerrno < 0) { SPDK_ERRLOG("Could not close blob on lvol\n"); - free(lvol->unique_id); - free(lvol); + _spdk_lvol_free(lvol); goto end; } @@ -905,6 +908,15 @@ end: free(req); } +bool +spdk_lvol_deletable(struct spdk_lvol *lvol) +{ + size_t count; + + spdk_blob_get_clones(lvol->lvol_store->blobstore, lvol->blob_id, NULL, &count); + return (count == 0); +} + static void _spdk_lvol_delete_blob_cb(void *cb_arg, int lvolerrno) { @@ -913,8 +925,6 @@ _spdk_lvol_delete_blob_cb(void *cb_arg, int lvolerrno) if (lvolerrno < 0) { SPDK_ERRLOG("Could not delete blob on lvol\n"); - free(lvol->unique_id); - free(lvol); goto end; } @@ -928,10 +938,8 @@ _spdk_lvol_delete_blob_cb(void *cb_arg, int lvolerrno) SPDK_INFOLOG(SPDK_LOG_LVOL, "Lvol %s deleted\n", lvol->unique_id); - free(lvol->unique_id); - free(lvol); - end: + _spdk_lvol_free(lvol); req->cb_fn(req->cb_arg, lvolerrno); free(req); } @@ -945,8 +953,7 @@ _spdk_lvol_destroy_cb(void *cb_arg, int lvolerrno) if (lvolerrno < 0) { SPDK_ERRLOG("Could not close blob on lvol\n"); - free(lvol->unique_id); - free(lvol); + _spdk_lvol_free(lvol); req->cb_fn(req->cb_arg, lvolerrno); free(req); return; @@ -1096,10 +1103,8 @@ spdk_lvol_create(struct spdk_lvol_store *lvs, const char *name, uint64_t sz, SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n"); return -ENOMEM; } - lvol->lvol_store = lvs; num_clusters = divide_round_up(sz, spdk_bs_get_cluster_size(bs)); - lvol->close_only = false; lvol->thin_provision = thin_provision; snprintf(lvol->name, sizeof(lvol->name), "%s", name); TAILQ_INSERT_TAIL(&lvol->lvol_store->pending_lvols, lvol, link); diff --git a/test/iscsi_tgt/filesystem/filesystem.sh b/test/iscsi_tgt/filesystem/filesystem.sh index 1ec388899..98b2e5f7e 100755 --- a/test/iscsi_tgt/filesystem/filesystem.sh +++ b/test/iscsi_tgt/filesystem/filesystem.sh @@ -13,7 +13,7 @@ rpc_py="python $rootdir/scripts/rpc.py" function remove_backends() { echo "INFO: Removing lvol bdev" - $rpc_py delete_bdev "lvs_0/lbd_0" + $rpc_py destroy_lvol_bdev "lvs_0/lbd_0" echo "INFO: Removing lvol stores" $rpc_py destroy_lvol_store -l lvs_0 diff --git a/test/iscsi_tgt/multiconnection/multiconnection.sh b/test/iscsi_tgt/multiconnection/multiconnection.sh index 08fd0460c..f624acd8f 100755 --- a/test/iscsi_tgt/multiconnection/multiconnection.sh +++ b/test/iscsi_tgt/multiconnection/multiconnection.sh @@ -16,7 +16,7 @@ function remove_backends() echo "INFO: Removing lvol bdevs" for i in `seq 1 $CONNECTION_NUMBER`; do lun="lvs0/lbd_$i" - $rpc_py delete_bdev $lun + $rpc_py destroy_lvol_bdev $lun echo -e "\tINFO: lvol bdev $lun removed" done sleep 1 diff --git a/test/lvol/test_cases.py b/test/lvol/test_cases.py index 778127d32..e299a4e13 100644 --- a/test/lvol/test_cases.py +++ b/test/lvol/test_cases.py @@ -1865,7 +1865,7 @@ class TestCases(object): fail_count += 1 # Delete snapshot - fail_count += self.c.delete_bdev(snapshot_bdev['name']) + fail_count += self.c.destroy_lvol_bdev(snapshot_bdev['name']) # Check data consistency fail_count += self.c.start_nbd_disk(lvol_clone['name'], nbd_name) @@ -1882,7 +1882,7 @@ class TestCases(object): self.c.stop_nbd_disk(nbd_name) # Destroy lvol bdev - fail_count += self.c.delete_bdev(lvol_bdev['name']) + fail_count += self.c.destroy_lvol_bdev(lvol_bdev['name']) # Destroy lvol store fail_count += self.c.destroy_lvol_store(uuid_store) diff --git a/test/nvmf/host/perf.sh b/test/nvmf/host/perf.sh index c9234c913..45b3f6409 100755 --- a/test/nvmf/host/perf.sh +++ b/test/nvmf/host/perf.sh @@ -76,9 +76,9 @@ if [ $RUN_NIGHTLY -eq 1 ]; then # Delete subsystems, lvol_bdev and destroy lvol_store. $rpc_py delete_nvmf_subsystem nqn.2016-06.io.spdk:cnode1 $rpc_py delete_nvmf_subsystem nqn.2016-06.io.spdk:cnode2 - $rpc_py delete_bdev "$lb_nested_guid" + $rpc_py destroy_lvol_bdev "$lb_nested_guid" $rpc_py destroy_lvol_store -l lvs_n_0 - $rpc_py delete_bdev "$lb_guid" + $rpc_py destroy_lvol_bdev "$lb_guid" $rpc_py destroy_lvol_store -l lvs_0 $rpc_py delete_bdev "Nvme0n1" fi 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 6c637e368..160512cfa 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 @@ -59,6 +59,7 @@ bool lvol_already_opened = false; bool g_examine_done = false; bool g_bdev_alias_already_exists = false; bool g_lvs_with_name_already_exists = false; +bool g_lvol_deletable = true; int spdk_bdev_alias_add(struct spdk_bdev *bdev, const char *alias) @@ -245,8 +246,13 @@ spdk_bs_bdev_claim(struct spdk_bs_dev *bs_dev, struct spdk_bdev_module *module) void spdk_bdev_unregister(struct spdk_bdev *vbdev, spdk_bdev_unregister_cb cb_fn, void *cb_arg) { + int rc; + SPDK_CU_ASSERT_FATAL(vbdev != NULL); - vbdev->fn_table->destruct(vbdev->ctxt); + rc = vbdev->fn_table->destruct(vbdev->ctxt); + + SPDK_CU_ASSERT_FATAL(cb_fn != NULL); + cb_fn(cb_arg, rc); } void @@ -366,8 +372,8 @@ spdk_lvs_destroy(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, g_lvol_store = NULL; lvs->bs_dev->destroy(lvs->bs_dev); - free(lvs); + if (cb_fn != NULL) { cb_fn(cb_arg, 0); } @@ -419,6 +425,9 @@ spdk_lvol_close(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_ar } } + SPDK_CU_ASSERT_FATAL(cb_fn != NULL); + cb_fn(cb_arg, 0); + destruct_req = lvol->lvol_store->destruct_req; if (destruct_req && all_lvols_closed == true) { if (!lvol->lvol_store->destruct) { @@ -426,8 +435,12 @@ spdk_lvol_close(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_ar free(destruct_req); } } +} - cb_fn(cb_arg, 0); +bool +spdk_lvol_deletable(struct spdk_lvol *lvol) +{ + return g_lvol_deletable; } void @@ -441,11 +454,12 @@ spdk_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_ TAILQ_REMOVE(&lvol->lvol_store->lvols, lvol, link); + SPDK_CU_ASSERT_FATAL(cb_fn != NULL); + cb_fn(cb_arg, 0); + destruct_req = lvol->lvol_store->destruct_req; if (destruct_req && TAILQ_EMPTY(&lvol->lvol_store->lvols)) { - if (!lvol->lvol_store->destruct) { - spdk_lvs_unload(lvol->lvol_store, destruct_req->cb_fn, destruct_req->cb_arg); - } else { + if (lvol->lvol_store->destruct) { spdk_lvs_destroy(lvol->lvol_store, destruct_req->cb_fn, destruct_req->cb_arg); free(destruct_req); } @@ -453,8 +467,6 @@ spdk_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_ g_lvol = NULL; free(lvol->unique_id); free(lvol); - - cb_fn(cb_arg, 0); } void @@ -739,8 +751,8 @@ ut_lvol_init(void) CU_ASSERT(g_lvol != NULL); CU_ASSERT(g_lvolerrno == 0); - /* Successful lvol destruct */ - vbdev_lvol_destruct(g_lvol); + /* Successful lvol destroy */ + vbdev_lvol_destroy(g_lvol, lvol_store_op_complete, NULL); CU_ASSERT(g_lvol == NULL); /* Destroy lvol store */ @@ -780,13 +792,13 @@ ut_lvol_snapshot(void) CU_ASSERT(g_lvol != NULL); CU_ASSERT(g_lvolerrno == 0); - /* Successful lvol destruct */ - vbdev_lvol_destruct(g_lvol); + /* Successful lvol destroy */ + vbdev_lvol_destroy(g_lvol, lvol_store_op_complete, NULL); CU_ASSERT(g_lvol == NULL); - /* Successful snap destruct */ + /* Successful snap destroy */ g_lvol = lvol; - vbdev_lvol_destruct(g_lvol); + vbdev_lvol_destroy(g_lvol, lvol_store_op_complete, NULL); CU_ASSERT(g_lvol == NULL); /* Destroy lvol store */ @@ -839,19 +851,19 @@ ut_lvol_clone(void) clone = g_lvol; - /* Successful lvol destruct */ + /* Successful lvol destroy */ g_lvol = lvol; - vbdev_lvol_destruct(g_lvol); + vbdev_lvol_destroy(g_lvol, lvol_store_op_complete, NULL); CU_ASSERT(g_lvol == NULL); - /* Successful clone destruct */ + /* Successful clone destroy */ g_lvol = clone; - vbdev_lvol_destruct(g_lvol); + vbdev_lvol_destroy(g_lvol, lvol_store_op_complete, NULL); CU_ASSERT(g_lvol == NULL); - /* Successful snap destruct */ + /* Successful lvol destroy */ g_lvol = snap; - vbdev_lvol_destruct(g_lvol); + vbdev_lvol_destroy(g_lvol, lvol_store_op_complete, NULL); CU_ASSERT(g_lvol == NULL); /* Destroy lvol store */ @@ -1002,11 +1014,11 @@ ut_lvol_rename(void) SPDK_CU_ASSERT_FATAL(g_lvolerrno == 0); CU_ASSERT_STRING_EQUAL(lvol->name, "new_lvol_name"); - /* Successful lvols destruct */ - vbdev_lvol_destruct(lvol); + /* Successful lvols destroy */ + vbdev_lvol_destroy(lvol, lvol_store_op_complete, NULL); CU_ASSERT(g_lvol == NULL); - vbdev_lvol_destruct(lvol2); + vbdev_lvol_destroy(lvol2, lvol_store_op_complete, NULL); CU_ASSERT(g_lvol == NULL); /* Destroy lvol store */ @@ -1015,6 +1027,59 @@ ut_lvol_rename(void) CU_ASSERT(g_lvol_store == NULL); } +static void +ut_lvol_destroy(void) +{ + struct spdk_lvol_store *lvs; + struct spdk_lvol *lvol; + struct spdk_lvol *lvol2; + int sz = 10; + int rc; + + /* Lvol store is succesfully created */ + rc = vbdev_lvs_create(&g_bdev, "lvs", 0, lvol_store_op_with_handle_complete, NULL); + CU_ASSERT(rc == 0); + CU_ASSERT(g_lvserrno == 0); + SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL); + CU_ASSERT(g_lvol_store->bs_dev != NULL); + lvs = g_lvol_store; + + /* Successful lvols create */ + g_lvolerrno = -1; + rc = vbdev_lvol_create(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(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; + + /* Unsuccessful lvols destroy */ + g_lvol_deletable = false; + vbdev_lvol_destroy(lvol, lvol_store_op_complete, NULL); + CU_ASSERT(g_lvol != NULL); + CU_ASSERT(g_lvserrno == -EPERM); + + g_lvol_deletable = true; + /* Successful lvols destroy */ + vbdev_lvol_destroy(lvol, lvol_store_op_complete, NULL); + CU_ASSERT(g_lvol == NULL); + CU_ASSERT(g_lvolerrno == 0); + + /* Hot remove lvol bdev */ + vbdev_lvol_unregister(lvol2); + + /* Unload lvol store */ + vbdev_lvs_unload(lvs, lvol_store_op_complete, NULL); + CU_ASSERT(g_lvserrno == 0); + CU_ASSERT(g_lvol_store == NULL); +} + static void ut_lvol_resize(void) { @@ -1049,8 +1114,8 @@ ut_lvol_resize(void) vbdev_lvol_resize(NULL, 20, vbdev_lvol_resize_complete, NULL); CU_ASSERT(g_lvolerrno != 0); - /* Successful lvol destruct */ - vbdev_lvol_destruct(lvol); + /* Successful lvol destroy */ + vbdev_lvol_destroy(lvol, lvol_store_op_complete, NULL); CU_ASSERT(g_lvol == NULL); /* Destroy lvol store */ @@ -1339,6 +1404,7 @@ int main(int argc, char **argv) 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, "ut_lvol_rename", ut_lvol_rename) == NULL || + CU_add_test(suite, "ut_lvol_destroy", ut_lvol_destroy) == NULL || CU_add_test(suite, "ut_lvs_rename", ut_lvs_rename) == NULL ) { CU_cleanup_registry(); diff --git a/test/unit/lib/lvol/lvol.c/lvol_ut.c b/test/unit/lib/lvol/lvol.c/lvol_ut.c index d22c95a42..37ec53961 100644 --- a/test/unit/lib/lvol/lvol.c/lvol_ut.c +++ b/test/unit/lib/lvol/lvol.c/lvol_ut.c @@ -231,6 +231,13 @@ spdk_blob_get_xattr_value(struct spdk_blob *blob, const char *name, return -ENOENT; } +int +spdk_blob_get_clones(struct spdk_blob_store *bs, spdk_blob_id blobid, spdk_blob_id *ids, + size_t *count) +{ + return 0; +} + uint64_t spdk_bs_get_page_size(struct spdk_blob_store *bs) {