Commit 96073478 authored by Jacek Kalwas's avatar Jacek Kalwas Committed by Jim Harris
Browse files

nvmf: introduce async transport create



An example of async operation which can be handled on specific
transport layer could be creation of spdk thread followed by
a poller registration.

This change also aligns with transport destroy which is already
async operation.

Current transport create function is marked deprecated and is meant
for transports supporting sync create only to maintain backward
compatibility. Async version supports both create operations.

Signed-off-by: default avatarJacek Kalwas <jacek.kalwas@intel.com>
Change-Id: I1f5a477819e58f30983d26f81a1416bed1279ecf
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16463


Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 461321cc
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -26,6 +26,9 @@ was used to format the namespace.
Added two new APIs `spdk_nvme_ns_cmd_io_mgmt_recv` and `spdk_nvme_ns_cmd_io_mgmt_send` to
receive and send the I/O management commands.

New `spdk_nvmf_transport_create_async` was added, it accepts a callback and callback argument.
`spdk_nvmf_transport_create` is marked deprecated.

## v23.01

### accel
+22 −1
Original line number Diff line number Diff line
@@ -968,7 +968,7 @@ spdk_nvmf_transport_opts_init(const char *transport_name,
			      struct spdk_nvmf_transport_opts *opts, size_t opts_size);

/**
 * Create a protocol transport
 * Create a protocol transport - deprecated, please use \ref spdk_nvmf_transport_create_async.
 *
 * \param transport_name The transport type to create
 * \param opts The transport options (e.g. max_io_size). It should not be NULL, and opts_size
@@ -979,6 +979,27 @@ spdk_nvmf_transport_opts_init(const char *transport_name,
struct spdk_nvmf_transport *spdk_nvmf_transport_create(const char *transport_name,
		struct spdk_nvmf_transport_opts *opts);

typedef void (*spdk_nvmf_transport_create_done_cb)(void *cb_arg,
		struct spdk_nvmf_transport *transport);

/**
 * Create a protocol transport
 *
 * The callback will be executed asynchronously - i.e. spdk_nvmf_transport_create_async will always return
 * prior to `cb_fn` being called.
 *
 * \param transport_name The transport type to create
 * \param opts The transport options (e.g. max_io_size). It should not be NULL, and opts_size
 *        pointed in this structure should not be zero value.
 * \param cb_fn A callback that will be called once the transport is created
 * \param cb_arg A context argument passed to cb_fn.
 *
 * \return 0 on success, or negative errno on failure (`cb_fn` will not be executed then).
 */
int spdk_nvmf_transport_create_async(const char *transport_name,
				     struct spdk_nvmf_transport_opts *opts,
				     spdk_nvmf_transport_create_done_cb cb_fn, void *cb_arg);

typedef void (*spdk_nvmf_transport_destroy_done_cb)(void *cb_arg);

/**
+4 −1
Original line number Diff line number Diff line
@@ -236,9 +236,12 @@ struct spdk_nvmf_transport_ops {
	void (*opts_init)(struct spdk_nvmf_transport_opts *opts);

	/**
	 * Create a transport for the given transport opts
	 * Create a transport for the given transport opts. Either synchronous
	 * or asynchronous version shall be implemented.
	 */
	struct spdk_nvmf_transport *(*create)(struct spdk_nvmf_transport_opts *opts);
	int (*create_async)(struct spdk_nvmf_transport_opts *opts, spdk_nvmf_transport_create_done_cb cb_fn,
			    void *cb_arg);

	/**
	 * Dump transport-specific opts into JSON
+23 −8
Original line number Diff line number Diff line
@@ -1924,12 +1924,32 @@ nvmf_rpc_tgt_add_transport_done(void *cb_arg, int status)
	nvmf_rpc_create_transport_ctx_free(ctx);
}

static void
nvmf_rpc_create_transport_done(void *cb_arg, struct spdk_nvmf_transport *transport)
{
	struct nvmf_rpc_create_transport_ctx *ctx = cb_arg;

	if (!transport) {
		SPDK_ERRLOG("Failed to create transport.\n");
		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
						 "Failed to create transport.");
		nvmf_rpc_create_transport_ctx_free(ctx);
		return;
	}

	ctx->transport = transport;

	spdk_nvmf_tgt_add_transport(spdk_nvmf_get_tgt(ctx->tgt_name), transport,
				    nvmf_rpc_tgt_add_transport_done, ctx);
}

static void
rpc_nvmf_create_transport(struct spdk_jsonrpc_request *request,
			  const struct spdk_json_val *params)
{
	struct nvmf_rpc_create_transport_ctx *ctx;
	struct spdk_nvmf_tgt *tgt;
	int rc;

	ctx = calloc(1, sizeof(*ctx));
	if (!ctx) {
@@ -1989,20 +2009,15 @@ rpc_nvmf_create_transport(struct spdk_jsonrpc_request *request,

	/* Transport can parse additional params themselves */
	ctx->opts.transport_specific = params;
	ctx->request = request;

	ctx->transport = spdk_nvmf_transport_create(ctx->trtype, &ctx->opts);

	if (!ctx->transport) {
	rc = spdk_nvmf_transport_create_async(ctx->trtype, &ctx->opts, nvmf_rpc_create_transport_done, ctx);
	if (rc) {
		SPDK_ERRLOG("Transport type '%s' create failed\n", ctx->trtype);
		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
						     "Transport type '%s' create failed", ctx->trtype);
		nvmf_rpc_create_transport_ctx_free(ctx);
		return;
	}

	/* add transport to target */
	ctx->request = request;
	spdk_nvmf_tgt_add_transport(tgt, ctx->transport, nvmf_rpc_tgt_add_transport_done, ctx);
}
SPDK_RPC_REGISTER("nvmf_create_transport", rpc_nvmf_create_transport, SPDK_RPC_RUNTIME)

+1 −0
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@
	spdk_nvmf_subsystem_get_max_nsid;
	spdk_nvmf_transport_opts_init;
	spdk_nvmf_transport_create;
	spdk_nvmf_transport_create_async;
	spdk_nvmf_transport_destroy;
	spdk_nvmf_tgt_get_transport;
	spdk_nvmf_transport_get_first;
Loading