summaryrefslogtreecommitdiffstats
path: root/src/nvme/tree.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2023-06-30 22:36:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2023-06-30 22:36:10 +0000
commit61d0a8bdffbbb7229776d2f4f2e79ed22d21551f (patch)
tree2e249969fedce45eb37ae6314ad167595900fe38 /src/nvme/tree.c
parentReleasing debian version 1.4-4. (diff)
downloadlibnvme-61d0a8bdffbbb7229776d2f4f2e79ed22d21551f.tar.xz
libnvme-61d0a8bdffbbb7229776d2f4f2e79ed22d21551f.zip
Merging upstream version 1.5.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/nvme/tree.c')
-rw-r--r--src/nvme/tree.c141
1 files changed, 135 insertions, 6 deletions
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;
}