blobstore: New API call to destroy blobstore [1/3]
Currently exposed API allows to load/unload and to initialize blobstore on a device. A spdk_bs_destroy() call is added in order to reach functional parity with spdk_bs_init(). It was not possible to remove blobstore from device from within SPDK previously. spdk_bs_destroy() takes blobstore pointer as argument (instead of bs_dev), because blobstore has to be already loaded to destroy it. Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com> Change-Id: I2c493a4407868fcf08fd1766a19fc8463f634ef5 Reviewed-on: https://review.gerrithub.io/382019 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
parent
63fce5595b
commit
2df9f03c47
@ -76,6 +76,9 @@ makes it explicit that the default is being used.
|
|||||||
|
|
||||||
### Blobstore
|
### Blobstore
|
||||||
|
|
||||||
|
spdk_bs_destroy() was added to allow destroying blobstore on device
|
||||||
|
with an initialized blobstore.
|
||||||
|
|
||||||
spdk_bs_io_readv_blob() and spdk_bs_io_writev_blob() were added to enable
|
spdk_bs_io_readv_blob() and spdk_bs_io_writev_blob() were added to enable
|
||||||
scattered payloads.
|
scattered payloads.
|
||||||
|
|
||||||
|
@ -163,6 +163,13 @@ void spdk_bs_load(struct spdk_bs_dev *dev, struct spdk_bs_opts *opts,
|
|||||||
void spdk_bs_init(struct spdk_bs_dev *dev, struct spdk_bs_opts *opts,
|
void spdk_bs_init(struct spdk_bs_dev *dev, struct spdk_bs_opts *opts,
|
||||||
spdk_bs_op_with_handle_complete cb_fn, void *cb_arg);
|
spdk_bs_op_with_handle_complete cb_fn, void *cb_arg);
|
||||||
|
|
||||||
|
/* Destroy a blob store by unmapping super block and destroying in-memory structures.
|
||||||
|
* If unmap_device is set to true, entire device will be unmapped. Otherwise only
|
||||||
|
* super block will be unmapped.
|
||||||
|
*/
|
||||||
|
void spdk_bs_destroy(struct spdk_blob_store *bs, bool unmap_device, spdk_bs_op_complete cb_fn,
|
||||||
|
void *cb_arg);
|
||||||
|
|
||||||
/* Flush all volatile data to disk and destroy in-memory structures. */
|
/* Flush all volatile data to disk and destroy in-memory structures. */
|
||||||
void spdk_bs_unload(struct spdk_blob_store *bs, spdk_bs_op_complete cb_fn, void *cb_arg);
|
void spdk_bs_unload(struct spdk_blob_store *bs, spdk_bs_op_complete cb_fn, void *cb_arg);
|
||||||
|
|
||||||
|
@ -2183,6 +2183,84 @@ spdk_bs_init(struct spdk_bs_dev *dev, struct spdk_bs_opts *o,
|
|||||||
|
|
||||||
/* END spdk_bs_init */
|
/* END spdk_bs_init */
|
||||||
|
|
||||||
|
/* START spdk_bs_destroy */
|
||||||
|
|
||||||
|
static void
|
||||||
|
_spdk_bs_destroy_trim_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno)
|
||||||
|
{
|
||||||
|
struct spdk_bs_init_ctx *ctx = cb_arg;
|
||||||
|
struct spdk_blob_store *bs = ctx->bs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to defer calling spdk_bs_call_cpl() until after
|
||||||
|
* dev destruction, so tuck these away for later use.
|
||||||
|
*/
|
||||||
|
bs->unload_err = bserrno;
|
||||||
|
memcpy(&bs->unload_cpl, &seq->cpl, sizeof(struct spdk_bs_cpl));
|
||||||
|
seq->cpl.type = SPDK_BS_CPL_TYPE_NONE;
|
||||||
|
|
||||||
|
spdk_bs_sequence_finish(seq, bserrno);
|
||||||
|
|
||||||
|
_spdk_bs_free(bs);
|
||||||
|
spdk_dma_free(ctx->super);
|
||||||
|
free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spdk_bs_destroy(struct spdk_blob_store *bs, bool unmap_device, spdk_bs_op_complete cb_fn,
|
||||||
|
void *cb_arg)
|
||||||
|
{
|
||||||
|
struct spdk_bs_cpl cpl;
|
||||||
|
spdk_bs_sequence_t *seq;
|
||||||
|
struct spdk_bs_init_ctx *ctx;
|
||||||
|
|
||||||
|
SPDK_DEBUGLOG(SPDK_TRACE_BLOB, "Destroying blobstore\n");
|
||||||
|
|
||||||
|
if (!TAILQ_EMPTY(&bs->blobs)) {
|
||||||
|
SPDK_ERRLOG("Blobstore still has open blobs\n");
|
||||||
|
cb_fn(cb_arg, -EBUSY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpl.type = SPDK_BS_CPL_TYPE_BS_BASIC;
|
||||||
|
cpl.u.bs_basic.cb_fn = cb_fn;
|
||||||
|
cpl.u.bs_basic.cb_arg = cb_arg;
|
||||||
|
|
||||||
|
ctx = calloc(1, sizeof(*ctx));
|
||||||
|
if (!ctx) {
|
||||||
|
cb_fn(cb_arg, -ENOMEM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->super = spdk_dma_zmalloc(sizeof(*ctx->super), 0x1000, NULL);
|
||||||
|
if (!ctx->super) {
|
||||||
|
free(ctx);
|
||||||
|
cb_fn(cb_arg, -ENOMEM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->bs = bs;
|
||||||
|
|
||||||
|
seq = spdk_bs_sequence_start(bs->md_target.md_channel, &cpl);
|
||||||
|
if (!seq) {
|
||||||
|
spdk_dma_free(ctx->super);
|
||||||
|
free(ctx);
|
||||||
|
cb_fn(cb_arg, -ENOMEM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unmap_device) {
|
||||||
|
/* TRIM the entire device */
|
||||||
|
spdk_bs_sequence_unmap(seq, 0, bs->dev->blockcnt, _spdk_bs_destroy_trim_cpl, ctx);
|
||||||
|
} else {
|
||||||
|
/* Write zeroes to the super block */
|
||||||
|
spdk_bs_sequence_write(seq, ctx->super, _spdk_bs_page_to_lba(bs, 0), _spdk_bs_byte_to_lba(bs,
|
||||||
|
sizeof(*ctx->super)), _spdk_bs_destroy_trim_cpl, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* END spdk_bs_destroy */
|
||||||
|
|
||||||
/* START spdk_bs_unload */
|
/* START spdk_bs_unload */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1263,6 +1263,42 @@ bs_resize_md(void)
|
|||||||
g_bs = NULL;
|
g_bs = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bs_destroy(void)
|
||||||
|
{
|
||||||
|
struct spdk_bs_dev *dev;
|
||||||
|
struct spdk_bs_opts opts;
|
||||||
|
|
||||||
|
g_scheduler_delay = true;
|
||||||
|
|
||||||
|
_bs_flush_scheduler();
|
||||||
|
CU_ASSERT(TAILQ_EMPTY(&g_scheduled_ops));
|
||||||
|
|
||||||
|
/* Initialize a new blob store */
|
||||||
|
dev = init_dev();
|
||||||
|
spdk_bs_opts_init(&opts);
|
||||||
|
spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
|
||||||
|
CU_ASSERT(g_bserrno == 0);
|
||||||
|
SPDK_CU_ASSERT_FATAL(g_bs != NULL);
|
||||||
|
|
||||||
|
/* Destroy the blob store */
|
||||||
|
g_bserrno = -1;
|
||||||
|
spdk_bs_destroy(g_bs, 0, bs_op_complete, NULL);
|
||||||
|
/* Callback is called after device is destroyed in next scheduler run. */
|
||||||
|
_bs_flush_scheduler();
|
||||||
|
CU_ASSERT(TAILQ_EMPTY(&g_scheduled_ops));
|
||||||
|
CU_ASSERT(g_bserrno == 0);
|
||||||
|
|
||||||
|
/* Loading an non-existent blob store should fail. */
|
||||||
|
g_bserrno = -1;
|
||||||
|
g_bs = NULL;
|
||||||
|
dev = init_dev();
|
||||||
|
|
||||||
|
spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
|
||||||
|
CU_ASSERT(g_bserrno != 0);
|
||||||
|
g_scheduler_delay = false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Try to hit all of the corner cases associated with serializing
|
/* Try to hit all of the corner cases associated with serializing
|
||||||
* a blob to disk
|
* a blob to disk
|
||||||
*/
|
*/
|
||||||
@ -1768,6 +1804,7 @@ int main(int argc, char **argv)
|
|||||||
CU_add_test(suite, "bs_unload", bs_unload) == NULL ||
|
CU_add_test(suite, "bs_unload", bs_unload) == NULL ||
|
||||||
CU_add_test(suite, "bs_cluster_sz", bs_cluster_sz) == NULL ||
|
CU_add_test(suite, "bs_cluster_sz", bs_cluster_sz) == NULL ||
|
||||||
CU_add_test(suite, "bs_resize_md", bs_resize_md) == NULL ||
|
CU_add_test(suite, "bs_resize_md", bs_resize_md) == NULL ||
|
||||||
|
CU_add_test(suite, "bs_destroy", bs_destroy) == NULL ||
|
||||||
CU_add_test(suite, "bs_type", bs_type) == NULL ||
|
CU_add_test(suite, "bs_type", bs_type) == NULL ||
|
||||||
CU_add_test(suite, "bs_super_block", bs_super_block) == NULL ||
|
CU_add_test(suite, "bs_super_block", bs_super_block) == NULL ||
|
||||||
CU_add_test(suite, "blob_serialize", blob_serialize) == NULL ||
|
CU_add_test(suite, "blob_serialize", blob_serialize) == NULL ||
|
||||||
|
Loading…
Reference in New Issue
Block a user