Adding upstream version 2.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
8dc527e3df
commit
a7aa0c3253
444 changed files with 5289 additions and 1980 deletions
296
fabrics.c
296
fabrics.c
|
@ -124,6 +124,94 @@ static void space_strip_len(int max, char *str)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two C strings and handle NULL pointers gracefully.
|
||||
* If either of the two strings is NULL, return 0
|
||||
* to let caller ignore the compare.
|
||||
*/
|
||||
static inline int strcmp0(const char *s1, const char *s2)
|
||||
{
|
||||
if (!s1 || !s2)
|
||||
return 0;
|
||||
return strcmp(s1, s2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two C strings and handle NULL pointers gracefully.
|
||||
* If either of the two strings is NULL, return 0
|
||||
* to let caller ignore the compare.
|
||||
*/
|
||||
static inline int strcasecmp0(const char *s1, const char *s2)
|
||||
{
|
||||
if (!s1 || !s2)
|
||||
return 0;
|
||||
return strcasecmp(s1, s2);
|
||||
}
|
||||
|
||||
static bool is_persistent_discovery_ctrl(nvme_host_t h, nvme_ctrl_t c)
|
||||
{
|
||||
if (nvme_host_is_pdc_enabled(h, DEFAULT_PDC_ENABLED))
|
||||
return nvme_ctrl_is_unique_discovery_ctrl(c);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool disc_ctrl_config_match(nvme_ctrl_t c, struct tr_config *trcfg)
|
||||
{
|
||||
if (nvme_ctrl_is_discovery_ctrl(c) &&
|
||||
!strcmp0(nvme_ctrl_get_transport(c), trcfg->transport) &&
|
||||
!strcasecmp0(nvme_ctrl_get_traddr(c), trcfg->traddr) &&
|
||||
!strcmp0(nvme_ctrl_get_trsvcid(c), trcfg->trsvcid) &&
|
||||
!strcmp0(nvme_ctrl_get_host_traddr(c), trcfg->host_traddr) &&
|
||||
!strcmp0(nvme_ctrl_get_host_iface(c), trcfg->host_iface))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ctrl_config_match(nvme_ctrl_t c, struct tr_config *trcfg)
|
||||
{
|
||||
if (!strcmp0(nvme_ctrl_get_subsysnqn(c), trcfg->subsysnqn) &&
|
||||
!strcmp0(nvme_ctrl_get_transport(c), trcfg->transport) &&
|
||||
!strcasecmp0(nvme_ctrl_get_traddr(c), trcfg->traddr) &&
|
||||
!strcmp0(nvme_ctrl_get_trsvcid(c), trcfg->trsvcid) &&
|
||||
!strcmp0(nvme_ctrl_get_host_traddr(c), trcfg->host_traddr) &&
|
||||
!strcmp0(nvme_ctrl_get_host_iface(c), trcfg->host_iface))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static nvme_ctrl_t __lookup_ctrl(nvme_root_t r, struct tr_config *trcfg,
|
||||
bool (*filter)(nvme_ctrl_t, struct tr_config *))
|
||||
{
|
||||
nvme_host_t h;
|
||||
nvme_subsystem_t s;
|
||||
nvme_ctrl_t c;
|
||||
|
||||
nvme_for_each_host(r, h) {
|
||||
nvme_for_each_subsystem(h, s) {
|
||||
nvme_subsystem_for_each_ctrl(s, c) {
|
||||
if (!(filter(c, trcfg)))
|
||||
continue;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return __lookup_ctrl(r, trcfg, ctrl_config_match);
|
||||
}
|
||||
|
||||
static int set_discovery_kato(struct nvme_fabrics_config *cfg)
|
||||
{
|
||||
int tmo = cfg->keep_alive_tmo;
|
||||
|
@ -152,6 +240,8 @@ static nvme_ctrl_t __create_discover_ctrl(nvme_root_t r, nvme_host_t h,
|
|||
return NULL;
|
||||
|
||||
nvme_ctrl_set_discovery_ctrl(c, true);
|
||||
nvme_ctrl_set_unique_discovery_ctrl(c,
|
||||
strcmp(trcfg->subsysnqn, NVME_DISC_SUBSYS_NAME));
|
||||
tmo = set_discovery_kato(cfg);
|
||||
|
||||
errno = 0;
|
||||
|
@ -159,7 +249,6 @@ static nvme_ctrl_t __create_discover_ctrl(nvme_root_t r, nvme_host_t h,
|
|||
|
||||
cfg->keep_alive_tmo = tmo;
|
||||
if (ret) {
|
||||
errno = ret;
|
||||
nvme_free_ctrl(c);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -177,7 +266,7 @@ static nvme_ctrl_t create_discover_ctrl(nvme_root_t r, nvme_host_t h,
|
|||
if (!c)
|
||||
return NULL;
|
||||
|
||||
if (!persistent)
|
||||
if (nvme_ctrl_is_unique_discovery_ctrl(c))
|
||||
return c;
|
||||
|
||||
/* Find out the name of discovery controller */
|
||||
|
@ -225,11 +314,12 @@ static void print_discovery_log(struct nvmf_discovery_log *log, int numrec)
|
|||
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", e->portid);
|
||||
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(e->eflags));
|
||||
printf("eflags: %s\n",
|
||||
nvmf_eflags_str(le16_to_cpu(e->eflags)));
|
||||
|
||||
switch (e->trtype) {
|
||||
case NVMF_TRTYPE_RDMA:
|
||||
|
@ -265,9 +355,9 @@ static void json_discovery_log(struct nvmf_discovery_log *log, int numrec)
|
|||
struct nvmf_disc_log_entry *e = &log->entries[i];
|
||||
struct json_object *entry = json_create_object();
|
||||
|
||||
nvme_strip_spaces(e->trsvcid, NVMF_TRSVCID_SIZE);
|
||||
nvme_strip_spaces(e->subnqn, NVMF_NQN_SIZE);
|
||||
nvme_strip_spaces(e->traddr, NVMF_TRADDR_SIZE);
|
||||
space_strip_len(NVMF_TRSVCID_SIZE, e->trsvcid);
|
||||
space_strip_len(NVMF_NQN_SIZE, e->subnqn);
|
||||
space_strip_len(NVMF_TRADDR_SIZE, e->traddr);
|
||||
|
||||
json_object_add_value_string(entry, "trtype",
|
||||
nvmf_trtype_str(e->trtype));
|
||||
|
@ -282,7 +372,8 @@ static void json_discovery_log(struct nvmf_discovery_log *log, int numrec)
|
|||
json_object_add_value_string(entry, "trsvcid", e->trsvcid);
|
||||
json_object_add_value_string(entry, "subnqn", e->subnqn);
|
||||
json_object_add_value_string(entry, "traddr", e->traddr);
|
||||
json_object_add_value_uint(entry, "eflags", e->eflags);
|
||||
json_object_add_value_string(entry, "eflags",
|
||||
nvmf_eflags_str(le16_to_cpu(e->eflags)));
|
||||
|
||||
switch (e->trtype) {
|
||||
case NVMF_TRTYPE_RDMA:
|
||||
|
@ -355,43 +446,104 @@ static int __discover(nvme_ctrl_t c, struct nvme_fabrics_config *defcfg,
|
|||
struct nvmf_discovery_log *log = NULL;
|
||||
nvme_subsystem_t s = nvme_ctrl_get_subsystem(c);
|
||||
nvme_host_t h = nvme_subsystem_get_host(s);
|
||||
nvme_root_t r = nvme_host_get_root(h);
|
||||
uint64_t numrec;
|
||||
int err;
|
||||
|
||||
err = nvmf_get_discovery_log(c, &log, MAX_DISC_RETRIES);
|
||||
if (err) {
|
||||
if (err > 0)
|
||||
nvme_show_status(err);
|
||||
else
|
||||
fprintf(stderr, "failed to get discovery log: %s\n",
|
||||
nvme_strerror(errno));
|
||||
return err;
|
||||
struct nvme_get_discovery_args args = {
|
||||
.c = c,
|
||||
.args_size = sizeof(args),
|
||||
.max_retries = MAX_DISC_RETRIES,
|
||||
.result = 0,
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
.lsp = 0,
|
||||
};
|
||||
|
||||
log = nvmf_get_discovery_wargs(&args);
|
||||
if (!log) {
|
||||
fprintf(stderr, "failed to get discovery log: %s\n",
|
||||
nvme_strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
numrec = le64_to_cpu(log->numrec);
|
||||
if (raw)
|
||||
save_discovery_log(raw, log);
|
||||
else if (!connect) {
|
||||
if (flags == JSON)
|
||||
json_discovery_log(log, numrec);
|
||||
else
|
||||
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;
|
||||
}
|
||||
} else if (connect) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < numrec; i++) {
|
||||
struct nvmf_disc_log_entry *e = &log->entries[i];
|
||||
nvme_ctrl_t cl;
|
||||
bool discover = false;
|
||||
bool disconnect;
|
||||
nvme_ctrl_t child;
|
||||
int tmo = defcfg->keep_alive_tmo;
|
||||
|
||||
/* Skip connect if the transport types don't match */
|
||||
if (strcmp(nvme_ctrl_get_transport(c), nvmf_trtype_str(e->trtype)))
|
||||
struct tr_config trcfg = {
|
||||
.subsysnqn = e->subnqn,
|
||||
.transport = nvmf_trtype_str(e->trtype),
|
||||
.traddr = e->traddr,
|
||||
.host_traddr = defcfg->host_traddr,
|
||||
.host_iface = defcfg->host_iface,
|
||||
.trsvcid = e->trsvcid,
|
||||
};
|
||||
|
||||
/* Already connected ? */
|
||||
cl = lookup_ctrl(r, &trcfg);
|
||||
if (cl && nvme_ctrl_get_name(cl))
|
||||
continue;
|
||||
|
||||
if (e->subtype == NVME_NQN_DISC)
|
||||
/* Skip connect if the transport types don't match */
|
||||
if (strcmp(nvme_ctrl_get_transport(c),
|
||||
nvmf_trtype_str(e->trtype)))
|
||||
continue;
|
||||
|
||||
if (e->subtype == NVME_NQN_DISC ||
|
||||
e->subtype == NVME_NQN_CURR) {
|
||||
__u16 eflags = le16_to_cpu(e->eflags);
|
||||
/*
|
||||
* Does this discovery controller return the
|
||||
* same information?
|
||||
*/
|
||||
if (eflags & NVMF_DISC_EFLAGS_DUPRETINFO)
|
||||
continue;
|
||||
|
||||
/* Are we supposed to keep the discovery
|
||||
* controller around? */
|
||||
disconnect = !persistent;
|
||||
|
||||
if (strcmp(e->subnqn, NVME_DISC_SUBSYS_NAME)) {
|
||||
/*
|
||||
* Does this discovery controller doesn't
|
||||
* support explicit persistent connection?
|
||||
*/
|
||||
if (!(eflags & NVMF_DISC_EFLAGS_EPCSD))
|
||||
disconnect = true;
|
||||
else
|
||||
disconnect = false;
|
||||
}
|
||||
|
||||
set_discovery_kato(defcfg);
|
||||
} else {
|
||||
/* NVME_NQN_NVME */
|
||||
disconnect = false;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
child = nvmf_connect_disc_entry(h, e, defcfg,
|
||||
|
@ -403,8 +555,8 @@ static int __discover(nvme_ctrl_t c, struct nvme_fabrics_config *defcfg,
|
|||
if (discover)
|
||||
__discover(child, defcfg, raw,
|
||||
true, persistent, flags);
|
||||
if (e->subtype != NVME_NQN_NVME &&
|
||||
!persistent) {
|
||||
|
||||
if (disconnect) {
|
||||
nvme_disconnect_ctrl(child);
|
||||
nvme_free_ctrl(child);
|
||||
}
|
||||
|
@ -423,62 +575,6 @@ static int __discover(nvme_ctrl_t c, struct nvme_fabrics_config *defcfg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two C strings and handle NULL pointers gracefully.
|
||||
* If either of the two strings is NULL, return 0
|
||||
* to let caller ignore the compare.
|
||||
*/
|
||||
static inline int strcmp0(const char *s1, const char *s2)
|
||||
{
|
||||
if (!s1 || !s2)
|
||||
return 0;
|
||||
return strcmp(s1, s2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two C strings and handle NULL pointers gracefully.
|
||||
* If either of the two strings is NULL, return 0
|
||||
* to let caller ignore the compare.
|
||||
*/
|
||||
static inline int strcasecmp0(const char *s1, const char *s2)
|
||||
{
|
||||
if (!s1 || !s2)
|
||||
return 0;
|
||||
return strcasecmp(s1, s2);
|
||||
}
|
||||
|
||||
static bool ctrl_config_match(nvme_ctrl_t c, struct tr_config *trcfg)
|
||||
{
|
||||
if (!strcmp0(nvme_ctrl_get_transport(c), trcfg->transport) &&
|
||||
!strcasecmp0(nvme_ctrl_get_traddr(c), trcfg->traddr) &&
|
||||
!strcmp0(nvme_ctrl_get_trsvcid(c), trcfg->trsvcid) &&
|
||||
!strcmp0(nvme_ctrl_get_host_traddr(c), trcfg->host_traddr) &&
|
||||
!strcmp0(nvme_ctrl_get_host_iface(c), trcfg->host_iface))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static nvme_ctrl_t lookup_discover_ctrl(nvme_root_t r, struct tr_config *trcfg)
|
||||
{
|
||||
nvme_host_t h;
|
||||
nvme_subsystem_t s;
|
||||
nvme_ctrl_t c;
|
||||
|
||||
nvme_for_each_host(r, h) {
|
||||
nvme_for_each_subsystem(h, s) {
|
||||
nvme_subsystem_for_each_ctrl(s, c) {
|
||||
if (!nvme_ctrl_is_discovery_ctrl(c))
|
||||
continue;
|
||||
if (ctrl_config_match(c, trcfg))
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *get_default_trsvcid(const char *transport,
|
||||
bool discovery_ctrl)
|
||||
{
|
||||
|
@ -581,7 +677,7 @@ static int discover_from_conf_file(nvme_root_t r, nvme_host_t h,
|
|||
};
|
||||
|
||||
if (!force) {
|
||||
c = lookup_discover_ctrl(r, &trcfg);
|
||||
c = lookup_discovery_ctrl(r, &trcfg);
|
||||
if (c) {
|
||||
__discover(c, &cfg, raw, connect,
|
||||
true, flags);
|
||||
|
@ -594,7 +690,7 @@ static int discover_from_conf_file(nvme_root_t r, nvme_host_t h,
|
|||
goto next;
|
||||
|
||||
__discover(c, &cfg, raw, connect, persistent, flags);
|
||||
if (!persistent)
|
||||
if (!(persistent || is_persistent_discovery_ctrl(h, c)))
|
||||
ret = nvme_disconnect_ctrl(c);
|
||||
nvme_free_ctrl(c);
|
||||
|
||||
|
@ -657,9 +753,9 @@ static int discover_from_json_config_file(nvme_root_t r, nvme_host_t h,
|
|||
};
|
||||
|
||||
if (!force) {
|
||||
cn = lookup_discover_ctrl(r, &trcfg);
|
||||
cn = lookup_discovery_ctrl(r, &trcfg);
|
||||
if (cn) {
|
||||
__discover(c, &cfg, raw, connect,
|
||||
__discover(cn, &cfg, raw, connect,
|
||||
true, flags);
|
||||
continue;
|
||||
}
|
||||
|
@ -670,7 +766,7 @@ static int discover_from_json_config_file(nvme_root_t r, nvme_host_t h,
|
|||
continue;
|
||||
|
||||
__discover(cn, &cfg, raw, connect, persistent, flags);
|
||||
if (!persistent)
|
||||
if (!(persistent || is_persistent_discovery_ctrl(h, cn)))
|
||||
ret = nvme_disconnect_ctrl(cn);
|
||||
nvme_free_ctrl(cn);
|
||||
}
|
||||
|
@ -825,7 +921,7 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect)
|
|||
}
|
||||
}
|
||||
if (!c && !force) {
|
||||
c = lookup_discover_ctrl(r, &trcfg);
|
||||
c = lookup_discovery_ctrl(r, &trcfg);
|
||||
if (c)
|
||||
persistent = true;
|
||||
}
|
||||
|
@ -841,9 +937,8 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect)
|
|||
}
|
||||
}
|
||||
|
||||
ret = __discover(c, &cfg, raw, connect,
|
||||
persistent, flags);
|
||||
if (!persistent)
|
||||
ret = __discover(c, &cfg, raw, connect, persistent, flags);
|
||||
if (!(persistent || is_persistent_discovery_ctrl(h, c)))
|
||||
nvme_disconnect_ctrl(c);
|
||||
nvme_free_ctrl(c);
|
||||
|
||||
|
@ -953,6 +1048,23 @@ int nvmf_connect(const char *desc, int argc, char **argv)
|
|||
nvme_host_set_dhchap_key(h, hostkey);
|
||||
if (!trsvcid)
|
||||
trsvcid = get_default_trsvcid(transport, false);
|
||||
|
||||
struct tr_config trcfg = {
|
||||
.subsysnqn = subsysnqn,
|
||||
.transport = transport,
|
||||
.traddr = traddr,
|
||||
.host_traddr = cfg.host_traddr,
|
||||
.host_iface = cfg.host_iface,
|
||||
.trsvcid = trsvcid,
|
||||
};
|
||||
|
||||
c = lookup_ctrl(r, &trcfg);
|
||||
if (c && nvme_ctrl_get_name(c)) {
|
||||
fprintf(stderr, "already connected\n");
|
||||
errno = EALREADY;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
c = nvme_create_ctrl(r, subsysnqn, transport, traddr,
|
||||
cfg.host_traddr, cfg.host_iface, trsvcid);
|
||||
if (!c) {
|
||||
|
@ -965,7 +1077,7 @@ int nvmf_connect(const char *desc, int argc, char **argv)
|
|||
errno = 0;
|
||||
ret = nvmf_add_ctrl(h, c, &cfg);
|
||||
if (ret)
|
||||
fprintf(stderr, "no controller found: %s\n",
|
||||
fprintf(stderr, "could not add new controller: %s\n",
|
||||
nvme_strerror(errno));
|
||||
else {
|
||||
errno = 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue