1
0
Fork 0

Adding upstream version 2.3.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-16 12:20:36 +01:00
parent 8dc527e3df
commit a7aa0c3253
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
444 changed files with 5289 additions and 1980 deletions

296
fabrics.c
View file

@ -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;