diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-05 08:38:36 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-05 08:38:36 +0000 |
commit | 3c0f1ed2ea093dd0d3e8ba70f3c9963e66321f87 (patch) | |
tree | 2020852fabf5e530c687d41e36ddc5c453b0c9ed /nvme.c | |
parent | Adding upstream version 2.9.1. (diff) | |
download | nvme-cli-3c0f1ed2ea093dd0d3e8ba70f3c9963e66321f87.tar.xz nvme-cli-3c0f1ed2ea093dd0d3e8ba70f3c9963e66321f87.zip |
Adding upstream version 2.10.upstream/2.10
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | nvme.c | 738 |
1 files changed, 383 insertions, 355 deletions
@@ -34,6 +34,7 @@ #include <inttypes.h> #include <locale.h> #include <stdio.h> +#include <stdint.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -88,7 +89,6 @@ struct passthru_config { __u32 namespace_id; __u32 data_len; __u32 metadata_len; - __u32 timeout; __u32 cdw2; __u32 cdw3; __u32 cdw10; @@ -163,14 +163,6 @@ struct set_reg_config { __u32 pmrmscu; }; -#define NVME_ARGS(n, ...) \ - struct argconfig_commandline_options n[] = { \ - OPT_INCR("verbose", 'v', &verbose_level, verbose), \ - OPT_FMT("output-format", 'o', &output_format_val, output_format), \ - ##__VA_ARGS__, \ - OPT_END() \ - } - static const char nvme_version_string[] = NVME_VERSION; static struct plugin builtin = { @@ -193,6 +185,9 @@ static struct program nvme = { }; const char *output_format = "Output format: normal|json|binary"; +const char *timeout = "timeout value, in milliseconds"; +const char *verbose = "Increase output verbosity"; + static const char *app_tag = "app tag for end-to-end PI"; static const char *app_tag_mask = "app tag mask for end-to-end PI"; static const char *block_count = "number of blocks (zeroes based) on device to access"; @@ -235,10 +230,8 @@ static const char *secp = "security protocol (cf. SPC-4)"; static const char *spsp = "security-protocol-specific (cf. SPC-4)"; static const char *start_block = "64-bit LBA of first block to access"; static const char *storage_tag = "storage tag for end-to-end PI"; -static const char *timeout = "timeout value, in milliseconds"; static const char *uuid_index = "UUID index"; static const char *uuid_index_specify = "specify uuid index"; -static const char *verbose = "Increase output verbosity"; static const char dash[51] = {[0 ... 49] = '=', '\0'}; static const char space[51] = {[0 ... 49] = ' ', '\0'}; static const char *offset = "offset of the requested register"; @@ -258,8 +251,9 @@ static const char *pmrctl = "PMRCTL=0xe04 register offset"; static const char *pmrmscl = "PMRMSCL=0xe14 register offset"; static const char *pmrmscu = "PMRMSCU=0xe18 register offset"; -static char *output_format_val = "normal"; -int verbose_level; +struct nvme_config nvme_cfg = { + .output_format = "normal", +}; static void *mmap_registers(struct nvme_dev *dev, bool writable); @@ -423,13 +417,29 @@ static int get_dev(struct nvme_dev **dev, int argc, char **argv, int flags) return ret; devname = argv[optind]; + errno = ENXIO; if (!strncmp(devname, "mctp:", strlen("mctp:"))) ret = open_dev_mi_mctp(dev, devname); else ret = open_dev_direct(dev, devname, flags); - return ret != 0 ? -errno : 0; + return ret ? -errno : 0; +} + +static int parse_args(int argc, char *argv[], const char *desc, + struct argconfig_commandline_options *opts) +{ + int ret; + + ret = argconfig_parse(argc, argv, desc, opts); + if (ret) + return ret; + + log_level = map_log_level(nvme_cfg.verbose, false); + nvme_init_default_logging(stderr, log_level, false, false); + + return 0; } int parse_and_open(struct nvme_dev **dev, int argc, char **argv, @@ -438,15 +448,13 @@ int parse_and_open(struct nvme_dev **dev, int argc, char **argv, { int ret; - ret = argconfig_parse(argc, argv, desc, opts); + ret = parse_args(argc, argv, desc, opts); if (ret) return ret; ret = get_dev(dev, argc, argv, O_RDONLY); if (ret < 0) argconfig_print_help(desc, opts); - else - log_level = map_log_level(verbose_level, false); return ret; } @@ -462,9 +470,9 @@ int open_exclusive(struct nvme_dev **dev, int argc, char **argv, return get_dev(dev, argc, argv, flags); } -int validate_output_format(const char *format, enum nvme_print_flags *flags) +int validate_output_format(const char *format, nvme_print_flags_t *flags) { - enum nvme_print_flags f; + nvme_print_flags_t f; if (!format) return -EINVAL; @@ -485,9 +493,9 @@ int validate_output_format(const char *format, enum nvme_print_flags *flags) bool nvme_is_output_format_json(void) { - enum nvme_print_flags flags; + nvme_print_flags_t flags; - if (validate_output_format(output_format_val, &flags)) + if (validate_output_format(nvme_cfg.output_format, &flags)) return false; return flags == JSON; @@ -516,7 +524,7 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug _cleanup_free_ struct nvme_smart_log *smart_log = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; const char *namespace = "(optional) desired namespace"; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err = -1; struct config { @@ -540,7 +548,7 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -549,7 +557,7 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug if (cfg.raw_binary) flags = BINARY; - if (cfg.human_readable) + if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; smart_log = nvme_alloc(sizeof(*smart_log)); @@ -578,10 +586,10 @@ static int get_ana_log(int argc, char **argv, struct command *cmd, _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; - _cleanup_free_ void *ana_log = NULL; - size_t ana_log_len; - enum nvme_print_flags flags; - enum nvme_log_ana_lsp lsp; + _cleanup_free_ struct nvme_ana_log *ana_log = NULL; + size_t max_ana_log_len; + __u32 ana_log_len; + nvme_print_flags_t flags; int err = -1; struct config { @@ -599,7 +607,7 @@ static int get_ana_log(int argc, char **argv, struct command *cmd, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -616,19 +624,19 @@ static int get_ana_log(int argc, char **argv, struct command *cmd, return err; } - ana_log_len = sizeof(struct nvme_ana_log) + - le32_to_cpu(ctrl->nanagrpid) * sizeof(struct nvme_ana_group_desc); - if (!(ctrl->anacap & (1 << 6))) - ana_log_len += le32_to_cpu(ctrl->mnan) * sizeof(__le32); + max_ana_log_len = nvme_get_ana_log_len_from_id_ctrl(ctrl, cfg.groups); + ana_log_len = max_ana_log_len; + if (ana_log_len < max_ana_log_len) { + nvme_show_error("ANA log length %zu too large", max_ana_log_len); + return -ENOMEM; + } ana_log = nvme_alloc(ana_log_len); if (!ana_log) return -ENOMEM; - lsp = cfg.groups ? NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY : - NVME_LOG_ANA_LSP_RGO_NAMESPACES; - - err = nvme_cli_get_log_ana(dev, lsp, true, 0, ana_log_len, ana_log); + err = nvme_cli_get_ana_log_atomic(dev, cfg.groups, true, 10, + ana_log, &ana_log_len); if (!err) nvme_show_ana_log(ana_log, dev->name, ana_log_len, flags); else if (err > 0) @@ -703,7 +711,10 @@ static int get_log_telemetry_ctrl(struct nvme_dev *dev, bool rae, size_t size, err = nvme_cli_get_log_telemetry_ctrl(dev, rae, 0, size, log); if (err) { free(log); - return -errno; + if (errno) + return -errno; + else + return err; } *buf = log; @@ -723,7 +734,10 @@ static int get_log_telemetry_host(struct nvme_dev *dev, size_t size, err = nvme_cli_get_log_telemetry_host(dev, 0, size, log); if (err) { free(log); - return -errno; + if (errno) + return -errno; + else + return err; } *buf = log; @@ -743,8 +757,12 @@ static int __create_telemetry_log_host(struct nvme_dev *dev, return -ENOMEM; err = nvme_cli_get_log_create_telemetry_host(dev, log); - if (err) - return -errno; + if (err) { + if (errno) + return -errno; + else + return err; + } err = parse_telemetry_da(dev, da, log, size); if (err) @@ -838,7 +856,7 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, _cleanup_free_ struct nvme_telemetry_log *log = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - _cleanup_file_ int output = -1; + _cleanup_fd_ int output = -1; int err = 0; size_t total_size; __u8 *data_ptr = NULL; @@ -944,7 +962,7 @@ static int get_endurance_log(int argc, char **argv, struct command *cmd, struct _cleanup_free_ struct nvme_endurance_group_log *endurance_log = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -962,7 +980,7 @@ static int get_endurance_log(int argc, char **argv, struct command *cmd, struct if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -1017,7 +1035,7 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl void *bar = NULL; int err = -1; - enum nvme_print_flags flags; + nvme_print_flags_t flags; struct config { bool human_readable; @@ -1040,7 +1058,7 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -1049,7 +1067,7 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl if (cfg.raw_binary) flags = BINARY; - if (cfg.human_readable) + if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; list_head_init(&log_pages); @@ -1068,7 +1086,7 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl .fd = dev_fd(dev), .offset = NVME_REG_CAP, .value = &cap, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, }; err = nvme_get_property(&args); if (err) @@ -1107,7 +1125,7 @@ static int get_supported_log_pages(int argc, char **argv, struct command *cmd, _cleanup_free_ struct nvme_supported_log_pages *supports = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err = -1; NVME_ARGS(opts); @@ -1116,7 +1134,7 @@ static int get_supported_log_pages(int argc, char **argv, struct command *cmd, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -1151,7 +1169,7 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug _cleanup_free_ struct nvme_error_log_page *err_log = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; struct nvme_id_ctrl ctrl; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err = -1; struct config { @@ -1172,7 +1190,7 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -1219,7 +1237,7 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin _cleanup_free_ struct nvme_firmware_slot *fw_log = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -1237,7 +1255,7 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -1268,7 +1286,7 @@ static int get_changed_ns_list_log(int argc, char **argv, struct command *cmd, s _cleanup_free_ struct nvme_ns_list *changed_ns_list_log = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -1286,7 +1304,7 @@ static int get_changed_ns_list_log(int argc, char **argv, struct command *cmd, s if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -1322,7 +1340,7 @@ static int get_pred_lat_per_nvmset_log(int argc, char **argv, _cleanup_free_ struct nvme_nvmset_predictable_lat_log *plpns_log = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -1343,7 +1361,7 @@ static int get_pred_lat_per_nvmset_log(int argc, char **argv, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -1380,7 +1398,7 @@ static int get_pred_lat_event_agg_log(int argc, char **argv, _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; _cleanup_free_ void *pea_log = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; __u32 log_size; int err; @@ -1405,7 +1423,7 @@ static int get_pred_lat_event_agg_log(int argc, char **argv, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -1462,11 +1480,11 @@ static int get_persistent_event_log(int argc, char **argv, "processing this persistent log page command."; const char *log_len = "number of bytes to retrieve"; - _cleanup_free_ struct nvme_persistent_event_log *pevent_collected = NULL; _cleanup_free_ struct nvme_persistent_event_log *pevent = NULL; + struct nvme_persistent_event_log *pevent_collected = NULL; _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; void *pevent_log_info; int err; @@ -1491,7 +1509,7 @@ static int get_persistent_event_log(int argc, char **argv, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -1582,7 +1600,7 @@ static int get_endurance_event_agg_log(int argc, char **argv, _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; _cleanup_free_ void *endurance_log = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; __u32 log_size; int err; @@ -1607,7 +1625,7 @@ static int get_endurance_event_agg_log(int argc, char **argv, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -1663,7 +1681,7 @@ static int get_lba_status_log(int argc, char **argv, _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; _cleanup_free_ void *lba_status = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; __u32 lslplen; int err; @@ -1682,7 +1700,7 @@ static int get_lba_status_log(int argc, char **argv, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -1723,7 +1741,7 @@ static int get_resv_notif_log(int argc, char **argv, _cleanup_free_ struct nvme_resv_notification_log *resv = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; NVME_ARGS(opts); @@ -1732,7 +1750,7 @@ static int get_resv_notif_log(int argc, char **argv, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -1764,9 +1782,9 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; _cleanup_free_ struct nvme_boot_partition *boot = NULL; _cleanup_free_ __u8 *bp_log = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err = -1; - _cleanup_file_ int output = -1; + _cleanup_fd_ int output = -1; __u32 bpsz = 0; struct config { @@ -1787,7 +1805,7 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -1858,7 +1876,7 @@ static int get_phy_rx_eom_log(int argc, char **argv, struct command *cmd, const char *controller = "Target Controller ID."; _cleanup_free_ struct nvme_phy_rx_eom_log *phy_rx_eom_log = NULL; size_t phy_rx_eom_log_len; - enum nvme_print_flags flags; + nvme_print_flags_t flags; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; int err = -1; __u8 lsp_tmp; @@ -1881,7 +1899,7 @@ static int get_phy_rx_eom_log(int argc, char **argv, struct command *cmd, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -1948,7 +1966,7 @@ static int get_media_unit_stat_log(int argc, char **argv, struct command *cmd, _cleanup_free_ struct nvme_media_unit_stat_log *mus = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err = -1; struct config { @@ -1969,7 +1987,7 @@ static int get_media_unit_stat_log(int argc, char **argv, struct command *cmd, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -2000,7 +2018,7 @@ static int get_supp_cap_config_log(int argc, char **argv, struct command *cmd, _cleanup_free_ struct nvme_supported_cap_config_list_log *cap_log = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err = -1; struct config { @@ -2021,7 +2039,7 @@ static int get_supp_cap_config_log(int argc, char **argv, struct command *cmd, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -2054,7 +2072,7 @@ static int io_mgmt_send(int argc, char **argv, struct command *cmd, struct plugi _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; _cleanup_free_ void *buf = NULL; int err = -1; - int dfd = STDIN_FILENO; + _cleanup_fd_ int dfd = STDIN_FILENO; struct config { __u16 mos; @@ -2104,7 +2122,7 @@ static int io_mgmt_send(int argc, char **argv, struct command *cmd, struct plugi err = read(dfd, buf, cfg.data_len); if (err < 0) { nvme_show_perror("read"); - goto close_fd; + return err; } struct nvme_io_mgmt_send_args args = { @@ -2115,7 +2133,7 @@ static int io_mgmt_send(int argc, char **argv, struct command *cmd, struct plugi .mo = cfg.mo, .data_len = cfg.data_len, .data = buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, }; err = nvme_io_mgmt_send(&args); @@ -2127,9 +2145,6 @@ static int io_mgmt_send(int argc, char **argv, struct command *cmd, struct plugi else nvme_show_perror("io-mgmt-send"); -close_fd: - if (cfg.file) - close(dfd); return err; } @@ -2141,7 +2156,7 @@ static int io_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugi _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; _cleanup_free_ void *buf = NULL; int err = -1; - _cleanup_file_ int dfd = -1; + _cleanup_fd_ int dfd = -1; struct config { __u16 mos; @@ -2188,7 +2203,7 @@ static int io_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugi .mo = cfg.mo, .data_len = cfg.data_len, .data = buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, }; err = nvme_io_mgmt_recv(&args); @@ -2357,7 +2372,7 @@ static int sanitize_log(int argc, char **argv, struct command *command, struct p _cleanup_free_ struct nvme_sanitize_log_page *sanitize_log = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -2381,7 +2396,7 @@ static int sanitize_log(int argc, char **argv, struct command *command, struct p if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -2390,7 +2405,7 @@ static int sanitize_log(int argc, char **argv, struct command *command, struct p if (cfg.raw_binary) flags = BINARY; - if (cfg.human_readable) + if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; sanitize_log = nvme_alloc(sizeof(*sanitize_log)); @@ -2415,7 +2430,7 @@ static int get_fid_support_effects_log(int argc, char **argv, struct command *cm _cleanup_free_ struct nvme_fid_supported_effects_log *fid_support_log = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err = -1; struct config { @@ -2433,13 +2448,13 @@ static int get_fid_support_effects_log(int argc, char **argv, struct command *cm if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; } - if (cfg.human_readable) + if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; fid_support_log = nvme_alloc(sizeof(*fid_support_log)); @@ -2464,7 +2479,7 @@ static int get_mi_cmd_support_effects_log(int argc, char **argv, struct command _cleanup_free_ struct nvme_mi_cmd_supported_effects_log *mi_cmd_support_log = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err = -1; struct config { @@ -2482,13 +2497,13 @@ static int get_mi_cmd_support_effects_log(int argc, char **argv, struct command if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; } - if (cfg.human_readable) + if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; mi_cmd_support_log = nvme_alloc(sizeof(*mi_cmd_support_log)); @@ -2514,7 +2529,7 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin * _cleanup_free_ struct nvme_ctrl_list *cntlist = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -2535,7 +2550,7 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin * if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -2570,7 +2585,7 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl _cleanup_free_ struct nvme_ns_list *ns_list = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -2594,7 +2609,7 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0 || (flags != JSON && flags != NORMAL)) { nvme_show_error("Invalid output format"); return -EINVAL; @@ -2611,7 +2626,7 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl struct nvme_identify_args args = { .args_size = sizeof(args), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .data = ns_list, .nsid = cfg.namespace_id - 1. }; @@ -2643,7 +2658,7 @@ static int id_ns_lba_format(int argc, char **argv, struct command *cmd, struct p _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; _cleanup_free_ struct nvme_id_ns *ns = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err = -1; struct config { @@ -2664,7 +2679,7 @@ static int id_ns_lba_format(int argc, char **argv, struct command *cmd, struct p if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -2698,7 +2713,7 @@ static int id_endurance_grp_list(int argc, char **argv, struct command *cmd, _cleanup_free_ struct nvme_id_endurance_group_list *endgrp_list = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err = -1; struct config { @@ -2716,7 +2731,7 @@ static int id_endurance_grp_list(int argc, char **argv, struct command *cmd, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0 || (flags != JSON && flags != NORMAL)) { nvme_show_error("invalid output format"); return -EINVAL; @@ -2752,17 +2767,16 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin * struct config { __u32 namespace_id; - __u32 timeout; }; struct config cfg = { .namespace_id = 0, - .timeout = 120000, }; + nvme_cfg.timeout = 120000; + NVME_ARGS(opts, - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), - OPT_UINT("timeout", 't', &cfg.timeout, timeout)); + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id)); err = parse_and_open(&dev, argc, argv, desc, opts); if (err) @@ -2776,7 +2790,7 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin * } } - err = nvme_cli_ns_mgmt_delete(dev, cfg.namespace_id); + err = nvme_cli_ns_mgmt_delete(dev, cfg.namespace_id, nvme_cfg.timeout); if (!err) printf("%s: Success, deleted nsid:%d\n", cmd->name, cfg.namespace_id); else if (err > 0) @@ -2790,9 +2804,9 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin * static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, struct command *cmd) { _cleanup_free_ struct nvme_ctrl_list *cntlist = NULL; - _cleanup_free_ __u16 *ctrlist = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - int err, num, i, list[2048]; + int err, num; + __u16 list[NVME_ID_CTRL_LIST_MAX]; const char *namespace_id = "namespace to attach"; const char *cont = "optional comma-sep controller id list"; @@ -2820,7 +2834,8 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s return -EINVAL; } - num = argconfig_parse_comma_sep_array(cfg.cntlist, list, 2047); + num = argconfig_parse_comma_sep_array_u16(cfg.cntlist, + list, ARRAY_SIZE(list)); if (!num) fprintf(stderr, "warning: empty controller-id list will result in no actual change in namespace attachment\n"); @@ -2833,14 +2848,7 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s if (!cntlist) return -ENOMEM; - ctrlist = nvme_alloc(sizeof(*ctrlist) * 2048); - if (!ctrlist) - return -ENOMEM; - - for (i = 0; i < num; i++) - ctrlist[i] = (__u16)list[i]; - - nvme_init_ctrl_list(cntlist, num, ctrlist); + nvme_init_ctrl_list(cntlist, num, list); if (attach) err = nvme_cli_ns_attach_ctrls(dev, cfg.namespace_id, @@ -2887,15 +2895,15 @@ static int parse_lba_num_si(struct nvme_dev *dev, const char *opt, _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; _cleanup_free_ struct nvme_id_ns *ns = NULL; __u32 nsid = 1; + __u8 lbaf; unsigned int remainder; char *endptr; int err = -EINVAL; - int i; int lbas; struct nvme_identify_args args = { .args_size = sizeof(args), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .cns = NVME_IDENTIFY_CNS_NS_ACTIVE_LIST, .nsid = nsid - 1. }; @@ -2956,8 +2964,8 @@ static int parse_lba_num_si(struct nvme_dev *dev, const char *opt, return err; } - i = flbas & NVME_NS_FLBAS_LOWER_MASK; - lbas = (1 << ns->lbaf[i].ds) + ns->lbaf[i].ms; + nvme_id_ns_flbas_to_lbaf_inuse(flbas, &lbaf); + lbas = (1 << ns->lbaf[lbaf].ds) + ns->lbaf[lbaf].ms; if (suffix_si_parse(val, &endptr, (uint64_t *)num)) { nvme_show_error("Expected long suffixed integer argument for '%s-si' but got '%s'!", @@ -3028,7 +3036,6 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * __u16 nvmsetid; __u16 endgid; __u64 bs; - __u32 timeout; __u8 csi; __u64 lbstm; __u16 nphndls; @@ -3051,7 +3058,6 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * .nvmsetid = 0, .endgid = 0, .bs = 0x00, - .timeout = 120000, .csi = 0, .lbstm = 0, .nphndls = 0, @@ -3064,6 +3070,8 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * .phndls = "", }; + nvme_cfg.timeout = 120000; + NVME_ARGS(opts, OPT_SUFFIX("nsze", 's', &cfg.nsze, nsze), OPT_SUFFIX("ncap", 'c', &cfg.ncap, ncap), @@ -3074,7 +3082,6 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * OPT_UINT("nvmset-id", 'i', &cfg.nvmsetid, nvmsetid), OPT_UINT("endg-id", 'e', &cfg.endgid, endgid), OPT_SUFFIX("block-size", 'b', &cfg.bs, bs), - OPT_UINT("timeout", 't', &cfg.timeout, timeout), OPT_BYTE("csi", 'y', &cfg.csi, csi), OPT_SUFFIX("lbstm", 'l', &cfg.lbstm, lbstm), OPT_SHRT("nphndls", 'n', &cfg.nphndls, nphndls), @@ -3220,7 +3227,7 @@ parse_lba: for (i = 0; i < num_phandle; i++) data->phndl[i] = cpu_to_le16(phndl[i]); - err = nvme_cli_ns_mgmt_create(dev, data, &nsid, cfg.timeout, cfg.csi); + err = nvme_cli_ns_mgmt_create(dev, data, &nsid, nvme_cfg.timeout, cfg.csi); if (!err) printf("%s: Success, created nsid:%d\n", cmd->name, nsid); else if (err > 0) @@ -3269,8 +3276,8 @@ static bool nvme_match_device_filter(nvme_subsystem_t s, static int list_subsys(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - nvme_root_t r = NULL; - enum nvme_print_flags flags; + _cleanup_nvme_root_ nvme_root_t r = NULL; + nvme_print_flags_t flags; const char *desc = "Retrieve information for subsystems"; nvme_scan_filter_t filter = NULL; char *devname; @@ -3279,15 +3286,15 @@ static int list_subsys(int argc, char **argv, struct command *cmd, NVME_ARGS(opts); - err = argconfig_parse(argc, argv, desc, opts); - if (err < 0) - goto ret; + err = parse_args(argc, argv, desc, opts); + if (err) + return err; devname = NULL; if (optind < argc) devname = basename(argv[optind++]); - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0 || (flags != JSON && flags != NORMAL)) { nvme_show_error("Invalid output format"); return -EINVAL; @@ -3303,8 +3310,7 @@ static int list_subsys(int argc, char **argv, struct command *cmd, nvme_show_error("Failed to scan nvme subsystem for %s", devname); else nvme_show_error("Failed to scan nvme subsystem"); - err = -errno; - goto ret; + return -errno; } if (devname) { @@ -3312,41 +3318,36 @@ static int list_subsys(int argc, char **argv, struct command *cmd, if (sscanf(devname, "nvme%dn%d", &subsys_num, &nsid) != 2) { nvme_show_error("Invalid device name %s", devname); - err = -EINVAL; - goto ret; + return -EINVAL; } filter = nvme_match_device_filter; } err = nvme_scan_topology(r, filter, (void *)devname); if (err) { - if (errno != ENOENT) - nvme_show_error("Failed to scan topology: %s", nvme_strerror(errno)); - goto ret; + nvme_show_error("Failed to scan topology: %s", nvme_strerror(errno)); + return -errno; } nvme_show_subsystem_list(r, nsid != NVME_NSID_ALL, flags); -ret: - if (r) - nvme_free_tree(r); - return err; + return 0; } static int list(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Retrieve basic information for all NVMe namespaces"; - enum nvme_print_flags flags; - nvme_root_t r; + nvme_print_flags_t flags; + _cleanup_nvme_root_ nvme_root_t r = NULL; int err = 0; NVME_ARGS(opts); - err = argconfig_parse(argc, argv, desc, opts); - if (err < 0) + err = parse_args(argc, argv, desc, opts); + if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0 || (flags != JSON && flags != NORMAL)) { nvme_show_error("Invalid output format"); return -EINVAL; @@ -3362,14 +3363,11 @@ static int list(int argc, char **argv, struct command *cmd, struct plugin *plugi } err = nvme_scan_topology(r, NULL, NULL); if (err < 0) { - if (errno != ENOENT) - nvme_show_error("Failed to scan topology: %s", nvme_strerror(errno)); - nvme_free_tree(r); + nvme_show_error("Failed to scan topology: %s", nvme_strerror(errno)); return err; } nvme_show_list_items(r, flags); - nvme_free_tree(r); return err; } @@ -3386,7 +3384,7 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -3410,7 +3408,7 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -3422,7 +3420,7 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, if (cfg.vendor_specific) flags |= VS; - if (cfg.human_readable) + if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; ctrl = nvme_alloc(sizeof(*ctrl)); @@ -3454,7 +3452,7 @@ static int nvm_id_ctrl(int argc, char **argv, struct command *cmd, _cleanup_free_ struct nvme_id_ctrl_nvm *ctrl_nvm = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err = -1; NVME_ARGS(opts); @@ -3463,7 +3461,7 @@ static int nvm_id_ctrl(int argc, char **argv, struct command *cmd, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -3494,7 +3492,7 @@ static int nvm_id_ns(int argc, char **argv, struct command *cmd, _cleanup_free_ struct nvme_nvm_id_ns *id_ns = NULL; _cleanup_free_ struct nvme_id_ns *ns = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err = -1; struct config { @@ -3515,7 +3513,7 @@ static int nvm_id_ns(int argc, char **argv, struct command *cmd, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -3568,7 +3566,7 @@ static int nvm_id_ns_lba_format(int argc, char **argv, struct command *cmd, stru _cleanup_free_ struct nvme_nvm_id_ns *nvm_ns = NULL; _cleanup_free_ struct nvme_id_ns *ns = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err = -1; struct config { @@ -3589,7 +3587,7 @@ static int nvm_id_ns_lba_format(int argc, char **argv, struct command *cmd, stru if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -3633,7 +3631,7 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; _cleanup_free_ void *nsdescs = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -3654,7 +3652,7 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -3700,7 +3698,7 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; _cleanup_free_ struct nvme_id_ns *ns = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -3730,7 +3728,7 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -3742,7 +3740,7 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug if (cfg.vendor_specific) flags |= VS; - if (cfg.human_readable) + if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; if (!cfg.namespace_id) { @@ -3781,7 +3779,7 @@ static int cmd_set_independent_id_ns(int argc, char **argv, struct command *cmd, _cleanup_free_ struct nvme_id_independent_id_ns *ns = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err = -1; struct config { @@ -3805,7 +3803,7 @@ static int cmd_set_independent_id_ns(int argc, char **argv, struct command *cmd, if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -3814,7 +3812,7 @@ static int cmd_set_independent_id_ns(int argc, char **argv, struct command *cmd, if (cfg.raw_binary) flags = BINARY; - if (cfg.human_readable) + if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; if (!cfg.namespace_id) { @@ -3849,7 +3847,7 @@ static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct _cleanup_free_ struct nvme_id_ns_granularity_list *granularity_list = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; NVME_ARGS(opts); @@ -3858,7 +3856,7 @@ static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -3889,7 +3887,7 @@ static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin * _cleanup_free_ struct nvme_id_nvmset_list *nvmset = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -3907,7 +3905,7 @@ static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin * if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -3938,7 +3936,7 @@ static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *pl _cleanup_free_ struct nvme_id_uuid_list *uuid_list = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -3959,7 +3957,7 @@ static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *pl if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -3968,7 +3966,7 @@ static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *pl if (cfg.raw_binary) flags = BINARY; - if (cfg.human_readable) + if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; uuid_list = nvme_alloc(sizeof(*uuid_list)); @@ -4038,7 +4036,7 @@ static int id_domain(int argc, char **argv, struct command *cmd, struct plugin * _cleanup_free_ struct nvme_id_domain_list *id_domain = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -4056,7 +4054,7 @@ static int id_domain(int argc, char **argv, struct command *cmd, struct plugin * if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -4158,7 +4156,7 @@ static int virtual_mgmt(int argc, char **argv, struct command *cmd, struct plugi .rt = cfg.rt, .cntlid = cfg.cntlid, .nr = cfg.nr, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = &result, }; err = nvme_virtual_mgmt(&args); @@ -4181,7 +4179,7 @@ static int primary_ctrl_caps(int argc, char **argv, struct command *cmd, struct _cleanup_free_ struct nvme_primary_ctrl_cap *caps = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -4202,13 +4200,13 @@ static int primary_ctrl_caps(int argc, char **argv, struct command *cmd, struct if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; } - if (cfg.human_readable) + if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; caps = nvme_alloc(sizeof(*caps)); @@ -4236,7 +4234,7 @@ static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struc _cleanup_free_ struct nvme_secondary_ctrl_list *sc_list = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -4257,7 +4255,7 @@ static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struc if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -4458,7 +4456,7 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p .fd = dev_fd(dev), .nsid = cfg.namespace_id, .stc = cfg.stc, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; err = nvme_dev_self_test(&args); @@ -4494,7 +4492,7 @@ static int self_test_log(int argc, char **argv, struct command *cmd, struct plug _cleanup_free_ struct nvme_self_test_log *log = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err; struct config { @@ -4512,7 +4510,7 @@ static int self_test_log(int argc, char **argv, struct command *cmd, struct plug if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -4570,7 +4568,7 @@ static int get_feature_id(struct nvme_dev *dev, struct feat_cfg *cfg, .uuidx = cfg->uuid_index, .data_len = cfg->data_len, .data = *buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = result, }; return nvme_cli_get_features(dev, &args); @@ -4617,8 +4615,8 @@ static int get_feature_id_changed(struct nvme_dev *dev, struct feat_cfg cfg, int err_def = 0; __u32 result; __u32 result_def; - void *buf = NULL; - void *buf_def = NULL; + _cleanup_free_ void *buf = NULL; + _cleanup_free_ void *buf_def = NULL; if (changed) cfg.sel = 0; @@ -4637,9 +4635,6 @@ static int get_feature_id_changed(struct nvme_dev *dev, struct feat_cfg cfg, (buf && buf_def && !strcmp(buf, buf_def))) get_feature_id_print(cfg, err, result, buf); - free(buf); - free(buf_def); - return err; } @@ -4778,7 +4773,7 @@ static int fw_download_single(struct nvme_dev *dev, void *fw_buf, .offset = offset, .data_len = len, .data = fw_buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; @@ -4870,7 +4865,7 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; - _cleanup_file_ int fw_fd = -1; + _cleanup_fd_ int fw_fd = -1; unsigned int fw_size, pos; int err; struct stat sb; @@ -5012,11 +5007,11 @@ static void fw_commit_print_mud(struct nvme_dev *dev, __u32 result) if (result & 0x1) printf("Detected an overlapping firmware/boot partition image update command\n" - "sequence due to processing a command from a Management Endpoint"); + "sequence due to processing a command from an Admin SQ on a controller\n"); if (result >> 1 & 0x1) printf("Detected an overlapping firmware/boot partition image update command\n" - "sequence due to processing a command from an Admin SQ on a controller"); + "sequence due to processing a command from a Management Endpoint\n"); } static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -5073,7 +5068,7 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin * .slot = cfg.slot, .action = cfg.action, .bpid = cfg.bpid, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = &result, }; err = nvme_cli_fw_commit(dev, &args); @@ -5287,7 +5282,7 @@ static int nvme_get_single_property(int fd, struct get_reg_config *cfg, __u64 *v .fd = fd, .offset = cfg->offset, .value = value, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, }; err = nvme_get_property(&args); @@ -5358,7 +5353,7 @@ static void *mmap_registers(struct nvme_dev *dev, bool writable) sprintf(path, "/sys/class/nvme/%s/device/resource0", dev->name); fd = open(path, writable ? O_RDWR : O_RDONLY); if (fd < 0) { - if (log_level >= LOG_DEBUG) + if (log_level >= LOG_INFO) nvme_show_error("%s did not find a pci resource, open failed %s", dev->name, strerror(errno)); return NULL; @@ -5366,9 +5361,12 @@ static void *mmap_registers(struct nvme_dev *dev, bool writable) membase = mmap(NULL, getpagesize(), prot, MAP_SHARED, fd, 0); if (membase == MAP_FAILED) { - if (log_level >= LOG_DEBUG) { - fprintf(stderr, "%s failed to map. ", dev->name); - fprintf(stderr, "Did your kernel enable CONFIG_IO_STRICT_DEVMEM?\n"); + if (log_level >= LOG_INFO) { + fprintf(stderr, "Failed to map registers to userspace.\n\n" + "Did your kernel enable CONFIG_IO_STRICT_DEVMEM?\n" + "You can disable this feature with command line argument\n\n" + "\tio_memory=relaxed\n\n" + "Also ensure secure boot is disabled.\n\n"); } membase = NULL; } @@ -5385,7 +5383,7 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu "show info in readable format in case of output_format == normal"; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; bool fabrics = false; void *bar; int err; @@ -5401,13 +5399,13 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; } - if (cfg.human_readable) + if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; bar = mmap_registers(dev, false); @@ -5509,7 +5507,7 @@ static int get_register_properties(int fd, void **pbar, struct get_reg_config *c .args_size = sizeof(args), .fd = fd, .value = &value, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, }; size = offset + get_reg_size(offset); @@ -5585,7 +5583,7 @@ bool nvme_is_ctrl_reg(int offset) } static bool get_register_offset(void *bar, bool fabrics, struct get_reg_config *cfg, - enum nvme_print_flags flags) + nvme_print_flags_t flags) { bool offset_matched = cfg->offset >= 0; int offset; @@ -5632,7 +5630,7 @@ static int get_register(int argc, char **argv, struct command *cmd, struct plugi _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; int err; - enum nvme_print_flags flags; + nvme_print_flags_t flags; bool fabrics = false; void *bar; @@ -5677,13 +5675,13 @@ static int get_register(int argc, char **argv, struct command *cmd, struct plugi if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; } - if (cfg.human_readable) + if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; bar = mmap_registers(dev, false); @@ -5718,7 +5716,7 @@ static int nvme_set_single_property(int fd, int offset, uint64_t value) .fd = fd, .offset = offset, .value = value, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; int err = nvme_set_property(&args); @@ -6076,7 +6074,7 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin "Can also be used to change LBAF to change the namespaces reported physical block format."; const char *lbaf = "LBA format to apply (required)"; const char *ses = "[0-2]: secure erase"; - const char *pil = "[0-1]: protection info location last/first 8 bytes of metadata"; + const char *pil = "[0-1]: protection info location last/first bytes of metadata"; const char *pi = "[0-3]: protection info off/Type 1/Type 2/Type 3"; const char *ms = "[0-1]: extended format off/on"; const char *reset = "Automatically reset the controller after successful format"; @@ -6092,7 +6090,6 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin struct config { __u32 namespace_id; - __u32 timeout; __u8 lbaf; __u8 ses; __u8 pi; @@ -6105,7 +6102,6 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin struct config cfg = { .namespace_id = 0, - .timeout = 600000, .lbaf = 0xff, .ses = 0, .pi = 0, @@ -6116,9 +6112,10 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin .bs = 0, }; + nvme_cfg.timeout = 600000; + NVME_ARGS(opts, OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), - OPT_UINT("timeout", 't', &cfg.timeout, timeout), OPT_BYTE("lbaf", 'l', &cfg.lbaf, lbaf), OPT_BYTE("ses", 's', &cfg.ses, ses), OPT_BYTE("pi", 'i', &cfg.pi, pi), @@ -6128,7 +6125,7 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin OPT_FLAG("force", 0, &cfg.force, force), OPT_SUFFIX("block-size", 'b', &cfg.bs, bs)); - err = argconfig_parse(argc, argv, desc, opts); + err = parse_args(argc, argv, desc, opts); if (err) return err; @@ -6269,13 +6266,13 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin struct nvme_format_nvm_args args = { .args_size = sizeof(args), .nsid = cfg.namespace_id, - .lbafu = (cfg.lbaf & NVME_NS_FLBAS_HIGHER_MASK) >> 4, - .lbaf = cfg.lbaf & NVME_NS_FLBAS_LOWER_MASK, + .lbafu = (cfg.lbaf >> 4) & 0x3, + .lbaf = cfg.lbaf & 0xf, .mset = cfg.ms, .pi = cfg.pi, .pil = cfg.pil, .ses = cfg.ses, - .timeout = cfg.timeout, + .timeout = nvme_cfg.timeout, .result = NULL, }; err = nvme_cli_format_nvm(dev, &args); @@ -6342,7 +6339,7 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; _cleanup_free_ void *buf = NULL; - _cleanup_file_ int ffd = STDIN_FILENO; + _cleanup_fd_ int ffd = STDIN_FILENO; int err; __u32 result; @@ -6420,7 +6417,8 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin * should use the buffer method if the value exceeds this * length. */ - if (cfg.feature_id == NVME_FEAT_FID_TIMESTAMP && cfg.value) { + if (cfg.feature_id == NVME_FEAT_FID_TIMESTAMP && + argconfig_parse_seen(opts, "value")) { memcpy(buf, &cfg.value, NVME_FEAT_TIMESTAMP_DATA_SIZE); } else { if (strlen(cfg.file)) @@ -6453,7 +6451,7 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin .cdw15 = 0, .data_len = cfg.data_len, .data = buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = &result, }; err = nvme_set_features(&args); @@ -6492,7 +6490,7 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; _cleanup_free_ void *sec_buf = NULL; - _cleanup_file_ int sec_fd = -1; + _cleanup_fd_ int sec_fd = -1; unsigned int sec_size; int err; @@ -6574,7 +6572,7 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p .tl = cfg.tl, .data_len = cfg.tl, .data = sec_buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; @@ -6601,7 +6599,7 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p _cleanup_free_ void *buf = NULL; __u32 result; __u32 dw12 = 0; - _cleanup_file_ int ffd = STDIN_FILENO; + _cleanup_fd_ int ffd = STDIN_FILENO; int err; struct config { @@ -6709,7 +6707,7 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p .cdw12 = dw12, .data_len = cfg.data_len, .data = buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = &result, }; err = nvme_directive_send(&args); @@ -6789,7 +6787,7 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin .nlb = cfg.block_count, .control = cfg.dtype << 4, .dspec = cfg.dspec, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; err = nvme_write_uncorrectable(&args); @@ -6813,15 +6811,15 @@ static int invalid_tags(__u64 storage_tag, __u64 ref_tag, __u8 sts, __u8 pif) } switch (pif) { - case 0: + case NVME_NVM_PIF_16B_GUARD: if (ref_tag >= (1LL << (32 - sts))) result = 1; break; - case 1: + case NVME_NVM_PIF_32B_GUARD: if (sts > 16 && ref_tag >= (1LL << (80 - sts))) result = 1; break; - case 2: + case NVME_NVM_PIF_64B_GUARD: if (sts > 0 && ref_tag >= (1LL << (48 - sts))) result = 1; break; @@ -6837,12 +6835,25 @@ static int invalid_tags(__u64 storage_tag, __u64 ref_tag, __u8 sts, __u8 pif) return result; } +static void get_pif_sts(struct nvme_id_ns *ns, struct nvme_nvm_id_ns *nvm_ns, __u8 *pif, __u8 *sts) +{ + __u8 lba_index; + __u32 elbaf; + + nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &lba_index); + elbaf = le32_to_cpu(nvm_ns->elbaf[lba_index]); + *sts = elbaf & NVME_NVM_ELBAF_STS_MASK; + *pif = (elbaf & NVME_NVM_ELBAF_PIF_MASK) >> 7; + if (*pif == NVME_NVM_PIF_QTYPE && (nvm_ns->pic & 0x8)) + *pif = (elbaf & NVME_NVM_ELBAF_QPIF_MASK) >> 9; +} + static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugin *plugin) { _cleanup_free_ struct nvme_nvm_id_ns *nvm_ns = NULL; _cleanup_free_ struct nvme_id_ns *ns = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - __u8 lba_index, sts = 0, pif = 0; + __u8 sts = 0, pif = 0; __u16 control = 0; int err; @@ -6953,9 +6964,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi err = nvme_identify_ns_csi(dev_fd(dev), cfg.namespace_id, 0, NVME_CSI_NVM, nvm_ns); if (!err) { - nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &lba_index); - sts = nvm_ns->elbaf[lba_index] & NVME_NVM_ELBAF_STS_MASK; - pif = (nvm_ns->elbaf[lba_index] & NVME_NVM_ELBAF_PIF_MASK) >> 7; + get_pif_sts(ns, nvm_ns, &pif, &sts); } if (invalid_tags(cfg.storage_tag, cfg.ref_tag, sts, pif)) @@ -6975,7 +6984,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi .pif = pif, .storage_tag = cfg.storage_tag, .dspec = cfg.dspec, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; err = nvme_write_zeros(&args); @@ -7078,7 +7087,7 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin .attrs = cfg.cdw11, .nr_ranges = nr, .dsm = dsm, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; err = nvme_dsm(&args); @@ -7282,7 +7291,7 @@ static int copy_cmd(int argc, char **argv, struct command *cmd, struct plugin *p .ilbrt_u64 = cfg.ilbrt, .lbatm = cfg.lbatm, .lbat = cfg.lbat, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; err = nvme_copy(&args); @@ -7405,7 +7414,7 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi .iekey = !!cfg.iekey, .crkey = cfg.crkey, .nrkey = cfg.prkey, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; err = nvme_resv_acquire(&args); @@ -7486,7 +7495,7 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug .iekey = !!cfg.iekey, .crkey = cfg.crkey, .nrkey = cfg.nrkey, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; err = nvme_resv_register(&args); @@ -7562,7 +7571,7 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi .rrela = cfg.rrela, .iekey = !!cfg.iekey, .crkey = cfg.crkey, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; err = nvme_resv_release(&args); @@ -7587,7 +7596,7 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin _cleanup_free_ struct nvme_resv_status *status = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; int err, size; struct config { @@ -7614,7 +7623,7 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -7649,7 +7658,7 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin .eds = cfg.eds, .len = size, .report = status, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; err = nvme_resv_report(&args); @@ -7677,8 +7686,8 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char void *buffer; _cleanup_free_ void *mbuffer = NULL; int err = 0; - _cleanup_file_ int dfd = -1, mfd = -1; - int flags; + _cleanup_fd_ int dfd = -1, mfd = -1; + int flags, pi_size; int mode = 0644; __u16 control = 0, nblocks = 0; __u32 dsmgmt = 0; @@ -7783,7 +7792,7 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char if (err) return err; } else { - err = argconfig_parse(argc, argv, desc, opts); + err = parse_args(argc, argv, desc, opts); if (err) return err; err = open_exclusive(&dev, argc, argv, cfg.force); @@ -7874,13 +7883,23 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &lba_index); logical_block_size = 1 << ns->lbaf[lba_index].ds; ms = ns->lbaf[lba_index].ms; + + nvm_ns = nvme_alloc(sizeof(*nvm_ns)); + if (!nvm_ns) + return -ENOMEM; + + err = nvme_identify_ns_csi(dev_fd(dev), cfg.namespace_id, 0, NVME_CSI_NVM, nvm_ns); + if (!err) + get_pif_sts(ns, nvm_ns, &pif, &sts); + + pi_size = (pif == NVME_NVM_PIF_16B_GUARD) ? 8 : 16; if (NVME_FLBAS_META_EXT(ns->flbas)) { /* - * No meta data is transferred for PRACT=1 and MD=8: + * No meta data is transferred for PRACT=1 and MD=PI size: * 5.2.2.1 Protection Information and Write Commands * 5.2.2.2 Protection Information and Read Commands */ - if (!((cfg.prinfo & 0x8) != 0 && ms == 8)) + if (!((cfg.prinfo & 0x8) != 0 && ms == pi_size)) logical_block_size += ms; } @@ -7905,17 +7924,7 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char if (!buffer) return -ENOMEM; - nvm_ns = nvme_alloc(sizeof(*nvm_ns)); - if (!nvm_ns) - return -ENOMEM; - if (cfg.metadata_size) { - err = nvme_identify_ns_csi(dev_fd(dev), 1, 0, NVME_CSI_NVM, nvm_ns); - if (!err) { - sts = nvm_ns->elbaf[lba_index] & NVME_NVM_ELBAF_STS_MASK; - pif = (nvm_ns->elbaf[lba_index] & NVME_NVM_ELBAF_PIF_MASK) >> 7; - } - mbuffer_size = ((unsigned long long)cfg.block_count + 1) * ms; if (ms && cfg.metadata_size < mbuffer_size) nvme_show_error("Rounding metadata size to fit block count (%lld bytes)", @@ -7990,7 +7999,7 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char .data = buffer, .metadata_len = mbuffer_size, .metadata = mbuffer, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; gettimeofday(&start_time, NULL); @@ -8048,11 +8057,11 @@ static int write_cmd(int argc, char **argv, struct command *cmd, struct plugin * static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - __u16 control = 0; - __u8 lba_index, sts = 0, pif = 0; _cleanup_free_ struct nvme_nvm_id_ns *nvm_ns = NULL; _cleanup_free_ struct nvme_id_ns *ns = NULL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + __u8 sts = 0, pif = 0; + __u16 control = 0; int err; const char *desc = "Verify specified logical blocks on the given device."; @@ -8145,9 +8154,7 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin err = nvme_identify_ns_csi(dev_fd(dev), cfg.namespace_id, 0, NVME_CSI_NVM, nvm_ns); if (!err) { - nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &lba_index); - sts = nvm_ns->elbaf[lba_index] & NVME_NVM_ELBAF_STS_MASK; - pif = (nvm_ns->elbaf[lba_index] & NVME_NVM_ELBAF_PIF_MASK) >> 7; + get_pif_sts(ns, nvm_ns, &pif, &sts); } if (invalid_tags(cfg.storage_tag, cfg.ref_tag, sts, pif)) @@ -8166,7 +8173,7 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin .sts = sts, .pif = pif, .storage_tag = cfg.storage_tag, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; err = nvme_verify(&args); @@ -8244,7 +8251,7 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p .al = cfg.al, .data_len = cfg.size, .data = sec_buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; @@ -8279,7 +8286,7 @@ static int get_lba_status(int argc, char **argv, struct command *cmd, _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; _cleanup_free_ void *buf = NULL; - enum nvme_print_flags flags; + nvme_print_flags_t flags; unsigned long buf_len; int err; @@ -8289,7 +8296,6 @@ static int get_lba_status(int argc, char **argv, struct command *cmd, __u32 mndw; __u8 atype; __u16 rl; - __u32 timeout; }; struct config cfg = { @@ -8298,7 +8304,6 @@ static int get_lba_status(int argc, char **argv, struct command *cmd, .mndw = 0, .atype = 0, .rl = 0, - .timeout = 0, }; NVME_ARGS(opts, @@ -8306,14 +8311,13 @@ static int get_lba_status(int argc, char **argv, struct command *cmd, OPT_SUFFIX("start-lba", 's', &cfg.slba, slba), OPT_UINT("max-dw", 'm', &cfg.mndw, mndw), OPT_BYTE("action", 'a', &cfg.atype, atype), - OPT_SHRT("range-len", 'l', &cfg.rl, rl), - OPT_UINT("timeout", 't', &cfg.timeout, timeout)); + OPT_SHRT("range-len", 'l', &cfg.rl, rl)); err = parse_and_open(&dev, argc, argv, desc, opts); if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -8338,7 +8342,7 @@ static int get_lba_status(int argc, char **argv, struct command *cmd, .rl = cfg.rl, .atype = cfg.atype, .lbas = buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; err = nvme_get_lba_status(&args); @@ -8405,7 +8409,7 @@ static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plug .element_id = cfg.element_id, .cdw11 = cfg.dw11, .cdw12 = cfg.dw12, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = &result, }; err = nvme_capacity_mgmt(&args); @@ -8429,7 +8433,7 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin const char *desc = "Read directive parameters of the specified directive type."; const char *nsr = "namespace stream requested"; - enum nvme_print_flags flags = NORMAL; + nvme_print_flags_t flags = NORMAL; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; _cleanup_free_ void *buf = NULL; __u32 result; @@ -8472,7 +8476,7 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin if (err) return err; - if (cfg.human_readable) + if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; if (cfg.raw_binary) flags = BINARY; @@ -8528,7 +8532,7 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin .cdw12 = dw12, .data_len = cfg.data_len, .data = buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = &result, }; err = nvme_directive_recv(&args); @@ -8627,7 +8631,7 @@ static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugi .ifc = cfg.ifc, .ofi = cfg.ofi, .uuidx = cfg.uuid, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .timeout = nvme_cfg.timeout, .result = NULL, }; err = nvme_lockdown(&args); @@ -8691,7 +8695,7 @@ static int passthru(int argc, char **argv, bool admin, _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - _cleanup_file_ int dfd = -1, mfd = -1; + _cleanup_fd_ int dfd = -1, mfd = -1; int flags; int mode = 0644; void *data = NULL; @@ -8709,7 +8713,6 @@ static int passthru(int argc, char **argv, bool admin, .namespace_id = 0, .data_len = 0, .metadata_len = 0, - .timeout = 0, .cdw2 = 0, .cdw3 = 0, .cdw10 = 0, @@ -8736,7 +8739,6 @@ static int passthru(int argc, char **argv, bool admin, OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_desired), OPT_UINT("data-len", 'l', &cfg.data_len, data_len), OPT_UINT("metadata-len", 'm', &cfg.metadata_len, metadata_len), - OPT_UINT("timeout", 't', &cfg.timeout, timeout), OPT_UINT("cdw2", '2', &cfg.cdw2, cdw2), OPT_UINT("cdw3", '3', &cfg.cdw3, cdw3), OPT_UINT("cdw10", '4', &cfg.cdw10, cdw10), @@ -8837,7 +8839,7 @@ static int passthru(int argc, char **argv, bool admin, printf("cdw13 : %08x\n", cfg.cdw13); printf("cdw14 : %08x\n", cfg.cdw14); printf("cdw15 : %08x\n", cfg.cdw15); - printf("timeout_ms : %08x\n", cfg.timeout); + printf("timeout_ms : %08x\n", nvme_cfg.timeout); } if (cfg.dry_run) return 0; @@ -8853,7 +8855,7 @@ static int passthru(int argc, char **argv, bool admin, cfg.cdw14, cfg.cdw15, cfg.data_len, data, cfg.metadata_len, - mdata, cfg.timeout, &result); + mdata, nvme_cfg.timeout, &result); else err = nvme_io_passthru(dev_fd(dev), cfg.opcode, cfg.flags, cfg.rsvd, @@ -8863,7 +8865,7 @@ static int passthru(int argc, char **argv, bool admin, cfg.cdw14, cfg.cdw15, cfg.data_len, data, cfg.metadata_len, - mdata, cfg.timeout, &result); + mdata, nvme_cfg.timeout, &result); gettimeofday(&end_time, NULL); cmd_name = nvme_cmd_to_string(admin, cfg.opcode); @@ -8975,7 +8977,7 @@ static int gen_dhchap_key(int argc, char **argv, struct command *command, struct OPT_STR("nqn", 'n', &cfg.nqn, nqn), OPT_UINT("hmac", 'm', &cfg.hmac, hmac)); - err = argconfig_parse(argc, argv, desc, opts); + err = parse_args(argc, argv, desc, opts); if (err) return err; @@ -9075,8 +9077,8 @@ static int check_dhchap_key(int argc, char **argv, struct command *command, stru unsigned char decoded_key[128]; unsigned int decoded_len; - u_int32_t crc = crc32(0L, NULL, 0); - u_int32_t key_crc; + uint32_t crc = crc32(0L, NULL, 0); + uint32_t key_crc; int err = 0, hmac; struct config { char *key; @@ -9089,7 +9091,7 @@ static int check_dhchap_key(int argc, char **argv, struct command *command, stru NVME_ARGS(opts, OPT_STR("key", 'k', &cfg.key, key)); - err = argconfig_parse(argc, argv, desc, opts); + err = parse_args(argc, argv, desc, opts); if (err) return err; @@ -9144,10 +9146,10 @@ static int check_dhchap_key(int argc, char **argv, struct command *command, stru return -EINVAL; } crc = crc32(crc, decoded_key, decoded_len); - key_crc = ((u_int32_t)decoded_key[decoded_len]) | - ((u_int32_t)decoded_key[decoded_len + 1] << 8) | - ((u_int32_t)decoded_key[decoded_len + 2] << 16) | - ((u_int32_t)decoded_key[decoded_len + 3] << 24); + key_crc = ((uint32_t)decoded_key[decoded_len]) | + ((uint32_t)decoded_key[decoded_len + 1] << 8) | + ((uint32_t)decoded_key[decoded_len + 2] << 16) | + ((uint32_t)decoded_key[decoded_len + 3] << 24); if (key_crc != crc) { nvme_show_error("CRC mismatch (key %08x, crc %08x)", key_crc, crc); return -EINVAL; @@ -9208,7 +9210,7 @@ static int gen_tls_key(int argc, char **argv, struct command *command, struct pl OPT_UINT("identity", 'I', &cfg.identity, identity), OPT_FLAG("insert", 'i', &cfg.insert, insert)); - err = argconfig_parse(argc, argv, desc, opts); + err = parse_args(argc, argv, desc, opts); if (err) return err; if (cfg.hmac < 1 || cfg.hmac > 2) { @@ -9326,7 +9328,7 @@ static int check_tls_key(int argc, char **argv, struct command *command, struct OPT_UINT("identity", 'I', &cfg.identity, identity), OPT_FLAG("insert", 'i', &cfg.insert, insert)); - err = argconfig_parse(argc, argv, desc, opts); + err = parse_args(argc, argv, desc, opts); if (err) return err; @@ -9402,6 +9404,47 @@ static void __scan_tls_key(long keyring_id, long key_id, fprintf(fd, "%s %s\n", desc, encoded_key); } +static int import_key(const char *keyring, FILE *fd) +{ + long keyring_id; + char tls_str[512]; + char *tls_key; + unsigned char *psk; + unsigned int hmac; + int linenum = -1, key_len; + + keyring_id = nvme_lookup_keyring(keyring); + if (!keyring_id) { + nvme_show_error("Invalid keyring '%s'", keyring); + return -ENOKEY; + } + + while (fgets(tls_str, 512, fd)) { + linenum++; + tls_key = strrchr(tls_str, ' '); + if (!tls_key) { + nvme_show_error("Parse error in line %d", + linenum); + continue; + } + *tls_key = '\0'; + tls_key++; + tls_key[strcspn(tls_key, "\n")] = 0; + psk = nvme_import_tls_key(tls_key, &key_len, &hmac); + if (!psk) { + nvme_show_error("Failed to import key in line %d", + linenum); + continue; + } + nvme_update_key(keyring_id, "psk", tls_str, + psk, key_len); + free(psk); + } + + return 0; +} + + static int tls_key(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Manipulation of TLS keys.\n"; @@ -9410,9 +9453,10 @@ static int tls_key(int argc, char **argv, struct command *command, struct plugin const char *keyfile = "File for list of keys."; const char *import = "Import all keys into the keyring."; const char *export = "Export all keys from the keyring."; + const char *revoke = "Revoke key from the keyring."; - FILE *fd; - int err = 0; + _cleanup_file_ FILE *fd = NULL; + int cnt, err = 0; struct config { char *keyring; @@ -9420,6 +9464,7 @@ static int tls_key(int argc, char **argv, struct command *command, struct plugin char *keyfile; bool import; bool export; + char *revoke; }; struct config cfg = { @@ -9428,6 +9473,7 @@ static int tls_key(int argc, char **argv, struct command *command, struct plugin .keyfile = NULL, .import = false, .export = false, + .revoke = NULL, }; NVME_ARGS(opts, @@ -9435,71 +9481,56 @@ static int tls_key(int argc, char **argv, struct command *command, struct plugin OPT_STR("keytype", 't', &cfg.keytype, keytype), OPT_STR("keyfile", 'f', &cfg.keyfile, keyfile), OPT_FLAG("import", 'i', &cfg.import, import), - OPT_FLAG("export", 'e', &cfg.export, export)); + OPT_FLAG("export", 'e', &cfg.export, export), + OPT_STR("revoke", 'r', &cfg.revoke, revoke)); err = argconfig_parse(argc, argv, desc, opts); if (err) return err; if (cfg.keyfile) { - fd = fopen(cfg.keyfile, "r"); + const char *mode; + + if (cfg.import) + mode = "r"; + else + mode = "w"; + + fd = fopen(cfg.keyfile, mode); if (!fd) { nvme_show_error("Cannot open keyfile %s, error %d\n", cfg.keyfile, errno); return -errno; } - } else - fd = stdin; + } else { + if (cfg.import) + fd = freopen(NULL, "r", stdin); + else + fd = freopen(NULL, "w", stdout); + } - if (cfg.export && cfg.import) { - nvme_show_error("Cannot specify both --import and --export"); - err = -EINVAL; + cnt = 0; + if (cfg.export) cnt++; + if (cfg.import) cnt++; + if (cfg.revoke) cnt++; + + if (cnt != 1) { + nvme_show_error("Must specify either --import, --export or --revoke"); + return -EINVAL; } else if (cfg.export) { - nvme_scan_tls_keys(cfg.keyring, __scan_tls_key, fd); + err = nvme_scan_tls_keys(cfg.keyring, __scan_tls_key, fd); + if (err) + nvme_show_error("Export of TLS keys failed with '%s'", + nvme_strerror(errno)); } else if (cfg.import) { - long keyring_id; - char tls_str[512]; - char *tls_key; - unsigned char *psk; - unsigned int hmac; - int linenum = -1, key_len; - - keyring_id = nvme_lookup_keyring(cfg.keyring); - if (!keyring_id) { - nvme_show_error("Invalid keyring '%s'", cfg.keyring); - err = -ENOKEY; - goto out; - } - - while (fgets(tls_str, 512, fd)) { - linenum++; - tls_key = strrchr(tls_str, ' '); - if (!tls_key) { - nvme_show_error("Parse error in line %d", - linenum); - continue; - } - *tls_key = '\0'; - tls_key++; - psk = nvme_import_tls_key(tls_key, &key_len, &hmac); - if (!psk) { - nvme_show_error("Failed to import key in line %d", - linenum); - continue; - } - nvme_update_key(keyring_id, "psk", tls_str, - psk, key_len); - free(psk); - } + err = import_key(cfg.keyring, fd); } else { - nvme_show_error("Must specify either --import or --export"); - err = -EINVAL; + err = nvme_revoke_tls_key(cfg.keyring, cfg.keytype, cfg.revoke); + if (err) + nvme_show_error("Failed to revoke key '%s'", + nvme_strerror(errno)); } -out: - if (cfg.keyfile) - fclose(fd); - return err; } @@ -9507,8 +9538,8 @@ static int show_topology_cmd(int argc, char **argv, struct command *command, str { const char *desc = "Show the topology\n"; const char *ranking = "Ranking order: namespace|ctrl"; - enum nvme_print_flags flags; - nvme_root_t r; + nvme_print_flags_t flags; + _cleanup_nvme_root_ nvme_root_t r = NULL; enum nvme_cli_topo_ranking rank; int err; @@ -9527,7 +9558,7 @@ static int show_topology_cmd(int argc, char **argv, struct command *command, str if (err) return err; - err = validate_output_format(output_format_val, &flags); + err = validate_output_format(nvme_cfg.output_format, &flags); if (err < 0) { nvme_show_error("Invalid output format"); return err; @@ -9553,14 +9584,11 @@ static int show_topology_cmd(int argc, char **argv, struct command *command, str err = nvme_scan_topology(r, NULL, NULL); if (err < 0) { - if (errno != ENOENT) - nvme_show_error("Failed to scan topology: %s", nvme_strerror(errno)); - nvme_free_tree(r); + nvme_show_error("Failed to scan topology: %s", nvme_strerror(errno)); return err; } nvme_show_topology(r, rank, flags); - nvme_free_tree(r); return err; } @@ -9629,7 +9657,7 @@ static int nvme_mi(int argc, char **argv, __u8 admin_opcode, const char *desc) void *data = NULL; int err = 0; bool send; - _cleanup_file_ int fd = -1; + _cleanup_fd_ int fd = -1; int flags; _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; |