Commit c0f38051 authored by Jim Harris's avatar Jim Harris
Browse files

reduce: add spdk_reduce_vol_destroy



This will remove the metadata from the associated backing
device and delete the pm_file associated with the reduce
volume.

Signed-off-by: default avatarJim Harris <james.r.harris@intel.com>
Change-Id: I30ffd68e5ba69b31ee1be85418c5b8c592d82e70

Reviewed-on: https://review.gerrithub.io/c/437995


Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarwuzhouhui <wuzhouhui@kingsoft.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
parent c887a4f9
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -158,6 +158,22 @@ void spdk_reduce_vol_unload(struct spdk_reduce_vol *vol,
			    spdk_reduce_vol_op_complete cb_fn,
			    void *cb_arg);

/**
 * Destroy an existing libreduce compressed volume.
 *
 * This will zero the metadata region on the backing device and delete the associated
 * pm metadata file.  If the backing device does not contain a compressed volume, the
 * cb_fn will be called with error status without modifying the backing device nor
 * deleting a pm file.
 *
 * \param backing_dev Structure describing the backing device containing the compressed volume.
 * \param cb_fn Callback function to signal completion of the destruction process.
 * \param cb_arg Argument to pass to the callback function.
 */
void spdk_reduce_vol_destroy(struct spdk_reduce_backing_dev *backing_dev,
			     spdk_reduce_vol_op_complete cb_fn,
			     void *cb_arg);

/**
 * Read data from a libreduce compressed volume.
 *
+88 −0
Original line number Diff line number Diff line
@@ -704,6 +704,94 @@ spdk_reduce_vol_unload(struct spdk_reduce_vol *vol,
	cb_fn(cb_arg, 0);
}

struct reduce_destroy_ctx {
	spdk_reduce_vol_op_complete		cb_fn;
	void					*cb_arg;
	struct spdk_reduce_vol			*vol;
	struct spdk_reduce_vol_superblock	*super;
	struct iovec				iov;
	struct spdk_reduce_vol_cb_args		backing_cb_args;
	int					reduce_errno;
	char					pm_path[REDUCE_PATH_MAX];
};

static void
destroy_unload_cpl(void *cb_arg, int reduce_errno)
{
	struct reduce_destroy_ctx *destroy_ctx = cb_arg;

	if (destroy_ctx->reduce_errno == 0) {
		if (unlink(destroy_ctx->pm_path)) {
			SPDK_ERRLOG("%s could not be unlinked: %s\n",
				    destroy_ctx->pm_path, strerror(errno));
		}
	}

	/* Even if the unload somehow failed, we still pass the destroy_ctx
	 * reduce_errno since that indicates whether or not the volume was
	 * actually destroyed.
	 */
	destroy_ctx->cb_fn(destroy_ctx->cb_arg, destroy_ctx->reduce_errno);
	spdk_dma_free(destroy_ctx->super);
	free(destroy_ctx);
}

static void
_destroy_zero_super_cpl(void *cb_arg, int reduce_errno)
{
	struct reduce_destroy_ctx *destroy_ctx = cb_arg;
	struct spdk_reduce_vol *vol = destroy_ctx->vol;

	destroy_ctx->reduce_errno = reduce_errno;
	spdk_reduce_vol_unload(vol, destroy_unload_cpl, destroy_ctx);
}

static void
destroy_load_cb(void *cb_arg, struct spdk_reduce_vol *vol, int reduce_errno)
{
	struct reduce_destroy_ctx *destroy_ctx = cb_arg;

	if (reduce_errno != 0) {
		destroy_ctx->cb_fn(destroy_ctx->cb_arg, reduce_errno);
		spdk_dma_free(destroy_ctx->super);
		free(destroy_ctx);
		return;
	}

	destroy_ctx->vol = vol;
	memcpy(destroy_ctx->pm_path, vol->pm_file.path, sizeof(destroy_ctx->pm_path));
	destroy_ctx->iov.iov_base = destroy_ctx->super;
	destroy_ctx->iov.iov_len = sizeof(*destroy_ctx->super);
	destroy_ctx->backing_cb_args.cb_fn = _destroy_zero_super_cpl;
	destroy_ctx->backing_cb_args.cb_arg = destroy_ctx;
	vol->backing_dev->writev(vol->backing_dev, &destroy_ctx->iov, 1, 0,
				 sizeof(*destroy_ctx->super) / vol->backing_dev->blocklen,
				 &destroy_ctx->backing_cb_args);
}

void
spdk_reduce_vol_destroy(struct spdk_reduce_backing_dev *backing_dev,
			spdk_reduce_vol_op_complete cb_fn, void *cb_arg)
{
	struct reduce_destroy_ctx *destroy_ctx;

	destroy_ctx = calloc(1, sizeof(*destroy_ctx));
	if (destroy_ctx == NULL) {
		cb_fn(cb_arg, -ENOMEM);
		return;
	}

	destroy_ctx->super = spdk_dma_zmalloc(sizeof(*destroy_ctx->super), 64, NULL);
	if (destroy_ctx->super == NULL) {
		free(destroy_ctx);
		cb_fn(cb_arg, -ENOMEM);
		return;
	}
	destroy_ctx->cb_fn = cb_fn;
	destroy_ctx->cb_arg = cb_arg;
	spdk_reduce_vol_load(backing_dev, destroy_load_cb, destroy_ctx);
}

static bool
_request_spans_chunk_boundary(struct spdk_reduce_vol *vol, uint64_t offset, uint64_t length)
{
+1 −0
Original line number Diff line number Diff line
@@ -35,5 +35,6 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk

TEST_FILE = reduce_ut.c
LDFLAGS += -Wl,--wrap,unlink

include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk
+68 −1
Original line number Diff line number Diff line
@@ -152,6 +152,19 @@ persistent_pm_buf_destroy(void)
	g_persistent_pm_buf_len = 0;
}

int __wrap_unlink(const char *path);

int
__wrap_unlink(const char *path)
{
	if (strcmp(g_path, path) != 0) {
		return ENOENT;
	}

	persistent_pm_buf_destroy();
	return 0;
}

static void
init_cb(void *cb_arg, struct spdk_reduce_vol *vol, int reduce_errno)
{
@@ -676,6 +689,59 @@ read_write(void)
	_read_write(4096);
}

static void
destroy_cb(void *ctx, int reduce_errno)
{
	g_reduce_errno = reduce_errno;
}

static void
destroy(void)
{
	struct spdk_reduce_vol_params params = {};
	struct spdk_reduce_backing_dev backing_dev = {};

	params.chunk_size = 16 * 1024;
	params.backing_io_unit_size = 512;
	params.logical_block_size = 512;
	spdk_uuid_generate(&params.uuid);

	backing_dev_init(&backing_dev, &params, 512);

	g_vol = NULL;
	g_reduce_errno = -1;
	spdk_reduce_vol_init(&params, &backing_dev, TEST_MD_PATH, init_cb, NULL);
	CU_ASSERT(g_reduce_errno == 0);
	SPDK_CU_ASSERT_FATAL(g_vol != NULL);

	g_reduce_errno = -1;
	spdk_reduce_vol_unload(g_vol, unload_cb, NULL);
	CU_ASSERT(g_reduce_errno == 0);

	g_vol = NULL;
	g_reduce_errno = -1;
	spdk_reduce_vol_load(&backing_dev, load_cb, NULL);
	CU_ASSERT(g_reduce_errno == 0);
	SPDK_CU_ASSERT_FATAL(g_vol != NULL);

	g_reduce_errno = -1;
	spdk_reduce_vol_unload(g_vol, unload_cb, NULL);
	CU_ASSERT(g_reduce_errno == 0);

	g_reduce_errno = -1;
	MOCK_CLEAR(spdk_dma_zmalloc);
	MOCK_CLEAR(spdk_malloc);
	MOCK_CLEAR(spdk_zmalloc);
	spdk_reduce_vol_destroy(&backing_dev, destroy_cb, NULL);
	CU_ASSERT(g_reduce_errno == 0);

	g_reduce_errno = 0;
	spdk_reduce_vol_load(&backing_dev, load_cb, NULL);
	CU_ASSERT(g_reduce_errno == -EILSEQ);

	backing_dev_destroy(&backing_dev);
}

int
main(int argc, char **argv)
{
@@ -700,7 +766,8 @@ main(int argc, char **argv)
		CU_add_test(suite, "init_backing_dev", init_backing_dev) == NULL ||
		CU_add_test(suite, "load", load) == NULL ||
		CU_add_test(suite, "write_maps", write_maps) == NULL ||
		CU_add_test(suite, "read_write", read_write) == NULL
		CU_add_test(suite, "read_write", read_write) == NULL ||
		CU_add_test(suite, "destroy", destroy) == NULL
	) {
		CU_cleanup_registry();
		return CU_get_error();