Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:15
nvme-cli.11415
0033-nvme-list-subsys-Add-device-name-argument-...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0033-nvme-list-subsys-Add-device-name-argument-and-print-.patch of Package nvme-cli.11415
From: Hannes Reinecke <hare@suse.de> Date: Fri, 27 Jul 2018 11:46:07 +0200 Subject: [PATCH] nvme-list-subsys: Add device name argument and print out ANA state References: bsc#1099018 Git-commit: 00aeb9226e7ad2a2f4952c18f4ee52a32dc19f03 Update the 'nvme list-subsys' command to accept a device name and print out the ANA state for all paths to that device. Signed-off-by: Hannes Reinecke <hare@suse.com> --- Documentation/nvme-list-subsys.txt | 4 +- nvme-print.c | 10 ++- nvme.c | 137 +++++++++++++++++++++++++++++++++++-- nvme.h | 3 +- 4 files changed, 143 insertions(+), 11 deletions(-) diff --git a/Documentation/nvme-list-subsys.txt b/Documentation/nvme-list-subsys.txt index c7de7ef..c40b708 100644 --- a/Documentation/nvme-list-subsys.txt +++ b/Documentation/nvme-list-subsys.txt @@ -8,12 +8,14 @@ nvme-list-subsys - List all NVMe subsystems SYNOPSIS -------- [verse] -'nvme list-subsys' [-o <fmt> | --output-format=<fmt>] +'nvme list-subsys' [-o <fmt> | --output-format=<fmt>] <device> DESCRIPTION ----------- Scan the sysfs tree for NVM Express subsystems and return the controllers for those subsystems as well as some pertinent information about them. +If a device is given, print out only the values for the controllers +and subsystems leading to the device. OPTIONS ------- diff --git a/nvme-print.c b/nvme-print.c index 156b48f..91881e0 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -2121,10 +2121,12 @@ static void show_nvme_subsystem(struct subsys_list_item *item) printf("\\\n"); for (i = 0; i < item->nctrls; i++) { - printf(" +- %s %s %s %s\n", item->ctrls[i].name, + printf(" +- %s %s %s %s %s\n", item->ctrls[i].name, item->ctrls[i].transport, item->ctrls[i].address, - item->ctrls[i].state); + item->ctrls[i].state, + item->ctrls[i].ana_state ? + item->ctrls[i].ana_state : ""); } } @@ -2172,6 +2174,10 @@ void json_print_nvme_subsystem_list(struct subsys_list_item *slist, int n) slist[i].ctrls[j].address); json_object_add_value_string(path_attrs, "State", slist[i].ctrls[j].state); + if (slist[i].ctrls[j].ana_state) + json_object_add_value_string(path_attrs, + "ANAState", + slist[i].ctrls[j].ana_state); json_array_add_value_object(paths, path_attrs); } if (j) { diff --git a/nvme.c b/nvme.c index 7d58500..e748204 100644 --- a/nvme.c +++ b/nvme.c @@ -1017,6 +1017,85 @@ err_free_path: return NULL; } +static int scan_ctrl_paths_filter(const struct dirent *d) +{ + int id, cntlid, nsid; + + if (d->d_name[0] == '.') + return 0; + + if (strstr(d->d_name, "nvme")) { + if (sscanf(d->d_name, "nvme%dc%dn%d", &id, &cntlid, &nsid) == 3) + return 1; + if (sscanf(d->d_name, "nvme%dn%d", &id, &nsid) == 2) + return 1; + } + + return 0; +} + +static char *get_nvme_ctrl_path_ana_state(char *path, int nsid) +{ + struct dirent **paths; + char *ana_state; + int i, n; + + ana_state = calloc(1, 16); + if (!ana_state) + return NULL; + + n = scandir(path, &paths, scan_ctrl_paths_filter, alphasort); + if (n <= 0) { + free(ana_state); + return NULL; + } + for (i = 0; i < n; i++) { + int id, cntlid, ns, fd; + ssize_t ret; + char *ctrl_path; + + if (sscanf(paths[i]->d_name, "nvme%dc%dn%d", + &id, &cntlid, &ns) != 3) { + if (sscanf(paths[i]->d_name, "nvme%dn%d", + &id, &ns) != 2) { + continue; + } + } + if (ns != nsid) + continue; + + ret = asprintf(&ctrl_path, "%s/%s/ana_state", + path, paths[i]->d_name); + if (ret < 0) { + free(ana_state); + ana_state = NULL; + break; + } + fd = open(ctrl_path, O_RDONLY); + if (fd < 0) { + free(ctrl_path); + free(ana_state); + ana_state = NULL; + break; + } + ret = read(fd, ana_state, 16); + if (ret < 0) { + fprintf(stderr, "Failed to read ANA state from %s\n", + ctrl_path); + free(ana_state); + ana_state = NULL; + } else if (ana_state[strlen(ana_state) - 1] == '\n') + ana_state[strlen(ana_state) - 1] = '\0'; + close(fd); + free(ctrl_path); + break; + } + for (i = 0; i < n; i++) + free(paths[i]); + free(paths); + return ana_state; +} + static int scan_ctrls_filter(const struct dirent *d) { int id, nsid; @@ -1039,10 +1118,11 @@ static void free_ctrl_list_item(struct ctrl_list_item *ctrls) free(ctrls->transport); free(ctrls->address); free(ctrls->state); + free(ctrls->ana_state); } -int get_nvme_subsystem_info(char *name, char *path, - struct subsys_list_item *item) +static int get_nvme_subsystem_info(char *name, char *path, + struct subsys_list_item *item, __u32 nsid) { char ctrl_path[512]; struct dirent **ctrls; @@ -1100,6 +1180,9 @@ int get_nvme_subsystem_info(char *name, char *path, continue; } + if (nsid != NVME_NSID_ALL) + item->ctrls[ccnt].ana_state = + get_nvme_ctrl_path_ana_state(ctrl_path, nsid); ccnt++; } @@ -1164,7 +1247,8 @@ void free_subsys_list(struct subsys_list_item *slist, int n) free(slist); } -struct subsys_list_item *get_subsys_list(int *subcnt) +struct subsys_list_item *get_subsys_list(int *subcnt, char *subsysnqn, + __u32 nsid) { char path[310]; struct dirent **subsys; @@ -1185,13 +1269,16 @@ struct subsys_list_item *get_subsys_list(int *subcnt) snprintf(path, sizeof(path), "%s%s", subsys_dir, subsys[i]->d_name); ret = get_nvme_subsystem_info(subsys[i]->d_name, path, - &slist[*subcnt]); + &slist[*subcnt], nsid); if (ret) { fprintf(stderr, "%s: failed to get subsystem info: %s\n", path, strerror(errno)); free_subsys_list_item(&slist[*subcnt]); - } else + } else if (subsysnqn && + strncmp(slist[*subcnt].subsysnqn, subsysnqn, 255)) + free_subsys_list_item(&slist[*subcnt]); + else (*subcnt)++; } @@ -1208,12 +1295,15 @@ static int list_subsys(int argc, char **argv, struct command *cmd, { struct subsys_list_item *slist; int fmt, ret, subcnt = 0; + char *subsysnqn = NULL; const char *desc = "Retrieve information for subsystems"; struct config { + __u32 namespace_id; char *output_format; }; struct config cfg = { + .namespace_id = NVME_NSID_ALL, .output_format = "normal", }; @@ -1227,11 +1317,42 @@ static int list_subsys(int argc, char **argv, struct command *cmd, if (ret < 0) return ret; + devicename = NULL; + if (optind < argc) { + char path[512]; + int id; + + devicename = basename(argv[optind]); + if (sscanf(devicename, "nvme%dn%d", &id, + &cfg.namespace_id) != 2) { + fprintf(stderr, "%s is not a NVMe namespace device\n", + argv[optind]); + return -EINVAL; + } + sprintf(path, "/sys/block/%s/device", devicename); + subsysnqn = get_nvme_subsnqn(path); + if (!subsysnqn) { + fprintf(stderr, "Cannot read subsys NQN from %s\n", + devicename); + return -EINVAL; + } + optind++; + } + + if (ret < 0) { + argconfig_print_help(desc, opts); + if (subsysnqn) + free(subsysnqn); + return ret; + } fmt = validate_output_format(cfg.output_format); - if (fmt != JSON && fmt != NORMAL) + if (fmt != JSON && fmt != NORMAL) { + if (subsysnqn) + free(subsysnqn); return -EINVAL; + } - slist = get_subsys_list(&subcnt); + slist = get_subsys_list(&subcnt, subsysnqn, cfg.namespace_id); if (fmt == JSON) json_print_nvme_subsystem_list(slist, subcnt); @@ -1239,6 +1360,8 @@ static int list_subsys(int argc, char **argv, struct command *cmd, show_nvme_subsystem_list(slist, subcnt); free_subsys_list(slist, subcnt); + if (subsysnqn) + free(subsysnqn); return ret; } diff --git a/nvme.h b/nvme.h index f363155..e4d58c8 100644 --- a/nvme.h +++ b/nvme.h @@ -122,6 +122,7 @@ struct ctrl_list_item { char *address; char *transport; char *state; + char *ana_state; }; struct subsys_list_item { @@ -148,6 +149,6 @@ extern const char *devicename; int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, void (*vs)(__u8 *vs, struct json_object *root)); int validate_output_format(char *format); -struct subsys_list_item *get_subsys_list(int *subcnt); +struct subsys_list_item *get_subsys_list(int *subcnt, char *subsysnqn, __u32 nsid); void free_subsys_list(struct subsys_list_item *slist, int n); #endif /* _NVME_H */ -- 2.12.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor