Commit c26733cf authored by Mateusz Kozlowski's avatar Mateusz Kozlowski Committed by Jim Harris
Browse files

module/bdev/ftl: FTL's RPC path update



It removes code duplication in the path of handling FTL's RPCs

Change-Id: I3fdb4518ca59b5139bcf617036d3287e4db5e9bc
Signed-off-by: default avatarMariusz Barczak <Mariusz.Barczak@solidigmtechnology.com>
Signed-off-by: default avatarMateusz Kozlowski <mateusz.kozlowski@solidigm.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/19004


Reviewed-by: default avatarBen Walker <ben@nvidia.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Community-CI: Mellanox Build Bot
parent ff9642e3
Loading
Loading
Loading
Loading
+95 −106
Original line number Diff line number Diff line
/*   SPDX-License-Identifier: BSD-3-Clause
 *   Copyright (C) 2020 Intel Corporation.
 *   All rights reserved.
 *   Copyright 2023 Solidigm All Rights Reserved
 */

#include "spdk/stdinc.h"
@@ -27,6 +28,16 @@ struct ftl_bdev {
	struct spdk_bdev_desc	*cache_bdev_desc;
};

struct bdev_ftl_action {
	struct spdk_bdev_desc	*ftl_bdev_desc;
	struct ftl_bdev		*ftl_bdev_dev;
	spdk_ftl_fn		cb_fn;
	void			*cb_arg;
	int			rc;
	size_t			ctx_size;
	char			ctx[0];
};

struct ftl_deferred_init {
	struct spdk_ftl_conf		conf;

@@ -39,6 +50,11 @@ static int bdev_ftl_initialize(void);
static void bdev_ftl_finish(void);
static void bdev_ftl_examine(struct spdk_bdev *bdev);

static void bdev_ftl_action_finish_cb(void *cb_arg, int status);
static struct bdev_ftl_action *bdev_ftl_action_start(const char *bdev_name,
		size_t ctx_size, spdk_ftl_fn cb_fn, void *cb_arg);
static void bdev_ftl_action_finish(struct bdev_ftl_action *action);

static int
bdev_ftl_get_ctx_size(void)
{
@@ -483,130 +499,48 @@ not_found:
	cb_fn(cb_arg, -ENODEV);
}

struct ftl_unmap_ctx {
	struct spdk_bdev_desc *bdev;
	spdk_ftl_fn cb_fn;
	void *cb_arg;
};

static void
bdev_ftl_unmap_cb(void *cb_arg, int status)
{
	struct ftl_unmap_ctx *ctx = cb_arg;

	spdk_bdev_close(ctx->bdev);
	ctx->cb_fn(ctx->cb_arg, status);
	free(ctx);
}

void
bdev_ftl_unmap(const char *name, uint64_t lba, uint64_t num_blocks, spdk_ftl_fn cb_fn, void *cb_arg)
bdev_ftl_unmap(const char *name, uint64_t lba, uint64_t num_blocks, spdk_ftl_fn cb_fn,
	       void *cb_arg)
{
	struct spdk_bdev_desc *ftl_bdev_desc;
	struct spdk_bdev *bdev;
	struct ftl_bdev *ftl;
	struct ftl_unmap_ctx *ctx;
	int rc;

	rc = spdk_bdev_open_ext(name, false, bdev_ftl_event_cb, NULL, &ftl_bdev_desc);

	if (rc) {
		goto not_found;
	}
	struct bdev_ftl_action *action;

	bdev = spdk_bdev_desc_get_bdev(ftl_bdev_desc);

	if (bdev->module != &g_ftl_if) {
		rc = -ENODEV;
		goto bdev_opened;
	}

	ctx = calloc(1, sizeof(struct ftl_unmap_ctx));
	if (!ctx) {
		rc = -ENOMEM;
		goto bdev_opened;
	action = bdev_ftl_action_start(name, 0, cb_fn, cb_arg);
	if (!action) {
		return;
	}

	ctx->bdev = ftl_bdev_desc;
	ctx->cb_arg = cb_arg;
	ctx->cb_fn = cb_fn;

	ftl = bdev->ctxt;
	assert(ftl);
	/* It's ok to pass NULL as IO channel - FTL will detect this and use it's internal IO channel for management operations */
	rc = spdk_ftl_unmap(ftl->dev, NULL, NULL, lba, num_blocks, bdev_ftl_unmap_cb, ctx);

	if (rc) {
		goto ctx_allocated;
	action->rc = spdk_ftl_unmap(action->ftl_bdev_dev->dev, NULL, NULL, lba, num_blocks,
				    bdev_ftl_action_finish_cb, action);
	if (action->rc) {
		bdev_ftl_action_finish(action);
	}

	return;
ctx_allocated:
	free(ctx);
bdev_opened:
	spdk_bdev_close(ftl_bdev_desc);
not_found:
	cb_fn(cb_arg, rc);
}

static void
bdev_ftl_get_stats_cb(struct ftl_stats *stats, void *ctx)
bdev_ftl_get_stats_cb(struct ftl_stats *stats, void *cb_arg)
{
	struct rpc_ftl_stats_ctx *ftl_stats_ctx = ctx;
	struct bdev_ftl_action *action = cb_arg;

	ftl_stats_ctx->cb(ftl_stats_ctx);

	spdk_bdev_close(ftl_stats_ctx->ftl_bdev_desc);
	free(ftl_stats_ctx);
	bdev_ftl_action_finish(action);
}


int
bdev_ftl_get_stats(const char *name, ftl_bdev_thread_fn cb, struct spdk_jsonrpc_request *request,
		   struct ftl_stats *stats)
void
bdev_ftl_get_stats(const char *name, spdk_ftl_fn cb, struct rpc_ftl_stats_ctx *ftl_stats_ctx)
{
	struct spdk_bdev_desc *ftl_bdev_desc;
	struct spdk_bdev *bdev;
	struct ftl_bdev *ftl;
	struct rpc_ftl_stats_ctx *ftl_stats_ctx;
	int rc;

	rc = spdk_bdev_open_ext(name, false, bdev_ftl_event_cb, NULL, &ftl_bdev_desc);
	if (rc) {
		goto not_found;
	}
	struct bdev_ftl_action *action;

	bdev = spdk_bdev_desc_get_bdev(ftl_bdev_desc);
	if (bdev->module != &g_ftl_if) {
		rc = -ENODEV;
		goto bdev_opened;
	}

	ftl_stats_ctx = calloc(1, sizeof(*ftl_stats_ctx));
	if (!ftl_stats_ctx) {
		SPDK_ERRLOG("Could not allocate ftl_stats_ctx\n");
		rc = -ENOMEM;
		goto bdev_opened;
	action = bdev_ftl_action_start(name, 0, cb, ftl_stats_ctx);
	if (!action) {
		return;
	}

	ftl = bdev->ctxt;
	ftl_stats_ctx->request = request;
	ftl_stats_ctx->ftl_bdev_desc = ftl_bdev_desc;
	ftl_stats_ctx->cb = cb;
	ftl_stats_ctx->ftl_stats = stats;

	rc = spdk_ftl_get_stats(ftl->dev, stats, bdev_ftl_get_stats_cb, ftl_stats_ctx);
	if (rc) {
		goto stats_allocated;
	ftl_stats_ctx->ftl_bdev_desc = action->ftl_bdev_desc;
	action->rc = spdk_ftl_get_stats(action->ftl_bdev_dev->dev, &ftl_stats_ctx->ftl_stats,
					bdev_ftl_get_stats_cb, action);
	if (action->rc) {
		bdev_ftl_action_finish(action);
	}

	return 0;
stats_allocated:
	free(ftl_stats_ctx);
bdev_opened:
	spdk_bdev_close(ftl_bdev_desc);
not_found:
	return rc;
}

static void
@@ -654,3 +588,58 @@ bdev_ftl_examine(struct spdk_bdev *bdev)
}

SPDK_LOG_REGISTER_COMPONENT(bdev_ftl)

/*
 * Generic function to execute an action on the FTL bdev
 */
static void
bdev_ftl_action_finish(struct bdev_ftl_action *action)
{
	action->cb_fn(action->cb_arg, action->rc);
	if (action->ftl_bdev_desc) {
		spdk_bdev_close(action->ftl_bdev_desc);
	}
	free(action);
}

static struct bdev_ftl_action *
bdev_ftl_action_start(const char *bdev_name, size_t ctx_size, spdk_ftl_fn cb_fn, void *cb_arg)
{
	struct spdk_bdev *bdev;
	struct bdev_ftl_action *action = calloc(1, sizeof(*action) + ctx_size);

	if (NULL == action) {
		cb_fn(cb_arg, -ENOMEM);
		return NULL;
	}
	action->cb_arg = cb_arg;
	action->cb_fn = cb_fn;

	action->rc = spdk_bdev_open_ext(bdev_name, false, bdev_ftl_event_cb, NULL, &action->ftl_bdev_desc);
	if (action->rc) {
		goto error;
	}

	bdev = spdk_bdev_desc_get_bdev(action->ftl_bdev_desc);
	if (bdev->module != &g_ftl_if) {
		action->rc = -ENODEV;
		goto error;
	}

	action->ftl_bdev_dev = bdev->ctxt;
	assert(action->ftl_bdev_dev);

	return action;
error:
	bdev_ftl_action_finish(action);
	return NULL;
}

static void
bdev_ftl_action_finish_cb(void *cb_arg, int status)
{
	struct bdev_ftl_action *action = cb_arg;

	action->rc = status;
	bdev_ftl_action_finish(action);
}
+14 −6
Original line number Diff line number Diff line
/*   SPDX-License-Identifier: BSD-3-Clause
 *   Copyright (C) 2020 Intel Corporation.
 *   All rights reserved.
 *   Copyright 2023 Solidigm All Rights Reserved
 */

#ifndef SPDK_BDEV_FTL_H
@@ -17,13 +18,10 @@ struct ftl_bdev_info {
	struct spdk_uuid	uuid;
};

typedef void (*ftl_bdev_thread_fn)(void *);

struct rpc_ftl_stats_ctx {
	struct spdk_bdev_desc		*ftl_bdev_desc;
	ftl_bdev_thread_fn		cb;
	struct spdk_jsonrpc_request	*request;
	struct ftl_stats		*ftl_stats;
	struct ftl_stats		ftl_stats;
};

typedef void (*ftl_bdev_init_fn)(const struct ftl_bdev_info *, void *, int);
@@ -34,7 +32,17 @@ void bdev_ftl_delete_bdev(const char *name, bool fast_shutdown, spdk_bdev_unregi
int bdev_ftl_defer_init(const struct spdk_ftl_conf *conf);
void bdev_ftl_unmap(const char *name, uint64_t lba, uint64_t num_blocks, spdk_ftl_fn cb_fn,
		    void *cb_arg);
int bdev_ftl_get_stats(const char *name, ftl_bdev_thread_fn cb,
		       struct spdk_jsonrpc_request *request, struct ftl_stats *stats);

/**
 * @brief Get FTL bdev device statistics
 *
 * @param name The name of the FTL bdev device
 * @param cb Collback function when the stats are ready
 * @param ftl_stats_ctx The context for getting the statistics
 *
 * @note In callback function will return the context of struct rpc_ftl_stats_ctx
 * and it contains struct ftl_stats
 */
void bdev_ftl_get_stats(const char *name, spdk_ftl_fn cb, struct rpc_ftl_stats_ctx *ftl_stats_ctx);

#endif /* SPDK_BDEV_FTL_H */
+52 −63
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
 *   Copyright (C) 2020 Intel Corporation.
 *   Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 *   All rights reserved.
 *   Copyright 2023 Solidigm All Rights Reserved
 */

#include "spdk/rpc.h"
@@ -12,6 +13,26 @@

#include "bdev_ftl.h"

static void
rpc_bdev_ftl_basic_cb(void *cb_arg, int bdeverrno)
{
	struct spdk_jsonrpc_request *request = cb_arg;

	if (bdeverrno == 0) {
		spdk_jsonrpc_send_bool_response(request, true);
	} else {
		spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno));
	}
}

struct rpc_ftl_basic_param {
	char *name;
};

static const struct spdk_json_object_decoder rpc_ftl_basic_decoders[] = {
	{"name", offsetof(struct rpc_ftl_basic_param, name), spdk_json_decode_string},
};

static const struct spdk_json_object_decoder rpc_bdev_ftl_create_decoders[] = {
	{"name", offsetof(struct spdk_ftl_conf, name), spdk_json_decode_string},
	{"base_bdev", offsetof(struct spdk_ftl_conf, base_bdev), spdk_json_decode_string},
@@ -119,18 +140,6 @@ static const struct spdk_json_object_decoder rpc_delete_ftl_decoders[] = {
	},
};

static void
rpc_bdev_ftl_delete_cb(void *cb_arg, int bdeverrno)
{
	struct spdk_jsonrpc_request *request = cb_arg;

	if (bdeverrno == 0) {
		spdk_jsonrpc_send_bool_response(request, true);
	} else {
		spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno));
	}
}

static void
rpc_bdev_ftl_delete(struct spdk_jsonrpc_request *request,
		    const struct spdk_json_val *params)
@@ -145,7 +154,7 @@ rpc_bdev_ftl_delete(struct spdk_jsonrpc_request *request,
		goto invalid;
	}

	bdev_ftl_delete_bdev(attrs.name, attrs.fast_shutdown, rpc_bdev_ftl_delete_cb, request);
	bdev_ftl_delete_bdev(attrs.name, attrs.fast_shutdown, rpc_bdev_ftl_basic_cb, request);
invalid:
	free(attrs.name);
}
@@ -171,17 +180,6 @@ static const struct spdk_json_object_decoder rpc_ftl_unmap_decoders[] = {
	{"num_blocks", offsetof(struct rpc_ftl_unmap, num_blocks), spdk_json_decode_uint64, true},
};

static void
rpc_bdev_ftl_unmap_cb(void *cb_arg, int bdeverrno)
{
	struct spdk_jsonrpc_request *request = cb_arg;

	if (bdeverrno == 0) {
		spdk_jsonrpc_send_bool_response(request, true);
	} else {
		spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno));
	}
}

static void
rpc_bdev_ftl_unmap(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
@@ -191,34 +189,32 @@ rpc_bdev_ftl_unmap(struct spdk_jsonrpc_request *request, const struct spdk_json_
	if (spdk_json_decode_object(params, rpc_ftl_unmap_decoders, SPDK_COUNTOF(rpc_ftl_unmap_decoders),
				    &attrs)) {
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
		goto invalid;
	} else {
		bdev_ftl_unmap(attrs.name, attrs.lba, attrs.num_blocks, rpc_bdev_ftl_basic_cb, request);
	}

	bdev_ftl_unmap(attrs.name, attrs.lba, attrs.num_blocks, rpc_bdev_ftl_unmap_cb, request);
invalid:
	free(attrs.name);
}

SPDK_RPC_REGISTER("bdev_ftl_unmap", rpc_bdev_ftl_unmap, SPDK_RPC_RUNTIME)

struct rpc_ftl_stats {
	char *name;
};

static const struct spdk_json_object_decoder rpc_ftl_stats_decoders[] = {
	{"name", offsetof(struct rpc_ftl_stats, name), spdk_json_decode_string},
};

static void
_rpc_bdev_ftl_get_stats(void *cntx)
_rpc_bdev_ftl_get_stats(void *ctx, int rc)
{
	struct rpc_ftl_stats_ctx *ftl_stats = cntx;
	struct spdk_jsonrpc_request *request = ftl_stats->request;
	struct ftl_stats *stats = ftl_stats->ftl_stats;
	struct spdk_json_write_ctx *w = spdk_jsonrpc_begin_result(request);
	struct rpc_ftl_stats_ctx *ftl_stats_ctx = ctx;
	struct spdk_jsonrpc_request *request = ftl_stats_ctx->request;
	struct ftl_stats *stats = &ftl_stats_ctx->ftl_stats;
	struct spdk_json_write_ctx *w;

	if (rc) {
		free(ftl_stats_ctx);
		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
		return;
	}

	w = spdk_jsonrpc_begin_result(request);
	spdk_json_write_object_begin(w);
	spdk_json_write_named_string(w, "name", spdk_bdev_desc_get_bdev(ftl_stats->ftl_bdev_desc)->name);
	spdk_json_write_named_string(w, "name",
				     spdk_bdev_desc_get_bdev(ftl_stats_ctx->ftl_bdev_desc)->name);

	/* TODO: Instead of named objects, store them in an array with the name being an attribute */
	for (uint64_t i = 0; i < FTL_STATS_TYPE_MAX; i++) {
@@ -270,38 +266,31 @@ _rpc_bdev_ftl_get_stats(void *cntx)

	spdk_json_write_object_end(w);
	spdk_jsonrpc_end_result(request, w);

	free(stats);
	free(ftl_stats_ctx);
}

static void
rpc_bdev_ftl_get_stats(struct spdk_jsonrpc_request *request,
		       const struct spdk_json_val *params)
{
	struct ftl_stats *stats;
	struct rpc_ftl_stats attrs = {};
	int rc;
	struct rpc_ftl_basic_param attrs = {};
	struct rpc_ftl_stats_ctx *ctx = calloc(1, sizeof(*ctx));

	if (spdk_json_decode_object(params, rpc_ftl_stats_decoders, SPDK_COUNTOF(rpc_ftl_stats_decoders),
				    &attrs)) {
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
		goto invalid;
	}

	stats = calloc(1, sizeof(struct ftl_stats));
	if (!stats) {
		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
		goto invalid;
	if (!ctx) {
		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(-ENOMEM));
		return;
	}

	rc = bdev_ftl_get_stats(attrs.name, _rpc_bdev_ftl_get_stats, request, stats);
	if (rc) {
		free(stats);
		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
		goto invalid;
	if (spdk_json_decode_object(params, rpc_ftl_basic_decoders, SPDK_COUNTOF(rpc_ftl_basic_decoders),
				    &attrs)) {
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
		free(ctx);
		free(attrs.name);
		return;
	}

invalid:
	ctx->request = request;
	bdev_ftl_get_stats(attrs.name, _rpc_bdev_ftl_get_stats, ctx);
	free(attrs.name);
}