From 61d0a8bdffbbb7229776d2f4f2e79ed22d21551f Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 1 Jul 2023 00:36:10 +0200 Subject: Merging upstream version 1.5. Signed-off-by: Daniel Baumann --- src/nvme/tree.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 135 insertions(+), 6 deletions(-) (limited to 'src/nvme/tree.c') diff --git a/src/nvme/tree.c b/src/nvme/tree.c index 3484463..a2ac069 100644 --- a/src/nvme/tree.c +++ b/src/nvme/tree.c @@ -34,6 +34,8 @@ #include "log.h" #include "private.h" +const char *nvme_slots_sysfs_dir = "/sys/bus/pci/slots"; + static struct nvme_host *default_host; static void __nvme_free_host(nvme_host_t h); @@ -48,6 +50,34 @@ static int nvme_ctrl_scan_namespace(nvme_root_t r, struct nvme_ctrl *c, char *name); static int nvme_ctrl_scan_path(nvme_root_t r, struct nvme_ctrl *c, char *name); +/** + * Compare two C strings and handle NULL pointers gracefully. + * Return true if both pointers are equal (including both set to NULL). + * Return false if one and only one of the two pointers is NULL. + * Perform string comparisong only if both pointers are not NULL and + * return true if both strings are the same, false otherwise. + */ +static bool streq0(const char *s1, const char *s2) +{ + if (s1 == s2) + return true; + if (!s1 || !s2) + return false; + return !strcmp(s1, s2); +} + +/** + * Same as streq0() but ignore the case of the characters. + */ +static bool streqcase0(const char *s1, const char *s2) +{ + if (s1 == s2) + return true; + if (!s1 || !s2) + return false; + return !strcasecmp(s1, s2); +} + static inline void nvme_free_dirents(struct dirent **d, int i) { while (i-- > 0) @@ -197,6 +227,19 @@ int nvme_dump_tree(nvme_root_t r) return json_dump_tree(r); } +const char *nvme_root_get_application(nvme_root_t r) +{ + return r->application; +} + +void nvme_root_set_application(nvme_root_t r, const char *a) +{ + if (r->application) + free(r->application); + if (a) + r->application = strdup(a); +} + nvme_host_t nvme_first_host(nvme_root_t r) { return list_top(&r->hosts, struct nvme_host, entry); @@ -288,10 +331,13 @@ void nvme_free_tree(nvme_root_t r) { struct nvme_host *h, *_h; + 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); free(r); } @@ -315,6 +361,19 @@ const char *nvme_subsystem_get_type(nvme_subsystem_t s) return s->subsystype; } +const char *nvme_subsystem_get_application(nvme_subsystem_t s) +{ + return s->application; +} + +void nvme_subsystem_set_application(nvme_subsystem_t s, const char *a) +{ + if (s->application) + free(s->application); + if (a) + s->application = strdup(a); +} + nvme_ctrl_t nvme_subsystem_first_ctrl(nvme_subsystem_t s) { return list_top(&s->ctrls, struct nvme_ctrl, entry); @@ -390,6 +449,8 @@ static void __nvme_free_subsystem(struct nvme_subsystem *s) free(s->firmware); if (s->subsystype) free(s->subsystype); + if (s->application) + free(s->application); free(s); } @@ -435,6 +496,12 @@ struct nvme_subsystem *nvme_lookup_subsystem(struct nvme_host *h, if (name && s->name && strcmp(s->name, name)) continue; + if (h->r->application) { + if (!s->application) + continue; + if (strcmp(h->r->application, s->application)) + continue; + } return s; } return nvme_alloc_subsystem(h, name, subsysnqn); @@ -541,6 +608,8 @@ static int nvme_init_subsystem(nvme_subsystem_t s, const char *name) } s->name = strdup(name); s->sysfs_dir = (char *)path; + if (s->h->r->application) + s->application = strdup(s->h->r->application); return 0; } @@ -755,6 +824,11 @@ const char *nvme_ctrl_get_address(nvme_ctrl_t c) return c->address ? c->address : ""; } +const char *nvme_ctrl_get_phy_slot(nvme_ctrl_t c) +{ + return c->phy_slot ? c->phy_slot : ""; +} + const char *nvme_ctrl_get_firmware(nvme_ctrl_t c) { return c->firmware; @@ -942,6 +1016,7 @@ void nvme_deconfigure_ctrl(nvme_ctrl_t c) FREE_CTRL_ATTR(c->address); FREE_CTRL_ATTR(c->dctype); FREE_CTRL_ATTR(c->cntrltype); + FREE_CTRL_ATTR(c->phy_slot); } int nvme_disconnect_ctrl(nvme_ctrl_t c) @@ -1072,22 +1147,28 @@ nvme_ctrl_t __nvme_lookup_ctrl(nvme_subsystem_t s, const char *transport, { struct nvme_ctrl *c; + bool (*addreq)(const char *, const char *); + + if (!strcmp(transport, "tcp") || !strcmp(transport, "rdma")) + addreq = nvme_ipaddrs_eq; /* IP address compare for TCP/RDMA */ + else + addreq = streqcase0; /* Case-insensitive for FC (n/a for loop) */ c = p ? nvme_subsystem_next_ctrl(s, p) : nvme_subsystem_first_ctrl(s); for (; c != NULL; c = nvme_subsystem_next_ctrl(s, c)) { - if (strcmp(c->transport, transport)) + if (!streq0(c->transport, transport)) continue; if (traddr && c->traddr && - strcasecmp(c->traddr, traddr)) + !addreq(c->traddr, traddr)) continue; if (host_traddr && c->cfg.host_traddr && - strcmp(c->cfg.host_traddr, host_traddr)) + !addreq(c->cfg.host_traddr, host_traddr)) continue; if (host_iface && c->cfg.host_iface && - strcmp(c->cfg.host_iface, host_iface)) + !streq0(c->cfg.host_iface, host_iface)) continue; if (trsvcid && c->trsvcid && - strcmp(c->trsvcid, trsvcid)) + !streq0(c->trsvcid, trsvcid)) continue; return c; } @@ -1183,6 +1264,53 @@ static char *nvme_ctrl_lookup_subsystem_name(nvme_root_t r, return subsys_name; } +static char *nvme_ctrl_lookup_phy_slot(nvme_root_t r, const char *address) +{ + char *target_addr; + char *addr; + char *path; + int found = 0; + int ret; + DIR *slots_dir; + struct dirent *entry; + + if (!address) + return NULL; + + slots_dir = opendir(nvme_slots_sysfs_dir); + if (!slots_dir) { + nvme_msg(r, LOG_WARNING, "failed to open slots dir %s\n", + nvme_slots_sysfs_dir); + return NULL; + } + + target_addr = strndup(address, 10); + while (!(entry = readdir(slots_dir))) { + if (entry->d_type == DT_DIR && + strncmp(entry->d_name, ".", 1) != 0 && + strncmp(entry->d_name, "..", 2) != 0) { + ret = asprintf(&path, "/sys/bus/pci/slots/%s", entry->d_name); + if (ret < 0) { + errno = ENOMEM; + return NULL; + } + addr = nvme_get_attr(path, "address"); + if (strcmp(addr, target_addr) == 0) { + found = 1; + free(path); + free(addr); + break; + } + free(path); + free(addr); + } + } + free(target_addr); + if (found) + return strdup(entry->d_name); + return NULL; +} + static int nvme_configure_ctrl(nvme_root_t r, nvme_ctrl_t c, const char *path, const char *name) { @@ -1224,6 +1352,7 @@ static int nvme_configure_ctrl(nvme_root_t r, nvme_ctrl_t c, const char *path, } c->cntrltype = nvme_get_ctrl_attr(c, "cntrltype"); c->dctype = nvme_get_ctrl_attr(c, "dctype"); + c->phy_slot = nvme_ctrl_lookup_phy_slot(r, c->address); errno = 0; /* cleanup after nvme_get_ctrl_attr() */ return 0; @@ -1481,7 +1610,7 @@ static int nvme_bytes_to_lba(nvme_ns_t n, off_t offset, size_t count, int bs; bs = nvme_ns_get_lba_size(n); - if (!count || offset & bs || count & bs) { + if (!count || offset & (bs - 1) || count & (bs - 1)) { errno = EINVAL; return -1; } -- cgit v1.2.3