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 <piotr.pelplinski@intel.com>
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: I99e6abded2ed3ae2742103f81fc7eb937ad1cab4
Reviewed-on: https://review.gerrithub.io/407402
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Tomasz Zawadzki 2018-07-23 09:57:02 -04:00 committed by Jim Harris
parent 848daf274b
commit 4219407a93
10 changed files with 249 additions and 114 deletions

View File

@ -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.
*

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

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

View File

@ -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

View File

@ -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();

View File

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