]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme-cli: add support for id-nvmset subcommand
authorMinwoo Im <minwoo.im.dev@gmail.com>
Sun, 15 Apr 2018 17:34:41 +0000 (02:34 +0900)
committerMinwoo Im <minwoo.im.dev@gmail.com>
Sun, 10 Jun 2018 12:09:32 +0000 (21:09 +0900)
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 <minwoo.im.dev@gmail.com>
linux/nvme.h
nvme-builtin.h
nvme-ioctl.c
nvme-ioctl.h
nvme-print.c
nvme-print.h
nvme.c

index 982bd9e1f06c6a95cd81fb6272701dfe80b0aa14..a72c1b28e4c3be63963257238529b07d9c4e3a57 100644 (file)
@@ -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)
  */
index adfa520095761ba5ca5742a2dbe60ee95585b908..86b0fff1932a8741bba20c06ed201abbfe744a61 100644 (file)
@@ -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)
index 4cf815b53bdcb5282e41e79341eca5f36779a484..d2825389fd698c24b639e4e04ccccea62e844a04 100644 (file)
@@ -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)
 {
index 75f8104e3754f82ede4c31a99cd03d8794f9a9c9..0d58be87345d14b5e026e9e36788a8f3ff27cefe 100644 (file)
@@ -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);
index 3f679d23cea0a9ad98196d929062dd201b6ff93c..bc5f1ee28c81da5b2b918eeccad85ccef687a1d6 100644 (file)
@@ -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;
index 98e15021d4720059280e70b5f8870ba279c5a4d3..7dd5f3430ac2316fa8ae27f4a6f319aabc2b892f 100644 (file)
@@ -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 440cb24668d14435883f23af8c11f99336a17032..db0337ac70e9ea3cb0f2859231e3324970ba5b6a 100644 (file)
--- 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;