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;
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);
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;
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);
{
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++) {
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();
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;
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;
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);
}
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;
* 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;
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;
c = s->ctrls;
c->name = strdup(s->name);
sscanf(c->name, "nvme%d", ¤t_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) {
continue;
}
- ret = asprintf(&path, "%s%s", dev, c->name);
+ ret = asprintf(&path, "%s%s", c->path, c->name);
if (ret < 0)
continue;
ret = 0;
free(n->name);
}
free(c->name);
+ free(c->path);
free(c->transport);
free(c->address);
free(c->state);
}
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++) {
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;
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()
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;
struct nvme_ctrl {
char *name;
+ char *path;
struct nvme_subsystem *subsys;
char *address;
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);