summaryrefslogtreecommitdiffstats
path: root/src/nvme/fabrics.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvme/fabrics.c')
-rw-r--r--src/nvme/fabrics.c158
1 files changed, 107 insertions, 51 deletions
diff --git a/src/nvme/fabrics.c b/src/nvme/fabrics.c
index 2a26843..ee20da2 100644
--- a/src/nvme/fabrics.c
+++ b/src/nvme/fabrics.c
@@ -118,8 +118,21 @@ static const char * const eflags_strings[] = {
[NVMF_DISC_EFLAGS_NONE] = "not specified",
[NVMF_DISC_EFLAGS_EPCSD] = "explicit discovery connections",
[NVMF_DISC_EFLAGS_DUPRETINFO] = "duplicate discovery information",
- [NVMF_DISC_EFLAGS_BOTH] = "explicit discovery connections, "
+ [NVMF_DISC_EFLAGS_EPCSD |
+ NVMF_DISC_EFLAGS_DUPRETINFO] = "explicit discovery connections, "
"duplicate discovery information",
+ [NVMF_DISC_EFLAGS_NCC] = "no cdc connectivity",
+ [NVMF_DISC_EFLAGS_EPCSD |
+ NVMF_DISC_EFLAGS_NCC] = "explicit discovery connections, "
+ "no cdc connectivity",
+ [NVMF_DISC_EFLAGS_DUPRETINFO |
+ NVMF_DISC_EFLAGS_NCC] = "duplicate discovery information, "
+ "no cdc connectivity",
+ [NVMF_DISC_EFLAGS_EPCSD |
+ NVMF_DISC_EFLAGS_DUPRETINFO |
+ NVMF_DISC_EFLAGS_NCC] = "explicit discovery connections, "
+ "duplicate discovery information, "
+ "no cdc connectivity",
};
const char *nvmf_eflags_str(__u16 eflags)
@@ -316,16 +329,19 @@ static int inet6_pton(nvme_root_t r, const char *src, uint16_t port,
{
int ret = -EINVAL;
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
+ const char *scope = NULL;
+ char *p;
if (strlen(src) > INET6_ADDRSTRLEN)
return -EINVAL;
char *tmp = strdup(src);
- if (!tmp)
+ if (!tmp) {
nvme_msg(r, LOG_ERR, "cannot copy: %s\n", src);
+ return -ENOMEM;
+ }
- const char *scope = NULL;
- char *p = strchr(tmp, SCOPE_DELIMITER);
+ p = strchr(tmp, '%');
if (p) {
*p = '\0';
scope = src + (p - tmp) + 1;
@@ -521,13 +537,33 @@ static int __nvmf_add_ctrl(nvme_root_t r, const char *argstr)
(int)strcspn(argstr,"\n"), argstr);
ret = write(fd, argstr, len);
if (ret != len) {
- nvme_msg(r, LOG_ERR, "Failed to write to %s: %s\n",
+ nvme_msg(r, LOG_NOTICE, "Failed to write to %s: %s\n",
nvmf_dev, strerror(errno));
- ret = -ENVME_CONNECT_WRITE;
+ switch (errno) {
+ case EALREADY:
+ ret = -ENVME_CONNECT_ALREADY;
+ break;
+ case EINVAL:
+ ret = -ENVME_CONNECT_INVAL;
+ break;
+ case EADDRINUSE:
+ ret = -ENVME_CONNECT_ADDRINUSE;
+ break;
+ case ENODEV:
+ ret = -ENVME_CONNECT_NODEV;
+ break;
+ case EOPNOTSUPP:
+ ret = -ENVME_CONNECT_OPNOTSUPP;
+ break;
+ default:
+ ret = -ENVME_CONNECT_WRITE;
+ break;
+ }
goto out_close;
}
- len = read(fd, buf, sizeof(buf));
+ memset(buf, 0x0, sizeof(buf));
+ len = read(fd, buf, sizeof(buf) - 1);
if (len < 0) {
nvme_msg(r, LOG_ERR, "Failed to read from %s: %s\n",
nvmf_dev, strerror(errno));
@@ -555,10 +591,37 @@ out_close:
int nvmf_add_ctrl(nvme_host_t h, nvme_ctrl_t c,
const struct nvme_fabrics_config *cfg)
{
+ nvme_subsystem_t s;
char *argstr;
int ret;
+ /* highest prio have configs from command line */
cfg = merge_config(c, cfg);
+
+ /* apply configuration from config file (JSON) */
+ s = nvme_lookup_subsystem(h, NULL, nvme_ctrl_get_subsysnqn(c));
+ if (s) {
+ nvme_ctrl_t fc;
+
+ fc = __nvme_lookup_ctrl(s, nvme_ctrl_get_transport(c),
+ nvme_ctrl_get_traddr(c),
+ nvme_ctrl_get_host_traddr(c),
+ nvme_ctrl_get_host_iface(c),
+ nvme_ctrl_get_trsvcid(c),
+ NULL);
+ if (fc) {
+ cfg = merge_config(c, nvme_ctrl_get_config(fc));
+ /*
+ * An authentication key might already been set
+ * in @cfg, so ensure to update @c with the correct
+ * controller key.
+ */
+ if (fc->dhchap_key)
+ nvme_ctrl_set_dhchap_key(c, fc->dhchap_key);
+ }
+
+ }
+
nvme_ctrl_set_discovered(c, true);
if (traddr_is_hostname(h->r, c)) {
char *traddr = c->traddr;
@@ -702,8 +765,6 @@ nvme_ctrl_t nvmf_connect_disc_entry(nvme_host_t h,
if (!ret)
return c;
}
- nvme_msg(h->r, LOG_ERR, "failed to connect controller, error %d\n",
- errno);
nvme_free_ctrl(c);
return NULL;
}
@@ -734,54 +795,27 @@ int nvmf_get_discovery_log(nvme_ctrl_t c, struct nvmf_discovery_log **logp,
int max_retries)
{
nvme_root_t r = c->s && c->s->h ? c->s->h->r : NULL;
- struct nvmf_discovery_log *log;
- int hdr, ret, retries = 0;
+ struct nvmf_discovery_log *log = NULL;
+ int ret, retries = 0;
const char *name = nvme_ctrl_get_name(c);
uint64_t genctr, numrec;
unsigned int size;
- hdr = sizeof(struct nvmf_discovery_log);
- log = malloc(hdr);
- if (!log) {
- nvme_msg(r, LOG_ERR,
- "could not allocate memory for discovery log header\n");
- errno = ENOMEM;
- return -1;
- }
- memset(log, 0, hdr);
-
- nvme_msg(r, LOG_DEBUG, "%s: discover length %d\n", name, 0x100);
- ret = nvme_discovery_log(nvme_ctrl_get_fd(c), 0x100, log, true);
- if (ret) {
- nvme_msg(r, LOG_INFO, "%s: discover failed, error %d\n",
- name, errno);
- goto out_free_log;
- }
-
do {
- numrec = le64_to_cpu(log->numrec);
- genctr = le64_to_cpu(log->genctr);
-
- if (numrec == 0) {
- *logp = log;
- return 0;
- }
-
- size = sizeof(struct nvmf_discovery_log) +
- sizeof(struct nvmf_disc_log_entry) * (numrec);
+ size = sizeof(struct nvmf_discovery_log);
free(log);
- log = malloc(size);
+ log = calloc(1, size);
if (!log) {
nvme_msg(r, LOG_ERR,
- "could not alloc memory for discovery log page\n");
+ "could not allocate memory for discovery log header\n");
errno = ENOMEM;
return -1;
}
- memset(log, 0, size);
- nvme_msg(r, LOG_DEBUG, "%s: discover length %d\n", name, size);
- ret = nvme_discovery_log(nvme_ctrl_get_fd(c), size, log, false);
+ nvme_msg(r, LOG_DEBUG, "%s: get header (try %d/%d)\n",
+ name, retries, max_retries);
+ ret = nvme_discovery_log(nvme_ctrl_get_fd(c), size, log, true);
if (ret) {
nvme_msg(r, LOG_INFO,
"%s: discover try %d/%d failed, error %d\n",
@@ -789,11 +823,29 @@ int nvmf_get_discovery_log(nvme_ctrl_t c, struct nvmf_discovery_log **logp,
goto out_free_log;
}
+ numrec = le64_to_cpu(log->numrec);
genctr = le64_to_cpu(log->genctr);
+
+ if (numrec == 0)
+ break;
+
+ size = sizeof(struct nvmf_discovery_log) +
+ sizeof(struct nvmf_disc_log_entry) * numrec;
+
+ free(log);
+ log = calloc(1, size);
+ if (!log) {
+ nvme_msg(r, LOG_ERR,
+ "could not alloc memory for discovery log page\n");
+ errno = ENOMEM;
+ return -1;
+ }
+
nvme_msg(r, LOG_DEBUG,
- "%s: discover genctr %" PRIu64 ", retry\n",
- name, genctr);
- ret = nvme_discovery_log(nvme_ctrl_get_fd(c), hdr, log, true);
+ "%s: get header and %" PRIu64
+ " records (length %d genctr %" PRIu64 ")\n",
+ name, numrec, size, genctr);
+ ret = nvme_discovery_log(nvme_ctrl_get_fd(c), size, log, false);
if (ret) {
nvme_msg(r, LOG_INFO,
"%s: discover try %d/%d failed, error %d\n",
@@ -1264,12 +1316,14 @@ static const char *dctype_str[] = {
* sysfs. We must get them directly from the controller by performing an
* identify command.
*/
-static void nvme_fetch_cntrltype_dctype_from_id(nvme_ctrl_t c)
+static int nvme_fetch_cntrltype_dctype_from_id(nvme_ctrl_t c)
{
struct nvme_id_ctrl id = { 0 };
+ int ret;
- if (nvme_ctrl_identify(c, &id))
- return;
+ ret = nvme_ctrl_identify(c, &id);
+ if (ret)
+ return ret;
if (!c->cntrltype) {
if (id.cntrltype > NVME_CTRL_CNTRLTYPE_ADMIN || !cntrltype_str[id.cntrltype])
@@ -1284,12 +1338,14 @@ static void nvme_fetch_cntrltype_dctype_from_id(nvme_ctrl_t c)
else
c->dctype = strdup(dctype_str[id.dctype]);
}
+ return 0;
}
bool nvmf_is_registration_supported(nvme_ctrl_t c)
{
if (!c->cntrltype || !c->dctype)
- nvme_fetch_cntrltype_dctype_from_id(c);
+ if (nvme_fetch_cntrltype_dctype_from_id(c))
+ return false;
return !strcmp(c->dctype, "ddc") || !strcmp(c->dctype, "cdc");
}