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) {