diff options
Diffstat (limited to 'src/nvme/fabrics.c')
-rw-r--r-- | src/nvme/fabrics.c | 158 |
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"); } |