From: Minwoo Im Date: Sun, 15 Apr 2018 17:34:41 +0000 (+0900) Subject: nvme-cli: add support for id-nvmset subcommand X-Git-Tag: v1.6~29^2~2 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=3bbde78b909ecac3436be7fcba4bb4513a1b9ef8;p=users%2Fsagi%2Fnvme-cli.git nvme-cli: add support for id-nvmset subcommand Identify for NVM Set List has been added and it can be found in TP 4018. This identify CNS 0x4 uses CDW11 as a NVM Set Identify(NVMSETID). Currently nvme-cli is not using cdw11 for the identify command. Therefore make it available for cdw11 to be passed to ioctl command by adding nvme_identify13() to support the new CNS. Signed-off-by: Minwoo Im --- diff --git a/linux/nvme.h b/linux/nvme.h index 982bd9e1..a72c1b28 100644 --- a/linux/nvme.h +++ b/linux/nvme.h @@ -330,6 +330,7 @@ enum { NVME_ID_CNS_CTRL = 0x01, NVME_ID_CNS_NS_ACTIVE_LIST = 0x02, NVME_ID_CNS_NS_DESC_LIST = 0x03, + NVME_ID_CNS_NVMSET_LIST = 0x04, NVME_ID_CNS_NS_PRESENT_LIST = 0x10, NVME_ID_CNS_NS_PRESENT = 0x11, NVME_ID_CNS_CTRL_NS_LIST = 0x12, @@ -385,6 +386,25 @@ enum { NVME_NIDT_UUID = 0x03, }; +#define NVME_MAX_NVMSET 31 + +struct nvme_nvmset_attr_entry { + __le16 id; + __le16 endurance_group_id; + __u8 rsvd4[4]; + __le32 random_4k_read_typical; + __le32 opt_write_size; + __u8 total_nvmset_cap[16]; + __u8 unalloc_nvmset_cap[16]; + __u8 rsvd48[80]; +}; + +struct nvme_id_nvmset { + __u8 nid; + __u8 rsvd1[127]; + struct nvme_nvmset_attr_entry ent[NVME_MAX_NVMSET]; +}; + /* Derived from 1.3a Figure 101: Get Log Page – Telemetry Host * -Initiated Log (Log Identifier 07h) */ diff --git a/nvme-builtin.h b/nvme-builtin.h index adfa5200..86b0fff1 100644 --- a/nvme-builtin.h +++ b/nvme-builtin.h @@ -13,6 +13,7 @@ COMMAND_LIST( ENTRY("id-ns", "Send NVMe Identify Namespace, display structure", id_ns) ENTRY("list-ns", "Send NVMe Identify List, display structure", list_ns) ENTRY("ns-descs", "Send NVMe Namespace Descriptor List, display structure", ns_descs) + ENTRY("id-nvmset", "Sned NVMe Identify NVM Set List, display structure", id_nvmset) ENTRY("create-ns", "Creates a namespace with the provided parameters", create_ns) ENTRY("delete-ns", "Deletes a namespace from the controller", delete_ns) ENTRY("attach-ns", "Attaches a namespace to requested controller(s)", attach_ns) diff --git a/nvme-ioctl.c b/nvme-ioctl.c index 4cf815b5..d2825389 100644 --- a/nvme-ioctl.c +++ b/nvme-ioctl.c @@ -357,7 +357,7 @@ int nvme_passthru_admin(int fd, __u8 opcode, __u8 flags, __u16 rsvd, metadata, timeout_ms, NULL); } -int nvme_identify(int fd, __u32 nsid, __u32 cdw10, void *data) +int nvme_identify13(int fd, __u32 nsid, __u32 cdw10, __u32 cdw11, void *data) { struct nvme_admin_cmd cmd = { .opcode = nvme_admin_identify, @@ -365,11 +365,17 @@ int nvme_identify(int fd, __u32 nsid, __u32 cdw10, void *data) .addr = (__u64)(uintptr_t) data, .data_len = NVME_IDENTIFY_DATA_SIZE, .cdw10 = cdw10, + .cdw11 = cdw11, }; return nvme_submit_admin_passthru(fd, &cmd); } +int nvme_identify(int fd, __u32 nsid, __u32 cdw10, void *data) +{ + return nvme_identify13(fd, nsid, cdw10, 0, data); +} + int nvme_identify_ctrl(int fd, void *data) { return nvme_identify(fd, 0, 1, data); @@ -402,6 +408,11 @@ int nvme_identify_ns_descs(int fd, __u32 nsid, void *data) return nvme_identify(fd, nsid, NVME_ID_CNS_NS_DESC_LIST, data); } +int nvme_identify_nvmset(int fd, __u16 nvmset_id, void *data) +{ + return nvme_identify13(fd, 0, NVME_ID_CNS_NVMSET_LIST, nvmset_id, data); +} + int nvme_get_log13(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo, __u16 lsi, __u32 data_len, void *data) { diff --git a/nvme-ioctl.h b/nvme-ioctl.h index 75f8104e..0d58be87 100644 --- a/nvme-ioctl.h +++ b/nvme-ioctl.h @@ -80,12 +80,14 @@ int nvme_passthru_admin(int fd, __u8 opcode, __u8 flags, __u16 rsvd, __u32 data_len, void *data, __u32 metadata_len, void *metadata, __u32 timeout); +int nvme_identify13(int fd, __u32 nsid, __u32 cdw10, __u32 cdw11, void *data); int nvme_identify(int fd, __u32 nsid, __u32 cdw10, void *data); int nvme_identify_ctrl(int fd, void *data); int nvme_identify_ns(int fd, __u32 nsid, bool present, void *data); int nvme_identify_ns_list(int fd, __u32 nsid, bool all, void *data); int nvme_identify_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data); int nvme_identify_ns_descs(int fd, __u32 nsid, void *data); +int nvme_identify_nvmset(int fd, __u16 nvmset_id, void *data); int nvme_get_log13(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo, __u16 group_id, __u32 data_len, void *data); int nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data); diff --git a/nvme-print.c b/nvme-print.c index 3f679d23..bc5f1ee2 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -949,6 +949,63 @@ void show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode) __show_nvme_id_ctrl(ctrl, mode, NULL); } +void show_nvme_id_nvmset(struct nvme_id_nvmset *nvmset) +{ + int i; + + printf("nid : %d\n", nvmset->nid); + printf(".................\n"); + for (i = 0; i < nvmset->nid; i++) { + printf(" NVM Set Attribute Entry[%2d]\n", i); + printf(".................\n"); + printf("nvmset_id : %d\n", + le16_to_cpu(nvmset->ent[i].id)); + printf("enduracne_group_id : %d\n", + le16_to_cpu(nvmset->ent[i].endurance_group_id)); + printf("random_4k_read_typical : %u\n", + le32_to_cpu(nvmset->ent[i].random_4k_read_typical)); + printf("optimal_write_size : %u\n", + le32_to_cpu(nvmset->ent[i].opt_write_size)); + printf("total_nvmset_cap : %.0Lf\n", + int128_to_double(nvmset->ent[i].total_nvmset_cap)); + printf("unalloc_nvmset_cap : %.0Lf\n", + int128_to_double(nvmset->ent[i].unalloc_nvmset_cap)); + printf(".................\n"); + } +} + +void json_nvme_id_nvmset(struct nvme_id_nvmset *nvmset, const char *devname) +{ + struct json_object *root; + struct json_array *entries; + __u32 nent = le32_to_cpu(nvmset->nid); + int i; + + root = json_create_object(); + + json_object_add_value_int(root, "nid", nent); + + entries = json_create_array(); + for (i = 0; i < nent; i++) { + struct json_object *entry = json_create_object(); + + json_object_add_value_int(entry, "nvmset_id", le16_to_cpu(nvmset->ent[i].id)); + json_object_add_value_int(entry, "endurance_group_id", le16_to_cpu(nvmset->ent[i].endurance_group_id)); + json_object_add_value_int(entry, "random_4k_read_typical", le32_to_cpu(nvmset->ent[i].random_4k_read_typical)); + json_object_add_value_int(entry, "optimal_write_size", le32_to_cpu(nvmset->ent[i].opt_write_size)); + json_object_add_value_float(entry, "total_nvmset_cap", int128_to_double(nvmset->ent[i].total_nvmset_cap)); + json_object_add_value_float(entry, "unalloc_nvmset_cap", int128_to_double(nvmset->ent[i].unalloc_nvmset_cap)); + + json_array_add_value_object(entries, entry); + } + + json_object_add_value_array(root, "NVMSet", entries); + + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + void show_error_log(struct nvme_error_log_page *err_log, int entries, const char *devname) { int i; diff --git a/nvme-print.h b/nvme-print.h index 98e15021..7dd5f343 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -34,6 +34,7 @@ void show_ctrl_registers(void *bar, unsigned int mode, bool fabrics); void show_nvme_id_ns_descs(void *data); void show_list_items(struct list_item *list_items, unsigned len); void show_nvme_subsystem_list(struct subsys_list_item *slist, int n); +void show_nvme_id_nvmset(struct nvme_id_nvmset *nvmset); void nvme_feature_show_fields(__u32 fid, unsigned int result, unsigned char *buf); void nvme_directive_show_fields(__u8 dtype, __u8 doper, unsigned int result, unsigned char *buf); @@ -56,6 +57,7 @@ void json_print_list_items(struct list_item *items, unsigned amnt); void json_nvme_id_ns_descs(void *data); void json_print_nvme_subsystem_list(struct subsys_list_item *slist, int n); void json_self_test_log(struct nvme_self_test_log *self_test, const char *devname); +void json_nvme_id_nvmset(struct nvme_id_nvmset *nvmset, const char *devname); #endif diff --git a/nvme.c b/nvme.c index 440cb246..db0337ac 100644 --- a/nvme.c +++ b/nvme.c @@ -1798,6 +1798,65 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug return err; } +static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Send an Identify NVM Set List command to the "\ + "given device, returns entries for NVM Set identifiers greater "\ + "than or equal to the value specified CDW11.NVMSETID "\ + "in either binary format or json format"; + const char *nvmset_id = "NVM Set Identify value"; + int err, fmt, fd; + struct nvme_id_nvmset nvmset; + + struct config { + __u16 nvmset_id; + char *output_format; + }; + + struct config cfg = { + .nvmset_id = 0, + .output_format = "normal", + }; + + const struct argconfig_commandline_options command_line_options[] = { + {"nvmset_id", 'i', "NUM", CFG_POSITIVE, &cfg.nvmset_id, required_argument, nvmset_id}, + {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format }, + {NULL} + }; + + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; + + fmt = validate_output_format(cfg.output_format); + if (fmt < 0) { + err = fmt; + goto close_fd; + } + + err = nvme_identify_nvmset(fd, cfg.nvmset_id, &nvmset); + if (!err) { + if (fmt == BINARY) + d_raw((unsigned char *)&nvmset, sizeof(nvmset)); + else if (fmt == JSON) + json_nvme_id_nvmset(&nvmset, devicename); + else { + printf("NVME Identify NVM Set List %d:\n", cfg.nvmset_id); + show_nvme_id_nvmset(&nvmset); + } + } + else if (err > 0) + fprintf(stderr, "NVMe Status:%s(%x) NVMSETID:%d\n", + nvme_status_to_string(err), err, cfg.nvmset_id); + else + perror("identify nvm set list"); + + close_fd: + close(fd); + + return err; +} + static int get_ns_id(int argc, char **argv, struct command *cmd, struct plugin *plugin) { int nsid, fd;