diff options
Diffstat (limited to '')
-rw-r--r-- | src/nvme/tree.c | 179 |
1 files changed, 153 insertions, 26 deletions
diff --git a/src/nvme/tree.c b/src/nvme/tree.c index eb9486d..3722461 100644 --- a/src/nvme/tree.c +++ b/src/nvme/tree.c @@ -117,16 +117,99 @@ static void cleanup_dirents(struct dirents *ents) #define _cleanup_dirents_ __cleanup__(cleanup_dirents) +static char *nvme_hostid_from_hostnqn(const char *hostnqn) +{ + const char *uuid; + + uuid = strstr(hostnqn, "uuid:"); + if (!uuid) + return NULL; + + return strdup(uuid + strlen("uuid:")); +} + +int nvme_host_get_ids(nvme_root_t r, + char *hostnqn_arg, char *hostid_arg, + char **hostnqn, char **hostid) +{ + _cleanup_free_ char *nqn = NULL; + _cleanup_free_ char *hid = NULL; + _cleanup_free_ char *hnqn = NULL; + nvme_host_t h; + + /* command line argumments */ + if (hostid_arg) + hid = strdup(hostid_arg); + if (hostnqn_arg) + hnqn = strdup(hostnqn_arg); + + /* JSON config: assume the first entry is the default host */ + h = nvme_first_host(r); + if (h) { + if (!hid) + hid = strdup(nvme_host_get_hostid(h)); + if (!hnqn) + hnqn = strdup(nvme_host_get_hostnqn(h)); + } + + /* /etc/nvme/hostid and/or /etc/nvme/hostnqn */ + if (!hid) + hid = nvmf_hostid_from_file(); + if (!hnqn) + hnqn = nvmf_hostnqn_from_file(); + + /* incomplete configuration, thus derive hostid from hostnqn */ + if (!hid && hnqn) + hid = nvme_hostid_from_hostnqn(hnqn); + + /* + * fallback to use either DMI information or device-tree. If all + * fails generate one + */ + if (!hid) { + hid = nvmf_hostid_generate(); + if (!hid) { + errno = -ENOMEM; + return -1; + } + + nvme_msg(r, LOG_DEBUG, + "warning: using auto generated hostid and hostnqn\n"); + } + + /* incomplete configuration, thus derive hostnqn from hostid */ + if (!hnqn) { + hnqn = nvmf_hostnqn_generate_from_hostid(hid); + if (!hnqn) { + errno = -ENOMEM; + return -1; + } + } + + /* sanity checks */ + nqn = nvme_hostid_from_hostnqn(hnqn); + if (nqn && strcmp(nqn, hid)) { + nvme_msg(r, LOG_DEBUG, + "warning: use hostid '%s' which does not match uuid in hostnqn '%s'\n", + hid, hnqn); + } + + *hostid = hid; + *hostnqn = hnqn; + hid = NULL; + hnqn = NULL; + + return 0; +} + nvme_host_t nvme_default_host(nvme_root_t r) { - struct nvme_host *h; _cleanup_free_ char *hostnqn = NULL; _cleanup_free_ char *hostid = NULL; + struct nvme_host *h; - hostnqn = nvmf_hostnqn_from_file(); - if (!hostnqn) - hostnqn = nvmf_hostnqn_generate(); - hostid = nvmf_hostid_from_file(); + if (nvme_host_get_ids(r, NULL, NULL, &hostnqn, &hostid)) + return NULL; h = nvme_lookup_host(r, hostnqn, hostid); @@ -187,25 +270,37 @@ int nvme_scan_topology(struct nvme_root *r, nvme_scan_filter_t f, void *f_args) nvme_root_t nvme_create_root(FILE *fp, int log_level) { - struct nvme_root *r = calloc(1, sizeof(*r)); + struct nvme_root *r; + int fd; + r = calloc(1, sizeof(*r)); if (!r) { errno = ENOMEM; return NULL; } - r->log_level = log_level; - r->fp = stderr; - if (fp) - r->fp = fp; + + if (fp) { + fd = fileno(fp); + if (fd < 0) { + free(r); + return NULL; + } + } else + fd = STDERR_FILENO; + + r->log.fd = fd; + r->log.level = log_level; + list_head_init(&r->hosts); list_head_init(&r->endpoints); - nvme_set_root(r); + return r; } int nvme_read_config(nvme_root_t r, const char *config_file) { int err = -1; + int tmp; if (!r || !config_file) { errno = ENODEV; @@ -217,13 +312,17 @@ int nvme_read_config(nvme_root_t r, const char *config_file) errno = ENOMEM; return err; } + + tmp = errno; err = json_read_config(r, config_file); /* * The json configuration file is optional, * so ignore errors when opening the file. */ - if (err < 0 && errno != EPROTO) - err = 0; + if (err < 0 && errno != EPROTO) { + errno = tmp; + return 0; + } return err; } @@ -270,6 +369,11 @@ void nvme_root_set_application(nvme_root_t r, const char *a) r->application = strdup(a); } +void nvme_root_skip_namespaces(nvme_root_t r) +{ + r->create_only = true; +} + nvme_host_t nvme_first_host(nvme_root_t r) { return list_top(&r->hosts, struct nvme_host, entry); @@ -361,14 +465,17 @@ void nvme_free_tree(nvme_root_t r) { struct nvme_host *h, *_h; - free(r->options); + if (!r) + return; + + if (r->options) + free(r->options); nvme_for_each_host_safe(r, h, _h) __nvme_free_host(h); if (r->config_file) free(r->config_file); if (r->application) free(r->application); - nvme_set_root(NULL); free(r); } @@ -538,7 +645,7 @@ struct nvme_subsystem *nvme_alloc_subsystem(struct nvme_host *h, list_head_init(&s->ctrls); list_head_init(&s->namespaces); list_node_init(&s->entry); - list_add(&h->subsystems, &s->entry); + list_add_tail(&h->subsystems, &s->entry); h->r->modified = true; return s; } @@ -622,7 +729,7 @@ struct nvme_host *nvme_lookup_host(nvme_root_t r, const char *hostnqn, list_head_init(&h->subsystems); list_node_init(&h->entry); h->r = r; - list_add(&r->hosts, &h->entry); + list_add_tail(&r->hosts, &h->entry); r->modified = true; return h; @@ -634,6 +741,12 @@ static int nvme_subsystem_scan_namespaces(nvme_root_t r, nvme_subsystem_t s, _cleanup_dirents_ struct dirents namespaces = {}; int i, ret; + if (r->create_only) { + nvme_msg(r, LOG_DEBUG, + "skipping namespace scan for subsys %s\n", + s->subsysnqn); + return 0; + } namespaces.num = nvme_scan_subsystem_namespaces(s, &namespaces.ents); if (namespaces.num < 0) { nvme_msg(r, LOG_DEBUG, @@ -806,7 +919,7 @@ static void nvme_subsystem_set_path_ns(nvme_subsystem_t s, nvme_path_t p) sprintf(n_name, "nvme%dn%d", i, nsid); nvme_subsystem_for_each_ns(s, n) { if (!strcmp(n_name, nvme_ns_get_name(n))) { - list_add(&n->paths, &p->nentry); + list_add_tail(&n->paths, &p->nentry); p->n = n; } } @@ -852,7 +965,7 @@ static int nvme_ctrl_scan_path(nvme_root_t r, struct nvme_ctrl *c, char *name) list_node_init(&p->nentry); nvme_subsystem_set_path_ns(c->s, p); list_node_init(&p->entry); - list_add(&c->paths, &p->entry); + list_add_tail(&c->paths, &p->entry); return 0; } @@ -1591,8 +1704,8 @@ nvme_ctrl_t __nvme_lookup_ctrl(nvme_subsystem_t s, const char *transport, const char *host_iface, const char *trsvcid, const char *subsysnqn, nvme_ctrl_t p) { + _cleanup_candidate_ struct candidate_args candidate = {}; struct nvme_ctrl *c, *matching_c = NULL; - _cleanup_candidate_ struct candidate_args candidate; ctrl_match_t ctrl_match; /* Init candidate and get the matching function to use */ @@ -1615,8 +1728,8 @@ bool nvme_ctrl_config_match(struct nvme_ctrl *c, const char *transport, const char *subsysnqn, const char *host_traddr, const char *host_iface) { + _cleanup_candidate_ struct candidate_args candidate = {}; ctrl_match_t ctrl_match; - _cleanup_candidate_ struct candidate_args candidate; /* Init candidate and get the matching function to use */ ctrl_match = _candidate_init(&candidate, transport, traddr, trsvcid, @@ -1655,7 +1768,7 @@ nvme_ctrl_t nvme_lookup_ctrl(nvme_subsystem_t s, const char *transport, host_traddr, host_iface, trsvcid); if (c) { c->s = s; - list_add(&s->ctrls, &c->entry); + list_add_tail(&s->ctrls, &c->entry); s->h->r->modified = true; } return c; @@ -1666,6 +1779,11 @@ static int nvme_ctrl_scan_paths(nvme_root_t r, struct nvme_ctrl *c) _cleanup_dirents_ struct dirents paths = {}; int i; + if (r->create_only) { + nvme_msg(r, LOG_DEBUG, + "skipping path scan for ctrl %s\n", c->name); + return 0; + } paths.num = nvme_scan_ctrl_namespace_paths(c, &paths.ents); if (paths.num < 0) return paths.num; @@ -1681,6 +1799,11 @@ static int nvme_ctrl_scan_namespaces(nvme_root_t r, struct nvme_ctrl *c) _cleanup_dirents_ struct dirents namespaces = {}; int i; + if (r->create_only) { + nvme_msg(r, LOG_DEBUG, "skipping namespace scan for ctrl %s\n", + c->name); + return 0; + } namespaces.num = nvme_scan_ctrl_namespaces(c, &namespaces.ents); for (i = 0; i < namespaces.num; i++) nvme_ctrl_scan_namespace(r, c, namespaces.ents[i]->d_name); @@ -1749,6 +1872,10 @@ static char *nvme_ctrl_lookup_phy_slot(nvme_root_t r, const char *address) return NULL; } addr = nvme_get_attr(path, "address"); + + /* some directories don't have an address entry */ + if (!addr) + continue; if (strcmp(addr, target_addr) == 0) return strdup(entry->d_name); } @@ -1861,7 +1988,7 @@ int nvme_init_ctrl(nvme_host_t h, nvme_ctrl_t c, int instance) if (s->subsystype && !strcmp(s->subsystype, "discovery")) c->discovery_ctrl = true; c->s = s; - list_add(&s->ctrls, &c->entry); + list_add_tail(&s->ctrls, &c->entry); return ret; } @@ -2635,7 +2762,7 @@ static int nvme_ctrl_scan_namespace(nvme_root_t r, struct nvme_ctrl *c, } n->s = c->s; n->c = c; - list_add(&c->namespaces, &n->entry); + list_add_tail(&c->namespaces, &n->entry); return 0; } @@ -2658,7 +2785,7 @@ static void nvme_subsystem_set_ns_path(nvme_subsystem_t s, nvme_ns_t n) if (ret != 3) continue; if (ns_ctrl == p_subsys && ns_nsid == p_nsid) { - list_add(&n->paths, &p->nentry); + list_add_tail(&n->paths, &p->nentry); p->n = n; } } @@ -2696,7 +2823,7 @@ static int nvme_subsystem_scan_namespace(nvme_root_t r, nvme_subsystem_t s, __nvme_free_ns(_n); } n->s = s; - list_add(&s->namespaces, &n->entry); + list_add_tail(&s->namespaces, &n->entry); nvme_subsystem_set_ns_path(s, n); return 0; } |