Commit f3cda926 authored by Yankun Li's avatar Yankun Li Committed by Konrad Sztyber
Browse files

bdev/compress: change comp bdev creation logic to asynchronous



Change-Id: Icb57244c2e0b52026ebdd73f9f42326ba8b96570
Signed-off-by: default avatarYankun Li <845245370@qq.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/24403


Reviewed-by: default avatarGangCao <gang.cao@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Community-CI: Mellanox Build Bot
parent 8369d695
Loading
Loading
Loading
Loading
+40 −8
Original line number Diff line number Diff line
@@ -508,10 +508,18 @@ vbdev_compress_config_json(struct spdk_json_write_ctx *w)
	return 0;
}

struct vbdev_init_reduce_ctx {
	struct vbdev_compress   *comp_bdev;
	int                     status;
	bdev_compress_create_cb cb_fn;
	void                    *cb_ctx;
};

static void
_vbdev_reduce_init_cb(void *ctx)
{
	struct vbdev_compress *comp_bdev = ctx;
	struct vbdev_init_reduce_ctx *init_ctx = ctx;
	struct vbdev_compress *comp_bdev = init_ctx->comp_bdev;
	int rc;

	assert(comp_bdev->base_desc != NULL);
@@ -522,13 +530,17 @@ _vbdev_reduce_init_cb(void *ctx)
	if (comp_bdev->vol) {
		rc = vbdev_compress_claim(comp_bdev);
		if (rc == 0) {
			init_ctx->cb_fn(init_ctx->cb_ctx, rc);
			free(init_ctx);
			return;
		}
		init_ctx->cb_fn(init_ctx->cb_ctx, rc);
	}

	/* Close the underlying bdev on its same opened thread. */
	spdk_bdev_close(comp_bdev->base_desc);
	free(comp_bdev);
	free(init_ctx);
}

/* Callback from reduce for when init is complete. We'll pass the vbdev_comp struct
@@ -538,19 +550,23 @@ _vbdev_reduce_init_cb(void *ctx)
static void
vbdev_reduce_init_cb(void *cb_arg, struct spdk_reduce_vol *vol, int reduce_errno)
{
	struct vbdev_compress *comp_bdev = cb_arg;
	struct vbdev_init_reduce_ctx *init_ctx = cb_arg;
	struct vbdev_compress *comp_bdev = init_ctx->comp_bdev;

	if (reduce_errno == 0) {
		comp_bdev->vol = vol;
	} else {
		SPDK_ERRLOG("for vol %s, error %u\n",
			    spdk_bdev_get_name(comp_bdev->base_bdev), reduce_errno);
		init_ctx->cb_fn(init_ctx->cb_ctx, reduce_errno);
	}

	init_ctx->status = reduce_errno;

	if (comp_bdev->thread && comp_bdev->thread != spdk_get_thread()) {
		spdk_thread_send_msg(comp_bdev->thread, _vbdev_reduce_init_cb, comp_bdev);
		spdk_thread_send_msg(comp_bdev->thread, _vbdev_reduce_init_cb, init_ctx);
	} else {
		_vbdev_reduce_init_cb(comp_bdev);
		_vbdev_reduce_init_cb(init_ctx);
	}
}

@@ -742,25 +758,40 @@ _prepare_for_load_init(struct spdk_bdev_desc *bdev_desc, uint32_t lb_size)

/* Call reducelib to initialize a new volume */
static int
vbdev_init_reduce(const char *bdev_name, const char *pm_path, uint32_t lb_size)
vbdev_init_reduce(const char *bdev_name, const char *pm_path, uint32_t lb_size,
		  bdev_compress_create_cb cb_fn, void *cb_arg)
{
	struct spdk_bdev_desc *bdev_desc = NULL;
	struct vbdev_init_reduce_ctx *init_ctx;
	struct vbdev_compress *comp_bdev;
	int rc;

	init_ctx = calloc(1, sizeof(*init_ctx));
	if (init_ctx == NULL) {
		SPDK_ERRLOG("failed to alloc init contexts\n");
		return - ENOMEM;
	}

	init_ctx->cb_fn = cb_fn;
	init_ctx->cb_ctx = cb_arg;

	rc = spdk_bdev_open_ext(bdev_name, true, vbdev_compress_base_bdev_event_cb,
				NULL, &bdev_desc);
	if (rc) {
		SPDK_ERRLOG("could not open bdev %s, error %s\n", bdev_name, spdk_strerror(-rc));
		free(init_ctx);
		return rc;
	}

	comp_bdev = _prepare_for_load_init(bdev_desc, lb_size);
	if (comp_bdev == NULL) {
		free(init_ctx);
		spdk_bdev_close(bdev_desc);
		return -EINVAL;
	}

	init_ctx->comp_bdev = comp_bdev;

	/* Save the thread where the base device is opened */
	comp_bdev->thread = spdk_get_thread();

@@ -769,7 +800,7 @@ vbdev_init_reduce(const char *bdev_name, const char *pm_path, uint32_t lb_size)
	spdk_reduce_vol_init(&comp_bdev->params, &comp_bdev->backing_dev,
			     pm_path,
			     vbdev_reduce_init_cb,
			     comp_bdev);
			     init_ctx);
	return 0;
}

@@ -847,7 +878,8 @@ comp_bdev_ch_destroy_cb(void *io_device, void *ctx_buf)

/* RPC entry point for compression vbdev creation. */
int
create_compress_bdev(const char *bdev_name, const char *pm_path, uint32_t lb_size)
create_compress_bdev(const char *bdev_name, const char *pm_path, uint32_t lb_size,
		     bdev_compress_create_cb cb_fn, void *cb_arg)
{
	struct vbdev_compress *comp_bdev = NULL;
	struct stat info;
@@ -871,7 +903,7 @@ create_compress_bdev(const char *bdev_name, const char *pm_path, uint32_t lb_siz
			return -EBUSY;
		}
	}
	return vbdev_init_reduce(bdev_name, pm_path, lb_size);
	return vbdev_init_reduce(bdev_name, pm_path, lb_size, cb_fn, cb_arg);
}

static int
+6 −1
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
#define LB_SIZE_4K	0x1000UL
#define LB_SIZE_512B	0x200UL

typedef void (*bdev_compress_create_cb)(void *ctx, int status);

/**
 * Get the first compression bdev.
 *
@@ -53,9 +55,12 @@ typedef void (*spdk_delete_compress_complete)(void *cb_arg, int bdeverrno);
 * \param bdev_name Bdev on which compression bdev will be created.
 * \param pm_path Path to persistent memory.
 * \param lb_size Logical block size for the compressed volume in bytes. Must be 4K or 512.
 * \param cb_fn Function to call after creation.
 * \param cb_arg Argument to pass to cb_fn.
 * \return 0 on success, other on failure.
 */
int create_compress_bdev(const char *bdev_name, const char *pm_path, uint32_t lb_size);
int create_compress_bdev(const char *bdev_name, const char *pm_path, uint32_t lb_size,
			 bdev_compress_create_cb cb_fn, void *cb_arg);

/**
 * Delete compress bdev.
+55 −14
Original line number Diff line number Diff line
@@ -78,12 +78,25 @@ struct rpc_construct_compress {
	uint32_t lb_size;
};

struct rpc_bdev_compress_create_ctx {
	struct rpc_construct_compress req;
	struct spdk_jsonrpc_request *request;
};

/* Free the allocated memory resource after the RPC handling. */
static void
free_rpc_construct_compress(struct rpc_construct_compress *r)
free_rpc_construct_compress(struct rpc_bdev_compress_create_ctx *ctx)
{
	free(r->base_bdev_name);
	free(r->pm_path);
	struct rpc_construct_compress *req;

	assert(ctx != NULL);

	req = &ctx->req;

	free(req->base_bdev_name);
	free(req->pm_path);

	free(ctx);
}

/* Structure to decode the input parameters for this RPC method. */
@@ -93,6 +106,28 @@ static const struct spdk_json_object_decoder rpc_construct_compress_decoders[] =
	{"lb_size", offsetof(struct rpc_construct_compress, lb_size), spdk_json_decode_uint32, true},
};

static void
rpc_bdev_compress_create_cb(void *_ctx, int status)
{
	struct rpc_bdev_compress_create_ctx *ctx = _ctx;
	struct rpc_construct_compress *req = &ctx->req;
	struct spdk_jsonrpc_request *request = ctx->request;
	struct spdk_json_write_ctx *w;
	char *name;

	if (status != 0) {
		spdk_jsonrpc_send_error_response(request, status, spdk_strerror(-status));
	} else {
		w = spdk_jsonrpc_begin_result(request);
		name = spdk_sprintf_alloc("COMP_%s", req->base_bdev_name);
		spdk_json_write_string(w, name);
		spdk_jsonrpc_end_result(request, w);
		free(name);
	}

	free_rpc_construct_compress(ctx);
}

/* Decode the parameters for this RPC method and properly construct the compress
 * device. Error status returned in the failed cases.
 */
@@ -100,21 +135,30 @@ static void
rpc_bdev_compress_create(struct spdk_jsonrpc_request *request,
			 const struct spdk_json_val *params)
{
	struct rpc_construct_compress req = {NULL};
	struct spdk_json_write_ctx *w;
	char *name;
	struct rpc_bdev_compress_create_ctx *ctx;
	struct rpc_construct_compress *req;
	int rc;

	ctx = calloc(1, sizeof(*ctx));
	if (ctx == NULL) {
		SPDK_ERRLOG("failed to alloc compress bdev creation contexts\n");
		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
		return;
	}

	req = &ctx->req;

	if (spdk_json_decode_object(params, rpc_construct_compress_decoders,
				    SPDK_COUNTOF(rpc_construct_compress_decoders),
				    &req)) {
				    req)) {
		SPDK_DEBUGLOG(vbdev_compress, "spdk_json_decode_object failed\n");
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
						 "spdk_json_decode_object failed");
		goto cleanup;
	}

	rc = create_compress_bdev(req.base_bdev_name, req.pm_path, req.lb_size);
	rc = create_compress_bdev(req->base_bdev_name, req->pm_path, req->lb_size,
				  rpc_bdev_compress_create_cb, ctx);
	if (rc != 0) {
		if (rc == -EBUSY) {
			spdk_jsonrpc_send_error_response(request, rc, "Base bdev already in use for compression.");
@@ -124,14 +168,11 @@ rpc_bdev_compress_create(struct spdk_jsonrpc_request *request,
		goto cleanup;
	}

	w = spdk_jsonrpc_begin_result(request);
	name = spdk_sprintf_alloc("COMP_%s", req.base_bdev_name);
	spdk_json_write_string(w, name);
	spdk_jsonrpc_end_result(request, w);
	free(name);
	ctx->request = request;
	return;

cleanup:
	free_rpc_construct_compress(&req);
	free_rpc_construct_compress(ctx);
}
SPDK_RPC_REGISTER("bdev_compress_create", rpc_bdev_compress_create, SPDK_RPC_RUNTIME)