Adding upstream version 2.5.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
7819359ae2
commit
acf5b2ec4c
507 changed files with 19440 additions and 17258 deletions
443
fabrics.c
443
fabrics.c
|
@ -1,4 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2016 Intel Corporation. All rights reserved.
|
||||
* Copyright (c) 2016 HGST, a Western Digital Company.
|
||||
|
@ -40,12 +40,14 @@
|
|||
|
||||
#include "common.h"
|
||||
#include "nvme.h"
|
||||
#include "nbft.h"
|
||||
#include "libnvme.h"
|
||||
#include "nvme-print.h"
|
||||
#include "nvme-print-json.h"
|
||||
#include "fabrics.h"
|
||||
|
||||
#define PATH_NVMF_DISC SYSCONFDIR "/nvme/discovery.conf"
|
||||
#define PATH_NVMF_CONFIG SYSCONFDIR "/nvme/config.json"
|
||||
#define PATH_NVMF_RUNDIR RUNDIR "/nvme"
|
||||
#define MAX_DISC_ARGS 32
|
||||
#define MAX_DISC_RETRIES 10
|
||||
|
||||
|
@ -83,41 +85,37 @@ static const char *nvmf_hdr_digest = "enable transport protocol header digest (T
|
|||
static const char *nvmf_data_digest = "enable transport protocol data digest (TCP transport)";
|
||||
static const char *nvmf_tls = "enable TLS";
|
||||
static const char *nvmf_config_file = "Use specified JSON configuration file or 'none' to disable";
|
||||
static const char *nvmf_context = "execution context identification string";
|
||||
|
||||
#define NVMF_OPTS(c) \
|
||||
OPT_STRING("transport", 't', "STR", &transport, nvmf_tport), \
|
||||
OPT_STRING("nqn", 'n', "STR", &subsysnqn, nvmf_nqn), \
|
||||
OPT_STRING("traddr", 'a', "STR", &traddr, nvmf_traddr), \
|
||||
OPT_STRING("trsvcid", 's', "STR", &trsvcid, nvmf_trsvcid), \
|
||||
OPT_STRING("host-traddr", 'w', "STR", &c.host_traddr, nvmf_htraddr), \
|
||||
OPT_STRING("host-iface", 'f', "STR", &c.host_iface, nvmf_hiface), \
|
||||
OPT_STRING("hostnqn", 'q', "STR", &hostnqn, nvmf_hostnqn), \
|
||||
OPT_STRING("hostid", 'I', "STR", &hostid, nvmf_hostid), \
|
||||
OPT_STRING("dhchap-secret", 'S', "STR", &hostkey, nvmf_hostkey), \
|
||||
OPT_INT("nr-io-queues", 'i', &c.nr_io_queues, nvmf_nr_io_queues), \
|
||||
OPT_INT("nr-write-queues", 'W', &c.nr_write_queues, nvmf_nr_write_queues),\
|
||||
OPT_INT("nr-poll-queues", 'P', &c.nr_poll_queues, nvmf_nr_poll_queues), \
|
||||
OPT_INT("queue-size", 'Q', &c.queue_size, nvmf_queue_size), \
|
||||
OPT_INT("keep-alive-tmo", 'k', &c.keep_alive_tmo, nvmf_keep_alive_tmo), \
|
||||
OPT_INT("reconnect-delay", 'c', &c.reconnect_delay, nvmf_reconnect_delay),\
|
||||
OPT_INT("ctrl-loss-tmo", 'l', &c.ctrl_loss_tmo, nvmf_ctrl_loss_tmo), \
|
||||
OPT_INT("tos", 'T', &c.tos, nvmf_tos), \
|
||||
OPT_INT("keyring", 0, &c.keyring, nvmf_keyring), \
|
||||
OPT_INT("tls_key", 0, &c.tls_key, nvmf_tls_key), \
|
||||
OPT_FLAG("duplicate-connect", 'D', &c.duplicate_connect, nvmf_dup_connect), \
|
||||
OPT_FLAG("disable-sqflow", 'd', &c.disable_sqflow, nvmf_disable_sqflow), \
|
||||
OPT_FLAG("hdr-digest", 'g', &c.hdr_digest, nvmf_hdr_digest), \
|
||||
OPT_FLAG("data-digest", 'G', &c.data_digest, nvmf_data_digest), \
|
||||
OPT_FLAG("tls", 0, &c.tls, nvmf_tls) \
|
||||
|
||||
struct tr_config {
|
||||
const char *subsysnqn;
|
||||
const char *transport;
|
||||
const char *traddr;
|
||||
const char *host_traddr;
|
||||
const char *host_iface;
|
||||
const char *trsvcid;
|
||||
};
|
||||
#define NVMF_ARGS(n, c, ...) \
|
||||
struct argconfig_commandline_options opts[] = { \
|
||||
OPT_STRING("transport", 't', "STR", &transport, nvmf_tport), \
|
||||
OPT_STRING("nqn", 'n', "STR", &subsysnqn, nvmf_nqn), \
|
||||
OPT_STRING("traddr", 'a', "STR", &traddr, nvmf_traddr), \
|
||||
OPT_STRING("trsvcid", 's', "STR", &trsvcid, nvmf_trsvcid), \
|
||||
OPT_STRING("host-traddr", 'w', "STR", &c.host_traddr, nvmf_htraddr), \
|
||||
OPT_STRING("host-iface", 'f', "STR", &c.host_iface, nvmf_hiface), \
|
||||
OPT_STRING("hostnqn", 'q', "STR", &hostnqn, nvmf_hostnqn), \
|
||||
OPT_STRING("hostid", 'I', "STR", &hostid, nvmf_hostid), \
|
||||
OPT_STRING("dhchap-secret", 'S', "STR", &hostkey, nvmf_hostkey), \
|
||||
OPT_INT("nr-io-queues", 'i', &c.nr_io_queues, nvmf_nr_io_queues), \
|
||||
OPT_INT("nr-write-queues", 'W', &c.nr_write_queues, nvmf_nr_write_queues), \
|
||||
OPT_INT("nr-poll-queues", 'P', &c.nr_poll_queues, nvmf_nr_poll_queues), \
|
||||
OPT_INT("queue-size", 'Q', &c.queue_size, nvmf_queue_size), \
|
||||
OPT_INT("keep-alive-tmo", 'k', &c.keep_alive_tmo, nvmf_keep_alive_tmo), \
|
||||
OPT_INT("reconnect-delay", 'c', &c.reconnect_delay, nvmf_reconnect_delay), \
|
||||
OPT_INT("ctrl-loss-tmo", 'l', &c.ctrl_loss_tmo, nvmf_ctrl_loss_tmo), \
|
||||
OPT_INT("tos", 'T', &c.tos, nvmf_tos), \
|
||||
OPT_INT("keyring", 0, &c.keyring, nvmf_keyring), \
|
||||
OPT_INT("tls_key", 0, &c.tls_key, nvmf_tls_key), \
|
||||
OPT_FLAG("duplicate-connect", 'D', &c.duplicate_connect, nvmf_dup_connect), \
|
||||
OPT_FLAG("disable-sqflow", 'd', &c.disable_sqflow, nvmf_disable_sqflow), \
|
||||
OPT_FLAG("hdr-digest", 'g', &c.hdr_digest, nvmf_hdr_digest), \
|
||||
OPT_FLAG("data-digest", 'G', &c.data_digest, nvmf_data_digest), \
|
||||
OPT_FLAG("tls", 0, &c.tls, nvmf_tls), \
|
||||
__VA_ARGS__, \
|
||||
OPT_END() \
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two C strings and handle NULL pointers gracefully.
|
||||
|
@ -202,7 +200,7 @@ static nvme_ctrl_t lookup_discovery_ctrl(nvme_root_t r, struct tr_config *trcfg)
|
|||
return __lookup_ctrl(r, trcfg, disc_ctrl_config_match);
|
||||
}
|
||||
|
||||
static nvme_ctrl_t lookup_ctrl(nvme_root_t r, struct tr_config *trcfg)
|
||||
nvme_ctrl_t lookup_ctrl(nvme_root_t r, struct tr_config *trcfg)
|
||||
{
|
||||
return __lookup_ctrl(r, trcfg, ctrl_config_match);
|
||||
}
|
||||
|
@ -266,6 +264,7 @@ static nvme_ctrl_t create_discover_ctrl(nvme_root_t r, nvme_host_t h,
|
|||
|
||||
/* Find out the name of discovery controller */
|
||||
struct nvme_id_ctrl id = { 0 };
|
||||
|
||||
if (nvme_ctrl_identify(c, &id)) {
|
||||
fprintf(stderr, "failed to identify controller, error %s\n",
|
||||
nvme_strerror(errno));
|
||||
|
@ -288,64 +287,19 @@ static nvme_ctrl_t create_discover_ctrl(nvme_root_t r, nvme_host_t h,
|
|||
return __create_discover_ctrl(r, h, cfg, trcfg);
|
||||
}
|
||||
|
||||
static void print_discovery_log(struct nvmf_discovery_log *log, int numrec)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("\nDiscovery Log Number of Records %d, "
|
||||
"Generation counter %"PRIu64"\n",
|
||||
numrec, le64_to_cpu(log->genctr));
|
||||
|
||||
for (i = 0; i < numrec; i++) {
|
||||
struct nvmf_disc_log_entry *e = &log->entries[i];
|
||||
|
||||
printf("=====Discovery Log Entry %d======\n", i);
|
||||
printf("trtype: %s\n", nvmf_trtype_str(e->trtype));
|
||||
printf("adrfam: %s\n",
|
||||
strlen(e->traddr) ?
|
||||
nvmf_adrfam_str(e->adrfam): "");
|
||||
printf("subtype: %s\n", nvmf_subtype_str(e->subtype));
|
||||
printf("treq: %s\n", nvmf_treq_str(e->treq));
|
||||
printf("portid: %d\n", le16_to_cpu(e->portid));
|
||||
printf("trsvcid: %s\n", e->trsvcid);
|
||||
printf("subnqn: %s\n", e->subnqn);
|
||||
printf("traddr: %s\n", e->traddr);
|
||||
printf("eflags: %s\n",
|
||||
nvmf_eflags_str(le16_to_cpu(e->eflags)));
|
||||
|
||||
switch (e->trtype) {
|
||||
case NVMF_TRTYPE_RDMA:
|
||||
printf("rdma_prtype: %s\n",
|
||||
nvmf_prtype_str(e->tsas.rdma.prtype));
|
||||
printf("rdma_qptype: %s\n",
|
||||
nvmf_qptype_str(e->tsas.rdma.qptype));
|
||||
printf("rdma_cms: %s\n",
|
||||
nvmf_cms_str(e->tsas.rdma.cms));
|
||||
printf("rdma_pkey: 0x%04x\n",
|
||||
le16_to_cpu(e->tsas.rdma.pkey));
|
||||
break;
|
||||
case NVMF_TRTYPE_TCP:
|
||||
printf("sectype: %s\n",
|
||||
nvmf_sectype_str(e->tsas.tcp.sectype));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void save_discovery_log(char *raw, struct nvmf_discovery_log *log)
|
||||
{
|
||||
uint64_t numrec = le64_to_cpu(log->numrec);
|
||||
int fd, len, ret;
|
||||
|
||||
fd = open(raw, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
|
||||
fd = open(raw, O_CREAT | O_RDWR | O_TRUNC, 0600);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "failed to open %s: %s\n",
|
||||
raw, strerror(errno));
|
||||
fprintf(stderr, "failed to open %s: %s\n", raw, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
len = sizeof(struct nvmf_discovery_log) +
|
||||
numrec * sizeof(struct nvmf_disc_log_entry);
|
||||
len = sizeof(struct nvmf_discovery_log) + numrec * sizeof(struct nvmf_disc_log_entry);
|
||||
|
||||
ret = write(fd, log, len);
|
||||
if (ret < 0)
|
||||
fprintf(stderr, "failed to write to %s: %s\n",
|
||||
|
@ -356,11 +310,6 @@ static void save_discovery_log(char *raw, struct nvmf_discovery_log *log)
|
|||
close(fd);
|
||||
}
|
||||
|
||||
static void print_connect_msg(nvme_ctrl_t c)
|
||||
{
|
||||
printf("device: %s\n", nvme_ctrl_get_name(c));
|
||||
}
|
||||
|
||||
static int __discover(nvme_ctrl_t c, struct nvme_fabrics_config *defcfg,
|
||||
char *raw, bool connect, bool persistent,
|
||||
enum nvme_print_flags flags)
|
||||
|
@ -384,28 +333,14 @@ static int __discover(nvme_ctrl_t c, struct nvme_fabrics_config *defcfg,
|
|||
if (!log) {
|
||||
fprintf(stderr, "failed to get discovery log: %s\n",
|
||||
nvme_strerror(errno));
|
||||
return errno;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
numrec = le64_to_cpu(log->numrec);
|
||||
if (raw)
|
||||
save_discovery_log(raw, log);
|
||||
else if (!connect) {
|
||||
switch (flags) {
|
||||
case NORMAL:
|
||||
print_discovery_log(log, numrec);
|
||||
break;
|
||||
case JSON:
|
||||
json_discovery_log(log, numrec);
|
||||
break;
|
||||
case BINARY:
|
||||
d_raw((unsigned char *)log,
|
||||
sizeof(struct nvmf_discovery_log) +
|
||||
numrec * sizeof(struct nvmf_disc_log_entry));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
nvme_show_discovery_log(log, numrec, flags);
|
||||
} else if (connect) {
|
||||
int i;
|
||||
|
||||
|
@ -446,8 +381,7 @@ static int __discover(nvme_ctrl_t c, struct nvme_fabrics_config *defcfg,
|
|||
if (eflags & NVMF_DISC_EFLAGS_DUPRETINFO)
|
||||
continue;
|
||||
|
||||
/* Are we supposed to keep the discovery
|
||||
* controller around? */
|
||||
/* Are we supposed to keep the discovery controller around? */
|
||||
disconnect = !persistent;
|
||||
|
||||
if (strcmp(e->subnqn, NVME_DISC_SUBSYS_NAME)) {
|
||||
|
@ -497,18 +431,16 @@ static int __discover(nvme_ctrl_t c, struct nvme_fabrics_config *defcfg,
|
|||
}
|
||||
|
||||
static char *get_default_trsvcid(const char *transport,
|
||||
bool discovery_ctrl)
|
||||
bool discovery_ctrl)
|
||||
{
|
||||
if (!transport)
|
||||
return NULL;
|
||||
if (!strcmp(transport, "tcp")) {
|
||||
if (discovery_ctrl) {
|
||||
if (discovery_ctrl)
|
||||
/* Default port for NVMe/TCP discovery controllers */
|
||||
return stringify(NVME_DISC_IP_PORT);
|
||||
} else {
|
||||
/* Default port for NVMe/TCP io controllers */
|
||||
return stringify(NVME_RDMA_IP_PORT);
|
||||
}
|
||||
/* Default port for NVMe/TCP io controllers */
|
||||
return stringify(NVME_RDMA_IP_PORT);
|
||||
} else if (!strcmp(transport, "rdma")) {
|
||||
/* Default port for NVMe/RDMA controllers */
|
||||
return stringify(NVME_RDMA_IP_PORT);
|
||||
|
@ -533,16 +465,13 @@ static int discover_from_conf_file(nvme_root_t r, nvme_host_t h,
|
|||
struct nvme_fabrics_config cfg;
|
||||
bool force = false;
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
NVMF_OPTS(cfg),
|
||||
OPT_FMT("output-format", 'o', &format, output_format),
|
||||
OPT_FILE("raw", 'r', &raw, "save raw output to file"),
|
||||
OPT_FLAG("persistent", 'p', &persistent, "persistent discovery connection"),
|
||||
OPT_FLAG("quiet", 'S', &quiet, "suppress already connected errors"),
|
||||
OPT_INCR("verbose", 'v', &verbose, "Increase logging verbosity"),
|
||||
OPT_FLAG("force", 0, &force, "Force persistent discovery controller creation"),
|
||||
OPT_END()
|
||||
};
|
||||
NVMF_ARGS(opts, cfg,
|
||||
OPT_FMT("output-format", 'o', &format, output_format),
|
||||
OPT_FILE("raw", 'r', &raw, "save raw output to file"),
|
||||
OPT_FLAG("persistent", 'p', &persistent, "persistent discovery connection"),
|
||||
OPT_FLAG("quiet", 'S', &quiet, "suppress already connected errors"),
|
||||
OPT_INCR("verbose", 'v', &verbose, "Increase logging verbosity"),
|
||||
OPT_FLAG("force", 0, &force, "Force persistent discovery controller creation"));
|
||||
|
||||
nvmf_default_config(&cfg);
|
||||
|
||||
|
@ -630,7 +559,7 @@ static int discover_from_json_config_file(nvme_root_t r, nvme_host_t h,
|
|||
enum nvme_print_flags flags,
|
||||
bool force)
|
||||
{
|
||||
const char *transport, *traddr, *trsvcid, *subsysnqn;
|
||||
const char *transport, *traddr, *host_traddr, *host_iface, *trsvcid, *subsysnqn;
|
||||
nvme_subsystem_t s;
|
||||
nvme_ctrl_t c, cn;
|
||||
struct nvme_fabrics_config cfg;
|
||||
|
@ -640,6 +569,8 @@ static int discover_from_json_config_file(nvme_root_t r, nvme_host_t h,
|
|||
nvme_subsystem_for_each_ctrl(s, c) {
|
||||
transport = nvme_ctrl_get_transport(c);
|
||||
traddr = nvme_ctrl_get_traddr(c);
|
||||
host_traddr = nvme_ctrl_get_host_traddr(c);
|
||||
host_iface = nvme_ctrl_get_host_iface(c);
|
||||
|
||||
if (!transport && !traddr)
|
||||
continue;
|
||||
|
@ -650,6 +581,22 @@ static int discover_from_json_config_file(nvme_root_t r, nvme_host_t h,
|
|||
strcmp(transport, "fc"))
|
||||
continue;
|
||||
|
||||
/* ignore if no host_traddr for fc */
|
||||
if (!strcmp(transport, "fc")) {
|
||||
if (!host_traddr) {
|
||||
fprintf(stderr, "host_traddr required for fc\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* ignore if host_iface set for any transport other than tcp */
|
||||
if (!strcmp(transport, "rdma") || !strcmp(transport, "fc")) {
|
||||
if (host_iface) {
|
||||
fprintf(stderr, "host_iface not permitted for rdma or fc\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
trsvcid = nvme_ctrl_get_trsvcid(c);
|
||||
if (!trsvcid || !strcmp(trsvcid, ""))
|
||||
trsvcid = get_default_trsvcid(transport, true);
|
||||
|
@ -668,8 +615,8 @@ static int discover_from_json_config_file(nvme_root_t r, nvme_host_t h,
|
|||
.subsysnqn = subsysnqn,
|
||||
.transport = transport,
|
||||
.traddr = traddr,
|
||||
.host_traddr = cfg.host_traddr,
|
||||
.host_iface = cfg.host_iface,
|
||||
.host_traddr = host_traddr,
|
||||
.host_iface = host_iface,
|
||||
.trsvcid = trsvcid,
|
||||
};
|
||||
|
||||
|
@ -696,13 +643,49 @@ static int discover_from_json_config_file(nvme_root_t r, nvme_host_t h,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int nvme_read_volatile_config(nvme_root_t r)
|
||||
{
|
||||
char *filename, *ext;
|
||||
struct dirent *dir;
|
||||
DIR *d;
|
||||
int ret = -ENOENT;
|
||||
|
||||
d = opendir(PATH_NVMF_RUNDIR);
|
||||
if (!d)
|
||||
return -ENOTDIR;
|
||||
|
||||
while ((dir = readdir(d))) {
|
||||
if (dir->d_type != DT_REG)
|
||||
continue;
|
||||
|
||||
ext = strchr(dir->d_name, '.');
|
||||
if (!ext || strcmp("json", ext + 1))
|
||||
continue;
|
||||
|
||||
if (asprintf(&filename, "%s/%s", PATH_NVMF_RUNDIR, dir->d_name) < 0) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
if (nvme_read_config(r, filename))
|
||||
ret = 0;
|
||||
|
||||
free(filename);
|
||||
}
|
||||
closedir(d);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int nvmf_discover(const char *desc, int argc, char **argv, bool connect)
|
||||
{
|
||||
char *subsysnqn = NVME_DISC_SUBSYS_NAME;
|
||||
char *hostnqn = NULL, *hostid = NULL, *hostkey = NULL;
|
||||
char *hostnqn_arg, *hostid_arg;
|
||||
char *transport = NULL, *traddr = NULL, *trsvcid = NULL;
|
||||
char *config_file = PATH_NVMF_CONFIG;
|
||||
char *hnqn = NULL, *hid = NULL;
|
||||
char *context = NULL;
|
||||
enum nvme_print_flags flags;
|
||||
nvme_root_t r;
|
||||
nvme_host_t h;
|
||||
|
@ -714,20 +697,23 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect)
|
|||
char *device = NULL;
|
||||
bool force = false;
|
||||
bool json_config = false;
|
||||
bool nbft = false, nonbft = false;
|
||||
char *nbft_path = NBFT_SYSFS_PATH;
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_STRING("device", 'd', "DEV", &device, "use existing discovery controller device"),
|
||||
NVMF_OPTS(cfg),
|
||||
OPT_FMT("output-format", 'o', &format, output_format),
|
||||
OPT_FILE("raw", 'r', &raw, "save raw output to file"),
|
||||
OPT_FLAG("persistent", 'p', &persistent, "persistent discovery connection"),
|
||||
OPT_FLAG("quiet", 'S', &quiet, "suppress already connected errors"),
|
||||
OPT_STRING("config", 'J', "FILE", &config_file, nvmf_config_file),
|
||||
OPT_INCR("verbose", 'v', &verbose, "Increase logging verbosity"),
|
||||
OPT_FLAG("dump-config", 'O', &dump_config, "Dump configuration file to stdout"),
|
||||
OPT_FLAG("force", 0, &force, "Force persistent discovery controller creation"),
|
||||
OPT_END()
|
||||
};
|
||||
NVMF_ARGS(opts, cfg,
|
||||
OPT_STRING("device", 'd', "DEV", &device, "use existing discovery controller device"),
|
||||
OPT_FMT("output-format", 'o', &format, output_format),
|
||||
OPT_FILE("raw", 'r', &raw, "save raw output to file"),
|
||||
OPT_FLAG("persistent", 'p', &persistent, "persistent discovery connection"),
|
||||
OPT_FLAG("quiet", 'S', &quiet, "suppress already connected errors"),
|
||||
OPT_STRING("config", 'J', "FILE", &config_file, nvmf_config_file),
|
||||
OPT_INCR("verbose", 'v', &verbose, "Increase logging verbosity"),
|
||||
OPT_FLAG("dump-config", 'O', &dump_config, "Dump configuration file to stdout"),
|
||||
OPT_FLAG("force", 0, &force, "Force persistent discovery controller creation"),
|
||||
OPT_FLAG("nbft", 0, &nbft, "Only look at NBFT tables"),
|
||||
OPT_FLAG("no-nbft", 0, &nonbft, "Do not look at NBFT tables"),
|
||||
OPT_STRING("nbft-path", 0, "STR", &nbft_path, "user-defined path for NBFT tables"),
|
||||
OPT_STRING("context", 0, "STR", &context, nvmf_context));
|
||||
|
||||
nvmf_default_config(&cfg);
|
||||
|
||||
|
@ -748,6 +734,8 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect)
|
|||
nvme_strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
if (context)
|
||||
nvme_root_set_application(r, context);
|
||||
ret = nvme_scan_topology(r, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to scan topology: %s\n",
|
||||
|
@ -755,9 +743,14 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect)
|
|||
nvme_free_tree(r);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!nvme_read_config(r, config_file))
|
||||
json_config = true;
|
||||
if (!nvme_read_volatile_config(r))
|
||||
json_config = true;
|
||||
|
||||
hostnqn_arg = hostnqn;
|
||||
hostid_arg = hostid;
|
||||
if (!hostnqn)
|
||||
hostnqn = hnqn = nvmf_hostnqn_from_file();
|
||||
if (!hostnqn)
|
||||
|
@ -779,6 +772,14 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect)
|
|||
nvme_host_set_dhchap_key(h, hostkey);
|
||||
|
||||
if (!device && !transport && !traddr) {
|
||||
if (!nonbft)
|
||||
discover_from_nbft(r, hostnqn_arg, hostid_arg,
|
||||
hostnqn, hostid, desc, connect,
|
||||
&cfg, nbft_path, flags, verbose);
|
||||
|
||||
if (nbft)
|
||||
goto out_free;
|
||||
|
||||
if (json_config)
|
||||
ret = discover_from_json_config_file(r, h, desc,
|
||||
connect, &cfg,
|
||||
|
@ -808,15 +809,13 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect)
|
|||
/* Check if device matches command-line options */
|
||||
if (!ctrl_config_match(c, &trcfg)) {
|
||||
fprintf(stderr,
|
||||
"ctrl device %s found, ignoring "
|
||||
"non matching command-line options\n",
|
||||
device);
|
||||
"ctrl device %s found, ignoring non matching command-line options\n",
|
||||
device);
|
||||
}
|
||||
|
||||
if (!nvme_ctrl_is_discovery_ctrl(c)) {
|
||||
fprintf(stderr,
|
||||
"ctrl device %s found, ignoring "
|
||||
"non discovery controller\n",
|
||||
"ctrl device %s found, ignoring non discovery controller\n",
|
||||
device);
|
||||
|
||||
nvme_free_ctrl(c);
|
||||
|
@ -863,10 +862,11 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect)
|
|||
if (!c) {
|
||||
/* No device or non-matching device, create a new controller */
|
||||
c = create_discover_ctrl(r, h, &cfg, &trcfg);
|
||||
if (!c) {
|
||||
fprintf(stderr,
|
||||
"failed to add controller, error %s\n",
|
||||
nvme_strerror(errno));
|
||||
if (!c) {
|
||||
if (errno != ENVME_CONNECT_IGNORED)
|
||||
fprintf(stderr,
|
||||
"failed to add controller, error %s\n",
|
||||
nvme_strerror(errno));
|
||||
ret = errno;
|
||||
goto out_free;
|
||||
}
|
||||
|
@ -895,24 +895,24 @@ int nvmf_connect(const char *desc, int argc, char **argv)
|
|||
char *hostkey = NULL, *ctrlkey = NULL;
|
||||
char *hnqn = NULL, *hid = NULL;
|
||||
char *config_file = PATH_NVMF_CONFIG;
|
||||
char *context = NULL;
|
||||
unsigned int verbose = 0;
|
||||
nvme_root_t r;
|
||||
nvme_host_t h;
|
||||
nvme_ctrl_t c;
|
||||
int ret;
|
||||
struct nvme_fabrics_config cfg;
|
||||
enum nvme_print_flags flags = -1;
|
||||
enum nvme_print_flags flags;
|
||||
struct nvme_fabrics_config cfg = { 0 };
|
||||
char *format = "";
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
NVMF_OPTS(cfg),
|
||||
OPT_STRING("dhchap-ctrl-secret", 'C', "STR", &ctrlkey, nvmf_ctrlkey),
|
||||
OPT_STRING("config", 'J', "FILE", &config_file, nvmf_config_file),
|
||||
OPT_INCR("verbose", 'v', &verbose, "Increase logging verbosity"),
|
||||
OPT_FLAG("dump-config", 'O', &dump_config, "Dump JSON configuration to stdout"),
|
||||
OPT_FMT("output-format", 'o', &format, "Output format: normal|json"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
NVMF_ARGS(opts, cfg,
|
||||
OPT_STRING("dhchap-ctrl-secret", 'C', "STR", &ctrlkey, nvmf_ctrlkey),
|
||||
OPT_STRING("config", 'J', "FILE", &config_file, nvmf_config_file),
|
||||
OPT_INCR("verbose", 'v', &verbose, "Increase logging verbosity"),
|
||||
OPT_FLAG("dump-config", 'O', &dump_config, "Dump JSON configuration to stdout"),
|
||||
OPT_FMT("output-format", 'o', &format, "Output format: normal|json"),
|
||||
OPT_STRING("context", 0, "STR", &context, nvmf_context));
|
||||
|
||||
nvmf_default_config(&cfg);
|
||||
|
||||
|
@ -920,25 +920,18 @@ int nvmf_connect(const char *desc, int argc, char **argv)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!strcmp(format, ""))
|
||||
flags = -1;
|
||||
else if (!strcmp(format, "normal"))
|
||||
flags = NORMAL;
|
||||
else if (!strcmp(format, "json"))
|
||||
flags = JSON;
|
||||
else
|
||||
return EINVAL;
|
||||
flags = validate_output_format(format);
|
||||
|
||||
if (!subsysnqn) {
|
||||
fprintf(stderr,
|
||||
"required argument [--nqn | -n] not specified\n");
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!transport) {
|
||||
fprintf(stderr,
|
||||
"required argument [--transport | -t] not specified\n");
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (strcmp(transport, "loop")) {
|
||||
|
@ -946,7 +939,7 @@ int nvmf_connect(const char *desc, int argc, char **argv)
|
|||
fprintf(stderr,
|
||||
"required argument [--traddr | -a] not specified for transport %s\n",
|
||||
transport);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -959,6 +952,8 @@ int nvmf_connect(const char *desc, int argc, char **argv)
|
|||
nvme_strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
if (context)
|
||||
nvme_root_set_application(r, context);
|
||||
ret = nvme_scan_topology(r, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to scan topology: %s\n",
|
||||
|
@ -967,6 +962,7 @@ int nvmf_connect(const char *desc, int argc, char **argv)
|
|||
return ret;
|
||||
}
|
||||
nvme_read_config(r, config_file);
|
||||
nvme_read_volatile_config(r);
|
||||
|
||||
if (!hostnqn)
|
||||
hostnqn = hnqn = nvmf_hostnqn_from_file();
|
||||
|
@ -1016,10 +1012,8 @@ int nvmf_connect(const char *desc, int argc, char **argv)
|
|||
nvme_strerror(errno));
|
||||
else {
|
||||
errno = 0;
|
||||
if (flags == NORMAL)
|
||||
print_connect_msg(c);
|
||||
else if (flags == JSON)
|
||||
json_connect_msg(c);
|
||||
if (flags != -EINVAL)
|
||||
nvme_show_connect_msg(c, flags);
|
||||
}
|
||||
|
||||
out_free:
|
||||
|
@ -1028,7 +1022,7 @@ out_free:
|
|||
if (dump_config)
|
||||
nvme_dump_config(r);
|
||||
nvme_free_tree(r);
|
||||
return errno;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
static nvme_ctrl_t lookup_nvme_ctrl(nvme_root_t r, const char *name)
|
||||
|
@ -1048,12 +1042,36 @@ static nvme_ctrl_t lookup_nvme_ctrl(nvme_root_t r, const char *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void nvmf_disconnect_nqn(nvme_root_t r, char *nqn)
|
||||
{
|
||||
int i = 0;
|
||||
char *n = nqn;
|
||||
char *p;
|
||||
nvme_host_t h;
|
||||
nvme_subsystem_t s;
|
||||
nvme_ctrl_t c;
|
||||
|
||||
while ((p = strsep(&n, ",")) != NULL) {
|
||||
if (!strlen(p))
|
||||
continue;
|
||||
nvme_for_each_host(r, h) {
|
||||
nvme_for_each_subsystem(h, s) {
|
||||
if (strcmp(nvme_subsystem_get_nqn(s), p))
|
||||
continue;
|
||||
nvme_subsystem_for_each_ctrl(s, c) {
|
||||
if (!nvme_disconnect_ctrl(c))
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("NQN:%s disconnected %d controller(s)\n", nqn, i);
|
||||
}
|
||||
|
||||
int nvmf_disconnect(const char *desc, int argc, char **argv)
|
||||
{
|
||||
const char *device = "nvme device handle";
|
||||
nvme_root_t r;
|
||||
nvme_host_t h;
|
||||
nvme_subsystem_t s;
|
||||
nvme_ctrl_t c;
|
||||
char *p;
|
||||
int ret;
|
||||
|
@ -1067,9 +1085,9 @@ int nvmf_disconnect(const char *desc, int argc, char **argv)
|
|||
struct config cfg = { 0 };
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_STRING("nqn", 'n', "NAME", &cfg.nqn, nvmf_nqn),
|
||||
OPT_STRING("device", 'd', "DEV", &cfg.device, device),
|
||||
OPT_INCR("verbose", 'v', &cfg.verbose, "Increase logging verbosity"),
|
||||
OPT_STRING("nqn", 'n', "NAME", &cfg.nqn, nvmf_nqn),
|
||||
OPT_STRING("device", 'd', "DEV", &cfg.device, device),
|
||||
OPT_INCR("verbose", 'v', &cfg.verbose, "Increase logging verbosity"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
|
@ -1080,7 +1098,7 @@ int nvmf_disconnect(const char *desc, int argc, char **argv)
|
|||
if (!cfg.nqn && !cfg.device) {
|
||||
fprintf(stderr,
|
||||
"Neither device name [--device | -d] nor NQN [--nqn | -n] provided\n");
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = nvme_create_root(stderr, map_log_level(cfg.verbose, false));
|
||||
|
@ -1097,26 +1115,8 @@ int nvmf_disconnect(const char *desc, int argc, char **argv)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (cfg.nqn) {
|
||||
int i = 0;
|
||||
char *n = cfg.nqn;
|
||||
|
||||
while ((p = strsep(&n, ",")) != NULL) {
|
||||
if (!strlen(p))
|
||||
continue;
|
||||
nvme_for_each_host(r, h) {
|
||||
nvme_for_each_subsystem(h, s) {
|
||||
if (strcmp(nvme_subsystem_get_nqn(s), p))
|
||||
continue;
|
||||
nvme_subsystem_for_each_ctrl(s, c) {
|
||||
if (!nvme_disconnect_ctrl(c))
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("NQN:%s disconnected %d controller(s)\n", cfg.nqn, i);
|
||||
}
|
||||
if (cfg.nqn)
|
||||
nvmf_disconnect_nqn(r, cfg.nqn);
|
||||
|
||||
if (cfg.device) {
|
||||
char *d;
|
||||
|
@ -1130,7 +1130,7 @@ int nvmf_disconnect(const char *desc, int argc, char **argv)
|
|||
fprintf(stderr,
|
||||
"Did not find device %s\n", p);
|
||||
nvme_free_tree(r);
|
||||
return errno;
|
||||
return -errno;
|
||||
}
|
||||
ret = nvme_disconnect_ctrl(c);
|
||||
if (ret)
|
||||
|
@ -1219,17 +1219,14 @@ int nvmf_config(const char *desc, int argc, char **argv)
|
|||
struct nvme_fabrics_config cfg;
|
||||
bool scan_tree = false, modify_config = false, update_config = false;
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
NVMF_OPTS(cfg),
|
||||
OPT_STRING("dhchap-ctrl-secret", 'C', "STR", &ctrlkey, nvmf_ctrlkey),
|
||||
OPT_STRING("config", 'J', "FILE", &config_file, nvmf_config_file),
|
||||
OPT_INCR("verbose", 'v', &verbose, "Increase logging verbosity"),
|
||||
OPT_FLAG("scan", 'R', &scan_tree, "Scan current NVMeoF topology"),
|
||||
OPT_FLAG("modify", 'M', &modify_config, "Modify JSON configuration file"),
|
||||
OPT_FLAG("dump", 'O', &dump_config, "Dump JSON configuration to stdout"),
|
||||
OPT_FLAG("update", 'U', &update_config, "Update JSON configuration file"),
|
||||
OPT_END()
|
||||
};
|
||||
NVMF_ARGS(opts, cfg,
|
||||
OPT_STRING("dhchap-ctrl-secret", 'C', "STR", &ctrlkey, nvmf_ctrlkey),
|
||||
OPT_STRING("config", 'J', "FILE", &config_file, nvmf_config_file),
|
||||
OPT_INCR("verbose", 'v', &verbose, "Increase logging verbosity"),
|
||||
OPT_FLAG("scan", 'R', &scan_tree, "Scan current NVMeoF topology"),
|
||||
OPT_FLAG("modify", 'M', &modify_config, "Modify JSON configuration file"),
|
||||
OPT_FLAG("dump", 'O', &dump_config, "Dump JSON configuration to stdout"),
|
||||
OPT_FLAG("update", 'U', &update_config, "Update JSON configuration file"));
|
||||
|
||||
nvmf_default_config(&cfg);
|
||||
|
||||
|
@ -1271,7 +1268,7 @@ int nvmf_config(const char *desc, int argc, char **argv)
|
|||
if (!transport) {
|
||||
fprintf(stderr,
|
||||
"required argument [--transport | -t] needed with --modify\n");
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!hostnqn)
|
||||
|
@ -1317,16 +1314,16 @@ out:
|
|||
if (hnqn)
|
||||
free(hnqn);
|
||||
nvme_free_tree(r);
|
||||
return errno;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
static void dim_operation(nvme_ctrl_t c, enum nvmf_dim_tas tas, const char * name)
|
||||
static void dim_operation(nvme_ctrl_t c, enum nvmf_dim_tas tas, const char *name)
|
||||
{
|
||||
static const char * const task[] = {
|
||||
[NVMF_DIM_TAS_REGISTER] = "register",
|
||||
[NVMF_DIM_TAS_DEREGISTER] = "deregister",
|
||||
};
|
||||
const char * t;
|
||||
const char *t;
|
||||
int status;
|
||||
__u32 result;
|
||||
|
||||
|
@ -1373,13 +1370,13 @@ int nvmf_dim(const char *desc, int argc, char **argv)
|
|||
if (!cfg.nqn && !cfg.device) {
|
||||
fprintf(stderr,
|
||||
"Neither device name [--device | -d] nor NQN [--nqn | -n] provided\n");
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!cfg.tas) {
|
||||
fprintf(stderr,
|
||||
"Task [--task | -t] must be specified\n");
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Allow partial name (e.g. "reg" for "register" */
|
||||
|
@ -1389,7 +1386,7 @@ int nvmf_dim(const char *desc, int argc, char **argv)
|
|||
tas = NVMF_DIM_TAS_DEREGISTER;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid --task: %s\n", cfg.tas);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = nvme_create_root(stderr, map_log_level(cfg.verbose, false));
|
||||
|
@ -1438,7 +1435,7 @@ int nvmf_dim(const char *desc, int argc, char **argv)
|
|||
"Did not find device %s: %s\n",
|
||||
p, nvme_strerror(errno));
|
||||
nvme_free_tree(r);
|
||||
return errno;
|
||||
return -errno;
|
||||
}
|
||||
dim_operation(c, tas, p);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue