From 5d64e8a26388e2abbf6a6585d17392d6e944ae7b Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 1 Jul 2023 00:38:51 +0200 Subject: Merging upstream version 2.5. Signed-off-by: Daniel Baumann --- nvme.c | 2437 +++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 1320 insertions(+), 1117 deletions(-) (limited to 'nvme.c') diff --git a/nvme.c b/nvme.c index 26ddc24..b5b0585 100644 --- a/nvme.c +++ b/nvme.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * nvme.c -- NVM-Express command line utility. + * NVM-Express command line utility. * * Copyright (c) 2014-2015, Intel Corporation. * @@ -63,11 +63,9 @@ #include "util/base64.h" #include "util/crc32.h" #include "nvme-wrap.h" - #include "util/argconfig.h" #include "util/suffix.h" #include "fabrics.h" - #define CREATE_CMD #include "nvme-builtin.h" @@ -83,6 +81,33 @@ struct feat_cfg { bool human_readable; }; +struct passthru_config { + __u8 opcode; + __u8 flags; + __u16 rsvd; + __u32 namespace_id; + __u32 data_len; + __u32 metadata_len; + __u32 timeout; + __u32 cdw2; + __u32 cdw3; + __u32 cdw10; + __u32 cdw11; + __u32 cdw12; + __u32 cdw13; + __u32 cdw14; + __u32 cdw15; + char *input_file; + char *metadata; + bool raw_binary; + bool show_command; + bool dry_run; + bool read; + bool write; + __u8 prefill; + bool latency; +}; + static const char nvme_version_string[] = NVME_VERSION; static struct plugin builtin = { @@ -97,9 +122,9 @@ static struct program nvme = { .name = "nvme", .version = nvme_version_string, .usage = " [] []", - .desc = "The '' may be either an NVMe character "\ - "device (ex: /dev/nvme0), an nvme block device "\ - "(ex: /dev/nvme0n1), or a mctp address in the form "\ + .desc = "The '' may be either an NVMe character\n" + "device (ex: /dev/nvme0), an nvme block device\n" + "(ex: /dev/nvme0n1), or a mctp address in the form\n" "mctp:,[:ctrl-id]", .extensions = &builtin, }; @@ -111,6 +136,7 @@ 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"; static const char *crkey = "current reservation key"; +static const char *csi = "command set identifier"; static const char *buf_len = "buffer len (if) data is sent or received"; static const char *domainid = "Domain Identifier"; static const char *doper = "directive operation"; @@ -124,7 +150,7 @@ static const char *human_readable_info = "show info in readable format"; static const char *human_readable_log = "show log in readable format"; static const char *iekey = "ignore existing res. key"; static const char *latency = "output latency statistics"; -static const char *lba_format_index = "The index into the LBA Format list "\ +static const char *lba_format_index = "The index into the LBA Format list\n" "identifying the LBA Format capabilities that are to be returned"; static const char *limited_retry = "limit media access attempts"; static const char *lsp = "log specific field"; @@ -157,7 +183,8 @@ static const char space[51] = {[0 ... 49] = ' ', '\0'}; static void *mmap_registers(nvme_root_t r, struct nvme_dev *dev); -static void *__nvme_alloc(size_t len, bool *huge) { +static void *__nvme_alloc(size_t len, bool *huge) +{ void *p; if (!posix_memalign(&p, getpagesize(), len)) { @@ -176,9 +203,9 @@ void nvme_free(void *p, bool huge) if (huge) { if (p) free_hugepage_region(p); - } - else + } else { free(p); + } } void *nvme_alloc(size_t len, bool *huge) @@ -287,19 +314,18 @@ static int open_dev_direct(struct nvme_dev **devp, char *devstr, int flags) dev->name = basename(devstr); err = open(devstr, flags); if (err < 0) { - perror(devstr); + nvme_show_perror(devstr); goto err_free; } dev->direct.fd = err; err = fstat(dev_fd(dev), &dev->direct.stat); if (err < 0) { - perror(devstr); + nvme_show_perror(devstr); goto err_close; } if (!is_chardev(dev) && !is_blkdev(dev)) { - fprintf(stderr, "%s is not a block or character device\n", - devstr); + nvme_show_error("%s is not a block or character device", devstr); err = -ENODEV; goto err_close; } @@ -341,7 +367,7 @@ static int open_dev_mi_mctp(struct nvme_dev **devp, char *devstr) rc = parse_mi_dev(devstr, &net, &eid, &ctrl_id); if (rc) { - fprintf(stderr, "invalid device specifier '%s'\n", devstr); + nvme_show_error("invalid device specifier '%s'", devstr); return rc; } @@ -381,7 +407,7 @@ static int check_arg_dev(int argc, char **argv) { if (optind >= argc) { errno = EINVAL; - perror(argv[0]); + nvme_show_perror(argv[0]); return -EINVAL; } return 0; @@ -438,12 +464,16 @@ enum nvme_print_flags validate_output_format(const char *format) { if (!format) return -EINVAL; + if (!strcmp(format, "normal")) return NORMAL; + if (!strcmp(format, "json")) return JSON; + if (!strcmp(format, "binary")) return BINARY; + return -EINVAL; } @@ -464,9 +494,9 @@ void dev_close(struct nvme_dev *dev) static int get_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct nvme_smart_log smart_log; - const char *desc = "Retrieve SMART log for the given device "\ - "(or optionally a namespace) in either decoded format "\ - "(default) or binary."; + const char *desc = "Retrieve SMART log for the given device\n" + "(or optionally a namespace) in either decoded format\n" + "(default) or binary."; const char *namespace = "(optional) desired namespace"; enum nvme_print_flags flags; struct nvme_dev *dev; @@ -500,10 +530,14 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_fd; + } + if (cfg.raw_binary) flags = BINARY; + if (cfg.human_readable) flags |= VERBOSE; @@ -515,7 +549,7 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "smart log: %s\n", nvme_strerror(errno)); + nvme_show_error("smart log: %s", nvme_strerror(errno)); close_fd: dev_close(dev); ret: @@ -525,8 +559,8 @@ ret: static int get_ana_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Retrieve ANA log for the given device in " \ - "decoded format (default), json or binary."; + const char *desc = "Retrieve ANA log for the given device in\n" + "decoded format (default), json or binary."; const char *groups = "Return ANA groups only."; void *ana_log; size_t ana_log_len; @@ -557,12 +591,14 @@ static int get_ana_log(int argc, char **argv, struct command *cmd, goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_fd; + } err = nvme_cli_identify_ctrl(dev, &ctrl); if (err) { - fprintf(stderr, "ERROR : nvme_identify_ctrl() failed: %s\n", + nvme_show_error("ERROR : nvme_identify_ctrl() failed: %s", nvme_strerror(errno)); goto close_fd; } @@ -582,12 +618,12 @@ static int get_ana_log(int argc, char **argv, struct command *cmd, NVME_LOG_ANA_LSP_RGO_NAMESPACES; err = nvme_cli_get_log_ana(dev, lsp, true, 0, ana_log_len, ana_log); - if (!err) { + if (!err) nvme_show_ana_log(ana_log, dev->name, flags, ana_log_len); - } else if (err > 0) + else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "ana-log: %s", nvme_strerror(errno)); + nvme_show_error("ana-log: %s", nvme_strerror(errno)); free(ana_log); close_fd: dev_close(dev); @@ -621,18 +657,18 @@ static int parse_telemetry_da(struct nvme_dev *dev, *size = (le32_to_cpu(telem->dalb4) + 1) * NVME_LOG_TELEM_BLOCK_SIZE; } else { - fprintf(stderr, "Data area 4 unsupported, bit 6 " - "of Log Page Attributes not set\n"); + nvme_show_error( + "Data area 4 unsupported, bit 6 of Log Page Attributes not set"); return -EINVAL; } break; default: - fprintf(stderr, "Invalid data area parameter - %d\n", da); + nvme_show_error("Invalid data area parameter - %d", da); return -EINVAL; } if (*size == NVME_LOG_TELEM_BLOCK_SIZE) { - fprintf(stderr, "ERROR: No telemetry data block\n"); + nvme_show_error("ERROR: No telemetry data block"); return -ENOENT; } return 0; @@ -808,7 +844,7 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, goto ret; if (!cfg.file_name) { - fprintf(stderr, "Please provide an output file!\n"); + nvme_show_error("Please provide an output file!"); err = -EINVAL; goto close_dev; } @@ -816,7 +852,7 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, cfg.host_gen = !!cfg.host_gen; output = open(cfg.file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (output < 0) { - fprintf(stderr, "Failed to open output file %s: %s!\n", + nvme_show_error("Failed to open output file %s: %s!", cfg.file_name, strerror(errno)); err = output; goto close_dev; @@ -833,8 +869,7 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, &total_size, &log); if (err < 0) { - fprintf(stderr, "get-telemetry-log: %s\n", - nvme_strerror(errno)); + nvme_show_error("get-telemetry-log: %s", nvme_strerror(errno)); goto close_output; } else if (err > 0) { nvme_show_status(err); @@ -863,7 +898,7 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, } if (fsync(output) < 0) { - fprintf(stderr, "ERROR : %s: : fsync : %s\n", __func__, strerror(errno)); + nvme_show_error("ERROR : %s: : fsync : %s", __func__, strerror(errno)); return -1; } @@ -907,8 +942,10 @@ static int get_endurance_log(int argc, char **argv, struct command *cmd, struct goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } err = nvme_cli_get_log_endurance_group(dev, cfg.group_id, &endurance_log); @@ -918,7 +955,7 @@ static int get_endurance_log(int argc, char **argv, struct command *cmd, struct else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "endurance log: %s\n", nvme_strerror(errno)); + nvme_show_error("endurance log: %s", nvme_strerror(errno)); close_dev: dev_close(dev); ret: @@ -949,7 +986,6 @@ static int collect_effects_log(struct nvme_dev *dev, enum nvme_csi csi, static int get_effects_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Retrieve command effects log page and print the table."; - const char *csi = ""; struct list_head log_pages; nvme_effects_log_node_t *node; struct nvme_dev *dev; @@ -974,10 +1010,10 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl }; OPT_ARGS(opts) = { - OPT_FMT("output-format", 'o', &cfg.output_format, output_format), - OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable_log), - OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_log), - OPT_INT("csi", 'c', &cfg.csi, csi), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable_log), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_log), + OPT_INT("csi", 'c', &cfg.csi, csi), OPT_END() }; @@ -986,10 +1022,14 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.raw_binary) flags = BINARY; + if (cfg.human_readable) flags |= VERBOSE; @@ -1035,12 +1075,11 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl else if (err > 0) nvme_show_status(err); else - perror("effects log page"); + nvme_show_perror("effects log page"); close_dev: - while ((node = list_pop(&log_pages, nvme_effects_log_node_t, node))) { + while ((node = list_pop(&log_pages, nvme_effects_log_node_t, node))) free(node); - } dev_close(dev); ret: @@ -1077,8 +1116,10 @@ static int get_supported_log_pages(int argc, char **argv, struct command *cmd, goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } if (cfg.verbose) flags |= VERBOSE; @@ -1089,8 +1130,7 @@ static int get_supported_log_pages(int argc, char **argv, struct command *cmd, else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "supported log pages: %s", - nvme_strerror(errno)); + nvme_show_error("supported log pages: %s", nvme_strerror(errno)); close_dev: dev_close(dev); @@ -1100,8 +1140,8 @@ ret: static int get_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Retrieve specified number of "\ - "error log entries from a given device "\ + const char *desc = "Retrieve specified number of\n" + "error log entries from a given device\n" "in either decoded format (default) or binary."; const char *log_entries = "number of entries to retrieve"; const char *raw = "dump in binary format"; @@ -1135,23 +1175,26 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.raw_binary) flags = BINARY; if (!cfg.log_entries) { - fprintf(stderr, "non-zero log-entries is required param\n"); + nvme_show_error("non-zero log-entries is required param"); err = -1; goto close_dev; } err = nvme_cli_identify_ctrl(dev, &ctrl); if (err < 0) { - perror("identify controller"); + nvme_show_perror("identify controller"); goto close_dev; } else if (err) { - fprintf(stderr, "could not identify controller\n"); + nvme_show_error("could not identify controller"); err = -1; goto close_dev; } @@ -1170,8 +1213,10 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug else if (err > 0) nvme_show_status(err); else - perror("error log"); + nvme_show_perror("error log"); + free(err_log); + close_dev: dev_close(dev); ret: @@ -1180,7 +1225,7 @@ ret: static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Retrieve the firmware log for the "\ + const char *desc = "Retrieve the firmware log for the\n" "specified device in either decoded format (default) or binary."; struct nvme_firmware_slot fw_log; enum nvme_print_flags flags; @@ -1208,8 +1253,11 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.raw_binary) flags = BINARY; @@ -1219,7 +1267,7 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "fw log: %s\n", nvme_strerror(errno)); + nvme_show_error("fw log: %s", nvme_strerror(errno)); close_dev: dev_close(dev); ret: @@ -1228,9 +1276,8 @@ ret: static int get_changed_ns_list_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Retrieve Changed Namespaces log for the given device "\ - "in either decoded format "\ - "(default) or binary."; + const char *desc = "Retrieve Changed Namespaces log for the given device\n" + "in either decoded format (default) or binary."; struct nvme_ns_list changed_ns_list_log; enum nvme_print_flags flags; struct nvme_dev *dev; @@ -1257,8 +1304,11 @@ static int get_changed_ns_list_log(int argc, char **argv, struct command *cmd, s goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.raw_binary) flags = BINARY; @@ -1270,8 +1320,7 @@ static int get_changed_ns_list_log(int argc, char **argv, struct command *cmd, s else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "changed ns list log: %s\n", - nvme_strerror(errno)); + nvme_show_error("changed ns list log: %s", nvme_strerror(errno)); close_dev: dev_close(dev); ret: @@ -1281,9 +1330,9 @@ ret: static int get_pred_lat_per_nvmset_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Retrieve Predictable latency per nvm set log "\ - "page and prints it for the given device in either decoded " \ - "format(default),json or binary."; + const char *desc = "Retrieve Predictable latency per nvm set log\n" + "page and prints it for the given device in either decoded\n" + "format(default),json or binary."; const char *nvmset_id = "NVM Set Identifier"; struct nvme_nvmset_predictable_lat_log plpns_log; enum nvme_print_flags flags; @@ -1314,21 +1363,23 @@ static int get_pred_lat_per_nvmset_log(int argc, char **argv, goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.raw_binary) flags = BINARY; err = nvme_cli_get_log_predictable_lat_nvmset(dev, cfg.nvmset_id, &plpns_log); if (!err) - nvme_show_predictable_latency_per_nvmset(&plpns_log, - cfg.nvmset_id, dev->name, flags); + nvme_show_predictable_latency_per_nvmset(&plpns_log, cfg.nvmset_id, dev->name, + flags); else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "predictable latency per nvm set: %s\n", - nvme_strerror(errno)); + nvme_show_error("predictable latency per nvm set: %s", nvme_strerror(errno)); close_dev: dev_close(dev); @@ -1339,12 +1390,10 @@ ret: static int get_pred_lat_event_agg_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Retrieve Predictable Latency Event" \ - "Aggregate Log page and prints it, for the given" \ - "device in either decoded format(default)," \ - "json or binary."; - const char *log_entries = "Number of pending NVM Set" \ - "log Entries list"; + const char *desc = "Retrieve Predictable Latency Event\n" + "Aggregate Log page and prints it, for the given\n" + "device in either decoded format(default), json or binary."; + const char *log_entries = "Number of pending NVM Set log Entries list"; enum nvme_print_flags flags; struct nvme_id_ctrl ctrl; struct nvme_dev *dev; @@ -1379,21 +1428,23 @@ static int get_pred_lat_event_agg_log(int argc, char **argv, goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.raw_binary) flags = BINARY; if (!cfg.log_entries) { - fprintf(stderr, "non-zero log-entries is required param\n"); + nvme_show_error("non-zero log-entries is required param"); err = -EINVAL; goto close_dev; } err = nvme_cli_identify_ctrl(dev, &ctrl); if (err < 0) { - fprintf(stderr, "identify controller: %s\n", - nvme_strerror(errno)); + nvme_show_error("identify controller: %s", nvme_strerror(errno)); goto close_dev; } else if (err) { nvme_show_status(err); @@ -1411,13 +1462,13 @@ static int get_pred_lat_event_agg_log(int argc, char **argv, err = nvme_cli_get_log_predictable_lat_event(dev, cfg.rae, 0, log_size, pea_log); if (!err) - nvme_show_predictable_latency_event_agg_log(pea_log, cfg.log_entries, - log_size, dev->name, flags); + nvme_show_predictable_latency_event_agg_log(pea_log, cfg.log_entries, log_size, + dev->name, flags); else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "predictable latency event aggregate log page: %s", - nvme_strerror(errno)); + nvme_show_error("predictable latency event aggregate log page: %s", + nvme_strerror(errno)); free(pea_log); close_dev: @@ -1429,11 +1480,10 @@ ret: static int get_persistent_event_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Retrieve Persistent Event log info for"\ - " the given device in either decoded format(default),"\ - " json or binary."; - const char *action = "action the controller shall take during"\ - " processing this persistent log page command."; + const char *desc = "Retrieve Persistent Event log info for\n" + "the given device in either decoded format(default), json or binary."; + const char *action = "action the controller shall take during\n" + "processing this persistent log page command."; const char *log_len = "number of bytes to retrieve"; struct nvme_persistent_event_log *pevent, *pevent_collected; enum nvme_print_flags flags; @@ -1469,8 +1519,11 @@ static int get_persistent_event_log(int argc, char **argv, goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.raw_binary) flags = BINARY; @@ -1483,8 +1536,7 @@ static int get_persistent_event_log(int argc, char **argv, err = nvme_cli_get_log_persistent_event(dev, cfg.action, sizeof(*pevent), pevent); if (err < 0) { - fprintf(stderr, "persistent event log: %s\n", - nvme_strerror(errno)); + nvme_show_error("persistent event log: %s", nvme_strerror(errno)); goto free_pevent; } else if (err) { nvme_show_status(err); @@ -1525,8 +1577,7 @@ static int get_persistent_event_log(int argc, char **argv, sizeof(*pevent), pevent); if (err < 0) { - fprintf(stderr, "persistent event log: %s\n", - nvme_strerror(errno)); + nvme_show_error("persistent event log: %s", nvme_strerror(errno)); goto free; } else if (err) { nvme_show_status(err); @@ -1534,18 +1585,18 @@ static int get_persistent_event_log(int argc, char **argv, } pevent_collected = pevent_log_info; if (pevent_collected->gen_number != pevent->gen_number) { - printf("Collected Persistent Event Log may be invalid, "\ - "Re-read the log is required\n"); + printf("Collected Persistent Event Log may be invalid,\n" + "Re-read the log is required\n"); goto free; } nvme_show_persistent_event_log(pevent_log_info, cfg.action, cfg.log_len, dev->name, flags); - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); - else - fprintf(stderr, "persistent event log: %s\n", - nvme_strerror(errno)); + } else { + nvme_show_error("persistent event log: %s", nvme_strerror(errno)); + } free: nvme_free(pevent_log_info, huge); @@ -1560,12 +1611,10 @@ ret: static int get_endurance_event_agg_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Retrieve Retrieve Predictable Latency " \ - "Event Aggregate page and prints it, for the given " \ - "device in either decoded format(default), " \ - "json or binary."; - const char *log_entries = "Number of pending Endurance Group " \ - "Event log Entries list"; + const char *desc = "Retrieve Retrieve Predictable Latency\n" + "Event Aggregate page and prints it, for the given\n" + "device in either decoded format(default), json or binary."; + const char *log_entries = "Number of pending Endurance Group Event log Entries list"; void *endurance_log; struct nvme_id_ctrl ctrl; enum nvme_print_flags flags; @@ -1600,24 +1649,26 @@ static int get_endurance_event_agg_log(int argc, char **argv, goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.raw_binary) flags = BINARY; if (!cfg.log_entries) { - fprintf(stderr, "non-zero log-entries is required param\n"); + nvme_show_error("non-zero log-entries is required param"); err = -EINVAL; goto close_dev; } err = nvme_cli_identify_ctrl(dev, &ctrl); if (err < 0) { - fprintf(stderr, "identify controller: %s\n", - nvme_strerror(errno)); + nvme_show_error("identify controller: %s", nvme_strerror(errno)); goto close_dev; } else if (err) { - fprintf(stderr, "could not identify controller\n"); + nvme_show_error("could not identify controller"); err = -ENODEV; goto close_dev; } @@ -1633,13 +1684,13 @@ static int get_endurance_event_agg_log(int argc, char **argv, err = nvme_cli_get_log_endurance_grp_evt(dev, cfg.rae, 0, log_size, endurance_log); if (!err) - nvme_show_endurance_group_event_agg_log(endurance_log, cfg.log_entries, - log_size, dev->name, flags); + nvme_show_endurance_group_event_agg_log(endurance_log, cfg.log_entries, log_size, + dev->name, flags); else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "endurance group event aggregate log page: %s\n", - nvme_strerror(errno)); + nvme_show_error("endurance group event aggregate log page: %s", + nvme_strerror(errno)); free(endurance_log); close_dev: @@ -1651,9 +1702,8 @@ ret: static int get_lba_status_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Retrieve Get LBA Status Info Log " \ - "and prints it, for the given device in either " \ - "decoded format(default),json or binary."; + const char *desc = "Retrieve Get LBA Status Info Log and prints it,\n" + "for the given device in either decoded format(default),json or binary."; void *lab_status; enum nvme_print_flags flags; struct nvme_dev *dev; @@ -1681,14 +1731,15 @@ static int get_lba_status_log(int argc, char **argv, goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } err = nvme_cli_get_log_lba_status(dev, true, 0, sizeof(__u32), &lslplen); if (err < 0) { - fprintf(stderr, "lba status log page: %s\n", - nvme_strerror(errno)); + nvme_show_error("lba status log page: %s", nvme_strerror(errno)); goto close_dev; } else if (err) { nvme_show_status(err); @@ -1701,15 +1752,13 @@ static int get_lba_status_log(int argc, char **argv, goto close_dev; } - err = nvme_cli_get_log_lba_status(dev, cfg.rae, 0, lslplen, - lab_status); + err = nvme_cli_get_log_lba_status(dev, cfg.rae, 0, lslplen, lab_status); if (!err) nvme_show_lba_status_log(lab_status, lslplen, dev->name, flags); else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "lba status log page: %s\n", - nvme_strerror(errno)); + nvme_show_error("lba status log page: %s", nvme_strerror(errno)); free(lab_status); close_dev: @@ -1722,10 +1771,9 @@ static int get_resv_notif_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Retrieve Reservation Notification " \ - "log page and prints it, for the given " \ - "device in either decoded format(default), " \ - "json or binary."; + const char *desc = "Retrieve Reservation Notification\n" + "log page and prints it, for the given\n" + "device in either decoded format(default), json or binary."; struct nvme_resv_notification_log resv; enum nvme_print_flags flags; struct nvme_dev *dev; @@ -1749,8 +1797,10 @@ static int get_resv_notif_log(int argc, char **argv, goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } err = nvme_cli_get_log_reservation(dev, false, &resv); if (!err) @@ -1758,8 +1808,7 @@ static int get_resv_notif_log(int argc, char **argv, else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "resv notifi log: %s\n", - nvme_strerror(errno)); + nvme_show_error("resv notifi log: %s", nvme_strerror(errno)); close_dev: dev_close(dev); @@ -1770,10 +1819,9 @@ ret: static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Retrieve Boot Partition " \ - "log page and prints it, for the given " \ - "device in either decoded format(default), " \ - "json or binary."; + const char *desc = "Retrieve Boot Partition\n" + "log page and prints it, for the given\n" + "device in either decoded format(default), json or binary."; const char *fname = "boot partition data output file name"; struct nvme_boot_partition boot; __u8 *bp_log; @@ -1806,24 +1854,26 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } if (!cfg.file_name) { - fprintf(stderr, "Please provide an output file!\n"); + nvme_show_error("Please provide an output file!"); err = -1; goto close_dev; } if (cfg.lsp > 127) { - fprintf(stderr, "invalid lsp param: %u\n", cfg.lsp); + nvme_show_error("invalid lsp param: %u", cfg.lsp); err = -1; goto close_dev; } output = open(cfg.file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (output < 0) { - fprintf(stderr, "Failed to open output file %s: %s!\n", + nvme_show_error("Failed to open output file %s: %s!", cfg.file_name, strerror(errno)); err = output; goto close_dev; @@ -1832,8 +1882,7 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct err = nvme_cli_get_log_boot_partition(dev, false, cfg.lsp, sizeof(boot), &boot); if (err < 0) { - fprintf(stderr, "boot partition log: %s\n", - nvme_strerror(errno)); + nvme_show_error("boot partition log: %s", nvme_strerror(errno)); goto close_output; } else if (err) { nvme_show_status(err); @@ -1851,20 +1900,17 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct sizeof(boot) + bpsz, (struct nvme_boot_partition *)bp_log); if (!err) - nvme_show_boot_part_log(&bp_log, dev->name, flags, - sizeof(boot) + bpsz); + nvme_show_boot_part_log(&bp_log, dev->name, flags, sizeof(boot) + bpsz); else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "boot partition log: %s\n", - nvme_strerror(errno)); + nvme_show_error("boot partition log: %s", nvme_strerror(errno)); err = write(output, (void *) bp_log + sizeof(boot), bpsz); - if (err != bpsz) { + if (err != bpsz) fprintf(stderr, "Failed to flush all data to file!\n"); - } else { + else printf("Data flushed into file %s\n", cfg.file_name); - } err = 0; free(bp_log); @@ -1910,8 +1956,10 @@ static int get_media_unit_stat_log(int argc, char **argv, struct command *cmd, goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } if (cfg.raw_binary) flags = BINARY; @@ -1922,8 +1970,7 @@ static int get_media_unit_stat_log(int argc, char **argv, struct command *cmd, else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "media unit status log: %s\n", - nvme_strerror(errno)); + nvme_show_error("media unit status log: %s", nvme_strerror(errno)); close_dev: dev_close(dev); @@ -1964,8 +2011,10 @@ static int get_supp_cap_config_log(int argc, char **argv, struct command *cmd, goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } if (cfg.raw_binary) flags = BINARY; @@ -1977,7 +2026,7 @@ static int get_supp_cap_config_log(int argc, char **argv, struct command *cmd, else if (err > 0) nvme_show_status(err); else - perror("supported capacity configuration list log"); + nvme_show_perror("supported capacity configuration list log"); close_dev: dev_close(dev); @@ -2009,7 +2058,7 @@ static int io_mgmt_send(int argc, char **argv, struct command *cmd, struct plugi OPT_ARGS(opts) = { OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), - OPT_UINT("mos", 's', &cfg.mos, mos), + OPT_SHRT("mos", 's', &cfg.mos, mos), OPT_BYTE("mo", 'm', &cfg.mo, mo), OPT_FILE("data", 'd', &cfg.file, data), OPT_UINT("data-len", 'l', &cfg.data_len, buf_len), @@ -2023,7 +2072,7 @@ static int io_mgmt_send(int argc, char **argv, struct command *cmd, struct plugi if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + nvme_show_perror("get-namespace-id"); goto close_dev; } } @@ -2031,7 +2080,7 @@ static int io_mgmt_send(int argc, char **argv, struct command *cmd, struct plugi if (cfg.data_len) { buf = calloc(1, cfg.data_len); if (!buf) { - perror("could not alloc memory for io mgmt receive data"); + nvme_show_perror("could not alloc memory for io mgmt receive data"); err = -ENOMEM; goto close_dev; } @@ -2040,14 +2089,14 @@ static int io_mgmt_send(int argc, char **argv, struct command *cmd, struct plugi if (cfg.file) { dfd = open(cfg.file, O_RDONLY); if (dfd < 0) { - perror(cfg.file); + nvme_show_perror(cfg.file); goto free; } } err = read(dfd, buf, cfg.data_len); if (err < 0) { - perror("read"); + nvme_show_perror("read"); goto close_fd; } @@ -2069,7 +2118,7 @@ static int io_mgmt_send(int argc, char **argv, struct command *cmd, struct plugi else if (err > 0) nvme_show_status(err); else - perror("io-mgmt-send"); + nvme_show_perror("io-mgmt-send"); close_fd: if (cfg.file) @@ -2105,7 +2154,7 @@ static int io_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugi OPT_ARGS(opts) = { OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), - OPT_UINT("mos", 's', &cfg.mos, mos), + OPT_SHRT("mos", 's', &cfg.mos, mos), OPT_BYTE("mo", 'm', &cfg.mo, mo), OPT_FILE("data", 'd', &cfg.file, data), OPT_UINT("data-len", 'l', &cfg.data_len, buf_len), @@ -2119,7 +2168,7 @@ static int io_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugi if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + nvme_show_perror("get-namespace-id"); goto close_dev; } } @@ -2127,7 +2176,7 @@ static int io_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugi if (cfg.data_len) { buf = calloc(1, cfg.data_len); if (!buf) { - perror("could not alloc memory for io mgmt receive data"); + nvme_show_perror("could not alloc memory for io mgmt receive data"); err = -ENOMEM; goto close_dev; } @@ -2152,13 +2201,13 @@ static int io_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugi if (cfg.file) { dfd = open(cfg.file, O_WRONLY | O_CREAT, 0644); if (dfd < 0) { - perror(cfg.file); + nvme_show_perror(cfg.file); goto free; } err = write(dfd, buf, cfg.data_len); if (err < 0) { - perror("write"); + nvme_show_perror("write"); goto close_fd; } } else { @@ -2167,7 +2216,7 @@ static int io_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugi } else if (err > 0) { nvme_show_status(err); } else { - perror("io-mgmt-recv"); + nvme_show_perror("io-mgmt-recv"); } close_fd: @@ -2183,8 +2232,8 @@ close_dev: static int get_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Retrieve desired number of bytes "\ - "from a given log on a specified device in either "\ + const char *desc = "Retrieve desired number of bytes\n" + "from a given log on a specified device in either\n" "hex-dump (default) or binary format"; const char *log_id = "identifier of log to retrieve"; const char *log_len = "how many bytes to retrieve"; @@ -2192,7 +2241,6 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl const char *lpo = "log page offset specifies the location within a log page from where to start returning data"; const char *lsi = "log specific identifier specifies an identifier that is required for a particular log page"; const char *raw = "output in raw format"; - const char *csi = "command set identifier"; const char *offset_type = "offset type"; const char *xfer_len = "read chunk size (default 4k)"; struct nvme_dev *dev; @@ -2258,32 +2306,32 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl } if (!cfg.log_len || cfg.log_len & 0x3) { - fprintf(stderr, "non-zero or non-dw alignment log-len is required param\n"); + nvme_show_error("non-zero or non-dw alignment log-len is required param"); err = -EINVAL; goto close_dev; } if (cfg.lsp > 127) { - fprintf(stderr, "invalid lsp param\n"); + nvme_show_error("invalid lsp param"); err = -EINVAL; goto close_dev; } if (cfg.uuid_index > 127) { - fprintf(stderr, "invalid uuid index param\n"); + nvme_show_error("invalid uuid index param"); err = -EINVAL; goto close_dev; } if (cfg.xfer_len == 0 || cfg.xfer_len % 4096) { - fprintf(stderr, "xfer-len argument invalid. It needs to be mulitple of 4k"); + nvme_show_error("xfer-len argument invalid. It needs to be multiple of 4k"); err = -EINVAL; goto close_dev; } log = malloc(cfg.log_len); if (!log) { - perror("could not alloc buffer for log\n"); + nvme_show_perror("could not alloc buffer for log\n"); err = -ENOMEM; goto close_dev; } @@ -2306,16 +2354,17 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl err = nvme_cli_get_log_page(dev, cfg.xfer_len, &args); if (!err) { if (!cfg.raw_binary) { - printf("Device:%s log-id:%d namespace-id:%#x\n", - dev->name, cfg.log_id, - cfg.namespace_id); + printf("Device:%s log-id:%d namespace-id:%#x\n", dev->name, cfg.log_id, + cfg.namespace_id); d(log, cfg.log_len, 16, 1); - } else + } else { d_raw((unsigned char *)log, cfg.log_len); - } else if (err > 0) + } + } else if (err > 0) { nvme_show_status(err); - else - fprintf(stderr, "log page: %s\n", nvme_strerror(errno)); + } else { + nvme_show_error("log page: %s", nvme_strerror(errno)); + } free(log); close_dev: @@ -2347,10 +2396,10 @@ static int sanitize_log(int argc, char **argv, struct command *command, struct p }; OPT_ARGS(opts) = { - OPT_FLAG("rae", 'r', &cfg.rae, rae), - OPT_FMT("output-format", 'o', &cfg.output_format, output_format), - OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable_log), - OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_log), + OPT_FLAG("rae", 'r', &cfg.rae, rae), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable_log), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_log), OPT_END() }; @@ -2359,10 +2408,14 @@ static int sanitize_log(int argc, char **argv, struct command *command, struct p goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.raw_binary) flags = BINARY; + if (cfg.human_readable) flags |= VERBOSE; @@ -2372,8 +2425,7 @@ static int sanitize_log(int argc, char **argv, struct command *command, struct p else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "sanitize status log: %s\n", - nvme_strerror(errno)); + nvme_show_error("sanitize status log: %s", nvme_strerror(errno)); close_dev: dev_close(dev); ret: @@ -2400,8 +2452,8 @@ static int get_fid_support_effects_log(int argc, char **argv, struct command *cm }; OPT_ARGS(opts) = { - OPT_FMT("output-format", 'o', &cfg.output_format, output_format), - OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable_log), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable_log), OPT_END() }; @@ -2410,21 +2462,21 @@ static int get_fid_support_effects_log(int argc, char **argv, struct command *cm goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.human_readable) flags |= VERBOSE; - err = nvme_cli_get_log_fid_supported_effects(dev, false, - &fid_support_log); + err = nvme_cli_get_log_fid_supported_effects(dev, false, &fid_support_log); if (!err) - nvme_show_fid_support_effects_log(&fid_support_log, - dev->name, flags); + nvme_show_fid_support_effects_log(&fid_support_log, dev->name, flags); else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "fid support effects log: %s\n", - nvme_strerror(errno)); + nvme_show_error("fid support effects log: %s", nvme_strerror(errno)); close_dev: dev_close(dev); ret: @@ -2451,8 +2503,8 @@ static int get_mi_cmd_support_effects_log(int argc, char **argv, struct command }; OPT_ARGS(opts) = { - OPT_FMT("output-format", 'o', &cfg.output_format, output_format), - OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable_log), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable_log), OPT_END() }; @@ -2461,21 +2513,21 @@ static int get_mi_cmd_support_effects_log(int argc, char **argv, struct command goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.human_readable) flags |= VERBOSE; - err = nvme_cli_get_log_mi_cmd_supported_effects(dev, false, - &mi_cmd_support_log); + err = nvme_cli_get_log_mi_cmd_supported_effects(dev, false, &mi_cmd_support_log); if (!err) - nvme_show_mi_cmd_support_effects_log(&mi_cmd_support_log, - dev->name, flags); + nvme_show_mi_cmd_support_effects_log(&mi_cmd_support_log, dev->name, flags); else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "mi command support effects log: %s\n", - nvme_strerror(errno)); + nvme_show_error("mi command support effects log: %s", nvme_strerror(errno)); close_dev: dev_close(dev); ret: @@ -2484,7 +2536,7 @@ ret: static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Show controller list information for the subsystem the "\ + const char *desc = "Show controller list information for the subsystem the\n" "given device is part of, or optionally controllers attached to a specific namespace."; const char *controller = "controller to display"; struct nvme_ctrl_list *cntlist; @@ -2516,11 +2568,13 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin * goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } if (posix_memalign((void *)&cntlist, getpagesize(), 0x1000)) { - fprintf(stderr, "can not allocate controller list payload\n"); + nvme_show_error("can not allocate controller list payload"); err = -ENOMEM; goto close_dev; } @@ -2535,8 +2589,7 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin * else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "id controller list: %s\n", - nvme_strerror(errno)); + nvme_show_error("id controller list: %s", nvme_strerror(errno)); free(cntlist); close_dev: @@ -2547,7 +2600,7 @@ ret: static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "For the specified controller handle, show the "\ + const char *desc = "For the specified controller handle, show the\n" "namespace list in the associated NVMe subsystem, optionally starting with a given nsid."; const char *namespace_id = "first nsid returned list should start from"; const char *csi = "I/O command set identifier"; @@ -2584,16 +2637,14 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) - goto close_dev; if (flags != JSON && flags != NORMAL) { - err = -EINVAL; + nvme_show_error("Invalid output format"); goto close_dev; } if (!cfg.namespace_id) { err = -EINVAL; - fprintf(stderr, "invalid nsid parameter\n"); + nvme_show_error("invalid nsid parameter"); goto close_dev; } @@ -2619,8 +2670,7 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "id namespace list: %s", - nvme_strerror(errno)); + nvme_show_error("id namespace list: %s", nvme_strerror(errno)); close_dev: dev_close(dev); ret: @@ -2629,8 +2679,8 @@ ret: static int id_ns_lba_format(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send an Identify Namespace command to the given "\ - "device, returns capability field properties of the specified "\ + const char *desc = "Send an Identify Namespace command to the given\n" + "device, returns capability field properties of the specified\n" "LBA Format index in various formats."; enum nvme_print_flags flags; struct nvme_id_ns ns; @@ -2664,8 +2714,10 @@ static int id_ns_lba_format(int argc, char **argv, struct command *cmd, struct p goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } if (cfg.verbose) flags |= VERBOSE; @@ -2678,7 +2730,8 @@ static int id_ns_lba_format(int argc, char **argv, struct command *cmd, struct p else if (err > 0) nvme_show_status(err); else - perror("identify namespace for specific LBA format"); + nvme_show_perror("identify namespace for specific LBA format"); + close_dev: dev_close(dev); ret: @@ -2688,8 +2741,7 @@ ret: static int id_endurance_grp_list(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Show endurance group list information for the given endurance "\ - "group id"; + const char *desc = "Show endurance group list information for the given endurance group id"; const char *endurance_grp_id = "Endurance Group ID"; struct nvme_id_endurance_group_list *endgrp_list; enum nvme_print_flags flags; @@ -2717,11 +2769,8 @@ static int id_endurance_grp_list(int argc, char **argv, struct command *cmd, goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) - goto close_dev; if (flags != JSON && flags != NORMAL) { - err = -EINVAL; - fprintf(stderr, "invalid output format\n"); + nvme_show_error("invalid output format"); goto close_dev; } @@ -2730,15 +2779,13 @@ static int id_endurance_grp_list(int argc, char **argv, struct command *cmd, goto close_dev; } - err = nvme_identify_endurance_group_list(dev_fd(dev), cfg.endgrp_id, - endgrp_list); + err = nvme_identify_endurance_group_list(dev_fd(dev), cfg.endgrp_id, endgrp_list); if (!err) nvme_show_endurance_group_list(endgrp_list, flags); else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "Id endurance group list: %s", - nvme_strerror(errno)); + nvme_show_error("Id endurance group list: %s", nvme_strerror(errno)); free(endgrp_list); close_dev: @@ -2749,11 +2796,11 @@ ret: static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Delete the given namespace by "\ - "sending a namespace management command to "\ - "the provided device. All controllers should be detached from "\ - "the namespace prior to namespace deletion. A namespace ID "\ - "becomes inactive when that namespace is detached or, if "\ + const char *desc = "Delete the given namespace by\n" + "sending a namespace management command to\n" + "the provided device. All controllers should be detached from\n" + "the namespace prior to namespace deletion. A namespace ID\n" + "becomes inactive when that namespace is detached or, if\n" "the namespace is not already inactive, once deleted."; const char *namespace_id = "namespace to delete"; struct nvme_dev *dev; @@ -2782,20 +2829,18 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin * if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - fprintf(stderr, "get-namespace-id: %s\n", - nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } } err = nvme_cli_ns_mgmt_delete(dev, cfg.namespace_id); if (!err) - printf("%s: Success, deleted nsid:%d\n", cmd->name, - cfg.namespace_id); + printf("%s: Success, deleted nsid:%d\n", cmd->name, cfg.namespace_id); else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "delete namespace: %s\n", nvme_strerror(errno)); + nvme_show_error("delete namespace: %s", nvme_strerror(errno)); close_dev: dev_close(dev); @@ -2834,20 +2879,17 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s goto ret; if (!cfg.namespace_id) { - fprintf(stderr, "%s: namespace-id parameter required\n", - cmd->name); + nvme_show_error("%s: namespace-id parameter required", cmd->name); err = -EINVAL; goto close_dev; } num = argconfig_parse_comma_sep_array(cfg.cntlist, list, 2047); - if (!num) { + if (!num) fprintf(stderr, "warning: empty controller-id list will result in no actual change in namespace attachment\n"); - } if (num == -1) { - fprintf(stderr, "%s: controller id list is malformed\n", - cmd->name); + nvme_show_error("%s: controller id list is malformed", cmd->name); err = -EINVAL; goto close_dev; } @@ -2869,7 +2911,7 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s else if (err > 0) nvme_show_status(err); else - perror(attach ? "attach namespace" : "detach namespace"); + nvme_show_perror(attach ? "attach namespace" : "detach namespace"); close_dev: dev_close(dev); @@ -2879,20 +2921,22 @@ ret: static int attach_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Attach the given namespace to the "\ - "given controller or comma-sep list of controllers. ID of the "\ - "given namespace becomes active upon attachment to a "\ - "controller. A namespace must be attached to a controller "\ + const char *desc = "Attach the given namespace to the\n" + "given controller or comma-sep list of controllers. ID of the\n" + "given namespace becomes active upon attachment to a\n" + "controller. A namespace must be attached to a controller\n" "before IO commands may be directed to that namespace."; + return nvme_attach_ns(argc, argv, 1, desc, cmd); } static int detach_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Detach the given namespace from the "\ - "given controller; de-activates the given namespace's ID. A "\ - "namespace must be attached to a controller before IO "\ + const char *desc = "Detach the given namespace from the\n" + "given controller; de-activates the given namespace's ID. A\n" + "namespace must be attached to a controller before IO\n" "commands may be directed to that namespace."; + return nvme_attach_ns(argc, argv, 0, desc, cmd); } @@ -2919,17 +2963,16 @@ static int parse_lba_num_si(struct nvme_dev *dev, const char *opt, return 0; if (*num) { - fprintf(stderr, - "Invalid specification of both %s and its SI argument, please specify only one\n", - opt); + nvme_show_error( + "Invalid specification of both %s and its SI argument, please specify only one", + opt); return err; } err = nvme_cli_identify_ctrl(dev, &ctrl); if (err) { if (err < 0) - fprintf(stderr, "identify controller: %s\n", - nvme_strerror(errno)); + nvme_show_error("identify controller: %s", nvme_strerror(errno)); else nvme_show_status(err); return err; @@ -2941,8 +2984,8 @@ static int parse_lba_num_si(struct nvme_dev *dev, const char *opt, err = nvme_cli_identify(dev, &args); if (err) { if (err < 0) - fprintf(stderr, "identify namespace list: %s", - nvme_strerror(errno)); + nvme_show_error("identify namespace list: %s", + nvme_strerror(errno)); else nvme_show_status(err); return err; @@ -2953,8 +2996,7 @@ static int parse_lba_num_si(struct nvme_dev *dev, const char *opt, err = nvme_cli_identify_ns(dev, nsid, &ns); if (err) { if (err < 0) - fprintf(stderr, "identify namespace: %s", - nvme_strerror(errno)); + nvme_show_error("identify namespace: %s", nvme_strerror(errno)); else nvme_show_status(err); return err; @@ -2963,10 +3005,9 @@ static int parse_lba_num_si(struct nvme_dev *dev, const char *opt, i = flbas & NVME_NS_FLBAS_LOWER_MASK; lbas = (1 << ns.lbaf[i].ds) + ns.lbaf[i].ms; - if (suffix_si_parse(val, &endptr, (uint64_t*)num)) { - fprintf(stderr, - "Expected long suffixed integer argument for '%s-si' but got '%s'!\n", - opt, val); + if (suffix_si_parse(val, &endptr, (uint64_t *)num)) { + nvme_show_error("Expected long suffixed integer argument for '%s-si' but got '%s'!", + opt, val); return -errno; } @@ -2978,30 +3019,38 @@ static int parse_lba_num_si(struct nvme_dev *dev, const char *opt, static int create_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send a namespace management command "\ - "to the specified device to create a namespace with the given "\ - "parameters. The next available namespace ID is used for the "\ - "create operation. Note that create-ns does not attach the "\ + const char *desc = "Send a namespace management command\n" + "to the specified device to create a namespace with the given\n" + "parameters. The next available namespace ID is used for the\n" + "create operation. Note that create-ns does not attach the\n" "namespace to a controller, the attach-ns command is needed."; const char *nsze = "size of ns (NSZE)"; const char *ncap = "capacity of ns (NCAP)"; - const char *flbas = "Formatted LBA size (FLBAS), if entering this "\ - "value ignore \'block-size\' field"; + const char *flbas = + "Formatted LBA size (FLBAS), if entering this value ignore \'block-size\' field"; const char *dps = "data protection settings (DPS)"; const char *nmic = "multipath and sharing capabilities (NMIC)"; const char *anagrpid = "ANA Group Identifier (ANAGRPID)"; const char *nvmsetid = "NVM Set Identifier (NVMSETID)"; const char *csi = "command set identifier (CSI)"; const char *lbstm = "logical block storage tag mask (LBSTM)"; - const char *bs = "target block size, specify only if \'FLBAS\' "\ - "value not entered"; + const char *nphndls = "Number of Placement Handles (NPHNDLS)"; + const char *bs = "target block size, specify only if \'FLBAS\' value not entered"; const char *nsze_si = "size of ns (NSZE) in standard SI units"; const char *ncap_si = "capacity of ns (NCAP) in standard SI units"; + const char *azr = "Allocate ZRWA Resources (AZR) for Zoned Namespace Command Set"; + const char *rar = "Requested Active Resources (RAR) for Zoned Namespace Command Set"; + const char *ror = "Requested Open Resources (ROR) for Zoned Namespace Command Set"; + const char *rnumzrwa = + "Requested Number of ZRWA Resources (RNUMZRWA) for Zoned Namespace Command Set"; + const char *phndls = "Comma separated list of Placement Handle Associated RUH"; struct nvme_id_ns ns; struct nvme_dev *dev; int err = 0, i; __u32 nsid; + uint16_t num_phandle; + uint16_t phndl[128] = { 0, }; struct config { __u64 nsze; @@ -3015,8 +3064,14 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * __u32 timeout; __u8 csi; __u64 lbstm; + __u16 nphndls; char *nsze_si; char *ncap_si; + bool azr; + __u32 rar; + __u32 ror; + __u32 rnumzrwa; + char *phndls; }; struct config cfg = { @@ -3027,12 +3082,18 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * .nmic = 0, .anagrpid = 0, .nvmsetid = 0, - .bs = 0x00, + .bs = 0x00, .timeout = 120000, .csi = 0, .lbstm = 0, + .nphndls = 0, .nsze_si = NULL, .ncap_si = NULL, + .azr = false, + .rar = 0, + .ror = 0, + .rnumzrwa = 0, + .phndls = "", }; OPT_ARGS(opts) = { @@ -3047,8 +3108,14 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * 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), OPT_STR("nsze-si", 'S', &cfg.nsze_si, nsze_si), OPT_STR("ncap-si", 'C', &cfg.ncap_si, ncap_si), + OPT_FLAG("azr", 'z', &cfg.azr, azr), + OPT_UINT("rar", 'r', &cfg.rar, rar), + OPT_UINT("ror", 'o', &cfg.ror, ror), + OPT_UINT("rnumzrwa", 'u', &cfg.rnumzrwa, rnumzrwa), + OPT_LIST("phndls", 'p', &cfg.phndls, phndls), OPT_END() }; @@ -3057,25 +3124,24 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * goto ret; if (cfg.flbas != 0xff && cfg.bs != 0x00) { - fprintf(stderr, - "Invalid specification of both FLBAS and Block Size, please specify only one\n"); + nvme_show_error( + "Invalid specification of both FLBAS and Block Size, please specify only one"); err = -EINVAL; goto close_dev; } if (cfg.bs) { if ((cfg.bs & (~cfg.bs + 1)) != cfg.bs) { - fprintf(stderr, - "Invalid value for block size (%"PRIu64"). Block size must be a power of two\n", - (uint64_t)cfg.bs); + nvme_show_error( + "Invalid value for block size (%"PRIu64"). Block size must be a power of two", + (uint64_t)cfg.bs); err = -EINVAL; goto close_dev; } err = nvme_cli_identify_ns(dev, NVME_NSID_ALL, &ns); if (err) { - if (err < 0) - fprintf(stderr, "identify-namespace: %s", - nvme_strerror(errno)); - else { + if (err < 0) { + nvme_show_error("identify-namespace: %s", nvme_strerror(errno)); + } else { fprintf(stderr, "identify failed\n"); nvme_show_status(err); } @@ -3090,11 +3156,9 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * } if (cfg.flbas == 0xff) { - fprintf(stderr, - "FLBAS corresponding to block size %"PRIu64" not found\n", + fprintf(stderr, "FLBAS corresponding to block size %"PRIu64" not found\n", (uint64_t)cfg.bs); - fprintf(stderr, - "Please correct block size, or specify FLBAS directly\n"); + fprintf(stderr, "Please correct block size, or specify FLBAS directly\n"); err = -EINVAL; goto close_dev; @@ -3108,7 +3172,13 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * if (err) goto close_dev; - struct nvme_id_ns ns2 = { + if (cfg.csi != NVME_CSI_ZNS && (cfg.azr || cfg.rar || cfg.ror || cfg.rnumzrwa)) { + nvme_show_error("Invalid ZNS argument is given (CSI:%#x)", cfg.csi); + err = -EINVAL; + goto close_dev; + } + + struct nvme_ns_mgmt_host_sw_specified data = { .nsze = cpu_to_le64(cfg.nsze), .ncap = cpu_to_le64(cfg.ncap), .flbas = cfg.flbas, @@ -3117,15 +3187,30 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * .anagrpid = cpu_to_le32(cfg.anagrpid), .nvmsetid = cpu_to_le16(cfg.nvmsetid), .lbstm = cpu_to_le64(cfg.lbstm), + .zns.znsco = cfg.azr, + .zns.rar = cpu_to_le32(cfg.rar), + .zns.ror = cpu_to_le32(cfg.ror), + .zns.rnumzrwa = cpu_to_le32(cfg.rnumzrwa), + .nphndls = cpu_to_le16(cfg.nphndls), }; - err = nvme_cli_ns_mgmt_create(dev, &ns2, &nsid, cfg.timeout, cfg.csi); + num_phandle = argconfig_parse_comma_sep_array_short(cfg.phndls, phndl, ARRAY_SIZE(phndl)); + if (cfg.nphndls != num_phandle) { + nvme_show_error("Invalid Placement handle list"); + err = -EINVAL; + goto close_dev; + } + + 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); if (!err) printf("%s: Success, created nsid:%d\n", cmd->name, nsid); else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "create namespace: %s\n", nvme_strerror(errno)); + nvme_show_error("create namespace: %s", nvme_strerror(errno)); close_dev: dev_close(dev); @@ -3204,23 +3289,20 @@ static int list_subsys(int argc, char **argv, struct command *cmd, devname = basename(argv[optind++]); err = flags = validate_output_format(cfg.output_format); - if (flags < 0) - goto ret; if (flags != JSON && flags != NORMAL) { - err = -EINVAL; + nvme_show_error("Invalid output format"); goto ret; } + if (cfg.verbose) flags |= VERBOSE; r = nvme_create_root(stderr, map_log_level(cfg.verbose, false)); if (!r) { if (devname) - fprintf(stderr, - "Failed to scan nvme subsystem for %s\n", - devname); + nvme_show_error("Failed to scan nvme subsystem for %s", devname); else - fprintf(stderr, "Failed to scan nvme subsystem\n"); + nvme_show_error("Failed to scan nvme subsystem"); err = -errno; goto ret; } @@ -3229,7 +3311,7 @@ static int list_subsys(int argc, char **argv, struct command *cmd, int subsys_num; if (sscanf(devname, "nvme%dn%d", &subsys_num, &nsid) != 2) { - fprintf(stderr, "Invalid device name %s\n", devname); + nvme_show_error("Invalid device name %s", devname); err = -EINVAL; goto ret; } @@ -3238,8 +3320,7 @@ static int list_subsys(int argc, char **argv, struct command *cmd, err = nvme_scan_topology(r, filter, (void *)devname); if (err) { - fprintf(stderr, "Failed to scan topology: %s\n", - nvme_strerror(errno)); + nvme_show_error("Failed to scan topology: %s", nvme_strerror(errno)); goto ret; } @@ -3278,26 +3359,23 @@ static int list(int argc, char **argv, struct command *cmd, struct plugin *plugi if (err < 0) return err; - err = flags = validate_output_format(cfg.output_format); - if (flags < 0) - return err; + flags = validate_output_format(cfg.output_format); if (flags != JSON && flags != NORMAL) { - fprintf(stderr, "Invalid output format\n"); + nvme_show_error("Invalid output format"); return -EINVAL; } + if (cfg.verbose) flags |= VERBOSE; r = nvme_create_root(stderr, map_log_level(cfg.verbose, false)); if (!r) { - fprintf(stderr, "Failed to create topology root: %s\n", - nvme_strerror(errno)); + nvme_show_error("Failed to create topology root: %s", nvme_strerror(errno)); return -errno; } err = nvme_scan_topology(r, NULL, NULL); if (err < 0) { - fprintf(stderr, "Failed to scan topology: %s\n", - nvme_strerror(errno)); + nvme_show_error("Failed to scan topology: %s", nvme_strerror(errno)); nvme_free_tree(r); return err; } @@ -3311,10 +3389,10 @@ static int list(int argc, char **argv, struct command *cmd, struct plugin *plugi int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, void (*vs)(__u8 *vs, struct json_object *root)) { - const char *desc = "Send an Identify Controller command to "\ - "the given device and report information about the specified "\ - "controller in human-readable or "\ - "binary format. May also return vendor-specific "\ + const char *desc = "Send an Identify Controller command to\n" + "the given device and report information about the specified\n" + "controller in human-readable or\n" + "binary format. May also return vendor-specific\n" "controller attributes in hex-dump if requested."; const char *vendor_specific = "dump binary vendor field"; enum nvme_print_flags flags; @@ -3349,12 +3427,17 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.raw_binary) flags = BINARY; + if (cfg.vendor_specific) flags |= VS; + if (cfg.human_readable) flags |= VERBOSE; @@ -3364,7 +3447,7 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "identify controller: %s\n", nvme_strerror(errno)); + nvme_show_error("identify controller: %s", nvme_strerror(errno)); close_dev: dev_close(dev); ret: @@ -3379,8 +3462,8 @@ static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *pl static int nvm_id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send an Identify Controller NVM Command Set "\ - "command to the given device and report information about "\ + const char *desc = "Send an Identify Controller NVM Command Set\n" + "command to the given device and report information about\n" "the specified controller in various formats."; enum nvme_print_flags flags; struct nvme_id_ctrl_nvm ctrl_nvm; @@ -3405,8 +3488,10 @@ static int nvm_id_ctrl(int argc, char **argv, struct command *cmd, goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } err = nvme_nvm_identify_ctrl(dev_fd(dev), &ctrl_nvm); if (!err) @@ -3414,7 +3499,7 @@ static int nvm_id_ctrl(int argc, char **argv, struct command *cmd, else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "nvm identify controller: %s\n", nvme_strerror(errno)); + nvme_show_error("nvm identify controller: %s", nvme_strerror(errno)); close_dev: dev_close(dev); ret: @@ -3424,8 +3509,8 @@ ret: static int nvm_id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send an Identify Namespace NVM Command Set "\ - "command to the given device and report information about "\ + const char *desc = "Send an Identify Namespace NVM Command Set\n" + "command to the given device and report information about\n" "the specified namespace in various formats."; enum nvme_print_flags flags; struct nvme_nvm_id_ns id_ns; @@ -3460,8 +3545,10 @@ static int nvm_id_ns(int argc, char **argv, struct command *cmd, goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } if (cfg.verbose) flags |= VERBOSE; @@ -3469,7 +3556,7 @@ static int nvm_id_ns(int argc, char **argv, struct command *cmd, if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + nvme_show_perror("get-namespace-id"); goto close_dev; } } @@ -3488,7 +3575,8 @@ static int nvm_id_ns(int argc, char **argv, struct command *cmd, else if (err > 0) nvme_show_status(err); else - perror("nvm identify namespace"); + nvme_show_perror("nvm identify namespace"); + close_dev: dev_close(dev); ret: @@ -3497,10 +3585,9 @@ ret: static int nvm_id_ns_lba_format(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send an NVM Command Set specific Identify Namespace " - "command to the given device, returns capability field properties of " - "the specified LBA Format index in the specified namespace in various " - "formats."; + const char *desc = "Send an NVM Command Set specific Identify Namespace\n" + "command to the given device, returns capability field properties of\n" + "the specified LBA Format index in the specified namespace in various formats."; enum nvme_print_flags flags; struct nvme_id_ns ns; struct nvme_nvm_id_ns nvm_ns; @@ -3534,8 +3621,10 @@ static int nvm_id_ns_lba_format(int argc, char **argv, struct command *cmd, stru goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } if (cfg.verbose) flags |= VERBOSE; @@ -3545,16 +3634,16 @@ static int nvm_id_ns_lba_format(int argc, char **argv, struct command *cmd, stru ns.nlbaf = NVME_FEAT_LBA_RANGE_MAX - 1; ns.nulbaf = 0; } - err = nvme_identify_iocs_ns_csi_user_data_format(dev_fd(dev), - cfg.lba_format_index, - cfg.uuid_index, NVME_CSI_NVM, &nvm_ns); + + err = nvme_identify_iocs_ns_csi_user_data_format(dev_fd(dev), cfg.lba_format_index, + cfg.uuid_index, NVME_CSI_NVM, &nvm_ns); if (!err) - nvme_show_nvm_id_ns(&nvm_ns, 0, &ns, cfg.lba_format_index, true, - flags); + nvme_show_nvm_id_ns(&nvm_ns, 0, &ns, cfg.lba_format_index, true, flags); else if (err > 0) nvme_show_status(err); else - perror("NVM identify namespace for specific LBA format"); + nvme_show_perror("NVM identify namespace for specific LBA format"); + close_dev: dev_close(dev); ret: @@ -3563,9 +3652,9 @@ ret: static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send Namespace Identification Descriptors command to the "\ - "given device, returns the namespace identification descriptors "\ - "of the specific namespace in either human-readable or binary format."; + const char *desc = "Send Namespace Identification Descriptors command to the\n" + "given device, returns the namespace identification descriptors\n" + "of the specific namespace in either human-readable or binary format."; const char *raw = "show descriptors in binary format"; enum nvme_print_flags flags; struct nvme_dev *dev; @@ -3596,15 +3685,18 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.raw_binary) flags = BINARY; if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } } @@ -3620,7 +3712,7 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "identify namespace: %s\n", nvme_strerror(errno)); + nvme_show_error("identify namespace: %s", nvme_strerror(errno)); free(nsdescs); close_dev: dev_close(dev); @@ -3630,9 +3722,9 @@ ret: static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send an Identify Namespace command to the "\ - "given device, returns properties of the specified namespace "\ - "in either human-readable or binary format. Can also return "\ + const char *desc = "Send an Identify Namespace command to the\n" + "given device, returns properties of the specified namespace\n" + "in either human-readable or binary format. Can also return\n" "binary vendor-specific namespace attributes."; const char *force = "Return this namespace, even if not attached (1.2 devices only)"; const char *vendor_specific = "dump binary vendor fields"; @@ -3675,26 +3767,30 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.raw_binary) flags = BINARY; + if (cfg.vendor_specific) flags |= VS; + if (cfg.human_readable) flags |= VERBOSE; if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } } if (cfg.force) - err = nvme_cli_identify_allocated_ns(dev, - cfg.namespace_id, &ns); + err = nvme_cli_identify_allocated_ns(dev, cfg.namespace_id, &ns); else err = nvme_cli_identify_ns(dev, cfg.namespace_id, &ns); @@ -3703,20 +3799,19 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "identify namespace: %s\n", nvme_strerror(errno)); + nvme_show_error("identify namespace: %s", nvme_strerror(errno)); close_dev: dev_close(dev); ret: return err; } -static int cmd_set_independent_id_ns(int argc, char **argv, - struct command *cmd, struct plugin *plugin) +static int cmd_set_independent_id_ns(int argc, char **argv, struct command *cmd, + struct plugin *plugin) { - const char *desc = "Send an I/O Command Set Independent Identify "\ - "Namespace command to the given device, returns properties of the "\ + const char *desc = "Send an I/O Command Set Independent Identify\n" + "Namespace command to the given device, returns properties of the\n" "specified namespace in human-readable or binary or json format."; - enum nvme_print_flags flags; struct nvme_id_independent_id_ns ns; struct nvme_dev *dev; @@ -3749,30 +3844,33 @@ static int cmd_set_independent_id_ns(int argc, char **argv, goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.raw_binary) flags = BINARY; + if (cfg.human_readable) flags |= VERBOSE; if (!cfg.namespace_id) { - err = cfg.namespace_id = nvme_get_nsid(dev_fd(dev), - &cfg.namespace_id); + err = cfg.namespace_id = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - perror("get-namespace-id"); + nvme_show_perror("get-namespace-id"); goto close_dev; } } - err = nvme_identify_independent_identify_ns(dev_fd(dev), - cfg.namespace_id, &ns); + err = nvme_identify_independent_identify_ns(dev_fd(dev), cfg.namespace_id, &ns); if (!err) nvme_show_cmd_set_independent_id_ns(&ns, cfg.namespace_id, flags); else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "I/O command set independent identify namespace: %s\n", nvme_strerror(errno)); + nvme_show_error("I/O command set independent identify namespace: %s", + nvme_strerror(errno)); close_dev: dev_close(dev); ret: @@ -3781,10 +3879,9 @@ ret: static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send an Identify Namespace Granularity List command to the "\ - "given device, returns namespace granularity list "\ + const char *desc = "Send an Identify Namespace Granularity List command to the\n" + "given device, returns namespace granularity list\n" "in either human-readable or binary format."; - struct nvme_id_ns_granularity_list *granularity_list; enum nvme_print_flags flags; struct nvme_dev *dev; @@ -3808,11 +3905,13 @@ static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } if (posix_memalign((void *)&granularity_list, getpagesize(), NVME_IDENTIFY_DATA_SIZE)) { - fprintf(stderr, "can not allocate granularity list payload\n"); + nvme_show_error("can not allocate granularity list payload"); err = -ENOMEM; goto close_dev; } @@ -3823,7 +3922,7 @@ static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "identify namespace granularity: %s\n", nvme_strerror(errno)); + nvme_show_error("identify namespace granularity: %s", nvme_strerror(errno)); free(granularity_list); close_dev: dev_close(dev); @@ -3833,12 +3932,11 @@ ret: static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send an Identify NVM Set List command to the "\ - "given device, returns entries for NVM Set identifiers greater "\ - "than or equal to the value specified CDW11.NVMSETID "\ + const char *desc = "Send an Identify NVM Set List command to the\n" + "given device, returns entries for NVM Set identifiers greater\n" + "than or equal to the value specified CDW11.NVMSETID\n" "in either binary format or json format"; const char *nvmset_id = "NVM Set Identify value"; - struct nvme_id_nvmset_list nvmset; enum nvme_print_flags flags; struct nvme_dev *dev; @@ -3865,8 +3963,10 @@ static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin * goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } err = nvme_identify_nvmset_list(dev_fd(dev), cfg.nvmset_id, &nvmset); if (!err) @@ -3874,7 +3974,7 @@ static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin * else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "identify nvm set list: %s\n", nvme_strerror(errno)); + nvme_show_error("identify nvm set list: %s", nvme_strerror(errno)); close_dev: dev_close(dev); @@ -3884,12 +3984,11 @@ ret: static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send an Identify UUID List command to the "\ - "given device, returns list of supported Vendor Specific UUIDs "\ + const char *desc = "Send an Identify UUID List command to the\n" + "given device, returns list of supported Vendor Specific UUIDs\n" "in either human-readable or binary format."; const char *raw = "show uuid in binary format"; const char *human_readable = "show uuid in readable format"; - struct nvme_id_uuid_list uuid_list; enum nvme_print_flags flags; struct nvme_dev *dev; @@ -3919,10 +4018,14 @@ static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *pl goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.raw_binary) flags = BINARY; + if (cfg.human_readable) flags |= VERBOSE; @@ -3932,17 +4035,17 @@ static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *pl else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "identify UUID list: %s\n", nvme_strerror(errno)); + nvme_show_error("identify UUID list: %s", nvme_strerror(errno)); close_dev: dev_close(dev); ret: - return err;; + return err; } static int id_iocs(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send an Identify Command Set Data command to the "\ - "given device, returns properties of the specified controller "\ + const char *desc = "Send an Identify Command Set Data command to\n" + "the given device, returns properties of the specified controller\n" "in either human-readable or binary format."; const char *controller_id = "identifier of desired controller"; struct nvme_id_iocs iocs; @@ -3969,20 +4072,22 @@ static int id_iocs(int argc, char **argv, struct command *cmd, struct plugin *pl err = nvme_identify_iocs(dev_fd(dev), cfg.cntid, &iocs); if (!err) { printf("NVMe Identify I/O Command Set:\n"); - nvme_show_id_iocs(&iocs); - } else if (err > 0) + nvme_show_id_iocs(&iocs, 0); + } else if (err > 0) { nvme_show_status(err); - else - fprintf(stderr, "NVMe Identify I/O Command Set: %s\n", nvme_strerror(errno)); + } else { + nvme_show_error("NVMe Identify I/O Command Set: %s", nvme_strerror(errno)); + } dev_close(dev); ret: return err; } -static int id_domain(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send an Identify Domain List command to the "\ - "given device, returns properties of the specified domain "\ +static int id_domain(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Send an Identify Domain List command to the\n" + "given device, returns properties of the specified domain\n" "in either normal|json|binary format."; const char *domain_id = "identifier of desired domain"; struct nvme_id_domain_list id_domain; @@ -4011,18 +4116,21 @@ static int id_domain(int argc, char **argv, struct command *cmd, struct plugin * goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } err = nvme_identify_domain_list(dev_fd(dev), cfg.dom_id, &id_domain); if (!err) { printf("NVMe Identify command for Domain List is successful:\n"); printf("NVMe Identify Domain List:\n"); nvme_show_id_domain_list(&id_domain, flags); - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); - else - fprintf(stderr, "NVMe Identify Domain List: %s\n", nvme_strerror(errno)); + } else { + nvme_show_error("NVMe Identify Domain List: %s", nvme_strerror(errno)); + } close_dev: dev_close(dev); @@ -4047,7 +4155,7 @@ static int get_ns_id(int argc, char **argv, struct command *cmd, struct plugin * err = nvme_get_nsid(dev_fd(dev), &nsid); if (err < 0) { - fprintf(stderr, "get namespace ID: %s\n", nvme_strerror(errno)); + nvme_show_error("get namespace ID: %s", nvme_strerror(errno)); err = errno; goto close_fd; } @@ -4062,19 +4170,19 @@ ret: static int virtual_mgmt(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "The Virtualization Management command is supported by primary controllers "\ - "that support the Virtualization Enhancements capability. This command is used for:\n"\ - " 1. Modifying Flexible Resource allocation for the primary controller\n"\ - " 2. Assigning Flexible Resources for secondary controllers\n"\ + const char *desc = "The Virtualization Management command is supported by primary controllers\n" + "that support the Virtualization Enhancements capability. This command is used for:\n" + " 1. Modifying Flexible Resource allocation for the primary controller\n" + " 2. Assigning Flexible Resources for secondary controllers\n" " 3. Setting the Online and Offline state for secondary controllers"; const char *cntlid = "Controller Identifier(CNTLID)"; - const char *rt = "Resource Type(RT): [0,1]\n"\ - "0h: VQ Resources\n"\ + const char *rt = "Resource Type(RT): [0,1]\n" + "0h: VQ Resources\n" "1h: VI Resources"; - const char *act = "Action(ACT): [1,7,8,9]\n"\ - "1h: Primary Flexible\n"\ - "7h: Secondary Offline\n"\ - "8h: Secondary Assign\n"\ + const char *act = "Action(ACT): [1,7,8,9]\n" + "1h: Primary Flexible\n" + "7h: Secondary Offline\n" + "8h: Secondary Assign\n" "9h: Secondary Online"; const char *nr = "Number of Controller Resources(NR)"; struct nvme_dev *dev; @@ -4118,13 +4226,12 @@ static int virtual_mgmt(int argc, char **argv, struct command *cmd, struct plugi .result = &result, }; err = nvme_virtual_mgmt(&args); - if (!err) { - printf("success, Number of Controller Resources Modified "\ - "(NRM):%#x\n", result); - } else if (err > 0) { + if (!err) + printf("success, Number of Controller Resources Modified (NRM):%#x\n", result); + else if (err > 0) nvme_show_status(err); - } else - fprintf(stderr, "virt-mgmt: %s\n", nvme_strerror(errno)); + else + nvme_show_error("virt-mgmt: %s", nvme_strerror(errno)); dev_close(dev); ret: @@ -4134,8 +4241,8 @@ ret: static int primary_ctrl_caps(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *cntlid = "Controller ID"; - const char *desc = "Send an Identify Primary Controller Capabilities "\ - "command to the given device and report the information in a "\ + const char *desc = "Send an Identify Primary Controller Capabilities\n" + "command to the given device and report the information in a\n" "decoded format (default), json or binary."; struct nvme_primary_ctrl_cap caps; enum nvme_print_flags flags; @@ -4166,8 +4273,11 @@ static int primary_ctrl_caps(int argc, char **argv, struct command *cmd, struct goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.human_readable) flags |= VERBOSE; @@ -4177,7 +4287,8 @@ static int primary_ctrl_caps(int argc, char **argv, struct command *cmd, struct else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "identify primary controller capabilities: %s\n", nvme_strerror(errno)); + nvme_show_error("identify primary controller capabilities: %s", + nvme_strerror(errno)); close_dev: dev_close(dev); ret: @@ -4186,8 +4297,8 @@ ret: static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Show secondary controller list associated with the primary controller "\ - "of the given device."; + const char *desc = + "Show secondary controller list associated with the primary controller of the given device."; const char *controller = "lowest controller identifier to display"; const char *num_entries = "number of entries to retrieve"; @@ -4223,29 +4334,30 @@ static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struc goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_err; + } if (!cfg.num_entries) { - fprintf(stderr, "non-zero num-entries is required param\n"); + nvme_show_error("non-zero num-entries is required param"); err = -EINVAL; goto close_err; } if (posix_memalign((void *)&sc_list, getpagesize(), sizeof(*sc_list))) { - fprintf(stderr, "can not allocate controller list payload\n"); + nvme_show_error("can not allocate controller list payload"); err = -ENOMEM; goto close_err; } - err = nvme_cli_identify_secondary_ctrl_list(dev, cfg.namespace_id, - cfg.cntid, sc_list); + err = nvme_cli_identify_secondary_ctrl_list(dev, cfg.namespace_id, cfg.cntid, sc_list); if (!err) nvme_show_list_secondary_ctrl(sc_list, cfg.num_entries, flags); else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "id secondary controller list: %s\n", nvme_strerror(errno)); + nvme_show_error("id secondary controller list: %s", nvme_strerror(errno)); free(sc_list); @@ -4258,6 +4370,7 @@ ret: static void intr_self_test(int signum) { printf("\nInterrupted device self-test operation by %s\n", strsignal(signum)); + errno = EINTR; } @@ -4285,7 +4398,7 @@ static int wait_self_test(struct nvme_dev *dev) err = nvme_cli_identify_ctrl(dev, &ctrl); if (err) { - fprintf(stderr, "identify-ctrl: %s\n", nvme_strerror(errno)); + nvme_show_error("identify-ctrl: %s", nvme_strerror(errno)); return err; } @@ -4310,7 +4423,7 @@ static int wait_self_test(struct nvme_dev *dev) } if (++cnt > wthr) { - fprintf(stderr, "no progress for %d seconds, stop waiting\n", wthr); + nvme_show_error("no progress for %d seconds, stop waiting", wthr); return -EIO; } @@ -4321,7 +4434,7 @@ static int wait_self_test(struct nvme_dev *dev) if (log.completion < p) { printf("\n"); - fprintf(stderr, "progress broken\n"); + nvme_show_error("progress broken"); return -EIO; } else if (log.completion != p) { p = log.completion; @@ -4341,25 +4454,26 @@ static void abort_self_test(struct nvme_dev_self_test_args *args) args->stc = NVME_DST_STC_ABORT; err = nvme_dev_self_test(args); - if (!err) { + if (!err) printf("Aborting device self-test operation\n"); - } else if (err > 0) { + else if (err > 0) nvme_show_status(err); - } else - fprintf(stderr, "Device self-test: %s\n", nvme_strerror(errno)); + else + nvme_show_error("Device self-test: %s", nvme_strerror(errno)); } static int device_self_test(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Implementing the device self-test feature"\ - " which provides the necessary log to determine the state of the device"; - const char *namespace_id = "Indicate the namespace in which the device self-test"\ - " has to be carried out"; - const char * self_test_code = "This field specifies the action taken by the device self-test command :\n"\ - "0h Show current state of device self-test operation\n"\ - "1h Start a short device self-test operation\n"\ - "2h Start a extended device self-test operation\n"\ - "eh Start a vendor specific device self-test operation\n"\ + const char *desc = "Implementing the device self-test feature\n" + "which provides the necessary log to determine the state of the device"; + const char *namespace_id = + "Indicate the namespace in which the device self-test has to be carried out"; + const char *self_test_code = + "This field specifies the action taken by the device self-test command :\n" + "0h Show current state of device self-test operation\n" + "1h Start a short device self-test operation\n" + "2h Start a extended device self-test operation\n" + "eh Start a vendor specific device self-test operation\n" "fh Abort the device self-test operation"; const char *wait = "Wait for the test to finish"; struct nvme_dev *dev; @@ -4390,6 +4504,7 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p if (cfg.stc == NVME_ST_CODE_RESERVED) { struct nvme_self_test_log log; + err = nvme_cli_get_log_device_self_test(dev, &log); if (err) { printf("\n"); @@ -4431,8 +4546,9 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p err = wait_self_test(dev); } else if (err > 0) { nvme_show_status(err); - } else - fprintf(stderr, "Device self-test: %s\n", nvme_strerror(errno)); + } else { + nvme_show_error("Device self-test: %s", nvme_strerror(errno)); + } close_dev: if (err == -EINTR) @@ -4445,12 +4561,10 @@ ret: static int self_test_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Retrieve the self-test log for the given device and given test "\ - "(or optionally a namespace) in either decoded format "\ - "(default) or binary."; - const char *dst_entries = "Indicate how many DST log entries to be retrieved, "\ - "by default all the 20 entries will be retrieved"; - + const char *desc = "Retrieve the self-test log for the given device and given test\n" + "(or optionally a namespace) in either decoded format (default) or binary."; + const char *dst_entries = "Indicate how many DST log entries to be retrieved,\n" + "by default all the 20 entries will be retrieved"; struct nvme_self_test_log log; enum nvme_print_flags flags; struct nvme_dev *dev; @@ -4480,19 +4594,21 @@ static int self_test_log(int argc, char **argv, struct command *cmd, struct plug goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.verbose) flags |= VERBOSE; err = nvme_cli_get_log_device_self_test(dev, &log); if (!err) - nvme_show_self_test_log(&log, cfg.dst_entries, 0, - dev->name, flags); + nvme_show_self_test_log(&log, cfg.dst_entries, 0, dev->name, flags); else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "self test log: %s\n", nvme_strerror(errno)); + nvme_show_error("self test log: %s", nvme_strerror(errno)); close_dev: dev_close(dev); ret: @@ -4656,14 +4772,14 @@ static int get_feature_ids(struct nvme_dev *dev, struct feat_cfg cfg) static int get_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Read operating parameters of the "\ - "specified controller. Operating parameters are grouped "\ - "and identified by Feature Identifiers; each Feature "\ - "Identifier contains one or more attributes that may affect "\ - "behavior of the feature. Each Feature has three possible "\ - "settings: default, saveable, and current. If a Feature is "\ - "saveable, it may be modified by set-feature. Default values "\ - "are vendor-specific and not changeable. Use set-feature to "\ + const char *desc = "Read operating parameters of the\n" + "specified controller. Operating parameters are grouped\n" + "and identified by Feature Identifiers; each Feature\n" + "Identifier contains one or more attributes that may affect\n" + "behavior of the feature. Each Feature has three possible\n" + "settings: default, saveable, and current. If a Feature is\n" + "saveable, it may be modified by set-feature. Default values\n" + "are vendor-specific and not changeable. Use set-feature to\n" "change saveable Features."; const char *raw = "show feature in binary format"; const char *feature_id = "feature identifier"; @@ -4685,14 +4801,14 @@ static int get_feature(int argc, char **argv, struct command *cmd, }; OPT_ARGS(opts) = { - OPT_BYTE("feature-id", 'f', &cfg.feature_id, feature_id), - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), - OPT_BYTE("sel", 's', &cfg.sel, sel), - OPT_UINT("data-len", 'l', &cfg.data_len, buf_len), - OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), - OPT_UINT("cdw11", 'c', &cfg.cdw11, cdw11), - OPT_BYTE("uuid-index", 'U', &cfg.uuid_index, uuid_index_specify), - OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable), + OPT_BYTE("feature-id", 'f', &cfg.feature_id, feature_id), + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), + OPT_BYTE("sel", 's', &cfg.sel, sel), + OPT_UINT("data-len", 'l', &cfg.data_len, buf_len), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_UINT("cdw11", 'c', &cfg.cdw11, cdw11), + OPT_BYTE("uuid-index", 'U', &cfg.uuid_index, uuid_index_specify), + OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable), OPT_END() }; @@ -4704,21 +4820,21 @@ static int get_feature(int argc, char **argv, struct command *cmd, err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { if (errno != ENOTTY) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } cfg.namespace_id = NVME_NSID_ALL; } } - if (cfg.sel > 7) { - fprintf(stderr, "invalid 'select' param:%d\n", cfg.sel); + if (cfg.sel > 8) { + nvme_show_error("invalid 'select' param:%d", cfg.sel); err = -EINVAL; goto close_dev; } if (cfg.uuid_index > 127) { - fprintf(stderr, "invalid uuid index param: %u\n", cfg.uuid_index); + nvme_show_error("invalid uuid index param: %u", cfg.uuid_index); err = -1; goto close_dev; } @@ -4732,7 +4848,8 @@ ret: return err; } -/* Transfers one chunk of firmware to the device, and decodes & reports any +/* + * Transfers one chunk of firmware to the device, and decodes & reports any * errors. Returns -1 on (fatal) error; signifying that the transfer should * be aborted. */ @@ -4759,7 +4876,6 @@ static int fw_download_single(struct nvme_dev *dev, void *fw_buf, }; for (try = 0; try < max_retries; try++) { - if (try > 0) { fprintf(stderr, "retrying offset %x (%u/%u)\n", offset, try, max_retries); @@ -4769,14 +4885,17 @@ static int fw_download_single(struct nvme_dev *dev, void *fw_buf, if (!err) return 0; - /* don't retry if the NVMe-type error indicates Do Not Resend. + /* + * don't retry if the NVMe-type error indicates Do Not Resend. */ retryable = !((err > 0) && (nvme_status_get_type(err) == NVME_STATUS_TYPE_NVME) && (nvme_status_get_value(err) & NVME_SC_DNR)); - /* detect overwrite errors, which are handled differently - * depending on ignore_ovr */ + /* + * detect overwrite errors, which are handled differently + * depending on ignore_ovr + */ ovr = (err > 0) && (nvme_status_get_type(err) == NVME_STATUS_TYPE_NVME) && (NVME_GET(err, SCT) == NVME_SCT_CMD_SPECIFIC) && @@ -4785,7 +4904,8 @@ static int fw_download_single(struct nvme_dev *dev, void *fw_buf, if (ovr && ignore_ovr) return 0; - /* if we're printing progress, we'll need a newline to separate + /* + * if we're printing progress, we'll need a newline to separate * error output from the progress data (which doesn't have a * \n), and flush before we write to stderr. */ @@ -4802,14 +4922,18 @@ static int fw_download_single(struct nvme_dev *dev, void *fw_buf, } else { nvme_show_status(err); if (ovr) { - /* non-ignored ovr error: print a little extra info - * about recovering */ + /* + * non-ignored ovr error: print a little extra info + * about recovering + */ fprintf(stderr, "Use --ignore-ovr to ignore overwrite errors\n"); - /* We'll just be attempting more overwrites if + /* + * We'll just be attempting more overwrites if * we retry. DNR will likely be set, but force - * an exit anyway. */ + * an exit anyway. + */ retryable = false; } } @@ -4823,13 +4947,13 @@ static int fw_download_single(struct nvme_dev *dev, void *fw_buf, static int fw_download(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Copy all or part of a firmware image to "\ - "a controller for future update. Optionally, specify how "\ - "many KiB of the firmware to transfer at once. The offset will "\ - "start at 0 and automatically adjust based on xfer size "\ - "unless fw is split across multiple files. May be submitted "\ - "while outstanding commands exist on the Admin and IO "\ - "Submission Queues. Activate downloaded firmware with "\ + const char *desc = "Copy all or part of a firmware image to\n" + "a controller for future update. Optionally, specify how\n" + "many KiB of the firmware to transfer at once. The offset will\n" + "start at 0 and automatically adjust based on xfer size\n" + "unless fw is split across multiple files. May be submitted\n" + "while outstanding commands exist on the Admin and IO\n" + "Submission Queues. Activate downloaded firmware with\n" "fw-activate, and then reset the device to apply the downloaded firmware."; const char *fw = "firmware file (required)"; const char *xfer = "transfer chunksize limit"; @@ -4876,21 +5000,20 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin fw_fd = open(cfg.fw, O_RDONLY); cfg.offset <<= 2; if (fw_fd < 0) { - fprintf(stderr, "Failed to open firmware file %s: %s\n", - cfg.fw, strerror(errno)); + nvme_show_error("Failed to open firmware file %s: %s", cfg.fw, strerror(errno)); err = -EINVAL; goto close_dev; } err = fstat(fw_fd, &sb); if (err < 0) { - perror("fstat"); + nvme_show_perror("fstat"); goto close_fw_fd; } fw_size = sb.st_size; if ((fw_size & 0x3) || (fw_size == 0)) { - fprintf(stderr, "Invalid size:%d for f/w image\n", fw_size); + nvme_show_error("Invalid size:%d for f/w image", fw_size); err = -EINVAL; goto close_fw_fd; } @@ -4898,15 +5021,14 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin if (cfg.xfer == 0) { err = nvme_cli_identify_ctrl(dev, &ctrl); if (err) { - fprintf(stderr, "identify-ctrl: %s\n", nvme_strerror(errno)); + nvme_show_error("identify-ctrl: %s", nvme_strerror(errno)); goto close_fw_fd; } if (ctrl.fwug == 0 || ctrl.fwug == 0xff) cfg.xfer = 4096; else cfg.xfer = ctrl.fwug * 4096; - } - else if (cfg.xfer % 4096) + } else if (cfg.xfer % 4096) cfg.xfer = 4096; if (cfg.xfer < HUGE_MIN) @@ -4921,7 +5043,7 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin if (read(fw_fd, fw_buf, fw_size) != ((ssize_t)(fw_size))) { err = -errno; - fprintf(stderr, "read :%s :%s\n", cfg.fw, strerror(errno)); + nvme_show_error("read :%s :%s", cfg.fw, strerror(errno)); goto free; } @@ -4976,7 +5098,7 @@ static bool fw_commit_support_mud(struct nvme_dev *dev) err = nvme_cli_identify_ctrl(dev, &ctrl); if (err) - fprintf(stderr, "identify-ctrl: %s\n", nvme_strerror(errno)); + nvme_show_error("identify-ctrl: %s", nvme_strerror(errno)); else if (ctrl.frmw >> 5 & 0x1) return true; @@ -4991,20 +5113,20 @@ static void fw_commit_print_mud(struct nvme_dev *dev, __u32 result) printf("Multiple Update Detected (MUD) Value: %u\n", result); if (result & 0x1) - printf("Detected an overlapping firmware/boot partition image update command "\ + printf("Detected an overlapping firmware/boot partition image update command\n" "sequence due to processing a command from a Management Endpoint"); if (result >> 1 & 0x1) - printf("Detected an overlapping firmware/boot partition image update command "\ + printf("Detected an overlapping firmware/boot partition image update command\n" "sequence due to processing a command from an Admin SQ on a controller"); } static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Verify downloaded firmware image and "\ - "commit to specific firmware slot. Device is not automatically "\ - "reset following firmware activation. A reset may be issued "\ - "with an 'echo 1 > /sys/class/nvme/nvmeX/reset_controller'. "\ + const char *desc = "Verify downloaded firmware image and\n" + "commit to specific firmware slot. Device is not automatically\n" + "reset following firmware activation. A reset may be issued\n" + "with an 'echo 1 > /sys/class/nvme/nvmeX/reset_controller'.\n" "Ensure nvmeX is the device you just activated before reset."; const char *slot = "[0-7]: firmware slot for commit action"; const char *action = "[0-7]: commit action"; @@ -5037,17 +5159,17 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin * goto ret; if (cfg.slot > 7) { - fprintf(stderr, "invalid slot:%d\n", cfg.slot); + nvme_show_error("invalid slot:%d", cfg.slot); err = -EINVAL; goto close_dev; } if (cfg.action > 7 || cfg.action == 4 || cfg.action == 5) { - fprintf(stderr, "invalid action:%d\n", cfg.action); + nvme_show_error("invalid action:%d", cfg.action); err = -EINVAL; goto close_dev; } if (cfg.bpid > 1) { - fprintf(stderr, "invalid boot partition id:%d\n", cfg.bpid); + nvme_show_error("invalid boot partition id:%d", cfg.bpid); err = -EINVAL; goto close_dev; } @@ -5062,9 +5184,9 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin * }; err = nvme_cli_fw_commit(dev, &args); - if (err < 0) - fprintf(stderr, "fw-commit: %s\n", nvme_strerror(errno)); - else if (err != 0) { + if (err < 0) { + nvme_show_error("fw-commit: %s", nvme_strerror(errno)); + } else if (err != 0) { __u32 val = nvme_status_get_value(err); int type = nvme_status_get_type(err); @@ -5119,10 +5241,9 @@ static int subsystem_reset(int argc, char **argv, struct command *cmd, struct pl err = nvme_subsystem_reset(dev_fd(dev)); if (err < 0) { if (errno == ENOTTY) - fprintf(stderr, - "Subsystem-reset: NVM Subsystem Reset not supported.\n"); + nvme_show_error("Subsystem-reset: NVM Subsystem Reset not supported."); else - fprintf(stderr, "Subsystem-reset: %s\n", nvme_strerror(errno)); + nvme_show_error("Subsystem-reset: %s", nvme_strerror(errno)); } dev_close(dev); @@ -5146,7 +5267,7 @@ static int reset(int argc, char **argv, struct command *cmd, struct plugin *plug err = nvme_ctrl_reset(dev_fd(dev)); if (err < 0) - fprintf(stderr, "Reset: %s\n", nvme_strerror(errno)); + nvme_show_error("Reset: %s", nvme_strerror(errno)); dev_close(dev); ret: @@ -5169,36 +5290,14 @@ static int ns_rescan(int argc, char **argv, struct command *cmd, struct plugin * err = nvme_ns_rescan(dev_fd(dev)); if (err < 0) - fprintf(stderr, "Namespace Rescan"); + nvme_show_error("Namespace Rescan"); dev_close(dev); ret: return err; } -static int parse_sanact(char *str, __u8 *val) -{ - int len = strlen(str); - - if (!strncasecmp(str, "exit-failure", len > 1 ? len : 1)) - *val = NVME_SANITIZE_SANACT_EXIT_FAILURE; - - if (!strncasecmp(str, "start-block-erase", len > 7 ? len : 7)) - *val = NVME_SANITIZE_SANACT_START_BLOCK_ERASE; - - if (!strncasecmp(str, "start-overwrite", len > 7 ? len : 7)) - *val = NVME_SANITIZE_SANACT_START_OVERWRITE; - - if (!strncasecmp(str, "start-crypto-erase", len > 7 ? len : 7)) - *val = NVME_SANITIZE_SANACT_START_CRYPTO_ERASE; - - if (*val) - return 0; - - return argconfig_parse_byte("sanact", str, val); -} - -static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int sanitize_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Send a sanitize command."; const char *no_dealloc_desc = "No deallocate after sanitize."; @@ -5209,14 +5308,13 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p const char *ovrpat_desc = "Overwrite pattern."; struct nvme_dev *dev; int err; - __u8 sanact = 0; struct config { bool no_dealloc; bool oipbp; __u8 owpass; bool ause; - char *sanact; + __u8 sanact; __u32 ovrpat; }; @@ -5225,16 +5323,24 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p .oipbp = false, .owpass = 0, .ause = false, - .sanact = NULL, + .sanact = 0, .ovrpat = 0, }; + OPT_VALS(sanact) = { + VAL_BYTE("exit-failure", NVME_SANITIZE_SANACT_EXIT_FAILURE), + VAL_BYTE("start-block-erase", NVME_SANITIZE_SANACT_START_BLOCK_ERASE), + VAL_BYTE("start-overwrite", NVME_SANITIZE_SANACT_START_OVERWRITE), + VAL_BYTE("start-crypto-erase", NVME_SANITIZE_SANACT_START_CRYPTO_ERASE), + VAL_END() + }; + OPT_ARGS(opts) = { OPT_FLAG("no-dealloc", 'd', &cfg.no_dealloc, no_dealloc_desc), OPT_FLAG("oipbp", 'i', &cfg.oipbp, oipbp_desc), OPT_BYTE("owpass", 'n', &cfg.owpass, owpass_desc), OPT_FLAG("ause", 'u', &cfg.ause, ause_desc), - OPT_STR("sanact", 'a', &cfg.sanact, sanact_desc), + OPT_BYTE("sanact", 'a', &cfg.sanact, sanact_desc, sanact), OPT_UINT("ovrpat", 'p', &cfg.ovrpat, ovrpat_desc), OPT_END() }; @@ -5243,41 +5349,35 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p if (err) goto ret; - if (cfg.sanact) { - err = parse_sanact(cfg.sanact, &sanact); - if (err) - goto close_dev; - } - - switch (sanact) { + switch (cfg.sanact) { case NVME_SANITIZE_SANACT_EXIT_FAILURE: case NVME_SANITIZE_SANACT_START_BLOCK_ERASE: case NVME_SANITIZE_SANACT_START_OVERWRITE: case NVME_SANITIZE_SANACT_START_CRYPTO_ERASE: break; default: - fprintf(stderr, "Invalid Sanitize Action\n"); + nvme_show_error("Invalid Sanitize Action"); err = -EINVAL; goto close_dev; } - if (sanact == NVME_SANITIZE_SANACT_EXIT_FAILURE) { + if (cfg.sanact == NVME_SANITIZE_SANACT_EXIT_FAILURE) { if (cfg.ause || cfg.no_dealloc) { - fprintf(stderr, "SANACT is Exit Failure Mode\n"); + nvme_show_error("SANACT is Exit Failure Mode"); err = -EINVAL; goto close_dev; } } - if (sanact == NVME_SANITIZE_SANACT_START_OVERWRITE) { + if (cfg.sanact == NVME_SANITIZE_SANACT_START_OVERWRITE) { if (cfg.owpass > 15) { - fprintf(stderr, "OWPASS out of range [0-15]\n"); + nvme_show_error("OWPASS out of range [0-15]"); err = -EINVAL; goto close_dev; } } else { if (cfg.owpass || cfg.oipbp || cfg.ovrpat) { - fprintf(stderr, "SANACT is not Overwrite\n"); + nvme_show_error("SANACT is not Overwrite"); err = -EINVAL; goto close_dev; } @@ -5285,7 +5385,7 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p struct nvme_sanitize_nvm_args args = { .args_size = sizeof(args), - .sanact = sanact, + .sanact = cfg.sanact, .ause = cfg.ause, .owpass = cfg.owpass, .oipbp = cfg.oipbp, @@ -5295,7 +5395,7 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p }; err = nvme_cli_sanitize_nvm(dev, &args); if (err < 0) - fprintf(stderr, "sanitize: %s\n", nvme_strerror(errno)); + nvme_show_error("sanitize: %s", nvme_strerror(errno)); else if (err > 0) nvme_show_status(err); @@ -5312,7 +5412,7 @@ static int nvme_get_properties(int fd, void **pbar) void *bar = malloc(size); if (!bar) { - fprintf(stderr, "malloc: %s\n", strerror(errno)); + nvme_show_error("malloc: %s", strerror(errno)); return -1; } @@ -5327,13 +5427,11 @@ static int nvme_get_properties(int fd, void **pbar) }; err = nvme_get_property(&args); - if (nvme_status_equals(err, NVME_STATUS_TYPE_NVME, - NVME_SC_INVALID_FIELD)) { + if (nvme_status_equals(err, NVME_STATUS_TYPE_NVME, NVME_SC_INVALID_FIELD)) { err = 0; value = -1; } else if (err) { - fprintf(stderr, "get-property: %s\n", - nvme_strerror(errno)); + nvme_show_error("get-property: %s", nvme_strerror(errno)); break; } if (nvme_is_64bit_reg(offset)) { @@ -5370,20 +5468,19 @@ static void *mmap_registers(nvme_root_t r, struct nvme_dev *dev) } else { n = nvme_scan_namespace(dev->name); if (!n) { - fprintf(stderr, "Unable to find %s\n", dev->name); + nvme_show_error("Unable to find %s", dev->name); return NULL; } snprintf(path, sizeof(path), "%s/device/device/resource0", - nvme_ns_get_sysfs_dir(n)); + nvme_ns_get_sysfs_dir(n)); nvme_free_ns(n); } fd = open(path, O_RDONLY); if (fd < 0) { if (map_log_level(0, false) >= LOG_DEBUG) - fprintf(stderr, - "%s did not find a pci resource, open failed %s\n", - dev->name, strerror(errno)); + nvme_show_error("%s did not find a pci resource, open failed %s", + dev->name, strerror(errno)); return NULL; } @@ -5402,11 +5499,10 @@ static void *mmap_registers(nvme_root_t r, struct nvme_dev *dev) static int show_registers(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Reads and shows the defined NVMe controller registers "\ - "in binary or human-readable format"; - const char *human_readable = "show info in readable format in case of "\ - "output_format == normal"; - + const char *desc = "Reads and shows the defined NVMe controller registers\n" + "in binary or human-readable format"; + const char *human_readable = + "show info in readable format in case of output_format == normal"; enum nvme_print_flags flags; struct nvme_dev *dev; bool fabrics = false; @@ -5425,8 +5521,8 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu }; OPT_ARGS(opts) = { - OPT_FMT("output-format", 'o', &cfg.output_format, output_format), - OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable), OPT_END() }; @@ -5436,10 +5532,14 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu r = nvme_scan(NULL); err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.human_readable) flags |= VERBOSE; + bar = mmap_registers(r, dev); if (!bar) { err = nvme_get_properties(dev_fd(dev), &bar); @@ -5462,12 +5562,11 @@ ret: static int get_property(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Reads and shows the defined NVMe controller property "\ - "for NVMe over Fabric. Property offset must be one of:\n" - "CAP=0x0, VS=0x8, CC=0x14, CSTS=0x1c, NSSR=0x20"; + const char *desc = "Reads and shows the defined NVMe controller property\n" + "for NVMe over Fabric. Property offset must be one of:\n" + "CAP=0x0, VS=0x8, CC=0x14, CSTS=0x1c, NSSR=0x20"; const char *offset = "offset of the requested property"; const char *human_readable = "show property in readable format"; - struct nvme_dev *dev; __u64 value; int err; @@ -5483,8 +5582,8 @@ static int get_property(int argc, char **argv, struct command *cmd, struct plugi }; OPT_ARGS(opts) = { - OPT_UINT("offset", 'o', &cfg.offset, offset), - OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable), + OPT_UINT("offset", 'o', &cfg.offset, offset), + OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable), OPT_END() }; @@ -5493,7 +5592,7 @@ static int get_property(int argc, char **argv, struct command *cmd, struct plugi goto ret; if (cfg.offset == -1) { - fprintf(stderr, "offset required param\n"); + nvme_show_error("offset required param"); err = -EINVAL; goto close_dev; } @@ -5506,13 +5605,12 @@ static int get_property(int argc, char **argv, struct command *cmd, struct plugi .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, }; err = nvme_get_property(&args); - if (err < 0) { - fprintf(stderr, "get-property: %s\n", nvme_strerror(errno)); - } else if (!err) { + if (err < 0) + nvme_show_error("get-property: %s", nvme_strerror(errno)); + else if (!err) nvme_show_single_property(cfg.offset, value, cfg.human_readable); - } else if (err > 0) { + else if (err > 0) nvme_show_status(err); - } close_dev: dev_close(dev); @@ -5522,8 +5620,8 @@ ret: static int set_property(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Writes and shows the defined NVMe controller property "\ - "for NVMe over Fabric"; + const char *desc = + "Writes and shows the defined NVMe controller property for NVMe over Fabric"; const char *offset = "the offset of the property"; const char *value = "the value of the property to be set"; struct nvme_dev *dev; @@ -5550,12 +5648,12 @@ static int set_property(int argc, char **argv, struct command *cmd, struct plugi goto ret; if (cfg.offset == -1) { - fprintf(stderr, "offset required param\n"); + nvme_show_error("offset required param"); err = -EINVAL; goto close_dev; } if (cfg.value == -1) { - fprintf(stderr, "value required param\n"); + nvme_show_error("value required param"); err = -EINVAL; goto close_dev; } @@ -5569,14 +5667,13 @@ static int set_property(int argc, char **argv, struct command *cmd, struct plugi .result = NULL, }; err = nvme_set_property(&args); - if (err < 0) { - fprintf(stderr, "set-property: %s\n", nvme_strerror(errno)); - } else if (!err) { + if (err < 0) + nvme_show_error("set-property: %s", nvme_strerror(errno)); + else if (!err) printf("set-property: %02x (%s), value: %#08x\n", cfg.offset, - nvme_register_to_string(cfg.offset), cfg.value); - } else if (err > 0) { + nvme_register_to_string(cfg.offset), cfg.value); + else if (err > 0) nvme_show_status(err); - } close_dev: dev_close(dev); @@ -5584,11 +5681,11 @@ ret: return err; } -static int format(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Re-format a specified namespace on the "\ - "given device. Can erase all data in namespace (user "\ - "data erase) or delete data encryption key if specified. "\ + const char *desc = "Re-format a specified namespace on the\n" + "given device. Can erase all data in namespace (user\n" + "data erase) or delete data encryption key if specified.\n" "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"; @@ -5652,29 +5749,27 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu err = open_exclusive(&dev, argc, argv, cfg.force); if (err) { if (errno == EBUSY) { - fprintf(stderr, "Failed to open %s.\n", - basename(argv[optind])); + fprintf(stderr, "Failed to open %s.\n", basename(argv[optind])); fprintf(stderr, "Namespace is currently busy.\n"); if (!cfg.force) - fprintf(stderr, - "Use the force [--force] option to ignore that.\n"); + fprintf(stderr, "Use the force [--force] option to ignore that.\n"); } else { argconfig_print_help(desc, opts); } goto ret; } - if (cfg.lbaf != 0xff && cfg.bs !=0) { - fprintf(stderr, - "Invalid specification of both LBAF and Block Size, please specify only one\n"); + if (cfg.lbaf != 0xff && cfg.bs != 0) { + nvme_show_error( + "Invalid specification of both LBAF and Block Size, please specify only one"); err = -EINVAL; goto close_dev; } if (cfg.bs) { if ((cfg.bs & (~cfg.bs + 1)) != cfg.bs) { - fprintf(stderr, - "Invalid value for block size (%"PRIu64"), must be a power of two\n", - (uint64_t) cfg.bs); + nvme_show_error( + "Invalid value for block size (%"PRIu64"), must be a power of two", + (uint64_t) cfg.bs); err = -EINVAL; goto close_dev; } @@ -5682,7 +5777,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu err = nvme_cli_identify_ctrl(dev, &ctrl); if (err) { - fprintf(stderr, "identify-ctrl: %s\n", nvme_strerror(errno)); + nvme_show_error("identify-ctrl: %s", nvme_strerror(errno)); goto close_dev; } @@ -5696,16 +5791,15 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu } else if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } } if (cfg.namespace_id == 0) { - fprintf(stderr, - "Invalid namespace ID, " - "specify a namespace to format or use '-n 0xffffffff' " - "to format all namespaces on this controller.\n"); + nvme_show_error( + "Invalid namespace ID, specify a namespace to format or use\n" + "'-n 0xffffffff' to format all namespaces on this controller."); err = -EINVAL; goto close_dev; } @@ -5714,7 +5808,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu err = nvme_cli_identify_ns(dev, cfg.namespace_id, &ns); if (err) { if (err < 0) { - fprintf(stderr, "identify-namespace: %s\n", nvme_strerror(errno)); + nvme_show_error("identify-namespace: %s", nvme_strerror(errno)); } else { fprintf(stderr, "identify failed\n"); nvme_show_status(err); @@ -5724,17 +5818,16 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &prev_lbaf); if (cfg.bs) { - for (i = 0; i < ns.nlbaf; ++i) { - if ((1ULL << ns.lbaf[i].ds) == cfg.bs && - ns.lbaf[i].ms == 0) { + for (i = 0; i <= ns.nlbaf; ++i) { + if ((1ULL << ns.lbaf[i].ds) == cfg.bs && ns.lbaf[i].ms == 0) { cfg.lbaf = i; break; } } if (cfg.lbaf == 0xff) { fprintf(stderr, - "LBAF corresponding to given block size %"PRIu64" not found\n", - (uint64_t)cfg.bs); + "LBAF corresponding to given block size %"PRIu64" not found\n", + (uint64_t)cfg.bs); fprintf(stderr, "Please correct block size, or specify LBAF directly\n"); err = -EINVAL; @@ -5750,27 +5843,27 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu /* ses & pi checks set to 7 for forward-compatibility */ if (cfg.ses > 7) { - fprintf(stderr, "invalid secure erase settings:%d\n", cfg.ses); + nvme_show_error("invalid secure erase settings:%d", cfg.ses); err = -EINVAL; goto close_dev; } if (cfg.lbaf > 63) { - fprintf(stderr, "invalid lbaf:%d\n", cfg.lbaf); + nvme_show_error("invalid lbaf:%d", cfg.lbaf); err = -EINVAL; goto close_dev; } if (cfg.pi > 7) { - fprintf(stderr, "invalid pi:%d\n", cfg.pi); + nvme_show_error("invalid pi:%d", cfg.pi); err = -EINVAL; goto close_dev; } if (cfg.pil > 1) { - fprintf(stderr, "invalid pil:%d\n", cfg.pil); + nvme_show_error("invalid pil:%d", cfg.pil); err = -EINVAL; goto close_dev; } if (cfg.ms > 1) { - fprintf(stderr, "invalid ms:%d\n", cfg.ms); + nvme_show_error("invalid ms:%d", cfg.ms); err = -EINVAL; goto close_dev; } @@ -5785,7 +5878,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu "You have 10 seconds to press Ctrl-C to cancel this operation.\n\n" "Use the force [--force] option to suppress this warning.\n"); sleep(10); - fprintf(stderr, "Sending format operation ... \n"); + fprintf(stderr, "Sending format operation ...\n"); } struct nvme_format_nvm_args args = { @@ -5802,7 +5895,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu }; err = nvme_cli_format_nvm(dev, &args); if (err < 0) { - fprintf(stderr, "format: %s\n", nvme_strerror(errno)); + nvme_show_error("format: %s", nvme_strerror(errno)); } else if (err != 0) { nvme_show_status(err); } else { @@ -5810,11 +5903,11 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu if (dev->type == NVME_DEV_DIRECT && cfg.lbaf != prev_lbaf) { if (is_chardev(dev)) { if (ioctl(dev_fd(dev), NVME_IOCTL_RESCAN) < 0) { - fprintf(stderr, "failed to rescan namespaces\n"); + nvme_show_error("failed to rescan namespaces"); err = -errno; goto close_dev; } - } else { + } else if (cfg.namespace_id != NVME_NSID_ALL) { block_size = 1 << ns.lbaf[cfg.lbaf].ds; /* @@ -5825,14 +5918,14 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu * update by itself without re-opening fd. */ if (ioctl(dev_fd(dev), BLKBSZSET, &block_size) < 0) { - fprintf(stderr, "failed to set block size to %d\n", - block_size); + nvme_show_error("failed to set block size to %d", + block_size); err = -errno; goto close_dev; } if (ioctl(dev_fd(dev), BLKRRPART) < 0) { - fprintf(stderr, "failed to re-read partition table\n"); + nvme_show_error("failed to re-read partition table"); err = -errno; goto close_dev; } @@ -5853,14 +5946,14 @@ ret: static int set_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Modify the saveable or changeable "\ - "current operating parameters of the controller. Operating "\ - "parameters are grouped and identified by Feature "\ - "Identifiers. Feature settings can be applied to the entire "\ - "controller and all associated namespaces, or to only a few "\ - "namespace(s) associated with the controller. Default values "\ - "for each Feature are vendor-specific and may not be modified."\ - "Use get-feature to determine which Features are supported by "\ + const char *desc = "Modify the saveable or changeable\n" + "current operating parameters of the controller.\n" + "Operating parameters are grouped and identified by Feature\n" + "Identifiers. Feature settings can be applied to the entire\n" + "controller and all associated namespaces, or to only a few\n" + "namespace(s) associated with the controller. Default values\n" + "for each Feature are vendor-specific and may not be modified.\n" + "Use get-feature to determine which Features are supported by\n" "the controller and are saveable/changeable."; const char *feature_id = "feature identifier (required)"; const char *data = "optional file for feature data (default stdin)"; @@ -5914,7 +6007,7 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { if (errno != ENOTTY) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } cfg.namespace_id = NVME_NSID_ALL; @@ -5922,13 +6015,13 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin } if (!cfg.feature_id) { - fprintf(stderr, "feature-id required param\n"); + nvme_show_error("feature-id required param"); err = -EINVAL; goto close_dev; } if (cfg.uuid_index > 127) { - fprintf(stderr, "invalid uuid index param: %u\n", cfg.uuid_index); + nvme_show_error("invalid uuid index param: %u", cfg.uuid_index); err = -1; goto close_dev; } @@ -5940,7 +6033,7 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin if (cfg.data_len) { if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { - fprintf(stderr, "can not allocate feature payload\n"); + nvme_show_error("can not allocate feature payload"); err = -ENOMEM; goto close_dev; } @@ -5954,14 +6047,14 @@ 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 (NVME_FEAT_FID_TIMESTAMP == cfg.feature_id && cfg.value) { + if (cfg.feature_id == NVME_FEAT_FID_TIMESTAMP && cfg.value) { memcpy(buf, &cfg.value, NVME_FEAT_TIMESTAMP_DATA_SIZE); } else { if (strlen(cfg.file)) { ffd = open(cfg.file, O_RDONLY); if (ffd <= 0) { - fprintf(stderr, "Failed to open file %s: %s\n", - cfg.file, strerror(errno)); + nvme_show_error("Failed to open file %s: %s", + cfg.file, strerror(errno)); err = -EINVAL; goto free; } @@ -5970,8 +6063,8 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin err = read(ffd, (void *)buf, cfg.data_len); if (err < 0) { err = -errno; - fprintf(stderr, "failed to read data buffer from input" - " file: %s\n", strerror(errno)); + nvme_show_error("failed to read data buffer from input file: %s", + strerror(errno)); goto close_ffd; } } @@ -5994,25 +6087,24 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin }; err = nvme_set_features(&args); if (err < 0) { - fprintf(stderr, "set-feature: %s\n", nvme_strerror(errno)); + nvme_show_error("set-feature: %s", nvme_strerror(errno)); } else if (!err) { printf("set-feature:%#0*x (%s), value:%#0*"PRIx64", cdw12:%#0*x, save:%#x\n", cfg.feature_id ? 4 : 2, cfg.feature_id, nvme_feature_to_string(cfg.feature_id), cfg.value ? 10 : 8, (uint64_t)cfg.value, cfg.cdw12 ? 10 : 8, cfg.cdw12, cfg.save); - if (cfg.feature_id == NVME_FEAT_FID_LBA_STS_INTERVAL) { + if (cfg.feature_id == NVME_FEAT_FID_LBA_STS_INTERVAL) nvme_show_lba_status_info(result); - } if (buf) { if (cfg.feature_id == NVME_FEAT_FID_LBA_RANGE) - nvme_show_lba_range((struct nvme_lba_range_type *)buf, - result); + nvme_show_lba_range((struct nvme_lba_range_type *)buf, result, 0); else d(buf, cfg.data_len, 16, 1); } - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); + } close_ffd: if (ffd != STDIN_FILENO) @@ -6028,11 +6120,10 @@ ret: static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct stat sb; - const char *desc = "Transfer security protocol data to "\ - "a controller. Security Receives for the same protocol should be "\ - "performed after Security Sends. The security protocol field "\ - "associates Security Sends (security-send) and Security Receives "\ - "(security-recv)."; + const char *desc = "Transfer security protocol data to\n" + "a controller. Security Receives for the same protocol should be\n" + "performed after Security Sends. The security protocol field\n" + "associates Security Sends (security-send) and Security Receives (security-recv)."; const char *file = "transfer payload"; const char *tl = "transfer length (cf. SPC-4)"; int err, sec_fd = STDIN_FILENO; @@ -6073,12 +6164,13 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p goto ret; if (cfg.tl == 0) { - fprintf(stderr, "--tl unspecified or zero\n"); + nvme_show_error("--tl unspecified or zero"); err = -EINVAL; goto close_dev; } if ((cfg.tl & 3) != 0) - fprintf(stderr, "WARNING: --tl not dword aligned; unaligned bytes may be truncated\n"); + nvme_show_error( + "WARNING: --tl not dword aligned; unaligned bytes may be truncated"); if (strlen(cfg.file) == 0) { sec_fd = STDIN_FILENO; @@ -6086,15 +6178,14 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p } else { sec_fd = open(cfg.file, O_RDONLY); if (sec_fd < 0) { - fprintf(stderr, "Failed to open %s: %s\n", - cfg.file, strerror(errno)); + nvme_show_error("Failed to open %s: %s", cfg.file, strerror(errno)); err = -EINVAL; goto close_dev; } err = fstat(sec_fd, &sb); if (err < 0) { - perror("fstat"); + nvme_show_perror("fstat"); goto close_sec_fd; } @@ -6102,7 +6193,7 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p } if (posix_memalign(&sec_buf, getpagesize(), cfg.tl)) { - fprintf(stderr, "No memory for security size:%d\n", cfg.tl); + nvme_show_error("No memory for security size:%d", cfg.tl); err = -ENOMEM; goto close_sec_fd; } @@ -6112,8 +6203,8 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p err = read(sec_fd, sec_buf, sec_size); if (err < 0) { err = -errno; - fprintf(stderr, "Failed to read data from security file" - " %s with %s\n", cfg.file, strerror(errno)); + nvme_show_error("Failed to read data from security file %s with %s", cfg.file, + strerror(errno)); goto free; } @@ -6134,7 +6225,7 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p err = nvme_cli_security_send(dev, &args); if (err < 0) - fprintf(stderr, "security-send: %s\n", nvme_strerror(errno)); + nvme_show_error("security-send: %s", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -6152,8 +6243,7 @@ ret: static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Set directive parameters of the "\ - "specified directive type."; + const char *desc = "Set directive parameters of the specified directive type."; const char *endir = "directive enable"; const char *ttype = "target directive type to be enabled/disabled"; const char *input = "write/send file (default stdin)"; @@ -6191,16 +6281,16 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p }; OPT_ARGS(opts) = { - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), - OPT_UINT("data-len", 'l', &cfg.data_len, buf_len), - OPT_BYTE("dir-type", 'D', &cfg.dtype, dtype), - OPT_BYTE("target-dir", 'T', &cfg.ttype, ttype), - OPT_SHRT("dir-spec", 'S', &cfg.dspec, dspec_w_dtype), - OPT_BYTE("dir-oper", 'O', &cfg.doper, doper), - OPT_SHRT("endir", 'e', &cfg.endir, endir), - OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable_directive), - OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_directive), - OPT_FILE("input-file", 'i', &cfg.file, input), + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), + OPT_UINT("data-len", 'l', &cfg.data_len, buf_len), + OPT_BYTE("dir-type", 'D', &cfg.dtype, dtype), + OPT_BYTE("target-dir", 'T', &cfg.ttype, ttype), + OPT_SHRT("dir-spec", 'S', &cfg.dspec, dspec_w_dtype), + OPT_BYTE("dir-oper", 'O', &cfg.doper, doper), + OPT_SHRT("endir", 'e', &cfg.endir, endir), + OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable_directive), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_directive), + OPT_FILE("input-file", 'i', &cfg.file, input), OPT_END() }; @@ -6213,14 +6303,14 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p switch (cfg.doper) { case NVME_DIRECTIVE_SEND_IDENTIFY_DOPER_ENDIR: if (!cfg.ttype) { - fprintf(stderr, "target-dir required param\n"); + nvme_show_error("target-dir required param\n"); err = -EINVAL; goto close_dev; } dw12 = cfg.ttype << 8 | cfg.endir; break; default: - fprintf(stderr, "invalid directive operations for Identify Directives\n"); + nvme_show_error("invalid directive operations for Identify Directives"); err = -EINVAL; goto close_dev; } @@ -6231,18 +6321,17 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p case NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_RESOURCE: break; default: - fprintf(stderr, "invalid directive operations for Streams Directives\n"); + nvme_show_error("invalid directive operations for Streams Directives"); err = -EINVAL; goto close_dev; } break; default: - fprintf(stderr, "invalid directive type\n"); + nvme_show_error("invalid directive type"); err = -EINVAL; goto close_dev; } - if (cfg.data_len) { if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { err = -ENOMEM; @@ -6255,7 +6344,7 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p if (strlen(cfg.file)) { ffd = open(cfg.file, O_RDONLY); if (ffd <= 0) { - fprintf(stderr, "Failed to open file %s: %s\n", + nvme_show_error("Failed to open file %s: %s", cfg.file, strerror(errno)); err = -EINVAL; goto free; @@ -6264,8 +6353,8 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p err = read(ffd, (void *)buf, cfg.data_len); if (err < 0) { err = -errno; - fprintf(stderr, "failed to read data buffer from input" - " file %s\n", strerror(errno)); + nvme_show_error("failed to read data buffer from input file %s", + strerror(errno)); goto close_ffd; } } @@ -6285,20 +6374,21 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p }; err = nvme_directive_send(&args); if (err < 0) { - fprintf(stderr, "dir-send: %s\n", nvme_strerror(errno)); + nvme_show_error("dir-send: %s", nvme_strerror(errno)); goto close_ffd; } if (!err) { - printf("dir-send: type %#x, operation %#x, spec_val %#x, nsid %#x, result %#x \n", - cfg.dtype, cfg.doper, cfg.dspec, cfg.namespace_id, result); + printf("dir-send: type %#x, operation %#x, spec_val %#x, nsid %#x, result %#x\n", + cfg.dtype, cfg.doper, cfg.dspec, cfg.namespace_id, result); if (buf) { if (!cfg.raw_binary) d(buf, cfg.data_len, 16, 1); else d_raw(buf, cfg.data_len); } - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); + } close_ffd: close(ffd); @@ -6312,8 +6402,8 @@ ret: static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "The Write Uncorrectable command is used to set a "\ - "range of logical blocks to invalid."; + const char *desc = + "The Write Uncorrectable command is used to set a range of logical blocks to invalid."; struct nvme_dev *dev; int err; @@ -6321,18 +6411,24 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin __u32 namespace_id; __u64 start_block; __u16 block_count; + __u8 dtype; + __u16 dspec; }; struct config cfg = { .namespace_id = 0, .start_block = 0, .block_count = 0, + .dtype = 0, + .dspec = 0, }; OPT_ARGS(opts) = { OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_desired), OPT_SUFFIX("start-block", 's', &cfg.start_block, start_block), OPT_SHRT("block-count", 'c', &cfg.block_count, block_count), + OPT_BYTE("dir-type", 'T', &cfg.dtype, dtype), + OPT_SHRT("dir-spec", 'S', &cfg.dspec, dspec_w_dtype), OPT_END() }; @@ -6343,23 +6439,31 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } } + if (cfg.dtype > 0xf) { + nvme_show_error("Invalid directive type, %x", cfg.dtype); + err = -EINVAL; + goto close_dev; + } + struct nvme_io_args args = { .args_size = sizeof(args), .fd = dev_fd(dev), .nsid = cfg.namespace_id, .slba = cfg.start_block, .nlb = cfg.block_count, + .control = cfg.dtype << 4, + .dspec = cfg.dspec, .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = NULL, }; err = nvme_write_uncorrectable(&args); if (err < 0) - fprintf(stderr, "write uncorrectable: %s\n", nvme_strerror(errno)); + nvme_show_error("write uncorrectable: %s", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -6376,7 +6480,7 @@ static int invalid_tags(__u64 storage_tag, __u64 ref_tag, __u8 sts, __u8 pif) int result = 0; if (sts < 64 && storage_tag >= (1LL << sts)) { - fprintf(stderr, "Storage tag larger than storage tag size\n"); + nvme_show_error("Storage tag larger than storage tag size"); return 1; } @@ -6394,12 +6498,13 @@ static int invalid_tags(__u64 storage_tag, __u64 ref_tag, __u8 sts, __u8 pif) result = 1; break; default: - fprintf(stderr, "Invalid PIF\n"); + nvme_show_error("Invalid PIF"); result = 1; + break; } if (result) - fprintf(stderr, "Reference tag larger than allowed by PIF\n"); + nvme_show_error("Reference tag larger than allowed by PIF"); return result; } @@ -6413,16 +6518,19 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi struct nvme_nvm_id_ns nvm_ns; int err; - const char *desc = "The Write Zeroes command is used to set a "\ - "range of logical blocks to zero."; - const char *deac = "Set DEAC bit, requesting controller to deallocate specified logical blocks"; - const char *storage_tag_check = "This bit specifies the Storage Tag field shall be checked as "\ - "part of end-to-end data protection processing"; + const char *desc = + "The Write Zeroes command is used to set a range of logical blocks to zero."; + const char *deac = + "Set DEAC bit, requesting controller to deallocate specified logical blocks"; + const char *storage_tag_check = + "This bit specifies the Storage Tag field shall be checked as\n" + "part of end-to-end data protection processing"; struct config { __u32 namespace_id; __u64 start_block; __u16 block_count; + __u8 dtype; bool deac; bool limited_retry; bool force_unit_access; @@ -6432,27 +6540,31 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi __u16 app_tag; __u64 storage_tag; bool storage_tag_check; + __u16 dspec; }; struct config cfg = { .namespace_id = 0, .start_block = 0, .block_count = 0, - .deac = false, + .dtype = 0, + .deac = false, .limited_retry = false, .force_unit_access = false, - .prinfo = 0, - .ref_tag = 0, + .prinfo = 0, + .ref_tag = 0, .app_tag_mask = 0, - .app_tag = 0, + .app_tag = 0, .storage_tag = 0, .storage_tag_check = false, + .dspec = 0, }; OPT_ARGS(opts) = { OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_desired), OPT_SUFFIX("start-block", 's', &cfg.start_block, start_block), OPT_SHRT("block-count", 'c', &cfg.block_count, block_count), + OPT_BYTE("dir-type", 'T', &cfg.dtype, dtype), OPT_FLAG("deac", 'd', &cfg.deac, deac), OPT_FLAG("limited-retry", 'l', &cfg.limited_retry, limited_retry), OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force_unit_access), @@ -6462,6 +6574,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi OPT_SHRT("app-tag", 'a', &cfg.app_tag, app_tag), OPT_SUFFIX("storage-tag", 'S', &cfg.storage_tag, storage_tag), OPT_FLAG("storage-tag-check", 'C', &cfg.storage_tag_check, storage_tag_check), + OPT_SHRT("dir-spec", 'D', &cfg.dspec, dspec_w_dtype), OPT_END() }; @@ -6474,6 +6587,12 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi goto close_dev; } + if (cfg.dtype > 0xf) { + nvme_show_error("Invalid directive type, %x", cfg.dtype); + err = -EINVAL; + goto close_dev; + } + control |= (cfg.prinfo << 10); if (cfg.limited_retry) control |= NVME_IO_LR; @@ -6483,25 +6602,25 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi control |= NVME_IO_DEAC; if (cfg.storage_tag_check) control |= NVME_IO_STC; + control |= (cfg.dtype << 4); if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } } err = nvme_cli_identify_ns(dev, cfg.namespace_id, &ns); if (err < 0) { - fprintf(stderr, "identify namespace: %s\n", nvme_strerror(errno)); + nvme_show_error("identify namespace: %s", nvme_strerror(errno)); goto close_dev; } else if (err) { nvme_show_status(err); goto close_dev; } - err = nvme_identify_ns_csi(dev_fd(dev), cfg.namespace_id, 0, - NVME_CSI_NVM, &nvm_ns); + 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; @@ -6515,7 +6634,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi struct nvme_io_args args = { .args_size = sizeof(args), - .fd = dev_fd(dev), + .fd = dev_fd(dev), .nsid = cfg.namespace_id, .slba = cfg.start_block, .nlb = cfg.block_count, @@ -6526,12 +6645,13 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi .sts = sts, .pif = pif, .storage_tag = cfg.storage_tag, + .dspec = cfg.dspec, .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = NULL, }; err = nvme_write_zeros(&args); if (err < 0) - fprintf(stderr, "write-zeroes: %s\n", nvme_strerror(errno)); + nvme_show_error("write-zeroes: %s", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -6545,9 +6665,9 @@ ret: static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "The Dataset Management command is used by the host to "\ - "indicate attributes for ranges of logical blocks. This includes attributes "\ - "for discarding unused blocks, data read and write frequency, access size, and other "\ + const char *desc = "The Dataset Management command is used by the host to\n" + "indicate attributes for ranges of logical blocks. This includes attributes\n" + "for discarding unused blocks, data read and write frequency, access size, and other\n" "information that may be used to optimize performance and reliability."; const char *blocks = "Comma separated list of the number of blocks in each range"; const char *starting_blocks = "Comma separated list of the starting block in each range"; @@ -6608,7 +6728,7 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin ns = argconfig_parse_comma_sep_array_long(cfg.slbas, (unsigned long long *)slbas, ARRAY_SIZE(slbas)); nr = max(nc, max(nb, ns)); if (!nr || nr > 256) { - fprintf(stderr, "No range definition provided\n"); + nvme_show_error("No range definition provided"); err = -EINVAL; goto close_dev; } @@ -6616,7 +6736,7 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } } @@ -6631,12 +6751,12 @@ 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_DEFAULT_IOCTL_TIMEOUT, .result = NULL, }; err = nvme_dsm(&args); if (err < 0) - fprintf(stderr, "data-set management: %s\n", nvme_strerror(errno)); + nvme_show_error("data-set management: %s", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -6648,13 +6768,11 @@ ret: return err; } -static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int copy_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "The Copy command is used by the host to copy data " - "from one or more source logical block ranges to a " - "single consecutive destination logical block " - "range."; - + const char *desc = "The Copy command is used by the host to copy data\n" + "from one or more source logical block ranges to a\n" + "single consecutive destination logical block range."; const char *d_sdlba = "64-bit addr of first destination logical block"; const char *d_slbas = "64-bit addr of first block per range (comma-separated list)"; const char *d_nlbs = "number of blocks per range (comma-separated list, zeroes-based values)"; @@ -6759,12 +6877,15 @@ static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugi nb = argconfig_parse_comma_sep_array_short(cfg.nlbs, nlbs, ARRAY_SIZE(nlbs)); ns = argconfig_parse_comma_sep_array_long(cfg.slbas, slbas, ARRAY_SIZE(slbas)); - if (cfg.format == 0) - nrts = argconfig_parse_comma_sep_array(cfg.eilbrts, (int *)eilbrts.f0, ARRAY_SIZE(eilbrts.f0)); - else if (cfg.format == 1) - nrts = argconfig_parse_comma_sep_array_long(cfg.eilbrts, (unsigned long long *)eilbrts.f1, ARRAY_SIZE(eilbrts.f1)); - else { - fprintf(stderr, "invalid format\n"); + if (cfg.format == 0) { + nrts = argconfig_parse_comma_sep_array(cfg.eilbrts, (int *)eilbrts.f0, + ARRAY_SIZE(eilbrts.f0)); + } else if (cfg.format == 1) { + nrts = argconfig_parse_comma_sep_array_long(cfg.eilbrts, + (unsigned long long *)eilbrts.f1, + ARRAY_SIZE(eilbrts.f1)); + } else { + nvme_show_error("invalid format"); err = -EINVAL; goto close_dev; } @@ -6774,7 +6895,7 @@ static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugi nr = max(nb, max(ns, max(nrts, max(natms, nats)))); if (!nr || nr > 128 || (cfg.format == 1 && nr > 101)) { - fprintf(stderr, "invalid range\n"); + nvme_show_error("invalid range"); err = -EINVAL; goto close_dev; } @@ -6782,7 +6903,7 @@ static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugi if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } } @@ -6816,7 +6937,7 @@ static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugi }; err = nvme_copy(&args); if (err < 0) - fprintf(stderr, "NVMe Copy: %s\n", nvme_strerror(errno)); + nvme_show_error("NVMe Copy: %s", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -6828,12 +6949,12 @@ ret: return err; } -static int flush(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int flush_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Commit data and metadata associated with "\ - "given namespaces to nonvolatile media. Applies to all commands "\ - "finished before the flush was submitted. Additional data may also be "\ - "flushed by the controller, from any namespace, depending on controller and "\ + const char *desc = "Commit data and metadata associated with\n" + "given namespaces to nonvolatile media. Applies to all commands\n" + "finished before the flush was submitted. Additional data may also be\n" + "flushed by the controller, from any namespace, depending on controller and\n" "associated namespace status."; struct nvme_dev *dev; int err; @@ -6858,14 +6979,14 @@ static int flush(int argc, char **argv, struct command *cmd, struct plugin *plug if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } } err = nvme_flush(dev_fd(dev), cfg.namespace_id); if (err < 0) - fprintf(stderr, "flush: %s\n", nvme_strerror(errno)); + nvme_show_error("flush: %s", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -6878,12 +6999,11 @@ ret: static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Obtain a reservation on a given "\ - "namespace. Only one reservation is allowed at a time on a "\ - "given namespace, though multiple controllers may register "\ - "with that namespace. Namespace reservation will abort with "\ - "status Reservation Conflict if the given namespace is "\ - "already reserved."; + const char *desc = "Obtain a reservation on a given\n" + "namespace. Only one reservation is allowed at a time on a\n" + "given namespace, though multiple controllers may register\n" + "with that namespace. Namespace reservation will abort with\n" + "status Reservation Conflict if the given namespace is already reserved."; const char *prkey = "pre-empt reservation key"; const char *racqa = "reservation acquire action"; struct nvme_dev *dev; @@ -6924,12 +7044,12 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } } if (cfg.racqa > 7) { - fprintf(stderr, "invalid racqa:%d\n", cfg.racqa); + nvme_show_error("invalid racqa:%d", cfg.racqa); err = -EINVAL; goto close_dev; } @@ -6948,7 +7068,7 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi }; err = nvme_resv_acquire(&args); if (err < 0) - fprintf(stderr, "reservation acquire: %s\n", nvme_strerror(errno)); + nvme_show_error("reservation acquire: %s", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -6962,8 +7082,8 @@ ret: static int resv_register(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Register, de-register, or "\ - "replace a controller's reservation on a given namespace. "\ + const char *desc = "Register, de-register, or\n" + "replace a controller's reservation on a given namespace.\n" "Only one reservation at a time is allowed on any namespace."; const char *nrkey = "new reservation key"; const char *rrega = "reservation registration action"; @@ -7005,18 +7125,18 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } } if (cfg.cptpl > 3) { - fprintf(stderr, "invalid cptpl:%d\n", cfg.cptpl); + nvme_show_error("invalid cptpl:%d", cfg.cptpl); err = -EINVAL; goto close_dev; } if (cfg.rrega > 7) { - fprintf(stderr, "invalid rrega:%d\n", cfg.rrega); + nvme_show_error("invalid rrega:%d", cfg.rrega); err = -EINVAL; goto close_dev; } @@ -7035,7 +7155,7 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug }; err = nvme_resv_register(&args); if (err < 0) - fprintf(stderr, "reservation register: %s\n", nvme_strerror(errno)); + nvme_show_error("reservation register: %s", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -7049,13 +7169,13 @@ ret: static int resv_release(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Releases reservation held on a "\ - "namespace by the given controller. If rtype != current reservation"\ - "type, release will fails. If the given controller holds no "\ - "reservation on the namespace or is not the namespace's current "\ - "reservation holder, the release command completes with no "\ - "effect. If the reservation type is not Write Exclusive or "\ - "Exclusive Access, all registrants on the namespace except "\ + const char *desc = "Releases reservation held on a\n" + "namespace by the given controller. If rtype != current reservation\n" + "type, release will fails. If the given controller holds no\n" + "reservation on the namespace or is not the namespace's current\n" + "reservation holder, the release command completes with no\n" + "effect. If the reservation type is not Write Exclusive or\n" + "Exclusive Access, all registrants on the namespace except\n" "the issuing controller are notified."; const char *rrela = "reservation release action"; struct nvme_dev *dev; @@ -7093,12 +7213,12 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } } if (cfg.rrela > 7) { - fprintf(stderr, "invalid rrela:%d\n", cfg.rrela); + nvme_show_error("invalid rrela:%d", cfg.rrela); err = -EINVAL; goto close_dev; } @@ -7116,7 +7236,7 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi }; err = nvme_resv_release(&args); if (err < 0) - fprintf(stderr, "reservation release: %s\n", nvme_strerror(errno)); + nvme_show_error("reservation release: %s", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -7130,11 +7250,10 @@ ret: static int resv_report(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Returns Reservation Status data "\ - "structure describing any existing reservations on and the "\ - "status of a given namespace. Namespace Reservation Status "\ - "depends on the number of controllers registered for that "\ - "namespace."; + const char *desc = "Returns Reservation Status data\n" + "structure describing any existing reservations on and the\n" + "status of a given namespace. Namespace Reservation Status\n" + "depends on the number of controllers registered for that namespace."; const char *numd = "number of dwords to transfer"; const char *eds = "request extended data structure"; @@ -7173,15 +7292,18 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin goto ret; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } + if (cfg.raw_binary) flags = BINARY; if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } } @@ -7194,7 +7316,7 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin size = (cfg.numd + 1) << 2; if (posix_memalign((void **)&status, getpagesize(), size)) { - fprintf(stderr, "No memory for resv report:%d\n", size); + nvme_show_error("No memory for resv report:%d", size); err = -ENOMEM; goto close_dev; } @@ -7216,7 +7338,7 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "reservation report: %s\n", nvme_strerror(errno)); + nvme_show_error("reservation report: %s", nvme_strerror(errno)); free(status); close_dev: dev_close(dev); @@ -7232,15 +7354,14 @@ unsigned long long elapsed_utime(struct timeval start_time, return err; } -static int submit_io(int opcode, char *command, const char *desc, - int argc, char **argv) +static int submit_io(int opcode, char *command, const char *desc, int argc, char **argv) { struct timeval start_time, end_time; void *buffer, *mbuffer = NULL; int err = 0; int dfd, mfd; int flags = opcode & 1 ? O_RDONLY : O_WRONLY | O_CREAT; - int mode = S_IRUSR | S_IWUSR |S_IRGRP | S_IWGRP| S_IROTH; + int mode = 0644; __u16 control = 0, nblocks = 0; __u32 dsmgmt = 0; int logical_block_size = 0; @@ -7261,7 +7382,7 @@ static int submit_io(int opcode, char *command, const char *desc, const char *dtype_for_write = "directive type (for write-only)"; const char *dspec = "directive specific (for write-only)"; const char *dsm = "dataset management attributes (lower 8 bits)"; - const char *storage_tag_check = "This bit specifies the Storage Tag field shall be " \ + const char *storage_tag_check = "This bit specifies the Storage Tag field shall be\n" "checked as part of end-to-end data protection processing"; const char *force = "The \"I know what I'm doing\" flag, do not enforce exclusive access for write"; @@ -7352,13 +7473,11 @@ static int submit_io(int opcode, char *command, const char *desc, err = open_exclusive(&dev, argc, argv, cfg.force); if (err) { if (errno == EBUSY) { - fprintf(stderr, "Failed to open %s.\n", - basename(argv[optind])); - fprintf(stderr, - "Namespace is currently busy.\n"); + fprintf(stderr, "Failed to open %s.\n", basename(argv[optind])); + fprintf(stderr, "Namespace is currently busy.\n"); if (!cfg.force) fprintf(stderr, - "Use the force [--force] option to ignore that.\n"); + "Use the force [--force] option to ignore that.\n"); } else { argconfig_print_help(desc, opts); } @@ -7369,7 +7488,7 @@ static int submit_io(int opcode, char *command, const char *desc, if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } } @@ -7390,8 +7509,7 @@ static int submit_io(int opcode, char *command, const char *desc, control |= NVME_IO_STC; if (cfg.dtype) { if (cfg.dtype > 0xf) { - fprintf(stderr, "Invalid directive type, %x\n", - cfg.dtype); + nvme_show_error("Invalid directive type, %x", cfg.dtype); err = -EINVAL; goto close_dev; } @@ -7402,7 +7520,7 @@ static int submit_io(int opcode, char *command, const char *desc, if (strlen(cfg.data)) { dfd = open(cfg.data, flags, mode); if (dfd < 0) { - perror(cfg.data); + nvme_show_perror(cfg.data); err = -EINVAL; goto close_dev; } @@ -7411,27 +7529,25 @@ static int submit_io(int opcode, char *command, const char *desc, if (strlen(cfg.metadata)) { mfd = open(cfg.metadata, flags, mode); if (mfd < 0) { - perror(cfg.metadata); + nvme_show_perror(cfg.metadata); err = -EINVAL; goto close_dfd; } } - if (!cfg.data_size) { - fprintf(stderr, "data size not provided\n"); + if (!cfg.data_size) { + nvme_show_error("data size not provided"); err = -EINVAL; goto close_mfd; } - if (nvme_get_logical_block_size(dev_fd(dev), cfg.namespace_id, - &logical_block_size) < 0) + if (nvme_get_logical_block_size(dev_fd(dev), cfg.namespace_id, &logical_block_size) < 0) goto close_mfd; buffer_size = ((long long)cfg.block_count + 1) * logical_block_size; - if (cfg.data_size < buffer_size) { - fprintf(stderr, "Rounding data size to fit block count (%lld bytes)\n", - buffer_size); - } else + if (cfg.data_size < buffer_size) + nvme_show_error("Rounding data size to fit block count (%lld bytes)", buffer_size); + else buffer_size = cfg.data_size; /* Get the required block count. Note this is a zeroes based value. */ @@ -7452,27 +7568,26 @@ static int submit_io(int opcode, char *command, const char *desc, nvme_show_status(err); goto free_buffer; } else if (err < 0) { - fprintf(stderr, "identify namespace: %s\n", nvme_strerror(errno)); + nvme_show_error("identify namespace: %s", nvme_strerror(errno)); goto free_buffer; } nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &lba_index); ms = ns.lbaf[lba_index].ms; - err = nvme_identify_ns_csi(dev_fd(dev), 1, 0, NVME_CSI_NVM, - &nvm_ns); + 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) { - fprintf(stderr, "Rounding metadata size to fit block count (%lld bytes)\n", + if (ms && cfg.metadata_size < mbuffer_size) + nvme_show_error("Rounding metadata size to fit block count (%lld bytes)", mbuffer_size); - } else { + else mbuffer_size = cfg.metadata_size; - } + mbuffer = malloc(mbuffer_size); if (!mbuffer) { err = -ENOMEM; @@ -7486,12 +7601,11 @@ static int submit_io(int opcode, char *command, const char *desc, goto free_buffer; } - if ((opcode & 1)) { + if (opcode & 1) { err = read(dfd, (void *)buffer, cfg.data_size); if (err < 0) { err = -errno; - fprintf(stderr, "failed to read data buffer from input" - " file %s\n", strerror(errno)); + nvme_show_error("failed to read data buffer from input file %s", strerror(errno)); goto free_mbuffer; } } @@ -7500,8 +7614,7 @@ static int submit_io(int opcode, char *command, const char *desc, err = read(mfd, (void *)mbuffer, mbuffer_size); if (err < 0) { err = -errno; - fprintf(stderr, "failed to read meta-data buffer from" - " input file %s\n", strerror(errno)); + nvme_show_error("failed to read meta-data buffer from input file %s", strerror(errno)); goto free_mbuffer; } } @@ -7544,7 +7657,7 @@ static int submit_io(int opcode, char *command, const char *desc, .storage_tag = cfg.storage_tag, .data_len = buffer_size, .data = buffer, - .metadata_len = cfg.metadata_size, + .metadata_len = mbuffer_size, .metadata = mbuffer, .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = NULL, @@ -7553,24 +7666,25 @@ static int submit_io(int opcode, char *command, const char *desc, err = nvme_io(&args, opcode); gettimeofday(&end_time, NULL); if (cfg.latency) - printf(" latency: %s: %llu us\n", - command, elapsed_utime(start_time, end_time)); - if (err < 0) - fprintf(stderr, "submit-io: %s\n", nvme_strerror(errno)); - else if (err) + printf(" latency: %s: %llu us\n", command, elapsed_utime(start_time, end_time)); + if (err < 0) { + nvme_show_error("submit-io: %s", nvme_strerror(errno)); + } else if (err) { nvme_show_status(err); - else { - if (!(opcode & 1) && write(dfd, (void *)buffer, cfg.data_size) < 0) { - fprintf(stderr, "write: %s: failed to write buffer to output file\n", - strerror(errno)); + } else { + if (!(opcode & 1) && write(dfd, (void *)buffer, buffer_size) < 0) { + nvme_show_error("write: %s: failed to write buffer to output file", + strerror(errno)); err = -EINVAL; } else if (!(opcode & 1) && cfg.metadata_size && - write(mfd, (void *)mbuffer, mbuffer_size) < 0) { - fprintf(stderr, "write: %s: failed to write meta-data buffer to output file\n", - strerror(errno)); + write(mfd, (void *)mbuffer, mbuffer_size) < 0) { + nvme_show_error( + "write: %s: failed to write meta-data buffer to output file", + strerror(errno)); err = -EINVAL; - } else - fprintf(stderr, "%s: Success\n", command); + } else { + printf("%s: Success\n", command); + } } free_mbuffer: @@ -7590,24 +7704,26 @@ ret: static int compare(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Compare specified logical blocks on "\ - "device with specified data buffer; return failure if buffer "\ + const char *desc = "Compare specified logical blocks on\n" + "device with specified data buffer; return failure if buffer\n" "and block(s) are dissimilar"; + return submit_io(nvme_cmd_compare, "compare", desc, argc, argv); } static int read_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Copy specified logical blocks on the given "\ + const char *desc = "Copy specified logical blocks on the given\n" "device to specified data buffer (default buffer is stdout)."; + return submit_io(nvme_cmd_read, "read", desc, argc, argv); } static int write_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Copy from provided data buffer (default "\ - "buffer is stdin) to specified logical blocks on the given "\ - "device."; + const char *desc = "Copy from provided data buffer (default\n" + "buffer is stdin) to specified logical blocks on the given device."; + return submit_io(nvme_cmd_write, "write", desc, argc, argv); } @@ -7621,9 +7737,10 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin int err; const char *desc = "Verify specified logical blocks on the given device."; - const char *force_unit_access_verify = "force device to commit cached data before performing the verify operation"; - const char *storage_tag_check = "This bit specifies the Storage Tag field shall "\ - "be checked as part of Verify operation"; + const char *force_unit_access_verify = + "force device to commit cached data before performing the verify operation"; + const char *storage_tag_check = + "This bit specifies the Storage Tag field shall be checked as part of Verify operation"; struct config { __u32 namespace_id; @@ -7688,14 +7805,14 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin if (!cfg.namespace_id) { err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { - fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); goto close_dev; } } err = nvme_cli_identify_ns(dev, cfg.namespace_id, &ns); if (err < 0) { - fprintf(stderr, "identify namespace: %s\n", nvme_strerror(errno)); + nvme_show_error("identify namespace: %s", nvme_strerror(errno)); goto close_dev; } else if (err) { nvme_show_status(err); @@ -7733,7 +7850,7 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin }; err = nvme_verify(&args); if (err < 0) - fprintf(stderr, "verify: %s\n", nvme_strerror(errno)); + nvme_show_error("verify: %s", nvme_strerror(errno)); else if (err != 0) nvme_show_status(err); else @@ -7747,11 +7864,11 @@ ret: static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Obtain results of one or more "\ - "previously submitted security-sends. Results, and association "\ - "between Security Send and Receive, depend on the security "\ - "protocol field as they are defined by the security protocol "\ - "used. A Security Receive must follow a Security Send made with "\ + const char *desc = "Obtain results of one or more\n" + "previously submitted security-sends. Results, and association\n" + "between Security Send and Receive, depend on the security\n" + "protocol field as they are defined by the security protocol\n" + "used. A Security Receive must follow a Security Send made with\n" "the same security protocol."; const char *size = "size of buffer (prints to stdout on success)"; const char *al = "allocation length (cf. SPC-4)"; @@ -7796,8 +7913,7 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p if (cfg.size) { if (posix_memalign(&sec_buf, getpagesize(), cfg.size)) { - fprintf(stderr, "No memory for security size:%d\n", - cfg.size); + nvme_show_error("No memory for security size:%d", cfg.size); err = -ENOMEM; goto close_dev; } @@ -7818,16 +7934,15 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p }; err = nvme_cli_security_receive(dev, &args); - - if (err < 0) - fprintf(stderr, "security receive: %s\n", nvme_strerror(errno)); - else if (err != 0) + if (err < 0) { + nvme_show_error("security receive: %s", nvme_strerror(errno)); + } else if (err != 0) { nvme_show_status(err); - else { + } else { printf("NVME Security Receive Command Success\n"); - if (!cfg.raw_binary) { + if (!cfg.raw_binary) d(sec_buf, cfg.size, 16, 1); - } else if (cfg.size) + else if (cfg.size) d_raw((unsigned char *)sec_buf, cfg.size); } @@ -7843,15 +7958,14 @@ static int get_lba_status(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Information about potentially unrecoverable LBAs."; - const char *slba = "Starting LBA(SLBA) in 64-bit address of the first"\ - " logical block addressed by this command"; - const char *mndw = "Maximum Number of Dwords(MNDW) specifies maximum"\ - " number of dwords to return"; - const char *atype = "Action Type(ATYPE) specifies the mechanism"\ - " the controller uses in determining the LBA"\ - " Status Descriptors to return."; - const char *rl = "Range Length(RL) specifies the length of the range"\ - " of contiguous LBAs beginning at SLBA"; + const char *slba = + "Starting LBA(SLBA) in 64-bit address of the first logical block addressed by this command"; + const char *mndw = + "Maximum Number of Dwords(MNDW) specifies maximum number of dwords to return"; + const char *atype = "Action Type(ATYPE) specifies the mechanism\n" + "the controller uses in determining the LBA Status Descriptors to return."; + const char *rl = + "Range Length(RL) specifies the length of the range of contiguous LBAs beginning at SLBA"; enum nvme_print_flags flags; unsigned long buf_len; @@ -7895,11 +8009,13 @@ static int get_lba_status(int argc, char **argv, struct command *cmd, goto err; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); goto close_dev; + } if (!cfg.atype) { - fprintf(stderr, "action type (--action) has to be given\n"); + nvme_show_error("action type (--action) has to be given"); err = -EINVAL; goto close_dev; } @@ -7929,7 +8045,7 @@ static int get_lba_status(int argc, char **argv, struct command *cmd, else if (err > 0) nvme_show_status(err); else - fprintf(stderr, "get lba status: %s\n", nvme_strerror(errno)); + nvme_show_error("get lba status: %s", nvme_strerror(errno)); free(buf); close_dev: dev_close(dev); @@ -7939,16 +8055,16 @@ err: static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Host software uses the Capacity Management command to "\ - "configure Endurance Groups and NVM Sets in an NVM subsystem by either " \ - "selecting one of a set of supported configurations or by specifying the "\ + const char *desc = "Host software uses the Capacity Management command to\n" + "configure Endurance Groups and NVM Sets in an NVM subsystem by either\n" + "selecting one of a set of supported configurations or by specifying the\n" "capacity of the Endurance Group or NVM Set to be created"; const char *operation = "Operation to be performed by the controller"; const char *element_id = "Value specific to the value of the Operation field."; - const char *cap_lower = "Least significant 32 bits of the capacity in bytes of the "\ - "Endurance Group or NVM Set to be created"; - const char *cap_upper = "Most significant 32 bits of the capacity in bytes of the "\ - "Endurance Group or NVM Set to be created"; + const char *cap_lower = + "Least significant 32 bits of the capacity in bytes of the Endurance Group or NVM Set to be created"; + const char *cap_upper = + "Most significant 32 bits of the capacity in bytes of the Endurance Group or NVM Set to be created"; struct nvme_dev *dev; int err = -1; @@ -7981,7 +8097,7 @@ static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plug goto ret; if (cfg.operation > 0xf) { - fprintf(stderr, "invalid operation field: %u\n", cfg.operation); + nvme_show_error("invalid operation field: %u", cfg.operation); err = -1; goto close_dev; } @@ -7999,15 +8115,15 @@ static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plug err = nvme_capacity_mgmt(&args); if (!err) { printf("Capacity Management Command is Success\n"); - if (cfg.operation == 1) { + if (cfg.operation == 1) printf("Created Element Identifier for Endurance Group is: %u\n", result); - } else if (cfg.operation == 3) { + else if (cfg.operation == 3) printf("Created Element Identifier for NVM Set is: %u\n", result); - } - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); - else if (err < 0) - fprintf(stderr, "capacity management: %s\n", nvme_strerror(errno)); + } else if (err < 0) { + nvme_show_error("capacity management: %s", nvme_strerror(errno)); + } close_dev: dev_close(dev); @@ -8017,8 +8133,7 @@ ret: static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Read directive parameters of the "\ - "specified directive type."; + const char *desc = "Read directive parameters of the specified directive type."; const char *nsr = "namespace stream requested"; enum nvme_print_flags flags = NORMAL; @@ -8051,14 +8166,14 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin }; OPT_ARGS(opts) = { - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), - OPT_UINT("data-len", 'l', &cfg.data_len, buf_len), - OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_directive), - OPT_BYTE("dir-type", 'D', &cfg.dtype, dtype), - OPT_SHRT("dir-spec", 'S', &cfg.dspec, dspec_w_dtype), - OPT_BYTE("dir-oper", 'O', &cfg.doper, doper), - OPT_SHRT("req-resource", 'r', &cfg.nsr, nsr), - OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable_directive), + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), + OPT_UINT("data-len", 'l', &cfg.data_len, buf_len), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_directive), + OPT_BYTE("dir-type", 'D', &cfg.dtype, dtype), + OPT_SHRT("dir-spec", 'S', &cfg.dspec, dspec_w_dtype), + OPT_BYTE("dir-oper", 'O', &cfg.doper, doper), + OPT_SHRT("req-resource", 'r', &cfg.nsr, nsr), + OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable_directive), OPT_END() }; @@ -8079,7 +8194,7 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin cfg.data_len = 4096; break; default: - fprintf(stderr, "invalid directive operations for Identify Directives\n"); + nvme_show_error("invalid directive operations for Identify Directives"); err = -EINVAL; goto close_dev; } @@ -8098,13 +8213,13 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin dw12 = cfg.nsr; break; default: - fprintf(stderr, "invalid directive operations for Streams Directives\n"); + nvme_show_error("invalid directive operations for Streams Directives"); err = -EINVAL; goto close_dev; } break; default: - fprintf(stderr, "invalid directive type\n"); + nvme_show_error("invalid directive type"); err = -EINVAL; goto close_dev; } @@ -8132,13 +8247,12 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin }; err = nvme_directive_recv(&args); if (!err) - nvme_directive_show(cfg.dtype, cfg.doper, cfg.dspec, - cfg.namespace_id, result, buf, cfg.data_len, - flags); + nvme_directive_show(cfg.dtype, cfg.doper, cfg.dspec, cfg.namespace_id, + result, buf, cfg.data_len, flags); else if (err > 0) nvme_show_status(err); else if (err < 0) - fprintf(stderr, "dir-receive: %s\n", nvme_strerror(errno)); + nvme_show_error("dir-receive: %s", nvme_strerror(errno)); free(buf); close_dev: @@ -8156,23 +8270,23 @@ static int rpmb_cmd(int argc, char **argv, struct command *cmd, struct plugin *p static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "The Lockdown command is used to control the "\ - "Command and Feature Lockdown capability which configures the "\ - "prohibition or allowance of execution of the specified command "\ + const char *desc = "The Lockdown command is used to control the\n" + "Command and Feature Lockdown capability which configures the\n" + "prohibition or allowance of execution of the specified command\n" "or Set Features command targeting a specific Feature Identifier."; - const char *ofi_desc = "Opcode or Feature Identifier(OFI) "\ - "specifies the command opcode or Set Features Feature Identifier "\ + const char *ofi_desc = "Opcode or Feature Identifier (OFI)\n" + "specifies the command opcode or Set Features Feature Identifier\n" "identified by the Scope field."; - const char *ifc_desc = "[0-3] Interface (INF) field identifies the "\ - "interfaces affected by this command."; - const char *prhbt_desc = "[0-1]Prohibit(PRHBT) bit specifies whether "\ - "to prohibit or allow the command opcode or Set Features Feature "\ + const char *ifc_desc = + "[0-3] Interface (INF) field identifies the interfaces affected by this command."; + const char *prhbt_desc = "[0-1]Prohibit(PRHBT) bit specifies whether\n" + "to prohibit or allow the command opcode or Set Features Feature\n" "Identifier specified by this command."; - const char *scp_desc = "[0-15]Scope(SCP) field specifies the contents "\ - "of the Opcode or Feature Identifier field."; - const char *uuid_desc = "UUID Index - If this field is set to a non-zero "\ - "value, then the value of this field is the index of a UUID in the UUID "\ - "List that is used by the command.If this field is cleared to 0h,"\ + const char *scp_desc = + "[0-15]Scope(SCP) field specifies the contents of the Opcode or Feature Identifier field."; + const char *uuid_desc = "UUID Index - If this field is set to a non-zero\n" + "value, then the value of this field is the index of a UUID in the UUID\n" + "List that is used by the command.If this field is cleared to 0h,\n" "then no UUID index is specified"; struct nvme_dev *dev; @@ -8209,22 +8323,22 @@ static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugi /* check for input argument limit */ if (cfg.ifc > 3) { - fprintf(stderr, "invalid interface settings:%d\n", cfg.ifc); + nvme_show_error("invalid interface settings:%d", cfg.ifc); err = -1; goto close_dev; } if (cfg.prhbt > 1) { - fprintf(stderr, "invalid prohibit settings:%d\n", cfg.prhbt); + nvme_show_error("invalid prohibit settings:%d", cfg.prhbt); err = -1; goto close_dev; } if (cfg.scp > 15) { - fprintf(stderr, "invalid scope settings:%d\n", cfg.scp); + nvme_show_error("invalid scope settings:%d", cfg.scp); err = -1; goto close_dev; } if (cfg.uuid > 127) { - fprintf(stderr, "invalid UUID index settings:%d\n", cfg.uuid); + nvme_show_error("invalid UUID index settings:%d", cfg.uuid); err = -1; goto close_dev; } @@ -8242,7 +8356,7 @@ static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugi }; err = nvme_lockdown(&args); if (err < 0) - fprintf(stderr, "lockdown: %s\n", nvme_strerror(errno)); + nvme_show_error("lockdown: %s", nvme_strerror(errno)); else if (err > 0) nvme_show_status(err); else @@ -8254,6 +8368,31 @@ ret: return err; } +static void passthru_print_read_output(struct passthru_config cfg, void *data, int dfd, void *mdata, + int mfd, int err) +{ + if (strlen(cfg.input_file)) { + if (write(dfd, (void *)data, cfg.data_len) < 0) + perror("failed to write data buffer"); + } else if (data) { + if (cfg.raw_binary) + d_raw((unsigned char *)data, cfg.data_len); + else if (!err) + d((unsigned char *)data, cfg.data_len, 16, 1); + } + if (cfg.metadata_len && cfg.metadata) { + if (strlen(cfg.metadata)) { + if (write(mfd, (void *)mdata, cfg.metadata_len) < 0) + perror("failed to write metadata buffer"); + } else { + if (cfg.raw_binary) + d_raw((unsigned char *)mdata, cfg.metadata_len); + else if (!err) + d((unsigned char *)mdata, cfg.metadata_len, 16, 1); + } + } +} + static int passthru(int argc, char **argv, bool admin, const char *desc, struct command *cmd) { @@ -8278,7 +8417,7 @@ static int passthru(int argc, char **argv, bool admin, const char *prefill = "prefill buffers with known byte-value, default 0"; int flags; - int mode = S_IRUSR | S_IWUSR |S_IRGRP | S_IWGRP| S_IROTH; + int mode = 0644; void *data = NULL, *mdata = NULL; int err = 0, dfd, mfd; struct nvme_dev *dev; @@ -8287,34 +8426,7 @@ static int passthru(int argc, char **argv, bool admin, const char *cmd_name = NULL; struct timeval start_time, end_time; - struct config { - __u8 opcode; - __u8 flags; - __u16 rsvd; - __u32 namespace_id; - __u32 data_len; - __u32 metadata_len; - __u32 timeout; - __u32 cdw2; - __u32 cdw3; - __u32 cdw10; - __u32 cdw11; - __u32 cdw12; - __u32 cdw13; - __u32 cdw14; - __u32 cdw15; - char *input_file; - char *metadata; - bool raw_binary; - bool show_command; - bool dry_run; - bool read; - bool write; - __u8 prefill; - bool latency; - }; - - struct config cfg = { + struct passthru_config cfg = { .opcode = 0, .flags = 0, .prefill = 0, @@ -8392,7 +8504,7 @@ static int passthru(int argc, char **argv, bool admin, if (strlen(cfg.input_file)) { dfd = open(cfg.input_file, flags, mode); if (dfd < 0) { - perror(cfg.input_file); + nvme_show_perror(cfg.input_file); err = -EINVAL; goto close_dev; } @@ -8401,7 +8513,7 @@ static int passthru(int argc, char **argv, bool admin, if (cfg.metadata && strlen(cfg.metadata)) { mfd = open(cfg.metadata, flags, mode); if (mfd < 0) { - perror(cfg.metadata); + nvme_show_perror(cfg.metadata); err = -EINVAL; goto close_dfd; } @@ -8417,11 +8529,12 @@ static int passthru(int argc, char **argv, bool admin, if (cfg.write) { if (read(mfd, mdata, cfg.metadata_len) < 0) { err = -errno; - perror("failed to read metadata write buffer"); + nvme_show_perror("failed to read metadata write buffer"); goto free_metadata; } - } else + } else { memset(mdata, cfg.prefill, cfg.metadata_len); + } } if (cfg.data_len) { @@ -8433,14 +8546,13 @@ static int passthru(int argc, char **argv, bool admin, memset(data, cfg.prefill, cfg.data_len); if (!cfg.read && !cfg.write) { - fprintf(stderr, "data direction not given\n"); + nvme_show_error("data direction not given"); err = -EINVAL; goto free_data; } else if (cfg.write) { if (read(dfd, data, cfg.data_len) < 0) { err = -errno; - fprintf(stderr, "failed to read write buffer " - "%s\n", strerror(errno)); + nvme_show_error("failed to read write buffer %s", strerror(errno)); goto free_data; } } @@ -8472,14 +8584,14 @@ static int passthru(int argc, char **argv, bool admin, if (admin) err = nvme_cli_admin_passthru(dev, cfg.opcode, cfg.flags, - cfg.rsvd, - cfg.namespace_id, cfg.cdw2, - cfg.cdw3, cfg.cdw10, - cfg.cdw11, cfg.cdw12, cfg.cdw13, - cfg.cdw14, - cfg.cdw15, cfg.data_len, data, - cfg.metadata_len, - mdata, cfg.timeout, &result); + cfg.rsvd, + cfg.namespace_id, cfg.cdw2, + cfg.cdw3, cfg.cdw10, + cfg.cdw11, cfg.cdw12, cfg.cdw13, + cfg.cdw14, + cfg.cdw15, cfg.data_len, data, + cfg.metadata_len, + mdata, cfg.timeout, &result); else err = nvme_io_passthru(dev_fd(dev), cfg.opcode, cfg.flags, cfg.rsvd, @@ -8494,31 +8606,19 @@ static int passthru(int argc, char **argv, bool admin, gettimeofday(&end_time, NULL); cmd_name = nvme_cmd_to_string(admin, cfg.opcode); if (cfg.latency) - printf("%s Command %s latency: %llu us\n", - admin ? "Admin": "IO", - strcmp(cmd_name, "Unknown") ? cmd_name: "Vendor Specific", - elapsed_utime(start_time, end_time)); + printf("%s Command %s latency: %llu us\n", admin ? "Admin" : "IO", + strcmp(cmd_name, "Unknown") ? cmd_name : "Vendor Specific", + elapsed_utime(start_time, end_time)); - if (err < 0) - fprintf(stderr, "passthru: %s\n", nvme_strerror(errno)); - else if (err) + if (err < 0) { + nvme_show_error("%s: %s", __func__, nvme_strerror(errno)); + } else if (err) { nvme_show_status(err); - else { - fprintf(stderr, "%s Command %s is Success and result: 0x%08x\n", - admin ? "Admin": "IO", - strcmp(cmd_name, "Unknown") ? cmd_name: "Vendor Specific", - result); - if (cfg.read && strlen(cfg.input_file)) { - if (write(dfd, (void *)data, cfg.data_len) < 0) - perror("failed to write data buffer"); - if (cfg.metadata_len && cfg.metadata) - if (write(mfd, (void *)mdata, cfg.metadata_len) < 0) - perror("failed to write metadata buffer"); - } else if (!cfg.raw_binary) { - if (data && cfg.read && !err) - d((unsigned char *)data, cfg.data_len, 16, 1); - } else if (data && cfg.read) - d_raw((unsigned char *)data, cfg.data_len); + } else { + printf("%s Command %s is Success and result: 0x%08x\n", admin ? "Admin" : "IO", + strcmp(cmd_name, "Unknown") ? cmd_name : "Vendor Specific", result); + if (cfg.read) + passthru_print_read_output(cfg, data, dfd, mdata, mfd, err); } free_metadata: free(mdata); @@ -8538,15 +8638,17 @@ ret: static int io_passthru(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send a user-defined IO command to the specified "\ - "device via IOCTL passthrough, return results."; + const char *desc = + "Send a user-defined IO command to the specified device via IOCTL passthrough, return results."; + return passthru(argc, argv, false, desc, cmd); } static int admin_passthru(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send a user-defined Admin command to the specified "\ - "device via IOCTL passthrough, return results."; + const char *desc = + "Send a user-defined Admin command to the specified device via IOCTL passthrough, return results."; + return passthru(argc, argv, true, desc, cmd); } @@ -8556,8 +8658,8 @@ static int gen_hostnqn_cmd(int argc, char **argv, struct command *command, struc hostnqn = nvmf_hostnqn_generate(); if (!hostnqn) { - fprintf(stderr, "\"%s\" not supported. Install lib uuid and rebuild.\n", - command->name); + nvme_show_error("\"%s\" not supported. Install lib uuid and rebuild.", + command->name); return -ENOTSUP; } printf("%s\n", hostnqn); @@ -8574,8 +8676,8 @@ static int show_hostnqn_cmd(int argc, char **argv, struct command *command, stru hostnqn = nvmf_hostnqn_generate(); if (!hostnqn) { - fprintf(stderr, "hostnqn is not available -- use nvme gen-hostnqn\n"); - return ENOENT; + nvme_show_error("hostnqn is not available -- use nvme gen-hostnqn"); + return -ENOENT; } fprintf(stdout, "%s\n", hostnqn); @@ -8587,14 +8689,13 @@ static int show_hostnqn_cmd(int argc, char **argv, struct command *command, stru static int gen_dhchap_key(int argc, char **argv, struct command *command, struct plugin *plugin) { - const char *desc = "Generate a DH-HMAC-CHAP host key usable "\ - "for NVMe In-Band Authentication."; - const char *secret = "Optional secret (in hexadecimal characters) "\ - "to be used to initialize the host key."; - const char *key_len = "Length of the resulting key "\ - "(32, 48, or 64 bytes)."; - const char *hmac = "HMAC function to use for key transformation "\ - "(0 = none, 1 = SHA-256, 2 = SHA-384, 3 = SHA-512)."; + const char *desc = + "Generate a DH-HMAC-CHAP host key usable for NVMe In-Band Authentication."; + const char *secret = + "Optional secret (in hexadecimal characters) to be used to initialize the host key."; + const char *key_len = "Length of the resulting key (32, 48, or 64 bytes)."; + const char *hmac = + "HMAC function to use for key transformation (0 = none, 1 = SHA-256, 2 = SHA-384, 3 = SHA-512)."; const char *nqn = "Host NQN to use for key transformation."; unsigned char *raw_secret; @@ -8630,46 +8731,44 @@ static int gen_dhchap_key(int argc, char **argv, struct command *command, struct return err; if (cfg.hmac > 3) { - fprintf(stderr, "Invalid HMAC identifier %u\n", cfg.hmac); + nvme_show_error("Invalid HMAC identifier %u", cfg.hmac); return -EINVAL; } if (cfg.hmac > 0) { switch (cfg.hmac) { case 1: - if (!cfg.key_len) + if (!cfg.key_len) { cfg.key_len = 32; - else if (cfg.key_len != 32) { - fprintf(stderr, "Invalid key length %d for SHA(256)\n", - cfg.key_len); + } else if (cfg.key_len != 32) { + nvme_show_error("Invalid key length %d for SHA(256)", cfg.key_len); return -EINVAL; } break; case 2: - if (!cfg.key_len) + if (!cfg.key_len) { cfg.key_len = 48; - else if (cfg.key_len != 48) { - fprintf(stderr, "Invalid key length %d for SHA(384)\n", - cfg.key_len); + } else if (cfg.key_len != 48) { + nvme_show_error("Invalid key length %d for SHA(384)", cfg.key_len); return -EINVAL; } break; case 3: - if (!cfg.key_len) + if (!cfg.key_len) { cfg.key_len = 64; - else if (cfg.key_len != 64) { - fprintf(stderr, "Invalid key length %d for SHA(512)\n", - cfg.key_len); + } else if (cfg.key_len != 64) { + nvme_show_error("Invalid key length %d for SHA(512)", cfg.key_len); return -EINVAL; } break; default: break; } - } else if (!cfg.key_len) + } else if (!cfg.key_len) { cfg.key_len = 32; + } if (cfg.key_len != 32 && cfg.key_len != 48 && cfg.key_len != 64) { - fprintf(stderr, "Invalid key length %u\n", cfg.key_len); + nvme_show_error("Invalid key length %u", cfg.key_len); return -EINVAL; } raw_secret = malloc(cfg.key_len); @@ -8682,17 +8781,15 @@ static int gen_dhchap_key(int argc, char **argv, struct command *command, struct int secret_len = 0, i; unsigned int c; - for (i = 0; i < strlen(cfg.secret); i+=2) { + for (i = 0; i < strlen(cfg.secret); i += 2) { if (sscanf(&cfg.secret[i], "%02x", &c) != 1) { - fprintf(stderr, "Invalid secret '%s'\n", - cfg.secret); + nvme_show_error("Invalid secret '%s'", cfg.secret); return -EINVAL; } raw_secret[secret_len++] = (unsigned char)c; } if (secret_len != cfg.key_len) { - fprintf(stderr, "Invalid key length (%d bytes)\n", - secret_len); + nvme_show_error("Invalid key length (%d bytes)", secret_len); return -EINVAL; } } @@ -8700,13 +8797,12 @@ static int gen_dhchap_key(int argc, char **argv, struct command *command, struct if (!cfg.nqn) { cfg.nqn = nvmf_hostnqn_from_file(); if (!cfg.nqn) { - fprintf(stderr, "Could not read host NQN\n"); + nvme_show_error("Could not read host NQN"); return -ENOENT; } } - if (nvme_gen_dhchap_key(cfg.nqn, cfg.hmac, cfg.key_len, - raw_secret, key) < 0) + if (nvme_gen_dhchap_key(cfg.nqn, cfg.hmac, cfg.key_len, raw_secret, key) < 0) return -errno; crc = crc32(crc, key, cfg.key_len); @@ -8724,10 +8820,9 @@ static int gen_dhchap_key(int argc, char **argv, struct command *command, struct static int check_dhchap_key(int argc, char **argv, struct command *command, struct plugin *plugin) { - const char *desc = "Check a DH-HMAC-CHAP host key for usability "\ - "for NVMe In-Band Authentication."; - const char *key = "DH-HMAC-CHAP key (in hexadecimal characters) "\ - "to be validated."; + const char *desc = + "Check a DH-HMAC-CHAP host key for usability for NVMe In-Band Authentication."; + const char *key = "DH-HMAC-CHAP key (in hexadecimal characters) to be validated."; unsigned char decoded_key[128]; unsigned int decoded_len; @@ -8752,12 +8847,12 @@ static int check_dhchap_key(int argc, char **argv, struct command *command, stru return err; if (!cfg.key) { - fprintf(stderr, "Key not specified\n"); + nvme_show_error("Key not specified"); return -EINVAL; } if (sscanf(cfg.key, "DHHC-1:%02x:*s", &hmac) != 1) { - fprintf(stderr, "Invalid key header '%s'\n", cfg.key); + nvme_show_error("Invalid key header '%s'", cfg.key); return -EINVAL; } switch (hmac) { @@ -8765,68 +8860,61 @@ static int check_dhchap_key(int argc, char **argv, struct command *command, stru break; case 1: if (strlen(cfg.key) != 59) { - fprintf(stderr, "Invalid key length for SHA(256)\n"); + nvme_show_error("Invalid key length for SHA(256)"); return -EINVAL; } break; case 2: if (strlen(cfg.key) != 83) { - fprintf(stderr, "Invalid key length for SHA(384)\n"); + nvme_show_error("Invalid key length for SHA(384)"); return -EINVAL; } break; case 3: if (strlen(cfg.key) != 103) { - fprintf(stderr, "Invalid key length for SHA(512)\n"); + nvme_show_error("Invalid key length for SHA(512)"); return -EINVAL; } break; default: - fprintf(stderr, "Invalid HMAC identifier %d\n", hmac); + nvme_show_error("Invalid HMAC identifier %d", hmac); return -EINVAL; - break; } - err = base64_decode(cfg.key + 10, strlen(cfg.key) - 11, - decoded_key); + err = base64_decode(cfg.key + 10, strlen(cfg.key) - 11, decoded_key); if (err < 0) { - fprintf(stderr, "Base64 decoding failed, error %d\n", - err); + nvme_show_error("Base64 decoding failed, error %d", err); return err; } decoded_len = err; if (decoded_len < 32) { - fprintf(stderr, "Base64 decoding failed (%s, size %u)\n", - cfg.key + 10, decoded_len); + nvme_show_error("Base64 decoding failed (%s, size %u)", cfg.key + 10, decoded_len); return -EINVAL; } decoded_len -= 4; if (decoded_len != 32 && decoded_len != 48 && decoded_len != 64) { - fprintf(stderr, "Invalid key length %d\n", decoded_len); + nvme_show_error("Invalid key length %d", decoded_len); 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); + ((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); if (key_crc != crc) { - fprintf(stderr, "CRC mismatch (key %08x, crc %08x)\n", - key_crc, crc); + nvme_show_error("CRC mismatch (key %08x, crc %08x)", key_crc, crc); return -EINVAL; } - printf("Key is valid (HMAC %d, length %d, CRC %08x)\n", - hmac, decoded_len, crc); + printf("Key is valid (HMAC %d, length %d, CRC %08x)\n", hmac, decoded_len, crc); return 0; } static int gen_tls_key(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Generate a TLS key in NVMe PSK Interchange format."; - const char *secret = "Optional secret (in hexadecimal characters) "\ - "to be used for the TLS key."; - const char *hmac = "HMAC function to use for the retained key "\ - "(1 = SHA-256, 2 = SHA-384)."; + const char *secret = + "Optional secret (in hexadecimal characters) to be used for the TLS key."; + const char *hmac = "HMAC function to use for the retained key (1 = SHA-256, 2 = SHA-384)."; const char *hostnqn = "Host NQN for the retained key."; const char *subsysnqn = "Subsystem NQN for the retained key."; const char *keyring = "Keyring for the retained key."; @@ -8875,11 +8963,11 @@ static int gen_tls_key(int argc, char **argv, struct command *command, struct pl if (err) return err; if (cfg.hmac < 1 || cfg.hmac > 3) { - fprintf(stderr, "Invalid HMAC identifier %u\n", cfg.hmac); + nvme_show_error("Invalid HMAC identifier %u", cfg.hmac); return -EINVAL; } if (cfg.insert && !cfg.subsysnqn) { - fprintf(stderr, "No subsystem NQN specified\n"); + nvme_show_error("No subsystem NQN specified"); return -EINVAL; } if (cfg.hmac == 2) @@ -8895,53 +8983,45 @@ static int gen_tls_key(int argc, char **argv, struct command *command, struct pl int secret_len = 0, i; unsigned int c; - for (i = 0; i < strlen(cfg.secret); i+=2) { + for (i = 0; i < strlen(cfg.secret); i += 2) { if (sscanf(&cfg.secret[i], "%02x", &c) != 1) { - fprintf(stderr, "Invalid secret '%s'\n", - cfg.secret); + nvme_show_error("Invalid secret '%s'", cfg.secret); return -EINVAL; } if (i >= key_len) { - fprintf(stderr, - "Skipping excess secret bytes\n"); + fprintf(stderr, "Skipping excess secret bytes\n"); break; } raw_secret[secret_len++] = (unsigned char)c; } if (secret_len != key_len) { - fprintf(stderr, "Invalid key length (%d bytes)\n", - secret_len); + nvme_show_error("Invalid key length (%d bytes)", secret_len); return -EINVAL; } } if (cfg.hostnqn && !cfg.subsysnqn) { - fprintf(stderr, - "Need to specify subsystem NQN to insert a TLS key\n"); + nvme_show_error("Need to specify subsystem NQN to insert a TLS key"); return -EINVAL; } if (cfg.subsysnqn) { if (!cfg.hostnqn) { cfg.hostnqn = nvmf_hostnqn_from_file(); if (!cfg.hostnqn) { - fprintf(stderr, - "Failed to read host NQN\n"); + nvme_show_error("Failed to read host NQN"); return -EINVAL; } } - tls_key = nvme_insert_tls_key(cfg.keyring, cfg.keytype, - cfg.hostnqn, cfg.subsysnqn, cfg.hmac, - raw_secret, key_len); + tls_key = nvme_insert_tls_key(cfg.keyring, cfg.keytype, cfg.hostnqn, cfg.subsysnqn, + cfg.hmac, raw_secret, key_len); if (tls_key < 0) { - fprintf(stderr, - "Failed to insert key, error %d\n", errno); + nvme_show_error("Failed to insert key, error %d", errno); return -errno; } if (cfg.insert) { - printf("Inserted TLS key %08x\n", - (unsigned int)tls_key); + printf("Inserted TLS key %08x\n", (unsigned int)tls_key); return 0; } } @@ -8961,8 +9041,7 @@ static int gen_tls_key(int argc, char **argv, struct command *command, struct pl static int check_tls_key(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Check a TLS key for NVMe PSK Interchange format.\n"; - const char *keydata = "TLS key (in PSK Interchange format) "\ - "to be validated."; + const char *keydata = "TLS key (in PSK Interchange format) to be validated."; const char *hostnqn = "Host NQN for the retained key."; const char *subsysnqn = "Subsystem NQN for the retained key."; const char *keyring = "Keyring for the retained key."; @@ -9004,46 +9083,41 @@ static int check_tls_key(int argc, char **argv, struct command *command, struct return err; if (!cfg.keydata) { - fprintf(stderr, "No key data\n"); + nvme_show_error("No key data"); return -EINVAL; } if (sscanf(cfg.keydata, "NVMeTLSkey-1:%02x:*s", &hmac) != 1) { - fprintf(stderr, "Invalid key '%s'\n", cfg.keydata); + nvme_show_error("Invalid key '%s'", cfg.keydata); return -EINVAL; } switch (hmac) { case 1: if (strlen(cfg.keydata) != 65) { - fprintf(stderr, "Invalid key length %zu for SHA(256)\n", - strlen(cfg.keydata)); + nvme_show_error("Invalid key length %zu for SHA(256)", strlen(cfg.keydata)); return -EINVAL; } break; case 2: if (strlen(cfg.keydata) != 89) { - fprintf(stderr, "Invalid key length %zu for SHA(384)\n", - strlen(cfg.keydata)); + nvme_show_error("Invalid key length %zu for SHA(384)", strlen(cfg.keydata)); return -EINVAL; } break; default: - fprintf(stderr, "Invalid HMAC identifier %d\n", hmac); + nvme_show_error("Invalid HMAC identifier %d", hmac); return -EINVAL; - break; } - err = base64_decode(cfg.keydata + 16, strlen(cfg.keydata) - 17, - decoded_key); + err = base64_decode(cfg.keydata + 16, strlen(cfg.keydata) - 17, decoded_key); if (err < 0) { - fprintf(stderr, "Base64 decoding failed (%s, error %d)\n", - cfg.keydata + 16, err); + nvme_show_error("Base64 decoding failed (%s, error %d)", cfg.keydata + 16, err); return err; } decoded_len = err; decoded_len -= 4; if (decoded_len != 32 && decoded_len != 48) { - fprintf(stderr, "Invalid key length %d\n", decoded_len); + nvme_show_error("Invalid key length %d", decoded_len); return -EINVAL; } crc = crc32(crc, decoded_key, decoded_len); @@ -9052,31 +9126,27 @@ static int check_tls_key(int argc, char **argv, struct command *command, struct ((u_int32_t)decoded_key[decoded_len + 2] << 16) | ((u_int32_t)decoded_key[decoded_len + 3] << 24); if (key_crc != crc) { - fprintf(stderr, "CRC mismatch (key %08x, crc %08x)\n", - key_crc, crc); + nvme_show_error("CRC mismatch (key %08x, crc %08x)", key_crc, crc); return -EINVAL; } if (cfg.subsysnqn) { if (!cfg.hostnqn) { cfg.hostnqn = nvmf_hostnqn_from_file(); if (!cfg.hostnqn) { - fprintf(stderr, - "Failed to read host NQN\n"); + nvme_show_error("Failed to read host NQN"); return -EINVAL; } } - tls_key = nvme_insert_tls_key(cfg.keyring, cfg.keytype, - cfg.hostnqn, cfg.subsysnqn, hmac, - decoded_key, decoded_len); + tls_key = nvme_insert_tls_key(cfg.keyring, cfg.keytype, cfg.hostnqn, cfg.subsysnqn, + hmac, decoded_key, decoded_len); if (tls_key < 0) { - fprintf(stderr, - "Failed to insert key, error %d\n", errno); + nvme_show_error("Failed to insert key, error %d", errno); return -errno; } - } else - printf("Key is valid (HMAC %d, length %d, CRC %08x)\n", - hmac, decoded_len, crc); + } else { + printf("Key is valid (HMAC %d, length %d, CRC %08x)\n", hmac, decoded_len, crc); + } return 0; } @@ -9113,37 +9183,37 @@ static int show_topology_cmd(int argc, char **argv, struct command *command, str return err; err = flags = validate_output_format(cfg.output_format); - if (flags < 0) + if (err < 0) { + nvme_show_error("Invalid output format"); return err; + } + if (cfg.verbose) flags |= VERBOSE; - if (!strcmp(cfg.ranking, "namespace")) + if (!strcmp(cfg.ranking, "namespace")) { rank = NVME_CLI_TOPO_NAMESPACE; - else if (!strcmp(cfg.ranking, "ctrl")) + } else if (!strcmp(cfg.ranking, "ctrl")) { rank = NVME_CLI_TOPO_CTRL; - else { - fprintf(stderr, "Invalid ranking argument: %s\n", - cfg.ranking); + } else { + nvme_show_error("Invalid ranking argument: %s", cfg.ranking); return -EINVAL; } r = nvme_create_root(stderr, map_log_level(cfg.verbose, false)); if (!r) { - fprintf(stderr, "Failed to create topology root: %s\n", - nvme_strerror(errno)); + nvme_show_error("Failed to create topology root: %s", nvme_strerror(errno)); return -errno; } err = nvme_scan_topology(r, NULL, NULL); if (err < 0) { - fprintf(stderr, "Failed to scan topology: %s\n", - nvme_strerror(errno)); + nvme_show_error("Failed to scan topology: %s", nvme_strerror(errno)); nvme_free_tree(r); return err; } - nvme_show_topology(r, flags, rank); + nvme_show_topology(r, rank, flags); nvme_free_tree(r); return err; @@ -9152,24 +9222,28 @@ static int show_topology_cmd(int argc, char **argv, struct command *command, str static int discover_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Send Get Log Page request to Discovery Controller."; + return nvmf_discover(desc, argc, argv, false); } static int connect_all_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Discover NVMeoF subsystems and connect to them"; + return nvmf_discover(desc, argc, argv, true); } static int connect_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Connect to NVMeoF subsystem"; + return nvmf_connect(desc, argc, argv); } static int disconnect_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Disconnect from NVMeoF subsystem"; + return nvmf_disconnect(desc, argc, argv); } @@ -9177,21 +9251,150 @@ int disconnect_all_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Disconnect from all connected NVMeoF subsystems"; + return nvmf_disconnect_all(desc, argc, argv); } static int config_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Configuration of NVMeoF subsystems"; + return nvmf_config(desc, argc, argv); } static int dim_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { - const char *desc = "Send Discovery Information Management command to a Discovery Controller (DC)"; + const char *desc = + "Send Discovery Information Management command to a Discovery Controller (DC)"; + return nvmf_dim(desc, argc, argv); } +static int nvme_mi(int argc, char **argv, __u8 admin_opcode, const char *desc) +{ + const char *opcode = "opcode (required)"; + const char *data_len = "data I/O length (bytes)"; + const char *nmimt = "nvme-mi message type"; + const char *nmd0 = "nvme management dword 0 value"; + const char *nmd1 = "nvme management dword 1 value"; + const char *input = "data input or output file"; + + int mode = 0644; + void *data = NULL; + int err = 0; + bool send = admin_opcode == nvme_admin_nvme_mi_send ? true : false; + int fd = send ? STDIN_FILENO : STDOUT_FILENO; + int flags = send ? O_RDONLY : O_WRONLY | O_CREAT; + struct nvme_dev *dev; + __u32 result; + bool huge = false; + + struct config { + __u8 opcode; + __u32 namespace_id; + __u32 data_len; + __u32 nmimt; + __u32 nmd0; + __u32 nmd1; + char *input_file; + }; + + struct config cfg = { + .opcode = 0, + .namespace_id = 0, + .data_len = 0, + .nmimt = 0, + .nmd0 = 0, + .nmd1 = 0, + .input_file = "", + }; + + OPT_ARGS(opts) = { + OPT_BYTE("opcode", 'o', &cfg.opcode, opcode), + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_desired), + OPT_UINT("data-len", 'l', &cfg.data_len, data_len), + OPT_UINT("nmimt", 'm', &cfg.nmimt, nmimt), + OPT_UINT("nmd0", '0', &cfg.nmd0, nmd0), + OPT_UINT("nmd1", '1', &cfg.nmd1, nmd1), + OPT_FILE("input-file", 'i', &cfg.input_file, input), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + goto ret; + + if (strlen(cfg.input_file)) { + fd = open(cfg.input_file, flags, mode); + if (fd < 0) { + nvme_show_perror(cfg.input_file); + err = -EINVAL; + goto close_dev; + } + } + + if (cfg.data_len) { + data = nvme_alloc(cfg.data_len, &huge); + if (!data) { + err = -ENOMEM; + goto close_fd; + } + if (send) { + if (read(fd, data, cfg.data_len) < 0) { + err = -errno; + nvme_show_error("failed to read write buffer %s", strerror(errno)); + goto free_data; + } + } + } + + err = nvme_cli_admin_passthru(dev, admin_opcode, 0, 0, cfg.namespace_id, 0, 0, + cfg.nmimt << 11 | 4, cfg.opcode, cfg.nmd0, cfg.nmd1, 0, 0, + cfg.data_len, data, 0, NULL, 0, &result); + if (err < 0) { + nvme_show_error("nmi_recv: %s", nvme_strerror(errno)); + } else if (err) { + nvme_show_status(err); + } else { + printf( + "%s Command is Success and result: 0x%08x (status: 0x%02x, response: 0x%06x)\n", + nvme_cmd_to_string(true, admin_opcode), result, result & 0xff, result >> 8); + if (result & 0xff) + printf("status: %s\n", nvme_mi_status_to_string(result & 0xff)); + if (!send && strlen(cfg.input_file)) { + if (write(fd, (void *)data, cfg.data_len) < 0) + perror("failed to write data buffer"); + } else if (data && !send && !err) { + d((unsigned char *)data, cfg.data_len, 16, 1); + } + } + +free_data: + nvme_free(data, huge); +close_fd: + if (strlen(cfg.input_file)) + close(fd); +close_dev: + dev_close(dev); +ret: + return err; +} + +static int nmi_recv(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = + "Send a NVMe-MI Receive command to the specified device, return results."; + + return nvme_mi(argc, argv, nvme_admin_nvme_mi_recv, desc); +} + +static int nmi_send(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Send a NVMe-MI Send command to the specified device, return results."; + + return nvme_mi(argc, argv, nvme_admin_nvme_mi_send, desc); +} + void register_extension(struct plugin *plugin) { plugin->parent = &nvme; -- cgit v1.2.3