Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.6:Update
nvme-cli.26914
0019-nvme-Add-show-topology-command.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0019-nvme-Add-show-topology-command.patch of Package nvme-cli.26914
From 1158f9d91049edb6b32c7a620e6280a202a2a3e7 Mon Sep 17 00:00:00 2001 From: Daniel Wagner <dwagner@suse.de> Date: Mon, 26 Sep 2022 18:17:01 +0200 Subject: [PATCH] nvme: Add show-topology command Add nvme show-topology which displays the entire nvme topology on the host - all the subsystems with all the underlying controllers and its states including ANA for all nvme devices. Signed-off-by: Daniel Wagner <dwagner@suse.de> --- nvme-builtin.h | 3 nvme-print.c | 244 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ nvme-print.h | 2 nvme.c | 70 ++++++++++++++++ nvme.h | 5 + 5 files changed, 323 insertions(+), 1 deletion(-) --- a/nvme-builtin.h +++ b/nvme-builtin.h @@ -104,7 +104,8 @@ COMMAND_LIST( ENTRY("virt-mgmt", "Manage Flexible Resources between Primary and Secondary Controller ", virtual_mgmt) ENTRY("rpmb", "Replay Protection Memory Block commands", rpmb_cmd) ENTRY("lockdown", "Submit a Lockdown command,return result", lockdown_cmd) - ENTRY("dim", "Send Discovery Information Management command to a Discovery Controller", dim_cmd) + ENTRY("dim", "Send Discovery Information Management command to a Discovery Controller", dim_cmd) \ + ENTRY("show-topology", "Show the topology", show_topology_cmd) \ ); #endif --- a/nvme.c +++ b/nvme.c @@ -7916,6 +7916,76 @@ static int check_tls_key(int argc, char return 0; } +static int show_topology_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) +{ + const char *desc = "Show the topolog\n"; + const char *verbose = "Increase output verbosity"; + const char *ranking = "Ranking order: namespace|ctrl"; + enum nvme_print_flags flags; + nvme_root_t r; + enum nvme_cli_topo_ranking rank; + int err; + + struct config { + char *output_format; + int verbose; + char *ranking; + }; + + struct config cfg = { + .output_format = "normal", + .verbose = 0, + .ranking = "namespace", + }; + + OPT_ARGS(opts) = { + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_INCR("verbose", 'v', &cfg.verbose, verbose), + OPT_FMT("ranking", 'r', &cfg.ranking, ranking), + OPT_END() + }; + + err = argconfig_parse(argc, argv, desc, opts); + if (err) + return err; + + err = flags = validate_output_format(cfg.output_format); + if (flags < 0) + return err; + if (cfg.verbose) + flags |= VERBOSE; + + if (!strcmp(cfg.ranking, "namespace")) + rank = NVME_CLI_TOPO_NAMESPACE; + else if (!strcmp(cfg.ranking, "ctrl")) + rank = NVME_CLI_TOPO_CTRL; + else { + fprintf(stderr, "Invalid ranking argument: %s\n", + cfg.ranking); + return -EINVAL; + } + + r = nvme_create_root(stderr, map_log_level(cfg.verbose, false)); + if (!r) { + fprintf(stderr, "Failed to create topology root: %s\n", + nvme_strerror(errno)); + return -errno; + } + + err = nvme_scan_topology(r, NULL, NULL); + if (err < 0) { + fprintf(stderr, "Failed to scan topology: %s\n", + nvme_strerror(errno)); + nvme_free_tree(r); + return err; + } + + nvme_show_topology(r, flags, rank); + nvme_free_tree(r); + + return err; +} + static int discover_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Send Get Log Page request to Discovery Controller."; --- a/nvme.h +++ b/nvme.h @@ -73,6 +73,11 @@ enum nvme_print_flags { BINARY = 1 << 3, /* binary dump raw bytes */ }; +enum nvme_cli_topo_ranking { + NVME_CLI_TOPO_NAMESPACE, + NVME_CLI_TOPO_CTRL, +}; + #define SYS_NVME "/sys/class/nvme" void register_extension(struct plugin *plugin); --- a/nvme-print.c +++ b/nvme-print.c @@ -7487,3 +7487,247 @@ void nvme_show_list_items(nvme_root_t r, else nvme_show_simple_list(r); } + +static unsigned int json_subsystem_topology_multipath(nvme_subsystem_t s, + json_object *namespaces) +{ + nvme_ns_t n; + nvme_path_t p; + unsigned int i = 0; + + nvme_subsystem_for_each_ns(s, n) { + struct json_object *ns_attrs; + struct json_object *paths; + + ns_attrs = json_create_object(); + json_object_add_value_int(ns_attrs, "NSID", + nvme_ns_get_nsid(n)); + + paths = json_create_array(); + nvme_namespace_for_each_path(n, p) { + struct json_object *path_attrs; + + nvme_ctrl_t c = nvme_path_get_ctrl(p); + + path_attrs = json_create_object(); + json_object_add_value_string(path_attrs, "Name", + nvme_ctrl_get_name(c)); + json_object_add_value_string(path_attrs, "Transport", + nvme_ctrl_get_transport(c)); + json_object_add_value_string(path_attrs, "Address", + nvme_ctrl_get_address(c)); + json_object_add_value_string(path_attrs, "State", + nvme_ctrl_get_state(c)); + json_object_add_value_string(path_attrs, "ANAState", + nvme_path_get_ana_state(p)); + json_array_add_value_object(paths, path_attrs); + } + json_object_add_value_array(ns_attrs, "Paths", paths); + json_array_add_value_object(namespaces, ns_attrs); + i++; + } + + return i; +} + +static void json_print_nvme_subsystem_topology(nvme_subsystem_t s, + json_object *namespaces) +{ + nvme_ctrl_t c; + nvme_ns_t n; + + nvme_subsystem_for_each_ctrl(s, c) { + nvme_ctrl_for_each_ns(c, n) { + struct json_object *ctrl_attrs; + struct json_object *ns_attrs; + struct json_object *ctrl; + + ns_attrs = json_create_object(); + json_object_add_value_int(ns_attrs, "NSID", + nvme_ns_get_nsid(n)); + + ctrl = json_create_array(); + ctrl_attrs = json_create_object(); + json_object_add_value_string(ctrl_attrs, "Name", + nvme_ctrl_get_name(c)); + json_object_add_value_string(ctrl_attrs, "Transport", + nvme_ctrl_get_transport(c)); + json_object_add_value_string(ctrl_attrs, "Address", + nvme_ctrl_get_address(c)); + json_object_add_value_string(ctrl_attrs, "State", + nvme_ctrl_get_state(c)); + + json_array_add_value_object(ctrl, ctrl_attrs); + json_object_add_value_array(ns_attrs, "Controller", ctrl); + json_array_add_value_object(namespaces, ns_attrs); + } + } +} + +static void json_simple_topology(nvme_root_t r) +{ + struct json_object *host_attrs, *subsystem_attrs; + struct json_object *subsystems, *namespaces; + struct json_object *root; + nvme_host_t h; + + root = json_create_array(); + + nvme_for_each_host(r, h) { + nvme_subsystem_t s; + const char *hostid; + + host_attrs = json_create_object(); + json_object_add_value_string(host_attrs, "HostNQN", + nvme_host_get_hostnqn(h)); + hostid = nvme_host_get_hostid(h); + if (hostid) + json_object_add_value_string(host_attrs, "HostID", hostid); + subsystems = json_create_array(); + nvme_for_each_subsystem(h, s) { + subsystem_attrs = json_create_object(); + json_object_add_value_string(subsystem_attrs, "Name", + nvme_subsystem_get_name(s)); + json_object_add_value_string(subsystem_attrs, "NQN", + nvme_subsystem_get_nqn(s)); + + json_array_add_value_object(subsystems, subsystem_attrs); + namespaces = json_create_array(); + + if (!json_subsystem_topology_multipath(s, namespaces)) + json_print_nvme_subsystem_topology(s, namespaces); + + json_object_add_value_array(subsystem_attrs, "Namespaces", + namespaces); + } + json_object_add_value_array(host_attrs, "Subsystems", subsystems); + json_array_add_value_object(root, host_attrs); + } + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +static bool nvme_is_multipath(nvme_subsystem_t s) +{ + nvme_ns_t n; + nvme_path_t p; + + nvme_subsystem_for_each_ns(s, n) + nvme_namespace_for_each_path(n, p) + return true; + + return false; +} + +static void nvme_show_subsystem_topology_multipath(nvme_subsystem_t s, + enum nvme_cli_topo_ranking ranking) +{ + nvme_ns_t n; + nvme_path_t p; + nvme_ctrl_t c; + + if (ranking == NVME_CLI_TOPO_NAMESPACE) { + nvme_subsystem_for_each_ns(s, n) { + printf(" +- ns %d\n", nvme_ns_get_nsid(n)); + printf(" \\\n"); + + nvme_namespace_for_each_path(n, p) { + c = nvme_path_get_ctrl(p); + + printf(" +- %s %s %s %s %s\n", + nvme_ctrl_get_name(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c), + nvme_ctrl_get_state(c), + nvme_path_get_ana_state(p)); + } + } + } else { + /* NVME_CLI_TOPO_CTRL */ + nvme_subsystem_for_each_ctrl(s, c) { + printf(" +- %s %s %s\n", + nvme_ctrl_get_name(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c)); + printf(" \\\n"); + + nvme_subsystem_for_each_ns(s, n) { + nvme_namespace_for_each_path(n, p) { + if (nvme_path_get_ctrl(p) != c) + continue; + + printf(" +- ns %d %s %s\n", + nvme_ns_get_nsid(n), + nvme_ctrl_get_state(c), + nvme_path_get_ana_state(p)); + } + } + } + } +} + +static void nvme_show_subsystem_topology(nvme_subsystem_t s, + enum nvme_cli_topo_ranking ranking) +{ + nvme_ctrl_t c; + nvme_ns_t n; + + if (ranking == NVME_CLI_TOPO_NAMESPACE) { + nvme_subsystem_for_each_ctrl(s, c) { + nvme_ctrl_for_each_ns(c, n) { + printf(" +- ns %d\n", nvme_ns_get_nsid(n)); + printf(" \\\n"); + printf(" +- %s %s %s %s\n", + nvme_ctrl_get_name(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c), + nvme_ctrl_get_state(c)); + } + } + } else { + /* NVME_CLI_TOPO_CTRL */ + nvme_subsystem_for_each_ctrl(s, c) { + printf(" +- %s %s %s\n", + nvme_ctrl_get_name(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c)); + printf(" \\\n"); + nvme_ctrl_for_each_ns(c, n) { + printf(" +- ns %d %s\n", + nvme_ns_get_nsid(n), + nvme_ctrl_get_state(c)); + } + } + } +} + +static void nvme_show_simple_topology(nvme_root_t r, + enum nvme_cli_topo_ranking ranking) +{ + nvme_host_t h; + nvme_subsystem_t s; + + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + + printf("%s - NQN=%s\n", nvme_subsystem_get_name(s), + nvme_subsystem_get_nqn(s)); + printf("\\\n"); + + if (nvme_is_multipath(s)) + nvme_show_subsystem_topology_multipath(s, ranking); + else + nvme_show_subsystem_topology(s, ranking); + } + } +} + +void nvme_show_topology(nvme_root_t r, enum nvme_print_flags flags, + enum nvme_cli_topo_ranking ranking) +{ + if (flags & JSON) + json_simple_topology(r); + else + nvme_show_simple_topology(r, ranking); +} --- a/nvme-print.h +++ b/nvme-print.h @@ -107,6 +107,8 @@ void nvme_show_endurance_group_list(stru enum nvme_print_flags flags); void nvme_show_list_ns(struct nvme_ns_list *ns_list, enum nvme_print_flags flags); +void nvme_show_topology(nvme_root_t t, enum nvme_print_flags flags, + enum nvme_cli_topo_ranking ranking); void nvme_feature_show_fields(enum nvme_features_id fid, unsigned int result, unsigned char *buf); void nvme_directive_show(__u8 type, __u8 oper, __u16 spec, __u32 nsid, __u32 result,
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