vbdev_lvol: allow creation of esnap clones
This adds the ability for create esnap clone lvol bdevs. Signed-off-by: Mike Gerdts <mgerdts@nvidia.com> Change-Id: Ifeef983430153d84d896d282fe914c6671283762 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16590 Reviewed-by: Ben Walker <benjamin.walker@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
f5e42c6c3f
commit
be54ccc4a9
@ -1144,6 +1144,82 @@ vbdev_lvol_create_clone(struct spdk_lvol *lvol, const char *clone_name,
|
|||||||
spdk_lvol_create_clone(lvol, clone_name, _vbdev_lvol_create_cb, req);
|
spdk_lvol_create_clone(lvol, clone_name, _vbdev_lvol_create_cb, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ignore_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *ctx)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vbdev_lvol_create_bdev_clone(const char *esnap_uuid,
|
||||||
|
struct spdk_lvol_store *lvs, const char *clone_name,
|
||||||
|
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
|
||||||
|
{
|
||||||
|
struct spdk_lvol_with_handle_req *req;
|
||||||
|
struct spdk_bdev_desc *desc;
|
||||||
|
struct spdk_bdev *bdev;
|
||||||
|
char bdev_uuid[SPDK_UUID_STRING_LEN];
|
||||||
|
struct spdk_uuid uuid;
|
||||||
|
uint64_t sz;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (lvs == NULL) {
|
||||||
|
SPDK_ERRLOG("lvol store not specified\n");
|
||||||
|
cb_fn(cb_arg, NULL, -EINVAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = spdk_uuid_parse(&uuid, esnap_uuid);
|
||||||
|
if (rc != 0) {
|
||||||
|
SPDK_ERRLOG("Invalid UUID '%s'\n", esnap_uuid);
|
||||||
|
cb_fn(cb_arg, NULL, -EINVAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = spdk_bdev_open_ext(esnap_uuid, false, ignore_bdev_event_cb, NULL, &desc);
|
||||||
|
if (rc != 0) {
|
||||||
|
SPDK_ERRLOG("bdev '%s' could not be opened: error %d\n", esnap_uuid, rc);
|
||||||
|
cb_fn(cb_arg, NULL, rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bdev = spdk_bdev_desc_get_bdev(desc);
|
||||||
|
|
||||||
|
rc = spdk_uuid_fmt_lower(bdev_uuid, sizeof(bdev_uuid), spdk_bdev_get_uuid(bdev));
|
||||||
|
if (rc != 0) {
|
||||||
|
spdk_bdev_close(desc);
|
||||||
|
SPDK_ERRLOG("bdev %s: unable to parse UUID\n", esnap_uuid);
|
||||||
|
assert(false);
|
||||||
|
cb_fn(cb_arg, NULL, -ENODEV);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify the bdev name or alias isn't a UUID that is different from the bdev's UUID. */
|
||||||
|
if (spdk_uuid_compare(&uuid, spdk_bdev_get_uuid(bdev)) != 0) {
|
||||||
|
spdk_bdev_close(desc);
|
||||||
|
SPDK_ERRLOG("bdev with name or alias %s has UUID %s\n", esnap_uuid, bdev_uuid);
|
||||||
|
cb_fn(cb_arg, NULL, -EINVAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
req = calloc(1, sizeof(*req));
|
||||||
|
if (req == NULL) {
|
||||||
|
spdk_bdev_close(desc);
|
||||||
|
cb_fn(cb_arg, NULL, -ENOMEM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
req->cb_fn = cb_fn;
|
||||||
|
req->cb_arg = cb_arg;
|
||||||
|
|
||||||
|
sz = spdk_bdev_get_num_blocks(bdev) * spdk_bdev_get_block_size(bdev);
|
||||||
|
rc = spdk_lvol_create_esnap_clone(bdev_uuid, sizeof(bdev_uuid), sz, lvs, clone_name,
|
||||||
|
_vbdev_lvol_create_cb, req);
|
||||||
|
spdk_bdev_close(desc);
|
||||||
|
if (rc != 0) {
|
||||||
|
cb_fn(cb_arg, NULL, rc);
|
||||||
|
free(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_vbdev_lvol_rename_cb(void *cb_arg, int lvolerrno)
|
_vbdev_lvol_rename_cb(void *cb_arg, int lvolerrno)
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: BSD-3-Clause
|
/* SPDX-License-Identifier: BSD-3-Clause
|
||||||
* Copyright (C) 2017 Intel Corporation.
|
* Copyright (C) 2017 Intel Corporation.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
* Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
* Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SPDK_VBDEV_LVOL_H
|
#ifndef SPDK_VBDEV_LVOL_H
|
||||||
@ -42,6 +42,9 @@ void vbdev_lvol_create_snapshot(struct spdk_lvol *lvol, const char *snapshot_nam
|
|||||||
|
|
||||||
void vbdev_lvol_create_clone(struct spdk_lvol *lvol, const char *clone_name,
|
void vbdev_lvol_create_clone(struct spdk_lvol *lvol, const char *clone_name,
|
||||||
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg);
|
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg);
|
||||||
|
void vbdev_lvol_create_bdev_clone(const char *esnap_uuid,
|
||||||
|
struct spdk_lvol_store *lvs, const char *clone_name,
|
||||||
|
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Change size of lvol
|
* \brief Change size of lvol
|
||||||
|
@ -304,6 +304,20 @@ spdk_blob_is_thin_provisioned(struct spdk_blob *blob)
|
|||||||
|
|
||||||
static struct spdk_lvol *_lvol_create(struct spdk_lvol_store *lvs);
|
static struct spdk_lvol *_lvol_create(struct spdk_lvol_store *lvs);
|
||||||
|
|
||||||
|
int
|
||||||
|
spdk_lvol_create_esnap_clone(const void *esnap_id, uint32_t id_len, uint64_t size_bytes,
|
||||||
|
struct spdk_lvol_store *lvs, const char *clone_name,
|
||||||
|
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
|
||||||
|
{
|
||||||
|
struct spdk_lvol *lvol;
|
||||||
|
|
||||||
|
lvol = _lvol_create(lvs);
|
||||||
|
snprintf(lvol->name, sizeof(lvol->name), "%s", clone_name);
|
||||||
|
|
||||||
|
cb_fn(cb_arg, lvol, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lvs_load(struct spdk_bs_dev *dev, const struct spdk_lvs_opts *lvs_opts,
|
lvs_load(struct spdk_bs_dev *dev, const struct spdk_lvs_opts *lvs_opts,
|
||||||
spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg)
|
spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg)
|
||||||
@ -575,6 +589,44 @@ spdk_bdev_get_by_name(const char *bdev_name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct spdk_bdev_desc {
|
||||||
|
struct spdk_bdev *bdev;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb,
|
||||||
|
void *event_ctx, struct spdk_bdev_desc **_desc)
|
||||||
|
{
|
||||||
|
struct spdk_bdev_desc *desc;
|
||||||
|
struct spdk_bdev *bdev;
|
||||||
|
|
||||||
|
bdev = spdk_bdev_get_by_name(bdev_name);
|
||||||
|
if (bdev == NULL) {
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc = calloc(1, sizeof(*desc));
|
||||||
|
if (desc == NULL) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc->bdev = bdev;
|
||||||
|
*_desc = desc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spdk_bdev_close(struct spdk_bdev_desc *desc)
|
||||||
|
{
|
||||||
|
free(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct spdk_bdev *
|
||||||
|
spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc)
|
||||||
|
{
|
||||||
|
return desc->bdev;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
spdk_lvol_close(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
|
spdk_lvol_close(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
|
||||||
{
|
{
|
||||||
@ -739,6 +791,18 @@ spdk_bdev_get_name(const struct spdk_bdev *bdev)
|
|||||||
return bdev->name;
|
return bdev->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
spdk_bdev_get_block_size(const struct spdk_bdev *bdev)
|
||||||
|
{
|
||||||
|
return bdev->blocklen;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
spdk_bdev_get_num_blocks(const struct spdk_bdev *bdev)
|
||||||
|
{
|
||||||
|
return bdev->blockcnt;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
spdk_bdev_register(struct spdk_bdev *vbdev)
|
spdk_bdev_register(struct spdk_bdev *vbdev)
|
||||||
{
|
{
|
||||||
@ -1756,6 +1820,64 @@ ut_esnap_dev_create(void)
|
|||||||
free(unterminated);
|
free(unterminated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ut_lvol_esnap_clone_bad_args(void)
|
||||||
|
{
|
||||||
|
struct spdk_bdev bdev = { 0 };
|
||||||
|
struct spdk_lvol_store *lvs;
|
||||||
|
const char *esnap_uuid = "255f4236-9427-42d0-a9d1-aa17f37dd8db";
|
||||||
|
const char *name_uuid = "5c164b0a-93af-434f-ac35-51af59791f3b";
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Lvol store is successfully created */
|
||||||
|
rc = vbdev_lvs_create("bdev", "lvs", 0, LVS_CLEAR_WITH_UNMAP, 0,
|
||||||
|
lvol_store_op_with_handle_complete, NULL);
|
||||||
|
CU_ASSERT(rc == 0);
|
||||||
|
CU_ASSERT(g_lvserrno == 0);
|
||||||
|
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
||||||
|
CU_ASSERT(g_lvol_store->bs_dev != NULL);
|
||||||
|
lvs = g_lvol_store;
|
||||||
|
|
||||||
|
rc = spdk_uuid_parse(&bdev.uuid, esnap_uuid);
|
||||||
|
CU_ASSERT(rc == 0);
|
||||||
|
bdev.name = strdup(name_uuid);
|
||||||
|
SPDK_CU_ASSERT_FATAL(bdev.name != NULL);
|
||||||
|
bdev.blocklen = 512;
|
||||||
|
bdev.blockcnt = 8192;
|
||||||
|
|
||||||
|
g_base_bdev = &bdev;
|
||||||
|
|
||||||
|
/* Error when lvs is NULL */
|
||||||
|
g_lvolerrno = 0xbad;
|
||||||
|
vbdev_lvol_create_bdev_clone(esnap_uuid, NULL, "clone1", vbdev_lvol_create_complete, NULL);
|
||||||
|
CU_ASSERT(g_lvolerrno == -EINVAL);
|
||||||
|
|
||||||
|
/* Error when a uuid-like name is provided and that matches the bdev name but not uuid */
|
||||||
|
g_lvolerrno = 0xbad;
|
||||||
|
vbdev_lvol_create_bdev_clone(name_uuid, lvs, "clone1", vbdev_lvol_create_complete, NULL);
|
||||||
|
CU_ASSERT(g_lvolerrno == -EINVAL);
|
||||||
|
|
||||||
|
/* Error when the bdev does not exist */
|
||||||
|
g_base_bdev = NULL;
|
||||||
|
g_lvolerrno = 0xbad;
|
||||||
|
vbdev_lvol_create_bdev_clone(esnap_uuid, lvs, "clone1", vbdev_lvol_create_complete, NULL);
|
||||||
|
CU_ASSERT(g_lvolerrno == -ENODEV);
|
||||||
|
|
||||||
|
/* Success when the stars all align. */
|
||||||
|
g_base_bdev = &bdev;
|
||||||
|
g_lvolerrno = 0xbad;
|
||||||
|
vbdev_lvol_create_bdev_clone(esnap_uuid, lvs, "clone1", vbdev_lvol_create_complete, NULL);
|
||||||
|
CU_ASSERT(g_lvolerrno == 0);
|
||||||
|
|
||||||
|
g_lvol_store = lvs;
|
||||||
|
vbdev_lvs_destruct(g_lvol_store, lvol_store_op_complete, NULL);
|
||||||
|
CU_ASSERT(g_lvserrno == 0);
|
||||||
|
CU_ASSERT(g_lvol_store == NULL);
|
||||||
|
|
||||||
|
free(bdev.name);
|
||||||
|
g_base_bdev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -1786,6 +1908,7 @@ main(int argc, char **argv)
|
|||||||
CU_ADD_TEST(suite, ut_lvs_rename);
|
CU_ADD_TEST(suite, ut_lvs_rename);
|
||||||
CU_ADD_TEST(suite, ut_lvol_seek);
|
CU_ADD_TEST(suite, ut_lvol_seek);
|
||||||
CU_ADD_TEST(suite, ut_esnap_dev_create);
|
CU_ADD_TEST(suite, ut_esnap_dev_create);
|
||||||
|
CU_ADD_TEST(suite, ut_lvol_esnap_clone_bad_args);
|
||||||
|
|
||||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||||
CU_basic_run_tests();
|
CU_basic_run_tests();
|
||||||
|
Loading…
Reference in New Issue
Block a user