summaryrefslogtreecommitdiffstats
path: root/nvme.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--nvme.c4792
-rw-r--r--nvme.control.in4
2 files changed, 3080 insertions, 1716 deletions
diff --git a/nvme.c b/nvme.c
index 862f9b6..4533413 100644
--- a/nvme.c
+++ b/nvme.c
@@ -23,7 +23,9 @@
/**
* This program uses NVMe IOCTLs to run native nvme commands to a device.
*/
-
+#include "config.h"
+#include "nvme/tree.h"
+#include "nvme/types.h"
#include <errno.h>
#include <getopt.h>
#include <fcntl.h>
@@ -36,31 +38,46 @@
#include <math.h>
#include <dirent.h>
#include <libgen.h>
+#include <zlib.h>
-#ifdef LIBHUGETLBFS
+#ifdef CONFIG_LIBHUGETLBFS
#include <hugetlbfs.h>
#endif
#include <linux/fs.h>
-#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
+#if HAVE_SYS_RANDOM
+ #include <sys/random.h>
+#endif
+
#include "common.h"
+#include "nvme.h"
+#include "libnvme.h"
#include "nvme-print.h"
-#include "nvme-ioctl.h"
-#include "nvme-status.h"
-#include "nvme-lightnvm.h"
#include "plugin.h"
+#include "util/base64.h"
-#include "argconfig.h"
+#include "util/argconfig.h"
#include "fabrics.h"
#define CREATE_CMD
#include "nvme-builtin.h"
+struct feat_cfg {
+ enum nvme_features_id feature_id;
+ __u32 namespace_id;
+ enum nvme_get_features_sel sel;
+ __u32 cdw11;
+ __u8 uuid_index;
+ __u32 data_len;
+ bool raw_binary;
+ bool human_readable;
+};
+
static struct stat nvme_stat;
const char *devicename;
@@ -84,23 +101,12 @@ static struct program nvme = {
.extensions = &builtin,
};
-static __u16 nvme_feat_buf_len[0x100] = {
- [NVME_FEAT_LBA_RANGE] = 4096,
- [NVME_FEAT_AUTO_PST] = 256,
- [NVME_FEAT_HOST_MEM_BUF] = 4096,
- [NVME_FEAT_HOST_ID] = 8,
- [NVME_FEAT_PLM_CONFIG] = 512,
- [NVME_FEAT_TIMESTAMP] = 8,
- [NVME_FEAT_HOST_BEHAVIOR] = 512,
- [NVME_MI_FEAT_CTRL_METADATA] = 4096,
- [NVME_MI_FEAT_NS_METADATA] = 4096,
-};
-
const char *output_format = "Output format: normal|json|binary";
static const char *output_format_no_binary = "Output format: normal|json";
-static void *__nvme_alloc(size_t len, bool *huge)
-{
+static void *mmap_registers(nvme_root_t r, const char *dev);
+
+static void *__nvme_alloc(size_t len, bool *huge) {
void *p;
if (!posix_memalign(&p, getpagesize(), len)) {
@@ -113,11 +119,13 @@ static void *__nvme_alloc(size_t len, bool *huge)
#define HUGE_MIN 0x80000
-#ifdef LIBHUGETLBFS
+#ifdef CONFIG_LIBHUGETLBFS
void nvme_free(void *p, bool huge)
{
- if (huge)
- free_hugepage_region(p);
+ if (huge) {
+ if (p)
+ free_hugepage_region(p);
+ }
else
free(p);
}
@@ -148,6 +156,57 @@ void *nvme_alloc(size_t len, bool *huge)
}
#endif
+const char *nvme_strerror(int errnum)
+{
+ if (errnum >= ENVME_CONNECT_RESOLVE)
+ return nvme_errno_to_string(errnum);
+ return strerror(errnum);
+}
+
+int map_log_level(int verbose, bool quiet)
+{
+ int log_level;
+
+ switch (verbose) {
+ case 0:
+ log_level = LOG_WARNING;
+ break;
+ case 1:
+ log_level = LOG_NOTICE;
+ break;
+ case 2:
+ log_level = LOG_INFO;
+ break;
+ default:
+ log_level = LOG_DEBUG;
+ break;
+ }
+ if (quiet)
+ log_level = LOG_ERR;
+
+ return log_level;
+}
+
+static ssize_t getrandom_bytes(void *buf, size_t buflen)
+{
+#if HAVE_SYS_RANDOM
+ return getrandom(buf, buflen, GRND_NONBLOCK);
+#else
+ ssize_t result;
+ int fd, err = 0;
+
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd < 0)
+ return fd;
+ result = read(fd, buf, buflen);
+ if (result < 0)
+ err = errno;
+ close(fd);
+ errno = err;
+ return result;
+#endif
+}
+
static bool is_chardev(void)
{
return S_ISCHR(nvme_stat.st_mode);
@@ -158,17 +217,12 @@ static bool is_blkdev(void)
return S_ISBLK(nvme_stat.st_mode);
}
-static bool is_ns_chardev(void)
-{
- return !strncmp(devicename, "ng", 2) && S_ISCHR(nvme_stat.st_mode);
-}
-
-static int open_dev(char *dev)
+static int open_dev(char *dev, int flags)
{
int err, fd;
devicename = basename(dev);
- err = open(dev, O_RDONLY);
+ err = open(dev, flags);
if (err < 0)
goto perror;
fd = err;
@@ -199,7 +253,7 @@ static int check_arg_dev(int argc, char **argv)
return 0;
}
-static int get_dev(int argc, char **argv)
+static int get_dev(int argc, char **argv, int flags)
{
int ret;
@@ -207,7 +261,7 @@ static int get_dev(int argc, char **argv)
if (ret)
return ret;
- return open_dev(argv[optind]);
+ return open_dev(argv[optind], flags);
}
int parse_and_open(int argc, char **argv, const char *desc,
@@ -219,13 +273,23 @@ int parse_and_open(int argc, char **argv, const char *desc,
if (ret)
return ret;
- ret = get_dev(argc, argv);
+ ret = get_dev(argc, argv, O_RDONLY);
if (ret < 0)
argconfig_print_help(desc, opts);
return ret;
}
+int open_exclusive(int argc, char **argv, int ignore_exclusive)
+{
+ int flags = O_RDONLY;
+
+ if (!ignore_exclusive)
+ flags |= O_EXCL;
+
+ return get_dev(argc, argv, flags);
+}
+
enum nvme_print_flags validate_output_format(const char *format)
{
if (!format)
@@ -252,15 +316,17 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug
int err = -1, fd;
struct config {
- __u32 namespace_id;
- int raw_binary;
- char *output_format;
- int human_readable;
+ __u32 namespace_id;
+ char *output_format;
+ bool raw_binary;
+ bool human_readable;
};
struct config cfg = {
- .namespace_id = NVME_NSID_ALL,
- .output_format = "normal",
+ .namespace_id = NVME_NSID_ALL,
+ .output_format = "normal",
+ .raw_binary = false,
+ .human_readable = false,
};
@@ -284,18 +350,18 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug
if (cfg.human_readable)
flags |= VERBOSE;
- err = nvme_smart_log(fd, cfg.namespace_id, &smart_log);
+ err = nvme_get_log_smart(fd, cfg.namespace_id, true, &smart_log);
if (!err)
nvme_show_smart_log(&smart_log, cfg.namespace_id, devicename,
flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("smart log");
+ fprintf(stderr, "smart log: %s\n", nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_ana_log(int argc, char **argv, struct command *cmd,
@@ -309,9 +375,10 @@ static int get_ana_log(int argc, char **argv, struct command *cmd,
size_t ana_log_len;
struct nvme_id_ctrl ctrl;
enum nvme_print_flags flags;
+ enum nvme_log_ana_lsp lsp;
struct config {
- char *output_format;
+ char *output_format;
};
struct config cfg = {
@@ -333,69 +400,64 @@ static int get_ana_log(int argc, char **argv, struct command *cmd,
err = nvme_identify_ctrl(fd, &ctrl);
if (err) {
- fprintf(stderr, "ERROR : nvme_identify_ctrl() failed 0x%x\n",
- err);
+ fprintf(stderr, "ERROR : nvme_identify_ctrl() failed: %s\n",
+ nvme_strerror(errno));
goto close_fd;
}
- ana_log_len = sizeof(struct nvme_ana_rsp_hdr) +
+ ana_log_len = sizeof(struct nvme_ana_log) +
le32_to_cpu(ctrl.nanagrpid) * sizeof(struct nvme_ana_group_desc);
if (!(ctrl.anacap & (1 << 6)))
ana_log_len += le32_to_cpu(ctrl.mnan) * sizeof(__le32);
ana_log = malloc(ana_log_len);
if (!ana_log) {
- perror("malloc");
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_fd;
}
- err = nvme_ana_log(fd, ana_log, ana_log_len, groups ? NVME_ANA_LOG_RGO : 0);
+ lsp = groups ? NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY :
+ NVME_LOG_ANA_LSP_RGO_NAMESPACES;
+
+ err = nvme_get_log_ana(fd, lsp, true, 0, ana_log_len, ana_log);
if (!err) {
nvme_show_ana_log(ana_log, devicename, flags, ana_log_len);
} else if (err > 0)
nvme_show_status(err);
else
- perror("ana-log");
+ fprintf(stderr, "ana-log: %s", nvme_strerror(errno));
free(ana_log);
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
-}
-
-__u16 get_feat_buf_len(unsigned short feature) {
- return nvme_feat_buf_len[feature];
+ return err;
}
-static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+static int get_telemetry_log(int argc, char **argv, struct command *cmd,
+ struct plugin *plugin)
{
const char *desc = "Retrieve telemetry log and write to binary file";
const char *fname = "File name to save raw binary, includes header";
const char *hgen = "Have the host tell the controller to generate the report";
const char *cgen = "Gather report generated by the controller.";
const char *dgen = "Pick which telemetry data area to report. Default is 3 to fetch areas 1-3. Valid options are 1, 2, 3, 4.";
- const size_t bs = 512;
- struct nvme_telemetry_log_page_hdr *hdr;
- struct nvme_id_ctrl ctrl;
- size_t full_size, offset = bs;
- int err = -1, fd, output;
- void *page_log;
- __u32 result;
- void *buf = NULL;
+ struct nvme_telemetry_log *log;
+ int err = 0, fd, output;
+ size_t total_size;
+ __u8 *data_ptr = NULL;
+ int data_written = 0, data_remaining = 0;
struct config {
- char *file_name;
- __u32 host_gen;
- int ctrl_init;
- int data_area;
+ char *file_name;
+ __u32 host_gen;
+ bool ctrl_init;
+ int data_area;
};
struct config cfg = {
- .file_name = NULL,
- .host_gen = 1,
- .ctrl_init = 0,
- .data_area = 3,
+ .file_name = NULL,
+ .host_gen = 1,
+ .ctrl_init = false,
+ .data_area = 3,
};
OPT_ARGS(opts) = {
@@ -412,135 +474,68 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct
if (!cfg.file_name) {
fprintf(stderr, "Please provide an output file!\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
cfg.host_gen = !!cfg.host_gen;
- hdr = malloc(bs);
- page_log = malloc(bs);
- if (!hdr || !page_log) {
- perror("failed to allocate buf for log\n");
- errno = ENOMEM;
- err = -1;
- goto free_mem;
- }
- memset(hdr, 0, bs);
-
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",
cfg.file_name, strerror(errno));
err = output;
- goto free_mem;
+ goto close_fd;
}
- err = nvme_get_telemetry_log(fd, hdr, cfg.host_gen, cfg.ctrl_init, bs, 0);
- if (err < 0)
- perror("get-telemetry-log");
- else if (err > 0) {
- nvme_show_status(err);
- fprintf(stderr, "Failed to acquire telemetry header %d!\n", err);
- goto close_output;
- }
+ if (cfg.ctrl_init)
+ err = nvme_get_ctrl_telemetry(fd, true, &log, cfg.data_area, &total_size);
+ else if (cfg.host_gen)
+ err = nvme_get_new_host_telemetry(fd, &log, cfg.data_area, &total_size);
+ else
+ err = nvme_get_host_telemetry(fd, &log, cfg.data_area, &total_size);
- err = write(output, (void *) hdr, bs);
- if (err != bs) {
- fprintf(stderr, "Failed to flush all data to file!\n");
+ if (err < 0) {
+ fprintf(stderr, "get-telemetry-log: %s\n",
+ nvme_strerror(errno));
+ } else if (err > 0) {
+ nvme_show_status(err);
+ fprintf(stderr, "Failed to acquire telemetry log %d!\n", err);
goto close_output;
}
- switch (cfg.data_area) {
- case 1:
- full_size = (le16_to_cpu(hdr->dalb1) * bs) + offset;
- break;
- case 2:
- full_size = (le16_to_cpu(hdr->dalb2) * bs) + offset;
- break;
- case 3:
- full_size = (le16_to_cpu(hdr->dalb3) * bs) + offset;
- break;
- case 4:
- err = nvme_identify_ctrl(fd, &ctrl);
- if (err) {
- perror("identify-ctrl");
- goto close_output;
- }
-
- if (posix_memalign(&buf, getpagesize(), nvme_feat_buf_len[NVME_FEAT_HOST_BEHAVIOR])) {
- fprintf(stderr, "can not allocate feature payload\n");
- errno = ENOMEM;
- err = -1;
- goto close_output;
- }
- memset(buf, 0, nvme_feat_buf_len[NVME_FEAT_HOST_BEHAVIOR]);
-
- err = nvme_get_feature(fd, NVME_NSID_ALL, NVME_FEAT_HOST_BEHAVIOR, 0, 0,
- 0, nvme_feat_buf_len[NVME_FEAT_HOST_BEHAVIOR], buf, &result);
- if (err > 0) {
- nvme_show_status(err);
- } else if (err < 0) {
- perror("get-feature");
- } else {
- if ((ctrl.lpa & 0x40)) {
- if (((unsigned char *)buf)[1] == 1)
- full_size = (le32_to_cpu(hdr->dalb4) * bs) + offset;
- else {
- fprintf(stderr, "Data area 4 unsupported, Host Behavior Support ETDAS not set to 1\n");
- errno = EINVAL;
- err = -1;
- }
- } else {
- fprintf(stderr, "Data area 4 unsupported, bit 6 of Log Page Attributes not set\n");
- errno = EINVAL;
- err = -1;
- }
- }
- free(buf);
- if (err)
- goto close_output;
- break;
- default:
- fprintf(stderr, "Invalid data area requested\n");
- errno = EINVAL;
- err = -1;
- goto close_output;
- }
+ data_written = 0;
+ data_remaining = total_size;
+ data_ptr = (__u8 *)log;
- /*
- * Continuously pull data until the offset hits the end of the last
- * block.
- */
- while (offset != full_size) {
- err = nvme_get_telemetry_log(fd, page_log, 0, cfg.ctrl_init, bs, offset);
- if (err < 0) {
- perror("get-telemetry-log");
+ while (data_remaining) {
+ data_written = write(output, data_ptr, data_remaining);
+ if (data_written < 0) {
+ data_remaining = data_written;
break;
- } else if (err > 0) {
- fprintf(stderr, "Failed to acquire full telemetry log!\n");
- nvme_show_status(err);
+ } else if (data_written <= data_remaining) {
+ data_remaining -= data_written;
+ data_ptr += data_written;
+ } else {
+ /* Unexpected overwrite */
+ fprintf(stderr, "Failure: Unexpected telemetry log overwrite - data_remaining = 0x%x, data_written = 0x%x\n",
+ data_remaining, data_written);
break;
}
+ }
- err = write(output, (void *) page_log, bs);
- if (err != bs) {
- fprintf(stderr, "Failed to flush all data to file!\n");
- break;
- }
- err = 0;
- offset += bs;
+ if (fsync(output) < 0) {
+ fprintf(stderr, "ERROR : %s: : fsync : %s\n", __func__, strerror(errno));
+ return -1;
}
+ free(log);
+
close_output:
close(output);
-free_mem:
- free(hdr);
- free(page_log);
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_endurance_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -549,16 +544,16 @@ static int get_endurance_log(int argc, char **argv, struct command *cmd, struct
const char *desc = "Retrieves endurance groups log page and prints the log.";
const char *group_id = "The endurance group identifier";
enum nvme_print_flags flags;
- int err = -1, fd;
+ int err, fd;
struct config {
- char *output_format;
- __u16 group_id;
+ char *output_format;
+ __u16 group_id;
};
struct config cfg = {
- .output_format = "normal",
- .group_id = 0,
+ .output_format = "normal",
+ .group_id = 0,
};
OPT_ARGS(opts) = {
@@ -575,17 +570,38 @@ static int get_endurance_log(int argc, char **argv, struct command *cmd, struct
if (flags < 0)
goto close_fd;
- err = nvme_endurance_log(fd, cfg.group_id, &endurance_log);
+ err = nvme_get_log_endurance_group(fd, cfg.group_id, &endurance_log);
if (!err)
nvme_show_endurance_log(&endurance_log, cfg.group_id, devicename, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("endurance log");
+ fprintf(stderr, "endurance log: %s\n", nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
+}
+
+void collect_effects_log(int fd, enum nvme_csi csi, struct list_head *list, int flags)
+{
+ int err;
+ nvme_effects_log_node_t *node = malloc(sizeof(nvme_effects_log_node_t));
+ if (!node)
+ return;
+ node->csi = csi;
+
+ err = nvme_get_log_cmd_effects(fd, csi, &node->effects);
+ if (!err) {
+ list_add(list, &node->node);
+ return;
+ }
+ else if (err > 0)
+ nvme_show_status(err);
+ else
+ fprintf(stderr, "effects log page: %s\n", nvme_strerror(errno));
+
+ free(node);
}
static int get_effects_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -593,25 +609,34 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl
const char *desc = "Retrieve command effects log page and print the table.";
const char *raw = "show log in binary format";
const char *human_readable = "show log in readable format";
- struct nvme_effects_log_page effects;
+ const char *csi = "";
+ struct list_head log_pages;
+ nvme_effects_log_node_t *node;
+
+ void *bar = NULL;
int err = -1, fd;
enum nvme_print_flags flags;
struct config {
- int raw_binary;
- int human_readable;
- char *output_format;
+ char *output_format;
+ bool human_readable;
+ bool raw_binary;
+ int csi;
};
struct config cfg = {
- .output_format = "normal",
+ .output_format = "normal",
+ .human_readable = false,
+ .raw_binary = false,
+ .csi = -1,
};
OPT_ARGS(opts) = {
OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable),
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
+ OPT_INT("csi", 'c', &cfg.csi, csi),
OPT_END()
};
@@ -627,17 +652,52 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl
if (cfg.human_readable)
flags |= VERBOSE;
- err = nvme_effects_log(fd, &effects);
- if (!err)
- nvme_show_effects_log(&effects, flags);
- else if (err > 0)
- nvme_show_status(err);
- else
- perror("effects log page");
+ list_head_init(&log_pages);
+
+ if (cfg.csi < 0) {
+ nvme_root_t nvme_root;
+ uint64_t cap;
+ int nvme_command_set_supported;
+ int other_command_sets_supported;
+ nvme_root = nvme_scan(NULL);
+ bar = mmap_registers(nvme_root, devicename);
+ nvme_free_tree(nvme_root);
+
+ if (!bar) {
+ goto close_fd;
+ }
+ cap = mmio_read64(bar + NVME_REG_CAP);
+ munmap(bar, getpagesize());
+
+ nvme_command_set_supported = NVME_CAP_CSS(cap) & NVME_CAP_CSS_NVM;
+ other_command_sets_supported = NVME_CAP_CSS(cap) & NVME_CAP_CSS_CSI;
+
+
+ if (nvme_command_set_supported) {
+ collect_effects_log(fd, NVME_CSI_NVM, &log_pages, flags);
+ }
+
+ if (other_command_sets_supported) {
+ collect_effects_log(fd, NVME_CSI_ZNS, &log_pages, flags);
+ }
+
+ nvme_print_effects_log_pages(&log_pages, flags);
+
+ }
+ else {
+ collect_effects_log(fd, cfg.csi, &log_pages, flags);
+ nvme_print_effects_log_pages(&log_pages, flags);
+ }
+
+
close_fd:
+ while ((node = list_pop(&log_pages, nvme_effects_log_node_t, node))) {
+ free(node);
+ }
+
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_supported_log_pages(int argc, char **argv, struct command *cmd,
@@ -645,18 +705,19 @@ static int get_supported_log_pages(int argc, char **argv, struct command *cmd,
{
const char *desc = "Retrieve supported logs and print the table.";
const char *verbose = "Increase output verbosity";
- struct nvme_support_log_pages supports;
+ struct nvme_supported_log_pages supports;
int err = -1, fd;
enum nvme_print_flags flags;
struct config {
- int verbose;
- char *output_format;
+ char *output_format;
+ bool verbose;
};
struct config cfg = {
- .output_format = "normal",
+ .output_format = "normal",
+ .verbose = false
};
OPT_ARGS(opts) = {
@@ -676,18 +737,19 @@ static int get_supported_log_pages(int argc, char **argv, struct command *cmd,
if (cfg.verbose)
flags |= VERBOSE;
- err = nvme_supported_log(fd, &supports);
+ err = nvme_get_log_supported_log_pages(fd, false, &supports);
if (!err)
nvme_show_supported_log(&supports, devicename, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("supported log pages");
+ fprintf(stderr, "supported log pages: %s",
+ nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -703,14 +765,15 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug
int err = -1, fd;
struct config {
- __u32 log_entries;
- int raw_binary;
- char *output_format;
+ __u32 log_entries;
+ char *output_format;
+ bool raw_binary;
};
struct config cfg = {
- .log_entries = 64,
- .output_format = "normal",
+ .log_entries = 64,
+ .output_format = "normal",
+ .raw_binary = false,
};
OPT_ARGS(opts) = {
@@ -732,7 +795,6 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug
if (!cfg.log_entries) {
fprintf(stderr, "non-zero log-entries is required param\n");
- errno = EINVAL;
err = -1;
goto close_fd;
}
@@ -743,7 +805,6 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug
goto close_fd;
} else if (err) {
fprintf(stderr, "could not identify controller\n");
- errno = ENODEV;
err = -1;
goto close_fd;
}
@@ -751,13 +812,11 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug
cfg.log_entries = min(cfg.log_entries, ctrl.elpe + 1);
err_log = calloc(cfg.log_entries, sizeof(struct nvme_error_log_page));
if (!err_log) {
- perror("could not alloc buffer for error log\n");
- errno = ENOMEM;
err = -1;
goto close_fd;
}
- err = nvme_error_log(fd, cfg.log_entries, err_log);
+ err = nvme_get_log_error(fd, cfg.log_entries, true, err_log);
if (!err)
nvme_show_error_log(err_log, cfg.log_entries, devicename, flags);
else if (err > 0)
@@ -768,7 +827,7 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -776,17 +835,18 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin
const char *desc = "Retrieve the firmware log for the "\
"specified device in either decoded format (default) or binary.";
const char *raw = "use binary output";
- struct nvme_firmware_log_page fw_log;
+ struct nvme_firmware_slot fw_log;
enum nvme_print_flags flags;
- int err = -1, fd;
+ int err, fd;
struct config {
- int raw_binary;
- char *output_format;
+ char *output_format;
+ bool raw_binary;
};
struct config cfg = {
- .output_format = "normal",
+ .output_format = "normal",
+ .raw_binary = false,
};
OPT_ARGS(opts) = {
@@ -805,36 +865,37 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin
if (cfg.raw_binary)
flags = BINARY;
- err = nvme_fw_log(fd, &fw_log);
+ err = nvme_get_log_fw_slot(fd, true, &fw_log);
if (!err)
nvme_show_fw_log(&fw_log, devicename, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("fw log");
+ fprintf(stderr, "fw log: %s\n", nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_changed_ns_list_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
- struct nvme_changed_ns_list_log changed_ns_list_log;
const char *desc = "Retrieve Changed Namespaces log for the given device "\
"in either decoded format "\
"(default) or binary.";
const char *raw = "output in binary format";
+ struct nvme_ns_list changed_ns_list_log;
enum nvme_print_flags flags;
- int err = -1, fd;
+ int err, fd;
struct config {
- int raw_binary;
- char *output_format;
+ char *output_format;
+ bool raw_binary;
};
struct config cfg = {
- .output_format = "normal",
+ .output_format = "normal",
+ .raw_binary = false,
};
OPT_ARGS(opts) = {
@@ -853,18 +914,19 @@ static int get_changed_ns_list_log(int argc, char **argv, struct command *cmd, s
if (cfg.raw_binary)
flags = BINARY;
- err = nvme_changed_ns_list_log(fd, &changed_ns_list_log);
+ err = nvme_get_log_changed_ns_list(fd, true, &changed_ns_list_log);
if (!err)
nvme_show_changed_ns_list_log(&changed_ns_list_log, devicename,
flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("changed ns list log");
+ fprintf(stderr, "changed ns list log: %s\n",
+ nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_pred_lat_per_nvmset_log(int argc, char **argv,
@@ -875,25 +937,26 @@ static int get_pred_lat_per_nvmset_log(int argc, char **argv,
"format(default),json or binary.";
const char *nvmset_id = "NVM Set Identifier";
const char *raw = "use binary output";
- struct nvme_predlat_per_nvmset_log_page plpns_log;
+ struct nvme_nvmset_predictable_lat_log plpns_log;
enum nvme_print_flags flags;
- int err = -1, fd;
+ int err, fd;
struct config {
- __u16 nvmset_id;
- char *output_format;
- int raw_binary;
+ __u16 nvmset_id;
+ char *output_format;
+ bool raw_binary;
};
struct config cfg = {
- .nvmset_id = 1,
- .output_format = "normal",
+ .nvmset_id = 1,
+ .output_format = "normal",
+ .raw_binary = false,
};
OPT_ARGS(opts) = {
- OPT_SHRT("nvmset-id", 'i', &cfg.nvmset_id, nvmset_id),
+ OPT_SHRT("nvmset-id", 'i', &cfg.nvmset_id, nvmset_id),
OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
- OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
+ OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
OPT_END()
};
@@ -907,20 +970,20 @@ static int get_pred_lat_per_nvmset_log(int argc, char **argv,
if (cfg.raw_binary)
flags = BINARY;
- err = nvme_predictable_latency_per_nvmset_log(fd,
- cfg.nvmset_id, &plpns_log);
+ err = nvme_get_log_predictable_lat_nvmset(fd, cfg.nvmset_id, &plpns_log);
if (!err)
nvme_show_predictable_latency_per_nvmset(&plpns_log,
cfg.nvmset_id, devicename, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("predictable latency per nvm set");
+ fprintf(stderr, "predictable latency per nvm set: %s\n",
+ nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_pred_lat_event_agg_log(int argc, char **argv,
@@ -934,23 +997,24 @@ static int get_pred_lat_event_agg_log(int argc, char **argv,
"log Entries list";
const char *rae = "Retain an Asynchronous Event";
const char *raw = "use binary output";
- void *pea_log;
- struct nvme_id_ctrl ctrl;
enum nvme_print_flags flags;
- int err = -1, fd;
+ struct nvme_id_ctrl ctrl;
__u32 log_size;
+ void *pea_log;
+ int err, fd;
struct config {
- __u64 log_entries;
- bool rae;
- char *output_format;
- int raw_binary;
+ __u64 log_entries;
+ bool rae;
+ char *output_format;
+ bool raw_binary;
};
struct config cfg = {
- .log_entries = 2044,
- .rae = false,
- .output_format = "normal",
+ .log_entries = 2044,
+ .rae = false,
+ .output_format = "normal",
+ .raw_binary = false,
};
OPT_ARGS(opts) = {
@@ -973,14 +1037,14 @@ static int get_pred_lat_event_agg_log(int argc, char **argv,
if (!cfg.log_entries) {
fprintf(stderr, "non-zero log-entries is required param\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
err = nvme_identify_ctrl(fd, &ctrl);
if (err < 0) {
- perror("identify controller");
+ fprintf(stderr, "identify controller: %s\n",
+ nvme_strerror(errno));
goto close_fd;
} else if (err) {
nvme_show_status(err);
@@ -991,28 +1055,25 @@ static int get_pred_lat_event_agg_log(int argc, char **argv,
log_size = sizeof(__u64) + cfg.log_entries * sizeof(__u16);
pea_log = calloc(log_size, 1);
if (!pea_log) {
- perror("could not alloc buffer for predictable " \
- "latency event agggregate log entries\n");
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_fd;
}
- err = nvme_predictable_latency_event_agg_log(fd, pea_log, cfg.rae,
- log_size);
+ err = nvme_get_log_predictable_lat_event(fd, cfg.rae, 0, log_size, pea_log);
if (!err)
nvme_show_predictable_latency_event_agg_log(pea_log, cfg.log_entries,
log_size, devicename, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("predictable latency event gggregate log page");
+ fprintf(stderr, "predictable latency event aggregate log page: %s",
+ nvme_strerror(errno));
free(pea_log);
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_persistent_event_log(int argc, char **argv,
@@ -1025,28 +1086,29 @@ static int get_persistent_event_log(int argc, char **argv,
" processing this persistent log page command.";
const char *log_len = "number of bytes to retrieve";
const char *raw = "use binary output";
- void *pevent_log_info;
- struct nvme_persistent_event_log_head *pevent_log_head, *collected_head;
+ struct nvme_persistent_event_log *pevent, *pevent_collected;
enum nvme_print_flags flags;
- int err = -1, fd;
+ void *pevent_log_info;
+ int err, fd;
bool huge;
struct config {
- __u8 action;
- __u32 log_len;
- int raw_binary;
- char *output_format;
+ __u8 action;
+ __u32 log_len;
+ char *output_format;
+ bool raw_binary;
};
struct config cfg = {
- .action = 0xff,
- .log_len = 0,
- .output_format = "normal",
+ .action = 0xff,
+ .log_len = 0,
+ .output_format = "normal",
+ .raw_binary = false,
};
OPT_ARGS(opts) = {
OPT_BYTE("action", 'a', &cfg.action, action),
- OPT_UINT("log_len", 'l', &cfg.log_len, log_len),
+ OPT_UINT("log_len", 'l', &cfg.log_len, log_len),
OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
OPT_END()
@@ -1062,42 +1124,33 @@ static int get_persistent_event_log(int argc, char **argv,
if (cfg.raw_binary)
flags = BINARY;
- if (cfg.action > 3) {
- fprintf(stderr, "invalid action field: %u\n", cfg.action);
- errno = EINVAL;
- err = -1;
- goto close_fd;
- }
-
- pevent_log_head = calloc(sizeof(*pevent_log_head), 1);
- if (!pevent_log_head) {
- perror("could not alloc buffer for persistent " \
- "event log header\n");
- errno = ENOMEM;
- err = -1;
+ pevent = calloc(sizeof(*pevent), 1);
+ if (!pevent) {
+ err = -ENOMEM;
goto close_fd;
}
- err = nvme_persistent_event_log(fd, cfg.action,
- sizeof(*pevent_log_head), pevent_log_head);
+ err = nvme_get_log_persistent_event(fd, cfg.action,
+ sizeof(*pevent), pevent);
if (err < 0) {
- perror("persistent event log");
- goto free_head;
+ fprintf(stderr, "persistent event log: %s\n",
+ nvme_strerror(errno));
+ goto free_pevent;
} else if (err) {
nvme_show_status(err);
- goto free_head;
+ goto free_pevent;
}
if (cfg.action == NVME_PEVENT_LOG_RELEASE_CTX) {
printf("Releasing Persistent Event Log Context\n");
- goto free_head;
+ goto free_pevent;
}
if (!cfg.log_len && cfg.action != NVME_PEVENT_LOG_EST_CTX_AND_READ) {
- cfg.log_len = le64_to_cpu(pevent_log_head->tll);
+ cfg.log_len = le64_to_cpu(pevent->tll);
} else if (!cfg.log_len && cfg.action == NVME_PEVENT_LOG_EST_CTX_AND_READ) {
printf("Establishing Persistent Event Log Context\n");
- goto free_head;
+ goto free_pevent;
}
/*
@@ -1112,45 +1165,45 @@ static int get_persistent_event_log(int argc, char **argv,
pevent_log_info = nvme_alloc(cfg.log_len, &huge);
if (!pevent_log_info) {
- perror("could not alloc buffer for persistent event log page\n");
- errno = ENOMEM;
- err = -1;
- goto free_head;
+ err = -ENOMEM;
+ goto free_pevent;
}
- err = nvme_persistent_event_log(fd, cfg.action,
+ err = nvme_get_log_persistent_event(fd, cfg.action,
cfg.log_len, pevent_log_info);
if (!err) {
- err = nvme_persistent_event_log(fd, cfg.action,
- sizeof(*pevent_log_head), pevent_log_head);
+ err = nvme_get_log_persistent_event(fd, cfg.action,
+ sizeof(*pevent), pevent);
if (err < 0) {
- perror("persistent event log");
+ fprintf(stderr, "persistent event log: %s\n",
+ nvme_strerror(errno));
goto free;
} else if (err) {
nvme_show_status(err);
goto free;
}
- collected_head = pevent_log_info;
- if(collected_head->gen_number != pevent_log_head->gen_number) {
+ 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 reiquired\n");
goto free;
}
+
nvme_show_persistent_event_log(pevent_log_info, cfg.action,
cfg.log_len, devicename, flags);
- }
- else if (err > 0)
+ } else if (err > 0)
nvme_show_status(err);
else
- perror("persistent event log");
+ fprintf(stderr, "persistent event log: %s\n",
+ nvme_strerror(errno));
free:
nvme_free(pevent_log_info, huge);
-free_head:
- free(pevent_log_head);
+free_pevent:
+ free(pevent);
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_endurance_event_agg_log(int argc, char **argv,
@@ -1167,20 +1220,21 @@ static int get_endurance_event_agg_log(int argc, char **argv,
void *endurance_log;
struct nvme_id_ctrl ctrl;
enum nvme_print_flags flags;
- int err = -1, fd;
+ int err, fd;
__u32 log_size;
struct config {
- __u64 log_entries;
- bool rae;
- char *output_format;
- int raw_binary;
+ __u64 log_entries;
+ bool rae;
+ char *output_format;
+ bool raw_binary;
};
struct config cfg = {
- .log_entries = 2044,
- .rae = false,
- .output_format = "normal",
+ .log_entries = 2044,
+ .rae = false,
+ .output_format = "normal",
+ .raw_binary = false,
};
OPT_ARGS(opts) = {
@@ -1203,19 +1257,18 @@ static int get_endurance_event_agg_log(int argc, char **argv,
if (!cfg.log_entries) {
fprintf(stderr, "non-zero log-entries is required param\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
err = nvme_identify_ctrl(fd, &ctrl);
if (err < 0) {
- perror("identify controller");
+ fprintf(stderr, "identify controller: %s\n",
+ nvme_strerror(errno));
goto close_fd;
} else if (err) {
fprintf(stderr, "could not identify controller\n");
- errno = ENODEV;
- err = -1;
+ err = -ENODEV;
goto close_fd;
}
@@ -1223,28 +1276,25 @@ static int get_endurance_event_agg_log(int argc, char **argv,
log_size = sizeof(__u64) + cfg.log_entries * sizeof(__u16);
endurance_log = calloc(log_size, 1);
if (!endurance_log) {
- perror("could not alloc buffer for endurance group" \
- " event agggregate log entries\n");
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_fd;
}
- err = nvme_endurance_group_event_agg_log(fd, endurance_log, cfg.rae,
- log_size);
+ err = nvme_get_log_endurance_grp_evt(fd, cfg.rae, 0, log_size, endurance_log);
if (!err)
nvme_show_endurance_group_event_agg_log(endurance_log, cfg.log_entries,
log_size, devicename, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("endurance group event aggregate log page");
+ fprintf(stderr, "endurance group event aggregate log page: %s\n",
+ nvme_strerror(errno));
free(endurance_log);
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_lba_status_log(int argc, char **argv,
@@ -1256,17 +1306,17 @@ static int get_lba_status_log(int argc, char **argv,
const char *rae = "Retain an Asynchronous Event";
void *lab_status;
enum nvme_print_flags flags;
- int err = -1, fd;
+ int err, fd;
__u32 lslplen;
struct config {
- bool rae;
- char *output_format;
+ bool rae;
+ char *output_format;
};
struct config cfg = {
- .rae = false,
- .output_format = "normal",
+ .rae = false,
+ .output_format = "normal",
};
OPT_ARGS(opts) = {
@@ -1283,9 +1333,10 @@ static int get_lba_status_log(int argc, char **argv,
if (flags < 0)
goto close_fd;
- err = nvme_lba_status_log(fd, &lslplen, true, sizeof(__u32));
+ err = nvme_get_log_lba_status(fd, true, 0, sizeof(__u32), &lslplen);
if (err < 0) {
- perror("lba status log page");
+ fprintf(stderr, "lba status log page: %s\n",
+ nvme_strerror(errno));
goto close_fd;
} else if (err) {
nvme_show_status(err);
@@ -1294,25 +1345,24 @@ static int get_lba_status_log(int argc, char **argv,
lab_status = calloc(lslplen, 1);
if (!lab_status) {
- perror("could not alloc buffer for lba status log");
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_fd;
}
- err = nvme_lba_status_log(fd, lab_status, cfg.rae, lslplen);
+ err = nvme_get_log_lba_status(fd, cfg.rae, 0, lslplen, lab_status);
if (!err)
nvme_show_lba_status_log(lab_status, lslplen, devicename, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("lba status log page");
+ fprintf(stderr, "lba status log page: %s\n",
+ nvme_strerror(errno));
free(lab_status);
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_resv_notif_log(int argc, char **argv,
@@ -1323,16 +1373,16 @@ static int get_resv_notif_log(int argc, char **argv,
"log page and prints it, for the given " \
"device in either decoded format(default), " \
"json or binary.";
- struct nvme_resv_notif_log resv;
+ struct nvme_resv_notification_log resv;
enum nvme_print_flags flags;
- int err = -1, fd;
+ int err, fd;
struct config {
- char *output_format;
+ char *output_format;
};
struct config cfg = {
- .output_format = "normal",
+ .output_format = "normal",
};
OPT_ARGS(opts) = {
@@ -1348,18 +1398,19 @@ static int get_resv_notif_log(int argc, char **argv,
if (flags < 0)
goto close_fd;
- err = nvme_resv_notif_log(fd, &resv);
+ err = nvme_get_log_reservation(fd, true, &resv);
if (!err)
nvme_show_resv_notif_log(&resv, devicename, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("resv notifi log");
+ fprintf(stderr, "resv notifi log: %s\n",
+ nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
@@ -1371,22 +1422,22 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct
"json or binary.";
const char *lsp = "log specific field";
const char *fname = "boot partition data output file name";
- struct nvme_boot_part_hdr boot;
+ struct nvme_boot_partition boot;
__u8 *bp_log;
enum nvme_print_flags flags;
int err = -1, fd = 0, output = 0;
__u32 bpsz = 0;
struct config {
- __u8 lsp;
- char *output_format;
- char *file_name;
+ __u8 lsp;
+ char *file_name;
+ char *output_format;
};
struct config cfg = {
- .lsp = 0,
- .file_name = NULL,
- .output_format = "normal",
+ .lsp = 0,
+ .output_format = "normal",
+ .file_name = NULL,
};
OPT_ARGS(opts) = {
@@ -1406,14 +1457,12 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct
if (!cfg.file_name) {
fprintf(stderr, "Please provide an output file!\n");
- errno = EINVAL;
err = -1;
goto close_fd;
}
if (cfg.lsp > 128) {
fprintf(stderr, "invalid lsp param: %u\n", cfg.lsp);
- errno = EINVAL;
err = -1;
goto close_fd;
}
@@ -1426,9 +1475,11 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct
goto close_fd;
}
- err = nvme_boot_part_log(fd, cfg.lsp, &boot, sizeof(boot));
+ err = nvme_get_log_boot_partition(fd, false, cfg.lsp,
+ sizeof(boot), &boot);
if (err < 0) {
- perror("boot partition log");
+ fprintf(stderr, "boot partition log: %s\n",
+ nvme_strerror(errno));
goto close_output;
} else if (err) {
nvme_show_status(err);
@@ -1438,19 +1489,20 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct
bpsz = (boot.bpinfo & 0x7fff) * 128 * 1024;
bp_log = calloc(sizeof(boot) + bpsz, 1);
if (!bp_log) {
- perror("could not alloc buffer for boot partition log");
- errno = ENOMEM;
err = -1;
goto close_output;
}
- err = nvme_boot_part_log(fd, cfg.lsp, &bp_log, sizeof(boot) + bpsz);
+ err = nvme_get_log_boot_partition(fd, false, cfg.lsp,
+ sizeof(boot) + bpsz,
+ (struct nvme_boot_partition *)bp_log);
if (!err)
nvme_show_boot_part_log(&bp_log, devicename, flags, sizeof(boot) + bpsz);
else if (err > 0)
nvme_show_status(err);
else
- perror("boot partition log");
+ fprintf(stderr, "boot partition log: %s\n",
+ nvme_strerror(errno));
err = write(output, (void *) bp_log + sizeof(boot), bpsz);
if (err != bpsz) {
@@ -1467,7 +1519,118 @@ close_output:
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
+}
+
+static int get_media_unit_stat_log(int argc, char **argv, struct command *cmd,
+ struct plugin *plugin)
+{
+ const char *desc = "Retrieve the configuration and wear of media units and print it";
+ const char *domainid = "Domain Identifier";
+ const char *raw = "use binary output";
+ struct nvme_media_unit_stat_log mus;
+
+ int err = -1, fd;
+ enum nvme_print_flags flags;
+
+ struct config {
+ __u16 domainid;
+ char *output_format;
+ bool raw_binary;
+ };
+
+ struct config cfg = {
+ .domainid = 0,
+ .output_format = "normal",
+ .raw_binary = false,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_UINT("domain-id", 'd', &cfg.domainid, domainid),
+ OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+ OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
+ OPT_END()
+ };
+
+ err = fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ goto ret;
+
+ err = flags = validate_output_format(cfg.output_format);
+ if (flags < 0)
+ goto close_fd;
+
+ if (cfg.raw_binary)
+ flags = BINARY;
+
+ err = nvme_get_log_media_unit_stat(fd, cfg.domainid, &mus);
+ if (!err)
+ nvme_show_media_unit_stat_log(&mus, flags);
+ else if (err > 0)
+ nvme_show_status(err);
+ else
+ fprintf(stderr, "media unit status log: %s\n",
+ nvme_strerror(errno));
+
+close_fd:
+ close(fd);
+ret:
+ return err;
+}
+
+static int get_supp_cap_config_log(int argc, char **argv, struct command *cmd,
+ struct plugin *plugin)
+{
+ const char *desc = "Retrieve the list of Supported Capacity Configuration Descriptors";
+ const char *domainid = "Domain Identifier";
+ const char *raw = "use binary output";
+ struct nvme_supported_cap_config_list_log cap_log;
+
+ int err = -1, fd;
+ enum nvme_print_flags flags;
+
+ struct config {
+ __u16 domainid;
+ char *output_format;
+ bool raw_binary;
+ };
+
+ struct config cfg = {
+ .domainid = 0,
+ .output_format = "normal",
+ .raw_binary = false,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_UINT("domain-id", 'd', &cfg.domainid, domainid),
+ OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+ OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
+ OPT_END()
+ };
+
+ err = fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ goto ret;
+
+ err = flags = validate_output_format(cfg.output_format);
+ if (flags < 0)
+ goto close_fd;
+
+ if (cfg.raw_binary)
+ flags = BINARY;
+
+ err = nvme_get_log_support_cap_config_list(fd, cfg.domainid, &cap_log);
+ if (!err)
+ nvme_show_supported_cap_config_log(&cap_log, flags);
+ else if (err > 0)
+ nvme_show_status(err);
+ else
+ perror("supported capacity configuration list log");
+
+close_fd:
+ close(fd);
+ret:
+ return err;
}
static int get_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -1487,35 +1650,37 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl
const char *uuid_index = "UUID index";
const char *csi = "command set identifier";
const char *offset_type = "offset type";
- int err = -1, fd;
+ int err, fd;
unsigned char *log;
struct config {
- __u16 lsi;
- __u32 namespace_id;
- __u8 log_id;
- __u32 log_len;
- __u32 aen;
- __u64 lpo;
- __u8 lsp;
- __u8 uuid_index;
- __u8 csi;
- int ot;
- int rae;
- int raw_binary;
+ __u32 namespace_id;
+ __u8 log_id;
+ __u32 log_len;
+ __u32 aen;
+ __u64 lpo;
+ __u8 lsp;
+ __u16 lsi;
+ bool rae;
+ __u8 uuid_index;
+ bool raw_binary;
+ __u8 csi;
+ bool ot;
};
struct config cfg = {
- .namespace_id = NVME_NSID_ALL,
- .log_id = 0xff,
- .log_len = 0,
- .lpo = NVME_NO_LOG_LPO,
- .lsp = NVME_NO_LOG_LSP,
- .lsi = 0,
- .rae = 0,
- .uuid_index = 0,
- .csi = 0,
- .ot = 0,
+ .namespace_id = NVME_NSID_ALL,
+ .log_id = 0xff,
+ .log_len = 0,
+ .aen = 0,
+ .lpo = NVME_LOG_LPO_NONE,
+ .lsp = NVME_LOG_LSP_NONE,
+ .lsi = NVME_LOG_LSI_NONE,
+ .rae = false,
+ .uuid_index = NVME_UUID_NONE,
+ .raw_binary = false,
+ .csi = NVME_CSI_NVM,
+ .ot = false,
};
OPT_ARGS(opts) = {
@@ -1528,9 +1693,9 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl
OPT_SHRT("lsi", 'S', &cfg.lsi, lsi),
OPT_FLAG("rae", 'r', &cfg.rae, rae),
OPT_BYTE("uuid-index", 'U', &cfg.uuid_index, uuid_index),
+ OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
OPT_BYTE("csi", 'y', &cfg.csi, csi),
OPT_FLAG("ot", 'O', &cfg.ot, offset_type),
- OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
OPT_END()
};
@@ -1544,23 +1709,20 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl
}
if (!cfg.log_len) {
- fprintf(stderr, "non-zero log-len is required param\n");
- errno = EINVAL;
- err = -1;
+ perror("non-zero log-len is required param\n");
+ err = -EINVAL;
goto close_fd;
}
if (cfg.lsp > 128) {
- fprintf(stderr, "invalid lsp param: %u\n", cfg.lsp);
- errno = EINVAL;
- err = -1;
+ perror("invalid lsp param\n");
+ err = -EINVAL;
goto close_fd;
}
if (cfg.uuid_index > 128) {
- fprintf(stderr, "invalid uuid index param: %u\n", cfg.uuid_index);
- errno = EINVAL;
- err = -1;
+ perror("invalid uuid index param\n");
+ err = -EINVAL;
goto close_fd;
}
@@ -1571,27 +1733,42 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl
goto close_fd;
}
- err = nvme_get_log14(fd, cfg.namespace_id, cfg.log_id,
- cfg.lsp, cfg.lpo, cfg.lsi, cfg.rae,
- cfg.uuid_index, cfg.csi, cfg.ot, cfg.log_len, log);
+ struct nvme_get_log_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .lid = cfg.log_id,
+ .nsid = cfg.namespace_id,
+ .lpo = cfg.lpo,
+ .lsp = cfg.lsp,
+ .lsi = cfg.lsi,
+ .rae = cfg.rae,
+ .uuidx = cfg.uuid_index,
+ .csi = cfg.csi,
+ .ot = cfg.ot,
+ .len = cfg.log_len,
+ .log = log,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_get_log(&args);
if (!err) {
if (!cfg.raw_binary) {
printf("Device:%s log-id:%d namespace-id:%#x\n",
- devicename, cfg.log_id,
- cfg.namespace_id);
+ devicename, cfg.log_id,
+ cfg.namespace_id);
d(log, cfg.log_len, 16, 1);
} else
d_raw((unsigned char *)log, cfg.log_len);
} else if (err > 0)
nvme_show_status(err);
else
- perror("log page");
+ fprintf(stderr, "log page: %s\n", nvme_strerror(errno));
free(log);
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int sanitize_log(int argc, char **argv, struct command *command, struct plugin *plugin)
@@ -1602,18 +1779,20 @@ static int sanitize_log(int argc, char **argv, struct command *command, struct p
const char *human_readable = "show log in readable format";
struct nvme_sanitize_log_page sanitize_log;
enum nvme_print_flags flags;
- int fd, err = -1;
+ int fd, err;
struct config {
- bool rae;
- int raw_binary;
- int human_readable;
- char *output_format;
+ bool rae;
+ char *output_format;
+ bool human_readable;
+ bool raw_binary;
};
struct config cfg = {
- .rae = false,
- .output_format = "normal",
+ .rae = false,
+ .output_format = "normal",
+ .human_readable = false,
+ .raw_binary = false,
};
OPT_ARGS(opts) = {
@@ -1636,17 +1815,18 @@ static int sanitize_log(int argc, char **argv, struct command *command, struct p
if (cfg.human_readable)
flags |= VERBOSE;
- err = nvme_sanitize_log(fd, cfg.rae, &sanitize_log);
+ err = nvme_get_log_sanitize(fd, cfg.rae, &sanitize_log);
if (!err)
nvme_show_sanitize_log(&sanitize_log, devicename, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("sanitize status log");
+ fprintf(stderr, "sanitize status log: %s\n",
+ nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_fid_support_effects_log(int argc, char **argv, struct command *cmd,
@@ -1654,17 +1834,18 @@ static int get_fid_support_effects_log(int argc, char **argv, struct command *cm
{
const char *desc = "Retrieve FID Support and Effects log and show it.";
const char *human_readable = "show log in readable format";
- struct nvme_fid_support_effects fid_support_log;
+ struct nvme_fid_supported_effects_log fid_support_log;
enum nvme_print_flags flags;
int fd, err = -1;
struct config {
- int human_readable;
- char *output_format;
+ char *output_format;
+ bool human_readable;
};
struct config cfg = {
- .output_format = "normal",
+ .output_format = "normal",
+ .human_readable = false,
};
OPT_ARGS(opts) = {
@@ -1683,17 +1864,67 @@ static int get_fid_support_effects_log(int argc, char **argv, struct command *cm
if (cfg.human_readable)
flags |= VERBOSE;
- err = nvme_fid_support_effects_log(fd, &fid_support_log);
+ err = nvme_get_log_fid_supported_effects(fd, false, &fid_support_log);
if (!err)
nvme_show_fid_support_effects_log(&fid_support_log, devicename, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("fid support effects log");
+ fprintf(stderr, "fid support effects log: %s\n",
+ nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
+}
+
+static int get_mi_cmd_support_effects_log(int argc, char **argv, struct command *cmd,
+ struct plugin *plugin)
+{
+ const char *desc = "Retrieve NVMe-MI Command Support and Effects log and show it.";
+ const char *human_readable = "show log in readable format";
+ struct nvme_mi_cmd_supported_effects_log mi_cmd_support_log;
+ enum nvme_print_flags flags;
+ int fd, err = -1;
+
+ struct config {
+ char *output_format;
+ bool human_readable;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ .human_readable = false,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+ OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable),
+ OPT_END()
+ };
+
+ err = fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ goto ret;
+
+ err = flags = validate_output_format(cfg.output_format);
+ if (flags < 0)
+ goto close_fd;
+ if (cfg.human_readable)
+ flags |= VERBOSE;
+
+ err = nvme_get_log_mi_cmd_supported_effects(fd, false, &mi_cmd_support_log);
+ if (!err)
+ nvme_show_mi_cmd_support_effects_log(&mi_cmd_support_log, devicename, flags);
+ else if (err > 0)
+ nvme_show_status(err);
+ else
+ fprintf(stderr, "mi command support effects log: %s\n",
+ nvme_strerror(errno));
+close_fd:
+ close(fd);
+ret:
+ return err;
}
static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -1702,19 +1933,20 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin *
"given device is part of, or optionally controllers attached to a specific namespace.";
const char *controller = "controller to display";
const char *namespace_id = "optional namespace attached to controller";
- int err = -1, fd;
- struct nvme_controller_list *cntlist;
+ int err, fd;
+ struct nvme_ctrl_list *cntlist;
enum nvme_print_flags flags;
struct config {
- __u16 cntid;
- __u32 namespace_id;
- char *output_format;
+ __u16 cntid;
+ __u32 namespace_id;
+ char *output_format;
};
struct config cfg = {
- .cntid = 0,
- .output_format = "normal",
+ .cntid = 0,
+ .namespace_id = NVME_NSID_NONE,
+ .output_format = "normal",
};
OPT_ARGS(opts) = {
@@ -1731,31 +1963,31 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin *
err = flags = validate_output_format(cfg.output_format);
if (flags < 0)
goto close_fd;
- if (flags != JSON && flags != NORMAL) {
- err = -EINVAL;
- goto close_fd;
- }
if (posix_memalign((void *)&cntlist, getpagesize(), 0x1000)) {
fprintf(stderr, "can not allocate controller list payload\n");
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_fd;
}
- err = nvme_identify_ctrl_list(fd, cfg.namespace_id, cfg.cntid, cntlist);
+ if (cfg.namespace_id == NVME_NSID_NONE)
+ err = nvme_identify_ctrl_list(fd, cfg.cntid, cntlist);
+ else
+ err = nvme_identify_nsid_ctrl_list(fd, cfg.namespace_id,
+ cfg.cntid, cntlist);
if (!err)
nvme_show_list_ctrl(cntlist, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("id controller list");
+ fprintf(stderr, "id controller list: %s\n",
+ nvme_strerror(errno));
free(cntlist);
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -1765,25 +1997,27 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl
const char *namespace_id = "first nsid returned list should start from";
const char *csi = "I/O command set identifier";
const char *all = "show all namespaces in the subsystem, whether attached or inactive";
- int err = -1, fd;
- __le32 ns_list[1024];
+ int err, fd;
+ struct nvme_ns_list ns_list;
enum nvme_print_flags flags;
struct config {
- __u32 namespace_id;
- int all;
- __u8 csi;
- char *output_format;
+ __u32 namespace_id;
+ int csi;
+ bool all;
+ char *output_format;
};
struct config cfg = {
- .namespace_id = 1,
+ .namespace_id = 1,
+ .csi = -1,
+ .all = false,
.output_format = "normal",
};
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
- OPT_BYTE("csi", 'y', &cfg.csi, csi),
+ OPT_INT("csi", 'y', &cfg.csi, csi),
OPT_FLAG("all", 'a', &cfg.all, all),
OPT_FMT("output-format", 'o', &cfg.output_format, output_format_no_binary),
OPT_END()
@@ -1802,20 +2036,95 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl
}
if (!cfg.namespace_id) {
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
fprintf(stderr, "invalid nsid parameter\n");
goto close_fd;
}
- err = nvme_identify_ns_list_csi(fd, cfg.namespace_id - 1, cfg.csi,
- !!cfg.all, ns_list);
+ if (cfg.csi < 0) {
+ if (cfg.all)
+ err = nvme_identify_allocated_ns_list(fd,
+ cfg.namespace_id - 1, &ns_list);
+ else
+ err = nvme_identify_active_ns_list(fd,
+ cfg.namespace_id - 1, &ns_list);
+
+ } else {
+ if (cfg.all)
+ err = nvme_identify_allocated_ns_list_csi(fd,
+ cfg.namespace_id - 1, cfg.csi, &ns_list);
+ else
+ err = nvme_identify_active_ns_list_csi(fd,
+ cfg.namespace_id - 1, cfg.csi, &ns_list);
+ }
+
+ if (!err)
+ nvme_show_list_ns(&ns_list, flags);
+ else if (err > 0)
+ nvme_show_status(err);
+ else
+ fprintf(stderr, "id namespace list: %s",
+ nvme_strerror(errno));
+close_fd:
+ close(fd);
+ret:
+ return err;
+}
+
+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 "\
+ "LBA Format index in various formats.";
+ const char *lba_format_index = "The index into the LBA Format list "\
+ "identifying the LBA Format capabilities that are to be returned";
+ const char *uuid_index = "UUID index";
+ const char *verbose = "Increase output verbosity";
+ enum nvme_print_flags flags;
+ struct nvme_id_ns ns;
+ int err = -1, fd;
+
+ struct config {
+ __u16 lba_format_index;
+ __u8 uuid_index;
+ bool verbose;
+ char *output_format;
+ };
+
+ struct config cfg = {
+ .lba_format_index = 0,
+ .uuid_index = NVME_UUID_NONE,
+ .verbose = false,
+ .output_format = "normal",
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_UINT("lba-format-index", 'i', &cfg.lba_format_index, lba_format_index),
+ OPT_BYTE("uuid-index", 'U', &cfg.uuid_index, uuid_index),
+ OPT_FLAG("verbose", 'v', &cfg.verbose, verbose),
+ OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+ OPT_END()
+ };
+
+ err = fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ goto ret;
+
+ err = flags = validate_output_format(cfg.output_format);
+ if (flags < 0)
+ goto close_fd;
+
+ if (cfg.verbose)
+ flags |= VERBOSE;
+
+ err = nvme_identify_ns_csi_user_data_format(fd, cfg.lba_format_index,
+ cfg.uuid_index, NVME_CSI_NVM, &ns);
if (!err)
- nvme_show_list_ns(ns_list, flags);
+ nvme_show_id_ns(&ns, 0, cfg.lba_format_index, true, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("id namespace list");
+ perror("identify namespace for specific LBA format");
close_fd:
close(fd);
ret:
@@ -1829,17 +2138,17 @@ static int id_endurance_grp_list(int argc, char **argv, struct command *cmd,
"group id";
const char *endurance_grp_id = "Endurance Group ID";
int err = -1, fd;
- struct nvme_endurance_group_list *endgrp_list;
+ struct nvme_id_endurance_group_list *endgrp_list;
enum nvme_print_flags flags;
struct config {
- __u16 endgrp_id;
- char *output_format;
+ __u16 endgrp_id;
+ char *output_format;
};
struct config cfg = {
- .endgrp_id = 0,
- .output_format = "normal",
+ .endgrp_id = 0,
+ .output_format = "normal",
};
OPT_ARGS(opts) = {
@@ -1862,8 +2171,6 @@ static int id_endurance_grp_list(int argc, char **argv, struct command *cmd,
}
if (posix_memalign((void *)&endgrp_list, getpagesize(), 0x1000)) {
- fprintf(stderr, "can not allocate memory for endurance gropu list\n");
- errno = ENOMEM;
err = -1;
goto close_fd;
}
@@ -1874,13 +2181,14 @@ static int id_endurance_grp_list(int argc, char **argv, struct command *cmd,
else if (err > 0)
nvme_show_status(err);
else
- perror("id endurance group list");
+ fprintf(stderr, "Id endurance group list: %s",
+ nvme_strerror(errno));
free(endgrp_list);
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -1893,7 +2201,7 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin *
"the namespace is not already inactive, once deleted.";
const char *namespace_id = "namespace to delete";
const char *timeout = "timeout value, in milliseconds";
- int err = -1, fd;
+ int err, fd;
struct config {
__u32 namespace_id;
@@ -1902,7 +2210,7 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin *
struct config cfg = {
.namespace_id = 0,
- .timeout = NVME_IOCTL_TIMEOUT,
+ .timeout = 120000,
};
OPT_ARGS(opts) = {
@@ -1916,44 +2224,46 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin *
goto ret;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n",
+ nvme_strerror(errno));
goto close_fd;
}
}
- err = nvme_ns_delete(fd, cfg.namespace_id, cfg.timeout);
+ err = nvme_ns_mgmt_delete(fd, cfg.namespace_id);
if (!err)
printf("%s: Success, deleted nsid:%d\n", cmd->name,
cfg.namespace_id);
else if (err > 0)
nvme_show_status(err);
else
- perror("delete namespace");
+ fprintf(stderr, "delete namespace: %s\n", nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, struct command *cmd)
{
- int err = -1, num, i, fd, list[2048];
+ int err, num, fd, i, list[2048];
+ struct nvme_ctrl_list cntlist;
__u16 ctrlist[2048];
const char *namespace_id = "namespace to attach";
const char *cont = "optional comma-sep controller id list";
struct config {
- char *cntlist;
- __u32 namespace_id;
+ __u32 namespace_id;
+ char *cntlist;
};
struct config cfg = {
- .cntlist = "",
- .namespace_id = 0,
+ .namespace_id = 0,
+ .cntlist = "",
};
OPT_ARGS(opts) = {
@@ -1969,8 +2279,7 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s
if (!cfg.namespace_id) {
fprintf(stderr, "%s: namespace-id parameter required\n",
cmd->name);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
@@ -1982,15 +2291,19 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s
if (num == -1) {
fprintf(stderr, "%s: controller id list is malformed\n",
cmd->name);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
for (i = 0; i < num; i++)
- ctrlist[i] = (uint16_t)list[i];
+ ctrlist[i] = (__u16)list[i];
+
+ nvme_init_ctrl_list(&cntlist, num, ctrlist);
- err = nvme_ns_attachment(fd, cfg.namespace_id, num, ctrlist, attach);
+ if (attach)
+ err = nvme_ns_attach_ctrls(fd, cfg.namespace_id, &cntlist);
+ else
+ err = nvme_ns_detach_ctrls(fd, cfg.namespace_id, &cntlist);
if (!err)
printf("%s: Success, nsid:%d\n", cmd->name, cfg.namespace_id);
@@ -2002,7 +2315,7 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int attach_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -2040,11 +2353,12 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin *
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 *timeout = "timeout value, in milliseconds";
const char *bs = "target block size, specify only if \'FLBAS\' "\
"value not entered";
- int err = -1, fd, i;
+ int err = 0, fd, i;
struct nvme_id_ns ns;
__u32 nsid;
@@ -2058,15 +2372,22 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin *
__u16 nvmsetid;
__u64 bs;
__u32 timeout;
- __u8 csi;
+ __u8 csi;
+ __u64 lbstm;
};
struct config cfg = {
+ .nsze = 0,
+ .ncap = 0,
.flbas = 0xff,
+ .dps = 0,
+ .nmic = 0,
.anagrpid = 0,
.nvmsetid = 0,
.bs = 0x00,
- .timeout = NVME_IOCTL_TIMEOUT,
+ .timeout = 120000,
+ .csi = 0,
+ .lbstm = 0,
};
OPT_ARGS(opts) = {
@@ -2080,6 +2401,7 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin *
OPT_SUFFIX("block-size", 'b', &cfg.bs, bs),
OPT_UINT("timeout", 't', &cfg.timeout, timeout),
OPT_BYTE("csi", 'y', &cfg.csi, csi),
+ OPT_SUFFIX("lbstm", 'l', &cfg.lbstm, lbstm),
OPT_END()
};
@@ -2090,8 +2412,7 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin *
if (cfg.flbas != 0xff && cfg.bs != 0x00) {
fprintf(stderr,
"Invalid specification of both FLBAS and Block Size, please specify only one\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (cfg.bs) {
@@ -2099,14 +2420,14 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin *
fprintf(stderr,
"Invalid value for block size (%"PRIu64"). Block size must be a power of two\n",
(uint64_t)cfg.bs);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
- err = nvme_identify_ns(fd, NVME_NSID_ALL, 0, &ns);
+ err = nvme_identify_ns(fd, NVME_NSID_ALL, &ns);
if (err) {
if (err < 0)
- perror("identify-namespace");
+ fprintf(stderr, "identify-namespace: %s",
+ nvme_strerror(errno));
else {
fprintf(stderr, "identify failed\n");
nvme_show_status(err);
@@ -2128,51 +2449,93 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin *
fprintf(stderr,
"Please correct block size, or specify FLBAS directly\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
- err = nvme_ns_create(fd, cfg.nsze, cfg.ncap, cfg.flbas, cfg.dps, cfg.nmic,
- cfg.anagrpid, cfg.nvmsetid, cfg.csi, cfg.timeout,
- &nsid);
+ struct nvme_id_ns ns2 = {
+ .nsze = cpu_to_le64(cfg.nsze),
+ .ncap = cpu_to_le64(cfg.ncap),
+ .flbas = cfg.flbas,
+ .dps = cfg.dps,
+ .nmic = cfg.nmic,
+ .anagrpid = cpu_to_le32(cfg.anagrpid),
+ .nvmsetid = cpu_to_le16(cfg.nvmsetid),
+ .lbstm = cpu_to_le64(cfg.lbstm),
+ };
+
+ err = nvme_ns_mgmt_create(fd, &ns2, &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
- perror("create namespace");
+ fprintf(stderr, "create namespace: %s\n", nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
+}
+
+static bool nvme_match_device_filter(nvme_subsystem_t s,
+ nvme_ctrl_t c, nvme_ns_t ns, void *f_args)
+{
+ int ret, instance, nsid, s_num;
+ char *devname = f_args;
+
+ if (!devname || !strlen(devname))
+ return true;
+
+ ret = sscanf(devname, "nvme%dn%d", &instance, &nsid);
+ if (ret != 2)
+ return true;
+
+ if (s) {
+ ret = sscanf(nvme_subsystem_get_name(s), "nvme-subsys%d",
+ &s_num);
+ if (ret == 1 && s_num == instance)
+ return true;
+ }
+ if (c) {
+ s = nvme_ctrl_get_subsystem(c);
+
+ ret = sscanf(nvme_subsystem_get_name(s), "nvme-subsys%d",
+ &s_num);
+ if (ret == 1 && s_num == instance)
+ return true;
+ }
+ if (ns) {
+ if (!strcmp(devname, nvme_ns_get_name(ns)))
+ return true;
+ }
+
+ return false;
}
static int list_subsys(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
- struct nvme_topology t = { };
+ nvme_root_t r = NULL;
enum nvme_print_flags flags;
- char *subsysnqn = NULL;
const char *desc = "Retrieve information for subsystems";
const char *verbose = "Increase output verbosity";
- __u32 ns_instance = 0;
- int err = -1, nsid = 0;
+ nvme_scan_filter_t filter = NULL;
+ int err;
struct config {
- char *output_format;
- int verbose;
+ char *output_format;
+ int verbose;
};
struct config cfg = {
- .output_format = "normal",
- .verbose = 0,
+ .output_format = "normal",
+ .verbose = 0,
};
OPT_ARGS(opts) = {
OPT_FMT("output-format", 'o', &cfg.output_format, output_format_no_binary),
- OPT_FLAG("verbose", 'v', &cfg.verbose, verbose),
+ OPT_INCR("verbose", 'v', &cfg.verbose, verbose),
OPT_END()
};
@@ -2181,95 +2544,77 @@ static int list_subsys(int argc, char **argv, struct command *cmd,
goto ret;
devicename = NULL;
- if (optind < argc) {
- char path[512];
- int id, fd;
-
- devicename = basename(argv[optind]);
- if (sscanf(devicename, "nvme%dn%d", &id, &ns_instance) != 2) {
- fprintf(stderr, "%s is not a NVMe namespace device\n",
- argv[optind]);
- errno = EINVAL;
- err = -1;
- goto ret;
- }
- sprintf(path, "/dev/%s", devicename);
- fd = open(path, O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "Cannot read nsid from %s\n",
- devicename);
- errno = EINVAL;
- err = -1;
- goto ret;
- }
- nsid = nvme_get_nsid(fd);
- close(fd);
- if (nsid < 0) {
- fprintf(stderr, "Cannot read nsid from %s\n",
- devicename);
- errno = EINVAL;
- err = -1;
- goto ret;
- }
- sprintf(path, "/sys/block/%s/device", devicename);
- subsysnqn = get_nvme_subsnqn(path);
- if (!subsysnqn) {
- fprintf(stderr, "Cannot read subsys NQN from %s\n",
- devicename);
- errno = EINVAL;
- err = -1;
- goto ret;
- }
- optind++;
- }
+ if (optind < argc)
+ devicename = basename(argv[optind++]);
err = flags = validate_output_format(cfg.output_format);
if (flags < 0)
- goto free;
+ goto ret;
if (flags != JSON && flags != NORMAL) {
- errno = EINVAL;
- err = -1;
- goto free;
+ err = -EINVAL;
+ goto ret;
}
if (cfg.verbose)
flags |= VERBOSE;
- err = scan_subsystems(&t, subsysnqn, ns_instance, nsid, NULL);
+ r = nvme_create_root(stderr, map_log_level(cfg.verbose, false));
+ if (!r) {
+ if (devicename)
+ fprintf(stderr,
+ "Failed to scan nvme subsystem for %s\n",
+ devicename);
+ else
+ fprintf(stderr, "Failed to scan nvme subsystem\n");
+ err = -errno;
+ goto ret;
+ }
+
+ if (devicename) {
+ int subsys_num, nsid;
+
+ if (sscanf(devicename,"nvme%dn%d",
+ &subsys_num, &nsid) != 2) {
+ fprintf(stderr, "Invalid device name %s\n", devicename);
+ err = -EINVAL;
+ goto ret;
+ }
+ filter = nvme_match_device_filter;
+ }
+
+ err = nvme_scan_topology(r, filter, (void *)devicename);
if (err) {
- fprintf(stderr, "Failed to scan namespaces\n");
- goto free;
+ fprintf(stderr, "Failed to scan topology: %s\n",
+ nvme_strerror(errno));
+ goto ret;
}
- nvme_show_subsystem_list(&t, flags);
-free:
- free_topology(&t);
- free(subsysnqn);
+
+ nvme_show_subsystem_list(r, flags);
+
ret:
- return nvme_status_to_errno(err, false);
+ if (r)
+ nvme_free_tree(r);
+ return err;
}
static int list(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Retrieve basic information for all NVMe namespaces";
- const char *device_dir = "Additional directory to search for devices";
const char *verbose = "Increase output verbosity";
- struct nvme_topology t = { };
enum nvme_print_flags flags;
- int err = -1;
+ nvme_root_t r;
+ int err = 0;
struct config {
- char *device_dir;
- char *output_format;
- int verbose;
+ char *output_format;
+ bool verbose;
};
struct config cfg = {
- .device_dir = NULL,
- .output_format = "normal",
- .verbose = 0,
+ .output_format = "normal",
+ .verbose = false,
};
OPT_ARGS(opts) = {
- OPT_STRING("directory", 'd', "DIR", &cfg.device_dir, device_dir),
OPT_FMT("output-format", 'o', &cfg.output_format, output_format_no_binary),
OPT_FLAG("verbose", 'v', &cfg.verbose, verbose),
OPT_END()
@@ -2289,15 +2634,24 @@ static int list(int argc, char **argv, struct command *cmd, struct plugin *plugi
if (cfg.verbose)
flags |= VERBOSE;
- err = scan_subsystems(&t, NULL, 0, 0, cfg.device_dir);
- if (err) {
- fprintf(stderr, "Failed to scan namespaces\n");
+ 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));
+ return -errno;
+ }
+ err = nvme_scan_topology(r, NULL, NULL);
+ if (err < 0) {
+ fprintf(stderr, "Failed to scan topoplogy: %s\n",
+ nvme_strerror(errno));
+ nvme_free_tree(r);
return err;
}
- nvme_show_list_items(&t, flags);
- free_topology(&t);
- return 0;
+ nvme_show_list_items(r, flags);
+ nvme_free_tree(r);
+
+ return err;
}
int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin,
@@ -2313,17 +2667,20 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin,
const char *human_readable = "show identify in readable format";
enum nvme_print_flags flags;
struct nvme_id_ctrl ctrl;
- int err = -1, fd;
+ int err, fd;
struct config {
- int vendor_specific;
- int raw_binary;
- int human_readable;
- char *output_format;
+ bool vendor_specific;
+ char *output_format;
+ bool raw_binary;
+ bool human_readable;
};
struct config cfg = {
- .output_format = "normal",
+ .vendor_specific = false,
+ .output_format = "normal",
+ .raw_binary = false,
+ .human_readable = false,
};
OPT_ARGS(opts) = {
@@ -2350,15 +2707,15 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin,
err = nvme_identify_ctrl(fd, &ctrl);
if (!err)
- __nvme_show_id_ctrl(&ctrl, flags, vs);
+ nvme_show_id_ctrl(&ctrl, flags, vs);
else if (err > 0)
nvme_show_status(err);
else
- perror("identify controller");
+ fprintf(stderr, "identify controller: %s\n", nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -2377,15 +2734,15 @@ static int nvm_id_ctrl(int argc, char **argv, struct command *cmd,
int fd, err = -1;
struct config {
- char *output_format;
+ char *output_format;
};
struct config cfg = {
- .output_format = "normal",
+ .output_format = "normal",
};
OPT_ARGS(opts) = {
- OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+ OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
OPT_END()
};
@@ -2397,13 +2754,156 @@ static int nvm_id_ctrl(int argc, char **argv, struct command *cmd,
if (flags < 0)
goto close_fd;
- err = nvme_identify_ctrl_nvm(fd, &ctrl_nvm);
+ err = nvme_nvm_identify_ctrl(fd, &ctrl_nvm);
if (!err)
nvme_show_id_ctrl_nvm(&ctrl_nvm, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("nvm identify controller");
+ fprintf(stderr, "nvm identify controller: %s\n", nvme_strerror(errno));
+close_fd:
+ close(fd);
+ret:
+ return err;
+}
+
+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 "\
+ "the specified namespace in various formats.";
+ const char *namespace_id = "identifier of desired namespace";
+ const char *uuid_index = "UUID index";
+ const char *verbose = "Increase output verbosity";
+ enum nvme_print_flags flags;
+ struct nvme_nvm_id_ns id_ns;
+ struct nvme_id_ns ns;
+ int fd, err = -1;
+
+ struct config {
+ __u32 namespace_id;
+ __u8 uuid_index;
+ char *output_format;
+ bool verbose;
+ };
+
+ struct config cfg = {
+ .namespace_id = 0,
+ .uuid_index = NVME_UUID_NONE,
+ .output_format = "normal",
+ .verbose = false,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
+ OPT_BYTE("uuid-index", 'U', &cfg.uuid_index, uuid_index),
+ OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+ OPT_FLAG("verbose", 'v', &cfg.verbose, verbose),
+ OPT_END()
+ };
+
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ goto ret;
+
+ err = flags = validate_output_format(cfg.output_format);
+ if (flags < 0)
+ goto close_fd;
+
+ if (cfg.verbose)
+ flags |= VERBOSE;
+
+ if (!cfg.namespace_id) {
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
+ if (err < 0) {
+ perror("get-namespace-id");
+ goto close_fd;
+ }
+ }
+
+ err = nvme_identify_ns(fd, cfg.namespace_id, &ns);
+ if (err) {
+ nvme_show_status(err);
+ goto close_fd;
+ }
+
+ err = nvme_identify_ns_csi(fd, cfg.namespace_id, cfg.uuid_index,
+ NVME_CSI_NVM, &id_ns);
+ if (!err)
+ nvme_show_nvm_id_ns(&id_ns, cfg.namespace_id, &ns, 0, false, flags);
+ else if (err > 0)
+ nvme_show_status(err);
+ else
+ perror("nvm identify namespace");
+close_fd:
+ close(fd);
+ret:
+ return nvme_status_to_errno(err, false);
+}
+
+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 *lba_format_index = "The index into the LBA Format list "\
+ "identifying the LBA Format capabilities that are to be returned";
+ const char *uuid_index = "UUID index";
+ const char *verbose = "Increase output verbosity";
+ enum nvme_print_flags flags;
+ struct nvme_id_ns ns;
+ struct nvme_nvm_id_ns nvm_ns;
+ int err = -1, fd;
+
+ struct config {
+ __u16 lba_format_index;
+ __u8 uuid_index;
+ bool verbose;
+ char *output_format;
+ };
+
+ struct config cfg = {
+ .lba_format_index = 0,
+ .uuid_index = NVME_UUID_NONE,
+ .verbose = false,
+ .output_format = "normal",
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_UINT("lba-format-index", 'i', &cfg.lba_format_index, lba_format_index),
+ OPT_BYTE("uuid-index", 'U', &cfg.uuid_index, uuid_index),
+ OPT_FLAG("verbose", 'v', &cfg.verbose, verbose),
+ OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+ OPT_END()
+ };
+
+ err = fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ goto ret;
+
+ err = flags = validate_output_format(cfg.output_format);
+ if (flags < 0)
+ goto close_fd;
+
+ if (cfg.verbose)
+ flags |= VERBOSE;
+
+ err = nvme_identify_ns(fd, NVME_NSID_ALL, &ns);
+ if (err) {
+ ns.nlbaf = NVME_FEAT_LBA_RANGE_MAX - 1;
+ ns.nulbaf = 0;
+ }
+ err = nvme_identify_iocs_ns_csi_user_data_format(fd, 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);
+ else if (err > 0)
+ nvme_show_status(err);
+ else
+ perror("NVM identify namespace for specific LBA format");
close_fd:
close(fd);
ret:
@@ -2418,18 +2918,19 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p
const char *raw = "show descriptors in binary format";
const char *namespace_id = "identifier of desired namespace";
enum nvme_print_flags flags;
- int err = -1, fd;
+ int err, fd;
void *nsdescs;
struct config {
- __u32 namespace_id;
- int raw_binary;
- char *output_format;
+ __u32 namespace_id;
+ char *output_format;
+ bool raw_binary;
};
struct config cfg = {
- .namespace_id = 0,
- .output_format = "normal",
+ .namespace_id = 0,
+ .output_format = "normal",
+ .raw_binary = false,
};
OPT_ARGS(opts) = {
@@ -2450,17 +2951,15 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p
flags = BINARY;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
}
if (posix_memalign(&nsdescs, getpagesize(), 0x1000)) {
- fprintf(stderr, "can not allocate controller list payload\n");
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_fd;
}
@@ -2470,12 +2969,12 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p
else if (err > 0)
nvme_show_status(err);
else
- perror("identify namespace");
+ fprintf(stderr, "identify namespace: %s\n", nvme_strerror(errno));
free(nsdescs);
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -2492,25 +2991,29 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug
enum nvme_print_flags flags;
struct nvme_id_ns ns;
- int err = -1, fd;
+ int err, fd;
struct config {
- __u32 namespace_id;
- int vendor_specific;
- int raw_binary;
- int human_readable;
- int force;
- char *output_format;
+ __u32 namespace_id;
+ bool force;
+ bool vendor_specific;
+ bool raw_binary;
+ char *output_format;
+ bool human_readable;
};
struct config cfg = {
- .namespace_id = 0,
- .output_format = "normal",
+ .namespace_id = 0,
+ .force = false,
+ .vendor_specific = false,
+ .raw_binary = false,
+ .output_format = "normal",
+ .human_readable = false,
};
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
- OPT_FLAG("force", 'f', &cfg.force, force),
+ OPT_FLAG("force", 0, &cfg.force, force),
OPT_FLAG("vendor-specific", 'v', &cfg.vendor_specific, vendor_specific),
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
@@ -2533,24 +3036,28 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug
flags |= VERBOSE;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
}
- err = nvme_identify_ns(fd, cfg.namespace_id, cfg.force, &ns);
+ if (cfg.force)
+ err = nvme_identify_allocated_ns(fd, cfg.namespace_id, &ns);
+ else
+ err = nvme_identify_ns(fd, cfg.namespace_id, &ns);
+
if (!err)
- nvme_show_id_ns(&ns, cfg.namespace_id, flags);
+ nvme_show_id_ns(&ns, cfg.namespace_id, 0, false, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("identify namespace");
+ fprintf(stderr, "identify namespace: %s\n", nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int cmd_set_independent_id_ns(int argc, char **argv,
@@ -2564,19 +3071,21 @@ static int cmd_set_independent_id_ns(int argc, char **argv,
const char *namespace_id = "identifier of desired namespace";
enum nvme_print_flags flags;
- struct nvme_cmd_set_independent_id_ns ns;
+ struct nvme_id_independent_id_ns ns;
int err = -1, fd;
struct config {
- __u32 namespace_id;
- int raw_binary;
- int human_readable;
- char *output_format;
+ __u32 namespace_id;
+ bool raw_binary;
+ char *output_format;
+ bool human_readable;
};
struct config cfg = {
- .namespace_id = 0,
- .output_format = "normal",
+ .namespace_id = 0,
+ .raw_binary = false,
+ .output_format = "normal",
+ .human_readable = false,
};
OPT_ARGS(opts) = {
@@ -2600,24 +3109,24 @@ static int cmd_set_independent_id_ns(int argc, char **argv,
flags |= VERBOSE;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = cfg.namespace_id = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
}
}
- err = nvme_cmd_set_independent_identify_ns(fd, cfg.namespace_id, &ns);
+ err = nvme_identify_independent_identify_ns(fd, cfg.namespace_id, &ns);
if (!err)
nvme_show_cmd_set_independent_id_ns(&ns, cfg.namespace_id, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("I/O command set independent identify namespace");
+ fprintf(stderr, "I/O command set independent identify namespace: %s\n", nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -2628,14 +3137,14 @@ static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct
struct nvme_id_ns_granularity_list *granularity_list;
enum nvme_print_flags flags;
- int err = -1, fd;
+ int err, fd;
struct config {
- char *output_format;
+ char *output_format;
};
struct config cfg = {
- .output_format = "normal",
+ .output_format = "normal",
};
OPT_ARGS(opts) = {
@@ -2653,8 +3162,7 @@ static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct
if (posix_memalign((void *)&granularity_list, getpagesize(), NVME_IDENTIFY_DATA_SIZE)) {
fprintf(stderr, "can not allocate granularity list payload\n");
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_fd;
}
@@ -2664,12 +3172,12 @@ static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct
else if (err > 0)
nvme_show_status(err);
else
- perror("identify namespace granularity");
+ fprintf(stderr, "identify namespace granularity: %s\n", nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -2680,18 +3188,18 @@ static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin *
"in either binary format or json format";
const char *nvmset_id = "NVM Set Identify value";
- struct nvme_id_nvmset nvmset;
+ struct nvme_id_nvmset_list nvmset;
enum nvme_print_flags flags;
- int err = -1, fd;
+ int err, fd;
struct config {
- __u16 nvmset_id;
- char *output_format;
+ __u16 nvmset_id;
+ char *output_format;
};
struct config cfg = {
- .nvmset_id = 0,
- .output_format = "normal",
+ .nvmset_id = 0,
+ .output_format = "normal",
};
OPT_ARGS(opts) = {
@@ -2708,18 +3216,18 @@ static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin *
if (flags < 0)
goto close_fd;
- err = nvme_identify_nvmset(fd, cfg.nvmset_id, &nvmset);
+ err = nvme_identify_nvmset_list(fd, cfg.nvmset_id, &nvmset);
if (!err)
nvme_show_id_nvmset(&nvmset, cfg.nvmset_id, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("identify nvm set list");
+ fprintf(stderr, "identify nvm set list: %s\n", nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -2732,16 +3240,18 @@ static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *pl
struct nvme_id_uuid_list uuid_list;
enum nvme_print_flags flags;
- int err = -1, fd;
+ int err, fd;
struct config {
- int raw_binary;
- int human_readable;
- char *output_format;
+ char *output_format;
+ bool raw_binary;
+ bool human_readable;
};
struct config cfg = {
- .output_format = "normal",
+ .output_format = "normal",
+ .raw_binary = false,
+ .human_readable = false,
};
OPT_ARGS(opts) = {
@@ -2769,11 +3279,11 @@ static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *pl
else if (err > 0)
nvme_show_status(err);
else
- perror("identify UUID list");
+ fprintf(stderr, "identify UUID list: %s\n", nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);;
+ return err;;
}
static int id_iocs(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -2782,26 +3292,19 @@ static int id_iocs(int argc, char **argv, struct command *cmd, struct plugin *pl
"given device, returns properties of the specified controller "\
"in either human-readable or binary format.";
const char *controller_id = "identifier of desired controller";
- const char *human_readable = "show info in human readable format";
struct nvme_id_iocs iocs;
- enum nvme_print_flags flags;
int err, fd;
struct config {
- __u16 cntid;
- char *output_format;
- int human_readable;
+ __u16 cntid;
};
struct config cfg = {
- .cntid = 0xffff,
- .output_format = "normal",
+ .cntid = 0xffff,
};
OPT_ARGS(opts) = {
- OPT_SHRT("controller-id", 'c', &cfg.cntid, controller_id),
- OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
- OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable),
+ OPT_SHRT("controller-id", 'c', &cfg.cntid, controller_id),
OPT_END()
};
@@ -2811,25 +3314,18 @@ static int id_iocs(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_fd;
- if (cfg.human_readable)
- flags |= VERBOSE;
-
err = nvme_identify_iocs(fd, cfg.cntid, &iocs);
if (!err) {
printf("NVMe Identify I/O Command Set:\n");
- nvme_show_id_iocs(&iocs, flags);
+ nvme_show_id_iocs(&iocs);
} else if (err > 0)
nvme_show_status(err);
else
- perror("NVMe Identify I/O Command Set");
+ fprintf(stderr, "NVMe Identify I/O Command Set: %s\n", nvme_strerror(errno));
-close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int id_domain(int argc, char **argv, struct command *cmd, struct plugin *plugin) {
@@ -2842,13 +3338,13 @@ static int id_domain(int argc, char **argv, struct command *cmd, struct plugin *
int err, fd;
struct config {
- __u16 dom_id;
- char *output_format;
+ __u16 dom_id;
+ char *output_format;
};
struct config cfg = {
- .dom_id = 0xffff,
- .output_format = "normal",
+ .dom_id = 0xffff,
+ .output_format = "normal",
};
OPT_ARGS(opts) = {
@@ -2875,18 +3371,19 @@ static int id_domain(int argc, char **argv, struct command *cmd, struct plugin *
} else if (err > 0)
nvme_show_status(err);
else
- perror("NVMe Identify Domain List");
+ fprintf(stderr, "NVMe Identify Domain List: %s\n", nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_ns_id(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
- int err = 0, nsid, fd;
- const char *desc = "Get namespce ID of a the block device.";
+ const char *desc = "Get namespace ID of a the block device.";
+ int err = 0, fd;
+ unsigned int nsid;
OPT_ARGS(opts) = {
OPT_END()
@@ -2896,9 +3393,9 @@ static int get_ns_id(int argc, char **argv, struct command *cmd, struct plugin *
if (fd < 0)
goto ret;
- nsid = nvme_get_nsid(fd);
- if (nsid <= 0) {
- perror(devicename);
+ err = nvme_get_nsid(fd, &nsid);
+ if (err < 0) {
+ fprintf(stderr, "get namespace ID: %s\n", nvme_strerror(errno));
err = errno;
goto close_fd;
}
@@ -2908,7 +3405,7 @@ static int get_ns_id(int argc, char **argv, struct command *cmd, struct plugin *
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int virtual_mgmt(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -2928,21 +3425,21 @@ static int virtual_mgmt(int argc, char **argv, struct command *cmd, struct plugi
"8h: Secondary Assign\n"\
"9h: Secondary Online";
const char *nr = "Number of Controller Resources(NR)";
- int fd, err = -1;
- __u32 result, cdw10;
+ int fd, err;
+ __u32 result;
struct config {
- __u16 cntlid;
- __u8 rt;
- __u8 act;
- __u16 nr;
+ __u16 cntlid;
+ __u8 rt;
+ __u8 act;
+ __u16 nr;
};
struct config cfg = {
- .cntlid = 0,
- .rt = 0,
- .act = 0,
- .nr = 0,
+ .cntlid = 0,
+ .rt = 0,
+ .act = 0,
+ .nr = 0,
};
OPT_ARGS(opts) = {
@@ -2957,43 +3454,56 @@ static int virtual_mgmt(int argc, char **argv, struct command *cmd, struct plugi
if (fd < 0)
goto ret;
- cdw10 = cfg.act | (cfg.rt << 8) | (cfg.cntlid << 16);
-
- err = nvme_virtual_mgmt(fd, cdw10, cfg.nr, &result);
+ struct nvme_virtual_mgmt_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .act = cfg.act,
+ .rt = cfg.rt,
+ .cntlid = cfg.cntlid,
+ .nr = cfg.nr,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_virtual_mgmt(&args);
if (!err) {
printf("success, Number of Controller Resources Modified "\
"(NRM):%#x\n", result);
} else if (err > 0) {
nvme_show_status(err);
} else
- perror("virt-mgmt");
+ fprintf(stderr, "virt-mgmt: %s\n", nvme_strerror(errno));
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
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 "\
"decoded format (default), json or binary.";
const char *human_readable = "show info in readable format";
- struct nvme_primary_ctrl_caps caps;
+ struct nvme_primary_ctrl_cap caps;
- int err = -1, fd;
+ int err, fd;
enum nvme_print_flags flags;
struct config {
- char *output_format;
- int human_readable;
+ __u16 cntlid;
+ char *output_format;
+ bool human_readable;
};
struct config cfg = {
- .output_format = "normal",
+ .cntlid = 0,
+ .output_format = "normal",
+ .human_readable = false,
};
OPT_ARGS(opts) = {
+ OPT_UINT("cntlid", 'c', &cfg.cntlid, cntlid),
OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable),
OPT_END()
@@ -3009,17 +3519,17 @@ static int primary_ctrl_caps(int argc, char **argv, struct command *cmd, struct
if (cfg.human_readable)
flags |= VERBOSE;
- err = nvme_identify_primary_ctrl_caps(fd, &caps);
+ err = nvme_identify_primary_ctrl(fd, cfg.cntlid, &caps);
if (!err)
- nvme_show_primary_ctrl_caps(&caps, flags);
+ nvme_show_primary_ctrl_cap(&caps, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("identify primary controller capabilities");
+ fprintf(stderr, "identify primary controller capabilities: %s\n", nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -3030,22 +3540,22 @@ static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struc
const char *namespace_id = "optional namespace attached to controller";
const char *num_entries = "number of entries to retrieve";
- struct nvme_secondary_controllers_list *sc_list;
+ struct nvme_secondary_ctrl_list *sc_list;
enum nvme_print_flags flags;
- int err = -1, fd;
+ int err, fd;
struct config {
- __u16 cntid;
- __u32 num_entries;
- __u32 namespace_id;
- char *output_format;
+ __u16 cntid;
+ __u32 namespace_id;
+ __u32 num_entries;
+ char *output_format;
};
struct config cfg = {
- .cntid = 0,
- .namespace_id = 0,
- .output_format = "normal",
- .num_entries = ARRAY_SIZE(sc_list->sc_entry),
+ .cntid = 0,
+ .namespace_id = 0,
+ .num_entries = ARRAY_SIZE(sc_list->sc_entry),
+ .output_format = "normal",
};
OPT_ARGS(opts) = {
@@ -3066,15 +3576,13 @@ static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struc
if (!cfg.num_entries) {
fprintf(stderr, "non-zero num-entries is required param\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (posix_memalign((void *)&sc_list, getpagesize(), sizeof(*sc_list))) {
fprintf(stderr, "can not allocate controller list payload\n");
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_fd;
}
@@ -3084,14 +3592,14 @@ static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struc
else if (err > 0)
nvme_show_status(err);
else
- perror("id secondary controller list");
+ fprintf(stderr, "id secondary controller list: %s\n", nvme_strerror(errno));
free(sc_list);
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int device_self_test(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -3105,16 +3613,16 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p
"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\n";
- int fd, err = -1;
+ int fd, err;
struct config {
- __u32 namespace_id;
- __u8 stc;
+ __u32 namespace_id;
+ __u8 stc;
};
struct config cfg = {
- .namespace_id = NVME_NSID_ALL,
- .stc = 0,
+ .namespace_id = NVME_NSID_ALL,
+ .stc = 0,
};
OPT_ARGS(opts) = {
@@ -3127,7 +3635,15 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p
if (fd < 0)
goto ret;
- err = nvme_self_test_start(fd, cfg.namespace_id, cfg.stc);
+ struct nvme_dev_self_test_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .stc = cfg.stc,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_dev_self_test(&args);
if (!err) {
if (cfg.stc == 0xf)
printf("Aborting device self-test operation\n");
@@ -3138,11 +3654,11 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p
} else if (err > 0) {
nvme_show_status(err);
} else
- perror("Device self-test");
+ fprintf(stderr, "Device self-test: %s\n", nvme_strerror(errno));
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int self_test_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -3154,20 +3670,20 @@ static int self_test_log(int argc, char **argv, struct command *cmd, struct plug
"by default all the 20 entries will be retrieved";
const char *verbose = "Increase output verbosity";
- struct nvme_self_test_log self_test_log;
+ struct nvme_self_test_log log;
enum nvme_print_flags flags;
- int err = -1, fd;
- __u32 log_size;
+ int err, fd;
struct config {
- __u8 dst_entries;
- char *output_format;
- int verbose;
+ __u8 dst_entries;
+ char *output_format;
+ bool verbose;
};
struct config cfg = {
- .dst_entries = NVME_ST_REPORTS,
- .output_format = "normal",
+ .dst_entries = NVME_LOG_ST_MAX_RESULTS,
+ .output_format = "normal",
+ .verbose = false,
};
OPT_ARGS(opts) = {
@@ -3187,22 +3703,146 @@ static int self_test_log(int argc, char **argv, struct command *cmd, struct plug
if (cfg.verbose)
flags |= VERBOSE;
- log_size = NVME_ST_LOG_HEAD_SIZE + cfg.dst_entries * NVME_ST_LOG_ENTRY_SIZE;
- err = nvme_self_test_log(fd, log_size, &self_test_log);
+ err = nvme_get_log_device_self_test(fd, &log);
if (!err)
- nvme_show_self_test_log(&self_test_log, cfg.dst_entries, log_size,
+ nvme_show_self_test_log(&log, cfg.dst_entries, 0,
devicename, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("self test log");
+ fprintf(stderr, "self test log: %s\n", nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
-static int get_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+static int get_feature_id(int fd, struct feat_cfg *cfg, void **buf,
+ __u32 *result)
+{
+ if (!cfg->data_len)
+ nvme_get_feature_length(cfg->feature_id, cfg->cdw11,
+ &cfg->data_len);
+
+ /* check for Extended Host Identifier */
+ if (cfg->feature_id == NVME_FEAT_FID_HOST_ID && (cfg->cdw11 & 0x1))
+ cfg->data_len = 16;
+
+ if (cfg->sel == 3)
+ cfg->data_len = 0;
+
+ if (cfg->data_len) {
+ if (posix_memalign(buf, getpagesize(), cfg->data_len)) {
+ return -1;
+ }
+ memset(*buf, 0, cfg->data_len);
+ }
+
+ struct nvme_get_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = cfg->feature_id,
+ .nsid = cfg->namespace_id,
+ .sel = cfg->sel,
+ .cdw11 = cfg->cdw11,
+ .uuidx = cfg->uuid_index,
+ .data_len = cfg->data_len,
+ .data = *buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = result,
+ };
+ return nvme_get_features(&args);
+}
+
+static void get_feature_id_print(struct feat_cfg cfg, int err, __u32 result,
+ void *buf)
+{
+ if (!err) {
+ if (!cfg.raw_binary || !buf) {
+ printf("get-feature:%#0*x (%s), %s value:%#0*x\n",
+ cfg.feature_id ? 4 : 2, cfg.feature_id,
+ nvme_feature_to_string(cfg.feature_id),
+ nvme_select_to_string(cfg.sel), result ? 10 : 8,
+ result);
+ if (cfg.sel == 3)
+ nvme_show_select_result(result);
+ else if (cfg.human_readable)
+ nvme_feature_show_fields(cfg.feature_id, result,
+ buf);
+ else if (buf)
+ d(buf, cfg.data_len, 16, 1);
+ } else if (buf) {
+ d_raw(buf, cfg.data_len);
+ }
+ } else if (err > 0) {
+ if (err != NVME_SC_INVALID_FIELD)
+ nvme_show_status(err);
+ } else {
+ fprintf(stderr, "get-feature: %s\n", nvme_strerror(errno));
+ }
+}
+
+static int get_feature_id_changed(int fd, struct feat_cfg cfg, bool changed)
+{
+ int err;
+ int err_def = 0;
+ __u32 result;
+ __u32 result_def;
+ void *buf = NULL;
+ void *buf_def = NULL;
+
+ if (changed)
+ cfg.sel = 0;
+
+ err = get_feature_id(fd, &cfg, &buf, &result);
+
+ if (!err && changed) {
+ cfg.sel = 1;
+ err_def = get_feature_id(fd, &cfg, &buf_def, &result_def);
+ }
+
+ if (changed)
+ cfg.sel = 8;
+
+ if (err || !changed || err_def || result != result_def ||
+ (buf && buf_def && !strcmp(buf, buf_def)))
+ get_feature_id_print(cfg, err, result, buf);
+
+ free(buf);
+ free(buf_def);
+
+ return err;
+}
+
+static int get_feature_ids(int fd, struct feat_cfg cfg)
+{
+ int err = 0;
+ int i;
+ int feat_max = 0x100;
+ int feat_num = 0;
+ bool changed = false;
+
+ if (cfg.sel == 8)
+ changed = true;
+
+ if (cfg.feature_id)
+ feat_max = cfg.feature_id + 1;
+
+ for (i = cfg.feature_id; i < feat_max; i++, feat_num++) {
+ cfg.feature_id = i;
+ err = get_feature_id_changed(fd, cfg, changed);
+ if (err && err != NVME_SC_INVALID_FIELD)
+ break;
+ }
+
+ if (err == NVME_SC_INVALID_FIELD && feat_num == 1)
+ nvme_show_status(err);
+
+ return err;
+}
+
+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 "\
@@ -3214,40 +3854,30 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin
"are vendor-specific and not changeable. Use set-feature to "\
"change saveable Features.";
const char *raw = "show feature in binary format";
- const char *namespace_id = "identifier of desired namespace";
const char *feature_id = "feature identifier";
- const char *sel = "[0-3]: current/default/saved/supported";
+ const char *namespace_id = "identifier of desired namespace";
+ const char *sel = "[0-3,8]: current/default/saved/supported/changed";
const char *data_len = "buffer len if data is returned through host memory buffer";
const char *cdw11 = "dword 11 for interrupt vector config";
const char *human_readable = "show feature in readable format";
const char *uuid_index = "specify uuid index";
- int err = -1, fd;
- __u32 result;
- void *buf = NULL;
-
- struct config {
- __u32 namespace_id;
- __u8 feature_id;
- __u8 sel;
- __u32 cdw11;
- __u8 uuid_index;
- __u32 data_len;
- int raw_binary;
- int human_readable;
- };
+ int err;
+ int fd;
- struct config cfg = {
- .namespace_id = 0,
- .feature_id = 0,
- .sel = 0,
- .cdw11 = 0,
- .uuid_index = 0,
- .data_len = 0,
+ struct feat_cfg cfg = {
+ .feature_id = 0,
+ .namespace_id = 0,
+ .sel = 0,
+ .data_len = 0,
+ .raw_binary = false,
+ .cdw11 = 0,
+ .uuid_index = 0,
+ .human_readable = false,
};
OPT_ARGS(opts) = {
- OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
OPT_BYTE("feature-id", 'f', &cfg.feature_id, feature_id),
+ OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
OPT_BYTE("sel", 's', &cfg.sel, sel),
OPT_UINT("data-len", 'l', &cfg.data_len, data_len),
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
@@ -3262,85 +3892,35 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin
goto ret;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
if (errno != ENOTTY) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
-
cfg.namespace_id = NVME_NSID_ALL;
}
}
- if (cfg.sel > 7) {
+ if (cfg.sel > 8) {
fprintf(stderr, "invalid 'select' param:%d\n", cfg.sel);
- errno = EINVAL;
- err = -1;
- goto close_fd;
- }
- if (!cfg.feature_id) {
- fprintf(stderr, "feature-id required param\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (cfg.uuid_index > 128) {
fprintf(stderr, "invalid uuid index param: %u\n", cfg.uuid_index);
- errno = EINVAL;
err = -1;
goto close_fd;
}
- if (!cfg.data_len)
- cfg.data_len = nvme_feat_buf_len[cfg.feature_id];
-
- /* check for Extended Host Identifier */
- if (cfg.feature_id == NVME_FEAT_HOST_ID && (cfg.cdw11 & 0x1))
- cfg.data_len = 16;
-
- if (cfg.sel == 3)
- cfg.data_len = 0;
-
- if (cfg.data_len) {
- if (posix_memalign(&buf, getpagesize(), cfg.data_len)) {
- fprintf(stderr, "can not allocate feature payload\n");
- errno = ENOMEM;
- err = -1;
- goto close_fd;
- }
- memset(buf, 0, cfg.data_len);
- }
-
- err = nvme_get_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.sel, cfg.cdw11,
- cfg.uuid_index, cfg.data_len, buf, &result);
- if (!err) {
- if (!cfg.raw_binary || !buf) {
- printf("get-feature:%#0*x (%s), %s value:%#0*x\n",
- cfg.feature_id ? 4 : 2, cfg.feature_id,
- nvme_feature_to_string(cfg.feature_id),
- nvme_select_to_string(cfg.sel), result ? 10 : 8,
- result);
- if (cfg.sel == 3)
- nvme_show_select_result(result);
- else if (cfg.human_readable)
- nvme_feature_show_fields(cfg.feature_id, result, buf);
- else if (buf)
- d(buf, cfg.data_len, 16, 1);
- } else if (buf)
- d_raw(buf, cfg.data_len);
- } else if (err > 0) {
- nvme_show_status(err);
- } else
- perror("get-feature");
-
- free(buf);
+ err = get_feature_ids(fd, cfg);
close_fd:
close(fd);
+
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int fw_download(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -3356,22 +3936,22 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin
const char *fw = "firmware file (required)";
const char *xfer = "transfer chunksize limit";
const char *offset = "starting dword offset, default 0";
- int err = -1, fd, fw_fd = -1;
+ int err, fd, fw_fd = -1;
unsigned int fw_size;
struct stat sb;
void *fw_buf, *buf;
bool huge;
struct config {
- char *fw;
- __u32 xfer;
- __u32 offset;
+ char *fw;
+ __u32 xfer;
+ __u32 offset;
};
struct config cfg = {
- .fw = "",
- .xfer = 4096,
- .offset = 0,
+ .fw = "",
+ .xfer = 4096,
+ .offset = 0,
};
OPT_ARGS(opts) = {
@@ -3390,8 +3970,7 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin
if (fw_fd < 0) {
fprintf(stderr, "Failed to open firmware file %s: %s\n",
cfg.fw, strerror(errno));
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
@@ -3404,8 +3983,7 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin
fw_size = sb.st_size;
if ((fw_size & 0x3) || (fw_size == 0)) {
fprintf(stderr, "Invalid size:%d for f/w image\n", fw_size);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fw_fd;
}
@@ -3418,9 +3996,7 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin
fw_buf = nvme_alloc(fw_size, &huge);
if (!fw_buf) {
- perror("No memory for f/w size:\n");
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_fw_fd;
}
@@ -3434,9 +4010,18 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin
while (fw_size > 0) {
cfg.xfer = min(cfg.xfer, fw_size);
- err = nvme_fw_download(fd, cfg.offset, cfg.xfer, fw_buf);
+ struct nvme_fw_download_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .offset = cfg.offset,
+ .data_len = cfg.xfer,
+ .data = fw_buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_fw_download(&args);
if (err < 0) {
- perror("fw-download");
+ fprintf(stderr, "fw-download: %s\n", nvme_strerror(errno));
break;
} else if (err != 0) {
nvme_show_status(err);
@@ -3456,7 +4041,7 @@ close_fw_fd:
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static char *nvme_fw_status_reset_type(__u16 status)
@@ -3479,19 +4064,19 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin *
const char *slot = "[0-7]: firmware slot for commit action";
const char *action = "[0-7]: commit action";
const char *bpid = "[0,1]: boot partition identifier, if applicable (default: 0)";
- int err = -1, fd;
+ int err, fd;
__u32 result;
struct config {
- __u8 slot;
- __u8 action;
- __u8 bpid;
+ __u8 slot;
+ __u8 action;
+ __u8 bpid;
};
struct config cfg = {
- .slot = 0,
- .action = 0,
- .bpid = 0,
+ .slot = 0,
+ .action = 0,
+ .bpid = 0,
};
OPT_ARGS(opts) = {
@@ -3507,26 +4092,32 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin *
if (cfg.slot > 7) {
fprintf(stderr, "invalid slot:%d\n", cfg.slot);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (cfg.action > 7 || cfg.action == 4 || cfg.action == 5) {
fprintf(stderr, "invalid action:%d\n", cfg.action);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (cfg.bpid > 1) {
fprintf(stderr, "invalid boot partition id:%d\n", cfg.bpid);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
- err = nvme_fw_commit(fd, cfg.slot, cfg.action, cfg.bpid, &result);
+ struct nvme_fw_commit_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .slot = cfg.slot,
+ .action = cfg.action,
+ .bpid = cfg.bpid,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_fw_commit(&args);
if (err < 0)
- perror("fw-commit");
+ fprintf(stderr, "fw-commit: %s\n", nvme_strerror(errno));
else if (err != 0)
switch (err & 0x7ff) {
case NVME_SC_FW_NEEDS_CONV_RESET:
@@ -3563,13 +4154,13 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin *
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int subsystem_reset(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Resets the NVMe subsystem\n";
- int err = -1, fd;
+ int err, fd;
OPT_ARGS(opts) = {
OPT_END()
@@ -3585,18 +4176,18 @@ static int subsystem_reset(int argc, char **argv, struct command *cmd, struct pl
fprintf(stderr,
"Subsystem-reset: NVM Subsystem Reset not supported.\n");
else
- perror("Subsystem-reset");
+ fprintf(stderr, "Subsystem-reset: %s\n", nvme_strerror(errno));
}
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int reset(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Resets the NVMe controller\n";
- int err = -1, fd;
+ int err, fd;
OPT_ARGS(opts) = {
OPT_END()
@@ -3606,13 +4197,13 @@ static int reset(int argc, char **argv, struct command *cmd, struct plugin *plug
if (fd < 0)
goto ret;
- err = nvme_reset_controller(fd);
+ err = nvme_ctrl_reset(fd);
if (err < 0)
- perror("Reset");
+ fprintf(stderr, "Reset: %s\n", nvme_strerror(errno));
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int ns_rescan(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -3630,11 +4221,11 @@ static int ns_rescan(int argc, char **argv, struct command *cmd, struct plugin *
err = nvme_ns_rescan(fd);
if (err < 0)
- perror("Namespace Rescan");
+ fprintf(stderr, "Namespace Rescan");
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -3646,25 +4237,24 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p
const char *ause_desc = "Allow unrestricted sanitize exit.";
const char *sanact_desc = "Sanitize action.";
const char *ovrpat_desc = "Overwrite pattern.";
-
- int fd, ret = -1;
+ int fd, err;
struct config {
- int no_dealloc;
- int oipbp;
- __u8 owpass;
- int ause;
- __u8 sanact;
- __u32 ovrpat;
+ bool no_dealloc;
+ bool oipbp;
+ __u8 owpass;
+ bool ause;
+ __u8 sanact;
+ __u32 ovrpat;
};
struct config cfg = {
- .no_dealloc = 0,
- .oipbp = 0,
- .owpass = 0,
- .ause = 0,
- .sanact = 0,
- .ovrpat = 0,
+ .no_dealloc = false,
+ .oipbp = false,
+ .owpass = 0,
+ .ause = false,
+ .sanact = 0,
+ .ovrpat = 0,
};
OPT_ARGS(opts) = {
@@ -3677,59 +4267,149 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p
OPT_END()
};
- ret = fd = parse_and_open(argc, argv, desc, opts);
+ err = fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
goto ret;
switch (cfg.sanact) {
- case NVME_SANITIZE_ACT_CRYPTO_ERASE:
- case NVME_SANITIZE_ACT_BLOCK_ERASE:
- case NVME_SANITIZE_ACT_EXIT:
- case NVME_SANITIZE_ACT_OVERWRITE:
+ 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");
- errno = EINVAL;
- ret = -1;
+ err = -EINVAL;
goto close_fd;
}
- if (cfg.sanact == NVME_SANITIZE_ACT_EXIT) {
+ if (cfg.sanact == NVME_SANITIZE_SANACT_EXIT_FAILURE) {
if (cfg.ause || cfg.no_dealloc) {
fprintf(stderr, "SANACT is Exit Failure Mode\n");
- errno = EINVAL;
- ret = -1;
+ err = -EINVAL;
goto close_fd;
}
}
- if (cfg.sanact == NVME_SANITIZE_ACT_OVERWRITE) {
- if (cfg.owpass >= 16) {
- fprintf(stderr, "OWPASS out of range [0-15]\n");
- errno = EINVAL;
- ret = -1;
+ if (cfg.sanact == NVME_SANITIZE_SANACT_START_OVERWRITE) {
+ if (cfg.owpass > 16) {
+ fprintf(stderr, "OWPASS out of range [0-16]\n");
+ err = -EINVAL;
goto close_fd;
}
} else {
if (cfg.owpass || cfg.oipbp || cfg.ovrpat) {
fprintf(stderr, "SANACT is not Overwrite\n");
- errno = EINVAL;
- ret = -1;
+ err = -EINVAL;
goto close_fd;
}
}
- ret = nvme_sanitize(fd, cfg.sanact, cfg.ause, cfg.owpass, cfg.oipbp,
- cfg.no_dealloc, cfg.ovrpat);
- if (ret < 0)
- perror("sanitize");
- else if (ret > 0)
- nvme_show_status(ret);
+ struct nvme_sanitize_nvm_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .sanact = cfg.sanact,
+ .ause = cfg.ause,
+ .owpass = cfg.owpass,
+ .oipbp = cfg.oipbp,
+ .nodas = cfg.no_dealloc,
+ .ovrpat = cfg.ovrpat,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_sanitize_nvm(&args);
+ if (err < 0)
+ fprintf(stderr, "sanitize: %s\n", nvme_strerror(errno));
+ else if (err > 0)
+ nvme_show_status(err);
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(ret, false);
+ return err;
+}
+
+static int nvme_get_properties(int fd, void **pbar)
+{
+ int offset, err, size = getpagesize();
+ __u64 value;
+
+ *pbar = malloc(size);
+ if (!*pbar) {
+ fprintf(stderr, "malloc: %s\n", strerror(errno));
+ return -1;
+ }
+
+ memset(*pbar, 0xff, size);
+ for (offset = NVME_REG_CAP; offset <= NVME_REG_CMBSZ;) {
+ struct nvme_get_property_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .offset = offset,
+ .value = &value,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ };
+ err = nvme_get_property(&args);
+ if (err > 0 && (err & 0xff) == NVME_SC_INVALID_FIELD) {
+ err = 0;
+ value = -1;
+ } else if (err) {
+ free(*pbar);
+ break;
+ }
+ if (nvme_is_64bit_reg(offset)) {
+ *(uint64_t *)(*pbar + offset) = value;
+ offset += 8;
+ } else {
+ *(uint32_t *)(*pbar + offset) = value;
+ offset += 4;
+ }
+ }
+
+ return err;
+}
+
+static void *mmap_registers(nvme_root_t r, const char *dev)
+{
+ nvme_ctrl_t c = NULL;
+ nvme_ns_t n = NULL;
+
+ char path[512];
+ void *membase;
+ int fd;
+
+ c = nvme_scan_ctrl(r, devicename);
+ if (c) {
+ snprintf(path, sizeof(path), "%s/device/resource0",
+ nvme_ctrl_get_sysfs_dir(c));
+ nvme_free_ctrl(c);
+ } else {
+ n = nvme_scan_namespace(devicename);
+ if (!n) {
+ fprintf(stderr, "Unable to find %s\n", devicename);
+ return NULL;
+ }
+ snprintf(path, sizeof(path), "%s/device/device/resource0",
+ nvme_ns_get_sysfs_dir(n));
+ nvme_free_ns(n);
+ }
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s did not find a pci resource, open failed %s\n",
+ devicename, strerror(errno));
+ return NULL;
+ }
+
+ membase = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd, 0);
+ if (membase == MAP_FAILED) {
+ fprintf(stderr, "%s failed to map. ", devicename);
+ fprintf(stderr, "Did your kernel enable CONFIG_IO_STRICT_DEVMEM?\n");
+ membase = NULL;
+ }
+
+ close(fd);
+ return membase;
}
static int show_registers(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -3740,18 +4420,19 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu
"output_format == normal";
enum nvme_print_flags flags;
+ nvme_root_t r;
bool fabrics = true;
- int fd, err = -1;
+ int fd, err;
void *bar;
struct config {
- int human_readable;
- char *output_format;
+ char *output_format;
+ bool human_readable;
};
struct config cfg = {
- .human_readable = 0,
- .output_format = "normal",
+ .output_format = "normal",
+ .human_readable = false,
};
OPT_ARGS(opts) = {
@@ -3764,6 +4445,7 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu
if (fd < 0)
goto ret;
+ r = nvme_scan(NULL);
err = flags = validate_output_format(cfg.output_format);
if (flags < 0)
goto close_fd;
@@ -3772,7 +4454,7 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu
err = nvme_get_properties(fd, &bar);
if (err) {
- bar = mmap_registers(devicename);
+ bar = mmap_registers(r, devicename);
fabrics = false;
if (bar)
err = 0;
@@ -3787,8 +4469,9 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu
munmap(bar, getpagesize());
close_fd:
close(fd);
+ nvme_free_tree(r);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_property(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -3799,17 +4482,17 @@ static int get_property(int argc, char **argv, struct command *cmd, struct plugi
const char *offset = "offset of the requested property";
const char *human_readable = "show property in readable format";
- int fd, err = -1;
- uint64_t value;
+ int fd, err;
+ __u64 value;
struct config {
- int offset;
- int human_readable;
+ int offset;
+ bool human_readable;
};
struct config cfg = {
- .offset = -1,
- .human_readable = 0,
+ .offset = -1,
+ .human_readable = false,
};
OPT_ARGS(opts) = {
@@ -3824,14 +4507,20 @@ static int get_property(int argc, char **argv, struct command *cmd, struct plugi
if (cfg.offset == -1) {
fprintf(stderr, "offset required param\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
- err = nvme_get_property(fd, cfg.offset, &value);
+ struct nvme_get_property_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .offset = cfg.offset,
+ .value = &value,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ };
+ err = nvme_get_property(&args);
if (err < 0) {
- perror("get-property");
+ fprintf(stderr, "get-property: %s\n", nvme_strerror(errno));
} else if (!err) {
nvme_show_single_property(cfg.offset, value, cfg.human_readable);
} else if (err > 0) {
@@ -3841,7 +4530,7 @@ static int get_property(int argc, char **argv, struct command *cmd, struct plugi
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int set_property(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -3850,16 +4539,16 @@ static int set_property(int argc, char **argv, struct command *cmd, struct plugi
"for NVMe ove Fabric";
const char *offset = "the offset of the property";
const char *value = "the value of the property to be set";
- int fd, err = -1;
+ int fd, err;
struct config {
- int offset;
- int value;
+ int offset;
+ int value;
};
struct config cfg = {
- .offset = -1,
- .value = -1,
+ .offset = -1,
+ .value = -1,
};
OPT_ARGS(opts) = {
@@ -3874,20 +4563,26 @@ static int set_property(int argc, char **argv, struct command *cmd, struct plugi
if (cfg.offset == -1) {
fprintf(stderr, "offset required param\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (cfg.value == -1) {
fprintf(stderr, "value required param\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
- err = nvme_set_property(fd, cfg.offset, cfg.value);
+ struct nvme_set_property_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .offset = cfg.offset,
+ .value = cfg.value,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_set_property(&args);
if (err < 0) {
- perror("set-property");
+ fprintf(stderr, "set-property: %s\n", nvme_strerror(errno));
} else if (!err) {
printf("set-property: %02x (%s), value: %#08x\n", cfg.offset,
nvme_register_to_string(cfg.offset), cfg.value);
@@ -3898,7 +4593,7 @@ static int set_property(int argc, char **argv, struct command *cmd, struct plugi
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int format(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -3908,8 +4603,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
"data erase) or delete data encryption key if specified. "\
"Can also be used to change LBAF to change the namespaces reported physical block format.";
const char *namespace_id = "identifier of desired namespace";
- const char *lbaf = "[0-63]: LBA format lower (LBAFL) and upper (LBAFU), "\
- "mention directly LBAF format that needs be applied (required)";
+ const char *lbaf = "LBA format to apply (required)";
const char *ses = "[0-2]: secure erase";
const char *pil = "[0-1]: protection info location last/first 8 bytes of metadata";
const char *pi = "[0-3]: protection info off/Type 1/Type 2/Type 3";
@@ -3920,32 +4614,34 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
const char *force = "The \"I know what I'm doing\" flag, skip confirmation before sending command";
struct nvme_id_ns ns;
struct nvme_id_ctrl ctrl;
- int err = -1, fd, i;
+ int err, fd, i;
int block_size;
__u8 prev_lbaf = 0;
struct config {
- __u32 namespace_id;
- __u32 timeout;
- __u8 lbaf;
- __u8 ses;
- __u8 pi;
- __u8 pil;
- __u8 ms;
- __u64 bs;
- int reset;
- int force;
+ __u32 namespace_id;
+ __u32 timeout;
+ __u8 lbaf;
+ __u8 ses;
+ __u8 pi;
+ __u8 pil;
+ __u8 ms;
+ bool reset;
+ bool force;
+ __u64 bs;
};
struct config cfg = {
- .namespace_id = 0,
- .timeout = 600000,
- .lbaf = 0xff,
- .ses = 0,
- .pi = 0,
- .reset = 0,
- .force = 0,
- .bs = 0,
+ .namespace_id = 0,
+ .timeout = 600000,
+ .lbaf = 0xff,
+ .ses = 0,
+ .pi = 0,
+ .pil = 0,
+ .ms = 0,
+ .reset = false,
+ .force = false,
+ .bs = 0,
};
OPT_ARGS(opts) = {
@@ -3957,20 +4653,35 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
OPT_BYTE("pil", 'p', &cfg.pil, pil),
OPT_BYTE("ms", 'm', &cfg.ms, ms),
OPT_FLAG("reset", 'r', &cfg.reset, reset),
- OPT_FLAG("force", 'f', &cfg.force, force),
+ OPT_FLAG("force", 0, &cfg.force, force),
OPT_SUFFIX("block-size", 'b', &cfg.bs, bs),
OPT_END()
};
- err = fd = parse_and_open(argc, argv, desc, opts);
- if (fd < 0)
+ err = argconfig_parse(argc, argv, desc, opts);
+ if (err)
+ goto ret;
+
+ err = fd = open_exclusive(argc, argv, cfg.force);
+ if (fd < 0) {
+ if (errno == EBUSY) {
+ 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");
+ } 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");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (cfg.bs) {
@@ -3978,15 +4689,14 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
fprintf(stderr,
"Invalid value for block size (%"PRIu64"), must be a power of two\n",
(uint64_t) cfg.bs);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
}
err = nvme_identify_ctrl(fd, &ctrl);
if (err) {
- perror("identify-ctrl");
+ fprintf(stderr, "identify-ctrl: %s\n", nvme_strerror(errno));
goto close_fd;
}
@@ -3998,9 +4708,9 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
*/
cfg.namespace_id = NVME_NSID_ALL;
} else if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
}
@@ -4010,23 +4720,22 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
"Invalid namespace ID, "
"specify a namespace to format or use '-n 0xffffffff' "
"to format all namespaces on this controller.\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (cfg.namespace_id != NVME_NSID_ALL) {
- err = nvme_identify_ns(fd, cfg.namespace_id, 0, &ns);
+ err = nvme_identify_ns(fd, cfg.namespace_id, &ns);
if (err) {
if (err < 0)
- perror("identify-namespace");
+ fprintf(stderr, "identify-namespace: %s\n", nvme_strerror(errno));
else {
fprintf(stderr, "identify failed\n");
nvme_show_status(err);
}
goto close_fd;
}
- prev_lbaf = ns.flbas & 0xf;
+ nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &prev_lbaf);
if (cfg.bs) {
for (i = 0; i < 16; ++i) {
@@ -4042,8 +4751,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
(uint64_t)cfg.bs);
fprintf(stderr,
"Please correct block size, or specify LBAF directly\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
} else if (cfg.lbaf == 0xff)
@@ -4055,32 +4763,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);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
- if (cfg.lbaf > 63) {
+ if (cfg.lbaf > 15) {
fprintf(stderr, "invalid lbaf:%d\n", cfg.lbaf);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (cfg.pi > 7) {
fprintf(stderr, "invalid pi:%d\n", cfg.pi);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (cfg.pil > 1) {
fprintf(stderr, "invalid pil:%d\n", cfg.pil);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (cfg.ms > 1) {
fprintf(stderr, "invalid ms:%d\n", cfg.ms);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
@@ -4091,15 +4794,26 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
nvme_show_relatives(devicename);
fprintf(stderr, "WARNING: Format may irrevocably delete this device's data.\n"
"You have 10 seconds to press Ctrl-C to cancel this operation.\n\n"
- "Use the force [--force|-f] option to suppress this warning.\n");
+ "Use the force [--force] option to suppress this warning.\n");
sleep(10);
fprintf(stderr, "Sending format operation ... \n");
}
- err = nvme_format(fd, cfg.namespace_id, cfg.lbaf, cfg.ses, cfg.pi,
- cfg.pil, cfg.ms, cfg.timeout);
+ struct nvme_format_nvm_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .lbaf = cfg.lbaf,
+ .mset = cfg.ms,
+ .pi = cfg.pi,
+ .pil = cfg.pil,
+ .ses = cfg.ses,
+ .timeout = cfg.timeout,
+ .result = NULL,
+ };
+ err = nvme_format_nvm(&args);
if (err < 0)
- perror("format");
+ fprintf(stderr, "format: %s\n", nvme_strerror(errno));
else if (err != 0)
nvme_show_status(err);
else {
@@ -4136,13 +4850,13 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
}
}
if (cfg.reset && is_chardev())
- nvme_reset_controller(fd);
+ nvme_ctrl_reset(fd);
}
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
#define STRTOUL_AUTO_BASE (0)
@@ -4167,30 +4881,30 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin
const char *cdw12 = "feature cdw12, if used";
const char *save = "specifies that the controller shall save the attribute";
const char *uuid_index = "specify uuid index";
- int err = -1;
+ int err;
__u32 result;
void *buf = NULL;
int fd, ffd = STDIN_FILENO;
struct config {
- char *file;
- __u32 namespace_id;
- __u8 feature_id;
- __u64 value;
- __u32 cdw12;
- __u8 uuid_index;
- __u32 data_len;
- int save;
+ __u32 namespace_id;
+ __u8 feature_id;
+ __u64 value;
+ __u32 cdw12;
+ __u8 uuid_index;
+ __u32 data_len;
+ char *file;
+ bool save;
};
struct config cfg = {
- .file = "",
- .namespace_id = 0,
- .feature_id = 0,
- .value = 0,
- .uuid_index = 0,
- .data_len = 0,
- .save = 0,
+ .namespace_id = 0,
+ .feature_id = 0,
+ .value = 0,
+ .uuid_index = 0,
+ .data_len = 0,
+ .file = "",
+ .save = false,
};
OPT_ARGS(opts) = {
@@ -4210,10 +4924,10 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin
goto ret;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
if (errno != ENOTTY) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
@@ -4223,26 +4937,24 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin
if (!cfg.feature_id) {
fprintf(stderr, "feature-id required param\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (cfg.uuid_index > 128) {
fprintf(stderr, "invalid uuid index param: %u\n", cfg.uuid_index);
- errno = EINVAL;
err = -1;
goto close_fd;
}
if (!cfg.data_len)
- cfg.data_len = nvme_feat_buf_len[cfg.feature_id];
+ nvme_get_feature_length(cfg.feature_id, cfg.value,
+ &cfg.data_len);
if (cfg.data_len) {
if (posix_memalign(&buf, getpagesize(), cfg.data_len)) {
fprintf(stderr, "can not allocate feature payload\n");
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_fd;
}
memset(buf, 0, cfg.data_len);
@@ -4255,16 +4967,15 @@ 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_TIMESTAMP == cfg.feature_id && cfg.value) {
+ if (NVME_FEAT_FID_TIMESTAMP == cfg.feature_id && 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) {
- errno = EINVAL;
fprintf(stderr, "Failed to open file %s: %s\n",
- cfg.file, strerror(errno));
- err = -1;
+ cfg.file, strerror(errno));
+ err = -EINVAL;
goto free;
}
}
@@ -4279,21 +4990,35 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin
}
}
- err = nvme_set_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.value,
- cfg.cdw12, cfg.save, cfg.uuid_index, cfg.data_len, buf, &result);
+ struct nvme_set_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = cfg.feature_id,
+ .nsid = cfg.namespace_id,
+ .cdw11 = cfg.value,
+ .cdw12 = cfg.cdw12,
+ .save = cfg.save,
+ .uuidx = cfg.uuid_index,
+ .cdw15 = 0,
+ .data_len = cfg.data_len,
+ .data = buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_set_features(&args);
if (err < 0) {
- perror("set-feature");
+ fprintf(stderr, "set-feature: %s\n", 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_LBA_STATUS_INFO) {
+ if (cfg.feature_id == NVME_FEAT_FID_LBA_STS_INTERVAL) {
nvme_show_lba_status_info(result);
}
if (buf) {
- if (cfg.feature_id == NVME_FEAT_LBA_RANGE)
+ if (cfg.feature_id == NVME_FEAT_FID_LBA_RANGE)
nvme_show_lba_range((struct nvme_lba_range_type *)buf,
result);
else
@@ -4309,7 +5034,7 @@ free:
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -4326,24 +5051,26 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p
const char *tl = "transfer length (cf. SPC-4)";
const char *namespace_id = "desired namespace";
const char *nssf = "NVMe Security Specific Field";
- int err = -1, fd, sec_fd = -1;
+ int err, fd, sec_fd = STDIN_FILENO;
void *sec_buf;
unsigned int sec_size;
struct config {
- __u32 namespace_id;
- char *file;
- __u8 nssf;
- __u8 secp;
- __u16 spsp;
- __u32 tl;
+ __u32 namespace_id;
+ char *file;
+ __u8 nssf;
+ __u8 secp;
+ __u16 spsp;
+ __u32 tl;
};
struct config cfg = {
- .file = "",
- .secp = 0,
- .spsp = 0,
- .tl = 0,
+ .namespace_id = 0,
+ .file = "",
+ .nssf = 0,
+ .secp = 0,
+ .spsp = 0,
+ .tl = 0,
};
OPT_ARGS(opts) = {
@@ -4365,16 +5092,6 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p
err = -EINVAL;
goto close_fd;
}
-
- sec_fd = open(cfg.file, O_RDONLY);
- if (sec_fd < 0) {
- fprintf(stderr, "Failed to open %s: %s\n",
- cfg.file, strerror(errno));
- errno = EINVAL;
- err = -1;
- goto close_fd;
- }
-
if ((cfg.tl & 3) != 0)
fprintf(stderr, "WARNING: --tl not dword aligned; unaligned bytes may be truncated\n");
@@ -4399,15 +5116,13 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p
sec_size = cfg.tl > sb.st_size ? cfg.tl : sb.st_size;
}
- sec_size = sb.st_size;
- if (posix_memalign(&sec_buf, getpagesize(), sec_size)) {
- fprintf(stderr, "No memory for security size:%d\n", sec_size);
- errno = ENOMEM;
- err = -1;
+ if (posix_memalign(&sec_buf, getpagesize(), cfg.tl)) {
+ fprintf(stderr, "No memory for security size:%d\n", cfg.tl);
+ err = -ENOMEM;
goto close_sec_fd;
}
- memset(sec_buf, 0, cfg.tl); // ensure zero fill if cfg.tl > sec_size
+ memset(sec_buf, 0, cfg.tl); // ensure zero fill if buf_size > sec_size
err = read(sec_fd, sec_buf, sec_size);
if (err < 0) {
@@ -4417,10 +5132,23 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p
goto free;
}
- err = nvme_sec_send(fd, cfg.namespace_id, cfg.nssf, cfg.spsp, cfg.secp,
- cfg.tl, sec_buf);
+ struct nvme_security_send_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .nssf = cfg.nssf,
+ .spsp0 = cfg.spsp & 0xff,
+ .spsp1 = cfg.spsp >> 8,
+ .secp = cfg.secp,
+ .tl = cfg.tl,
+ .data_len = cfg.tl,
+ .data = sec_buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_security_send(&args);
if (err < 0)
- perror("security-send");
+ fprintf(stderr, "security-send: %s\n", nvme_strerror(errno));
else if (err != 0)
nvme_show_status(err);
else
@@ -4433,7 +5161,7 @@ close_sec_fd:
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -4449,34 +5177,37 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p
const char *endir = "directive enable";
const char *ttype = "target directive type to be enabled/disabled";
const char *human_readable = "show directive in readable format";
- int err = -1, fd;
+ const char *input = "write/send file (default stdin)";
+ int err, fd;
__u32 result;
__u32 dw12 = 0;
void *buf = NULL;
int ffd = STDIN_FILENO;
struct config {
- char *file;
- __u32 namespace_id;
- __u32 data_len;
- __u16 dspec;
- __u8 dtype;
- __u8 doper;
- __u16 endir;
- __u8 ttype;
- int raw_binary;
- int human_readable;
+ __u32 namespace_id;
+ __u32 data_len;
+ __u8 dtype;
+ __u8 ttype;
+ __u16 dspec;
+ __u8 doper;
+ __u16 endir;
+ bool human_readable;
+ bool raw_binary;
+ char *file;
};
struct config cfg = {
- .file = "",
- .namespace_id = 1,
- .data_len = 0,
- .dspec = 0,
- .dtype = 0,
- .ttype = 0,
- .doper = 0,
- .endir = 1,
+ .namespace_id = 1,
+ .data_len = 0,
+ .dtype = 0,
+ .ttype = 0,
+ .dspec = 0,
+ .doper = 0,
+ .endir = 1,
+ .human_readable = false,
+ .raw_binary = false,
+ .file = "",
};
OPT_ARGS(opts) = {
@@ -4489,6 +5220,7 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p
OPT_SHRT("endir", 'e', &cfg.endir, endir),
OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable),
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
+ OPT_FILE("input-file", 'i', &cfg.file, input),
OPT_END()
};
@@ -4497,48 +5229,43 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p
goto ret;
switch (cfg.dtype) {
- case NVME_DIR_IDENTIFY:
+ case NVME_DIRECTIVE_DTYPE_IDENTIFY:
switch (cfg.doper) {
- case NVME_DIR_SND_ID_OP_ENABLE:
+ case NVME_DIRECTIVE_SEND_IDENTIFY_DOPER_ENDIR:
if (!cfg.ttype) {
fprintf(stderr, "target-dir required param\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
dw12 = cfg.ttype << 8 | cfg.endir;
break;
default:
fprintf(stderr, "invalid directive operations for Identify Directives\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
break;
- case NVME_DIR_STREAMS:
+ case NVME_DIRECTIVE_DTYPE_STREAMS:
switch (cfg.doper) {
- case NVME_DIR_SND_ST_OP_REL_ID:
- case NVME_DIR_SND_ST_OP_REL_RSC:
+ case NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_IDENTIFIER:
+ case NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_RESOURCE:
break;
default:
fprintf(stderr, "invalid directive operations for Streams Directives\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
break;
default:
fprintf(stderr, "invalid directive type\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (cfg.data_len) {
if (posix_memalign(&buf, getpagesize(), cfg.data_len)) {
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_fd;
}
memset(buf, 0, cfg.data_len);
@@ -4550,8 +5277,7 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p
if (ffd <= 0) {
fprintf(stderr, "Failed to open file %s: %s\n",
cfg.file, strerror(errno));
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto free;
}
}
@@ -4564,10 +5290,22 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p
}
}
- err = nvme_dir_send(fd, cfg.namespace_id, cfg.dspec, cfg.dtype, cfg.doper,
- cfg.data_len, dw12, buf, &result);
+ struct nvme_directive_send_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .dspec = cfg.dspec,
+ .doper = cfg.doper,
+ .dtype = cfg.dtype,
+ .cdw12 = dw12,
+ .data_len = cfg.data_len,
+ .data = buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_directive_send(&args);
if (err < 0) {
- perror("dir-send");
+ fprintf(stderr, "dir-send: %s\n", nvme_strerror(errno));
goto close_ffd;
}
if (!err) {
@@ -4589,12 +5327,12 @@ free:
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
- int err = -1, fd;
+ int err, fd;
const char *desc = "The Write Uncorrectable command is used to set a "\
"range of logical blocks to invalid.";
const char *namespace_id = "desired namespace";
@@ -4602,15 +5340,15 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin
const char *block_count = "number of blocks (zeroes based) on device to access";
struct config {
- __u64 start_block;
- __u32 namespace_id;
- __u16 block_count;
+ __u32 namespace_id;
+ __u64 start_block;
+ __u16 block_count;
};
struct config cfg = {
- .start_block = 0,
- .namespace_id = 0,
- .block_count = 0,
+ .namespace_id = 0,
+ .start_block = 0,
+ .block_count = 0,
};
OPT_ARGS(opts) = {
@@ -4625,17 +5363,25 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin
goto ret;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
}
- err = nvme_write_uncorrectable(fd, cfg.namespace_id, cfg.start_block,
- cfg.block_count);
+ struct nvme_io_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .slba = cfg.start_block,
+ .nlb = cfg.block_count,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_write_uncorrectable(&args);
if (err < 0)
- perror("write uncorrectable");
+ fprintf(stderr, "write uncorrectable: %s\n", nvme_strerror(errno));
else if (err != 0)
nvme_show_status(err);
else
@@ -4644,12 +5390,12 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
- int err = -1, fd;
+ int err, fd;
__u16 control = 0;
const char *desc = "The Write Zeroes command is used to set a "\
"range of logical blocks to zero.";
@@ -4657,7 +5403,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
const char *start_block = "64-bit LBA of first block to access";
const char *block_count = "number of blocks (zeroes based) on device to access";
const char *limited_retry = "limit media access attempts";
- const char *force = "force device to commit data before command completes";
+ const char *force_unit_access = "force device to commit data before command completes";
const char *prinfo = "PI and check field";
const char *ref_tag = "reference tag (for end to end PI)";
const char *app_tag_mask = "app tag mask (for end to end PI)";
@@ -4669,29 +5415,33 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
"part of end-to-end data protection processing";
struct config {
- __u64 start_block;
- __u32 namespace_id;
- __u32 ref_tag;
- __u16 app_tag;
- __u16 app_tag_mask;
- __u16 block_count;
- __u8 prinfo;
- __u64 storage_tag;
- int deac;
- int limited_retry;
- int force_unit_access;
- int storage_tag_check;
+ __u32 namespace_id;
+ __u64 start_block;
+ __u16 block_count;
+ bool deac;
+ bool limited_retry;
+ bool force_unit_access;
+ __u8 prinfo;
+ __u32 ref_tag;
+ __u16 app_tag_mask;
+ __u16 app_tag;
+ __u64 storage_tag;
+ bool storage_tag_check;
};
struct config cfg = {
- .start_block = 0,
- .block_count = 0,
- .prinfo = 0,
- .ref_tag = 0,
- .app_tag_mask = 0,
- .app_tag = 0,
- .storage_tag = 0,
- .storage_tag_check = 0,
+ .namespace_id = 0,
+ .start_block = 0,
+ .block_count = 0,
+ .deac = false,
+ .limited_retry = false,
+ .force_unit_access = false,
+ .prinfo = 0,
+ .ref_tag = 0,
+ .app_tag_mask = 0,
+ .app_tag = 0,
+ .storage_tag = 0,
+ .storage_tag_check = false,
};
OPT_ARGS(opts) = {
@@ -4700,7 +5450,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
OPT_SHRT("block-count", 'c', &cfg.block_count, block_count),
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),
+ OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force_unit_access),
OPT_BYTE("prinfo", 'p', &cfg.prinfo, prinfo),
OPT_UINT("ref-tag", 'r', &cfg.ref_tag, ref_tag),
OPT_SHRT("app-tag-mask", 'm', &cfg.app_tag_mask, app_tag_mask),
@@ -4715,33 +5465,44 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
goto ret;
if (cfg.prinfo > 0xf) {
- fprintf(stderr, "invalid prinfo: %u\n", cfg.prinfo);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
control |= (cfg.prinfo << 10);
if (cfg.limited_retry)
- control |= NVME_RW_LR;
+ control |= NVME_IO_LR;
if (cfg.force_unit_access)
- control |= NVME_RW_FUA;
+ control |= NVME_IO_FUA;
if (cfg.deac)
- control |= NVME_RW_DEAC;
+ control |= NVME_IO_DEAC;
if (cfg.storage_tag_check)
- control |= NVME_RW_STORAGE_TAG_CHECK;
+ control |= NVME_SC_STORAGE_TAG_CHECK;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
}
- err = nvme_write_zeros(fd, cfg.namespace_id, cfg.start_block, cfg.block_count,
- control, cfg.ref_tag, cfg.app_tag, cfg.app_tag_mask, cfg.storage_tag);
+ struct nvme_io_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .slba = cfg.start_block,
+ .nlb = cfg.block_count,
+ .control = control,
+ .reftag = cfg.ref_tag,
+ .apptag = cfg.app_tag,
+ .appmask = cfg.app_tag_mask,
+ .storage_tag = cfg.storage_tag,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_write_zeros(&args);
if (err < 0)
- perror("write-zeroes");
+ fprintf(stderr, "write-zeroes: %s\n", nvme_strerror(errno));
else if (err != 0)
nvme_show_status(err);
else
@@ -4750,7 +5511,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -4768,43 +5529,43 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin
const char *idr = "Attribute Integral Dataset for Read";
const char *cdw11 = "All the command DWORD 11 attributes. Use instead of specifying individual attributes";
- int err = -1, fd;
+ int err, fd;
uint16_t nr, nc, nb, ns;
- int ctx_attrs[256] = {0,};
- int nlbs[256] = {0,};
- unsigned long long slbas[256] = {0,};
- struct nvme_dsm_range *dsm;
+ __u32 ctx_attrs[256] = {0,};
+ __u32 nlbs[256] = {0,};
+ __u64 slbas[256] = {0,};
+ struct nvme_dsm_range dsm[256];
struct config {
- char *ctx_attrs;
- char *blocks;
- char *slbas;
- int ad;
- int idw;
- int idr;
- __u32 cdw11;
- __u32 namespace_id;
+ __u32 namespace_id;
+ char *ctx_attrs;
+ char *blocks;
+ char *slbas;
+ bool ad;
+ bool idw;
+ bool idr;
+ __u32 cdw11;
};
struct config cfg = {
- .ctx_attrs = "",
- .blocks = "",
- .slbas = "",
- .namespace_id = 0,
- .ad = 0,
- .idw = 0,
- .idr = 0,
- .cdw11 = 0,
+ .namespace_id = 0,
+ .ctx_attrs = "",
+ .blocks = "",
+ .slbas = "",
+ .ad = false,
+ .idw = false,
+ .idr = false,
+ .cdw11 = 0,
};
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
OPT_LIST("ctx-attrs", 'a', &cfg.ctx_attrs, context_attrs),
- OPT_LIST("blocks", 'b', &cfg.blocks, blocks),
- OPT_LIST("slbs", 's', &cfg.slbas, starting_blocks),
- OPT_FLAG("ad", 'd', &cfg.ad, ad),
- OPT_FLAG("idw", 'w', &cfg.idw, idw),
- OPT_FLAG("idr", 'r', &cfg.idr, idr),
+ OPT_LIST("blocks", 'b', &cfg.blocks, blocks),
+ OPT_LIST("slbs", 's', &cfg.slbas, starting_blocks),
+ OPT_FLAG("ad", 'd', &cfg.ad, ad),
+ OPT_FLAG("idw", 'w', &cfg.idw, idw),
+ OPT_FLAG("idr", 'r', &cfg.idr, idr),
OPT_UINT("cdw11", 'c', &cfg.cdw11, cdw11),
OPT_END()
};
@@ -4813,49 +5574,49 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin
if (fd < 0)
goto ret;
- nc = argconfig_parse_comma_sep_array(cfg.ctx_attrs, ctx_attrs, ARRAY_SIZE(ctx_attrs));
- nb = argconfig_parse_comma_sep_array(cfg.blocks, nlbs, ARRAY_SIZE(nlbs));
- ns = argconfig_parse_comma_sep_array_long(cfg.slbas, slbas, ARRAY_SIZE(slbas));
+ nc = argconfig_parse_comma_sep_array(cfg.ctx_attrs, (int *)ctx_attrs, ARRAY_SIZE(ctx_attrs));
+ nb = argconfig_parse_comma_sep_array(cfg.blocks, (int *)nlbs, ARRAY_SIZE(nlbs));
+ 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");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
}
if (!cfg.cdw11)
cfg.cdw11 = (cfg.ad << 2) | (cfg.idw << 1) | (cfg.idr << 0);
- dsm = nvme_setup_dsm_range(ctx_attrs, nlbs, slbas, nr);
- if (!dsm) {
- fprintf(stderr, "failed to allocate data set payload\n");
- errno = ENOMEM;
- err = -1;
- goto close_fd;
- }
-
- err = nvme_dsm(fd, cfg.namespace_id, cfg.cdw11, dsm, nr);
+ nvme_init_dsm_range(dsm, ctx_attrs, nlbs, slbas, nr);
+ struct nvme_dsm_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .attrs = cfg.cdw11,
+ .nr_ranges = nr,
+ .dsm = dsm,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_dsm(&args);
if (err < 0)
- perror("data-set management");
+ fprintf(stderr, "data-set management: %s\n", nvme_strerror(errno));
else if (err != 0)
nvme_show_status(err);
else
printf("NVMe DSM: success\n");
- free(dsm);
-
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -4883,62 +5644,73 @@ static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugi
const char *d_dspec = "directive specific (write part)";
const char *d_format = "source range entry format";
- int err = -1, fd;
+ int err, fd;
uint16_t nr, nb, ns, nrts, natms, nats;
- int nlbs[128] = { 0 };
+ __u16 nlbs[128] = { 0 };
unsigned long long slbas[128] = {0,};
- int eilbrts[128] = { 0 };
- int elbatms[128] = { 0 };
- int elbats[128] = { 0 };
- struct nvme_copy_range *copy;
+ __u32 eilbrts[128] = { 0 };
+ __u32 elbatms[128] = { 0 };
+ __u32 elbats[128] = { 0 };
+ struct nvme_copy_range copy[128];
struct config {
- __u32 namespace_id;
- __u64 sdlba;
- char *nlbs;
- char *slbas;
- __u32 ilbrt;
- char *eilbrts;
- __u16 lbatm;
- char *elbatms;
- __u16 lbat;
- char *elbats;
- __u8 prinfow;
- __u8 prinfor;
- int lr;
- int fua;
- __u8 dtype;
- __u16 dspec;
- __u8 format;
+ __u32 namespace_id;
+ __u64 sdlba;
+ char *slbas;
+ char *nlbs;
+ bool lr;
+ bool fua;
+ __u8 prinfow;
+ __u8 prinfor;
+ __u32 ilbrt;
+ char *eilbrts;
+ __u16 lbat;
+ char *elbatms;
+ __u16 lbatm;
+ char *elbats;
+ __u8 dtype;
+ __u16 dspec;
+ __u8 format;
};
struct config cfg = {
- .namespace_id = 0,
- .nlbs = "",
- .slbas = "",
- .eilbrts = "",
- .elbatms = "",
- .elbats = "",
+ .namespace_id = 0,
+ .sdlba = 0,
+ .slbas = "",
+ .nlbs = "",
+ .lr = false,
+ .fua = false,
+ .prinfow = 0,
+ .prinfor = 0,
+ .ilbrt = 0,
+ .eilbrts = "",
+ .lbat = 0,
+ .elbats = "",
+ .lbatm = 0,
+ .elbatms = "",
+ .dtype = 0,
+ .dspec = 0,
+ .format = 0,
};
OPT_ARGS(opts) = {
- OPT_UINT("namespace-id", 'n', &cfg.namespace_id, d_nsid),
- OPT_SUFFIX("sdlba", 'd', &cfg.sdlba, d_sdlba),
- OPT_LIST("slbs", 's', &cfg.slbas, d_slbas),
- OPT_LIST("blocks", 'b', &cfg.nlbs, d_nlbs),
- OPT_FLAG("limited-retry", 'l', &cfg.lr, d_lr),
- OPT_FLAG("force-unit-access", 'f', &cfg.fua, d_fua),
- OPT_BYTE("prinfow", 'p', &cfg.prinfow, d_prinfow),
- OPT_BYTE("prinfor", 'P', &cfg.prinfor, d_prinfor),
- OPT_UINT("ref-tag", 'r', &cfg.ilbrt, d_ilbrt),
- OPT_LIST("expected-ref-tags", 'R', &cfg.eilbrts, d_eilbrts),
- OPT_SHRT("app-tag", 'a', &cfg.lbat, d_lbat),
- OPT_LIST("expected-app-tags", 'A', &cfg.elbats, d_elbats),
- OPT_SHRT("app-tag-mask", 'm', &cfg.lbatm, d_lbatm),
- OPT_LIST("expected-app-tag-masks", 'M', &cfg.elbatms, d_elbatms),
- OPT_BYTE("dir-type", 'T', &cfg.dtype, d_dtype),
- OPT_SHRT("dir-spec", 'S', &cfg.dspec, d_dspec),
- OPT_BYTE("format", 'F', &cfg.format, d_format),
+ OPT_UINT("namespace-id", 'n', &cfg.namespace_id, d_nsid),
+ OPT_SUFFIX("sdlba", 'd', &cfg.sdlba, d_sdlba),
+ OPT_LIST("slbs", 's', &cfg.slbas, d_slbas),
+ OPT_LIST("blocks", 'b', &cfg.nlbs, d_nlbs),
+ OPT_FLAG("limited-retry", 'l', &cfg.lr, d_lr),
+ OPT_FLAG("force-unit-access", 'f', &cfg.fua, d_fua),
+ OPT_BYTE("prinfow", 'p', &cfg.prinfow, d_prinfow),
+ OPT_BYTE("prinfor", 'P', &cfg.prinfor, d_prinfor),
+ OPT_UINT("ref-tag", 'r', &cfg.ilbrt, d_ilbrt),
+ OPT_LIST("expected-ref-tags", 'R', &cfg.eilbrts, d_eilbrts),
+ OPT_SHRT("app-tag", 'a', &cfg.lbat, d_lbat),
+ OPT_LIST("expected-app-tags", 'A', &cfg.elbats, d_elbats),
+ OPT_SHRT("app-tag-mask", 'm', &cfg.lbatm, d_lbatm),
+ OPT_LIST("expected-app-tag-masks", 'M', &cfg.elbatms, d_elbatms),
+ OPT_BYTE("dir-type", 'T', &cfg.dtype, d_dtype),
+ OPT_SHRT("dir-spec", 'S', &cfg.dspec, d_dspec),
+ OPT_BYTE("format", 'F', &cfg.format, d_format),
OPT_END()
};
@@ -4948,52 +5720,61 @@ static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugi
goto ret;
}
- nb = argconfig_parse_comma_sep_array(cfg.nlbs, nlbs, ARRAY_SIZE(nlbs));
+ nb = argconfig_parse_comma_sep_array(cfg.nlbs, (int *)nlbs, ARRAY_SIZE(nlbs));
ns = argconfig_parse_comma_sep_array_long(cfg.slbas, slbas, ARRAY_SIZE(slbas));
- nrts = argconfig_parse_comma_sep_array(cfg.eilbrts, eilbrts, ARRAY_SIZE(eilbrts));
- natms = argconfig_parse_comma_sep_array(cfg.elbatms, elbatms, ARRAY_SIZE(elbatms));
- nats = argconfig_parse_comma_sep_array(cfg.elbats, elbats, ARRAY_SIZE(elbats));
+ nrts = argconfig_parse_comma_sep_array(cfg.eilbrts, (int *)eilbrts, ARRAY_SIZE(eilbrts));
+ natms = argconfig_parse_comma_sep_array(cfg.elbatms, (int *)elbatms, ARRAY_SIZE(elbatms));
+ nats = argconfig_parse_comma_sep_array(cfg.elbats, (int *)elbats, ARRAY_SIZE(elbats));
nr = max(nb, max(ns, max(nrts, max(natms, nats))));
if (!nr || nr > 128) {
fprintf(stderr, "invalid range\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
}
- copy = nvme_setup_copy_range(nlbs, slbas, eilbrts, elbatms, elbats, nr);
- if (!copy) {
- fprintf(stderr, "failed to allocate payload\n");
- errno = ENOMEM;
- err = -1;
- goto close_fd;
- }
-
- err = nvme_copy(fd, cfg.namespace_id, copy, cfg.sdlba, nr, cfg.prinfor,
- cfg.prinfow, cfg.dtype, cfg.dspec, cfg.format, cfg.lr,
- cfg.fua, cfg.ilbrt, cfg.lbatm, cfg.lbat);
+ nvme_init_copy_range(copy, nlbs, (__u64 *)slbas, eilbrts, elbatms, elbats, nr);
+
+ struct nvme_copy_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .copy = copy,
+ .sdlba = cfg.sdlba,
+ .nr = nr,
+ .prinfor = cfg.prinfor,
+ .prinfow = cfg.prinfow,
+ .dtype = cfg.dtype,
+ .dspec = cfg.dspec,
+ .format = cfg.format,
+ .lr = cfg.lr,
+ .fua = cfg.fua,
+ .ilbrt = cfg.ilbrt,
+ .lbatm = cfg.lbatm,
+ .lbat = cfg.lbat,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_copy(&args);
if (err < 0)
- perror("NVMe Copy");
+ fprintf(stderr, "NVMe Copy: %s\n", nvme_strerror(errno));
else if (err != 0)
nvme_show_status(err);
else
printf("NVMe Copy: success\n");
- free(copy);
-
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int flush(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -5004,14 +5785,14 @@ static int flush(int argc, char **argv, struct command *cmd, struct plugin *plug
"flushed by the controller, from any namespace, depending on controller and "\
"associated namespace status.";
const char *namespace_id = "identifier of desired namespace";
- int err = -1, fd;
+ int err, fd;
struct config {
- __u32 namespace_id;
+ __u32 namespace_id;
};
struct config cfg = {
- .namespace_id = 0,
+ .namespace_id = 0,
};
OPT_ARGS(opts) = {
@@ -5024,16 +5805,16 @@ static int flush(int argc, char **argv, struct command *cmd, struct plugin *plug
goto ret;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
}
err = nvme_flush(fd, cfg.namespace_id);
if (err < 0)
- perror("flush");
+ fprintf(stderr, "flush: %s\n", nvme_strerror(errno));
else if (err != 0)
nvme_show_status(err);
else
@@ -5041,7 +5822,7 @@ static int flush(int argc, char **argv, struct command *cmd, struct plugin *plug
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -5058,23 +5839,24 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi
const char *rtype = "reservation type";
const char *racqa = "reservation acquire action";
const char *iekey = "ignore existing res. key";
- int err = -1, fd;
+ int err, fd;
struct config {
- __u32 namespace_id;
- __u64 crkey;
- __u64 prkey;
- __u8 rtype;
- __u8 racqa;
- int iekey;
+ __u32 namespace_id;
+ __u64 crkey;
+ __u64 prkey;
+ __u8 rtype;
+ __u8 racqa;
+ bool iekey;
};
struct config cfg = {
- .namespace_id = 0,
- .crkey = 0,
- .prkey = 0,
- .rtype = 0,
- .racqa = 0,
+ .namespace_id = 0,
+ .crkey = 0,
+ .prkey = 0,
+ .rtype = 0,
+ .racqa = 0,
+ .iekey = false,
};
OPT_ARGS(opts) = {
@@ -5092,23 +5874,33 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi
goto ret;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
}
if (cfg.racqa > 7) {
fprintf(stderr, "invalid racqa:%d\n", cfg.racqa);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
- err = nvme_resv_acquire(fd, cfg.namespace_id, cfg.rtype, cfg.racqa,
- !!cfg.iekey, cfg.crkey, cfg.prkey);
+ struct nvme_resv_acquire_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .rtype = cfg.rtype,
+ .racqa = cfg.racqa,
+ .iekey = !!cfg.iekey,
+ .crkey = cfg.crkey,
+ .nrkey = cfg.prkey,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_resv_acquire(&args);
if (err < 0)
- perror("reservation acquire");
+ fprintf(stderr, "reservation acquire: %s\n", nvme_strerror(errno));
else if (err != 0)
nvme_show_status(err);
else
@@ -5117,7 +5909,7 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int resv_register(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -5131,23 +5923,23 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug
const char *nrkey = "new reservation key";
const char *rrega = "reservation registration action";
const char *cptpl = "change persistence through power loss setting";
- int err = -1, fd;
+ int err, fd;
struct config {
- __u32 namespace_id;
- __u64 crkey;
- __u64 nrkey;
- __u8 rrega;
- __u8 cptpl;
- int iekey;
+ __u32 namespace_id;
+ __u64 crkey;
+ __u64 nrkey;
+ __u8 rrega;
+ __u8 cptpl;
+ bool iekey;
};
struct config cfg = {
- .namespace_id = 0,
- .crkey = 0,
- .nrkey = 0,
- .rrega = 0,
- .cptpl = 0,
+ .namespace_id = 0,
+ .crkey = 0,
+ .nrkey = 0,
+ .rrega = 0,
+ .cptpl = false,
};
OPT_ARGS(opts) = {
@@ -5165,30 +5957,39 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug
goto ret;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
}
if (cfg.cptpl > 3) {
fprintf(stderr, "invalid cptpl:%d\n", cfg.cptpl);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (cfg.rrega > 7) {
fprintf(stderr, "invalid rrega:%d\n", cfg.rrega);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
- err = nvme_resv_register(fd, cfg.namespace_id, cfg.rrega, cfg.cptpl,
- !!cfg.iekey, cfg.crkey, cfg.nrkey);
+ struct nvme_resv_register_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .rrega = cfg.rrega,
+ .cptpl = cfg.cptpl,
+ .iekey = !!cfg.iekey,
+ .crkey = cfg.crkey,
+ .nrkey = cfg.nrkey,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_resv_register(&args);
if (err < 0)
- perror("reservation register");
+ fprintf(stderr, "reservation register: %s\n", nvme_strerror(errno));
else if (err != 0)
nvme_show_status(err);
else
@@ -5197,7 +5998,7 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int resv_release(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -5215,22 +6016,22 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi
const char *iekey = "ignore existing res. key";
const char *rtype = "reservation type";
const char *rrela = "reservation release action";
- int err = -1, fd;
+ int err, fd;
struct config {
- __u32 namespace_id;
- __u64 crkey;
- __u8 rtype;
- __u8 rrela;
- __u8 iekey;
+ __u32 namespace_id;
+ __u64 crkey;
+ __u8 rtype;
+ __u8 rrela;
+ __u8 iekey;
};
struct config cfg = {
- .namespace_id = 0,
- .crkey = 0,
- .rtype = 0,
- .rrela = 0,
- .iekey = 0,
+ .namespace_id = 0,
+ .crkey = 0,
+ .rtype = 0,
+ .rrela = 0,
+ .iekey = 0,
};
OPT_ARGS(opts) = {
@@ -5247,23 +6048,32 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi
goto ret;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
}
if (cfg.rrela > 7) {
fprintf(stderr, "invalid rrela:%d\n", cfg.rrela);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
- err = nvme_resv_release(fd, cfg.namespace_id, cfg.rtype, cfg.rrela,
- !!cfg.iekey, cfg.crkey);
+ struct nvme_resv_release_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .rtype = cfg.rtype,
+ .rrela = cfg.rrela,
+ .iekey = !!cfg.iekey,
+ .crkey = cfg.crkey,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_resv_release(&args);
if (err < 0)
- perror("reservation release");
+ fprintf(stderr, "reservation release: %s\n", nvme_strerror(errno));
else if (err != 0)
nvme_show_status(err);
else
@@ -5272,7 +6082,7 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int resv_report(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -5284,32 +6094,33 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin
"namespace.";
const char *namespace_id = "identifier of desired namespace";
const char *numd = "number of dwords to transfer";
- const char *cdw11 = "command dword 11 value";
+ const char *eds = "request extended data structure";
const char *raw = "dump output in binary format";
- struct nvme_reservation_status *status;
+ struct nvme_resv_status *status;
enum nvme_print_flags flags;
- int err = -1, fd, size;
+ int err, fd, size;
struct config {
- __u32 namespace_id;
- __u32 numd;
- __u32 cdw11;
- int raw_binary;
- char *output_format;
+ __u32 namespace_id;
+ __u32 numd;
+ __u8 eds;
+ char *output_format;
+ bool raw_binary;
};
struct config cfg = {
- .namespace_id = 0,
- .numd = 0,
- .cdw11 = 0,
- .output_format = "normal",
+ .namespace_id = 0,
+ .numd = 0,
+ .eds = false,
+ .output_format = "normal",
+ .raw_binary = false,
};
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
OPT_UINT("numd", 'd', &cfg.numd, numd),
- OPT_UINT("cdw11", 'c', &cfg.cdw11, cdw11),
+ OPT_FLAG("eds", 'e', &cfg.eds, eds),
OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
OPT_END()
@@ -5326,9 +6137,9 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin
flags = BINARY;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
}
@@ -5342,24 +6153,33 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin
if (posix_memalign((void **)&status, getpagesize(), size)) {
fprintf(stderr, "No memory for resv report:%d\n", size);
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_fd;
}
memset(status, 0, size);
- err = nvme_resv_report(fd, cfg.namespace_id, cfg.numd, cfg.cdw11, status);
+ struct nvme_resv_report_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .eds = cfg.eds,
+ .len = size,
+ .report = status,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_resv_report(&args);
if (!err)
- nvme_show_resv_report(status, size, cfg.cdw11, flags);
+ nvme_show_resv_report(status, size, cfg.eds, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("reservation report");
+ fprintf(stderr, "reservation report: %s\n", nvme_strerror(errno));
free(status);
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
unsigned long long elapsed_utime(struct timeval start_time,
@@ -5375,19 +6195,19 @@ static int submit_io(int opcode, char *command, const char *desc,
{
struct timeval start_time, end_time;
void *buffer, *mbuffer = NULL;
- int err = -1;
+ int err = 0;
int dfd, mfd, fd;
int flags = opcode & 1 ? O_RDONLY : O_WRONLY | O_CREAT;
int mode = S_IRUSR | S_IWUSR |S_IRGRP | S_IWGRP| S_IROTH;
__u16 control = 0;
- __u32 dsmgmt = 0, nsid = 0;
+ __u32 dsmgmt = 0;
int logical_block_size = 0;
long long buffer_size = 0, mbuffer_size = 0;
bool huge;
struct nvme_id_ns ns;
__u8 lba_index, ms = 0;
- const char *namespace_id = "desired namespace";
+ const char *namespace_id = "Identifier of desired namespace";
const char *start_block = "64-bit addr of first block to access";
const char *block_count = "number of blocks (zeroes based) on device to access";
const char *data_size = "size of data in bytes";
@@ -5400,55 +6220,66 @@ static int submit_io(int opcode, char *command, const char *desc,
const char *app_tag = "app tag (for end to end PI)";
const char *limited_retry = "limit num. media access attempts";
const char *latency = "output latency statistics";
- const char *force = "force device to commit data before command completes";
+ const char *force_unit_access = "force device to commit data before command completes";
const char *show = "show command before sending";
const char *dry = "show command instead of sending";
const char *dtype = "directive type (for write-only)";
const char *dspec = "directive specific (for write-only)";
- const char *dsm = "dataset management attributes (lower 16 bits)";
+ const char *dsm = "dataset management attributes (lower 8 bits)";
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 *storage_tag = "storage tag, CDW2 and CDW3 (00:47) bits "\
"(for end to end PI)";
+ const char *force = "The \"I know what I'm doing\" flag, do not enforce exclusive access for write";
struct config {
- __u32 namespace_id;
- __u64 start_block;
- __u16 block_count;
- __u64 data_size;
- __u64 metadata_size;
- __u32 ref_tag;
- char *data;
- char *metadata;
- __u8 prinfo;
- __u8 dtype;
- __u16 dspec;
- __u16 dsmgmt;
- __u16 app_tag_mask;
- __u16 app_tag;
- __u64 storage_tag;
- int limited_retry;
- int force_unit_access;
- int storage_tag_check;
- int show;
- int dry_run;
- int latency;
+ __u32 namespace_id;
+ __u64 start_block;
+ __u16 block_count;
+ __u64 data_size;
+ __u64 metadata_size;
+ __u32 ref_tag;
+ char *data;
+ char *metadata;
+ __u8 prinfo;
+ __u16 app_tag_mask;
+ __u16 app_tag;
+ __u64 storage_tag;
+ bool limited_retry;
+ bool force_unit_access;
+ bool storage_tag_check;
+ __u8 dtype;
+ __u16 dspec;
+ __u8 dsmgmt;
+ bool show;
+ bool dry_run;
+ bool latency;
+ bool force;
};
struct config cfg = {
.namespace_id = 0,
- .start_block = 0,
- .block_count = 0,
- .data_size = 0,
- .metadata_size = 0,
- .ref_tag = 0,
- .data = "",
- .metadata = "",
- .prinfo = 0,
- .app_tag_mask = 0,
- .app_tag = 0,
- .storage_tag_check = 0,
+ .start_block = 0,
+ .block_count = 0,
+ .data_size = 0,
+ .metadata_size = 0,
+ .ref_tag = 0,
+ .data = "",
+ .metadata = "",
+ .prinfo = 0,
+ .app_tag_mask = 0,
+ .app_tag = 0,
.storage_tag = 0,
+ .limited_retry = false,
+ .force_unit_access = false,
+ .storage_tag_check = false,
+ .dtype = 0,
+ .dspec = 0,
+ .dsmgmt = 0,
+ .show = false,
+ .dry_run = false,
+ .latency = false,
+ .force = false,
};
OPT_ARGS(opts) = {
@@ -5465,50 +6296,70 @@ static int submit_io(int opcode, char *command, const char *desc,
OPT_SHRT("app-tag", 'a', &cfg.app_tag, app_tag),
OPT_SUFFIX("storage-tag", 'g', &cfg.storage_tag, storage_tag),
OPT_FLAG("limited-retry", 'l', &cfg.limited_retry, limited_retry),
- OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force),
+ OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force_unit_access),
OPT_FLAG("storage-tag-check", 'C', &cfg.storage_tag_check, storage_tag_check),
OPT_BYTE("dir-type", 'T', &cfg.dtype, dtype),
OPT_SHRT("dir-spec", 'S', &cfg.dspec, dspec),
- OPT_SHRT("dsm", 'D', &cfg.dsmgmt, dsm),
+ OPT_BYTE("dsm", 'D', &cfg.dsmgmt, dsm),
OPT_FLAG("show-command", 'v', &cfg.show, show),
OPT_FLAG("dry-run", 'w', &cfg.dry_run, dry),
OPT_FLAG("latency", 't', &cfg.latency, latency),
+ OPT_FLAG("force", 0, &cfg.force, force),
OPT_END()
};
- err = fd = parse_and_open(argc, argv, desc, opts);
- if (fd < 0)
- goto ret;
+ if (opcode != nvme_cmd_write) {
+ err = fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ goto ret;
+ } else {
+ err = argconfig_parse(argc, argv, desc, opts);
+ if (err)
+ goto ret;
+ err = fd = open_exclusive(argc, argv, cfg.force);
+ if (err < 0) {
+ if (errno == EBUSY) {
+ 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");
+ } else {
+ argconfig_print_help(desc, opts);
+ }
+ goto ret;
+ }
+ }
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
}
dfd = mfd = opcode & 1 ? STDIN_FILENO : STDOUT_FILENO;
if (cfg.prinfo > 0xf) {
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
dsmgmt = cfg.dsmgmt;
control |= (cfg.prinfo << 10);
if (cfg.limited_retry)
- control |= NVME_RW_LR;
+ control |= NVME_IO_LR;
if (cfg.force_unit_access)
- control |= NVME_RW_FUA;
+ control |= NVME_IO_FUA;
if (cfg.storage_tag_check)
- control |= NVME_RW_STORAGE_TAG_CHECK;
+ control |= NVME_SC_STORAGE_TAG_CHECK;
if (cfg.dtype) {
if (cfg.dtype > 0xf) {
fprintf(stderr, "Invalid directive type, %x\n",
cfg.dtype);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
control |= cfg.dtype << 4;
@@ -5519,36 +6370,29 @@ static int submit_io(int opcode, char *command, const char *desc,
dfd = open(cfg.data, flags, mode);
if (dfd < 0) {
perror(cfg.data);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
- mfd = dfd;
}
+
if (strlen(cfg.metadata)) {
mfd = open(cfg.metadata, flags, mode);
if (mfd < 0) {
perror(cfg.metadata);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_dfd;
}
}
if (!cfg.data_size) {
fprintf(stderr, "data size not provided\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_mfd;
}
- if (is_ns_chardev()) {
- logical_block_size =
- nvme_logical_block_size_from_ns_char(devicename);
- } else {
- if (ioctl(fd, BLKSSZGET, &logical_block_size) < 0)
+ if (nvme_get_logical_block_size(fd, cfg.namespace_id,
+ &logical_block_size) < 0)
goto close_mfd;
- }
buffer_size = (cfg.block_count + 1) * logical_block_size;
if (cfg.data_size < buffer_size) {
@@ -5560,27 +6404,20 @@ static int submit_io(int opcode, char *command, const char *desc,
buffer = nvme_alloc(buffer_size, &huge);
if (!buffer) {
- perror("can not allocate io payload\n");
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_mfd;
}
if (cfg.metadata_size) {
- err = nsid = nvme_get_nsid(fd);
- if (err < 0) {
- perror("get-namespace-id");
- goto close_mfd;
- }
- err = nvme_identify_ns(fd, nsid, false, &ns);
+ err = nvme_identify_ns(fd, cfg.namespace_id, &ns);
if (err) {
nvme_show_status(err);
goto free_buffer;
} else if (err < 0) {
- perror("identify namespace");
+ fprintf(stderr, "identify namespace: %s\n", nvme_strerror(errno));
goto free_buffer;
}
- lba_index = ns.flbas & NVME_NS_FLBAS_LBA_MASK;
+ nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &lba_index);
ms = ns.lbaf[lba_index].ms;
mbuffer_size = (cfg.block_count + 1) * ms;
if (ms && cfg.metadata_size < mbuffer_size) {
@@ -5591,9 +6428,7 @@ static int submit_io(int opcode, char *command, const char *desc,
}
mbuffer = malloc(mbuffer_size);
if (!mbuffer) {
- perror("can not allocate buf for io metadata payload\n");
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto free_buffer;
}
memset(mbuffer, 0, mbuffer_size);
@@ -5619,48 +6454,68 @@ static int submit_io(int opcode, char *command, const char *desc,
}
}
- if (cfg.show) {
- printf("opcode : %02x\n", opcode);
- printf("nsid : %02x\n", cfg.namespace_id);
- printf("control : %04x\n", control);
- printf("nblocks : %04x\n", cfg.block_count);
- printf("metadata : %"PRIx64"\n", (uint64_t)(uintptr_t)mbuffer);
- printf("addr : %"PRIx64"\n", (uint64_t)(uintptr_t)buffer);
- printf("slba : %"PRIx64"\n", (uint64_t)cfg.start_block);
- printf("dsmgmt : %08x\n", dsmgmt);
- printf("reftag : %08x\n", cfg.ref_tag);
- printf("apptag : %04x\n", cfg.app_tag);
- printf("appmask : %04x\n", cfg.app_tag_mask);
+ if (cfg.show || cfg.dry_run) {
+ printf("opcode : %02x\n", opcode);
+ printf("nsid : %02x\n", cfg.namespace_id);
+ printf("flags : %02x\n", 0);
+ printf("control : %04x\n", control);
+ printf("nblocks : %04x\n", cfg.block_count);
+ printf("metadata : %"PRIx64"\n", (uint64_t)(uintptr_t)mbuffer);
+ printf("addr : %"PRIx64"\n", (uint64_t)(uintptr_t)buffer);
+ printf("slba : %"PRIx64"\n", (uint64_t)cfg.start_block);
+ printf("dsmgmt : %08x\n", dsmgmt);
+ printf("reftag : %08x\n", cfg.ref_tag);
+ printf("apptag : %04x\n", cfg.app_tag);
+ printf("appmask : %04x\n", cfg.app_tag_mask);
printf("storagetagcheck : %04x\n", cfg.storage_tag_check);
printf("storagetag : %"PRIx64"\n", (uint64_t)cfg.storage_tag);
}
if (cfg.dry_run)
goto free_mbuffer;
+ struct nvme_io_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .slba = cfg.start_block,
+ .nlb = cfg.block_count,
+ .control = control,
+ .dsm = cfg.dsmgmt,
+ .dspec = cfg.dspec,
+ .reftag = cfg.ref_tag,
+ .apptag = cfg.app_tag,
+ .appmask = cfg.app_tag_mask,
+ .storage_tag = cfg.storage_tag,
+ .data_len = buffer_size,
+ .data = buffer,
+ .metadata_len = cfg.metadata_size,
+ .metadata = mbuffer,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
gettimeofday(&start_time, NULL);
- err = nvme_io(fd, opcode, cfg.namespace_id, cfg.start_block, cfg.block_count,
- control, dsmgmt, cfg.ref_tag, cfg.app_tag, cfg.app_tag_mask,
- cfg.storage_tag, buffer, buffer_size, mbuffer, mbuffer_size);
+ if (opcode & 1)
+ err = nvme_write(&args);
+ else
+ err = nvme_read(&args);
gettimeofday(&end_time, NULL);
if (cfg.latency)
printf(" latency: %s: %llu us\n",
command, elapsed_utime(start_time, end_time));
if (err < 0)
- perror("submit-io");
+ fprintf(stderr, "submit-io: %s\n", 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));
- errno = EINVAL;
- err = -1;
+ 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));
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
} else
fprintf(stderr, "%s: Success\n", command);
}
@@ -5677,7 +6532,7 @@ close_dfd:
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int compare(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -5705,14 +6560,14 @@ static int write_cmd(int argc, char **argv, struct command *cmd, struct plugin *
static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
- int err = -1, fd;
+ int err, fd;
__u16 control = 0;
const char *desc = "Verify specified logical blocks on the given device.";
const char *namespace_id = "desired namespace";
const char *start_block = "64-bit LBA of first block to access";
const char *block_count = "number of blocks (zeroes based) on device to access";
const char *limited_retry = "limit media access attempts";
- const char *force = "force device to commit cached data before performing the verify operation";
+ const char *force_unit_access = "force device to commit cached data before performing the verify operation";
const char *prinfo = "PI and check field";
const char *ref_tag = "reference tag (for end to end PI)";
const char *app_tag_mask = "app tag mask (for end to end PI)";
@@ -5723,31 +6578,31 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin
"be checked as part of Verify operation";
struct config {
- __u64 start_block;
- __u32 namespace_id;
- __u32 ref_tag;
- __u16 app_tag;
- __u16 app_tag_mask;
- __u16 block_count;
- __u8 prinfo;
- __u64 storage_tag;
- int storage_tag_check;
- int limited_retry;
- int force_unit_access;
+ __u32 namespace_id;
+ __u64 start_block;
+ __u16 block_count;
+ bool limited_retry;
+ bool force_unit_access;
+ __u8 prinfo;
+ __u32 ref_tag;
+ __u16 app_tag;
+ __u16 app_tag_mask;
+ __u64 storage_tag;
+ bool storage_tag_check;
};
struct config cfg = {
- .namespace_id = 0,
- .start_block = 0,
- .block_count = 0,
- .prinfo = 0,
- .ref_tag = 0,
- .app_tag = 0,
- .app_tag_mask = 0,
- .limited_retry = 0,
- .force_unit_access = 0,
- .storage_tag = 0,
- .storage_tag_check = 0,
+ .namespace_id = 0,
+ .start_block = 0,
+ .block_count = 0,
+ .limited_retry = false,
+ .force_unit_access = false,
+ .prinfo = 0,
+ .ref_tag = 0,
+ .app_tag = 0,
+ .app_tag_mask = 0,
+ .storage_tag = 0,
+ .storage_tag_check = false,
};
OPT_ARGS(opts) = {
@@ -5755,7 +6610,7 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin
OPT_SUFFIX("start-block", 's', &cfg.start_block, start_block),
OPT_SHRT("block-count", 'c', &cfg.block_count, block_count),
OPT_FLAG("limited-retry", 'l', &cfg.limited_retry, limited_retry),
- OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force),
+ OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force_unit_access),
OPT_BYTE("prinfo", 'p', &cfg.prinfo, prinfo),
OPT_UINT("ref-tag", 'r', &cfg.ref_tag, ref_tag),
OPT_SHRT("app-tag", 'a', &cfg.app_tag, app_tag),
@@ -5770,32 +6625,43 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin
goto ret;
if (cfg.prinfo > 0xf) {
- fprintf(stderr, "invalid 'prinfo' param:%u\n", cfg.prinfo);
- errno = EINVAL;
- err = -1;
+ err = EINVAL;
goto close_fd;
}
control |= (cfg.prinfo << 10);
if (cfg.limited_retry)
- control |= NVME_RW_LR;
+ control |= NVME_IO_LR;
if (cfg.force_unit_access)
- control |= NVME_RW_FUA;
+ control |= NVME_IO_FUA;
if (cfg.storage_tag_check)
- control |= NVME_RW_STORAGE_TAG_CHECK;
+ control |= NVME_SC_STORAGE_TAG_CHECK;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
- perror("get-namespace-id");
+ fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno));
goto close_fd;
}
}
- err = nvme_verify(fd, cfg.namespace_id, cfg.start_block, cfg.block_count,
- control, cfg.ref_tag, cfg.app_tag, cfg.app_tag_mask, cfg.storage_tag);
+ struct nvme_io_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .slba = cfg.start_block,
+ .nlb = cfg.block_count,
+ .control = control,
+ .reftag = cfg.ref_tag,
+ .apptag = cfg.app_tag,
+ .appmask = cfg.app_tag_mask,
+ .storage_tag = cfg.storage_tag,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_verify(&args);
if (err < 0)
- perror("verify");
+ fprintf(stderr, "verify: %s\n", nvme_strerror(errno));
else if (err != 0)
nvme_show_status(err);
else
@@ -5804,7 +6670,7 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);;
+ return err;
}
static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -5822,24 +6688,27 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p
const char *raw = "dump output in binary format";
const char *namespace_id = "desired namespace";
const char *nssf = "NVMe Security Specific Field";
- int err = -1, fd;
+ int err, fd;
void *sec_buf = NULL;
struct config {
- __u32 namespace_id;
- __u32 size;
- __u8 secp;
- __u8 nssf;
- __u16 spsp;
- __u32 al;
- int raw_binary;
+ __u32 namespace_id;
+ __u32 size;
+ __u8 nssf;
+ __u8 secp;
+ __u16 spsp;
+ __u32 al;
+ bool raw_binary;
};
struct config cfg = {
- .size = 0,
- .secp = 0,
- .spsp = 0,
- .al = 0,
+ .namespace_id = 0,
+ .size = 0,
+ .nssf = 0,
+ .secp = 0,
+ .spsp = 0,
+ .al = 0,
+ .raw_binary = false,
};
OPT_ARGS(opts) = {
@@ -5861,16 +6730,28 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p
if (posix_memalign(&sec_buf, getpagesize(), cfg.size)) {
fprintf(stderr, "No memory for security size:%d\n",
cfg.size);
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_fd;
}
}
- err = nvme_sec_recv(fd, cfg.namespace_id, cfg.nssf, cfg.spsp,
- cfg.secp, cfg.al, cfg.size, sec_buf);
+ struct nvme_security_receive_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .nssf = cfg.nssf,
+ .spsp0 = cfg.spsp & 0xff,
+ .spsp1 = cfg.spsp >> 8,
+ .secp = cfg.secp,
+ .al = cfg.al,
+ .data_len = cfg.size,
+ .data = sec_buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_security_receive(&args);
if (err < 0)
- perror("security receive");
+ fprintf(stderr, "security receive: %s\n", nvme_strerror(errno));
else if (err != 0)
nvme_show_status(err);
else {
@@ -5886,7 +6767,7 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int get_lba_status(int argc, char **argv, struct command *cmd,
@@ -5907,27 +6788,27 @@ static int get_lba_status(int argc, char **argv, struct command *cmd,
enum nvme_print_flags flags;
unsigned long buf_len;
- int err = -1, fd;
+ int err, fd;
void *buf;
struct config {
- __u32 namespace_id;
- __u64 slba;
- __u32 mndw;
- __u8 atype;
- __u16 rl;
- __u32 timeout;
- char *output_format;
+ __u32 namespace_id;
+ __u64 slba;
+ __u32 mndw;
+ __u8 atype;
+ __u16 rl;
+ __u32 timeout;
+ char *output_format;
};
struct config cfg = {
- .namespace_id = 0,
- .slba = 0,
- .mndw = 0,
- .atype = 0,
- .rl = 0,
- .timeout = 0,
- .output_format = "normal",
+ .namespace_id = 0,
+ .slba = 0,
+ .mndw = 0,
+ .atype = 0,
+ .rl = 0,
+ .timeout = 0,
+ .output_format = "normal",
};
OPT_ARGS(opts) = {
@@ -5951,33 +6832,41 @@ static int get_lba_status(int argc, char **argv, struct command *cmd,
if (!cfg.atype) {
fprintf(stderr, "action type (--action) has to be given\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
buf_len = (cfg.mndw + 1) * 4;
buf = calloc(1, buf_len);
if (!buf) {
- perror("could not alloc memory for get lba status");
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_fd;
}
- err = nvme_get_lba_status(fd, cfg.namespace_id, cfg.slba, cfg.mndw,
- cfg.atype, cfg.rl, buf, cfg.timeout);
+ struct nvme_get_lba_status_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .slba = cfg.slba,
+ .mndw = cfg.mndw,
+ .rl = cfg.rl,
+ .atype = cfg.atype,
+ .lbas = buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_get_lba_status(&args);
if (!err)
nvme_show_lba_status(buf, buf_len, flags);
else if (err > 0)
nvme_show_status(err);
else
- perror("get lba status");
+ fprintf(stderr, "get lba status: %s\n", nvme_strerror(errno));
free(buf);
close_fd:
close(fd);
err:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -5997,23 +6886,23 @@ static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plug
__u32 result;
struct config {
- __u8 operation;
- __u16 element_id;
- __u32 dw11;
- __u32 dw12;
+ __u8 operation;
+ __u16 element_id;
+ __u32 dw11;
+ __u32 dw12;
};
struct config cfg = {
- .operation = 0xff,
- .element_id = 0xffff,
- .dw11 = 0,
- .dw12 = 0,
+ .operation = 0xff,
+ .element_id = 0xffff,
+ .dw11 = 0,
+ .dw12 = 0,
};
OPT_ARGS(opts) = {
OPT_BYTE("operation", 'o', &cfg.operation, operation),
OPT_SHRT("element-id", 'i', &cfg.element_id, element_id),
- OPT_UINT("cap-lower", 'l', &cfg.dw11, cap_lower),
+ OPT_UINT("cap-lower", 'l', &cfg.dw11, cap_lower),
OPT_UINT("cap-upper", 'u', &cfg.dw12, cap_upper),
OPT_END()
};
@@ -6024,13 +6913,21 @@ static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plug
if (cfg.operation > 0xf) {
fprintf(stderr, "invalid operation field: %u\n", cfg.operation);
- errno = EINVAL;
err = -1;
goto close_fd;
}
- err = nvme_cap_mgmt(fd, cfg.operation, cfg.element_id, cfg.dw11,
- cfg.dw12, &result);
+ struct nvme_capacity_mgmt_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .op = cfg.operation,
+ .element_id = cfg.element_id,
+ .cdw11 = cfg.dw11,
+ .cdw12 = cfg.dw12,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_capacity_mgmt(&args);
if (!err) {
printf("Capacity Management Command is Success\n");
if (cfg.operation == 1) {
@@ -6041,12 +6938,12 @@ static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plug
} else if (err > 0)
nvme_show_status(err);
else if (err < 0)
- perror("capacity management");
+ fprintf(stderr, "capacity management: %s\n", nvme_strerror(errno));
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -6063,29 +6960,31 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin
const char *human_readable = "show directive in readable format";
enum nvme_print_flags flags = NORMAL;
- int err = -1, fd;
+ int err, fd;
__u32 result;
__u32 dw12 = 0;
void *buf = NULL;
struct config {
- __u32 namespace_id;
- __u32 data_len;
- __u16 dspec;
- __u8 dtype;
- __u8 doper;
- __u16 nsr; /* dw12 for NVME_DIR_ST_RCVOP_STATUS */
- int raw_binary;
- int human_readable;
+ __u32 namespace_id;
+ __u32 data_len;
+ bool raw_binary;
+ __u8 dtype;
+ __u16 dspec;
+ __u8 doper;
+ __u16 nsr; /* dw12 for NVME_DIR_ST_RCVOP_STATUS */
+ bool human_readable;
};
struct config cfg = {
- .namespace_id = 1,
- .data_len = 0,
- .dspec = 0,
- .dtype = 0,
- .doper = 0,
- .nsr = 0,
+ .namespace_id = 1,
+ .data_len = 0,
+ .raw_binary = false,
+ .dtype = 0,
+ .dspec = 0,
+ .doper = 0,
+ .nsr = 0,
+ .human_readable = false,
};
OPT_ARGS(opts) = {
@@ -6110,57 +7009,65 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin
flags = BINARY;
switch (cfg.dtype) {
- case NVME_DIR_IDENTIFY:
+ case NVME_DIRECTIVE_DTYPE_IDENTIFY:
switch (cfg.doper) {
- case NVME_DIR_RCV_ID_OP_PARAM:
+ case NVME_DIRECTIVE_RECEIVE_IDENTIFY_DOPER_PARAM:
if (!cfg.data_len)
cfg.data_len = 4096;
break;
default:
fprintf(stderr, "invalid directive operations for Identify Directives\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
break;
- case NVME_DIR_STREAMS:
+ case NVME_DIRECTIVE_DTYPE_STREAMS:
switch (cfg.doper) {
- case NVME_DIR_RCV_ST_OP_PARAM:
+ case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM:
if (!cfg.data_len)
cfg.data_len = 32;
break;
- case NVME_DIR_RCV_ST_OP_STATUS:
+ case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_STATUS:
if (!cfg.data_len)
cfg.data_len = 128 * 1024;
break;
- case NVME_DIR_RCV_ST_OP_RESOURCE:
+ case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_RESOURCE:
dw12 = cfg.nsr;
break;
default:
fprintf(stderr, "invalid directive operations for Streams Directives\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
break;
default:
fprintf(stderr, "invalid directive type\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
if (cfg.data_len) {
if (posix_memalign(&buf, getpagesize(), cfg.data_len)) {
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto close_fd;
}
memset(buf, 0, cfg.data_len);
}
- err = nvme_dir_recv(fd, cfg.namespace_id, cfg.dspec, cfg.dtype, cfg.doper,
- cfg.data_len, dw12, buf, &result);
+ struct nvme_directive_recv_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .dspec = cfg.dspec,
+ .doper = cfg.doper,
+ .dtype = cfg.dtype,
+ .cdw12 = dw12,
+ .data_len = cfg.data_len,
+ .data = buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_directive_recv(&args);
if (!err)
nvme_directive_show(cfg.dtype, cfg.doper, cfg.dspec,
cfg.namespace_id, result, buf, cfg.data_len,
@@ -6168,13 +7075,13 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin
else if (err > 0)
nvme_show_status(err);
else if (err < 0)
- perror("dir-receive");
+ fprintf(stderr, "dir-receive: %s\n", nvme_strerror(errno));
free(buf);
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
/* rpmb_cmd_option is defined in nvme-rpmb.c */
@@ -6208,23 +7115,23 @@ static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugi
int fd, err = -1;
struct config {
- __u8 ofi;
- __u8 ifc;
- __u8 prhbt;
- __u8 scp;
- __u8 uuid;
+ __u8 ofi;
+ __u8 ifc;
+ __u8 prhbt;
+ __u8 scp;
+ __u8 uuid;
};
struct config cfg = {
- .ofi = 0,
- .ifc = 0,
- .prhbt = 0,
- .scp = 0,
- .uuid = 0,
+ .ofi = 0,
+ .ifc = 0,
+ .prhbt = 0,
+ .scp = 0,
+ .uuid = 0,
};
OPT_ARGS(opts) = {
- OPT_BYTE("ofi", 'o', &cfg.ofi, ofi_desc),
+ OPT_BYTE("ofi", 'o', &cfg.ofi, ofi_desc),
OPT_BYTE("ifc", 'f', &cfg.ifc, ifc_desc),
OPT_BYTE("prhbt", 'p', &cfg.prhbt, prhbt_desc),
OPT_BYTE("scp", 's', &cfg.scp, scp_desc),
@@ -6239,34 +7146,39 @@ static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugi
/* check for input arguement limit */
if (cfg.ifc > 3) {
fprintf(stderr, "invalid interface settings:%d\n", cfg.ifc);
- errno = EINVAL;
err = -1;
goto close_fd;
}
if (cfg.prhbt > 1) {
fprintf(stderr, "invalid prohibit settings:%d\n", cfg.prhbt);
- errno = EINVAL;
err = -1;
goto close_fd;
}
if (cfg.scp > 15) {
fprintf(stderr, "invalid scope settings:%d\n", cfg.scp);
- errno = EINVAL;
err = -1;
goto close_fd;
}
if (cfg.uuid > 127) {
fprintf(stderr, "invalid UUID index settings:%d\n", cfg.uuid);
- errno = EINVAL;
err = -1;
goto close_fd;
}
- err = nvme_lockdown(fd, cfg.scp,cfg.prhbt,cfg.ifc,cfg.ofi,
- cfg.uuid);
-
+ struct nvme_lockdown_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .scp = cfg.scp,
+ .prhbt = cfg.prhbt,
+ .ifc = cfg.ifc,
+ .ofi = cfg.ofi,
+ .uuidx = cfg.uuid,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_lockdown(&args);
if (err < 0)
- perror("lockdown");
+ fprintf(stderr, "lockdown: %s\n", nvme_strerror(errno));
else if (err > 0)
nvme_show_status(err);
else
@@ -6275,18 +7187,19 @@ static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugi
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
-static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type,
- const char *desc, struct command *cmd)
+static int passthru(int argc, char **argv, bool admin,
+ const char *desc, struct command *cmd)
{
const char *opcode = "opcode (required)";
- const char *flags = "command flags";
+ const char *cflags = "command flags";
const char *rsvd = "value for reserved field";
const char *namespace_id = "desired namespace";
const char *data_len = "data I/O length (bytes)";
const char *metadata_len = "metadata seg. length (bytes)";
+ const char *metadata = "metadata input or output file";
const char *timeout = "timeout value, in milliseconds";
const char *cdw2 = "command dword 2 value";
const char *cdw3 = "command dword 3 value";
@@ -6296,7 +7209,7 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type,
const char *cdw13 = "command dword 13 value";
const char *cdw14 = "command dword 14 value";
const char *cdw15 = "command dword 15 value";
- const char *input = "write/send file (default stdin)";
+ const char *input = "data input or output file";
const char *raw_binary = "dump output in binary format";
const char *show = "print command before sending";
const char *dry = "show command instead of sending";
@@ -6305,62 +7218,72 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type,
const char *prefill = "prefill buffers with known byte-value, default 0";
const char *latency = "output latency statistics";
- void *data = NULL, *metadata = NULL;
- int err = -1, wfd = STDIN_FILENO, fd;
+ int flags;
+ int mode = S_IRUSR | S_IWUSR |S_IRGRP | S_IWGRP| S_IROTH;
+ void *data = NULL, *mdata = NULL;
+ int err = 0, dfd, mfd, fd;
__u32 result;
- bool huge;
+ bool huge = false;
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;
- int raw_binary;
- int show_command;
- int dry_run;
- int read;
- int write;
- __u8 prefill;
- int latency;
+ __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 = {
- .opcode = 0,
- .flags = 0,
- .rsvd = 0,
- .namespace_id = 0,
- .data_len = 0,
- .metadata_len = 0,
- .timeout = 0,
- .cdw2 = 0,
- .cdw3 = 0,
- .cdw10 = 0,
- .cdw11 = 0,
- .cdw12 = 0,
- .cdw13 = 0,
- .cdw14 = 0,
- .cdw15 = 0,
- .input_file = "",
- .prefill = 0,
+ .opcode = 0,
+ .flags = 0,
+ .prefill = 0,
+ .rsvd = 0,
+ .namespace_id = 0,
+ .data_len = 0,
+ .metadata_len = 0,
+ .timeout = 0,
+ .cdw2 = 0,
+ .cdw3 = 0,
+ .cdw10 = 0,
+ .cdw11 = 0,
+ .cdw12 = 0,
+ .cdw13 = 0,
+ .cdw14 = 0,
+ .cdw15 = 0,
+ .input_file = "",
+ .metadata = "",
+ .raw_binary = false,
+ .show_command = false,
+ .dry_run = false,
+ .read = false,
+ .write = false,
+ .latency = false,
};
OPT_ARGS(opts) = {
OPT_BYTE("opcode", 'o', &cfg.opcode, opcode),
- OPT_BYTE("flags", 'f', &cfg.flags, flags),
+ OPT_BYTE("flags", 'f', &cfg.flags, cflags),
OPT_BYTE("prefill", 'p', &cfg.prefill, prefill),
OPT_SHRT("rsvd", 'R', &cfg.rsvd, rsvd),
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
@@ -6376,6 +7299,7 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type,
OPT_UINT("cdw14", '8', &cfg.cdw14, cdw14),
OPT_UINT("cdw15", '9', &cfg.cdw15, cdw15),
OPT_FILE("input-file", 'i', &cfg.input_file, input),
+ OPT_FILE("metadata", 'M', &cfg.metadata, metadata),
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_binary),
OPT_FLAG("show-command", 's', &cfg.show_command, show),
OPT_FLAG("dry-run", 'd', &cfg.dry_run, dry),
@@ -6389,33 +7313,47 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type,
if (fd < 0)
goto ret;
+ flags = cfg.opcode & 1 ? O_RDONLY : O_WRONLY | O_CREAT;
+ dfd = mfd = cfg.opcode & 1 ? STDIN_FILENO : STDOUT_FILENO;
if (strlen(cfg.input_file)) {
- wfd = open(cfg.input_file, O_RDONLY,
- S_IRUSR | S_IRGRP | S_IROTH);
- if (wfd < 0) {
+ dfd = open(cfg.input_file, flags, mode);
+ if (dfd < 0) {
perror(cfg.input_file);
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto close_fd;
}
}
+ if (cfg.metadata && strlen(cfg.metadata)) {
+ mfd = open(cfg.metadata, flags, mode);
+ if (mfd < 0) {
+ perror(cfg.metadata);
+ err = -EINVAL;
+ goto close_dfd;
+ }
+ }
+
if (cfg.metadata_len) {
- metadata = malloc(cfg.metadata_len);
- if (!metadata) {
- perror("can not allocate metadata payload\n");
- errno = ENOMEM;
- err = -1;
- goto close_wfd;
+ mdata = malloc(cfg.metadata_len);
+ if (!mdata) {
+ err = -ENOMEM;
+ goto close_mfd;
}
- memset(metadata, cfg.prefill, cfg.metadata_len);
+
+ if (cfg.write) {
+ if (read(mfd, mdata, cfg.metadata_len) < 0) {
+ err = -errno;
+ perror("failed to read metadata write buffer");
+ goto free_metadata;
+ }
+ } else
+ memset(mdata, cfg.prefill, cfg.metadata_len);
}
+
if (cfg.data_len) {
data = nvme_alloc(cfg.data_len, &huge);
if (!data) {
- perror("can not allocate data payload\n");
- errno = ENOMEM;
- err = -1;
+ err = -ENOMEM;
goto free_metadata;
}
@@ -6430,11 +7368,10 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type,
memset(data, cfg.prefill, cfg.data_len);
if (!cfg.read && !cfg.write) {
fprintf(stderr, "data direction not given\n");
- errno = EINVAL;
- err = -1;
+ err = -EINVAL;
goto free_data;
} else if (cfg.write) {
- if (read(wfd, data, cfg.data_len) < 0) {
+ if (read(dfd, data, cfg.data_len) < 0) {
err = -errno;
fprintf(stderr, "failed to read write buffer "
"%s\n", strerror(errno));
@@ -6443,7 +7380,7 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type,
}
}
- if (cfg.show_command) {
+ if (cfg.show_command || cfg.dry_run) {
printf("opcode : %02x\n", cfg.opcode);
printf("flags : %02x\n", cfg.flags);
printf("rsvd1 : %04x\n", cfg.rsvd);
@@ -6453,7 +7390,7 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type,
printf("data_len : %08x\n", cfg.data_len);
printf("metadata_len : %08x\n", cfg.metadata_len);
printf("addr : %"PRIx64"\n", (uint64_t)(uintptr_t)data);
- printf("metadata : %"PRIx64"\n", (uint64_t)(uintptr_t)metadata);
+ printf("metadata : %"PRIx64"\n", (uint64_t)(uintptr_t)mdata);
printf("cdw10 : %08x\n", cfg.cdw10);
printf("cdw11 : %08x\n", cfg.cdw11);
printf("cdw12 : %08x\n", cfg.cdw12);
@@ -6467,86 +7404,90 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type,
gettimeofday(&start_time, NULL);
- err = nvme_passthru(fd, ioctl_cmd, cfg.opcode, cfg.flags, cfg.rsvd,
+ if (admin)
+ err = nvme_admin_passthru(fd, 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, metadata,
- cfg.timeout, &result);
+ 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(fd, 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);
gettimeofday(&end_time, NULL);
- cmd_name = nvme_cmd_to_string(cmd_type, cfg.opcode);
+ cmd_name = nvme_cmd_to_string(admin, cfg.opcode);
if (cfg.latency)
printf("%s Command %s latency: %llu us\n",
- cmd_type ? "Admin": "IO",
+ admin ? "Admin": "IO",
strcmp(cmd_name, "Unknown") ? cmd_name: "Vendor Specific",
elapsed_utime(start_time, end_time));
if (err < 0)
- perror("passthru");
+ fprintf(stderr, "passthru: %s\n", nvme_strerror(errno));
else if (err)
nvme_show_status(err);
else {
fprintf(stderr, "%s Command %s is Success and result: 0x%08x\n",
- cmd_type ? "Admin": "IO",
+ admin ? "Admin": "IO",
strcmp(cmd_name, "Unknown") ? cmd_name: "Vendor Specific",
result);
- if (!cfg.raw_binary) {
+ if (cfg.read && 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);
}
+free_metadata:
+ free(mdata);
free_data:
nvme_free(data, huge);
-free_metadata:
- free(metadata);
-close_wfd:
+close_dfd:
if (strlen(cfg.input_file))
- close(wfd);
+ close(dfd);
+close_mfd:
+ if (strlen(cfg.metadata))
+ close(mfd);
close_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
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.";
- return passthru(argc, argv, NVME_IOCTL_IO_CMD, 0, desc, cmd);
+ 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.";
- return passthru(argc, argv, NVME_IOCTL_ADMIN_CMD, 1, desc, cmd);
+ return passthru(argc, argv, true, desc, cmd);
}
static int gen_hostnqn_cmd(int argc, char **argv, struct command *command, struct plugin *plugin)
{
- int ret;
- char uuid_str[37]; /* e.g. 1b4e28ba-2fa1-11d2-883f-0016d3cca427 + \0 */
-#ifdef LIBUUID
- uuid_t uuid;
-#endif
+ char *hostnqn;
- ret = uuid_from_dmi(uuid_str);
- if (ret < 0)
- ret = uuid_from_systemd(uuid_str);
-#ifdef LIBUUID
- if (ret < 0) {
- uuid_generate_random(uuid);
- uuid_unparse_lower(uuid, uuid_str);
- ret = 0;
- }
-#endif
- if (ret < 0) {
+ hostnqn = nvmf_hostnqn_generate();
+ if (!hostnqn) {
fprintf(stderr, "\"%s\" not supported. Install lib uuid and rebuild.\n",
command->name);
return -ENOTSUP;
}
- printf("nqn.2014-08.org.nvmexpress:uuid:%s\n", uuid_str);
+ printf("%s\n", hostnqn);
+ free(hostnqn);
return 0;
}
@@ -6554,45 +7495,468 @@ static int show_hostnqn_cmd(int argc, char **argv, struct command *command, stru
{
char *hostnqn;
- hostnqn = hostnqn_read();
- if (hostnqn) {
- fputs(hostnqn, stdout);
- free(hostnqn);
- return 0;
- } else {
+ hostnqn = nvmf_hostnqn_from_file();
+ if (!hostnqn)
+ hostnqn = nvmf_hostnqn_generate();
+
+ if (!hostnqn) {
fprintf(stderr, "hostnqn is not available -- use nvme gen-hostnqn\n");
- return -ENOENT;
+ return ENOENT;
+ }
+
+ fprintf(stdout, "%s\n", hostnqn);
+ free(hostnqn);
+
+ return 0;
+}
+
+
+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 *nqn = "Host NQN to use for key transformation.";
+
+ unsigned char *raw_secret;
+ unsigned char key[68];
+ char encoded_key[128];
+ unsigned long crc = crc32(0L, NULL, 0);
+ int err = 0;
+
+ struct config {
+ char *secret;
+ unsigned int key_len;
+ char *nqn;
+ unsigned int hmac;
+ };
+
+ struct config cfg = {
+ .secret = NULL,
+ .key_len = 0,
+ .nqn = NULL,
+ .hmac = 0,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_STR("secret", 's', &cfg.secret, secret),
+ OPT_UINT("key-length", 'l', &cfg.key_len, key_len),
+ OPT_STR("nqn", 'n', &cfg.nqn, nqn),
+ OPT_UINT("hmac", 'm', &cfg.hmac, hmac),
+ OPT_END()
+ };
+
+ err = argconfig_parse(argc, argv, desc, opts);
+ if (err)
+ return err;
+
+ if (cfg.hmac > 3) {
+ fprintf(stderr, "Invalid HMAC identifier %u\n", cfg.hmac);
+ return -EINVAL;
+ }
+ if (cfg.hmac > 0) {
+ switch (cfg.hmac) {
+ case 1:
+ 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);
+ return -EINVAL;
+ }
+ break;
+ case 2:
+ 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);
+ return -EINVAL;
+ }
+ break;
+ case 3:
+ 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);
+ return -EINVAL;
+ }
+ break;
+ default:
+ break;
+ }
+ } 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);
+ return -EINVAL;
+ }
+ raw_secret = malloc(cfg.key_len);
+ if (!raw_secret)
+ return -ENOMEM;
+ if (!cfg.secret) {
+ if (getrandom_bytes(raw_secret, cfg.key_len) < 0)
+ return -errno;
+ } else {
+ int secret_len = 0, i;
+ unsigned int c;
+
+ 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);
+ 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);
+ return -EINVAL;
+ }
+ }
+
+ if (!cfg.nqn) {
+ cfg.nqn = nvmf_hostnqn_from_file();
+ if (!cfg.nqn) {
+ fprintf(stderr, "Could not read host NQN\n");
+ return -ENOENT;
+ }
+ }
+
+ 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);
+ key[cfg.key_len++] = crc & 0xff;
+ key[cfg.key_len++] = (crc >> 8) & 0xff;
+ key[cfg.key_len++] = (crc >> 16) & 0xff;
+ key[cfg.key_len++] = (crc >> 24) & 0xff;
+
+ memset(encoded_key, 0, sizeof(encoded_key));
+ base64_encode(key, cfg.key_len, encoded_key);
+
+ printf("DHHC-1:%02x:%s:\n", cfg.hmac, encoded_key);
+ return 0;
+}
+
+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.";
+
+ unsigned char decoded_key[128];
+ unsigned int decoded_len;
+ u_int32_t crc = crc32(0L, NULL, 0);
+ u_int32_t key_crc;
+ int err = 0, hmac;
+ struct config {
+ char *key;
+ };
+
+ struct config cfg = {
+ .key = NULL,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_STR("key", 'k', &cfg.key, key),
+ OPT_END()
+ };
+
+ err = argconfig_parse(argc, argv, desc, opts);
+ if (err)
+ return err;
+
+ if (!cfg.key) {
+ fprintf(stderr, "Key not specified\n");
+ return -EINVAL;
+ }
+
+ if (sscanf(cfg.key, "DHHC-1:%02x:*s", &hmac) != 1) {
+ fprintf(stderr, "Invalid key header '%s'\n", cfg.key);
+ return -EINVAL;
+ }
+ switch (hmac) {
+ case 0:
+ break;
+ case 1:
+ if (strlen(cfg.key) != 59) {
+ fprintf(stderr, "Invalid key length for SHA(256)\n");
+ return -EINVAL;
+ }
+ break;
+ case 2:
+ if (strlen(cfg.key) != 83) {
+ fprintf(stderr, "Invalid key length for SHA(384)\n");
+ return -EINVAL;
+ }
+ break;
+ case 3:
+ if (strlen(cfg.key) != 103) {
+ fprintf(stderr, "Invalid key length for SHA(512)\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ fprintf(stderr, "Invalid HMAC identifier %d\n", hmac);
+ return -EINVAL;
+ break;
+ }
+
+ err = base64_decode(cfg.key + 10, strlen(cfg.key) - 11,
+ decoded_key);
+ if (err < 0) {
+ fprintf(stderr, "Base64 decoding failed, error %d\n",
+ err);
+ return err;
+ }
+ decoded_len = err;
+ if (decoded_len < 32) {
+ fprintf(stderr, "Base64 decoding failed (%s, size %u)\n",
+ 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);
+ 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);
+ if (key_crc != crc) {
+ fprintf(stderr, "CRC mismatch (key %08x, crc %08x)\n",
+ key_crc, crc);
+ return -EINVAL;
+ }
+ 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).";
+
+ unsigned char *raw_secret;
+ char encoded_key[128];
+ int key_len = 32;
+ unsigned long crc = crc32(0L, NULL, 0);
+ int err = 0;
+
+ struct config {
+ char *secret;
+ unsigned int hmac;
+ };
+
+ struct config cfg = {
+ .secret = NULL,
+ .hmac = 1,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_STR("secret", 's', &cfg.secret, secret),
+ OPT_UINT("hmac", 'm', &cfg.hmac, hmac),
+ OPT_END()
+ };
+
+ err = argconfig_parse(argc, argv, desc, opts);
+ if (err)
+ return err;
+ if (cfg.hmac < 1 || cfg.hmac > 3) {
+ fprintf(stderr, "Invalid HMAC identifier %u\n", cfg.hmac);
+ return -EINVAL;
+ }
+
+ if (cfg.hmac == 2)
+ key_len = 48;
+
+ raw_secret = malloc(key_len + 4);
+ if (!raw_secret)
+ return -ENOMEM;
+ if (!cfg.secret) {
+ if (getrandom_bytes(raw_secret, key_len) < 0)
+ return -errno;
+ } else {
+ int secret_len = 0, i;
+ unsigned int c;
+
+ 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);
+ return -EINVAL;
+ }
+ if (i >= key_len) {
+ 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);
+ return -EINVAL;
+ }
+ }
+
+ crc = crc32(crc, raw_secret, key_len);
+ raw_secret[key_len++] = crc & 0xff;
+ raw_secret[key_len++] = (crc >> 8) & 0xff;
+ raw_secret[key_len++] = (crc >> 16) & 0xff;
+ raw_secret[key_len++] = (crc >> 24) & 0xff;
+
+ memset(encoded_key, 0, sizeof(encoded_key));
+ base64_encode(raw_secret, key_len, encoded_key);
+
+ printf("NVMeTLSkey-1:%02x:%s:\n", cfg.hmac, encoded_key);
+ return 0;
+}
+
+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 *key = "TLS key (in PSK Interchange format) "\
+ "to be validated.";
+
+ unsigned char decoded_key[128];
+ unsigned int decoded_len;
+ u_int32_t crc = crc32(0L, NULL, 0);
+ u_int32_t key_crc;
+ int err = 0, hmac;
+ struct config {
+ char *key;
+ };
+
+ struct config cfg = {
+ .key = NULL,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_STR("key", 'k', &cfg.key, key),
+ OPT_END()
+ };
+
+ err = argconfig_parse(argc, argv, desc, opts);
+ if (err)
+ return err;
+
+ if (!cfg.key) {
+ fprintf(stderr, "Key not specified\n");
+ return -EINVAL;
+ }
+
+ if (sscanf(cfg.key, "NVMeTLSkey-1:%02x:*s", &hmac) != 1) {
+ fprintf(stderr, "Invalid key header '%s'\n", cfg.key);
+ return -EINVAL;
+ }
+ switch (hmac) {
+ case 1:
+ if (strlen(cfg.key) != 65) {
+ fprintf(stderr, "Invalid key length %lu for SHA(256)\n",
+ strlen(cfg.key));
+ return -EINVAL;
+ }
+ break;
+ case 2:
+ if (strlen(cfg.key) != 89) {
+ fprintf(stderr, "Invalid key length %lu for SHA(384)\n",
+ strlen(cfg.key));
+ return -EINVAL;
+ }
+ break;
+ default:
+ fprintf(stderr, "Invalid HMAC identifier %d\n", hmac);
+ return -EINVAL;
+ break;
+ }
+
+ err = base64_decode(cfg.key + 16, strlen(cfg.key) - 17,
+ decoded_key);
+ if (err < 0) {
+ fprintf(stderr, "Base64 decoding failed (%s, error %d)\n",
+ cfg.key + 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);
+ 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);
+ if (key_crc != crc) {
+ fprintf(stderr, "CRC mismatch (key %08x, crc %08x)\n",
+ key_crc, crc);
+ return -EINVAL;
+ }
+ printf("Key is valid (HMAC %d, length %d, CRC %08x)\n",
+ hmac, decoded_len, crc);
+ return 0;
}
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 fabrics_discover(desc, argc, argv, false);
+ 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 fabrics_discover(desc, argc, argv, true);
+ 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 fabrics_connect(desc, argc, argv);
+ 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 fabrics_disconnect(desc, argc, argv);
+ return nvmf_disconnect(desc, argc, argv);
}
-static int disconnect_all_cmd(int argc, char **argv, struct command *command, struct plugin *plugin)
+int disconnect_all_cmd(int argc, char **argv, struct command *command,
+ struct plugin *plugin)
{
const char *desc = "Disconnect from all connected NVMeoF subsystems";
- return fabrics_disconnect_all(desc, argc, argv);
+ 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)";
+ return nvmf_dim(desc, argc, argv);
}
void register_extension(struct plugin *plugin)
@@ -6617,5 +7981,5 @@ int main(int argc, char **argv)
if (err == -ENOTTY)
general_help(&builtin);
- return err;
+ return err ? 1 : 0;
}
diff --git a/nvme.control.in b/nvme.control.in
index 46714d4..74d36aa 100644
--- a/nvme.control.in
+++ b/nvme.control.in
@@ -1,9 +1,9 @@
Package: nvme
-Version: @@VERSION@@
+Version: @VERSION@
Section: base
Priority: optional
Architecture: amd64
-Depends: @@DEPENDS@@
+Depends: @DEPENDS@
Maintainer: Keith Busch <kbusch@kernel.org>
Description: NVM-Express Command Line Interface
The nvme management tool