From 31f73521b81fcb1bcd3ba62ecbc1a5f7c20beb5e Mon Sep 17 00:00:00 2001 From: Steven Seungcheol Lee Date: Wed, 25 Aug 2021 17:24:02 +0900 Subject: [PATCH] nvme: Add Identify for CNS 08h NVMe spec 2.0a based I/O Command Set Independent Identify Namespace data structure (CNS 08h) Most of data comes from existing data of id-ns which is common from All I/O command set Signed-off-by: Steven Seungcheol Lee [dwagner: ported from monolitic branch and updated context] Signed-off-by: Daniel Wagner --- nvme-builtin.h | 1 + nvme-print.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++ nvme-print.h | 3 ++ nvme.c | 67 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+) diff --git a/nvme-builtin.h b/nvme-builtin.h index 80839410..53cea348 100644 --- a/nvme-builtin.h +++ b/nvme-builtin.h @@ -17,6 +17,7 @@ COMMAND_LIST( ENTRY("nvm-id-ctrl", "Send NVMe Identify Controller NVM Command Set, display structure", nvm_id_ctrl) ENTRY("primary-ctrl-caps", "Send NVMe Identify Primary Controller Capabilities", primary_ctrl_caps) ENTRY("list-secondary", "List Secondary Controllers associated with a Primary Controller", list_secondary_ctrl) + ENTRY("cmdset-ind-id-ns", "I/O Command Set Independent Identify Namespace", cmd_set_independent_id_ns) ENTRY("ns-descs", "Send NVMe Namespace Descriptor List, display structure", ns_descs) ENTRY("id-nvmset", "Send NVMe Identify NVM Set List, display structure", id_nvmset) ENTRY("id-uuid", "Send NVMe Identify UUID List, display structure", id_uuid) diff --git a/nvme-print.c b/nvme-print.c index 424769a4..e89d2361 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -3542,6 +3542,88 @@ void nvme_show_id_ns(struct nvme_id_ns *ns, unsigned int nsid, } } +static void nvme_show_cmd_set_independent_id_ns_nsfeat(__u8 nsfeat) +{ + __u8 rsvd5 = (nsfeat & 0xE0) >> 5; + __u8 rmedia = (nsfeat & 0x10) >> 4; + __u8 uidreuse = (nsfeat & 0x8) >> 3; + __u8 rsvd0 = (nsfeat & 0x7); + if (rsvd5) + printf(" [7:5] : %#x\tReserved\n", rsvd5); + printf(" [4:4] : %#x\tNamespace %sstore data on rotational media\n", + rmedia, rmedia ? "" : "does not "); + printf(" [3:3] : %#x\tNGUID and EUI64 fields if non-zero, %sReused\n", + uidreuse, uidreuse ? "Never " : ""); + if (rsvd0) + printf(" [2:0] : %#x\tReserved\n", rsvd0); + printf("\n"); +} + +static void nvme_show_cmd_set_independent_id_ns_nstat(__u8 nstat) +{ + __u8 rsvd1 = (nstat & 0xfe) >> 1; + __u8 nrdy = nstat & 0x1; + if (rsvd1) + printf(" [7:1] : %#x\tReserved\n", rsvd1); + printf(" [0:0] : %#x\tName space is %sready\n", + nrdy, nrdy ? "" : "not "); + printf("\n"); +} + +static void json_nvme_cmd_set_independent_id_ns( + struct nvme_id_independent_id_ns *ns) +{ + struct json_object *root; + root = json_create_object(); + + json_object_add_value_int(root, "nsfeat", ns->nsfeat); + json_object_add_value_int(root, "nmic", ns->nmic); + json_object_add_value_int(root, "rescap", ns->rescap); + json_object_add_value_int(root, "fpi", ns->fpi); + json_object_add_value_int(root, "anagrpid", le32_to_cpu(ns->anagrpid)); + json_object_add_value_int(root, "nsattr", ns->nsattr); + json_object_add_value_int(root, "nvmsetid", le16_to_cpu(ns->nvmsetid)); + json_object_add_value_int(root, "endgid", le16_to_cpu(ns->endgid)); + json_object_add_value_int(root, "nstat", ns->nstat); + + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +void nvme_show_cmd_set_independent_id_ns( + struct nvme_id_independent_id_ns *ns, unsigned int nsid, + enum nvme_print_flags flags) +{ + int human = flags & VERBOSE; + + if (flags & BINARY) + return d_raw((unsigned char *)ns, sizeof(*ns)); + if (flags & JSON) + return json_nvme_cmd_set_independent_id_ns(ns); + + printf("NVME Identify Command Set Idependent Namespace %d:\n", nsid); + printf("nsfeat : %#x\n", ns->nsfeat); + if (human) + nvme_show_cmd_set_independent_id_ns_nsfeat(ns->nsfeat); + printf("nmic : %#x\n", ns->nmic); + if (human) + nvme_show_id_ns_nmic(ns->nmic); + printf("rescap : %#x\n", ns->rescap); + if (human) + nvme_show_id_ns_rescap(ns->rescap); + printf("fpi : %#x\n", ns->fpi); + if (human) + nvme_show_id_ns_fpi(ns->fpi); + printf("anagrpid: %u\n", le32_to_cpu(ns->anagrpid)); + printf("nsattr : %u\n", ns->nsattr); + printf("nvmsetid: %d\n", le16_to_cpu(ns->nvmsetid)); + printf("endgid : %d\n", le16_to_cpu(ns->endgid)); + + printf("nstat : %#x\n", ns->nstat); + if (human) + nvme_show_cmd_set_independent_id_ns_nstat(ns->nstat); +} static void json_nvme_id_ns_descs(void *data) { diff --git a/nvme-print.h b/nvme-print.h index 2d5a0cad..ce1e81ce 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -26,6 +26,9 @@ void __nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, void nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode); void nvme_show_id_ns(struct nvme_id_ns *ns, unsigned int nsid, enum nvme_print_flags flags); +void nvme_show_cmd_set_independent_id_ns( + struct nvme_id_independent_id_ns *ns, unsigned int nsid, + enum nvme_print_flags flags); void nvme_show_resv_report(struct nvme_resv_status *status, int bytes, bool eds, enum nvme_print_flags flags); void nvme_show_lba_range(struct nvme_lba_range_type *lbrt, int nr_ranges); diff --git a/nvme.c b/nvme.c index ccd6af8e..66502ba4 100644 --- a/nvme.c +++ b/nvme.c @@ -2233,6 +2233,73 @@ ret: return nvme_status_to_errno(err, false); } +static int cmd_set_independent_id_ns(int argc, char **argv, + struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Send an I/O Command Set Independent Identify "\ + "Namespace command to the given device, returns properties of the "\ + "specified namespace in human-readable or binary or json format."; + const char *raw = "show identify in binary format"; + const char *human_readable = "show identify in readable format"; + const char *namespace_id = "identifier of desired namespace"; + + enum nvme_print_flags flags; + struct nvme_id_independent_id_ns ns; + int err = -1, fd; + + struct config { + __u32 namespace_id; + int raw_binary; + int human_readable; + char *output_format; + }; + + struct config cfg = { + .namespace_id = 0, + .output_format = "normal", + }; + + OPT_ARGS(opts) = { + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable), + OPT_END() + }; + + err = fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + goto ret; + + err = flags = validate_output_format(cfg.output_format); + if (flags < 0) + goto close_fd; + if (cfg.raw_binary) + flags = BINARY; + if (cfg.human_readable) + flags |= VERBOSE; + + if (!cfg.namespace_id) { + err = cfg.namespace_id = nvme_get_nsid(fd, &cfg.namespace_id); + if (err < 0) { + perror("get-namespace-id"); + goto close_fd; + } + } + + err = nvme_identify_independent_identify_ns(fd, cfg.namespace_id, &ns); + if (!err) + nvme_show_cmd_set_independent_id_ns(&ns, cfg.namespace_id, flags); + else if (err > 0) + nvme_show_status(err); + else + perror("I/O command set independent identify namespace"); +close_fd: + close(fd); +ret: + return nvme_status_to_errno(err, false); +} + static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Send an Identify Namespace Granularity List command to the "\ -- 2.50.1