diff --git a/include/spdk/lvol.h b/include/spdk/lvol.h index f84d9799dc..ce1f8d8f38 100644 --- a/include/spdk/lvol.h +++ b/include/spdk/lvol.h @@ -62,6 +62,8 @@ typedef void (*spdk_lvol_op_with_handle_complete)(void *cb_arg, struct spdk_lvol int spdk_lvs_init(struct spdk_bs_dev *bs_dev, struct spdk_lvs_opts *o, 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_lvs_destroy(struct spdk_lvol_store *lvol_store, bool unmap_device, + 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); void spdk_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg); diff --git a/lib/lvol/lvol.c b/lib/lvol/lvol.c index 572b83e617..dd4f424174 100644 --- a/lib/lvol/lvol.c +++ b/lib/lvol/lvol.c @@ -297,6 +297,57 @@ _spdk_lvs_destruct_cb(void *cb_arg, int lvserrno) free(req); } +static void +_lvs_destroy_cb(void *cb_arg, int lvserrno) +{ + struct spdk_lvs_req *lvs_req = cb_arg; + + SPDK_INFOLOG(SPDK_TRACE_LVOL, "Lvol store destroyed\n"); + assert(lvs_req->cb_fn != NULL); + lvs_req->cb_fn(lvs_req->cb_arg, lvserrno); + free(lvs_req); +} + +int +spdk_lvs_destroy(struct spdk_lvol_store *lvs, bool unmap_device, spdk_lvs_op_complete cb_fn, + void *cb_arg) +{ + struct spdk_lvs_req *lvs_req; + struct spdk_lvol *iter_lvol, *tmp; + + if (lvs == NULL) { + SPDK_ERRLOG("Lvol store is NULL\n"); + return -ENODEV; + } + + TAILQ_FOREACH_SAFE(iter_lvol, &lvs->lvols, link, tmp) { + if (iter_lvol->ref_count != 0) { + SPDK_ERRLOG("Lvols still open on lvol store\n"); + return -EBUSY; + } + } + + TAILQ_FOREACH_SAFE(iter_lvol, &lvs->lvols, link, tmp) { + free(iter_lvol->name); + free(iter_lvol); + } + + 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->cb_fn = cb_fn; + lvs_req->cb_arg = cb_arg; + + SPDK_INFOLOG(SPDK_TRACE_LVOL, "Destroying lvol store\n"); + spdk_bs_destroy(lvs->blobstore, unmap_device, _lvs_destroy_cb, lvs_req); + free(lvs); + + return 0; +} + static void _spdk_lvol_close_blob_cb(void *cb_arg, int lvolerrno) { diff --git a/test/unit/lib/lvol/lvol.c/lvol_ut.c b/test/unit/lib/lvol/lvol.c/lvol_ut.c index 9ca6d05c54..9141fa3c47 100644 --- a/test/unit/lib/lvol/lvol.c/lvol_ut.c +++ b/test/unit/lib/lvol/lvol.c/lvol_ut.c @@ -115,6 +115,15 @@ spdk_bs_unload(struct spdk_blob_store *bs, spdk_bs_op_complete cb_fn, void *cb_a cb_fn(cb_arg, 0); } +void +spdk_bs_destroy(struct spdk_blob_store *bs, bool unmap_device, 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) @@ -263,6 +272,48 @@ lvs_init_unload_success(void) spdk_free_thread(); } +static void +lvs_init_destroy_success(void) +{ + struct spdk_bs_dev bs_dev; + struct spdk_lvs_opts opts; + int rc = 0; + + init_dev(&bs_dev); + + spdk_allocate_thread(_lvol_send_msg, NULL, NULL); + spdk_lvs_opts_init(&opts); + + g_lvserrno = -1; + + rc = spdk_lvs_init(&bs_dev, &opts, lvol_store_op_with_handle_complete, NULL); + CU_ASSERT(rc == 0); + CU_ASSERT(g_lvserrno == 0); + SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL); + + spdk_lvol_create(g_lvol_store, 10, lvol_op_with_handle_complete, NULL); + CU_ASSERT(g_lvserrno == 0); + SPDK_CU_ASSERT_FATAL(g_lvol != NULL); + + /* Lvol store contains one lvol, this destroy should fail. */ + g_lvserrno = -1; + rc = spdk_lvs_destroy(g_lvol_store, true, NULL, NULL); + CU_ASSERT(rc == -EBUSY); + CU_ASSERT(g_lvserrno == -1); + SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL); + + spdk_lvol_close(g_lvol, close_cb, NULL); + CU_ASSERT(g_lvserrno == 0); + + g_lvserrno = -1; + rc = spdk_lvs_destroy(g_lvol_store, true, lvol_store_op_complete, NULL); + CU_ASSERT(rc == 0); + CU_ASSERT(g_lvserrno == 0); + g_lvol_store = NULL; + + spdk_free_thread(); +} + static void lvs_init_opts_success(void) { @@ -576,6 +627,7 @@ int main(int argc, char **argv) if ( CU_add_test(suite, "lvs_init_unload_success", lvs_init_unload_success) == NULL || + CU_add_test(suite, "lvs_init_destroy_success", lvs_init_destroy_success) == NULL || CU_add_test(suite, "lvs_init_opts_success", lvs_init_opts_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 ||