]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme: add host-discovery-log command
authorTokunori Ikegami <ikegami.t@gmail.com>
Fri, 21 Feb 2025 15:30:54 +0000 (00:30 +0900)
committerDaniel Wagner <wagi@monom.org>
Wed, 26 Feb 2025 07:41:20 +0000 (08:41 +0100)
Since added the NVMe 2.1 log page.

Signed-off-by: Tokunori Ikegami <ikegami.t@gmail.com>
nvme-builtin.h
nvme-print-binary.c
nvme-print-json.c
nvme-print-stdout.c
nvme-print.c
nvme-print.h
nvme-wrap.c
nvme-wrap.h
nvme.c

index 6c71143d2cf3ad15ff949bc1a0fc041481c3a1f5..0b41c8bf041f0ec95e529da5332032bec5f00352 100644 (file)
@@ -64,6 +64,7 @@ COMMAND_LIST(
        ENTRY("dispersed-ns-participating-nss-log", "Retrieve Dispersed Namespace Participating NVM Subsystems Log, show it", get_dispersed_ns_participating_nss_log)
        ENTRY("reachability-groups-log", "Retrieve Reachability Groups Log, show it", get_reachability_groups_log)
        ENTRY("reachability-associations-log", "Retrieve Reachability Associations Log, show it", get_reachability_associations_log)
+       ENTRY("host-discovery-log", "Retrieve Host Discovery Log, show it", get_host_discovery_log)
        ENTRY("set-feature", "Set a feature and show the resulting value", set_feature)
        ENTRY("set-property", "Set a property and show the resulting value", set_property)
        ENTRY("get-property", "Get a property and show the resulting value", get_property)
index 640727d49b1f70bdf7e9483383edfb1230613390..0bbf1dc180208dbf1de3f4632c9c3d1cc0e97b22 100644 (file)
@@ -332,6 +332,11 @@ static void binary_reachability_associations_log(struct nvme_reachability_associ
        d_raw((unsigned char *)log, len);
 }
 
+static void binary_host_discovery_log(struct nvme_host_discover_log *log)
+{
+       d_raw((unsigned char *)log, le32_to_cpu(log->thdlpl));
+}
+
 static struct print_ops binary_print_ops = {
        /* libnvme types.h print functions */
        .ana_log                        = binary_ana_log,
@@ -403,6 +408,7 @@ static struct print_ops binary_print_ops = {
        .dispersed_ns_psub_log          = binary_dispersed_ns_psub_log,
        .reachability_groups_log        = binary_reachability_groups_log,
        .reachability_associations_log  = binary_reachability_associations_log,
+       .host_discovery_log             = binary_host_discovery_log,
 
        /* libnvme tree print functions */
        .list_item                      = NULL,
index 338e0bcb373b96e709062ce8744c9723c6e1c021..61a706a49cdc3d30dc01f44fa8cba8b0eecad2e3 100644 (file)
@@ -4751,6 +4751,76 @@ static void json_reachability_associations_log(struct nvme_reachability_associat
        json_print(r);
 }
 
+static void json_host_discovery_log(struct nvme_host_discover_log *log)
+{
+       struct json_object *r = json_create_object();
+       __u32 i;
+       __u16 j;
+       struct nvme_host_ext_discover_log *hedlpe;
+       struct nvmf_ext_attr *exat;
+       __u32 thdlpl = le32_to_cpu(log->thdlpl);
+       __u32 tel;
+       __u16 numexat;
+       char json_str[STR_LEN];
+       struct json_object *hedlpe_o;
+       struct json_object *tsas_o;
+       struct json_object *exat_o;
+       int n = 0;
+
+       obj_add_uint64(r, "genctr", le64_to_cpu(log->genctr));
+       obj_add_uint64(r, "numrec", le64_to_cpu(log->numrec));
+       obj_add_uint(r, "recfmt", le16_to_cpu(log->recfmt));
+       obj_add_uint_02x(r, "hdlpf", log->hdlpf);
+       obj_add_uint(r, "thdlpl", thdlpl);
+
+       for (i = sizeof(*log); i < le32_to_cpu(log->thdlpl); i += tel) {
+               hedlpe_o = json_create_object();
+               hedlpe = (void *)log + i;
+               tel = le32_to_cpu(hedlpe->tel);
+               numexat = le16_to_cpu(hedlpe->numexat);
+               obj_add_str(hedlpe_o, "trtype", nvmf_trtype_str(hedlpe->trtype));
+               obj_add_str(hedlpe_o, "adrfam",
+                           strlen(hedlpe->traddr) ? nvmf_adrfam_str(hedlpe->adrfam) : "");
+               obj_add_str(hedlpe_o, "eflags", nvmf_eflags_str(le16_to_cpu(hedlpe->eflags)));
+               obj_add_str(hedlpe_o, "hostnqn", hedlpe->hostnqn);
+               obj_add_str(hedlpe_o, "traddr", hedlpe->traddr);
+               tsas_o = json_create_object();
+               switch (hedlpe->trtype) {
+               case NVMF_TRTYPE_RDMA:
+                       obj_add_str(tsas_o, "prtype", nvmf_prtype_str(hedlpe->tsas.rdma.prtype));
+                       obj_add_str(tsas_o, "qptype", nvmf_qptype_str(hedlpe->tsas.rdma.qptype));
+                       obj_add_str(tsas_o, "cms", nvmf_cms_str(hedlpe->tsas.rdma.cms));
+                       obj_add_uint_0nx(tsas_o, "pkey", le16_to_cpu(hedlpe->tsas.rdma.pkey), 4);
+                       break;
+               case NVMF_TRTYPE_TCP:
+                       obj_add_str(tsas_o, "sectype", nvmf_sectype_str(hedlpe->tsas.tcp.sectype));
+                       break;
+               default:
+                       obj_d(tsas_o, "common", (unsigned char *)hedlpe->tsas.common,
+                             sizeof(hedlpe->tsas.common), 16, 1);
+                       break;
+               }
+               obj_add_obj(hedlpe_o, "tsas", tsas_o);
+               obj_add_uint(hedlpe_o, "tel", tel);
+               obj_add_uint(hedlpe_o, "numexat", numexat);
+
+               exat = hedlpe->exat;
+               for (j = 0; j < numexat; j++) {
+                       exat_o = json_create_object();
+                       snprintf(json_str, sizeof(json_str), "exat: %d", j);
+                       obj_add_uint(exat_o, "exattype", le16_to_cpu(exat->exattype));
+                       obj_add_uint(exat_o, "exatlen", le16_to_cpu(exat->exatlen));
+                       printf(":\n");
+                       obj_d(exat_o, "exatval", (unsigned char *)exat->exatval,
+                             le16_to_cpu(exat->exatlen), 16, 1);
+                       obj_add_obj(hedlpe_o, json_str, exat_o);
+                       exat = nvmf_exat_ptr_next(exat);
+               }
+               snprintf(json_str, sizeof(json_str), "hedlpe: %d", n++);
+               obj_add_obj(r, json_str, hedlpe_o);
+       }
+}
+
 static struct print_ops json_print_ops = {
        /* libnvme types.h print functions */
        .ana_log                        = json_ana_log,
@@ -4823,6 +4893,7 @@ static struct print_ops json_print_ops = {
        .dispersed_ns_psub_log          = json_dispersed_ns_psub_log,
        .reachability_groups_log        = json_reachability_groups_log,
        .reachability_associations_log  = json_reachability_associations_log,
+       .host_discovery_log             = json_host_discovery_log,
 
        /* libnvme tree print functions */
        .list_item                      = json_list_item,
index 2c7cafded81c72f4aa89d40f392762b2614ceb6e..ed0bcc55b0704a3cd753c970502329513e213d25 100644 (file)
@@ -5699,6 +5699,66 @@ static void stdout_reachability_associations_log(struct nvme_reachability_associ
        }
 }
 
+static void stdout_host_discovery_log(struct nvme_host_discover_log *log)
+{
+       __u32 i;
+       __u16 j;
+       struct nvme_host_ext_discover_log *hedlpe;
+       struct nvmf_ext_attr *exat;
+       __u32 thdlpl = le32_to_cpu(log->thdlpl);
+       __u32 tel;
+       __u16 numexat;
+       int n = 0;
+
+       printf("genctr: %"PRIu64"\n", le64_to_cpu(log->genctr));
+       printf("numrec: %"PRIu64"\n", le64_to_cpu(log->numrec));
+       printf("recfmt: %u\n", le16_to_cpu(log->recfmt));
+       printf("hdlpf: %02x\n", log->hdlpf);
+       printf("thdlpl: %u\n", thdlpl);
+
+       for (i = sizeof(*log); i < le32_to_cpu(log->thdlpl); i += tel) {
+               printf("hedlpe: %d\n", n++);
+               hedlpe = (void *)log + i;
+               tel = le32_to_cpu(hedlpe->tel);
+               numexat = le16_to_cpu(hedlpe->numexat);
+               printf("trtype: %s\n", nvmf_trtype_str(hedlpe->trtype));
+               printf("adrfam: %s\n",
+                      strlen(hedlpe->traddr) ? nvmf_adrfam_str(hedlpe->adrfam) : "");
+               printf("eflags: %s\n", nvmf_eflags_str(le16_to_cpu(hedlpe->eflags)));
+               printf("hostnqn: %s\n", hedlpe->hostnqn);
+               printf("traddr: %s\n", hedlpe->traddr);
+               printf("tsas: ");
+               switch (hedlpe->trtype) {
+               case NVMF_TRTYPE_RDMA:
+                       printf("prtype: %s, qptype: %s, cms: %s, pkey: 0x%04x\n",
+                              nvmf_prtype_str(hedlpe->tsas.rdma.prtype),
+                              nvmf_qptype_str(hedlpe->tsas.rdma.qptype),
+                              nvmf_cms_str(hedlpe->tsas.rdma.cms),
+                              le16_to_cpu(hedlpe->tsas.rdma.pkey));
+                       break;
+               case NVMF_TRTYPE_TCP:
+                       printf("sectype: %s\n", nvmf_sectype_str(hedlpe->tsas.tcp.sectype));
+                       break;
+               default:
+                       printf("common:\n");
+                       d((unsigned char *)hedlpe->tsas.common, sizeof(hedlpe->tsas.common), 16, 1);
+                       break;
+               }
+               printf("tel: %u\n", tel);
+               printf("numexat: %u\n", numexat);
+
+               exat = hedlpe->exat;
+               for (j = 0; j < numexat; j++) {
+                       printf("exat: %d\n", j);
+                       printf("exattype: %u\n", le16_to_cpu(exat->exattype));
+                       printf("exatlen: %u\n", le16_to_cpu(exat->exatlen));
+                       printf("exatval:\n");
+                       d((unsigned char *)exat->exatval, le16_to_cpu(exat->exatlen), 16, 1);
+                       exat = nvmf_exat_ptr_next(exat);
+               }
+       }
+}
+
 static struct print_ops stdout_print_ops = {
        /* libnvme types.h print functions */
        .ana_log                        = stdout_ana_log,
@@ -5771,6 +5831,7 @@ static struct print_ops stdout_print_ops = {
        .dispersed_ns_psub_log          = stdout_dispersed_ns_psub_log,
        .reachability_groups_log        = stdout_reachability_groups_log,
        .reachability_associations_log  = stdout_reachability_associations_log,
+       .host_discovery_log             = stdout_host_discovery_log,
 
        /* libnvme tree print functions */
        .list_item                      = stdout_list_item,
index a766c1e53cf9463559abc650453f203c4fa0d393..65516e930fd599e943da6d61ad78a0170415d7da 100644 (file)
@@ -1520,3 +1520,8 @@ void nvme_show_reachability_associations_log(struct nvme_reachability_associatio
 {
        nvme_print(reachability_associations_log, flags, log, len);
 }
+
+void nvme_show_host_discovery_log(struct nvme_host_discover_log *log, nvme_print_flags_t flags)
+{
+       nvme_print(host_discovery_log, flags, log);
+}
index 37d90f5f9930cb5fd890b88d144f8207147285a8..2073b27c055baad186a3b0942c30a627fa5437eb 100644 (file)
@@ -94,6 +94,7 @@ struct print_ops {
        void (*reachability_groups_log)(struct nvme_reachability_groups_log *log, __u64 len);
        void (*reachability_associations_log)(struct nvme_reachability_associations_log *log,
                                              __u64 len);
+       void (*host_discovery_log)(struct nvme_host_discover_log *log);
 
        /* libnvme tree print functions */
        void (*list_item)(nvme_ns_t n);
@@ -345,4 +346,5 @@ void nvme_show_reachability_groups_log(struct nvme_reachability_groups_log *log,
                                       __u64 len, nvme_print_flags_t flags);
 void nvme_show_reachability_associations_log(struct nvme_reachability_associations_log *log,
                                             __u64 len, nvme_print_flags_t flags);
+void nvme_show_host_discovery_log(struct nvme_host_discover_log *log, nvme_print_flags_t flags);
 #endif /* NVME_PRINT_H */
index 6c2c4573def4bfb5ea3ab25dff3763466a359a5d..bbf4264f33db3dbca263af0c3bc71394e04d2d1d 100644 (file)
@@ -469,3 +469,9 @@ int nvme_cli_get_log_reachability_associations(struct nvme_dev *dev, bool rao, b
 {
        return do_admin_op(get_log_reachability_associations, dev, rao, rae, len, log);
 }
+
+int nvme_cli_get_log_host_discovery(struct nvme_dev *dev, bool allhoste, bool rae, __u32 len,
+                                   struct nvme_host_discover_log *log)
+{
+       return do_admin_op(get_log_host_discover, dev, allhoste, rae, len, log);
+}
index d0f91c1f6a1e2d970aa3a33723b7a467aa67f636..d5317a1378171185c5e6788a4d04faf46b89e687 100644 (file)
@@ -162,4 +162,7 @@ int nvme_cli_get_log_reachability_groups(struct nvme_dev *dev, bool rgo, bool ra
 
 int nvme_cli_get_log_reachability_associations(struct nvme_dev *dev, bool rgo, bool rae, __u32 len,
                                               struct nvme_reachability_associations_log *log);
+
+int nvme_cli_get_log_host_discovery(struct nvme_dev *dev, bool allhoste, bool rae, __u32 len,
+                                   struct nvme_host_discover_log *log);
 #endif /* _NVME_WRAP_H */
diff --git a/nvme.c b/nvme.c
index 0c9be68d294e4009034f5621e9bc513c2c20f295..54ddcfe84928e61ac5af346dd449ad4c028f0604 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -10618,6 +10618,90 @@ static int get_reachability_associations_log(int argc, char **argv, struct comma
        return err;
 }
 
+static int get_host_discovery(struct nvme_dev *dev, bool allhoste, bool rae,
+                             struct nvme_host_discover_log **logp)
+{
+       int err;
+       struct nvme_host_discover_log *log;
+       __u64 log_len = sizeof(*log);
+       struct nvme_get_log_args args = {
+               .args_size = sizeof(args),
+               .fd = dev_fd(dev),
+               .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+               .lid = NVME_LOG_LID_HOST_DISCOVER,
+               .nsid = NVME_NSID_ALL,
+               .lsp = allhoste,
+               .rae = rae,
+       };
+
+       log = nvme_alloc(log_len);
+       if (!log)
+               return -ENOMEM;
+
+       err = nvme_cli_get_log_host_discovery(dev, allhoste, rae, log_len, log);
+       if (err)
+               goto err_free;
+
+       log_len = le32_to_cpu(log->thdlpl);
+       err = get_log_offset(dev, &args, &log_len, le32_to_cpu(log->thdlpl) - log_len,
+                            (void **)&log);
+       if (err)
+               goto err_free;
+
+       *logp = log;
+       return 0;
+
+err_free:
+       free(log);
+       return err;
+}
+
+static int get_host_discovery_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+       const char *desc = "Retrieve Host Discovery Log, show it";
+       const char *allhoste = "All Host Entries";
+       nvme_print_flags_t flags;
+       int err;
+
+       _cleanup_free_ struct nvme_host_discover_log *log = NULL;
+
+       _cleanup_nvme_dev_ struct nvme_dev *dev = NULL;
+
+       struct config {
+               bool allhoste;
+               bool rae;
+       };
+
+       struct config cfg = {
+               .allhoste = false,
+               .rae = false,
+       };
+
+       NVME_ARGS(opts,
+                 OPT_FLAG("all-host-entries", 'a', &cfg.allhoste, allhoste),
+                 OPT_FLAG("rae", 'r', &cfg.rae, rae));
+
+       err = parse_and_open(&dev, argc, argv, desc, opts);
+       if (err)
+               return err;
+
+       err = validate_output_format(nvme_cfg.output_format, &flags);
+       if (err < 0) {
+               nvme_show_error("Invalid output format");
+               return err;
+       }
+
+       err = get_host_discovery(dev, cfg.allhoste, cfg.rae, &log);
+       if (!err)
+               nvme_show_host_discovery_log(log, flags);
+       else if (err > 0)
+               nvme_show_status(err);
+       else
+               nvme_show_perror("host discovery log");
+
+       return err;
+}
+
 void register_extension(struct plugin *plugin)
 {
        plugin->parent = &nvme;