/* global, used for controller specific namespace filter */
int current_index;
+int scan_ctrl_namespace_filter(const struct dirent *d)
+{
+ int c, i, n;
+
+ if (d->d_name[0] == '.')
+ return 0;
+
+ if (strstr(d->d_name, "nvme")) {
+ if (sscanf(d->d_name, "nvme%dc%dn%d", &i, &c, &n) == 3)
+ return 1;
+ if (sscanf(d->d_name, "nvme%dn%d", &i, &n) == 2)
+ return 1;
+ }
+ return 0;
+}
+
int scan_namespace_filter(const struct dirent *d)
{
int i, n;
#include <string.h>
#include <stdlib.h>
#include <time.h>
+#include <sys/stat.h>
#include "nvme-print.h"
#include "util/json.h"
const char *l_suffix = suffix_binary_get(&lba);
char usage[128];
- char format[128];
+ char format[128], path[256];
+ struct stat st;
+ int ret;
+
+ sprintf(path, "/dev/%s", n->name);
+ ret = stat(path, &st);
+ if (ret < 0)
+ return;
sprintf(usage,"%6.2f %2sB / %6.2f %2sB", nuse, u_suffix,
nsze, s_suffix);
printf("%s", n->ctrl->name);
else {
struct nvme_subsystem *s = n->ctrl->subsys;
- int i;
+ int i, j;
+ bool comma = false;
+
+ for (i = 0; i < s->nr_ctrls; i++) {
+ struct nvme_ctrl *c = &s->ctrls[i];
- for (i = 0; i < s->nr_ctrls; i++)
- printf("%s%s", i ? ", " : "", s->ctrls[i].name);
+ for (j = 0; j < c->nr_namespaces; j++) {
+ struct nvme_namespace *ns = &c->namespaces[j];
+
+ if (ns->nsid == n->nsid) {
+ printf("%s%s", comma ? ", " : "",
+ c->name);
+ comma = true;
+ }
+ }
+ }
}
printf("\n");
}
static void nvme_show_detailed_list(struct nvme_topology *t)
{
- int i, j, k;
+ int i, j, k, l;
printf("NVM Express Subsystems\n\n");
printf("%-16s %-96s %-.16s\n", "Subsystem", "Subsystem-NQN", "Controllers");
for (k = 0; k < c->nr_namespaces; k++) {
struct nvme_namespace *n = &c->namespaces[k];
- printf("%s%s", comma ? ", " : "", n->name);
- comma = true;
- }
- for (k = 0; k < s->nr_namespaces; k++) {
- struct nvme_namespace *n = &s->namespaces[k];
- printf("%s%s", comma ? ", " : "", n->name);
- comma = true;
+
+ for (l = 0; l < s->nr_namespaces; l++) {
+ struct nvme_namespace *ns = &s->namespaces[l];
+ if (n->nsid == ns->nsid) {
+ printf("%s%s", comma ? ", " : "", ns->name);
+ comma = true;
+ }
+ }
}
printf("\n");
}
for (i = 0; i < t->nr_subsystems; i++) {
struct nvme_subsystem *s = &t->subsystems[i];
- for (j = 0; j < s->nr_ctrls; j++) {
- struct nvme_ctrl *c = &s->ctrls[j];
+ if (s->nr_namespaces) {
+ for (j = 0; j < s->nr_namespaces; j++) {
+ struct nvme_namespace *n = &s->namespaces[j];
+ nvme_show_details_ns(n, false);
+ }
+ } else {
+ for (j = 0; j < s->nr_ctrls; j++) {
+ struct nvme_ctrl *c = &s->ctrls[j];
- for (k = 0; k < c->nr_namespaces; k++) {
- struct nvme_namespace *n = &c->namespaces[k];
- nvme_show_details_ns(n, true);
+ for (k = 0; k < c->nr_namespaces; k++) {
+ struct nvme_namespace *n = &c->namespaces[k];
+ nvme_show_details_ns(n, true);
+ }
}
}
- for (j = 0; j < s->nr_namespaces; j++) {
- struct nvme_namespace *n = &s->namespaces[j];
- nvme_show_details_ns(n, false);
- }
}
}
if (fd < 0)
goto free;
- n->nsid = nvme_get_nsid(fd);
- if (n->nsid < 0)
- goto close_fd;
+ if (!n->nsid) {
+ n->nsid = nvme_get_nsid(fd);
+ if (n->nsid < 0)
+ goto close_fd;
+ }
ret = nvme_identify_ns(fd, n->nsid, 0, &n->ns);
if (ret < 0)
if (ns_instance)
c->ana_state = get_nvme_ctrl_path_ana_state(path, ns_instance);
- ret = scandir(path, &ns, scan_namespace_filter, alphasort);
+ ret = scandir(path, &ns, scan_ctrl_namespace_filter, alphasort);
if (ret == -1) {
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
return errno;
c->nr_namespaces = ret;
c->namespaces = calloc(c->nr_namespaces, sizeof(*n));
- for (i = 0; i < c->nr_namespaces; i++) {
- n = &c->namespaces[i];
- n->name = strdup(ns[i]->d_name);
- n->ctrl = c;
- scan_namespace(n);
+ if (c->namespaces) {
+ for (i = 0; i < c->nr_namespaces; i++) {
+ char *ns_path, nsid[16];
+ int ns_fd;
+
+ n = &c->namespaces[i];
+ n->name = strdup(ns[i]->d_name);
+ n->ctrl = c;
+ ret = asprintf(&ns_path, "%s/%s/nsid", path, n->name);
+ if (ret < 0)
+ continue;
+ ns_fd = open(ns_path, O_RDONLY);
+ if (ns_fd < 0) {
+ free(ns_path);
+ continue;
+ }
+ ret = read(ns_fd, nsid, 16);
+ if (ret < 0) {
+ close(ns_fd);
+ free(ns_path);
+ continue;
+ }
+ n->nsid = (unsigned)strtol(nsid, NULL, 10);
+ scan_namespace(n);
+ close(ns_fd);
+ free(ns_path);
+ }
+ } else {
+ i = c->nr_namespaces;
+ c->nr_namespaces = 0;
}
while (i--)
s->nr_namespaces = ret;
s->namespaces = calloc(s->nr_namespaces, sizeof(*n));
- for (i = 0; i < s->nr_namespaces; i++) {
- n = &s->namespaces[i];
- n->name = strdup(ns[i]->d_name);
- n->ctrl = &s->ctrls[0];
- scan_namespace(n);
+ if (s->namespaces) {
+ for (i = 0; i < s->nr_namespaces; i++) {
+ n = &s->namespaces[i];
+ n->name = strdup(ns[i]->d_name);
+ n->ctrl = &s->ctrls[0];
+ scan_namespace(n);
+ }
+ } else {
+ i = s->nr_namespaces;
+ s->nr_namespaces = 0;
}
while (i--)
c->nr_namespaces = scandir(dev, &namespaces, scan_dev_filter,
alphasort);
c->namespaces = calloc(c->nr_namespaces, sizeof(*n));
+ if (!c->namespaces) {
+ while (c->nr_namespaces--)
+ free(namespaces[c->nr_namespaces]);
+ free(namespaces);
+ continue;
+ }
ret = asprintf(&path, "%s%s", dev, c->name);
if (ret < 0)