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

reduce: add spdk_reduce_vol_init() and _unload()



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

Reviewed-on: https://review.gerrithub.io/430645


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
parent dd42c808
Loading
Loading
Loading
Loading
+67 −0
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@
 * Describes the parameters of an spdk_reduce_vol.
 */
struct spdk_reduce_vol_params {
	struct spdk_uuid	uuid;

	/**
	 * Size in bytes of the IO unit for the backing device.  This
	 *  is the unit in which space is allocated from the backing
@@ -84,4 +86,69 @@ int64_t spdk_reduce_get_pm_file_size(struct spdk_reduce_vol_params *params);
 */
int64_t spdk_reduce_get_backing_device_size(struct spdk_reduce_vol_params *params);

struct spdk_reduce_vol;

/**
 * Describes a persistent memory file used to hold metadata associated with a
 *  compressed volume.
 */
struct spdk_reduce_pm_file {
	/** Size of the persistent memory file in bytes. */
	uint64_t		size;
};

typedef void (*spdk_reduce_vol_op_complete)(void *ctx, int ziperrno);
typedef void (*spdk_reduce_vol_op_with_handle_complete)(void *ctx,
		struct spdk_reduce_vol *vol,
		int ziperrno);

typedef void (*spdk_reduce_dev_cpl)(void *cb_arg, int ziperrno);

struct spdk_reduce_vol_cb_args {
	spdk_reduce_dev_cpl	cb_fn;
	void			*cb_arg;
};

struct spdk_reduce_backing_dev {
	void (*readv)(struct spdk_reduce_backing_dev *dev, struct iovec *iov, int iovcnt,
		      uint64_t lba, uint32_t lba_count, struct spdk_reduce_vol_cb_args *args);

	void (*writev)(struct spdk_reduce_backing_dev *dev, struct iovec *iov, int iovcnt,
		       uint64_t lba, uint32_t lba_count, struct spdk_reduce_vol_cb_args *args);

	void (*unmap)(struct spdk_reduce_backing_dev *dev,
		      uint64_t lba, uint32_t lba_count, struct spdk_reduce_vol_cb_args *args);

	void (*close)(struct spdk_reduce_backing_dev *dev);

	uint64_t	blockcnt;
	uint32_t	blocklen;
};

/**
 * Initialize a new libreduce compressed volume.
 *
 * \param params Parameters for the new volume.
 * \param backing_dev Structure describing the backing device to use for the new volume.
 * \param pm_file Structure describing the persistent memory file to use for the new volume.
 * \param cb_fn Callback function to signal completion of the initialization process.
 * \param cb_arg Argument to pass to the callback function.
 */
void spdk_reduce_vol_init(struct spdk_reduce_vol_params *params,
			  struct spdk_reduce_backing_dev *backing_dev,
			  struct spdk_reduce_pm_file *pm_file,
			  spdk_reduce_vol_op_with_handle_complete cb_fn,
			  void *cb_arg);

/**
 * Unload a previously initialized or loaded libreduce compressed volume.
 *
 * \param vol Volume to unload.
 * \param cb_fn Callback function to signal completion of the unload process.
 * \param cb_arg Argument to pass to the callback function.
 */
void spdk_reduce_vol_unload(struct spdk_reduce_vol *vol,
			    spdk_reduce_vol_op_complete cb_fn,
			    void *cb_arg);

#endif /* SPDK_REDUCE_H_ */
+75 −1
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#include "spdk/stdinc.h"

#include "spdk/reduce.h"
#include "spdk/string.h"
#include "spdk_internal/log.h"

/* Always round up the size of the PM region to the nearest cacheline. */
@@ -42,11 +43,14 @@
/* Structure written to offset 0 of both the pm file and the backing device. */
struct spdk_reduce_vol_superblock {
	struct spdk_reduce_vol_params	params;
	uint8_t				reserved[4080];
	uint8_t				reserved[4064];
};
SPDK_STATIC_ASSERT(sizeof(struct spdk_reduce_vol_superblock) == 4096, "size incorrect");

struct spdk_reduce_vol {
	struct spdk_uuid		uuid;
	struct spdk_reduce_pm_file	pm_file;
	struct spdk_reduce_backing_dev	*backing_dev;
};

/*
@@ -154,4 +158,74 @@ spdk_reduce_get_backing_device_size(struct spdk_reduce_vol_params *params)
	return total_backing_size;
}

void
spdk_reduce_vol_init(struct spdk_reduce_vol_params *params,
		     struct spdk_reduce_backing_dev *backing_dev,
		     struct spdk_reduce_pm_file *pm_file,
		     spdk_reduce_vol_op_with_handle_complete cb_fn, void *cb_arg)
{
	struct spdk_reduce_vol *vol;
	int64_t size, size_needed;
	int rc;

	rc = _validate_vol_params(params);
	if (rc != 0) {
		SPDK_ERRLOG("invalid vol params\n");
		cb_fn(cb_arg, NULL, rc);
		return;
	}

	size_needed = spdk_reduce_get_backing_device_size(params);
	size = backing_dev->blockcnt * backing_dev->blocklen;
	if (size_needed > size) {
		SPDK_ERRLOG("backing device size %" PRIi64 " but %" PRIi64 " needed\n",
			    size, size_needed);
		cb_fn(cb_arg, NULL, -EINVAL);
		return;
	}

	size_needed = spdk_reduce_get_pm_file_size(params);
	size = pm_file->size;
	if (size_needed > size) {
		SPDK_ERRLOG("pm file size %" PRIi64 " but %" PRIi64 " needed\n",
			    size, size_needed);
		cb_fn(cb_arg, NULL, -EINVAL);
		return;
	}

	if (spdk_mem_all_zero(&params->uuid, sizeof(params->uuid))) {
		SPDK_ERRLOG("no uuid specified\n");
		cb_fn(cb_arg, NULL, -EINVAL);
		return;
	}

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

	memcpy(&vol->pm_file, pm_file, sizeof(*pm_file));

	memcpy(&vol->uuid, &params->uuid, sizeof(params->uuid));
	vol->backing_dev = backing_dev;

	cb_fn(cb_arg, vol, 0);
}

void
spdk_reduce_vol_unload(struct spdk_reduce_vol *vol,
		       spdk_reduce_vol_op_complete cb_fn, void *cb_arg)
{
	if (vol == NULL) {
		/* This indicates a programming error. */
		assert(false);
		cb_fn(cb_arg, -EINVAL);
		return;
	}

	free(vol);
	cb_fn(cb_arg, 0);
}

SPDK_LOG_REGISTER_COMPONENT("reduce", SPDK_LOG_REDUCE)
+75 −1
Original line number Diff line number Diff line
@@ -38,6 +38,9 @@
#include "reduce/reduce.c"
#include "common/lib/test_env.c"

static struct spdk_reduce_vol *g_vol;
static int g_ziperrno;

static void
get_pm_file_size(void)
{
@@ -120,6 +123,76 @@ get_backing_device_size(void)
	CU_ASSERT(backing_size == expected_backing_size);
}

static void
init_cb(void *cb_arg, struct spdk_reduce_vol *vol, int ziperrno)
{
	g_vol = vol;
	g_ziperrno = ziperrno;
}

static void
unload_cb(void *cb_arg, int ziperrno)
{
	g_ziperrno = ziperrno;
}

static void
init(void)
{
	struct spdk_reduce_vol_params params = {};
	struct spdk_reduce_backing_dev backing_dev = {};
	struct spdk_reduce_pm_file pm_file = {};

	backing_dev.blocklen = 512;

	params.vol_size = 1024 * 1024; /* 1MB */
	params.chunk_size = 16 * 1024;
	params.backing_io_unit_size = backing_dev.blocklen;

	/* backing_dev and pm_file have an invalid size.  This should fail. */
	g_vol = NULL;
	g_ziperrno = 0;
	spdk_reduce_vol_init(&params, &backing_dev, &pm_file, init_cb, NULL);
	CU_ASSERT(g_ziperrno == -EINVAL);
	SPDK_CU_ASSERT_FATAL(g_vol == NULL);

	/* backing_dev now has valid size, but pm_file is still invalid.
	 * This should fail.
	 */
	backing_dev.blockcnt = spdk_reduce_get_backing_device_size(&params) / backing_dev.blocklen;

	g_vol = NULL;
	g_ziperrno = 0;
	spdk_reduce_vol_init(&params, &backing_dev, &pm_file, init_cb, NULL);
	CU_ASSERT(g_ziperrno == -EINVAL);
	SPDK_CU_ASSERT_FATAL(g_vol == NULL);

	/* pm_file now has valid size, but uuid is still all zeroes.
	 * This should fail.
	 */
	pm_file.size = spdk_reduce_get_pm_file_size(&params);

	g_vol = NULL;
	g_ziperrno = 0;
	spdk_reduce_vol_init(&params, &backing_dev, &pm_file, init_cb, NULL);
	CU_ASSERT(g_ziperrno == -EINVAL);
	SPDK_CU_ASSERT_FATAL(g_vol == NULL);

	/* Now specify a uuid.  spdk_reduce_vol_init() should then pass. */
	spdk_uuid_generate(&params.uuid);

	g_vol = NULL;
	g_ziperrno = -1;
	spdk_reduce_vol_init(&params, &backing_dev, &pm_file, init_cb, NULL);
	CU_ASSERT(g_ziperrno == 0);
	SPDK_CU_ASSERT_FATAL(g_vol != NULL);
	CU_ASSERT(spdk_uuid_compare(&params.uuid, &g_vol->uuid) == 0);

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

int
main(int argc, char **argv)
{
@@ -138,7 +211,8 @@ main(int argc, char **argv)

	if (
		CU_add_test(suite, "get_pm_file_size", get_pm_file_size) == NULL ||
		CU_add_test(suite, "get_backing_device_size", get_backing_device_size) == NULL
		CU_add_test(suite, "get_backing_device_size", get_backing_device_size) == NULL ||
		CU_add_test(suite, "init", init) == NULL
	) {
		CU_cleanup_registry();
		return CU_get_error();