lvol: Logical volume implementation
Change-Id: Ia96ae78ff9530d953181ac5f7255a38f3c8ec430 Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com> Signed-off-by: Maciej Szwed <maciej.szwed@intel.com> Signed-off-by: Piotr Pelplinski <piotr.pelplinski@intel.com> Reviewed-on: https://review.gerrithub.io/375392 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
0caab4e1da
commit
27f44662ac
11
CHANGELOG.md
11
CHANGELOG.md
@ -2,6 +2,10 @@
|
||||
|
||||
## v17.10: (Upcoming Release)
|
||||
|
||||
### New dependency
|
||||
|
||||
libuuid added as new depenency for logical volumes.
|
||||
|
||||
### Block Device Abstraction Layer (bdev)
|
||||
|
||||
An [fio](http://github.com/axboe/fio) plugin was added that can route
|
||||
@ -80,6 +84,13 @@ which will show up in tools like `gdb`.
|
||||
The API spdk_trace_dump() now takes a new parameter to allow the caller to
|
||||
specify stdout or stderr for example.
|
||||
|
||||
### Logical Volumes
|
||||
|
||||
Logical volumes library built on top of SPDK blobstore has been added.
|
||||
It is possible create logical volumes on top of other devices using RPC.
|
||||
|
||||
See [logical volumes](http://www.spdk.io/doc/lvol.html) documentation for more information.
|
||||
|
||||
## v17.07: Build system improvements, userspace vhost-blk target, and GPT bdev
|
||||
|
||||
### Build System
|
||||
|
68
include/spdk/lvol.h
Normal file
68
include/spdk/lvol.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Logical Volume Interface
|
||||
*/
|
||||
|
||||
#ifndef SPDK_LVOL_H
|
||||
#define SPDK_LVOL_H
|
||||
|
||||
#include "spdk/queue.h"
|
||||
#include "spdk/blob.h"
|
||||
#include <uuid/uuid.h>
|
||||
|
||||
struct spdk_lvol_store;
|
||||
struct spdk_lvol;
|
||||
|
||||
typedef void (*spdk_lvs_op_with_handle_complete)(void *cb_arg, struct spdk_lvol_store *lvol_store,
|
||||
int lvserrno);
|
||||
typedef void (*spdk_lvs_op_complete)(void *cb_arg, int lvserrno);
|
||||
typedef void (*spdk_lvol_op_complete)(void *cb_arg, int lvolerrno);
|
||||
typedef void (*spdk_lvol_op_with_handle_complete)(void *cb_arg, struct spdk_lvol *lvol,
|
||||
int lvolerrno);
|
||||
|
||||
int spdk_lvs_init(struct spdk_bs_dev *bs_dev, spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg);
|
||||
int spdk_lvs_unload(struct spdk_lvol_store *lvol_store, spdk_lvs_op_complete cb_fn, void *cb_arg);
|
||||
int spdk_lvol_create(struct spdk_lvol_store *lvs, uint64_t sz,
|
||||
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg);
|
||||
int spdk_lvol_resize(struct spdk_lvol *lvol, uint64_t sz,
|
||||
spdk_lvol_op_complete cb_fn, void *cb_arg);
|
||||
void spdk_lvol_destroy(struct spdk_lvol *lvol);
|
||||
void spdk_lvol_close(struct spdk_lvol *lvol);
|
||||
struct spdk_io_channel *spdk_lvol_get_io_channel(struct spdk_lvol *lvol);
|
||||
struct lvol_store_bdev *vbdev_get_lvs_bdev_by_lvs(struct spdk_lvol_store *lvs_orig);
|
||||
struct spdk_lvol *vbdev_get_lvol_by_name(const char *name);
|
||||
struct spdk_lvol_store *vbdev_get_lvol_store_by_uuid(uuid_t uuid);
|
||||
|
||||
#endif /* SPDK_LVOL_H */
|
@ -222,6 +222,8 @@ struct spdk_bdev {
|
||||
|
||||
TAILQ_ENTRY(spdk_bdev) vbdev_link;
|
||||
|
||||
bool bdev_opened;
|
||||
|
||||
bool bdev_opened_for_write;
|
||||
|
||||
/**
|
||||
@ -425,6 +427,8 @@ void spdk_scsi_nvme_translate(const struct spdk_bdev_io *bdev_io,
|
||||
|
||||
void spdk_bdev_module_list_add(struct spdk_bdev_module_if *bdev_module);
|
||||
|
||||
bool spdk_is_bdev_opened(struct spdk_bdev *bdev);
|
||||
|
||||
static inline struct spdk_bdev_io *
|
||||
spdk_bdev_io_from_ctx(void *ctx)
|
||||
{
|
||||
|
93
include/spdk_internal/lvolstore.h
Normal file
93
include/spdk_internal/lvolstore.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SPDK_INTERNAL_LVOLSTORE_H
|
||||
#define SPDK_INTERNAL_LVOLSTORE_H
|
||||
|
||||
#include "spdk/lvol.h"
|
||||
#include "spdk_internal/bdev.h"
|
||||
|
||||
struct spdk_lvol_store_req {
|
||||
union {
|
||||
struct {
|
||||
spdk_lvs_op_complete cb_fn;
|
||||
void *cb_arg;
|
||||
struct spdk_bdev *base_bdev;
|
||||
} lvs_basic;
|
||||
|
||||
struct {
|
||||
spdk_lvs_op_with_handle_complete cb_fn;
|
||||
void *cb_arg;
|
||||
struct spdk_lvol_store *lvol_store;
|
||||
struct spdk_bs_dev *bs_dev;
|
||||
struct spdk_bdev *base_bdev;
|
||||
} lvs_handle;
|
||||
|
||||
struct {
|
||||
spdk_lvol_op_complete cb_fn;
|
||||
void *cb_arg;
|
||||
} lvol_basic;
|
||||
|
||||
struct {
|
||||
spdk_lvol_op_with_handle_complete cb_fn;
|
||||
void *cb_arg;
|
||||
struct spdk_lvol *lvol;
|
||||
} lvol_handle;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct spdk_lvol_store {
|
||||
struct spdk_bs_dev *bs_dev;
|
||||
struct spdk_blob_store *blobstore;
|
||||
uuid_t uuid;
|
||||
uint64_t page_size;
|
||||
struct spdk_lvol_store_req *destruct_req;
|
||||
TAILQ_HEAD(, spdk_lvol) lvols;
|
||||
};
|
||||
|
||||
struct spdk_lvol {
|
||||
struct spdk_lvol_store *lvol_store;
|
||||
struct spdk_blob *blob;
|
||||
uint64_t sz;
|
||||
spdk_blob_id blob_id;
|
||||
char *name;
|
||||
bool close_only;
|
||||
struct spdk_bdev *bdev;
|
||||
TAILQ_ENTRY(spdk_lvol) link;
|
||||
};
|
||||
|
||||
struct lvol_task {
|
||||
enum spdk_bdev_io_status status;
|
||||
};
|
||||
|
||||
#endif /* SPDK_INTERNAL_LVOLSTORE_H */
|
@ -35,7 +35,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
DIRS-y += bdev blob blobfs conf copy cunit event json jsonrpc \
|
||||
log env_dpdk net rpc trace util nvme nvmf scsi ioat \
|
||||
log lvol env_dpdk net rpc trace util nvme nvmf scsi ioat \
|
||||
ut_mock iscsi
|
||||
ifeq ($(OS),Linux)
|
||||
DIRS-y += nbd
|
||||
|
@ -44,7 +44,7 @@ C_SRCS-$(CONFIG_VTUNE) += vtune.c
|
||||
|
||||
LIBNAME = bdev
|
||||
|
||||
DIRS-y += error gpt malloc null nvme rpc split
|
||||
DIRS-y += error gpt lvol malloc null nvme rpc split
|
||||
|
||||
ifeq ($(OS),Linux)
|
||||
DIRS-y += aio virtio
|
||||
|
@ -1480,6 +1480,7 @@ _spdk_bdev_register(struct spdk_bdev *bdev)
|
||||
bdev->status = SPDK_BDEV_STATUS_READY;
|
||||
|
||||
TAILQ_INIT(&bdev->open_descs);
|
||||
bdev->bdev_opened = false;
|
||||
bdev->bdev_opened_for_write = false;
|
||||
|
||||
TAILQ_INIT(&bdev->vbdevs);
|
||||
@ -1573,6 +1574,24 @@ spdk_vbdev_unregister(struct spdk_bdev *vbdev)
|
||||
spdk_bdev_unregister(vbdev);
|
||||
}
|
||||
|
||||
bool
|
||||
spdk_is_bdev_opened(struct spdk_bdev *bdev)
|
||||
{
|
||||
struct spdk_bdev *base;
|
||||
|
||||
if (bdev->bdev_opened) {
|
||||
return true;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(base, &bdev->base_bdevs, base_bdev_link) {
|
||||
if (spdk_is_bdev_opened(base)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_bdev_open(struct spdk_bdev *bdev, bool write, spdk_bdev_remove_cb_t remove_cb,
|
||||
void *remove_ctx, struct spdk_bdev_desc **_desc)
|
||||
@ -1599,6 +1618,8 @@ spdk_bdev_open(struct spdk_bdev *bdev, bool write, spdk_bdev_remove_cb_t remove_
|
||||
bdev->bdev_opened_for_write = true;
|
||||
}
|
||||
|
||||
bdev->bdev_opened = true;
|
||||
|
||||
desc->bdev = bdev;
|
||||
desc->remove_cb = remove_cb;
|
||||
desc->remove_ctx = remove_ctx;
|
||||
@ -1623,6 +1644,8 @@ spdk_bdev_close(struct spdk_bdev_desc *desc)
|
||||
bdev->bdev_opened_for_write = false;
|
||||
}
|
||||
|
||||
bdev->bdev_opened = false;
|
||||
|
||||
TAILQ_REMOVE(&bdev->open_descs, desc, link);
|
||||
free(desc);
|
||||
|
||||
|
40
lib/bdev/lvol/Makefile
Normal file
40
lib/bdev/lvol/Makefile
Normal file
@ -0,0 +1,40 @@
|
||||
#
|
||||
# BSD LICENSE
|
||||
#
|
||||
# Copyright (c) Intel Corporation.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Intel Corporation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
C_SRCS = vbdev_lvol.c vbdev_lvol_rpc.c
|
||||
LIBNAME = vbdev_lvol
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
|
578
lib/bdev/lvol/vbdev_lvol.c
Normal file
578
lib/bdev/lvol/vbdev_lvol.c
Normal file
@ -0,0 +1,578 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "spdk/blob_bdev.h"
|
||||
#include "spdk/rpc.h"
|
||||
#include "spdk_internal/bdev.h"
|
||||
#include "spdk_internal/log.h"
|
||||
|
||||
#include "vbdev_lvol.h"
|
||||
|
||||
SPDK_DECLARE_BDEV_MODULE(lvol);
|
||||
|
||||
static TAILQ_HEAD(, lvol_store_bdev) g_spdk_lvol_pairs = TAILQ_HEAD_INITIALIZER(
|
||||
g_spdk_lvol_pairs);
|
||||
|
||||
static void
|
||||
_vbdev_lvs_create_cb(void *cb_arg, struct spdk_lvol_store *lvs, int lvserrno)
|
||||
{
|
||||
struct spdk_lvol_store_req *req = cb_arg;
|
||||
struct spdk_bs_dev *bs_dev = req->u.lvs_handle.bs_dev;
|
||||
struct lvol_store_bdev *lvs_bdev;
|
||||
struct spdk_bdev *bdev = req->u.lvs_handle.base_bdev;
|
||||
|
||||
if (lvserrno != 0) {
|
||||
assert(lvs == NULL);
|
||||
SPDK_INFOLOG(SPDK_TRACE_VBDEV_LVOL, "Cannot create lvol store bdev\n");
|
||||
bs_dev->destroy(bs_dev);
|
||||
goto end;
|
||||
}
|
||||
|
||||
assert(lvs != NULL);
|
||||
|
||||
lvs_bdev = calloc(1, sizeof(*lvs_bdev));
|
||||
if (!lvs_bdev) {
|
||||
bs_dev->destroy(bs_dev);
|
||||
lvserrno = -ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
lvs_bdev->lvs = lvs;
|
||||
lvs_bdev->bdev = bdev;
|
||||
|
||||
TAILQ_INSERT_TAIL(&g_spdk_lvol_pairs, lvs_bdev, lvol_stores);
|
||||
SPDK_INFOLOG(SPDK_TRACE_VBDEV_LVOL, "Lvol store bdev inserted\n");
|
||||
|
||||
end:
|
||||
req->u.lvs_handle.cb_fn(req->u.lvs_handle.cb_arg, lvs, lvserrno);
|
||||
free(req);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
vbdev_lvs_create(struct spdk_bdev *base_bdev,
|
||||
spdk_lvs_op_with_handle_complete cb_fn,
|
||||
void *cb_arg)
|
||||
{
|
||||
struct spdk_bs_dev *bs_dev;
|
||||
struct spdk_lvol_store_req *lvs_req;
|
||||
int rc;
|
||||
|
||||
lvs_req = calloc(1, sizeof(*lvs_req));
|
||||
if (!lvs_req) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for vbdev lvol store request pointer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bs_dev = spdk_bdev_create_bs_dev(base_bdev);
|
||||
if (!bs_dev) {
|
||||
SPDK_ERRLOG("Cannot create blobstore device\n");
|
||||
free(lvs_req);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
lvs_req->u.lvs_handle.bs_dev = bs_dev;
|
||||
lvs_req->u.lvs_handle.base_bdev = base_bdev;
|
||||
lvs_req->u.lvs_handle.cb_fn = cb_fn;
|
||||
lvs_req->u.lvs_handle.cb_arg = cb_arg;
|
||||
|
||||
rc = spdk_lvs_init(bs_dev, _vbdev_lvs_create_cb, lvs_req);
|
||||
if (rc < 0) {
|
||||
free(lvs_req);
|
||||
bs_dev->destroy(bs_dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_vbdev_lvs_destruct_cb(void *cb_arg, int lvserrno)
|
||||
{
|
||||
struct spdk_lvol_store_req *req = cb_arg;
|
||||
|
||||
SPDK_INFOLOG(SPDK_TRACE_VBDEV_LVOL, "Lvol store bdev deleted\n");
|
||||
|
||||
if (req->u.lvs_basic.cb_fn != NULL)
|
||||
req->u.lvs_basic.cb_fn(req->u.lvs_basic.cb_arg, lvserrno);
|
||||
free(req);
|
||||
}
|
||||
|
||||
void
|
||||
vbdev_lvs_destruct(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn,
|
||||
void *cb_arg)
|
||||
{
|
||||
|
||||
struct spdk_lvol_store_req *req;
|
||||
struct lvol_store_bdev *lvs_bdev;
|
||||
struct spdk_lvol *lvol, *tmp;
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for vbdev lvol store request pointer\n");
|
||||
return;
|
||||
}
|
||||
req->u.lvs_basic.cb_fn = cb_fn;
|
||||
req->u.lvs_basic.cb_arg = cb_arg;
|
||||
|
||||
lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
|
||||
req->u.lvs_basic.base_bdev = lvs_bdev->bdev;
|
||||
TAILQ_REMOVE(&g_spdk_lvol_pairs, lvs_bdev, lvol_stores);
|
||||
|
||||
free(lvs_bdev);
|
||||
|
||||
if (TAILQ_EMPTY(&lvs->lvols)) {
|
||||
spdk_lvs_unload(lvs, _vbdev_lvs_destruct_cb, req);
|
||||
} else {
|
||||
lvs->destruct_req = req;
|
||||
TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
|
||||
lvol->close_only = true;
|
||||
spdk_bdev_unregister(lvol->bdev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct lvol_store_bdev *
|
||||
_vbdev_lvol_store_first(void)
|
||||
{
|
||||
struct lvol_store_bdev *lvs_bdev;
|
||||
|
||||
lvs_bdev = TAILQ_FIRST(&g_spdk_lvol_pairs);
|
||||
if (lvs_bdev) {
|
||||
SPDK_INFOLOG(SPDK_TRACE_VBDEV_LVOL, "Starting lvolstore iteration at %p\n", lvs_bdev->lvs);
|
||||
}
|
||||
|
||||
return lvs_bdev;
|
||||
}
|
||||
|
||||
static struct lvol_store_bdev *
|
||||
_vbdev_lvol_store_next(struct lvol_store_bdev *prev)
|
||||
{
|
||||
struct lvol_store_bdev *lvs_bdev;
|
||||
|
||||
lvs_bdev = TAILQ_NEXT(prev, lvol_stores);
|
||||
if (lvs_bdev) {
|
||||
SPDK_INFOLOG(SPDK_TRACE_VBDEV_LVOL, "Continuing lvolstore iteration at %p\n", lvs_bdev->lvs);
|
||||
}
|
||||
|
||||
return lvs_bdev;
|
||||
}
|
||||
|
||||
struct spdk_lvol_store *
|
||||
vbdev_get_lvol_store_by_uuid(uuid_t uuid)
|
||||
{
|
||||
struct spdk_lvol_store *lvs = NULL;
|
||||
struct lvol_store_bdev *lvs_bdev = _vbdev_lvol_store_first();
|
||||
|
||||
while (lvs_bdev != NULL) {
|
||||
lvs = lvs_bdev->lvs;
|
||||
if (uuid_compare(lvs->uuid, uuid) == 0) {
|
||||
return lvs;
|
||||
}
|
||||
lvs_bdev = _vbdev_lvol_store_next(lvs_bdev);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct lvol_store_bdev *
|
||||
vbdev_get_lvs_bdev_by_lvs(struct spdk_lvol_store *lvs_orig)
|
||||
{
|
||||
struct spdk_lvol_store *lvs = NULL;
|
||||
struct lvol_store_bdev *lvs_bdev = _vbdev_lvol_store_first();
|
||||
|
||||
while (lvs_bdev != NULL) {
|
||||
lvs = lvs_bdev->lvs;
|
||||
if (lvs == lvs_orig) {
|
||||
return lvs_bdev;
|
||||
}
|
||||
lvs_bdev = _vbdev_lvol_store_next(lvs_bdev);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct spdk_lvol *
|
||||
vbdev_get_lvol_by_name(const char *name)
|
||||
{
|
||||
struct spdk_lvol *lvol, *tmp_lvol;
|
||||
struct lvol_store_bdev *lvs_bdev, *tmp_lvs_bdev;
|
||||
|
||||
TAILQ_FOREACH_SAFE(lvs_bdev, &g_spdk_lvol_pairs, lvol_stores, tmp_lvs_bdev) {
|
||||
TAILQ_FOREACH_SAFE(lvol, &lvs_bdev->lvs->lvols, link, tmp_lvol) {
|
||||
if (!strcmp(lvol->name, name)) {
|
||||
return lvol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
vbdev_lvol_destruct(void *ctx)
|
||||
{
|
||||
struct spdk_lvol *lvol = ctx;
|
||||
|
||||
assert(lvol != NULL);
|
||||
free(lvol->bdev);
|
||||
if (lvol->close_only) {
|
||||
spdk_lvol_close(lvol);
|
||||
} else {
|
||||
spdk_lvol_destroy(lvol);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
vbdev_lvol_dump_config_json(void *ctx, struct spdk_json_write_ctx *w)
|
||||
{
|
||||
struct spdk_lvol *lvol = ctx;
|
||||
struct lvol_store_bdev *lvs_bdev;
|
||||
struct spdk_bdev *bdev;
|
||||
|
||||
lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvol->lvol_store);
|
||||
bdev = lvs_bdev->bdev;
|
||||
|
||||
spdk_json_write_name(w, "base_bdev");
|
||||
spdk_json_write_string(w, spdk_bdev_get_name(bdev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spdk_io_channel *
|
||||
vbdev_lvol_get_io_channel(void *ctx)
|
||||
{
|
||||
struct spdk_lvol *lvol = ctx;
|
||||
|
||||
return spdk_lvol_get_io_channel(lvol);
|
||||
}
|
||||
|
||||
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_FLUSH:
|
||||
case SPDK_BDEV_IO_TYPE_RESET:
|
||||
return true;
|
||||
case SPDK_BDEV_IO_TYPE_UNMAP:
|
||||
case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_op_comp(void *cb_arg, int bserrno)
|
||||
{
|
||||
struct lvol_task *task = cb_arg;
|
||||
struct spdk_bdev_io *bdev_io = spdk_bdev_io_from_ctx(task);
|
||||
|
||||
if (bserrno != 0) {
|
||||
task->status = SPDK_BDEV_IO_STATUS_FAILED;
|
||||
}
|
||||
|
||||
SPDK_INFOLOG(SPDK_TRACE_VBDEV_LVOL, "Vbdev processing callback on device %s with type %d\n",
|
||||
bdev_io->bdev->name, bdev_io->type);
|
||||
spdk_bdev_io_complete(bdev_io, task->status);
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_read(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
|
||||
{
|
||||
uint64_t start_page, num_pages;
|
||||
struct spdk_lvol *lvol = bdev_io->bdev->ctxt;
|
||||
struct spdk_blob *blob = lvol->blob;
|
||||
struct lvol_task *task = (struct lvol_task *)bdev_io->driver_ctx;
|
||||
|
||||
start_page = bdev_io->u.read.offset_blocks;
|
||||
num_pages = bdev_io->u.read.num_blocks;
|
||||
|
||||
task->status = SPDK_BDEV_IO_STATUS_SUCCESS;
|
||||
|
||||
SPDK_INFOLOG(SPDK_TRACE_VBDEV_LVOL,
|
||||
"Vbdev doing read at offset %" PRIu64 " using %" PRIu64 " pages on device %s\n", start_page,
|
||||
num_pages, bdev_io->bdev->name);
|
||||
spdk_bs_io_readv_blob(blob, ch, bdev_io->u.read.iovs, bdev_io->u.read.iovcnt, start_page, num_pages,
|
||||
lvol_op_comp, task);
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_write(struct spdk_lvol *lvol, struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
|
||||
{
|
||||
uint64_t start_page, num_pages;
|
||||
struct spdk_blob *blob = lvol->blob;
|
||||
struct lvol_task *task = (struct lvol_task *)bdev_io->driver_ctx;
|
||||
|
||||
start_page = bdev_io->u.write.offset_blocks;
|
||||
num_pages = bdev_io->u.write.num_blocks;
|
||||
|
||||
task->status = SPDK_BDEV_IO_STATUS_SUCCESS;
|
||||
|
||||
SPDK_INFOLOG(SPDK_TRACE_VBDEV_LVOL,
|
||||
"Vbdev doing write at offset %" PRIu64 " using %" PRIu64 " pages on device %s\n", start_page,
|
||||
num_pages, bdev_io->bdev->name);
|
||||
spdk_bs_io_writev_blob(blob, ch, bdev_io->u.write.iovs, bdev_io->u.write.iovcnt, start_page,
|
||||
num_pages, lvol_op_comp, task);
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_flush(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
|
||||
{
|
||||
struct lvol_task *task = (struct lvol_task *)bdev_io->driver_ctx;
|
||||
|
||||
task->status = SPDK_BDEV_IO_STATUS_SUCCESS;
|
||||
|
||||
spdk_bs_io_flush_channel(ch, lvol_op_comp, task);
|
||||
}
|
||||
|
||||
static int
|
||||
lvol_reset(struct spdk_bdev_io *bdev_io)
|
||||
{
|
||||
spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
vbdev_lvol_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
|
||||
{
|
||||
struct spdk_lvol *lvol = bdev_io->bdev->ctxt;
|
||||
|
||||
SPDK_INFOLOG(SPDK_TRACE_VBDEV_LVOL, "Vbdev request type %d submitted\n", bdev_io->type);
|
||||
|
||||
switch (bdev_io->type) {
|
||||
case SPDK_BDEV_IO_TYPE_READ:
|
||||
spdk_bdev_io_get_buf(bdev_io, lvol_read);
|
||||
break;
|
||||
case SPDK_BDEV_IO_TYPE_WRITE:
|
||||
lvol_write(lvol, ch, bdev_io);
|
||||
break;
|
||||
case SPDK_BDEV_IO_TYPE_RESET:
|
||||
lvol_reset(bdev_io);
|
||||
break;
|
||||
case SPDK_BDEV_IO_TYPE_FLUSH:
|
||||
lvol_flush(ch, bdev_io);
|
||||
break;
|
||||
case SPDK_BDEV_IO_TYPE_UNMAP:
|
||||
case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
|
||||
default:
|
||||
SPDK_INFOLOG(SPDK_TRACE_VBDEV_LVOL, "lvol: unsupported I/O type %d\n", bdev_io->type);
|
||||
spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static struct spdk_bdev_fn_table vbdev_lvol_fn_table = {
|
||||
.destruct = vbdev_lvol_destruct,
|
||||
.io_type_supported = vbdev_lvol_io_type_supported,
|
||||
.submit_request = vbdev_lvol_submit_request,
|
||||
.get_io_channel = vbdev_lvol_get_io_channel,
|
||||
.dump_config_json = vbdev_lvol_dump_config_json,
|
||||
};
|
||||
|
||||
static struct spdk_bdev *
|
||||
_create_lvol_disk(struct spdk_lvol *lvol)
|
||||
{
|
||||
struct spdk_bdev *bdev;
|
||||
struct lvol_store_bdev *lvs_bdev;
|
||||
|
||||
if (!lvol->name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvol->lvol_store);
|
||||
if (lvs_bdev == NULL) {
|
||||
SPDK_ERRLOG("No spdk lvs-bdev pair found for lvol %s\n", lvol->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bdev = calloc(1, sizeof(struct spdk_bdev));
|
||||
if (!bdev) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for lvol bdev\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bdev->name = lvol->name;
|
||||
bdev->product_name = "Logical Volume";
|
||||
bdev->write_cache = 1;
|
||||
bdev->blocklen = lvol->lvol_store->page_size;
|
||||
assert((lvol->sz % bdev->blocklen) == 0);
|
||||
bdev->blockcnt = lvol->sz / bdev->blocklen;
|
||||
|
||||
bdev->ctxt = lvol;
|
||||
bdev->fn_table = &vbdev_lvol_fn_table;
|
||||
bdev->module = SPDK_GET_BDEV_MODULE(lvol);
|
||||
|
||||
spdk_bdev_register(bdev);
|
||||
|
||||
return bdev;
|
||||
}
|
||||
|
||||
static void
|
||||
_vbdev_lvol_create_cb(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
|
||||
{
|
||||
struct spdk_lvol_store_req *req = cb_arg;
|
||||
struct spdk_bdev *bdev = NULL;
|
||||
|
||||
if (lvolerrno < 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
bdev = _create_lvol_disk(lvol);
|
||||
if (bdev == NULL) {
|
||||
lvolerrno = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
lvol->bdev = bdev;
|
||||
|
||||
end:
|
||||
req->u.lvol_handle.cb_fn(req->u.lvol_handle.cb_arg, lvol, lvolerrno);
|
||||
free(req);
|
||||
}
|
||||
|
||||
int
|
||||
vbdev_lvol_create(uuid_t uuid, size_t sz,
|
||||
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol_store_req *req;
|
||||
struct spdk_lvol_store *lvs;
|
||||
int rc;
|
||||
|
||||
lvs = vbdev_get_lvol_store_by_uuid(uuid);
|
||||
if (lvs == NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (req == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
req->u.lvol_handle.cb_fn = cb_fn;
|
||||
req->u.lvol_handle.cb_arg = cb_arg;
|
||||
|
||||
rc = spdk_lvol_create(lvs, sz, _vbdev_lvol_create_cb, req);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
_vbdev_lvol_resize_cb(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
struct spdk_lvol_store_req *req = cb_arg;
|
||||
|
||||
req->u.lvol_basic.cb_fn(req->u.lvol_basic.cb_arg, lvolerrno);
|
||||
free(req);
|
||||
}
|
||||
|
||||
int
|
||||
vbdev_lvol_resize(char *name, size_t sz,
|
||||
spdk_lvol_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol_store_req *req;
|
||||
struct spdk_bdev *bdev;
|
||||
struct spdk_lvol *lvol;
|
||||
struct spdk_lvol_store *lvs;
|
||||
uint64_t cluster_size;
|
||||
int rc;
|
||||
|
||||
lvol = vbdev_get_lvol_by_name(name);
|
||||
if (lvol == NULL) {
|
||||
SPDK_ERRLOG("lvol '%s' does not exist\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bdev = spdk_bdev_get_by_name(name);
|
||||
if (bdev == NULL) {
|
||||
SPDK_ERRLOG("bdev '%s' does not exist\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spdk_is_bdev_opened(bdev)) {
|
||||
SPDK_ERRLOG("bdev '%s' cannot be resized because it is currently opened\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lvs = lvol->lvol_store;
|
||||
cluster_size = spdk_bs_get_cluster_size(lvs->blobstore);
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (req == NULL) {
|
||||
cb_fn(cb_arg, -1);
|
||||
return -ENOMEM;
|
||||
}
|
||||
req->u.lvol_basic.cb_fn = cb_fn;
|
||||
req->u.lvol_basic.cb_arg = cb_arg;
|
||||
|
||||
rc = spdk_lvol_resize(lvol, sz, _vbdev_lvol_resize_cb, req);
|
||||
|
||||
if (rc == 0) {
|
||||
bdev->blockcnt = sz * cluster_size / bdev->blocklen;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
vbdev_lvs_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
vbdev_lvs_fini(void)
|
||||
{
|
||||
struct lvol_store_bdev *lvs_bdev, *tmp;
|
||||
|
||||
TAILQ_FOREACH_SAFE(lvs_bdev, &g_spdk_lvol_pairs, lvol_stores, tmp) {
|
||||
vbdev_lvs_destruct(lvs_bdev->lvs, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
vbdev_lvs_get_ctx_size(void)
|
||||
{
|
||||
return sizeof(struct lvol_task);
|
||||
}
|
||||
|
||||
static void
|
||||
vbdev_lvs_examine(struct spdk_bdev *bdev)
|
||||
{
|
||||
spdk_bdev_module_examine_done(SPDK_GET_BDEV_MODULE(lvol));
|
||||
}
|
||||
|
||||
SPDK_BDEV_MODULE_REGISTER(lvol, vbdev_lvs_init, vbdev_lvs_fini, NULL, vbdev_lvs_get_ctx_size,
|
||||
vbdev_lvs_examine)
|
||||
SPDK_LOG_REGISTER_TRACE_FLAG("vbdev_lvol", SPDK_TRACE_VBDEV_LVOL);
|
56
lib/bdev/lvol/vbdev_lvol.h
Normal file
56
lib/bdev/lvol/vbdev_lvol.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SPDK_VBDEV_LVOL_H
|
||||
#define SPDK_VBDEV_LVOL_H
|
||||
|
||||
#include "spdk/lvol.h"
|
||||
#include "spdk_internal/bdev.h"
|
||||
|
||||
#include "spdk_internal/lvolstore.h"
|
||||
|
||||
struct lvol_store_bdev {
|
||||
struct spdk_lvol_store *lvs;
|
||||
struct spdk_bdev *bdev;
|
||||
|
||||
TAILQ_ENTRY(lvol_store_bdev) lvol_stores;
|
||||
};
|
||||
int vbdev_lvs_create(struct spdk_bdev *base_bdev, spdk_lvs_op_with_handle_complete cb_fn,
|
||||
void *cb_arg);
|
||||
void vbdev_lvs_destruct(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, void *cb_arg);
|
||||
|
||||
int vbdev_lvol_create(uuid_t uuid, size_t sz, 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);
|
||||
#endif /* SPDK_VBDEV_LVOL_H */
|
380
lib/bdev/lvol/vbdev_lvol_rpc.c
Normal file
380
lib/bdev/lvol/vbdev_lvol_rpc.c
Normal file
@ -0,0 +1,380 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "spdk/rpc.h"
|
||||
#include "spdk/bdev.h"
|
||||
#include "spdk/util.h"
|
||||
#include "vbdev_lvol.h"
|
||||
#include "spdk/string.h"
|
||||
#include "spdk_internal/log.h"
|
||||
|
||||
SPDK_LOG_REGISTER_TRACE_FLAG("lvolrpc", SPDK_TRACE_LVOL_RPC)
|
||||
|
||||
struct rpc_construct_lvol_store {
|
||||
char *base_name;
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_construct_lvol_store(struct rpc_construct_lvol_store *req)
|
||||
{
|
||||
free(req->base_name);
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_construct_lvol_store_decoders[] = {
|
||||
{"base_name", offsetof(struct rpc_construct_lvol_store, base_name), spdk_json_decode_string},
|
||||
};
|
||||
|
||||
static void
|
||||
_spdk_rpc_lvol_store_construct_cb(void *cb_arg, struct spdk_lvol_store *lvol_store, int lvserrno)
|
||||
{
|
||||
struct spdk_json_write_ctx *w;
|
||||
char lvol_store_uuid[37];
|
||||
struct spdk_jsonrpc_request *request = cb_arg;
|
||||
char buf[64];
|
||||
|
||||
if (lvserrno != 0) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
uuid_unparse(lvol_store->uuid, lvol_store_uuid);
|
||||
|
||||
w = spdk_jsonrpc_begin_result(request);
|
||||
if (w == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_json_write_array_begin(w);
|
||||
spdk_json_write_string(w, lvol_store_uuid);
|
||||
spdk_json_write_array_end(w);
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_strerror_r(-lvserrno, buf, sizeof(buf));
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
spdk_rpc_construct_lvol_store(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_construct_lvol_store req = {};
|
||||
struct spdk_bdev *bdev;
|
||||
int rc;
|
||||
char buf[64];
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_construct_lvol_store_decoders,
|
||||
SPDK_COUNTOF(rpc_construct_lvol_store_decoders),
|
||||
&req)) {
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL_RPC, "spdk_json_decode_object failed\n");
|
||||
rc = -EINVAL;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
if (req.base_name == NULL) {
|
||||
SPDK_ERRLOG("missing name param\n");
|
||||
rc = -EINVAL;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
bdev = spdk_bdev_get_by_name(req.base_name);
|
||||
if (bdev == NULL) {
|
||||
SPDK_ERRLOG("bdev '%s' does not exist\n", req.base_name);
|
||||
rc = -ENODEV;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
rc = vbdev_lvs_create(bdev, _spdk_rpc_lvol_store_construct_cb, request);
|
||||
if (rc < 0) {
|
||||
goto invalid;
|
||||
}
|
||||
free_rpc_construct_lvol_store(&req);
|
||||
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_strerror_r(-rc, buf, sizeof(buf));
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf);
|
||||
free_rpc_construct_lvol_store(&req);
|
||||
}
|
||||
SPDK_RPC_REGISTER("construct_lvol_store", spdk_rpc_construct_lvol_store)
|
||||
|
||||
struct rpc_destroy_lvol_store {
|
||||
char *lvol_store_uuid;
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_destroy_lvol_store(struct rpc_destroy_lvol_store *req)
|
||||
{
|
||||
free(req->lvol_store_uuid);
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_destroy_lvol_store_decoders[] = {
|
||||
{"lvol_store_uuid", offsetof(struct rpc_destroy_lvol_store, lvol_store_uuid), spdk_json_decode_string},
|
||||
};
|
||||
|
||||
static void
|
||||
_spdk_rpc_lvol_store_destroy_cb(void *cb_arg, int lvserrno)
|
||||
{
|
||||
struct spdk_json_write_ctx *w;
|
||||
struct spdk_jsonrpc_request *request = cb_arg;
|
||||
char buf[64];
|
||||
|
||||
if (lvserrno != 0) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
w = spdk_jsonrpc_begin_result(request);
|
||||
if (w == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_json_write_bool(w, true);
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_strerror_r(-lvserrno, buf, sizeof(buf));
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
spdk_rpc_destroy_lvol_store(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_destroy_lvol_store req = {};
|
||||
struct spdk_lvol_store *lvs;
|
||||
uuid_t lvol_store_uuid;
|
||||
int rc;
|
||||
char buf[64];
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_destroy_lvol_store_decoders,
|
||||
SPDK_COUNTOF(rpc_destroy_lvol_store_decoders),
|
||||
&req)) {
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL_RPC, "spdk_json_decode_object failed\n");
|
||||
rc = -EINVAL;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
if (uuid_parse(req.lvol_store_uuid, lvol_store_uuid)) {
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL_RPC, "incorrect UUID '%s'\n", req.lvol_store_uuid);
|
||||
rc = -EINVAL;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
lvs = vbdev_get_lvol_store_by_uuid(lvol_store_uuid);
|
||||
if (lvs == NULL) {
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL_RPC, "blobstore with UUID '%p' not found\n", &lvol_store_uuid);
|
||||
rc = -ENODEV;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
vbdev_lvs_destruct(lvs, _spdk_rpc_lvol_store_destroy_cb, request);
|
||||
|
||||
free_rpc_destroy_lvol_store(&req);
|
||||
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_strerror_r(-rc, buf, sizeof(buf));
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf);
|
||||
free_rpc_destroy_lvol_store(&req);
|
||||
}
|
||||
SPDK_RPC_REGISTER("destroy_lvol_store", spdk_rpc_destroy_lvol_store)
|
||||
|
||||
struct rpc_construct_lvol_bdev {
|
||||
char *lvol_store_uuid;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_construct_lvol_bdev(struct rpc_construct_lvol_bdev *req)
|
||||
{
|
||||
free(req->lvol_store_uuid);
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_construct_lvol_bdev_decoders[] = {
|
||||
{"lvol_store_uuid", offsetof(struct rpc_construct_lvol_bdev, lvol_store_uuid), spdk_json_decode_string},
|
||||
{"size", offsetof(struct rpc_construct_lvol_bdev, size), spdk_json_decode_uint64},
|
||||
};
|
||||
|
||||
static void
|
||||
_spdk_rpc_construct_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;
|
||||
char buf[64];
|
||||
|
||||
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->name);
|
||||
spdk_json_write_array_end(w);
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_strerror_r(-lvolerrno, buf, sizeof(buf));
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
spdk_rpc_construct_lvol_bdev(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_construct_lvol_bdev req = {};
|
||||
uuid_t lvol_store_uuid;
|
||||
size_t sz;
|
||||
int rc;
|
||||
char buf[64];
|
||||
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL_RPC, "Creating blob\n");
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_construct_lvol_bdev_decoders,
|
||||
SPDK_COUNTOF(rpc_construct_lvol_bdev_decoders),
|
||||
&req)) {
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL_RPC, "spdk_json_decode_object failed\n");
|
||||
rc = -EINVAL;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
if (uuid_parse(req.lvol_store_uuid, lvol_store_uuid)) {
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL_RPC, "incorrect UUID '%s'\n", req.lvol_store_uuid);
|
||||
rc = -EINVAL;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
sz = (size_t)req.size;
|
||||
|
||||
rc = vbdev_lvol_create(lvol_store_uuid, sz, _spdk_rpc_construct_lvol_bdev_cb, request);
|
||||
if (rc < 0) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
free_rpc_construct_lvol_bdev(&req);
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_strerror_r(-rc, buf, sizeof(buf));
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf);
|
||||
free_rpc_construct_lvol_bdev(&req);
|
||||
}
|
||||
|
||||
SPDK_RPC_REGISTER("construct_lvol_bdev", spdk_rpc_construct_lvol_bdev)
|
||||
|
||||
struct rpc_resize_lvol_bdev {
|
||||
char *name;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_resize_lvol_bdev(struct rpc_resize_lvol_bdev *req)
|
||||
{
|
||||
free(req->name);
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_resize_lvol_bdev_decoders[] = {
|
||||
{"name", offsetof(struct rpc_resize_lvol_bdev, name), spdk_json_decode_string},
|
||||
{"size", offsetof(struct rpc_resize_lvol_bdev, size), spdk_json_decode_uint64},
|
||||
};
|
||||
|
||||
static void
|
||||
_spdk_rpc_resize_lvol_bdev_cb(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
struct spdk_json_write_ctx *w;
|
||||
struct spdk_jsonrpc_request *request = cb_arg;
|
||||
char buf[64];
|
||||
|
||||
if (lvolerrno != 0) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
w = spdk_jsonrpc_begin_result(request);
|
||||
if (w == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_json_write_bool(w, true);
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_strerror_r(-lvolerrno, buf, sizeof(buf));
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
spdk_rpc_resize_lvol_bdev(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_resize_lvol_bdev req = {};
|
||||
int rc = 0;
|
||||
char buf[64];
|
||||
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL_RPC, "Resizing lvol\n");
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_resize_lvol_bdev_decoders,
|
||||
SPDK_COUNTOF(rpc_resize_lvol_bdev_decoders),
|
||||
&req)) {
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL_RPC, "spdk_json_decode_object failed\n");
|
||||
rc = -EINVAL;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
if (req.name == NULL) {
|
||||
SPDK_ERRLOG("missing name param\n");
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
rc = vbdev_lvol_resize(req.name, (size_t)req.size, _spdk_rpc_resize_lvol_bdev_cb, request);
|
||||
if (rc < 0) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
free_rpc_resize_lvol_bdev(&req);
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_strerror_r(-rc, buf, sizeof(buf));
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, buf);
|
||||
free_rpc_resize_lvol_bdev(&req);
|
||||
}
|
||||
|
||||
SPDK_RPC_REGISTER("resize_lvol_bdev", spdk_rpc_resize_lvol_bdev)
|
41
lib/lvol/Makefile
Normal file
41
lib/lvol/Makefile
Normal file
@ -0,0 +1,41 @@
|
||||
#
|
||||
# BSD LICENSE
|
||||
#
|
||||
# Copyright (c) Intel Corporation.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Intel Corporation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
CFLAGS += $(ENV_CFLAGS)
|
||||
C_SRCS = lvol.c
|
||||
LIBNAME = lvol
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
|
394
lib/lvol/lvol.c
Normal file
394
lib/lvol/lvol.c
Normal file
@ -0,0 +1,394 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "spdk_internal/lvolstore.h"
|
||||
#include "spdk_internal/log.h"
|
||||
#include "spdk/string.h"
|
||||
#include "spdk/io_channel.h"
|
||||
|
||||
/* Length of string returned from uuid_unparse() */
|
||||
#define UUID_STRING_LEN 37
|
||||
|
||||
SPDK_LOG_REGISTER_TRACE_FLAG("lvol", SPDK_TRACE_LVOL)
|
||||
|
||||
static void
|
||||
_lvs_init_cb(void *cb_arg, struct spdk_blob_store *bs, int lvserrno)
|
||||
{
|
||||
struct spdk_lvol_store_req *lvs_req = cb_arg;
|
||||
struct spdk_lvol_store *lvs = lvs_req->u.lvs_handle.lvol_store;
|
||||
|
||||
if (lvserrno != 0) {
|
||||
assert(bs == NULL);
|
||||
SPDK_ERRLOG("Lvol store init failed: could not initialize blobstore\n");
|
||||
free(lvs);
|
||||
lvs = NULL;
|
||||
} else {
|
||||
assert(bs != NULL);
|
||||
lvs->blobstore = bs;
|
||||
lvs->page_size = spdk_bs_get_page_size(bs);
|
||||
TAILQ_INIT(&lvs->lvols);
|
||||
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL, "Lvol store initialized\n");
|
||||
}
|
||||
assert(lvs_req->u.lvs_handle.cb_fn != NULL);
|
||||
lvs_req->u.lvs_handle.cb_fn(lvs_req->u.lvs_handle.cb_arg, lvs, lvserrno);
|
||||
free(lvs_req);
|
||||
}
|
||||
|
||||
int
|
||||
spdk_lvs_init(struct spdk_bs_dev *bs_dev, spdk_lvs_op_with_handle_complete cb_fn,
|
||||
void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol_store *lvs;
|
||||
struct spdk_lvol_store_req *lvs_req;
|
||||
|
||||
if (bs_dev == NULL) {
|
||||
SPDK_ERRLOG("Blobstore device does not exist\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
lvs = calloc(1, sizeof(*lvs));
|
||||
if (!lvs) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for lvol store base pointer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
uuid_generate_time(lvs->uuid);
|
||||
|
||||
lvs_req = calloc(1, sizeof(*lvs_req));
|
||||
if (!lvs_req) {
|
||||
free(lvs);
|
||||
SPDK_ERRLOG("Cannot alloc memory for lvol store request pointer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
lvs_req->u.lvs_handle.cb_fn = cb_fn;
|
||||
lvs_req->u.lvs_handle.cb_arg = cb_arg;
|
||||
lvs_req->u.lvs_handle.lvol_store = lvs;
|
||||
lvs->bs_dev = bs_dev;
|
||||
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL, "Initializing lvol store\n");
|
||||
spdk_bs_init(bs_dev, NULL, _lvs_init_cb, lvs_req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_lvs_unload_cb(void *cb_arg, int lvserrno)
|
||||
{
|
||||
struct spdk_lvol_store_req *lvs_req = cb_arg;
|
||||
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL, "Lvol store unloaded\n");
|
||||
assert(lvs_req->u.lvs_basic.cb_fn != NULL);
|
||||
lvs_req->u.lvs_basic.cb_fn(lvs_req->u.lvs_basic.cb_arg, lvserrno);
|
||||
free(lvs_req);
|
||||
}
|
||||
|
||||
int
|
||||
spdk_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn,
|
||||
void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol_store_req *lvs_req;
|
||||
|
||||
if (lvs == NULL) {
|
||||
SPDK_ERRLOG("Lvol store is NULL\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
lvs_req = calloc(1, sizeof(*lvs_req));
|
||||
if (!lvs_req) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for lvol store request pointer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
lvs_req->u.lvs_basic.cb_fn = cb_fn;
|
||||
lvs_req->u.lvs_basic.cb_arg = cb_arg;
|
||||
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL, "Unloading lvol store\n");
|
||||
spdk_bs_unload(lvs->blobstore, _lvs_unload_cb, lvs_req);
|
||||
free(lvs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_spdk_lvol_return_to_caller(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
struct spdk_lvol_store_req *req = cb_arg;
|
||||
|
||||
assert(req->u.lvol_handle.cb_fn != NULL);
|
||||
req->u.lvol_handle.cb_fn(req->u.lvol_handle.cb_arg, req->u.lvol_handle.lvol, lvolerrno);
|
||||
free(req);
|
||||
}
|
||||
|
||||
static void
|
||||
_spdk_lvs_destruct_cb(void *cb_arg, int lvserrno)
|
||||
{
|
||||
struct spdk_lvol_store_req *req = cb_arg;
|
||||
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL, "Lvol store bdev deleted\n");
|
||||
|
||||
if (req->u.lvs_basic.cb_fn != NULL)
|
||||
req->u.lvs_basic.cb_fn(req->u.lvs_basic.cb_arg, lvserrno);
|
||||
free(req);
|
||||
}
|
||||
|
||||
static void
|
||||
_spdk_lvol_close_blob_cb(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
struct spdk_lvol *lvol = cb_arg;
|
||||
|
||||
if (lvolerrno < 0) {
|
||||
SPDK_ERRLOG("Could not close blob on lvol\n");
|
||||
return;
|
||||
}
|
||||
|
||||
TAILQ_REMOVE(&lvol->lvol_store->lvols, lvol, link);
|
||||
|
||||
if (lvol->lvol_store->destruct_req && TAILQ_EMPTY(&lvol->lvol_store->lvols)) {
|
||||
spdk_lvs_unload(lvol->lvol_store, _spdk_lvs_destruct_cb, lvol->lvol_store->destruct_req);
|
||||
}
|
||||
|
||||
free(lvol->name);
|
||||
free(lvol);
|
||||
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL, "Blob closed on lvol\n");
|
||||
}
|
||||
|
||||
static void
|
||||
_spdk_lvol_delete_blob_cb(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
struct spdk_lvol *lvol = cb_arg;
|
||||
struct spdk_blob_store *bs = lvol->lvol_store->blobstore;
|
||||
|
||||
if (lvolerrno < 0) {
|
||||
SPDK_ERRLOG("Could not delete blob on lvol\n");
|
||||
return;
|
||||
}
|
||||
SPDK_INFOLOG(SPDK_TRACE_LVOL, "Blob closed on lvol\n");
|
||||
spdk_bs_md_delete_blob(bs, lvol->blob_id, _spdk_lvol_close_blob_cb, lvol);
|
||||
}
|
||||
|
||||
static void
|
||||
_spdk_lvol_create_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
|
||||
{
|
||||
struct spdk_lvol_store_req *req = cb_arg;
|
||||
spdk_blob_id blob_id = spdk_blob_get_id(blob);
|
||||
struct spdk_lvol *lvol = req->u.lvol_handle.lvol;
|
||||
uint64_t cluster_size = spdk_bs_get_cluster_size(lvol->lvol_store->blobstore);
|
||||
uint64_t number_of_clusters = lvol->sz / cluster_size;
|
||||
char uuid[UUID_STRING_LEN];
|
||||
|
||||
if (lvolerrno < 0) {
|
||||
free(lvol);
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
lvol->blob = blob;
|
||||
lvol->blob_id = blob_id;
|
||||
|
||||
uuid_unparse(lvol->lvol_store->uuid, uuid);
|
||||
lvol->name = spdk_sprintf_alloc("%s_%"PRIu64, uuid, (uint64_t)blob_id);
|
||||
if (!lvol->name) {
|
||||
spdk_bs_md_close_blob(&blob, _spdk_lvol_delete_blob_cb, lvol);
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
lvolerrno = spdk_bs_md_resize_blob(blob, number_of_clusters);
|
||||
if (lvolerrno < 0) {
|
||||
spdk_bs_md_close_blob(&blob, _spdk_lvol_delete_blob_cb, lvol);
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&lvol->lvol_store->lvols, lvol, link);
|
||||
|
||||
spdk_bs_md_sync_blob(blob, _spdk_lvol_return_to_caller, req);
|
||||
|
||||
return;
|
||||
|
||||
invalid:
|
||||
assert(req->u.lvol_handle.cb_fn != NULL);
|
||||
req->u.lvol_handle.cb_fn(req->u.lvol_handle.cb_arg, NULL, lvolerrno);
|
||||
free(req);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
_spdk_lvol_create_cb(void *cb_arg, spdk_blob_id blobid, int lvolerrno)
|
||||
{
|
||||
struct spdk_lvol_store_req *req = cb_arg;
|
||||
struct spdk_blob_store *bs;
|
||||
|
||||
if (lvolerrno < 0) {
|
||||
free(req->u.lvol_handle.lvol);
|
||||
assert(req->u.lvol_handle.cb_fn != NULL);
|
||||
req->u.lvol_handle.cb_fn(req->u.lvol_handle.cb_arg, NULL, lvolerrno);
|
||||
free(req);
|
||||
return;
|
||||
}
|
||||
|
||||
bs = req->u.lvol_handle.lvol->lvol_store->blobstore;
|
||||
|
||||
spdk_bs_md_open_blob(bs, blobid, _spdk_lvol_create_open_cb, req);
|
||||
}
|
||||
|
||||
int
|
||||
spdk_lvol_create(struct spdk_lvol_store *lvs, uint64_t sz,
|
||||
spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol_store_req *req;
|
||||
struct spdk_lvol *lvol;
|
||||
uint64_t free_clusters;
|
||||
|
||||
if (lvs == NULL) {
|
||||
SPDK_ERRLOG("lvol store does not exist\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
free_clusters = spdk_bs_free_cluster_count(lvs->blobstore);
|
||||
if (sz > free_clusters) {
|
||||
SPDK_ERRLOG("Not enough free clusters left on lvol store to add lvol with %zu clusters\n", sz);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
req->u.lvol_handle.cb_fn = cb_fn;
|
||||
req->u.lvol_handle.cb_arg = cb_arg;
|
||||
|
||||
lvol = calloc(1, sizeof(*lvol));
|
||||
if (!lvol) {
|
||||
free(req);
|
||||
SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
lvol->lvol_store = lvs;
|
||||
lvol->sz = sz * spdk_bs_get_cluster_size(lvs->blobstore);
|
||||
lvol->close_only = false;
|
||||
req->u.lvol_handle.lvol = lvol;
|
||||
|
||||
spdk_bs_md_create_blob(lvs->blobstore, _spdk_lvol_create_cb, req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_spdk_lvol_resize_cb(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
struct spdk_lvol_store_req *req = cb_arg;
|
||||
|
||||
req->u.lvol_basic.cb_fn(req->u.lvol_basic.cb_arg, lvolerrno);
|
||||
free(req);
|
||||
}
|
||||
|
||||
int
|
||||
spdk_lvol_resize(struct spdk_lvol *lvol, uint64_t sz,
|
||||
spdk_lvol_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
int rc;
|
||||
struct spdk_blob *blob = lvol->blob;
|
||||
struct spdk_lvol_store *lvs = lvol->lvol_store;
|
||||
struct spdk_lvol_store_req *req;
|
||||
uint64_t cluster_size = spdk_bs_get_cluster_size(lvs->blobstore);
|
||||
uint64_t free_clusters = spdk_bs_free_cluster_count(lvs->blobstore);
|
||||
uint64_t used_clusters = lvol->sz / cluster_size;
|
||||
|
||||
/* Check if size of lvol increasing */
|
||||
if (sz > used_clusters) {
|
||||
/* Check if there is enough clusters left to resize */
|
||||
if (sz - used_clusters > free_clusters) {
|
||||
SPDK_ERRLOG("Not enough free clusters left on lvol store to resize lvol to %zu clusters\n", sz);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
req->u.lvol_basic.cb_fn = cb_fn;
|
||||
req->u.lvol_basic.cb_arg = cb_arg;
|
||||
|
||||
rc = spdk_bs_md_resize_blob(blob, sz);
|
||||
if (rc < 0) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
lvol->sz = sz * cluster_size;
|
||||
|
||||
spdk_blob_md_set_xattr(blob, "length", &sz, sizeof(sz));
|
||||
|
||||
spdk_bs_md_sync_blob(blob, _spdk_lvol_resize_cb, req);
|
||||
|
||||
return rc;
|
||||
|
||||
invalid:
|
||||
req->u.lvol_basic.cb_fn(req->u.lvol_basic.cb_arg, rc);
|
||||
free(req);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_lvol_destroy(struct spdk_lvol *lvol)
|
||||
{
|
||||
if (lvol == NULL) {
|
||||
SPDK_ERRLOG("lvol does not exist\n");
|
||||
return;
|
||||
}
|
||||
|
||||
TAILQ_REMOVE(&lvol->lvol_store->lvols, lvol, link);
|
||||
spdk_bs_md_close_blob(&(lvol->blob), _spdk_lvol_delete_blob_cb, lvol);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_lvol_close(struct spdk_lvol *lvol)
|
||||
{
|
||||
if (lvol == NULL) {
|
||||
SPDK_ERRLOG("lvol does not exist\n");
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_bs_md_close_blob(&(lvol->blob), _spdk_lvol_close_blob_cb, lvol);
|
||||
}
|
||||
|
||||
struct spdk_io_channel *
|
||||
spdk_lvol_get_io_channel(struct spdk_lvol *lvol)
|
||||
{
|
||||
return spdk_bs_alloc_io_channel(lvol->lvol_store->blobstore);
|
||||
}
|
@ -54,11 +54,12 @@ CXXFLAGS += -fno-sanitize=address
|
||||
endif
|
||||
|
||||
SPDK_LIB_LIST = event_bdev event_copy event_rpc
|
||||
SPDK_LIB_LIST += blobfs blob bdev blob_bdev copy event util conf trace \
|
||||
SPDK_LIB_LIST += blobfs bdev copy event util conf trace \
|
||||
log jsonrpc json rpc
|
||||
|
||||
AM_LINK += $(COPY_MODULES_LINKER_ARGS) $(BLOCKDEV_MODULES_LINKER_ARGS)
|
||||
AM_LINK += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
||||
AM_LINK += -luuid
|
||||
|
||||
ifeq ($(CONFIG_UBSAN),y)
|
||||
AM_LINK += -fsanitize=undefined
|
||||
|
@ -127,6 +127,7 @@ CFLAGS += $(COMMON_CFLAGS) -Wno-pointer-sign -Wstrict-prototypes -Wold-style-d
|
||||
CXXFLAGS += $(COMMON_CFLAGS) -std=c++0x
|
||||
|
||||
SYS_LIBS += -lrt
|
||||
SYS_LIBS += -luuid
|
||||
|
||||
MAKEFLAGS += --no-print-directory
|
||||
|
||||
|
@ -31,7 +31,10 @@
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
BLOCKDEV_MODULES_LIST = bdev_malloc bdev_null bdev_nvme nvme vbdev_error vbdev_gpt vbdev_split
|
||||
BLOCKDEV_MODULES_LIST = bdev_malloc bdev_null bdev_nvme nvme vbdev_error vbdev_gpt vbdev_lvol vbdev_split
|
||||
|
||||
# Modules below are added as dependency for vbdev_lvol
|
||||
BLOCKDEV_MODULES_LIST += blob blob_bdev lvol
|
||||
|
||||
ifeq ($(CONFIG_RDMA),y)
|
||||
BLOCKDEV_MODULES_DEPS += -libverbs -lrdmacm
|
||||
|
@ -10,7 +10,7 @@ if [ -s /etc/redhat-release ]; then
|
||||
yum --enablerepo=extras install -y epel-release
|
||||
fi
|
||||
yum install -y gcc gcc-c++ make CUnit-devel libaio-devel openssl-devel \
|
||||
git astyle-devel python-pep8 lcov python clang-analyzer
|
||||
git astyle-devel python-pep8 lcov python clang-analyzer libuuid-devel
|
||||
# Additional dependencies for NVMe over Fabrics
|
||||
yum install -y libibverbs-devel librdmacm-devel
|
||||
# Additional dependencies for building docs
|
||||
@ -18,14 +18,14 @@ if [ -s /etc/redhat-release ]; then
|
||||
elif [ -f /etc/debian_version ]; then
|
||||
# Includes Ubuntu, Debian
|
||||
apt-get install -y gcc g++ make libcunit1-dev libaio-dev libssl-dev \
|
||||
git astyle pep8 lcov clang
|
||||
git astyle pep8 lcov clang uuid-dev
|
||||
# Additional dependencies for NVMe over Fabrics
|
||||
apt-get install -y libibverbs-dev librdmacm-dev
|
||||
# Additional dependencies for building docs
|
||||
apt-get install -y doxygen mscgen
|
||||
elif [ $SYSTEM = "FreeBSD" ] ; then
|
||||
pkg install gmake cunit openssl git devel/astyle bash devel/pep8 \
|
||||
python
|
||||
python misc/e2fsprogs-libuuid
|
||||
# Additional dependencies for building docs
|
||||
pkg install doxygen mscgen
|
||||
else
|
||||
|
@ -247,6 +247,47 @@ p = subparsers.add_parser('construct_error_bdev', help='Add bdev with error inje
|
||||
p.add_argument('base_name', help='base bdev name')
|
||||
p.set_defaults(func=construct_error_bdev)
|
||||
|
||||
|
||||
def construct_lvol_store(args):
|
||||
params = {'base_name': args.base_name}
|
||||
print_array(jsonrpc_call('construct_lvol_store', params))
|
||||
p = subparsers.add_parser('construct_lvol_store', help='Add logical volume store on base bdev')
|
||||
p.add_argument('base_name', help='base bdev name')
|
||||
p.set_defaults(func=construct_lvol_store)
|
||||
|
||||
|
||||
def construct_lvol_bdev(args):
|
||||
params = {
|
||||
'lvol_store_uuid': args.lvol_store_uuid,
|
||||
'size': args.size,
|
||||
}
|
||||
print_array(jsonrpc_call('construct_lvol_bdev', params))
|
||||
p = subparsers.add_parser('construct_lvol_bdev', help='Add a bdev with an logical volume backend')
|
||||
p.add_argument('lvol_store_uuid', help='lvol store UUID')
|
||||
p.add_argument('size', help='size in MiB for this bdev', type=int)
|
||||
p.set_defaults(func=construct_lvol_bdev)
|
||||
|
||||
|
||||
def resize_lvol_bdev(args):
|
||||
params = {
|
||||
'name': args.name,
|
||||
'size': args.size,
|
||||
}
|
||||
jsonrpc_call('resize_lvol_bdev', params)
|
||||
p = subparsers.add_parser('resize_lvol_bdev', help='Resize existing lvol bdev')
|
||||
p.add_argument('name', help='lvol bdev name')
|
||||
p.add_argument('size', help='new size in MiB for this bdev', type=int)
|
||||
p.set_defaults(func=resize_lvol_bdev)
|
||||
|
||||
|
||||
def destroy_lvol_store(args):
|
||||
params = {'lvol_store_uuid': args.lvol_store_uuid}
|
||||
jsonrpc_call('destroy_lvol_store', params)
|
||||
p = subparsers.add_parser('destroy_lvol_store', help='Destroy an logical volume store')
|
||||
p.add_argument('lvol_store_uuid', help='lvol store UUID')
|
||||
p.set_defaults(func=destroy_lvol_store)
|
||||
|
||||
|
||||
def set_trace_flag(args):
|
||||
params = {'flag': args.flag}
|
||||
jsonrpc_call('set_trace_flag', params)
|
||||
|
@ -34,7 +34,7 @@
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
DIRS-y = bdev blob blobfs event ioat iscsi json jsonrpc log nvme nvmf scsi util
|
||||
DIRS-y = bdev blob blobfs event ioat iscsi json jsonrpc log lvol nvme nvmf scsi util
|
||||
ifeq ($(OS),Linux)
|
||||
DIRS-$(CONFIG_VHOST) += vhost
|
||||
endif
|
||||
|
@ -34,7 +34,7 @@
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
DIRS-y = bdev.c scsi_nvme.c gpt
|
||||
DIRS-y = bdev.c scsi_nvme.c gpt vbdev_lvol.c
|
||||
|
||||
.PHONY: all clean $(DIRS-y)
|
||||
|
||||
|
1
test/unit/lib/bdev/vbdev_lvol.c/.gitignore
vendored
Normal file
1
test/unit/lib/bdev/vbdev_lvol.c/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
vbdev_lvol_ut
|
57
test/unit/lib/bdev/vbdev_lvol.c/Makefile
Normal file
57
test/unit/lib/bdev/vbdev_lvol.c/Makefile
Normal file
@ -0,0 +1,57 @@
|
||||
#
|
||||
# BSD LICENSE
|
||||
#
|
||||
# Copyright (c) Intel Corporation.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Intel Corporation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../../)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.app.mk
|
||||
|
||||
APP = vbdev_lvol_ut
|
||||
|
||||
C_SRCS := vbdev_lvol_ut.c
|
||||
CFLAGS += -I$(SPDK_ROOT_DIR)/test
|
||||
CFLAGS += -I$(SPDK_ROOT_DIR)/lib/bdev/lvol
|
||||
CFLAGS += -I$(SPDK_ROOT_DIR)/lib/lvol/bdev
|
||||
|
||||
SPDK_LIB_LIST = log util
|
||||
|
||||
LIBS += $(SPDK_LIB_LINKER_ARGS) -lcunit
|
||||
|
||||
all : $(APP)
|
||||
|
||||
$(APP) : $(OBJS) $(SPDK_LIB_FILES)
|
||||
$(LINK_C)
|
||||
|
||||
clean :
|
||||
$(CLEAN_C) $(APP)
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.deps.mk
|
505
test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c
Normal file
505
test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c
Normal file
@ -0,0 +1,505 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "spdk_cunit.h"
|
||||
#include "spdk/string.h"
|
||||
|
||||
#include "vbdev_lvol.c"
|
||||
|
||||
int g_lvolerrno;
|
||||
int g_lvserrno;
|
||||
int g_cluster_size;
|
||||
struct spdk_lvol_store *g_lvs = NULL;
|
||||
struct spdk_lvol *g_lvol = NULL;
|
||||
struct lvol_store_bdev *g_lvs_bdev = NULL;
|
||||
struct spdk_bdev *g_base_bdev = NULL;
|
||||
|
||||
|
||||
static struct spdk_bdev g_bdev = {};
|
||||
static struct spdk_bs_dev *g_bs_dev = NULL;
|
||||
static struct spdk_lvol_store *g_lvol_store = NULL;
|
||||
bool lvol_store_initialize_fail = false;
|
||||
bool lvol_store_initialize_cb_fail = false;
|
||||
bool lvol_already_opened = false;
|
||||
|
||||
void
|
||||
spdk_bdev_unregister(struct spdk_bdev *bdev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
bdev_blob_destroy(struct spdk_bs_dev *bs_dev)
|
||||
{
|
||||
CU_ASSERT(g_bs_dev != NULL);
|
||||
CU_ASSERT(bs_dev != NULL);
|
||||
CU_ASSERT(g_bs_dev == bs_dev);
|
||||
free(bs_dev);
|
||||
g_bs_dev = NULL;
|
||||
lvol_already_opened = false;
|
||||
}
|
||||
|
||||
struct spdk_bs_dev *
|
||||
spdk_bdev_create_bs_dev(struct spdk_bdev *bdev)
|
||||
{
|
||||
struct spdk_bs_dev *bs_dev;
|
||||
|
||||
if (lvol_already_opened == true)
|
||||
return NULL;
|
||||
|
||||
lvol_already_opened = true;
|
||||
|
||||
bs_dev = calloc(1, sizeof(*bs_dev));
|
||||
bs_dev->destroy = bdev_blob_destroy;
|
||||
|
||||
CU_ASSERT(g_bs_dev == NULL);
|
||||
g_bs_dev = bs_dev;
|
||||
return bs_dev;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_lvs_init(struct spdk_bs_dev *bs_dev, spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol_store *lvs;
|
||||
int error = 0;
|
||||
|
||||
if (lvol_store_initialize_fail)
|
||||
return -1;
|
||||
|
||||
if (lvol_store_initialize_cb_fail) {
|
||||
lvs = NULL;
|
||||
error = -1;
|
||||
} else {
|
||||
lvs = calloc(1, sizeof(*lvs));
|
||||
lvs->bs_dev = bs_dev;
|
||||
error = 0;
|
||||
}
|
||||
cb_fn(cb_arg, lvs, error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn,
|
||||
void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol_store_req *req = cb_arg;
|
||||
free(req);
|
||||
free(lvs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_lvol_resize(struct spdk_lvol *lvol, size_t sz,
|
||||
spdk_lvol_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
cb_fn(cb_arg, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
spdk_bs_get_cluster_size(struct spdk_blob_store *bs)
|
||||
{
|
||||
return g_cluster_size;
|
||||
}
|
||||
|
||||
struct spdk_bdev *
|
||||
spdk_bdev_get_by_name(const char *bdev_name)
|
||||
{
|
||||
if (!strcmp(g_base_bdev->name, bdev_name)) {
|
||||
return g_base_bdev;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_lvol_close(struct spdk_lvol *lvol)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
spdk_lvol_destroy(struct spdk_lvol *lvol)
|
||||
{
|
||||
SPDK_CU_ASSERT_FATAL(lvol == g_lvol);
|
||||
free(lvol->name);
|
||||
free(lvol);
|
||||
g_lvol = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
spdk_is_bdev_opened(struct spdk_bdev *bdev)
|
||||
{
|
||||
struct spdk_bdev *base;
|
||||
|
||||
if (bdev->bdev_opened) {
|
||||
return true;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(base, &bdev->base_bdevs, base_bdev_link) {
|
||||
if (spdk_is_bdev_opened(base)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bdev_io_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_status status)
|
||||
{
|
||||
}
|
||||
|
||||
struct spdk_io_channel *spdk_lvol_get_io_channel(struct spdk_lvol *lvol)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bdev_io_get_buf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_buf_cb cb)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bs_io_read_blob(struct spdk_blob *blob, struct spdk_io_channel *channel,
|
||||
void *payload, uint64_t offset, uint64_t length,
|
||||
spdk_blob_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bs_io_write_blob(struct spdk_blob *blob, struct spdk_io_channel *channel,
|
||||
void *payload, uint64_t offset, uint64_t length,
|
||||
spdk_blob_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bs_io_writev_blob(struct spdk_blob *blob, struct spdk_io_channel *channel,
|
||||
struct iovec *iov, int iovcnt, uint64_t offset, uint64_t length,
|
||||
spdk_blob_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bs_io_readv_blob(struct spdk_blob *blob, struct spdk_io_channel *channel,
|
||||
struct iovec *iov, int iovcnt, uint64_t offset, uint64_t length,
|
||||
spdk_blob_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bs_io_flush_channel(struct spdk_io_channel *channel, spdk_blob_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bdev_module_list_add(struct spdk_bdev_module_if *bdev_module)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
spdk_json_write_name(struct spdk_json_write_ctx *w, const char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_json_write_string(struct spdk_json_write_ctx *w, const char *val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
spdk_bdev_get_name(const struct spdk_bdev *bdev)
|
||||
{
|
||||
return "test";
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bdev_register(struct spdk_bdev *bdev)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bdev_module_examine_done(struct spdk_bdev_module_if *module)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
spdk_lvol_create(struct spdk_lvol_store *lvs, size_t sz, spdk_lvol_op_with_handle_complete cb_fn,
|
||||
void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol *lvol = calloc(1, sizeof(*lvol));
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(lvol != NULL);
|
||||
|
||||
|
||||
lvol->lvol_store = lvs;
|
||||
lvol->sz = sz * 1024 * 1024;
|
||||
lvol->name = spdk_sprintf_alloc("%s", "UNIT_TEST_UUID");
|
||||
SPDK_CU_ASSERT_FATAL(lvol->name != NULL);
|
||||
|
||||
TAILQ_INIT(&lvs->lvols);
|
||||
TAILQ_INSERT_TAIL(&lvol->lvol_store->lvols, lvol, link);
|
||||
|
||||
cb_fn(cb_arg, lvol, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_store_op_complete(void *cb_arg, int lvserrno)
|
||||
{
|
||||
g_lvserrno = lvserrno;
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_store_op_with_handle_complete(void *cb_arg, struct spdk_lvol_store *lvs, int lvserrno)
|
||||
{
|
||||
g_lvserrno = lvserrno;
|
||||
g_lvol_store = lvs;
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
vbdev_lvol_create_complete(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno)
|
||||
{
|
||||
g_lvolerrno = lvolerrno;
|
||||
g_lvol = lvol;
|
||||
}
|
||||
|
||||
static void
|
||||
vbdev_lvol_resize_complete(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
g_lvolerrno = lvolerrno;
|
||||
}
|
||||
|
||||
static void
|
||||
ut_lvol_init(void)
|
||||
{
|
||||
uuid_t wrong_uuid;
|
||||
int sz = 10;
|
||||
int rc;
|
||||
|
||||
g_lvs = calloc(1, sizeof(*g_lvs));
|
||||
g_lvs_bdev = calloc(1, sizeof(*g_lvs_bdev));
|
||||
g_base_bdev = calloc(1, sizeof(*g_base_bdev));
|
||||
|
||||
g_lvs_bdev->lvs = g_lvs;
|
||||
g_lvs_bdev->bdev = g_base_bdev;
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(g_lvs != NULL);
|
||||
|
||||
uuid_generate_time(g_lvs->uuid);
|
||||
uuid_generate_time(wrong_uuid);
|
||||
g_lvs->page_size = 4096;
|
||||
|
||||
/* Incorrect uuid set */
|
||||
g_lvolerrno = 0;
|
||||
rc = vbdev_lvol_create(wrong_uuid, sz, vbdev_lvol_create_complete, NULL);
|
||||
CU_ASSERT(rc == -ENODEV);
|
||||
|
||||
TAILQ_INSERT_TAIL(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores);
|
||||
|
||||
/* Successful lvol create */
|
||||
g_lvolerrno = -1;
|
||||
rc = vbdev_lvol_create(g_lvs->uuid, sz, 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);
|
||||
|
||||
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_resize(void)
|
||||
{
|
||||
int sz = 10;
|
||||
int rc = 0;
|
||||
|
||||
g_lvs = calloc(1, sizeof(*g_lvs));
|
||||
g_lvs_bdev = calloc(1, sizeof(*g_lvs_bdev));
|
||||
g_base_bdev = calloc(1, sizeof(*g_base_bdev));
|
||||
g_lvs_bdev->lvs = g_lvs;
|
||||
g_lvs_bdev->bdev = g_base_bdev;
|
||||
|
||||
|
||||
uuid_generate_time(g_lvs->uuid);
|
||||
g_lvs->page_size = 4096;
|
||||
g_base_bdev->blocklen = 4096;
|
||||
TAILQ_INSERT_TAIL(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores);
|
||||
|
||||
/* Successful lvol create */
|
||||
g_lvolerrno = -1;
|
||||
rc = vbdev_lvol_create(g_lvs->uuid, sz, vbdev_lvol_create_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(g_lvolerrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
||||
|
||||
g_base_bdev->bdev_opened = false;
|
||||
g_base_bdev->ctxt = g_lvol;
|
||||
|
||||
g_base_bdev->name = spdk_sprintf_alloc("%s", g_lvol->name);
|
||||
|
||||
/* Successful lvol resize */
|
||||
rc = vbdev_lvol_resize(g_lvol->name, 20, vbdev_lvol_resize_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(g_base_bdev->blockcnt == 20 * g_cluster_size / g_base_bdev->blocklen);
|
||||
|
||||
/* Resize while bdev is open */
|
||||
g_base_bdev->bdev_opened = true;
|
||||
rc = vbdev_lvol_resize(g_lvol->name, 20, vbdev_lvol_resize_complete, NULL);
|
||||
CU_ASSERT(rc != 0);
|
||||
|
||||
/* Resize with wrong bdev name */
|
||||
g_base_bdev->bdev_opened = false;
|
||||
rc = vbdev_lvol_resize("wrong name", 20, vbdev_lvol_resize_complete, NULL);
|
||||
CU_ASSERT(rc != 0);
|
||||
|
||||
/* Resize with correct bdev name, but wrong lvol name */
|
||||
sprintf(g_lvol->name, "wrong name");
|
||||
rc = vbdev_lvol_resize(g_base_bdev->name, 20, vbdev_lvol_resize_complete, NULL);
|
||||
CU_ASSERT(rc != 0);
|
||||
|
||||
/* Successful lvol destruct */
|
||||
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->name);
|
||||
free(g_base_bdev);
|
||||
}
|
||||
|
||||
static void
|
||||
ut_lvs_init(void)
|
||||
{
|
||||
int rc = 0;
|
||||
struct spdk_lvol_store *lvs;
|
||||
struct spdk_bs_dev *bs_dev_temp;
|
||||
|
||||
/* spdk_lvs_init() fails */
|
||||
lvol_store_initialize_fail = true;
|
||||
|
||||
rc = vbdev_lvs_create(&g_bdev, lvol_store_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(rc != 0);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
CU_ASSERT(g_lvol_store == NULL);
|
||||
CU_ASSERT(g_bs_dev == NULL);
|
||||
|
||||
lvol_store_initialize_fail = false;
|
||||
|
||||
/* spdk_lvs_init_cb() fails */
|
||||
lvol_store_initialize_cb_fail = true;
|
||||
|
||||
rc = vbdev_lvs_create(&g_bdev, lvol_store_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(g_lvserrno != 0);
|
||||
CU_ASSERT(g_lvol_store == NULL);
|
||||
CU_ASSERT(g_bs_dev == NULL);
|
||||
|
||||
lvol_store_initialize_cb_fail = false;
|
||||
|
||||
/* Lvol store is succesfully created */
|
||||
rc = vbdev_lvs_create(&g_bdev, lvol_store_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
CU_ASSERT(g_lvol_store != NULL);
|
||||
CU_ASSERT(g_bs_dev != NULL);
|
||||
|
||||
lvs = g_lvol_store;
|
||||
g_lvol_store = NULL;
|
||||
bs_dev_temp = g_bs_dev;
|
||||
g_bs_dev = NULL;
|
||||
|
||||
/* Bdev with lvol store already claimed */
|
||||
rc = vbdev_lvs_create(&g_bdev, lvol_store_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(rc != 0);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
CU_ASSERT(g_lvol_store == NULL);
|
||||
CU_ASSERT(g_bs_dev == NULL);
|
||||
|
||||
/* Destruct lvol store */
|
||||
g_bs_dev = bs_dev_temp;
|
||||
|
||||
vbdev_lvs_destruct(lvs, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
CU_ASSERT(g_lvol_store == NULL);
|
||||
free(g_bs_dev);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
unsigned int num_failures;
|
||||
|
||||
if (CU_initialize_registry() != CUE_SUCCESS) {
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
suite = CU_add_suite("lvol", NULL, NULL);
|
||||
if (suite == NULL) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
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_resize", ut_lvol_resize) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||
CU_basic_run_tests();
|
||||
num_failures = CU_get_number_of_failures();
|
||||
CU_cleanup_registry();
|
||||
return num_failures;
|
||||
}
|
44
test/unit/lib/lvol/Makefile
Normal file
44
test/unit/lib/lvol/Makefile
Normal file
@ -0,0 +1,44 @@
|
||||
#
|
||||
# BSD LICENSE
|
||||
#
|
||||
# Copyright (c) Intel Corporation.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Intel Corporation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
DIRS-y = lvol.c
|
||||
|
||||
.PHONY: all clean $(DIRS-y)
|
||||
|
||||
all: $(DIRS-y)
|
||||
clean: $(DIRS-y)
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.subdirs.mk
|
1
test/unit/lib/lvol/lvol.c/.gitignore
vendored
Normal file
1
test/unit/lib/lvol/lvol.c/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
lvol_ut
|
56
test/unit/lib/lvol/lvol.c/Makefile
Normal file
56
test/unit/lib/lvol/lvol.c/Makefile
Normal file
@ -0,0 +1,56 @@
|
||||
#
|
||||
# BSD LICENSE
|
||||
#
|
||||
# Copyright (c) Intel Corporation.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Intel Corporation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.app.mk
|
||||
|
||||
SPDK_LIB_LIST = util log
|
||||
|
||||
CFLAGS += -I$(SPDK_ROOT_DIR)/test
|
||||
CFLAGS += -I$(SPDK_ROOT_DIR)/lib/lvol
|
||||
LIBS += $(SPDK_LIB_LINKER_ARGS)
|
||||
LIBS += -lcunit
|
||||
|
||||
APP = lvol_ut
|
||||
C_SRCS := lvol_ut.c
|
||||
|
||||
all : $(APP)
|
||||
|
||||
$(APP) : $(OBJS) $(SPDK_LIB_FILES)
|
||||
$(LINK_C)
|
||||
|
||||
clean :
|
||||
$(CLEAN_C) $(APP)
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.deps.mk
|
482
test/unit/lib/lvol/lvol.c/lvol_ut.c
Normal file
482
test/unit/lib/lvol/lvol.c/lvol_ut.c
Normal file
@ -0,0 +1,482 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "spdk_cunit.h"
|
||||
#include "spdk/blob.h"
|
||||
#include "spdk/io_channel.h"
|
||||
|
||||
#include "lib/test_env.c"
|
||||
|
||||
#include "lvol.c"
|
||||
|
||||
#define DEV_BUFFER_SIZE (64 * 1024 * 1024)
|
||||
#define DEV_BUFFER_BLOCKLEN (4096)
|
||||
#define DEV_BUFFER_BLOCKCNT (DEV_BUFFER_SIZE / DEV_BUFFER_BLOCKLEN)
|
||||
#define DEV_FREE_CLUSTERS 0xFFFF
|
||||
|
||||
int g_lvserrno;
|
||||
int g_resize_rc;
|
||||
struct spdk_lvol_store *g_lvol_store;
|
||||
struct spdk_lvol *g_lvol;
|
||||
struct spdk_blob_store {};
|
||||
|
||||
struct spdk_io_channel *spdk_bs_alloc_io_channel(struct spdk_blob_store *bs)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_blob_md_set_xattr(struct spdk_blob *blob, const char *name, const void *value,
|
||||
uint16_t value_len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
spdk_bs_get_page_size(struct spdk_blob_store *bs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
init_dev(struct spdk_bs_dev *dev)
|
||||
{
|
||||
dev->blockcnt = DEV_BUFFER_BLOCKCNT;
|
||||
dev->blocklen = DEV_BUFFER_BLOCKLEN;
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct spdk_blob_store *bs;
|
||||
|
||||
bs = calloc(1, sizeof(*bs));
|
||||
|
||||
cb_fn(cb_arg, bs, 0);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bs_unload(struct spdk_blob_store *bs, spdk_bs_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
free(bs);
|
||||
|
||||
cb_fn(cb_arg, 0);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bs_md_delete_blob(struct spdk_blob_store *bs, spdk_blob_id blobid,
|
||||
spdk_blob_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
cb_fn(cb_arg, 0);
|
||||
}
|
||||
|
||||
spdk_blob_id
|
||||
spdk_blob_get_id(struct spdk_blob *blob)
|
||||
{
|
||||
spdk_blob_id id = 0;
|
||||
return id;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
spdk_bs_get_cluster_size(struct spdk_blob_store *bs)
|
||||
{
|
||||
return DEV_BUFFER_BLOCKLEN;
|
||||
}
|
||||
|
||||
void spdk_bs_md_close_blob(struct spdk_blob **b,
|
||||
spdk_blob_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
cb_fn(cb_arg, 0);
|
||||
}
|
||||
|
||||
int
|
||||
spdk_bs_md_resize_blob(struct spdk_blob *blob, uint64_t sz)
|
||||
{
|
||||
return g_resize_rc;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bs_md_sync_blob(struct spdk_blob *blob,
|
||||
spdk_blob_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
cb_fn(cb_arg, 0);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bs_md_open_blob(struct spdk_blob_store *bs, spdk_blob_id blobid,
|
||||
spdk_blob_op_with_handle_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
cb_fn(cb_arg, NULL, 0);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
spdk_bs_free_cluster_count(struct spdk_blob_store *bs)
|
||||
{
|
||||
return DEV_FREE_CLUSTERS;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bs_md_create_blob(struct spdk_blob_store *bs,
|
||||
spdk_blob_op_with_id_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
cb_fn(cb_arg, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
_lvol_send_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx)
|
||||
{
|
||||
fn(ctx);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
static void
|
||||
lvol_op_with_handle_complete(void *cb_arg, struct spdk_lvol *lvol, int lvserrno)
|
||||
{
|
||||
g_lvol = lvol;
|
||||
g_lvserrno = lvserrno;
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_store_op_complete(void *cb_arg, int lvserrno)
|
||||
{
|
||||
g_lvserrno = lvserrno;
|
||||
}
|
||||
|
||||
static void
|
||||
lvs_init_unload_success(void)
|
||||
{
|
||||
struct spdk_bs_dev bs_dev;
|
||||
int rc = 0;
|
||||
|
||||
init_dev(&bs_dev);
|
||||
|
||||
spdk_allocate_thread(_lvol_send_msg, NULL, NULL);
|
||||
|
||||
g_lvserrno = -1;
|
||||
rc = spdk_lvs_init(&bs_dev, 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 = -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;
|
||||
|
||||
spdk_free_thread();
|
||||
}
|
||||
|
||||
static void
|
||||
lvs_unload_lvs_is_null_fail(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
spdk_allocate_thread(_lvol_send_msg, NULL, NULL);
|
||||
|
||||
g_lvserrno = -1;
|
||||
rc = spdk_lvs_unload(NULL, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(rc == -ENODEV);
|
||||
CU_ASSERT(g_lvserrno == -1);
|
||||
|
||||
spdk_free_thread();
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_create_destroy_success(void)
|
||||
{
|
||||
struct spdk_bs_dev bs_dev;
|
||||
int rc = 0;
|
||||
|
||||
init_dev(&bs_dev);
|
||||
|
||||
spdk_allocate_thread(_lvol_send_msg, NULL, NULL);
|
||||
|
||||
g_lvserrno = -1;
|
||||
rc = spdk_lvs_init(&bs_dev, 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, 10, lvol_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
||||
|
||||
spdk_lvol_destroy(g_lvol);
|
||||
|
||||
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;
|
||||
|
||||
spdk_free_thread();
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_create_fail(void)
|
||||
{
|
||||
struct spdk_bs_dev bs_dev;
|
||||
int rc = 0;
|
||||
|
||||
init_dev(&bs_dev);
|
||||
|
||||
spdk_allocate_thread(_lvol_send_msg, NULL, NULL);
|
||||
|
||||
g_lvol_store = NULL;
|
||||
g_lvserrno = 0;
|
||||
rc = spdk_lvs_init(NULL, lvol_store_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(rc != 0);
|
||||
CU_ASSERT(g_lvol_store == NULL);
|
||||
|
||||
rc = spdk_lvs_init(&bs_dev, lvol_store_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
||||
|
||||
g_lvol = NULL;
|
||||
rc = spdk_lvol_create(NULL, 10, lvol_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(rc != 0);
|
||||
CU_ASSERT(g_lvol == NULL);
|
||||
|
||||
rc = spdk_lvol_create(g_lvol_store, DEV_FREE_CLUSTERS + 1, lvol_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(rc != 0);
|
||||
CU_ASSERT(g_lvol == NULL);
|
||||
|
||||
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;
|
||||
|
||||
spdk_free_thread();
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_destroy_fail(void)
|
||||
{
|
||||
struct spdk_bs_dev bs_dev;
|
||||
int rc = 0;
|
||||
|
||||
init_dev(&bs_dev);
|
||||
|
||||
spdk_allocate_thread(_lvol_send_msg, NULL, NULL);
|
||||
|
||||
rc = spdk_lvs_init(&bs_dev, 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, 10, lvol_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
||||
|
||||
spdk_lvol_destroy(g_lvol);
|
||||
// nothing to check here... it should just still work
|
||||
|
||||
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;
|
||||
|
||||
spdk_free_thread();
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_close_fail(void)
|
||||
{
|
||||
struct spdk_bs_dev bs_dev;
|
||||
int rc = 0;
|
||||
|
||||
init_dev(&bs_dev);
|
||||
|
||||
spdk_allocate_thread(_lvol_send_msg, NULL, NULL);
|
||||
|
||||
rc = spdk_lvs_init(&bs_dev, 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, 10, lvol_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
||||
|
||||
spdk_lvol_close(g_lvol);
|
||||
// nothing to check here... it should just still work
|
||||
|
||||
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;
|
||||
|
||||
spdk_free_thread();
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_close_success(void)
|
||||
{
|
||||
struct spdk_bs_dev bs_dev;
|
||||
int rc = 0;
|
||||
|
||||
init_dev(&bs_dev);
|
||||
|
||||
spdk_allocate_thread(_lvol_send_msg, NULL, NULL);
|
||||
|
||||
g_lvserrno = -1;
|
||||
rc = spdk_lvs_init(&bs_dev, 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, 10, lvol_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
||||
|
||||
spdk_lvol_close(g_lvol);
|
||||
|
||||
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;
|
||||
|
||||
spdk_free_thread();
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_resize(void)
|
||||
{
|
||||
struct spdk_bs_dev bs_dev;
|
||||
int rc = 0;
|
||||
|
||||
init_dev(&bs_dev);
|
||||
|
||||
spdk_allocate_thread(_lvol_send_msg, NULL, NULL);
|
||||
|
||||
g_resize_rc = 0;
|
||||
g_lvserrno = -1;
|
||||
rc = spdk_lvs_init(&bs_dev, 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, 10, lvol_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
||||
|
||||
/* Resize to same size */
|
||||
rc = spdk_lvol_resize(g_lvol, 10, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
|
||||
/* Resize to smaller size */
|
||||
rc = spdk_lvol_resize(g_lvol, 5, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
|
||||
/* Resize to bigger size */
|
||||
rc = spdk_lvol_resize(g_lvol, 15, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
|
||||
/* Resize to size = 0 */
|
||||
rc = spdk_lvol_resize(g_lvol, 0, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
|
||||
/* Resize to bigger size than available */
|
||||
rc = spdk_lvol_resize(g_lvol, 0xFFFFFFFF, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(rc != 0);
|
||||
|
||||
/* Fail resize */
|
||||
g_resize_rc = -1;
|
||||
g_lvserrno = 0;
|
||||
rc = spdk_lvol_resize(g_lvol, 10, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(rc != 0);
|
||||
CU_ASSERT(g_lvserrno != 0);
|
||||
|
||||
spdk_lvol_destroy(g_lvol);
|
||||
|
||||
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;
|
||||
|
||||
spdk_free_thread();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
unsigned int num_failures;
|
||||
|
||||
if (CU_initialize_registry() != CUE_SUCCESS) {
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
suite = CU_add_suite("lvol", NULL, NULL);
|
||||
if (suite == NULL) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
if (
|
||||
CU_add_test(suite, "lvs_init_unload_success", lvs_init_unload_success) == NULL ||
|
||||
CU_add_test(suite, "lvs_unload_lvs_is_null_fail", lvs_unload_lvs_is_null_fail) == NULL ||
|
||||
CU_add_test(suite, "lvol_create_destroy_success", lvol_create_destroy_success) == NULL ||
|
||||
CU_add_test(suite, "lvol_create_fail", lvol_create_fail) == NULL ||
|
||||
CU_add_test(suite, "lvol_destroy_fail", lvol_destroy_fail) == NULL ||
|
||||
CU_add_test(suite, "lvol_close_fail", lvol_close_fail) == NULL ||
|
||||
CU_add_test(suite, "lvol_close_success", lvol_close_success) == NULL ||
|
||||
CU_add_test(suite, "lvol_resize", lvol_resize) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||
CU_basic_run_tests();
|
||||
num_failures = CU_get_number_of_failures();
|
||||
CU_cleanup_registry();
|
||||
|
||||
return num_failures;
|
||||
}
|
@ -44,6 +44,7 @@ fi
|
||||
$valgrind test/unit/lib/bdev/bdev.c/bdev_ut
|
||||
$valgrind test/unit/lib/bdev/scsi_nvme.c/scsi_nvme_ut
|
||||
$valgrind test/unit/lib/bdev/gpt/gpt.c/gpt_ut
|
||||
$valgrind test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut
|
||||
|
||||
$valgrind test/unit/lib/blob/blob.c/blob_ut
|
||||
$valgrind test/unit/lib/blobfs/tree.c/tree_ut
|
||||
@ -84,6 +85,8 @@ $valgrind test/unit/lib/scsi/lun.c/lun_ut
|
||||
$valgrind test/unit/lib/scsi/scsi.c/scsi_ut
|
||||
$valgrind test/unit/lib/scsi/scsi_bdev.c/scsi_bdev_ut
|
||||
|
||||
$valgrind test/unit/lib/lvol/lvol.c/lvol_ut
|
||||
|
||||
$valgrind test/unit/lib/iscsi/param.c/param_ut
|
||||
$valgrind test/unit/lib/iscsi/tgt_node.c/tgt_node_ut test/unit/lib/iscsi/tgt_node.c/tgt_node.conf
|
||||
$valgrind test/unit/lib/iscsi/iscsi.c/iscsi_ut
|
||||
|
Loading…
x
Reference in New Issue
Block a user