]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
add path to nvme list
authorTomasz Zawadzki <tomasz.zawadzki@intel.com>
Mon, 29 Jun 2020 13:04:18 +0000 (09:04 -0400)
committerKeith Busch <kbusch@kernel.org>
Thu, 14 Jan 2021 21:50:08 +0000 (14:50 -0700)
In SPDK project (spdk.io) it is possible to represent
devices using CUSE as character devices in "/dev/spdk/" directory.
No sysfs entries are generated for those devices.

nvme-cli default behavior is to scan the sysfs for entries on
newer kernels. Previously legacy_list() was used to determine
the topology, but that worked only on "/dev/" path.

To enable listing SPDK devices following changes were made:
- pass path parameter to list command
- before checking sysfs, check the path using legacy_list()
- expand arguments of scan_subsystems and related functions to accept the path

Example:
nvme list -d /dev/spdk/

Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
fabrics.c
nvme-print.c
nvme-topology.c
nvme.c
nvme.h

index f8a055b7d9ba041c377bfcd5cf9807be31f9790a..87e6b57e30e6265c321f20b5016df073b8ac03d8 100644 (file)
--- a/fabrics.c
+++ b/fabrics.c
@@ -1687,7 +1687,7 @@ int fabrics_disconnect_all(const char *desc, int argc, char **argv)
        if (err)
                goto out;
 
-       err = scan_subsystems(&t, NULL, 0);
+       err = scan_subsystems(&t, NULL, 0, NULL);
        if (err) {
                fprintf(stderr, "Failed to scan namespaces\n");
                goto out;
index e7eac50e1ed0cac79d6e68f920ed1d51c480615e..ccb2f5a4f837bbe949dbb13408ce10279b7ace2b 100644 (file)
@@ -2334,7 +2334,7 @@ void nvme_show_relatives(const char *name)
                        free(path);
                        return;
                }
-               err = scan_subsystems(&t, subsysnqn, 0);
+               err = scan_subsystems(&t, subsysnqn, 0, NULL);
                if (err || t.nr_subsystems != 1) {
                        free(subsysnqn);
                        free(path);
@@ -5404,7 +5404,7 @@ static void nvme_show_list_item(struct nvme_namespace *n)
        struct stat st;
        int ret;
 
-       sprintf(path, "/dev/%s", n->name);
+       sprintf(path, "%s%s", n->ctrl->path, n->name);
        ret = stat(path, &st);
        if (ret < 0)
                return;
@@ -5413,7 +5413,7 @@ static void nvme_show_list_item(struct nvme_namespace *n)
                nsze, s_suffix);
        sprintf(format,"%3.0f %2sB + %2d B", (double)lba, l_suffix,
                le16_to_cpu(n->ns.lbaf[(n->ns.flbas & 0x0f)].ms));
-       printf("/dev/%-11s %-*.*s %-*.*s %-9d %-26s %-16s %-.*s\n", n->name,
+       printf("%-21s %-*.*s %-*.*s %-9d %-26s %-16s %-.*s\n", path,
                (int)sizeof(n->ctrl->id.sn), (int)sizeof(n->ctrl->id.sn), n->ctrl->id.sn,
                (int)sizeof(n->ctrl->id.mn), (int)sizeof(n->ctrl->id.mn), n->ctrl->id.mn,
                n->nsid, usage, format, (int)sizeof(n->ctrl->id.fr), n->ctrl->id.fr);
@@ -5423,9 +5423,9 @@ static void nvme_show_simple_list(struct nvme_topology *t)
 {
        int i, j, k;
 
-       printf("%-16s %-20s %-40s %-9s %-26s %-16s %-8s\n",
+       printf("%-21s %-20s %-40s %-9s %-26s %-16s %-8s\n",
            "Node", "SN", "Model", "Namespace", "Usage", "Format", "FW Rev");
-       printf("%-.16s %-.20s %-.40s %-.9s %-.26s %-.16s %-.8s\n", dash, dash,
+       printf("%-.21s %-.20s %-.40s %-.9s %-.26s %-.16s %-.8s\n", dash, dash,
                dash, dash, dash, dash, dash);
 
        for (i = 0; i < t->nr_subsystems; i++) {
@@ -5672,7 +5672,7 @@ static void json_simple_ns(struct nvme_namespace *n, struct json_array *devices)
        long long lba;
        char *devnode;
 
-       if (asprintf(&devnode, "/dev/%s", n->name) < 0)
+       if (asprintf(&devnode, "%s%s", n->ctrl->path, n->name) < 0)
                return;
 
        device_attrs = json_create_object();
index 94a4c563d4751cac6bb74fc7e7d56508f5ed0d73..202a808763f39063b7c7c54d0e95642765f68587 100644 (file)
@@ -144,7 +144,7 @@ static int scan_namespace(struct nvme_namespace *n)
        int ret, fd;
        char *path;
 
-       ret = asprintf(&path, "%s%s", dev, n->name);
+       ret = asprintf(&path, "%s%s", n->ctrl->path, n->name);
        if (ret < 0)
                return ret;
 
@@ -295,7 +295,7 @@ static int scan_ctrl(struct nvme_ctrl *c, char *p, __u32 ns_instance)
        free(ns);
        free(path);
 
-       ret = asprintf(&path, "%s%s", dev, c->name);
+       ret = asprintf(&path, "%s%s", c->path, c->name);
        if (ret < 0)
                return ret;
 
@@ -338,6 +338,7 @@ static int scan_subsystem(struct nvme_subsystem *s, __u32 ns_instance)
        for (i = 0; i < s->nr_ctrls; i++) {
                c = &s->ctrls[i];
                c->name = strdup(ctrls[i]->d_name);
+               c->path = strdup(dev);
                c->subsys = s;
                scan_ctrl(c, path, ns_instance);
        }
@@ -381,7 +382,7 @@ static int verify_legacy_ns(struct nvme_namespace *n)
        char *path;
        int ret, fd;
 
-       ret = asprintf(&path, "%s%s", dev, n->name);
+       ret = asprintf(&path, "%s%s", n->ctrl->path, n->name);
        if (ret < 0)
                return ret;
 
@@ -420,7 +421,7 @@ static int verify_legacy_ns(struct nvme_namespace *n)
  * is the controller to nvme0n1 for such older kernels. We will also assume
  * every controller is its own subsystem.
  */
-static int legacy_list(struct nvme_topology *t)
+static int legacy_list(struct nvme_topology *t, char *dev_dir)
 {
        struct nvme_ctrl *c;
        struct nvme_subsystem *s;
@@ -429,7 +430,7 @@ static int legacy_list(struct nvme_topology *t)
        int ret = 0, fd, i;
        char *path;
 
-       t->nr_subsystems = scandir(dev, &devices, scan_ctrls_filter, alphasort);
+       t->nr_subsystems = scandir(dev_dir, &devices, scan_ctrls_filter, alphasort);
        if (t->nr_subsystems < 0) {
                fprintf(stderr, "no NVMe device(s) detected.\n");
                return t->nr_subsystems;
@@ -449,7 +450,8 @@ static int legacy_list(struct nvme_topology *t)
                c = s->ctrls;
                c->name = strdup(s->name);
                sscanf(c->name, "nvme%d", &current_index);
-               c->nr_namespaces = scandir(dev, &namespaces, scan_dev_filter,
+               c->path = strdup(dev_dir);
+               c->nr_namespaces = scandir(c->path, &namespaces, scan_dev_filter,
                                           alphasort);
                c->namespaces = calloc(c->nr_namespaces, sizeof(*n));
                if (!c->namespaces) {
@@ -459,7 +461,7 @@ static int legacy_list(struct nvme_topology *t)
                        continue;
                }
 
-               ret = asprintf(&path, "%s%s", dev, c->name);
+               ret = asprintf(&path, "%s%s", c->path, c->name);
                if (ret < 0)
                        continue;
                ret = 0;
@@ -501,6 +503,7 @@ static void free_ctrl(struct nvme_ctrl *c)
                free(n->name);
        }
        free(c->name);
+       free(c->path);
        free(c->transport);
        free(c->address);
        free(c->state);
@@ -527,16 +530,19 @@ static void free_subsystem(struct nvme_subsystem *s)
 }
 
 int scan_subsystems(struct nvme_topology *t, const char *subsysnqn,
-                   __u32 ns_instance)
+                   __u32 ns_instance, char *dev_dir)
 {
        struct nvme_subsystem *s;
        struct dirent **subsys;
        int i, j = 0;
 
+       if (dev_dir != NULL)
+               return legacy_list(t, dev_dir);
+
        t->nr_subsystems = scandir(subsys_dir, &subsys, scan_subsys_filter,
                                   alphasort);
        if (t->nr_subsystems < 0)
-               return legacy_list(t);
+               return legacy_list(t, (char *)dev);
 
        t->subsystems = calloc(t->nr_subsystems, sizeof(*s));
        for (i = 0; i < t->nr_subsystems; i++) {
diff --git a/nvme.c b/nvme.c
index f84eef10cdc85fc5c311bc102c881d2d13f2dab4..d84b6774f3db0afe4aa48c7b9fa9dc9220dc6e38 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -1589,7 +1589,7 @@ static int list_subsys(int argc, char **argv, struct command *cmd,
        if (cfg.verbose)
                flags |= VERBOSE;
 
-       err = scan_subsystems(&t, subsysnqn, ns_instance);
+       err = scan_subsystems(&t, subsysnqn, ns_instance, NULL);
        if (err) {
                fprintf(stderr, "Failed to scan namespaces\n");
                goto free;
@@ -1606,22 +1606,26 @@ ret:
 static int list(int argc, char **argv, struct command *cmd, struct plugin *plugin)
 {
        const char *desc = "Retrieve basic information for all NVMe namespaces";
+       const char *device_dir = "Directory to search for devices";
        const char *verbose = "Increase output verbosity";
        struct nvme_topology t = { };
        enum nvme_print_flags flags;
        int err = 0;
 
        struct config {
+               char *device_dir;
                char *output_format;
                int verbose;
        };
 
        struct config cfg = {
+               .device_dir = NULL,
                .output_format = "normal",
                .verbose = 0,
        };
 
        OPT_ARGS(opts) = {
+               OPT_STRING("directory",  'd', "DIR",             &cfg.device_dir, device_dir),
                OPT_FMT("output-format", 'o', &cfg.output_format, output_format_no_binary),
                OPT_FLAG("verbose",      'v', &cfg.verbose,       verbose),
                OPT_END()
@@ -1641,7 +1645,7 @@ static int list(int argc, char **argv, struct command *cmd, struct plugin *plugi
        if (cfg.verbose)
                flags |= VERBOSE;
 
-       err = scan_subsystems(&t, NULL, 0);
+       err = scan_subsystems(&t, NULL, 0, cfg.device_dir);
        if (err) {
                fprintf(stderr, "Failed to scan namespaces\n");
                return err;
diff --git a/nvme.h b/nvme.h
index 9a54bdb1b941dcab07329eeda796ec33dde7bf9c..3fb1060760ee5008d711403f232e7f98d5d26b42 100644 (file)
--- a/nvme.h
+++ b/nvme.h
@@ -47,6 +47,7 @@ struct nvme_namespace {
 
 struct nvme_ctrl {
        char *name;
+       char *path;
        struct nvme_subsystem *subsys;
 
        char *address;
@@ -105,7 +106,7 @@ int scan_subsys_filter(const struct dirent *d);
 int scan_dev_filter(const struct dirent *d);
 
 int scan_subsystems(struct nvme_topology *t, const char *subsysnqn,
-                   __u32 ns_instance);
+                   __u32 ns_instance, char *dev_dir);
 void free_topology(struct nvme_topology *t);
 char *get_nvme_subsnqn(char *path);
 char *nvme_get_ctrl_attr(char *path, const char *attr);