Commit 46a3d50b authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Jim Harris
Browse files

subsystem/nvmf: Add set_nvmf_target_options/config RPCs



Two new RPCs allocate and initialize options and conf dynamically.
Initialization of NVMf subsystem skips initialization of them
if they are already allocated.

To use and test them, add python script too.

Change-Id: I3be83c33edf9960cb4340d52abb47b7331a6fb92
Signed-off-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/406932


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 5f1c1189
Loading
Loading
Loading
Loading
+74 −15
Original line number Diff line number Diff line
@@ -41,11 +41,10 @@
#include "spdk/string.h"
#include "spdk/util.h"

#define ACCEPT_TIMEOUT_US		10000 /* 10ms */

#define SPDK_NVMF_MAX_NAMESPACES (1 << 14)

struct spdk_nvmf_tgt_conf g_spdk_nvmf_tgt_conf;
struct spdk_nvmf_tgt_opts *g_spdk_nvmf_tgt_opts = NULL;
struct spdk_nvmf_tgt_conf *g_spdk_nvmf_tgt_conf = NULL;

static int
spdk_add_nvmf_discovery_subsystem(void)
@@ -65,7 +64,7 @@ spdk_add_nvmf_discovery_subsystem(void)
}

static void
spdk_nvmf_read_config_file_params(struct spdk_conf_section *sp,
spdk_nvmf_read_config_file_tgt_opts(struct spdk_conf_section *sp,
				    struct spdk_nvmf_tgt_opts *opts)
{
	int max_queue_depth;
@@ -73,7 +72,6 @@ spdk_nvmf_read_config_file_params(struct spdk_conf_section *sp,
	int in_capsule_data_size;
	int max_io_size;
	int io_unit_size;
	int acceptor_poll_rate;

	max_queue_depth = spdk_conf_section_get_intval(sp, "MaxQueueDepth");
	if (max_queue_depth >= 0) {
@@ -99,29 +97,90 @@ spdk_nvmf_read_config_file_params(struct spdk_conf_section *sp,
	if (io_unit_size >= 0) {
		opts->io_unit_size = io_unit_size;
	}
}

static void
spdk_nvmf_read_config_file_tgt_conf(struct spdk_conf_section *sp,
				    struct spdk_nvmf_tgt_conf *conf)
{
	int acceptor_poll_rate;

	acceptor_poll_rate = spdk_conf_section_get_intval(sp, "AcceptorPollRate");
	if (acceptor_poll_rate >= 0) {
		g_spdk_nvmf_tgt_conf.acceptor_poll_rate = acceptor_poll_rate;
		conf->acceptor_poll_rate = acceptor_poll_rate;
	}
}

static int
spdk_nvmf_parse_nvmf_tgt(void)
static struct spdk_nvmf_tgt_opts *
spdk_nvmf_parse_tgt_opts(void)
{
	struct spdk_nvmf_tgt_opts *opts;
	struct spdk_conf_section *sp;
	struct spdk_nvmf_tgt_opts opts;
	int rc;

	spdk_nvmf_tgt_opts_init(&opts);
	g_spdk_nvmf_tgt_conf.acceptor_poll_rate = ACCEPT_TIMEOUT_US;
	opts = calloc(1, sizeof(*opts));
	if (!opts) {
		SPDK_ERRLOG("calloc() failed for target options\n");
		return NULL;
	}

	spdk_nvmf_tgt_opts_init(opts);

	sp = spdk_conf_find_section(NULL, "Nvmf");
	if (sp != NULL) {
		spdk_nvmf_read_config_file_params(sp, &opts);
		spdk_nvmf_read_config_file_tgt_opts(sp, opts);
	}

	return opts;
}

static struct spdk_nvmf_tgt_conf *
spdk_nvmf_parse_tgt_conf(void)
{
	struct spdk_nvmf_tgt_conf *conf;
	struct spdk_conf_section *sp;

	conf = calloc(1, sizeof(*conf));
	if (!conf) {
		SPDK_ERRLOG("calloc() failed for target conf\n");
		return NULL;
	}

	g_spdk_nvmf_tgt = spdk_nvmf_tgt_create(&opts);
	conf->acceptor_poll_rate = ACCEPT_TIMEOUT_US;

	sp = spdk_conf_find_section(NULL, "Nvmf");
	if (sp != NULL) {
		spdk_nvmf_read_config_file_tgt_conf(sp, conf);
	}

	return conf;
}

static int
spdk_nvmf_parse_nvmf_tgt(void)
{
	int rc;

	if (!g_spdk_nvmf_tgt_opts) {
		g_spdk_nvmf_tgt_opts = spdk_nvmf_parse_tgt_opts();
		if (!g_spdk_nvmf_tgt_opts) {
			SPDK_ERRLOG("spdk_nvmf_parse_tgt_opts() failed\n");
			return -1;
		}
	}

	if (!g_spdk_nvmf_tgt_conf) {
		g_spdk_nvmf_tgt_conf = spdk_nvmf_parse_tgt_conf();
		if (!g_spdk_nvmf_tgt_conf) {
			SPDK_ERRLOG("spdk_nvmf_parse_tgt_conf() failed\n");
			return -1;
		}
	}

	g_spdk_nvmf_tgt = spdk_nvmf_tgt_create(g_spdk_nvmf_tgt_opts);

	free(g_spdk_nvmf_tgt_opts);
	g_spdk_nvmf_tgt_opts = NULL;

	if (!g_spdk_nvmf_tgt) {
		SPDK_ERRLOG("spdk_nvmf_tgt_create() failed\n");
		return -1;
+4 −1
Original line number Diff line number Diff line
@@ -42,11 +42,14 @@
#include "spdk_internal/event.h"
#include "spdk_internal/log.h"

#define ACCEPT_TIMEOUT_US	10000 /* 10ms */

struct spdk_nvmf_tgt_conf {
	uint32_t acceptor_poll_rate;
};

extern struct spdk_nvmf_tgt_conf g_spdk_nvmf_tgt_conf;
extern struct spdk_nvmf_tgt_opts *g_spdk_nvmf_tgt_opts;
extern struct spdk_nvmf_tgt_conf *g_spdk_nvmf_tgt_conf;

extern struct spdk_nvmf_tgt *g_spdk_nvmf_tgt;

+107 −0
Original line number Diff line number Diff line
@@ -1554,3 +1554,110 @@ nvmf_rpc_subsystem_allow_any_host(struct spdk_jsonrpc_request *request,
}
SPDK_RPC_REGISTER("nvmf_subsystem_allow_any_host", nvmf_rpc_subsystem_allow_any_host,
		  SPDK_RPC_RUNTIME)

static const struct spdk_json_object_decoder nvmf_rpc_subsystem_tgt_opts_decoder[] = {
	{"max_queue_depth", offsetof(struct spdk_nvmf_tgt_opts, max_queue_depth), spdk_json_decode_uint16, true},
	{"max_qpairs_per_ctrlr", offsetof(struct spdk_nvmf_tgt_opts, max_qpairs_per_ctrlr), spdk_json_decode_uint16, true},
	{"in_capsule_data_size", offsetof(struct spdk_nvmf_tgt_opts, in_capsule_data_size), spdk_json_decode_uint32, true},
	{"max_io_size", offsetof(struct spdk_nvmf_tgt_opts, max_io_size), spdk_json_decode_uint32, true},
	{"max_subsystems", offsetof(struct spdk_nvmf_tgt_opts, max_subsystems), spdk_json_decode_uint32, true},
	{"io_unit_size", offsetof(struct spdk_nvmf_tgt_opts, io_unit_size), spdk_json_decode_uint32, true},
};

static void
nvmf_rpc_subsystem_set_tgt_opts(struct spdk_jsonrpc_request *request,
				const struct spdk_json_val *params)
{
	struct spdk_nvmf_tgt_opts *opts;
	struct spdk_json_write_ctx *w;

	if (g_spdk_nvmf_tgt_opts != NULL) {
		SPDK_ERRLOG("this RPC must not be called more than once.\n");
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
						 "Must not call more than once");
		return;
	}

	opts = calloc(1, sizeof(*opts));
	if (opts == NULL) {
		SPDK_ERRLOG("malloc() failed for target options\n");
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
						 "Out of memory");
		return;
	}

	spdk_nvmf_tgt_opts_init(opts);

	if (params != NULL) {
		if (spdk_json_decode_object(params, nvmf_rpc_subsystem_tgt_opts_decoder,
					    SPDK_COUNTOF(nvmf_rpc_subsystem_tgt_opts_decoder), opts)) {
			free(opts);
			SPDK_ERRLOG("spdk_json_decode_object() failed\n");
			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
							 "Invalid parameters");
			return;
		}
	}

	g_spdk_nvmf_tgt_opts = opts;

	w = spdk_jsonrpc_begin_result(request);
	if (w == NULL) {
		return;
	}

	spdk_json_write_bool(w, true);
	spdk_jsonrpc_end_result(request, w);
}
SPDK_RPC_REGISTER("set_nvmf_target_options", nvmf_rpc_subsystem_set_tgt_opts, SPDK_RPC_STARTUP)

static const struct spdk_json_object_decoder nvmf_rpc_subsystem_tgt_conf_decoder[] = {
	{"acceptor_poll_rate", offsetof(struct spdk_nvmf_tgt_conf, acceptor_poll_rate), spdk_json_decode_uint32, true},
};

static void
nvmf_rpc_subsystem_set_tgt_conf(struct spdk_jsonrpc_request *request,
				const struct spdk_json_val *params)
{
	struct spdk_nvmf_tgt_conf *conf;
	struct spdk_json_write_ctx *w;

	if (g_spdk_nvmf_tgt_conf != NULL) {
		SPDK_ERRLOG("this RPC must not be called more than once.\n");
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
						 "Must not call more than once");
		return;
	}

	conf = calloc(1, sizeof(*conf));
	if (conf == NULL) {
		SPDK_ERRLOG("calloc() failed for target config\n");
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
						 "Out of memory");
		return;
	}

	conf->acceptor_poll_rate = ACCEPT_TIMEOUT_US;

	if (params != NULL) {
		if (spdk_json_decode_object(params, nvmf_rpc_subsystem_tgt_conf_decoder,
					    SPDK_COUNTOF(nvmf_rpc_subsystem_tgt_conf_decoder), conf)) {
			free(conf);
			SPDK_ERRLOG("spdk_json_decode_object() failed\n");
			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
							 "Invalid parameters");
			return;
		}
	}

	g_spdk_nvmf_tgt_conf = conf;

	w = spdk_jsonrpc_begin_result(request);
	if (w == NULL) {
		return;
	}

	spdk_json_write_bool(w, true);
	spdk_jsonrpc_end_result(request, w);
}
SPDK_RPC_REGISTER("set_nvmf_target_config", nvmf_rpc_subsystem_set_tgt_conf, SPDK_RPC_STARTUP)
+2 −1
Original line number Diff line number Diff line
@@ -218,6 +218,7 @@ static void
nvmf_tgt_destroy_done(void *ctx, int status)
{
	g_tgt_state = NVMF_TGT_STOPPED;
	free(g_spdk_nvmf_tgt_conf);
	nvmf_tgt_advance_state();
}

@@ -278,7 +279,7 @@ nvmf_tgt_advance_state(void)
		}
		case NVMF_TGT_INIT_START_ACCEPTOR:
			g_acceptor_poller = spdk_poller_register(acceptor_poll, g_spdk_nvmf_tgt,
					    g_spdk_nvmf_tgt_conf.acceptor_poll_rate);
					    g_spdk_nvmf_tgt_conf->acceptor_poll_rate);
			SPDK_INFOLOG(SPDK_LOG_NVMF, "Acceptor running\n");
			g_tgt_state = NVMF_TGT_RUNNING;
			break;
+21 −0
Original line number Diff line number Diff line
@@ -819,6 +819,27 @@ if __name__ == "__main__":
    p.set_defaults(func=get_interfaces)

    # NVMe-oF
    @call_cmd
    def set_nvmf_target_options(args):
        rpc.nvmf.set_nvmf_target_options(args.client, args)

    p = subparsers.add_parser('set_nvmf_target_options', help='Set NVMf target options')
    p.add_argument('-q', '--max-queue-depth', help='Max number of outstanding I/O per queue', type=int)
    p.add_argument('-p', '--max-qpairs-per-session', help='Max number of SQ and CQ per session', type=int)
    p.add_argument('-c', '--in-capsule-data-size', help='Max number of in-capsule data size', type=int)
    p.add_argument('-i', '--max-io-size', help='Max I/O size', type=int)
    p.add_argument('-x', '--max-subsystems', help='Max number of NVMf subsystems', type=int)
    p.add_argument('-u', '--io-unit-size', help='I/O unit size', type=int)
    p.set_defaults(func=set_nvmf_target_options)

    @call_cmd
    def set_nvmf_target_config(args):
        rpc.nvmf.set_nvmf_target_config(args.client, args)

    p = subparsers.add_parser('set_nvmf_target_config', help='Set NVMf target config')
    p.add_argument('-r', '--acceptor-poll-rate', help='How often the acceptor polls for incoming connections', type=int)
    p.set_defaults(func=set_nvmf_target_config)

    @call_cmd
    def get_nvmf_subsystems(args):
        print_dict(rpc.nvmf.get_nvmf_subsystems(args.client, args))
Loading