From b8a403b272a342c2a313c710ca05ed48032f63c6 Mon Sep 17 00:00:00 2001 From: Nate Roiger Date: Fri, 2 Apr 2021 19:59:19 -0500 Subject: [PATCH] Add NVMe MI Features: Controller Metadata (0x7E) and Namespace Metadata (0x7F). Signed-off-by: Nate Roiger --- linux/nvme.h | 31 +++++++++++++++++++++++- nvme-print.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++- nvme.c | 6 +++-- 3 files changed, 100 insertions(+), 4 deletions(-) diff --git a/linux/nvme.h b/linux/nvme.h index 4ad09eec..17d41970 100644 --- a/linux/nvme.h +++ b/linux/nvme.h @@ -1191,6 +1191,31 @@ struct nvme_feat_auto_pst { __le64 entries[32]; }; +struct nvme_mi_host_metadata_element_desc { + __u8 type; /* Element Type */ + __u8 rev; /* Element Revision */ + __u16 len; /* Element Length */ + __u8 val[0]; /* Element Value (UTF-8) */ +}; + +struct nvme_mi_host_metadata { + __u8 ndesc; + __u8 rsvd1; + struct nvme_mi_host_metadata_element_desc descs[0]; +}; + +enum { + NVME_MI_CTRL_METADATA_OS_CTRL_NAME = 0x01, + NVME_MI_CTRL_METADATA_OS_DRIVER_NAME = 0x02, + NVME_MI_CTRL_METADATA_OS_DRIVER_VER = 0x03, + NVME_MI_CTRL_METADATA_PRE_BOOT_CTRL_NAME = 0x04, + NVME_MI_CTRL_METADATA_PRE_BOOT_DRIVER_NAME = 0x05, + NVME_MI_CTRL_METADATA_PRE_BOOT_DRIVER_VER = 0x06, + + NVME_MI_NS_METADATA_OS_NS_NAME = 0x01, + NVME_MI_NS_METADATA_PRE_BOOT_NS_NAME = 0x02, +}; + enum { NVME_HOST_MEM_ENABLE = (1 << 0), NVME_HOST_MEM_RETURN = (1 << 1), @@ -1284,13 +1309,17 @@ enum nvme_feat { NVME_LBA_STATUS_INFO = 0x15, NVME_FEAT_HOST_BEHAVIOR = 0x16, NVME_FEAT_SANITIZE = 0x17, - NVME_FEAT_ENDURANCE = 0x18, + NVME_FEAT_ENDURANCE = 0x18, NVME_FEAT_IOCS_PROFILE = 0x19, NVME_FEAT_SW_PROGRESS = 0x80, NVME_FEAT_HOST_ID = 0x81, NVME_FEAT_RESV_MASK = 0x82, NVME_FEAT_RESV_PERSIST = 0x83, NVME_FEAT_WRITE_PROTECT = 0x84, + + NVME_MI_FEAT_CTRL_METADATA = 0x7E, + NVME_MI_FEAT_NS_METADATA = 0x7F, + } __attribute__ ((__packed__)); enum { diff --git a/nvme-print.c b/nvme-print.c index 1a8f3cde..83819499 100755 --- a/nvme-print.c +++ b/nvme-print.c @@ -5085,7 +5085,7 @@ const char *nvme_feature_to_string(enum nvme_feat feature) case NVME_FEAT_PLM_CONFIG: return "Predicatable Latency Mode Config"; case NVME_FEAT_PLM_WINDOW: return "Predicatable Latency Mode Window"; case NVME_LBA_STATUS_INFO: return "LBA Status Infomation Attributes"; - case NVME_FEAT_ENDURANCE: return "Enduarance Event Group Configuration"; + case NVME_FEAT_ENDURANCE: return "Enduarance Event Group Configuration"; case NVME_FEAT_IOCS_PROFILE: return "I/O Command Set Profile"; case NVME_FEAT_SW_PROGRESS: return "Software Progress"; case NVME_FEAT_HOST_ID: return "Host Identifier"; @@ -5096,6 +5096,8 @@ const char *nvme_feature_to_string(enum nvme_feat feature) case NVME_FEAT_HCTM: return "Host Controlled Thermal Management"; case NVME_FEAT_HOST_BEHAVIOR: return "Host Behavior"; case NVME_FEAT_SANITIZE: return "Sanitize"; + case NVME_MI_FEAT_CTRL_METADATA:return "MI Controller Metadata"; + case NVME_MI_FEAT_NS_METADATA: return "MI Namespace Metadata"; } /* * We don't use the "default:" statement to let the compiler warning if @@ -5602,6 +5604,65 @@ static void nvme_show_plm_config(struct nvme_plm_config *plmcfg) printf("\tDTWIN Time Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwin_time_thresh)); } +static char* nvme_show_mi_host_metadata_type_to_string(enum nvme_feat fid, __u8 type) +{ + switch (fid) { + case NVME_MI_FEAT_CTRL_METADATA: + switch (type) { + case NVME_MI_CTRL_METADATA_OS_CTRL_NAME: + return "Operating System Controller Name"; + case NVME_MI_CTRL_METADATA_OS_DRIVER_NAME: + return "Operating System Driver Name"; + case NVME_MI_CTRL_METADATA_OS_DRIVER_VER: + return "Operating System Driver Version"; + case NVME_MI_CTRL_METADATA_PRE_BOOT_CTRL_NAME: + return "Pre-boot Controller Name"; + case NVME_MI_CTRL_METADATA_PRE_BOOT_DRIVER_NAME: + return "Pre-boot Driver Name"; + case NVME_MI_CTRL_METADATA_PRE_BOOT_DRIVER_VER: + return "Pre-boot Driver Version"; + default: + return "Unknown Controller Type"; + } + case NVME_MI_FEAT_NS_METADATA: + switch (type) { + case NVME_MI_NS_METADATA_OS_NS_NAME: + return "Operating System Namespace Name"; + case NVME_MI_NS_METADATA_PRE_BOOT_NS_NAME: + return "Pre-boot Namespace Name"; + default: + return "Unknown Namespace Type"; + } + default: + return "Unknown Feature"; + } +} + +static void nvme_show_mi_host_metadata(enum nvme_feat fid, + struct nvme_mi_host_metadata *data) +{ + struct nvme_mi_host_metadata_element_desc *desc = &data->descs[0]; + int i; + char val[4096]; + __u16 len; + + printf("\tNum Metadata Element Descriptors: %d\n", data->ndesc); + for (i = 0; i < data->ndesc; i++) { + len = le16_to_cpu(desc->len); + strncpy(val, (char *)desc->val, min(sizeof(val) - 1, len)); + + printf("\tElement[%-3d]:\n", i); + printf("\t\tType : 0x%02x (%s)\n", desc->type, + nvme_show_mi_host_metadata_type_to_string(fid, desc->type)); + printf("\t\tRevision : %d\n", desc->rev); + printf("\t\tLength : %d\n", len); + printf("\t\tValue : %s\n", val); + + desc = (struct nvme_mi_host_metadata_element_desc *) + &desc->val[desc->len]; + } +} + void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, unsigned char *buf) { __u8 field; @@ -5737,6 +5798,10 @@ void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, unsigned case NVME_FEAT_RRL: printf("\tRead Recovery Level (RRL): %u\n", result & 0xf); break; + case NVME_MI_FEAT_CTRL_METADATA: + case NVME_MI_FEAT_NS_METADATA: + nvme_show_mi_host_metadata(fid, (struct nvme_mi_host_metadata *)buf); + break; } } diff --git a/nvme.c b/nvme.c index 926651f5..0c980e32 100644 --- a/nvme.c +++ b/nvme.c @@ -91,7 +91,9 @@ static __u16 nvme_feat_buf_len[0x100] = { [NVME_FEAT_HOST_ID] = 8, [NVME_FEAT_PLM_CONFIG] = 512, [NVME_FEAT_TIMESTAMP] = 8, - [NVME_FEAT_HOST_BEHAVIOR] = 512 + [NVME_FEAT_HOST_BEHAVIOR] = 512, + [NVME_MI_FEAT_CTRL_METADATA] = 4096, + [NVME_MI_FEAT_NS_METADATA] = 4096, }; const char *output_format = "Output format: normal|json|binary"; @@ -3654,7 +3656,7 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin memset(buf, 0, cfg.data_len); memcpy(buf, &number, NVME_FEAT_TIMESTAMP_DATA_SIZE); } - } + } } err = nvme_set_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.value, -- 2.50.1