summaryrefslogtreecommitdiffstats
path: root/nvme-print-stdout.c
diff options
context:
space:
mode:
Diffstat (limited to 'nvme-print-stdout.c')
-rw-r--r--nvme-print-stdout.c619
1 files changed, 473 insertions, 146 deletions
diff --git a/nvme-print-stdout.c b/nvme-print-stdout.c
index 877ba75..90cd8dd 100644
--- a/nvme-print-stdout.c
+++ b/nvme-print-stdout.c
@@ -7,6 +7,11 @@
#include <time.h>
#include <sys/stat.h>
+#include <ccan/ccan/strset/strset.h>
+#include <ccan/ccan/htable/htable_type.h>
+#include <ccan/ccan/htable/htable.h>
+#include <ccan/ccan/hash/hash.h>
+
#include "nvme.h"
#include "libnvme.h"
#include "nvme-print.h"
@@ -23,13 +28,158 @@ static struct print_ops stdout_print_ops;
struct nvme_bar_cap {
__u16 mqes;
- __u8 ams_cqr;
+ __u8 cqr:1;
+ __u8 ams:2;
+ __u8 rsvd19:5;
__u8 to;
- __u16 bps_css_nssrs_dstrd;
- __u8 mpsmax_mpsmin;
- __u8 rsvd_crms_nsss_cmbs_pmrs;
+ __u16 dstrd:4;
+ __u16 nssrs:1;
+ __u16 css:8;
+ __u16 bps:1;
+ __u8 cps:2;
+ __u8 mpsmin:4;
+ __u8 mpsmax:4;
+ __u8 pmrs:1;
+ __u8 cmbs:1;
+ __u8 nsss:1;
+ __u8 crwms:1;
+ __u8 crims:1;
+ __u8 rsvd61:3;
+};
+
+static const char *subsys_key(const struct nvme_subsystem *s)
+{
+ return nvme_subsystem_get_name((nvme_subsystem_t)s);
+}
+
+static const char *ctrl_key(const struct nvme_ctrl *c)
+{
+ return nvme_ctrl_get_name((nvme_ctrl_t)c);
+}
+
+static const char *ns_key(const struct nvme_ns *n)
+{
+ return nvme_ns_get_name((nvme_ns_t)n);
+}
+
+static bool subsys_cmp(const struct nvme_subsystem *s, const char *name)
+{
+ return !strcmp(nvme_subsystem_get_name((nvme_subsystem_t)s), name);
+}
+
+static bool ctrl_cmp(const struct nvme_ctrl *c, const char *name)
+{
+ return !strcmp(nvme_ctrl_get_name((nvme_ctrl_t)c), name);
+}
+
+static bool ns_cmp(const struct nvme_ns *n, const char *name)
+{
+ return !strcmp(nvme_ns_get_name((nvme_ns_t)n), name);
+}
+
+HTABLE_DEFINE_TYPE(struct nvme_subsystem, subsys_key, hash_string,
+ subsys_cmp, htable_subsys);
+HTABLE_DEFINE_TYPE(struct nvme_ctrl, ctrl_key, hash_string,
+ ctrl_cmp, htable_ctrl);
+HTABLE_DEFINE_TYPE(struct nvme_ns, ns_key, hash_string,
+ ns_cmp, htable_ns);
+
+static void htable_ctrl_add_unique(struct htable_ctrl *ht, nvme_ctrl_t c)
+{
+ if (htable_ctrl_get(ht, nvme_ctrl_get_name(c)))
+ return;
+
+ htable_ctrl_add(ht, c);
+}
+
+static void htable_ns_add_unique(struct htable_ns *ht, nvme_ns_t n)
+{
+ struct htable_ns_iter it;
+ nvme_ns_t _n;
+
+ /*
+ * Test if namespace pointer is already in the hash, and thus avoid
+ * inserting severaltimes the same pointer.
+ */
+ for (_n = htable_ns_getfirst(ht, nvme_ns_get_name(n), &it);
+ _n;
+ _n = htable_ns_getnext(ht, nvme_ns_get_name(n), &it)) {
+ if (_n == n)
+ return;
+ }
+ htable_ns_add(ht, n);
+}
+
+struct nvme_resources {
+ nvme_root_t r;
+
+ struct htable_subsys ht_s;
+ struct htable_ctrl ht_c;
+ struct htable_ns ht_n;
+ struct strset subsystems;
+ struct strset ctrls;
+ struct strset namespaces;
};
+static int nvme_resources_init(nvme_root_t r, struct nvme_resources *res)
+{
+ nvme_host_t h;
+ nvme_subsystem_t s;
+ nvme_ctrl_t c;
+ nvme_ns_t n;
+ nvme_path_t p;
+
+ res->r = r;
+ htable_subsys_init(&res->ht_s);
+ htable_ctrl_init(&res->ht_c);
+ htable_ns_init(&res->ht_n);
+ strset_init(&res->subsystems);
+ strset_init(&res->ctrls);
+ strset_init(&res->namespaces);
+
+ nvme_for_each_host(r, h) {
+ nvme_for_each_subsystem(h, s) {
+ htable_subsys_add(&res->ht_s, s);
+ strset_add(&res->subsystems, nvme_subsystem_get_name(s));
+
+ nvme_subsystem_for_each_ctrl(s, c) {
+ htable_ctrl_add_unique(&res->ht_c, c);
+ strset_add(&res->ctrls, nvme_ctrl_get_name(c));
+
+ nvme_ctrl_for_each_ns(c, n) {
+ htable_ns_add_unique(&res->ht_n, n);
+ strset_add(&res->namespaces, nvme_ns_get_name(n));
+ }
+
+ nvme_ctrl_for_each_path(c, p) {
+ n = nvme_path_get_ns(p);
+ if (n) {
+ htable_ns_add_unique(&res->ht_n, n);
+ strset_add(&res->namespaces, nvme_ns_get_name(n));
+ }
+ }
+ }
+
+ nvme_subsystem_for_each_ns(s, n) {
+ htable_ns_add_unique(&res->ht_n, n);
+ strset_add(&res->namespaces, nvme_ns_get_name(n));
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void nvme_resources_free(struct nvme_resources *res)
+{
+ strset_clear(&res->namespaces);
+ strset_clear(&res->ctrls);
+ strset_clear(&res->subsystems);
+ htable_ns_clear(&res->ht_n);
+ htable_ctrl_clear(&res->ht_c);
+ htable_subsys_clear(&res->ht_s);
+}
+
static void stdout_feature_show_fields(enum nvme_features_id fid,
unsigned int result,
unsigned char *buf);
@@ -567,6 +717,111 @@ static void stdout_boot_part_log(void *bp_log, const char *devname,
printf("Active BPID: %u\n", (le32_to_cpu(hdr->bpinfo) >> 31) & 0x1);
}
+static const char *eomip_to_string(__u8 eomip)
+{
+ const char *string;
+ switch (eomip) {
+ case NVME_PHY_RX_EOM_NOT_STARTED:
+ string = "Not Started";
+ break;
+ case NVME_PHY_RX_EOM_IN_PROGRESS:
+ string = "In Progress";
+ break;
+ case NVME_PHY_RX_EOM_COMPLETED:
+ string = "Completed";
+ break;
+ default:
+ string = "Unknown";
+ }
+ return string;
+}
+
+static void stdout_phy_rx_eom_odp(uint8_t odp)
+{
+ __u8 rsvd = (odp >> 2) & 0x3F;
+ __u8 edfp = (odp >> 1) & 0x1;
+ __u8 pefp = odp & 0x1;
+
+ if (rsvd)
+ printf(" [7:2] : %#x\tReserved\n", rsvd);
+ printf(" [1:1] : %#x\tEye Data Field %sPresent\n",
+ edfp, edfp ? "" : "Not ");
+ printf(" [0:0] : %#x\tPrintable Eye Field %sPresent\n",
+ pefp, pefp ? "" : "Not ");
+}
+
+static void stdout_eom_printable_eye(struct nvme_eom_lane_desc *lane)
+{
+ char *eye = (char *)lane->eye_desc;
+ int i, j;
+ for (i = 0; i < lane->nrows; i++) {
+ for (j = 0; j < lane->ncols; j++)
+ printf("%c", eye[i * lane->ncols + j]);
+ printf("\n");
+ }
+}
+
+static void stdout_phy_rx_eom_descs(struct nvme_phy_rx_eom_log *log)
+{
+ void *p = log->descs;
+ int i;
+
+ for (i = 0; i < log->nd; i++) {
+ struct nvme_eom_lane_desc *desc = p;
+
+ printf("Measurement Status: %s\n",
+ desc->mstatus ? "Successful" : "Not Successful");
+ printf("Lane: %u\n", desc->lane);
+ printf("Eye: %u\n", desc->eye);
+ printf("Top: %u\n", le16_to_cpu(desc->top));
+ printf("Bottom: %u\n", le16_to_cpu(desc->bottom));
+ printf("Left: %u\n", le16_to_cpu(desc->left));
+ printf("Right: %u\n", le16_to_cpu(desc->right));
+ printf("Number of Rows: %u\n", le16_to_cpu(desc->nrows));
+ printf("Number of Columns: %u\n", le16_to_cpu(desc->ncols));
+ printf("Eye Data Length: %u\n", le16_to_cpu(desc->edlen));
+
+ if (log->odp & NVME_EOM_PRINTABLE_EYE_PRESENT)
+ stdout_eom_printable_eye(desc);
+
+ /* Eye Data field is vendor specific */
+
+ p += log->dsize;
+ }
+}
+
+static void stdout_phy_rx_eom_log(struct nvme_phy_rx_eom_log *log, __u16 controller)
+{
+ int human = stdout_print_ops.flags & VERBOSE;
+
+ printf("Physical Interface Receiver Eye Opening Measurement Log for controller ID: %u\n", controller);
+ printf("Log ID: %u\n", log->lid);
+ printf("EOM In Progress: %s\n", eomip_to_string(log->eomip));
+ printf("Header Size: %u\n", le16_to_cpu(log->hsize));
+ printf("Result Size: %u\n", le32_to_cpu(log->rsize));
+ printf("EOM Data Generation Number: %u\n", log->eomdgn);
+ printf("Log Revision: %u\n", log->lr);
+ printf("Optional Data Present: %u\n", log->odp);
+ if (human)
+ stdout_phy_rx_eom_odp(log->odp);
+ printf("Lanes: %u\n", log->lanes);
+ printf("Eyes Per Lane: %u\n", log->epl);
+ printf("Log Specific Parameter Field Copy: %u\n", log->lspfc);
+ printf("Link Information: %u\n", log->li);
+ printf("Log Specific Identifier Copy: %u\n", le16_to_cpu(log->lsic));
+ printf("Descriptor Size: %u\n", le32_to_cpu(log->dsize));
+ printf("Number of Descriptors: %u\n", le16_to_cpu(log->nd));
+ printf("Maximum Top Bottom: %u\n", le16_to_cpu(log->maxtb));
+ printf("Maximum Left Right: %u\n", le16_to_cpu(log->maxlr));
+ printf("Estimated Time for Good Quality: %u\n", le16_to_cpu(log->etgood));
+ printf("Estimated Time for Better Quality: %u\n", le16_to_cpu(log->etbetter));
+ printf("Estimated Time for Best Quality: %u\n", le16_to_cpu(log->etbest));
+
+ if (log->eomip == NVME_PHY_RX_EOM_COMPLETED) {
+ stdout_phy_rx_eom_descs(log);
+ }
+}
+
static void stdout_media_unit_stat_log(struct nvme_media_unit_stat_log *mus_log)
{
int i;
@@ -597,7 +852,7 @@ static void stdout_media_unit_stat_log(struct nvme_media_unit_stat_log *mus_log)
static void stdout_fdp_config_fdpa(uint8_t fdpa)
{
__u8 valid = (fdpa >> 7) & 0x1;
- __u8 rsvd = (fdpa >> 5) >> 0x3;
+ __u8 rsvd = (fdpa >> 5) & 0x3;
__u8 fdpvwc = (fdpa >> 4) & 0x1;
__u8 rgif = fdpa & 0xf;
@@ -826,13 +1081,24 @@ static void stdout_subsystem_ctrls(nvme_subsystem_t s)
static void stdout_subsystem(nvme_root_t r, bool show_ana)
{
nvme_host_t h;
+ bool first = true;
nvme_for_each_host(r, h) {
nvme_subsystem_t s;
nvme_for_each_subsystem(h, s) {
+ int len = strlen(nvme_subsystem_get_name(s));
+
+ if (!first)
+ printf("\n");
+ first = false;
+
printf("%s - NQN=%s\n", nvme_subsystem_get_name(s),
nvme_subsystem_get_nqn(s));
+ printf("%*s hostnqn=%s\n", len, " ",
+ nvme_host_get_hostnqn(nvme_subsystem_get_host(s)));
+ printf("%*s iopolicy=%s\n", len, " ",
+ nvme_subsystem_get_iopolicy(s));
printf("\\\n");
if (!show_ana || !stdout_subsystem_multipath(s))
@@ -849,39 +1115,33 @@ static void stdout_subsystem_list(nvme_root_t r, bool show_ana)
static void stdout_registers_cap(struct nvme_bar_cap *cap)
{
printf("\tController Ready With Media Support (CRWMS): %s\n",
- ((cap->rsvd_crms_nsss_cmbs_pmrs & 0x08) >> 3) ? "Supported" : "Not Supported");
+ cap->crwms ? "Supported" : "Not Supported");
printf("\tController Ready Independent of Media Support (CRIMS): %s\n",
- ((cap->rsvd_crms_nsss_cmbs_pmrs & 0x10) >> 4) ? "Supported" : "Not Supported");
+ cap->crims ? "Supported" : "Not Supported");
+ printf("\tNVM Subsystem Shutdown Supported (NSSS): %s\n", cap->nsss ? "Supported" : "Not Supported");
printf("\tController Memory Buffer Supported (CMBS): The Controller Memory Buffer is %s\n",
- ((cap->rsvd_crms_nsss_cmbs_pmrs & 0x02) >> 1) ? "Supported" :
- "Not Supported");
+ cap->cmbs ? "Supported" : "Not Supported");
printf("\tPersistent Memory Region Supported (PMRS): The Persistent Memory Region is %s\n",
- (cap->rsvd_crms_nsss_cmbs_pmrs & 0x01) ? "Supported" : "Not Supported");
- printf("\tMemory Page Size Maximum (MPSMAX): %u bytes\n",
- 1 << (12 + ((cap->mpsmax_mpsmin & 0xf0) >> 4)));
- printf("\tMemory Page Size Minimum (MPSMIN): %u bytes\n",
- 1 << (12 + (cap->mpsmax_mpsmin & 0x0f)));
- printf("\tBoot Partition Support (BPS): %s\n",
- (cap->bps_css_nssrs_dstrd & 0x2000) ? "Yes":"No");
+ cap->pmrs ? "Supported" : "Not Supported");
+ printf("\tMemory Page Size Maximum (MPSMAX): %u bytes\n", 1 << (12 + cap->mpsmax));
+ printf("\tMemory Page Size Minimum (MPSMIN): %u bytes\n", 1 << (12 + cap->mpsmin));
+ printf("\tController Power Scope (CPS): %s\n",
+ !cap->cps ? "Not Reported" : cap->cps == 1 ? "Controller scope" :
+ cap->cps == 2 ? "Domain scope" : "NVM subsystem scope");
+ printf("\tBoot Partition Support (BPS): %s\n", cap->bps ? "Yes" : "No");
printf("\tCommand Sets Supported (CSS): NVM command set is %s\n",
- (cap->bps_css_nssrs_dstrd & 0x0020) ? "Supported" : "Not Supported");
+ cap->css & 0x01 ? "Supported" : "Not Supported");
printf("\t One or more I/O Command Sets are %s\n",
- (cap->bps_css_nssrs_dstrd & 0x0800) ? "Supported" : "Not Supported");
+ cap->css & 0x40 ? "Supported" : "Not Supported");
printf("\t %s\n",
- (cap->bps_css_nssrs_dstrd & 0x1000) ? "Only Admin Command Set Supported" :
- "I/O Command Set is Supported");
- printf("\tNVM Subsystem Reset Supported (NSSRS): %s\n",
- (cap->bps_css_nssrs_dstrd & 0x0010) ? "Yes":"No");
- printf("\tDoorbell Stride (DSTRD): %u bytes\n",
- 1 << (2 + (cap->bps_css_nssrs_dstrd & 0x000f)));
- printf("\tTimeout (TO): %u ms\n",
- cap->to * 500);
+ cap->css & 0x80 ? "Only Admin Command Set Supported" : "I/O Command Set is Supported");
+ printf("\tNVM Subsystem Reset Supported (NSSRS): %s\n", cap->nssrs ? "Yes" : "No");
+ printf("\tDoorbell Stride (DSTRD): %u bytes\n", 1 << (2 + cap->dstrd));
+ printf("\tTimeout (TO): %u ms\n", cap->to * 500);
printf("\tArbitration Mechanism Supported (AMS): Weighted Round Robin with Urgent Priority Class is %s\n",
- (cap->ams_cqr & 0x02) ? "supported":"not supported");
- printf("\tContiguous Queues Required (CQR): %s\n",
- (cap->ams_cqr & 0x01) ? "Yes":"No");
- printf("\tMaximum Queue Entries Supported (MQES): %u\n\n",
- cap->mqes + 1);
+ cap->ams & 0x02 ? "Supported" : "Not supported");
+ printf("\tContiguous Queues Required (CQR): %s\n", cap->cqr ? "Yes" : "No");
+ printf("\tMaximum Queue Entries Supported (MQES): %u\n\n", cap->mqes + 1);
}
static void stdout_registers_version(__u32 vs)
@@ -2184,9 +2444,9 @@ static void stdout_id_ns_dpc(__u8 dpc)
__u8 pit1 = dpc & 0x1;
if (rsvd)
printf(" [7:5] : %#x\tReserved\n", rsvd);
- printf(" [4:4] : %#x\tProtection Information Transferred as Last 8 Bytes of Metadata %sSupported\n",
+ printf(" [4:4] : %#x\tProtection Information Transferred as Last Bytes of Metadata %sSupported\n",
pil8, pil8 ? "" : "Not ");
- printf(" [3:3] : %#x\tProtection Information Transferred as First 8 Bytes of Metadata %sSupported\n",
+ printf(" [3:3] : %#x\tProtection Information Transferred as First Bytes of Metadata %sSupported\n",
pif8, pif8 ? "" : "Not ");
printf(" [2:2] : %#x\tProtection Information Type 3 %sSupported\n",
pit3, pit3 ? "" : "Not ");
@@ -2204,7 +2464,7 @@ static void stdout_id_ns_dps(__u8 dps)
__u8 pit = dps & 0x7;
if (rsvd)
printf(" [7:4] : %#x\tReserved\n", rsvd);
- printf(" [3:3] : %#x\tProtection Information is Transferred as %s 8 Bytes of Metadata\n",
+ printf(" [3:3] : %#x\tProtection Information is Transferred as %s Bytes of Metadata\n",
pif8, pif8 ? "First" : "Last");
printf(" [2:0] : %#x\tProtection Information %s\n", pit,
pit == 3 ? "Type 3 Enabled" :
@@ -2765,6 +3025,7 @@ static void stdout_id_ctrl(struct nvme_id_ctrl *ctrl,
printf("maxdna : %s\n",
uint128_t_to_l10n_string(le128_to_cpu(ctrl->maxdna)));
printf("maxcna : %u\n", le32_to_cpu(ctrl->maxcna));
+ printf("oaqd : %u\n", le32_to_cpu(ctrl->oaqd));
printf("subnqn : %-.*s\n", (int)sizeof(ctrl->subnqn), ctrl->subnqn);
printf("ioccsz : %u\n", le32_to_cpu(ctrl->ioccsz));
printf("iorcsz : %u\n", le32_to_cpu(ctrl->iorcsz));
@@ -2846,7 +3107,7 @@ static void stdout_nvm_id_ns(struct nvme_nvm_id_ns *nvm_ns, unsigned int nsid,
pif == 1 ? "32b Guard" : "16b Guard",
pif, sts, i == (ns->flbas & 0xf) ? in_use : "");
else
- printf("elbaf %2d : pif:%d lbads:%-2d %s\n", i,
+ printf("elbaf %2d : pif:%d sts:%-2d %s\n", i,
pif, sts, i == (ns->flbas & 0xf) ? in_use : "");
}
}
@@ -3207,8 +3468,8 @@ static void stdout_id_uuid_list(const struct nvme_id_uuid_list *uuid_list)
{
int i, human = stdout_print_ops.flags & VERBOSE;
- /* The 0th entry is reserved */
printf("NVME Identify UUID:\n");
+
for (i = 0; i < NVME_ID_UUID_LIST_MAX; i++) {
__u8 uuid[NVME_UUID_LEN];
char *association = "";
@@ -3560,41 +3821,36 @@ static void stdout_supported_log(struct nvme_supported_log_pages *support_log,
}
}
-static void stdout_endurance_log(struct nvme_endurance_group_log *endurance_log,
- __u16 group_id, const char *devname)
+static void stdout_endurance_log(struct nvme_endurance_group_log *endurance_log, __u16 group_id,
+ const char *devname)
{
- printf("Endurance Group Log for NVME device:%s Group ID:%x\n", devname,
- group_id);
- printf("critical warning : %u\n",
- endurance_log->critical_warning);
+ printf("Endurance Group Log for NVME device:%s Group ID:%x\n", devname, group_id);
+ printf("critical_warning : %u\n", endurance_log->critical_warning);
+ printf("endurance_group_features: %u\n", endurance_log->endurance_group_features);
printf("avl_spare : %u\n", endurance_log->avl_spare);
- printf("avl_spare_threshold : %u\n",
- endurance_log->avl_spare_threshold);
+ printf("avl_spare_threshold : %u\n", endurance_log->avl_spare_threshold);
printf("percent_used : %u%%\n", endurance_log->percent_used);
+ printf("domain_identifier : %u\n", endurance_log->domain_identifier);
printf("endurance_estimate : %s\n",
- uint128_t_to_l10n_string(
- le128_to_cpu(endurance_log->endurance_estimate)));
+ uint128_t_to_l10n_string(le128_to_cpu(endurance_log->endurance_estimate)));
printf("data_units_read : %s\n",
- uint128_t_to_l10n_string(
- le128_to_cpu(endurance_log->data_units_read)));
+ uint128_t_to_l10n_string(le128_to_cpu(endurance_log->data_units_read)));
printf("data_units_written : %s\n",
- uint128_t_to_l10n_string(
- le128_to_cpu(endurance_log->data_units_written)));
+ uint128_t_to_l10n_string(le128_to_cpu(endurance_log->data_units_written)));
printf("media_units_written : %s\n",
- uint128_t_to_l10n_string(
- le128_to_cpu(endurance_log->media_units_written)));
+ uint128_t_to_l10n_string(le128_to_cpu(endurance_log->media_units_written)));
printf("host_read_cmds : %s\n",
- uint128_t_to_l10n_string(
- le128_to_cpu(endurance_log->host_read_cmds)));
+ uint128_t_to_l10n_string(le128_to_cpu(endurance_log->host_read_cmds)));
printf("host_write_cmds : %s\n",
- uint128_t_to_l10n_string(
- le128_to_cpu(endurance_log->host_write_cmds)));
+ uint128_t_to_l10n_string(le128_to_cpu(endurance_log->host_write_cmds)));
printf("media_data_integrity_err: %s\n",
- uint128_t_to_l10n_string(
- le128_to_cpu(endurance_log->media_data_integrity_err)));
+ uint128_t_to_l10n_string(le128_to_cpu(endurance_log->media_data_integrity_err)));
printf("num_err_info_log_entries: %s\n",
- uint128_t_to_l10n_string(
- le128_to_cpu(endurance_log->num_err_info_log_entries)));
+ uint128_t_to_l10n_string(le128_to_cpu(endurance_log->num_err_info_log_entries)));
+ printf("total_end_grp_cap : %s\n",
+ uint128_t_to_l10n_string(le128_to_cpu(endurance_log->total_end_grp_cap)));
+ printf("unalloc_end_grp_cap : %s\n",
+ uint128_t_to_l10n_string(le128_to_cpu(endurance_log->unalloc_end_grp_cap)));
}
static void stdout_smart_log(struct nvme_smart_log *smart, unsigned int nsid,
@@ -4387,28 +4643,30 @@ static void stdout_list_item(nvme_ns_t n)
nvme_ns_get_firmware(n));
}
-static void stdout_simple_list(nvme_root_t r)
+static bool stdout_simple_ns(const char *name, void *arg)
{
- nvme_host_t h;
- nvme_subsystem_t s;
- nvme_ctrl_t c;
+ struct nvme_resources *res = arg;
nvme_ns_t n;
+ n = htable_ns_get(&res->ht_n, name);
+ stdout_list_item(n);
+
+ return true;
+}
+
+static void stdout_simple_list(nvme_root_t r)
+{
+ struct nvme_resources res;
+
+ nvme_resources_init(r, &res);
+
printf("%-21s %-21s %-20s %-40s %-10s %-26s %-16s %-8s\n",
"Node", "Generic", "SN", "Model", "Namespace", "Usage", "Format", "FW Rev");
printf("%-.21s %-.21s %-.20s %-.40s %-.10s %-.26s %-.16s %-.8s\n",
dash, dash, dash, dash, dash, dash, dash, dash);
+ strset_iterate(&res.namespaces, stdout_simple_ns, &res);
- nvme_for_each_host(r, h) {
- nvme_for_each_subsystem(h, s) {
- nvme_subsystem_for_each_ns(s, n)
- stdout_list_item(n);
-
- nvme_subsystem_for_each_ctrl(s, c)
- nvme_ctrl_for_each_ns(c, n)
- stdout_list_item(n);
- }
- }
+ nvme_resources_free(&res);
}
static void stdout_ns_details(nvme_ns_t n)
@@ -4435,100 +4693,155 @@ static void stdout_ns_details(nvme_ns_t n)
genname, nvme_ns_get_nsid(n), usage, format);
}
-static void stdout_detailed_list(nvme_root_t r)
+static bool stdout_detailed_name(const char *name, void *arg)
{
- nvme_host_t h;
+ bool *first = arg;
+
+ printf("%s%s", *first ? "" : ", ", name);
+ *first = false;
+
+ return true;
+}
+
+static bool stdout_detailed_subsys(const char *name, void *arg)
+{
+ struct nvme_resources *res = arg;
+ struct htable_subsys_iter it;
+ struct strset ctrls;
nvme_subsystem_t s;
nvme_ctrl_t c;
- nvme_path_t p;
- nvme_ns_t n;
-
- printf("%-16s %-96s %-.16s\n", "Subsystem", "Subsystem-NQN", "Controllers");
- printf("%-.16s %-.96s %-.16s\n", dash, dash, dash);
+ bool first;
- nvme_for_each_host(r, h) {
- nvme_for_each_subsystem(h, s) {
- bool first = true;
- printf("%-16s %-96s ", nvme_subsystem_get_name(s),
- nvme_subsystem_get_nqn(s));
+ strset_init(&ctrls);
+ first = true;
+ for (s = htable_subsys_getfirst(&res->ht_s, name, &it);
+ s;
+ s = htable_subsys_getnext(&res->ht_s, name, &it)) {
- nvme_subsystem_for_each_ctrl(s, c) {
- printf("%s%s", first ? "": ", ",
- nvme_ctrl_get_name(c));
- first = false;
- }
- printf("\n");
+ if (first) {
+ printf("%-16s %-96s ", name, nvme_subsystem_get_nqn(s));
+ first = false;
}
+
+ nvme_subsystem_for_each_ctrl(s, c)
+ strset_add(&ctrls, nvme_ctrl_get_name(c));
}
+
+ first = true;
+ strset_iterate(&ctrls, stdout_detailed_name, &first);
+ strset_clear(&ctrls);
printf("\n");
- printf("%-8s %-20s %-40s %-8s %-6s %-14s %-6s %-12s %-16s\n", "Device",
- "SN", "MN", "FR", "TxPort", "Address", "Slot", "Subsystem", "Namespaces");
- printf("%-.8s %-.20s %-.40s %-.8s %-.6s %-.14s %-.6s %-.12s %-.16s\n", dash,
- dash, dash, dash, dash, dash, dash, dash, dash);
+ return true;
+}
- nvme_for_each_host(r, h) {
- nvme_for_each_subsystem(h, s) {
- nvme_subsystem_for_each_ctrl(s, c) {
- bool first = true;
+static bool stdout_detailed_ctrl(const char *name, void *arg)
+{
+ struct nvme_resources *res = arg;
+ struct strset namespaces;
+ nvme_ctrl_t c;
+ nvme_path_t p;
+ nvme_ns_t n;
+ bool first;
+
+ c = htable_ctrl_get(&res->ht_c, name);
+ assert(c);
+
+ printf("%-8s %-20s %-40s %-8s %-6s %-14s %-6s %-12s ",
+ nvme_ctrl_get_name(c),
+ nvme_ctrl_get_serial(c),
+ nvme_ctrl_get_model(c),
+ nvme_ctrl_get_firmware(c),
+ nvme_ctrl_get_transport(c),
+ nvme_ctrl_get_address(c),
+ nvme_ctrl_get_phy_slot(c),
+ nvme_subsystem_get_name(nvme_ctrl_get_subsystem(c)));
+
+ strset_init(&namespaces);
+
+ nvme_ctrl_for_each_ns(c, n)
+ strset_add(&namespaces, nvme_ns_get_name(n));
+ nvme_ctrl_for_each_path(c, p) {
+ n = nvme_path_get_ns(p);
+ if (!n)
+ continue;
+ strset_add(&namespaces, nvme_ns_get_name(n));
+ }
- printf("%-8s %-20s %-40s %-8s %-6s %-14s %-6s %-12s ",
- nvme_ctrl_get_name(c),
- nvme_ctrl_get_serial(c),
- nvme_ctrl_get_model(c),
- nvme_ctrl_get_firmware(c),
- nvme_ctrl_get_transport(c),
- nvme_ctrl_get_address(c),
- nvme_ctrl_get_phy_slot(c),
- nvme_subsystem_get_name(s));
+ first = true;
+ strset_iterate(&namespaces, stdout_detailed_name, &first);
+ strset_clear(&namespaces);
- nvme_ctrl_for_each_ns(c, n) {
- printf("%s%s", first ? "": ", ",
- nvme_ns_get_name(n));
- first = false;
- }
+ printf("\n");
- nvme_ctrl_for_each_path(c, p) {
- n = nvme_path_get_ns(p);
- if (!n)
- continue;
- printf("%s%s", first ? "": ", ",
- nvme_ns_get_name(n));
- first = false;
- }
- printf("\n");
- }
+ return true;
+}
+
+static bool stdout_detailed_ns(const char *name, void *arg)
+{
+ struct nvme_resources *res = arg;
+ struct htable_ns_iter it;
+ struct strset ctrls;
+ nvme_ctrl_t c;
+ nvme_path_t p;
+ nvme_ns_t n;
+ bool first;
+
+ strset_init(&ctrls);
+ first = true;
+ for (n = htable_ns_getfirst(&res->ht_n, name, &it);
+ n;
+ n = htable_ns_getnext(&res->ht_n, name, &it)) {
+
+ if (first) {
+ stdout_ns_details(n);
+ first = false;
+ }
+
+ if (nvme_ns_get_ctrl(n)) {
+ printf("%s\n", nvme_ctrl_get_name(nvme_ns_get_ctrl(n)));
+ return true;
+ }
+
+ nvme_namespace_for_each_path(n, p) {
+ c = nvme_path_get_ctrl(p);
+ strset_add(&ctrls, nvme_ctrl_get_name(c));
}
}
+
+ first = true;
+ strset_iterate(&ctrls, stdout_detailed_name, &first);
+ strset_clear(&ctrls);
+
+ printf("\n");
+ return true;
+}
+
+static void stdout_detailed_list(nvme_root_t r)
+{
+ struct nvme_resources res;
+
+ nvme_resources_init(r, &res);
+
+ printf("%-16s %-96s %-.16s\n", "Subsystem", "Subsystem-NQN", "Controllers");
+ printf("%-.16s %-.96s %-.16s\n", dash, dash, dash);
+ strset_iterate(&res.subsystems, stdout_detailed_subsys, &res);
+ printf("\n");
+
+ printf("%-8s %-20s %-40s %-8s %-6s %-14s %-6s %-12s %-16s\n", "Device",
+ "SN", "MN", "FR", "TxPort", "Asdress", "Slot", "Subsystem", "Namespaces");
+ printf("%-.8s %-.20s %-.40s %-.8s %-.6s %-.14s %-.6s %-.12s %-.16s\n", dash,
+ dash, dash, dash, dash, dash, dash, dash, dash);
+ strset_iterate(&res.ctrls, stdout_detailed_ctrl, &res);
printf("\n");
printf("%-12s %-12s %-10s %-26s %-16s %-16s\n", "Device", "Generic",
"NSID", "Usage", "Format", "Controllers");
printf("%-.12s %-.12s %-.10s %-.26s %-.16s %-.16s\n", dash, dash, dash,
dash, dash, dash);
+ strset_iterate(&res.namespaces, stdout_detailed_ns, &res);
- nvme_for_each_host(r, h) {
- nvme_for_each_subsystem(h, s) {
- nvme_subsystem_for_each_ctrl(s, c) {
- nvme_ctrl_for_each_ns(c, n) {
- stdout_ns_details(n);
- printf("%s\n", nvme_ctrl_get_name(c));
- }
- }
-
- nvme_subsystem_for_each_ns(s, n) {
- bool first = true;
-
- stdout_ns_details(n);
- nvme_subsystem_for_each_ctrl(s, c) {
- printf("%s%s", first ? "" : ", ",
- nvme_ctrl_get_name(c));
- first = false;
- }
- printf("\n");
- }
- }
- }
+ nvme_resources_free(&res);
}
static void stdout_list_items(nvme_root_t r)
@@ -4560,6 +4873,9 @@ static void stdout_subsystem_topology_multipath(nvme_subsystem_t s,
if (ranking == NVME_CLI_TOPO_NAMESPACE) {
nvme_subsystem_for_each_ns(s, n) {
+ if (!nvme_namespace_first_path(n))
+ continue;
+
printf(" +- ns %d\n", nvme_ns_get_nsid(n));
printf(" \\\n");
@@ -4638,12 +4954,22 @@ static void stdout_simple_topology(nvme_root_t r,
{
nvme_host_t h;
nvme_subsystem_t s;
+ bool first = true;
nvme_for_each_host(r, h) {
nvme_for_each_subsystem(h, s) {
+ int len = strlen(nvme_subsystem_get_name(s));
+
+ if (!first)
+ printf("\n");
+ first = false;
printf("%s - NQN=%s\n", nvme_subsystem_get_name(s),
nvme_subsystem_get_nqn(s));
+ printf("%*s hostnqn=%s\n", len, " ",
+ nvme_host_get_hostnqn(nvme_subsystem_get_host(s)));
+ printf("%*s iopolicy=%s\n", len, " ",
+ nvme_subsystem_get_iopolicy(s));
printf("\\\n");
if (nvme_is_multipath(s))
@@ -4727,6 +5053,7 @@ static void stdout_connect_msg(nvme_ctrl_t c)
static struct print_ops stdout_print_ops = {
.ana_log = stdout_ana_log,
.boot_part_log = stdout_boot_part_log,
+ .phy_rx_eom_log = stdout_phy_rx_eom_log,
.ctrl_list = stdout_list_ctrl,
.ctrl_registers = stdout_ctrl_registers,
.directive = stdout_directive_show,