lvol: add snapshots and clones
Signed-off-by: Piotr Pelplinski <piotr.pelplinski@intel.com> Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com> Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com> Change-Id: Ibc43e3ee65d85a83d78d6e15457ae57992a1188a Reviewed-on: https://review.gerrithub.io/395059 Reviewed-by: Jim Harris <james.r.harris@intel.com> Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
38d75b56f4
commit
97934c5291
@ -161,6 +161,26 @@ int spdk_lvs_destroy(struct spdk_lvol_store *lvol_store,
|
||||
*/
|
||||
int spdk_lvol_create(struct spdk_lvol_store *lvs, const char *name, uint64_t sz,
|
||||
bool thin_provisioned, spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg);
|
||||
/**
|
||||
* \brief Create snapshot of given lvol
|
||||
* \param lvol Handle to lvol
|
||||
* \param snapshot_name Name of created snapshot
|
||||
* \param cb_fn Completion callback
|
||||
* \param cb_arg Completion callback custom arguments
|
||||
*/
|
||||
void spdk_lvol_create_snapshot(struct spdk_lvol *lvol, const char *snapshot_name,
|
||||
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg);
|
||||
|
||||
/**
|
||||
* \brief Create clone of given snapshot
|
||||
* \param lvol Handle to lvol snapshot
|
||||
* \param clone_name Name of created clone
|
||||
* \param cb_fn Completion callback
|
||||
* \param cb_arg Completion callback custom arguments
|
||||
*/
|
||||
void spdk_lvol_create_clone(struct spdk_lvol *lvol, const char *clone_name,
|
||||
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Renames lvol with new_name.
|
||||
|
@ -448,7 +448,7 @@ struct spdk_bdev_io {
|
||||
|
||||
int spdk_bdev_register(struct spdk_bdev *bdev);
|
||||
void spdk_bdev_unregister(struct spdk_bdev *bdev, spdk_bdev_unregister_cb cb_fn, void *cb_arg);
|
||||
void spdk_bdev_unregister_done(struct spdk_bdev *bdev, int bdeverrno);
|
||||
void spdk_bdev_destruct_done(struct spdk_bdev *bdev, int bdeverrno);
|
||||
int spdk_vbdev_register(struct spdk_bdev *vbdev, struct spdk_bdev **base_bdevs,
|
||||
int base_bdev_count);
|
||||
|
||||
|
@ -2648,7 +2648,7 @@ spdk_vbdev_register(struct spdk_bdev *vbdev, struct spdk_bdev **base_bdevs, int
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bdev_unregister_done(struct spdk_bdev *bdev, int bdeverrno)
|
||||
spdk_bdev_destruct_done(struct spdk_bdev *bdev, int bdeverrno)
|
||||
{
|
||||
if (bdev->unregister_cb != NULL) {
|
||||
bdev->unregister_cb(bdev->unregister_ctx, bdeverrno);
|
||||
|
@ -523,9 +523,13 @@ _vbdev_lvol_destroy_cb(void *cb_arg, int lvserrno)
|
||||
{
|
||||
struct spdk_bdev *bdev = cb_arg;
|
||||
|
||||
if (lvserrno == -EBUSY) {
|
||||
/* TODO: Handle reporting error to spdk_bdev_unregister */
|
||||
}
|
||||
|
||||
SPDK_INFOLOG(SPDK_LOG_VBDEV_LVOL, "Lvol destroyed\n");
|
||||
|
||||
spdk_bdev_unregister_done(bdev, lvserrno);
|
||||
spdk_bdev_destruct_done(bdev, lvserrno);
|
||||
free(bdev->name);
|
||||
free(bdev);
|
||||
}
|
||||
@ -538,7 +542,7 @@ _vbdev_lvol_destroy_after_close_cb(void *cb_arg, int lvserrno)
|
||||
|
||||
if (lvserrno != 0) {
|
||||
SPDK_INFOLOG(SPDK_LOG_VBDEV_LVOL, "Could not close Lvol %s\n", lvol->unique_id);
|
||||
spdk_bdev_unregister_done(bdev, lvserrno);
|
||||
spdk_bdev_destruct_done(bdev, lvserrno);
|
||||
free(bdev->name);
|
||||
free(bdev);
|
||||
return;
|
||||
@ -619,11 +623,13 @@ static bool
|
||||
vbdev_lvol_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
|
||||
{
|
||||
switch (io_type) {
|
||||
case SPDK_BDEV_IO_TYPE_READ:
|
||||
case SPDK_BDEV_IO_TYPE_WRITE:
|
||||
case SPDK_BDEV_IO_TYPE_RESET:
|
||||
case SPDK_BDEV_IO_TYPE_UNMAP:
|
||||
case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
|
||||
/* TODO: Report false if snapshot */
|
||||
return true;
|
||||
case SPDK_BDEV_IO_TYPE_RESET:
|
||||
case SPDK_BDEV_IO_TYPE_READ:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@ -887,6 +893,42 @@ vbdev_lvol_create(struct spdk_lvol_store *lvs, const char *name, size_t sz,
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
vbdev_lvol_create_snapshot(struct spdk_lvol *lvol, const char *snapshot_name,
|
||||
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol_with_handle_req *req;
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (req == NULL) {
|
||||
cb_fn(cb_arg, NULL, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
req->cb_fn = cb_fn;
|
||||
req->cb_arg = cb_arg;
|
||||
|
||||
spdk_lvol_create_snapshot(lvol, snapshot_name, _vbdev_lvol_create_cb, req);
|
||||
}
|
||||
|
||||
void
|
||||
vbdev_lvol_create_clone(struct spdk_lvol *lvol, const char *clone_name,
|
||||
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol_with_handle_req *req;
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (req == NULL) {
|
||||
cb_fn(cb_arg, NULL, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
req->cb_fn = cb_fn;
|
||||
req->cb_arg = cb_arg;
|
||||
|
||||
spdk_lvol_create_clone(lvol, clone_name, _vbdev_lvol_create_cb, req);
|
||||
}
|
||||
|
||||
static void
|
||||
_vbdev_lvol_rename_cb(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
|
@ -55,6 +55,12 @@ void vbdev_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, v
|
||||
int vbdev_lvol_create(struct spdk_lvol_store *lvs, const char *name, size_t sz,
|
||||
bool thin_provisioned, spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg);
|
||||
|
||||
void vbdev_lvol_create_snapshot(struct spdk_lvol *lvol, const char *snapshot_name,
|
||||
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg);
|
||||
|
||||
void vbdev_lvol_create_clone(struct spdk_lvol *lvol, const char *clone_name,
|
||||
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg);
|
||||
|
||||
int vbdev_lvol_resize(char *name, size_t sz, spdk_lvol_op_complete cb_fn, void *cb_arg);
|
||||
|
||||
void vbdev_lvol_rename(struct spdk_lvol *lvol, const char *new_lvol_name,
|
||||
|
@ -418,6 +418,182 @@ invalid:
|
||||
|
||||
SPDK_RPC_REGISTER("construct_lvol_bdev", spdk_rpc_construct_lvol_bdev)
|
||||
|
||||
struct rpc_snapshot_lvol_bdev {
|
||||
char *lvol_name;
|
||||
char *snapshot_name;
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_snapshot_lvol_bdev(struct rpc_snapshot_lvol_bdev *req)
|
||||
{
|
||||
free(req->lvol_name);
|
||||
free(req->snapshot_name);
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_snapshot_lvol_bdev_decoders[] = {
|
||||
{"lvol_name", offsetof(struct rpc_snapshot_lvol_bdev, lvol_name), spdk_json_decode_string, true},
|
||||
{"snapshot_name", offsetof(struct rpc_snapshot_lvol_bdev, snapshot_name), spdk_json_decode_string, true},
|
||||
};
|
||||
|
||||
static void
|
||||
_spdk_rpc_snapshot_lvol_bdev_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
|
||||
{
|
||||
struct spdk_json_write_ctx *w;
|
||||
struct spdk_jsonrpc_request *request = cb_arg;
|
||||
|
||||
if (lvolerrno != 0) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
w = spdk_jsonrpc_begin_result(request);
|
||||
if (w == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_json_write_array_begin(w);
|
||||
spdk_json_write_string(w, lvol->bdev->name);
|
||||
spdk_json_write_array_end(w);
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
spdk_strerror(-lvolerrno));
|
||||
}
|
||||
|
||||
static void
|
||||
spdk_rpc_snapshot_lvol_bdev(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_snapshot_lvol_bdev req = {};
|
||||
struct spdk_bdev *bdev;
|
||||
struct spdk_lvol *lvol;
|
||||
int rc;
|
||||
|
||||
SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Snapshotting blob\n");
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_snapshot_lvol_bdev_decoders,
|
||||
SPDK_COUNTOF(rpc_snapshot_lvol_bdev_decoders),
|
||||
&req)) {
|
||||
SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
|
||||
rc = -EINVAL;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
bdev = spdk_bdev_get_by_name(req.lvol_name);
|
||||
if (bdev == NULL) {
|
||||
SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "bdev '%s' does not exist\n", req.lvol_name);
|
||||
rc = -ENODEV;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
lvol = vbdev_lvol_get_from_bdev(bdev);
|
||||
if (lvol == NULL) {
|
||||
SPDK_ERRLOG("lvol does not exist\n");
|
||||
rc = -ENODEV;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
vbdev_lvol_create_snapshot(lvol, req.snapshot_name, _spdk_rpc_snapshot_lvol_bdev_cb, request);
|
||||
|
||||
free_rpc_snapshot_lvol_bdev(&req);
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc));
|
||||
free_rpc_snapshot_lvol_bdev(&req);
|
||||
}
|
||||
|
||||
SPDK_RPC_REGISTER("snapshot_lvol_bdev", spdk_rpc_snapshot_lvol_bdev)
|
||||
|
||||
struct rpc_clone_lvol_bdev {
|
||||
char *snapshot_name;
|
||||
char *clone_name;
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_clone_lvol_bdev(struct rpc_clone_lvol_bdev *req)
|
||||
{
|
||||
free(req->snapshot_name);
|
||||
free(req->clone_name);
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_clone_lvol_bdev_decoders[] = {
|
||||
{"snapshot_name", offsetof(struct rpc_clone_lvol_bdev, snapshot_name), spdk_json_decode_string},
|
||||
{"clone_name", offsetof(struct rpc_clone_lvol_bdev, clone_name), spdk_json_decode_string, true},
|
||||
};
|
||||
|
||||
static void
|
||||
_spdk_rpc_clone_lvol_bdev_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
|
||||
{
|
||||
struct spdk_json_write_ctx *w;
|
||||
struct spdk_jsonrpc_request *request = cb_arg;
|
||||
|
||||
if (lvolerrno != 0) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
w = spdk_jsonrpc_begin_result(request);
|
||||
if (w == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_json_write_array_begin(w);
|
||||
spdk_json_write_string(w, lvol->bdev->name);
|
||||
spdk_json_write_array_end(w);
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
spdk_strerror(-lvolerrno));
|
||||
}
|
||||
|
||||
static void
|
||||
spdk_rpc_clone_lvol_bdev(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_clone_lvol_bdev req = {};
|
||||
struct spdk_bdev *bdev;
|
||||
struct spdk_lvol *lvol;
|
||||
int rc;
|
||||
|
||||
SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "Cloning blob\n");
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_clone_lvol_bdev_decoders,
|
||||
SPDK_COUNTOF(rpc_clone_lvol_bdev_decoders),
|
||||
&req)) {
|
||||
SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
|
||||
rc = -EINVAL;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
bdev = spdk_bdev_get_by_name(req.snapshot_name);
|
||||
if (bdev == NULL) {
|
||||
SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "bdev '%s' does not exist\n", req.snapshot_name);
|
||||
rc = -ENODEV;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
lvol = vbdev_lvol_get_from_bdev(bdev);
|
||||
if (lvol == NULL) {
|
||||
SPDK_ERRLOG("lvol does not exist\n");
|
||||
rc = -ENODEV;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
vbdev_lvol_create_clone(lvol, req.clone_name, _spdk_rpc_clone_lvol_bdev_cb, request);
|
||||
|
||||
free_rpc_clone_lvol_bdev(&req);
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc));
|
||||
free_rpc_clone_lvol_bdev(&req);
|
||||
}
|
||||
|
||||
SPDK_RPC_REGISTER("clone_lvol_bdev", spdk_rpc_clone_lvol_bdev)
|
||||
|
||||
struct rpc_rename_lvol_bdev {
|
||||
char *old_name;
|
||||
char *new_name;
|
||||
|
111
lib/lvol/lvol.c
111
lib/lvol/lvol.c
@ -1103,6 +1103,117 @@ spdk_lvol_create(struct spdk_lvol_store *lvs, const char *name, uint64_t sz,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_lvol_create_snapshot(struct spdk_lvol *origlvol, const char *snapshot_name,
|
||||
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol_store *lvs;
|
||||
struct spdk_lvol *newlvol;
|
||||
struct spdk_blob *origblob;
|
||||
struct spdk_lvol_with_handle_req *req;
|
||||
struct spdk_blob_xattr_opts snapshot_xattrs;
|
||||
char *xattr_names = LVOL_NAME;
|
||||
int rc;
|
||||
|
||||
if (origlvol == NULL) {
|
||||
SPDK_INFOLOG(SPDK_LOG_LVOL, "Lvol not provided.\n");
|
||||
cb_fn(cb_arg, NULL, -EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
origblob = origlvol->blob;
|
||||
lvs = origlvol->lvol_store;
|
||||
rc = _spdk_lvs_verify_lvol_name(lvs, snapshot_name);
|
||||
if (rc < 0) {
|
||||
cb_fn(cb_arg, NULL, rc);
|
||||
return;
|
||||
}
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
|
||||
cb_fn(cb_arg, NULL, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
newlvol = calloc(1, sizeof(*newlvol));
|
||||
if (!newlvol) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
|
||||
free(req);
|
||||
cb_fn(cb_arg, NULL, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
newlvol->lvol_store = origlvol->lvol_store;
|
||||
strncpy(newlvol->name, snapshot_name, SPDK_LVOL_NAME_MAX);
|
||||
snapshot_xattrs.count = 1;
|
||||
snapshot_xattrs.ctx = newlvol;
|
||||
snapshot_xattrs.names = &xattr_names;
|
||||
snapshot_xattrs.get_value = spdk_lvol_get_xattr_value;
|
||||
req->lvol = newlvol;
|
||||
req->cb_fn = cb_fn;
|
||||
req->cb_arg = cb_arg;
|
||||
|
||||
spdk_bs_create_snapshot(lvs->blobstore, spdk_blob_get_id(origblob), &snapshot_xattrs,
|
||||
_spdk_lvol_create_cb, req);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_lvol_create_clone(struct spdk_lvol *origlvol, const char *clone_name,
|
||||
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol *newlvol;
|
||||
struct spdk_lvol_with_handle_req *req;
|
||||
struct spdk_lvol_store *lvs;
|
||||
struct spdk_blob *origblob;
|
||||
struct spdk_blob_xattr_opts clone_xattrs;
|
||||
char *xattr_names = LVOL_NAME;
|
||||
int rc;
|
||||
|
||||
if (origlvol == NULL) {
|
||||
SPDK_INFOLOG(SPDK_LOG_LVOL, "Lvol not provided.\n");
|
||||
cb_fn(cb_arg, NULL, -EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
origblob = origlvol->blob;
|
||||
lvs = origlvol->lvol_store;
|
||||
rc = _spdk_lvs_verify_lvol_name(lvs, clone_name);
|
||||
if (rc < 0) {
|
||||
cb_fn(cb_arg, NULL, rc);
|
||||
return;
|
||||
}
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
|
||||
cb_fn(cb_arg, NULL, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
newlvol = calloc(1, sizeof(*newlvol));
|
||||
if (!newlvol) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
|
||||
free(req);
|
||||
cb_fn(cb_arg, NULL, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
newlvol->lvol_store = lvs;
|
||||
strncpy(newlvol->name, clone_name, SPDK_LVOL_NAME_MAX);
|
||||
clone_xattrs.count = 1;
|
||||
clone_xattrs.ctx = newlvol;
|
||||
clone_xattrs.names = &xattr_names;
|
||||
clone_xattrs.get_value = spdk_lvol_get_xattr_value;
|
||||
req->lvol = newlvol;
|
||||
req->cb_fn = cb_fn;
|
||||
req->cb_arg = cb_arg;
|
||||
|
||||
spdk_bs_create_clone(lvs->blobstore, spdk_blob_get_id(origblob), &clone_xattrs,
|
||||
_spdk_lvol_create_cb,
|
||||
req);
|
||||
}
|
||||
|
||||
static void
|
||||
_spdk_lvol_resize_done(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
|
@ -509,6 +509,24 @@ if __name__ == "__main__":
|
||||
p.add_argument('size', help='size in MiB for this bdev', type=int)
|
||||
p.set_defaults(func=construct_lvol_bdev)
|
||||
|
||||
@call_cmd
|
||||
def snapshot_lvol_bdev(args):
|
||||
rpc.lvol.snapshot_lvol_bdev(args.client, args)
|
||||
|
||||
p = subparsers.add_parser('snapshot_lvol_bdev', help='Create a snapshot of an lvol bdev')
|
||||
p.add_argument('lvol_name', help='lvol bdev name')
|
||||
p.add_argument('snapshot_name', help='lvol snapshot name')
|
||||
p.set_defaults(func=snapshot_lvol_bdev)
|
||||
|
||||
@call_cmd
|
||||
def clone_lvol_bdev(args):
|
||||
rpc.lvol.clone_lvol_bdev(args.client, args)
|
||||
|
||||
p = subparsers.add_parser('clone_lvol_bdev', help='Create a clone of an lvol snapshot')
|
||||
p.add_argument('snapshot_name', help='lvol snapshot name')
|
||||
p.add_argument('clone_name', help='lvol clone name')
|
||||
p.set_defaults(func=clone_lvol_bdev)
|
||||
|
||||
@call_cmd
|
||||
def rename_lvol_bdev(args):
|
||||
rpc.lvol.rename_lvol_bdev(args.client, args)
|
||||
|
@ -28,6 +28,22 @@ def construct_lvol_bdev(client, args):
|
||||
return client.call('construct_lvol_bdev', params)
|
||||
|
||||
|
||||
def snapshot_lvol_bdev(client, args):
|
||||
params = {
|
||||
'lvol_name': args.lvol_name,
|
||||
'snapshot_name': args.snapshot_name
|
||||
}
|
||||
return client.call('snapshot_lvol_bdev', params)
|
||||
|
||||
|
||||
def clone_lvol_bdev(client, args):
|
||||
params = {
|
||||
'snapshot_name': args.snapshot_name,
|
||||
'clone_name': args.clone_name
|
||||
}
|
||||
return client.call('clone_lvol_bdev', params)
|
||||
|
||||
|
||||
def rename_lvol_bdev(client, args):
|
||||
params = {
|
||||
'old_name': args.old_name,
|
||||
|
@ -104,7 +104,7 @@ spdk_bdev_alias_del(struct spdk_bdev *bdev, const char *alias)
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bdev_unregister_done(struct spdk_bdev *bdev, int bdeverrno)
|
||||
spdk_bdev_destruct_done(struct spdk_bdev *bdev, int bdeverrno)
|
||||
{
|
||||
}
|
||||
|
||||
@ -577,6 +577,28 @@ spdk_lvol_create(struct spdk_lvol_store *lvs, const char *name, size_t sz,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_lvol_create_snapshot(struct spdk_lvol *lvol, const char *snapshot_name,
|
||||
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol *snap;
|
||||
|
||||
snap = _lvol_create(lvol->lvol_store);
|
||||
strncpy(snap->name, snapshot_name, SPDK_LVOL_NAME_MAX);
|
||||
cb_fn(cb_arg, snap, 0);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_lvol_create_clone(struct spdk_lvol *lvol, const char *clone_name,
|
||||
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol *clone;
|
||||
|
||||
clone = _lvol_create(lvol->lvol_store);
|
||||
strncpy(clone->name, clone_name, SPDK_LVS_NAME_MAX);
|
||||
cb_fn(cb_arg, clone, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_store_op_complete(void *cb_arg, int lvserrno)
|
||||
{
|
||||
@ -696,6 +718,139 @@ ut_lvol_init(void)
|
||||
free(g_base_bdev);
|
||||
}
|
||||
|
||||
static void
|
||||
ut_lvol_snapshot(void)
|
||||
{
|
||||
int sz = 10;
|
||||
int rc;
|
||||
struct spdk_lvol *lvol = NULL;
|
||||
|
||||
g_lvs = calloc(1, sizeof(*g_lvs));
|
||||
SPDK_CU_ASSERT_FATAL(g_lvs != NULL);
|
||||
TAILQ_INIT(&g_lvs->lvols);
|
||||
g_lvs_bdev = calloc(1, sizeof(*g_lvs_bdev));
|
||||
SPDK_CU_ASSERT_FATAL(g_lvs_bdev != NULL);
|
||||
g_base_bdev = calloc(1, sizeof(*g_base_bdev));
|
||||
SPDK_CU_ASSERT_FATAL(g_base_bdev != NULL);
|
||||
|
||||
/* Assign name to lvs */
|
||||
strncpy(g_lvs->name, "UNIT_TEST_LVS_NAME", SPDK_LVS_NAME_MAX);
|
||||
SPDK_CU_ASSERT_FATAL(g_lvs->name != NULL);
|
||||
|
||||
g_lvs_bdev->lvs = g_lvs;
|
||||
g_lvs_bdev->bdev = g_base_bdev;
|
||||
|
||||
spdk_uuid_generate(&g_lvs->uuid);
|
||||
|
||||
TAILQ_INSERT_TAIL(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores);
|
||||
|
||||
/* Successful lvol create */
|
||||
g_lvolerrno = -1;
|
||||
rc = vbdev_lvol_create(g_lvs, "lvol", sz, false, vbdev_lvol_create_complete, NULL);
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
CU_ASSERT(g_lvol != NULL);
|
||||
CU_ASSERT(g_lvolerrno == 0);
|
||||
|
||||
lvol = g_lvol;
|
||||
|
||||
/* Successful snap create */
|
||||
vbdev_lvol_create_snapshot(lvol, "snap", vbdev_lvol_create_complete, NULL);
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
CU_ASSERT(g_lvol != NULL);
|
||||
CU_ASSERT(g_lvolerrno == 0);
|
||||
|
||||
/* Successful lvol destruct */
|
||||
vbdev_lvol_destruct(g_lvol);
|
||||
CU_ASSERT(g_lvol == NULL);
|
||||
|
||||
/* Successful snap destruct */
|
||||
g_lvol = lvol;
|
||||
vbdev_lvol_destruct(g_lvol);
|
||||
CU_ASSERT(g_lvol == NULL);
|
||||
|
||||
TAILQ_REMOVE(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores);
|
||||
|
||||
free(g_lvs);
|
||||
free(g_lvs_bdev);
|
||||
free(g_base_bdev);
|
||||
}
|
||||
|
||||
static void
|
||||
ut_lvol_clone(void)
|
||||
{
|
||||
int sz = 10;
|
||||
int rc;
|
||||
struct spdk_lvol *lvol = NULL;
|
||||
struct spdk_lvol *snap = NULL;
|
||||
struct spdk_lvol *clone = NULL;
|
||||
|
||||
g_lvs = calloc(1, sizeof(*g_lvs));
|
||||
SPDK_CU_ASSERT_FATAL(g_lvs != NULL);
|
||||
TAILQ_INIT(&g_lvs->lvols);
|
||||
g_lvs_bdev = calloc(1, sizeof(*g_lvs_bdev));
|
||||
SPDK_CU_ASSERT_FATAL(g_lvs_bdev != NULL);
|
||||
g_base_bdev = calloc(1, sizeof(*g_base_bdev));
|
||||
SPDK_CU_ASSERT_FATAL(g_base_bdev != NULL);
|
||||
|
||||
/* Assign name to lvs */
|
||||
strncpy(g_lvs->name, "UNIT_TEST_LVS_NAME", SPDK_LVS_NAME_MAX);
|
||||
SPDK_CU_ASSERT_FATAL(g_lvs->name != NULL);
|
||||
|
||||
g_lvs_bdev->lvs = g_lvs;
|
||||
g_lvs_bdev->bdev = g_base_bdev;
|
||||
|
||||
spdk_uuid_generate(&g_lvs->uuid);
|
||||
|
||||
TAILQ_INSERT_TAIL(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores);
|
||||
|
||||
/* Successful lvol create */
|
||||
g_lvolerrno = -1;
|
||||
rc = vbdev_lvol_create(g_lvs, "lvol", sz, false, vbdev_lvol_create_complete, NULL);
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
CU_ASSERT(g_lvol != NULL);
|
||||
CU_ASSERT(g_lvolerrno == 0);
|
||||
|
||||
lvol = g_lvol;
|
||||
|
||||
/* Successful snap create */
|
||||
vbdev_lvol_create_snapshot(lvol, "snap", vbdev_lvol_create_complete, NULL);
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
CU_ASSERT(g_lvol != NULL);
|
||||
CU_ASSERT(g_lvolerrno == 0);
|
||||
|
||||
snap = g_lvol;
|
||||
|
||||
/* Successful clone create */
|
||||
vbdev_lvol_create_clone(snap, "clone", vbdev_lvol_create_complete, NULL);
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
CU_ASSERT(g_lvol != NULL);
|
||||
CU_ASSERT(g_lvolerrno == 0);
|
||||
|
||||
clone = g_lvol;
|
||||
|
||||
/* Successful lvol destruct */
|
||||
g_lvol = lvol;
|
||||
vbdev_lvol_destruct(g_lvol);
|
||||
CU_ASSERT(g_lvol == NULL);
|
||||
|
||||
/* Successful clone destruct */
|
||||
g_lvol = clone;
|
||||
vbdev_lvol_destruct(g_lvol);
|
||||
CU_ASSERT(g_lvol == NULL);
|
||||
|
||||
/* Successful snap destruct */
|
||||
g_lvol = snap;
|
||||
vbdev_lvol_destruct(g_lvol);
|
||||
CU_ASSERT(g_lvol == NULL);
|
||||
|
||||
TAILQ_REMOVE(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores);
|
||||
|
||||
free(g_lvs);
|
||||
free(g_lvs_bdev);
|
||||
free(g_base_bdev);
|
||||
}
|
||||
|
||||
static void
|
||||
ut_lvol_hotremove(void)
|
||||
{
|
||||
@ -1233,6 +1388,8 @@ int main(int argc, char **argv)
|
||||
if (
|
||||
CU_add_test(suite, "ut_lvs_init", ut_lvs_init) == NULL ||
|
||||
CU_add_test(suite, "ut_lvol_init", ut_lvol_init) == NULL ||
|
||||
CU_add_test(suite, "ut_lvol_snapshot", ut_lvol_snapshot) == NULL ||
|
||||
CU_add_test(suite, "ut_lvol_clone", ut_lvol_clone) == NULL ||
|
||||
CU_add_test(suite, "ut_lvs_destroy", ut_lvs_destroy) == NULL ||
|
||||
CU_add_test(suite, "ut_lvs_unload", ut_lvs_unload) == NULL ||
|
||||
CU_add_test(suite, "ut_lvol_resize", ut_lvol_resize) == NULL ||
|
||||
|
@ -59,6 +59,7 @@ const char *uuid = "828d9766-ae50-11e7-bd8d-001e67edf350";
|
||||
struct spdk_blob {
|
||||
spdk_blob_id id;
|
||||
uint32_t ref;
|
||||
struct spdk_blob_store *bs;
|
||||
int close_status;
|
||||
int open_status;
|
||||
int load_status;
|
||||
@ -399,11 +400,28 @@ spdk_bs_create_blob_ext(struct spdk_blob_store *bs, const struct spdk_blob_opts
|
||||
if (opts != NULL && opts->thin_provision) {
|
||||
b->thin_provisioned = true;
|
||||
}
|
||||
b->bs = bs;
|
||||
|
||||
TAILQ_INSERT_TAIL(&bs->blobs, b, link);
|
||||
cb_fn(cb_arg, b->id, 0);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
_lvol_send_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx)
|
||||
{
|
||||
@ -1281,6 +1299,265 @@ lvol_open(void)
|
||||
spdk_free_thread();
|
||||
}
|
||||
|
||||
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_allocate_thread(_lvol_send_msg, NULL, NULL, NULL, NULL);
|
||||
|
||||
spdk_lvs_opts_init(&opts);
|
||||
strncpy(opts.name, "lvs", sizeof(opts.name));
|
||||
|
||||
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, true, lvol_op_with_handle_complete, NULL);
|
||||
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. */
|
||||
spdk_lvol_close(g_lvol, close_cb, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
g_lvserrno = -1;
|
||||
|
||||
spdk_lvol_close(lvol, close_cb, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
g_lvserrno = -1;
|
||||
|
||||
rc = spdk_lvs_unload(g_lvol_store, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
g_lvol_store = NULL;
|
||||
|
||||
free_dev(&dev);
|
||||
|
||||
spdk_free_thread();
|
||||
}
|
||||
|
||||
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_allocate_thread(_lvol_send_msg, NULL, NULL, NULL, NULL);
|
||||
|
||||
spdk_lvs_opts_init(&opts);
|
||||
strncpy(opts.name, "lvs", sizeof(opts.name));
|
||||
|
||||
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, true, lvol_op_with_handle_complete, NULL);
|
||||
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);
|
||||
|
||||
spdk_lvol_close(lvol, close_cb, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
g_lvserrno = -1;
|
||||
|
||||
spdk_lvol_close(snap, close_cb, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
g_lvserrno = -1;
|
||||
|
||||
rc = spdk_lvs_unload(g_lvol_store, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
g_lvol_store = NULL;
|
||||
|
||||
free_dev(&dev);
|
||||
|
||||
spdk_free_thread();
|
||||
}
|
||||
|
||||
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_allocate_thread(_lvol_send_msg, NULL, NULL, NULL, NULL);
|
||||
|
||||
spdk_lvs_opts_init(&opts);
|
||||
strncpy(opts.name, "lvs", sizeof(opts.name));
|
||||
|
||||
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, true, lvol_op_with_handle_complete, NULL);
|
||||
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. */
|
||||
spdk_lvol_close(g_lvol, close_cb, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
g_lvserrno = -1;
|
||||
|
||||
spdk_lvol_close(snap, close_cb, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
g_lvserrno = -1;
|
||||
|
||||
spdk_lvol_close(lvol, close_cb, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
g_lvserrno = -1;
|
||||
|
||||
rc = spdk_lvs_unload(g_lvol_store, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
g_lvol_store = NULL;
|
||||
|
||||
free_dev(&dev);
|
||||
|
||||
spdk_free_thread();
|
||||
}
|
||||
|
||||
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_allocate_thread(_lvol_send_msg, NULL, NULL, NULL, NULL);
|
||||
|
||||
spdk_lvs_opts_init(&opts);
|
||||
strncpy(opts.name, "lvs", sizeof(opts.name));
|
||||
|
||||
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, true, lvol_op_with_handle_complete, NULL);
|
||||
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. */
|
||||
spdk_lvol_close(clone, close_cb, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
g_lvserrno = -1;
|
||||
|
||||
spdk_lvol_close(snap, close_cb, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
g_lvserrno = -1;
|
||||
|
||||
spdk_lvol_close(lvol, close_cb, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
g_lvserrno = -1;
|
||||
|
||||
rc = spdk_lvs_unload(g_lvol_store, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
g_lvol_store = NULL;
|
||||
|
||||
free_dev(&dev);
|
||||
|
||||
spdk_free_thread();
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_names(void)
|
||||
{
|
||||
@ -1659,6 +1936,10 @@ int main(int argc, char **argv)
|
||||
CU_add_test(suite, "lvol_load", lvs_load) == NULL ||
|
||||
CU_add_test(suite, "lvs_load", lvols_load) == NULL ||
|
||||
CU_add_test(suite, "lvol_open", lvol_open) == NULL ||
|
||||
CU_add_test(suite, "lvol_snapshot", lvol_snapshot) == NULL ||
|
||||
CU_add_test(suite, "lvol_snapshot_fail", lvol_snapshot_fail) == NULL ||
|
||||
CU_add_test(suite, "lvol_clone", lvol_clone) == NULL ||
|
||||
CU_add_test(suite, "lvol_clone_fail", lvol_clone_fail) == NULL ||
|
||||
CU_add_test(suite, "lvol_refcnt", lvol_refcnt) == NULL ||
|
||||
CU_add_test(suite, "lvol_names", lvol_names) == NULL ||
|
||||
CU_add_test(suite, "lvol_create_thin_provisioned", lvol_create_thin_provisioned) == NULL ||
|
||||
|
Loading…
Reference in New Issue
Block a user