nvmf_example: construct the nvmf target

Construct nvmf target.

Change-Id: I126d2f6b9f96840975fbc8fb833d0d7bc03b35fd
Signed-off-by: JinYu <jin.yu@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/468657
Community-CI: SPDK CI Jenkins <sys_sgci@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: GangCao <gang.cao@intel.com>
This commit is contained in:
JinYu 2019-08-26 17:21:54 +08:00 committed by Tomasz Zawadzki
parent c871ee40e6
commit b63e47f237

View File

@ -38,13 +38,18 @@
#include "spdk/thread.h"
#include "spdk/bdev.h"
#include "spdk/rpc.h"
#include "spdk/nvmf.h"
#include "spdk_internal/event.h"
#define NVMF_DEFAULT_SUBSYSTEMS 32
static const char *g_rpc_addr = SPDK_DEFAULT_RPC_ADDR;
enum nvmf_target_state {
NVMF_INIT_SUBSYSTEM = 0,
NVMF_INIT_TARGET,
NVMF_FINI_TARGET,
NVMF_FINI_SUBSYSTEM,
};
@ -59,11 +64,21 @@ struct nvmf_reactor {
TAILQ_HEAD(, nvmf_lw_thread) threads;
TAILQ_ENTRY(nvmf_reactor) link;
};
struct nvmf_target {
struct spdk_nvmf_tgt *tgt;
int max_subsystems;
};
TAILQ_HEAD(, nvmf_reactor) g_reactors = TAILQ_HEAD_INITIALIZER(g_reactors);
static struct nvmf_reactor *g_master_reactor = NULL;
static struct nvmf_reactor *g_next_reactor = NULL;
static struct spdk_thread *g_init_thread = NULL;
static struct nvmf_target g_nvmf_tgt = {
.max_subsystems = NVMF_DEFAULT_SUBSYSTEMS,
};
static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
static bool g_reactors_exit = false;
static enum nvmf_target_state g_target_state;
@ -79,6 +94,7 @@ usage(char *program_name)
printf("\t[-h show this usage]\n");
printf("\t[-i shared memory ID (optional)]\n");
printf("\t[-m core mask for DPDK]\n");
printf("\t[-n max subsystems for target(default: 32)]\n");
printf("\t[-r RPC listen address (default /var/tmp/spdk.sock)]\n");
printf("\t[-s memory size in MB for DPDK (default: 0MB)]\n");
printf("\t[-u disable PCI access]\n");
@ -90,7 +106,7 @@ parse_args(int argc, char **argv, struct spdk_env_opts *opts)
int op;
long int value;
while ((op = getopt(argc, argv, "i:m:r:s:u:h")) != -1) {
while ((op = getopt(argc, argv, "i:m:n:r:s:u:h")) != -1) {
switch (op) {
case 'i':
value = spdk_strtol(optarg, 10);
@ -103,6 +119,13 @@ parse_args(int argc, char **argv, struct spdk_env_opts *opts)
case 'm':
opts->core_mask = optarg;
break;
case 'n':
g_nvmf_tgt.max_subsystems = spdk_strtol(optarg, 10);
if (g_nvmf_tgt.max_subsystems < 0) {
fprintf(stderr, "converting a string to integer failed\n");
return -EINVAL;
}
break;
case 'r':
g_rpc_addr = optarg;
break;
@ -299,6 +322,69 @@ nvmf_destroy_threads(void)
fprintf(stdout, "nvmf threads destroy successfully\n");
}
static void
nvmf_tgt_destroy_done(void *ctx, int status)
{
fprintf(stdout, "destroyed the nvmf target service\n");
g_target_state = NVMF_FINI_SUBSYSTEM;
nvmf_target_advance_state();
}
static void
nvmf_destroy_nvmf_tgt(void)
{
if (g_nvmf_tgt.tgt) {
spdk_nvmf_tgt_destroy(g_nvmf_tgt.tgt, nvmf_tgt_destroy_done, NULL);
} else {
g_target_state = NVMF_FINI_SUBSYSTEM;
}
}
static void
nvmf_create_nvmf_tgt(void)
{
struct spdk_nvmf_subsystem *subsystem;
struct spdk_nvmf_target_opts tgt_opts;
tgt_opts.max_subsystems = g_nvmf_tgt.max_subsystems;
snprintf(tgt_opts.name, sizeof(tgt_opts.name), "%s", "nvmf_example");
/* Construct the default NVMe-oF target
* An NVMe-oF target is a collection of subsystems, namespace, and poll
* groups, and defines the scope of the NVMe-oF discovery service.
*/
g_nvmf_tgt.tgt = spdk_nvmf_tgt_create(&tgt_opts);
if (g_nvmf_tgt.tgt == NULL) {
fprintf(stderr, "spdk_nvmf_tgt_create() failed\n");
goto error;
}
/* Create and add discovery subsystem to the NVMe-oF target.
* NVMe-oF defines a discovery mechanism that a host uses to determine
* the NVM subsystems that expose namespaces that the host may access.
* It provides a host with following capabilities:
* 1,The ability to discover a list of NVM subsystems with namespaces
* that are accessible to the host.
* 2,The ability to discover multiple paths to an NVM subsystem.
* 3,The ability to discover controllers that are statically configured.
*/
subsystem = spdk_nvmf_subsystem_create(g_nvmf_tgt.tgt, SPDK_NVMF_DISCOVERY_NQN,
SPDK_NVMF_SUBTYPE_DISCOVERY, 0);
if (subsystem == NULL) {
fprintf(stderr, "failed to create discovery nvmf library subsystem\n");
goto error;
}
/* Allow any host to access the discovery subsystem */
spdk_nvmf_subsystem_set_allow_any_host(subsystem, true);
fprintf(stdout, "created a nvmf target service\n");
return;
error:
g_target_state = NVMF_FINI_TARGET;
}
static void
nvmf_subsystem_fini_done(void *cb_arg)
{
@ -313,6 +399,9 @@ nvmf_subsystem_init_done(int rc, void *cb_arg)
fprintf(stdout, "bdev subsystem init successfully\n");
spdk_rpc_initialize(g_rpc_addr);
spdk_rpc_set_state(SPDK_RPC_RUNTIME);
g_target_state = NVMF_INIT_TARGET;
nvmf_target_advance_state();
}
static void
@ -328,6 +417,12 @@ nvmf_target_advance_state(void)
/* initlize the bdev layer */
spdk_subsystem_init(nvmf_subsystem_init_done, NULL);
break;
case NVMF_INIT_TARGET:
nvmf_create_nvmf_tgt();
break;
case NVMF_FINI_TARGET:
nvmf_destroy_nvmf_tgt();
break;
case NVMF_FINI_SUBSYSTEM:
spdk_subsystem_fini(nvmf_subsystem_fini_done, NULL);
break;
@ -346,15 +441,15 @@ static void
_nvmf_shutdown_cb(void *ctx)
{
/* Still in initialization state, defer shutdown operation */
if (g_target_state < NVMF_INIT_SUBSYSTEM) {
if (g_target_state < NVMF_INIT_TARGET) {
spdk_thread_send_msg(spdk_get_thread(), _nvmf_shutdown_cb, NULL);
return;
} else if (g_target_state >= NVMF_FINI_SUBSYSTEM) {
} else if (g_target_state >= NVMF_FINI_TARGET) {
/* Already in Shutdown status, ignore the signal */
return;
}
g_target_state = NVMF_FINI_SUBSYSTEM;
g_target_state = NVMF_FINI_TARGET;
nvmf_target_advance_state();
}