Commit 2df9f03c authored by Tomasz Zawadzki's avatar Tomasz Zawadzki Committed by Jim Harris
Browse files

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: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: I2c493a4407868fcf08fd1766a19fc8463f634ef5
Reviewed-on: https://review.gerrithub.io/382019


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent 63fce559
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -76,6 +76,9 @@ makes it explicit that the default is being used.

### 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
scattered payloads.

+7 −0
Original line number Diff line number Diff line
@@ -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,
		  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. */
void spdk_bs_unload(struct spdk_blob_store *bs, spdk_bs_op_complete cb_fn, void *cb_arg);

+78 −0
Original line number Diff line number Diff line
@@ -2183,6 +2183,84 @@ spdk_bs_init(struct spdk_bs_dev *dev, struct spdk_bs_opts *o,

/* 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 */

static void
+37 −0
Original line number Diff line number Diff line
@@ -1263,6 +1263,42 @@ bs_resize_md(void)
	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
 * 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_cluster_sz", bs_cluster_sz) == 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_super_block", bs_super_block) == NULL ||
		CU_add_test(suite, "blob_serialize", blob_serialize) == NULL ||