lvol: Add vbdev_lvs_destruct() and change unload behaviour [3/3]

This patch adds new API to remove logical volume store
from device it is on. It is only used from RPC, when
user explicitly requests. It allows to use the device to
use as any other bdev.

vbdev_lvs_unload() is now only called from hotremove and
during application shutdown. Which makes it possible to
load it again during application start up.

Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: If6452ecc3fff99237d1704ff7cd8de4d7133221d
Reviewed-on: https://review.gerrithub.io/382021
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Tomasz Zawadzki 2017-10-21 03:23:54 +02:00 committed by Jim Harris
parent d189b8eedd
commit ebf0312eef
5 changed files with 152 additions and 19 deletions

View File

@ -85,6 +85,7 @@ struct spdk_lvol_store {
uint64_t total_blocks;
int lvol_count;
int lvols_opened;
bool destruct;
TAILQ_HEAD(, spdk_lvol) lvols;
bool on_list;
TAILQ_ENTRY(spdk_lvol_store) link;

View File

@ -53,7 +53,7 @@ vbdev_lvs_hotremove_cb(void *ctx)
TAILQ_FOREACH_SAFE(lvs_bdev, &g_spdk_lvol_pairs, lvol_stores, tmp) {
if (lvs_bdev) {
if (lvs_bdev->bdev == bdev) {
vbdev_lvs_destruct(lvs_bdev->lvs, NULL, NULL);
vbdev_lvs_unload(lvs_bdev->lvs, NULL, NULL);
}
}
}
@ -155,6 +155,60 @@ vbdev_lvs_create(struct spdk_bdev *base_bdev, uint32_t cluster_sz,
return 0;
}
static void
_vbdev_lvs_unload_cb(void *cb_arg, int lvserrno)
{
struct spdk_lvs_req *req = cb_arg;
SPDK_INFOLOG(SPDK_TRACE_VBDEV_LVOL, "Lvol store bdev unloaded\n");
if (req->cb_fn != NULL)
req->cb_fn(req->cb_arg, lvserrno);
free(req);
}
void
vbdev_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, void *cb_arg)
{
struct spdk_lvs_req *req;
struct lvol_store_bdev *lvs_bdev;
struct spdk_lvol *lvol, *tmp;
lvs_bdev = vbdev_get_lvs_bdev_by_lvs(lvs);
TAILQ_REMOVE(&g_spdk_lvol_pairs, lvs_bdev, lvol_stores);
req = calloc(1, sizeof(*req));
if (!req) {
SPDK_ERRLOG("Cannot alloc memory for vbdev lvol store request pointer\n");
if (cb_fn != NULL)
cb_fn(cb_arg, -ENOMEM);
return;
}
req->cb_fn = cb_fn;
req->cb_arg = cb_arg;
if (TAILQ_EMPTY(&lvs->lvols)) {
spdk_lvs_unload(lvs, _vbdev_lvs_unload_cb, req);
} else {
lvs->destruct_req = calloc(1, sizeof(*lvs->destruct_req));
if (!lvs->destruct_req) {
SPDK_ERRLOG("Cannot alloc memory for vbdev lvol store request pointer\n");
_vbdev_lvs_unload_cb(req, -ENOMEM);
return;
}
lvs->destruct_req->cb_fn = _vbdev_lvs_unload_cb;
lvs->destruct_req->cb_arg = req;
lvs->destruct = false;
TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
lvol->close_only = true;
spdk_vbdev_unregister(lvol->bdev, NULL, NULL);
}
}
free(lvs_bdev);
}
static void
_vbdev_lvs_destruct_cb(void *cb_arg, int lvserrno)
{
@ -168,10 +222,8 @@ _vbdev_lvs_destruct_cb(void *cb_arg, int lvserrno)
}
void
vbdev_lvs_destruct(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn,
void *cb_arg)
vbdev_lvs_destruct(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, void *cb_arg)
{
struct spdk_lvs_req *req;
struct lvol_store_bdev *lvs_bdev;
struct spdk_lvol *lvol, *tmp;
@ -198,7 +250,7 @@ vbdev_lvs_destruct(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn,
}
if (all_lvols_closed == true) {
spdk_lvs_unload(lvs, _vbdev_lvs_destruct_cb, req);
spdk_lvs_destroy(lvs, false, _vbdev_lvs_destruct_cb, req);
} else {
lvs->destruct_req = calloc(1, sizeof(*lvs->destruct_req));
if (!lvs->destruct_req) {
@ -208,8 +260,9 @@ vbdev_lvs_destruct(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn,
}
lvs->destruct_req->cb_fn = _vbdev_lvs_destruct_cb;
lvs->destruct_req->cb_arg = req;
lvs->destruct = true;
TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
lvol->close_only = true;
lvol->close_only = false;
spdk_vbdev_unregister(lvol->bdev, NULL, NULL);
}
}
@ -686,7 +739,7 @@ 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);
vbdev_lvs_unload(lvs_bdev->lvs, NULL, NULL);
}
}

View File

@ -48,6 +48,7 @@ struct lvol_store_bdev {
int vbdev_lvs_create(struct spdk_bdev *base_bdev, uint32_t cluster_sz,
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);
void vbdev_lvs_unload(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);

View File

@ -575,6 +575,7 @@ spdk_lvs_init(struct spdk_bs_dev *bs_dev, struct spdk_lvs_opts *o,
lvs_req->cb_arg = cb_arg;
lvs_req->lvol_store = lvs;
lvs->bs_dev = bs_dev;
lvs->destruct = false;
strncpy(opts.bstype.bstype, "LVOLSTORE", SPDK_BLOBSTORE_TYPE_LENGTH);
@ -751,7 +752,9 @@ _spdk_lvol_close_blob_cb(void *cb_arg, int lvolerrno)
SPDK_INFOLOG(SPDK_TRACE_LVOL, "Lvol %s closed\n", lvol->old_name);
if (lvol->lvol_store->destruct_req && all_lvols_closed == true) {
spdk_lvs_unload(lvol->lvol_store, _spdk_lvs_destruct_cb, lvol->lvol_store->destruct_req);
if (!lvol->lvol_store->destruct) {
spdk_lvs_unload(lvol->lvol_store, _spdk_lvs_destruct_cb, lvol->lvol_store->destruct_req);
}
}
end:
@ -773,8 +776,11 @@ _spdk_lvol_delete_blob_cb(void *cb_arg, int lvolerrno)
goto end;
}
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);
if (lvol->lvol_store->destruct)
spdk_lvs_destroy(lvol->lvol_store, false, _spdk_lvs_destruct_cb, lvol->lvol_store->destruct_req);
}
SPDK_INFOLOG(SPDK_TRACE_LVOL, "Lvol %s deleted\n", lvol->old_name);
@ -1065,7 +1071,6 @@ spdk_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_
req->cb_arg = lvol_req;
req->lvol = lvol;
TAILQ_REMOVE(&lvol->lvol_store->lvols, lvol, link);
spdk_bs_md_delete_blob(bs, lvol->blob_id, _spdk_lvol_delete_blob_cb, req);
}

View File

@ -183,15 +183,13 @@ spdk_lvs_init(struct spdk_bs_dev *bs_dev, struct spdk_lvs_opts *o,
int
spdk_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, void *cb_arg)
{
struct spdk_lvol *lvol;
struct spdk_lvol *lvol, *tmp;
while (!TAILQ_EMPTY(&lvs->lvols)) {
lvol = TAILQ_FIRST(&lvs->lvols);
TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
TAILQ_REMOVE(&lvs->lvols, lvol, link);
free(lvol->old_name);
free(lvol);
}
g_lvol_store = NULL;
free(lvs);
@ -204,8 +202,29 @@ spdk_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, void *c
}
int
spdk_lvol_resize(struct spdk_lvol *lvol, size_t sz,
spdk_lvol_op_complete cb_fn, void *cb_arg)
spdk_lvs_destroy(struct spdk_lvol_store *lvs, bool unmap_device, spdk_lvs_op_complete cb_fn,
void *cb_arg)
{
struct spdk_lvol *lvol, *tmp;
TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
TAILQ_REMOVE(&lvs->lvols, lvol, link);
free(lvol->old_name);
free(lvol);
}
g_lvol_store = NULL;
free(lvs);
g_bs_dev->destroy(g_bs_dev);
if (cb_fn != NULL)
cb_fn(cb_arg, 0);
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);
@ -245,8 +264,10 @@ spdk_lvol_close(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_ar
destruct_req = lvol->lvol_store->destruct_req;
if (destruct_req && all_lvols_closed == true) {
spdk_lvs_unload(lvol->lvol_store, destruct_req->cb_fn, destruct_req->cb_arg);
free(destruct_req);
if (!lvol->lvol_store->destruct) {
spdk_lvs_unload(lvol->lvol_store, destruct_req->cb_fn, destruct_req->cb_arg);
free(destruct_req);
}
}
cb_fn(cb_arg, 0);
@ -255,10 +276,28 @@ spdk_lvol_close(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_ar
void
spdk_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
{
struct spdk_lvs_req *destruct_req;
SPDK_CU_ASSERT_FATAL(lvol == g_lvol);
if (lvol->ref_count != 0) {
cb_fn(cb_arg, -ENODEV);
}
TAILQ_REMOVE(&lvol->lvol_store->lvols, lvol, link);
destruct_req = lvol->lvol_store->destruct_req;
if (destruct_req && TAILQ_EMPTY(&lvol->lvol_store->lvols)) {
if (!lvol->lvol_store->destruct) {
spdk_lvs_unload(lvol->lvol_store, destruct_req->cb_fn, destruct_req->cb_arg);
} else {
spdk_lvs_destroy(lvol->lvol_store, false, destruct_req->cb_fn, destruct_req->cb_arg);
free(destruct_req);
}
}
g_lvol = NULL;
free(lvol->old_name);
free(lvol);
g_lvol = NULL;
cb_fn(cb_arg, 0);
}
@ -673,6 +712,39 @@ ut_lvol_resize(void)
free(g_base_bdev);
}
static void
ut_lvs_unload(void)
{
int rc = 0;
int sz = 10;
struct spdk_lvol_store *lvs;
/* Lvol store is succesfully created */
rc = vbdev_lvs_create(&g_bdev, 0, lvol_store_op_with_handle_complete, NULL);
CU_ASSERT(rc == 0);
CU_ASSERT(g_lvserrno == 0);
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
CU_ASSERT(g_bs_dev != NULL);
lvs = g_lvol_store;
g_lvol_store = NULL;
uuid_generate_time(lvs->uuid);
/* Suuccessfully create lvol, which should be destroyed with lvs later */
g_lvolerrno = -1;
rc = vbdev_lvol_create(lvs->uuid, sz, vbdev_lvol_create_complete, NULL);
CU_ASSERT(rc == 0);
CU_ASSERT(g_lvolerrno == 0);
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
/* Unload lvol store */
vbdev_lvs_unload(lvs, lvol_store_op_complete, NULL);
CU_ASSERT(g_lvserrno == 0);
CU_ASSERT(g_lvol_store == NULL);
CU_ASSERT(g_lvol != NULL);
}
static void
ut_lvs_init(void)
{
@ -868,6 +940,7 @@ int main(int argc, char **argv)
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_lvs_destroy", ut_lvs_destroy) == NULL ||
CU_add_test(suite, "ut_lvs_unload", ut_lvs_unload) == NULL ||
CU_add_test(suite, "ut_lvol_resize", ut_lvol_resize) == NULL ||
CU_add_test(suite, "lvol_hotremove", ut_lvol_hotremove) == NULL ||
CU_add_test(suite, "ut_vbdev_lvol_get_io_channel", ut_vbdev_lvol_get_io_channel) == NULL ||