From 4ed089396bc7f14bcb94e80f0f9f4757fd8c48b7 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 5 Nov 2022 19:23:30 +0100 Subject: Merging upstream version 2.2.1. Signed-off-by: Daniel Baumann --- nvme-print.c | 714 +++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 479 insertions(+), 235 deletions(-) (limited to 'nvme-print.c') diff --git a/nvme-print.c b/nvme-print.c index e92ba82..c27f087 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -6,22 +6,15 @@ #include #include #include -#include #include "nvme.h" #include "libnvme.h" #include "nvme-print.h" #include "nvme-models.h" #include "util/suffix.h" +#include "util/types.h" #include "common.h" -#define ABSOLUTE_ZERO_CELSIUS -273 - -static inline long kelvin_to_celsius(long t) -{ - return t + ABSOLUTE_ZERO_CELSIUS; -} - static const uint8_t zero_uuid[16] = { 0 }; static const uint8_t invalid_uuid[16] = {[0 ... 15] = 0xff }; static const char dash[100] = {[0 ... 99] = '-'}; @@ -35,18 +28,6 @@ struct nvme_bar_cap { __u8 rsvd_crms_nsss_cmbs_pmrs; }; -static long double int128_to_double(__u8 *data) -{ - int i; - long double result = 0; - - for (i = 0; i < 16; i++) { - result *= 256; - result += data[15 - i]; - } - return result; -} - static const char *nvme_ana_state_to_string(enum nvme_ana_state state) { switch (state) { @@ -120,17 +101,6 @@ const char *nvme_cmd_to_string(int admin, __u8 opcode) return "Unknown"; } -static const char *fw_to_string(char *c) -{ - static char ret[9]; - int i; - - for (i = 0; i < 8; i++) - ret[i] = c[i] >= '!' && c[i] <= '~' ? c[i] : '.'; - ret[i] = '\0'; - return ret; -} - static const char *get_sanitize_log_sstat_status_str(__u16 status) { switch (status & NVME_SANITIZE_SSTAT_STATUS_MASK) { @@ -158,7 +128,7 @@ static void json_nvme_id_ns(struct nvme_id_ns *ns, bool cap_only) struct json_object *lbafs; int i; - long double nvmcap = int128_to_double(ns->nvmcap); + nvme_uint128_t nvmcap = le128_to_cpu(ns->nvmcap); root = json_create_object(); @@ -186,7 +156,7 @@ static void json_nvme_id_ns(struct nvme_id_ns *ns, bool cap_only) json_object_add_value_int(root, "nabo", le16_to_cpu(ns->nabo)); json_object_add_value_int(root, "nabspf", le16_to_cpu(ns->nabspf)); json_object_add_value_int(root, "noiob", le16_to_cpu(ns->noiob)); - json_object_add_value_double(root, "nvmcap", nvmcap); + json_object_add_value_uint128(root, "nvmcap", nvmcap); json_object_add_value_int(root, "nsattr", ns->nsattr); json_object_add_value_int(root, "nvmsetid", le16_to_cpu(ns->nvmsetid)); @@ -245,10 +215,10 @@ static void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, struct json_object *root; struct json_object *psds; - long double tnvmcap = int128_to_double(ctrl->tnvmcap); - long double unvmcap = int128_to_double(ctrl->unvmcap); - long double megcap = int128_to_double(ctrl->megcap); - long double maxdna = int128_to_double(ctrl->maxdna); + nvme_uint128_t tnvmcap = le128_to_cpu(ctrl->tnvmcap); + nvme_uint128_t unvmcap = le128_to_cpu(ctrl->unvmcap); + nvme_uint128_t megcap = le128_to_cpu(ctrl->megcap); + nvme_uint128_t maxdna = le128_to_cpu(ctrl->maxdna); char sn[sizeof(ctrl->sn) + 1], mn[sizeof(ctrl->mn) + 1], fr[sizeof(ctrl->fr) + 1], subnqn[sizeof(ctrl->subnqn) + 1]; @@ -279,6 +249,8 @@ static void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, json_object_add_value_uint(root, "oaes", le32_to_cpu(ctrl->oaes)); json_object_add_value_int(root, "ctratt", le32_to_cpu(ctrl->ctratt)); json_object_add_value_int(root, "rrls", le16_to_cpu(ctrl->rrls)); + json_object_add_value_int(root, "cntrltype", ctrl->cntrltype); + json_object_add_value_string(root, "fguid", util_uuid_to_string(ctrl->fguid)); json_object_add_value_int(root, "crdt1", le16_to_cpu(ctrl->crdt1)); json_object_add_value_int(root, "crdt2", le16_to_cpu(ctrl->crdt2)); json_object_add_value_int(root, "crdt3", le16_to_cpu(ctrl->crdt3)); @@ -299,8 +271,8 @@ static void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, json_object_add_value_int(root, "mtfa", le16_to_cpu(ctrl->mtfa)); json_object_add_value_uint(root, "hmpre", le32_to_cpu(ctrl->hmpre)); json_object_add_value_uint(root, "hmmin", le32_to_cpu(ctrl->hmmin)); - json_object_add_value_double(root, "tnvmcap", tnvmcap); - json_object_add_value_double(root, "unvmcap", unvmcap); + json_object_add_value_uint128(root, "tnvmcap", tnvmcap); + json_object_add_value_uint128(root, "unvmcap", unvmcap); json_object_add_value_uint(root, "rpmbs", le32_to_cpu(ctrl->rpmbs)); json_object_add_value_int(root, "edstt", le16_to_cpu(ctrl->edstt)); json_object_add_value_int(root, "dsto", ctrl->dsto); @@ -314,15 +286,16 @@ static void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, json_object_add_value_int(root, "hmmaxd", le16_to_cpu(ctrl->hmmaxd)); json_object_add_value_int(root, "nsetidmax", le16_to_cpu(ctrl->nsetidmax)); - + json_object_add_value_int(root, "endgidmax", le16_to_cpu(ctrl->endgidmax)); json_object_add_value_int(root, "anatt",ctrl->anatt); json_object_add_value_int(root, "anacap", ctrl->anacap); json_object_add_value_int(root, "anagrpmax", le32_to_cpu(ctrl->anagrpmax)); json_object_add_value_int(root, "nanagrpid", le32_to_cpu(ctrl->nanagrpid)); + json_object_add_value_int(root, "pels", le32_to_cpu(ctrl->pels)); json_object_add_value_int(root, "domainid", le16_to_cpu(ctrl->domainid)); - json_object_add_value_double(root, "megcap", megcap); + json_object_add_value_uint128(root, "megcap", megcap); json_object_add_value_int(root, "sqes", ctrl->sqes); json_object_add_value_int(root, "cqes", ctrl->cqes); json_object_add_value_int(root, "maxcmd", le16_to_cpu(ctrl->maxcmd)); @@ -338,7 +311,8 @@ static void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, json_object_add_value_int(root, "acwu", le16_to_cpu(ctrl->acwu)); json_object_add_value_int(root, "ocfs", le16_to_cpu(ctrl->ocfs)); json_object_add_value_int(root, "sgls", le32_to_cpu(ctrl->sgls)); - json_object_add_value_double(root, "maxdna", maxdna); + json_object_add_value_int(root, "mnan", le32_to_cpu(ctrl->mnan)); + json_object_add_value_uint128(root, "maxdna", maxdna); json_object_add_value_int(root, "maxcna", le32_to_cpu(ctrl->maxcna)); if (strlen(subnqn)) @@ -532,7 +506,7 @@ static void json_fw_log(struct nvme_firmware_slot *fw_log, const char *devname) frs = (__le64 *)&fw_log->frs[i]; snprintf(str, sizeof(str), "%"PRIu64" (%s)", le64_to_cpu(*frs), - fw_to_string(fw_log->frs[i])); + util_fw_to_string(fw_log->frs[i])); json_object_add_value_string(fwsi, fmt, str); } } @@ -585,22 +559,22 @@ static void json_endurance_log(struct nvme_endurance_group_log *endurance_group, { struct json_object *root; - long double endurance_estimate = - int128_to_double(endurance_group->endurance_estimate); - long double data_units_read = - int128_to_double(endurance_group->data_units_read); - long double data_units_written = - int128_to_double(endurance_group->data_units_written); - long double media_units_written = - int128_to_double(endurance_group->media_units_written); - long double host_read_cmds = - int128_to_double(endurance_group->host_read_cmds); - long double host_write_cmds = - int128_to_double(endurance_group->host_write_cmds); - long double media_data_integrity_err = - int128_to_double(endurance_group->media_data_integrity_err); - long double num_err_info_log_entries = - int128_to_double(endurance_group->num_err_info_log_entries); + nvme_uint128_t endurance_estimate = + le128_to_cpu(endurance_group->endurance_estimate); + nvme_uint128_t data_units_read = + le128_to_cpu(endurance_group->data_units_read); + nvme_uint128_t data_units_written = + le128_to_cpu(endurance_group->data_units_written); + nvme_uint128_t media_units_written = + le128_to_cpu(endurance_group->media_units_written); + nvme_uint128_t host_read_cmds = + le128_to_cpu(endurance_group->host_read_cmds); + nvme_uint128_t host_write_cmds = + le128_to_cpu(endurance_group->host_write_cmds); + nvme_uint128_t media_data_integrity_err = + le128_to_cpu(endurance_group->media_data_integrity_err); + nvme_uint128_t num_err_info_log_entries = + le128_to_cpu(endurance_group->num_err_info_log_entries); root = json_create_object(); @@ -612,18 +586,18 @@ static void json_endurance_log(struct nvme_endurance_group_log *endurance_group, endurance_group->avl_spare_threshold); json_object_add_value_int(root, "percent_used", endurance_group->percent_used); - json_object_add_value_double(root, "endurance_estimate", + json_object_add_value_uint128(root, "endurance_estimate", endurance_estimate); - json_object_add_value_double(root, "data_units_read", data_units_read); - json_object_add_value_double(root, "data_units_written", + json_object_add_value_uint128(root, "data_units_read", data_units_read); + json_object_add_value_uint128(root, "data_units_written", data_units_written); - json_object_add_value_double(root, "mediate_write_commands", + json_object_add_value_uint128(root, "media_units_written", media_units_written); - json_object_add_value_double(root, "host_read_cmds", host_read_cmds); - json_object_add_value_double(root, "host_write_cmds", host_write_cmds); - json_object_add_value_double(root, "media_data_integrity_err", + json_object_add_value_uint128(root, "host_read_cmds", host_read_cmds); + json_object_add_value_uint128(root, "host_write_cmds", host_write_cmds); + json_object_add_value_uint128(root, "media_data_integrity_err", media_data_integrity_err); - json_object_add_value_double(root, "num_err_info_log_entries", + json_object_add_value_uint128(root, "num_err_info_log_entries", num_err_info_log_entries); json_print_object(root, NULL); @@ -641,16 +615,16 @@ static void json_smart_log(struct nvme_smart_log *smart, unsigned int nsid, unsigned int temperature = ((smart->temperature[1] << 8) | smart->temperature[0]); - long double data_units_read = int128_to_double(smart->data_units_read); - long double data_units_written = int128_to_double(smart->data_units_written); - long double host_read_commands = int128_to_double(smart->host_reads); - long double host_write_commands = int128_to_double(smart->host_writes); - long double controller_busy_time = int128_to_double(smart->ctrl_busy_time); - long double power_cycles = int128_to_double(smart->power_cycles); - long double power_on_hours = int128_to_double(smart->power_on_hours); - long double unsafe_shutdowns = int128_to_double(smart->unsafe_shutdowns); - long double media_errors = int128_to_double(smart->media_errors); - long double num_err_log_entries = int128_to_double(smart->num_err_log_entries); + nvme_uint128_t data_units_read = le128_to_cpu(smart->data_units_read); + nvme_uint128_t data_units_written = le128_to_cpu(smart->data_units_written); + nvme_uint128_t host_read_commands = le128_to_cpu(smart->host_reads); + nvme_uint128_t host_write_commands = le128_to_cpu(smart->host_writes); + nvme_uint128_t controller_busy_time = le128_to_cpu(smart->ctrl_busy_time); + nvme_uint128_t power_cycles = le128_to_cpu(smart->power_cycles); + nvme_uint128_t power_on_hours = le128_to_cpu(smart->power_on_hours); + nvme_uint128_t unsafe_shutdowns = le128_to_cpu(smart->unsafe_shutdowns); + nvme_uint128_t media_errors = le128_to_cpu(smart->media_errors); + nvme_uint128_t num_err_log_entries = le128_to_cpu(smart->num_err_log_entries); root = json_create_object(); @@ -676,20 +650,20 @@ static void json_smart_log(struct nvme_smart_log *smart, unsigned int nsid, json_object_add_value_int(root, "percent_used", smart->percent_used); json_object_add_value_int(root, "endurance_grp_critical_warning_summary", smart->endu_grp_crit_warn_sumry); - json_object_add_value_double(root, "data_units_read", data_units_read); - json_object_add_value_double(root, "data_units_written", + json_object_add_value_uint128(root, "data_units_read", data_units_read); + json_object_add_value_uint128(root, "data_units_written", data_units_written); - json_object_add_value_double(root, "host_read_commands", + json_object_add_value_uint128(root, "host_read_commands", host_read_commands); - json_object_add_value_double(root, "host_write_commands", + json_object_add_value_uint128(root, "host_write_commands", host_write_commands); - json_object_add_value_double(root, "controller_busy_time", + json_object_add_value_uint128(root, "controller_busy_time", controller_busy_time); - json_object_add_value_double(root, "power_cycles", power_cycles); - json_object_add_value_double(root, "power_on_hours", power_on_hours); - json_object_add_value_double(root, "unsafe_shutdowns", unsafe_shutdowns); - json_object_add_value_double(root, "media_errors", media_errors); - json_object_add_value_double(root, "num_err_log_entries", + json_object_add_value_uint128(root, "power_cycles", power_cycles); + json_object_add_value_uint128(root, "power_on_hours", power_on_hours); + json_object_add_value_uint128(root, "unsafe_shutdowns", unsafe_shutdowns); + json_object_add_value_uint128(root, "media_errors", media_errors); + json_object_add_value_uint128(root, "num_err_log_entries", num_err_log_entries); json_object_add_value_uint(root, "warning_temp_time", le32_to_cpu(smart->warning_temp_time)); @@ -1110,6 +1084,8 @@ static const char *nvme_show_nss_hw_error(__u16 error_code) return "Controller Fatal Status"; case 0xA: return "Media and Data Integrity Status"; + case 0xB: + return "Controller Ready Timeout Exceeded"; default: return "Reserved"; } @@ -1191,8 +1167,8 @@ static void json_persistent_event_log(void *pevent_log_info, __u32 size) le16_to_cpu(pevent_log_head->lhl)); json_object_add_value_uint64(root, "timestamp", le64_to_cpu(pevent_log_head->ts)); - json_object_add_value_double(root, "power_on_hours", - int128_to_double(pevent_log_head->poh)); + json_object_add_value_uint128(root, "power_on_hours", + le128_to_cpu(pevent_log_head->poh)); json_object_add_value_uint64(root, "power_cycle_count", le64_to_cpu(pevent_log_head->pcc)); json_object_add_value_uint(root, "pci_vid", @@ -1256,16 +1232,16 @@ static void json_persistent_event_log(void *pevent_log_info, __u32 size) unsigned int temperature = ((smart_event->temperature[1] << 8) | smart_event->temperature[0]); - long double data_units_read = int128_to_double(smart_event->data_units_read); - long double data_units_written = int128_to_double(smart_event->data_units_written); - long double host_read_commands = int128_to_double(smart_event->host_reads); - long double host_write_commands = int128_to_double(smart_event->host_writes); - long double controller_busy_time = int128_to_double(smart_event->ctrl_busy_time); - long double power_cycles = int128_to_double(smart_event->power_cycles); - long double power_on_hours = int128_to_double(smart_event->power_on_hours); - long double unsafe_shutdowns = int128_to_double(smart_event->unsafe_shutdowns); - long double media_errors = int128_to_double(smart_event->media_errors); - long double num_err_log_entries = int128_to_double(smart_event->num_err_log_entries); + nvme_uint128_t data_units_read = le128_to_cpu(smart_event->data_units_read); + nvme_uint128_t data_units_written = le128_to_cpu(smart_event->data_units_written); + nvme_uint128_t host_read_commands = le128_to_cpu(smart_event->host_reads); + nvme_uint128_t host_write_commands = le128_to_cpu(smart_event->host_writes); + nvme_uint128_t controller_busy_time = le128_to_cpu(smart_event->ctrl_busy_time); + nvme_uint128_t power_cycles = le128_to_cpu(smart_event->power_cycles); + nvme_uint128_t power_on_hours = le128_to_cpu(smart_event->power_on_hours); + nvme_uint128_t unsafe_shutdowns = le128_to_cpu(smart_event->unsafe_shutdowns); + nvme_uint128_t media_errors = le128_to_cpu(smart_event->media_errors); + nvme_uint128_t num_err_log_entries = le128_to_cpu(smart_event->num_err_log_entries); json_object_add_value_int(valid_attrs, "critical_warning", smart_event->critical_warning); @@ -1280,25 +1256,25 @@ static void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_int(valid_attrs, "endurance_grp_critical_warning_summary", smart_event->endu_grp_crit_warn_sumry); - json_object_add_value_double(valid_attrs, "data_units_read", + json_object_add_value_uint128(valid_attrs, "data_units_read", data_units_read); - json_object_add_value_double(valid_attrs, "data_units_written", + json_object_add_value_uint128(valid_attrs, "data_units_written", data_units_written); - json_object_add_value_double(valid_attrs, "host_read_commands", + json_object_add_value_uint128(valid_attrs, "host_read_commands", host_read_commands); - json_object_add_value_double(valid_attrs, "host_write_commands", + json_object_add_value_uint128(valid_attrs, "host_write_commands", host_write_commands); - json_object_add_value_double(valid_attrs, "controller_busy_time", + json_object_add_value_uint128(valid_attrs, "controller_busy_time", controller_busy_time); - json_object_add_value_double(valid_attrs, "power_cycles", + json_object_add_value_uint128(valid_attrs, "power_cycles", power_cycles); - json_object_add_value_double(valid_attrs, "power_on_hours", + json_object_add_value_uint128(valid_attrs, "power_on_hours", power_on_hours); - json_object_add_value_double(valid_attrs, "unsafe_shutdowns", + json_object_add_value_uint128(valid_attrs, "unsafe_shutdowns", unsafe_shutdowns); - json_object_add_value_double(valid_attrs, "media_errors", + json_object_add_value_uint128(valid_attrs, "media_errors", media_errors); - json_object_add_value_double(valid_attrs, "num_err_log_entries", + json_object_add_value_uint128(valid_attrs, "num_err_log_entries", num_err_log_entries); json_object_add_value_uint(valid_attrs, "warning_temp_time", le32_to_cpu(smart_event->warning_temp_time)); @@ -1326,11 +1302,11 @@ static void json_persistent_event_log(void *pevent_log_info, __u32 size) fw_commit_event = pevent_log_info + offset; snprintf(fw_str, sizeof(fw_str), "%"PRIu64" (%s)", le64_to_cpu(fw_commit_event->old_fw_rev), - fw_to_string((char *)&fw_commit_event->old_fw_rev)); + util_fw_to_string((char *)&fw_commit_event->old_fw_rev)); json_object_add_value_string(valid_attrs, "old_fw_rev", fw_str); snprintf(fw_str, sizeof(fw_str), "%"PRIu64" (%s)", le64_to_cpu(fw_commit_event->new_fw_rev), - fw_to_string((char *)&fw_commit_event->new_fw_rev)); + util_fw_to_string((char *)&fw_commit_event->new_fw_rev)); json_object_add_value_string(valid_attrs, "new_fw_rev", fw_str); json_object_add_value_uint(valid_attrs, "fw_commit_action", fw_commit_event->fw_commit_action); @@ -1361,7 +1337,7 @@ static void json_persistent_event_log(void *pevent_log_info, __u32 size) fw_rev = pevent_log_info + offset; snprintf(fw_str, sizeof(fw_str), "%"PRIu64" (%s)", le64_to_cpu(*fw_rev), - fw_to_string((char *)fw_rev)); + util_fw_to_string((char *)fw_rev)); json_object_add_value_string(valid_attrs, "fw_rev", fw_str); for (int i = 0; i < por_info_list; i++) { por_event = pevent_log_info + offset + @@ -1541,8 +1517,8 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("Log Header Length: %u\n", pevent_log_head->lhl); printf("Timestamp: %"PRIu64"\n", le64_to_cpu(pevent_log_head->ts)); - printf("Power On Hours (POH): %'.0Lf\n", - int128_to_double(pevent_log_head->poh)); + printf("Power On Hours (POH): %s", + uint128_t_to_string(le128_to_cpu(pevent_log_head->poh))); printf("Power Cycle Count: %"PRIu64"\n", le64_to_cpu(pevent_log_head->pcc)); printf("PCI Vendor ID (VID): %u\n", @@ -1615,10 +1591,10 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("FW Commit Event Entry: \n"); printf("Old Firmware Revision: %"PRIu64" (%s)\n", le64_to_cpu(fw_commit_event->old_fw_rev), - fw_to_string((char *)&fw_commit_event->old_fw_rev)); + util_fw_to_string((char *)&fw_commit_event->old_fw_rev)); printf("New Firmware Revision: %"PRIu64" (%s)\n", le64_to_cpu(fw_commit_event->new_fw_rev), - fw_to_string((char *)&fw_commit_event->new_fw_rev)); + util_fw_to_string((char *)&fw_commit_event->new_fw_rev)); printf("FW Commit Action: %u\n", fw_commit_event->fw_commit_action); printf("FW Slot: %u\n", fw_commit_event->fw_slot); @@ -1646,7 +1622,7 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("Power On Reset Event Entry: \n"); fw_rev = pevent_log_info + offset; printf("Firmware Revision: %"PRIu64" (%s)\n", le64_to_cpu(*fw_rev), - fw_to_string((char *)fw_rev)); + util_fw_to_string((char *)fw_rev)); printf("Reset Information List: \n"); for (int i = 0; i < por_info_list; i++) { @@ -2263,10 +2239,10 @@ static void json_supported_cap_config_log( le16_to_cpu(cap_log->cap_config_desc[i].egcd[j].endgid)); json_object_add_value_uint(endurance, "cap_adj_factor", le16_to_cpu(cap_log->cap_config_desc[i].egcd[j].cap_adj_factor)); - json_object_add_value_double(endurance, "tegcap", - int128_to_double(cap_log->cap_config_desc[i].egcd[j].tegcap)); - json_object_add_value_double(endurance, "segcap", - int128_to_double(cap_log->cap_config_desc[i].egcd[j].segcap)); + json_object_add_value_uint128(endurance, "tegcap", + le128_to_cpu(cap_log->cap_config_desc[i].egcd[j].tegcap)); + json_object_add_value_uint128(endurance, "segcap", + le128_to_cpu(cap_log->cap_config_desc[i].egcd[j].segcap)); json_object_add_value_uint(endurance, "egsets", le16_to_cpu(cap_log->cap_config_desc[i].egcd[j].egsets)); egsets = le16_to_cpu(cap_log->cap_config_desc[i].egcd[j].egsets); @@ -2343,12 +2319,15 @@ void nvme_show_supported_cap_config_log( le16_to_cpu(cap->cap_config_desc[i].egcd[j].endgid)); printf("Capacity Adjustment Factor: %u\n", le16_to_cpu(cap->cap_config_desc[i].egcd[j].cap_adj_factor)); - printf("Total Endurance Group Capacity: %'.0Lf\n", - int128_to_double(cap->cap_config_desc[i].egcd[j].tegcap)); - printf("Spare Endurance Group Capacity: %'.0Lf\n", - int128_to_double(cap->cap_config_desc[i].egcd[j].segcap)); - printf("Endurance Estimate: %'.0Lf\n", - int128_to_double(cap->cap_config_desc[i].egcd[j].end_est)); + printf("Total Endurance Group Capacity: %s\n", + uint128_t_to_string(le128_to_cpu( + cap->cap_config_desc[i].egcd[j].tegcap))); + printf("Spare Endurance Group Capacity: %s\n", + uint128_t_to_string(le128_to_cpu( + cap->cap_config_desc[i].egcd[j].segcap))); + printf("Endurance Estimate: %s\n", + uint128_t_to_string(le128_to_cpu( + cap->cap_config_desc[i].egcd[j].end_est))); egsets = le16_to_cpu(cap->cap_config_desc[i].egcd[j].egsets); printf("Number of NVM Sets: %u\n", egsets); for(k = 0; k < egsets; k++) { @@ -2503,12 +2482,14 @@ static void json_print_nvme_subsystem_list(nvme_root_t r, bool show_ana) 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)); - json_object_add_value_string(host_attrs, "HostID", - nvme_host_get_hostid(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(); @@ -3274,20 +3255,32 @@ void d_raw(unsigned char *buf, unsigned len) putchar(*(buf+i)); } -void nvme_show_status(__u16 status) -{ - fprintf(stderr, "NVMe status: %s(%#x)\n", - nvme_status_to_string(status, false), status); -} - -static const char *nvme_uuid_to_string(uuid_t uuid) +void nvme_show_status(int status) { - /* large enough to hold uuid str (37) + null-termination byte */ - static char uuid_str[40]; + int val = nvme_status_get_value(status); + int type = nvme_status_get_type(status); - uuid_unparse_lower(uuid, uuid_str); + /* Callers should be checking for negative values first, but provide a + * sensible fallback anyway + */ + if (status < 0) { + fprintf(stderr, "Error: %s\n", nvme_strerror(errno)); + return; + } - return uuid_str; + switch (type) { + case NVME_STATUS_TYPE_NVME: + fprintf(stderr, "NVMe status: %s(%#x)\n", + nvme_status_to_string(val, false), val); + break; + case NVME_STATUS_TYPE_MI: + fprintf(stderr, "NVMe-MI status: %s(%#x)\n", + nvme_mi_status_to_string(val), val); + break; + default: + fprintf(stderr, "Unknown status type %d, value %#x\n", + type, val); + } } static void nvme_show_id_ctrl_cmic(__u8 cmic) @@ -3618,16 +3611,14 @@ static void nvme_show_id_ctrl_cctemp(__le16 cctemp) static void nvme_show_id_ctrl_tnvmcap(__u8 *tnvmcap) { - printf("[127:0] : %.0Lf\tTotal NVM Capacity (TNVMCAP)\n", - int128_to_double(tnvmcap)); - printf("\n"); + printf("[127:0] : %s\n", uint128_t_to_string(le128_to_cpu(tnvmcap))); + printf("\tTotal NVM Capacity (TNVMCAP)\n\n"); } static void nvme_show_id_ctrl_unvmcap(__u8 *unvmcap) { - printf("[127:0] : %.0Lf\tUnallocated NVM Capacity (UNVMCAP)\n", - int128_to_double(unvmcap)); - printf("\n"); + printf("[127:0] : %s\n", uint128_t_to_string(le128_to_cpu(unvmcap))); + printf("\tUnallocated NVM Capacity (UNVMCAP)\n\n"); } void nvme_show_id_ctrl_rpmbs(__le32 ctrl_rpmbs) @@ -4208,7 +4199,8 @@ void nvme_show_id_ns(struct nvme_id_ns *ns, unsigned int nsid, printf("nabo : %d\n", le16_to_cpu(ns->nabo)); printf("nabspf : %d\n", le16_to_cpu(ns->nabspf)); printf("noiob : %d\n", le16_to_cpu(ns->noiob)); - printf("nvmcap : %.0Lf\n", int128_to_double(ns->nvmcap)); + printf("nvmcap : %s\n", + uint128_t_to_string(le128_to_cpu(ns->nvmcap))); if (ns->nsfeat & 0x10) { printf("npwg : %u\n", le16_to_cpu(ns->npwg)); printf("npwa : %u\n", le16_to_cpu(ns->npwa)); @@ -4355,7 +4347,7 @@ static void json_nvme_id_ns_descs(void *data) union { __u8 eui64[NVME_NIDT_EUI64_LEN]; __u8 nguid[NVME_NIDT_NGUID_LEN]; - uuid_t uuid; + __u8 uuid[NVME_UUID_LEN]; __u8 csi; } desc; @@ -4396,7 +4388,7 @@ static void json_nvme_id_ns_descs(void *data) case NVME_NIDT_UUID: memcpy(desc.uuid, data + off, sizeof(desc.uuid)); - uuid_unparse_lower(desc.uuid, json_str); + nvme_uuid_to_string(desc.uuid, json_str); len = sizeof(desc.uuid); nidt_name = "uuid"; break; @@ -4446,8 +4438,8 @@ void nvme_show_id_ns_descs(void *data, unsigned nsid, enum nvme_print_flags flag { int pos, len = 0; int i; - uuid_t uuid; - char uuid_str[37]; + __u8 uuid[NVME_UUID_LEN]; + char uuid_str[NVME_UUID_LEN_STRING]; __u8 eui64[8]; __u8 nguid[16]; __u8 csi; @@ -4483,7 +4475,7 @@ void nvme_show_id_ns_descs(void *data, unsigned nsid, enum nvme_print_flags flag break; case NVME_NIDT_UUID: memcpy(uuid, data + pos + sizeof(*cur), 16); - uuid_unparse_lower(uuid, uuid_str); + nvme_uuid_to_string(uuid, uuid_str); printf("uuid : %s\n", uuid_str); len = sizeof(uuid); break; @@ -4622,7 +4614,7 @@ void nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags, printf("cntrltype : %d\n", ctrl->cntrltype); if (human) nvme_show_id_ctrl_cntrltype(ctrl->cntrltype); - printf("fguid : %-.*s\n", (int)sizeof(ctrl->fguid), ctrl->fguid); + printf("fguid : %s\n", util_uuid_to_string(ctrl->fguid)); printf("crdt1 : %u\n", le16_to_cpu(ctrl->crdt1)); printf("crdt2 : %u\n", le16_to_cpu(ctrl->crdt2)); printf("crdt3 : %u\n", le16_to_cpu(ctrl->crdt3)); @@ -4668,10 +4660,12 @@ void nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags, printf("mtfa : %d\n", le16_to_cpu(ctrl->mtfa)); printf("hmpre : %d\n", le32_to_cpu(ctrl->hmpre)); printf("hmmin : %d\n", le32_to_cpu(ctrl->hmmin)); - printf("tnvmcap : %.0Lf\n", int128_to_double(ctrl->tnvmcap)); + printf("tnvmcap : %s\n", + uint128_t_to_string(le128_to_cpu(ctrl->tnvmcap))); if (human) nvme_show_id_ctrl_tnvmcap(ctrl->tnvmcap); - printf("unvmcap : %.0Lf\n", int128_to_double(ctrl->unvmcap)); + printf("unvmcap : %s\n", + uint128_t_to_string(le128_to_cpu(ctrl->unvmcap))); if (human) nvme_show_id_ctrl_unvmcap(ctrl->unvmcap); printf("rpmbs : %#x\n", le32_to_cpu(ctrl->rpmbs)); @@ -4705,7 +4699,8 @@ void nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags, printf("nanagrpid : %d\n", le32_to_cpu(ctrl->nanagrpid)); printf("pels : %d\n", le32_to_cpu(ctrl->pels)); printf("domainid : %d\n", le16_to_cpu(ctrl->domainid)); - printf("megcap : %.0Lf\n", int128_to_double(ctrl->megcap)); + printf("megcap : %s\n", + uint128_t_to_string(le128_to_cpu(ctrl->megcap))); printf("sqes : %#x\n", ctrl->sqes); if (human) nvme_show_id_ctrl_sqes(ctrl->sqes); @@ -4742,7 +4737,8 @@ void nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags, if (human) nvme_show_id_ctrl_sgls(ctrl->sgls); printf("mnan : %d\n", le32_to_cpu(ctrl->mnan)); - printf("maxdna : %.0Lf\n", int128_to_double(ctrl->maxdna)); + printf("maxdna : %s\n", + uint128_t_to_string(le128_to_cpu(ctrl->maxdna))); printf("maxcna : %d\n", le32_to_cpu(ctrl->maxcna)); printf("subnqn : %-.*s\n", (int)sizeof(ctrl->subnqn), ctrl->subnqn); printf("ioccsz : %d\n", le32_to_cpu(ctrl->ioccsz)); @@ -5366,10 +5362,10 @@ static void json_nvme_id_nvmset(struct nvme_id_nvmset_list *nvmset) le32_to_cpu(nvmset->ent[i].rr4kt)); json_object_add_value_int(entry, "optimal_write_size", le32_to_cpu(nvmset->ent[i].ows)); - json_object_add_value_double(entry, "total_nvmset_cap", - int128_to_double(nvmset->ent[i].tnvmsetcap)); - json_object_add_value_double(entry, "unalloc_nvmset_cap", - int128_to_double(nvmset->ent[i].unvmsetcap)); + json_object_add_value_uint128(entry, "total_nvmset_cap", + le128_to_cpu(nvmset->ent[i].tnvmsetcap)); + json_object_add_value_uint128(entry, "unalloc_nvmset_cap", + le128_to_cpu(nvmset->ent[i].unvmsetcap)); json_array_add_value_object(entries, entry); } @@ -5403,10 +5399,12 @@ void nvme_show_id_nvmset(struct nvme_id_nvmset_list *nvmset, unsigned nvmset_id, le32_to_cpu(nvmset->ent[i].rr4kt)); printf("optimal_write_size : %u\n", le32_to_cpu(nvmset->ent[i].ows)); - printf("total_nvmset_cap : %.0Lf\n", - int128_to_double(nvmset->ent[i].tnvmsetcap)); - printf("unalloc_nvmset_cap : %.0Lf\n", - int128_to_double(nvmset->ent[i].unvmsetcap)); + printf("total_nvmset_cap : %s\n", + uint128_t_to_string( + le128_to_cpu(nvmset->ent[i].tnvmsetcap))); + printf("unalloc_nvmset_cap : %s\n", + uint128_t_to_string( + le128_to_cpu(nvmset->ent[i].unvmsetcap))); printf(".................\n"); } } @@ -5630,7 +5628,7 @@ static void json_nvme_id_uuid_list(const struct nvme_id_uuid_list *uuid_list) entries = json_create_array(); /* The 0th entry is reserved */ for (i = 1; i < NVME_ID_UUID_LIST_MAX; i++) { - uuid_t uuid; + __u8 uuid[NVME_UUID_LEN]; struct json_object *entry = json_create_object(); /* The list is terminated by a zero UUID value */ @@ -5640,7 +5638,7 @@ static void json_nvme_id_uuid_list(const struct nvme_id_uuid_list *uuid_list) json_object_add_value_int(entry, "association", uuid_list->entry[i].header & 0x3); json_object_add_value_string(entry, "uuid", - nvme_uuid_to_string(uuid)); + util_uuid_to_string(uuid)); json_array_add_value_object(entries, entry); } json_object_add_value_array(root, "UUID-list", entries); @@ -5662,13 +5660,13 @@ void nvme_show_id_uuid_list(const struct nvme_id_uuid_list *uuid_list, /* The 0th entry is reserved */ printf("NVME Identify UUID:\n"); for (i = 0; i < NVME_ID_UUID_LIST_MAX; i++) { - uuid_t uuid; + __u8 uuid[NVME_UUID_LEN]; char *association = ""; uint8_t identifier_association = uuid_list->entry[i].header & 0x3; /* The list is terminated by a zero UUID value */ - if (memcmp(uuid_list->entry[i].uuid, zero_uuid, sizeof(zero_uuid)) == 0) + if (memcmp(uuid_list->entry[i].uuid, zero_uuid, NVME_UUID_LEN) == 0) break; - memcpy(&uuid, uuid_list->entry[i].uuid, sizeof(uuid)); + memcpy(&uuid, uuid_list->entry[i].uuid, NVME_UUID_LEN); if (human) { switch (identifier_association) { case 0x0: @@ -5688,7 +5686,7 @@ void nvme_show_id_uuid_list(const struct nvme_id_uuid_list *uuid_list, printf(" Entry[%3d]\n", i+1); printf(".................\n"); printf("association : 0x%x %s\n", identifier_association, association); - printf("UUID : %s", nvme_uuid_to_string(uuid)); + printf("UUID : %s", util_uuid_to_string(uuid)); if (memcmp(uuid_list->entry[i].uuid, invalid_uuid, sizeof(zero_uuid)) == 0) printf(" (Invalid UUID)"); @@ -5702,7 +5700,7 @@ static void json_id_domain_list(struct nvme_id_domain_list *id_dom) struct json_object *entries; struct json_object *entry; int i; - long double dom_cap, unalloc_dom_cap, max_egrp_dom_cap; + nvme_uint128_t dom_cap, unalloc_dom_cap, max_egrp_dom_cap; root = json_create_object(); entries = json_create_array(); @@ -5711,14 +5709,14 @@ static void json_id_domain_list(struct nvme_id_domain_list *id_dom) for (i = 0; i < id_dom->num; i++) { entry = json_create_object(); - dom_cap = int128_to_double(id_dom->domain_attr[i].dom_cap); - unalloc_dom_cap = int128_to_double(id_dom->domain_attr[i].unalloc_dom_cap); - max_egrp_dom_cap = int128_to_double(id_dom->domain_attr[i].max_egrp_dom_cap); + dom_cap = le128_to_cpu(id_dom->domain_attr[i].dom_cap); + unalloc_dom_cap = le128_to_cpu(id_dom->domain_attr[i].unalloc_dom_cap); + max_egrp_dom_cap = le128_to_cpu(id_dom->domain_attr[i].max_egrp_dom_cap); json_object_add_value_uint(entry, "dom_id", le16_to_cpu(id_dom->domain_attr[i].dom_id)); - json_object_add_value_double(entry, "dom_cap", dom_cap); - json_object_add_value_double(entry, "unalloc_dom_cap", unalloc_dom_cap); - json_object_add_value_double(entry, "max_egrp_dom_cap", max_egrp_dom_cap); + json_object_add_value_uint128(entry, "dom_cap", dom_cap); + json_object_add_value_uint128(entry, "unalloc_dom_cap", unalloc_dom_cap); + json_object_add_value_uint128(entry, "max_egrp_dom_cap", max_egrp_dom_cap); json_array_add_value_object(entries, entry); } @@ -5742,12 +5740,15 @@ void nvme_show_id_domain_list(struct nvme_id_domain_list *id_dom, for (i = 0; i < id_dom->num; i++) { printf("Domain Id for Attr Entry[%u]: %u\n", i, le16_to_cpu(id_dom->domain_attr[i].dom_id)); - printf("Domain Capacity for Attr Entry[%u]: %.0Lf\\n", i, - int128_to_double(id_dom->domain_attr[i].dom_cap)); - printf("Unallocated Domain Capacity for Attr Entry[%u]: %.0Lf\n", i, - int128_to_double(id_dom->domain_attr[i].unalloc_dom_cap)); - printf("Max Endurance Group Domain Capacity for Attr Entry[%u]: %.0Lf\n", i, - int128_to_double(id_dom->domain_attr[i].max_egrp_dom_cap)); + printf("Domain Capacity for Attr Entry[%u]: %s\n", i, + uint128_t_to_string( + le128_to_cpu(id_dom->domain_attr[i].dom_cap))); + printf("Unallocated Domain Capacity for Attr Entry[%u]: %s\n", i, + uint128_t_to_string( + le128_to_cpu(id_dom->domain_attr[i].unalloc_dom_cap))); + printf("Max Endurance Group Domain Capacity for Attr Entry[%u]: %s\n", i, + uint128_t_to_string( + le128_to_cpu(id_dom->domain_attr[i].max_egrp_dom_cap))); } } @@ -5938,7 +5939,7 @@ void nvme_show_fw_log(struct nvme_firmware_slot *fw_log, frs = (__le64 *)&fw_log->frs[i]; printf("frs%d : %#016"PRIx64" (%s)\n", i + 1, le64_to_cpu(*frs), - fw_to_string(fw_log->frs[i])); + util_fw_to_string(fw_log->frs[i])); } } } @@ -6175,18 +6176,6 @@ void nvme_show_supported_log(struct nvme_supported_log_pages *support_log, } } -uint64_t int48_to_long(__u8 *data) -{ - int i; - uint64_t result = 0; - - for (i = 0; i < 6; i++) { - result *= 256; - result += data[5 - i]; - } - return result; -} - void nvme_show_endurance_log(struct nvme_endurance_group_log *endurance_log, __u16 group_id, const char *devname, enum nvme_print_flags flags) @@ -6205,22 +6194,30 @@ void nvme_show_endurance_log(struct nvme_endurance_group_log *endurance_log, printf("avl_spare_threshold : %u\n", endurance_log->avl_spare_threshold); printf("percent_used : %u%%\n", endurance_log->percent_used); - printf("endurance_estimate : %'.0Lf\n", - int128_to_double(endurance_log->endurance_estimate)); - printf("data_units_read : %'.0Lf\n", - int128_to_double(endurance_log->data_units_read)); - printf("data_units_written : %'.0Lf\n", - int128_to_double(endurance_log->data_units_written)); - printf("media_units_written : %'.0Lf\n", - int128_to_double(endurance_log->media_units_written)); - printf("host_read_cmds : %'.0Lf\n", - int128_to_double(endurance_log->host_read_cmds)); - printf("host_write_cmds : %'.0Lf\n", - int128_to_double(endurance_log->host_write_cmds)); - printf("media_data_integrity_err: %'.0Lf\n", - int128_to_double(endurance_log->media_data_integrity_err)); - printf("num_err_info_log_entries: %'.0Lf\n", - int128_to_double(endurance_log->num_err_info_log_entries)); + printf("endurance_estimate : %s\n", + uint128_t_to_string( + le128_to_cpu(endurance_log->endurance_estimate))); + printf("data_units_read : %s\n", + uint128_t_to_string( + le128_to_cpu(endurance_log->data_units_read))); + printf("data_units_written : %s\n", + uint128_t_to_string( + le128_to_cpu(endurance_log->data_units_written))); + printf("media_units_written : %s\n", + uint128_t_to_string( + le128_to_cpu(endurance_log->media_units_written))); + printf("host_read_cmds : %s\n", + uint128_t_to_string( + le128_to_cpu(endurance_log->host_read_cmds))); + printf("host_write_cmds : %s\n", + uint128_t_to_string( + le128_to_cpu(endurance_log->host_write_cmds))); + printf("media_data_integrity_err: %s\n", + uint128_t_to_string( + le128_to_cpu(endurance_log->media_data_integrity_err))); + printf("num_err_info_log_entries: %s\n", + uint128_t_to_string( + le128_to_cpu(endurance_log->num_err_info_log_entries))); } void nvme_show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, @@ -6258,26 +6255,26 @@ void nvme_show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, smart->percent_used); printf("endurance group critical warning summary: %#x\n", smart->endu_grp_crit_warn_sumry); - printf("data_units_read : %'.0Lf\n", - int128_to_double(smart->data_units_read)); - printf("data_units_written : %'.0Lf\n", - int128_to_double(smart->data_units_written)); - printf("host_read_commands : %'.0Lf\n", - int128_to_double(smart->host_reads)); - printf("host_write_commands : %'.0Lf\n", - int128_to_double(smart->host_writes)); - printf("controller_busy_time : %'.0Lf\n", - int128_to_double(smart->ctrl_busy_time)); - printf("power_cycles : %'.0Lf\n", - int128_to_double(smart->power_cycles)); - printf("power_on_hours : %'.0Lf\n", - int128_to_double(smart->power_on_hours)); - printf("unsafe_shutdowns : %'.0Lf\n", - int128_to_double(smart->unsafe_shutdowns)); - printf("media_errors : %'.0Lf\n", - int128_to_double(smart->media_errors)); - printf("num_err_log_entries : %'.0Lf\n", - int128_to_double(smart->num_err_log_entries)); + printf("data_units_read : %s\n", + uint128_t_to_string(le128_to_cpu(smart->data_units_read))); + printf("data_units_written : %s\n", + uint128_t_to_string(le128_to_cpu(smart->data_units_written))); + printf("host_read_commands : %s\n", + uint128_t_to_string(le128_to_cpu(smart->host_reads))); + printf("host_write_commands : %s\n", + uint128_t_to_string(le128_to_cpu(smart->host_writes))); + printf("controller_busy_time : %s\n", + uint128_t_to_string(le128_to_cpu(smart->ctrl_busy_time))); + printf("power_cycles : %s\n", + uint128_t_to_string(le128_to_cpu(smart->power_cycles))); + printf("power_on_hours : %s\n", + uint128_t_to_string(le128_to_cpu(smart->power_on_hours))); + printf("unsafe_shutdowns : %s\n", + uint128_t_to_string(le128_to_cpu(smart->unsafe_shutdowns))); + printf("media_errors : %s\n", + uint128_t_to_string(le128_to_cpu(smart->media_errors))); + printf("num_err_log_entries : %s\n", + uint128_t_to_string(le128_to_cpu(smart->num_err_log_entries))); printf("Warning Temperature Time : %u\n", le32_to_cpu(smart->warning_temp_time)); printf("Critical Composite Temperature Time : %u\n", @@ -6500,7 +6497,7 @@ void nvme_show_sanitize_log(struct nvme_sanitize_log_page *sanitize, printf("\n"); printf("Sanitize Status (SSTAT) : %#x\n", - le16_to_cpu(sanitize->sstat)); + le16_to_cpu(sanitize->sstat) & NVME_SANITIZE_SSTAT_STATUS_MASK); if (human) nvme_show_sanitize_log_sstat(le16_to_cpu(sanitize->sstat)); @@ -7385,9 +7382,12 @@ static void json_detail_list(nvme_root_t r) nvme_for_each_host(r, h) { struct json_object *hss = json_create_object(); struct json_object *jsslist = json_create_array(); + const char *hostid; json_object_add_value_string(hss, "HostNQN", nvme_host_get_hostnqn(h)); - json_object_add_value_string(hss, "HostID", nvme_host_get_hostid(h)); + hostid = nvme_host_get_hostid(h); + if (hostid) + json_object_add_value_string(hss, "HostID", hostid); nvme_for_each_subsystem(h , s) { struct json_object *jss = json_create_object(); @@ -7540,3 +7540,247 @@ void nvme_show_list_items(nvme_root_t r, enum nvme_print_flags flags) 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); +} -- cgit v1.2.3