From 86495e85ef73dea6d8aab14bc438c6362c046403 Mon Sep 17 00:00:00 2001 From: Tokunori Ikegami Date: Wed, 12 Feb 2025 00:15:37 +0900 Subject: [PATCH] nvme: add reachability-associations-log command Since added the NVMe 2.1 log page. Signed-off-by: Tokunori Ikegami --- nvme-builtin.h | 1 + nvme-print-binary.c | 6 +++ nvme-print-json.c | 26 ++++++++++ nvme-print-stdout.c | 19 ++++++++ nvme-print.c | 6 +++ nvme-print.h | 3 ++ nvme-wrap.c | 6 +++ nvme-wrap.h | 3 ++ nvme.c | 112 ++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 182 insertions(+) diff --git a/nvme-builtin.h b/nvme-builtin.h index b97d2dde..6c71143d 100644 --- a/nvme-builtin.h +++ b/nvme-builtin.h @@ -63,6 +63,7 @@ COMMAND_LIST( ENTRY("changed-alloc-ns-list-log", "Retrieve Changed Allocated Namespace List, show it", get_changed_alloc_ns_list_log) 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("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) diff --git a/nvme-print-binary.c b/nvme-print-binary.c index dcaaddc6..a1e4885a 100644 --- a/nvme-print-binary.c +++ b/nvme-print-binary.c @@ -326,6 +326,11 @@ static void binary_reachability_groups_log(struct nvme_reachability_groups_log * d_raw((unsigned char *)log, sizeof(*log)); } +static void binary_reachability_associations_log(struct nvme_reachability_associations_log *log) +{ + d_raw((unsigned char *)log, sizeof(*log)); +} + static struct print_ops binary_print_ops = { /* libnvme types.h print functions */ .ana_log = binary_ana_log, @@ -396,6 +401,7 @@ static struct print_ops binary_print_ops = { .rotational_media_info_log = binary_rotational_media_info_log, .dispersed_ns_psub_log = binary_dispersed_ns_psub_log, .reachability_groups_log = binary_reachability_groups_log, + .reachability_associations_log = binary_reachability_associations_log, /* libnvme tree print functions */ .list_item = NULL, diff --git a/nvme-print-json.c b/nvme-print-json.c index 5320f573..4f342eb5 100644 --- a/nvme-print-json.c +++ b/nvme-print-json.c @@ -4701,6 +4701,31 @@ static void json_reachability_groups_log(struct nvme_reachability_groups_log *lo json_print(r); } +static void json_reachability_associations_log(struct nvme_reachability_associations_log *log) +{ + struct json_object *r = json_create_object(); + __u16 i; + __u32 j; + char json_str[STR_LEN]; + struct json_object *rad; + + obj_add_uint64(r, "chngc", le64_to_cpu(log->chngc)); + obj_add_uint(r, "nrad", le16_to_cpu(log->nrad)); + + for (i = 0; i < le16_to_cpu(log->nrad); i++) { + snprintf(json_str, sizeof(json_str), "rasid: %u", le32_to_cpu(log->rad[i].rasid)); + rad = json_create_object(); + obj_add_uint(rad, "nrid", le32_to_cpu(log->rad[i].nrid)); + obj_add_uint64(rad, "chngc", le64_to_cpu(log->rad[i].chngc)); + obj_add_uint(rad, "rac", log->rad[i].rac); + for (j = 0; j < le32_to_cpu(log->rad[i].nrid); j++) + obj_add_uint(rad, "rgid", le32_to_cpu(log->rad[i].rgid[j])); + obj_add_obj(r, json_str, rad); + } + + json_print(r); +} + static struct print_ops json_print_ops = { /* libnvme types.h print functions */ .ana_log = json_ana_log, @@ -4772,6 +4797,7 @@ static struct print_ops json_print_ops = { .rotational_media_info_log = json_rotational_media_info_log, .dispersed_ns_psub_log = json_dispersed_ns_psub_log, .reachability_groups_log = json_reachability_groups_log, + .reachability_associations_log = json_reachability_associations_log, /* libnvme tree print functions */ .list_item = json_list_item, diff --git a/nvme-print-stdout.c b/nvme-print-stdout.c index f9abf03f..b3f95baf 100644 --- a/nvme-print-stdout.c +++ b/nvme-print-stdout.c @@ -5655,6 +5655,24 @@ static void stdout_reachability_groups_log(struct nvme_reachability_groups_log * } } +static void stdout_reachability_associations_log(struct nvme_reachability_associations_log *log) +{ + __u16 i; + __u32 j; + + printf("chngc: %"PRIu64"\n", le64_to_cpu(log->chngc)); + printf("nrad: %u\n", le16_to_cpu(log->nrad)); + + for (i = 0; i < le16_to_cpu(log->nrad); i++) { + printf("rasid: %u\n", le32_to_cpu(log->rad[i].rasid)); + printf("nrid: %u\n", le32_to_cpu(log->rad[i].nrid)); + printf("chngc: %"PRIu64"\n", le64_to_cpu(log->rad[i].chngc)); + printf("rac: %u\n", log->rad[i].rac); + for (j = 0; j < le32_to_cpu(log->rad[i].nrid); j++) + printf("rgid%u: %u\n", j, le32_to_cpu(log->rad[i].rgid[j])); + } +} + static struct print_ops stdout_print_ops = { /* libnvme types.h print functions */ .ana_log = stdout_ana_log, @@ -5726,6 +5744,7 @@ static struct print_ops stdout_print_ops = { .rotational_media_info_log = stdout_rotational_media_info_log, .dispersed_ns_psub_log = stdout_dispersed_ns_psub_log, .reachability_groups_log = stdout_reachability_groups_log, + .reachability_associations_log = stdout_reachability_associations_log, /* libnvme tree print functions */ .list_item = stdout_list_item, diff --git a/nvme-print.c b/nvme-print.c index f15a3b4d..5c0f7ca5 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -1514,3 +1514,9 @@ void nvme_show_reachability_groups_log(struct nvme_reachability_groups_log *log, { nvme_print(reachability_groups_log, flags, log); } + +void nvme_show_reachability_associations_log(struct nvme_reachability_associations_log *log, + nvme_print_flags_t flags) +{ + nvme_print(reachability_associations_log, flags, log); +} diff --git a/nvme-print.h b/nvme-print.h index 5a3d939c..5e6663ad 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -92,6 +92,7 @@ struct print_ops { void (*rotational_media_info_log)(struct nvme_rotational_media_info_log *info); void (*dispersed_ns_psub_log)(struct nvme_dispersed_ns_participating_nss_log *log); void (*reachability_groups_log)(struct nvme_reachability_groups_log *log); + void (*reachability_associations_log)(struct nvme_reachability_associations_log *log); /* libnvme tree print functions */ void (*list_item)(nvme_ns_t n); @@ -341,4 +342,6 @@ void nvme_show_dispersed_ns_psub_log(struct nvme_dispersed_ns_participating_nss_ nvme_print_flags_t flags); void nvme_show_reachability_groups_log(struct nvme_reachability_groups_log *log, nvme_print_flags_t flags); +void nvme_show_reachability_associations_log(struct nvme_reachability_associations_log *log, + nvme_print_flags_t flags); #endif /* NVME_PRINT_H */ diff --git a/nvme-wrap.c b/nvme-wrap.c index cd90ceea..371a603d 100644 --- a/nvme-wrap.c +++ b/nvme-wrap.c @@ -463,3 +463,9 @@ int nvme_cli_get_log_reachability_groups(struct nvme_dev *dev, bool rgo, bool ra { return do_admin_op(get_log_reachability_groups, dev, rgo, rae, len, log); } + +int nvme_cli_get_log_reachability_associations(struct nvme_dev *dev, bool rao, bool rae, __u32 len, + struct nvme_reachability_associations_log *log) +{ + return do_admin_op(get_log_reachability_associations, dev, len, rao, rae, log); +} diff --git a/nvme-wrap.h b/nvme-wrap.h index 9300e8b0..d0f91c1f 100644 --- a/nvme-wrap.h +++ b/nvme-wrap.h @@ -159,4 +159,7 @@ int nvme_cli_get_log_dispersed_ns_participating_nss(struct nvme_dev *dev, __u32 int nvme_cli_get_log_reachability_groups(struct nvme_dev *dev, bool rgo, bool rae, __u32 len, struct nvme_reachability_groups_log *log); + +int nvme_cli_get_log_reachability_associations(struct nvme_dev *dev, bool rgo, bool rae, __u32 len, + struct nvme_reachability_associations_log *log); #endif /* _NVME_WRAP_H */ diff --git a/nvme.c b/nvme.c index 5a989206..4f6cde85 100644 --- a/nvme.c +++ b/nvme.c @@ -10334,6 +10334,118 @@ static int get_reachability_groups_log(int argc, char **argv, struct command *cm return err; } +static int get_reachability_association_desc(struct nvme_dev *dev, struct nvme_get_log_args *args, + __u64 offset, + struct nvme_reachability_associations_log **logp) +{ + int err; + struct nvme_reachability_associations_log *log = *logp; + __u16 i; + __u32 len; + + for (i = 0; i < le16_to_cpu(log->nrad); i++) { + len = sizeof(*log->rad); + err = get_log_offset(dev, args, &offset, len, (void **)&log); + if (err) + goto err_free; + len = le32_to_cpu(log->rad[i].nrid) * sizeof(*log->rad[i].rgid); + err = get_log_offset(dev, args, &offset, len, (void **)&log); + if (err) + goto err_free; + } + + *logp = log; + return 0; + +err_free: + free(log); + *logp = NULL; + return err; +} + +static int get_reachability_associations(struct nvme_dev *dev, bool rao, bool rae, + struct nvme_reachability_associations_log **logp) +{ + int err; + struct nvme_reachability_associations_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_REACHABILITY_ASSOCIATIONS, + .nsid = NVME_NSID_ALL, + .lsp = rao, + .rae = rae, + }; + + log = nvme_alloc(log_len); + if (!log) + return -ENOMEM; + + err = nvme_cli_get_log_reachability_associations(dev, rao, rae, log_len, log); + if (err) + goto err_free; + + err = get_reachability_association_desc(dev, &args, log_len, &log); + if (err) + goto err_free; + + *logp = log; + return 0; + +err_free: + free(log); + return err; +} + +static int get_reachability_associations_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + const char *desc = "Retrieve Reachability Associations Log, show it"; + const char *rao = "Return Associations Only"; + nvme_print_flags_t flags; + int err; + + _cleanup_free_ struct nvme_reachability_associations_log *log = NULL; + + _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + + struct config { + bool rao; + bool rae; + }; + + struct config cfg = { + .rao = false, + .rae = false, + }; + + NVME_ARGS(opts, + OPT_FLAG("associations-only", 'a', &cfg.rao, rao), + 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_reachability_associations(dev, cfg.rao, cfg.rae, &log); + if (!err) + nvme_show_reachability_associations_log(log, flags); + else if (err > 0) + nvme_show_status(err); + else + nvme_show_perror("reachability associations log"); + + return err; +} + void register_extension(struct plugin *plugin) { plugin->parent = &nvme; -- 2.50.1