2022-06-03 19:15:11 +00:00
|
|
|
/* SPDX-License-Identifier: BSD-3-Clause
|
2022-11-01 20:26:26 +00:00
|
|
|
* Copyright (C) 2017 Intel Corporation.
|
2017-09-14 14:53:36 +00:00
|
|
|
* All rights reserved.
|
2022-10-12 20:01:10 +00:00
|
|
|
* Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
2017-09-14 14:53:36 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "spdk_cunit.h"
|
|
|
|
#include "spdk/blob.h"
|
2017-10-18 22:01:52 +00:00
|
|
|
#include "spdk/util.h"
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2021-05-03 20:35:59 +00:00
|
|
|
#include "spdk/bdev_module.h"
|
2021-06-05 12:50:15 +00:00
|
|
|
#include "thread/thread_internal.h"
|
2021-05-03 20:35:59 +00:00
|
|
|
|
2018-08-15 21:02:38 +00:00
|
|
|
#include "common/lib/ut_multithread.c"
|
2018-02-13 16:03:52 +00:00
|
|
|
#include "lvol/lvol.c"
|
2017-09-14 14:53:36 +00:00
|
|
|
|
|
|
|
#define DEV_BUFFER_SIZE (64 * 1024 * 1024)
|
|
|
|
#define DEV_BUFFER_BLOCKLEN (4096)
|
|
|
|
#define DEV_BUFFER_BLOCKCNT (DEV_BUFFER_SIZE / DEV_BUFFER_BLOCKLEN)
|
2017-09-27 11:18:50 +00:00
|
|
|
#define BS_CLUSTER_SIZE (1024 * 1024)
|
|
|
|
#define BS_FREE_CLUSTERS (DEV_BUFFER_SIZE / BS_CLUSTER_SIZE)
|
2017-10-03 10:54:06 +00:00
|
|
|
#define BS_PAGE_SIZE (4096)
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2017-09-29 07:46:50 +00:00
|
|
|
#define SPDK_BLOB_OPTS_CLUSTER_SZ (1024 * 1024)
|
|
|
|
#define SPDK_BLOB_OPTS_NUM_MD_PAGES UINT32_MAX
|
|
|
|
#define SPDK_BLOB_OPTS_MAX_MD_OPS 32
|
|
|
|
#define SPDK_BLOB_OPTS_MAX_CHANNEL_OPS 512
|
|
|
|
|
2018-01-26 13:33:27 +00:00
|
|
|
#define SPDK_BLOB_THIN_PROV (1ULL << 0)
|
|
|
|
|
2023-01-17 16:12:48 +00:00
|
|
|
|
2022-10-12 20:01:10 +00:00
|
|
|
DEFINE_STUB(spdk_bdev_get_name, const char *, (const struct spdk_bdev *bdev), NULL);
|
|
|
|
DEFINE_STUB(spdk_bdev_get_by_name, struct spdk_bdev *, (const char *name), NULL);
|
|
|
|
DEFINE_STUB(spdk_bdev_create_bs_dev_ro, int,
|
|
|
|
(const char *bdev_name, spdk_bdev_event_cb_t event_cb, void *event_ctx,
|
|
|
|
struct spdk_bs_dev **bs_dev), -ENOTSUP);
|
2023-01-17 16:12:48 +00:00
|
|
|
DEFINE_STUB(spdk_blob_is_esnap_clone, bool, (const struct spdk_blob *blob), false);
|
2023-04-28 19:11:50 +00:00
|
|
|
DEFINE_STUB(spdk_blob_is_degraded, bool, (const struct spdk_blob *blob), false);
|
2022-10-12 20:01:10 +00:00
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
const char *uuid = "828d9766-ae50-11e7-bd8d-001e67edf350";
|
2017-10-19 15:30:32 +00:00
|
|
|
|
|
|
|
struct spdk_blob {
|
2017-10-18 22:01:52 +00:00
|
|
|
spdk_blob_id id;
|
|
|
|
uint32_t ref;
|
2018-02-22 12:29:49 +00:00
|
|
|
struct spdk_blob_store *bs;
|
2017-10-18 22:01:52 +00:00
|
|
|
int close_status;
|
|
|
|
int open_status;
|
2018-03-02 19:49:36 +00:00
|
|
|
int load_status;
|
2017-10-18 22:01:52 +00:00
|
|
|
TAILQ_ENTRY(spdk_blob) link;
|
2018-03-02 00:59:50 +00:00
|
|
|
char uuid[SPDK_UUID_STRING_LEN];
|
2017-08-29 17:37:41 +00:00
|
|
|
char name[SPDK_LVS_NAME_MAX];
|
2018-01-26 13:33:27 +00:00
|
|
|
bool thin_provisioned;
|
2023-04-13 16:41:00 +00:00
|
|
|
struct spdk_bs_dev *back_bs_dev;
|
2017-10-19 15:30:32 +00:00
|
|
|
};
|
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
int g_lvserrno;
|
2017-10-19 15:30:32 +00:00
|
|
|
int g_close_super_status;
|
2017-09-14 14:53:36 +00:00
|
|
|
int g_resize_rc;
|
2018-04-23 12:30:16 +00:00
|
|
|
int g_inflate_rc;
|
2019-03-01 13:48:13 +00:00
|
|
|
int g_remove_rc;
|
2018-01-10 10:03:39 +00:00
|
|
|
bool g_lvs_rename_blob_open_error = false;
|
2023-02-15 16:57:44 +00:00
|
|
|
bool g_blob_read_only = false;
|
2017-09-14 14:53:36 +00:00
|
|
|
struct spdk_lvol_store *g_lvol_store;
|
|
|
|
struct spdk_lvol *g_lvol;
|
2017-10-24 02:51:49 +00:00
|
|
|
spdk_blob_id g_blobid = 1;
|
2018-04-23 12:30:16 +00:00
|
|
|
struct spdk_io_channel *g_io_channel;
|
2022-10-12 20:01:10 +00:00
|
|
|
struct lvol_ut_bs_dev g_esnap_dev;
|
2017-09-29 16:31:45 +00:00
|
|
|
|
|
|
|
struct spdk_blob_store {
|
2017-10-18 22:01:52 +00:00
|
|
|
struct spdk_bs_opts bs_opts;
|
|
|
|
spdk_blob_id super_blobid;
|
|
|
|
TAILQ_HEAD(, spdk_blob) blobs;
|
|
|
|
int get_super_status;
|
2022-10-12 20:01:10 +00:00
|
|
|
spdk_bs_esnap_dev_create esnap_bs_dev_create;
|
2017-09-29 16:31:45 +00:00
|
|
|
};
|
2017-10-19 15:30:32 +00:00
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
struct lvol_ut_bs_dev {
|
|
|
|
struct spdk_bs_dev bs_dev;
|
|
|
|
int init_status;
|
|
|
|
int load_status;
|
|
|
|
struct spdk_blob_store *bs;
|
|
|
|
};
|
2017-10-19 15:30:32 +00:00
|
|
|
|
2022-10-12 20:01:10 +00:00
|
|
|
struct ut_cb_res {
|
|
|
|
void *data;
|
|
|
|
int err;
|
|
|
|
};
|
|
|
|
|
2022-06-22 21:35:04 +00:00
|
|
|
void
|
|
|
|
spdk_bs_inflate_blob(struct spdk_blob_store *bs, struct spdk_io_channel *channel,
|
|
|
|
spdk_blob_id blobid, spdk_blob_op_complete cb_fn, void *cb_arg)
|
2018-04-23 12:30:16 +00:00
|
|
|
{
|
|
|
|
cb_fn(cb_arg, g_inflate_rc);
|
|
|
|
}
|
|
|
|
|
2022-06-22 21:35:04 +00:00
|
|
|
void
|
|
|
|
spdk_bs_blob_decouple_parent(struct spdk_blob_store *bs, struct spdk_io_channel *channel,
|
|
|
|
spdk_blob_id blobid, spdk_blob_op_complete cb_fn, void *cb_arg)
|
2018-05-10 10:01:29 +00:00
|
|
|
{
|
|
|
|
cb_fn(cb_arg, g_inflate_rc);
|
|
|
|
}
|
|
|
|
|
2017-10-19 15:30:32 +00:00
|
|
|
void
|
2017-12-12 20:53:10 +00:00
|
|
|
spdk_bs_iter_next(struct spdk_blob_store *bs, struct spdk_blob *b,
|
2017-12-08 21:09:12 +00:00
|
|
|
spdk_blob_op_with_handle_complete cb_fn, void *cb_arg)
|
2017-10-19 15:30:32 +00:00
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct spdk_blob *next;
|
|
|
|
int _errno = 0;
|
|
|
|
|
2017-12-12 20:53:10 +00:00
|
|
|
next = TAILQ_NEXT(b, link);
|
2017-10-18 22:01:52 +00:00
|
|
|
if (next == NULL) {
|
|
|
|
_errno = -ENOENT;
|
2017-10-27 13:09:53 +00:00
|
|
|
} else if (next->load_status != 0) {
|
|
|
|
_errno = next->load_status;
|
2017-10-18 22:01:52 +00:00
|
|
|
}
|
2017-10-19 15:30:32 +00:00
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
cb_fn(cb_arg, next, _errno);
|
2017-10-19 15:30:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-12-08 21:09:12 +00:00
|
|
|
spdk_bs_iter_first(struct spdk_blob_store *bs,
|
|
|
|
spdk_blob_op_with_handle_complete cb_fn, void *cb_arg)
|
2017-10-19 15:30:32 +00:00
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct spdk_blob *first;
|
|
|
|
int _errno = 0;
|
|
|
|
|
|
|
|
first = TAILQ_FIRST(&bs->blobs);
|
|
|
|
if (first == NULL) {
|
|
|
|
_errno = -ENOENT;
|
2017-10-27 13:09:53 +00:00
|
|
|
} else if (first->load_status != 0) {
|
|
|
|
_errno = first->load_status;
|
2017-10-18 22:01:52 +00:00
|
|
|
}
|
2017-10-19 15:30:32 +00:00
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
cb_fn(cb_arg, first, _errno);
|
2017-10-19 15:30:32 +00:00
|
|
|
}
|
|
|
|
|
2022-06-22 21:35:04 +00:00
|
|
|
uint64_t
|
|
|
|
spdk_blob_get_num_clusters(struct spdk_blob *blob)
|
2017-10-19 15:30:32 +00:00
|
|
|
{
|
2023-02-15 16:57:44 +00:00
|
|
|
return 1;
|
2017-10-19 15:30:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
spdk_bs_get_super(struct spdk_blob_store *bs,
|
|
|
|
spdk_blob_op_with_id_complete cb_fn, void *cb_arg)
|
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
if (bs->get_super_status != 0) {
|
|
|
|
cb_fn(cb_arg, 0, bs->get_super_status);
|
|
|
|
} else {
|
|
|
|
cb_fn(cb_arg, bs->super_blobid, 0);
|
|
|
|
}
|
2017-10-19 15:30:32 +00:00
|
|
|
}
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2017-09-22 12:13:56 +00:00
|
|
|
void
|
|
|
|
spdk_bs_set_super(struct spdk_blob_store *bs, spdk_blob_id blobid,
|
|
|
|
spdk_bs_op_complete cb_fn, void *cb_arg)
|
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
bs->super_blobid = blobid;
|
2017-09-22 12:13:56 +00:00
|
|
|
cb_fn(cb_arg, 0);
|
|
|
|
}
|
|
|
|
|
2017-10-19 15:30:32 +00:00
|
|
|
void
|
|
|
|
spdk_bs_load(struct spdk_bs_dev *dev, struct spdk_bs_opts *opts,
|
|
|
|
spdk_bs_op_with_handle_complete cb_fn, void *cb_arg)
|
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct lvol_ut_bs_dev *ut_dev = SPDK_CONTAINEROF(dev, struct lvol_ut_bs_dev, bs_dev);
|
|
|
|
struct spdk_blob_store *bs = NULL;
|
|
|
|
|
|
|
|
if (ut_dev->load_status == 0) {
|
|
|
|
bs = ut_dev->bs;
|
2017-10-19 15:30:32 +00:00
|
|
|
}
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
cb_fn(cb_arg, bs, ut_dev->load_status);
|
2017-10-19 15:30:32 +00:00
|
|
|
}
|
|
|
|
|
2021-10-05 03:28:38 +00:00
|
|
|
void
|
|
|
|
spdk_bs_grow(struct spdk_bs_dev *dev, struct spdk_bs_opts *o,
|
|
|
|
spdk_bs_op_with_handle_complete cb_fn, void *cb_arg)
|
|
|
|
{
|
|
|
|
cb_fn(cb_arg, NULL, -EINVAL);
|
|
|
|
}
|
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
struct spdk_io_channel *spdk_bs_alloc_io_channel(struct spdk_blob_store *bs)
|
|
|
|
{
|
2018-04-23 12:30:16 +00:00
|
|
|
if (g_io_channel == NULL) {
|
|
|
|
g_io_channel = calloc(1, sizeof(struct spdk_io_channel));
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_io_channel != NULL);
|
|
|
|
}
|
|
|
|
g_io_channel->ref++;
|
|
|
|
return g_io_channel;
|
|
|
|
}
|
|
|
|
|
2022-06-22 21:35:04 +00:00
|
|
|
void
|
|
|
|
spdk_bs_free_io_channel(struct spdk_io_channel *channel)
|
2018-04-23 12:30:16 +00:00
|
|
|
{
|
|
|
|
g_io_channel->ref--;
|
|
|
|
if (g_io_channel->ref == 0) {
|
|
|
|
free(g_io_channel);
|
|
|
|
g_io_channel = NULL;
|
|
|
|
}
|
|
|
|
return;
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2017-12-08 16:38:33 +00:00
|
|
|
spdk_blob_set_xattr(struct spdk_blob *blob, const char *name, const void *value,
|
|
|
|
uint16_t value_len)
|
2017-09-14 14:53:36 +00:00
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
if (!strcmp(name, "uuid")) {
|
2018-03-02 00:59:50 +00:00
|
|
|
CU_ASSERT(value_len == SPDK_UUID_STRING_LEN);
|
|
|
|
memcpy(blob->uuid, value, SPDK_UUID_STRING_LEN);
|
2017-08-29 17:37:41 +00:00
|
|
|
} else if (!strcmp(name, "name")) {
|
|
|
|
CU_ASSERT(value_len <= SPDK_LVS_NAME_MAX);
|
|
|
|
memcpy(blob->name, value, value_len);
|
2017-10-18 22:01:52 +00:00
|
|
|
}
|
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-10-19 15:30:32 +00:00
|
|
|
int
|
2017-12-08 16:38:33 +00:00
|
|
|
spdk_blob_get_xattr_value(struct spdk_blob *blob, const char *name,
|
|
|
|
const void **value, size_t *value_len)
|
2017-10-19 15:30:32 +00:00
|
|
|
{
|
2018-03-02 00:59:50 +00:00
|
|
|
if (!strcmp(name, "uuid") && strnlen(blob->uuid, SPDK_UUID_STRING_LEN) != 0) {
|
|
|
|
CU_ASSERT(strnlen(blob->uuid, SPDK_UUID_STRING_LEN) == (SPDK_UUID_STRING_LEN - 1));
|
2017-10-18 22:01:52 +00:00
|
|
|
*value = blob->uuid;
|
2018-03-02 00:59:50 +00:00
|
|
|
*value_len = SPDK_UUID_STRING_LEN;
|
2017-10-18 22:01:52 +00:00
|
|
|
return 0;
|
2017-08-29 17:37:41 +00:00
|
|
|
} else if (!strcmp(name, "name") && strnlen(blob->name, SPDK_LVS_NAME_MAX) != 0) {
|
|
|
|
*value = blob->name;
|
|
|
|
*value_len = strnlen(blob->name, SPDK_LVS_NAME_MAX) + 1;
|
|
|
|
return 0;
|
2017-10-18 22:01:52 +00:00
|
|
|
}
|
2017-10-19 15:30:32 +00:00
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
return -ENOENT;
|
2017-10-19 15:30:32 +00:00
|
|
|
}
|
|
|
|
|
2023-04-13 16:41:00 +00:00
|
|
|
void
|
|
|
|
spdk_blob_set_esnap_bs_dev(struct spdk_blob *blob, struct spdk_bs_dev *back_bs_dev,
|
|
|
|
spdk_blob_op_complete cb_fn, void *cb_arg)
|
|
|
|
{
|
|
|
|
blob->back_bs_dev = back_bs_dev;
|
|
|
|
cb_fn(cb_arg, 0);
|
|
|
|
}
|
|
|
|
|
2022-06-22 21:35:04 +00:00
|
|
|
bool
|
|
|
|
spdk_blob_is_thin_provisioned(struct spdk_blob *blob)
|
2020-05-15 02:17:57 +00:00
|
|
|
{
|
|
|
|
return blob->thin_provisioned;
|
|
|
|
}
|
|
|
|
|
2023-02-15 16:57:44 +00:00
|
|
|
void
|
|
|
|
spdk_bs_blob_shallow_copy(struct spdk_blob_store *bs, struct spdk_io_channel *channel,
|
|
|
|
spdk_blob_id blobid, struct spdk_bs_dev *ext_dev,
|
|
|
|
spdk_blob_op_complete cb_fn, void *cb_arg)
|
|
|
|
{
|
|
|
|
cb_fn(cb_arg, 0);
|
|
|
|
}
|
|
|
|
|
2020-03-26 09:58:59 +00:00
|
|
|
DEFINE_STUB(spdk_bs_get_page_size, uint64_t, (struct spdk_blob_store *bs), BS_PAGE_SIZE);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2018-01-26 10:00:36 +00:00
|
|
|
int
|
|
|
|
spdk_bdev_notify_blockcnt_change(struct spdk_bdev *bdev, uint64_t size)
|
|
|
|
{
|
|
|
|
bdev->blockcnt = size;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-10-12 20:01:10 +00:00
|
|
|
const struct spdk_uuid *
|
|
|
|
spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
|
|
|
|
{
|
|
|
|
return &bdev->uuid;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
spdk_bdev_get_num_blocks(const struct spdk_bdev *bdev)
|
|
|
|
{
|
|
|
|
return bdev->blockcnt;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
spdk_bdev_get_block_size(const struct spdk_bdev *bdev)
|
|
|
|
{
|
|
|
|
return bdev->blocklen;
|
|
|
|
}
|
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
static void
|
2017-10-18 22:01:52 +00:00
|
|
|
init_dev(struct lvol_ut_bs_dev *dev)
|
2017-09-14 14:53:36 +00:00
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
memset(dev, 0, sizeof(*dev));
|
|
|
|
dev->bs_dev.blockcnt = DEV_BUFFER_BLOCKCNT;
|
|
|
|
dev->bs_dev.blocklen = DEV_BUFFER_BLOCKLEN;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
free_dev(struct lvol_ut_bs_dev *dev)
|
|
|
|
{
|
|
|
|
struct spdk_blob_store *bs = dev->bs;
|
|
|
|
struct spdk_blob *blob, *tmp;
|
|
|
|
|
|
|
|
if (bs == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TAILQ_FOREACH_SAFE(blob, &bs->blobs, link, tmp) {
|
|
|
|
TAILQ_REMOVE(&bs->blobs, blob, link);
|
|
|
|
free(blob);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(bs);
|
|
|
|
dev->bs = NULL;
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
2022-10-12 20:01:10 +00:00
|
|
|
static void
|
|
|
|
init_bdev(struct spdk_bdev *bdev, char *name, size_t size)
|
|
|
|
{
|
|
|
|
memset(bdev, 0, sizeof(*bdev));
|
|
|
|
bdev->name = name;
|
|
|
|
spdk_uuid_generate(&bdev->uuid);
|
|
|
|
bdev->blocklen = BS_PAGE_SIZE;
|
|
|
|
bdev->phys_blocklen = BS_PAGE_SIZE;
|
|
|
|
bdev->blockcnt = size / BS_PAGE_SIZE;
|
|
|
|
}
|
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
void
|
|
|
|
spdk_bs_init(struct spdk_bs_dev *dev, struct spdk_bs_opts *o,
|
|
|
|
spdk_bs_op_with_handle_complete cb_fn, void *cb_arg)
|
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct lvol_ut_bs_dev *ut_dev = SPDK_CONTAINEROF(dev, struct lvol_ut_bs_dev, bs_dev);
|
2017-09-14 14:53:36 +00:00
|
|
|
struct spdk_blob_store *bs;
|
|
|
|
|
|
|
|
bs = calloc(1, sizeof(*bs));
|
2017-10-19 15:30:32 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(bs != NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
TAILQ_INIT(&bs->blobs);
|
|
|
|
|
|
|
|
ut_dev->bs = bs;
|
2022-10-12 20:01:10 +00:00
|
|
|
bs->esnap_bs_dev_create = o->esnap_bs_dev_create;
|
2017-10-18 22:01:52 +00:00
|
|
|
|
|
|
|
memcpy(&bs->bs_opts, o, sizeof(struct spdk_bs_opts));
|
2017-09-29 07:46:50 +00:00
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
cb_fn(cb_arg, bs, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
spdk_bs_unload(struct spdk_blob_store *bs, spdk_bs_op_complete cb_fn, void *cb_arg)
|
|
|
|
{
|
|
|
|
cb_fn(cb_arg, 0);
|
|
|
|
}
|
|
|
|
|
2017-10-20 13:44:30 +00:00
|
|
|
void
|
2017-12-04 18:05:49 +00:00
|
|
|
spdk_bs_destroy(struct spdk_blob_store *bs, spdk_bs_op_complete cb_fn,
|
2017-10-20 13:44:30 +00:00
|
|
|
void *cb_arg)
|
|
|
|
{
|
|
|
|
free(bs);
|
|
|
|
|
|
|
|
cb_fn(cb_arg, 0);
|
|
|
|
}
|
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
void
|
2017-12-08 21:09:12 +00:00
|
|
|
spdk_bs_delete_blob(struct spdk_blob_store *bs, spdk_blob_id blobid,
|
|
|
|
spdk_blob_op_complete cb_fn, void *cb_arg)
|
2017-09-14 14:53:36 +00:00
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct spdk_blob *blob;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(blob, &bs->blobs, link) {
|
|
|
|
if (blob->id == blobid) {
|
|
|
|
TAILQ_REMOVE(&bs->blobs, blob, link);
|
|
|
|
free(blob);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-01 13:48:13 +00:00
|
|
|
cb_fn(cb_arg, g_remove_rc);
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
spdk_blob_id
|
|
|
|
spdk_blob_get_id(struct spdk_blob *blob)
|
|
|
|
{
|
2017-10-19 15:30:32 +00:00
|
|
|
return blob->id;
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
2017-09-29 07:46:50 +00:00
|
|
|
void
|
2020-12-23 14:39:20 +00:00
|
|
|
spdk_bs_opts_init(struct spdk_bs_opts *opts, size_t opts_size)
|
2017-09-29 07:46:50 +00:00
|
|
|
{
|
2022-10-12 20:01:10 +00:00
|
|
|
memset(opts, 0, sizeof(*opts));
|
2020-12-23 14:39:20 +00:00
|
|
|
opts->opts_size = opts_size;
|
2017-09-29 07:46:50 +00:00
|
|
|
opts->cluster_sz = SPDK_BLOB_OPTS_CLUSTER_SZ;
|
|
|
|
opts->num_md_pages = SPDK_BLOB_OPTS_NUM_MD_PAGES;
|
|
|
|
opts->max_md_ops = SPDK_BLOB_OPTS_MAX_MD_OPS;
|
|
|
|
opts->max_channel_ops = SPDK_BLOB_OPTS_MAX_CHANNEL_OPS;
|
|
|
|
}
|
|
|
|
|
2020-03-26 09:58:59 +00:00
|
|
|
DEFINE_STUB(spdk_bs_get_cluster_size, uint64_t, (struct spdk_blob_store *bs), BS_CLUSTER_SIZE);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2022-06-22 21:35:04 +00:00
|
|
|
void
|
|
|
|
spdk_blob_close(struct spdk_blob *b, spdk_blob_op_complete cb_fn, void *cb_arg)
|
2017-09-14 14:53:36 +00:00
|
|
|
{
|
2017-12-12 20:42:56 +00:00
|
|
|
b->ref--;
|
2017-10-19 15:30:32 +00:00
|
|
|
|
2017-12-12 20:42:56 +00:00
|
|
|
cb_fn(cb_arg, b->close_status);
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 21:05:44 +00:00
|
|
|
void
|
|
|
|
spdk_blob_resize(struct spdk_blob *blob, uint64_t sz, spdk_blob_op_complete cb_fn, void *cb_arg)
|
2017-09-14 14:53:36 +00:00
|
|
|
{
|
2018-01-30 12:48:21 +00:00
|
|
|
if (g_resize_rc != 0) {
|
2018-03-19 21:05:44 +00:00
|
|
|
return cb_fn(cb_arg, g_resize_rc);
|
2018-01-30 12:48:21 +00:00
|
|
|
} else if (sz > DEV_BUFFER_SIZE / BS_CLUSTER_SIZE) {
|
2018-03-19 21:05:44 +00:00
|
|
|
return cb_fn(cb_arg, -ENOMEM);
|
2018-01-30 12:48:21 +00:00
|
|
|
}
|
2018-03-19 21:05:44 +00:00
|
|
|
cb_fn(cb_arg, 0);
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
2020-03-26 09:58:59 +00:00
|
|
|
DEFINE_STUB(spdk_blob_set_read_only, int, (struct spdk_blob *blob), 0);
|
2019-01-15 15:31:05 +00:00
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
void
|
2017-12-08 16:38:33 +00:00
|
|
|
spdk_blob_sync_md(struct spdk_blob *blob, spdk_blob_op_complete cb_fn, void *cb_arg)
|
2017-09-14 14:53:36 +00:00
|
|
|
{
|
|
|
|
cb_fn(cb_arg, 0);
|
|
|
|
}
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
void
|
|
|
|
spdk_bs_open_blob_ext(struct spdk_blob_store *bs, spdk_blob_id blobid,
|
|
|
|
struct spdk_blob_open_opts *opts, spdk_blob_op_with_handle_complete cb_fn, void *cb_arg)
|
|
|
|
{
|
|
|
|
spdk_bs_open_blob(bs, blobid, cb_fn, cb_arg);
|
|
|
|
}
|
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
void
|
2017-12-08 21:09:12 +00:00
|
|
|
spdk_bs_open_blob(struct spdk_blob_store *bs, spdk_blob_id blobid,
|
|
|
|
spdk_blob_op_with_handle_complete cb_fn, void *cb_arg)
|
2017-09-14 14:53:36 +00:00
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct spdk_blob *blob;
|
|
|
|
|
2018-01-10 10:03:39 +00:00
|
|
|
if (!g_lvs_rename_blob_open_error) {
|
|
|
|
TAILQ_FOREACH(blob, &bs->blobs, link) {
|
|
|
|
if (blob->id == blobid) {
|
|
|
|
blob->ref++;
|
|
|
|
cb_fn(cb_arg, blob, blob->open_status);
|
|
|
|
return;
|
|
|
|
}
|
2017-10-18 22:01:52 +00:00
|
|
|
}
|
2017-10-19 15:30:32 +00:00
|
|
|
}
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
cb_fn(cb_arg, NULL, -ENOENT);
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
2020-03-26 09:58:59 +00:00
|
|
|
DEFINE_STUB(spdk_bs_free_cluster_count, uint64_t, (struct spdk_blob_store *bs), BS_FREE_CLUSTERS);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2018-01-26 13:33:27 +00:00
|
|
|
void
|
2020-12-23 16:56:38 +00:00
|
|
|
spdk_blob_opts_init(struct spdk_blob_opts *opts, size_t opts_size)
|
2018-01-26 13:33:27 +00:00
|
|
|
{
|
2020-12-23 16:56:38 +00:00
|
|
|
opts->opts_size = opts_size;
|
2018-01-26 13:33:27 +00:00
|
|
|
opts->num_clusters = 0;
|
|
|
|
opts->thin_provision = false;
|
2018-01-29 09:25:43 +00:00
|
|
|
opts->xattrs.count = 0;
|
|
|
|
opts->xattrs.names = NULL;
|
|
|
|
opts->xattrs.ctx = NULL;
|
|
|
|
opts->xattrs.get_value = NULL;
|
2018-01-26 13:33:27 +00:00
|
|
|
}
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
void
|
2020-12-28 11:59:57 +00:00
|
|
|
spdk_blob_open_opts_init(struct spdk_blob_open_opts *opts, size_t opts_size)
|
2019-01-22 08:47:24 +00:00
|
|
|
{
|
2020-12-28 11:59:57 +00:00
|
|
|
opts->opts_size = opts_size;
|
2019-01-22 08:47:24 +00:00
|
|
|
opts->clear_method = BLOB_CLEAR_WITH_DEFAULT;
|
|
|
|
}
|
|
|
|
|
2023-02-15 16:57:44 +00:00
|
|
|
bool
|
|
|
|
spdk_blob_is_read_only(struct spdk_blob *blob)
|
|
|
|
{
|
|
|
|
return g_blob_read_only;
|
|
|
|
}
|
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
void
|
2017-12-08 21:09:12 +00:00
|
|
|
spdk_bs_create_blob(struct spdk_blob_store *bs,
|
|
|
|
spdk_blob_op_with_id_complete cb_fn, void *cb_arg)
|
2018-01-26 13:33:27 +00:00
|
|
|
{
|
|
|
|
spdk_bs_create_blob_ext(bs, NULL, cb_fn, cb_arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
spdk_bs_create_blob_ext(struct spdk_blob_store *bs, const struct spdk_blob_opts *opts,
|
|
|
|
spdk_blob_op_with_id_complete cb_fn, void *cb_arg)
|
2017-09-14 14:53:36 +00:00
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct spdk_blob *b;
|
|
|
|
|
2018-01-30 12:48:21 +00:00
|
|
|
if (opts && opts->num_clusters > DEV_BUFFER_SIZE / BS_CLUSTER_SIZE) {
|
|
|
|
cb_fn(cb_arg, 0, -1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
b = calloc(1, sizeof(*b));
|
|
|
|
SPDK_CU_ASSERT_FATAL(b != NULL);
|
|
|
|
|
2017-10-24 02:51:49 +00:00
|
|
|
b->id = g_blobid++;
|
2018-01-26 13:33:27 +00:00
|
|
|
if (opts != NULL && opts->thin_provision) {
|
|
|
|
b->thin_provisioned = true;
|
|
|
|
}
|
2018-02-22 12:29:49 +00:00
|
|
|
b->bs = bs;
|
2017-10-24 02:51:49 +00:00
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
TAILQ_INSERT_TAIL(&bs->blobs, b, link);
|
2017-10-24 02:51:49 +00:00
|
|
|
cb_fn(cb_arg, b->id, 0);
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
2018-02-22 12:29:49 +00:00
|
|
|
void
|
|
|
|
spdk_bs_create_snapshot(struct spdk_blob_store *bs, spdk_blob_id blobid,
|
|
|
|
const struct spdk_blob_xattr_opts *snapshot_xattrs,
|
|
|
|
spdk_blob_op_with_id_complete cb_fn, void *cb_arg)
|
|
|
|
{
|
|
|
|
spdk_bs_create_blob_ext(bs, NULL, cb_fn, cb_arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
spdk_bs_create_clone(struct spdk_blob_store *bs, spdk_blob_id blobid,
|
|
|
|
const struct spdk_blob_xattr_opts *clone_xattrs,
|
|
|
|
spdk_blob_op_with_id_complete cb_fn, void *cb_arg)
|
|
|
|
{
|
|
|
|
spdk_bs_create_blob_ext(bs, NULL, cb_fn, cb_arg);
|
|
|
|
}
|
|
|
|
|
2022-10-10 20:19:49 +00:00
|
|
|
static int g_spdk_blob_get_esnap_id_errno;
|
|
|
|
static bool g_spdk_blob_get_esnap_id_called;
|
|
|
|
static void *g_spdk_blob_get_esnap_id;
|
|
|
|
static size_t g_spdk_blob_get_esnap_id_len;
|
|
|
|
int
|
|
|
|
spdk_blob_get_esnap_id(struct spdk_blob *blob, const void **id, size_t *len)
|
|
|
|
{
|
|
|
|
g_spdk_blob_get_esnap_id_called = true;
|
|
|
|
if (g_spdk_blob_get_esnap_id_errno == 0) {
|
|
|
|
*id = g_spdk_blob_get_esnap_id;
|
|
|
|
*len = g_spdk_blob_get_esnap_id_len;
|
|
|
|
}
|
|
|
|
return g_spdk_blob_get_esnap_id_errno;
|
|
|
|
}
|
|
|
|
|
2023-01-17 16:12:48 +00:00
|
|
|
static spdk_blob_id g_spdk_blob_get_clones_snap_id = 0xbad;
|
|
|
|
static size_t g_spdk_blob_get_clones_count;
|
|
|
|
static spdk_blob_id *g_spdk_blob_get_clones_ids;
|
|
|
|
int
|
|
|
|
spdk_blob_get_clones(struct spdk_blob_store *bs, spdk_blob_id blob_id, spdk_blob_id *ids,
|
|
|
|
size_t *count)
|
|
|
|
{
|
|
|
|
if (blob_id != g_spdk_blob_get_clones_snap_id) {
|
|
|
|
*count = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (ids == NULL || *count < g_spdk_blob_get_clones_count) {
|
|
|
|
*count = g_spdk_blob_get_clones_count;
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
memcpy(ids, g_spdk_blob_get_clones_ids, g_spdk_blob_get_clones_count * sizeof(*ids));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
static void
|
|
|
|
lvol_store_op_with_handle_complete(void *cb_arg, struct spdk_lvol_store *lvol_store, int lvserrno)
|
|
|
|
{
|
|
|
|
g_lvol_store = lvol_store;
|
|
|
|
g_lvserrno = lvserrno;
|
|
|
|
}
|
2017-10-24 02:51:49 +00:00
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
static void
|
|
|
|
lvol_op_with_handle_complete(void *cb_arg, struct spdk_lvol *lvol, int lvserrno)
|
|
|
|
{
|
|
|
|
g_lvol = lvol;
|
|
|
|
g_lvserrno = lvserrno;
|
2022-10-12 20:01:10 +00:00
|
|
|
if (cb_arg != NULL) {
|
|
|
|
struct ut_cb_res *res = cb_arg;
|
|
|
|
|
|
|
|
res->data = lvol;
|
|
|
|
res->err = lvserrno;
|
|
|
|
}
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-03-26 09:54:19 +00:00
|
|
|
op_complete(void *cb_arg, int lvserrno)
|
2017-10-20 09:43:07 +00:00
|
|
|
{
|
2020-03-26 09:41:42 +00:00
|
|
|
g_lvserrno = lvserrno;
|
2022-10-12 20:01:10 +00:00
|
|
|
if (cb_arg != NULL) {
|
|
|
|
struct ut_cb_res *res = cb_arg;
|
|
|
|
|
|
|
|
res->err = lvserrno;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct ut_cb_res *
|
|
|
|
ut_cb_res_clear(struct ut_cb_res *res)
|
|
|
|
{
|
2023-01-17 16:12:48 +00:00
|
|
|
memset(res, 0, sizeof(*res));
|
2022-10-12 20:01:10 +00:00
|
|
|
res->data = (void *)(uintptr_t)(-1);
|
|
|
|
res->err = 0xbad;
|
|
|
|
return res;
|
2017-10-20 09:43:07 +00:00
|
|
|
}
|
|
|
|
|
2023-01-17 16:12:48 +00:00
|
|
|
static bool
|
|
|
|
ut_cb_res_untouched(const struct ut_cb_res *res)
|
|
|
|
{
|
|
|
|
struct ut_cb_res pristine;
|
|
|
|
|
|
|
|
ut_cb_res_clear(&pristine);
|
|
|
|
return !memcmp(&pristine, res, sizeof(pristine));
|
|
|
|
}
|
|
|
|
|
2023-04-11 04:41:15 +00:00
|
|
|
struct count_clones_ctx {
|
|
|
|
struct spdk_lvol *stop_on_lvol;
|
|
|
|
int stop_errno;
|
|
|
|
int count;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
count_clones(void *_ctx, struct spdk_lvol *lvol)
|
|
|
|
{
|
|
|
|
struct count_clones_ctx *ctx = _ctx;
|
|
|
|
|
|
|
|
if (ctx->stop_on_lvol == lvol) {
|
|
|
|
return ctx->stop_errno;
|
|
|
|
}
|
|
|
|
ctx->count++;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
static void
|
|
|
|
lvs_init_unload_success(void)
|
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct lvol_ut_bs_dev dev;
|
2017-10-18 19:40:28 +00:00
|
|
|
struct spdk_lvs_opts opts;
|
2017-09-14 14:53:36 +00:00
|
|
|
int rc = 0;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
init_dev(&dev);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2017-10-18 19:40:28 +00:00
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2017-09-14 14:53:36 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2017-09-29 07:46:50 +00:00
|
|
|
|
2017-10-18 18:05:41 +00:00
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
2017-10-18 22:01:52 +00:00
|
|
|
rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
|
2017-09-29 07:46:50 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
2017-10-18 18:05:41 +00:00
|
|
|
CU_ASSERT(!TAILQ_EMPTY(&g_lvol_stores));
|
2017-09-29 07:46:50 +00:00
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2017-10-12 07:47:41 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
|
|
|
/* Lvol store has an open lvol, this unload should fail. */
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2017-10-12 07:47:41 +00:00
|
|
|
CU_ASSERT(rc == -EBUSY);
|
2017-10-25 08:15:02 +00:00
|
|
|
CU_ASSERT(g_lvserrno == -EBUSY);
|
2017-10-12 07:47:41 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
2017-10-18 18:05:41 +00:00
|
|
|
CU_ASSERT(!TAILQ_EMPTY(&g_lvol_stores));
|
2017-10-12 07:47:41 +00:00
|
|
|
|
|
|
|
/* Lvol has to be closed (or destroyed) before unloading lvol store. */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
2017-10-20 09:43:07 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2017-10-12 07:47:41 +00:00
|
|
|
|
2017-09-29 07:46:50 +00:00
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2017-09-29 07:46:50 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
2017-10-18 18:05:41 +00:00
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
2017-09-29 07:46:50 +00:00
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
free_dev(&dev);
|
2017-09-29 07:46:50 +00:00
|
|
|
}
|
|
|
|
|
2017-10-20 13:44:30 +00:00
|
|
|
static void
|
|
|
|
lvs_init_destroy_success(void)
|
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct lvol_ut_bs_dev dev;
|
2017-10-20 13:44:30 +00:00
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
int rc = 0;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
init_dev(&dev);
|
2017-10-20 13:44:30 +00:00
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2017-10-20 13:44:30 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
|
2017-10-20 13:44:30 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2017-10-20 13:44:30 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
|
|
|
/* Lvol store contains one lvol, this destroy should fail. */
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_destroy(g_lvol_store, op_complete, NULL);
|
2017-10-20 13:44:30 +00:00
|
|
|
CU_ASSERT(rc == -EBUSY);
|
2017-10-25 08:15:02 +00:00
|
|
|
CU_ASSERT(g_lvserrno == -EBUSY);
|
2017-10-20 13:44:30 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
2017-10-20 13:44:30 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_destroy(g_lvol, op_complete, NULL);
|
2017-10-18 22:01:52 +00:00
|
|
|
|
2017-10-20 13:44:30 +00:00
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_destroy(g_lvol_store, op_complete, NULL);
|
2017-10-20 13:44:30 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
}
|
|
|
|
|
2017-09-29 07:46:50 +00:00
|
|
|
static void
|
|
|
|
lvs_init_opts_success(void)
|
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct lvol_ut_bs_dev dev;
|
2017-09-29 07:46:50 +00:00
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
int rc = 0;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
init_dev(&dev);
|
2017-09-29 07:46:50 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
|
2017-08-29 17:37:41 +00:00
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2017-09-29 07:46:50 +00:00
|
|
|
opts.cluster_sz = 8192;
|
2017-10-18 22:01:52 +00:00
|
|
|
rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2017-10-18 22:01:52 +00:00
|
|
|
CU_ASSERT(dev.bs->bs_opts.cluster_sz == opts.cluster_sz);
|
2017-09-14 14:53:36 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
free_dev(&dev);
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lvs_unload_lvs_is_null_fail(void)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(NULL, op_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc == -ENODEV);
|
|
|
|
CU_ASSERT(g_lvserrno == -1);
|
|
|
|
}
|
|
|
|
|
2017-08-29 17:37:41 +00:00
|
|
|
static void
|
|
|
|
lvs_names(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev_x, dev_y, dev_x2;
|
|
|
|
struct spdk_lvs_opts opts_none, opts_x, opts_y, opts_full;
|
|
|
|
struct spdk_lvol_store *lvs_x, *lvs_y, *lvs_x2;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
init_dev(&dev_x);
|
|
|
|
init_dev(&dev_y);
|
|
|
|
init_dev(&dev_x2);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts_none);
|
|
|
|
spdk_lvs_opts_init(&opts_x);
|
|
|
|
opts_x.name[0] = 'x';
|
|
|
|
spdk_lvs_opts_init(&opts_y);
|
|
|
|
opts_y.name[0] = 'y';
|
|
|
|
spdk_lvs_opts_init(&opts_full);
|
|
|
|
memset(opts_full.name, 'a', sizeof(opts_full.name));
|
|
|
|
|
|
|
|
/* Test that opts with no name fails spdk_lvs_init(). */
|
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
|
|
|
rc = spdk_lvs_init(&dev_x.bs_dev, &opts_none, lvol_store_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(rc != 0);
|
|
|
|
CU_ASSERT(g_lvol_store == NULL);
|
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
|
|
|
|
|
|
|
/* Test that opts with no null terminator for name fails spdk_lvs_init(). */
|
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
|
|
|
rc = spdk_lvs_init(&dev_x.bs_dev, &opts_full, lvol_store_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(rc != 0);
|
|
|
|
CU_ASSERT(g_lvol_store == NULL);
|
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
|
|
|
|
|
|
|
/* Test that we can create an lvolstore with name 'x'. */
|
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
rc = spdk_lvs_init(&dev_x.bs_dev, &opts_x, lvol_store_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(!TAILQ_EMPTY(&g_lvol_stores));
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
lvs_x = g_lvol_store;
|
|
|
|
|
|
|
|
/* Test that we can create an lvolstore with name 'y'. */
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
rc = spdk_lvs_init(&dev_y.bs_dev, &opts_y, lvol_store_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
lvs_y = g_lvol_store;
|
|
|
|
|
|
|
|
/* Test that we cannot create another lvolstore with name 'x'. */
|
|
|
|
rc = spdk_lvs_init(&dev_x2.bs_dev, &opts_x, lvol_store_op_with_handle_complete, NULL);
|
2017-10-27 13:47:34 +00:00
|
|
|
CU_ASSERT(rc == -EEXIST);
|
2017-08-29 17:37:41 +00:00
|
|
|
|
|
|
|
/* Now destroy lvolstore 'x' and then confirm we can create a new lvolstore with name 'x'. */
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_destroy(lvs_x, op_complete, NULL);
|
2017-08-29 17:37:41 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
rc = spdk_lvs_init(&dev_x.bs_dev, &opts_x, lvol_store_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
lvs_x = g_lvol_store;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unload lvolstore 'x'. Then we should be able to create another lvolstore with name 'x'.
|
|
|
|
*/
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(lvs_x, op_complete, NULL);
|
2017-08-29 17:37:41 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
rc = spdk_lvs_init(&dev_x2.bs_dev, &opts_x, lvol_store_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
lvs_x2 = g_lvol_store;
|
|
|
|
|
|
|
|
/* Confirm that we cannot load the first lvolstore 'x'. */
|
|
|
|
g_lvserrno = 0;
|
|
|
|
spdk_lvs_load(&dev_x.bs_dev, lvol_store_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
|
|
|
|
|
|
|
/* Destroy the second lvolstore 'x'. Then we should be able to load the first lvolstore 'x'. */
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_destroy(lvs_x2, op_complete, NULL);
|
2017-08-29 17:37:41 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvserrno = -1;
|
|
|
|
spdk_lvs_load(&dev_x.bs_dev, lvol_store_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
lvs_x = g_lvol_store;
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_destroy(lvs_x, op_complete, NULL);
|
2017-08-29 17:37:41 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_destroy(lvs_y, op_complete, NULL);
|
2017-08-29 17:37:41 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
}
|
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
static void
|
|
|
|
lvol_create_destroy_success(void)
|
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct lvol_ut_bs_dev dev;
|
2017-10-18 19:40:28 +00:00
|
|
|
struct spdk_lvs_opts opts;
|
2017-09-14 14:53:36 +00:00
|
|
|
int rc = 0;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
init_dev(&dev);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2017-10-18 19:40:28 +00:00
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2017-10-18 19:40:28 +00:00
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
g_lvserrno = -1;
|
2017-10-18 22:01:52 +00:00
|
|
|
rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
2017-10-20 08:34:22 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_destroy(g_lvol, op_complete, NULL);
|
2017-10-20 09:43:07 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
free_dev(&dev);
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lvol_create_fail(void)
|
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct lvol_ut_bs_dev dev;
|
2017-10-18 19:40:28 +00:00
|
|
|
struct spdk_lvs_opts opts;
|
2017-09-14 14:53:36 +00:00
|
|
|
int rc = 0;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
init_dev(&dev);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2017-10-18 19:40:28 +00:00
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2017-10-18 19:40:28 +00:00
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
g_lvol_store = NULL;
|
|
|
|
g_lvserrno = 0;
|
2017-10-18 19:40:28 +00:00
|
|
|
rc = spdk_lvs_init(NULL, &opts, lvol_store_op_with_handle_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc != 0);
|
|
|
|
CU_ASSERT(g_lvol_store == NULL);
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
|
|
|
|
g_lvol = NULL;
|
2019-01-22 08:47:24 +00:00
|
|
|
rc = spdk_lvol_create(NULL, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc != 0);
|
|
|
|
CU_ASSERT(g_lvol == NULL);
|
|
|
|
|
2018-01-30 12:48:21 +00:00
|
|
|
g_lvol = NULL;
|
2019-01-22 08:47:24 +00:00
|
|
|
rc = spdk_lvol_create(g_lvol_store, "lvol", DEV_BUFFER_SIZE + 1, false, LVOL_CLEAR_WITH_DEFAULT,
|
2017-10-24 02:51:49 +00:00
|
|
|
lvol_op_with_handle_complete, NULL);
|
2018-01-30 12:48:21 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(g_lvol == NULL);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
free_dev(&dev);
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lvol_destroy_fail(void)
|
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct lvol_ut_bs_dev dev;
|
2017-10-18 19:40:28 +00:00
|
|
|
struct spdk_lvs_opts opts;
|
2017-09-14 14:53:36 +00:00
|
|
|
int rc = 0;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
init_dev(&dev);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2017-10-18 19:40:28 +00:00
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2017-10-18 19:40:28 +00:00
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
2017-10-20 08:34:22 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_destroy(g_lvol, op_complete, NULL);
|
2017-10-20 09:43:07 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2019-03-01 13:48:13 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
2019-03-01 13:48:13 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_remove_rc = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_destroy(g_lvol, op_complete, NULL);
|
2019-03-01 13:48:13 +00:00
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_store->lvols));
|
|
|
|
g_remove_rc = 0;
|
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
free_dev(&dev);
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lvol_close_fail(void)
|
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct lvol_ut_bs_dev dev;
|
2017-10-18 19:40:28 +00:00
|
|
|
struct spdk_lvs_opts opts;
|
2017-09-14 14:53:36 +00:00
|
|
|
int rc = 0;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
init_dev(&dev);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2017-10-18 19:40:28 +00:00
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2017-10-18 19:40:28 +00:00
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
2017-10-20 09:43:07 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
free_dev(&dev);
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lvol_close_success(void)
|
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct lvol_ut_bs_dev dev;
|
2017-10-18 19:40:28 +00:00
|
|
|
struct spdk_lvs_opts opts;
|
2017-09-14 14:53:36 +00:00
|
|
|
int rc = 0;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
init_dev(&dev);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2017-10-18 19:40:28 +00:00
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2017-10-18 19:40:28 +00:00
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
g_lvserrno = -1;
|
2017-10-18 22:01:52 +00:00
|
|
|
rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
2017-10-20 09:43:07 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
free_dev(&dev);
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lvol_resize(void)
|
|
|
|
{
|
2017-10-18 22:01:52 +00:00
|
|
|
struct lvol_ut_bs_dev dev;
|
2017-10-18 19:40:28 +00:00
|
|
|
struct spdk_lvs_opts opts;
|
2017-09-14 14:53:36 +00:00
|
|
|
int rc = 0;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
init_dev(&dev);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2017-10-18 19:40:28 +00:00
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2017-10-18 19:40:28 +00:00
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
g_resize_rc = 0;
|
|
|
|
g_lvserrno = -1;
|
2017-10-18 22:01:52 +00:00
|
|
|
rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
|
|
|
/* Resize to same size */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_resize(g_lvol, 10, op_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
/* Resize to smaller size */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_resize(g_lvol, 5, op_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
/* Resize to bigger size */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_resize(g_lvol, 15, op_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
/* Resize to size = 0 */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_resize(g_lvol, 0, op_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
/* Resize to bigger size than available */
|
2018-03-19 21:05:44 +00:00
|
|
|
g_lvserrno = 0;
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_resize(g_lvol, 0xFFFFFFFF, op_complete, NULL);
|
2018-03-19 21:05:44 +00:00
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
|
|
|
/* Fail resize */
|
|
|
|
g_resize_rc = -1;
|
|
|
|
g_lvserrno = 0;
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_resize(g_lvol, 10, op_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
2017-10-25 12:57:07 +00:00
|
|
|
g_resize_rc = 0;
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2017-10-24 02:51:49 +00:00
|
|
|
g_resize_rc = 0;
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
2017-10-20 08:34:22 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_destroy(g_lvol, op_complete, NULL);
|
2017-10-20 09:43:07 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
free_dev(&dev);
|
2017-09-14 14:53:36 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 15:31:05 +00:00
|
|
|
static void
|
|
|
|
lvol_set_read_only(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
int rc = 0;
|
|
|
|
struct spdk_lvol *lvol, *clone;
|
|
|
|
|
|
|
|
init_dev(&dev);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
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);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2020-03-26 09:41:42 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2019-01-15 15:31:05 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
lvol = g_lvol;
|
|
|
|
|
|
|
|
/* Set lvol as read only */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_set_read_only(lvol, op_complete, NULL);
|
2020-03-26 09:41:42 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2019-01-15 15:31:05 +00:00
|
|
|
|
|
|
|
/* Create lvol clone from read only lvol */
|
|
|
|
spdk_lvol_create_clone(lvol, "clone", lvol_op_with_handle_complete, NULL);
|
2020-03-26 09:41:42 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2019-01-15 15:31:05 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
CU_ASSERT_STRING_EQUAL(g_lvol->name, "clone");
|
|
|
|
clone = g_lvol;
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(lvol, op_complete, NULL);
|
2019-01-15 15:31:05 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(clone, op_complete, NULL);
|
2019-01-15 15:31:05 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2019-01-15 15:31:05 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
free_dev(&dev);
|
|
|
|
}
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
static void
|
|
|
|
null_cb(void *ctx, struct spdk_blob_store *bs, int bserrno)
|
|
|
|
{
|
|
|
|
SPDK_CU_ASSERT_FATAL(bs != NULL);
|
|
|
|
}
|
|
|
|
|
2017-10-19 15:30:32 +00:00
|
|
|
static void
|
2022-10-12 20:01:10 +00:00
|
|
|
test_lvs_load(void)
|
2017-10-19 15:30:32 +00:00
|
|
|
{
|
|
|
|
int rc = -1;
|
2017-10-18 22:01:52 +00:00
|
|
|
struct lvol_ut_bs_dev dev;
|
2017-10-19 15:30:32 +00:00
|
|
|
struct spdk_lvs_with_handle_req *req;
|
2017-10-18 22:01:52 +00:00
|
|
|
struct spdk_bs_opts bs_opts = {};
|
|
|
|
struct spdk_blob *super_blob;
|
2023-04-13 13:56:50 +00:00
|
|
|
struct spdk_lvs_opts opts = {};
|
2017-10-19 15:30:32 +00:00
|
|
|
|
|
|
|
req = calloc(1, sizeof(*req));
|
|
|
|
SPDK_CU_ASSERT_FATAL(req != NULL);
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
init_dev(&dev);
|
2020-12-23 14:39:20 +00:00
|
|
|
spdk_bs_opts_init(&bs_opts, sizeof(bs_opts));
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "LVOLSTORE");
|
2017-10-18 22:01:52 +00:00
|
|
|
spdk_bs_init(&dev.bs_dev, &bs_opts, null_cb, NULL);
|
2019-06-28 09:53:18 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(dev.bs != NULL);
|
2017-10-19 15:30:32 +00:00
|
|
|
|
|
|
|
/* Fail on bs load */
|
2017-10-18 22:01:52 +00:00
|
|
|
dev.load_status = -1;
|
2017-10-18 18:05:41 +00:00
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
2017-10-18 22:01:52 +00:00
|
|
|
spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
|
2017-10-19 15:30:32 +00:00
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
|
|
|
CU_ASSERT(g_lvol_store == NULL);
|
2017-10-18 18:05:41 +00:00
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
2017-10-19 15:30:32 +00:00
|
|
|
|
|
|
|
/* Fail on getting super blob */
|
2017-10-18 22:01:52 +00:00
|
|
|
dev.load_status = 0;
|
|
|
|
dev.bs->get_super_status = -1;
|
|
|
|
spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
|
2017-10-19 15:30:32 +00:00
|
|
|
CU_ASSERT(g_lvserrno == -ENODEV);
|
|
|
|
CU_ASSERT(g_lvol_store == NULL);
|
2017-10-18 18:05:41 +00:00
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
2017-10-19 15:30:32 +00:00
|
|
|
|
|
|
|
/* Fail on opening super blob */
|
|
|
|
g_lvserrno = 0;
|
2017-10-18 22:01:52 +00:00
|
|
|
super_blob = calloc(1, sizeof(*super_blob));
|
|
|
|
super_blob->id = 0x100;
|
|
|
|
super_blob->open_status = -1;
|
|
|
|
TAILQ_INSERT_TAIL(&dev.bs->blobs, super_blob, link);
|
|
|
|
dev.bs->super_blobid = 0x100;
|
|
|
|
dev.bs->get_super_status = 0;
|
|
|
|
spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
|
2017-10-19 15:30:32 +00:00
|
|
|
CU_ASSERT(g_lvserrno == -ENODEV);
|
|
|
|
CU_ASSERT(g_lvol_store == NULL);
|
2017-10-18 18:05:41 +00:00
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
2017-10-19 15:30:32 +00:00
|
|
|
|
|
|
|
/* Fail on getting uuid */
|
|
|
|
g_lvserrno = 0;
|
2017-10-18 22:01:52 +00:00
|
|
|
super_blob->open_status = 0;
|
|
|
|
spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
|
2017-10-27 13:47:34 +00:00
|
|
|
CU_ASSERT(g_lvserrno == -EINVAL);
|
2017-10-19 15:30:32 +00:00
|
|
|
CU_ASSERT(g_lvol_store == NULL);
|
2017-10-18 18:05:41 +00:00
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
2017-10-19 15:30:32 +00:00
|
|
|
|
2017-08-29 17:37:41 +00:00
|
|
|
/* Fail on getting name */
|
2017-10-19 15:30:32 +00:00
|
|
|
g_lvserrno = 0;
|
2018-03-02 00:59:50 +00:00
|
|
|
spdk_blob_set_xattr(super_blob, "uuid", uuid, SPDK_UUID_STRING_LEN);
|
2017-08-29 17:37:41 +00:00
|
|
|
spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
|
2017-10-27 13:47:34 +00:00
|
|
|
CU_ASSERT(g_lvserrno == -EINVAL);
|
2017-08-29 17:37:41 +00:00
|
|
|
CU_ASSERT(g_lvol_store == NULL);
|
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
|
|
|
|
|
|
|
/* Fail on closing super blob */
|
|
|
|
g_lvserrno = 0;
|
2022-06-22 10:10:33 +00:00
|
|
|
spdk_blob_set_xattr(super_blob, "name", "lvs", strlen("lvs") + 1);
|
2017-10-18 22:01:52 +00:00
|
|
|
super_blob->close_status = -1;
|
|
|
|
spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
|
2017-10-19 15:30:32 +00:00
|
|
|
CU_ASSERT(g_lvserrno == -ENODEV);
|
|
|
|
CU_ASSERT(g_lvol_store == NULL);
|
2017-10-18 18:05:41 +00:00
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
2017-10-19 15:30:32 +00:00
|
|
|
|
2023-04-13 13:56:50 +00:00
|
|
|
/* Fail on invalid options */
|
|
|
|
g_lvserrno = -1;
|
|
|
|
spdk_lvs_opts_init(&opts);
|
|
|
|
opts.opts_size = 0; /* Invalid length */
|
|
|
|
spdk_lvs_load_ext(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == -EINVAL);
|
|
|
|
CU_ASSERT(g_lvol_store == NULL);
|
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
|
|
|
|
2017-10-19 15:30:32 +00:00
|
|
|
/* Load successfully */
|
|
|
|
g_lvserrno = 0;
|
2017-10-18 22:01:52 +00:00
|
|
|
super_blob->close_status = 0;
|
|
|
|
spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
|
2017-10-19 15:30:32 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
CU_ASSERT(g_lvol_store != NULL);
|
2017-10-18 18:05:41 +00:00
|
|
|
CU_ASSERT(!TAILQ_EMPTY(&g_lvol_stores));
|
2017-10-19 15:30:32 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2017-10-19 15:30:32 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2017-10-18 18:05:41 +00:00
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_stores));
|
2017-10-19 15:30:32 +00:00
|
|
|
|
|
|
|
free(req);
|
2017-10-18 22:01:52 +00:00
|
|
|
free_dev(&dev);
|
2017-10-19 15:30:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lvols_load(void)
|
|
|
|
{
|
|
|
|
int rc = -1;
|
2017-10-18 22:01:52 +00:00
|
|
|
struct lvol_ut_bs_dev dev;
|
2017-10-19 15:30:32 +00:00
|
|
|
struct spdk_lvs_with_handle_req *req;
|
2017-10-18 22:01:52 +00:00
|
|
|
struct spdk_bs_opts bs_opts;
|
|
|
|
struct spdk_blob *super_blob, *blob1, *blob2, *blob3;
|
2017-10-19 15:30:32 +00:00
|
|
|
|
|
|
|
req = calloc(1, sizeof(*req));
|
|
|
|
SPDK_CU_ASSERT_FATAL(req != NULL);
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
init_dev(&dev);
|
2020-12-23 14:39:20 +00:00
|
|
|
spdk_bs_opts_init(&bs_opts, sizeof(bs_opts));
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "LVOLSTORE");
|
2017-10-18 22:01:52 +00:00
|
|
|
spdk_bs_init(&dev.bs_dev, &bs_opts, null_cb, NULL);
|
|
|
|
super_blob = calloc(1, sizeof(*super_blob));
|
2017-10-24 19:41:55 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(super_blob != NULL);
|
2017-10-18 22:01:52 +00:00
|
|
|
super_blob->id = 0x100;
|
2018-03-02 00:59:50 +00:00
|
|
|
spdk_blob_set_xattr(super_blob, "uuid", uuid, SPDK_UUID_STRING_LEN);
|
2022-06-22 10:10:33 +00:00
|
|
|
spdk_blob_set_xattr(super_blob, "name", "lvs", strlen("lvs") + 1);
|
2017-10-18 22:01:52 +00:00
|
|
|
TAILQ_INSERT_TAIL(&dev.bs->blobs, super_blob, link);
|
|
|
|
dev.bs->super_blobid = 0x100;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create 3 blobs, write different char values to the last char in the UUID
|
|
|
|
* to make sure they are unique.
|
|
|
|
*/
|
|
|
|
blob1 = calloc(1, sizeof(*blob1));
|
2017-10-24 19:41:55 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(blob1 != NULL);
|
2017-10-18 22:01:52 +00:00
|
|
|
blob1->id = 0x1;
|
2018-03-02 00:59:50 +00:00
|
|
|
spdk_blob_set_xattr(blob1, "uuid", uuid, SPDK_UUID_STRING_LEN);
|
2022-06-22 10:10:33 +00:00
|
|
|
spdk_blob_set_xattr(blob1, "name", "lvol1", strlen("lvol1") + 1);
|
2018-03-02 00:59:50 +00:00
|
|
|
blob1->uuid[SPDK_UUID_STRING_LEN - 2] = '1';
|
2017-10-18 22:01:52 +00:00
|
|
|
|
|
|
|
blob2 = calloc(1, sizeof(*blob2));
|
2017-10-24 19:41:55 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(blob2 != NULL);
|
2017-10-18 22:01:52 +00:00
|
|
|
blob2->id = 0x2;
|
2018-03-02 00:59:50 +00:00
|
|
|
spdk_blob_set_xattr(blob2, "uuid", uuid, SPDK_UUID_STRING_LEN);
|
2022-06-22 10:10:33 +00:00
|
|
|
spdk_blob_set_xattr(blob2, "name", "lvol2", strlen("lvol2") + 1);
|
2018-03-02 00:59:50 +00:00
|
|
|
blob2->uuid[SPDK_UUID_STRING_LEN - 2] = '2';
|
2017-10-18 22:01:52 +00:00
|
|
|
|
|
|
|
blob3 = calloc(1, sizeof(*blob3));
|
2017-10-24 19:41:55 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(blob3 != NULL);
|
2017-10-18 22:01:52 +00:00
|
|
|
blob3->id = 0x2;
|
2018-03-02 00:59:50 +00:00
|
|
|
spdk_blob_set_xattr(blob3, "uuid", uuid, SPDK_UUID_STRING_LEN);
|
2022-06-22 10:10:33 +00:00
|
|
|
spdk_blob_set_xattr(blob3, "name", "lvol3", strlen("lvol3") + 1);
|
2018-03-02 00:59:50 +00:00
|
|
|
blob3->uuid[SPDK_UUID_STRING_LEN - 2] = '3';
|
2017-10-19 15:30:32 +00:00
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
/* Load lvs with 0 blobs */
|
2017-10-19 15:30:32 +00:00
|
|
|
g_lvserrno = 0;
|
2017-10-18 22:01:52 +00:00
|
|
|
spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
|
2017-10-19 15:30:32 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
CU_ASSERT(g_lvol_store != NULL);
|
2017-10-18 22:01:52 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2017-10-19 15:30:32 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2017-10-19 15:30:32 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
2017-10-18 22:01:52 +00:00
|
|
|
TAILQ_INSERT_TAIL(&dev.bs->blobs, blob1, link);
|
|
|
|
TAILQ_INSERT_TAIL(&dev.bs->blobs, blob2, link);
|
|
|
|
TAILQ_INSERT_TAIL(&dev.bs->blobs, blob3, link);
|
|
|
|
|
2017-10-27 13:09:53 +00:00
|
|
|
/* Load lvs again with 3 blobs, but fail on 1st one */
|
2017-10-18 22:01:52 +00:00
|
|
|
g_lvol_store = NULL;
|
|
|
|
g_lvserrno = 0;
|
2017-10-27 13:09:53 +00:00
|
|
|
blob1->load_status = -1;
|
|
|
|
spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
|
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
|
|
|
CU_ASSERT(g_lvol_store == NULL);
|
|
|
|
|
|
|
|
/* Load lvs again with 3 blobs, but fail on 3rd one */
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
g_lvserrno = 0;
|
|
|
|
blob1->load_status = 0;
|
|
|
|
blob2->load_status = 0;
|
|
|
|
blob3->load_status = -1;
|
|
|
|
spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
|
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
|
|
|
CU_ASSERT(g_lvol_store == NULL);
|
|
|
|
|
|
|
|
/* Load lvs again with 3 blobs, with success */
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
g_lvserrno = 0;
|
|
|
|
blob1->load_status = 0;
|
|
|
|
blob2->load_status = 0;
|
|
|
|
blob3->load_status = 0;
|
2017-10-18 22:01:52 +00:00
|
|
|
spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2017-10-27 13:09:53 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
CU_ASSERT(!TAILQ_EMPTY(&g_lvol_store->lvols));
|
2017-10-18 22:01:52 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
/* rc = */ spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2017-10-18 22:01:52 +00:00
|
|
|
/*
|
|
|
|
* Disable these two asserts for now. lvolstore should allow unload as long
|
|
|
|
* as the lvols were not opened - but this is coming a future patch.
|
|
|
|
*/
|
|
|
|
/* CU_ASSERT(rc == 0); */
|
|
|
|
/* CU_ASSERT(g_lvserrno == 0); */
|
|
|
|
|
2017-10-19 15:30:32 +00:00
|
|
|
free(req);
|
2017-10-18 22:01:52 +00:00
|
|
|
free_dev(&dev);
|
2017-10-19 15:30:32 +00:00
|
|
|
}
|
|
|
|
|
2017-10-20 14:15:04 +00:00
|
|
|
static void
|
|
|
|
lvol_open(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvs_with_handle_req *req;
|
|
|
|
struct spdk_bs_opts bs_opts;
|
|
|
|
struct spdk_blob *super_blob, *blob1, *blob2, *blob3;
|
|
|
|
struct spdk_lvol *lvol, *tmp;
|
|
|
|
|
|
|
|
req = calloc(1, sizeof(*req));
|
|
|
|
SPDK_CU_ASSERT_FATAL(req != NULL);
|
|
|
|
|
|
|
|
init_dev(&dev);
|
2020-12-23 14:39:20 +00:00
|
|
|
spdk_bs_opts_init(&bs_opts, sizeof(bs_opts));
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "LVOLSTORE");
|
2017-10-20 14:15:04 +00:00
|
|
|
spdk_bs_init(&dev.bs_dev, &bs_opts, null_cb, NULL);
|
|
|
|
super_blob = calloc(1, sizeof(*super_blob));
|
|
|
|
SPDK_CU_ASSERT_FATAL(super_blob != NULL);
|
|
|
|
super_blob->id = 0x100;
|
2018-03-02 00:59:50 +00:00
|
|
|
spdk_blob_set_xattr(super_blob, "uuid", uuid, SPDK_UUID_STRING_LEN);
|
2022-06-22 10:10:33 +00:00
|
|
|
spdk_blob_set_xattr(super_blob, "name", "lvs", strlen("lvs") + 1);
|
2017-10-20 14:15:04 +00:00
|
|
|
TAILQ_INSERT_TAIL(&dev.bs->blobs, super_blob, link);
|
|
|
|
dev.bs->super_blobid = 0x100;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create 3 blobs, write different char values to the last char in the UUID
|
|
|
|
* to make sure they are unique.
|
|
|
|
*/
|
|
|
|
blob1 = calloc(1, sizeof(*blob1));
|
|
|
|
SPDK_CU_ASSERT_FATAL(blob1 != NULL);
|
|
|
|
blob1->id = 0x1;
|
2018-03-02 00:59:50 +00:00
|
|
|
spdk_blob_set_xattr(blob1, "uuid", uuid, SPDK_UUID_STRING_LEN);
|
2022-06-22 10:10:33 +00:00
|
|
|
spdk_blob_set_xattr(blob1, "name", "lvol1", strlen("lvol1") + 1);
|
2018-03-02 00:59:50 +00:00
|
|
|
blob1->uuid[SPDK_UUID_STRING_LEN - 2] = '1';
|
2017-10-20 14:15:04 +00:00
|
|
|
|
|
|
|
blob2 = calloc(1, sizeof(*blob2));
|
|
|
|
SPDK_CU_ASSERT_FATAL(blob2 != NULL);
|
|
|
|
blob2->id = 0x2;
|
2018-03-02 00:59:50 +00:00
|
|
|
spdk_blob_set_xattr(blob2, "uuid", uuid, SPDK_UUID_STRING_LEN);
|
2022-06-22 10:10:33 +00:00
|
|
|
spdk_blob_set_xattr(blob2, "name", "lvol2", strlen("lvol2") + 1);
|
2018-03-02 00:59:50 +00:00
|
|
|
blob2->uuid[SPDK_UUID_STRING_LEN - 2] = '2';
|
2017-10-20 14:15:04 +00:00
|
|
|
|
|
|
|
blob3 = calloc(1, sizeof(*blob3));
|
|
|
|
SPDK_CU_ASSERT_FATAL(blob3 != NULL);
|
|
|
|
blob3->id = 0x2;
|
2018-03-02 00:59:50 +00:00
|
|
|
spdk_blob_set_xattr(blob3, "uuid", uuid, SPDK_UUID_STRING_LEN);
|
2022-06-22 10:10:33 +00:00
|
|
|
spdk_blob_set_xattr(blob3, "name", "lvol3", strlen("lvol3") + 1);
|
2018-03-02 00:59:50 +00:00
|
|
|
blob3->uuid[SPDK_UUID_STRING_LEN - 2] = '3';
|
2017-10-20 14:15:04 +00:00
|
|
|
|
|
|
|
TAILQ_INSERT_TAIL(&dev.bs->blobs, blob1, link);
|
|
|
|
TAILQ_INSERT_TAIL(&dev.bs->blobs, blob2, link);
|
|
|
|
TAILQ_INSERT_TAIL(&dev.bs->blobs, blob3, link);
|
|
|
|
|
|
|
|
/* Load lvs with 3 blobs */
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
g_lvserrno = 0;
|
|
|
|
spdk_lvs_load(&dev.bs_dev, lvol_store_op_with_handle_complete, req);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_lvol_stores));
|
|
|
|
|
|
|
|
blob1->open_status = -1;
|
|
|
|
blob2->open_status = -1;
|
|
|
|
blob3->open_status = -1;
|
|
|
|
|
|
|
|
/* Fail opening all lvols */
|
|
|
|
TAILQ_FOREACH_SAFE(lvol, &g_lvol_store->lvols, link, tmp) {
|
|
|
|
spdk_lvol_open(lvol, lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
blob1->open_status = 0;
|
|
|
|
blob2->open_status = 0;
|
|
|
|
blob3->open_status = 0;
|
|
|
|
|
|
|
|
/* Open all lvols */
|
|
|
|
TAILQ_FOREACH_SAFE(lvol, &g_lvol_store->lvols, link, tmp) {
|
|
|
|
spdk_lvol_open(lvol, lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
}
|
|
|
|
|
2017-10-24 02:51:49 +00:00
|
|
|
/* Close all lvols */
|
|
|
|
TAILQ_FOREACH_SAFE(lvol, &g_lvol_store->lvols, link, tmp) {
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(lvol, op_complete, NULL);
|
2017-10-24 02:51:49 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
}
|
|
|
|
|
2017-10-20 14:15:04 +00:00
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvs_destroy(g_lvol_store, op_complete, NULL);
|
2017-10-20 14:15:04 +00:00
|
|
|
|
|
|
|
free(req);
|
2017-10-24 02:51:49 +00:00
|
|
|
free(blob1);
|
|
|
|
free(blob2);
|
|
|
|
free(blob3);
|
|
|
|
}
|
|
|
|
|
2018-02-22 12:29:49 +00:00
|
|
|
static void
|
|
|
|
lvol_snapshot(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvol *lvol;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
init_dev(&dev);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2018-02-22 12:29:49 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
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);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
|
|
|
lvol = g_lvol;
|
|
|
|
|
|
|
|
spdk_lvol_create_snapshot(lvol, "snap", lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
CU_ASSERT_STRING_EQUAL(g_lvol->name, "snap");
|
|
|
|
|
|
|
|
/* Lvol has to be closed (or destroyed) before unloading lvol store. */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvserrno = -1;
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(lvol, op_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvserrno = -1;
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
free_dev(&dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lvol_snapshot_fail(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvol *lvol, *snap;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
init_dev(&dev);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2018-02-22 12:29:49 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
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);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
|
|
|
lvol = g_lvol;
|
|
|
|
|
|
|
|
spdk_lvol_create_snapshot(NULL, "snap", lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno < 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol == NULL);
|
|
|
|
|
|
|
|
spdk_lvol_create_snapshot(lvol, "", lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno < 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol == NULL);
|
|
|
|
|
|
|
|
spdk_lvol_create_snapshot(lvol, NULL, lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno < 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol == NULL);
|
|
|
|
|
|
|
|
spdk_lvol_create_snapshot(lvol, "snap", lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
CU_ASSERT_STRING_EQUAL(g_lvol->name, "snap");
|
|
|
|
|
|
|
|
snap = g_lvol;
|
|
|
|
|
|
|
|
spdk_lvol_create_snapshot(lvol, "snap", lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno < 0);
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(lvol, op_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvserrno = -1;
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(snap, op_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvserrno = -1;
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
free_dev(&dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lvol_clone(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvol *lvol;
|
|
|
|
struct spdk_lvol *snap;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
init_dev(&dev);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2018-02-22 12:29:49 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
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);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
|
|
|
lvol = g_lvol;
|
|
|
|
|
|
|
|
spdk_lvol_create_snapshot(lvol, "snap", lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
CU_ASSERT_STRING_EQUAL(g_lvol->name, "snap");
|
|
|
|
|
|
|
|
snap = g_lvol;
|
|
|
|
|
|
|
|
spdk_lvol_create_clone(snap, "clone", lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
CU_ASSERT_STRING_EQUAL(g_lvol->name, "clone");
|
|
|
|
|
|
|
|
/* Lvol has to be closed (or destroyed) before unloading lvol store. */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvserrno = -1;
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(snap, op_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvserrno = -1;
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(lvol, op_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvserrno = -1;
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
free_dev(&dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lvol_clone_fail(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvol *lvol;
|
|
|
|
struct spdk_lvol *snap;
|
|
|
|
struct spdk_lvol *clone;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
init_dev(&dev);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2018-02-22 12:29:49 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
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);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
|
|
|
lvol = g_lvol;
|
|
|
|
|
|
|
|
spdk_lvol_create_snapshot(lvol, "snap", lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
CU_ASSERT_STRING_EQUAL(g_lvol->name, "snap");
|
|
|
|
|
|
|
|
snap = g_lvol;
|
|
|
|
|
|
|
|
spdk_lvol_create_clone(NULL, "clone", lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno < 0);
|
|
|
|
|
|
|
|
spdk_lvol_create_clone(snap, "", lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno < 0);
|
|
|
|
|
|
|
|
spdk_lvol_create_clone(snap, NULL, lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno < 0);
|
|
|
|
|
|
|
|
spdk_lvol_create_clone(snap, "clone", lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
CU_ASSERT_STRING_EQUAL(g_lvol->name, "clone");
|
|
|
|
|
|
|
|
clone = g_lvol;
|
|
|
|
|
|
|
|
spdk_lvol_create_clone(snap, "clone", lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno < 0);
|
|
|
|
|
|
|
|
/* Lvol has to be closed (or destroyed) before unloading lvol store. */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(clone, op_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvserrno = -1;
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(snap, op_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvserrno = -1;
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(lvol, op_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvserrno = -1;
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2018-02-22 12:29:49 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
free_dev(&dev);
|
|
|
|
}
|
|
|
|
|
2023-04-11 04:41:15 +00:00
|
|
|
static void
|
|
|
|
lvol_iter_clones(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvol *lvol, *snap, *clone;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
struct count_clones_ctx ctx = { 0 };
|
|
|
|
spdk_blob_id mock_clones[2];
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
init_dev(&dev);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
|
|
|
|
|
|
|
g_spdk_blob_get_clones_ids = mock_clones;
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
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);
|
|
|
|
|
|
|
|
/* Create a volume */
|
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
lvol = g_lvol;
|
|
|
|
|
|
|
|
/* Create a snapshot of the volume */
|
|
|
|
spdk_lvol_create_snapshot(lvol, "snap", lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
CU_ASSERT_STRING_EQUAL(g_lvol->name, "snap");
|
|
|
|
snap = g_lvol;
|
|
|
|
|
|
|
|
g_spdk_blob_get_clones_snap_id = snap->blob_id;
|
|
|
|
g_spdk_blob_get_clones_count = 1;
|
|
|
|
mock_clones[0] = lvol->blob_id;
|
|
|
|
|
|
|
|
/* The snapshot turned the lvol into a clone, so the snapshot now has one clone. */
|
|
|
|
memset(&ctx, 0, sizeof(ctx));
|
|
|
|
rc = spdk_lvol_iter_immediate_clones(snap, count_clones, &ctx);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(ctx.count == 1);
|
|
|
|
|
|
|
|
/* The snapshotted volume still has no clones. */
|
|
|
|
memset(&ctx, 0, sizeof(ctx));
|
|
|
|
rc = spdk_lvol_iter_immediate_clones(lvol, count_clones, &ctx);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(ctx.count == 0);
|
|
|
|
|
|
|
|
/* Iteration can be stopped and the return value is propagated. */
|
|
|
|
memset(&ctx, 0, sizeof(ctx));
|
|
|
|
ctx.stop_on_lvol = lvol;
|
|
|
|
ctx.stop_errno = 42;
|
|
|
|
rc = spdk_lvol_iter_immediate_clones(snap, count_clones, &ctx);
|
|
|
|
CU_ASSERT(rc == 42);
|
|
|
|
CU_ASSERT(ctx.count == 0);
|
|
|
|
|
|
|
|
/* Create a clone of the snapshot */
|
|
|
|
spdk_lvol_create_clone(snap, "clone", lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
CU_ASSERT_STRING_EQUAL(g_lvol->name, "clone");
|
|
|
|
clone = g_lvol;
|
|
|
|
|
|
|
|
g_spdk_blob_get_clones_count = 2;
|
|
|
|
mock_clones[1] = clone->blob_id;
|
|
|
|
|
|
|
|
/* The snapshot now has two clones */
|
|
|
|
memset(&ctx, 0, sizeof(ctx));
|
|
|
|
rc = spdk_lvol_iter_immediate_clones(snap, count_clones, &ctx);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(ctx.count == 2);
|
|
|
|
|
|
|
|
/* Cleanup */
|
|
|
|
g_spdk_blob_get_clones_snap_id = 0xbad;
|
|
|
|
g_spdk_blob_get_clones_count = 0;
|
|
|
|
g_spdk_blob_get_clones_ids = NULL;
|
|
|
|
|
|
|
|
spdk_lvol_close(snap, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
spdk_lvol_close(clone, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
spdk_lvol_close(lvol, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
g_lvol = NULL;
|
|
|
|
|
|
|
|
free_dev(&dev);
|
|
|
|
}
|
|
|
|
|
2017-10-24 02:51:49 +00:00
|
|
|
static void
|
|
|
|
lvol_names(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
struct spdk_lvol_store *lvs;
|
|
|
|
struct spdk_lvol *lvol, *lvol2;
|
|
|
|
char fullname[SPDK_LVOL_NAME_MAX];
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
init_dev(&dev);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2017-10-24 02:51:49 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
rc = spdk_lvol_create(lvs, NULL, 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
|
|
|
|
NULL);
|
2017-10-24 02:51:49 +00:00
|
|
|
CU_ASSERT(rc == -EINVAL);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
rc = spdk_lvol_create(lvs, "", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
|
|
|
|
NULL);
|
2017-10-24 02:51:49 +00:00
|
|
|
CU_ASSERT(rc == -EINVAL);
|
|
|
|
|
|
|
|
memset(fullname, 'x', sizeof(fullname));
|
2019-01-22 08:47:24 +00:00
|
|
|
rc = spdk_lvol_create(lvs, fullname, 1, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2017-10-24 02:51:49 +00:00
|
|
|
CU_ASSERT(rc == -EINVAL);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2019-01-22 08:47:24 +00:00
|
|
|
rc = spdk_lvol_create(lvs, "lvol", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
|
|
|
|
NULL);
|
2017-10-24 02:51:49 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
lvol = g_lvol;
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
rc = spdk_lvol_create(lvs, "lvol", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
|
|
|
|
NULL);
|
2018-04-06 10:20:32 +00:00
|
|
|
CU_ASSERT(rc == -EEXIST);
|
2017-10-24 02:51:49 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2019-01-22 08:47:24 +00:00
|
|
|
rc = spdk_lvol_create(lvs, "lvol2", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
|
|
|
|
NULL);
|
2017-10-24 02:51:49 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
lvol2 = g_lvol;
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(lvol, op_complete, NULL);
|
|
|
|
spdk_lvol_destroy(lvol, op_complete, NULL);
|
2017-10-24 02:51:49 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
g_lvol = NULL;
|
2019-01-22 08:47:24 +00:00
|
|
|
rc = spdk_lvol_create(lvs, "lvol", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
|
|
|
|
NULL);
|
2017-10-24 02:51:49 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
lvol = g_lvol;
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(lvol, op_complete, NULL);
|
|
|
|
spdk_lvol_destroy(lvol, op_complete, NULL);
|
2017-10-24 02:51:49 +00:00
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(lvol2, op_complete, NULL);
|
|
|
|
spdk_lvol_destroy(lvol2, op_complete, NULL);
|
2017-10-24 02:51:49 +00:00
|
|
|
|
2018-04-12 08:10:49 +00:00
|
|
|
/* Simulate creating two lvols with same name simultaneously. */
|
|
|
|
lvol = calloc(1, sizeof(*lvol));
|
|
|
|
SPDK_CU_ASSERT_FATAL(lvol != NULL);
|
|
|
|
snprintf(lvol->name, sizeof(lvol->name), "tmp_name");
|
|
|
|
TAILQ_INSERT_TAIL(&lvs->pending_lvols, lvol, link);
|
2019-01-22 08:47:24 +00:00
|
|
|
rc = spdk_lvol_create(lvs, "tmp_name", 1, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2018-04-12 08:10:49 +00:00
|
|
|
CU_ASSERT(rc == -EEXIST);
|
|
|
|
|
|
|
|
/* Remove name from temporary list and try again. */
|
|
|
|
TAILQ_REMOVE(&lvs->pending_lvols, lvol, link);
|
|
|
|
free(lvol);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
rc = spdk_lvol_create(lvs, "tmp_name", 1, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2018-04-12 08:10:49 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
lvol = g_lvol;
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(lvol, op_complete, NULL);
|
|
|
|
spdk_lvol_destroy(lvol, op_complete, NULL);
|
2018-04-12 08:10:49 +00:00
|
|
|
|
2017-10-24 02:51:49 +00:00
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_destroy(lvs, op_complete, NULL);
|
2017-10-24 02:51:49 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
2017-10-20 14:15:04 +00:00
|
|
|
}
|
2018-01-10 10:02:27 +00:00
|
|
|
|
|
|
|
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_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2018-01-10 10:02:27 +00:00
|
|
|
|
|
|
|
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;
|
2019-01-22 08:47:24 +00:00
|
|
|
rc = spdk_lvol_create(lvs, "lvol", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
|
|
|
|
NULL);
|
2018-01-10 10:02:27 +00:00
|
|
|
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;
|
2019-01-22 08:47:24 +00:00
|
|
|
rc = spdk_lvol_create(lvs, "lvol", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
|
|
|
|
NULL);
|
2018-04-06 10:20:32 +00:00
|
|
|
CU_ASSERT(rc == -EEXIST);
|
2018-01-10 10:02:27 +00:00
|
|
|
CU_ASSERT(g_lvserrno == -1);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol == NULL);
|
|
|
|
|
|
|
|
/* Trying to create second lvol with non existing name */
|
|
|
|
g_lvserrno = -1;
|
2019-01-22 08:47:24 +00:00
|
|
|
rc = spdk_lvol_create(lvs, "lvol2", 1, false, LVOL_CLEAR_WITH_DEFAULT, lvol_op_with_handle_complete,
|
|
|
|
NULL);
|
2018-01-10 10:02:27 +00:00
|
|
|
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 */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_rename(lvol, "lvol_new", op_complete, NULL);
|
2020-03-26 09:41:42 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2018-01-10 10:02:27 +00:00
|
|
|
CU_ASSERT_STRING_EQUAL(lvol->name, "lvol_new");
|
|
|
|
|
|
|
|
/* Trying to rename lvol with other lvol name */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_rename(lvol2, "lvol_new", op_complete, NULL);
|
2020-03-26 09:41:42 +00:00
|
|
|
CU_ASSERT(g_lvserrno == -EEXIST);
|
2018-01-10 10:02:27 +00:00
|
|
|
CU_ASSERT_STRING_NOT_EQUAL(lvol2->name, "lvol_new");
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(lvol, op_complete, NULL);
|
|
|
|
spdk_lvol_destroy(lvol, op_complete, NULL);
|
2018-01-10 10:02:27 +00:00
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(lvol2, op_complete, NULL);
|
|
|
|
spdk_lvol_destroy(lvol2, op_complete, NULL);
|
2018-01-10 10:02:27 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_destroy(lvs, op_complete, NULL);
|
2018-01-10 10:02:27 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
}
|
|
|
|
|
2018-01-10 10:03:39 +00:00
|
|
|
static void
|
|
|
|
lvs_rename(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
struct spdk_lvol_store *lvs, *lvs2;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
init_dev(&dev);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2018-01-10 10:03:39 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "unimportant_lvs_name");
|
2018-01-10 10:03:39 +00:00
|
|
|
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);
|
|
|
|
lvs2 = g_lvol_store;
|
|
|
|
|
|
|
|
/* Trying to rename lvs with new name */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvs_rename(lvs, "new_lvs_name", op_complete, NULL);
|
2018-01-10 10:03:39 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
CU_ASSERT_STRING_EQUAL(lvs->name, "new_lvs_name");
|
|
|
|
|
|
|
|
/* Trying to rename lvs with name lvs already has */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvs_rename(lvs, "new_lvs_name", op_complete, NULL);
|
2018-01-10 10:03:39 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
CU_ASSERT_STRING_EQUAL(lvs->name, "new_lvs_name");
|
|
|
|
|
|
|
|
/* Trying to rename lvs with name already existing */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvs_rename(lvs2, "new_lvs_name", op_complete, NULL);
|
2018-01-10 10:03:39 +00:00
|
|
|
CU_ASSERT(g_lvserrno == -EEXIST);
|
|
|
|
CU_ASSERT_STRING_EQUAL(lvs2->name, "unimportant_lvs_name");
|
|
|
|
|
|
|
|
/* Trying to rename lvs with another rename process started with the same name */
|
|
|
|
/* Simulate renaming process in progress */
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(lvs2->new_name, sizeof(lvs2->new_name), "another_new_lvs_name");
|
2018-01-10 10:03:39 +00:00
|
|
|
CU_ASSERT_STRING_EQUAL(lvs2->new_name, "another_new_lvs_name");
|
|
|
|
/* Start second process */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvs_rename(lvs, "another_new_lvs_name", op_complete, NULL);
|
2018-01-10 10:03:39 +00:00
|
|
|
CU_ASSERT(g_lvserrno == -EEXIST);
|
|
|
|
CU_ASSERT_STRING_EQUAL(lvs->name, "new_lvs_name");
|
|
|
|
/* reverting lvs2 new name to proper value */
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(lvs2->new_name, sizeof(lvs2->new_name), "unimportant_lvs_name");
|
2018-01-10 10:03:39 +00:00
|
|
|
CU_ASSERT_STRING_EQUAL(lvs2->new_name, "unimportant_lvs_name");
|
|
|
|
|
|
|
|
/* Simulate error while lvs rename */
|
|
|
|
g_lvs_rename_blob_open_error = true;
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvs_rename(lvs, "complete_new_lvs_name", op_complete, NULL);
|
2018-01-10 10:03:39 +00:00
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
|
|
|
CU_ASSERT_STRING_EQUAL(lvs->name, "new_lvs_name");
|
|
|
|
CU_ASSERT_STRING_EQUAL(lvs->new_name, "new_lvs_name");
|
|
|
|
g_lvs_rename_blob_open_error = false;
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_destroy(lvs, op_complete, NULL);
|
2018-01-10 10:03:39 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_destroy(lvs2, op_complete, NULL);
|
2018-01-10 10:03:39 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
}
|
2022-06-22 21:35:04 +00:00
|
|
|
static void
|
|
|
|
lvol_refcnt(void)
|
2017-10-25 12:57:07 +00:00
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvs_opts opts;
|
2018-08-30 16:02:52 +00:00
|
|
|
struct spdk_lvol *lvol;
|
2017-10-25 12:57:07 +00:00
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
init_dev(&dev);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2017-10-25 12:57:07 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2017-10-25 12:57:07 +00:00
|
|
|
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
CU_ASSERT(g_lvol->ref_count == 1);
|
|
|
|
|
2018-08-30 16:02:52 +00:00
|
|
|
lvol = g_lvol;
|
2017-10-25 12:57:07 +00:00
|
|
|
spdk_lvol_open(g_lvol, lvol_op_with_handle_complete, NULL);
|
2018-08-30 16:02:52 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
CU_ASSERT(lvol->ref_count == 2);
|
2017-10-25 12:57:07 +00:00
|
|
|
|
|
|
|
/* Trying to destroy lvol while its open should fail */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_destroy(lvol, op_complete, NULL);
|
2020-03-26 09:41:42 +00:00
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
2017-10-25 12:57:07 +00:00
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(lvol, op_complete, NULL);
|
2018-08-30 16:02:52 +00:00
|
|
|
CU_ASSERT(lvol->ref_count == 1);
|
2020-03-26 09:41:42 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2017-10-25 12:57:07 +00:00
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(lvol, op_complete, NULL);
|
2018-08-30 16:02:52 +00:00
|
|
|
CU_ASSERT(lvol->ref_count == 0);
|
2020-03-26 09:41:42 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2017-10-25 12:57:07 +00:00
|
|
|
|
|
|
|
/* Try to close already closed lvol */
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(lvol, op_complete, NULL);
|
2018-08-30 16:02:52 +00:00
|
|
|
CU_ASSERT(lvol->ref_count == 0);
|
2020-03-26 09:41:42 +00:00
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
2017-10-25 12:57:07 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2017-10-25 12:57:07 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
free_dev(&dev);
|
|
|
|
}
|
2017-10-20 14:15:04 +00:00
|
|
|
|
2018-01-26 13:33:27 +00:00
|
|
|
static void
|
|
|
|
lvol_create_thin_provisioned(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
init_dev(&dev);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
2018-04-09 23:08:34 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
2018-01-26 13:33:27 +00:00
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
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);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2018-01-26 13:33:27 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
|
|
|
CU_ASSERT(g_lvol->blob->thin_provisioned == false);
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
2018-01-26 13:33:27 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_destroy(g_lvol, op_complete, NULL);
|
2018-01-26 13:33:27 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2018-01-26 13:33:27 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
|
|
|
CU_ASSERT(g_lvol->blob->thin_provisioned == true);
|
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
2018-01-26 13:33:27 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_destroy(g_lvol, op_complete, NULL);
|
2018-01-26 13:33:27 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2018-01-26 13:33:27 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
free_dev(&dev);
|
|
|
|
}
|
2017-10-20 14:15:04 +00:00
|
|
|
|
2018-04-23 12:30:16 +00:00
|
|
|
static void
|
|
|
|
lvol_inflate(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
init_dev(&dev);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
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);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2018-04-23 12:30:16 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
|
|
|
g_inflate_rc = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_inflate(g_lvol, op_complete, NULL);
|
2020-03-26 09:41:42 +00:00
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
2018-04-23 12:30:16 +00:00
|
|
|
|
|
|
|
g_inflate_rc = 0;
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_inflate(g_lvol, op_complete, NULL);
|
2020-03-26 09:41:42 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2018-04-23 12:30:16 +00:00
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
2018-04-23 12:30:16 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_destroy(g_lvol, op_complete, NULL);
|
2018-04-23 12:30:16 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2018-04-23 12:30:16 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
free_dev(&dev);
|
|
|
|
|
|
|
|
/* Make sure that all references to the io_channel was closed after
|
|
|
|
* inflate call
|
|
|
|
*/
|
|
|
|
CU_ASSERT(g_io_channel == NULL);
|
|
|
|
}
|
|
|
|
|
2018-05-10 10:01:29 +00:00
|
|
|
static void
|
|
|
|
lvol_decouple_parent(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
init_dev(&dev);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
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);
|
|
|
|
|
2019-01-22 08:47:24 +00:00
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2018-05-10 10:01:29 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
|
|
|
g_inflate_rc = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_decouple_parent(g_lvol, op_complete, NULL);
|
2020-03-26 09:41:42 +00:00
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
2018-05-10 10:01:29 +00:00
|
|
|
|
|
|
|
g_inflate_rc = 0;
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_decouple_parent(g_lvol, op_complete, NULL);
|
2020-03-26 09:41:42 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2018-05-10 10:01:29 +00:00
|
|
|
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
2018-05-10 10:01:29 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
2020-03-26 09:54:19 +00:00
|
|
|
spdk_lvol_destroy(g_lvol, op_complete, NULL);
|
2018-05-10 10:01:29 +00:00
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
2020-03-26 09:54:19 +00:00
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
2018-05-10 10:01:29 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
free_dev(&dev);
|
|
|
|
|
|
|
|
/* Make sure that all references to the io_channel was closed after
|
|
|
|
* inflate call
|
|
|
|
*/
|
|
|
|
CU_ASSERT(g_io_channel == NULL);
|
|
|
|
}
|
|
|
|
|
2022-01-27 20:18:20 +00:00
|
|
|
static void
|
|
|
|
lvol_get_xattr(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
int rc = 0;
|
|
|
|
struct spdk_lvol *lvol;
|
|
|
|
const char *value = NULL;
|
|
|
|
size_t value_len = 0;
|
|
|
|
|
|
|
|
init_dev(&dev);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
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);
|
|
|
|
|
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
lvol = g_lvol;
|
|
|
|
|
|
|
|
/* Should be able to look up name */
|
|
|
|
lvol_get_xattr_value(lvol, "name", (const void **)&value, &value_len);
|
|
|
|
CU_ASSERT(value != NULL && strcmp(value, "lvol") == 0);
|
|
|
|
CU_ASSERT(value_len != 0);
|
|
|
|
|
|
|
|
/* Looking up something that doesn't exist should indicate non-existence */
|
|
|
|
lvol_get_xattr_value(lvol, "mumble", (const void **)&value, &value_len);
|
|
|
|
CU_ASSERT(value == NULL);
|
|
|
|
CU_ASSERT(value_len == 0);
|
|
|
|
|
|
|
|
/* Clean up */
|
|
|
|
spdk_lvol_close(lvol, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
spdk_lvol_destroy(lvol, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
free_dev(&dev);
|
|
|
|
}
|
|
|
|
|
2022-10-10 20:19:49 +00:00
|
|
|
struct spdk_bs_dev *g_esnap_bs_dev;
|
|
|
|
int g_esnap_bs_dev_errno = -ENOTSUP;
|
|
|
|
|
2022-10-12 20:01:10 +00:00
|
|
|
static int
|
|
|
|
ut_esnap_bs_dev_create(void *bs_ctx, void *blob_ctx, struct spdk_blob *blob,
|
|
|
|
const void *esnap_id, uint32_t id_len,
|
|
|
|
struct spdk_bs_dev **_bs_dev)
|
|
|
|
{
|
2022-10-10 20:19:49 +00:00
|
|
|
*_bs_dev = g_esnap_bs_dev;
|
|
|
|
return g_esnap_bs_dev_errno;
|
2022-10-12 20:01:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lvol_esnap_reload(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvs_with_handle_req *req;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
int rc;
|
|
|
|
|
2022-10-10 20:19:49 +00:00
|
|
|
g_esnap_bs_dev = NULL;
|
|
|
|
g_esnap_bs_dev_errno = -ENOTSUP;
|
|
|
|
|
2022-10-12 20:01:10 +00:00
|
|
|
req = calloc(1, sizeof(*req));
|
|
|
|
SPDK_CU_ASSERT_FATAL(req != NULL);
|
|
|
|
|
|
|
|
init_dev(&dev);
|
|
|
|
|
|
|
|
/* Create an lvstore with external snapshot support */
|
|
|
|
spdk_lvs_opts_init(&opts);
|
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
|
|
|
opts.esnap_bs_dev_create = ut_esnap_bs_dev_create;
|
|
|
|
g_lvserrno = -1;
|
|
|
|
rc = spdk_lvs_init(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
CU_ASSERT(dev.bs->esnap_bs_dev_create == ut_esnap_bs_dev_create);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
|
|
|
|
/* Unload the lvstore */
|
|
|
|
g_lvserrno = -1;
|
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
/* Load the lvstore with external snapshot support */
|
|
|
|
g_lvserrno = -1;
|
|
|
|
spdk_lvs_opts_init(&opts);
|
|
|
|
opts.esnap_bs_dev_create = ut_esnap_bs_dev_create;
|
|
|
|
spdk_lvs_load_ext(&dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
|
|
|
CU_ASSERT(dev.bs->esnap_bs_dev_create == ut_esnap_bs_dev_create);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
rc = spdk_lvs_destroy(g_lvol_store, op_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
free(req);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lvol_esnap_create_bad_args(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_bdev esnap_bdev;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
char long_name[SPDK_LVOL_NAME_MAX + 1];
|
|
|
|
int rc;
|
|
|
|
struct ut_cb_res lvres1, lvres2;
|
|
|
|
struct spdk_lvol *lvol;
|
|
|
|
char uuid_str[SPDK_UUID_STRING_LEN];
|
2023-04-18 04:20:26 +00:00
|
|
|
uint64_t block_sz, cluster_sz;
|
2022-10-12 20:01:10 +00:00
|
|
|
|
|
|
|
init_dev(&dev);
|
2023-04-18 04:20:26 +00:00
|
|
|
block_sz = dev.bs_dev.blocklen;
|
2022-10-12 20:01:10 +00:00
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
2023-04-18 04:20:26 +00:00
|
|
|
cluster_sz = opts.cluster_sz;
|
2022-10-12 20:01:10 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
|
|
|
opts.esnap_bs_dev_create = ut_esnap_bs_dev_create;
|
|
|
|
g_lvserrno = -1;
|
|
|
|
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);
|
|
|
|
|
|
|
|
init_bdev(&esnap_bdev, "bdev1", BS_CLUSTER_SIZE);
|
|
|
|
CU_ASSERT(spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &esnap_bdev.uuid) == 0);
|
|
|
|
MOCK_SET(spdk_bdev_get_by_name, &esnap_bdev);
|
|
|
|
|
|
|
|
/* error with lvs == NULL */
|
2023-04-18 04:20:26 +00:00
|
|
|
rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz, NULL, "clone1",
|
2022-10-12 20:01:10 +00:00
|
|
|
lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(rc == -EINVAL);
|
|
|
|
|
|
|
|
/* error with clone name that is too short */
|
2023-04-18 04:20:26 +00:00
|
|
|
rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz, g_lvol_store, "",
|
2022-10-12 20:01:10 +00:00
|
|
|
lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(rc == -EINVAL);
|
|
|
|
|
|
|
|
/* error with clone name that is too long */
|
|
|
|
memset(long_name, 'a', sizeof(long_name));
|
2023-04-18 04:20:26 +00:00
|
|
|
rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz, g_lvol_store,
|
|
|
|
long_name, lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(rc == -EINVAL);
|
|
|
|
|
|
|
|
/* error with size that is not a multiple of an integer multiple of cluster_sz */
|
|
|
|
CU_ASSERT(((cluster_sz + block_sz) % cluster_sz) != 0);
|
|
|
|
rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz + block_sz,
|
|
|
|
g_lvol_store, "clone1",
|
2022-10-12 20:01:10 +00:00
|
|
|
lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(rc == -EINVAL);
|
|
|
|
|
|
|
|
/* error when an lvol with that name already exists */
|
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
lvol = g_lvol;
|
2023-04-18 04:20:26 +00:00
|
|
|
rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz, g_lvol_store,
|
|
|
|
"lvol", lvol_op_with_handle_complete, NULL);
|
2022-10-12 20:01:10 +00:00
|
|
|
CU_ASSERT(rc == -EEXIST);
|
|
|
|
spdk_lvol_close(lvol, op_complete, ut_cb_res_clear(&lvres1));
|
|
|
|
spdk_lvol_destroy(lvol, op_complete, ut_cb_res_clear(&lvres2));
|
|
|
|
poll_threads();
|
|
|
|
CU_ASSERT(lvres1.err == 0);
|
|
|
|
CU_ASSERT(lvres2.err == 0);
|
|
|
|
g_lvol = NULL;
|
|
|
|
|
|
|
|
/* error when two clones created at the same time with the same name */
|
2023-04-18 04:20:26 +00:00
|
|
|
rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz, g_lvol_store,
|
|
|
|
"clone1", lvol_op_with_handle_complete,
|
|
|
|
ut_cb_res_clear(&lvres1));
|
|
|
|
rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz, g_lvol_store,
|
|
|
|
"clone1", lvol_op_with_handle_complete,
|
|
|
|
ut_cb_res_clear(&lvres2));
|
2022-10-12 20:01:10 +00:00
|
|
|
CU_ASSERT(rc == -EEXIST);
|
|
|
|
poll_threads();
|
|
|
|
CU_ASSERT(g_lvol != NULL);
|
|
|
|
CU_ASSERT(lvres1.err == 0);
|
|
|
|
CU_ASSERT(lvres2.err == 0xbad);
|
|
|
|
CU_ASSERT(TAILQ_EMPTY(&g_lvol_store->pending_lvols));
|
|
|
|
spdk_lvol_close(g_lvol, op_complete, ut_cb_res_clear(&lvres1));
|
|
|
|
spdk_lvol_destroy(g_lvol, op_complete, ut_cb_res_clear(&lvres2));
|
|
|
|
poll_threads();
|
|
|
|
CU_ASSERT(lvres1.err == 0);
|
|
|
|
CU_ASSERT(lvres2.err == 0);
|
|
|
|
g_lvol = NULL;
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
free_dev(&dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lvol_esnap_create_delete(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_bdev esnap_bdev;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
char uuid_str[SPDK_UUID_STRING_LEN];
|
|
|
|
int rc;
|
2023-04-18 04:20:26 +00:00
|
|
|
uint64_t cluster_sz;
|
2022-10-12 20:01:10 +00:00
|
|
|
|
|
|
|
init_dev(&dev);
|
|
|
|
init_dev(&g_esnap_dev);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
2023-04-18 04:20:26 +00:00
|
|
|
cluster_sz = opts.cluster_sz;
|
2022-10-12 20:01:10 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
|
|
|
opts.esnap_bs_dev_create = ut_esnap_bs_dev_create;
|
|
|
|
g_lvserrno = -1;
|
|
|
|
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);
|
|
|
|
|
|
|
|
g_lvserrno = 0xbad;
|
|
|
|
init_bdev(&esnap_bdev, "bdev1", BS_CLUSTER_SIZE);
|
|
|
|
CU_ASSERT(spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &esnap_bdev.uuid) == 0);
|
|
|
|
MOCK_SET(spdk_bdev_get_by_name, &esnap_bdev);
|
2023-04-18 04:20:26 +00:00
|
|
|
rc = spdk_lvol_create_esnap_clone(uuid_str, strlen(uuid_str), cluster_sz, g_lvol_store,
|
|
|
|
"clone1", lvol_op_with_handle_complete, NULL);
|
2022-10-12 20:01:10 +00:00
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
poll_threads();
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
MOCK_CLEAR(spdk_bdev_get_by_name);
|
|
|
|
|
|
|
|
g_lvserrno = 0xbad;
|
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvserrno = 0xbad;
|
|
|
|
spdk_lvol_destroy(g_lvol, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol = NULL;
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
rc = spdk_lvs_destroy(g_lvol_store, op_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
}
|
|
|
|
|
2022-10-10 20:19:49 +00:00
|
|
|
static void
|
|
|
|
lvol_esnap_load_esnaps(void)
|
|
|
|
{
|
|
|
|
struct spdk_blob blob = { .id = 42 };
|
|
|
|
struct spdk_lvol_store *lvs;
|
|
|
|
struct spdk_lvol *lvol;
|
|
|
|
struct spdk_bs_dev *bs_dev = NULL;
|
|
|
|
struct spdk_bs_dev esnap_bs_dev = { 0 };
|
|
|
|
int rc;
|
|
|
|
uint64_t esnap_id = 42;
|
|
|
|
|
|
|
|
lvs = lvs_alloc();
|
|
|
|
SPDK_CU_ASSERT_FATAL(lvs != NULL);
|
|
|
|
lvs->esnap_bs_dev_create = ut_esnap_bs_dev_create;
|
|
|
|
lvol = lvol_alloc(lvs, __func__, true, LVOL_CLEAR_WITH_DEFAULT);
|
|
|
|
SPDK_CU_ASSERT_FATAL(lvol != NULL);
|
|
|
|
|
|
|
|
/* Handle missing bs_ctx and blob_ctx gracefully */
|
|
|
|
rc = lvs_esnap_bs_dev_create(NULL, NULL, &blob, &esnap_id, sizeof(esnap_id), &bs_dev);
|
|
|
|
CU_ASSERT(rc == -EINVAL);
|
|
|
|
|
|
|
|
/* Do not try to load external snapshot when load_esnaps is false */
|
|
|
|
g_spdk_blob_get_esnap_id_called = false;
|
|
|
|
bs_dev = NULL;
|
|
|
|
rc = lvs_esnap_bs_dev_create(lvs, lvol, &blob, &esnap_id, sizeof(esnap_id), &bs_dev);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(bs_dev == NULL);
|
|
|
|
CU_ASSERT(!g_spdk_blob_get_esnap_id_called);
|
|
|
|
|
|
|
|
/* Same, with only lvs */
|
|
|
|
bs_dev = NULL;
|
|
|
|
rc = lvs_esnap_bs_dev_create(lvs, NULL, &blob, &esnap_id, sizeof(esnap_id), &bs_dev);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(bs_dev == NULL);
|
|
|
|
CU_ASSERT(!g_spdk_blob_get_esnap_id_called);
|
|
|
|
|
|
|
|
/* Same, with only lvol */
|
|
|
|
bs_dev = NULL;
|
|
|
|
rc = lvs_esnap_bs_dev_create(NULL, lvol, &blob, &esnap_id, sizeof(esnap_id), &bs_dev);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(bs_dev == NULL);
|
|
|
|
CU_ASSERT(!g_spdk_blob_get_esnap_id_called);
|
|
|
|
|
|
|
|
/* Happy path */
|
|
|
|
g_esnap_bs_dev = &esnap_bs_dev;
|
|
|
|
g_esnap_bs_dev_errno = 0;
|
|
|
|
|
|
|
|
lvs->load_esnaps = true;
|
|
|
|
ut_spdk_bdev_create_bs_dev_ro = 0;
|
|
|
|
g_spdk_blob_get_esnap_id_errno = 0;
|
|
|
|
bs_dev = NULL;
|
|
|
|
rc = lvs_esnap_bs_dev_create(lvs, lvol, &blob, &esnap_id, sizeof(esnap_id), &bs_dev);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
|
|
|
|
/* Clean up */
|
|
|
|
lvol_free(lvol);
|
|
|
|
lvs_free(lvs);
|
|
|
|
g_esnap_bs_dev = NULL;
|
|
|
|
g_esnap_bs_dev_errno = -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
2023-01-17 16:12:48 +00:00
|
|
|
struct ut_degraded_dev {
|
|
|
|
struct spdk_bs_dev bs_dev;
|
|
|
|
struct spdk_lvol *lvol;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
ut_destroy_degraded(struct spdk_bs_dev *ddev)
|
|
|
|
{
|
|
|
|
free(ddev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ut_create_degraded(struct spdk_lvol_store *lvs, struct spdk_lvol *lvol,
|
|
|
|
struct spdk_blob *blob, const char *name, struct spdk_bs_dev **bs_dev)
|
|
|
|
{
|
|
|
|
struct ut_degraded_dev *ddev;
|
|
|
|
|
|
|
|
ddev = calloc(1, sizeof(*ddev));
|
|
|
|
SPDK_CU_ASSERT_FATAL(ddev != NULL);
|
|
|
|
|
|
|
|
ddev->lvol = lvol;
|
|
|
|
ddev->bs_dev.destroy = ut_destroy_degraded;
|
|
|
|
ddev->bs_dev.blockcnt = UINT64_MAX / 512;
|
|
|
|
ddev->bs_dev.blocklen = 512;
|
|
|
|
*bs_dev = &ddev->bs_dev;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lvol_esnap_missing(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
struct spdk_blob blob = { .id = 42 };
|
|
|
|
struct ut_cb_res cb_res;
|
|
|
|
struct spdk_lvol_store *lvs;
|
|
|
|
struct spdk_lvol *lvol1, *lvol2;
|
|
|
|
struct spdk_bs_dev *bs_dev;
|
|
|
|
struct spdk_bdev esnap_bdev;
|
|
|
|
struct spdk_lvs_degraded_lvol_set *degraded_set;
|
|
|
|
const char *name1 = "lvol1";
|
|
|
|
const char *name2 = "lvol2";
|
|
|
|
char uuid_str[SPDK_UUID_STRING_LEN];
|
2023-04-18 04:20:26 +00:00
|
|
|
uint64_t cluster_sz;
|
2023-01-17 16:12:48 +00:00
|
|
|
int rc;
|
|
|
|
|
|
|
|
/* Create an lvstore */
|
|
|
|
init_dev(&dev);
|
|
|
|
spdk_lvs_opts_init(&opts);
|
2023-04-18 04:20:26 +00:00
|
|
|
cluster_sz = opts.cluster_sz;
|
2023-01-17 16:12:48 +00:00
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
|
|
|
g_lvserrno = -1;
|
|
|
|
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;
|
|
|
|
lvs->load_esnaps = true;
|
|
|
|
|
|
|
|
/* Pre-populate the lvstore with a degraded device */
|
|
|
|
lvol1 = lvol_alloc(lvs, name1, true, LVOL_CLEAR_WITH_DEFAULT);
|
|
|
|
SPDK_CU_ASSERT_FATAL(lvol1 != NULL);
|
|
|
|
lvol1->blob_id = blob.id;
|
|
|
|
TAILQ_REMOVE(&lvs->pending_lvols, lvol1, link);
|
|
|
|
TAILQ_INSERT_TAIL(&lvs->lvols, lvol1, link);
|
|
|
|
rc = ut_create_degraded(lvs, lvol1, &blob, name1, &bs_dev);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(bs_dev != NULL);
|
|
|
|
|
|
|
|
/* A clone with a missing external snapshot prevents a conflicting clone's creation */
|
|
|
|
init_bdev(&esnap_bdev, "bdev1", BS_CLUSTER_SIZE);
|
|
|
|
CU_ASSERT(spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &esnap_bdev.uuid) == 0);
|
|
|
|
MOCK_SET(spdk_bdev_get_by_name, &esnap_bdev);
|
2023-04-18 04:20:26 +00:00
|
|
|
rc = spdk_lvol_create_esnap_clone(uuid_str, sizeof(uuid_str), cluster_sz, g_lvol_store,
|
|
|
|
name1, lvol_op_with_handle_complete,
|
|
|
|
ut_cb_res_clear(&cb_res));
|
2023-01-17 16:12:48 +00:00
|
|
|
CU_ASSERT(rc == -EEXIST);
|
|
|
|
CU_ASSERT(ut_cb_res_untouched(&cb_res));
|
|
|
|
MOCK_CLEAR(spdk_bdev_get_by_name);
|
|
|
|
|
|
|
|
/* A clone with a missing external snapshot prevents a conflicting lvol's creation */
|
|
|
|
rc = spdk_lvol_create(lvs, name1, 10, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, ut_cb_res_clear(&cb_res));
|
|
|
|
CU_ASSERT(rc == -EEXIST);
|
|
|
|
CU_ASSERT(ut_cb_res_untouched(&cb_res));
|
|
|
|
|
|
|
|
/* Using a unique lvol name allows the clone to be created. */
|
|
|
|
MOCK_SET(spdk_bdev_get_by_name, &esnap_bdev);
|
|
|
|
MOCK_SET(spdk_blob_is_esnap_clone, true);
|
2023-04-18 04:20:26 +00:00
|
|
|
rc = spdk_lvol_create_esnap_clone(uuid_str, sizeof(uuid_str), cluster_sz, g_lvol_store,
|
|
|
|
name2, lvol_op_with_handle_complete,
|
|
|
|
ut_cb_res_clear(&cb_res));
|
2023-01-17 16:12:48 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(rc == 0);
|
|
|
|
CU_ASSERT(cb_res.err == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(cb_res.data != NULL);
|
|
|
|
lvol2 = cb_res.data;
|
|
|
|
CU_ASSERT(lvol2->degraded_set == NULL);
|
|
|
|
spdk_lvol_close(lvol2, op_complete, ut_cb_res_clear(&cb_res));
|
|
|
|
CU_ASSERT(cb_res.err == 0);
|
|
|
|
spdk_lvol_destroy(lvol2, op_complete, ut_cb_res_clear(&cb_res));
|
|
|
|
CU_ASSERT(cb_res.err == 0);
|
|
|
|
MOCK_CLEAR(spdk_blob_is_esnap_clone);
|
|
|
|
MOCK_CLEAR(spdk_bdev_get_by_name);
|
|
|
|
|
|
|
|
/* Destroying the esnap clone removes it from the degraded_set esnaps tree. */
|
|
|
|
spdk_lvol_destroy(lvol1, op_complete, ut_cb_res_clear(&cb_res));
|
|
|
|
CU_ASSERT(cb_res.err == 0);
|
|
|
|
CU_ASSERT(RB_EMPTY(&lvs->degraded_lvol_sets_tree));
|
|
|
|
bs_dev->destroy(bs_dev);
|
|
|
|
|
|
|
|
/* Create a missing device again */
|
|
|
|
lvol1 = lvol_alloc(lvs, name1, true, LVOL_CLEAR_WITH_DEFAULT);
|
|
|
|
SPDK_CU_ASSERT_FATAL(lvol1 != NULL);
|
|
|
|
lvol1->blob_id = blob.id;
|
|
|
|
TAILQ_REMOVE(&lvs->pending_lvols, lvol1, link);
|
|
|
|
TAILQ_INSERT_TAIL(&lvs->lvols, lvol1, link);
|
|
|
|
rc = ut_create_degraded(lvs, lvol1, &blob, name1, &bs_dev);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(bs_dev != NULL);
|
|
|
|
lvol1->blob = &blob;
|
|
|
|
rc = spdk_lvs_esnap_missing_add(lvs, lvol1, esnap_bdev.name, strlen(esnap_bdev.name) + 1);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
lvol1->ref_count = 1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Creating a snapshot of lvol1 makes lvol1 a clone of the new snapshot. What was a clone of
|
|
|
|
* the external snapshot is now a clone of the snapshot. The snapshot is a clone of the
|
|
|
|
* external snapshot. Now the snapshot is degraded_set its external snapshot.
|
|
|
|
*/
|
|
|
|
degraded_set = lvol1->degraded_set;
|
|
|
|
CU_ASSERT(degraded_set != NULL);
|
|
|
|
spdk_lvol_create_snapshot(lvol1, name2, lvol_op_with_handle_complete,
|
|
|
|
ut_cb_res_clear(&cb_res));
|
|
|
|
CU_ASSERT(cb_res.err == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(cb_res.data != NULL);
|
|
|
|
lvol2 = cb_res.data;
|
|
|
|
CU_ASSERT(lvol1->degraded_set == NULL);
|
|
|
|
CU_ASSERT(lvol2->degraded_set == degraded_set);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Removing the snapshot (lvol2) makes the first lvol (lvol1) back into a clone of an
|
|
|
|
* external snapshot.
|
|
|
|
*/
|
|
|
|
MOCK_SET(spdk_blob_is_esnap_clone, true);
|
|
|
|
g_spdk_blob_get_clones_snap_id = lvol2->blob_id;
|
|
|
|
g_spdk_blob_get_clones_ids = &lvol1->blob_id;
|
|
|
|
g_spdk_blob_get_clones_count = 1;
|
|
|
|
spdk_lvol_close(lvol2, op_complete, ut_cb_res_clear(&cb_res));
|
|
|
|
CU_ASSERT(cb_res.err == 0);
|
|
|
|
spdk_lvol_destroy(lvol2, op_complete, ut_cb_res_clear(&cb_res));
|
|
|
|
CU_ASSERT(cb_res.err == 0);
|
|
|
|
CU_ASSERT(lvol1->degraded_set == degraded_set);
|
|
|
|
g_spdk_blob_get_clones_snap_id = 0xbad;
|
|
|
|
g_spdk_blob_get_clones_ids = NULL;
|
|
|
|
g_spdk_blob_get_clones_count = 0;
|
|
|
|
|
|
|
|
/* Clean up */
|
|
|
|
spdk_lvol_close(lvol1, op_complete, ut_cb_res_clear(&cb_res));
|
|
|
|
CU_ASSERT(cb_res.err == 0);
|
|
|
|
spdk_lvol_destroy(lvol1, op_complete, ut_cb_res_clear(&cb_res));
|
|
|
|
CU_ASSERT(cb_res.err == 0);
|
|
|
|
bs_dev->destroy(bs_dev);
|
|
|
|
rc = spdk_lvs_destroy(g_lvol_store, op_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
MOCK_CLEAR(spdk_blob_is_esnap_clone);
|
|
|
|
}
|
|
|
|
|
2023-04-13 16:41:00 +00:00
|
|
|
struct hotplug_lvol {
|
|
|
|
/*
|
|
|
|
* These fields must be set before calling lvol_esnap_hotplug_scenario().
|
|
|
|
*/
|
|
|
|
char *lvol_name;
|
|
|
|
char *esnap_id;
|
|
|
|
/* How many times hotplug is expected to be called, likely 1. */
|
|
|
|
int expect_hp_count;
|
|
|
|
/* If not 0, return this during hotplug without registering esnap_dev. */
|
|
|
|
int hotplug_retval;
|
|
|
|
/* If true, call spdk_lvs_esnap_missing_add(), return 0, NULL bs_dev */
|
|
|
|
bool register_missing;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* These fields set are set by lvol_esnap_hotplug_scenario().
|
|
|
|
*/
|
|
|
|
struct spdk_lvol *lvol;
|
|
|
|
int id_len;
|
|
|
|
int hp_count;
|
|
|
|
bool created;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct missing_esnap {
|
|
|
|
char *esnap_id;
|
|
|
|
struct spdk_bs_dev *esnap_dev;
|
|
|
|
int expect_missing_lvol_count_after_create;
|
|
|
|
int expect_missing_lvol_count_after_hotplug;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Arrays. Terminate with a zeroed struct. */
|
|
|
|
struct hotplug_lvol *g_hotplug_lvols;
|
|
|
|
struct missing_esnap *g_missing_esnap;
|
|
|
|
|
|
|
|
static int
|
|
|
|
missing_get_lvol_count(struct spdk_lvol_store *lvs, char *esnap_id)
|
|
|
|
{
|
|
|
|
struct spdk_lvs_degraded_lvol_set find = { 0 };
|
|
|
|
struct spdk_lvs_degraded_lvol_set *found;
|
|
|
|
struct spdk_lvol *lvol;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
find.esnap_id = esnap_id;
|
|
|
|
find.id_len = strlen(esnap_id) + 1;
|
|
|
|
|
|
|
|
found = RB_FIND(degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree, &find);
|
|
|
|
if (found == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
TAILQ_FOREACH(lvol, &found->lvols, degraded_link) {
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct missing_esnap *
|
|
|
|
get_missing_esnap(struct missing_esnap *missing_esnap, const char *esnap_id)
|
|
|
|
{
|
|
|
|
for (; missing_esnap->esnap_id != NULL; missing_esnap++) {
|
|
|
|
if (strcmp(missing_esnap->esnap_id, esnap_id) == 0) {
|
|
|
|
return missing_esnap;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ut_esnap_hotplug_dev_create(void *bs_ctx, void *blob_ctx, struct spdk_blob *blob,
|
|
|
|
const void *esnap_id, uint32_t id_len, struct spdk_bs_dev **bs_dev)
|
|
|
|
{
|
|
|
|
struct spdk_lvol_store *lvs = bs_ctx;
|
|
|
|
struct spdk_lvol *lvol = blob_ctx;
|
|
|
|
struct hotplug_lvol *hp_lvol;
|
|
|
|
struct missing_esnap *missing_esnap;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
CU_ASSERT(lvs != NULL);
|
|
|
|
CU_ASSERT(lvol != NULL);
|
|
|
|
|
|
|
|
for (hp_lvol = g_hotplug_lvols; hp_lvol->lvol != NULL; hp_lvol++) {
|
|
|
|
if (hp_lvol->lvol->blob == lvol->blob) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (hp_lvol->lvol == NULL) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hp_lvol->created) {
|
|
|
|
hp_lvol->created = true;
|
|
|
|
rc = spdk_lvs_esnap_missing_add(lvs, lvol, hp_lvol->esnap_id, hp_lvol->id_len);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
*bs_dev = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
hp_lvol->hp_count++;
|
|
|
|
|
|
|
|
if (hp_lvol->hotplug_retval != 0) {
|
|
|
|
return hp_lvol->hotplug_retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
missing_esnap = get_missing_esnap(g_missing_esnap, esnap_id);
|
|
|
|
if (missing_esnap == NULL) {
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hp_lvol->register_missing) {
|
|
|
|
rc = spdk_lvs_esnap_missing_add(hp_lvol->lvol->lvol_store, hp_lvol->lvol,
|
|
|
|
hp_lvol->esnap_id, hp_lvol->id_len);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
*bs_dev = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
*bs_dev = missing_esnap->esnap_dev;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Creates an lvolstore with the specified esnap clone lvols. They are all initially missing their
|
|
|
|
* external snapshots, similar to what would happen if an lvolstore's device is examined before the
|
|
|
|
* devices that act as external snapshots. After the lvols are loaded, the blobstore is notified of
|
|
|
|
* each missing esnap (degraded_set).
|
|
|
|
*
|
|
|
|
* @param hotplug_lvols An array of esnap clone lvols to create. The array is terminated by zeroed
|
|
|
|
* element.
|
|
|
|
* @parm degraded_lvol_sets_tree An array of external snapshots that will be hotplugged. The array is
|
|
|
|
* terminated by a zeroed element.
|
|
|
|
* @desc Unused, but is very helpful when displaying stack traces in a debugger.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
lvol_esnap_hotplug_scenario(struct hotplug_lvol *hotplug_lvols,
|
|
|
|
struct missing_esnap *degraded_lvol_sets_tree,
|
|
|
|
char *desc)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
struct spdk_lvol_store *lvs;
|
|
|
|
struct spdk_lvs_degraded_lvol_set *degraded_set;
|
|
|
|
struct hotplug_lvol *hp_lvol;
|
|
|
|
struct missing_esnap *m_esnap;
|
|
|
|
int count;
|
|
|
|
int rc;
|
|
|
|
uint32_t num_failures = CU_get_number_of_failures();
|
|
|
|
|
|
|
|
g_hotplug_lvols = hotplug_lvols;
|
|
|
|
g_missing_esnap = degraded_lvol_sets_tree;
|
|
|
|
|
|
|
|
/* Create the lvstore */
|
|
|
|
init_dev(&dev);
|
|
|
|
spdk_lvs_opts_init(&opts);
|
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
|
|
|
g_lvserrno = -1;
|
|
|
|
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;
|
|
|
|
lvs->esnap_bs_dev_create = ut_esnap_hotplug_dev_create;
|
|
|
|
|
|
|
|
/* Create the lvols */
|
|
|
|
for (hp_lvol = hotplug_lvols; hp_lvol->lvol_name != NULL; hp_lvol++) {
|
|
|
|
if (hp_lvol->id_len == 0) {
|
|
|
|
hp_lvol->id_len = strlen(hp_lvol->esnap_id) + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_lvserrno = 0xbad;
|
|
|
|
rc = spdk_lvol_create_esnap_clone(hp_lvol->esnap_id, hp_lvol->id_len,
|
2023-04-18 04:20:26 +00:00
|
|
|
opts.cluster_sz, lvs, hp_lvol->lvol_name,
|
2023-04-13 16:41:00 +00:00
|
|
|
lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
poll_threads();
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
CU_ASSERT(g_lvol != NULL);
|
|
|
|
if (g_lvol == NULL) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
hp_lvol->lvol = g_lvol;
|
|
|
|
/* This is normally triggered by the blobstore in blob_load_esnap(), but that part
|
|
|
|
* of blobstore is not mocked by lvol_ut. Later commits will further exercise
|
|
|
|
* hotplug with a functional blobstore. See test/lvol/esnap/esnap.c and
|
|
|
|
* test/lvol/external_snapshot.sh in later commits.
|
|
|
|
*/
|
|
|
|
rc = ut_esnap_hotplug_dev_create(lvs, hp_lvol->lvol, hp_lvol->lvol->blob,
|
|
|
|
hp_lvol->esnap_id, hp_lvol->id_len,
|
|
|
|
&hp_lvol->lvol->blob->back_bs_dev);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Verify lvol count in lvs->degraded_lvol_sets_tree tree. */
|
|
|
|
for (m_esnap = degraded_lvol_sets_tree; m_esnap->esnap_id != NULL; m_esnap++) {
|
|
|
|
count = missing_get_lvol_count(lvs, m_esnap->esnap_id);
|
|
|
|
CU_ASSERT(m_esnap->expect_missing_lvol_count_after_create == count);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Verify lvs->degraded_lvol_sets_tree tree has nothing extra */
|
|
|
|
RB_FOREACH(degraded_set, degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree) {
|
|
|
|
m_esnap = get_missing_esnap(degraded_lvol_sets_tree, degraded_set->esnap_id);
|
|
|
|
CU_ASSERT(m_esnap != NULL);
|
|
|
|
if (m_esnap != NULL) {
|
|
|
|
count = missing_get_lvol_count(lvs, m_esnap->esnap_id);
|
|
|
|
CU_ASSERT(m_esnap->expect_missing_lvol_count_after_create == count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Perform hotplug */
|
|
|
|
for (m_esnap = degraded_lvol_sets_tree; m_esnap->esnap_id != NULL; m_esnap++) {
|
2023-01-30 18:13:06 +00:00
|
|
|
spdk_lvs_notify_hotplug(m_esnap->esnap_id, strlen(m_esnap->esnap_id) + 1,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
2023-04-13 16:41:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Verify lvol->degraded_set and back_bs_dev */
|
|
|
|
for (hp_lvol = hotplug_lvols; hp_lvol->lvol != NULL; hp_lvol++) {
|
|
|
|
if (hp_lvol->register_missing || hp_lvol->hotplug_retval != 0) {
|
|
|
|
CU_ASSERT(hp_lvol->lvol->degraded_set != NULL);
|
|
|
|
CU_ASSERT(hp_lvol->lvol->blob->back_bs_dev == NULL);
|
|
|
|
} else {
|
|
|
|
CU_ASSERT(hp_lvol->lvol->degraded_set == NULL);
|
|
|
|
m_esnap = get_missing_esnap(degraded_lvol_sets_tree, hp_lvol->esnap_id);
|
|
|
|
CU_ASSERT(m_esnap != NULL);
|
|
|
|
if (m_esnap != NULL) {
|
|
|
|
CU_ASSERT(hp_lvol->lvol->blob->back_bs_dev == m_esnap->esnap_dev);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Verify hotplug count on lvols */
|
|
|
|
for (hp_lvol = hotplug_lvols; hp_lvol->lvol != NULL; hp_lvol++) {
|
|
|
|
CU_ASSERT(hp_lvol->hp_count == 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Verify lvol count in lvs->degraded_lvol_sets_tree tree. */
|
|
|
|
for (m_esnap = degraded_lvol_sets_tree; m_esnap->esnap_id != NULL; m_esnap++) {
|
|
|
|
count = missing_get_lvol_count(lvs, m_esnap->esnap_id);
|
|
|
|
CU_ASSERT(m_esnap->expect_missing_lvol_count_after_hotplug == count);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Verify lvs->degraded_lvol_sets_tree tree has nothing extra */
|
|
|
|
RB_FOREACH(degraded_set, degraded_lvol_sets_tree, &lvs->degraded_lvol_sets_tree) {
|
|
|
|
m_esnap = get_missing_esnap(degraded_lvol_sets_tree, degraded_set->esnap_id);
|
|
|
|
CU_ASSERT(m_esnap != NULL);
|
|
|
|
if (m_esnap != NULL) {
|
|
|
|
count = missing_get_lvol_count(lvs, m_esnap->esnap_id);
|
|
|
|
CU_ASSERT(m_esnap->expect_missing_lvol_count_after_hotplug == count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Clean up */
|
|
|
|
for (hp_lvol = hotplug_lvols; hp_lvol->lvol != NULL; hp_lvol++) {
|
|
|
|
g_lvserrno = 0xbad;
|
|
|
|
spdk_lvol_close(hp_lvol->lvol, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvserrno = 0xbad;
|
|
|
|
spdk_lvol_destroy(hp_lvol->lvol, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
}
|
|
|
|
g_lvserrno = 0xabad;
|
|
|
|
rc = spdk_lvs_destroy(g_lvol_store, op_complete, NULL);
|
|
|
|
poll_threads();
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol = NULL;
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
return num_failures == CU_get_number_of_failures();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lvol_esnap_hotplug(void)
|
|
|
|
{
|
|
|
|
struct spdk_bs_dev bs_dev = { 0 };
|
|
|
|
struct spdk_bs_dev bs_dev2 = { 0 };
|
|
|
|
uint64_t i;
|
|
|
|
bool ok;
|
|
|
|
#define HOTPLUG_LVOL(_lvol_name, _esnap_id, _hotplug_retval, _register_missing) { \
|
|
|
|
.lvol_name = _lvol_name, \
|
|
|
|
.esnap_id = _esnap_id, \
|
|
|
|
.hotplug_retval = _hotplug_retval, \
|
|
|
|
.register_missing = _register_missing, \
|
|
|
|
}
|
|
|
|
#define MISSING_ESNAP(_esnap_id, _esnap_dev, _after_create, _after_hotplug) { \
|
|
|
|
.esnap_id = _esnap_id, \
|
|
|
|
.esnap_dev = _esnap_dev, \
|
|
|
|
.expect_missing_lvol_count_after_create = _after_create, \
|
|
|
|
.expect_missing_lvol_count_after_hotplug = _after_hotplug, \
|
|
|
|
}
|
|
|
|
struct {
|
|
|
|
char *desc;
|
|
|
|
struct hotplug_lvol h[4];
|
|
|
|
struct missing_esnap m[3];
|
|
|
|
} scenario[] = {
|
|
|
|
{
|
|
|
|
"one missing, happy path",
|
|
|
|
{ HOTPLUG_LVOL("lvol1", "esnap1", 0, false) },
|
|
|
|
{ MISSING_ESNAP("esnap1", &bs_dev, 1, 0) }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"one missing, cb registers degraded_set",
|
|
|
|
{ HOTPLUG_LVOL("lvol1", "esnap1", 0, true) },
|
|
|
|
{ MISSING_ESNAP("esnap1", &bs_dev, 1, 1) }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"one missing, cb retuns -ENOMEM",
|
|
|
|
{ HOTPLUG_LVOL("lvol1", "esnap1", -ENOMEM, true) },
|
|
|
|
{ MISSING_ESNAP("esnap1", &bs_dev, 1, 1) }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"two missing with same esnap, happy path",
|
|
|
|
{
|
|
|
|
HOTPLUG_LVOL("lvol1", "esnap1", 0, false),
|
|
|
|
HOTPLUG_LVOL("lvol2", "esnap1", 0, false)
|
|
|
|
},
|
|
|
|
{ MISSING_ESNAP("esnap1", &bs_dev, 2, 0) }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"two missing with same esnap, first -ENOMEM",
|
|
|
|
{
|
|
|
|
HOTPLUG_LVOL("lvol1", "esnap1", -ENOMEM, false),
|
|
|
|
HOTPLUG_LVOL("lvol2", "esnap1", 0, false)
|
|
|
|
},
|
|
|
|
{ MISSING_ESNAP("esnap1", &bs_dev, 2, 1) }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"two missing with same esnap, second -ENOMEM",
|
|
|
|
{
|
|
|
|
HOTPLUG_LVOL("lvol1", "esnap1", 0, false),
|
|
|
|
HOTPLUG_LVOL("lvol2", "esnap1", -ENOMEM, false)
|
|
|
|
},
|
|
|
|
{ MISSING_ESNAP("esnap1", &bs_dev, 2, 1) }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"two missing with different esnaps, happy path",
|
|
|
|
{
|
|
|
|
HOTPLUG_LVOL("lvol1", "esnap1", 0, false),
|
|
|
|
HOTPLUG_LVOL("lvol2", "esnap2", 0, false)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
MISSING_ESNAP("esnap1", &bs_dev, 1, 0),
|
|
|
|
MISSING_ESNAP("esnap2", &bs_dev2, 1, 0)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"two missing with different esnaps, first still missing",
|
|
|
|
{
|
|
|
|
HOTPLUG_LVOL("lvol1", "esnap1", 0, true),
|
|
|
|
HOTPLUG_LVOL("lvol2", "esnap2", 0, false)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
MISSING_ESNAP("esnap1", &bs_dev, 1, 1),
|
|
|
|
MISSING_ESNAP("esnap2", &bs_dev2, 1, 0)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"three missing with same esnap, happy path",
|
|
|
|
{
|
|
|
|
HOTPLUG_LVOL("lvol1", "esnap1", 0, false),
|
|
|
|
HOTPLUG_LVOL("lvol2", "esnap1", 0, false),
|
|
|
|
HOTPLUG_LVOL("lvol3", "esnap1", 0, false)
|
|
|
|
},
|
|
|
|
{ MISSING_ESNAP("esnap1", &bs_dev, 3, 0) }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"three missing with same esnap, first still missing",
|
|
|
|
{
|
|
|
|
HOTPLUG_LVOL("lvol1", "esnap1", 0, true),
|
|
|
|
HOTPLUG_LVOL("lvol2", "esnap1", 0, false),
|
|
|
|
HOTPLUG_LVOL("lvol3", "esnap1", 0, false)
|
|
|
|
},
|
|
|
|
{ MISSING_ESNAP("esnap1", &bs_dev, 3, 1) }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"three missing with same esnap, first two still missing",
|
|
|
|
{
|
|
|
|
HOTPLUG_LVOL("lvol1", "esnap1", 0, true),
|
|
|
|
HOTPLUG_LVOL("lvol2", "esnap1", 0, true),
|
|
|
|
HOTPLUG_LVOL("lvol3", "esnap1", 0, false)
|
|
|
|
},
|
|
|
|
{ MISSING_ESNAP("esnap1", &bs_dev, 3, 2) }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"three missing with same esnap, middle still missing",
|
|
|
|
{
|
|
|
|
HOTPLUG_LVOL("lvol1", "esnap1", 0, false),
|
|
|
|
HOTPLUG_LVOL("lvol2", "esnap1", 0, true),
|
|
|
|
HOTPLUG_LVOL("lvol3", "esnap1", 0, false)
|
|
|
|
},
|
|
|
|
{ MISSING_ESNAP("esnap1", &bs_dev, 3, 1) }
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"three missing with same esnap, last still missing",
|
|
|
|
{
|
|
|
|
HOTPLUG_LVOL("lvol1", "esnap1", 0, false),
|
|
|
|
HOTPLUG_LVOL("lvol2", "esnap1", 0, false),
|
|
|
|
HOTPLUG_LVOL("lvol3", "esnap1", 0, true)
|
|
|
|
},
|
|
|
|
{ MISSING_ESNAP("esnap1", &bs_dev, 3, 1) }
|
|
|
|
},
|
|
|
|
};
|
|
|
|
#undef HOTPLUG_LVOL
|
|
|
|
#undef MISSING_ESNAP
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
for (i = 0; i < SPDK_COUNTOF(scenario); i++) {
|
|
|
|
ok = lvol_esnap_hotplug_scenario(scenario[i].h, scenario[i].m, scenario[i].desc);
|
|
|
|
/* Add markers in the output to help correlate failures to scenarios. */
|
|
|
|
CU_ASSERT(ok);
|
|
|
|
printf("\t%s scenario %" PRIu64 ": %s - %s\n", __func__, i,
|
|
|
|
ok ? "PASS" : "FAIL", scenario[i].desc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-11 22:02:42 +00:00
|
|
|
static void
|
|
|
|
lvol_get_by(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev dev1, dev2;
|
|
|
|
struct spdk_lvol_store *lvs1, *lvs2;
|
|
|
|
struct spdk_lvol *lvol1, *lvol2, *lvol3;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
int rc = 0;
|
|
|
|
struct spdk_uuid uuid;
|
|
|
|
|
|
|
|
init_dev(&dev1);
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
rc = spdk_lvs_init(&dev1.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);
|
|
|
|
lvs1 = g_lvol_store;
|
|
|
|
|
|
|
|
/* Create lvol name "lvol" */
|
|
|
|
spdk_lvol_create(lvs1, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
lvol1 = g_lvol;
|
|
|
|
|
|
|
|
/* Should be able to look up lvol1 by its name and UUID */
|
|
|
|
CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvol") == lvol1);
|
|
|
|
/* Be sure a pointer comparison isn't used. */
|
|
|
|
memcpy(&uuid, &lvol1->uuid, sizeof(uuid));
|
|
|
|
CU_ASSERT(spdk_lvol_get_by_uuid(&uuid) == lvol1);
|
|
|
|
|
|
|
|
/* Shorter and longer values for lvol_name must not match. */
|
|
|
|
CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvoll") == NULL);
|
|
|
|
CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvo") == NULL);
|
|
|
|
|
|
|
|
/* Shorter and longer values for lvs_name must not match. */
|
|
|
|
CU_ASSERT(spdk_lvol_get_by_names("lvss", "lvol") == NULL);
|
|
|
|
CU_ASSERT(spdk_lvol_get_by_names("lv", "lvol") == NULL);
|
|
|
|
|
|
|
|
/* Create lvol name "lvol2" */
|
|
|
|
spdk_lvol_create(lvs1, "lvol2", 10, true, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
lvol2 = g_lvol;
|
|
|
|
|
|
|
|
/* When there are multiple lvols, the right one is found */
|
|
|
|
CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvol") == lvol1);
|
|
|
|
CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvol2") == lvol2);
|
|
|
|
|
|
|
|
/* Create a second lvolstore */
|
|
|
|
init_dev(&dev2);
|
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs2");
|
|
|
|
g_lvserrno = -1;
|
|
|
|
rc = spdk_lvs_init(&dev2.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);
|
|
|
|
lvs2 = g_lvol_store;
|
|
|
|
|
|
|
|
/* Lookups that worked with one lvstore still work */
|
|
|
|
memcpy(&uuid, &lvol1->uuid, sizeof(uuid));
|
|
|
|
CU_ASSERT(spdk_lvol_get_by_uuid(&uuid) == lvol1);
|
|
|
|
CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvol") == lvol1);
|
|
|
|
CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvol2") == lvol2);
|
|
|
|
|
|
|
|
/* Add an lvol name "lvol" in the second lvstore */
|
|
|
|
spdk_lvol_create(lvs2, "lvol", 10, true, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
lvol3 = g_lvol;
|
|
|
|
|
|
|
|
/* Lookups by name find the lvols in the right lvstores */
|
|
|
|
CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvol") == lvol1);
|
|
|
|
CU_ASSERT(spdk_lvol_get_by_names("lvs", "lvol2") == lvol2);
|
|
|
|
CU_ASSERT(spdk_lvol_get_by_names("lvs2", "lvol") == lvol3);
|
|
|
|
|
|
|
|
/* Clean up */
|
|
|
|
g_lvserrno = -1;
|
|
|
|
spdk_lvol_close(lvol1, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
spdk_lvol_close(lvol2, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
spdk_lvol_close(lvol3, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
rc = spdk_lvs_unload(lvs1, op_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
rc = spdk_lvs_unload(lvs2, op_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
g_lvol = NULL;
|
|
|
|
|
|
|
|
free_dev(&dev1);
|
|
|
|
free_dev(&dev2);
|
|
|
|
}
|
|
|
|
|
2023-02-15 16:57:44 +00:00
|
|
|
static void
|
|
|
|
lvol_shallow_copy(void)
|
|
|
|
{
|
|
|
|
struct lvol_ut_bs_dev bs_dev;
|
|
|
|
struct spdk_lvs_opts opts;
|
|
|
|
struct spdk_bs_dev ext_dev;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
init_dev(&bs_dev);
|
|
|
|
|
|
|
|
ext_dev.blocklen = DEV_BUFFER_BLOCKLEN;
|
|
|
|
ext_dev.blockcnt = BS_CLUSTER_SIZE / DEV_BUFFER_BLOCKLEN;
|
|
|
|
|
|
|
|
spdk_lvs_opts_init(&opts);
|
|
|
|
snprintf(opts.name, sizeof(opts.name), "lvs");
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
rc = spdk_lvs_init(&bs_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);
|
|
|
|
|
|
|
|
spdk_lvol_create(g_lvol_store, "lvol", BS_CLUSTER_SIZE, false, LVOL_CLEAR_WITH_DEFAULT,
|
|
|
|
lvol_op_with_handle_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
|
|
|
|
|
|
|
/* Successful shallow copy */
|
|
|
|
g_blob_read_only = true;
|
|
|
|
spdk_lvol_shallow_copy(g_lvol, &ext_dev, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
/* Shallow copy with null lvol */
|
|
|
|
spdk_lvol_shallow_copy(NULL, &ext_dev, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
|
|
|
|
|
|
|
/* Shallow copy with null ext_dev */
|
|
|
|
spdk_lvol_shallow_copy(g_lvol, NULL, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
|
|
|
|
|
|
|
/* Shallow copy with invalid ext_dev size */
|
|
|
|
ext_dev.blockcnt = 1;
|
|
|
|
spdk_lvol_shallow_copy(g_lvol, &ext_dev, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
|
|
|
|
|
|
|
/* Shallow copy with writable lvol */
|
|
|
|
g_blob_read_only = false;
|
|
|
|
spdk_lvol_shallow_copy(g_lvol, &ext_dev, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno != 0);
|
|
|
|
|
|
|
|
spdk_lvol_close(g_lvol, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
spdk_lvol_destroy(g_lvol, op_complete, NULL);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
|
|
|
|
g_lvserrno = -1;
|
|
|
|
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
|
|
|
CU_ASSERT(rc == 0);
|
|
|
|
CU_ASSERT(g_lvserrno == 0);
|
|
|
|
g_lvol_store = NULL;
|
|
|
|
|
|
|
|
free_dev(&bs_dev);
|
|
|
|
|
|
|
|
/* Make sure that all references to the io_channel was closed after
|
|
|
|
* shallow copy call
|
|
|
|
*/
|
|
|
|
CU_ASSERT(g_io_channel == NULL);
|
|
|
|
}
|
|
|
|
|
2022-06-22 21:35:04 +00:00
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
2017-09-14 14:53:36 +00:00
|
|
|
{
|
|
|
|
CU_pSuite suite = NULL;
|
|
|
|
unsigned int num_failures;
|
|
|
|
|
2020-03-26 10:28:29 +00:00
|
|
|
CU_set_error_action(CUEA_ABORT);
|
|
|
|
CU_initialize_registry();
|
2017-09-14 14:53:36 +00:00
|
|
|
|
|
|
|
suite = CU_add_suite("lvol", NULL, NULL);
|
|
|
|
|
2020-03-26 10:28:29 +00:00
|
|
|
CU_ADD_TEST(suite, lvs_init_unload_success);
|
|
|
|
CU_ADD_TEST(suite, lvs_init_destroy_success);
|
|
|
|
CU_ADD_TEST(suite, lvs_init_opts_success);
|
|
|
|
CU_ADD_TEST(suite, lvs_unload_lvs_is_null_fail);
|
|
|
|
CU_ADD_TEST(suite, lvs_names);
|
|
|
|
CU_ADD_TEST(suite, lvol_create_destroy_success);
|
|
|
|
CU_ADD_TEST(suite, lvol_create_fail);
|
|
|
|
CU_ADD_TEST(suite, lvol_destroy_fail);
|
|
|
|
CU_ADD_TEST(suite, lvol_close_fail);
|
|
|
|
CU_ADD_TEST(suite, lvol_close_success);
|
|
|
|
CU_ADD_TEST(suite, lvol_resize);
|
|
|
|
CU_ADD_TEST(suite, lvol_set_read_only);
|
2022-10-12 20:01:10 +00:00
|
|
|
CU_ADD_TEST(suite, test_lvs_load);
|
2020-03-26 10:28:29 +00:00
|
|
|
CU_ADD_TEST(suite, lvols_load);
|
|
|
|
CU_ADD_TEST(suite, lvol_open);
|
|
|
|
CU_ADD_TEST(suite, lvol_snapshot);
|
|
|
|
CU_ADD_TEST(suite, lvol_snapshot_fail);
|
|
|
|
CU_ADD_TEST(suite, lvol_clone);
|
|
|
|
CU_ADD_TEST(suite, lvol_clone_fail);
|
2023-04-11 04:41:15 +00:00
|
|
|
CU_ADD_TEST(suite, lvol_iter_clones);
|
2020-03-26 10:28:29 +00:00
|
|
|
CU_ADD_TEST(suite, lvol_refcnt);
|
|
|
|
CU_ADD_TEST(suite, lvol_names);
|
|
|
|
CU_ADD_TEST(suite, lvol_create_thin_provisioned);
|
|
|
|
CU_ADD_TEST(suite, lvol_rename);
|
|
|
|
CU_ADD_TEST(suite, lvs_rename);
|
|
|
|
CU_ADD_TEST(suite, lvol_inflate);
|
|
|
|
CU_ADD_TEST(suite, lvol_decouple_parent);
|
2022-01-27 20:18:20 +00:00
|
|
|
CU_ADD_TEST(suite, lvol_get_xattr);
|
2022-10-12 20:01:10 +00:00
|
|
|
CU_ADD_TEST(suite, lvol_esnap_reload);
|
|
|
|
CU_ADD_TEST(suite, lvol_esnap_create_bad_args);
|
|
|
|
CU_ADD_TEST(suite, lvol_esnap_create_delete);
|
2022-10-10 20:19:49 +00:00
|
|
|
CU_ADD_TEST(suite, lvol_esnap_load_esnaps);
|
2023-01-17 16:12:48 +00:00
|
|
|
CU_ADD_TEST(suite, lvol_esnap_missing);
|
2023-04-13 16:41:00 +00:00
|
|
|
CU_ADD_TEST(suite, lvol_esnap_hotplug);
|
2023-04-11 22:02:42 +00:00
|
|
|
CU_ADD_TEST(suite, lvol_get_by);
|
2023-02-15 16:57:44 +00:00
|
|
|
CU_ADD_TEST(suite, lvol_shallow_copy);
|
2017-09-14 14:53:36 +00:00
|
|
|
|
2018-08-15 21:02:38 +00:00
|
|
|
allocate_threads(1);
|
|
|
|
set_thread(0);
|
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
CU_basic_set_mode(CU_BRM_VERBOSE);
|
|
|
|
CU_basic_run_tests();
|
|
|
|
num_failures = CU_get_number_of_failures();
|
|
|
|
CU_cleanup_registry();
|
|
|
|
|
2018-08-15 21:02:38 +00:00
|
|
|
free_threads();
|
|
|
|
|
2017-09-14 14:53:36 +00:00
|
|
|
return num_failures;
|
|
|
|
}
|