1
0
Fork 0

Adding upstream version 2.6.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-16 12:24:26 +01:00
parent acf5b2ec4c
commit 83f51a6dde
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
262 changed files with 7434 additions and 3024 deletions

View file

@ -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 bool stdout_simple_ns(const char *name, void *arg)
{
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)
{
nvme_host_t h;
nvme_subsystem_t s;
nvme_ctrl_t c;
nvme_ns_t n;
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;
bool first;
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)) {
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");
return 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));
}
first = true;
strset_iterate(&namespaces, stdout_detailed_name, &first);
strset_clear(&namespaces);
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);
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));
nvme_subsystem_for_each_ctrl(s, c) {
printf("%s%s", first ? "": ", ",
nvme_ctrl_get_name(c));
first = false;
}
printf("\n");
}
}
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", "Address", "Slot", "Subsystem", "Namespaces");
"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);
nvme_for_each_host(r, h) {
nvme_for_each_subsystem(h, s) {
nvme_subsystem_for_each_ctrl(s, c) {
bool first = true;
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));
nvme_ctrl_for_each_ns(c, n) {
printf("%s%s", first ? "": ", ",
nvme_ns_get_name(n));
first = false;
}
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");
}
}
}
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,