From 18de3a6d61a7f090ecea9f6afa52c2d6591d1700 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 16 Jun 2021 15:58:04 +0200 Subject: [PATCH] Convert to libnvme Convert cli and plugins to libnvme and remove old files. Signed-off-by: Hannes Reinecke --- .gitmodules | 3 +- Makefile | 18 +- fabrics.c | 2119 ++++++---------------------- fabrics.h | 60 +- linux/nvme.h | 1879 ------------------------ linux/nvme_ioctl.h | 91 -- nvme-filters.c | 104 -- nvme-ioctl.c | 1073 -------------- nvme-ioctl.h | 182 --- nvme-print.c | 1926 +++++++++++-------------- nvme-print.h | 52 +- nvme-rpmb.c | 13 +- nvme-topology.c | 773 ---------- nvme.c | 1251 ++++++++-------- nvme.h | 9 + plugins/amzn/amzn-nvme.c | 7 +- plugins/dera/dera-nvme.c | 10 +- plugins/huawei/huawei-nvme.c | 16 +- plugins/intel/intel-nvme.c | 54 +- plugins/memblaze/memblaze-nvme.c | 58 +- plugins/micron/micron-nvme.c | 161 ++- plugins/netapp/netapp-nvme.c | 30 +- plugins/nvidia/nvidia-nvme.c | 7 +- plugins/scaleflux/sfx-nvme.c | 32 +- plugins/seagate/seagate-nvme.c | 54 +- plugins/shannon/shannon-nvme.c | 27 +- plugins/shannon/shannon-nvme.h | 8 +- plugins/toshiba/toshiba-nvme.c | 15 +- plugins/transcend/transcend-nvme.c | 10 +- plugins/virtium/virtium-nvme.c | 24 +- plugins/wdc/wdc-nvme.c | 837 ++++++----- plugins/ymtc/ymtc-nvme.c | 11 +- plugins/zns/zns.c | 37 +- 33 files changed, 2636 insertions(+), 8315 deletions(-) delete mode 100644 linux/nvme.h delete mode 100644 linux/nvme_ioctl.h delete mode 100644 nvme-filters.c delete mode 100644 nvme-ioctl.c delete mode 100644 nvme-ioctl.h delete mode 100644 nvme-topology.c diff --git a/.gitmodules b/.gitmodules index 90cf4e6cf1..ed57521ef1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "libnvme"] path = libnvme - url = https://github.com/linux-nvme/libnvme + url = https://github.com/hreinecke/libnvme.git + branch = nvme-cli diff --git a/Makefile b/Makefile index 002c49b28e..d99aa06d62 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CFLAGS ?= -O2 -g -Wall -Werror -override CFLAGS += -std=gnu99 -I. -override CPPFLAGS += -D_GNU_SOURCE -D__CHECK_ENDIAN__ +override CFLAGS += -std=gnu99 +override CPPFLAGS += -D_GNU_SOURCE -D__CHECK_ENDIAN__ -I. -Iutil/ LIBUUID = $(shell $(LD) -o /dev/null -luuid >/dev/null 2>&1; echo $$?) LIBHUGETLBFS = $(shell $(LD) -o /dev/null -lhugetlbfs >/dev/null 2>&1; echo $$?) HAVE_SYSTEMD = $(shell pkg-config --exists libsystemd --atleast-version=242; echo $$?) @@ -18,6 +18,7 @@ UDEVDIR ?= $(SYSCONFDIR)/udev UDEVRULESDIR ?= $(UDEVDIR)/rules.d DRACUTDIR ?= $(LIBDIR)/dracut LIBNVMEDIR = libnvme/ +LDFLAGS ?= -L$(LIBNVMEDIR)src/ -lnvme LIB_DEPENDS = ifeq ($(LIBUUID),0) @@ -61,13 +62,12 @@ default: $(NVME) NVME-VERSION-FILE: FORCE @$(SHELL_PATH) ./NVME-VERSION-GEN -include NVME-VERSION-FILE -override CFLAGS += -DNVME_VERSION='"$(NVME_VERSION)"' +override CFLAGS += -DNVME_VERSION='"$(NVME_VERSION)"' -I$(LIBNVMEDIR)src/ NVME_DPKG_VERSION=1~`lsb_release -sc` -OBJS := nvme-print.o nvme-ioctl.o nvme-rpmb.o \ - fabrics.o nvme-models.o plugin.o \ - nvme-status.o nvme-filters.o nvme-topology.o +OBJS := nvme-print.o nvme-rpmb.o \ + fabrics.o nvme-models.o plugin.o UTIL_OBJS := util/argconfig.o util/suffix.o util/parser.o \ util/cleanup.o util/log.o @@ -104,13 +104,13 @@ nvme: nvme.c nvme.h libnvme $(OBJS) $(PLUGIN_OBJS) $(UTIL_OBJS) NVME-VERSION-FIL verify-no-dep: nvme.c nvme.h $(OBJS) $(UTIL_OBJS) NVME-VERSION-FILE $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) $< -o $@ $(OBJS) $(UTIL_OBJS) $(LDFLAGS) -nvme.o: nvme.c nvme.h nvme-print.h nvme-ioctl.h util/argconfig.h util/suffix.h fabrics.h +nvme.o: nvme.c nvme.h nvme-print.h util/argconfig.h util/suffix.h fabrics.h $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) -c $< -%.o: %.c %.h nvme.h linux/nvme.h linux/nvme_ioctl.h nvme-ioctl.h nvme-print.h util/argconfig.h +%.o: %.c %.h nvme.h linux/nvme.h nvme-print.h util/argconfig.h $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) -o $@ -c $< -%.o: %.c nvme.h linux/nvme.h linux/nvme_ioctl.h nvme-ioctl.h nvme-print.h util/argconfig.h +%.o: %.c nvme.h linux/nvme.h nvme-print.h util/argconfig.h $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) -o $@ -c $< doc: $(NVME) diff --git a/fabrics.c b/fabrics.c index 6cc142d51a..8eb91224dd 100644 --- a/fabrics.c +++ b/fabrics.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -36,728 +35,145 @@ #include #include -#include -#include - -#include "util/parser.h" -#include "nvme-ioctl.h" -#include "nvme-status.h" -#include "fabrics.h" +#include +#include "common.h" #include "nvme.h" -#include "util/argconfig.h" +#include "libnvme.h" +#include "nvme-print.h" -#include "common.h" -#include "util/log.h" -#include "util/cleanup.h" - -#ifdef HAVE_SYSTEMD -#include -#define NVME_HOSTNQN_ID SD_ID128_MAKE(c7,f4,61,81,12,be,49,32,8c,83,10,6f,9d,dd,d8,6b) -#endif - -#define NVMF_HOSTID_SIZE 36 - -/* default to 600 seconds of reconnect attempts before giving up */ -#define NVMF_DEF_CTRL_LOSS_TMO 600 - -const char *conarg_nqn = "nqn"; -const char *conarg_transport = "transport"; -const char *conarg_traddr = "traddr"; -const char *conarg_trsvcid = "trsvcid"; -const char *conarg_host_traddr = "host_traddr"; -const char *conarg_host_iface = "host_iface"; - -struct fabrics_config fabrics_cfg = { - .ctrl_loss_tmo = -1, - .fast_io_fail_tmo = -1, - .output_format = "normal", -}; - -struct connect_args { - char *subsysnqn; - char *transport; - char *traddr; - char *trsvcid; - char *host_traddr; - char *host_iface; - struct connect_args *next; - struct connect_args *tail; -}; - -struct connect_args *tracked_ctrls; - -#define PATH_NVME_FABRICS "/dev/nvme-fabrics" #define PATH_NVMF_DISC "/etc/nvme/discovery.conf" -#define PATH_NVMF_HOSTNQN "/etc/nvme/hostnqn" -#define PATH_NVMF_HOSTID "/etc/nvme/hostid" -#define MAX_DISC_ARGS 10 +#define PATH_NVMF_CONFIG "/etc/nvme/config.json" +#define MAX_DISC_ARGS 32 #define MAX_DISC_RETRIES 10 -enum { - OPT_INSTANCE, - OPT_CNTLID, - OPT_ERR -}; - -static const match_table_t opt_tokens = { - { OPT_INSTANCE, "instance=%d" }, - { OPT_CNTLID, "cntlid=%d" }, - { OPT_ERR, NULL }, -}; - -const char *arg_str(const char * const *strings, - size_t array_size, size_t idx) -{ - if (idx < array_size && strings[idx]) - return strings[idx]; - return "unrecognized"; -} - -const char * const trtypes[] = { - [NVMF_TRTYPE_RDMA] = "rdma", - [NVMF_TRTYPE_FC] = "fc", - [NVMF_TRTYPE_TCP] = "tcp", - [NVMF_TRTYPE_LOOP] = "loop", -}; - -static const char *trtype_str(__u8 trtype) -{ - return arg_str(trtypes, ARRAY_SIZE(trtypes), trtype); -} - -static const char * const adrfams[] = { - [NVMF_ADDR_FAMILY_PCI] = "pci", - [NVMF_ADDR_FAMILY_IP4] = "ipv4", - [NVMF_ADDR_FAMILY_IP6] = "ipv6", - [NVMF_ADDR_FAMILY_IB] = "infiniband", - [NVMF_ADDR_FAMILY_FC] = "fibre-channel", - [NVMF_ADDR_FAMILY_LOOP] = "loop", -}; - -static inline const char *adrfam_str(__u8 adrfam) -{ - return arg_str(adrfams, ARRAY_SIZE(adrfams), adrfam); -} - -static const char * const subtypes[] = { - [NVME_NQN_DISC] = "discovery subsystem", - [NVME_NQN_NVME] = "nvme subsystem", -}; - -static inline const char *subtype_str(__u8 subtype) -{ - return arg_str(subtypes, ARRAY_SIZE(subtypes), subtype); -} - -static const char * const treqs[] = { - [NVMF_TREQ_NOT_SPECIFIED] = "not specified", - [NVMF_TREQ_REQUIRED] = "required", - [NVMF_TREQ_NOT_REQUIRED] = "not required", - [NVMF_TREQ_DISABLE_SQFLOW] = "not specified, " - "sq flow control disable supported", -}; - -static inline const char *treq_str(__u8 treq) -{ - return arg_str(treqs, ARRAY_SIZE(treqs), treq); -} - -static const char * const sectypes[] = { - [NVMF_TCP_SECTYPE_NONE] = "none", - [NVMF_TCP_SECTYPE_TLS] = "tls", -}; - -static inline const char *sectype_str(__u8 sectype) -{ - return arg_str(sectypes, ARRAY_SIZE(sectypes), sectype); -} - -static const char * const prtypes[] = { - [NVMF_RDMA_PRTYPE_NOT_SPECIFIED] = "not specified", - [NVMF_RDMA_PRTYPE_IB] = "infiniband", - [NVMF_RDMA_PRTYPE_ROCE] = "roce", - [NVMF_RDMA_PRTYPE_ROCEV2] = "roce-v2", - [NVMF_RDMA_PRTYPE_IWARP] = "iwarp", -}; - -static inline const char *prtype_str(__u8 prtype) -{ - return arg_str(prtypes, ARRAY_SIZE(prtypes), prtype); -} - -static const char * const qptypes[] = { - [NVMF_RDMA_QPTYPE_CONNECTED] = "connected", - [NVMF_RDMA_QPTYPE_DATAGRAM] = "datagram", -}; - -static inline const char *qptype_str(__u8 qptype) -{ - return arg_str(qptypes, ARRAY_SIZE(qptypes), qptype); -} - -static const char * const cms[] = { - [NVMF_RDMA_CMS_RDMA_CM] = "rdma-cm", -}; - -static const char *cms_str(__u8 cm) -{ - return arg_str(cms, ARRAY_SIZE(cms), cm); -} - -/* - * parse strings with connect arguments to find a particular field. - * If field found, return string containing field value. If field - * not found, return an empty string. - */ -char *parse_conn_arg(const char *conargs, const char delim, const char *field) -{ - char *s, *e; - size_t cnt; - - /* - * There are field name overlaps: traddr and host_traddr. - * By chance, both connect arg strings are set up to - * have traddr field followed by host_traddr field. Thus field - * name matching doesn't overlap in the searches. Technically, - * as is, the loop and delimiter checking isn't necessary. - * However, better to be prepared. - */ - do { - s = strstr(conargs, field); - if (!s) - goto empty_field; - /* validate prior character is delimiter */ - if (s == conargs || *(s - 1) == delim) { - /* match requires next character to be assignment */ - s += strlen(field); - if (*s == '=') - /* match */ - break; - } - /* field overlap: seek to delimiter and keep looking */ - conargs = strchr(s, delim); - if (!conargs) - goto empty_field; - conargs++; /* skip delimiter */ - } while (1); - s++; /* skip assignment character */ - e = strchr(s, delim); - if (e) - cnt = e - s; - else - cnt = strlen(s); - - return strndup(s, cnt); - -empty_field: - return strdup("\0"); -} - -int ctrl_instance(const char *device) -{ - char d[64]; - const char *p; - int ret, instance; - - p = strrchr(device, '/'); - if (p == NULL) - p = device; - else - p++; - ret = sscanf(p, "nvme%d", &instance); - if (ret <= 0) - return -EINVAL; - if (snprintf(d, sizeof(d), "nvme%d", instance) <= 0 || - strcmp(p, d)) - return -EINVAL; - return instance; -} - -/* - * Given a controller name, create a connect_args with its - * attributes and compare the attributes against the connect args - * given. - * Return true/false based on whether it matches - */ -static bool ctrl_matches_connectargs(const char *name, struct connect_args *args) -{ - struct connect_args cargs; - bool found = false; - char *path = NULL, *addr; - int ret; - bool persistent = true; - - ret = asprintf(&path, "%s/%s", SYS_NVME, name); - if (ret < 0) - return found; - - addr = nvme_get_ctrl_attr(path, "address"); - if (!addr) { - fprintf(stderr, "nvme_get_ctrl_attr failed\n"); - return found; - } - - cargs.subsysnqn = nvme_get_ctrl_attr(path, "subsysnqn"); - cargs.transport = nvme_get_ctrl_attr(path, "transport"); - cargs.traddr = parse_conn_arg(addr, ' ', conarg_traddr); - cargs.trsvcid = parse_conn_arg(addr, ' ', conarg_trsvcid); - cargs.host_traddr = parse_conn_arg(addr, ' ', conarg_host_traddr); - cargs.host_iface = parse_conn_arg(addr, ' ', conarg_host_iface); - - if (!strcmp(cargs.subsysnqn, NVME_DISC_SUBSYS_NAME)) { - char *kato_str = nvme_get_ctrl_attr(path, "kato"), *p; - unsigned int kato = 0; - - /* - * When looking up discovery controllers we have to skip - * any non-persistent controllers (ie those with a zero - * kato value). Otherwise the controller will vanish from - * underneath us as they are owned by another program. - * - * On older kernels, the 'kato' attribute isn't present. - * Assume a persistent controller for these installations. - */ - if (kato_str) { - kato = strtoul(kato_str, &p, 0); - if (p == kato_str) - kato = 0; - free(kato_str); - persistent = (kato != 0); - } - } - - if (persistent && - !strcmp(cargs.subsysnqn, args->subsysnqn) && - !strcmp(cargs.transport, args->transport) && - (!strcmp(cargs.traddr, args->traddr) || - !strcmp(args->traddr, "none")) && - (!strcmp(cargs.trsvcid, args->trsvcid) || - !strcmp(args->trsvcid, "none")) && - (!strcmp(cargs.host_traddr, args->host_traddr) || - !strcmp(args->host_traddr, "none")) && - (!strcmp(cargs.host_iface, args->host_iface) || - !strcmp(args->host_iface, "none"))) - found = true; - - free(cargs.subsysnqn); - free(cargs.transport); - free(cargs.traddr); - free(cargs.trsvcid); - free(cargs.host_traddr); - free(cargs.host_iface); - free(addr); - free(path); - - return found; -} - -/* - * Look through the system to find an existing controller whose - * attributes match the connect arguments specified - * If found, a string containing the controller name (ex: "nvme?") - * is returned. - * If not found, a NULL is returned. - */ -static char *find_ctrl_with_connectargs(struct connect_args *args) -{ - struct dirent **devices; - char *devname = NULL; - int i, n; - - n = scandir(SYS_NVME, &devices, scan_ctrls_filter, alphasort); - if (n < 0) { - msg(LOG_ERR, "no NVMe controller(s) detected.\n"); - return NULL; - } - - for (i = 0; i < n; i++) { - if (ctrl_matches_connectargs(devices[i]->d_name, args)) { - devname = strdup(devices[i]->d_name); - if (devname == NULL) - msg(LOG_ERR, "no memory for ctrl name %s\n", - devices[i]->d_name); - goto cleanup_devices; - } - } - -cleanup_devices: - for (i = 0; i < n; i++) - free(devices[i]); - free(devices); - - return devname; -} - -static struct connect_args *extract_connect_args(char *argstr) -{ - struct connect_args *cargs; - - cargs = calloc(1, sizeof(*cargs)); - if (!cargs) - return NULL; - cargs->subsysnqn = parse_conn_arg(argstr, ',', conarg_nqn); - cargs->transport = parse_conn_arg(argstr, ',', conarg_transport); - cargs->traddr = parse_conn_arg(argstr, ',', conarg_traddr); - cargs->trsvcid = parse_conn_arg(argstr, ',', conarg_trsvcid); - cargs->host_traddr = parse_conn_arg(argstr, ',', conarg_host_traddr); - cargs->host_iface = parse_conn_arg(argstr, ',', conarg_host_iface); - return cargs; -} - -static void destruct_connect_args(struct connect_args *cargs) -{ - free(cargs->subsysnqn); - free(cargs->transport); - free(cargs->traddr); - free(cargs->trsvcid); - free(cargs->host_traddr); - free(cargs->host_iface); -} - -static void free_connect_args(struct connect_args *cargs) -{ - destruct_connect_args(cargs); - free(cargs); -} - -static void track_ctrl(char *argstr) -{ - struct connect_args *cargs; - - cargs = extract_connect_args(argstr); - if (!cargs) - return; - - if (!tracked_ctrls) - tracked_ctrls = cargs; - else - tracked_ctrls->tail->next = cargs; - tracked_ctrls->tail = cargs; -} - -static int add_ctrl(const char *argstr) -{ - substring_t args[MAX_OPT_ARGS]; - char buf[BUF_SIZE], *options, *p; - int token, ret, fd, len = strlen(argstr); - - fd = open(PATH_NVME_FABRICS, O_RDWR); - if (fd < 0) { - msg(LOG_ERR, "Failed to open %s: %s\n", - PATH_NVME_FABRICS, strerror(errno)); - ret = -errno; - goto out; - } - - ret = write(fd, argstr, len); - if (ret != len) { - if (errno != EALREADY) - msg(LOG_NOTICE, "Failed to write to %s: %s\n", - PATH_NVME_FABRICS, strerror(errno)); - ret = -errno; - goto out_close; - } - - len = read(fd, buf, BUF_SIZE); - if (len < 0) { - msg(LOG_ERR, "Failed to read from %s: %s\n", - PATH_NVME_FABRICS, strerror(errno)); - ret = -errno; - goto out_close; - } - - buf[len] = '\0'; - options = buf; - while ((p = strsep(&options, ",\n")) != NULL) { - if (!*p) - continue; - - token = match_token(p, opt_tokens, args); - switch (token) { - case OPT_INSTANCE: - if (match_int(args, &token)) - goto out_fail; - ret = token; - track_ctrl((char *)argstr); - goto out_close; - default: - /* ignore */ - break; - } - } - -out_fail: - msg(LOG_ERR, "Failed to parse ctrl info for \"%s\"\n", argstr); - ret = -EINVAL; -out_close: - close(fd); -out: - return ret; -} - -static int remove_ctrl_by_path(char *sysfs_path) -{ - int ret, fd; - - fd = open(sysfs_path, O_WRONLY); - if (fd < 0) { - ret = -errno; - msg(LOG_ERR, "Failed to open %s: %s\n", sysfs_path, - strerror(errno)); - goto out; - } - - if (write(fd, "1", 1) != 1) { - ret = -errno; - goto out_close; - } - - ret = 0; -out_close: - close(fd); -out: - return ret; -} - -int remove_ctrl(int instance) -{ - char *sysfs_path; - int ret; - - if (asprintf(&sysfs_path, "/sys/class/nvme/nvme%d/delete_controller", - instance) < 0) { - ret = -errno; - goto out; - } - - ret = remove_ctrl_by_path(sysfs_path); - free(sysfs_path); -out: - return ret; -} - -enum { - DISC_OK, - DISC_NO_LOG, - DISC_GET_NUMRECS, - DISC_GET_LOG, - DISC_RETRY_EXHAUSTED, - DISC_NOT_EQUAL, -}; - -static int nvmf_get_log_page_discovery(const char *dev_path, - struct nvmf_disc_rsp_page_hdr **logp, int *numrec, int *status) -{ - struct nvmf_disc_rsp_page_hdr *log; - unsigned int hdr_size; - unsigned long genctr; - int error, fd, max_retries = MAX_DISC_RETRIES, retries = 0; - - fd = open(dev_path, O_RDWR); - if (fd < 0) { - error = -errno; - msg(LOG_ERR, "Failed to open %s: %s\n", - dev_path, strerror(errno)); - goto out; - } - - /* first get_log_page we just need numrec entry from discovery hdr. - * host supplies its desired bytes via dwords, per NVMe spec. - */ - hdr_size = round_up((offsetof(struct nvmf_disc_rsp_page_hdr, numrec) + - sizeof(log->numrec)), sizeof(__u32)); - - /* - * Issue first get log page w/numdl small enough to retrieve numrec. - * We just want to know how many records to retrieve. - */ - log = calloc(1, hdr_size); - if (!log) { - perror("could not alloc memory for discovery log header"); - error = -ENOMEM; - goto out_close; - } - - error = nvme_discovery_log(fd, log, hdr_size); - if (error) { - error = DISC_GET_NUMRECS; - goto out_free_log; - } - - do { - unsigned int log_size; - - /* check numrec limits */ - *numrec = le64_to_cpu(log->numrec); - genctr = le64_to_cpu(log->genctr); - free(log); - - if (*numrec == 0) { - error = DISC_NO_LOG; - goto out_close; - } - - /* we are actually retrieving the entire discovery tables - * for the second get_log_page(), per - * NVMe spec so no need to round_up(), or there is something - * seriously wrong with the standard - */ - log_size = sizeof(struct nvmf_disc_rsp_page_hdr) + - sizeof(struct nvmf_disc_rsp_page_entry) * *numrec; - - /* allocate discovery log pages based on page_hdr->numrec */ - log = calloc(1, log_size); - if (!log) { - perror("could not alloc memory for discovery log page"); - error = -ENOMEM; - goto out_close; - } - - /* - * issue new get_log_page w/numdl+numdh set to get all records, - * up to MAX_DISC_LOGS. - */ - error = nvme_discovery_log(fd, log, log_size); - if (error) { - error = DISC_GET_LOG; - goto out_free_log; - } - - /* - * The above call to nvme_discovery_log() might result - * in several calls (with different offsets), so we need - * to fetch the header again to have the most up-to-date - * value for the generation counter - */ - genctr = le64_to_cpu(log->genctr); - error = nvme_discovery_log(fd, log, hdr_size); - if (error) { - error = DISC_GET_LOG; - goto out_free_log; - } - } while (genctr != le64_to_cpu(log->genctr) && - ++retries < max_retries); - - /* - * If genctr is still different with the one in the log entry, it - * means the retires have been exhausted to max_retries. Then it - * should be retried by the caller or the user. - */ - if (genctr != le64_to_cpu(log->genctr)) { - error = DISC_RETRY_EXHAUSTED; - goto out_free_log; - } - - if (*numrec != le64_to_cpu(log->numrec)) { - error = DISC_NOT_EQUAL; - goto out_free_log; - } - - /* needs to be freed by the caller */ - *logp = log; - error = DISC_OK; - goto out_close; - -out_free_log: - free(log); -out_close: - close(fd); -out: - *status = nvme_status_to_errno(error, true); - return error; -} - -static int space_strip_len(int max, const char *str) +/* Name of file to output log pages in their raw format */ +static char *raw; +static bool persistent; +static bool quiet; + +static const char *nvmf_tport = "transport type"; +static const char *nvmf_traddr = "transport address"; +static const char *nvmf_nqn = "subsystem nqn"; +static const char *nvmf_trsvcid = "transport service id (e.g. IP port)"; +static const char *nvmf_htraddr = "host traddr (e.g. FC WWN's)"; +static const char *nvmf_hiface = "host interface (for tcp transport)"; +static const char *nvmf_hostnqn = "user-defined hostnqn"; +static const char *nvmf_hostid = "user-defined hostid (if default not used)"; +static const char *nvmf_nr_io_queues = "number of io queues to use (default is core count)"; +static const char *nvmf_nr_write_queues = "number of write queues to use (default 0)"; +static const char *nvmf_nr_poll_queues = "number of poll queues to use (default 0)"; +static const char *nvmf_queue_size = "number of io queue elements to use (default 128)"; +static const char *nvmf_keep_alive_tmo = "keep alive timeout period in seconds"; +static const char *nvmf_reconnect_delay = "reconnect timeout period in seconds"; +static const char *nvmf_ctrl_loss_tmo = "controller loss timeout period in seconds"; +static const char *nvmf_tos = "type of service"; +static const char *nvmf_dup_connect = "allow duplicate connections between same transport host and subsystem port"; +static const char *nvmf_disable_sqflow = "disable controller sq flow control (default false)"; +static const char *nvmf_hdr_digest = "enable transport protocol header digest (TCP transport)"; +static const char *nvmf_data_digest = "enable transport protocol data digest (TCP transport)"; +static const char *nvmf_config_file = "Use specified JSON configuration file or 'none' to disable"; + +#define NVMF_OPTS(c) \ + OPT_STRING("transport", 't', "STR", &transport, nvmf_tport), \ + OPT_STRING("traddr", 'a', "STR", &traddr, nvmf_traddr), \ + OPT_STRING("trsvcid", 's', "STR", &trsvcid, nvmf_trsvcid), \ + OPT_STRING("host-traddr", 'w', "STR", &host_traddr, nvmf_htraddr), \ + OPT_STRING("host-iface", 'f', "STR", &host_iface, nvmf_hiface), \ + OPT_STRING("hostnqn", 'q', "STR", &hostnqn, nvmf_hostnqn), \ + OPT_STRING("hostid", 'I', "STR", &hostid, nvmf_hostid), \ + OPT_INT("nr-io-queues", 'i', &c.nr_io_queues, nvmf_nr_io_queues), \ + OPT_INT("nr-write-queues", 'W', &c.nr_write_queues, nvmf_nr_write_queues),\ + OPT_INT("nr-poll-queues", 'P', &c.nr_poll_queues, nvmf_nr_poll_queues), \ + OPT_INT("queue-size", 'Q', &c.queue_size, nvmf_queue_size), \ + OPT_INT("keep-alive-tmo", 'k', &c.keep_alive_tmo, nvmf_keep_alive_tmo), \ + OPT_INT("reconnect-delay", 'c', &c.reconnect_delay, nvmf_reconnect_delay),\ + OPT_INT("ctrl-loss-tmo", 'l', &c.ctrl_loss_tmo, nvmf_ctrl_loss_tmo), \ + OPT_INT("tos", 'T', &c.tos, nvmf_tos), \ + OPT_FLAG("duplicate-connect", 'D', &c.duplicate_connect, nvmf_dup_connect), \ + OPT_FLAG("disable-sqflow", 'd', &c.disable_sqflow, nvmf_disable_sqflow), \ + OPT_FLAG("hdr-digest", 'g', &c.hdr_digest, nvmf_hdr_digest), \ + OPT_FLAG("data-digest", 'G', &c.data_digest, nvmf_data_digest) \ + + +static void space_strip_len(int max, char *str) { int i; - for (i = max - 1; i >= 0; i--) + for (i = max - 1; i >= 0; i--) { if (str[i] != '\0' && str[i] != ' ') - break; - - return i + 1; + return; + else + str[i] = '\0'; + } } -static void print_discovery_log(struct nvmf_disc_rsp_page_hdr *log, int numrec, - int instance) +static void print_discovery_log(struct nvmf_discovery_log *log, int numrec) { int i; - printf("\n"); - - if (fabrics_cfg.persistent) - printf("Persistent device: nvme%d\n", instance); - - printf("Discovery Log Number of Records %d, " + printf("\nDiscovery Log Number of Records %d, " "Generation counter %"PRIu64"\n", numrec, le64_to_cpu(log->genctr)); for (i = 0; i < numrec; i++) { - struct nvmf_disc_rsp_page_entry *e = &log->entries[i]; + struct nvmf_disc_log_entry *e = &log->entries[i]; + + space_strip_len(NVMF_TRSVCID_SIZE, e->trsvcid); + space_strip_len(NVMF_TRADDR_SIZE, e->traddr); printf("=====Discovery Log Entry %d======\n", i); - printf("trtype: %s\n", trtype_str(e->trtype)); - printf("adrfam: %s\n", adrfam_str(e->adrfam)); - printf("subtype: %s\n", subtype_str(e->subtype)); - printf("treq: %s\n", treq_str(e->treq)); + printf("trtype: %s\n", nvmf_trtype_str(e->trtype)); + printf("adrfam: %s\n", nvmf_adrfam_str(e->adrfam)); + printf("subtype: %s\n", nvmf_subtype_str(e->subtype)); + printf("treq: %s\n", nvmf_treq_str(e->treq)); printf("portid: %d\n", e->portid); - printf("trsvcid: %.*s\n", - space_strip_len(NVMF_TRSVCID_SIZE, e->trsvcid), - e->trsvcid); + printf("trsvcid: %s\n", e->trsvcid); printf("subnqn: %s\n", e->subnqn); - printf("traddr: %.*s\n", - space_strip_len(NVMF_TRADDR_SIZE, e->traddr), - e->traddr); + printf("traddr: %s\n", e->traddr); switch (e->trtype) { case NVMF_TRTYPE_RDMA: printf("rdma_prtype: %s\n", - prtype_str(e->tsas.rdma.prtype)); + nvmf_prtype_str(e->tsas.rdma.prtype)); printf("rdma_qptype: %s\n", - qptype_str(e->tsas.rdma.qptype)); + nvmf_qptype_str(e->tsas.rdma.qptype)); printf("rdma_cms: %s\n", - cms_str(e->tsas.rdma.cms)); + nvmf_cms_str(e->tsas.rdma.cms)); printf("rdma_pkey: 0x%04x\n", e->tsas.rdma.pkey); break; case NVMF_TRTYPE_TCP: printf("sectype: %s\n", - sectype_str(e->tsas.tcp.sectype)); + nvmf_sectype_str(e->tsas.tcp.sectype)); break; } } } -static void json_discovery_log(struct nvmf_disc_rsp_page_hdr *log, int numrec, - int instance) +static void json_discovery_log(struct nvmf_discovery_log *log, int numrec) { struct json_object *root; struct json_object *entries; - char *dev_name = NULL; int i; - if (asprintf(&dev_name, "nvme%d", instance) < 0) - return; - root = json_create_object(); entries = json_create_array(); - json_object_add_value_string(root, "device", dev_name); json_object_add_value_uint(root, "genctr", le64_to_cpu(log->genctr)); json_object_add_value_array(root, "records", entries); for (i = 0; i < numrec; i++) { - struct nvmf_disc_rsp_page_entry *e = &log->entries[i]; + struct nvmf_disc_log_entry *e = &log->entries[i]; struct json_object *entry = json_create_object(); json_object_add_value_string(entry, "trtype", - trtype_str(e->trtype)); + nvmf_trtype_str(e->trtype)); json_object_add_value_string(entry, "adrfam", - adrfam_str(e->adrfam)); + nvmf_adrfam_str(e->adrfam)); json_object_add_value_string(entry, "subtype", - subtype_str(e->subtype)); + nvmf_subtype_str(e->subtype)); json_object_add_value_string(entry,"treq", - treq_str(e->treq)); + nvmf_treq_str(e->treq)); json_object_add_value_uint(entry, "portid", e->portid); json_object_add_value_string(entry, "trsvcid", e->trsvcid); @@ -767,17 +183,17 @@ static void json_discovery_log(struct nvmf_disc_rsp_page_hdr *log, int numrec, switch (e->trtype) { case NVMF_TRTYPE_RDMA: json_object_add_value_string(entry, "rdma_prtype", - prtype_str(e->tsas.rdma.prtype)); + nvmf_prtype_str(e->tsas.rdma.prtype)); json_object_add_value_string(entry, "rdma_qptype", - qptype_str(e->tsas.rdma.qptype)); + nvmf_qptype_str(e->tsas.rdma.qptype)); json_object_add_value_string(entry, "rdma_cms", - cms_str(e->tsas.rdma.cms)); + nvmf_cms_str(e->tsas.rdma.cms)); json_object_add_value_uint(entry, "rdma_pkey", e->tsas.rdma.pkey); break; case NVMF_TRTYPE_TCP: json_object_add_value_string(entry, "sectype", - sectype_str(e->tsas.tcp.sectype)); + nvmf_sectype_str(e->tsas.tcp.sectype)); break; } json_array_add_value_object(entries, entry); @@ -785,1106 +201,481 @@ static void json_discovery_log(struct nvmf_disc_rsp_page_hdr *log, int numrec, json_print_object(root, NULL); printf("\n"); json_free_object(root); - free(dev_name); } -static void save_discovery_log(struct nvmf_disc_rsp_page_hdr *log, int numrec) +static void save_discovery_log(char *raw, struct nvmf_discovery_log *log) { - int fd; - int len, ret; + uint64_t numrec = le64_to_cpu(log->numrec); + int fd, len, ret; - fd = open(fabrics_cfg.raw, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); + fd = open(raw, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); if (fd < 0) { - msg(LOG_ERR, "failed to open %s: %s\n", - fabrics_cfg.raw, strerror(errno)); + nvme_msg(LOG_ERR, "failed to open %s: %s\n", + raw, strerror(errno)); return; } - len = sizeof(struct nvmf_disc_rsp_page_hdr) + - numrec * sizeof(struct nvmf_disc_rsp_page_entry); + len = sizeof(struct nvmf_discovery_log) + + numrec * sizeof(struct nvmf_disc_log_entry); ret = write(fd, log, len); if (ret < 0) - msg(LOG_ERR, "failed to write to %s: %s\n", - fabrics_cfg.raw, strerror(errno)); + nvme_msg(LOG_ERR, "failed to write to %s: %s\n", + raw, strerror(errno)); else - printf("Discovery log is saved to %s\n", fabrics_cfg.raw); + printf("Discovery log is saved to %s\n", raw); close(fd); } -static char *hostnqn_read_file(void) -{ - FILE *f; - char hostnqn[NVMF_NQN_SIZE]; - char *ret = NULL; - - f = fopen(PATH_NVMF_HOSTNQN, "r"); - if (f == NULL) - return false; - - if (fgets(hostnqn, sizeof(hostnqn), f) == NULL || - !strlen(hostnqn)) - goto out; - - ret = strndup(hostnqn, strcspn(hostnqn, "\n")); - -out: - fclose(f); - return ret; -} - -static char *hostnqn_generate_systemd(void) -{ -#ifdef HAVE_SYSTEMD - sd_id128_t id; - char *ret; - - if (sd_id128_get_machine_app_specific(NVME_HOSTNQN_ID, &id) < 0) - return NULL; - - if (asprintf(&ret, "nqn.2014-08.org.nvmexpress:uuid:" SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(id)) == -1) - ret = NULL; - - return ret; -#else - return NULL; -#endif -} - -static char *hostnqn_read_dmi(void) -{ - char uuid[16]; - char *ret = NULL; - - if (uuid_from_dmi(uuid) < 0) - return NULL; - if (asprintf(&ret, "nqn.2014-08.org.nvmexpress:uuid:%s", uuid) == -1) - return NULL; - return ret; -} - -/* returns an allocated string or NULL */ -char *hostnqn_read(void) -{ - char *ret; - - ret = hostnqn_read_file(); - if (ret) - return ret; - - ret = hostnqn_read_dmi(); - if (ret) - return ret; - - ret = hostnqn_generate_systemd(); - if (ret) - return ret; - - return NULL; -} - -static int nvmf_hostnqn_file(void) -{ - fabrics_cfg.hostnqn = hostnqn_read(); - - return fabrics_cfg.hostnqn != NULL; -} - -static int nvmf_hostid_file(void) -{ - FILE *f; - char hostid[NVMF_HOSTID_SIZE + 1]; - int ret = false; - - f = fopen(PATH_NVMF_HOSTID, "r"); - if (f == NULL) - return false; - - if (fgets(hostid, sizeof(hostid), f) == NULL) - goto out; - - fabrics_cfg.hostid = strdup(hostid); - if (!fabrics_cfg.hostid) - goto out; - - ret = true; -out: - fclose(f); - return ret; -} - -static int -add_bool_argument(char **argstr, int *max_len, char *arg_str, bool arg) -{ - int len; - - if (arg) { - len = snprintf(*argstr, *max_len, ",%s", arg_str); - if (len < 0) - return -EINVAL; - *argstr += len; - *max_len -= len; - } - - return 0; -} - -static int -add_int_argument(char **argstr, int *max_len, char *arg_str, int arg, - bool allow_zero) -{ - int len; - - if ((arg && !allow_zero) || (arg != -1 && allow_zero)) { - len = snprintf(*argstr, *max_len, ",%s=%d", arg_str, arg); - if (len < 0) - return -EINVAL; - *argstr += len; - *max_len -= len; - } - - return 0; -} - -static int -add_argument(char **argstr, int *max_len, char *arg_str, const char *arg) -{ - int len; - - if (arg && strcmp(arg, "none")) { - len = snprintf(*argstr, *max_len, ",%s=%s", arg_str, arg); - if (len < 0) - return -EINVAL; - *argstr += len; - *max_len -= len; - } - - return 0; -} - -int build_options(char *argstr, int max_len, bool discover) -{ - int len; - - if (!fabrics_cfg.transport) { - msg(LOG_ERR, "need a transport (-t) argument\n"); - return -EINVAL; - } - - if (strncmp(fabrics_cfg.transport, "loop", 4)) { - if (!fabrics_cfg.traddr) { - msg(LOG_ERR, "need a address (-a) argument\n"); - return -EINVAL; - } - /* Use the default ctrl loss timeout if unset */ - if (fabrics_cfg.ctrl_loss_tmo == -1) - fabrics_cfg.ctrl_loss_tmo = NVMF_DEF_CTRL_LOSS_TMO; - } - - /* always specify nqn as first arg - this will init the string */ - len = snprintf(argstr, max_len, "nqn=%s", fabrics_cfg.nqn); - if (len < 0) - return -EINVAL; - argstr += len; - max_len -= len; - - if (add_argument(&argstr, &max_len, "transport", fabrics_cfg.transport) || - add_argument(&argstr, &max_len, "traddr", fabrics_cfg.traddr) || - add_argument(&argstr, &max_len, "host_traddr", fabrics_cfg.host_traddr) || - add_argument(&argstr, &max_len, "host_iface", fabrics_cfg.host_iface) || - add_argument(&argstr, &max_len, "trsvcid", fabrics_cfg.trsvcid) || - ((fabrics_cfg.hostnqn || nvmf_hostnqn_file()) && - add_argument(&argstr, &max_len, "hostnqn", fabrics_cfg.hostnqn)) || - ((fabrics_cfg.hostid || nvmf_hostid_file()) && - add_argument(&argstr, &max_len, "hostid", fabrics_cfg.hostid)) || - (!discover && - add_int_argument(&argstr, &max_len, "nr_io_queues", - fabrics_cfg.nr_io_queues, false)) || - add_int_argument(&argstr, &max_len, "nr_write_queues", - fabrics_cfg.nr_write_queues, false) || - add_int_argument(&argstr, &max_len, "nr_poll_queues", - fabrics_cfg.nr_poll_queues, false) || - (!discover && - add_int_argument(&argstr, &max_len, "queue_size", - fabrics_cfg.queue_size, false)) || - add_int_argument(&argstr, &max_len, "keep_alive_tmo", - fabrics_cfg.keep_alive_tmo, false) || - add_int_argument(&argstr, &max_len, "reconnect_delay", - fabrics_cfg.reconnect_delay, false) || - (strncmp(fabrics_cfg.transport, "loop", 4) && - add_int_argument(&argstr, &max_len, "ctrl_loss_tmo", - fabrics_cfg.ctrl_loss_tmo, true)) || - add_int_argument(&argstr, &max_len, "fast_io_fail_tmo", - fabrics_cfg.fast_io_fail_tmo, true) || - add_int_argument(&argstr, &max_len, "tos", - fabrics_cfg.tos, true) || - add_bool_argument(&argstr, &max_len, "duplicate_connect", - fabrics_cfg.duplicate_connect) || - add_bool_argument(&argstr, &max_len, "disable_sqflow", - fabrics_cfg.disable_sqflow) || - add_bool_argument(&argstr, &max_len, "hdr_digest", fabrics_cfg.hdr_digest) || - add_bool_argument(&argstr, &max_len, "data_digest", fabrics_cfg.data_digest)) - return -EINVAL; - - return 0; -} - -static void set_discovery_kato(struct fabrics_config *cfg) +static int __discover(nvme_ctrl_t c, const struct nvme_fabrics_config *defcfg, + char *raw, bool connect, bool persistent, bool quiet, + enum nvme_print_flags flags) { - /* Set kato to NVMF_DEF_DISC_TMO for persistent controllers */ - if (cfg->persistent && !cfg->keep_alive_tmo) - cfg->keep_alive_tmo = NVMF_DEF_DISC_TMO; - /* Set kato to zero for non-persistent controllers */ - else if (!cfg->persistent && (cfg->keep_alive_tmo > 0)) - cfg->keep_alive_tmo = 0; -} - -static void discovery_trsvcid(struct fabrics_config *fabrics_cfg) -{ - if (!strcmp(fabrics_cfg->transport, "tcp")) { - /* Default port for NVMe/TCP discovery controllers */ - fabrics_cfg->trsvcid = __stringify(NVME_DISC_IP_PORT); - } else if (!strcmp(fabrics_cfg->transport, "rdma")) { - /* Default port for NVMe/RDMA controllers */ - fabrics_cfg->trsvcid = __stringify(NVME_RDMA_IP_PORT); - } -} - -static bool traddr_is_hostname(struct fabrics_config *fabrics_cfg) -{ - char addrstr[NVMF_TRADDR_SIZE]; - - if (!fabrics_cfg->traddr || !fabrics_cfg->transport) - return false; - if (strcmp(fabrics_cfg->transport, "tcp") && strcmp(fabrics_cfg->transport, "rdma")) - return false; - if (inet_pton(AF_INET, fabrics_cfg->traddr, addrstr) > 0 || - inet_pton(AF_INET6, fabrics_cfg->traddr, addrstr) > 0) - return false; - return true; -} - -static int hostname2traddr(struct fabrics_config *fabrics_cfg) -{ - struct addrinfo *host_info, hints = {.ai_family = AF_UNSPEC}; - char addrstr[NVMF_TRADDR_SIZE]; - const char *p; + struct nvmf_discovery_log *log = NULL; + nvme_subsystem_t s = nvme_ctrl_get_subsystem(c); + nvme_host_t h = nvme_subsystem_get_host(s); + uint64_t numrec; int ret; - ret = getaddrinfo(fabrics_cfg->traddr, NULL, &hints, &host_info); + ret = nvmf_get_discovery_log(c, &log, MAX_DISC_RETRIES); if (ret) { - msg(LOG_ERR, "failed to resolve host %s info\n", fabrics_cfg->traddr); - return ret; - } - - switch (host_info->ai_family) { - case AF_INET: - p = inet_ntop(host_info->ai_family, - &(((struct sockaddr_in *)host_info->ai_addr)->sin_addr), - addrstr, NVMF_TRADDR_SIZE); - break; - case AF_INET6: - p = inet_ntop(host_info->ai_family, - &(((struct sockaddr_in6 *)host_info->ai_addr)->sin6_addr), - addrstr, NVMF_TRADDR_SIZE); - break; - default: - msg(LOG_ERR, "unrecognized address family (%d) %s\n", - host_info->ai_family, fabrics_cfg->traddr); - ret = -EINVAL; - goto free_addrinfo; - } - - if (!p) { - msg(LOG_ERR, "failed to get traddr for %s\n", fabrics_cfg->traddr); - ret = -errno; - goto free_addrinfo; - } - fabrics_cfg->traddr = strdup(addrstr); - -free_addrinfo: - freeaddrinfo(host_info); - return ret; -} - -static int connect_ctrl(struct nvmf_disc_rsp_page_entry *e) -{ - char argstr[BUF_SIZE], *p; - const char *transport; - bool discover, disable_sqflow = true; - int len, ret; - -retry: - p = argstr; - discover = false; - - switch (e->subtype) { - case NVME_NQN_DISC: - discover = true; - case NVME_NQN_NVME: - break; - default: - msg(LOG_ERR, "skipping unsupported subtype %d\n", - e->subtype); - return -EINVAL; - } - - len = sprintf(p, "nqn=%s", e->subnqn); - if (len < 0) - return -EINVAL; - p += len; - - if (fabrics_cfg.hostnqn && strcmp(fabrics_cfg.hostnqn, "none")) { - len = sprintf(p, ",hostnqn=%s", fabrics_cfg.hostnqn); - if (len < 0) - return -EINVAL; - p += len; - } - - if (fabrics_cfg.hostid && strcmp(fabrics_cfg.hostid, "none")) { - len = sprintf(p, ",hostid=%s", fabrics_cfg.hostid); - if (len < 0) - return -EINVAL; - p += len; - } - - if (fabrics_cfg.queue_size && !discover) { - len = sprintf(p, ",queue_size=%d", fabrics_cfg.queue_size); - if (len < 0) - return -EINVAL; - p += len; - } - - if (fabrics_cfg.nr_io_queues && !discover) { - len = sprintf(p, ",nr_io_queues=%d", fabrics_cfg.nr_io_queues); - if (len < 0) - return -EINVAL; - p += len; - } - - if (fabrics_cfg.nr_write_queues) { - len = sprintf(p, ",nr_write_queues=%d", fabrics_cfg.nr_write_queues); - if (len < 0) - return -EINVAL; - p += len; - } - - if (fabrics_cfg.nr_poll_queues) { - len = sprintf(p, ",nr_poll_queues=%d", fabrics_cfg.nr_poll_queues); - if (len < 0) - return -EINVAL; - p += len; - } - - if (fabrics_cfg.host_traddr && strcmp(fabrics_cfg.host_traddr, "none")) { - len = sprintf(p, ",host_traddr=%s", fabrics_cfg.host_traddr); - if (len < 0) - return -EINVAL; - p+= len; - } - - if (fabrics_cfg.host_iface && strcmp(fabrics_cfg.host_iface, "none")) { - len = sprintf(p, ",host_iface=%s", fabrics_cfg.host_iface); - if (len < 0) - return -EINVAL; - p+= len; - } - - if (fabrics_cfg.reconnect_delay) { - len = sprintf(p, ",reconnect_delay=%d", fabrics_cfg.reconnect_delay); - if (len < 0) - return -EINVAL; - p += len; - } - - if ((e->trtype != NVMF_TRTYPE_LOOP) && (fabrics_cfg.ctrl_loss_tmo >= -1)) { - len = sprintf(p, ",ctrl_loss_tmo=%d", fabrics_cfg.ctrl_loss_tmo); - if (len < 0) - return -EINVAL; - p += len; - } - - if (fabrics_cfg.fast_io_fail_tmo) { - len = sprintf(p, ",fast_io_fail_tmo=%d", fabrics_cfg.fast_io_fail_tmo); - if (len < 0) - return -EINVAL; - p += len; - } - - if (fabrics_cfg.tos != -1) { - len = sprintf(p, ",tos=%d", fabrics_cfg.tos); - if (len < 0) - return -EINVAL; - p += len; - } - - if (fabrics_cfg.keep_alive_tmo) { - len = sprintf(p, ",keep_alive_tmo=%d", fabrics_cfg.keep_alive_tmo); - if (len < 0) - return -EINVAL; - p += len; - } - - transport = trtype_str(e->trtype); - if (!strcmp(transport, "unrecognized")) { - msg(LOG_ERR, "skipping unsupported transport %d\n", - e->trtype); - return -EINVAL; - } - - len = sprintf(p, ",transport=%s", transport); - if (len < 0) - return -EINVAL; - p += len; - - if (fabrics_cfg.hdr_digest) { - len = sprintf(p, ",hdr_digest"); - if (len < 0) - return -EINVAL; - p += len; - } - - if (fabrics_cfg.data_digest) { - len = sprintf(p, ",data_digest"); - if (len < 0) - return -EINVAL; - p += len; - } - - switch (e->trtype) { - case NVMF_TRTYPE_RDMA: - case NVMF_TRTYPE_TCP: - switch (e->adrfam) { - case NVMF_ADDR_FAMILY_IP4: - case NVMF_ADDR_FAMILY_IP6: - /* FALLTHRU */ - len = sprintf(p, ",traddr=%.*s", - space_strip_len(NVMF_TRADDR_SIZE, e->traddr), - e->traddr); - if (len < 0) - return -EINVAL; - p += len; - - len = sprintf(p, ",trsvcid=%.*s", - space_strip_len(NVMF_TRSVCID_SIZE, e->trsvcid), - e->trsvcid); - if (len < 0) - return -EINVAL; - p += len; - break; - default: - msg(LOG_ERR, "skipping unsupported adrfam\n"); - return -EINVAL; - } - break; - case NVMF_TRTYPE_FC: - switch (e->adrfam) { - case NVMF_ADDR_FAMILY_FC: - len = sprintf(p, ",traddr=%.*s", - space_strip_len(NVMF_TRADDR_SIZE, e->traddr), - e->traddr); - if (len < 0) - return -EINVAL; - p += len; - break; - default: - msg(LOG_ERR, "skipping unsupported adrfam\n"); - return -EINVAL; - } - break; - } - - if (e->treq & NVMF_TREQ_DISABLE_SQFLOW && disable_sqflow) { - len = sprintf(p, ",disable_sqflow"); - if (len < 0) - return -EINVAL; - p += len; - } - - if (discover) { - enum nvme_print_flags flags; - - flags = validate_output_format(fabrics_cfg.output_format); - if (flags < 0) - flags = NORMAL; - ret = do_discover(argstr, true, flags); - } else - ret = add_ctrl(argstr); - if (ret == -EINVAL && disable_sqflow && - e->treq & NVMF_TREQ_DISABLE_SQFLOW) { - /* disable_sqflow param might not be supported, try without it */ - disable_sqflow = false; - goto retry; + if (ret > 0) + nvme_show_status(ret); + else + nvme_msg(LOG_ERR, "Failed to get discovery log: %d\n", + ret); + return nvme_status_to_errno(ret, false); } - return ret; -} -static bool cargs_match_found(struct nvmf_disc_rsp_page_entry *entry) -{ - struct connect_args cargs __cleanup__(destruct_connect_args) = { NULL, }; - struct connect_args *c = tracked_ctrls; - - cargs.traddr = strdup(entry->traddr); - cargs.transport = strdup(trtype_str(entry->trtype)); - cargs.subsysnqn = strdup(entry->subnqn); - cargs.trsvcid = strdup(entry->trsvcid); - cargs.host_traddr = strdup(fabrics_cfg.host_traddr ?: "\0"); - cargs.host_iface = strdup(fabrics_cfg.host_iface ?: "\0"); - - /* check if we have a match in the discovery recursion */ - while (c) { - if (!strcmp(cargs.subsysnqn, c->subsysnqn) && - !strcmp(cargs.transport, c->transport) && - !strcmp(cargs.traddr, c->traddr) && - !strcmp(cargs.trsvcid, c->trsvcid) && - !strcmp(cargs.host_traddr, c->host_traddr) && - !strcmp(cargs.host_iface, c->host_iface)) - return true; - c = c->next; - } - /* check if we have a matching existing controller */ - return find_ctrl_with_connectargs(&cargs) != NULL; -} - -static bool should_connect(struct nvmf_disc_rsp_page_entry *entry) -{ - int len; - - if (cargs_match_found(entry)) - return false; - - /* skip connect if the transport type doesn't match */ - if (strcmp(fabrics_cfg.transport, trtype_str(entry->trtype))) - return false; - - if (!fabrics_cfg.matching_only || !fabrics_cfg.traddr) - return true; - - len = space_strip_len(NVMF_TRADDR_SIZE, entry->traddr); - return !strncmp(fabrics_cfg.traddr, entry->traddr, len); -} - -static int connect_ctrls(struct nvmf_disc_rsp_page_hdr *log, int numrec) -{ - int i; - int instance; - int ret = 0; - - for (i = 0; i < numrec; i++) { - if (!should_connect(&log->entries[i])) - continue; - - instance = connect_ctrl(&log->entries[i]); - - /* clean success */ - if (instance >= 0) - continue; - - /* already connected print message */ - if (instance == -EALREADY) { - const char *traddr = log->entries[i].traddr; - - msg(LOG_NOTICE, "traddr=%.*s is already connected\n", - space_strip_len(NVMF_TRADDR_SIZE, - traddr), - traddr); - continue; + numrec = le64_to_cpu(log->numrec); + if (raw) + save_discovery_log(raw, log); + else if (!connect) { + if (flags == JSON) + json_discovery_log(log, numrec); + else + print_discovery_log(log, numrec); + } else if (connect) { + int i; + + for (i = 0; i < numrec; i++) { + struct nvmf_disc_log_entry *e = &log->entries[i]; + bool discover = false; + nvme_ctrl_t child; + + errno = 0; + child = nvmf_connect_disc_entry(h, e, defcfg, + &discover); + if (child) { + if (discover) + __discover(child, defcfg, raw, + persistent, quiet, + true, flags); + if (!persistent) { + nvme_ctrl_disconnect(child); + nvme_free_ctrl(child); + } + } else if (errno == EALREADY && !quiet) { + char *traddr = log->entries[i].traddr; + + space_strip_len(NVMF_TRADDR_SIZE, traddr); + nvme_msg(LOG_ERR, + "traddr=%s is already connected\n", + traddr); + } } - - /* - * don't error out. The Discovery Log may contain - * devices that aren't necessarily connectable via - * the system/host transport port. Let those items - * fail and continue on to the next log element. - */ } - return ret; -} - -static void nvmf_get_host_identifiers(int ctrl_instance) -{ - char *path; - - if (asprintf(&path, "%s/nvme%d", SYS_NVME, ctrl_instance) < 0) - return; - fabrics_cfg.hostnqn = nvme_get_ctrl_attr(path, "hostnqn"); - fabrics_cfg.hostid = nvme_get_ctrl_attr(path, "hostid"); + free(log); + return 0; } -static DEFINE_CLEANUP_FUNC(cleanup_log, struct nvmf_disc_rsp_page_hdr *, free); - -int do_discover(char *argstr, bool connect, enum nvme_print_flags flags) +static int discover_from_conf_file(nvme_host_t h, const char *desc, + bool connect, const struct nvme_fabrics_config *defcfg) { - struct nvmf_disc_rsp_page_hdr *log __cleanup__(cleanup_log) = NULL; - char *dev_name; - int instance, numrec = 0, ret, err; - int status = 0; - struct connect_args *cargs; - - cargs = extract_connect_args(argstr); - if (!cargs) - return -ENOMEM; - - if (fabrics_cfg.device && - !ctrl_matches_connectargs(fabrics_cfg.device, cargs)) { - free(fabrics_cfg.device); - fabrics_cfg.device = NULL; - } - if (!fabrics_cfg.device) - fabrics_cfg.device = find_ctrl_with_connectargs(cargs); - free_connect_args(cargs); - - if (!fabrics_cfg.device) { - instance = add_ctrl(argstr); - } else { - instance = ctrl_instance(fabrics_cfg.device); - nvmf_get_host_identifiers(instance); - } - if (instance < 0) - return instance; - - if (asprintf(&dev_name, "/dev/nvme%d", instance) < 0) - return -errno; - ret = nvmf_get_log_page_discovery(dev_name, &log, &numrec, &status); - free(dev_name); - if (!fabrics_cfg.device && !fabrics_cfg.persistent) { - err = remove_ctrl(instance); - if (err) - return err; - } - - switch (ret) { - case DISC_OK: - if (connect) - ret = connect_ctrls(log, numrec); - else if (fabrics_cfg.raw || flags == BINARY) - save_discovery_log(log, numrec); - else if (flags == JSON) - json_discovery_log(log, numrec, instance); - else - print_discovery_log(log, numrec, instance); - break; - case DISC_GET_NUMRECS: - msg(LOG_ERR, - "Get number of discovery log entries failed.\n"); - ret = status; - break; - case DISC_GET_LOG: - msg(LOG_ERR, "Get discovery log entries failed.\n"); - ret = status; - break; - case DISC_NO_LOG: - fprintf(stdout, "No discovery log entries to fetch.\n"); - ret = DISC_OK; - break; - case DISC_RETRY_EXHAUSTED: - fprintf(stdout, "Discovery retries exhausted.\n"); - ret = -EAGAIN; - break; - case DISC_NOT_EQUAL: - msg(LOG_ERR, - "Numrec values of last two get discovery log page not equal\n"); - ret = -EBADSLT; - break; - default: - msg(LOG_ERR, "Get discovery log page failed: %d\n", ret); - break; - } + char *transport = NULL, *traddr = NULL, *trsvcid = NULL; + char *host_traddr = NULL, *host_iface = NULL; + char *hostnqn = NULL, *hostid = NULL; + char *ptr, **argv, *p, line[4096]; + int argc, ret = 0; + FILE *f; - return ret; -} + struct nvme_fabrics_config cfg = { + .tos = -1, + .ctrl_loss_tmo = NVMF_DEF_CTRL_LOSS_TMO, + }; -static int discover_from_conf_file(const char *desc, char *argstr, - const struct argconfig_commandline_options *opts, bool connect) -{ - FILE *f; - char line[256], *ptr, *all_args, *args, **argv; - int argc, err, ret = 0; + OPT_ARGS(opts) = { + NVMF_OPTS(cfg), + }; f = fopen(PATH_NVMF_DISC, "r"); if (f == NULL) { - msg(LOG_ERR, "No discover params given and no %s\n", - PATH_NVMF_DISC); - return -EINVAL; + errno = ENOENT; + return -1; + } + + argv = calloc(MAX_DISC_ARGS, sizeof(char *)); + if (!argv) { + ret = -1; + goto out; } + argv[0] = "discover"; + memset(line, 0, sizeof(line)); while (fgets(line, sizeof(line), f) != NULL) { - enum nvme_print_flags flags; + nvme_ctrl_t c; if (line[0] == '#' || line[0] == '\n') continue; - args = strdup(line); - if (!args) { - msg(LOG_ERR, "failed to strdup args\n"); - ret = -ENOMEM; - goto out; - } - all_args = args; - - argv = calloc(MAX_DISC_ARGS, BUF_SIZE); - if (!argv) { - msg(LOG_ERR, "failed to allocate argv vector: %m\n"); - free(args); - ret = -ENOMEM; - goto out; - } - - argc = 0; - argv[argc++] = "discover"; - while ((ptr = strsep(&args, " =\n")) != NULL) + argc = 1; + p = line; + while ((ptr = strsep(&p, " =\n")) != NULL) argv[argc++] = ptr; + argv[argc] = NULL; - err = argconfig_parse(argc, argv, desc, opts); - if (err) - goto free_and_continue; - - if (!fabrics_cfg.transport || !fabrics_cfg.traddr) - goto free_and_continue; - - err = flags = validate_output_format(fabrics_cfg.output_format); - if (err < 0) - goto free_and_continue; - set_discovery_kato(&fabrics_cfg); - - if (traddr_is_hostname(&fabrics_cfg)) { - ret = hostname2traddr(&fabrics_cfg); - if (ret) - goto out; - } - - if (!fabrics_cfg.trsvcid) - discovery_trsvcid(&fabrics_cfg); - - err = build_options(argstr, BUF_SIZE, true); - if (err) { - ret = err; - goto free_and_continue; + memcpy(&cfg, defcfg, sizeof(cfg)); + ret = argconfig_parse(argc, argv, desc, opts); + if (ret) + goto next; + + if (!transport && !traddr) + goto next; + + c = nvme_create_ctrl(NVME_DISC_SUBSYS_NAME, transport, + traddr, host_traddr, host_iface, trsvcid); + if (!c) + goto next; + errno = 0; + ret = nvmf_add_ctrl(h, c, &cfg, false); + if (!ret) { + __discover(c, defcfg, NULL, persistent, quiet, + connect, 0); + return 0; + if (!persistent) + ret = nvme_ctrl_disconnect(c); + nvme_free_ctrl(c); } - - err = do_discover(argstr, connect, flags); - if (err) - ret = err; - -free_and_continue: - free(all_args); - free(argv); - fabrics_cfg.transport = fabrics_cfg.traddr = - fabrics_cfg.trsvcid = fabrics_cfg.host_traddr = - fabrics_cfg.host_iface = NULL; +next: + memset(&cfg, 0, sizeof(cfg)); } - + free(argv); out: fclose(f); return ret; } -int fabrics_discover(const char *desc, int argc, char **argv, bool connect) +int nvmf_discover(const char *desc, int argc, char **argv, bool connect) { - char argstr[BUF_SIZE]; - int ret; + char *nqn = NVME_DISC_SUBSYS_NAME; + char *hostnqn = NULL, *hostid = NULL; + char *host_traddr = NULL, *host_iface = NULL; + char *transport = NULL, *traddr = NULL, *trsvcid = NULL; + char *hnqn = NULL, *hid = NULL; + char *config_file = PATH_NVMF_CONFIG; enum nvme_print_flags flags; - bool quiet = false; + nvme_root_t r; + nvme_host_t h; + int ret; + char *format = "normal"; + const char *tmp_device; + + struct nvme_fabrics_config cfg = { + .tos = -1, + }; + + char *device = NULL; OPT_ARGS(opts) = { - OPT_LIST("transport", 't', &fabrics_cfg.transport, "transport type"), - OPT_LIST("traddr", 'a', &fabrics_cfg.traddr, "transport address"), - OPT_LIST("trsvcid", 's', &fabrics_cfg.trsvcid, "transport service id (e.g. IP port)"), - OPT_LIST("host-traddr", 'w', &fabrics_cfg.host_traddr, "host traddr (e.g. FC WWN's or IP source address)"), - OPT_LIST("host-iface", 'f', &fabrics_cfg.host_iface, "host transport interface (e.g. IP eth1, enp2s0)"), - OPT_LIST("hostnqn", 'q', &fabrics_cfg.hostnqn, "user-defined hostnqn (if default not used)"), - OPT_LIST("hostid", 'I', &fabrics_cfg.hostid, "user-defined hostid (if default not used)"), - OPT_LIST("raw", 'r', &fabrics_cfg.raw, "raw output file"), - OPT_LIST("device", 'd', &fabrics_cfg.device, "existing discovery controller device"), - OPT_INT("keep-alive-tmo", 'k', &fabrics_cfg.keep_alive_tmo, "keep alive timeout period in seconds"), - OPT_INT("reconnect-delay", 'c', &fabrics_cfg.reconnect_delay, "reconnect timeout period in seconds"), - OPT_INT("ctrl-loss-tmo", 'l', &fabrics_cfg.ctrl_loss_tmo, "controller loss timeout period in seconds"), - OPT_INT("fast_io_fail_tmo",'f',&fabrics_cfg.fast_io_fail_tmo, "fast I/O fail timeout (default off)"), - OPT_INT("tos", 'T', &fabrics_cfg.tos, "type of service"), - OPT_FLAG("hdr_digest", 'g', &fabrics_cfg.hdr_digest, "enable transport protocol header digest (TCP transport)"), - OPT_FLAG("data_digest", 'G', &fabrics_cfg.data_digest, "enable transport protocol data digest (TCP transport)"), - OPT_INT("nr-io-queues", 'i', &fabrics_cfg.nr_io_queues, "number of io queues to use (default is core count)"), - OPT_INT("nr-write-queues", 'W', &fabrics_cfg.nr_write_queues, "number of write queues to use (default 0)"), - OPT_INT("nr-poll-queues", 'P', &fabrics_cfg.nr_poll_queues, "number of poll queues to use (default 0)"), - OPT_INT("queue-size", 'Q', &fabrics_cfg.queue_size, "number of io queue elements to use (default 128)"), - OPT_FLAG("persistent", 'p', &fabrics_cfg.persistent, "persistent discovery connection"), - OPT_FLAG("quiet", 'S', &quiet, "suppress already connected errors"), - OPT_FLAG("matching", 'm', &fabrics_cfg.matching_only, "connect only records matching the traddr"), - OPT_FMT("output-format", 'o', &fabrics_cfg.output_format, output_format), + OPT_STRING("device", 'd', "DEV", &device, "use existing discovery controller device"), + NVMF_OPTS(cfg), + OPT_FMT("output-format", 'o', &format, output_format), + OPT_FILE("raw", 'r', &raw, "save raw output to file"), + OPT_FLAG("persistent", 'p', &persistent, "persistent discovery connection"), + OPT_FLAG("quiet", 'S', &quiet, "suppress already connected errors"), + OPT_STRING("config", 'C', "FILE", &config_file, nvmf_config_file), OPT_END() }; - fabrics_cfg.tos = -1; ret = argconfig_parse(argc, argv, desc, opts); if (ret) - goto out; + return ret; - ret = flags = validate_output_format(fabrics_cfg.output_format); + ret = flags = validate_output_format(format); if (ret < 0) - goto out; - if (fabrics_cfg.device && strcmp(fabrics_cfg.device, "none")) { - fabrics_cfg.device = strdup(fabrics_cfg.device); - if (!fabrics_cfg.device) { - ret = -ENOMEM; - goto out; - } - } - - if (quiet) - log_level = LOG_WARNING; - - if (fabrics_cfg.device && !strcmp(fabrics_cfg.device, "none")) - fabrics_cfg.device = NULL; - - fabrics_cfg.nqn = NVME_DISC_SUBSYS_NAME; - - if (!fabrics_cfg.transport && !fabrics_cfg.traddr) { - ret = discover_from_conf_file(desc, argstr, opts, connect); - } else { - set_discovery_kato(&fabrics_cfg); + return ret; - if (traddr_is_hostname(&fabrics_cfg)) { - ret = hostname2traddr(&fabrics_cfg); - if (ret) - goto out; + if (!strcmp(config_file, "none")) + config_file = NULL; + r = nvme_scan(config_file); + if (persistent && !cfg.keep_alive_tmo) + cfg.keep_alive_tmo = 30; + if (!hostnqn) + hostnqn = hnqn = nvmf_hostnqn_from_file(); + if (!hostid) + hostid = hid = nvmf_hostid_from_file(); + h = nvme_lookup_host(r, hostnqn, hostid); + if (!h) { + ret = ENOMEM; + goto out_free; + } + if (device && !strcmp(device, "none")) + device = NULL; + + if (!device && !transport && !traddr) + ret = discover_from_conf_file(h, desc, connect, &cfg); + else { + nvme_ctrl_t c; + + c = nvme_create_ctrl(nqn, transport, traddr, + host_traddr, host_iface, trsvcid); + if (!c) { + ret = ENOMEM; + goto out_free; + } + tmp_device = nvme_ctrl_get_name(c); + if (!tmp_device) { + errno = 0; + ret = nvmf_add_ctrl(h, c, &cfg, false); + } else if (strcmp(tmp_device, device)) { + device = NULL; + ret = 0; } - if (!fabrics_cfg.trsvcid) - discovery_trsvcid(&fabrics_cfg); - - ret = build_options(argstr, BUF_SIZE, true); - if (ret) - goto out; - - ret = do_discover(argstr, connect, flags); + if (!ret) { + ret = __discover(c, &cfg, raw, connect, + persistent, quiet, flags); + if (!device && !persistent) + nvme_ctrl_disconnect(c); + nvme_free_ctrl(c); + } else { + nvme_msg(LOG_ERR, "no controller found\n"); + ret = errno; + nvme_free_ctrl(c); + } } +out_free: + if (hnqn) + free(hnqn); + if (hid) + free(hid); -out: - return nvme_status_to_errno(ret, true); + return ret; } -int fabrics_connect(const char *desc, int argc, char **argv) +int nvmf_connect(const char *desc, int argc, char **argv) { - char argstr[BUF_SIZE]; - int instance, ret; + char *hnqn = NULL, *hid = NULL; + char *subsysnqn = NULL; + char *transport = NULL, *traddr = NULL; + char *host_traddr = NULL, *host_iface = NULL; + char *trsvcid = NULL, *hostnqn = NULL, *hostid = NULL; + char *config_file = PATH_NVMF_CONFIG; + nvme_root_t r; + nvme_host_t h; + nvme_ctrl_t c; + int ret; + + struct nvme_fabrics_config cfg = { + .tos = -1, + .ctrl_loss_tmo = NVMF_DEF_CTRL_LOSS_TMO, + }; OPT_ARGS(opts) = { - OPT_LIST("transport", 't', &fabrics_cfg.transport, "transport type"), - OPT_LIST("nqn", 'n', &fabrics_cfg.nqn, "nqn name"), - OPT_LIST("traddr", 'a', &fabrics_cfg.traddr, "transport address"), - OPT_LIST("trsvcid", 's', &fabrics_cfg.trsvcid, "transport service id (e.g. IP port)"), - OPT_LIST("host-traddr", 'w', &fabrics_cfg.host_traddr, "host traddr (e.g. FC WWN's or IP source address)"), - OPT_LIST("host-iface", 'f', &fabrics_cfg.host_iface, "host transport interface (e.g. IP eth1, enp2s0)"), - OPT_LIST("hostnqn", 'q', &fabrics_cfg.hostnqn, "user-defined hostnqn"), - OPT_LIST("hostid", 'I', &fabrics_cfg.hostid, "user-defined hostid (if default not used)"), - OPT_INT("nr-io-queues", 'i', &fabrics_cfg.nr_io_queues, "number of io queues to use (default is core count)"), - OPT_INT("nr-write-queues", 'W', &fabrics_cfg.nr_write_queues, "number of write queues to use (default 0)"), - OPT_INT("nr-poll-queues", 'P', &fabrics_cfg.nr_poll_queues, "number of poll queues to use (default 0)"), - OPT_INT("queue-size", 'Q', &fabrics_cfg.queue_size, "number of io queue elements to use (default 128)"), - OPT_INT("keep-alive-tmo", 'k', &fabrics_cfg.keep_alive_tmo, "keep alive timeout period in seconds"), - OPT_INT("reconnect-delay", 'c', &fabrics_cfg.reconnect_delay, "reconnect timeout period in seconds"), - OPT_INT("ctrl-loss-tmo", 'l', &fabrics_cfg.ctrl_loss_tmo, "controller loss timeout period in seconds"), - OPT_INT("fast_io_fail_tmo", 'f', &fabrics_cfg.fast_io_fail_tmo, "fast I/O fail timeout (default off)"), - OPT_INT("tos", 'T', &fabrics_cfg.tos, "type of service"), - OPT_FLAG("duplicate-connect", 'D', &fabrics_cfg.duplicate_connect, "allow duplicate connections between same transport host and subsystem port"), - OPT_FLAG("disable-sqflow", 'd', &fabrics_cfg.disable_sqflow, "disable controller sq flow control (default false)"), - OPT_FLAG("hdr-digest", 'g', &fabrics_cfg.hdr_digest, "enable transport protocol header digest (TCP transport)"), - OPT_FLAG("data-digest", 'G', &fabrics_cfg.data_digest, "enable transport protocol data digest (TCP transport)"), + OPT_STRING("nqn", 'n', "NAME", &subsysnqn, nvmf_nqn), + NVMF_OPTS(cfg), + OPT_STRING("config", 'C', "FILE", &config_file, nvmf_config_file), OPT_END() }; - fabrics_cfg.tos = -1; ret = argconfig_parse(argc, argv, desc, opts); if (ret) - goto out; + return ret; - if (traddr_is_hostname(&fabrics_cfg)) { - ret = hostname2traddr(&fabrics_cfg); - if (ret) - goto out; + if (!subsysnqn) { + nvme_msg(LOG_ERR, + "required argument [--nqn | -n] not specified\n"); + return EINVAL; } - ret = build_options(argstr, BUF_SIZE, false); - if (ret) - goto out; - - if (!fabrics_cfg.nqn) { - msg(LOG_ERR, "need a -n argument\n"); - ret = -EINVAL; - goto out; + if (!transport) { + nvme_msg(LOG_ERR, + "required argument [--transport | -t] not specified\n"); + return EINVAL; } - instance = add_ctrl(argstr); - if (instance < 0) - ret = instance; - -out: - return nvme_status_to_errno(ret, true); -} - -static int scan_sys_nvme_filter(const struct dirent *d) -{ - if (!strcmp(d->d_name, ".")) - return 0; - if (!strcmp(d->d_name, "..")) - return 0; - return 1; -} - -/* - * Returns 1 if disconnect occurred, 0 otherwise. - */ -static int disconnect_subsys(const char *nqn, char *ctrl) -{ - char *sysfs_nqn_path = NULL, *sysfs_del_path = NULL; - char subsysnqn[NVMF_NQN_SIZE] = {}; - int fd, ret = 0; - - if (asprintf(&sysfs_nqn_path, "%s/%s/subsysnqn", SYS_NVME, ctrl) < 0) - goto free; - if (asprintf(&sysfs_del_path, "%s/%s/delete_controller", SYS_NVME, ctrl) < 0) - goto free; - - fd = open(sysfs_nqn_path, O_RDONLY); - if (fd < 0) { - msg(LOG_ERR, "Failed to open %s: %s\n", - sysfs_nqn_path, strerror(errno)); - goto free; + if (strcmp(transport, "loop")) { + if (!traddr) { + nvme_msg(LOG_ERR, + "required argument [--address | -a] not specified for transport %s\n", + transport); + return EINVAL; + } } - if (read(fd, subsysnqn, NVMF_NQN_SIZE) < 0) - goto close; - - subsysnqn[strcspn(subsysnqn, "\n")] = '\0'; - if (strcmp(subsysnqn, nqn)) - goto close; - - if (!remove_ctrl_by_path(sysfs_del_path)) - ret = 1; - close: - close(fd); - free: - free(sysfs_del_path); - free(sysfs_nqn_path); - return ret; -} - -/* - * Returns the number of controllers successfully disconnected. - */ -static int disconnect_by_nqn(const char *nqn) -{ - struct dirent **devices = NULL; - int i, n, ret = 0; - - if (strlen(nqn) > NVMF_NQN_SIZE) - return -EINVAL; - - n = scandir(SYS_NVME, &devices, scan_sys_nvme_filter, alphasort); - if (n < 0) - return n; - - for (i = 0; i < n; i++) - ret += disconnect_subsys(nqn, devices[i]->d_name); - - for (i = 0; i < n; i++) - free(devices[i]); - free(devices); + if (strcmp(config_file, "none")) + config_file = NULL; + r = nvme_scan(config_file); + if (!hostnqn) + hostnqn = hnqn = nvmf_hostnqn_from_file(); + if (!hostid) + hostid = hid = nvmf_hostid_from_file(); + h = nvme_lookup_host(r, hostnqn, hostid); + if (!h) { + errno = ENOMEM; + goto out_free; + } + c = nvme_create_ctrl(subsysnqn, transport, traddr, + host_traddr, host_iface, trsvcid); + if (!c) { + errno = ENOMEM; + goto out_free; + } - return ret; -} + errno = 0; + ret = nvmf_add_ctrl(h, c, &cfg, cfg.disable_sqflow); + if (ret) + nvme_msg(LOG_ERR, "no controller found\n"); +out_free: + if (hnqn) + free(hnqn); + if (hid) + free(hid); + nvme_free_tree(r); + return errno; +} + +int nvmf_disconnect(const char *desc, int argc, char **argv) +{ + const char *device = "nvme device handle"; + nvme_root_t r; + nvme_host_t h; + nvme_subsystem_t s; + nvme_ctrl_t c; + char *p; + int ret; -static int disconnect_by_device(const char *device) -{ - int instance; + struct config { + char *nqn; + char *device; + }; - instance = ctrl_instance(device); - if (instance < 0) - return instance; - return remove_ctrl(instance); -} - -int fabrics_disconnect(const char *desc, int argc, char **argv) -{ - const char *nqn = "nqn name"; - const char *device = "nvme device"; - int ret; + struct config cfg = { 0 }; OPT_ARGS(opts) = { - OPT_LIST("nqn", 'n', &fabrics_cfg.nqn, nqn), - OPT_LIST("device", 'd', &fabrics_cfg.device, device), + OPT_STRING("nqn", 'n', "NAME", &cfg.nqn, nvmf_nqn), + OPT_STRING("device", 'd', "DEV", &cfg.device, device), OPT_END() }; ret = argconfig_parse(argc, argv, desc, opts); if (ret) - goto out; + return ret; - if (!fabrics_cfg.nqn && !fabrics_cfg.device) { - msg(LOG_ERR, "need a -n or -d argument\n"); - ret = -EINVAL; - goto out; + if (!cfg.nqn && !cfg.device) { + nvme_msg(LOG_ERR, + "Neither device name [--device | -d] nor NQN [--nqn | -n] provided\n"); + return EINVAL; } + r = nvme_scan(NULL); + if (cfg.nqn) { + int i = 0; + char *n = cfg.nqn; - if (fabrics_cfg.nqn) { - ret = disconnect_by_nqn(fabrics_cfg.nqn); - if (ret < 0) - msg(LOG_ERR, "Failed to disconnect by NQN: %s\n", - fabrics_cfg.nqn); - else { - printf("NQN:%s disconnected %d controller(s)\n", fabrics_cfg.nqn, ret); - ret = 0; + while ((p = strsep(&n, ",")) != NULL) { + if (!strlen(p)) + continue; + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + if (strcmp(nvme_subsystem_get_nqn(s), p)) + continue; + nvme_subsystem_for_each_ctrl(s, c) { + if (!nvme_ctrl_disconnect(c)) + i++; + } + } + } + } + printf("NQN:%s disconnected %d controller(s)\n", cfg.nqn, i); + } + + if (cfg.device) { + char *d; + + d = cfg.device; + while ((p = strsep(&d, ",")) != NULL) { + c = nvme_scan_ctrl(r, p); + if (!c) { + nvme_msg(LOG_ERR, + "Did not find device: %s\n", p); + nvme_free_tree(r); + return errno; + } + ret = nvme_ctrl_disconnect(c); + if (!ret) + printf("Disconnected %s\n", + nvme_ctrl_get_name(c)); + else + nvme_msg(LOG_ERR, + "Failed to disconnect %s: %s\n", + nvme_ctrl_get_name(c), strerror(errno)); } } + nvme_free_tree(r); - if (fabrics_cfg.device) { - ret = disconnect_by_device(fabrics_cfg.device); - if (ret) - msg(LOG_ERR, - "Failed to disconnect by device name: %s\n", - fabrics_cfg.device); - } - -out: - return nvme_status_to_errno(ret, true); + return 0; } -int fabrics_disconnect_all(const char *desc, int argc, char **argv) +int nvmf_disconnect_all(const char *desc, int argc, char **argv) { - struct nvme_topology t = { }; - int i, j, err; + nvme_host_t h; + nvme_subsystem_t s; + nvme_root_t r; + nvme_ctrl_t c; + int ret; - OPT_ARGS(opts) = { - OPT_END() + struct config { + char *transport; }; - err = argconfig_parse(argc, argv, desc, opts); - if (err) - goto out; - - err = scan_subsystems(&t, NULL, 0, 0, NULL); - if (err) { - msg(LOG_ERR, "Failed to scan namespaces\n"); - goto out; - } + struct config cfg = { 0 }; - for (i = 0; i < t.nr_subsystems; i++) { - struct nvme_subsystem *s = &t.subsystems[i]; + OPT_ARGS(opts) = { + OPT_STRING("transport", 'r', "STR", (char *)&cfg.transport, nvmf_tport), + OPT_END() + }; - for (j = 0; j < s->nr_ctrls; j++) { - struct nvme_ctrl *c = &s->ctrls[j]; + ret = argconfig_parse(argc, argv, desc, opts); + if (ret) + return ret; - if (!c->transport || !strcmp(c->transport, "pcie")) - continue; - err = disconnect_by_device(c->name); - if (err) - goto free; + r = nvme_scan(NULL); + if (!r) { + nvme_msg(LOG_ERR, "Failed to scan nvme subsystem: %s\n", + strerror(errno)); + return errno; + } + + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + nvme_subsystem_for_each_ctrl(s, c) { + if (cfg.transport && + strcmp(cfg.transport, + nvme_ctrl_get_transport(c))) + continue; + else if (!strcmp(nvme_ctrl_get_transport(c), + "pcie")) + continue; + if (nvme_ctrl_disconnect(c)) + nvme_msg(LOG_ERR, + "failed to disconnect %s\n", + nvme_ctrl_get_name(c)); + } } } -free: - free_topology(&t); -out: - return nvme_status_to_errno(err, true); + nvme_free_tree(r); + + return 0; } diff --git a/fabrics.h b/fabrics.h index 9b2554eb0d..62f260db99 100644 --- a/fabrics.h +++ b/fabrics.h @@ -1,57 +1,9 @@ -#ifndef _DISCOVER_H -#define _DISCOVER_H +#ifndef _FABRICS_H +#define _FABRICS_H -#define NVMF_DEF_DISC_TMO 30 - -extern char *hostnqn_read(void); - -extern int fabrics_discover(const char *desc, int argc, char **argv, bool connect); -extern int fabrics_connect(const char *desc, int argc, char **argv); -extern int fabrics_disconnect(const char *desc, int argc, char **argv); -extern int fabrics_disconnect_all(const char *desc, int argc, char **argv); - -/* Symbols used by monitor.c */ - -const char *arg_str(const char * const *strings, size_t array_size, size_t idx); - -struct fabrics_config { - const char *nqn; - const char *transport; - const char *traddr; - const char *trsvcid; - const char *host_traddr; - const char *host_iface; - const char *hostnqn; - const char *hostid; - int nr_io_queues; - int nr_write_queues; - int nr_poll_queues; - int queue_size; - int keep_alive_tmo; - int reconnect_delay; - int ctrl_loss_tmo; - int fast_io_fail_tmo; - int tos; - const char *raw; - char *device; - int duplicate_connect; - int disable_sqflow; - int hdr_digest; - int data_digest; - bool persistent; - bool matching_only; - const char *output_format; -}; -extern struct fabrics_config fabrics_cfg; - -extern const char *const trtypes[]; - -#define BUF_SIZE 4096 - -int build_options(char *argstr, int max_len, bool discover); -int do_discover(char *argstr, bool connect, enum nvme_print_flags flags); -int ctrl_instance(const char *device); -char *parse_conn_arg(const char *conargs, const char delim, const char *field); -int remove_ctrl(int instance); +extern int nvmf_discover(const char *desc, int argc, char **argv, bool connect); +extern int nvmf_connect(const char *desc, int argc, char **argv); +extern int nvmf_disconnect(const char *desc, int argc, char **argv); +extern int nvmf_disconnect_all(const char *desc, int argc, char **argv); #endif diff --git a/linux/nvme.h b/linux/nvme.h deleted file mode 100644 index 5ec2cd37ae..0000000000 --- a/linux/nvme.h +++ /dev/null @@ -1,1879 +0,0 @@ -/* - * Definitions for the NVM Express interface - * Copyright (c) 2011-2014, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#ifndef _LINUX_NVME_H -#define _LINUX_NVME_H - -#include - -#ifdef LIBUUID -#include -#else -typedef struct { - uint8_t b[16]; -} uuid_t; -#endif - -#ifdef __CHECKER__ -#define __force __attribute__((force)) -#else -#define __force -#endif - -static inline __le16 cpu_to_le16(uint16_t x) -{ - return (__force __le16)htole16(x); -} -static inline __le32 cpu_to_le32(uint32_t x) -{ - return (__force __le32)htole32(x); -} -static inline __le64 cpu_to_le64(uint64_t x) -{ - return (__force __le64)htole64(x); -} - -static inline uint16_t le16_to_cpu(__le16 x) -{ - return le16toh((__force __u16)x); -} -static inline uint32_t le32_to_cpu(__le32 x) -{ - return le32toh((__force __u32)x); -} -static inline uint64_t le64_to_cpu(__le64 x) -{ - return le64toh((__force __u64)x); -} - -/* NQN names in commands fields specified one size */ -#define NVMF_NQN_FIELD_LEN 256 - -/* However the max length of a qualified name is another size */ -#define NVMF_NQN_SIZE 223 - -#define NVMF_TRSVCID_SIZE 32 -#define NVMF_TRADDR_SIZE 256 -#define NVMF_TSAS_SIZE 256 - -#define NVME_DISC_SUBSYS_NAME "nqn.2014-08.org.nvmexpress.discovery" - -#define NVME_RDMA_IP_PORT 4420 -#define NVME_DISC_IP_PORT 8009 - -#define NVME_NSID_ALL 0xffffffff - -enum nvme_subsys_type { - NVME_NQN_DISC = 1, /* Discovery type target subsystem */ - NVME_NQN_NVME = 2, /* NVME type target subsystem */ -}; - -/* Address Family codes for Discovery Log Page entry ADRFAM field */ -enum { - NVMF_ADDR_FAMILY_PCI = 0, /* PCIe */ - NVMF_ADDR_FAMILY_IP4 = 1, /* IP4 */ - NVMF_ADDR_FAMILY_IP6 = 2, /* IP6 */ - NVMF_ADDR_FAMILY_IB = 3, /* InfiniBand */ - NVMF_ADDR_FAMILY_FC = 4, /* Fibre Channel */ - NVMF_ADDR_FAMILY_LOOP = 254, /* Reserved for host usage */ - NVMF_ADDR_FAMILY_MAX, -}; - -/* Transport Type codes for Discovery Log Page entry TRTYPE field */ -enum { - NVMF_TRTYPE_RDMA = 1, /* RDMA */ - NVMF_TRTYPE_FC = 2, /* Fibre Channel */ - NVMF_TRTYPE_TCP = 3, /* TCP */ - NVMF_TRTYPE_LOOP = 254, /* Reserved for host usage */ - NVMF_TRTYPE_MAX, -}; - -/* Transport Requirements codes for Discovery Log Page entry TREQ field */ -enum { - NVMF_TREQ_NOT_SPECIFIED = 0, /* Not specified */ - NVMF_TREQ_REQUIRED = 1, /* Required */ - NVMF_TREQ_NOT_REQUIRED = 2, /* Not Required */ - NVMF_TREQ_DISABLE_SQFLOW = (1 << 2), /* SQ flow control disable supported */ -}; - -/* RDMA QP Service Type codes for Discovery Log Page entry TSAS - * RDMA_QPTYPE field - */ -enum { - NVMF_RDMA_QPTYPE_CONNECTED = 1, /* Reliable Connected */ - NVMF_RDMA_QPTYPE_DATAGRAM = 2, /* Reliable Datagram */ -}; - -/* RDMA QP Service Type codes for Discovery Log Page entry TSAS - * RDMA_QPTYPE field - */ -enum { - NVMF_RDMA_PRTYPE_NOT_SPECIFIED = 1, /* No Provider Specified */ - NVMF_RDMA_PRTYPE_IB = 2, /* InfiniBand */ - NVMF_RDMA_PRTYPE_ROCE = 3, /* InfiniBand RoCE */ - NVMF_RDMA_PRTYPE_ROCEV2 = 4, /* InfiniBand RoCEV2 */ - NVMF_RDMA_PRTYPE_IWARP = 5, /* IWARP */ -}; - -/* RDMA Connection Management Service Type codes for Discovery Log Page - * entry TSAS RDMA_CMS field - */ -enum { - NVMF_RDMA_CMS_RDMA_CM = 1, /* Sockets based endpoint addressing */ -}; - -/* TCP port security type for Discovery Log Page entry TSAS - */ -enum { - NVMF_TCP_SECTYPE_NONE = 0, /* No Security */ - NVMF_TCP_SECTYPE_TLS = 1, /* Transport Layer Security */ -}; - -/* I/O Command Sets - */ -enum { - NVME_IOCS_NVM = 0x00, - NVME_IOCS_ZONED = 0x02, -}; - -#define NVME_NUM_IOCS_COMBINATIONS 512 - -#define NVME_AQ_DEPTH 32 -#define NVME_NR_AEN_COMMANDS 1 -#define NVME_AQ_BLK_MQ_DEPTH (NVME_AQ_DEPTH - NVME_NR_AEN_COMMANDS) - -/* - * Subtract one to leave an empty queue entry for 'Full Queue' condition. See - * NVM-Express 1.2 specification, section 4.1.2. - */ -#define NVME_AQ_MQ_TAG_DEPTH (NVME_AQ_BLK_MQ_DEPTH - 1) - -enum { - NVME_REG_CAP = 0x0000, /* Controller Capabilities */ - NVME_REG_VS = 0x0008, /* Version */ - NVME_REG_INTMS = 0x000c, /* Interrupt Mask Set */ - NVME_REG_INTMC = 0x0010, /* Interrupt Mask Clear */ - NVME_REG_CC = 0x0014, /* Controller Configuration */ - NVME_REG_CSTS = 0x001c, /* Controller Status */ - NVME_REG_NSSR = 0x0020, /* NVM Subsystem Reset */ - NVME_REG_AQA = 0x0024, /* Admin Queue Attributes */ - NVME_REG_ASQ = 0x0028, /* Admin SQ Base Address */ - NVME_REG_ACQ = 0x0030, /* Admin CQ Base Address */ - NVME_REG_CMBLOC = 0x0038, /* Controller Memory Buffer Location */ - NVME_REG_CMBSZ = 0x003c, /* Controller Memory Buffer Size */ - NVME_REG_BPINFO = 0x0040, /* Boot Partition Information */ - NVME_REG_BPRSEL = 0x0044, /* Boot Partition Read Select */ - NVME_REG_BPMBL = 0x0048, /* Boot Partition Memory Buffer Location */ - NVME_REG_CMBMSC = 0x0050, /* Controller Memory Buffer Memory Space Control */ - NVME_REG_CMBSTS = 0x0058, /* Controller Memory Buffer Status */ - NVME_REG_PMRCAP = 0x0e00, /* Persistent Memory Capabilities */ - NVME_REG_PMRCTL = 0x0e04, /* Persistent Memory Region Control */ - NVME_REG_PMRSTS = 0x0e08, /* Persistent Memory Region Status */ - NVME_REG_PMREBS = 0x0e0c, /* Persistent Memory Region Elasticity Buffer Size */ - NVME_REG_PMRSWTP= 0x0e10, /* Persistent Memory Region Sustained Write Throughput */ - NVME_REG_PMRMSCL= 0x0e14, /* Persistent Memory Region Controller Memory Space Control Lower */ - NVME_REG_PMRMSCU= 0x0e18, /* Persistent Memory Region Controller Memory Space Control Upper*/ - NVME_REG_DBS = 0x1000, /* SQ 0 Tail Doorbell */ -}; - -#define NVME_CAP_MQES(cap) ((cap) & 0xffff) -#define NVME_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff) -#define NVME_CAP_STRIDE(cap) (((cap) >> 32) & 0xf) -#define NVME_CAP_NSSRC(cap) (((cap) >> 36) & 0x1) -#define NVME_CAP_MPSMIN(cap) (((cap) >> 48) & 0xf) -#define NVME_CAP_MPSMAX(cap) (((cap) >> 52) & 0xf) - -#define NVME_CMB_BIR(cmbloc) ((cmbloc) & 0x7) -#define NVME_CMB_OFST(cmbloc) (((cmbloc) >> 12) & 0xfffff) -#define NVME_CMB_SZ(cmbsz) (((cmbsz) >> 12) & 0xfffff) -#define NVME_CMB_SZU(cmbsz) (((cmbsz) >> 8) & 0xf) - -#define NVME_CMB_WDS(cmbsz) ((cmbsz) & 0x10) -#define NVME_CMB_RDS(cmbsz) ((cmbsz) & 0x8) -#define NVME_CMB_LISTS(cmbsz) ((cmbsz) & 0x4) -#define NVME_CMB_CQS(cmbsz) ((cmbsz) & 0x2) -#define NVME_CMB_SQS(cmbsz) ((cmbsz) & 0x1) - -/* - * Submission and Completion Queue Entry Sizes for the NVM command set. - * (In bytes and specified as a power of two (2^n)). - */ -#define NVME_NVM_IOSQES 6 -#define NVME_NVM_IOCQES 4 - -enum { - NVME_CC_ENABLE = 1 << 0, - NVME_CC_CSS_NVM = 0 << 4, - NVME_CC_EN_SHIFT = 0, - NVME_CC_CSS_SHIFT = 4, - NVME_CC_MPS_SHIFT = 7, - NVME_CC_AMS_SHIFT = 11, - NVME_CC_SHN_SHIFT = 14, - NVME_CC_IOSQES_SHIFT = 16, - NVME_CC_IOCQES_SHIFT = 20, - NVME_CC_AMS_RR = 0 << NVME_CC_AMS_SHIFT, - NVME_CC_AMS_WRRU = 1 << NVME_CC_AMS_SHIFT, - NVME_CC_AMS_VS = 7 << NVME_CC_AMS_SHIFT, - NVME_CC_SHN_NONE = 0 << NVME_CC_SHN_SHIFT, - NVME_CC_SHN_NORMAL = 1 << NVME_CC_SHN_SHIFT, - NVME_CC_SHN_ABRUPT = 2 << NVME_CC_SHN_SHIFT, - NVME_CC_SHN_MASK = 3 << NVME_CC_SHN_SHIFT, - NVME_CC_IOSQES = NVME_NVM_IOSQES << NVME_CC_IOSQES_SHIFT, - NVME_CC_IOCQES = NVME_NVM_IOCQES << NVME_CC_IOCQES_SHIFT, - NVME_CSTS_RDY = 1 << 0, - NVME_CSTS_CFS = 1 << 1, - NVME_CSTS_NSSRO = 1 << 4, - NVME_CSTS_PP = 1 << 5, - NVME_CSTS_SHST_NORMAL = 0 << 2, - NVME_CSTS_SHST_OCCUR = 1 << 2, - NVME_CSTS_SHST_CMPLT = 2 << 2, - NVME_CSTS_SHST_MASK = 3 << 2, -}; - -struct nvme_id_power_state { - __le16 max_power; /* centiwatts */ - __u8 rsvd2; - __u8 flags; - __le32 entry_lat; /* microseconds */ - __le32 exit_lat; /* microseconds */ - __u8 read_tput; - __u8 read_lat; - __u8 write_tput; - __u8 write_lat; - __le16 idle_power; - __u8 idle_scale; - __u8 rsvd19; - __le16 active_power; - __u8 active_work_scale; - __u8 rsvd23[9]; -}; - -/* idle and active power scales occupy the last 2 bits of the field */ -#define POWER_SCALE(s) ((s) >> 6) - -enum { - NVME_PS_FLAGS_MAX_POWER_SCALE = 1 << 0, - NVME_PS_FLAGS_NON_OP_STATE = 1 << 1, -}; - -struct nvme_id_ctrl { - __le16 vid; - __le16 ssvid; - char sn[20]; - char mn[40]; - char fr[8]; - __u8 rab; - __u8 ieee[3]; - __u8 cmic; - __u8 mdts; - __le16 cntlid; - __le32 ver; - __le32 rtd3r; - __le32 rtd3e; - __le32 oaes; - __le32 ctratt; - __le16 rrls; - __u8 rsvd102[9]; - __u8 cntrltype; - char fguid[16]; - __le16 crdt1; - __le16 crdt2; - __le16 crdt3; - __u8 rsvd134[122]; - __le16 oacs; - __u8 acl; - __u8 aerl; - __u8 frmw; - __u8 lpa; - __u8 elpe; - __u8 npss; - __u8 avscc; - __u8 apsta; - __le16 wctemp; - __le16 cctemp; - __le16 mtfa; - __le32 hmpre; - __le32 hmmin; - __u8 tnvmcap[16]; - __u8 unvmcap[16]; - __le32 rpmbs; - __le16 edstt; - __u8 dsto; - __u8 fwug; - __le16 kas; - __le16 hctma; - __le16 mntmt; - __le16 mxtmt; - __le32 sanicap; - __le32 hmminds; - __le16 hmmaxd; - __le16 nsetidmax; - __le16 endgidmax; - __u8 anatt; - __u8 anacap; - __le32 anagrpmax; - __le32 nanagrpid; - __le32 pels; - __u8 rsvd356[156]; - __u8 sqes; - __u8 cqes; - __le16 maxcmd; - __le32 nn; - __le16 oncs; - __le16 fuses; - __u8 fna; - __u8 vwc; - __le16 awun; - __le16 awupf; - __u8 icsvscc; - __u8 nwpc; - __le16 acwu; - __le16 ocfs; - __le32 sgls; - __le32 mnan; - __u8 rsvd544[224]; - char subnqn[256]; - __u8 rsvd1024[768]; - __le32 ioccsz; - __le32 iorcsz; - __le16 icdoff; - __u8 fcatt; - __u8 msdbd; - __le16 ofcs; - __u8 rsvd1806[242]; - struct nvme_id_power_state psd[32]; - __u8 vs[1024]; -}; - -enum { - NVME_CTRL_ONCS_COMPARE = 1 << 0, - NVME_CTRL_ONCS_WRITE_UNCORRECTABLE = 1 << 1, - NVME_CTRL_ONCS_DSM = 1 << 2, - NVME_CTRL_ONCS_WRITE_ZEROES = 1 << 3, - NVME_CTRL_ONCS_TIMESTAMP = 1 << 6, - NVME_CTRL_VWC_PRESENT = 1 << 0, - NVME_CTRL_OACS_SEC_SUPP = 1 << 0, - NVME_CTRL_OACS_DIRECTIVES = 1 << 5, - NVME_CTRL_OACS_DBBUF_SUPP = 1 << 8, - NVME_CTRL_LPA_CMD_EFFECTS_LOG = 1 << 1, - NVME_CTRL_CTRATT_128_ID = 1 << 0, - NVME_CTRL_CTRATT_NON_OP_PSP = 1 << 1, - NVME_CTRL_CTRATT_NVM_SETS = 1 << 2, - NVME_CTRL_CTRATT_READ_RECV_LVLS = 1 << 3, - NVME_CTRL_CTRATT_ENDURANCE_GROUPS = 1 << 4, - NVME_CTRL_CTRATT_PREDICTABLE_LAT = 1 << 5, - NVME_CTRL_CTRATT_NAMESPACE_GRANULARITY = 1 << 7, - NVME_CTRL_CTRATT_UUID_LIST = 1 << 9, -}; - -struct nvme_lbaf { - __le16 ms; - __u8 ds; - __u8 rp; -}; - -struct nvme_id_ns { - __le64 nsze; - __le64 ncap; - __le64 nuse; - __u8 nsfeat; - __u8 nlbaf; - __u8 flbas; - __u8 mc; - __u8 dpc; - __u8 dps; - __u8 nmic; - __u8 rescap; - __u8 fpi; - __u8 dlfeat; - __le16 nawun; - __le16 nawupf; - __le16 nacwu; - __le16 nabsn; - __le16 nabo; - __le16 nabspf; - __le16 noiob; - __u8 nvmcap[16]; - __le16 npwg; - __le16 npwa; - __le16 npdg; - __le16 npda; - __le16 nows; - __le16 mssrl; - __le32 mcl; - __u8 msrc; - __u8 rsvd81[11]; - __le32 anagrpid; - __u8 rsvd96[3]; - __u8 nsattr; - __le16 nvmsetid; - __le16 endgid; - __u8 nguid[16]; - __u8 eui64[8]; - struct nvme_lbaf lbaf[16]; - __u8 rsvd192[192]; - __u8 vs[3712]; -}; - -struct nvme_id_iocs { - __le64 iocs[NVME_NUM_IOCS_COMBINATIONS]; -}; - -enum { - NVME_ID_CNS_NS = 0x00, - NVME_ID_CNS_CTRL = 0x01, - NVME_ID_CNS_NS_ACTIVE_LIST = 0x02, - NVME_ID_CNS_NS_DESC_LIST = 0x03, - NVME_ID_CNS_NVMSET_LIST = 0x04, - NVME_ID_CNS_CSI_ID_NS = 0x05, - NVME_ID_CNS_CSI_ID_CTRL = 0x06, - NVME_ID_CNS_CSI_NS_ACTIVE_LIST = 0x07, - NVME_ID_CNS_NS_PRESENT_LIST = 0x10, - NVME_ID_CNS_NS_PRESENT = 0x11, - NVME_ID_CNS_CTRL_NS_LIST = 0x12, - NVME_ID_CNS_CTRL_LIST = 0x13, - NVME_ID_CNS_PRIMARY_CTRL_CAPS = 0x14, - NVME_ID_CNS_SCNDRY_CTRL_LIST = 0x15, - NVME_ID_CNS_NS_GRANULARITY = 0x16, - NVME_ID_CNS_UUID_LIST = 0x17, - NVME_ID_CNS_CSI_NS_PRESENT_LIST = 0x1a, - NVME_ID_CNS_CSI_NS_PRESENT = 0x1b, - NVME_ID_CNS_CSI = 0x1c, -}; - -enum { - NVME_DIR_IDENTIFY = 0x00, - NVME_DIR_STREAMS = 0x01, - NVME_DIR_SND_ID_OP_ENABLE = 0x01, - NVME_DIR_SND_ST_OP_REL_ID = 0x01, - NVME_DIR_SND_ST_OP_REL_RSC = 0x02, - NVME_DIR_RCV_ID_OP_PARAM = 0x01, - NVME_DIR_RCV_ST_OP_PARAM = 0x01, - NVME_DIR_RCV_ST_OP_STATUS = 0x02, - NVME_DIR_RCV_ST_OP_RESOURCE = 0x03, - NVME_DIR_ENDIR = 0x01, -}; - -enum { - NVME_NS_FEAT_THIN = 1 << 0, - NVME_NS_FLBAS_LBA_MASK = 0xf, - NVME_NS_FLBAS_META_EXT = 0x10, - NVME_LBAF_RP_BEST = 0, - NVME_LBAF_RP_BETTER = 1, - NVME_LBAF_RP_GOOD = 2, - NVME_LBAF_RP_DEGRADED = 3, - NVME_NS_DPC_PI_LAST = 1 << 4, - NVME_NS_DPC_PI_FIRST = 1 << 3, - NVME_NS_DPC_PI_TYPE3 = 1 << 2, - NVME_NS_DPC_PI_TYPE2 = 1 << 1, - NVME_NS_DPC_PI_TYPE1 = 1 << 0, - NVME_NS_DPS_PI_FIRST = 1 << 3, - NVME_NS_DPS_PI_MASK = 0x7, - NVME_NS_DPS_PI_TYPE1 = 1, - NVME_NS_DPS_PI_TYPE2 = 2, - NVME_NS_DPS_PI_TYPE3 = 3, -}; - -struct nvme_ns_id_desc { - __u8 nidt; - __u8 nidl; - __le16 reserved; -}; - -#define NVME_NIDT_EUI64_LEN 8 -#define NVME_NIDT_NGUID_LEN 16 -#define NVME_NIDT_UUID_LEN 16 -#define NVME_NIDT_CSI_LEN 1 - -enum { - NVME_NIDT_EUI64 = 0x01, - NVME_NIDT_NGUID = 0x02, - NVME_NIDT_UUID = 0x03, - NVME_NIDT_CSI = 0x04, -}; - -#define NVME_MAX_NVMSET 31 - -struct nvme_nvmset_attr_entry { - __le16 id; - __le16 endurance_group_id; - __u8 rsvd4[4]; - __le32 random_4k_read_typical; - __le32 opt_write_size; - __u8 total_nvmset_cap[16]; - __u8 unalloc_nvmset_cap[16]; - __u8 rsvd48[80]; -}; - -struct nvme_id_nvmset { - __u8 nid; - __u8 rsvd1[127]; - struct nvme_nvmset_attr_entry ent[NVME_MAX_NVMSET]; -}; - -struct nvme_id_ns_granularity_list_entry { - __le64 namespace_size_granularity; - __le64 namespace_capacity_granularity; -}; - -struct nvme_id_ns_granularity_list { - __le32 attributes; - __u8 num_descriptors; - __u8 rsvd[27]; - struct nvme_id_ns_granularity_list_entry entry[16]; -}; - -#define NVME_MAX_UUID_ENTRIES 128 -struct nvme_id_uuid_list_entry { - __u8 header; - __u8 rsvd1[15]; - __u8 uuid[16]; -}; - -struct nvme_id_uuid_list { - struct nvme_id_uuid_list_entry entry[NVME_MAX_UUID_ENTRIES]; -}; - -/** - * struct nvme_telemetry_log_page_hdr - structure for telemetry log page - * @lpi: Log page identifier - * @iee_oui: IEEE OUI Identifier - * @dalb1: Data area 1 last block - * @dalb2: Data area 2 last block - * @dalb3: Data area 3 last block - * @ctrlavail: Controller initiated data available - * @ctrldgn: Controller initiated telemetry Data Generation Number - * @rsnident: Reason Identifier - * @telemetry_dataarea: Contains telemetry data block - * - * This structure can be used for both telemetry host-initiated log page - * and controller-initiated log page. - */ -struct nvme_telemetry_log_page_hdr { - __u8 lpi; - __u8 rsvd[4]; - __u8 iee_oui[3]; - __le16 dalb1; - __le16 dalb2; - __le16 dalb3; - __u8 rsvd1[368]; - __u8 ctrlavail; - __u8 ctrldgn; - __u8 rsnident[128]; - __u8 telemetry_dataarea[0]; -}; - -struct nvme_endurance_group_log { - __u8 critical_warning; - __u8 rsvd1[2]; - __u8 avl_spare; - __u8 avl_spare_threshold; - __u8 percent_used; - __u8 rsvd6[26]; - __u8 endurance_estimate[16]; - __u8 data_units_read[16]; - __u8 data_units_written[16]; - __u8 media_units_written[16]; - __u8 host_read_cmds[16]; - __u8 host_write_cmds[16]; - __u8 media_data_integrity_err[16]; - __u8 num_err_info_log_entries[16]; - __u8 rsvd160[352]; -}; - -struct nvme_smart_log { - __u8 critical_warning; - __u8 temperature[2]; - __u8 avail_spare; - __u8 spare_thresh; - __u8 percent_used; - __u8 endu_grp_crit_warn_sumry; - __u8 rsvd7[25]; - __u8 data_units_read[16]; - __u8 data_units_written[16]; - __u8 host_reads[16]; - __u8 host_writes[16]; - __u8 ctrl_busy_time[16]; - __u8 power_cycles[16]; - __u8 power_on_hours[16]; - __u8 unsafe_shutdowns[16]; - __u8 media_errors[16]; - __u8 num_err_log_entries[16]; - __le32 warning_temp_time; - __le32 critical_comp_time; - __le16 temp_sensor[8]; - __le32 thm_temp1_trans_count; - __le32 thm_temp2_trans_count; - __le32 thm_temp1_total_time; - __le32 thm_temp2_total_time; - __u8 rsvd232[280]; -}; - -struct nvme_self_test_res { - __u8 dsts; - __u8 seg; - __u8 vdi; - __u8 rsvd3; - __le64 poh; - __le32 nsid; - __le64 flba; - __u8 sct; - __u8 sc; - __u8 vs[2]; -} __attribute__((packed)); - -enum { - NVME_ST_CODE_SHIFT = 4, - NVME_ST_CODE_SHORT_OP = 0x1, - NVME_ST_CODE_EXT_OP = 0x2, - NVME_ST_CODE_VS = 0xe, - NVME_ST_RES_MASK = 0xf, - NVME_ST_RES_NO_ERR = 0x0, - NVME_ST_RES_ABORTED = 0x1, - NVME_ST_RES_CLR = 0x2, - NVME_ST_RES_NS_REMOVED = 0x3, - NVME_ST_RES_ABORTED_FORMAT = 0x4, - NVME_ST_RES_FATAL_ERR = 0x5, - NVME_ST_RES_UNKNOWN_SEG_FAIL = 0x6, - NVME_ST_RES_KNOWN_SEG_FAIL = 0x7, - NVME_ST_RES_ABORTED_UNKNOWN = 0x8, - NVME_ST_RES_ABORTED_SANITIZE = 0x9, - NVME_ST_RES_NOT_USED = 0xf, - NVME_ST_VALID_NSID = 1 << 0, - NVME_ST_VALID_FLBA = 1 << 1, - NVME_ST_VALID_SCT = 1 << 2, - NVME_ST_VALID_SC = 1 << 3, - NVME_ST_REPORTS = 20, - NVME_ST_LOG_ENTRY_SIZE = 28, - NVME_ST_LOG_HEAD_SIZE = 4, -}; - -struct nvme_self_test_log { - __u8 crnt_dev_selftest_oprn; - __u8 crnt_dev_selftest_compln; - __u8 rsvd2[2]; - struct nvme_self_test_res result[20]; -} __attribute__((packed)); - -struct nvme_fw_slot_info_log { - __u8 afi; - __u8 rsvd1[7]; - __le64 frs[7]; - __u8 rsvd64[448]; -}; - -struct nvme_lba_status_desc { - __u64 dslba; - __u32 nlb; - __u8 rsvd_12; - __u8 status; - __u8 rsvd_15_14[2]; -}; - -struct nvme_lba_status { - __u32 nlsd; - __u8 cmpc; - __u8 rsvd_7_5[3]; - struct nvme_lba_status_desc descs[0]; -}; - -/* NVMe Namespace Write Protect State */ -enum { - NVME_NS_NO_WRITE_PROTECT = 0, - NVME_NS_WRITE_PROTECT, - NVME_NS_WRITE_PROTECT_POWER_CYCLE, - NVME_NS_WRITE_PROTECT_PERMANENT, -}; - -#define NVME_MAX_CHANGED_NAMESPACES 1024 - -struct nvme_changed_ns_list_log { - __le32 log[NVME_MAX_CHANGED_NAMESPACES]; -}; - -enum { - NVME_CMD_EFFECTS_CSUPP = 1 << 0, - NVME_CMD_EFFECTS_LBCC = 1 << 1, - NVME_CMD_EFFECTS_NCC = 1 << 2, - NVME_CMD_EFFECTS_NIC = 1 << 3, - NVME_CMD_EFFECTS_CCC = 1 << 4, - NVME_CMD_EFFECTS_CSE_MASK = 3 << 16, - NVME_CMD_EFFECTS_UUID_SEL = 1 << 19, -}; - -struct nvme_effects_log { - __le32 acs[256]; - __le32 iocs[256]; - __u8 resv[2048]; -}; - -enum nvme_ana_state { - NVME_ANA_OPTIMIZED = 0x01, - NVME_ANA_NONOPTIMIZED = 0x02, - NVME_ANA_INACCESSIBLE = 0x03, - NVME_ANA_PERSISTENT_LOSS = 0x04, - NVME_ANA_CHANGE = 0x0f, -}; - -struct nvme_ana_group_desc { - __le32 grpid; - __le32 nnsids; - __le64 chgcnt; - __u8 state; - __u8 rsvd17[15]; - __le32 nsids[]; -}; - -/* flag for the log specific field of the ANA log */ -#define NVME_ANA_LOG_RGO (1 << 0) - -struct nvme_ana_rsp_hdr { - __le64 chgcnt; - __le16 ngrps; - __le16 rsvd10[3]; -}; - -/* persistent event type 02h */ -struct nvme_fw_commit_event { - __le64 old_fw_rev; - __le64 new_fw_rev; - __u8 fw_commit_action; - __u8 fw_slot; - __u8 sct_fw; - __u8 sc_fw; - __le16 vndr_assign_fw_commit_rc; -} __attribute__((packed)); - -/* persistent event type 03h */ -struct nvme_time_stamp_change_event { - __le64 previous_timestamp; - __le64 ml_secs_since_reset; -}; - -/* persistent event type 04h */ -struct nvme_power_on_reset_info_list { - __le16 cid; - __u8 fw_act; - __u8 op_in_prog; - __u8 rsvd4[12]; - __le32 ctrl_power_cycle; - __le64 power_on_ml_seconds; - __le64 ctrl_time_stamp; -} __attribute__((packed)); - -/* persistent event type 05h */ -struct nvme_nss_hw_err_event { - __le16 nss_hw_err_event_code; - __u8 rsvd2[2]; - __u8 *add_hw_err_info; -}; - -/* persistent event type 06h */ -struct nvme_change_ns_event { - __le32 nsmgt_cdw10; - __u8 rsvd4[4]; - __le64 nsze; - __u8 rsvd16[8]; - __le64 nscap; - __u8 flbas; - __u8 dps; - __u8 nmic; - __u8 rsvd35; - __le32 ana_grp_id; - __le16 nvmset_id; - __le16 rsvd42; - __le32 nsid; -}; - -/* persistent event type 07h */ -struct nvme_format_nvm_start_event { - __le32 nsid; - __u8 fna; - __u8 rsvd5[3]; - __le32 format_nvm_cdw10; -}; - -/* persistent event type 08h */ -struct nvme_format_nvm_compln_event { - __le32 nsid; - __u8 smallest_fpi; - __u8 format_nvm_status; - __le16 compln_info; - __le32 status_field; -}; - -/* persistent event type 09h */ -struct nvme_sanitize_start_event { - __le32 sani_cap; - __le32 sani_cdw10; - __le32 sani_cdw11; -}; - -/* persistent event type 0Ah */ -struct nvme_sanitize_compln_event { - __le16 sani_prog; - __le16 sani_status; - __le16 cmpln_info; - __u8 rsvd6[2]; -}; - -/* persistent event type 0Dh */ -struct nvme_thermal_exc_event { - __u8 over_temp; - __u8 threshold; -}; - -/* persistent event entry head */ -struct nvme_persistent_event_entry_head { - __u8 etype; - __u8 etype_rev; - __u8 ehl; - __u8 rsvd3; - __le16 ctrl_id; - __le64 etimestamp; - __u8 rsvd14[6]; - __le16 vsil; - __le16 el; -} __attribute__((packed)); - -/* persistent event log head */ -struct nvme_persistent_event_log_head { - __u8 log_id; - __u8 rsvd1[3]; - __le32 tnev; - __le64 tll; - __u8 log_rev; - __u8 rsvd17; - __le16 head_len; - __le64 timestamp; - __u8 poh[16]; - __le64 pcc; - __le16 vid; - __le16 ssvid; - __u8 sn[20]; - __u8 mn[40]; - __u8 subnqn[256]; - __u8 rsvd372[108]; - __u8 supp_event_bm[32]; -} __attribute__((packed)); - -enum nvme_persistent_event_types { - NVME_SMART_HEALTH_EVENT = 0x01, - NVME_FW_COMMIT_EVENT = 0x02, - NVME_TIMESTAMP_EVENT = 0x03, - NVME_POWER_ON_RESET_EVENT = 0x04, - NVME_NSS_HW_ERROR_EVENT = 0x05, - NVME_CHANGE_NS_EVENT = 0x06, - NVME_FORMAT_START_EVENT = 0x07, - NVME_FORMAT_COMPLETION_EVENT = 0x08, - NVME_SANITIZE_START_EVENT = 0x09, - NVME_SANITIZE_COMPLETION_EVENT = 0x0a, - NVME_THERMAL_EXCURSION_EVENT = 0x0d -}; - -enum nvme_persistent_event_log_actions { - NVME_PEVENT_LOG_READ = 0x0, - NVME_PEVENT_LOG_EST_CTX_AND_READ = 0x1, - NVME_PEVENT_LOG_RELEASE_CTX = 0x2, -}; - -/** - * struct nvme_event_agg_log_page - is common for both - * predictable latency event aggregate log and endurance - * group event aggregate log - * @num_entries: indicates the number of entries in the list. - * @entries: indicates NVMSET ID or ENDURANCE Group ID entries - */ -struct nvme_event_agg_log_page { - __le64 num_entries; - __le16 entries[]; -}; - -struct nvme_predlat_per_nvmset_log_page { - __u8 status; - __u8 rsvd1; - __le16 event_type; - __u8 rsvd4[28]; - __le64 dtwin_rtyp; - __le64 dtwin_wtyp; - __le64 dtwin_timemax; - __le64 ndwin_timemin_high; - __le64 ndwin_timemin_low; - __u8 rsvd72[56]; - __le64 dtwin_restimate; - __le64 dtwin_westimate; - __le64 dtwin_testimate; - __u8 rsvd152[360]; -}; - -struct nvme_lba_status_range_desc { - __le64 rslba; - __le32 rnlb; - __u8 rsvd12[4]; -}; - -struct nvme_lba_status_ns_element { - __le32 neid; - __le32 nlrd; - __u8 ratype; - __u8 rsvd9[7]; -}; - -struct nvme_lba_status_hdr { - __le32 lslplen; - __le32 nlslne; - __le32 estulb; - __u8 rsvd12[2]; - __le16 lsgc; -}; - -struct nvme_resv_notif_log { - __le64 log_page_count; - __u8 resv_notif_log_type; - __u8 num_logs; - __u8 rsvd10[2]; - __le32 nsid; - __u8 rsvd16[48]; -}; - -enum { - NVME_SMART_CRIT_SPARE = 1 << 0, - NVME_SMART_CRIT_TEMPERATURE = 1 << 1, - NVME_SMART_CRIT_RELIABILITY = 1 << 2, - NVME_SMART_CRIT_MEDIA = 1 << 3, - NVME_SMART_CRIT_VOLATILE_MEMORY = 1 << 4, -}; - -enum { - NVME_AER_ERROR = 0, - NVME_AER_SMART = 1, - NVME_AER_CSS = 6, - NVME_AER_VS = 7, -}; - -struct nvme_lba_range_type { - __u8 type; - __u8 attributes; - __u8 rsvd2[14]; - __u64 slba; - __u64 nlb; - __u8 guid[16]; - __u8 rsvd48[16]; -}; - -enum { - NVME_LBART_TYPE_FS = 0x01, - NVME_LBART_TYPE_RAID = 0x02, - NVME_LBART_TYPE_CACHE = 0x03, - NVME_LBART_TYPE_SWAP = 0x04, - - NVME_LBART_ATTRIB_TEMP = 1 << 0, - NVME_LBART_ATTRIB_HIDE = 1 << 1, -}; - -/* Predictable Latency Mode - Deterministic Threshold Configuration Data */ -struct nvme_plm_config { - __le16 enable_event; - __u8 rsvd2[30]; - __le64 dtwin_reads_thresh; - __le64 dtwin_writes_thresh; - __le64 dtwin_time_thresh; - __u8 rsvd56[456]; -}; - -struct nvme_reservation_status { - __le32 gen; - __u8 rtype; - __u8 regctl[2]; - __u8 resv5[2]; - __u8 ptpls; - __u8 resv10[13]; - struct { - __le16 cntlid; - __u8 rcsts; - __u8 resv3[5]; - __le64 hostid; - __le64 rkey; - } regctl_ds[]; -}; - -struct nvme_reservation_status_ext { - __le32 gen; - __u8 rtype; - __u8 regctl[2]; - __u8 resv5[2]; - __u8 ptpls; - __u8 resv10[14]; - __u8 resv24[40]; - struct { - __le16 cntlid; - __u8 rcsts; - __u8 resv3[5]; - __le64 rkey; - __u8 hostid[16]; - __u8 resv32[32]; - } regctl_eds[]; -}; - -enum nvme_async_event_type { - NVME_AER_TYPE_ERROR = 0, - NVME_AER_TYPE_SMART = 1, - NVME_AER_TYPE_NOTICE = 2, -}; - -/* I/O commands */ - -enum nvme_opcode { - nvme_cmd_flush = 0x00, - nvme_cmd_write = 0x01, - nvme_cmd_read = 0x02, - nvme_cmd_write_uncor = 0x04, - nvme_cmd_compare = 0x05, - nvme_cmd_write_zeroes = 0x08, - nvme_cmd_dsm = 0x09, - nvme_cmd_verify = 0x0c, - nvme_cmd_resv_register = 0x0d, - nvme_cmd_resv_report = 0x0e, - nvme_cmd_resv_acquire = 0x11, - nvme_cmd_resv_release = 0x15, - nvme_cmd_copy = 0x19, - nvme_zns_cmd_mgmt_send = 0x79, - nvme_zns_cmd_mgmt_recv = 0x7a, - nvme_zns_cmd_append = 0x7d, -}; - -/* - * Descriptor subtype - lower 4 bits of nvme_(keyed_)sgl_desc identifier - * - * @NVME_SGL_FMT_ADDRESS: absolute address of the data block - * @NVME_SGL_FMT_OFFSET: relative offset of the in-capsule data block - * @NVME_SGL_FMT_TRANSPORT_A: transport defined format, value 0xA - * @NVME_SGL_FMT_INVALIDATE: RDMA transport specific remote invalidation - * request subtype - */ -enum { - NVME_SGL_FMT_ADDRESS = 0x00, - NVME_SGL_FMT_OFFSET = 0x01, - NVME_SGL_FMT_TRANSPORT_A = 0x0A, - NVME_SGL_FMT_INVALIDATE = 0x0f, -}; - -/* - * Descriptor type - upper 4 bits of nvme_(keyed_)sgl_desc identifier - * - * For struct nvme_sgl_desc: - * @NVME_SGL_FMT_DATA_DESC: data block descriptor - * @NVME_SGL_FMT_SEG_DESC: sgl segment descriptor - * @NVME_SGL_FMT_LAST_SEG_DESC: last sgl segment descriptor - * - * For struct nvme_keyed_sgl_desc: - * @NVME_KEY_SGL_FMT_DATA_DESC: keyed data block descriptor - * - * Transport-specific SGL types: - * @NVME_TRANSPORT_SGL_DATA_DESC: Transport SGL data dlock descriptor - */ -enum { - NVME_SGL_FMT_DATA_DESC = 0x00, - NVME_SGL_FMT_SEG_DESC = 0x02, - NVME_SGL_FMT_LAST_SEG_DESC = 0x03, - NVME_KEY_SGL_FMT_DATA_DESC = 0x04, - NVME_TRANSPORT_SGL_DATA_DESC = 0x05, -}; - -struct nvme_sgl_desc { - __le64 addr; - __le32 length; - __u8 rsvd[3]; - __u8 type; -}; - -struct nvme_keyed_sgl_desc { - __le64 addr; - __u8 length[3]; - __u8 key[4]; - __u8 type; -}; - -union nvme_data_ptr { - struct { - __le64 prp1; - __le64 prp2; - }; - struct nvme_sgl_desc sgl; - struct nvme_keyed_sgl_desc ksgl; -}; - -/* - * Lowest two bits of our flags field (FUSE field in the spec): - * - * @NVME_CMD_FUSE_FIRST: Fused Operation, first command - * @NVME_CMD_FUSE_SECOND: Fused Operation, second command - * - * Highest two bits in our flags field (PSDT field in the spec): - * - * @NVME_CMD_PSDT_SGL_METABUF: Use SGLS for this transfer, - * If used, MPTR contains addr of single physical buffer (byte aligned). - * @NVME_CMD_PSDT_SGL_METASEG: Use SGLS for this transfer, - * If used, MPTR contains an address of an SGL segment containing - * exactly 1 SGL descriptor (qword aligned). - */ -enum { - NVME_CMD_FUSE_FIRST = (1 << 0), - NVME_CMD_FUSE_SECOND = (1 << 1), - - NVME_CMD_SGL_METABUF = (1 << 6), - NVME_CMD_SGL_METASEG = (1 << 7), - NVME_CMD_SGL_ALL = NVME_CMD_SGL_METABUF | NVME_CMD_SGL_METASEG, -}; - -enum { - NVME_RW_LR = 1 << 15, - NVME_RW_FUA = 1 << 14, - NVME_RW_DEAC = 1 << 9, - NVME_RW_DSM_FREQ_UNSPEC = 0, - NVME_RW_DSM_FREQ_TYPICAL = 1, - NVME_RW_DSM_FREQ_RARE = 2, - NVME_RW_DSM_FREQ_READS = 3, - NVME_RW_DSM_FREQ_WRITES = 4, - NVME_RW_DSM_FREQ_RW = 5, - NVME_RW_DSM_FREQ_ONCE = 6, - NVME_RW_DSM_FREQ_PREFETCH = 7, - NVME_RW_DSM_FREQ_TEMP = 8, - NVME_RW_DSM_LATENCY_NONE = 0 << 4, - NVME_RW_DSM_LATENCY_IDLE = 1 << 4, - NVME_RW_DSM_LATENCY_NORM = 2 << 4, - NVME_RW_DSM_LATENCY_LOW = 3 << 4, - NVME_RW_DSM_SEQ_REQ = 1 << 6, - NVME_RW_DSM_COMPRESSED = 1 << 7, - NVME_RW_PIREMAP = 1 << 9, - NVME_RW_PRINFO_PRCHK_REF = 1 << 10, - NVME_RW_PRINFO_PRCHK_APP = 1 << 11, - NVME_RW_PRINFO_PRCHK_GUARD = 1 << 12, - NVME_RW_PRINFO_PRACT = 1 << 13, - NVME_RW_DTYPE_STREAMS = 1 << 4, -}; - -enum { - NVME_DSMGMT_IDR = 1 << 0, - NVME_DSMGMT_IDW = 1 << 1, - NVME_DSMGMT_AD = 1 << 2, -}; - -#define NVME_DSM_MAX_RANGES 256 - -struct nvme_dsm_range { - __le32 cattr; - __le32 nlb; - __le64 slba; -}; - -struct nvme_copy_range { - __u8 rsvd0[8]; - __le64 slba; - __le16 nlb; - __u8 rsvd18[6]; - __le32 eilbrt; - __le16 elbatm; - __le16 elbat; -}; - -/* Features */ -struct nvme_feat_auto_pst { - __le64 entries[32]; -}; - -enum { - NVME_HOST_MEM_ENABLE = (1 << 0), - NVME_HOST_MEM_RETURN = (1 << 1), -}; - -/* Admin commands */ - -enum nvme_admin_opcode { - nvme_admin_delete_sq = 0x00, - nvme_admin_create_sq = 0x01, - nvme_admin_get_log_page = 0x02, - nvme_admin_delete_cq = 0x04, - nvme_admin_create_cq = 0x05, - nvme_admin_identify = 0x06, - nvme_admin_abort_cmd = 0x08, - nvme_admin_set_features = 0x09, - nvme_admin_get_features = 0x0a, - nvme_admin_async_event = 0x0c, - nvme_admin_ns_mgmt = 0x0d, - nvme_admin_activate_fw = 0x10, - nvme_admin_download_fw = 0x11, - nvme_admin_dev_self_test = 0x14, - nvme_admin_ns_attach = 0x15, - nvme_admin_keep_alive = 0x18, - nvme_admin_directive_send = 0x19, - nvme_admin_directive_recv = 0x1a, - nvme_admin_virtual_mgmt = 0x1c, - nvme_admin_nvme_mi_send = 0x1d, - nvme_admin_nvme_mi_recv = 0x1e, - nvme_admin_dbbuf = 0x7C, - nvme_admin_format_nvm = 0x80, - nvme_admin_security_send = 0x81, - nvme_admin_security_recv = 0x82, - nvme_admin_sanitize_nvm = 0x84, - nvme_admin_get_lba_status = 0x86, -}; - -enum { - NVME_QUEUE_PHYS_CONTIG = (1 << 0), - NVME_CQ_IRQ_ENABLED = (1 << 1), - NVME_SQ_PRIO_URGENT = (0 << 1), - NVME_SQ_PRIO_HIGH = (1 << 1), - NVME_SQ_PRIO_MEDIUM = (2 << 1), - NVME_SQ_PRIO_LOW = (3 << 1), - NVME_LOG_ERROR = 0x01, - NVME_LOG_SMART = 0x02, - NVME_LOG_FW_SLOT = 0x03, - NVME_LOG_CHANGED_NS = 0x04, - NVME_LOG_CMD_EFFECTS = 0x05, - NVME_LOG_DEVICE_SELF_TEST = 0x06, - NVME_LOG_TELEMETRY_HOST = 0x07, - NVME_LOG_TELEMETRY_CTRL = 0x08, - NVME_LOG_ENDURANCE_GROUP = 0x09, - NVME_LOG_PRELAT_PER_NVMSET = 0x0a, - NVME_LOG_ANA = 0x0c, - NVME_LOG_PRELAT_EVENT_AGG = 0x0b, - NVME_LOG_PERSISTENT_EVENT = 0x0d, - NVME_LOG_LBA_STATUS = 0x0e, - NVME_LOG_ENDURANCE_GROUP_EVENT_AGG = 0x0f, - NVME_LOG_DISC = 0x70, - NVME_LOG_RESERVATION = 0x80, - NVME_LOG_SANITIZE = 0x81, - NVME_LOG_ZONE_CHANGED_LIST = 0xbf, - NVME_FWACT_REPL = (0 << 3), - NVME_FWACT_REPL_ACTV = (1 << 3), - NVME_FWACT_ACTV = (2 << 3), -}; - -enum nvme_feat { - NVME_FEAT_NONE = 0x0, - NVME_FEAT_ARBITRATION = 0x01, - NVME_FEAT_POWER_MGMT = 0x02, - NVME_FEAT_LBA_RANGE = 0x03, - NVME_FEAT_TEMP_THRESH = 0x04, - NVME_FEAT_ERR_RECOVERY = 0x05, - NVME_FEAT_VOLATILE_WC = 0x06, - NVME_FEAT_NUM_QUEUES = 0x07, - NVME_FEAT_IRQ_COALESCE = 0x08, - NVME_FEAT_IRQ_CONFIG = 0x09, - NVME_FEAT_WRITE_ATOMIC = 0x0a, - NVME_FEAT_ASYNC_EVENT = 0x0b, - NVME_FEAT_AUTO_PST = 0x0c, - NVME_FEAT_HOST_MEM_BUF = 0x0d, - NVME_FEAT_TIMESTAMP = 0x0e, - NVME_FEAT_KATO = 0x0f, - NVME_FEAT_HCTM = 0X10, - NVME_FEAT_NOPSC = 0X11, - NVME_FEAT_RRL = 0x12, - NVME_FEAT_PLM_CONFIG = 0x13, - NVME_FEAT_PLM_WINDOW = 0x14, - NVME_LBA_STATUS_INFO = 0x15, - NVME_FEAT_HOST_BEHAVIOR = 0x16, - NVME_FEAT_SANITIZE = 0x17, - NVME_FEAT_ENDURANCE = 0x18, - NVME_FEAT_IOCS_PROFILE = 0x19, - NVME_FEAT_SW_PROGRESS = 0x80, - NVME_FEAT_HOST_ID = 0x81, - NVME_FEAT_RESV_MASK = 0x82, - NVME_FEAT_RESV_PERSIST = 0x83, - NVME_FEAT_WRITE_PROTECT = 0x84, -} __attribute__ ((__packed__)); - -enum { - NVME_NO_LOG_LSP = 0x0, - NVME_NO_LOG_LPO = 0x0, - NVME_LOG_ANA_LSP_RGO = 0x1, - NVME_TELEM_LSP_CREATE = 0x1, -}; - -/* Sanitize and Sanitize Monitor/Log */ -enum { - /* Sanitize */ - NVME_SANITIZE_NO_DEALLOC = 0x00000200, - NVME_SANITIZE_OIPBP = 0x00000100, - NVME_SANITIZE_OWPASS_SHIFT = 0x00000004, - NVME_SANITIZE_AUSE = 0x00000008, - NVME_SANITIZE_ACT_CRYPTO_ERASE = 0x00000004, - NVME_SANITIZE_ACT_OVERWRITE = 0x00000003, - NVME_SANITIZE_ACT_BLOCK_ERASE = 0x00000002, - NVME_SANITIZE_ACT_EXIT = 0x00000001, - - /* Sanitize Monitor/Log */ - NVME_SANITIZE_LOG_DATA_LEN = 0x0014, - NVME_SANITIZE_LOG_GLOBAL_DATA_ERASED = 0x0100, - NVME_SANITIZE_LOG_NUM_CMPLTED_PASS_MASK = 0x00F8, - NVME_SANITIZE_LOG_STATUS_MASK = 0x0007, - NVME_SANITIZE_LOG_NEVER_SANITIZED = 0x0000, - NVME_SANITIZE_LOG_COMPLETED_SUCCESS = 0x0001, - NVME_SANITIZE_LOG_IN_PROGESS = 0x0002, - NVME_SANITIZE_LOG_COMPLETED_FAILED = 0x0003, - NVME_SANITIZE_LOG_ND_COMPLETED_SUCCESS = 0x0004, -}; - -#define NVME_IDENTIFY_DATA_SIZE 4096 - -struct nvme_host_mem_buf_desc { - __le64 addr; - __le32 size; - __u32 rsvd; -}; - -/* Sanitize Log Page */ -struct nvme_sanitize_log_page { - __le16 progress; - __le16 status; - __le32 cdw10_info; - __le32 est_ovrwrt_time; - __le32 est_blk_erase_time; - __le32 est_crypto_erase_time; - __le32 est_ovrwrt_time_with_no_deallocate; - __le32 est_blk_erase_time_with_no_deallocate; - __le32 est_crypto_erase_time_with_no_deallocate; - __u8 rsvd32[480]; -}; - -/* - * Fabrics subcommands. - */ -enum nvmf_fabrics_opcode { - nvme_fabrics_command = 0x7f, -}; - -enum nvmf_capsule_command { - nvme_fabrics_type_property_set = 0x00, - nvme_fabrics_type_connect = 0x01, - nvme_fabrics_type_property_get = 0x04, -}; - -/* - * The legal cntlid range a NVMe Target will provide. - * Note that cntlid of value 0 is considered illegal in the fabrics world. - * Devices based on earlier specs did not have the subsystem concept; - * therefore, those devices had their cntlid value set to 0 as a result. - */ -#define NVME_CNTLID_MIN 1 -#define NVME_CNTLID_MAX 0xffef -#define NVME_CNTLID_DYNAMIC 0xffff - -#define MAX_DISC_LOGS 255 - -/* Discovery log page entry */ -struct nvmf_disc_rsp_page_entry { - __u8 trtype; - __u8 adrfam; - __u8 subtype; - __u8 treq; - __le16 portid; - __le16 cntlid; - __le16 asqsz; - __u8 resv8[22]; - char trsvcid[NVMF_TRSVCID_SIZE]; - __u8 resv64[192]; - char subnqn[NVMF_NQN_FIELD_LEN]; - char traddr[NVMF_TRADDR_SIZE]; - union tsas { - char common[NVMF_TSAS_SIZE]; - struct rdma { - __u8 qptype; - __u8 prtype; - __u8 cms; - __u8 resv3[5]; - __u16 pkey; - __u8 resv10[246]; - } rdma; - struct tcp { - __u8 sectype; - } tcp; - } tsas; -}; - -/* Discovery log page header */ -struct nvmf_disc_rsp_page_hdr { - __le64 genctr; - __le64 numrec; - __le16 recfmt; - __u8 resv14[1006]; - struct nvmf_disc_rsp_page_entry entries[0]; -}; - -struct nvmf_connect_data { - uuid_t hostid; - __le16 cntlid; - char resv4[238]; - char subsysnqn[NVMF_NQN_FIELD_LEN]; - char hostnqn[NVMF_NQN_FIELD_LEN]; - char resv5[256]; -}; - -struct streams_directive_params { - __le16 msl; - __le16 nssa; - __le16 nsso; - __u8 rsvd[10]; - __le32 sws; - __le16 sgs; - __le16 nsa; - __le16 nso; - __u8 rsvd2[6]; -}; - -struct nvme_effects_log_page { - __le32 acs[256]; - __le32 iocs[256]; - __u8 resv[2048]; -}; - -struct nvme_error_log_page { - __le64 error_count; - __le16 sqid; - __le16 cmdid; - __le16 status_field; - __le16 parm_error_location; - __le64 lba; - __le32 nsid; - __u8 vs; - __u8 trtype; - __u8 resv[2]; - __le64 cs; - __le16 trtype_spec_info; - __u8 resv2[22]; -}; - -struct nvme_firmware_log_page { - __u8 afi; - __u8 resv[7]; - __u64 frs[7]; - __u8 resv2[448]; -}; - -struct nvme_host_mem_buffer { - __u32 hsize; - __u32 hmdlal; - __u32 hmdlau; - __u32 hmdlec; - __u8 rsvd16[4080]; -}; - -struct nvme_auto_pst { - __u32 data; - __u32 rsvd32; -}; - -struct nvme_timestamp { - __u8 timestamp[6]; - __u8 attr; - __u8 rsvd; -}; - -struct nvme_controller_list { - __le16 num; - __le16 identifier[2047]; -}; - -struct nvme_primary_ctrl_caps { - __le16 cntlid; /* Controller Identifier */ - __le16 portid; /* Port Identifier */ - __u8 crt; /* Controller Resource Types */ - __u8 rsvd5[27]; - __le32 vqfrt; /* VQ Resources Flexible Total */ - __le32 vqrfa; /* VQ Resources Flexible Assigned */ - __le16 vqrfap; /* VQ Resources Flexible Allocated to Primary */ - __le16 vqprt; /* VQ Resources Private Total */ - __le16 vqfrsm; /* VQ Resources Flexible Secondary Maximum */ - __le16 vqgran; /* VQ Flexible Resource Preferred Granularity */ - __u8 rsvd48[16]; - __le32 vifrt; /* VI Resources Flexible Total */ - __le32 virfa; /* VI Resources Flexible Assigned */ - __u16 virfap; /* VI Resources Flexible Allocated to Primary */ - __u16 viprt; /* VI Resources Private Total */ - __u16 vifrsm; /* VI Resources Flexible Secondary Maximum */ - __u16 vigran; /* VI Flexible Resource Preferred Granularity */ - __u8 rsvd80[4016]; -}; - -struct nvme_secondary_controller_entry { - __le16 scid; /* Secondary Controller Identifier */ - __le16 pcid; /* Primary Controller Identifier */ - __u8 scs; /* Secondary Controller State */ - __u8 rsvd5[3]; - __le16 vfn; /* Virtual Function Number */ - __le16 nvq; /* Number of VQ Flexible Resources Assigned */ - __le16 nvi; /* Number of VI Flexible Resources Assigned */ - __u8 rsvd14[18]; -}; - -struct nvme_secondary_controllers_list { - __u8 num; - __u8 rsvd[31]; - struct nvme_secondary_controller_entry sc_entry[127]; -}; - -struct nvme_bar_cap { - __u16 mqes; - __u8 ams_cqr; - __u8 to; - __u16 bps_css_nssrs_dstrd; - __u8 mpsmax_mpsmin; - __u8 rsvd_cmbs_pmrs; -}; - -/* - * is_64bit_reg - It checks whether given offset of the controller register is - * 64bit or not. - * @offset: offset of controller register field in bytes - * - * It gives true if given offset is 64bit register, otherwise it returns false. - * - * Notes: This function does not care about transport so that the offset is - * not going to be checked inside of this function for the unsupported fields - * in a specific transport. For example, BPMBL(Boot Partition Memory Buffer - * Location) register is not supported by fabrics, but it can be chcked here. - */ -static inline bool is_64bit_reg(__u32 offset) -{ - if (offset == NVME_REG_CAP || - offset == NVME_REG_ASQ || - offset == NVME_REG_ACQ || - offset == NVME_REG_BPMBL) - return true; - - return false; -} - -enum { - NVME_SCT_GENERIC = 0x0, - NVME_SCT_CMD_SPECIFIC = 0x1, - NVME_SCT_MEDIA = 0x2, - NVME_SCT_PATH = 0x3, -}; - -enum { - /* - * Generic Command Status: - */ - NVME_SC_SUCCESS = 0x0, - NVME_SC_INVALID_OPCODE = 0x1, - NVME_SC_INVALID_FIELD = 0x2, - NVME_SC_CMDID_CONFLICT = 0x3, - NVME_SC_DATA_XFER_ERROR = 0x4, - NVME_SC_POWER_LOSS = 0x5, - NVME_SC_INTERNAL = 0x6, - NVME_SC_ABORT_REQ = 0x7, - NVME_SC_ABORT_QUEUE = 0x8, - NVME_SC_FUSED_FAIL = 0x9, - NVME_SC_FUSED_MISSING = 0xa, - NVME_SC_INVALID_NS = 0xb, - NVME_SC_CMD_SEQ_ERROR = 0xc, - NVME_SC_SGL_INVALID_LAST = 0xd, - NVME_SC_SGL_INVALID_COUNT = 0xe, - NVME_SC_SGL_INVALID_DATA = 0xf, - NVME_SC_SGL_INVALID_METADATA = 0x10, - NVME_SC_SGL_INVALID_TYPE = 0x11, - NVME_SC_CMB_INVALID_USE = 0x12, - NVME_SC_PRP_INVALID_OFFSET = 0x13, - NVME_SC_ATOMIC_WRITE_UNIT_EXCEEDED= 0x14, - NVME_SC_OPERATION_DENIED = 0x15, - NVME_SC_SGL_INVALID_OFFSET = 0x16, - - NVME_SC_INCONSISTENT_HOST_ID= 0x18, - NVME_SC_KEEP_ALIVE_EXPIRED = 0x19, - NVME_SC_KEEP_ALIVE_INVALID = 0x1A, - NVME_SC_PREEMPT_ABORT = 0x1B, - NVME_SC_SANITIZE_FAILED = 0x1C, - NVME_SC_SANITIZE_IN_PROGRESS = 0x1D, - - NVME_SC_NS_WRITE_PROTECTED = 0x20, - NVME_SC_CMD_INTERRUPTED = 0x21, - NVME_SC_TRANSIENT_TRANSPORT = 0x22, - - NVME_SC_LBA_RANGE = 0x80, - NVME_SC_CAP_EXCEEDED = 0x81, - NVME_SC_NS_NOT_READY = 0x82, - NVME_SC_RESERVATION_CONFLICT = 0x83, - NVME_SC_FORMAT_IN_PROGRESS = 0x84, - - /* - * Command Specific Status: - */ - NVME_SC_CQ_INVALID = 0x100, - NVME_SC_QID_INVALID = 0x101, - NVME_SC_QUEUE_SIZE = 0x102, - NVME_SC_ABORT_LIMIT = 0x103, - NVME_SC_ABORT_MISSING = 0x104, - NVME_SC_ASYNC_LIMIT = 0x105, - NVME_SC_FIRMWARE_SLOT = 0x106, - NVME_SC_FIRMWARE_IMAGE = 0x107, - NVME_SC_INVALID_VECTOR = 0x108, - NVME_SC_INVALID_LOG_PAGE = 0x109, - NVME_SC_INVALID_FORMAT = 0x10a, - NVME_SC_FW_NEEDS_CONV_RESET = 0x10b, - NVME_SC_INVALID_QUEUE = 0x10c, - NVME_SC_FEATURE_NOT_SAVEABLE = 0x10d, - NVME_SC_FEATURE_NOT_CHANGEABLE = 0x10e, - NVME_SC_FEATURE_NOT_PER_NS = 0x10f, - NVME_SC_FW_NEEDS_SUBSYS_RESET = 0x110, - NVME_SC_FW_NEEDS_RESET = 0x111, - NVME_SC_FW_NEEDS_MAX_TIME = 0x112, - NVME_SC_FW_ACTIVATE_PROHIBITED = 0x113, - NVME_SC_OVERLAPPING_RANGE = 0x114, - NVME_SC_NS_INSUFFICIENT_CAP = 0x115, - NVME_SC_NS_ID_UNAVAILABLE = 0x116, - NVME_SC_NS_ALREADY_ATTACHED = 0x118, - NVME_SC_NS_IS_PRIVATE = 0x119, - NVME_SC_NS_NOT_ATTACHED = 0x11a, - NVME_SC_THIN_PROV_NOT_SUPP = 0x11b, - NVME_SC_CTRL_LIST_INVALID = 0x11c, - NVME_SC_DEVICE_SELF_TEST_IN_PROGRESS= 0x11d, - NVME_SC_BP_WRITE_PROHIBITED = 0x11e, - NVME_SC_INVALID_CTRL_ID = 0x11f, - NVME_SC_INVALID_SECONDARY_CTRL_STATE= 0x120, - NVME_SC_INVALID_NUM_CTRL_RESOURCE = 0x121, - NVME_SC_INVALID_RESOURCE_ID = 0x122, - NVME_SC_PMR_SAN_PROHIBITED = 0x123, - NVME_SC_ANA_INVALID_GROUP_ID= 0x124, - NVME_SC_ANA_ATTACH_FAIL = 0x125, - - /* - * Command Set Specific - Namespace Types commands: - */ - NVME_SC_IOCS_NOT_SUPPORTED = 0x129, - NVME_SC_IOCS_NOT_ENABLED = 0x12A, - NVME_SC_IOCS_COMBINATION_REJECTED = 0x12B, - NVME_SC_INVALID_IOCS = 0x12C, - - /* - * I/O Command Set Specific - NVM commands: - */ - NVME_SC_BAD_ATTRIBUTES = 0x180, - NVME_SC_INVALID_PI = 0x181, - NVME_SC_READ_ONLY = 0x182, - NVME_SC_CMD_SIZE_LIMIT_EXCEEDED = 0x183, - - /* - * I/O Command Set Specific - Fabrics commands: - */ - NVME_SC_CONNECT_FORMAT = 0x180, - NVME_SC_CONNECT_CTRL_BUSY = 0x181, - NVME_SC_CONNECT_INVALID_PARAM = 0x182, - NVME_SC_CONNECT_RESTART_DISC = 0x183, - NVME_SC_CONNECT_INVALID_HOST = 0x184, - - NVME_SC_DISCOVERY_RESTART = 0x190, - NVME_SC_AUTH_REQUIRED = 0x191, - - /* - * I/O Command Set Specific - Zoned Namespace commands: - */ - NVME_SC_ZONE_BOUNDARY_ERROR = 0x1B8, - NVME_SC_ZONE_IS_FULL = 0x1B9, - NVME_SC_ZONE_IS_READ_ONLY = 0x1BA, - NVME_SC_ZONE_IS_OFFLINE = 0x1BB, - NVME_SC_ZONE_INVALID_WRITE = 0x1BC, - NVME_SC_TOO_MANY_ACTIVE_ZONES = 0x1BD, - NVME_SC_TOO_MANY_OPEN_ZONES = 0x1BE, - NVME_SC_ZONE_INVALID_STATE_TRANSITION = 0x1BF, - - /* - * Media and Data Integrity Errors: - */ - NVME_SC_WRITE_FAULT = 0x280, - NVME_SC_READ_ERROR = 0x281, - NVME_SC_GUARD_CHECK = 0x282, - NVME_SC_APPTAG_CHECK = 0x283, - NVME_SC_REFTAG_CHECK = 0x284, - NVME_SC_COMPARE_FAILED = 0x285, - NVME_SC_ACCESS_DENIED = 0x286, - NVME_SC_UNWRITTEN_BLOCK = 0x287, - - /* - * Path-related Errors: - */ - NVME_SC_INTERNAL_PATH_ERROR = 0x300, - NVME_SC_ANA_PERSISTENT_LOSS = 0x301, - NVME_SC_ANA_INACCESSIBLE = 0x302, - NVME_SC_ANA_TRANSITION = 0x303, - - /* - * Controller Detected Path errors - */ - NVME_SC_CTRL_PATHING_ERROR = 0x360, - - /* - * Host Detected Path Errors - */ - NVME_SC_HOST_PATHING_ERROR = 0x370, - NVME_SC_HOST_CMD_ABORT = 0x371, - - NVME_SC_CRD = 0x1800, - NVME_SC_DNR = 0x4000, -}; - -#define NVME_VS(major, minor, tertiary) \ - (((major) << 16) | ((minor) << 8) | (tertiary)) - -#define NVME_MAJOR(ver) ((ver) >> 16) -#define NVME_MINOR(ver) (((ver) >> 8) & 0xff) -#define NVME_TERTIARY(ver) ((ver) & 0xff) - - -/** - * struct nvme_zns_lbafe - - * zsze: - * zdes: - */ -struct nvme_zns_lbafe { - __le64 zsze; - __u8 zdes; - __u8 rsvd9[7]; -}; - -/** - * struct nvme_zns_id_ns - - * @zoc: - * @ozcs: - * @mar: - * @mor: - * @rrl: - * @frl: - * @lbafe: - * @vs: - */ -struct nvme_zns_id_ns { - __le16 zoc; - __le16 ozcs; - __le32 mar; - __le32 mor; - __le32 rrl; - __le32 frl; - __u8 rsvd20[2796]; - struct nvme_zns_lbafe lbafe[16]; - __u8 rsvd3072[768]; - __u8 vs[256]; -}; - -struct nvme_id_ctrl_nvm { - __u8 vsl; - __u8 wzsl; - __u8 wusl; - __u8 dmrl; - __u32 dmrsl; - __u64 dmsl; - __u8 rsvd16[4080]; -}; - -/** - * struct nvme_zns_id_ctrl - - * @zasl: - */ -struct nvme_zns_id_ctrl { - __u8 zasl; - __u8 rsvd1[4095]; -}; - -#define NVME_ZNS_CHANGED_ZONES_MAX 511 - -/** - * struct nvme_zns_changed_zone_log - ZNS Changed Zone List log - * @nrzid: - * @zid: - */ -struct nvme_zns_changed_zone_log { - __le16 nrzid; - __u8 rsvd2[6]; - __le64 zid[NVME_ZNS_CHANGED_ZONES_MAX]; -}; - -/** - * enum nvme_zns_zt - - */ -enum nvme_zns_zt { - NVME_ZONE_TYPE_SEQWRITE_REQ = 0x2, -}; - -/** - * enum nvme_zns_za - - */ -enum nvme_zns_za { - NVME_ZNS_ZA_ZFC = 1 << 0, - NVME_ZNS_ZA_FZR = 1 << 1, - NVME_ZNS_ZA_RZR = 1 << 2, - NVME_ZNS_ZA_ZDEV = 1 << 7, -}; - -/** - * enum nvme_zns_zs - - */ -enum nvme_zns_zs { - NVME_ZNS_ZS_EMPTY = 0x1, - NVME_ZNS_ZS_IMPL_OPEN = 0x2, - NVME_ZNS_ZS_EXPL_OPEN = 0x3, - NVME_ZNS_ZS_CLOSED = 0x4, - NVME_ZNS_ZS_READ_ONLY = 0xd, - NVME_ZNS_ZS_FULL = 0xe, - NVME_ZNS_ZS_OFFLINE = 0xf, -}; - -/** - * struct nvme_zns_desc - - */ -struct nvme_zns_desc { - __u8 zt; - __u8 zs; - __u8 za; - __u8 rsvd3[5]; - __le64 zcap; - __le64 zslba; - __le64 wp; - __u8 rsvd32[32]; -}; - -/** - * struct nvme_zone_report - - */ -struct nvme_zone_report { - __le64 nr_zones; - __u8 resv8[56]; - struct nvme_zns_desc entries[]; -}; - -enum nvme_zns_send_action { - NVME_ZNS_ZSA_CLOSE = 0x1, - NVME_ZNS_ZSA_FINISH = 0x2, - NVME_ZNS_ZSA_OPEN = 0x3, - NVME_ZNS_ZSA_RESET = 0x4, - NVME_ZNS_ZSA_OFFLINE = 0x5, - NVME_ZNS_ZSA_SET_DESC_EXT = 0x10, -}; - -enum nvme_zns_recv_action { - NVME_ZNS_ZRA_REPORT_ZONES = 0x0, - NVME_ZNS_ZRA_EXTENDED_REPORT_ZONES = 0x1, -}; - -enum nvme_zns_report_options { - NVME_ZNS_ZRAS_REPORT_ALL = 0x0, - NVME_ZNS_ZRAS_REPORT_EMPTY = 0x1, - NVME_ZNS_ZRAS_REPORT_IMPL_OPENED = 0x2, - NVME_ZNS_ZRAS_REPORT_EXPL_OPENED = 0x3, - NVME_ZNS_ZRAS_REPORT_CLOSED = 0x4, - NVME_ZNS_ZRAS_REPORT_FULL = 0x5, - NVME_ZNS_ZRAS_REPORT_READ_ONLY = 0x6, - NVME_ZNS_ZRAS_REPORT_OFFLINE = 0x7, -}; -#endif /* _LINUX_NVME_H */ diff --git a/linux/nvme_ioctl.h b/linux/nvme_ioctl.h deleted file mode 100644 index d569414211..0000000000 --- a/linux/nvme_ioctl.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Definitions for the NVM Express ioctl interface - * Copyright (c) 2011-2014, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#ifndef _UAPI_LINUX_NVME_IOCTL_H -#define _UAPI_LINUX_NVME_IOCTL_H - -#include -#include - -struct nvme_user_io { - __u8 opcode; - __u8 flags; - __u16 control; - __u16 nblocks; - __u16 rsvd; - __u64 metadata; - __u64 addr; - __u64 slba; - __u32 dsmgmt; - __u32 reftag; - __u16 apptag; - __u16 appmask; -}; - -struct nvme_passthru_cmd { - __u8 opcode; - __u8 flags; - __u16 rsvd1; - __u32 nsid; - __u32 cdw2; - __u32 cdw3; - __u64 metadata; - __u64 addr; - __u32 metadata_len; - __u32 data_len; - __u32 cdw10; - __u32 cdw11; - __u32 cdw12; - __u32 cdw13; - __u32 cdw14; - __u32 cdw15; - __u32 timeout_ms; - __u32 result; -}; - -struct nvme_passthru_cmd64 { - __u8 opcode; - __u8 flags; - __u16 rsvd1; - __u32 nsid; - __u32 cdw2; - __u32 cdw3; - __u64 metadata; - __u64 addr; - __u32 metadata_len; - __u32 data_len; - __u32 cdw10; - __u32 cdw11; - __u32 cdw12; - __u32 cdw13; - __u32 cdw14; - __u32 cdw15; - __u32 timeout_ms; - __u32 rsvd2; - __u64 result; -}; - -#define nvme_admin_cmd nvme_passthru_cmd - -#define NVME_IOCTL_ID _IO('N', 0x40) -#define NVME_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct nvme_admin_cmd) -#define NVME_IOCTL_SUBMIT_IO _IOW('N', 0x42, struct nvme_user_io) -#define NVME_IOCTL_IO_CMD _IOWR('N', 0x43, struct nvme_passthru_cmd) -#define NVME_IOCTL_RESET _IO('N', 0x44) -#define NVME_IOCTL_SUBSYS_RESET _IO('N', 0x45) -#define NVME_IOCTL_RESCAN _IO('N', 0x46) -#define NVME_IOCTL_ADMIN64_CMD _IOWR('N', 0x47, struct nvme_passthru_cmd64) -#define NVME_IOCTL_IO64_CMD _IOWR('N', 0x48, struct nvme_passthru_cmd64) - -#endif /* _UAPI_LINUX_NVME_IOCTL_H */ diff --git a/nvme-filters.c b/nvme-filters.c deleted file mode 100644 index 17c375f5a9..0000000000 --- a/nvme-filters.c +++ /dev/null @@ -1,104 +0,0 @@ -#include -#include -#include - -#include "nvme.h" - -/* global, used for controller specific namespace filter */ -int current_index; - -int scan_ctrl_namespace_filter(const struct dirent *d) -{ - int c, i, n; - - if (d->d_name[0] == '.') - return 0; - - if (strstr(d->d_name, "nvme")) { - if (sscanf(d->d_name, "nvme%dc%dn%d", &i, &c, &n) == 3) - return 1; - if (sscanf(d->d_name, "nvme%dn%d", &i, &n) == 2) - return 1; - } - return 0; -} - -int scan_namespace_filter(const struct dirent *d) -{ - int i, n; - - if (d->d_name[0] == '.') - return 0; - - if (strstr(d->d_name, "nvme")) - if (sscanf(d->d_name, "nvme%dn%d", &i, &n) == 2) - return 1; - return 0; -} - -int scan_ctrl_paths_filter(const struct dirent *d) -{ - int id, cntlid, nsid; - - if (d->d_name[0] == '.') - return 0; - - if (strstr(d->d_name, "nvme")) { - if (sscanf(d->d_name, "nvme%dc%dn%d", &id, &cntlid, &nsid) == 3) - return 1; - if (sscanf(d->d_name, "nvme%dn%d", &id, &nsid) == 2) - return 1; - } - - return 0; -} - -int scan_ctrls_filter(const struct dirent *d) -{ - int id, nsid; - - if (d->d_name[0] == '.') - return 0; - - if (strstr(d->d_name, "nvme")) { - if (sscanf(d->d_name, "nvme%dn%d", &id, &nsid) == 2) - return 0; - if (sscanf(d->d_name, "nvme%dn", &id) == 1) - return 1; - return 0; - } - - return 0; -} - -int scan_subsys_filter(const struct dirent *d) -{ - int id; - - if (d->d_name[0] == '.') - return 0; - - if (strstr(d->d_name, "nvme-subsys")) { - if (sscanf(d->d_name, "nvme-subsys%d", &id) != 1) - return 0; - return 1; - } - - return 0; -} - -int scan_dev_filter(const struct dirent *d) -{ - int ctrl, ns, part; - - if (d->d_name[0] == '.') - return 0; - - if (strstr(d->d_name, "nvme")) { - if (sscanf(d->d_name, "nvme%dn%dp%d", &ctrl, &ns, &part) == 3) - return 0; - if (sscanf(d->d_name, "nvme%dn%d", &ctrl, &ns) == 2) - return ctrl == current_index; - } - return 0; -} diff --git a/nvme-ioctl.c b/nvme-ioctl.c deleted file mode 100644 index cc12ae60d0..0000000000 --- a/nvme-ioctl.c +++ /dev/null @@ -1,1073 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nvme-ioctl.h" - -static int nvme_verify_chr(int fd) -{ - static struct stat nvme_stat; - int err = fstat(fd, &nvme_stat); - - if (err < 0) { - perror("fstat"); - return errno; - } - if (!S_ISCHR(nvme_stat.st_mode)) { - fprintf(stderr, - "Error: requesting reset on non-controller handle\n"); - return ENOTBLK; - } - return 0; -} - -int nvme_subsystem_reset(int fd) -{ - int ret; - - ret = nvme_verify_chr(fd); - if (ret) - return ret; - return ioctl(fd, NVME_IOCTL_SUBSYS_RESET); -} - -int nvme_reset_controller(int fd) -{ - int ret; - - ret = nvme_verify_chr(fd); - if (ret) - return ret; - return ioctl(fd, NVME_IOCTL_RESET); -} - -int nvme_ns_rescan(int fd) -{ - int ret; - - ret = nvme_verify_chr(fd); - if (ret) - return ret; - return ioctl(fd, NVME_IOCTL_RESCAN); -} - -int nvme_get_nsid(int fd) -{ - static struct stat nvme_stat; - int err = fstat(fd, &nvme_stat); - - if (err < 0) - return -errno; - - return ioctl(fd, NVME_IOCTL_ID); -} - -int nvme_submit_passthru(int fd, unsigned long ioctl_cmd, - struct nvme_passthru_cmd *cmd) -{ - return ioctl(fd, ioctl_cmd, cmd); -} - -int nvme_submit_admin_passthru(int fd, struct nvme_passthru_cmd *cmd) -{ - return ioctl(fd, NVME_IOCTL_ADMIN_CMD, cmd); -} - -int nvme_submit_io_passthru(int fd, struct nvme_passthru_cmd *cmd) -{ - return ioctl(fd, NVME_IOCTL_IO_CMD, cmd); -} - -int nvme_passthru(int fd, unsigned long ioctl_cmd, __u8 opcode, - __u8 flags, __u16 rsvd, - __u32 nsid, __u32 cdw2, __u32 cdw3, __u32 cdw10, __u32 cdw11, - __u32 cdw12, __u32 cdw13, __u32 cdw14, __u32 cdw15, - __u32 data_len, void *data, __u32 metadata_len, - void *metadata, __u32 timeout_ms, __u32 *result) -{ - struct nvme_passthru_cmd cmd = { - .opcode = opcode, - .flags = flags, - .rsvd1 = rsvd, - .nsid = nsid, - .cdw2 = cdw2, - .cdw3 = cdw3, - .metadata = (__u64)(uintptr_t) metadata, - .addr = (__u64)(uintptr_t) data, - .metadata_len = metadata_len, - .data_len = data_len, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw13 = cdw13, - .cdw14 = cdw14, - .cdw15 = cdw15, - .timeout_ms = timeout_ms, - .result = 0, - }; - int err; - - err = nvme_submit_passthru(fd, ioctl_cmd, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} - -int nvme_io(int fd, __u8 opcode, __u64 slba, __u16 nblocks, __u16 control, - __u32 dsmgmt, __u32 reftag, __u16 apptag, __u16 appmask, void *data, - void *metadata) -{ - struct nvme_user_io io = { - .opcode = opcode, - .flags = 0, - .control = control, - .nblocks = nblocks, - .rsvd = 0, - .metadata = (__u64)(uintptr_t) metadata, - .addr = (__u64)(uintptr_t) data, - .slba = slba, - .dsmgmt = dsmgmt, - .reftag = reftag, - .appmask = appmask, - .apptag = apptag, - }; - return ioctl(fd, NVME_IOCTL_SUBMIT_IO, &io); -} - -int nvme_verify(int fd, __u32 nsid, __u64 slba, __u16 nblocks, - __u16 control, __u32 reftag, __u16 apptag, __u16 appmask) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_verify, - .nsid = nsid, - .cdw10 = slba & 0xffffffff, - .cdw11 = slba >> 32, - .cdw12 = nblocks | (control << 16), - .cdw14 = reftag, - .cdw15 = apptag | (appmask << 16), - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_passthru_io(int fd, __u8 opcode, __u8 flags, __u16 rsvd, - __u32 nsid, __u32 cdw2, __u32 cdw3, __u32 cdw10, - __u32 cdw11, __u32 cdw12, __u32 cdw13, __u32 cdw14, - __u32 cdw15, __u32 data_len, void *data, - __u32 metadata_len, void *metadata, __u32 timeout_ms) -{ - return nvme_passthru(fd, NVME_IOCTL_IO_CMD, opcode, flags, rsvd, nsid, - cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, cdw14, - cdw15, data_len, data, metadata_len, metadata, - timeout_ms, NULL); -} - -int nvme_write_zeros(int fd, __u32 nsid, __u64 slba, __u16 nlb, - __u16 control, __u32 reftag, __u16 apptag, __u16 appmask) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_write_zeroes, - .nsid = nsid, - .cdw10 = slba & 0xffffffff, - .cdw11 = slba >> 32, - .cdw12 = nlb | (control << 16), - .cdw14 = reftag, - .cdw15 = apptag | (appmask << 16), - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_write_uncorrectable(int fd, __u32 nsid, __u64 slba, __u16 nlb) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_write_uncor, - .nsid = nsid, - .cdw10 = slba & 0xffffffff, - .cdw11 = slba >> 32, - .cdw12 = nlb, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_flush(int fd, __u32 nsid) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_flush, - .nsid = nsid, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_dsm(int fd, __u32 nsid, __u32 cdw11, struct nvme_dsm_range *dsm, - __u16 nr_ranges) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_dsm, - .nsid = nsid, - .addr = (__u64)(uintptr_t) dsm, - .data_len = nr_ranges * sizeof(*dsm), - .cdw10 = nr_ranges - 1, - .cdw11 = cdw11, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -struct nvme_dsm_range *nvme_setup_dsm_range(int *ctx_attrs, int *llbas, - unsigned long long *slbas, - __u16 nr_ranges) -{ - int i; - struct nvme_dsm_range *dsm = malloc(nr_ranges * sizeof(*dsm)); - - if (!dsm) { - fprintf(stderr, "malloc: %s\n", strerror(errno)); - return NULL; - } - for (i = 0; i < nr_ranges; i++) { - dsm[i].cattr = cpu_to_le32(ctx_attrs[i]); - dsm[i].nlb = cpu_to_le32(llbas[i]); - dsm[i].slba = cpu_to_le64(slbas[i]); - } - return dsm; -} - -int nvme_copy(int fd, __u32 nsid, struct nvme_copy_range *copy, __u64 sdlba, - __u16 nr, __u8 prinfor, __u8 prinfow, __u8 dtype, __u16 dspec, - __u8 format, int lr, int fua, __u32 ilbrt, __u16 lbatm, - __u16 lbat) -{ - __u32 cdw12 = ((nr - 1) & 0xff) | ((format & 0xf) << 8) | - ((prinfor & 0xf) << 12) | ((dtype & 0xf) << 20) | - ((prinfow & 0xf) << 26) | ((fua & 0x1) << 30) | - ((lr & 0x1) << 31); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_copy, - .nsid = nsid, - .addr = (__u64)(uintptr_t)copy, - .data_len = nr * sizeof(*copy), - .cdw10 = sdlba & 0xffffffff, - .cdw11 = sdlba >> 32, - .cdw12 = cdw12, - .cdw13 = (dspec & 0xffff) << 16, - .cdw14 = ilbrt, - .cdw15 = (lbatm << 16) | lbat, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -struct nvme_copy_range *nvme_setup_copy_range(int *nlbs, unsigned long long *slbas, - int *eilbrts, int *elbatms, int *elbats, __u16 nr) -{ - struct nvme_copy_range *copy = malloc(nr * sizeof(*copy)); - if (!copy) { - fprintf(stderr, "malloc: %s\n", strerror(errno)); - return NULL; - } - - for (int i = 0; i < nr; i++) { - copy[i].nlb = cpu_to_le16(nlbs[i]); - copy[i].slba = cpu_to_le64(slbas[i]); - copy[i].eilbrt = cpu_to_le32(eilbrts[i]); - copy[i].elbatm = cpu_to_le16(elbatms[i]); - copy[i].elbat = cpu_to_le16(elbats[i]); - } - - return copy; -} - -int nvme_resv_acquire(int fd, __u32 nsid, __u8 rtype, __u8 racqa, - bool iekey, __u64 crkey, __u64 nrkey) -{ - __le64 payload[2] = { cpu_to_le64(crkey), cpu_to_le64(nrkey) }; - __u32 cdw10 = (racqa & 0x7) | (iekey ? 1 << 3 : 0) | rtype << 8; - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_resv_acquire, - .nsid = nsid, - .cdw10 = cdw10, - .addr = (__u64)(uintptr_t) (payload), - .data_len = sizeof(payload), - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_resv_register(int fd, __u32 nsid, __u8 rrega, __u8 cptpl, - bool iekey, __u64 crkey, __u64 nrkey) -{ - __le64 payload[2] = { cpu_to_le64(crkey), cpu_to_le64(nrkey) }; - __u32 cdw10 = (rrega & 0x7) | (iekey ? 1 << 3 : 0) | cptpl << 30; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_resv_register, - .nsid = nsid, - .cdw10 = cdw10, - .addr = (__u64)(uintptr_t) (payload), - .data_len = sizeof(payload), - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_resv_release(int fd, __u32 nsid, __u8 rtype, __u8 rrela, - bool iekey, __u64 crkey) -{ - __le64 payload[1] = { cpu_to_le64(crkey) }; - __u32 cdw10 = (rrela & 0x7) | (iekey ? 1 << 3 : 0) | rtype << 8; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_resv_release, - .nsid = nsid, - .cdw10 = cdw10, - .addr = (__u64)(uintptr_t) (payload), - .data_len = sizeof(payload), - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_resv_report(int fd, __u32 nsid, __u32 numd, __u32 cdw11, void *data) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_resv_report, - .nsid = nsid, - .cdw10 = numd, - .cdw11 = cdw11, - .addr = (__u64)(uintptr_t) data, - .data_len = (numd + 1) << 2, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_identify13(int fd, __u32 nsid, __u32 cdw10, __u32 cdw11, void *data) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_identify, - .nsid = nsid, - .addr = (__u64)(uintptr_t) data, - .data_len = NVME_IDENTIFY_DATA_SIZE, - .cdw10 = cdw10, - .cdw11 = cdw11, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_identify(int fd, __u32 nsid, __u32 cdw10, void *data) -{ - return nvme_identify13(fd, nsid, cdw10, 0, data); -} - -int nvme_identify_ctrl(int fd, void *data) -{ - memset(data, 0, sizeof(struct nvme_id_ctrl)); - return nvme_identify(fd, 0, 1, data); -} - -int nvme_identify_ns(int fd, __u32 nsid, bool present, void *data) -{ - int cns = present ? NVME_ID_CNS_NS_PRESENT : NVME_ID_CNS_NS; - - return nvme_identify(fd, nsid, cns, data); -} - -int nvme_identify_ns_list_csi(int fd, __u32 nsid, __u8 csi, bool all, void *data) -{ - int cns; - - if (csi) { - cns = all ? NVME_ID_CNS_CSI_NS_PRESENT_LIST : NVME_ID_CNS_CSI_NS_ACTIVE_LIST; - } else { - cns = all ? NVME_ID_CNS_NS_PRESENT_LIST : NVME_ID_CNS_NS_ACTIVE_LIST; - } - - return nvme_identify13(fd, nsid, cns, csi << 24, data); -} - -int nvme_identify_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data) -{ - int cns = nsid ? NVME_ID_CNS_CTRL_NS_LIST : NVME_ID_CNS_CTRL_LIST; - - return nvme_identify(fd, nsid, (cntid << 16) | cns, data); -} - -int nvme_identify_primary_ctrl_caps(int fd, void *data) -{ - return nvme_identify(fd, 0, NVME_ID_CNS_PRIMARY_CTRL_CAPS, data); -} - -int nvme_identify_secondary_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data) -{ - return nvme_identify(fd, nsid, (cntid << 16) | NVME_ID_CNS_SCNDRY_CTRL_LIST, data); -} - -int nvme_identify_ns_descs(int fd, __u32 nsid, void *data) -{ - - return nvme_identify(fd, nsid, NVME_ID_CNS_NS_DESC_LIST, data); -} - -int nvme_identify_nvmset(int fd, __u16 nvmset_id, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_NVMSET_LIST, nvmset_id, data); -} - -int nvme_identify_ns_granularity(int fd, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_NS_GRANULARITY, 0, data); -} - -int nvme_identify_uuid(int fd, void *data) -{ - return nvme_identify(fd, 0, NVME_ID_CNS_UUID_LIST, data); -} - -int nvme_identify_ctrl_nvm(int fd, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_CSI_ID_CTRL, 0, data); -} - -int nvme_zns_identify_ns(int fd, __u32 nsid, void *data) -{ - return nvme_identify13(fd, nsid, NVME_ID_CNS_CSI_ID_NS, 2 << 24, data); -} - -int nvme_zns_identify_ctrl(int fd, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_CSI_ID_CTRL, 2 << 24, data); -} - -int nvme_identify_iocs(int fd, __u16 cntid, void *data) -{ - return nvme_identify(fd, 0, (cntid << 16) | NVME_ID_CNS_CSI, data); -} - -int nvme_get_log14(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo, - __u16 lsi, bool rae, __u8 uuid_ix, __u32 data_len, void *data) -{ - __u32 numd = (data_len >> 2) - 1; - __u16 numdu = numd >> 16, numdl = numd & 0xffff; - __u32 cdw10 = log_id | (numdl << 16) | (rae ? 1 << 15 : 0) | lsp << 8; - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_get_log_page, - .nsid = nsid, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - .cdw10 = cdw10, - .cdw11 = numdu | (lsi << 16), - .cdw12 = lpo & 0xffffffff, - .cdw13 = lpo >> 32, - .cdw14 = uuid_ix, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_get_log13(int fd, __u32 nsid, __u8 log_id, __u8 lsp, - __u64 lpo, __u16 lsi, bool rae, __u32 data_len, - void *data) -{ - return nvme_get_log14(fd, nsid, log_id, lsp, lpo, lsi, rae, 0, - data_len, data); -} - -int nvme_get_log(int fd, __u32 nsid, __u8 log_id, bool rae, - __u8 lsp, __u32 data_len, void *data) -{ - __u32 offset = 0, xfer_len = data_len; - void *ptr = data; - int ret; - - /* - * 4k is the smallest possible transfer unit, so by - * restricting ourselves for 4k transfers we avoid having - * to check the MDTS value of the controller. - */ - do { - xfer_len = data_len - offset; - if (xfer_len > 4096) - xfer_len = 4096; - - ret = nvme_get_log13(fd, nsid, log_id, lsp, - offset, 0, rae, xfer_len, ptr); - if (ret) - return ret; - - offset += xfer_len; - ptr += xfer_len; - } while (offset < data_len); - - return 0; -} - -int nvme_get_telemetry_log(int fd, void *lp, int generate_report, - int ctrl_init, size_t log_page_size, __u64 offset) -{ - if (ctrl_init) - return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_TELEMETRY_CTRL, - NVME_NO_LOG_LSP, offset, - 0, 1, log_page_size, lp); - if (generate_report) - return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_TELEMETRY_HOST, - NVME_TELEM_LSP_CREATE, offset, - 0, 1, log_page_size, lp); - else - return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_TELEMETRY_HOST, - NVME_NO_LOG_LSP, offset, - 0, 1, log_page_size, lp); -} - -int nvme_fw_log(int fd, struct nvme_firmware_log_page *fw_log) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_FW_SLOT, true, - NVME_NO_LOG_LSP, sizeof(*fw_log), fw_log); -} - -int nvme_changed_ns_list_log(int fd, struct nvme_changed_ns_list_log *changed_ns_list_log) -{ - return nvme_get_log(fd, 0, NVME_LOG_CHANGED_NS, true, - NVME_NO_LOG_LSP, sizeof(changed_ns_list_log->log), - changed_ns_list_log->log); -} - -int nvme_error_log(int fd, int entries, struct nvme_error_log_page *err_log) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_ERROR, false, - NVME_NO_LOG_LSP, entries * sizeof(*err_log), err_log); -} - -int nvme_endurance_log(int fd, __u16 group_id, struct nvme_endurance_group_log *endurance_log) -{ - return nvme_get_log13(fd, 0, NVME_LOG_ENDURANCE_GROUP, 0, 0, group_id, 0, - sizeof(*endurance_log), endurance_log); -} - -int nvme_smart_log(int fd, __u32 nsid, struct nvme_smart_log *smart_log) -{ - return nvme_get_log(fd, nsid, NVME_LOG_SMART, false, - NVME_NO_LOG_LSP, sizeof(*smart_log), smart_log); -} - -int nvme_ana_log(int fd, void *ana_log, size_t ana_log_len, int rgo) -{ - return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_ANA, rgo, 0, 0, - true, ana_log_len, ana_log); -} - -int nvme_self_test_log(int fd, __u32 size, struct nvme_self_test_log *self_test_log) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_DEVICE_SELF_TEST, false, - NVME_NO_LOG_LSP, size, self_test_log); -} - -int nvme_effects_log(int fd, struct nvme_effects_log_page *effects_log) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_CMD_EFFECTS, false, - NVME_NO_LOG_LSP, sizeof(*effects_log), effects_log); -} - -int nvme_discovery_log(int fd, struct nvmf_disc_rsp_page_hdr *log, __u32 size) -{ - return nvme_get_log(fd, 0, NVME_LOG_DISC, false, NVME_NO_LOG_LSP, size, log); -} - -int nvme_sanitize_log(int fd, bool rae, struct nvme_sanitize_log_page *sanitize_log) -{ - return nvme_get_log(fd, 0, NVME_LOG_SANITIZE, rae, - NVME_NO_LOG_LSP, sizeof(*sanitize_log), sanitize_log); -} - -int nvme_predictable_latency_per_nvmset_log(int fd, - __u16 nvmset_id, - struct nvme_predlat_per_nvmset_log_page *plpns_log) -{ - return nvme_get_log13(fd, NVME_NSID_ALL, - NVME_LOG_PRELAT_PER_NVMSET, 0, 0, nvmset_id, - false, sizeof(*plpns_log), plpns_log); -} - -int nvme_predictable_latency_event_agg_log(int fd, - void *pea_log, bool rae, __u32 size) -{ - return nvme_get_log(fd, NVME_NSID_ALL, - NVME_LOG_PRELAT_EVENT_AGG, rae, NVME_NO_LOG_LSP, - size, pea_log); -} - -int nvme_persistent_event_log(int fd, __u8 action, __u32 size, - void *pevent_log_info) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_PERSISTENT_EVENT, - false, action, size, pevent_log_info); -} - -int nvme_endurance_group_event_agg_log(int fd, - void *endurance_log, bool rae, __u32 size) -{ - return nvme_get_log(fd, NVME_NSID_ALL, - NVME_LOG_ENDURANCE_GROUP_EVENT_AGG, rae, NVME_NO_LOG_LSP, - size, endurance_log); -} - -int nvme_lba_status_log(int fd, void *lba_status, bool rae, - __u32 size) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_LBA_STATUS, - rae, NVME_NO_LOG_LSP, size, lba_status); -} - -int nvme_resv_notif_log(int fd, struct nvme_resv_notif_log *resv) -{ - return nvme_get_log(fd, 0, NVME_LOG_RESERVATION, false, - NVME_NO_LOG_LSP, sizeof(*resv), resv); -} - -int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10, __u32 cdw11, - __u32 cdw12, __u32 cdw14, __u32 data_len, void *data, __u32 *result) -{ - struct nvme_admin_cmd cmd = { - .opcode = opcode, - .nsid = nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw14 = cdw14, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - }; - int err; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} - -int nvme_set_feature(int fd, __u32 nsid, __u8 fid, __u32 value, __u32 cdw12, - bool save, __u8 uuid_index, __u32 data_len, void *data, __u32 *result) -{ - __u32 cdw10 = fid | (save ? 1 << 31 : 0); - __u32 cdw14 = uuid_index; - - return nvme_feature(fd, nvme_admin_set_features, nsid, cdw10, value, - cdw12, cdw14, data_len, data, result); -} - - -int nvme_get_property(int fd, int offset, uint64_t *value) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_fabrics_command, - .nsid = nvme_fabrics_type_property_get, - .cdw10 = is_64bit_reg(offset), - .cdw11 = offset, - }; - int err; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && value) - *value = cmd.result; - return err; -} - -int nvme_get_properties(int fd, void **pbar) -{ - int offset; - uint64_t value; - int err, size = getpagesize(); - - *pbar = malloc(size); - if (!*pbar) { - fprintf(stderr, "malloc: %s\n", strerror(errno)); - return -ENOMEM; - } - - memset(*pbar, 0xff, size); - for (offset = NVME_REG_CAP; offset <= NVME_REG_CMBSZ;) { - err = nvme_get_property(fd, offset, &value); - if (err > 0 && (err & 0xff) == NVME_SC_INVALID_FIELD) { - err = 0; - value = -1; - } else if (err) { - free(*pbar); - break; - } - if (is_64bit_reg(offset)) { - *(uint64_t *)(*pbar + offset) = value; - offset += 8; - } else { - *(uint32_t *)(*pbar + offset) = value; - offset += 4; - } - } - - return err; -} - -int nvme_set_property(int fd, int offset, uint64_t value) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_fabrics_command, - .nsid = nvme_fabrics_type_property_set, - .cdw10 = is_64bit_reg(offset), - .cdw11 = offset, - .cdw12 = value & 0xffffffff, - .cdw13 = value >> 32, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_get_feature(int fd, __u32 nsid, __u8 fid, __u8 sel, __u32 cdw11, - __u8 uuid_index, __u32 data_len, void *data, __u32 *result) -{ - __u32 cdw10 = fid | sel << 8; - __u32 cdw14 = uuid_index; - - return nvme_feature(fd, nvme_admin_get_features, nsid, cdw10, cdw11, - 0, cdw14, data_len, data, result); -} - -int nvme_format(int fd, __u32 nsid, __u8 lbaf, __u8 ses, __u8 pi, - __u8 pil, __u8 ms, __u32 timeout) -{ - __u8 lbafl = lbaf & 0xf; - __u8 lbafu = (lbaf >> 4) & 0x3; - __u32 cdw10 = lbafl | ms << 4 | pi << 5 | pil << 8 | ses << 9 | - lbafu << 12; - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_format_nvm, - .nsid = nsid, - .cdw10 = cdw10, - .timeout_ms = timeout, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_ns_create(int fd, __u64 nsze, __u64 ncap, __u8 flbas, __u8 dps, - __u8 nmic, __u32 anagrpid, __u16 nvmsetid, __u8 csi, - __u32 timeout, __u32 *result) -{ - struct nvme_id_ns ns = { - .nsze = cpu_to_le64(nsze), - .ncap = cpu_to_le64(ncap), - .flbas = flbas, - .dps = dps, - .nmic = nmic, - .anagrpid = anagrpid, - .nvmsetid = nvmsetid, - }; - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_ns_mgmt, - .addr = (__u64)(uintptr_t) ((void *)&ns), - .cdw10 = 0, - .cdw11 = csi << 24, - .data_len = 0x1000, - .timeout_ms = timeout, - }; - int err; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} - -int nvme_ns_delete(int fd, __u32 nsid, __u32 timeout) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_ns_mgmt, - .nsid = nsid, - .cdw10 = 1, - .timeout_ms = timeout, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_ns_attachment(int fd, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist, - bool attach) -{ - struct nvme_controller_list cntlist = { - .num = cpu_to_le16(num_ctrls), - }; - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_ns_attach, - .nsid = nsid, - .addr = (__u64)(uintptr_t)&cntlist, - .cdw10 = attach ? 0 : 1, - .data_len = 0x1000, - }; - int i; - - for (i = 0; i < num_ctrls; i++) - cntlist.identifier[i] = cpu_to_le16(ctrlist[i]); - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_fw_download(int fd, __u32 offset, __u32 data_len, void *data) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_download_fw, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - .cdw10 = (data_len >> 2) - 1, - .cdw11 = offset >> 2, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_fw_commit(int fd, __u8 slot, __u8 action, __u8 bpid) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_activate_fw, - .cdw10 = (bpid << 31) | (action << 3) | slot, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_sec_send(int fd, __u32 nsid, __u8 nssf, __u16 spsp, - __u8 secp, __u32 tl, __u32 data_len, void *data) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_security_send, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - .nsid = nsid, - .cdw10 = secp << 24 | spsp << 8 | nssf, - .cdw11 = tl, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_sec_recv(int fd, __u32 nsid, __u8 nssf, __u16 spsp, - __u8 secp, __u32 al, __u32 data_len, void *data) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_security_recv, - .nsid = nsid, - .cdw10 = secp << 24 | spsp << 8 | nssf, - .cdw11 = al, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_get_lba_status(int fd, __u32 namespace_id, __u64 slba, __u32 mndw, - __u8 atype, __u16 rl, void *data, __u32 timeout_ms) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_get_lba_status, - .nsid = namespace_id, - .addr = (__u64)(uintptr_t) data, - .data_len = (mndw + 1) * 4, - .cdw10 = slba & 0xffffffff, - .cdw11 = slba >> 32, - .cdw12 = mndw, - .cdw13 = (atype << 24) | rl, - .timeout_ms = timeout_ms, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_dir_send(int fd, __u32 nsid, __u16 dspec, __u8 dtype, __u8 doper, - __u32 data_len, __u32 dw12, void *data, __u32 *result) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_directive_send, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - .nsid = nsid, - .cdw10 = data_len? (data_len >> 2) - 1 : 0, - .cdw11 = dspec << 16 | dtype << 8 | doper, - .cdw12 = dw12, - }; - int err; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} - -int nvme_dir_recv(int fd, __u32 nsid, __u16 dspec, __u8 dtype, __u8 doper, - __u32 data_len, __u32 dw12, void *data, __u32 *result) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_directive_recv, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - .nsid = nsid, - .cdw10 = data_len? (data_len >> 2) - 1 : 0, - .cdw11 = dspec << 16 | dtype << 8 | doper, - .cdw12 = dw12, - }; - int err; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} - -int nvme_sanitize(int fd, __u8 sanact, __u8 ause, __u8 owpass, __u8 oipbp, - __u8 no_dealloc, __u32 ovrpat) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_sanitize_nvm, - .cdw10 = no_dealloc << 9 | oipbp << 8 | - owpass << NVME_SANITIZE_OWPASS_SHIFT | - ause << 3 | sanact, - .cdw11 = ovrpat, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_self_test_start(int fd, __u32 nsid, __u8 stc) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_dev_self_test, - .nsid = nsid, - .cdw10 = stc, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_virtual_mgmt(int fd, __u32 cdw10, __u32 cdw11, __u32 *result) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_virtual_mgmt, - .cdw10 = cdw10, - .cdw11 = cdw11, - }; - int err; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && result) - *result = cmd.result; - - return err; -} - -int nvme_zns_mgmt_send(int fd, __u32 nsid, __u64 slba, bool select_all, - enum nvme_zns_send_action zsa, __u32 data_len, - void *data) -{ - __u32 cdw10 = slba & 0xffffffff; - __u32 cdw11 = slba >> 32; - __u32 cdw13 = zsa | (!!select_all) << 8; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_zns_cmd_mgmt_send, - .nsid = nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw13 = cdw13, - .addr = (__u64)(uintptr_t)data, - .data_len = data_len, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_zns_mgmt_recv(int fd, __u32 nsid, __u64 slba, - enum nvme_zns_recv_action zra, __u8 zrasf, - bool zras_feat, __u32 data_len, void *data) -{ - __u32 cdw10 = slba & 0xffffffff; - __u32 cdw11 = slba >> 32; - __u32 cdw12 = (data_len >> 2) - 1; - __u32 cdw13 = zra | zrasf << 8 | zras_feat << 16; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_zns_cmd_mgmt_recv, - .nsid = nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw13 = cdw13, - .addr = (__u64)(uintptr_t)data, - .data_len = data_len, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_zns_report_zones(int fd, __u32 nsid, __u64 slba, bool extended, - enum nvme_zns_report_options opts, bool partial, - __u32 data_len, void *data) -{ - enum nvme_zns_recv_action zra; - - if (extended) - zra = NVME_ZNS_ZRA_EXTENDED_REPORT_ZONES; - else - zra = NVME_ZNS_ZRA_REPORT_ZONES; - - return nvme_zns_mgmt_recv(fd, nsid, slba, zra, opts, partial, - data_len, data); -} - -int nvme_zns_append(int fd, __u32 nsid, __u64 zslba, __u16 nlb, __u16 control, - __u32 ilbrt, __u16 lbat, __u16 lbatm, __u32 data_len, - void *data, __u32 metadata_len, void *metadata, - __u64 *result) -{ - __u32 cdw10 = zslba & 0xffffffff; - __u32 cdw11 = zslba >> 32; - __u32 cdw12 = nlb | (control << 16); - __u32 cdw14 = ilbrt; - __u32 cdw15 = lbat | (lbatm << 16); - - struct nvme_passthru_cmd64 cmd = { - .opcode = nvme_zns_cmd_append, - .nsid = nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw14 = cdw14, - .cdw15 = cdw15, - .metadata = (__u64)(uintptr_t)metadata, - .addr = (__u64)(uintptr_t)data, - .metadata_len = metadata_len, - .data_len = data_len, - }; - - int err; - - err = ioctl(fd, NVME_IOCTL_IO64_CMD, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} diff --git a/nvme-ioctl.h b/nvme-ioctl.h deleted file mode 100644 index 18e49f0d75..0000000000 --- a/nvme-ioctl.h +++ /dev/null @@ -1,182 +0,0 @@ -#ifndef _NVME_LIB_H -#define _NVME_LIB_H - -#include -#include -#include "linux/nvme_ioctl.h" -#include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" - -#define NVME_IOCTL_TIMEOUT 120000 /* in milliseconds */ - -int nvme_get_nsid(int fd); - -/* Generic passthrough */ -int nvme_submit_passthru(int fd, unsigned long ioctl_cmd, - struct nvme_passthru_cmd *cmd); -int nvme_submit_admin_passthru(int fd, struct nvme_passthru_cmd *cmd); -int nvme_submit_io_passthru(int fd, struct nvme_passthru_cmd *cmd); - -int nvme_passthru(int fd, unsigned long ioctl_cmd, __u8 opcode, __u8 flags, - __u16 rsvd, __u32 nsid, __u32 cdw2, __u32 cdw3, - __u32 cdw10, __u32 cdw11, __u32 cdw12, - __u32 cdw13, __u32 cdw14, __u32 cdw15, - __u32 data_len, void *data, __u32 metadata_len, - void *metadata, __u32 timeout_ms, __u32 *result); - - -/* NVME_SUBMIT_IO */ -int nvme_io(int fd, __u8 opcode, __u64 slba, __u16 nblocks, __u16 control, - __u32 dsmgmt, __u32 reftag, __u16 apptag, - __u16 appmask, void *data, void *metadata); - -/* NVME_IO_CMD */ -int nvme_passthru_io(int fd, __u8 opcode, __u8 flags, __u16 rsvd, - __u32 nsid, __u32 cdw2, __u32 cdw3, - __u32 cdw10, __u32 cdw11, __u32 cdw12, - __u32 cdw13, __u32 cdw14, __u32 cdw15, - __u32 data_len, void *data, __u32 metadata_len, - void *metadata, __u32 timeout); - -int nvme_write_zeros(int fd, __u32 nsid, __u64 slba, __u16 nlb, - __u16 control, __u32 reftag, __u16 apptag, __u16 appmask); - -int nvme_write_uncorrectable(int fd, __u32 nsid, __u64 slba, __u16 nlb); - -int nvme_verify(int fd, __u32 nsid, __u64 slba, __u16 nblocks, - __u16 control, __u32 reftag, __u16 apptag, __u16 appmask); - -int nvme_flush(int fd, __u32 nsid); - -int nvme_dsm(int fd, __u32 nsid, __u32 cdw11, struct nvme_dsm_range *dsm, - __u16 nr_ranges); -struct nvme_dsm_range *nvme_setup_dsm_range(int *ctx_attrs, int *llbas, - unsigned long long *slbas, - __u16 nr_ranges); - -int nvme_copy(int fd, __u32 nsid, struct nvme_copy_range *copy, __u64 sdlba, - __u16 nr, __u8 prinfor, __u8 prinfow, __u8 dtype, __u16 dspec, - __u8 format, int lr, int fua, __u32 ilbrt, __u16 lbatm, - __u16 lbat); -struct nvme_copy_range *nvme_setup_copy_range(int *nlbs, unsigned long long *slbas, - int *eilbrts, int *elbatms, int *elbats, __u16 nr); - -int nvme_resv_acquire(int fd, __u32 nsid, __u8 rtype, __u8 racqa, - bool iekey, __u64 crkey, __u64 nrkey); -int nvme_resv_register(int fd, __u32 nsid, __u8 rrega, __u8 cptpl, - bool iekey, __u64 crkey, __u64 nrkey); -int nvme_resv_release(int fd, __u32 nsid, __u8 rtype, __u8 rrela, - bool iekey, __u64 crkey); -int nvme_resv_report(int fd, __u32 nsid, __u32 numd, __u32 cdw11, void *data); - -/* NVME_ADMIN_CMD */ -int nvme_identify13(int fd, __u32 nsid, __u32 cdw10, __u32 cdw11, void *data); -int nvme_identify(int fd, __u32 nsid, __u32 cdw10, void *data); -int nvme_identify_ctrl(int fd, void *data); -int nvme_identify_ns(int fd, __u32 nsid, bool present, void *data); -int nvme_identify_ns_list_csi(int fd, __u32 nsid, __u8 csi, bool all, void *data); -int nvme_identify_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data); -int nvme_identify_ns_descs(int fd, __u32 nsid, void *data); -int nvme_identify_nvmset(int fd, __u16 nvmset_id, void *data); -int nvme_identify_uuid(int fd, void *data); -int nvme_identify_primary_ctrl_caps(int fd, void *data); -int nvme_identify_secondary_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data); -int nvme_identify_ns_granularity(int fd, void *data); -int nvme_identify_ctrl_nvm(int fd, void *data); -int nvme_zns_identify_ctrl(int fd, void *data); -int nvme_zns_identify_ns(int fd, __u32 nsid, void *data); -int nvme_identify_iocs(int fd, __u16 cntid, void *data); -int nvme_get_log(int fd, __u32 nsid, __u8 log_id, bool rae, - __u8 lsp, __u32 data_len, void *data); -int nvme_get_log14(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo, - __u16 group_id, bool rae, __u8 uuid_ix, - __u32 data_len, void *data); -int nvme_get_log13(int fd, __u32 nsid, __u8 log_id, __u8 lsp, - __u64 lpo, __u16 lsi, bool rae, __u32 data_len, - void *data); -int nvme_get_telemetry_log(int fd, void *lp, int generate_report, - int ctrl_gen, size_t log_page_size, __u64 offset); -int nvme_fw_log(int fd, struct nvme_firmware_log_page *fw_log); -int nvme_changed_ns_list_log(int fd, - struct nvme_changed_ns_list_log *changed_ns_list_log); -int nvme_error_log(int fd, int entries, struct nvme_error_log_page *err_log); -int nvme_smart_log(int fd, __u32 nsid, struct nvme_smart_log *smart_log); -int nvme_ana_log(int fd, void *ana_log, size_t ana_log_len, int rgo); -int nvme_effects_log(int fd, struct nvme_effects_log_page *effects_log); -int nvme_discovery_log(int fd, struct nvmf_disc_rsp_page_hdr *log, __u32 size); -int nvme_sanitize_log(int fd, bool rae, struct nvme_sanitize_log_page *sanitize_log); -int nvme_predictable_latency_per_nvmset_log(int fd, - __u16 nvmset_id, struct nvme_predlat_per_nvmset_log_page *plpns_log); -int nvme_predictable_latency_event_agg_log(int fd, void *pea_log, - bool rae, __u32 size); -int nvme_persistent_event_log(int fd, __u8 action, __u32 size, - void *pevent_log_info); -int nvme_endurance_group_event_agg_log(int fd, void *endurance_log, - bool rae, __u32 size); -int nvme_endurance_log(int fd, __u16 group_id, - struct nvme_endurance_group_log *endurance_log); -int nvme_lba_status_log(int fd, void *lba_status, bool rae, - __u32 size); -int nvme_resv_notif_log(int fd, struct nvme_resv_notif_log *resv); -int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10, - __u32 cdw11, __u32 cdw12, __u32 cdw14, __u32 data_len, void *data, - __u32 *result); -int nvme_set_feature(int fd, __u32 nsid, __u8 fid, __u32 value, __u32 cdw12, - bool save, __u8 uuid_index, __u32 data_len, void *data, __u32 *result); -int nvme_get_feature(int fd, __u32 nsid, __u8 fid, __u8 sel, - __u32 cdw11, __u8 uuid_index, __u32 data_len, void *data, __u32 *result); - -int nvme_format(int fd, __u32 nsid, __u8 lbaf, __u8 ses, __u8 pi, - __u8 pil, __u8 ms, __u32 timeout); - -int nvme_ns_create(int fd, __u64 nsze, __u64 ncap, __u8 flbas, __u8 dps, - __u8 nmic, __u32 anagrpid, __u16 nvmsetid, __u8 csi, - __u32 timeout, __u32 *result); -int nvme_ns_delete(int fd, __u32 nsid, __u32 timeout); - -int nvme_ns_attachment(int fd, __u32 nsid, __u16 num_ctrls, - __u16 *ctrlist, bool attach); - -int nvme_fw_download(int fd, __u32 offset, __u32 data_len, void *data); -int nvme_fw_commit(int fd, __u8 slot, __u8 action, __u8 bpid); - -int nvme_sec_send(int fd, __u32 nsid, __u8 nssf, __u16 spsp, - __u8 secp, __u32 tl, __u32 data_len, void *data); -int nvme_sec_recv(int fd, __u32 nsid, __u8 nssf, __u16 spsp, - __u8 secp, __u32 al, __u32 data_len, void *data); - -int nvme_subsystem_reset(int fd); -int nvme_reset_controller(int fd); -int nvme_ns_rescan(int fd); - -int nvme_get_lba_status(int fd, __u32 namespace_id, __u64 slba, __u32 mndw, - __u8 atype, __u16 rl, void *data, __u32 timeout_ms); -int nvme_dir_send(int fd, __u32 nsid, __u16 dspec, __u8 dtype, __u8 doper, - __u32 data_len, __u32 dw12, void *data, __u32 *result); -int nvme_dir_recv(int fd, __u32 nsid, __u16 dspec, __u8 dtype, __u8 doper, - __u32 data_len, __u32 dw12, void *data, __u32 *result); -int nvme_get_properties(int fd, void **pbar); -int nvme_set_property(int fd, int offset, uint64_t value); -int nvme_get_property(int fd, int offset, uint64_t *value); -int nvme_sanitize(int fd, __u8 sanact, __u8 ause, __u8 owpass, __u8 oipbp, - __u8 no_dealloc, __u32 ovrpat); -int nvme_self_test_start(int fd, __u32 nsid, __u8 stc); -int nvme_self_test_log(int fd, __u32 nsid, struct nvme_self_test_log *self_test_log); -int nvme_virtual_mgmt(int fd, __u32 cdw10, __u32 cdw11, __u32 *result); - -int nvme_zns_mgmt_send(int fd, __u32 nsid, __u64 slba, bool select_all, - enum nvme_zns_send_action zsa, __u32 data_len, - void *data); -int nvme_zns_mgmt_recv(int fd, __u32 nsid, __u64 slba, - enum nvme_zns_recv_action zra, __u8 zrasf, - bool zras_feat, __u32 data_len, void *data); -int nvme_zns_report_zones(int fd, __u32 nsid, __u64 slba, bool extended, - enum nvme_zns_report_options opts, bool partial, - __u32 data_len, void *data); -int nvme_zns_append(int fd, __u32 nsid, __u64 zslba, __u16 nlb, __u16 control, - __u32 ilbrt, __u16 lbat, __u16 lbatm, __u32 data_len, - void *data, __u32 metadata_len, void *metadata, - __u64 *result); - -#endif /* _NVME_LIB_H */ diff --git a/nvme-print.c b/nvme-print.c index 57ae7fc7a8..86ede4e79c 100755 --- a/nvme-print.c +++ b/nvme-print.c @@ -1,13 +1,14 @@ #include +#include #include #include #include #include #include +#include #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" +#include "libnvme.h" #include "nvme-print.h" #include "nvme-models.h" #include "util/suffix.h" @@ -24,6 +25,15 @@ static const uint8_t zero_uuid[16] = { 0 }; static const uint8_t invalid_uuid[16] = {[0 ... 15] = 0xff }; static const char dash[100] = {[0 ... 99] = '-'}; +struct nvme_bar_cap { + __u16 mqes; + __u8 ams_cqr; + __u8 to; + __u16 bps_css_nssrs_dstrd; + __u8 mpsmax_mpsmin; + __u8 rsvd_cmbs_pmrs; +}; + static long double int128_to_double(__u8 *data) { int i; @@ -39,15 +49,15 @@ static long double int128_to_double(__u8 *data) static const char *nvme_ana_state_to_string(enum nvme_ana_state state) { switch (state) { - case NVME_ANA_OPTIMIZED: + case NVME_ANA_STATE_OPTIMIZED: return "optimized"; - case NVME_ANA_NONOPTIMIZED: + case NVME_ANA_STATE_NONOPTIMIZED: return "non-optimized"; - case NVME_ANA_INACCESSIBLE: + case NVME_ANA_STATE_INACCESSIBLE: return "inaccessible"; - case NVME_ANA_PERSISTENT_LOSS: + case NVME_ANA_STATE_PERSISTENT_LOSS: return "persistent-loss"; - case NVME_ANA_CHANGE: + case NVME_ANA_STATE_CHANGE: return "change"; } return "invalid state"; @@ -68,8 +78,8 @@ const char *nvme_cmd_to_string(int admin, __u8 opcode) case nvme_admin_get_features: return "Get Features"; case nvme_admin_async_event: return "Asynchronous Event Request"; case nvme_admin_ns_mgmt: return "Namespace Management"; - case nvme_admin_activate_fw: return "Firmware Commit"; - case nvme_admin_download_fw: return "Firmware Image Download"; + case nvme_admin_fw_commit: return "Firmware Commit"; + case nvme_admin_fw_download: return "Firmware Image Download"; case nvme_admin_dev_self_test: return "Device Self-test"; case nvme_admin_ns_attach: return "Namespace Attachment"; case nvme_admin_keep_alive: return "Keep Alive"; @@ -106,10 +116,9 @@ const char *nvme_cmd_to_string(int admin, __u8 opcode) return "Unknown"; } -static const char *fw_to_string(__u64 fw) +static const char *fw_to_string(char *c) { static char ret[9]; - char *c = (char *)&fw; int i; for (i = 0; i < 8; i++) @@ -120,16 +129,16 @@ static const char *fw_to_string(__u64 fw) static const char *get_sanitize_log_sstat_status_str(__u16 status) { - switch (status & NVME_SANITIZE_LOG_STATUS_MASK) { - case NVME_SANITIZE_LOG_NEVER_SANITIZED: + switch (status & NVME_SANITIZE_SSTAT_STATUS_MASK) { + case NVME_SANITIZE_SSTAT_STATUS_NEVER_SANITIZED: return "NVM Subsystem has never been sanitized."; - case NVME_SANITIZE_LOG_COMPLETED_SUCCESS: + case NVME_SANITIZE_SSTAT_STATUS_COMPLETE_SUCCESS: return "Most Recent Sanitize Command Completed Successfully."; - case NVME_SANITIZE_LOG_IN_PROGESS: + case NVME_SANITIZE_SSTAT_STATUS_IN_PROGESS: return "Sanitize in Progress."; - case NVME_SANITIZE_LOG_COMPLETED_FAILED: + case NVME_SANITIZE_SSTAT_STATUS_COMPLETED_FAILED: return "Most Recent Sanitize Command Failed."; - case NVME_SANITIZE_LOG_ND_COMPLETED_SUCCESS: + case NVME_SANITIZE_SSTAT_STATUS_ND_COMPLETE_SUCCESS: return "Most Recent Sanitize Command (No-Deallocate After Sanitize) Completed Successfully."; default: return "Unknown"; @@ -307,7 +316,6 @@ static void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, json_object_add_value_int(root, "icsvscc", ctrl->icsvscc); json_object_add_value_int(root, "nwpc", ctrl->nwpc); json_object_add_value_int(root, "acwu", le16_to_cpu(ctrl->acwu)); - json_object_add_value_int(root, "ocfs", le16_to_cpu(ctrl->ocfs)); json_object_add_value_int(root, "sgls", le32_to_cpu(ctrl->sgls)); if (strlen(subnqn)) @@ -327,28 +335,28 @@ static void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, struct json_object *psd = json_create_object(); json_object_add_value_int(psd, "max_power", - le16_to_cpu(ctrl->psd[i].max_power)); + le16_to_cpu(ctrl->psd[i].mp)); json_object_add_value_int(psd, "flags", ctrl->psd[i].flags); json_object_add_value_uint(psd, "entry_lat", - le32_to_cpu(ctrl->psd[i].entry_lat)); + le32_to_cpu(ctrl->psd[i].enlat)); json_object_add_value_uint(psd, "exit_lat", - le32_to_cpu(ctrl->psd[i].exit_lat)); + le32_to_cpu(ctrl->psd[i].exlat)); json_object_add_value_int(psd, "read_tput", - ctrl->psd[i].read_tput); + ctrl->psd[i].rrt); json_object_add_value_int(psd, "read_lat", - ctrl->psd[i].read_lat); + ctrl->psd[i].rrl); json_object_add_value_int(psd, "write_tput", - ctrl->psd[i].write_tput); + ctrl->psd[i].rwt); json_object_add_value_int(psd, "write_lat", - ctrl->psd[i].write_lat); + ctrl->psd[i].rwl); json_object_add_value_int(psd, "idle_power", - le16_to_cpu(ctrl->psd[i].idle_power)); + le16_to_cpu(ctrl->psd[i].idlp)); json_object_add_value_int(psd, "idle_scale", - ctrl->psd[i].idle_scale); + ctrl->psd[i].ips); json_object_add_value_int(psd, "active_power", - le16_to_cpu(ctrl->psd[i].active_power)); + le16_to_cpu(ctrl->psd[i].actp)); json_object_add_value_int(psd, "active_work_scale", - ctrl->psd[i].active_work_scale); + ctrl->psd[i].aps); json_array_add_value_object(psds, psd); } @@ -404,7 +412,7 @@ static void json_error_log(struct nvme_error_log_page *err_log, int entries) json_free_object(root); } -static void json_nvme_resv_report(struct nvme_reservation_status *status, +static void json_nvme_resv_report(struct nvme_resv_status *status, int bytes, __u32 cdw11) { struct json_object *root; @@ -447,8 +455,7 @@ static void json_nvme_resv_report(struct nvme_reservation_status *status, json_array_add_value_object(rcs, rc); } } else { - struct nvme_reservation_status_ext *ext_status = (struct nvme_reservation_status_ext *)status; - char hostid[33]; + char hostid[33]; /* if status buffer was too small, don't loop past the end of the buffer */ entries = (bytes - 64) / 64; @@ -460,14 +467,14 @@ static void json_nvme_resv_report(struct nvme_reservation_status *status, struct json_object *rc = json_create_object(); json_object_add_value_int(rc, "cntlid", - le16_to_cpu(ext_status->regctl_eds[i].cntlid)); + le16_to_cpu(status->regctl_eds[i].cntlid)); json_object_add_value_int(rc, "rcsts", - ext_status->regctl_eds[i].rcsts); + status->regctl_eds[i].rcsts); json_object_add_value_uint(rc, "rkey", - le64_to_cpu(ext_status->regctl_eds[i].rkey)); + le64_to_cpu(status->regctl_eds[i].rkey)); for (j = 0; j < 16; j++) sprintf(hostid + j * 2, "%02x", - ext_status->regctl_eds[i].hostid[j]); + status->regctl_eds[i].hostid[j]); json_object_add_value_string(rc, "hostid", hostid); json_array_add_value_object(rcs, rc); @@ -479,7 +486,7 @@ static void json_nvme_resv_report(struct nvme_reservation_status *status, json_free_object(root); } -static void json_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname) +static void json_fw_log(struct nvme_firmware_slot *fw_log, const char *devname) { struct json_object *root; struct json_object *fwsi; @@ -509,7 +516,7 @@ static void json_fw_log(struct nvme_firmware_log_page *fw_log, const char *devna json_free_object(root); } -static void json_changed_ns_list_log(struct nvme_changed_ns_list_log *log, +static void json_changed_ns_list_log(struct nvme_ns_list *log, const char *devname) { struct json_object *root; @@ -519,7 +526,7 @@ static void json_changed_ns_list_log(struct nvme_changed_ns_list_log *log, __u32 nsid; int i; - if (log->log[0] == cpu_to_le32(0xffffffff)) + if (log->ns[0] == cpu_to_le32(0xffffffff)) return; root = json_create_object(); @@ -528,8 +535,8 @@ static void json_changed_ns_list_log(struct nvme_changed_ns_list_log *log, json_object_add_value_string(root, "Changed Namespace List Log", devname); - for (i = 0; i < NVME_MAX_CHANGED_NAMESPACES; i++) { - nsid = le32_to_cpu(log->log[i]); + for (i = 0; i < NVME_ID_NS_LIST_MAX; i++) { + nsid = le32_to_cpu(log->ns[i]); if (nsid == 0) break; @@ -685,10 +692,10 @@ static void json_smart_log(struct nvme_smart_log *smart, unsigned int nsid, json_free_object(root); } -static void json_ana_log(struct nvme_ana_rsp_hdr *ana_log, const char *devname) +static void json_ana_log(struct nvme_ana_log *ana_log, const char *devname) { - int offset = sizeof(struct nvme_ana_rsp_hdr); - struct nvme_ana_rsp_hdr *hdr = ana_log; + int offset = sizeof(struct nvme_ana_log); + struct nvme_ana_log *hdr = ana_log; struct nvme_ana_group_desc *ana_desc; struct json_object *desc_list; struct json_object *ns_list; @@ -753,12 +760,12 @@ static void json_self_test_log(struct nvme_self_test_log *self_test, __u8 dst_en root = json_create_object(); json_object_add_value_int(root, "Current Device Self-Test Operation", - self_test->crnt_dev_selftest_oprn); + self_test->current_operation); json_object_add_value_int(root, "Current Device Self-Test Completion", - self_test->crnt_dev_selftest_compln); + self_test->completion); valid = json_create_array(); - num_entries = min(dst_entries, NVME_ST_REPORTS); + num_entries = min(dst_entries, NVME_LOG_ST_MAX_RESULTS); for (i = 0; i < num_entries; i++) { valid_attrs = json_create_object(); json_object_add_value_int(valid_attrs, "Self test result", @@ -773,16 +780,16 @@ static void json_self_test_log(struct nvme_self_test_log *self_test, __u8 dst_en self_test->result[i].vdi); json_object_add_value_uint(valid_attrs, "Power on hours", le64_to_cpu(self_test->result[i].poh)); - if (self_test->result[i].vdi & NVME_ST_VALID_NSID) + if (self_test->result[i].vdi & NVME_ST_VALID_DIAG_INFO_NSID) json_object_add_value_int(valid_attrs, "Namespace Identifier", le32_to_cpu(self_test->result[i].nsid)); - if (self_test->result[i].vdi & NVME_ST_VALID_FLBA) + if (self_test->result[i].vdi & NVME_ST_VALID_DIAG_INFO_FLBA) json_object_add_value_uint(valid_attrs, "Failing LBA", le64_to_cpu(self_test->result[i].flba)); - if (self_test->result[i].vdi & NVME_ST_VALID_SCT) + if (self_test->result[i].vdi & NVME_ST_VALID_DIAG_INFO_SCT) json_object_add_value_int(valid_attrs, "Status Code Type", self_test->result[i].sct); - if (self_test->result[i].vdi & NVME_ST_VALID_SC) + if (self_test->result[i].vdi & NVME_ST_VALID_DIAG_INFO_SC) json_object_add_value_int(valid_attrs, "Status Code", self_test->result[i].sc); json_object_add_value_int(valid_attrs, "Vendor Specific", @@ -797,7 +804,7 @@ static void json_self_test_log(struct nvme_self_test_log *self_test, __u8 dst_en json_free_object(root); } -static void json_effects_log(struct nvme_effects_log_page *effects_log) +static void json_effects_log(struct nvme_cmd_effects_log *effects_log) { struct json_object *root; struct json_object *acs; @@ -843,40 +850,41 @@ static void json_sanitize_log(struct nvme_sanitize_log_page *sanitize_log, struct json_object *sstat; const char *status_str; char str[128]; - __u16 status = le16_to_cpu(sanitize_log->status); + __u16 status = le16_to_cpu(sanitize_log->sstat); root = json_create_object(); dev = json_create_object(); sstat = json_create_object(); json_object_add_value_int(dev, "sprog", - le16_to_cpu(sanitize_log->progress)); + le16_to_cpu(sanitize_log->sprog)); json_object_add_value_int(sstat, "global_erased", - (status & NVME_SANITIZE_LOG_GLOBAL_DATA_ERASED) >> 8); + (status & NVME_SANITIZE_SSTAT_GLOBAL_DATA_ERASED) >> 8); json_object_add_value_int(sstat, "no_cmplted_passes", - (status & NVME_SANITIZE_LOG_NUM_CMPLTED_PASS_MASK) >> 3); + (status >> NVME_SANITIZE_SSTAT_COMPLETED_PASSES_SHIFT) & + NVME_SANITIZE_SSTAT_COMPLETED_PASSES_MASK); status_str = get_sanitize_log_sstat_status_str(status); - sprintf(str, "(%d) %s", status & NVME_SANITIZE_LOG_STATUS_MASK, + sprintf(str, "(%d) %s", status & NVME_SANITIZE_SSTAT_STATUS_MASK, status_str); json_object_add_value_string(sstat, "status", str); json_object_add_value_object(dev, "sstat", sstat); json_object_add_value_uint(dev, "cdw10_info", - le32_to_cpu(sanitize_log->cdw10_info)); + le32_to_cpu(sanitize_log->scdw10)); json_object_add_value_uint(dev, "time_over_write", - le32_to_cpu(sanitize_log->est_ovrwrt_time)); + le32_to_cpu(sanitize_log->eto)); json_object_add_value_uint(dev, "time_block_erase", - le32_to_cpu(sanitize_log->est_blk_erase_time)); + le32_to_cpu(sanitize_log->etbe)); json_object_add_value_uint(dev, "time_crypto_erase", - le32_to_cpu(sanitize_log->est_crypto_erase_time)); + le32_to_cpu(sanitize_log->etce)); json_object_add_value_uint(dev, "time_over_write_no_dealloc", - le32_to_cpu(sanitize_log->est_ovrwrt_time_with_no_deallocate)); + le32_to_cpu(sanitize_log->etond)); json_object_add_value_uint(dev, "time_block_erase_no_dealloc", - le32_to_cpu(sanitize_log->est_blk_erase_time_with_no_deallocate)); + le32_to_cpu(sanitize_log->etbend)); json_object_add_value_uint(dev, "time_crypto_erase_no_dealloc", - le32_to_cpu(sanitize_log->est_crypto_erase_time_with_no_deallocate)); + le32_to_cpu(sanitize_log->etcend)); json_object_add_value_object(root, devname, dev); json_print_object(root, NULL); @@ -885,7 +893,7 @@ static void json_sanitize_log(struct nvme_sanitize_log_page *sanitize_log, } void json_predictable_latency_per_nvmset( - struct nvme_predlat_per_nvmset_log_page *plpns_log, + struct nvme_nvmset_predictable_lat_log *plpns_log, __u16 nvmset_id) { struct json_object *root; @@ -898,21 +906,21 @@ void json_predictable_latency_per_nvmset( json_object_add_value_uint(root, "event_type", le16_to_cpu(plpns_log->event_type)); json_object_add_value_uint(root, "dtwin_reads_typical", - le64_to_cpu(plpns_log->dtwin_rtyp)); + le64_to_cpu(plpns_log->dtwin_rt)); json_object_add_value_uint(root, "dtwin_writes_typical", - le64_to_cpu(plpns_log->dtwin_wtyp)); + le64_to_cpu(plpns_log->dtwin_wt)); json_object_add_value_uint(root, "dtwin_time_maximum", - le64_to_cpu(plpns_log->dtwin_timemax)); + le64_to_cpu(plpns_log->dtwin_tmax)); json_object_add_value_uint(root, "ndwin_time_minimum_high", - le64_to_cpu(plpns_log->ndwin_timemin_high)); + le64_to_cpu(plpns_log->ndwin_tmin_hi)); json_object_add_value_uint(root, "ndwin_time_minimum_low", - le64_to_cpu(plpns_log->ndwin_timemin_low)); + le64_to_cpu(plpns_log->ndwin_tmin_lo)); json_object_add_value_uint(root, "dtwin_reads_estimate", - le64_to_cpu(plpns_log->dtwin_restimate)); + le64_to_cpu(plpns_log->dtwin_re)); json_object_add_value_uint(root, "dtwin_writes_estimate", - le64_to_cpu(plpns_log->dtwin_westimate)); + le64_to_cpu(plpns_log->dtwin_we)); json_object_add_value_uint(root, "dtwin_time_estimate", - le64_to_cpu(plpns_log->dtwin_testimate)); + le64_to_cpu(plpns_log->dtwin_te)); json_print_object(root, NULL); printf("\n"); @@ -920,7 +928,7 @@ void json_predictable_latency_per_nvmset( } void nvme_show_predictable_latency_per_nvmset( - struct nvme_predlat_per_nvmset_log_page *plpns_log, + struct nvme_nvmset_predictable_lat_log *plpns_log, __u16 nvmset_id, const char *devname, enum nvme_print_flags flags) { @@ -939,25 +947,25 @@ void nvme_show_predictable_latency_per_nvmset( printf("Event Type: %u\n", le16_to_cpu(plpns_log->event_type)); printf("DTWIN Reads Typical: %"PRIu64"\n", - le64_to_cpu(plpns_log->dtwin_rtyp)); + le64_to_cpu(plpns_log->dtwin_rt)); printf("DTWIN Writes Typical: %"PRIu64"\n", - le64_to_cpu(plpns_log->dtwin_wtyp)); + le64_to_cpu(plpns_log->dtwin_wt)); printf("DTWIN Time Maximum: %"PRIu64"\n", - le64_to_cpu(plpns_log->dtwin_timemax)); + le64_to_cpu(plpns_log->dtwin_tmax)); printf("NDWIN Time Minimum High: %"PRIu64" \n", - le64_to_cpu(plpns_log->ndwin_timemin_high)); + le64_to_cpu(plpns_log->ndwin_tmin_hi)); printf("NDWIN Time Minimum Low: %"PRIu64"\n", - le64_to_cpu(plpns_log->ndwin_timemin_low)); + le64_to_cpu(plpns_log->ndwin_tmin_lo)); printf("DTWIN Reads Estimate: %"PRIu64"\n", - le64_to_cpu(plpns_log->dtwin_restimate)); + le64_to_cpu(plpns_log->dtwin_re)); printf("DTWIN Writes Estimate: %"PRIu64"\n", - le64_to_cpu(plpns_log->dtwin_westimate)); + le64_to_cpu(plpns_log->dtwin_we)); printf("DTWIN Time Estimate: %"PRIu64"\n\n\n", - le64_to_cpu(plpns_log->dtwin_testimate)); + le64_to_cpu(plpns_log->dtwin_te)); } void json_predictable_latency_event_agg_log( - struct nvme_event_agg_log_page *pea_log, + struct nvme_aggregate_predictable_lat_event *pea_log, __u64 log_entries) { struct json_object *root; @@ -986,7 +994,7 @@ void json_predictable_latency_event_agg_log( } void nvme_show_predictable_latency_event_agg_log( - struct nvme_event_agg_log_page *pea_log, + struct nvme_aggregate_predictable_lat_event *pea_log, __u64 log_entries, __u32 size, const char *devname, enum nvme_print_flags flags) { @@ -1049,19 +1057,20 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) __u32 offset, por_info_len, por_info_list; __u64 *fw_rev; char key[128]; + struct nvme_smart_log *smart_event; struct nvme_fw_commit_event *fw_commit_event; struct nvme_time_stamp_change_event *ts_change_event; struct nvme_power_on_reset_info_list *por_event; struct nvme_nss_hw_err_event *nss_hw_err_event; - struct nvme_change_ns_event *ns_event; + struct nvme_change_ns_event *ns_event; struct nvme_format_nvm_start_event *format_start_event; struct nvme_format_nvm_compln_event *format_cmpln_event; struct nvme_sanitize_start_event *sanitize_start_event; struct nvme_sanitize_compln_event *sanitize_cmpln_event; struct nvme_thermal_exc_event *thermal_exc_event; - struct nvme_persistent_event_log_head *pevent_log_head; - struct nvme_persistent_event_entry_head *pevent_entry_head; + struct nvme_persistent_event_log *pevent_log_head; + struct nvme_persistent_event_entry *pevent_entry_head; root = json_create_object(); valid = json_create_array(); @@ -1081,17 +1090,17 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) (int)sizeof(pevent_log_head->subnqn), pevent_log_head->subnqn); json_object_add_value_uint(root, "log_id", - pevent_log_head->log_id); + pevent_log_head->lid); json_object_add_value_uint(root, "total_num_of_events", le32_to_cpu(pevent_log_head->tnev)); json_object_add_value_uint(root, "total_log_len", le64_to_cpu(pevent_log_head->tll)); json_object_add_value_uint(root, "log_revision", - pevent_log_head->log_rev); + pevent_log_head->rv); json_object_add_value_uint(root, "log_header_len", - le16_to_cpu(pevent_log_head->head_len)); + le16_to_cpu(pevent_log_head->lhl)); json_object_add_value_uint(root, "timestamp", - le64_to_cpu(pevent_log_head->timestamp)); + le64_to_cpu(pevent_log_head->ts)); json_object_add_value_float(root, "power_on_hours", int128_to_double(pevent_log_head->poh)); json_object_add_value_uint(root, "power_cycle_count", @@ -1104,11 +1113,11 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_string(root, "mn", mn); json_object_add_value_string(root, "subnqn", subnqn); for (int i = 0; i < 32; i++) { - if (pevent_log_head->supp_event_bm[i] == 0) + if (pevent_log_head->seb[i] == 0) continue; sprintf(key, "bitmap_%d", i); json_object_add_value_uint(root, key, - pevent_log_head->supp_event_bm[i]); + pevent_log_head->seb[i]); } } else { printf("No log data can be shown with this log len at least " \ @@ -1134,9 +1143,9 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_uint(valid_attrs, "event_header_len", pevent_entry_head->ehl); json_object_add_value_uint(valid_attrs, "ctrl_id", - le16_to_cpu(pevent_entry_head->ctrl_id)); + le16_to_cpu(pevent_entry_head->cntlid)); json_object_add_value_uint(valid_attrs, "event_time_stamp", - le64_to_cpu(pevent_entry_head->etimestamp)); + le64_to_cpu(pevent_entry_head->ets)); json_object_add_value_uint(valid_attrs, "vu_info_len", le16_to_cpu(pevent_entry_head->vsil)); json_object_add_value_uint(valid_attrs, "event_len", @@ -1145,7 +1154,7 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) offset += pevent_entry_head->ehl + 3; switch (pevent_entry_head->etype) { - case NVME_SMART_HEALTH_EVENT: + case NVME_PEL_SMART_HEALTH_EVENT: smart_event = pevent_log_info + offset; unsigned int temperature = ((smart_event->temperature[1] << 8) | smart_event->temperature[0]); @@ -1216,7 +1225,7 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_uint(valid_attrs, "thm_temp2_total_time", le32_to_cpu(smart_event->thm_temp2_total_time)); break; - case NVME_FW_COMMIT_EVENT: + case NVME_PEL_FW_COMMIT_EVENT: fw_commit_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "old_fw_rev", le64_to_cpu(fw_commit_event->old_fw_rev)); @@ -1234,7 +1243,7 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) "vu_assign_fw_commit_rc", le16_to_cpu(fw_commit_event->vndr_assign_fw_commit_rc)); break; - case NVME_TIMESTAMP_EVENT: + case NVME_PEL_TIMESTAMP_EVENT: ts_change_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "prev_ts", le64_to_cpu(ts_change_event->previous_timestamp)); @@ -1242,7 +1251,7 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) "ml_secs_since_reset", le64_to_cpu(ts_change_event->ml_secs_since_reset)); break; - case NVME_POWER_ON_RESET_EVENT: + case NVME_PEL_POWER_ON_RESET_EVENT: por_info_len = (le16_to_cpu(pevent_entry_head->el) - le16_to_cpu(pevent_entry_head->vsil) - sizeof(*fw_rev)); @@ -1268,18 +1277,18 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) le64_to_cpu(por_event->ctrl_time_stamp)); } break; - case NVME_NSS_HW_ERROR_EVENT: + case NVME_PEL_NSS_HW_ERROR_EVENT: nss_hw_err_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "nss_hw_err_code", le16_to_cpu(nss_hw_err_event->nss_hw_err_event_code)); break; - case NVME_CHANGE_NS_EVENT: + case NVME_PEL_CHANGE_NS_EVENT: ns_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "nsmgt_cdw10", le32_to_cpu(ns_event->nsmgt_cdw10)); json_object_add_value_uint(valid_attrs, "nsze", le64_to_cpu(ns_event->nsze)); - json_object_add_value_uint(valid_attrs, "nscap", + json_object_add_value_float(valid_attrs, "nscap", le64_to_cpu(ns_event->nscap)); json_object_add_value_uint(valid_attrs, "flbas", ns_event->flbas); @@ -1294,7 +1303,7 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_uint(valid_attrs, "nsid", le32_to_cpu(ns_event->nsid)); break; - case NVME_FORMAT_START_EVENT: + case NVME_PEL_FORMAT_START_EVENT: format_start_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "nsid", le32_to_cpu(format_start_event->nsid)); @@ -1303,7 +1312,7 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_uint(valid_attrs, "format_nvm_cdw10", le32_to_cpu(format_start_event->format_nvm_cdw10)); break; - case NVME_FORMAT_COMPLETION_EVENT: + case NVME_PEL_FORMAT_COMPLETION_EVENT: format_cmpln_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "nsid", le32_to_cpu(format_cmpln_event->nsid)); @@ -1316,7 +1325,7 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_uint(valid_attrs, "status_field", le32_to_cpu(format_cmpln_event->status_field)); break; - case NVME_SANITIZE_START_EVENT: + case NVME_PEL_SANITIZE_START_EVENT: sanitize_start_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "SANICAP", le32_to_cpu(sanitize_start_event->sani_cap)); @@ -1325,7 +1334,7 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_uint(valid_attrs, "sani_cdw11", le32_to_cpu(sanitize_start_event->sani_cdw11)); break; - case NVME_SANITIZE_COMPLETION_EVENT: + case NVME_PEL_SANITIZE_COMPLETION_EVENT: sanitize_cmpln_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "sani_prog", le16_to_cpu(sanitize_cmpln_event->sani_prog)); @@ -1334,7 +1343,7 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_uint(valid_attrs, "cmpln_info", le16_to_cpu(sanitize_cmpln_event->cmpln_info)); break; - case NVME_THERMAL_EXCURSION_EVENT: + case NVME_PEL_THERMAL_EXCURSION_EVENT: thermal_exc_event = pevent_log_info + offset; json_object_add_value_uint(valid_attrs, "over_temp", thermal_exc_event->over_temp); @@ -1370,8 +1379,8 @@ void nvme_show_persistent_event_log(void *pevent_log_info, struct nvme_sanitize_start_event *sanitize_start_event; struct nvme_sanitize_compln_event *sanitize_cmpln_event; struct nvme_thermal_exc_event *thermal_exc_event; - struct nvme_persistent_event_log_head *pevent_log_head; - struct nvme_persistent_event_entry_head *pevent_entry_head; + struct nvme_persistent_event_log *pevent_log_head; + struct nvme_persistent_event_entry *pevent_entry_head; if (flags & BINARY) return d_raw((unsigned char *)pevent_log_info, size); @@ -1384,15 +1393,15 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("Action for Persistent Event Log: %u\n", action); if (size >= offset) { pevent_log_head = pevent_log_info; - printf("Log Identifier: %u\n", pevent_log_head->log_id); + printf("Log Identifier: %u\n", pevent_log_head->lid); printf("Total Number of Events: %u\n", le32_to_cpu(pevent_log_head->tnev)); printf("Total Log Length : %"PRIu64"\n", le64_to_cpu(pevent_log_head->tll)); - printf("Log Revision: %u\n", pevent_log_head->log_rev); - printf("Log Header Length: %u\n", pevent_log_head->head_len); + printf("Log Revision: %u\n", pevent_log_head->rv); + printf("Log Header Length: %u\n", pevent_log_head->lhl); printf("Timestamp: %"PRIu64"\n", - le64_to_cpu(pevent_log_head->timestamp)); + le64_to_cpu(pevent_log_head->ts)); printf("Power On Hours (POH): %'.0Lf\n", int128_to_double(pevent_log_head->poh)); printf("Power Cycle Count: %"PRIu64"\n", @@ -1410,10 +1419,10 @@ void nvme_show_persistent_event_log(void *pevent_log_info, pevent_log_head->subnqn); printf("Supported Events Bitmap: "); for (int i = 0; i < 32; i++) { - if (pevent_log_head->supp_event_bm[i] == 0) + if (pevent_log_head->seb[i] == 0) continue; - printf("BitMap[%d] is 0x%x\n", i, - pevent_log_head->supp_event_bm[i]); + printf(" BitMap[%d] is 0x%x\n", i, + pevent_log_head->seb[i]); } } else { printf("No log data can be shown with this log len at least " \ @@ -1437,9 +1446,9 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("Event Type Revision: %u\n", pevent_entry_head->etype_rev); printf("Event Header Length: %u\n", pevent_entry_head->ehl); printf("Controller Identifier: %u\n", - le16_to_cpu(pevent_entry_head->ctrl_id)); + le16_to_cpu(pevent_entry_head->cntlid)); printf("Event Timestamp: %"PRIu64"\n", - le64_to_cpu(pevent_entry_head->etimestamp)); + le64_to_cpu(pevent_entry_head->ets)); printf("Vendor Specific Information Length: %u\n", le16_to_cpu(pevent_entry_head->vsil)); printf("Event Length: %u\n", le16_to_cpu(pevent_entry_head->el)); @@ -1447,12 +1456,12 @@ void nvme_show_persistent_event_log(void *pevent_log_info, offset += pevent_entry_head->ehl + 3; switch (pevent_entry_head->etype) { - case NVME_SMART_HEALTH_EVENT: + case NVME_PEL_SMART_HEALTH_EVENT: smart_event = pevent_log_info + offset; printf("Smart Health Event: \n"); nvme_show_smart_log(smart_event, NVME_NSID_ALL, devname, flags); break; - case NVME_FW_COMMIT_EVENT: + case NVME_PEL_FW_COMMIT_EVENT: fw_commit_event = pevent_log_info + offset; printf("FW Commit Event: \n"); printf("Old Firmware Revision: %"PRIu64"\n", @@ -1469,7 +1478,7 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("Vendor Assigned Firmware Commit Result Code: %u\n", le16_to_cpu(fw_commit_event->vndr_assign_fw_commit_rc)); break; - case NVME_TIMESTAMP_EVENT: + case NVME_PEL_TIMESTAMP_EVENT: ts_change_event = pevent_log_info + offset; printf("Time Stamp Change Event: \n"); printf("Previous Timestamp: %"PRIu64"\n", @@ -1477,7 +1486,7 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("Milliseconds Since Reset: %"PRIu64"\n", le64_to_cpu(ts_change_event->ml_secs_since_reset)); break; - case NVME_POWER_ON_RESET_EVENT: + case NVME_PEL_POWER_ON_RESET_EVENT: por_info_len = (le16_to_cpu(pevent_entry_head->el) - le16_to_cpu(pevent_entry_head->vsil) - sizeof(*fw_rev)); @@ -1504,13 +1513,13 @@ void nvme_show_persistent_event_log(void *pevent_log_info, le64_to_cpu(por_event->ctrl_time_stamp)); } break; - case NVME_NSS_HW_ERROR_EVENT: + case NVME_PEL_NSS_HW_ERROR_EVENT: nss_hw_err_event = pevent_log_info + offset; printf("NVM Subsystem Hardware Error Event Code: %u, %s\n", le16_to_cpu(nss_hw_err_event->nss_hw_err_event_code), nvme_show_nss_hw_error(nss_hw_err_event->nss_hw_err_event_code)); break; - case NVME_CHANGE_NS_EVENT: + case NVME_PEL_CHANGE_NS_EVENT: ns_event = pevent_log_info + offset; printf("Change Namespace Event: \n"); printf("Namespace Management CDW10: %u\n", @@ -1529,7 +1538,7 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("NVM Set Identifier: %u\n", le16_to_cpu(ns_event->nvmset_id)); printf("Namespace ID: %u\n", le32_to_cpu(ns_event->nsid)); break; - case NVME_FORMAT_START_EVENT: + case NVME_PEL_FORMAT_START_EVENT: format_start_event = pevent_log_info + offset; printf("Format NVM Start Event: \n"); printf("Namespace Identifier: %u\n", @@ -1539,7 +1548,7 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("Format NVM CDW10: %u\n", le32_to_cpu(format_start_event->format_nvm_cdw10)); break; - case NVME_FORMAT_COMPLETION_EVENT: + case NVME_PEL_FORMAT_COMPLETION_EVENT: format_cmpln_event = pevent_log_info + offset; printf("Format NVM Completion Event: \n"); printf("Namespace Identifier: %u\n", @@ -1553,7 +1562,7 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("Status Field: %u\n", le32_to_cpu(format_cmpln_event->status_field)); break; - case NVME_SANITIZE_START_EVENT: + case NVME_PEL_SANITIZE_START_EVENT: sanitize_start_event = pevent_log_info + offset; printf("Sanitize Start Event: \n"); printf("SANICAP: %u\n", sanitize_start_event->sani_cap); @@ -1562,7 +1571,7 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("Sanitize CDW11: %u\n", le32_to_cpu(sanitize_start_event->sani_cdw11)); break; - case NVME_SANITIZE_COMPLETION_EVENT: + case NVME_PEL_SANITIZE_COMPLETION_EVENT: sanitize_cmpln_event = pevent_log_info + offset; printf("Sanitize Completion Event: \n"); printf("Sanitize Progress: %u\n", @@ -1572,7 +1581,7 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("Completion Information: %u\n", le16_to_cpu(sanitize_cmpln_event->cmpln_info)); break; - case NVME_THERMAL_EXCURSION_EVENT: + case NVME_PEL_THERMAL_EXCURSION_EVENT: thermal_exc_event = pevent_log_info + offset; printf("Thermal Excursion Event: \n"); printf("Over Temperature: %u\n", thermal_exc_event->over_temp); @@ -1587,7 +1596,7 @@ void nvme_show_persistent_event_log(void *pevent_log_info, } void json_endurance_group_event_agg_log( - struct nvme_event_agg_log_page *endurance_log, + struct nvme_aggregate_predictable_lat_event *endurance_log, __u64 log_entries) { struct json_object *root; @@ -1612,7 +1621,7 @@ void json_endurance_group_event_agg_log( } void nvme_show_endurance_group_event_agg_log( - struct nvme_event_agg_log_page *endurance_log, + struct nvme_aggregate_predictable_lat_event *endurance_log, __u64 log_entries, __u32 size, const char *devname, enum nvme_print_flags flags) { @@ -1642,9 +1651,9 @@ void json_lba_status_log(void *lba_status) struct json_object *element; struct json_object *desc_list; struct json_object *elements_list; - struct nvme_lba_status_hdr *hdr; - struct nvme_lba_status_ns_element *ns_element; - struct nvme_lba_status_range_desc *range_desc; + struct nvme_lba_status_log *hdr; + struct nvme_lbas_ns_element *ns_element; + struct nvme_lba_rd *range_desc; int offset = sizeof(*hdr); __u32 num_lba_desc, num_elements; @@ -1698,9 +1707,9 @@ void json_lba_status_log(void *lba_status) void nvme_show_lba_status_log(void *lba_status, __u32 size, const char *devname, enum nvme_print_flags flags) { - struct nvme_lba_status_hdr *hdr; - struct nvme_lba_status_ns_element *ns_element; - struct nvme_lba_status_range_desc *range_desc; + struct nvme_lba_status_log *hdr; + struct nvme_lbas_ns_element *ns_element; + struct nvme_lba_rd *range_desc; int offset = sizeof(*hdr); __u32 num_lba_desc, num_elements; @@ -1755,17 +1764,17 @@ static const char *resv_notif_to_string(__u8 type) } } -static void json_resv_notif_log(struct nvme_resv_notif_log *resv) +static void json_resv_notif_log(struct nvme_resv_notification_log *resv) { struct json_object *root; root = json_create_object(); json_object_add_value_uint(root, "count", - le64_to_cpu(resv->log_page_count)); + le64_to_cpu(resv->lpc)); json_object_add_value_uint(root, "rn_log_type", - resv->resv_notif_log_type); + resv->rnlpt); json_object_add_value_uint(root, "num_logs", - resv->num_logs); + resv->nalp); json_object_add_value_uint(root, "nsid", le32_to_cpu(resv->nsid)); @@ -1774,7 +1783,7 @@ static void json_resv_notif_log(struct nvme_resv_notif_log *resv) json_free_object(root); } -void nvme_show_resv_notif_log(struct nvme_resv_notif_log *resv, +void nvme_show_resv_notif_log(struct nvme_resv_notification_log *resv, const char *devname, enum nvme_print_flags flags) { if (flags & BINARY) @@ -1784,95 +1793,98 @@ void nvme_show_resv_notif_log(struct nvme_resv_notif_log *resv, printf("Reservation Notif Log for device: %s\n", devname); printf("Log Page Count : %"PRIx64"\n", - le64_to_cpu(resv->log_page_count)); + le64_to_cpu(resv->lpc)); printf("Resv Notif Log Page Type : %u (%s)\n", - resv->resv_notif_log_type, - resv_notif_to_string(resv->resv_notif_log_type)); - printf("Num of Available Log Pages : %u\n", resv->num_logs); + resv->rnlpt, + resv_notif_to_string(resv->rnlpt)); + printf("Num of Available Log Pages : %u\n", resv->nalp); printf("Namespace ID: : %"PRIx32"\n", le32_to_cpu(resv->nsid)); } -static void nvme_show_subsystem(struct nvme_subsystem *s) +static void nvme_show_subsystem(nvme_root_t r) { - int i; + nvme_host_t h; + + nvme_for_each_host(r, h) { + nvme_subsystem_t s; + + nvme_for_each_subsystem(h, s) { + nvme_ctrl_t c; - printf("%s - NQN=%s\n", s->name, s->subsysnqn); - printf("\\\n"); + printf("%s - NQN=%s\n", nvme_subsystem_get_name(s), + nvme_subsystem_get_nqn(s)); + printf("\\\n"); - for (i = 0; i < s->nr_ctrls; i++) { - printf(" +- %s %s %s %s %s\n", s->ctrls[i].name, - s->ctrls[i].transport ? : "", - s->ctrls[i].address ? : "", - s->ctrls[i].state ? : "", - s->ctrls[i].ana_state ? : ""); + nvme_subsystem_for_each_ctrl(s, c) { + printf(" +- %s %s %s %s\n", + nvme_ctrl_get_name(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c), + nvme_ctrl_get_state(c)); + } + } } } -static void json_print_nvme_subsystem_list(struct nvme_topology *t) +static void json_print_nvme_subsystem_list(nvme_root_t r) { - struct json_object *subsystem_attrs, *path_attrs; + struct json_object *host_attrs, *subsystem_attrs, *path_attrs; struct json_object *subsystems, *paths; struct json_object *root; - int i, j; + nvme_host_t h; root = json_create_object(); - subsystems = json_create_array(); - - for (i = 0; i < t->nr_subsystems; i++) { - struct nvme_subsystem *s = &t->subsystems[i]; - - subsystem_attrs = json_create_object(); - json_object_add_value_string(subsystem_attrs, - "Name", s->name); - json_object_add_value_string(subsystem_attrs, - "NQN", s->subsysnqn); - - json_array_add_value_object(subsystems, subsystem_attrs); - - paths = json_create_array(); - for (j = 0; j < s->nr_ctrls; j++) { - struct nvme_ctrl *c = &s->ctrls[j]; - - path_attrs = json_create_object(); - json_object_add_value_string(path_attrs, "Name", - c->name); - if (c->transport) - json_object_add_value_string(path_attrs, - "Transport", c->transport); - if (c->address) - json_object_add_value_string(path_attrs, - "Address", c->address); - if (c->state) - json_object_add_value_string(path_attrs, - "State", c->state); - if (c->ana_state) - json_object_add_value_string(path_attrs, - "ANAState", c->ana_state); - json_array_add_value_object(paths, path_attrs); - } - if (j) + + nvme_for_each_host(r, h) { + nvme_subsystem_t s; + + host_attrs = json_create_object(); + json_object_add_value_string(host_attrs, "HostNQN", + nvme_host_get_hostnqn(h)); + json_object_add_value_string(host_attrs, "HostID", + nvme_host_get_hostid(h)); + subsystems = json_create_array(); + nvme_for_each_subsystem(h, s) { + nvme_ctrl_t c; + + subsystem_attrs = json_create_object(); + json_object_add_value_string(subsystem_attrs, "Name", + nvme_subsystem_get_name(s)); + json_object_add_value_string(subsystem_attrs, "NQN", + nvme_subsystem_get_nqn(s)); + + json_array_add_value_object(subsystems, subsystem_attrs); + paths = json_create_array(); + + nvme_subsystem_for_each_ctrl(s, c) { + path_attrs = json_create_object(); + json_object_add_value_string(path_attrs, "Name", + nvme_ctrl_get_name(c)); + json_object_add_value_string(path_attrs, "Transport", + nvme_ctrl_get_transport(c)); + json_object_add_value_string(path_attrs, "Address", + nvme_ctrl_get_address(c)); + json_object_add_value_string(path_attrs, "State", + nvme_ctrl_get_state(c)); + json_array_add_value_object(paths, path_attrs); + } json_object_add_value_array(subsystem_attrs, "Paths", - paths); + paths); + } + json_object_add_value_array(host_attrs, "Subsystems", subsystems); + json_array_add_value_object(root, host_attrs); } - - if (i) - json_object_add_value_array(root, "Subsystems", subsystems); json_print_object(root, NULL); printf("\n"); json_free_object(root); } -void nvme_show_subsystem_list(struct nvme_topology *t, - enum nvme_print_flags flags) +void nvme_show_subsystem_list(nvme_root_t r, enum nvme_print_flags flags) { - int i; - if (flags & JSON) - return json_print_nvme_subsystem_list(t); - - for (i = 0; i < t->nr_subsystems; i++) - nvme_show_subsystem(&t->subsystems[i]); + return json_print_nvme_subsystem_list(r); + nvme_show_subsystem(r); } static void nvme_show_registers_cap(struct nvme_bar_cap *cap) @@ -2494,7 +2506,7 @@ void nvme_show_single_property(int offset, uint64_t value64, int human) uint32_t value32; if (!human) { - if (is_64bit_reg(offset)) + if (nvme_is_64bit_reg(offset)) printf("property: 0x%02x (%s), value: %"PRIx64"\n", offset, nvme_register_to_string(offset), value64); @@ -2544,81 +2556,7 @@ void nvme_show_single_property(int offset, uint64_t value64, int human) void nvme_show_relatives(const char *name) { - unsigned id, i, nsid = NVME_NSID_ALL; - char *path = NULL; - bool block = true; - int ret; - - ret = sscanf(name, "nvme%dn%d", &id, &nsid); - switch (ret) { - case 1: - if (asprintf(&path, "/sys/class/nvme/%s", name) < 0) - path = NULL; - block = false; - break; - case 2: - if (asprintf(&path, "/sys/block/%s/device", name) < 0) - path = NULL; - break; - default: - return; - } - - if (!path) - return; - - if (block) { - struct nvme_topology t = { }; - char *subsysnqn; - int err; - - subsysnqn = get_nvme_subsnqn(path); - if (!subsysnqn) { - free(path); - return; - } - err = scan_subsystems(&t, subsysnqn, 0, 0, NULL); - if (err || t.nr_subsystems != 1) { - free(subsysnqn); - free(path); - return; - } - - fprintf(stderr, "Namespace %s has parent controller(s):", name); - for (i = 0; i < t.subsystems[0].nr_ctrls; i++) - fprintf(stderr, "%s%s", i ? ", " : "", - t.subsystems[0].ctrls[i].name); - fprintf(stderr, "\n\n"); - free(subsysnqn); - free_topology(&t); - } else { - struct dirent **paths; - bool comma = false; - int n, ns, cntlid; - - n = scandir(path, &paths, scan_ctrl_paths_filter, alphasort); - if (n < 0) { - free(path); - return; - } - - fprintf(stderr, "Controller %s has child namespace(s):", name); - for (i = 0; i < n; i++) { - if (sscanf(paths[i]->d_name, "nvme%dc%dn%d", - &id, &cntlid, &ns) != 3) { - if (sscanf(paths[i]->d_name, "nvme%dn%d", - &id, &ns) != 2) { - continue; - } - } - fprintf(stderr, "%snvme%dn%d", comma ? ", " : "", id, - ns); - comma = true; - } - fprintf(stderr, "\n\n"); - free(paths); - } - free(path); + /* XXX: TBD */ } void d(unsigned char *buf, int len, int width, int group) @@ -2660,7 +2598,7 @@ void d_raw(unsigned char *buf, unsigned len) { unsigned i; for (i = 0; i < len; i++) - putchar(*(buf + i)); + putchar(*(buf+i)); } void nvme_show_status(__u16 status) @@ -2669,21 +2607,6 @@ void nvme_show_status(__u16 status) status); } -static void format(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz) -{ - - fmt_sz = snprintf(formatter,fmt_sz, "%-*.*s", - (int)tofmtsz, (int)tofmtsz, tofmt); - /* trim() the obnoxious trailing white lines */ - while (fmt_sz) { - if (formatter[fmt_sz - 1] != ' ' && formatter[fmt_sz - 1] != '\0') { - formatter[fmt_sz] = '\0'; - break; - } - fmt_sz--; - } -} - static const char *nvme_uuid_to_string(uuid_t uuid) { /* large enough to hold uuid str (37) + null-termination byte */ @@ -3168,17 +3091,6 @@ static void nvme_show_id_ctrl_nwpc(__u8 nwpc) printf("\n"); } -static void nvme_show_id_ctrl_ocfs(__u16 ocfs) -{ - __u16 rsvd = (ocfs & 0xfffe) >> 1; - __u8 copy_fmt_0 = ocfs & 0x1; - if (rsvd) - printf(" [15:1] : %#x\tReserved\n", rsvd); - printf(" [0:0] : %#x\tController Copy Format 0h %sSupported\n", - copy_fmt_0, copy_fmt_0 ? "" : "Not "); - printf("\n"); -} - static void nvme_show_id_ctrl_sgls(__le32 ctrl_sgls) { __u32 sgls = le32_to_cpu(ctrl_sgls); @@ -3420,7 +3332,7 @@ static void nvme_show_id_ns_dlfeat(__u8 dlfeat) void nvme_show_id_ns(struct nvme_id_ns *ns, unsigned int nsid, enum nvme_print_flags flags) { - int human = flags & VERBOSE; + bool human = flags & VERBOSE; int vs = flags & VS; int i; @@ -3712,29 +3624,29 @@ static void nvme_show_id_ctrl_power(struct nvme_id_ctrl *ctrl) int i; for (i = 0; i <= ctrl->npss; i++) { - __u16 max_power = le16_to_cpu(ctrl->psd[i].max_power); + __u16 max_power = le16_to_cpu(ctrl->psd[i].mp); printf("ps %4d : mp:", i); - if (ctrl->psd[i].flags & NVME_PS_FLAGS_MAX_POWER_SCALE) + if (ctrl->psd[i].flags & NVME_PSD_FLAGS_MXPS) printf("%01u.%04uW ", max_power / 10000, max_power % 10000); else printf("%01u.%02uW ", max_power / 100, max_power % 100); - if (ctrl->psd[i].flags & NVME_PS_FLAGS_NON_OP_STATE) + if (ctrl->psd[i].flags & NVME_PSD_FLAGS_NOPS) printf("non-"); printf("operational enlat:%d exlat:%d rrt:%d rrl:%d\n" " rwt:%d rwl:%d idle_power:", - le32_to_cpu(ctrl->psd[i].entry_lat), - le32_to_cpu(ctrl->psd[i].exit_lat), - ctrl->psd[i].read_tput, ctrl->psd[i].read_lat, - ctrl->psd[i].write_tput, ctrl->psd[i].write_lat); - print_ps_power_and_scale(ctrl->psd[i].idle_power, - POWER_SCALE(ctrl->psd[i].idle_scale)); + le32_to_cpu(ctrl->psd[i].enlat), + le32_to_cpu(ctrl->psd[i].exlat), + ctrl->psd[i].rrt, ctrl->psd[i].rrl, + ctrl->psd[i].rwt, ctrl->psd[i].rwl); + print_ps_power_and_scale(ctrl->psd[i].idlp, + nvme_psd_power_scale(ctrl->psd[i].ips)); printf(" active_power:"); - print_ps_power_and_scale(ctrl->psd[i].active_power, - POWER_SCALE(ctrl->psd[i].active_work_scale)); + print_ps_power_and_scale(ctrl->psd[i].actp, + nvme_psd_power_scale(ctrl->psd[i].aps)); printf("\n"); } @@ -3867,9 +3779,6 @@ void __nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags, if (human) nvme_show_id_ctrl_nwpc(ctrl->nwpc); printf("acwu : %d\n", le16_to_cpu(ctrl->acwu)); - printf("ocfs : %#x\n", le16_to_cpu(ctrl->ocfs)); - if (human) - nvme_show_id_ctrl_ocfs(ctrl->ocfs); printf("sgls : %#x\n", le32_to_cpu(ctrl->sgls)); if (human) nvme_show_id_ctrl_sgls(ctrl->sgls); @@ -4092,7 +4001,7 @@ void nvme_show_zns_id_ns(struct nvme_zns_id_ns *ns, } } -static void json_nvme_list_ns(__u32 *ns_list) +static void json_nvme_list_ns(struct nvme_ns_list *ns_list) { struct json_object *root; struct json_object *valid_attrs; @@ -4103,10 +4012,10 @@ static void json_nvme_list_ns(__u32 *ns_list) valid = json_create_array(); for (i = 0; i < 1024; i++) { - if (ns_list[i]) { + if (ns_list->ns[i]) { valid_attrs = json_create_object(); json_object_add_value_uint(valid_attrs, "nsid", - le32_to_cpu(ns_list[i])); + le32_to_cpu(ns_list->ns[i])); json_array_add_value_object(valid, valid_attrs); } } @@ -4116,15 +4025,15 @@ static void json_nvme_list_ns(__u32 *ns_list) json_free_object(root); } -void nvme_show_list_ns(__u32 *ns_list, enum nvme_print_flags flags) +void nvme_show_list_ns(struct nvme_ns_list *ns_list, enum nvme_print_flags flags) { int i; if (flags & JSON) return json_nvme_list_ns(ns_list); for (i = 0; i < 1024; i++) { - if (ns_list[i]) - printf("[%4u]:%#x\n", i, le32_to_cpu(ns_list[i])); + if (ns_list->ns[i]) + printf("[%4u]:%#x\n", i, le32_to_cpu(ns_list->ns[i])); } } @@ -4218,7 +4127,7 @@ void nvme_show_zns_report_zones(void *report, __u32 descs, } } -static void json_nvme_list_ctrl(struct nvme_controller_list *ctrl_list, __u16 num) +static void json_nvme_list_ctrl(struct nvme_ctrl_list *ctrl_list, __u16 num) { struct json_object *root; struct json_object *valid_attrs; @@ -4245,7 +4154,7 @@ static void json_nvme_list_ctrl(struct nvme_controller_list *ctrl_list, __u16 nu json_free_object(root); } -void nvme_show_list_ctrl(struct nvme_controller_list *ctrl_list, +void nvme_show_list_ctrl(struct nvme_ctrl_list *ctrl_list, enum nvme_print_flags flags) { int i; @@ -4260,7 +4169,7 @@ void nvme_show_list_ctrl(struct nvme_controller_list *ctrl_list, } } -static void json_nvme_id_nvmset(struct nvme_id_nvmset *nvmset) +static void json_nvme_id_nvmset(struct nvme_id_nvmset_list *nvmset) { __u32 nent = nvmset->nid; struct json_object *entries; @@ -4276,17 +4185,17 @@ static void json_nvme_id_nvmset(struct nvme_id_nvmset *nvmset) struct json_object *entry = json_create_object(); json_object_add_value_int(entry, "nvmset_id", - le16_to_cpu(nvmset->ent[i].id)); + le16_to_cpu(nvmset->ent[i].nvmsetid)); json_object_add_value_int(entry, "endurance_group_id", - le16_to_cpu(nvmset->ent[i].endurance_group_id)); + le16_to_cpu(nvmset->ent[i].endgid)); json_object_add_value_int(entry, "random_4k_read_typical", - le32_to_cpu(nvmset->ent[i].random_4k_read_typical)); + le32_to_cpu(nvmset->ent[i].rr4kt)); json_object_add_value_int(entry, "optimal_write_size", - le32_to_cpu(nvmset->ent[i].opt_write_size)); + le32_to_cpu(nvmset->ent[i].ows)); json_object_add_value_float(entry, "total_nvmset_cap", - int128_to_double(nvmset->ent[i].total_nvmset_cap)); + int128_to_double(nvmset->ent[i].tnvmsetcap)); json_object_add_value_float(entry, "unalloc_nvmset_cap", - int128_to_double(nvmset->ent[i].unalloc_nvmset_cap)); + int128_to_double(nvmset->ent[i].unvmsetcap)); json_array_add_value_object(entries, entry); } @@ -4296,7 +4205,7 @@ static void json_nvme_id_nvmset(struct nvme_id_nvmset *nvmset) json_free_object(root); } -void nvme_show_id_nvmset(struct nvme_id_nvmset *nvmset, unsigned nvmset_id, +void nvme_show_id_nvmset(struct nvme_id_nvmset_list *nvmset, unsigned nvmset_id, enum nvme_print_flags flags) { int i; @@ -4313,22 +4222,22 @@ void nvme_show_id_nvmset(struct nvme_id_nvmset *nvmset, unsigned nvmset_id, printf(" NVM Set Attribute Entry[%2d]\n", i); printf(".................\n"); printf("nvmset_id : %d\n", - le16_to_cpu(nvmset->ent[i].id)); + le16_to_cpu(nvmset->ent[i].endgid)); printf("enduracne_group_id : %d\n", - le16_to_cpu(nvmset->ent[i].endurance_group_id)); + le16_to_cpu(nvmset->ent[i].endgid)); printf("random_4k_read_typical : %u\n", - le32_to_cpu(nvmset->ent[i].random_4k_read_typical)); + le32_to_cpu(nvmset->ent[i].rr4kt)); printf("optimal_write_size : %u\n", - le32_to_cpu(nvmset->ent[i].opt_write_size)); + le32_to_cpu(nvmset->ent[i].ows)); printf("total_nvmset_cap : %.0Lf\n", - int128_to_double(nvmset->ent[i].total_nvmset_cap)); + int128_to_double(nvmset->ent[i].tnvmsetcap)); printf("unalloc_nvmset_cap : %.0Lf\n", - int128_to_double(nvmset->ent[i].unalloc_nvmset_cap)); + int128_to_double(nvmset->ent[i].unvmsetcap)); printf(".................\n"); } } -static void json_nvme_primary_ctrl_caps(const struct nvme_primary_ctrl_caps *caps) +static void json_nvme_primary_ctrl_cap(const struct nvme_primary_ctrl_cap *caps) { struct json_object *root; @@ -4369,15 +4278,15 @@ static void nvme_show_primary_ctrl_caps_crt(__u8 crt) printf(" [0:0] %#x\tVQ Resources are %ssupported\n", vq, vq ? "" : "not "); } -void nvme_show_primary_ctrl_caps(const struct nvme_primary_ctrl_caps *caps, - enum nvme_print_flags flags) +void nvme_show_primary_ctrl_cap(const struct nvme_primary_ctrl_cap *caps, + enum nvme_print_flags flags) { int human = flags & VERBOSE; if (flags & BINARY) return d_raw((unsigned char *)caps, sizeof(*caps)); else if (flags & JSON) - return json_nvme_primary_ctrl_caps(caps); + return json_nvme_primary_ctrl_cap(caps); printf("NVME Identify Primary Controller Capabilities:\n"); printf("cntlid : %#x\n", le16_to_cpu(caps->cntlid)); @@ -4399,10 +4308,10 @@ void nvme_show_primary_ctrl_caps(const struct nvme_primary_ctrl_caps *caps, printf("vigran : %d\n", le16_to_cpu(caps->vigran)); } -static void json_nvme_list_secondary_ctrl(const struct nvme_secondary_controllers_list *sc_list, +static void json_nvme_list_secondary_ctrl(const struct nvme_secondary_ctrl_list *sc_list, __u32 count) { - const struct nvme_secondary_controller_entry *sc_entry = &sc_list->sc_entry[0]; + const struct nvme_secondary_ctrl *sc_entry = &sc_list->sc_entry[0]; __u32 nent = min(sc_list->num, count); struct json_object *entries; struct json_object *root; @@ -4441,10 +4350,10 @@ static void json_nvme_list_secondary_ctrl(const struct nvme_secondary_controller } void nvme_show_list_secondary_ctrl( - const struct nvme_secondary_controllers_list *sc_list, + const struct nvme_secondary_ctrl_list *sc_list, __u32 count, enum nvme_print_flags flags) { - const struct nvme_secondary_controller_entry *sc_entry = + const struct nvme_secondary_ctrl *sc_entry = &sc_list->sc_entry[0]; static const char * const state_desc[] = { "Offline", "Online" }; @@ -4497,9 +4406,9 @@ static void json_nvme_id_ns_granularity_list( struct json_object *entry = json_create_object(); json_object_add_value_uint(entry, "namespace-size-granularity", - le64_to_cpu(glist->entry[i].namespace_size_granularity)); + le64_to_cpu(glist->entry[i].nszegran)); json_object_add_value_uint(entry, "namespace-capacity-granularity", - le64_to_cpu(glist->entry[i].namespace_capacity_granularity)); + le64_to_cpu(glist->entry[i].ncapgran)); json_array_add_value_object(entries, entry); } @@ -4531,9 +4440,9 @@ void nvme_show_id_ns_granularity_list(const struct nvme_id_ns_granularity_list * printf("\n Entry[%2d] :\n", i); printf("................\n"); printf(" NSG : Namespace Size Granularity : 0x%"PRIx64"\n", - le64_to_cpu(glist->entry[i].namespace_size_granularity)); + le64_to_cpu(glist->entry[i].nszegran)); printf(" NCG : Namespace Capacity Granularity : 0x%"PRIx64"\n", - le64_to_cpu(glist->entry[i].namespace_capacity_granularity)); + le64_to_cpu(glist->entry[i].ncapgran)); } } @@ -4546,7 +4455,7 @@ static void json_nvme_id_uuid_list(const struct nvme_id_uuid_list *uuid_list) root = json_create_object(); entries = json_create_array(); /* The 0th entry is reserved */ - for (i = 1; i < NVME_MAX_UUID_ENTRIES; i++) { + for (i = 1; i < NVME_ID_UUID_LIST_MAX; i++) { uuid_t uuid; struct json_object *entry = json_create_object(); @@ -4578,7 +4487,7 @@ void nvme_show_id_uuid_list(const struct nvme_id_uuid_list *uuid_list, /* The 0th entry is reserved */ printf("NVME Identify UUID:\n"); - for (i = 1; i < NVME_MAX_UUID_ENTRIES; i++) { + for (i = 1; i < NVME_ID_UUID_LIST_MAX; i++) { uuid_t uuid; char *association = ""; uint8_t identifier_association = uuid_list->entry[i].header & 0x3; @@ -4613,67 +4522,14 @@ void nvme_show_id_uuid_list(const struct nvme_id_uuid_list *uuid_list, } } -static void nvme_show_iocs_vector(__u64 iocs_vec) +void nvme_show_id_iocs(struct nvme_id_iocs *iocs) { - __u64 rsvd3 = iocs_vec >> 3; - __u8 zns_cmd_set = (iocs_vec >> 2) & 0x1; - __u8 kv_cmd_set = (iocs_vec >> 1) & 0x1; - __u8 nvm_cmd_set = iocs_vec & 0x1; + __u16 i; - if (rsvd3) - printf(" [63:3] : %"PRIx64"\tReserved3\n", le64_to_cpu(rsvd3)); - printf(" [2:2] : %#x\tZNS Command Set %sSelected\n", - zns_cmd_set, zns_cmd_set ? "" : "not "); - printf(" [1:1] : %#x\tKV Command Set %sSelected\n", - kv_cmd_set, kv_cmd_set ? "" : "not "); - printf(" [0:0] : %#x\tNVM Command Set %sSelected\n", - nvm_cmd_set, nvm_cmd_set ? "" : "not "); - printf("\n"); -} - -static void json_id_iocs(struct nvme_id_iocs *iocs) -{ - struct json_object *root; - struct json_object *entries; - int i; - - root = json_create_object(); - entries = json_create_array(); - - for (i = 0; i < NVME_NUM_IOCS_COMBINATIONS; i++) { - if (iocs->iocs[i]) { - struct json_object *entry = json_create_object(); - json_object_add_value_uint(entry, "iocs", - le64_to_cpu(iocs->iocs[i])); - json_array_add_value_object(entries, entry); - } - } - - json_object_add_value_array(root, "iocs_list", entries); - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); - -} - -void nvme_show_id_iocs(struct nvme_id_iocs *iocs, enum nvme_print_flags flags) -{ - if (flags & BINARY) - return d_raw((unsigned char *)iocs, sizeof(*iocs)); - else if (flags & JSON) - return json_id_iocs(iocs); - - bool human = flags & VERBOSE; - int i; - - for (i = 0; i < NVME_NUM_IOCS_COMBINATIONS; i++) { - if (iocs->iocs[i]) { - printf("I/O Command Set Combination[%u]: %"PRIx64"\n", i, - (uint64_t)le64_to_cpu(iocs->iocs[i])); - if (human) - nvme_show_iocs_vector(le64_to_cpu(iocs->iocs[i])); - } - } + for (i = 0; i < 512; i++) + if (iocs->iocsc[i]) + printf("I/O Command Set Combination[%u]:%"PRIx64"\n", i, + (uint64_t)le64_to_cpu(iocs->iocsc[i])); } static const char *nvme_trtype_to_string(__u8 trtype) @@ -4730,7 +4586,7 @@ void nvme_show_error_log(struct nvme_error_log_page *err_log, int entries, } } -void nvme_show_resv_report(struct nvme_reservation_status *status, int bytes, +void nvme_show_resv_report(struct nvme_resv_status *status, int bytes, __u32 cdw11, enum nvme_print_flags flags) { int i, j, regctl, entries; @@ -4770,8 +4626,6 @@ void nvme_show_resv_report(struct nvme_reservation_status *status, int bytes, le64_to_cpu(status->regctl_ds[i].rkey)); } } else { - struct nvme_reservation_status_ext *ext_status = - (struct nvme_reservation_status_ext *)status; /* if status buffer was too small, don't loop past the end of the buffer */ entries = (bytes - 64) / 64; if (entries < regctl) @@ -4780,22 +4634,22 @@ void nvme_show_resv_report(struct nvme_reservation_status *status, int bytes, for (i = 0; i < regctl; i++) { printf("regctlext[%d] :\n", i); printf(" cntlid : %x\n", - le16_to_cpu(ext_status->regctl_eds[i].cntlid)); + le16_to_cpu(status->regctl_eds[i].cntlid)); printf(" rcsts : %x\n", - ext_status->regctl_eds[i].rcsts); + status->regctl_eds[i].rcsts); printf(" rkey : %"PRIx64"\n", - le64_to_cpu(ext_status->regctl_eds[i].rkey)); + le64_to_cpu(status->regctl_eds[i].rkey)); printf(" hostid : "); for (j = 0; j < 16; j++) printf("%x", - ext_status->regctl_eds[i].hostid[j]); + status->regctl_eds[i].hostid[j]); printf("\n"); } } printf("\n"); } -void nvme_show_fw_log(struct nvme_firmware_log_page *fw_log, +void nvme_show_fw_log(struct nvme_firmware_slot *fw_log, const char *devname, enum nvme_print_flags flags) { int i; @@ -4815,7 +4669,7 @@ void nvme_show_fw_log(struct nvme_firmware_log_page *fw_log, } } -void nvme_show_changed_ns_list_log(struct nvme_changed_ns_list_log *log, +void nvme_show_changed_ns_list_log(struct nvme_ns_list *log, const char *devname, enum nvme_print_flags flags) { @@ -4827,9 +4681,9 @@ void nvme_show_changed_ns_list_log(struct nvme_changed_ns_list_log *log, else if (flags & JSON) return json_changed_ns_list_log(log, devname); - if (log->log[0] != cpu_to_le32(0XFFFFFFFF)) { - for (i = 0; i < NVME_MAX_CHANGED_NAMESPACES; i++) { - nsid = le32_to_cpu(log->log[i]); + if (log->ns[0] != cpu_to_le32(NVME_NSID_ALL)) { + for (i = 0; i < NVME_ID_NS_LIST_MAX; i++) { + nsid = le32_to_cpu(log->ns[i]); if (nsid == 0) break; @@ -4837,7 +4691,7 @@ void nvme_show_changed_ns_list_log(struct nvme_changed_ns_list_log *log, } } else printf("more than %d ns changed\n", - NVME_MAX_CHANGED_NAMESPACES); + NVME_ID_NS_LIST_MAX); } static void nvme_show_effects_log_human(__u32 effect) @@ -4862,7 +4716,7 @@ static void nvme_show_effects_log_human(__u32 effect) printf(" Reserved CSE\n"); } -void nvme_show_effects_log(struct nvme_effects_log_page *effects, +void nvme_show_effects_log(struct nvme_cmd_effects_log *effects, unsigned int flags) { int i, human = flags & VERBOSE; @@ -5012,7 +4866,7 @@ void nvme_show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, if (temp == 0) continue; printf("Temperature Sensor %d : %ld C (%u Kelvin)\n", - i + 1, kelvin_to_celsius(temp), temp); + i + 1, kelvin_to_celsius(temp), temp); } printf("Thermal Management T1 Trans Count : %u\n", le32_to_cpu(smart->thm_temp1_trans_count)); @@ -5024,11 +4878,11 @@ void nvme_show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, le32_to_cpu(smart->thm_temp2_total_time)); } -void nvme_show_ana_log(struct nvme_ana_rsp_hdr *ana_log, const char *devname, +void nvme_show_ana_log(struct nvme_ana_log *ana_log, const char *devname, enum nvme_print_flags flags, size_t len) { - int offset = sizeof(struct nvme_ana_rsp_hdr); - struct nvme_ana_rsp_hdr *hdr = ana_log; + int offset = sizeof(struct nvme_ana_log); + struct nvme_ana_log *hdr = ana_log; struct nvme_ana_group_desc *desc; size_t nsid_buf_size; void *base = ana_log; @@ -5068,7 +4922,7 @@ void nvme_show_ana_log(struct nvme_ana_rsp_hdr *ana_log, const char *devname, } } -static void nvme_show_self_test_result(struct nvme_self_test_res *res, +static void nvme_show_self_test_result(struct nvme_st_result *res, enum nvme_print_flags flags) { static const char *const test_res[] = { @@ -5085,17 +4939,17 @@ static void nvme_show_self_test_result(struct nvme_self_test_res *res, "Operation was aborted for unknown reason", "Operation was aborted due to a sanitize operation", "Reserved", - [NVME_ST_RES_NOT_USED] = "Entry not used (does not contain a result)", + [NVME_ST_RESULT_NOT_USED] = "Entry not used (does not contain a result)", }; __u8 op, code; - op = res->dsts & NVME_ST_RES_MASK; + op = res->dsts & NVME_ST_RESULT_MASK; printf(" Operation Result : %#x", op); if (flags & VERBOSE) printf(" %s", (op < ARRAY_SIZE(test_res) && test_res[op]) ? test_res[op] : test_res[ARRAY_SIZE(test_res) - 1]); printf("\n"); - if (op == NVME_ST_RES_NOT_USED) + if (op == NVME_ST_RESULT_NOT_USED) return; code = res->dsts >> NVME_ST_CODE_SHIFT; @@ -5103,10 +4957,10 @@ static void nvme_show_self_test_result(struct nvme_self_test_res *res, if (flags & VERBOSE) { switch (code) { - case NVME_ST_CODE_SHORT_OP: + case NVME_ST_CODE_SHORT: printf(" Short device self-test operation"); break; - case NVME_ST_CODE_EXT_OP: + case NVME_ST_CODE_EXTENDED: printf(" Extended device self-test operation"); break; case NVME_ST_CODE_VS: @@ -5119,22 +4973,22 @@ static void nvme_show_self_test_result(struct nvme_self_test_res *res, } printf("\n"); - if (op == NVME_ST_RES_KNOWN_SEG_FAIL) + if (op == NVME_ST_RESULT_KNOWN_SEG_FAIL) printf(" Segment Number : %#x\n", res->seg); printf(" Valid Diagnostic Information : %#x\n", res->vdi); printf(" Power on hours (POH) : %#"PRIx64"\n", (uint64_t)le64_to_cpu(res->poh)); - if (res->vdi & NVME_ST_VALID_NSID) + if (res->vdi & NVME_ST_VALID_DIAG_INFO_NSID) printf(" Namespace Identifier : %#x\n", le32_to_cpu(res->nsid)); - if (res->vdi & NVME_ST_VALID_FLBA) + if (res->vdi & NVME_ST_VALID_DIAG_INFO_FLBA) printf(" Failing LBA : %#"PRIx64"\n", (uint64_t)le64_to_cpu(res->flba)); - if (res->vdi & NVME_ST_VALID_SCT) + if (res->vdi & NVME_ST_VALID_DIAG_INFO_SCT) printf(" Status Code Type : %#x\n", res->sct); - if (res->vdi & NVME_ST_VALID_SC) { + if (res->vdi & NVME_ST_VALID_DIAG_INFO_SC) { printf(" Status Code : %#x", res->sc); if (flags & VERBOSE) printf(" %s", nvme_status_to_string( @@ -5157,9 +5011,9 @@ void nvme_show_self_test_log(struct nvme_self_test_log *self_test, __u8 dst_entr return json_self_test_log(self_test, dst_entries); printf("Device Self Test Log for NVME device:%s\n", devname); - printf("Current operation : %#x\n", self_test->crnt_dev_selftest_oprn); - printf("Current Completion : %u%%\n", self_test->crnt_dev_selftest_compln); - num_entries = min(dst_entries, NVME_ST_REPORTS); + printf("Current operation : %#x\n", self_test->current_operation); + printf("Current Completion : %u%%\n", self_test->completion); + num_entries = min(dst_entries, NVME_LOG_ST_MAX_RESULTS); for (i = 0; i < num_entries; i++) { printf("Self Test Result[%d]:\n", i); nvme_show_self_test_result(&self_test->result[i], flags); @@ -5181,10 +5035,11 @@ static void nvme_show_sanitize_log_sstat(__u16 status) printf("\t[2:0]\t%s\n", str); str = "Number of completed passes if most recent operation was overwrite"; printf("\t[7:3]\t%s:\t%u\n", str, - (status & NVME_SANITIZE_LOG_NUM_CMPLTED_PASS_MASK) >> 3); + (status >> NVME_SANITIZE_SSTAT_COMPLETED_PASSES_SHIFT) & + NVME_SANITIZE_SSTAT_COMPLETED_PASSES_MASK); printf("\t [8]\t"); - if (status & NVME_SANITIZE_LOG_GLOBAL_DATA_ERASED) + if (status & NVME_SANITIZE_SSTAT_GLOBAL_DATA_ERASED) str = "Global Data Erased set: no NS LB in the NVM subsystem "\ "has been written to and no PMR in the NVM subsystem "\ "has been enabled"; @@ -5205,80 +5060,81 @@ void nvme_show_sanitize_log(struct nvme_sanitize_log_page *sanitize, const char *devname, enum nvme_print_flags flags) { int human = flags & VERBOSE; - __u16 status = le16_to_cpu(sanitize->status) & NVME_SANITIZE_LOG_STATUS_MASK; + __u16 status = le16_to_cpu(sanitize->sstat) & NVME_SANITIZE_SSTAT_STATUS_MASK; if (flags & BINARY) - return d_raw((unsigned char *)sanitize, sizeof(*sanitize)); - else if (flags & JSON) - return json_sanitize_log(sanitize, devname); + d_raw((unsigned char *)sanitize, sizeof(*sanitize)); + else if (flags & JSON) { + json_sanitize_log(sanitize, devname); + return; + } printf("Sanitize Progress (SPROG) : %u", - le16_to_cpu(sanitize->progress)); + le16_to_cpu(sanitize->sprog)); - if (human && status == NVME_SANITIZE_LOG_IN_PROGESS) - nvme_show_sanitize_log_sprog(le16_to_cpu(sanitize->progress)); + if (human && status == NVME_SANITIZE_SSTAT_STATUS_IN_PROGESS) + nvme_show_sanitize_log_sprog(le16_to_cpu(sanitize->sprog)); else printf("\n"); printf("Sanitize Status (SSTAT) : %#x\n", - le16_to_cpu(sanitize->status)); + le16_to_cpu(sanitize->sstat)); if (human) - nvme_show_sanitize_log_sstat(le16_to_cpu(sanitize->status)); + nvme_show_sanitize_log_sstat(le16_to_cpu(sanitize->sstat)); printf("Sanitize Command Dword 10 Information (SCDW10) : %#x\n", - le32_to_cpu(sanitize->cdw10_info)); + le32_to_cpu(sanitize->scdw10)); nvme_show_estimate_sanitize_time("Estimated Time For Overwrite ", - le32_to_cpu(sanitize->est_ovrwrt_time)); + le32_to_cpu(sanitize->eto)); nvme_show_estimate_sanitize_time("Estimated Time For Block Erase ", - le32_to_cpu(sanitize->est_blk_erase_time)); + le32_to_cpu(sanitize->etbe)); nvme_show_estimate_sanitize_time("Estimated Time For Crypto Erase ", - le32_to_cpu(sanitize->est_crypto_erase_time)); + le32_to_cpu(sanitize->etce)); nvme_show_estimate_sanitize_time("Estimated Time For Overwrite (No-Deallocate) ", - le32_to_cpu(sanitize->est_ovrwrt_time_with_no_deallocate)); + le32_to_cpu(sanitize->etond)); nvme_show_estimate_sanitize_time("Estimated Time For Block Erase (No-Deallocate) ", - le32_to_cpu(sanitize->est_blk_erase_time_with_no_deallocate)); + le32_to_cpu(sanitize->etbend)); nvme_show_estimate_sanitize_time("Estimated Time For Crypto Erase (No-Deallocate)", - le32_to_cpu(sanitize->est_crypto_erase_time_with_no_deallocate)); + le32_to_cpu(sanitize->etcend)); } -const char *nvme_feature_to_string(enum nvme_feat feature) +const char *nvme_feature_to_string(enum nvme_features_id feature) { switch (feature) { - case NVME_FEAT_NONE: return "Reserved"; - case NVME_FEAT_ARBITRATION: return "Arbitration"; - case NVME_FEAT_POWER_MGMT: return "Power Management"; - case NVME_FEAT_LBA_RANGE: return "LBA Range Type"; - case NVME_FEAT_TEMP_THRESH: return "Temperature Threshold"; - case NVME_FEAT_ERR_RECOVERY: return "Error Recovery"; - case NVME_FEAT_VOLATILE_WC: return "Volatile Write Cache"; - case NVME_FEAT_NUM_QUEUES: return "Number of Queues"; - case NVME_FEAT_IRQ_COALESCE: return "Interrupt Coalescing"; - case NVME_FEAT_IRQ_CONFIG: return "Interrupt Vector Configuration"; - case NVME_FEAT_WRITE_ATOMIC: return "Write Atomicity Normal"; - case NVME_FEAT_ASYNC_EVENT: return "Async Event Configuration"; - case NVME_FEAT_AUTO_PST: return "Autonomous Power State Transition"; - case NVME_FEAT_HOST_MEM_BUF: return "Host Memory Buffer"; - case NVME_FEAT_KATO: return "Keep Alive Timer"; - case NVME_FEAT_NOPSC: return "Non-Operational Power State Config"; - case NVME_FEAT_RRL: return "Read Recovery Level"; - case NVME_FEAT_PLM_CONFIG: return "Predicatable Latency Mode Config"; - case NVME_FEAT_PLM_WINDOW: return "Predicatable Latency Mode Window"; - case NVME_LBA_STATUS_INFO: return "LBA Status Infomation Attributes"; - case NVME_FEAT_ENDURANCE: return "Enduarance Event Group Configuration"; - case NVME_FEAT_IOCS_PROFILE: return "I/O Command Set Profile"; - case NVME_FEAT_SW_PROGRESS: return "Software Progress"; - case NVME_FEAT_HOST_ID: return "Host Identifier"; - case NVME_FEAT_RESV_MASK: return "Reservation Notification Mask"; - case NVME_FEAT_RESV_PERSIST: return "Reservation Persistence"; - case NVME_FEAT_TIMESTAMP: return "Timestamp"; - case NVME_FEAT_WRITE_PROTECT: return "Namespce Write Protect"; - case NVME_FEAT_HCTM: return "Host Controlled Thermal Management"; - case NVME_FEAT_HOST_BEHAVIOR: return "Host Behavior"; - case NVME_FEAT_SANITIZE: return "Sanitize"; + case NVME_FEAT_FID_ARBITRATION: return "Arbitration"; + case NVME_FEAT_FID_POWER_MGMT: return "Power Management"; + case NVME_FEAT_FID_LBA_RANGE: return "LBA Range Type"; + case NVME_FEAT_FID_TEMP_THRESH: return "Temperature Threshold"; + case NVME_FEAT_FID_ERR_RECOVERY:return "Error Recovery"; + case NVME_FEAT_FID_VOLATILE_WC: return "Volatile Write Cache"; + case NVME_FEAT_FID_NUM_QUEUES: return "Number of Queues"; + case NVME_FEAT_FID_IRQ_COALESCE:return "Interrupt Coalescing"; + case NVME_FEAT_FID_IRQ_CONFIG: return "Interrupt Vector Configuration"; + case NVME_FEAT_FID_WRITE_ATOMIC:return "Write Atomicity Normal"; + case NVME_FEAT_FID_ASYNC_EVENT: return "Async Event Configuration"; + case NVME_FEAT_FID_AUTO_PST: return "Autonomous Power State Transition"; + case NVME_FEAT_FID_HOST_MEM_BUF:return "Host Memory Buffer"; + case NVME_FEAT_FID_KATO: return "Keep Alive Timer"; + case NVME_FEAT_FID_NOPSC: return "Non-Operational Power State Config"; + case NVME_FEAT_FID_RRL: return "Read Recovery Level"; + case NVME_FEAT_FID_PLM_CONFIG: return "Predicatable Latency Mode Config"; + case NVME_FEAT_FID_PLM_WINDOW: return "Predicatable Latency Mode Window"; + case NVME_FEAT_FID_ENDURANCE_EVT_CFG: return "Enduarance Event Group Configuration"; + case NVME_FEAT_FID_IOCS_PROFILE:return "I/O Command Set Profile"; + case NVME_FEAT_FID_SW_PROGRESS: return "Software Progress"; + case NVME_FEAT_FID_HOST_ID: return "Host Identifier"; + case NVME_FEAT_FID_RESV_MASK: return "Reservation Notification Mask"; + case NVME_FEAT_FID_RESV_PERSIST:return "Reservation Persistence"; + case NVME_FEAT_FID_TIMESTAMP: return "Timestamp"; + case NVME_FEAT_FID_WRITE_PROTECT:return "Namespce Write Protect"; + case NVME_FEAT_FID_HCTM: return "Host Controlled Thermal Management"; + case NVME_FEAT_FID_HOST_BEHAVIOR:return "Host Behavior"; + case NVME_FEAT_FID_SANITIZE: return "Sanitize"; + case NVME_FEAT_FID_LBA_STS_INTERVAL: return "LBA Status Interval"; } /* * We don't use the "default:" statement to let the compiler warning if - * some values of the enum nvme_feat are missing in the switch(). + * some values of the enum nvme_features_id are missing in the switch(). * The following return is acting as the default: statement. */ return "Unknown"; @@ -5324,222 +5180,173 @@ void nvme_show_select_result(__u32 result) printf(" Feature is changeable\n"); } +static const char * const generic_status[] = { + [NVME_SC_SUCCESS] = "Successful Completion: The command completed without error", + [NVME_SC_INVALID_OPCODE] = "Invalid Command Opcode: A reserved coded value or an unsupported value in the command opcode field", + [NVME_SC_INVALID_FIELD] = "Invalid Field in Command: A reserved coded value or an unsupported value in a defined field", + [NVME_SC_CMDID_CONFLICT] = "Command ID Conflict: The command identifier is already in use", + [NVME_SC_DATA_XFER_ERROR] = "Data Transfer Error: Transferring the data or metadata associated with a command experienced an error", + [NVME_SC_POWER_LOSS] = "Commands Aborted due to Power Loss Notification: Indicates that the command was aborted due to a power loss notification", + [NVME_SC_INTERNAL] = "Internal Error: The command was not completed successfully due to an internal error", + [NVME_SC_ABORT_REQ] = "Command Abort Requested: The command was aborted due to an Abort command", + [NVME_SC_ABORT_QUEUE] = "Command Aborted due to SQ Deletion: The command was aborted due to a Delete I/O Submission Queue", + [NVME_SC_FUSED_FAIL] = "Command Aborted due to Failed Fused Command: The command was aborted due to the other command in a fused operation failing", + [NVME_SC_FUSED_MISSING] = "Command Aborted due to Missing Fused Command: The fused command was aborted due to the adjacent submission queue entry not containing a fused command", + [NVME_SC_INVALID_NS] = "Invalid Namespace or Format: The namespace or the format of that namespace is invalid", + [NVME_SC_CMD_SEQ_ERROR] = "Command Sequence Error: The command was aborted due to a protocol violation in a multi- command sequence", + [NVME_SC_SGL_INVALID_LAST] = "Invalid SGL Segment Descriptor: The command includes an invalid SGL Last Segment or SGL Segment descriptor", + [NVME_SC_SGL_INVALID_COUNT] = "Invalid Number of SGL Descriptors: There is an SGL Last Segment descriptor or an SGL Segment descriptor in a location other than the last descriptor of a segment based on the length indicated", + [NVME_SC_SGL_INVALID_DATA] = "Data SGL Length Invalid: The length of a Data SGL is too short or too long and the controller does not support SGL transfers longer than the amount of data to be transferred", + [NVME_SC_SGL_INVALID_METADATA] = "Metadata SGL Length Invalid: The length of a Metadata SGL is too short or too long and the controller does not support SGL transfers longer than the amount of data to be transferred", + [NVME_SC_SGL_INVALID_TYPE] = "SGL Descriptor Type Invalid: The type of an SGL Descriptor is a type that is not supported by the controller", + [NVME_SC_CMB_INVALID_USE] = "Invalid Use of Controller Memory Buffer: The attempted use of the Controller Memory Buffer is not supported by the controller", + [NVME_SC_PRP_INVALID_OFFSET] = "PRP Offset Invalid: The Offset field for a PRP entry is invalid", + [NVME_SC_AWU_EXCEEDED] = "Atomic Write Unit Exceeded: The length specified exceeds the atomic write unit size", + [NVME_SC_OP_DENIED] = "Operation Denied: The command was denied due to lack of access rights", + [NVME_SC_SGL_INVALID_OFFSET] = "SGL Offset Invalid: The offset specified in a descriptor is invalid", + [NVME_SC_HOSTID_FORMAT] = "Host Identifier Inconsistent Format: The NVM subsystem detected the simultaneous use of 64- bit and 128-bit Host Identifier values on different controllers", + [NVME_SC_KAT_EXPIRED] = "Keep Alive Timer Expired: The Keep Alive Timer expired", + [NVME_SC_KAT_INVALID] = "Keep Alive Timeout Invalid: The Keep Alive Timeout value specified is invalid", + [NVME_SC_CMD_ABORTED_PREMEPT] = "Command Aborted due to Preempt and Abort: The command was aborted due to a Reservation Acquire command", + [NVME_SC_SANITIZE_FAILED] = "Sanitize Failed: The most recent sanitize operation failed and no recovery action has been successfully completed", + [NVME_SC_SANITIZE_IN_PROGRESS] = "Sanitize In Progress: The requested function is prohibited while a sanitize operation is in progress", + [NVME_SC_SGL_INVALID_GRANULARITY] = "SGL Data Block Granularity Invalid: The Address alignment or Length granularity for an SGL Data Block descriptor is invalid", + [NVME_SC_CMD_IN_CMBQ_NOT_SUPP] = "Command Not Supported for Queue in CMB: The controller does not support Submission Queue in the Controller Memory Buffer or Completion Queue in the Controller Memory Buffer", + [NVME_SC_NS_WRITE_PROTECTED] = "Namespace is Write Protected: The command is prohibited while the namespace is write protected", + [NVME_SC_CMD_INTERRUPTED] = "Command Interrupted: Command processing was interrupted and the controller is unable to successfully complete the command", + [NVME_SC_TRAN_TPORT_ERROR] = "Transient Transport Error: A transient transport error was detected", + [NVME_SC_LBA_RANGE] = "LBA Out of Range: The command references an LBA that exceeds the size of the namespace", + [NVME_SC_CAP_EXCEEDED] = "Capacity Exceeded: Execution of the command has caused the capacity of the namespace to be exceeded", + [NVME_SC_NS_NOT_READY] = "Namespace Not Ready: The namespace is not ready to be accessed", + [NVME_SC_RESERVATION_CONFLICT] = "Reservation Conflict: The command was aborted due to a conflict with a reservation held on the accessed namespace", + [NVME_SC_FORMAT_IN_PROGRESS] = "Format In Progress: A Format NVM command is in progress on the namespace", +}; + +static const char * const cmd_spec_status[] = { + [NVME_SC_CQ_INVALID] = "Completion Queue Invalid: The Completion Queue identifier specified in the command does not exist", + [NVME_SC_QID_INVALID] = "Invalid Queue Identifier: The creation of the I/O Completion Queue failed due to an invalid queue identifier specified as part of the command", + [NVME_SC_QUEUE_SIZE] = "Invalid Queue Size: The host attempted to create an I/O Completion Queue with an invalid number of entries", + [NVME_SC_ABORT_LIMIT] = "Abort Command Limit Exceeded: The number of concurrently outstanding Abort commands has exceeded the limit indicated in the Identify Controller data structure", + [NVME_SC_ASYNC_LIMIT] = "Asynchronous Event Request Limit Exceeded: The number of concurrently outstanding Asynchronous Event Request commands has been exceeded", + [NVME_SC_FIRMWARE_SLOT] = "Invalid Firmware Slot: The firmware slot indicated is invalid or read only", + [NVME_SC_FIRMWARE_IMAGE] = "Invalid Firmware Image: The firmware image specified for activation is invalid and not loaded by the controller", + [NVME_SC_INVALID_VECTOR] = "Invalid Interrupt Vector: The creation of the I/O Completion Queue failed due to an invalid interrupt vector specified as part of the command", + [NVME_SC_INVALID_LOG_PAGE] = "Invalid Log Page: The log page indicated is invalid", + [NVME_SC_INVALID_FORMAT] = "Invalid Format: The LBA Format specified is not supported", + [NVME_SC_FW_NEEDS_CONV_RESET] = "Firmware Activation Requires Conventional Reset: The firmware commit was successful, however, activation of the firmware image requires a conventional reset", + [NVME_SC_INVALID_QUEUE] = "Invalid Queue Deletion: Invalid I/O Completion Queue specified to delete", + [NVME_SC_FEATURE_NOT_SAVEABLE] = "Feature Identifier Not Saveable: The Feature Identifier specified does not support a saveable value", + [NVME_SC_FEATURE_NOT_CHANGEABLE] = "Feature Not Changeable: The Feature Identifier is not able to be changed", + [NVME_SC_FEATURE_NOT_PER_NS] = "Feature Not Namespace Specific: The Feature Identifier specified is not namespace specific", + [NVME_SC_FW_NEEDS_SUBSYS_RESET] = "Firmware Activation Requires NVM Subsystem Reset: The firmware commit was successful, however, activation of the firmware image requires an NVM Subsystem", + [NVME_SC_FW_NEEDS_RESET] = "Firmware Activation Requires Controller Level Reset: The firmware commit was successful; however, the image specified does not support being activated without a reset", + [NVME_SC_FW_NEEDS_MAX_TIME] = "Firmware Activation Requires Maximum Time Violation: The image specified if activated immediately would exceed the Maximum Time for Firmware Activation (MTFA) value reported in Identify Controller", + [NVME_SC_FW_ACTIVATE_PROHIBITED] = "Firmware Activation Prohibited: The image specified is being prohibited from activation by the controller for vendor specific reasons", + [NVME_SC_OVERLAPPING_RANGE] = "Overlapping Range: The downloaded firmware image has overlapping ranges", + [NVME_SC_NS_INSUFFICIENT_CAP] = "Namespace Insufficient Capacity: Creating the namespace requires more free space than is currently available", + [NVME_SC_NS_ID_UNAVAILABLE] = "Namespace Identifier Unavailable: The number of namespaces supported has been exceeded", + [NVME_SC_NS_ALREADY_ATTACHED] = "Namespace Already Attached: The controller is already attached to the namespace specified", + [NVME_SC_NS_IS_PRIVATE] = "Namespace Is Private: The namespace is private and is already attached to one controller", + [NVME_SC_NS_NOT_ATTACHED] = "Namespace Not Attached: The request to detach the controller could not be completed because the controller is not attached to the namespace", + [NVME_SC_THIN_PROV_NOT_SUPP] = "Thin Provisioning Not Supported: Thin provisioning is not supported by the controller", + [NVME_SC_CTRL_LIST_INVALID] = "Controller List Invalid: The controller list provided contains invalid controller ids", + [NVME_SC_SELF_TEST_IN_PROGRESS] = "Device Self-test In Progress", + [NVME_SC_BP_WRITE_PROHIBITED] = "Boot Partition Write Prohibited: The command tried to modify a locked Boot Partition", + [NVME_SC_INVALID_CTRL_ID] = "Invalid Controller Identifier: An invalid controller id was specified", + [NVME_SC_INVALID_SEC_CTRL_STATE] = "Invalid Secondary Controller State: The requested secondary controller action is invalid based on the secondary and primary controllers current states", + [NVME_SC_INVALID_CTRL_RESOURCES] = "Invalid Number of Controller Resources: The specified number of Flexible Resources is invalid", + [NVME_SC_INVALID_RESOURCE_ID] = "Invalid Resource Identifier: At least one of the specified resource identifiers was invalid", + [NVME_SC_PMR_SAN_PROHIBITED] = "Sanitize Prohibited While Persistent Memory Region is Enabled", + [NVME_SC_ANA_GROUP_ID_INVALID] = "ANA Group Identifier Invalid", + [NVME_SC_ANA_ATTACH_FAILED] = "ANA Attach Failed: The command's specified ANA Group Identifier is not supported", +}; + +static const char * const nvm_status[] = { + [NVME_SC_BAD_ATTRIBUTES] = "Conflicting Attributes: The attributes specified in the command are conflicting", + [NVME_SC_INVALID_PI] = "Invalid Protection Information: The command's Protection Information Field settings are invalid for the namespace's Protection Information format", + [NVME_SC_READ_ONLY] = "Attempted Write to Read Only Range: The LBA range specified contains read-only blocks", +}; + +static const char * const nvmf_status[] = { + [NVME_SC_CONNECT_FORMAT] = "Incompatible Format: The NVM subsystem does not support the record format specified by the host", + [NVME_SC_CONNECT_CTRL_BUSY] = "Controller Busy: The controller is already associated with a host", + [NVME_SC_CONNECT_INVALID_PARAM] = "Connect Invalid Parameters: One or more of the command parameters", + [NVME_SC_CONNECT_RESTART_DISC] = "Connect Restart Discovery: The NVM subsystem requested is not available", + [NVME_SC_CONNECT_INVALID_HOST] = "Connect Invalid Host: The host is not allowed to establish an association to either any controller in the NVM subsystem or the specified controller", + [NVME_SC_DISCONNECT_INVALID_QTYPE] = "Invalid Queue Type: The command was sent on the wrong queue type", + [NVME_SC_DISCOVERY_RESTART] = "Discover Restart: The snapshot of the records is now invalid or out of date", + [NVME_SC_AUTH_REQUIRED] = "Authentication Required: NVMe in-band authentication is required and the queue has not yet been authenticated", +}; + +static const char * const media_status[] = { + [NVME_SC_WRITE_FAULT] = "Write Fault: The write data could not be committed to the media", + [NVME_SC_READ_ERROR] = "Unrecovered Read Error: The read data could not be recovered from the media", + [NVME_SC_GUARD_CHECK] = "End-to-end Guard Check Error: The command was aborted due to an end-to-end guard check failure", + [NVME_SC_APPTAG_CHECK] = "End-to-end Application Tag Check Error: The command was aborted due to an end-to-end application tag check failure", + [NVME_SC_REFTAG_CHECK] = "End-to-end Reference Tag Check Error: The command was aborted due to an end-to-end reference tag check failure", + [NVME_SC_COMPARE_FAILED] = "Compare Failure: The command failed due to a miscompare during a Compare command", + [NVME_SC_ACCESS_DENIED] = "Access Denied: Access to the namespace and/or LBA range is denied due to lack of access rights", + [NVME_SC_UNWRITTEN_BLOCK] = "Deallocated or Unwritten Logical Block: The command failed due to an attempt to read from or verify an LBA range containing a deallocated or unwritten logical block", +}; + +static const char * const path_status[] = { + [NVME_SC_ANA_INTERNAL_PATH_ERROR] = "Internal Path Error: An internal error specific to the controller processing the commmand prevented completion", + [NVME_SC_ANA_PERSISTENT_LOSS] = "Asymmetric Access Persistent Loss: The controller is in a persistent loss state with the requested namespace", + [NVME_SC_ANA_INACCESSIBLE] = "Asymmetric Access Inaccessible: The controller is in an inaccessible state with the requested namespace", + [NVME_SC_ANA_TRANSITION] = "Asymmetric Access Transition: The controller is currently transitioning states with the requested namespace", + [NVME_SC_CTRL_PATH_ERROR] = "Controller Pathing Error: A pathing error was detected by the controller", + [NVME_SC_HOST_PATH_ERROR] = "Host Pathing Error: A pathing error was detected by the host", + [NVME_SC_CMD_ABORTED_BY_HOST] = "Command Aborted By Host: The command was aborted as a result of host action", +}; + +#define ARGSTR(s, i) arg_str(s, ARRAY_SIZE(s), i) + +static const char *arg_str(const char * const *strings, + size_t array_size, size_t idx) +{ + if (idx < array_size && strings[idx]) + return strings[idx]; + return "unrecognized"; +} + const char *nvme_status_to_string(__u16 status) { - switch (status & 0x7ff) { - case NVME_SC_SUCCESS: - return "SUCCESS: The command completed successfully"; - case NVME_SC_INVALID_OPCODE: - return "INVALID_OPCODE: The associated command opcode field is not valid"; - case NVME_SC_INVALID_FIELD: - return "INVALID_FIELD: A reserved coded value or an unsupported value in a defined field"; - case NVME_SC_CMDID_CONFLICT: - return "CMDID_CONFLICT: The command identifier is already in use"; - case NVME_SC_DATA_XFER_ERROR: - return "DATA_XFER_ERROR: Error while trying to transfer the data or metadata"; - case NVME_SC_POWER_LOSS: - return "POWER_LOSS: Command aborted due to power loss notification"; - case NVME_SC_INTERNAL: - return "INTERNAL: The command was not completed successfully due to an internal error"; - case NVME_SC_ABORT_REQ: - return "ABORT_REQ: The command was aborted due to a Command Abort request"; - case NVME_SC_ABORT_QUEUE: - return "ABORT_QUEUE: The command was aborted due to a Delete I/O Submission Queue request"; - case NVME_SC_FUSED_FAIL: - return "FUSED_FAIL: The command was aborted due to the other command in a fused operation failing"; - case NVME_SC_FUSED_MISSING: - return "FUSED_MISSING: The command was aborted due to a Missing Fused Command"; - case NVME_SC_INVALID_NS: - return "INVALID_NS: The namespace or the format of that namespace is invalid"; - case NVME_SC_CMD_SEQ_ERROR: - return "CMD_SEQ_ERROR: The command was aborted due to a protocol violation in a multicommand sequence"; - case NVME_SC_SGL_INVALID_LAST: - return "SGL_INVALID_LAST: The command includes an invalid SGL Last Segment or SGL Segment descriptor."; - case NVME_SC_SGL_INVALID_COUNT: - return "SGL_INVALID_COUNT: There is an SGL Last Segment descriptor or an SGL Segment descriptor in a location other than the last descriptor of a segment based on the length indicated."; - case NVME_SC_SGL_INVALID_DATA: - return "SGL_INVALID_DATA: This may occur if the length of a Data SGL is too short."; - case NVME_SC_SGL_INVALID_METADATA: - return "SGL_INVALID_METADATA: This may occur if the length of a Metadata SGL is too short"; - case NVME_SC_SGL_INVALID_TYPE: - return "SGL_INVALID_TYPE: The type of an SGL Descriptor is a type that is not supported by the controller."; - case NVME_SC_CMB_INVALID_USE: - return "CMB_INVALID_USE: The attempted use of the Controller Memory Buffer is not supported by the controller."; - case NVME_SC_PRP_INVALID_OFFSET: - return "PRP_INVALID_OFFSET: The Offset field for a PRP entry is invalid."; - case NVME_SC_ATOMIC_WRITE_UNIT_EXCEEDED: - return "ATOMIC_WRITE_UNIT_EXCEEDED: The length specified exceeds the atomic write unit size."; - case NVME_SC_OPERATION_DENIED: - return "OPERATION_DENIED: The command was denied due to lack of access rights."; - case NVME_SC_SGL_INVALID_OFFSET: - return "SGL_INVALID_OFFSET: The offset specified in a descriptor is invalid."; - case NVME_SC_INCONSISTENT_HOST_ID: - return "INCONSISTENT_HOST_ID: The NVM subsystem detected the simultaneous use of 64-bit and 128-bit Host Identifier values on different controllers."; - case NVME_SC_KEEP_ALIVE_EXPIRED: - return "KEEP_ALIVE_EXPIRED: The Keep Alive Timer expired."; - case NVME_SC_KEEP_ALIVE_INVALID: - return "KEEP_ALIVE_INVALID: The Keep Alive Timeout value specified is invalid."; - case NVME_SC_PREEMPT_ABORT: - return "PREEMPT_ABORT: The command was aborted due to a Reservation Acquire command with the Reservation Acquire Action (RACQA) set to 010b (Preempt and Abort)."; - case NVME_SC_SANITIZE_FAILED: - return "SANITIZE_FAILED: The most recent sanitize operation failed and no recovery actions has been successfully completed"; - case NVME_SC_SANITIZE_IN_PROGRESS: - return "SANITIZE_IN_PROGRESS: The requested function is prohibited while a sanitize operation is in progress"; - case NVME_SC_IOCS_NOT_SUPPORTED: - return "IOCS_NOT_SUPPORTED: The I/O command set is not supported"; - case NVME_SC_IOCS_NOT_ENABLED: - return "IOCS_NOT_ENABLED: The I/O command set is not enabled"; - case NVME_SC_IOCS_COMBINATION_REJECTED: - return "IOCS_COMBINATION_REJECTED: The I/O command set combination is rejected"; - case NVME_SC_INVALID_IOCS: - return "INVALID_IOCS: the I/O command set is invalid"; - case NVME_SC_LBA_RANGE: - return "LBA_RANGE: The command references a LBA that exceeds the size of the namespace"; - case NVME_SC_NS_WRITE_PROTECTED: - return "NS_WRITE_PROTECTED: The command is prohibited while the namespace is write protected by the host."; - case NVME_SC_TRANSIENT_TRANSPORT: - return "TRANSIENT_TRANSPORT: A transient transport error was detected."; - case NVME_SC_CAP_EXCEEDED: - return "CAP_EXCEEDED: The execution of the command has caused the capacity of the namespace to be exceeded"; - case NVME_SC_NS_NOT_READY: - return "NS_NOT_READY: The namespace is not ready to be accessed as a result of a condition other than a condition that is reported as an Asymmetric Namespace Access condition"; - case NVME_SC_RESERVATION_CONFLICT: - return "RESERVATION_CONFLICT: The command was aborted due to a conflict with a reservation held on the accessed namespace"; - case NVME_SC_FORMAT_IN_PROGRESS: - return "FORMAT_IN_PROGRESS: A Format NVM command is in progress on the namespace."; - case NVME_SC_ZONE_BOUNDARY_ERROR: - return "ZONE_BOUNDARY_ERROR: Invalid Zone Boundary crossing"; - case NVME_SC_ZONE_IS_FULL: - return "ZONE_IS_FULL: The accessed zone is in ZSF:Full state"; - case NVME_SC_ZONE_IS_READ_ONLY: - return "ZONE_IS_READ_ONLY: The accessed zone is in ZSRO:Read Only state"; - case NVME_SC_ZONE_IS_OFFLINE: - return "ZONE_IS_OFFLINE: The access zone is in ZSO:Offline state"; - case NVME_SC_ZONE_INVALID_WRITE: - return "ZONE_INVALID_WRITE: The write to zone was not at the write pointer offset"; - case NVME_SC_TOO_MANY_ACTIVE_ZONES: - return "TOO_MANY_ACTIVE_ZONES: The controller does not allow additional active zones"; - case NVME_SC_TOO_MANY_OPEN_ZONES: - return "TOO_MANY_OPEN_ZONES: The controller does not allow additional open zones"; - case NVME_SC_ZONE_INVALID_STATE_TRANSITION: - return "INVALID_ZONE_STATE_TRANSITION: The zone state change was invalid"; - case NVME_SC_CQ_INVALID: - return "CQ_INVALID: The Completion Queue identifier specified in the command does not exist"; - case NVME_SC_QID_INVALID: - return "QID_INVALID: The creation of the I/O Completion Queue failed due to an invalid queue identifier specified as part of the command. An invalid queue identifier is one that is currently in use or one that is outside the range supported by the controller"; - case NVME_SC_QUEUE_SIZE: - return "QUEUE_SIZE: The host attempted to create an I/O Completion Queue with an invalid number of entries"; - case NVME_SC_ABORT_LIMIT: - return "ABORT_LIMIT: The number of concurrently outstanding Abort commands has exceeded the limit indicated in the Identify Controller data structure"; - case NVME_SC_ABORT_MISSING: - return "ABORT_MISSING: The abort command is missing"; - case NVME_SC_ASYNC_LIMIT: - return "ASYNC_LIMIT: The number of concurrently outstanding Asynchronous Event Request commands has been exceeded"; - case NVME_SC_FIRMWARE_SLOT: - return "FIRMWARE_SLOT: The firmware slot indicated is invalid or read only. This error is indicated if the firmware slot exceeds the number supported"; - case NVME_SC_FIRMWARE_IMAGE: - return "FIRMWARE_IMAGE: The firmware image specified for activation is invalid and not loaded by the controller"; - case NVME_SC_INVALID_VECTOR: - return "INVALID_VECTOR: The creation of the I/O Completion Queue failed due to an invalid interrupt vector specified as part of the command"; - case NVME_SC_INVALID_LOG_PAGE: - return "INVALID_LOG_PAGE: The log page indicated is invalid. This error condition is also returned if a reserved log page is requested"; - case NVME_SC_INVALID_FORMAT: - return "INVALID_FORMAT: The LBA Format specified is not supported. This may be due to various conditions"; - case NVME_SC_FW_NEEDS_CONV_RESET: - return "FW_NEEDS_CONVENTIONAL_RESET: The firmware commit was successful, however, activation of the firmware image requires a conventional reset"; - case NVME_SC_INVALID_QUEUE: - return "INVALID_QUEUE: This error indicates that it is invalid to delete the I/O Completion Queue specified. The typical reason for this error condition is that there is an associated I/O Submission Queue that has not been deleted."; - case NVME_SC_FEATURE_NOT_SAVEABLE: - return "FEATURE_NOT_SAVEABLE: The Feature Identifier specified does not support a saveable value"; - case NVME_SC_FEATURE_NOT_CHANGEABLE: - return "FEATURE_NOT_CHANGEABLE: The Feature Identifier is not able to be changed"; - case NVME_SC_FEATURE_NOT_PER_NS: - return "FEATURE_NOT_PER_NS: The Feature Identifier specified is not namespace specific. The Feature Identifier settings apply across all namespaces"; - case NVME_SC_FW_NEEDS_SUBSYS_RESET: - return "FW_NEEDS_SUBSYSTEM_RESET: The firmware commit was successful, however, activation of the firmware image requires an NVM Subsystem"; - case NVME_SC_FW_NEEDS_RESET: - return "FW_NEEDS_RESET: The firmware commit was successful; however, the image specified does not support being activated without a reset"; - case NVME_SC_FW_NEEDS_MAX_TIME: - return "FW_NEEDS_MAX_TIME_VIOLATION: The image specified if activated immediately would exceed the Maximum Time for Firmware Activation (MTFA) value reported in Identify Controller. To activate the firmware, the Firmware Commit command needs to be re-issued and the image activated using a reset"; - case NVME_SC_FW_ACTIVATE_PROHIBITED: - return "FW_ACTIVATION_PROHIBITED: The image specified is being prohibited from activation by the controller for vendor specific reasons"; - case NVME_SC_OVERLAPPING_RANGE: - return "OVERLAPPING_RANGE: This error is indicated if the firmware image has overlapping ranges"; - case NVME_SC_NS_INSUFFICIENT_CAP: - return "NS_INSUFFICIENT_CAPACITY: Creating the namespace requires more free space than is currently available. The Command Specific Information field of the Error Information Log specifies the total amount of NVM capacity required to create the namespace in bytes"; - case NVME_SC_NS_ID_UNAVAILABLE: - return "NS_ID_UNAVAILABLE: The number of namespaces supported has been exceeded"; - case NVME_SC_NS_ALREADY_ATTACHED: - return "NS_ALREADY_ATTACHED: The controller is already attached to the namespace specified"; - case NVME_SC_NS_IS_PRIVATE: - return "NS_IS_PRIVATE: The namespace is private and is already attached to one controller"; - case NVME_SC_NS_NOT_ATTACHED: - return "NS_NOT_ATTACHED: The request to detach the controller could not be completed because the controller is not attached to the namespace"; - case NVME_SC_THIN_PROV_NOT_SUPP: - return "THIN_PROVISIONING_NOT_SUPPORTED: Thin provisioning is not supported by the controller"; - case NVME_SC_CTRL_LIST_INVALID: - return "CONTROLLER_LIST_INVALID: The controller list provided is invalid"; - case NVME_SC_DEVICE_SELF_TEST_IN_PROGRESS: - return "DEVICE_SELF_TEST_IN_PROGRESS: The controller or NVM subsystem already has a device self-test operation in process."; - case NVME_SC_BP_WRITE_PROHIBITED: - return "BOOT PARTITION WRITE PROHIBITED: The command is trying to modify a Boot Partition while it is locked"; - case NVME_SC_INVALID_CTRL_ID: - return "INVALID_CTRL_ID: An invalid Controller Identifier was specified."; - case NVME_SC_INVALID_SECONDARY_CTRL_STATE: - return "INVALID_SECONDARY_CTRL_STATE: The action requested for the secondary controller is invalid based on the current state of the secondary controller and its primary controller."; - case NVME_SC_INVALID_NUM_CTRL_RESOURCE: - return "INVALID_NUM_CTRL_RESOURCE: The specified number of Flexible Resources is invalid"; - case NVME_SC_INVALID_RESOURCE_ID: - return "INVALID_RESOURCE_ID: At least one of the specified resource identifiers was invalid"; - case NVME_SC_ANA_INVALID_GROUP_ID: - return "ANA_INVALID_GROUP_ID: The specified ANA Group Identifier (ANAGRPID) is not supported in the submitted command."; - case NVME_SC_ANA_ATTACH_FAIL: - return "ANA_ATTACH_FAIL: The controller is not attached to the namespace as a result of an ANA condition"; - case NVME_SC_BAD_ATTRIBUTES: - return "BAD_ATTRIBUTES: Bad attributes were given"; - case NVME_SC_INVALID_PI: - return "INVALID_PROTECION_INFO: The Protection Information Field settings specified in the command are invalid"; - case NVME_SC_READ_ONLY: - return "WRITE_ATTEMPT_READ_ONLY_RANGE: The LBA range specified contains read-only blocks"; - case NVME_SC_CMD_SIZE_LIMIT_EXCEEDED: - return "CMD_SIZE_LIMIT_EXCEEDED: Command size limit exceeded"; - case NVME_SC_WRITE_FAULT: - return "WRITE_FAULT: The write data could not be committed to the media"; - case NVME_SC_READ_ERROR: - return "READ_ERROR: The read data could not be recovered from the media"; - case NVME_SC_GUARD_CHECK: - return "GUARD_CHECK: The command was aborted due to an end-to-end guard check failure"; - case NVME_SC_APPTAG_CHECK: - return "APPTAG_CHECK: The command was aborted due to an end-to-end application tag check failure"; - case NVME_SC_REFTAG_CHECK: - return "REFTAG_CHECK: The command was aborted due to an end-to-end reference tag check failure"; - case NVME_SC_COMPARE_FAILED: - return "COMPARE_FAILED: The command failed due to a miscompare during a Compare command"; - case NVME_SC_ACCESS_DENIED: - return "ACCESS_DENIED: Access to the namespace and/or LBA range is denied due to lack of access rights"; - case NVME_SC_UNWRITTEN_BLOCK: - return "UNWRITTEN_BLOCK: The command failed due to an attempt to read from an LBA range containing a deallocated or unwritten logical block"; - case NVME_SC_INTERNAL_PATH_ERROR: - return "INTERNAL_PATH_ERROT: The command was not completed as the result of a controller internal error"; - case NVME_SC_ANA_PERSISTENT_LOSS: - return "ASYMMETRIC_NAMESPACE_ACCESS_PERSISTENT_LOSS: The requested function (e.g., command) is not able to be performed as a result of the relationship between the controller and the namespace being in the ANA Persistent Loss state"; - case NVME_SC_ANA_INACCESSIBLE: - return "ASYMMETRIC_NAMESPACE_ACCESS_INACCESSIBLE: The requested function (e.g., command) is not able to be performed as a result of the relationship between the controller and the namespace being in the ANA Inaccessible state"; - case NVME_SC_ANA_TRANSITION: - return "ASYMMETRIC_NAMESPACE_ACCESS_TRANSITION: The requested function (e.g., command) is not able to be performed as a result of the relationship between the controller and the namespace transitioning between Asymmetric Namespace Access states"; - case NVME_SC_CTRL_PATHING_ERROR: - return "CONTROLLER_PATHING_ERROR: A pathing error was detected by the controller"; - case NVME_SC_HOST_PATHING_ERROR: - return "HOST_PATHING_ERROR: A pathing error was detected by the host"; - case NVME_SC_HOST_CMD_ABORT: - return "HOST_COMMAND_ABORT: The command was aborted as a result of host action"; - case NVME_SC_CMD_INTERRUPTED: - return "CMD_INTERRUPTED: Command processing was interrupted and the controller is unable to successfully complete the command. The host should retry the command."; - case NVME_SC_PMR_SAN_PROHIBITED: - return "Sanitize Prohibited While Persistent Memory Region is Enabled: A sanitize operation is prohibited while the Persistent Memory Region is enabled."; + const char *s = "Unknown status"; + __u16 sc, sct; + bool fabrics = false; /* make this a parameter */ + + if (status < 0) + return strerror(errno); + + sc = nvme_status_code(status); + sct = nvme_status_code_type(status); + + switch (sct) { + case NVME_SCT_GENERIC: + s = ARGSTR(generic_status, sc); + break; + case NVME_SCT_CMD_SPECIFIC: + if (sc < ARRAY_SIZE(cmd_spec_status)) + s = ARGSTR(cmd_spec_status, sc); + else if (fabrics) + s = ARGSTR(nvmf_status, sc); + else + s = ARGSTR(nvm_status, sc); + break; + case NVME_SCT_MEDIA: + s = ARGSTR(media_status, sc); + break; + case NVME_SCT_PATH: + s = ARGSTR(path_status, sc); + break; + case NVME_SCT_VS: + s = "Vendor Specific Status"; + break; default: - return "Unknown"; + break; } + + return s; } static const char *nvme_feature_lba_type_to_string(__u8 type) @@ -5563,20 +5370,20 @@ void nvme_show_lba_range(struct nvme_lba_range_type *lbrt, int nr_ranges) int i, j; for (i = 0; i <= nr_ranges; i++) { - printf("\ttype : %#x - %s\n", lbrt[i].type, - nvme_feature_lba_type_to_string(lbrt[i].type)); - printf("\tattributes : %#x - %s, %s\n", lbrt[i].attributes, - (lbrt[i].attributes & 0x0001) ? + printf("\ttype : %#x - %s\n", lbrt->entry[i].type, + nvme_feature_lba_type_to_string(lbrt->entry[i].type)); + printf("\tattributes : %#x - %s, %s\n", lbrt->entry[i].attributes, + (lbrt->entry[i].attributes & 0x0001) ? "LBA range may be overwritten" : "LBA range should not be overwritten", - ((lbrt[i].attributes & 0x0002) >> 1) ? + ((lbrt->entry[i].attributes & 0x0002) >> 1) ? "LBA range should be hidden from the OS/EFI/BIOS" : "LBA range should be visible from the OS/EFI/BIOS"); - printf("\tslba : %#"PRIx64"\n", (uint64_t)(lbrt[i].slba)); - printf("\tnlb : %#"PRIx64"\n", (uint64_t)(lbrt[i].nlb)); + printf("\tslba : %#"PRIx64"\n", (uint64_t)(lbrt->entry[i].slba)); + printf("\tnlb : %#"PRIx64"\n", (uint64_t)(lbrt->entry[i].nlb)); printf("\tguid : "); for (j = 0; j < 16; j++) - printf("%02x", lbrt[i].guid[j]); + printf("%02x", lbrt->entry[i].guid[j]); printf("\n"); } } @@ -5617,19 +5424,22 @@ static const char *nvme_feature_temp_sel_to_string(__u8 sel) } } -static void nvme_show_auto_pst(struct nvme_auto_pst *apst) +static void nvme_show_auto_pst(struct nvme_feat_auto_pst *apst) { int i; + __u64 value; printf( "\tAuto PST Entries"); printf("\t.................\n"); for (i = 0; i < 32; i++) { + value = le64_to_cpu(apst->apst_entry[i]); + printf("\tEntry[%2d] \n", i); printf("\t.................\n"); printf("\tIdle Time Prior to Transition (ITPT): %u ms\n", - (apst[i].data & 0xffffff00) >> 8); + (__u32)(value >> NVME_APST_ENTRY_ITPT_SHIFT) & NVME_APST_ENTRY_ITPT_MASK); printf("\tIdle Transition Power State (ITPS): %u\n", - (apst[i].data & 0x000000f8) >> 3); + (__u32)(value >> NVME_APST_ENTRY_ITPS_SHIFT ) & NVME_APST_ENTRY_ITPS_MASK); printf("\t.................\n"); } } @@ -5657,7 +5467,7 @@ static void nvme_show_timestamp(struct nvme_timestamp *ts) "continuously since the Timestamp value was initialized."); } -static void nvme_show_host_mem_buffer(struct nvme_host_mem_buffer *hmb) +static void nvme_show_host_mem_buffer(struct nvme_host_mem_buf_attrs *hmb) { printf("\tHost Memory Descriptor List Entry Count (HMDLEC): %u\n", le32_to_cpu(hmb->hmdlec)); @@ -5669,16 +5479,16 @@ static void nvme_show_host_mem_buffer(struct nvme_host_mem_buffer *hmb) le32_to_cpu(hmb->hsize)); } -static const char *nvme_show_ns_write_protect_config(__u8 state) +static const char *nvme_show_ns_wp_cfg(enum nvme_ns_write_protect_cfg state) { switch (state) { - case NVME_NS_NO_WRITE_PROTECT: + case NVME_NS_WP_CFG_NONE: return "No Write Protect"; - case NVME_NS_WRITE_PROTECT: + case NVME_NS_WP_CFG_PROTECT: return "Write Protect"; - case NVME_NS_WRITE_PROTECT_POWER_CYCLE: + case NVME_NS_WP_CFG_PROTECT_POWER_CYCLE: return "Write Protect Until Power Cycle"; - case NVME_NS_WRITE_PROTECT_PERMANENT: + case NVME_NS_WP_CFG_PROTECT_PERMANENT: return "Permanent Write Protect"; default: return "Reserved"; @@ -5692,9 +5502,9 @@ static void nvme_directive_show_fields(__u8 dtype, __u8 doper, int count, i; switch (dtype) { - case NVME_DIR_IDENTIFY: + case NVME_DIRECTIVE_DTYPE_IDENTIFY: switch (doper) { - case NVME_DIR_RCV_ID_OP_PARAM: + case NVME_DIRECTIVE_RECEIVE_IDENTIFY_DOPER_PARAM: printf("\tDirective support \n"); printf("\t\tIdentify Directive : %s\n", (*field & 0x1) ? "supported":"not supported"); @@ -5711,9 +5521,9 @@ static void nvme_directive_show_fields(__u8 dtype, __u8 doper, "invalid directive operations for Identify Directives\n"); } break; - case NVME_DIR_STREAMS: + case NVME_DIRECTIVE_DTYPE_STREAMS: switch (doper) { - case NVME_DIR_RCV_ST_OP_PARAM: + case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM: printf("\tMax Streams Limit (MSL): %u\n", *(__u16 *) field); printf("\tNVM Subsystem Streams Available (NSSA): %u\n", @@ -5731,7 +5541,7 @@ static void nvme_directive_show_fields(__u8 dtype, __u8 doper, printf("\tNamespace Streams Open (NSO): %u\n", *(__u16 *) (field + 24)); break; - case NVME_DIR_RCV_ST_OP_STATUS: + case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_STATUS: count = *(__u16 *) field; printf("\tOpen Stream Count : %u\n", *(__u16 *) field); for ( i = 0; i < count; i++ ) { @@ -5739,7 +5549,7 @@ static void nvme_directive_show_fields(__u8 dtype, __u8 doper, *(__u16 *) (field + ((i + 1) * 2))); } break; - case NVME_DIR_RCV_ST_OP_RESOURCE: + case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_RESOURCE: printf("\tNamespace Streams Allocated (NSA): %u\n", result & 0xffff); break; @@ -5786,29 +5596,25 @@ static const char *nvme_plm_window(__u32 plm) void nvme_show_lba_status_info(__u32 result) { - printf("\tLBA Status Information Poll Interval (LSIPI) : %u\n", (result >> 16) & 0xffff); + printf("\tLBA Status Information Poll Interval (LSIPI) : %u\n", (result >> 16) & 0xffff); printf("\tLBA Status Information Report Interval (LSIRI): %u\n", result & 0xffff); } static void nvme_show_plm_config(struct nvme_plm_config *plmcfg) { - printf("\tEnable Event :%04x\n", le16_to_cpu(plmcfg->enable_event)); - printf("\tDTWIN Reads Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwin_reads_thresh)); - printf("\tDTWIN Writes Threshold:%"PRIu64"\n", le64_to_cpu(plmcfg->dtwin_writes_thresh)); - printf("\tDTWIN Time Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwin_time_thresh)); + printf("\tEnable Event :%04x\n", le16_to_cpu(plmcfg->ee)); + printf("\tDTWIN Reads Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwinrt)); + printf("\tDTWIN Writes Threshold:%"PRIu64"\n", le64_to_cpu(plmcfg->dtwinwt)); + printf("\tDTWIN Time Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwintt)); } -void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, - unsigned char *buf) +void nvme_feature_show_fields(enum nvme_features_id fid, unsigned int result, unsigned char *buf) { __u8 field; uint64_t ull; switch (fid) { - case NVME_FEAT_NONE: - printf("\tFeature Identifier Reserved\n"); - break; - case NVME_FEAT_ARBITRATION: + case NVME_FEAT_FID_ARBITRATION: printf("\tHigh Priority Weight (HPW): %u\n", ((result & 0xff000000) >> 24) + 1); printf("\tMedium Priority Weight (MPW): %u\n", ((result & 0x00ff0000) >> 16) + 1); printf("\tLow Priority Weight (LPW): %u\n", ((result & 0x0000ff00) >> 8) + 1); @@ -5818,126 +5624,144 @@ void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, else printf("%u\n", 1 << (result & 0x00000007)); break; - case NVME_FEAT_POWER_MGMT: + case NVME_FEAT_FID_POWER_MGMT: field = (result & 0x000000E0) >> 5; printf("\tWorkload Hint (WH): %u - %s\n", field, nvme_feature_wl_hints_to_string(field)); printf("\tPower State (PS): %u\n", result & 0x0000001f); break; - case NVME_FEAT_LBA_RANGE: + case NVME_FEAT_FID_LBA_RANGE: field = result & 0x0000003f; printf("\tNumber of LBA Ranges (NUM): %u\n", field + 1); nvme_show_lba_range((struct nvme_lba_range_type *)buf, field); break; - case NVME_FEAT_TEMP_THRESH: + case NVME_FEAT_FID_TEMP_THRESH: field = (result & 0x00300000) >> 20; - printf("\tThreshold Type Select (THSEL): %u - %s\n", field, nvme_feature_temp_type_to_string(field)); + printf("\tThreshold Type Select (THSEL): %u - %s\n", field, + nvme_feature_temp_type_to_string(field)); field = (result & 0x000f0000) >> 16; - printf("\tThreshold Temperature Select (TMPSEL): %u - %s\n", field, nvme_feature_temp_sel_to_string(field)); + printf("\tThreshold Temperature Select (TMPSEL): %u - %s\n", field, + nvme_feature_temp_sel_to_string(field)); printf("\tTemperature Threshold (TMPTH): %ld C (%u Kelvin)\n", kelvin_to_celsius(result & 0x0000ffff), result & 0x0000ffff); break; - case NVME_FEAT_ERR_RECOVERY: - printf("\tDeallocated or Unwritten Logical Block Error Enable (DULBE): %s\n", ((result & 0x00010000) >> 16) ? "Enabled":"Disabled"); - printf("\tTime Limited Error Recovery (TLER): %u ms\n", (result & 0x0000ffff) * 100); + case NVME_FEAT_FID_ERR_RECOVERY: + printf("\tDeallocated or Unwritten Logical Block Error Enable (DULBE): %s\n", + ((result & 0x00010000) >> 16) ? "Enabled":"Disabled"); + printf("\tTime Limited Error Recovery (TLER): %u ms\n", + (result & 0x0000ffff) * 100); break; - case NVME_FEAT_VOLATILE_WC: + case NVME_FEAT_FID_VOLATILE_WC: printf("\tVolatile Write Cache Enable (WCE): %s\n", (result & 0x00000001) ? "Enabled":"Disabled"); break; - case NVME_FEAT_NUM_QUEUES: + case NVME_FEAT_FID_NUM_QUEUES: printf("\tNumber of IO Completion Queues Allocated (NCQA): %u\n", ((result & 0xffff0000) >> 16) + 1); printf("\tNumber of IO Submission Queues Allocated (NSQA): %u\n", (result & 0x0000ffff) + 1); break; - case NVME_FEAT_IRQ_COALESCE: + case NVME_FEAT_FID_IRQ_COALESCE: printf("\tAggregation Time (TIME): %u usec\n", ((result & 0x0000ff00) >> 8) * 100); printf("\tAggregation Threshold (THR): %u\n", (result & 0x000000ff) + 1); break; - case NVME_FEAT_IRQ_CONFIG: + case NVME_FEAT_FID_IRQ_CONFIG: printf("\tCoalescing Disable (CD): %s\n", ((result & 0x00010000) >> 16) ? "True":"False"); printf("\tInterrupt Vector (IV): %u\n", result & 0x0000ffff); break; - case NVME_FEAT_WRITE_ATOMIC: + case NVME_FEAT_FID_WRITE_ATOMIC: printf("\tDisable Normal (DN): %s\n", (result & 0x00000001) ? "True":"False"); break; - case NVME_FEAT_ASYNC_EVENT: - printf("\tZone Descriptor Changed Notices: %s\n", ((result >> 27) & 0x1) ? "Send async event":"Do not send async event"); - printf("\tEndurance Group Event Aggregate Log Change Notices: %s\n", ((result & 0x00004000) >> 14) ? "Send async event":"Do not send async event"); - printf("\tLBA Status Information Notices : %s\n", ((result & 0x00002000) >> 13) ? "Send async event":"Do not send async event"); - printf("\tPredictable Latency Event Aggregate Log Change Notices: %s\n", ((result & 0x00001000) >> 12) ? "Send async event":"Do not send async event"); - printf("\tAsymmetric Namespace Access Change Notices: %s\n", ((result & 0x00000800) >> 11) ? "Send async event":"Do not send async event"); - printf("\tTelemetry Log Notices : %s\n", ((result & 0x00000400) >> 10) ? "Send async event":"Do not send async event"); - printf("\tFirmware Activation Notices : %s\n", ((result & 0x00000200) >> 9) ? "Send async event":"Do not send async event"); - printf("\tNamespace Attribute Notices : %s\n", ((result & 0x00000100) >> 8) ? "Send async event":"Do not send async event"); - printf("\tSMART / Health Critical Warnings: %s\n", (result & 0x000000ff) ? "Send async event":"Do not send async event"); + case NVME_FEAT_FID_ASYNC_EVENT: + printf("\tEndurance Group Event Aggregate Log Change Notices: %s\n", + ((result & 0x00004000) >> 14) ? "Send async event":"Do not send async event"); + printf("\tLBA Status Information Notices : %s\n", + ((result & 0x00002000) >> 13) ? "Send async event":"Do not send async event"); + printf("\tPredictable Latency Event Aggregate Log Change Notices: %s\n", + ((result & 0x00001000) >> 12) ? "Send async event":"Do not send async event"); + printf("\tAsymmetric Namespace Access Change Notices: %s\n", + ((result & 0x00000800) >> 11) ? "Send async event":"Do not send async event"); + printf("\tTelemetry Log Notices : %s\n", + ((result & 0x00000400) >> 10) ? "Send async event":"Do not send async event"); + printf("\tFirmware Activation Notices : %s\n", + ((result & 0x00000200) >> 9) ? "Send async event":"Do not send async event"); + printf("\tNamespace Attribute Notices : %s\n", + ((result & 0x00000100) >> 8) ? "Send async event":"Do not send async event"); + printf("\tSMART / Health Critical Warnings: %s\n", + (result & 0x000000ff) ? "Send async event":"Do not send async event"); break; - case NVME_FEAT_AUTO_PST: - printf("\tAutonomous Power State Transition Enable (APSTE): %s\n", (result & 0x00000001) ? "Enabled":"Disabled"); - nvme_show_auto_pst((struct nvme_auto_pst *)buf); + case NVME_FEAT_FID_AUTO_PST: + printf("\tAutonomous Power State Transition Enable (APSTE): %s\n", + (result & 0x00000001) ? "Enabled":"Disabled"); + nvme_show_auto_pst((struct nvme_feat_auto_pst *)buf); break; - case NVME_FEAT_HOST_MEM_BUF: + case NVME_FEAT_FID_HOST_MEM_BUF: printf("\tEnable Host Memory (EHM): %s\n", (result & 0x00000001) ? "Enabled":"Disabled"); - nvme_show_host_mem_buffer((struct nvme_host_mem_buffer *)buf); + nvme_show_host_mem_buffer((struct nvme_host_mem_buf_attrs *)buf); break; - case NVME_FEAT_SW_PROGRESS: + case NVME_FEAT_FID_SW_PROGRESS: printf("\tPre-boot Software Load Count (PBSLC): %u\n", result & 0x000000ff); break; - case NVME_FEAT_PLM_CONFIG: + case NVME_FEAT_FID_PLM_CONFIG: printf("\tPredictable Latency Window Enabled: %s\n", result & 0x1 ? "True":"False"); nvme_show_plm_config((struct nvme_plm_config *)buf); break; - case NVME_FEAT_PLM_WINDOW: + case NVME_FEAT_FID_PLM_WINDOW: printf("\tWindow Select: %s", nvme_plm_window(result)); break; - case NVME_LBA_STATUS_INFO: + case NVME_FEAT_FID_LBA_STS_INTERVAL: nvme_show_lba_status_info(result); break; - case NVME_FEAT_ENDURANCE: + case NVME_FEAT_FID_ENDURANCE_EVT_CFG: printf("\tEndurance Group Identifier (ENDGID): %u\n", result & 0xffff); printf("\tEndurance Group Critical Warnings : %u\n", (result >> 16) & 0xff); + break; + case NVME_FEAT_FID_IOCS_PROFILE: + printf("\tI/O Command Set Profile: %s\n", result & 0x1 ? "True":"False"); break; - case NVME_FEAT_IOCS_PROFILE: - printf("\tI/O Command Set Comination Index(IOCSCI): %u\n", result & 0x1ff); - break; - case NVME_FEAT_HOST_ID: + case NVME_FEAT_FID_HOST_ID: ull = buf[7]; ull <<= 8; ull |= buf[6]; ull <<= 8; ull |= buf[5]; ull <<= 8; ull |= buf[4]; ull <<= 8; ull |= buf[3]; ull <<= 8; ull |= buf[2]; ull <<= 8; ull |= buf[1]; ull <<= 8; ull |= buf[0]; printf("\tHost Identifier (HOSTID): %" PRIu64 "\n", ull); break; - case NVME_FEAT_RESV_MASK: - printf("\tMask Reservation Preempted Notification (RESPRE): %s\n", ((result & 0x00000008) >> 3) ? "True":"False"); - printf("\tMask Reservation Released Notification (RESREL): %s\n", ((result & 0x00000004) >> 2) ? "True":"False"); - printf("\tMask Registration Preempted Notification (REGPRE): %s\n", ((result & 0x00000002) >> 1) ? "True":"False"); + case NVME_FEAT_FID_RESV_MASK: + printf("\tMask Reservation Preempted Notification (RESPRE): %s\n", + ((result & 0x00000008) >> 3) ? "True":"False"); + printf("\tMask Reservation Released Notification (RESREL): %s\n", + ((result & 0x00000004) >> 2) ? "True":"False"); + printf("\tMask Registration Preempted Notification (REGPRE): %s\n", + ((result & 0x00000002) >> 1) ? "True":"False"); break; - case NVME_FEAT_RESV_PERSIST: + case NVME_FEAT_FID_RESV_PERSIST: printf("\tPersist Through Power Loss (PTPL): %s\n", (result & 0x00000001) ? "True":"False"); break; - case NVME_FEAT_WRITE_PROTECT: - printf("\tNamespace Write Protect state: %s\n", nvme_show_ns_write_protect_config(result & 0x7)); + case NVME_FEAT_FID_WRITE_PROTECT: + printf("\tNamespace Write Protect: %s\n", nvme_show_ns_wp_cfg(result)); break; - case NVME_FEAT_TIMESTAMP: + case NVME_FEAT_FID_TIMESTAMP: nvme_show_timestamp((struct nvme_timestamp *)buf); break; - case NVME_FEAT_HCTM: + case NVME_FEAT_FID_HCTM: printf("\tThermal Management Temperature 1 (TMT1) : %u Kelvin (%ld C)\n", result >> 16, kelvin_to_celsius(result >> 16)); printf("\tThermal Management Temperature 2 (TMT2) : %u Kelvin (%ld C)\n", result & 0x0000ffff, kelvin_to_celsius(result & 0x0000ffff)); break; - case NVME_FEAT_KATO: + case NVME_FEAT_FID_KATO: printf("\tKeep Alive Timeout (KATO) in milliseconds: %u\n", result); break; - case NVME_FEAT_NOPSC: - printf("\tNon-Operational Power State Permissive Mode Enable (NOPPME): %s\n", (result & 1) ? "True" : "False"); + case NVME_FEAT_FID_NOPSC: + printf("\tNon-Operational Power State Permissive Mode Enable (NOPPME): %s\n", + (result & 1) ? "True" : "False"); break; - case NVME_FEAT_HOST_BEHAVIOR: + case NVME_FEAT_FID_HOST_BEHAVIOR: printf("\tHost Behavior Support: %s\n", (buf[0] & 0x1) ? "True" : "False"); break; - case NVME_FEAT_SANITIZE: + case NVME_FEAT_FID_SANITIZE: printf("\tNo-Deallocate Response Mode (NODRM) : %u\n", result & 0x1); break; - case NVME_FEAT_RRL: + case NVME_FEAT_FID_RRL: printf("\tRead Recovery Level (RRL): %u\n", result & 0xf); break; + default: + break; } } @@ -5974,393 +5798,329 @@ void nvme_show_lba_status(struct nvme_lba_status *list, unsigned long len, } } -static void nvme_show_list_item(struct nvme_namespace *n) +static void nvme_show_list_item(nvme_ns_t n) { - long long lba = 1 << n->ns.lbaf[(n->ns.flbas & 0x0f)].ds; - double nsze = le64_to_cpu(n->ns.nsze) * lba; - double nuse = le64_to_cpu(n->ns.nuse) * lba; + char usage[128] = { 0 }, format[128] = { 0 }; + + long long lba = nvme_ns_get_lba_size(n); + double nsze = nvme_ns_get_lba_count(n) * lba; + double nuse = nvme_ns_get_lba_util(n) * lba; const char *s_suffix = suffix_si_get(&nsze); const char *u_suffix = suffix_si_get(&nuse); const char *l_suffix = suffix_binary_get(&lba); - char usage[128]; - char format[128], path[256]; - struct stat st; - int ret; + nvme_ctrl_t c = nvme_ns_get_ctrl(n); - sprintf(path, "%s%s", n->ctrl->path, n->name); - ret = stat(path, &st); - if (ret < 0) - return; + snprintf(usage, sizeof(usage), "%6.2f %2sB / %6.2f %2sB", nuse, + u_suffix, nsze, s_suffix); + snprintf(format, sizeof(format), "%3.0f %2sB + %2d B", (double)lba, + l_suffix, nvme_ns_get_meta_size(n)); - sprintf(usage,"%6.2f %2sB / %6.2f %2sB", nuse, u_suffix, - nsze, s_suffix); - sprintf(format,"%3.0f %2sB + %2d B", (double)lba, l_suffix, - le16_to_cpu(n->ns.lbaf[(n->ns.flbas & 0x0f)].ms)); - printf("%-21s %-*.*s %-*.*s %-9d %-26s %-16s %-.*s\n", path, - (int)sizeof(n->ctrl->id.sn), (int)sizeof(n->ctrl->id.sn), n->ctrl->id.sn, - (int)sizeof(n->ctrl->id.mn), (int)sizeof(n->ctrl->id.mn), n->ctrl->id.mn, - n->nsid, usage, format, (int)sizeof(n->ctrl->id.fr), n->ctrl->id.fr); + printf("%-21s %-20s %-40s %-9d %-26s %-16s %-8s\n", + nvme_ns_get_name(n), nvme_ctrl_get_serial(c), + nvme_ctrl_get_model(c), nvme_ns_get_nsid(n), usage, format, + nvme_ctrl_get_firmware(c)); } -static void nvme_show_simple_list(struct nvme_topology *t) +static void nvme_show_simple_list(nvme_root_t r) { - int i, j, k; + nvme_host_t h; + nvme_subsystem_t s; + nvme_ctrl_t c; + nvme_ns_t n; printf("%-21s %-20s %-40s %-9s %-26s %-16s %-8s\n", "Node", "SN", "Model", "Namespace", "Usage", "Format", "FW Rev"); printf("%-.21s %-.20s %-.40s %-.9s %-.26s %-.16s %-.8s\n", dash, dash, dash, dash, dash, dash, dash); - for (i = 0; i < t->nr_subsystems; i++) { - struct nvme_subsystem *s = &t->subsystems[i]; - - for (j = 0; j < s->nr_ctrls; j++) { - struct nvme_ctrl *c = &s->ctrls[j]; - - for (k = 0; k < c->nr_namespaces; k++) { - struct nvme_namespace *n = &c->namespaces[k]; + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + nvme_subsystem_for_each_ns(s, n) nvme_show_list_item(n); - } - } - for (j = 0; j < s->nr_namespaces; j++) { - struct nvme_namespace *n = &s->namespaces[j]; - nvme_show_list_item(n); + nvme_subsystem_for_each_ctrl(s, c) + nvme_ctrl_for_each_ns(c, n) + nvme_show_list_item(n); } } } -static void nvme_show_details_ns(struct nvme_namespace *n, bool ctrl) +static void nvme_show_ns_details(nvme_ns_t n) { - long long lba = 1 << n->ns.lbaf[(n->ns.flbas & 0x0f)].ds; - double nsze = le64_to_cpu(n->ns.nsze) * lba; - double nuse = le64_to_cpu(n->ns.nuse) * lba; + char usage[128] = { 0 }, format[128] = { 0 }; + + long long lba = nvme_ns_get_lba_size(n); + double nsze = nvme_ns_get_lba_count(n) * lba; + double nuse = nvme_ns_get_lba_util(n) * lba; const char *s_suffix = suffix_si_get(&nsze); const char *u_suffix = suffix_si_get(&nuse); const char *l_suffix = suffix_binary_get(&lba); - char usage[128]; - char format[128]; - - sprintf(usage,"%6.2f %2sB / %6.2f %2sB", nuse, u_suffix, - nsze, s_suffix); + sprintf(usage,"%6.2f %2sB / %6.2f %2sB", nuse, u_suffix, nsze, s_suffix); sprintf(format,"%3.0f %2sB + %2d B", (double)lba, l_suffix, - le16_to_cpu(n->ns.lbaf[(n->ns.flbas & 0x0f)].ms)); - - printf("%-12s %-8d %-26s %-16s ", n->name, n->nsid, usage, format); + nvme_ns_get_meta_size(n)); - if (ctrl) - printf("%s", n->ctrl->name); - else { - struct nvme_subsystem *s = n->ctrl->subsys; - int i, j; - bool comma = false; - - for (i = 0; i < s->nr_ctrls; i++) { - struct nvme_ctrl *c = &s->ctrls[i]; - - for (j = 0; j < c->nr_namespaces; j++) { - struct nvme_namespace *ns = &c->namespaces[j]; - - if (ns->nsid == n->nsid) { - printf("%s%s", comma ? ", " : "", - c->name); - comma = true; - } - } - } - } - printf("\n"); + printf("%-12s %-8x %-26s %-16s ", nvme_ns_get_name(n), + nvme_ns_get_nsid(n), usage, format); } -static void nvme_show_detailed_list(struct nvme_topology *t) +static void nvme_show_detailed_list(nvme_root_t r) { - int i, j, k; + nvme_host_t h; + nvme_subsystem_t s; + nvme_ctrl_t c; + nvme_path_t p; + nvme_ns_t n; - printf("NVM Express Subsystems\n\n"); printf("%-16s %-96s %-.16s\n", "Subsystem", "Subsystem-NQN", "Controllers"); printf("%-.16s %-.96s %-.16s\n", dash, dash, dash); - for (i = 0; i < t->nr_subsystems; i++) { - struct nvme_subsystem *s = &t->subsystems[i]; - printf("%-16s %-96s ", s->name, s->subsysnqn); - for (j = 0; j < s->nr_ctrls; j++) { - struct nvme_ctrl *c = &s->ctrls[j]; + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + bool first = true; + printf("%-16s %-96s ", nvme_subsystem_get_name(s), + nvme_subsystem_get_nqn(s)); - printf("%s%s", j ? ", " : "", c->name); + nvme_subsystem_for_each_ctrl(s, c) { + printf("%s%s", first ? "": ", ", + nvme_ctrl_get_name(c)); + first = false; + } + printf("\n"); } - printf("\n"); - }; + } + printf("\n"); - printf("\nNVM Express Controllers\n\n"); printf("%-8s %-20s %-40s %-8s %-6s %-14s %-12s %-16s\n", "Device", "SN", "MN", "FR", "TxPort", "Address", "Subsystem", "Namespaces"); printf("%-.8s %-.20s %-.40s %-.8s %-.6s %-.14s %-.12s %-.16s\n", dash, dash, dash, dash, dash, dash, dash, dash); - for (i = 0; i < t->nr_subsystems; i++) { - struct nvme_subsystem *s = &t->subsystems[i]; - - for (j = 0; j < s->nr_ctrls; j++) { - bool comma = false; - struct nvme_ctrl *c = &s->ctrls[j]; - printf("%-8s %-.20s %-.40s %-.8s %-6s %-14s %-12s ", - c->name, c->id.sn, c->id.mn, c->id.fr, - c->transport ? : "", c->address ? : "", s->name); - - for (k = 0; k < c->nr_namespaces; k++) { - struct nvme_namespace *n = &c->namespaces[k]; + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + nvme_subsystem_for_each_ctrl(s, c) { + bool first = true; + + printf("%-8s %-20s %-40s %-8s %-6s %-14s %-12s ", + nvme_ctrl_get_name(c), + nvme_ctrl_get_serial(c), + nvme_ctrl_get_model(c), + nvme_ctrl_get_firmware(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c), + nvme_subsystem_get_name(s)); + + nvme_ctrl_for_each_ns(c, n) { + printf("%s%s", first ? "": ", ", + nvme_ns_get_name(n)); + first = false; + } - printf("%s%s", comma ? ", " : "", n->name); - comma = true; + nvme_ctrl_for_each_path(c, p) { + printf("%s%s", first ? "": ", ", + nvme_ns_get_name(nvme_path_get_ns(p))); + first = false; + } + printf("\n"); } - printf("\n"); } } + printf("\n"); - printf("\nNVM Express Namespaces\n\n"); - printf("%-12s %-8s %-26s %-16s %-16s\n", "Device", "NSID", "Usage", "Format", "Controllers"); - printf("%-.12s %-.8s %-.26s %-.16s %-.16s\n", dash, dash, dash, dash, dash); - - for (i = 0; i < t->nr_subsystems; i++) { - struct nvme_subsystem *s = &t->subsystems[i]; - - if (s->nr_namespaces) { - for (j = 0; j < s->nr_namespaces; j++) { - struct nvme_namespace *n = &s->namespaces[j]; - nvme_show_details_ns(n, false); + printf("%-12s %-8s %-26s %-16s %-16s\n", "Device", "NSID", "Usage", + "Format", "Controllers"); + printf("%-.12s %-.8s %-.26s %-.16s %-.16s\n", dash, dash, dash, dash, + dash); + + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + nvme_subsystem_for_each_ctrl(s, c) { + nvme_ctrl_for_each_ns(c, n) { + nvme_show_ns_details(n); + printf("%s\n", nvme_ctrl_get_name(c)); + } } - } else { - for (j = 0; j < s->nr_ctrls; j++) { - struct nvme_ctrl *c = &s->ctrls[j]; - for (k = 0; k < c->nr_namespaces; k++) { - struct nvme_namespace *n = &c->namespaces[k]; - nvme_show_details_ns(n, true); + nvme_subsystem_for_each_ns(s, n) { + bool first = true; + + nvme_show_ns_details(n); + nvme_subsystem_for_each_ctrl(s, c) { + printf("%s%s", first ? "" : ", ", + nvme_ctrl_get_name(c)); + first = false; } + printf("\n"); } } } } -static void json_detail_ns(struct nvme_namespace *n, struct json_object *ns_attrs) +static void json_detail_list(nvme_root_t r) { - long long lba; - double nsze, nuse; + struct json_object *jroot = json_create_object(); + struct json_object *jsslist = json_create_array(); - lba = 1 << n->ns.lbaf[(n->ns.flbas & 0x0f)].ds; - nsze = le64_to_cpu(n->ns.nsze) * lba; - nuse = le64_to_cpu(n->ns.nuse) * lba; + nvme_host_t h; + nvme_subsystem_t s; + nvme_ctrl_t c; + nvme_path_t p; + nvme_ns_t n; - json_object_add_value_string(ns_attrs, "NameSpace", n->name); - json_object_add_value_uint(ns_attrs, "NSID", n->nsid); + nvme_for_each_host(r, h) { + struct json_object *hss = json_create_object(); - json_object_add_value_uint(ns_attrs, "UsedBytes", nuse); - json_object_add_value_uint(ns_attrs, "MaximumLBA", - le64_to_cpu(n->ns.nsze)); - json_object_add_value_uint(ns_attrs, "PhysicalSize", nsze); - json_object_add_value_uint(ns_attrs, "SectorSize", lba); -} + json_object_add_value_string(hss, "hostnqn", nvme_host_get_hostnqn(h)); + json_object_add_value_string(hss, "hostid", nvme_host_get_hostid(h)); -static void json_detail_list(struct nvme_topology *t) -{ - int i, j, k; - struct json_object *root; - struct json_object *devices; - char formatter[41] = { 0 }; + nvme_for_each_subsystem(h , s) { + struct json_object *jss = json_create_object(); + struct json_object *jctrls = json_create_array(); + struct json_object *jnss = json_create_array(); - root = json_create_object(); - devices = json_create_array(); - - for (i = 0; i < t->nr_subsystems; i++) { - struct nvme_subsystem *s = &t->subsystems[i]; - struct json_object *subsys_attrs; - struct json_object *namespaces, *ctrls; - - subsys_attrs = json_create_object(); - json_object_add_value_string(subsys_attrs, "Subsystem", s->name); - json_object_add_value_string(subsys_attrs, "SubsystemNQN", s->subsysnqn); - - ctrls = json_create_array(); - json_object_add_value_array(subsys_attrs, "Controllers", ctrls); - for (j = 0; j < s->nr_ctrls; j++) { - struct json_object *ctrl_attrs = json_create_object(); - struct nvme_ctrl *c = &s->ctrls[j]; - struct json_object *namespaces; - - json_object_add_value_string(ctrl_attrs, "Controller", c->name); - if (c->transport) - json_object_add_value_string(ctrl_attrs, "Transport", c->transport); - if (c->address) - json_object_add_value_string(ctrl_attrs, "Address", c->address); - if (c->state) - json_object_add_value_string(ctrl_attrs, "State", c->state); - if (c->hostnqn) - json_object_add_value_string(ctrl_attrs, "HostNQN", c->hostnqn); - if (c->hostid) - json_object_add_value_string(ctrl_attrs, "HostID", c->hostid); - - format(formatter, sizeof(formatter), c->id.fr, sizeof(c->id.fr)); - json_object_add_value_string(ctrl_attrs, "Firmware", formatter); - - format(formatter, sizeof(formatter), c->id.mn, sizeof(c->id.mn)); - json_object_add_value_string(ctrl_attrs, "ModelNumber", formatter); - - format(formatter, sizeof(formatter), c->id.sn, sizeof(c->id.sn)); - json_object_add_value_string(ctrl_attrs, "SerialNumber", formatter); - - namespaces = json_create_array(); - - for (k = 0; k < c->nr_namespaces; k++) { - struct json_object *ns_attrs = json_create_object(); - struct nvme_namespace *n = &c->namespaces[k]; - - json_detail_ns(n, ns_attrs); - json_array_add_value_object(namespaces, ns_attrs); - } - if (k) - json_object_add_value_array(ctrl_attrs, "Namespaces", namespaces); - else - json_free_array(namespaces); + json_object_add_value_string(jss, "subsystem", nvme_subsystem_get_name(s)); + json_object_add_value_string(jss, "nqn", nvme_subsystem_get_nqn(s)); - json_array_add_value_object(ctrls, ctrl_attrs); - } + nvme_subsystem_for_each_ctrl(s, c) { + struct json_object *jctrl = json_create_object(); + struct json_object *jnss = json_create_array(); + struct json_object *jpaths = json_create_array(); - namespaces = json_create_array(); - for (k = 0; k < s->nr_namespaces; k++) { - struct json_object *ns_attrs = json_create_object(); - struct nvme_namespace *n = &s->namespaces[k]; + json_object_add_value_string(jctrl, "controller", nvme_ctrl_get_name(c)); + json_object_add_value_string(jctrl, "serial", nvme_ctrl_get_serial(c)); + json_object_add_value_string(jctrl, "model", nvme_ctrl_get_model(c)); + json_object_add_value_string(jctrl, "firmware", nvme_ctrl_get_firmware(c)); + json_object_add_value_string(jctrl, "transport", nvme_ctrl_get_transport(c)); + json_object_add_value_string(jctrl, "address", nvme_ctrl_get_address(c)); - json_detail_ns(n, ns_attrs); - json_array_add_value_object(namespaces, ns_attrs); - } - if (k) - json_object_add_value_array(subsys_attrs, "Namespaces", namespaces); - else - json_free_array(namespaces); + nvme_ctrl_for_each_ns(c, n) { + struct json_object *jns = json_create_object(); + long long lba = nvme_ns_get_lba_size(n); + double nsze = nvme_ns_get_lba_count(n) * lba; + double nuse = nvme_ns_get_lba_util(n) * lba; - json_array_add_value_object(devices, subsys_attrs); - } + json_object_add_value_string(jns, "namespace", nvme_ns_get_name(n)); + json_object_add_value_int(jns, "nsid", nvme_ns_get_nsid(n)); + json_object_add_value_int(jns, "util", nuse); + json_object_add_value_int(jns, "maxlba", nvme_ns_get_lba_count(n)); + json_object_add_value_int(jns, "capacity", nsze); + json_object_add_value_int(jns, "sector", lba); - json_object_add_value_array(root, "Devices", devices); - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); -} - -static void json_simple_ns(struct nvme_namespace *n, struct json_object *devices) -{ - struct json_object *device_attrs; - char formatter[41] = { 0 }; - double nsze, nuse; - int ret, index = -1; - long long lba; - char *devnode; - struct stat st; + json_array_add_value_object(jnss, jns); + } + json_object_add_value_object(jctrl, "namespaces", jnss); - if (asprintf(&devnode, "%s%s", n->ctrl->path, n->name) < 0) - return; + nvme_ctrl_for_each_path(c, p) { + struct json_object *jpath = json_create_object(); - ret = stat(devnode, &st); - if (ret < 0) - return; + json_object_add_value_string(jpath, "path", nvme_path_get_name(p)); + json_object_add_value_string(jpath, "ana-state", nvme_path_get_ana_state(p)); - device_attrs = json_create_object(); - json_object_add_value_int(device_attrs, "NameSpace", n->nsid); - - json_object_add_value_string(device_attrs, "DevicePath", devnode); - free(devnode); + json_array_add_value_object(jpaths, jpath); + } + json_object_add_value_object(jctrl, "paths", jpaths); - format(formatter, sizeof(formatter), - n->ctrl->id.fr, - sizeof(n->ctrl->id.fr)); + json_array_add_value_object(jctrls, jctrl); + } + json_object_add_value_object(jss, "controllers", jctrls); - json_object_add_value_string(device_attrs, "Firmware", formatter); + nvme_subsystem_for_each_ns(s, n) { + struct json_object *jns = json_create_object(); - if (sscanf(n->ctrl->name, "nvme%d", &index) == 1) - json_object_add_value_int(device_attrs, "Index", index); + long long lba = nvme_ns_get_lba_size(n); + double nsze = nvme_ns_get_lba_count(n) * lba; + double nuse = nvme_ns_get_lba_util(n) * lba; - format(formatter, sizeof(formatter), - n->ctrl->id.mn, - sizeof(n->ctrl->id.mn)); + json_object_add_value_string(jns, "namespace", nvme_ns_get_name(n)); + json_object_add_value_int(jns, "nsid", nvme_ns_get_nsid(n)); + json_object_add_value_int(jns, "util", nuse); + json_object_add_value_int(jns, "maxlba", nvme_ns_get_lba_count(n)); + json_object_add_value_int(jns, "capacity", nsze); + json_object_add_value_int(jns, "sector", lba); - json_object_add_value_string(device_attrs, "ModelNumber", formatter); + json_array_add_value_object(jnss, jns); + } + json_object_add_value_object(jss, "namespaces", jnss); - if (index >= 0 && n->ctrl->transport && !strcmp(n->ctrl->transport, "pcie")) { - char *product = nvme_product_name(index); + json_array_add_value_object(jsslist, jss); + } - json_object_add_value_string(device_attrs, "ProductName", product); - free((void*)product); + json_object_add_value_object(hss, "subsystems", jsslist); + json_array_add_value_object(jroot, hss); } + json_print_object(jroot, NULL); + printf("\n"); + json_free_object(jroot); +} - format(formatter, sizeof(formatter), - n->ctrl->id.sn, - sizeof(n->ctrl->id.sn)); - - json_object_add_value_string(device_attrs, "SerialNumber", formatter); +static struct json_object *json_list_item(nvme_ns_t n) +{ + struct json_object *jdevice = json_create_object(); + nvme_ctrl_t c = nvme_ns_get_ctrl(n); - lba = 1 << n->ns.lbaf[(n->ns.flbas & 0x0f)].ds; - nsze = le64_to_cpu(n->ns.nsze) * lba; - nuse = le64_to_cpu(n->ns.nuse) * lba; + long long lba = nvme_ns_get_lba_size(n); + double nsze = nvme_ns_get_lba_count(n) * lba; + double nuse = nvme_ns_get_lba_util(n) * lba; - json_object_add_value_uint(device_attrs, "UsedBytes", nuse); - json_object_add_value_uint(device_attrs, "MaximumLBA", - le64_to_cpu(n->ns.nsze)); - json_object_add_value_uint(device_attrs, "PhysicalSize", nsze); - json_object_add_value_uint(device_attrs, "SectorSize", lba); + json_object_add_value_int(jdevice, "namespace", nvme_ns_get_nsid(n)); + json_object_add_value_string(jdevice, "device", nvme_ns_get_name(n)); + json_object_add_value_string(jdevice, "firmware", nvme_ctrl_get_firmware(c)); + json_object_add_value_string(jdevice, "model", nvme_ctrl_get_model(c)); + json_object_add_value_string(jdevice, "serial", nvme_ctrl_get_serial(c)); + json_object_add_value_int(jdevice, "util", nuse); + json_object_add_value_int(jdevice, "maxlba", nvme_ns_get_lba_count(n)); + json_object_add_value_int(jdevice, "capacity", nsze); + json_object_add_value_int(jdevice, "sector", lba); - json_array_add_value_object(devices, device_attrs); + return jdevice; } -static void json_simple_list(struct nvme_topology *t) +static void json_simple_list(nvme_root_t r) { - struct json_object *root; - struct json_object *devices; - int i, j, k; + struct json_object *jroot = json_create_object(); + struct json_object *jdevices = json_create_array(); - root = json_create_object(); - devices = json_create_array(); - for (i = 0; i < t->nr_subsystems; i++) { - struct nvme_subsystem *s = &t->subsystems[i]; + nvme_host_t h; + nvme_subsystem_t s; + nvme_ctrl_t c; + nvme_ns_t n; - for (j = 0; j < s->nr_ctrls; j++) { - struct nvme_ctrl *c = &s->ctrls[j]; + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + nvme_subsystem_for_each_ns(s, n) + json_array_add_value_object(jdevices, + json_list_item(n)); - for (k = 0; k < c->nr_namespaces; k++) { - struct nvme_namespace *n = &c->namespaces[k]; - json_simple_ns(n, devices); - } - } - - for (j = 0; j < s->nr_namespaces; j++) { - struct nvme_namespace *n = &s->namespaces[j]; - json_simple_ns(n, devices); + nvme_subsystem_for_each_ctrl(s, c) + nvme_ctrl_for_each_ns(c, n) + json_array_add_value_object(jdevices, + json_list_item(n)); } + json_object_add_value_object(jroot, "devices", jdevices); } - json_object_add_value_array(root, "Devices", devices); - json_print_object(root, NULL); + json_print_object(jroot, NULL); printf("\n"); - json_free_object(root); + json_free_object(jroot); } -static void json_print_list_items(struct nvme_topology *t, +static void json_print_list_items(nvme_root_t r, enum nvme_print_flags flags) { if (flags & VERBOSE) - json_detail_list(t); + json_detail_list(r); else - json_simple_list(t); + json_simple_list(r); } -void nvme_show_list_items(struct nvme_topology *t, enum nvme_print_flags flags) +void nvme_show_list_items(nvme_root_t r, enum nvme_print_flags flags) { if (flags & JSON) - json_print_list_items(t, flags); + json_print_list_items(r, flags); else if (flags & VERBOSE) - nvme_show_detailed_list(t); + nvme_show_detailed_list(r); else - nvme_show_simple_list(t); + nvme_show_simple_list(r); } diff --git a/nvme-print.h b/nvme-print.h index 97076636f6..efecf402d2 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -1,6 +1,7 @@ #ifndef NVME_PRINT_H #define NVME_PRINT_H +#include "nvme.h" #include void d(unsigned char *buf, int len, int width, int group); @@ -8,44 +9,46 @@ void d_raw(unsigned char *buf, unsigned len); uint64_t int48_to_long(__u8 *data); void nvme_show_status(__u16 status); +void nvme_show_lba_status_info(__u32 result); void nvme_show_relatives(const char *name); -const char *nvme_cmd_to_string(int admin, __u8 opcode); + +void nvme_show_id_iocs(struct nvme_id_iocs *iocs); void __nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, void (*vendor_show)(__u8 *vs, struct json_object *root)); void nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode); void nvme_show_id_ns(struct nvme_id_ns *ns, unsigned int nsid, enum nvme_print_flags flags); -void nvme_show_resv_report(struct nvme_reservation_status *status, int bytes, __u32 cdw11, +void nvme_show_resv_report(struct nvme_resv_status *status, int bytes, __u32 cdw11, enum nvme_print_flags flags); void nvme_show_lba_range(struct nvme_lba_range_type *lbrt, int nr_ranges); void nvme_show_error_log(struct nvme_error_log_page *err_log, int entries, const char *devname, enum nvme_print_flags flags); void nvme_show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char *devname, enum nvme_print_flags flags); -void nvme_show_ana_log(struct nvme_ana_rsp_hdr *ana_log, const char *devname, +void nvme_show_ana_log(struct nvme_ana_log *ana_log, const char *devname, enum nvme_print_flags flags, size_t len); void nvme_show_self_test_log(struct nvme_self_test_log *self_test, __u8 dst_entries, __u32 size, const char *devname, enum nvme_print_flags flags); -void nvme_show_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname, +void nvme_show_fw_log(struct nvme_firmware_slot *fw_log, const char *devname, enum nvme_print_flags flags); -void nvme_show_effects_log(struct nvme_effects_log_page *effects, unsigned int flags); -void nvme_show_changed_ns_list_log(struct nvme_changed_ns_list_log *log, +void nvme_show_effects_log(struct nvme_cmd_effects_log *effects, unsigned int flags); +void nvme_show_changed_ns_list_log(struct nvme_ns_list *log, const char *devname, enum nvme_print_flags flags); void nvme_show_endurance_log(struct nvme_endurance_group_log *endurance_log, __u16 group_id, const char *devname, enum nvme_print_flags flags); void nvme_show_sanitize_log(struct nvme_sanitize_log_page *sanitize, const char *devname, enum nvme_print_flags flags); void json_predictable_latency_per_nvmset( - struct nvme_predlat_per_nvmset_log_page *plpns_log, + struct nvme_nvmset_predictable_lat_log *plpns_log, __u16 nvmset_id); void nvme_show_predictable_latency_per_nvmset( - struct nvme_predlat_per_nvmset_log_page *plpns_log, + struct nvme_nvmset_predictable_lat_log *plpns_log, __u16 nvmset_id, const char *devname, enum nvme_print_flags flags); void json_predictable_latency_event_agg_log( - struct nvme_event_agg_log_page *pea_log, + struct nvme_aggregate_predictable_lat_event *pea_log, __u64 log_entries); void nvme_show_predictable_latency_event_agg_log( - struct nvme_event_agg_log_page *pea_log, + struct nvme_aggregate_predictable_lat_event *pea_log, __u64 log_entries, __u32 size, const char *devname, enum nvme_print_flags flags); void json_persistent_event_log(void *pevent_log_info, __u32 size); @@ -53,45 +56,43 @@ void nvme_show_persistent_event_log(void *pevent_log_info, __u8 action, __u32 size, const char *devname, enum nvme_print_flags flags); void json_endurance_group_event_agg_log( - struct nvme_event_agg_log_page *endurance_log, + struct nvme_aggregate_predictable_lat_event *endurance_log, __u64 log_entries); void nvme_show_endurance_group_event_agg_log( - struct nvme_event_agg_log_page *endurance_log, + struct nvme_aggregate_predictable_lat_event *endurance_log, __u64 log_entries, __u32 size, const char *devname, enum nvme_print_flags flags); void json_lba_status_log(void *lba_status); void nvme_show_lba_status_log(void *lba_status, __u32 size, const char *devname, enum nvme_print_flags flags); -void nvme_show_resv_notif_log(struct nvme_resv_notif_log *resv, +void nvme_show_resv_notif_log(struct nvme_resv_notification_log *resv, const char *devname, enum nvme_print_flags flags); void nvme_show_ctrl_registers(void *bar, bool fabrics, enum nvme_print_flags flags); void nvme_show_single_property(int offset, uint64_t prop, int human); void nvme_show_id_ns_descs(void *data, unsigned nsid, enum nvme_print_flags flags); void nvme_show_lba_status(struct nvme_lba_status *list, unsigned long len, enum nvme_print_flags flags); -void nvme_show_list_items(struct nvme_topology *t, enum nvme_print_flags flags); -void nvme_show_subsystem_list(struct nvme_topology *t, - enum nvme_print_flags flags); -void nvme_show_id_nvmset(struct nvme_id_nvmset *nvmset, unsigned nvmset_id, +void nvme_show_list_items(nvme_root_t t, enum nvme_print_flags flags); +void nvme_show_subsystem_list(nvme_root_t t, enum nvme_print_flags flags); +void nvme_show_id_nvmset(struct nvme_id_nvmset_list *nvmset, unsigned nvmset_id, enum nvme_print_flags flags); -void nvme_show_primary_ctrl_caps(const struct nvme_primary_ctrl_caps *caps, +void nvme_show_primary_ctrl_cap(const struct nvme_primary_ctrl_cap *cap, enum nvme_print_flags flags); -void nvme_show_list_secondary_ctrl(const struct nvme_secondary_controllers_list *sc_list, +void nvme_show_list_secondary_ctrl(const struct nvme_secondary_ctrl_list *sc_list, __u32 count, enum nvme_print_flags flags); void nvme_show_id_ns_granularity_list(const struct nvme_id_ns_granularity_list *glist, enum nvme_print_flags flags); void nvme_show_id_uuid_list(const struct nvme_id_uuid_list *uuid_list, enum nvme_print_flags flags); -void nvme_show_id_iocs(struct nvme_id_iocs *iocs, enum nvme_print_flags flags); -void nvme_show_list_ctrl(struct nvme_controller_list *ctrl_list, +void nvme_show_list_ctrl(struct nvme_ctrl_list *ctrl_list, + enum nvme_print_flags flags); +void nvme_show_list_ns(struct nvme_ns_list *ns_list, enum nvme_print_flags flags); -void nvme_show_list_ns(__u32 *ns_list, enum nvme_print_flags flags); -void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, unsigned char *buf); +void nvme_feature_show_fields(enum nvme_features_id fid, unsigned int result, unsigned char *buf); void nvme_directive_show(__u8 type, __u8 oper, __u16 spec, __u32 nsid, __u32 result, void *buf, __u32 len, enum nvme_print_flags flags); void nvme_show_select_result(__u32 result); -void nvme_show_lba_status_info(__u32 result); void nvme_show_zns_id_ctrl(struct nvme_zns_id_ctrl *ctrl, unsigned int mode); void nvme_show_id_ctrl_nvm(struct nvme_id_ctrl_nvm *ctrl_nvm, @@ -103,9 +104,10 @@ void nvme_show_zns_changed( struct nvme_zns_changed_zone_log *log, void nvme_show_zns_report_zones(void *report, __u32 descs, __u8 ext_size, __u32 report_size, unsigned long flags); +const char *nvme_cmd_to_string(int admin, __u8 opcode); const char *nvme_status_to_string(__u16 status); const char *nvme_select_to_string(int sel); -const char *nvme_feature_to_string(enum nvme_feat feature); +const char *nvme_feature_to_string(enum nvme_features_id feature); const char *nvme_register_to_string(int reg); #endif diff --git a/nvme-rpmb.c b/nvme-rpmb.c index 0b55391fc8..77a99f4854 100644 --- a/nvme-rpmb.c +++ b/nvme-rpmb.c @@ -27,10 +27,7 @@ #include #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #define CREATE_CMD @@ -268,12 +265,12 @@ struct rpmb_config_block_t { #define RPMB_NVME_SPSP 0x0001 #define SEND_RPMB_REQ(tgt, size, req) \ -nvme_sec_send(fd, 0, tgt, RPMB_NVME_SPSP, RPMB_NVME_SECP, size, size, \ - (unsigned char *)(req)) +nvme_security_send(fd, 0, tgt, RPMB_NVME_SPSP, 0, RPMB_NVME_SECP, 0, size, \ + (unsigned char *)(req), NULL) #define RECV_RPMB_RSP(tgt, size, rsp) \ -nvme_sec_recv(fd, 0, tgt, RPMB_NVME_SPSP, RPMB_NVME_SECP, size, size, \ - (unsigned char *)(rsp)) +nvme_security_receive(fd, 0, tgt, RPMB_NVME_SPSP, 0, RPMB_NVME_SECP, 0, size, \ + (unsigned char *)(rsp), NULL) /* Initialize nonce value in rpmb request frame */ static void rpmb_nonce_init(struct rpmb_data_frame_t *req) diff --git a/nvme-topology.c b/nvme-topology.c deleted file mode 100644 index 47121e4437..0000000000 --- a/nvme-topology.c +++ /dev/null @@ -1,773 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "nvme.h" -#include "nvme-ioctl.h" - -#ifdef HAVE_SYSTEMD -#include -#define NVME_HOSTNQN_ID SD_ID128_MAKE(c7,f4,61,81,12,be,49,32,8c,83,10,6f,9d,dd,d8,6b) -#endif - -static const char *dev = "/dev/"; -static const char *subsys_dir = "/sys/class/nvme-subsystem/"; -static void free_ctrl(struct nvme_ctrl *c); - -char *get_nvme_subsnqn(char *path) -{ - char sspath[320], *subsysnqn; - int fd, ret; - - snprintf(sspath, sizeof(sspath), "%s/subsysnqn", path); - - fd = open(sspath, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "Failed to open %s: %s\n", - sspath, strerror(errno)); - return NULL; - } - - subsysnqn = calloc(1, 256); - if (!subsysnqn) - goto close_fd; - - ret = read(fd, subsysnqn, 256); - if (ret < 0) { - fprintf(stderr, "Failed to read %s: %s\n", sspath, - strerror(errno)); - free(subsysnqn); - subsysnqn = NULL; - } else if (subsysnqn[strlen(subsysnqn) - 1] == '\n') { - subsysnqn[strlen(subsysnqn) - 1] = '\0'; - } - -close_fd: - close(fd); - return subsysnqn; -} - -char *nvme_get_ctrl_attr(const char *path, const char *attr) -{ - char *attrpath, *value; - ssize_t ret; - int fd, i; - - ret = asprintf(&attrpath, "%s/%s", path, attr); - if (ret < 0) - return NULL; - - value = calloc(1, 1024); - if (!value) - goto err_free_path; - - fd = open(attrpath, O_RDONLY); - if (fd < 0) - goto err_free_value; - - ret = read(fd, value, 1024); - if (ret < 0) { - fprintf(stderr, "read :%s :%s\n", attrpath, strerror(errno)); - goto err_close_fd; - } - - if (value[strlen(value) - 1] == '\n') - value[strlen(value) - 1] = '\0'; - - for (i = 0; i < strlen(value); i++) { - if (value[i] == ',' ) - value[i] = ' '; - } - - close(fd); - free(attrpath); - return value; -err_close_fd: - close(fd); -err_free_value: - free(value); -err_free_path: - free(attrpath); - return NULL; -} - -static char *path_trim_last(char *path, char needle) -{ - int i; - i = strlen(path); - if (i>0 && path[i-1] == needle) // remove trailing slash - path[--i] = 0; - for (; i>0; i--) - if (path[i] == needle) { - path[i] = 0; - return path+i+1; - } - return NULL; -} - -static void legacy_get_pci_bdf(char *node, char *bdf) -{ - int ret; - char path[264], nodetmp[264]; - struct stat st; - char *p, *__path = path; - - bdf[0] = 0; - strcpy(nodetmp, node); - p = path_trim_last(nodetmp, '/'); - sprintf(path, "/sys/block/%s/device", p); - ret = readlink(path, nodetmp, sizeof(nodetmp)); - if (ret <= 0) - return; - nodetmp[ret] = 0; - /* The link value is either "device -> ../../../0000:86:00.0" or "device -> ../../nvme0" */ - (void) path_trim_last(path, '/'); - sprintf(path+strlen(path), "/%s/device", nodetmp); - ret = stat(path, &st); - if (ret < 0) - return; - if ((st.st_mode & S_IFLNK) == 0) { - /* follow the second link to get the PCI address */ - ret = readlink(path, __path, sizeof(path)); - if (ret <= 0) - return; - path[ret] = 0; - } - else - (void) path_trim_last(path, '/'); - - p = path_trim_last(path, '/'); - if (p && strlen(p) == 12) - strcpy(bdf, p); -} - -static int scan_namespace(struct nvme_namespace *n) -{ - int ret, fd; - char *path; - - ret = asprintf(&path, "%s%s", n->ctrl->path, n->name); - if (ret < 0) - return ret; - - fd = open(path, O_RDONLY); - if (fd < 0) - goto free; - - if (!n->nsid) { - n->nsid = nvme_get_nsid(fd); - if (n->nsid < 0) - goto close_fd; - } - - ret = nvme_identify_ns(fd, n->nsid, 0, &n->ns); - if (ret < 0) - goto close_fd; -close_fd: - close(fd); -free: - free(path); - return 0; -} - -static char *get_nvme_ctrl_path_ana_state(char *path, int nsid) -{ - struct dirent **paths; - char *ana_state; - int i, n; - - ana_state = calloc(1, 16); - if (!ana_state) - return NULL; - - n = scandir(path, &paths, scan_ctrl_paths_filter, alphasort); - if (n <= 0) { - free(ana_state); - return NULL; - } - for (i = 0; i < n; i++) { - int id, cntlid, ns, fd; - char *ctrl_path; - ssize_t ret; - - if (sscanf(paths[i]->d_name, "nvme%dc%dn%d", - &id, &cntlid, &ns) != 3) { - if (sscanf(paths[i]->d_name, "nvme%dn%d", - &id, &ns) != 2) { - continue; - } - } - if (ns != nsid) - continue; - - ret = asprintf(&ctrl_path, "%s/%s/ana_state", - path, paths[i]->d_name); - if (ret < 0) { - free(ana_state); - ana_state = NULL; - break; - } - fd = open(ctrl_path, O_RDONLY); - if (fd < 0) { - free(ctrl_path); - free(ana_state); - ana_state = NULL; - break; - } - ret = read(fd, ana_state, 16); - if (ret < 0) { - fprintf(stderr, "Failed to read ANA state from %s\n", - ctrl_path); - free(ana_state); - ana_state = NULL; - } else if (ana_state[strlen(ana_state) - 1] == '\n') - ana_state[strlen(ana_state) - 1] = '\0'; - close(fd); - free(ctrl_path); - break; - } - for (i = 0; i < n; i++) - free(paths[i]); - free(paths); - return ana_state; -} - -static bool ns_attached_to_ctrl(int nsid, struct nvme_ctrl *ctrl) -{ - struct nvme_namespace *n; - int i; - - for (i = 0; i < ctrl->nr_namespaces; i++) { - n = &ctrl->namespaces[i]; - if (nsid == n->nsid) - return true; - } - return false; -} - -static int scan_ctrl(struct nvme_ctrl *c, char *p, __u32 ns_instance) -{ - struct nvme_namespace *n; - struct dirent **ns; - char *path; - int i, fd, ret; - - ret = asprintf(&path, "%s/%s", p, c->name); - if (ret < 0) - return ret; - - c->address = nvme_get_ctrl_attr(path, "address"); - c->transport = nvme_get_ctrl_attr(path, "transport"); - c->state = nvme_get_ctrl_attr(path, "state"); - c->hostnqn = nvme_get_ctrl_attr(path, "hostnqn"); - c->hostid = nvme_get_ctrl_attr(path, "hostid"); - - if (ns_instance) - c->ana_state = get_nvme_ctrl_path_ana_state(path, ns_instance); - - ret = scandir(path, &ns, scan_ctrl_namespace_filter, alphasort); - if (ret == -1) { - fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno)); - return errno; - } - - c->nr_namespaces = ret; - c->namespaces = calloc(c->nr_namespaces, sizeof(*n)); - if (c->namespaces) { - for (i = 0; i < c->nr_namespaces; i++) { - char *ns_path, nsid[16]; - int ns_fd; - - n = &c->namespaces[i]; - n->name = strdup(ns[i]->d_name); - n->ctrl = c; - ret = asprintf(&ns_path, "%s/%s/nsid", path, n->name); - if (ret < 0) - continue; - ns_fd = open(ns_path, O_RDONLY); - if (ns_fd < 0) { - free(ns_path); - continue; - } - ret = read(ns_fd, nsid, 16); - if (ret < 0) { - close(ns_fd); - free(ns_path); - continue; - } - n->nsid = (unsigned)strtol(nsid, NULL, 10); - scan_namespace(n); - close(ns_fd); - free(ns_path); - } - } else { - i = c->nr_namespaces; - c->nr_namespaces = 0; - } - - while (i--) - free(ns[i]); - free(ns); - free(path); - - ret = asprintf(&path, "%s%s", c->path, c->name); - if (ret < 0) - return ret; - - fd = open(path, O_RDONLY); - if (fd < 0) - goto free; - - ret = nvme_identify_ctrl(fd, &c->id); - if (ret < 0) - goto close_fd; -close_fd: - close(fd); -free: - free(path); - return 0; -} - -static int scan_subsystem(struct nvme_subsystem *s, __u32 ns_instance, int nsid) -{ - struct dirent **ctrls, **ns; - struct nvme_namespace *n; - struct nvme_ctrl *c; - int i, j = 0, ret; - char *path; - - ret = asprintf(&path, "%s%s", subsys_dir, s->name); - if (ret < 0) - return ret; - - s->subsysnqn = get_nvme_subsnqn(path); - ret = scandir(path, &ctrls, scan_ctrls_filter, alphasort); - if (ret == -1) { - fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno)); - return errno; - } - s->nr_ctrls = ret; - s->ctrls = calloc(s->nr_ctrls, sizeof(*c)); - for (i = 0; i < s->nr_ctrls; i++) { - c = &s->ctrls[j]; - c->name = strdup(ctrls[i]->d_name); - c->path = strdup(dev); - c->subsys = s; - scan_ctrl(c, path, ns_instance); - - if (!ns_instance || ns_attached_to_ctrl(nsid, c)) - j++; - else - free_ctrl(c); - } - s->nr_ctrls = j; - - while (i--) - free(ctrls[i]); - free(ctrls); - - ret = scandir(path, &ns, scan_namespace_filter, alphasort); - if (ret == -1) { - fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno)); - return errno; - } - - s->nr_namespaces = ret; - s->namespaces = calloc(s->nr_namespaces, sizeof(*n)); - if (s->namespaces) { - for (i = 0; i < s->nr_namespaces; i++) { - n = &s->namespaces[i]; - n->name = strdup(ns[i]->d_name); - n->ctrl = &s->ctrls[0]; - scan_namespace(n); - } - } else { - i = s->nr_namespaces; - s->nr_namespaces = 0; - } - - while (i--) - free(ns[i]); - free(ns); - - free(path); - return 0; -} - -static int verify_legacy_ns(struct nvme_namespace *n) -{ - struct nvme_ctrl *c = n->ctrl; - struct nvme_id_ctrl id; - char *path; - int ret, fd; - - ret = asprintf(&path, "%s%s", n->ctrl->path, n->name); - if (ret < 0) - return ret; - - if (!n->ctrl->transport && !n->ctrl->address) { - char tmp_address[64] = ""; - legacy_get_pci_bdf(path, tmp_address); - if (tmp_address[0]) { - if (asprintf(&n->ctrl->transport, "pcie") < 0) - return -1; - if (asprintf(&n->ctrl->address, "%s", tmp_address) < 0) - return -1; - } - } - - fd = open(path, O_RDONLY); - free (path); - - if (fd < 0) - return fd; - - ret = nvme_identify_ctrl(fd, &id); - close(fd); - - if (ret) - return ret; - - if (memcmp(id.mn, c->id.mn, sizeof(id.mn)) || - memcmp(id.sn, c->id.sn, sizeof(id.sn))) - return -ENODEV; - return 0; -} - -/* - * For pre-subsystem enabled kernel. Topology information is limited, but we can - * assume controller names are always a prefix to their namespaces, i.e. nvme0 - * is the controller to nvme0n1 for such older kernels. We will also assume - * every controller is its own subsystem. - */ -static int legacy_list(struct nvme_topology *t, char *dev_dir) -{ - struct nvme_ctrl *c; - struct nvme_subsystem *s; - struct nvme_namespace *n; - struct dirent **devices, **namespaces; - int ret = 0, fd, i; - char *path; - - t->nr_subsystems = scandir(dev_dir, &devices, scan_ctrls_filter, alphasort); - if (t->nr_subsystems == -1) { - fprintf(stderr, "Failed to open %s: %s\n", dev_dir, strerror(errno)); - return errno; - } - - t->subsystems = calloc(t->nr_subsystems, sizeof(*s)); - for (i = 0; i < t->nr_subsystems; i++) { - int j; - - s = &t->subsystems[i]; - s->nr_ctrls = 1; - s->ctrls = calloc(s->nr_ctrls, sizeof(*c)); - s->name = strdup(devices[i]->d_name); - s->subsysnqn = strdup(s->name); - s->nr_namespaces = 0; - - c = s->ctrls; - c->name = strdup(s->name); - sscanf(c->name, "nvme%d", ¤t_index); - c->path = strdup(dev_dir); - c->nr_namespaces = scandir(c->path, &namespaces, scan_dev_filter, - alphasort); - c->namespaces = calloc(c->nr_namespaces, sizeof(*n)); - if (!c->namespaces) { - while (c->nr_namespaces--) - free(namespaces[c->nr_namespaces]); - free(namespaces); - continue; - } - - ret = asprintf(&path, "%s%s", c->path, c->name); - if (ret < 0) - continue; - ret = 0; - - fd = open(path, O_RDONLY); - if (fd > 0) { - nvme_identify_ctrl(fd, &c->id); - close(fd); - } - free(path); - - for (j = 0; j < c->nr_namespaces; j++) { - n = &c->namespaces[j]; - n->name = strdup(namespaces[j]->d_name); - n->ctrl = c; - scan_namespace(n); - ret = verify_legacy_ns(n); - if (ret) - goto free; - } - while (j--) - free(namespaces[j]); - free(namespaces); - } - -free: - while (i--) - free(devices[i]); - free(devices); - return ret; -} - -static void free_ctrl(struct nvme_ctrl *c) -{ - int i; - - for (i = 0; i < c->nr_namespaces; i++) { - struct nvme_namespace *n = &c->namespaces[i]; - free(n->name); - } - free(c->name); - free(c->path); - free(c->transport); - free(c->address); - free(c->state); - free(c->hostnqn); - free(c->hostid); - free(c->ana_state); - free(c->namespaces); -} - -static void free_subsystem(struct nvme_subsystem *s) -{ - int i; - - for (i = 0; i < s->nr_ctrls; i++) - free_ctrl(&s->ctrls[i]); - for (i = 0; i < s->nr_namespaces; i++) { - struct nvme_namespace *n = &s->namespaces[i]; - free(n->name); - } - free(s->name); - free(s->subsysnqn); - free(s->ctrls); - free(s->namespaces); -} - -static int scan_subsystem_dir(struct nvme_topology *t, char *dev_dir) -{ - struct nvme_topology dev_dir_t = { }; - int ret, i, total_nr_subsystems; - - ret = legacy_list(&dev_dir_t, dev_dir); - if (ret != 0) - return ret; - - total_nr_subsystems = t->nr_subsystems + dev_dir_t.nr_subsystems; - t->subsystems = realloc(t->subsystems, - total_nr_subsystems * sizeof(struct nvme_subsystem)); - for (i = 0; i < dev_dir_t.nr_subsystems; i++){ - t->subsystems[i+t->nr_subsystems] = dev_dir_t.subsystems[i]; - } - t->nr_subsystems = total_nr_subsystems; - - return 0; -} - -int scan_subsystems(struct nvme_topology *t, const char *subsysnqn, - __u32 ns_instance, int nsid, char *dev_dir) -{ - struct nvme_subsystem *s; - struct dirent **subsys; - int ret = 0, i, j = 0; - - t->nr_subsystems = scandir(subsys_dir, &subsys, scan_subsys_filter, - alphasort); - if (t->nr_subsystems < 0) { - ret = legacy_list(t, (char *)dev); - if (ret != 0) - return ret; - } else { - - t->subsystems = calloc(t->nr_subsystems, sizeof(*s)); - for (i = 0; i < t->nr_subsystems; i++) { - s = &t->subsystems[j]; - s->name = strdup(subsys[i]->d_name); - scan_subsystem(s, ns_instance, nsid); - - if (!subsysnqn || !strcmp(s->subsysnqn, subsysnqn)) - j++; - else - free_subsystem(s); - } - t->nr_subsystems = j; - - while (i--) - free(subsys[i]); - free(subsys); - } - - if (dev_dir != NULL && strcmp(dev_dir, "/dev/")) { - ret = scan_subsystem_dir(t, dev_dir); - } - - return ret; -} - -void free_topology(struct nvme_topology *t) -{ - int i; - - for (i = 0; i < t->nr_subsystems; i++) - free_subsystem(&t->subsystems[i]); - free(t->subsystems); -} - -char *nvme_char_from_block(char *dev) -{ - char *path = NULL; - char buf[256] = {0}; - int ret, id, nsid; - - ret = sscanf(dev, "nvme%dn%d", &id, &nsid); - switch (ret) { - case 1: - return strdup(dev); - break; - case 2: - if (asprintf(&path, "/sys/block/%s/device", dev) < 0) - path = NULL; - break; - default: - fprintf(stderr, "%s is not an nvme device\n", dev); - return NULL; - } - - if (!path) - return NULL; - - ret = readlink(path, buf, sizeof(buf)); - if (ret > 0) { - char *r = strdup(basename(buf)); - - free(path); - if (sscanf(r, "nvme%d", &id) != 1) { - fprintf(stderr, "%s is not a physical nvme controller\n", r); - free(r); - r = NULL; - } - return r; - } - - free(path); - ret = asprintf(&path, "nvme%d", id); - if (ret < 0) - return NULL; - return path; -} - -void *mmap_registers(const char *dev) -{ - int fd; - char *base, path[512]; - void *membase; - - base = nvme_char_from_block((char *)dev); - if (!base) - return NULL; - - sprintf(path, "/sys/class/nvme/%s/device/resource0", base); - fd = open(path, O_RDONLY); - if (fd < 0) { - sprintf(path, "/sys/class/misc/%s/device/resource0", base); - fd = open(path, O_RDONLY); - } - if (fd < 0) { - fprintf(stderr, "%s did not find a pci resource, open failed %s\n", - base, strerror(errno)); - free(base); - return NULL; - } - - membase = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd, 0); - if (membase == MAP_FAILED) { - fprintf(stderr, "%s failed to map. ", base); - fprintf(stderr, "Did your kernel enable CONFIG_IO_STRICT_DEVMEM?\n"); - membase = NULL; - } - - free(base); - close(fd); - return membase; -} - -#define PATH_DMI_ENTRIES "/sys/firmware/dmi/entries" - -int uuid_from_dmi(char *system_uuid) -{ - int f; - DIR *d; - struct dirent *de; - char buf[512]; - - system_uuid[0] = '\0'; - d = opendir(PATH_DMI_ENTRIES); - if (!d) - return -ENXIO; - while ((de = readdir(d))) { - char filename[PATH_MAX]; - int len, type; - - if (de->d_name[0] == '.') - continue; - sprintf(filename, "%s/%s/type", PATH_DMI_ENTRIES, de->d_name); - f = open(filename, O_RDONLY); - if (f < 0) - continue; - len = read(f, buf, 512); - close(f); - if (len < 0) - continue; - if (sscanf(buf, "%d", &type) != 1) - continue; - if (type != 1) - continue; - sprintf(filename, "%s/%s/raw", PATH_DMI_ENTRIES, de->d_name); - f = open(filename, O_RDONLY); - if (f < 0) - continue; - len = read(f, buf, 512); - close(f); - if (len < 0) - continue; - /* Sigh. https://en.wikipedia.org/wiki/Overengineering */ - /* DMTF SMBIOS 3.0 Section 7.2.1 System UUID */ - sprintf(system_uuid, - "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" - "%02x%02x%02x%02x%02x%02x", - (uint8_t)buf[8 + 3], (uint8_t)buf[8 + 2], - (uint8_t)buf[8 + 1], (uint8_t)buf[8 + 0], - (uint8_t)buf[8 + 5], (uint8_t)buf[8 + 4], - (uint8_t)buf[8 + 7], (uint8_t)buf[8 + 6], - (uint8_t)buf[8 + 8], (uint8_t)buf[8 + 9], - (uint8_t)buf[8 + 10], (uint8_t)buf[8 + 11], - (uint8_t)buf[8 + 12], (uint8_t)buf[8 + 13], - (uint8_t)buf[8 + 14], (uint8_t)buf[8 + 15]); - break; - } - closedir(d); - return strlen(system_uuid) ? 0 : -ENXIO; -} - -int uuid_from_systemd(char *systemd_uuid) -{ -#ifdef HAVE_SYSTEMD - sd_id128_t id; - - if (sd_id128_get_machine_app_specific(NVME_HOSTNQN_ID, &id) < 0) - return -ENXIO; - - sprintf(systemd_uuid, SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id)); - return 0; -#else - return -ENOTSUP; -#endif -} diff --git a/nvme.c b/nvme.c index 4f985046dc..8cf698892a 100644 --- a/nvme.c +++ b/nvme.c @@ -43,18 +43,14 @@ #include -#include #include #include #include #include "common.h" #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" +#include "libnvme.h" #include "nvme-print.h" -#include "nvme-ioctl.h" -#include "nvme-status.h" #include "plugin.h" #include "argconfig.h" @@ -86,16 +82,6 @@ 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 -}; - const char *output_format = "Output format: normal|json|binary"; static const char *output_format_no_binary = "Output format: normal|json"; @@ -279,7 +265,7 @@ 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); @@ -304,6 +290,7 @@ 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; @@ -333,7 +320,7 @@ static int get_ana_log(int argc, char **argv, struct command *cmd, 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); @@ -341,12 +328,14 @@ static int get_ana_log(int argc, char **argv, struct command *cmd, 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) @@ -367,11 +356,9 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct 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 all. Valid options are 1, 2, 3."; - const size_t bs = 512; - struct nvme_telemetry_log_page_hdr *hdr; - size_t full_size, offset = bs; - int err = -1, fd, output; - void *page_log; + struct nvme_telemetry_log *log; + int err = 0, fd, output; + unsigned total_size; struct config { char *file_name; @@ -400,22 +387,11 @@ 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", @@ -424,67 +400,44 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct goto free_mem; } - err = nvme_get_telemetry_log(fd, hdr, cfg.host_gen, cfg.ctrl_init, bs, 0); + if (cfg.ctrl_init) + err = nvme_get_ctrl_telemetry(fd, true, &log); + else if (cfg.host_gen) + err = nvme_get_new_host_telemetry(fd, &log); + else + err = nvme_get_host_telemetry(fd, &log); + 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; - } - - err = write(output, (void *) hdr, bs); - if (err != bs) { - fprintf(stderr, "Failed to flush all data to file!\n"); + 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; + total_size = (le16_to_cpu(log->dalb1) + 1) * NVME_LOG_TELEM_BLOCK_SIZE; break; case 2: - full_size = (le16_to_cpu(hdr->dalb2) * bs) + offset; + total_size = (le16_to_cpu(log->dalb2) + 1) * NVME_LOG_TELEM_BLOCK_SIZE; break; case 3: - full_size = (le16_to_cpu(hdr->dalb3) * bs) + offset; - break; default: - fprintf(stderr, "Invalid data area requested\n"); - errno = EINVAL; - err = -1; - goto close_output; + total_size = (le16_to_cpu(log->dalb3) + 1) * NVME_LOG_TELEM_BLOCK_SIZE; + break; } - /* - * 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"); - break; - } else if (err > 0) { - fprintf(stderr, "Failed to acquire full telemetry log!\n"); - nvme_show_status(err); - 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; + err = write(output, (void *)log, total_size); + if (err != total_size) { + fprintf(stderr, "Failed to flush all data to file!\n"); + goto close_output; } close_output: close(output); free_mem: - free(hdr); - free(page_log); + free(log); close_fd: close(fd); ret: @@ -497,7 +450,7 @@ 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; @@ -523,7 +476,7 @@ 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) @@ -541,7 +494,7 @@ 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; + struct nvme_cmd_effects_log effects; int err = -1, fd; enum nvme_print_flags flags; @@ -575,7 +528,7 @@ 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); + err = nvme_get_log_cmd_effects(fd, NVME_CSI_NVM, &effects); if (!err) nvme_show_effects_log(&effects, flags); else if (err > 0) @@ -655,7 +608,7 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug 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) @@ -674,9 +627,9 @@ 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; @@ -703,7 +656,7 @@ 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) @@ -718,13 +671,13 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin 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; @@ -751,7 +704,7 @@ 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); @@ -773,9 +726,9 @@ 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; @@ -805,8 +758,7 @@ 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); @@ -832,11 +784,11 @@ 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; @@ -871,8 +823,7 @@ 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; } @@ -891,13 +842,11 @@ static int get_pred_lat_event_agg_log(int argc, char **argv, 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); @@ -923,10 +872,10 @@ 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 = NULL; + struct nvme_persistent_event_log *pevent; enum nvme_print_flags flags; - int err = -1, fd; + void *pevent_log_info; + int err, fd; bool huge; struct config { @@ -960,24 +909,16 @@ 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) { + pevent = calloc(sizeof(*pevent), 1); + if (!pevent) { perror("could not alloc buffer for persistent " \ "event log header\n"); - errno = ENOMEM; - err = -1; + 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 close_fd; @@ -992,7 +933,7 @@ static int get_persistent_event_log(int argc, char **argv, } 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 close_fd; @@ -1011,11 +952,10 @@ 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; + err = -ENOMEM; goto close_fd; } - 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) nvme_show_persistent_event_log(pevent_log_info, cfg.action, @@ -1028,7 +968,7 @@ static int get_persistent_event_log(int argc, char **argv, nvme_free(pevent_log_info, huge); close_fd: - free(pevent_log_head); + free(pevent); close(fd); ret: return nvme_status_to_errno(err, false); @@ -1048,7 +988,7 @@ 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 { @@ -1084,8 +1024,7 @@ 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; } @@ -1095,8 +1034,7 @@ static int get_endurance_event_agg_log(int argc, char **argv, goto close_fd; } else if (err) { fprintf(stderr, "could not identify controller\n"); - errno = ENODEV; - err = -1; + err = -ENODEV; goto close_fd; } @@ -1106,13 +1044,11 @@ static int get_endurance_event_agg_log(int argc, char **argv, 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); @@ -1137,7 +1073,7 @@ 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 { @@ -1164,7 +1100,7 @@ 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"); goto close_fd; @@ -1176,12 +1112,11 @@ 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) @@ -1204,9 +1139,9 @@ 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; @@ -1229,7 +1164,7 @@ 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) @@ -1259,8 +1194,7 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl const char *rae = "retain an asynchronous event"; const char *raw = "output in raw format"; const char *uuid_index = "UUID index"; - int err = -1, fd; - unsigned char *log; + int err, fd; struct config { __u16 lsi; @@ -1279,9 +1213,9 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl .namespace_id = NVME_NSID_ALL, .log_id = 0xff, .log_len = 0, - .lpo = NVME_NO_LOG_LPO, - .lsp = NVME_NO_LOG_LSP, - .lsi = 0, + .lpo = NVME_LOG_LPO_NONE, + .lsp = NVME_LOG_LSP_NONE, + .lsi = NVME_LOG_LSI_NONE, .rae = 0, .uuid_index = 0, }; @@ -1311,49 +1245,35 @@ 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; - goto close_fd; - } - - if (cfg.lsp > 16) { - fprintf(stderr, "invalid lsp param: %u\n", cfg.lsp); - errno = EINVAL; - err = -1; - goto close_fd; - } + err = -EINVAL; + } else { + unsigned char *log; - if (cfg.uuid_index > 128) { - fprintf(stderr, "invalid uuid index param: %u\n", cfg.uuid_index); - errno = EINVAL; - err = -1; - goto close_fd; - } + log = malloc(cfg.log_len); + if (!log) { + perror("could not alloc buffer for log\n"); + err = -ENOMEM; + goto close_fd; + } - log = malloc(cfg.log_len); - if (!log) { - perror("could not alloc buffer for log\n"); - err = -ENOMEM; - goto close_fd; + err = nvme_get_log(fd, cfg.log_id, cfg.namespace_id, + cfg.lpo, cfg.lsp, cfg.lsi, cfg.rae, + cfg.uuid_index, NVME_CSI_NVM, + cfg.log_len, log); + if (!err) { + if (!cfg.raw_binary) { + printf("Device:%s log-id:%d namespace-id:%#x\n", + 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"); + free(log); } - - err = nvme_get_log14(fd, cfg.namespace_id, cfg.log_id, - cfg.lsp, cfg.lpo, cfg.lsi, cfg.rae, - cfg.uuid_index, cfg.log_len, log); - if (!err) { - if (!cfg.raw_binary) { - printf("Device:%s log-id:%d namespace-id:%#x\n", - 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"); - free(log); - close_fd: close(fd); ret: @@ -1368,7 +1288,7 @@ 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; @@ -1402,7 +1322,7 @@ 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) @@ -1421,8 +1341,8 @@ 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 { @@ -1433,6 +1353,7 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin * struct config cfg = { .cntid = 0, + .namespace_id = NVME_NSID_NONE, .output_format = "normal", }; @@ -1457,13 +1378,13 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin * 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 (!err) + 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); @@ -1484,8 +1405,8 @@ 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 { @@ -1521,16 +1442,19 @@ 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.all) + err = nvme_identify_allocated_ns_list(fd, cfg.namespace_id, + &ns_list); + else + err = nvme_identify_active_ns_list(fd, cfg.namespace_id, + &ns_list); if (!err) - nvme_show_list_ns(ns_list, flags); + nvme_show_list_ns(&ns_list, flags); else if (err > 0) nvme_show_status(err); else @@ -1551,7 +1475,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; @@ -1560,7 +1484,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) = { @@ -1574,14 +1498,14 @@ 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"); 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); @@ -1598,7 +1522,8 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin * static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, struct command *cmd) { - int err = -1, num, i, fd, list[2048]; + int err, num, fd, list[2048]; + struct nvme_ctrl_list cntlist; __u16 ctrlist[2048]; const char *namespace_id = "namespace to attach"; @@ -1627,8 +1552,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; } @@ -1640,15 +1564,16 @@ 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]; + 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); @@ -1702,7 +1627,7 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * 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; @@ -1724,7 +1649,7 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * .anagrpid = 0, .nvmsetid = 0, .bs = 0x00, - .timeout = NVME_IOCTL_TIMEOUT, + .timeout = 120000, }; OPT_ARGS(opts) = { @@ -1748,8 +1673,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) { @@ -1757,11 +1681,10 @@ 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"); @@ -1786,14 +1709,13 @@ 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); + nvme_init_id_ns(&ns, cfg.nsze, cfg.ncap, cfg.flbas, cfg.dps, cfg.nmic, + cfg.anagrpid, cfg.nvmsetid); + err = nvme_ns_mgmt_create(fd, &ns, &nsid, cfg.timeout); if (!err) printf("%s: Success, created nsid:%d\n", cmd->name, nsid); else if (err > 0) @@ -1807,16 +1729,33 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * return nvme_status_to_errno(err, false); } +static bool nvme_match_device_filter(nvme_subsystem_t s) +{ + nvme_ctrl_t c; + nvme_ns_t n; + + if (!devicename || !strlen(devicename)) + return true; + + nvme_subsystem_for_each_ctrl(s, c) + if (!strcmp(devicename, nvme_ctrl_get_name(c))) + return true; + + nvme_subsystem_for_each_ns(s, n) + if (!strcmp(devicename, nvme_ns_get_name(n))) + 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; 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; + int err; struct config { char *output_format; @@ -1839,68 +1778,34 @@ 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); - if (err) { - fprintf(stderr, "Failed to scan namespaces\n"); - goto free; + if (devicename) + r = nvme_scan_filter(nvme_match_device_filter); + else + r = nvme_scan(NULL); + + if (r) { + nvme_show_subsystem_list(r, flags); + nvme_free_tree(r); + } else { + if (devicename) + fprintf(stderr, "Failed to scan nvme subsystem for %s\n", devicename); + else + fprintf(stderr, "Failed to scan nvme subsystem\n"); + err = -errno; } - nvme_show_subsystem_list(&t, flags); -free: - free_topology(&t); - free(subsysnqn); ret: return nvme_status_to_errno(err, false); } @@ -1910,9 +1815,9 @@ static int list(int argc, char **argv, struct command *cmd, struct plugin *plugi 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; @@ -1947,15 +1852,16 @@ 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"); - return err; + r = nvme_scan(NULL); + if (r) { + nvme_show_list_items(r, flags); + nvme_free_tree(r); + } else { + fprintf(stderr, "Failed to scan nvme subsystems\n"); + err = -errno; } - nvme_show_list_items(&t, flags); - free_topology(&t); - return 0; + return err; } int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, @@ -1971,7 +1877,7 @@ 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; @@ -2043,7 +1949,7 @@ static int nvm_id_ctrl(int argc, char **argv, struct command *cmd, }; 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() }; @@ -2055,7 +1961,7 @@ 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) @@ -2076,7 +1982,7 @@ 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 { @@ -2108,7 +2014,7 @@ 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"); goto close_fd; @@ -2117,8 +2023,7 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p if (posix_memalign(&nsdescs, getpagesize(), 0x1000)) { fprintf(stderr, "can not allocate controller list payload\n"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fd; } @@ -2150,7 +2055,7 @@ 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; @@ -2191,14 +2096,18 @@ 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"); 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); else if (err > 0) @@ -2219,7 +2128,7 @@ 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; @@ -2244,8 +2153,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; } @@ -2271,9 +2179,9 @@ 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; @@ -2299,7 +2207,7 @@ 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) @@ -2323,7 +2231,7 @@ 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; @@ -2372,26 +2280,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; }; struct config cfg = { .cntid = 0xffff, - .output_format = "normal", }; 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() }; @@ -2401,22 +2302,15 @@ 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"); -close_fd: close(fd); ret: return nvme_status_to_errno(err, false); @@ -2424,8 +2318,9 @@ static int id_iocs(int argc, char **argv, struct command *cmd, struct plugin *pl 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."; + int err = 0, fd; + unsigned nsid; OPT_ARGS(opts) = { OPT_END() @@ -2435,8 +2330,8 @@ 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) { + err = nvme_get_nsid(fd, &nsid); + if (err <= 0) { perror(devicename); err = errno; goto close_fd; @@ -2467,8 +2362,8 @@ 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; @@ -2496,9 +2391,7 @@ 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); + err = nvme_virtual_mgmt(fd, cfg.act, cfg.rt, cfg.cntlid, cfg.nr, &result); if (!err) { printf("success, Number of Controller Resources Modified "\ "(NRM):%#x\n", result); @@ -2514,25 +2407,29 @@ static int virtual_mgmt(int argc, char **argv, struct command *cmd, struct plugi 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 { + __u16 cntlid; char *output_format; int human_readable; }; struct config cfg = { + .cntlid = 0, .output_format = "normal", }; 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() @@ -2548,9 +2445,9 @@ 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 @@ -2569,9 +2466,9 @@ 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; @@ -2605,15 +2502,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; } @@ -2644,7 +2539,7 @@ 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; @@ -2666,7 +2561,7 @@ 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); + err = nvme_dev_self_test(fd, cfg.namespace_id, cfg.stc); if (!err) { if (cfg.stc == 0xf) printf("Aborting device self-test operation\n"); @@ -2693,10 +2588,9 @@ 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; @@ -2705,7 +2599,7 @@ static int self_test_log(int argc, char **argv, struct command *cmd, struct plug }; struct config cfg = { - .dst_entries = NVME_ST_REPORTS, + .dst_entries = NVME_LOG_ST_MAX_RESULTS, .output_format = "normal", }; @@ -2726,10 +2620,9 @@ 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); @@ -2760,7 +2653,7 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin 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; + int err, fd; __u32 result; void *buf = NULL; @@ -2801,7 +2694,7 @@ 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"); @@ -2814,14 +2707,12 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin if (cfg.sel > 7) { fprintf(stderr, "invalid 'select' param:%d\n", cfg.sel); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } @@ -2832,11 +2723,7 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin goto close_fd; } - 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; + nvme_get_feature_length(cfg.feature_id, cfg.cdw11, &cfg.data_len); if (cfg.sel == 3) cfg.data_len = 0; @@ -2844,22 +2731,20 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin if (cfg.data_len) { if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { fprintf(stderr, "can not allocate feature payload\n"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; 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); + err = nvme_get_features(fd, cfg.feature_id, cfg.namespace_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); + printf("get-feature:%#02x (%s), %s value:%#08x\n", cfg.feature_id, + nvme_feature_to_string(cfg.feature_id), + nvme_select_to_string(cfg.sel), result); if (cfg.sel == 3) nvme_show_select_result(result); else if (cfg.human_readable) @@ -2894,7 +2779,7 @@ 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; @@ -2928,8 +2813,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; } @@ -2942,8 +2826,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; } @@ -2957,8 +2840,7 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin if (!fw_buf) { perror("No memory for f/w size:\n"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_fw_fd; } @@ -3017,7 +2899,7 @@ 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; struct config { __u8 slot; @@ -3044,20 +2926,17 @@ 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; } @@ -3096,7 +2975,7 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin * 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() @@ -3123,7 +3002,7 @@ static int subsystem_reset(int argc, char **argv, struct command *cmd, struct pl 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() @@ -3133,7 +3012,7 @@ 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"); @@ -3174,7 +3053,7 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p const char *sanact_desc = "Sanitize action."; const char *ovrpat_desc = "Overwrite pattern."; - int fd, ret = -1; + int fd, ret; struct config { int no_dealloc; @@ -3209,44 +3088,40 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p 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; + ret = -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; + ret = -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"); + ret = -EINVAL; goto close_fd; } } else { if (cfg.owpass || cfg.oipbp || cfg.ovrpat) { fprintf(stderr, "SANACT is not Overwrite\n"); - errno = EINVAL; - ret = -1; + ret = -EINVAL; goto close_fd; } } - ret = nvme_sanitize(fd, cfg.sanact, cfg.ause, cfg.owpass, cfg.oipbp, + ret = nvme_sanitize_nvm(fd, cfg.sanact, cfg.ause, cfg.owpass, cfg.oipbp, cfg.no_dealloc, cfg.ovrpat); if (ret < 0) perror("sanitize"); @@ -3259,6 +3134,82 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p return nvme_status_to_errno(ret, false); } +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;) { + err = nvme_get_property(fd, offset, &value); + 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) { const char *desc = "Reads and shows the defined NVMe controller registers "\ @@ -3267,8 +3218,9 @@ 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 { @@ -3291,6 +3243,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; @@ -3299,7 +3252,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; @@ -3314,6 +3267,7 @@ 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); } @@ -3326,8 +3280,8 @@ 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; @@ -3351,8 +3305,7 @@ 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; } @@ -3377,7 +3330,7 @@ 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; @@ -3401,14 +3354,12 @@ 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; } @@ -3435,8 +3386,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"; @@ -3447,7 +3397,7 @@ 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; @@ -3496,8 +3446,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu 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) { @@ -3505,8 +3454,7 @@ 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; } } @@ -3525,7 +3473,7 @@ 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"); goto close_fd; @@ -3537,13 +3485,12 @@ 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"); @@ -3569,8 +3516,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) @@ -3582,32 +3528,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; } @@ -3623,8 +3564,8 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu 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); + err = nvme_format_nvm(fd, cfg.namespace_id, cfg.lbaf, cfg.ms, cfg.pi, + cfg.pil, cfg.ses, cfg.timeout); if (err < 0) perror("format"); else if (err != 0) @@ -3663,7 +3604,7 @@ 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: @@ -3694,7 +3635,7 @@ 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; @@ -3739,7 +3680,7 @@ 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"); @@ -3752,8 +3693,7 @@ 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; } @@ -3764,13 +3704,14 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin goto close_fd; } - cfg.data_len = nvme_feat_buf_len[cfg.feature_id]; + if (!cfg.data_len) + 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); @@ -3778,16 +3719,15 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin if (buf) { /* if feature ID is 0x0E, get timestamp value by -v option */ - 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; + err = -EINVAL; goto free; } } @@ -3799,7 +3739,7 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin goto close_ffd; } /* if feature ID is 0x0E, then change string from file to integer */ - if (NVME_FEAT_TIMESTAMP == cfg.feature_id) { + if (NVME_FEAT_FID_TIMESTAMP == cfg.feature_id) { number = strtoul(buf, &endptr, STRTOUL_AUTO_BASE); memset(buf, 0, cfg.data_len); memcpy(buf, &number, NVME_FEAT_TIMESTAMP_DATA_SIZE); @@ -3807,21 +3747,20 @@ 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); + err = nvme_set_features(fd, cfg.feature_id, cfg.namespace_id, cfg.value, + cfg.cdw12, cfg.save, cfg.uuid_index, 0, + cfg.data_len, buf, &result); if (err < 0) { perror("set-feature"); } 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) { + printf("set-feature:%#02x (%s), value:%#08"PRIx64", cdw12:%#08"PRIx32", \ + save:%#x\n", cfg.feature_id, nvme_feature_to_string(cfg.feature_id), + (uint64_t)cfg.value, cfg.cdw12, cfg.save); + 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 @@ -3854,7 +3793,7 @@ 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; @@ -3868,7 +3807,7 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p }; struct config cfg = { - .file = "", + .file = NULL, .secp = 0, .spsp = 0, .tl = 0, @@ -3892,8 +3831,7 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p if (sec_fd < 0) { fprintf(stderr, "Failed to open %s: %s\n", cfg.file, strerror(errno)); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } @@ -3906,8 +3844,7 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p 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; + err = -ENOMEM; goto close_sec_fd; } @@ -3919,8 +3856,8 @@ 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_size, sec_buf); + err = nvme_security_send(fd, cfg.namespace_id, cfg.nssf, cfg.spsp & 0xff, + cfg.spsp >> 8, cfg.secp, cfg.tl, sec_size, sec_buf, NULL); if (err < 0) perror("security-send"); else if (err != 0) @@ -3951,7 +3888,7 @@ 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; + int err, fd; __u32 result; __u32 dw12 = 0; void *buf = NULL; @@ -3999,48 +3936,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); @@ -4052,8 +3984,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; } } @@ -4066,8 +3997,8 @@ 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); + err = nvme_directive_send(fd, cfg.namespace_id, cfg.dspec, cfg.doper, + cfg.dtype, dw12, cfg.data_len, buf, &result); if (err < 0) { perror("dir-send"); goto close_ffd; @@ -4096,7 +4027,7 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p 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"; @@ -4127,7 +4058,7 @@ 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"); goto close_fd; @@ -4151,7 +4082,7 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin 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."; @@ -4207,21 +4138,19 @@ 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.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"); goto close_fd; @@ -4258,12 +4187,12 @@ 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; @@ -4303,19 +4232,18 @@ 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)); + 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, 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"); goto close_fd; @@ -4324,15 +4252,8 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin 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); + err = nvme_dsm(fd, cfg.namespace_id, cfg.cdw11, nr, dsm); if (err < 0) perror("data-set management"); else if (err != 0) @@ -4340,8 +4261,6 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin else printf("NVMe DSM: success\n"); - free(dsm); - close_fd: close(fd); ret: @@ -4373,14 +4292,14 @@ 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; @@ -4438,35 +4357,28 @@ 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"); 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; - } + nvme_init_copy_range(copy, nlbs, slbas, eilbrts, elbatms, elbats, nr); err = nvme_copy(fd, cfg.namespace_id, copy, cfg.sdlba, nr, cfg.prinfor, cfg.prinfow, cfg.dtype, cfg.dspec, cfg.format, cfg.lr, @@ -4478,8 +4390,6 @@ static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugi else printf("NVMe Copy: success\n"); - free(copy); - close_fd: close(fd); ret: @@ -4494,7 +4404,7 @@ 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; @@ -4514,7 +4424,7 @@ 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"); goto close_fd; @@ -4548,7 +4458,7 @@ 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; @@ -4582,7 +4492,7 @@ 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"); goto close_fd; @@ -4590,8 +4500,7 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi } if (cfg.racqa > 7) { fprintf(stderr, "invalid racqa:%d\n", cfg.racqa); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } @@ -4621,7 +4530,7 @@ 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; @@ -4655,7 +4564,7 @@ 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"); goto close_fd; @@ -4663,15 +4572,13 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug } 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; } @@ -4705,7 +4612,7 @@ 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; @@ -4737,7 +4644,7 @@ 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"); goto close_fd; @@ -4745,8 +4652,7 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi } if (cfg.rrela > 7) { fprintf(stderr, "invalid rrela:%d\n", cfg.rrela); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } @@ -4777,9 +4683,9 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin const char *cdw11 = "command dword 11 value"; 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; @@ -4816,7 +4722,7 @@ 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"); goto close_fd; @@ -4832,8 +4738,7 @@ 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); @@ -4865,7 +4770,7 @@ 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; @@ -4877,6 +4782,7 @@ static int submit_io(int opcode, char *command, const char *desc, struct nvme_id_ns ns; __u8 lba_index, ms = 0; + 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"; @@ -4897,6 +4803,7 @@ static int submit_io(int opcode, char *command, const char *desc, const char *dsm = "dataset management attributes (lower 16 bits)"; struct config { + __u32 namespace_id; __u64 start_block; __u16 block_count; __u64 data_size; @@ -4931,6 +4838,7 @@ static int submit_io(int opcode, char *command, const char *desc, }; OPT_ARGS(opts) = { + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), OPT_SUFFIX("start-block", 's', &cfg.start_block, start_block), OPT_SHRT("block-count", 'c', &cfg.block_count, block_count), OPT_SUFFIX("data-size", 'z', &cfg.data_size, data_size), @@ -4956,25 +4864,32 @@ static int submit_io(int opcode, char *command, const char *desc, if (fd < 0) goto ret; + if (!cfg.namespace_id) { + err = nvme_get_nsid(fd, &cfg.namespace_id); + if (err < 0) { + perror("get-namespace-id"); + goto close_fd; + } + err = -1; + } + 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.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; @@ -4985,8 +4900,7 @@ 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; @@ -4995,16 +4909,14 @@ static int submit_io(int opcode, char *command, const char *desc, 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; } @@ -5022,18 +4934,17 @@ 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); + err = nvme_get_nsid(fd, &nsid); if (err < 0) { perror("get-namespace-id"); goto close_mfd; } - err = nvme_identify_ns(fd, nsid, false, &ns); + err = nvme_identify_ns(fd, nsid, &ns); if (err) { nvme_show_status(err); goto free_buffer; @@ -5053,8 +4964,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); @@ -5097,8 +5007,16 @@ static int submit_io(int opcode, char *command, const char *desc, goto free_mbuffer; gettimeofday(&start_time, NULL); - err = nvme_io(fd, opcode, cfg.start_block, cfg.block_count, control, dsmgmt, - cfg.ref_tag, cfg.app_tag, cfg.app_tag_mask, buffer, mbuffer); + if (opcode & 1) + err = nvme_write(fd, cfg.namespace_id, cfg.start_block, + cfg.block_count, control, dsmgmt, 0, cfg.ref_tag, + cfg.app_tag, cfg.app_tag_mask, buffer_size, buffer, + cfg.metadata_size, mbuffer); + else + err = nvme_read(fd, cfg.namespace_id, cfg.start_block, + cfg.block_count, control, dsmgmt, cfg.ref_tag, + cfg.app_tag, cfg.app_tag_mask, buffer_size, buffer, + cfg.metadata_size, mbuffer); gettimeofday(&end_time, NULL); if (cfg.latency) printf(" latency: %s: %llu us\n", @@ -5111,14 +5029,12 @@ static int submit_io(int opcode, char *command, const char *desc, 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); } @@ -5163,7 +5079,7 @@ 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"; @@ -5218,20 +5134,18 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin goto err; 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.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"); goto close_fd; @@ -5268,7 +5182,7 @@ 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 { @@ -5307,14 +5221,13 @@ 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); + err = nvme_security_receive(fd, cfg.namespace_id, cfg.nssf, cfg.spsp & 0xff, + cfg.spsp >> 8, cfg.secp, cfg.al, cfg.size, sec_buf, NULL); if (err < 0) perror("security receive"); else if (err != 0) @@ -5353,7 +5266,7 @@ 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 { @@ -5397,8 +5310,7 @@ 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; } @@ -5406,13 +5318,12 @@ static int get_lba_status(int argc, char **argv, struct command *cmd, 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); + cfg.atype, cfg.rl, buf); if (!err) nvme_show_lba_status(buf, buf_len, flags); else if (err > 0) @@ -5440,7 +5351,7 @@ 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; @@ -5487,57 +5398,53 @@ 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); + err = nvme_directive_recv(fd, cfg.namespace_id, cfg.dspec, cfg.doper, + cfg.dtype, dw12, cfg.data_len, buf, &result); if (!err) nvme_directive_show(cfg.dtype, cfg.doper, cfg.dspec, cfg.namespace_id, result, buf, cfg.data_len, @@ -5561,8 +5468,8 @@ static int rpmb_cmd(int argc, char **argv, struct command *cmd, struct plugin *p return rpmb_cmd_option(argc, argv, cmd, plugin); } -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"; @@ -5589,7 +5496,7 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type, const char *latency = "output latency statistics"; void *data = NULL, *metadata = NULL; - int err = -1, wfd = STDIN_FILENO, fd; + int err = 0, wfd = STDIN_FILENO, fd; __u32 result; bool huge; const char *cmd_name = NULL; @@ -5677,8 +5584,7 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type, S_IRUSR | S_IRGRP | S_IROTH); if (wfd < 0) { perror(cfg.input_file); - errno = EINVAL; - err = -1; + err = -EINVAL; goto close_fd; } } @@ -5687,8 +5593,7 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type, metadata = malloc(cfg.metadata_len); if (!metadata) { perror("can not allocate metadata payload\n"); - errno = ENOMEM; - err = -1; + err = -ENOMEM; goto close_wfd; } memset(metadata, cfg.prefill, cfg.metadata_len); @@ -5697,8 +5602,7 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type, 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; } @@ -5713,8 +5617,7 @@ 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) { @@ -5750,17 +5653,24 @@ 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); + 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, metadata, - cfg.timeout, &result); + cfg.cdw11, cfg.cdw12, cfg.cdw13, cfg.cdw14, + cfg.cdw15, cfg.data_len, data, cfg.metadata_len, + metadata, 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)); @@ -5770,7 +5680,7 @@ static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type, 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) { @@ -5796,40 +5706,28 @@ static int io_passthru(int argc, char **argv, struct command *cmd, struct 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; } @@ -5837,45 +5735,50 @@ 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, hostnqn); + free(hostnqn); + + 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); } void register_extension(struct plugin *plugin) diff --git a/nvme.h b/nvme.h index 592ba52fa0..50e7bdf772 100644 --- a/nvme.h +++ b/nvme.h @@ -78,4 +78,13 @@ void nvme_free(void *p, bool huge); unsigned long long elapsed_utime(struct timeval start_time, struct timeval end_time); + +/* nvme-print.c */ +const char *nvme_status_to_string(uint16_t status); +const char *nvme_select_to_string(int sel); + +void d(unsigned char *buf, int len, int width, int group); +void d_raw(unsigned char *buf, unsigned len); +uint64_t int48_to_long(uint8_t *data); + #endif /* _NVME_H */ diff --git a/plugins/amzn/amzn-nvme.c b/plugins/amzn/amzn-nvme.c index 9217586c95..6400bb28ad 100644 --- a/plugins/amzn/amzn-nvme.c +++ b/plugins/amzn/amzn-nvme.c @@ -5,14 +5,9 @@ #include #include -#include "linux/nvme_ioctl.h" - #include "common.h" #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" #include "argconfig.h" diff --git a/plugins/dera/dera-nvme.c b/plugins/dera/dera-nvme.c index a91d658b89..7f9e7760d2 100644 --- a/plugins/dera/dera-nvme.c +++ b/plugins/dera/dera-nvme.c @@ -10,10 +10,7 @@ #include #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" #include "argconfig.h" @@ -110,7 +107,7 @@ static int nvme_dera_get_device_status(int fd, enum dera_device_status *result) .cdw12 = 0x104, }; - err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &cmd); + err = nvme_submit_admin_passthru(fd, &cmd, NULL); if (!err && result) { *result = cmd.result; } @@ -133,8 +130,7 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin if (fd < 0) return fd; - err = nvme_get_log(fd, 0xffffffff, 0xc0, false, NVME_NO_LOG_LSP, - sizeof(log), &log); + err = nvme_get_log_simple(fd, 0xc0, sizeof(log), &log); if (err) { goto exit; } diff --git a/plugins/huawei/huawei-nvme.c b/plugins/huawei/huawei-nvme.c index 05c6336f6d..b7e65c50a2 100644 --- a/plugins/huawei/huawei-nvme.c +++ b/plugins/huawei/huawei-nvme.c @@ -26,18 +26,12 @@ #include -#include "linux/nvme_ioctl.h" - #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" #include "argconfig.h" #include "suffix.h" -#include #define CREATE_CMD #include "huawei-nvme.h" @@ -52,7 +46,7 @@ struct huawei_list_item { char node[1024]; struct nvme_id_ctrl ctrl; - int nsid; + unsigned nsid; struct nvme_id_ns ns; unsigned block; char ns_name[NS_NAME_LEN]; @@ -89,8 +83,8 @@ static int huawei_get_nvme_info(int fd, struct huawei_list_item *item, const cha } item->huawei_device = true; - item->nsid = nvme_get_nsid(fd); - err = nvme_identify_ns(fd, item->nsid, 0, &item->ns); + err = nvme_get_nsid(fd, &item->nsid); + err = nvme_identify_ns(fd, item->nsid, &item->ns); if (err) return err; @@ -322,7 +316,7 @@ static int huawei_list(int argc, char **argv, struct command *command, if (fmt != JSON && fmt != NORMAL) return -EINVAL; - n = scandir("/dev", &devices, scan_namespace_filter, alphasort); + n = scandir("/dev", &devices, nvme_namespace_filter, alphasort); if (n <= 0) return n; diff --git a/plugins/intel/intel-nvme.c b/plugins/intel/intel-nvme.c index 59fbd94556..d3cbca7283 100644 --- a/plugins/intel/intel-nvme.c +++ b/plugins/intel/intel-nvme.c @@ -5,15 +5,11 @@ #include #include -#include "linux/nvme_ioctl.h" - #include "common.h" #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" +#include "linux/types.h" #include "argconfig.h" #include "suffix.h" @@ -372,8 +368,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, if (fd < 0) return fd; - err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, - NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log); + err = nvme_get_log_simple(fd, 0xca, sizeof(smart_log), &smart_log); if (!err) { if (cfg.json) show_intel_smart_log_jsn(&smart_log, cfg.namespace_id, devicename); @@ -412,8 +407,7 @@ static int get_market_log(int argc, char **argv, struct command *cmd, struct plu if (fd < 0) return fd; - err = nvme_get_log(fd, NVME_NSID_ALL, 0xdd, false, - NVME_NO_LOG_LSP, sizeof(log), log); + err = nvme_get_log_simple(fd, 0xdd, sizeof(log), log); if (!err) { if (!cfg.raw_binary) printf("Intel Marketing Name Log:\n%s\n", log); @@ -474,8 +468,7 @@ static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct if (fd < 0) return fd; - err = nvme_get_log(fd, NVME_NSID_ALL, 0xc5, false, - NVME_NO_LOG_LSP, sizeof(stats), &stats); + err = nvme_get_log_simple(fd, 0xc5, sizeof(stats), &stats); if (!err) { if (!cfg.raw_binary) show_temp_stats(&stats); @@ -1057,9 +1050,8 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct return fd; /* Query maj and minor version first */ - err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1, - false, NVME_NO_LOG_LSP, sizeof(media_version), - media_version); + err = nvme_get_log_simple(fd, cfg.write ? 0xc2 : 0xc1, + sizeof(media_version), media_version); if (err) goto close_fd; @@ -1067,7 +1059,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct __u32 thresholds[OPTANE_V1000_BUCKET_LEN] = {0}; __u32 result; - err = nvme_get_feature(fd, 0, 0xf7, 0, cfg.write ? 0x1 : 0x0, 0, + err = nvme_get_features(fd, 0xf7, 0, 0, cfg.write ? 0x1 : 0x0, 0, sizeof(thresholds), thresholds, &result); if (err) { fprintf(stderr, "Quering thresholds failed. NVMe Status:%s(%x)\n", @@ -1085,13 +1077,11 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct } - err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1, - false, NVME_NO_LOG_LSP, sizeof(v1000_stats), - &v1000_stats); + err = nvme_get_log_simple(fd, cfg.write ? 0xc2 : 0xc1, + sizeof(v1000_stats), &v1000_stats); } else { - err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1, - false, NVME_NO_LOG_LSP, sizeof(stats), - &stats); + err = nvme_get_log_simple(fd, cfg.write ? 0xc2 : 0xc1, + sizeof(stats), &stats); } if (!err) { @@ -1215,7 +1205,7 @@ static int read_entire_cmd(struct nvme_passthru_cmd *cmd, int total_size, dword_tfer = min(max_tfer, total_size); while (total_size > 0) { - err = nvme_submit_admin_passthru(ioctl_fd, cmd); + err = nvme_submit_admin_passthru(ioctl_fd, cmd, NULL); if (err) { fprintf(stderr, "failed on cmd.data_len %u cmd.cdw13 %u cmd.cdw12 %x cmd.cdw10 %u err %x remaining size %d\n", @@ -1544,7 +1534,7 @@ static int enable_lat_stats_tracking(int argc, char **argv, return fd; switch (option) { case None: - err = nvme_get_feature(fd, nsid, fid, sel, cdw11, 0, data_len, buf, + err = nvme_get_features(fd, fid, nsid, sel, cdw11, 0, data_len, buf, &result); if (!err) { printf( @@ -1557,8 +1547,8 @@ static int enable_lat_stats_tracking(int argc, char **argv, break; case True: case False: - err = nvme_set_feature(fd, nsid, fid, option, cdw12, save, 0, - data_len, buf, &result); + err = nvme_set_features(fd, fid, nsid, option, cdw12, save, 0, + 0, data_len, buf, &result); if (err > 0) { fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); @@ -1617,9 +1607,8 @@ static int set_lat_stats_thresholds(int argc, char **argv, * valid buckets a user is allowed to modify. Read or write doesn't * matter */ - err = nvme_get_log(fd, NVME_NSID_ALL, 0xc2, - false, NVME_NO_LOG_LSP, sizeof(media_version), - media_version); + err = nvme_get_log_simple(fd, 0xc2, + sizeof(media_version), media_version); if (err) { fprintf(stderr, "Querying media version failed. NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); @@ -1637,9 +1626,10 @@ static int set_lat_stats_thresholds(int argc, char **argv, } - err = nvme_set_feature(fd, nsid, fid, cfg.write ? 0x1 : 0x0, - cdw12, save, 0, OPTANE_V1000_BUCKET_LEN, - thresholds, &result); + err = nvme_set_features(fd, fid, nsid, cfg.write ? 0x1 : 0x0, + cdw12, save, 0, 0, + OPTANE_V1000_BUCKET_LEN, + thresholds, &result); if (err > 0) { fprintf(stderr, "NVMe Status:%s(%x)\n", diff --git a/plugins/memblaze/memblaze-nvme.c b/plugins/memblaze/memblaze-nvme.c index f6fbc802d1..118a756fe3 100644 --- a/plugins/memblaze/memblaze-nvme.c +++ b/plugins/memblaze/memblaze-nvme.c @@ -5,13 +5,8 @@ #include #include -#include "linux/nvme_ioctl.h" - #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" #include "argconfig.h" @@ -467,8 +462,8 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm if (fd < 0) return fd; - err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, - NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log); + err = nvme_get_nsid_log(fd, 0xca, cfg.namespace_id, + sizeof(smart_log), &smart_log); if (!err) { if (!cfg.raw_binary) err = show_memblaze_smart_log(fd, cfg.namespace_id, devicename, &smart_log); @@ -505,7 +500,7 @@ static int mb_get_powermanager_status(int argc, char **argv, struct command *cmd fd = parse_and_open(argc, argv, desc, opts); if (fd < 0) return fd; - err = nvme_get_feature(fd, 0, feature_id, 0, 0, 0, 0, NULL, &result); + err = nvme_get_features(fd, feature_id, 0, 0, 0, 0, 0, NULL, &result); if (err < 0) { perror("get-feature"); } @@ -547,7 +542,8 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd fd = parse_and_open(argc, argv, desc, opts); if (fd < 0) return fd; - err = nvme_set_feature(fd, 0, cfg.feature_id, cfg.value, 0, cfg.save, 0, 0, NULL, &result); + err = nvme_set_features(fd, cfg.feature_id, 0, cfg.value, 0, cfg.save, + 0, 0, 0, NULL, &result); if (err < 0) { perror("set-feature"); } @@ -604,7 +600,8 @@ static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, s } cfg.value = (param1 << MB_FEAT_HIGH_LATENCY_VALUE_SHIFT) | param2; - err = nvme_set_feature(fd, 0, cfg.feature_id, cfg.value, 0, 0, 0, 0, NULL, &result); + err = nvme_set_features(fd, cfg.feature_id, 0, cfg.value, 0, 0, 0, 0, 0, + NULL, &result); if (err < 0) { perror("set-feature"); } @@ -723,11 +720,11 @@ static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd, if (fd < 0) return fd; glp_high_latency_show_bar(fdi, DO_PRINT_FLAG); - err = nvme_get_log(fd, NVME_NSID_ALL, GLP_ID_VU_GET_HIGH_LATENCY_LOG, 0, NVME_NO_LOG_LSP, sizeof(buf), &buf); + err = nvme_get_log_simple(fd, GLP_ID_VU_GET_HIGH_LATENCY_LOG, sizeof(buf), &buf); - while ( 1) { + while (1) { if (!glp_high_latency(fdi, buf, LOG_PAGE_SIZE, DO_PRINT_FLAG)) break; - err = nvme_get_log(fd, NVME_NSID_ALL, GLP_ID_VU_GET_HIGH_LATENCY_LOG, 0, NVME_NO_LOG_LSP, sizeof(buf), &buf); + err = nvme_get_log_simple(fd, GLP_ID_VU_GET_HIGH_LATENCY_LOG, sizeof(buf), &buf); if ( err) { fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); break; @@ -741,13 +738,13 @@ static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd, static int memblaze_fw_commit(int fd, int select) { - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_activate_fw, + struct nvme_passthru_cmd cmd = { + .opcode = nvme_admin_fw_commit, .cdw10 = 8, .cdw12 = select, }; - return nvme_submit_admin_passthru(fd, &cmd); + return nvme_submit_admin_passthru(fd, &cmd, NULL); } static int mb_selective_download(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -996,7 +993,7 @@ static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, st fd = parse_and_open(argc, argv, desc, opts); if (fd < 0) return fd; - err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1, false, NVME_NO_LOG_LSP, sizeof(stats), &stats); + err = nvme_get_log_simple(fd, cfg.write ? 0xc2 : 0xc1, sizeof(stats), &stats); if (!err) io_latency_histogram(cfg.write ? f2 : f1, stats, DO_PRINT_FLAG, cfg.write ? GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM : GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM); @@ -1030,17 +1027,18 @@ static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd, .save = 0, }; - OPT_ARGS(opts) = { - OPT_END() - }; + OPT_ARGS(opts) = { + OPT_END() + }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + return fd; - err = nvme_set_feature(fd, 0, cfg.feature_id, cfg.value, 0, cfg.save, 0, 0, NULL, &result); + err = nvme_set_features(fd, cfg.feature_id, 0, cfg.value, 0, cfg.save, + 0, 0, 0, NULL, &result); if (err < 0) { perror("set-feature"); } @@ -1117,8 +1115,8 @@ static int mb_set_lat_stats(int argc, char **argv, return fd; switch (option) { case None: - err = nvme_get_feature(fd, nsid, fid, sel, cdw11, 0, data_len, buf, - &result); + err = nvme_get_features(fd, nsid, fid, sel, cdw11, 0, + data_len, buf, &result); if (!err) { printf( "Latency Statistics Tracking (FID 0x%X) is currently (%i).\n", @@ -1130,8 +1128,8 @@ static int mb_set_lat_stats(int argc, char **argv, break; case True: case False: - err = nvme_set_feature(fd, nsid, fid, option, cdw12, save, 0, - data_len, buf, &result); + err = nvme_set_features(fd, fid, nsid, option, cdw12, save, + 0, 0, data_len, buf, &result); if (err > 0) { fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); @@ -1140,7 +1138,7 @@ static int mb_set_lat_stats(int argc, char **argv, fprintf(stderr, "Command failed while parsing.\n"); } else { printf("Successfully set enable bit for FID (0x%X) to %i.\n", - fid, option); + 0xe2, option); } break; default: diff --git a/plugins/micron/micron-nvme.c b/plugins/micron/micron-nvme.c index 32cecbb8e1..c50de546b6 100644 --- a/plugins/micron/micron-nvme.c +++ b/plugins/micron/micron-nvme.c @@ -10,12 +10,7 @@ #include #include #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-status.h" -#include "nvme-ioctl.h" -#include +#include "libnvme.h" #include #define CREATE_CMD #include "micron-nvme.h" @@ -313,8 +308,8 @@ static int GetLogPageSize(int nFD, unsigned char ucLogID, int *nLogSize) LogPageHeader_t *pLogHeader = NULL; if (ucLogID == 0xC1 || ucLogID == 0xC2 || ucLogID == 0xC4) { - err = nvme_get_log(nFD, NVME_NSID_ALL, ucLogID, false, NVME_NO_LOG_LSP, - CommonChunkSize, pTmpBuf); + err = nvme_get_log_simple(nFD, ucLogID, + CommonChunkSize, pTmpBuf); if (err == 0) { pLogHeader = (LogPageHeader_t *) pTmpBuf; LogPageHeader_t *pLogHeader1 = (LogPageHeader_t *) pLogHeader; @@ -336,7 +331,7 @@ static int GetLogPageSize(int nFD, unsigned char ucLogID, int *nLogSize) static int NVMEGetLogPage(int nFD, unsigned char ucLogID, unsigned char *pBuffer, int nBuffSize) { int err = 0; - struct nvme_admin_cmd cmd = { 0 }; + struct nvme_passthru_cmd cmd = { 0 }; unsigned int uiNumDwords = (unsigned int)nBuffSize / sizeof(unsigned int); unsigned int uiMaxChunk = uiNumDwords; unsigned int uiNumChunks = 1; @@ -382,7 +377,7 @@ static int NVMEGetLogPage(int nFD, unsigned char ucLogID, unsigned char *pBuffer cmd.addr = (__u64) (uintptr_t) pTempPtr; cmd.nsid = 0xFFFFFFFF; cmd.data_len = uiXferDwords * 4; - err = nvme_submit_passthru(nFD, NVME_IOCTL_ADMIN_CMD, &cmd); + err = nvme_submit_admin_passthru(nFD, &cmd, NULL); ullBytesRead += uiXferDwords * 4; pTempPtr = pBuffer + ullBytesRead; } @@ -424,8 +419,7 @@ static int GetCommonLogPage(int nFD, unsigned char ucLogID, goto exit_status; } memset(pTempPtr, 0, nBuffSize); - err = nvme_get_log(nFD, NVME_NSID_ALL, ucLogID, false, NVME_NO_LOG_LSP, - nBuffSize, pTempPtr); + err = nvme_get_log_simple(nFD, ucLogID, nBuffSize, pTempPtr); *pBuffer = pTempPtr; exit_status: @@ -456,8 +450,8 @@ static int micron_parse_options(int argc, char **argv, const char *desc, static int micron_fw_commit(int fd, int select) { - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_activate_fw, + struct nvme_passthru_cmd cmd = { + .opcode = nvme_admin_fw_commit, .cdw10 = 8, .cdw12 = select, }; @@ -629,7 +623,7 @@ static int micron_smbus_option(int argc, char **argv, if (!strcmp(opt.option, "enable")) { cdw11 = opt.value << 1 | 1; - err = nvme_set_feature(fd, 1, fid, cdw11, 0, opt.save, 0, 0, 0, &result); + err = nvme_set_features_simple(fd, fid, 1, cdw11, opt.save, &result); if (err == 0) { printf("successfully enabled SMBus on drive\n"); } else { @@ -638,7 +632,7 @@ static int micron_smbus_option(int argc, char **argv, } else if (!strcmp(opt.option, "status")) { cdw10 = opt.value; - err = nvme_get_feature(fd, 1, fid, cdw10, 0, 0, 0, 0, &result); + err = nvme_get_features(fd, fid, 1, 0, cdw10, 0, 0, NULL, &result); if (err == 0) { printf("SMBus status on the drive: %s (returns %s temperature) \n", (result & 1) ? "enabled" : "disabled", @@ -649,7 +643,7 @@ static int micron_smbus_option(int argc, char **argv, } else if (!strcmp(opt.option, "disable")) { cdw11 = opt.value << 1 | 0; - err = nvme_set_feature(fd, 1, fid, cdw11, 0, opt.save, 0, 0, 0, &result); + err = nvme_set_features_simple(fd, fid, 1, cdw11, opt.save, &result); if (err == 0) { printf("Successfully disabled SMBus on drive\n"); } else { @@ -700,7 +694,7 @@ static int micron_temp_stats(int argc, char **argv, struct command *cmd, if (strcmp(cfg.fmt, "json") == 0) is_json = true; - err = nvme_smart_log(fd, 0xffffffff, &smart_log); + err = nvme_get_log_smart(fd, 0xffffffff, false, &smart_log); if (!err) { temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]); temperature = temperature ? temperature - 273 : 0; @@ -935,11 +929,12 @@ static int micron_clear_pcie_correctable_errors(int argc, char **argv, /* For M51CX models, PCIe errors are cleared using 0xC3 feature */ if (model == M51CX) { - err = nvme_set_feature(fd, 0, fid, (1 << 31), 0, 0, 0, 0, 0, &result); + err = nvme_set_features_simple(fd, fid, 0, (1 << 31), false, &result); if (err == 0 && (err = (int)result) == 0) printf("Device correctable errors cleared!\n"); - else if (err > 0) - nvme_show_status(err); + else if (err > 0) + fprintf(stderr, "NVMe status: %s(%#x)\n", + nvme_status_to_string(err), err); else printf("Error clearing Device correctable errors = 0x%x\n", err); goto out; @@ -1274,13 +1269,13 @@ static void print_nand_stats_fb(__u8 *buf, __u8 *buf2, __u8 nsze, bool is_json, init_d0_log_page(buf2, nsze); if (is_json) { - for (int i = 0; i < 7; i++) { + for (int i = 4; i < 7; i++) { json_object_add_value_string(stats, - d0_log_page[i].field, - d0_log_page[i].datastr); + d0_log_page[i].field, + d0_log_page[i].datastr); } } else { - for (int i = 0; i < 7; i++) { + for (int i = 4; i < 7; i++) { printf("%-40s : %s\n", d0_log_page[i].field, d0_log_page[i].datastr); } } @@ -1371,37 +1366,37 @@ static int micron_nand_stats(int argc, char **argv, sscanf(argv[optind], "/dev/nvme%d", &ctrlIdx); if ((eModel = GetDriveModel(ctrlIdx)) == UNKNOWN_MODEL) { printf ("Unsupported drive model for vs-nand-stats command\n"); - err = -1; + err = -1; goto out; } - err = nvme_get_log(fd, NVME_NSID_ALL, 0xD0, false, NVME_NO_LOG_LSP, - D0_log_size, extSmartLog); + err = nvme_get_log_simple(fd, 0xD0, D0_log_size, extSmartLog); has_d0_log = (0 == err); /* should check for firmware version if this log is supported or not */ - if (eModel != M5407 && eModel != M5410) { - err = nvme_get_log(fd, NVME_NSID_ALL, 0xFB, false, NVME_NO_LOG_LSP, - FB_log_size, logFB); + if (eModel == M5407 || eModel == M5410) { + err = nvme_get_log_simple(fd, 0xFB, FB_log_size, logFB); has_fb_log = (0 == err); } nsze = (ctrl.vs[987] == 0x12); - if (nsze == 0 && nsze_from_oacs) nsze = ((ctrl.oacs >> 3) & 0x1); - + err = 0; if (has_fb_log) { __u8 spec = (eModel == M5410) ? 0 : 1; /* FB spec version */ print_nand_stats_fb((__u8 *)logFB, (__u8 *)extSmartLog, nsze, is_json, spec); } else if (has_d0_log) { print_nand_stats_d0((__u8 *)extSmartLog, nsze, is_json); - err = 0; + } else { + printf("Unable to retrieve extended smart log for the drive\n"); + err = -ENOTTY; } out: close(fd); if (err > 0) - nvme_show_status(err); + fprintf(stderr, "NVMe status: %s(%#x)\n", nvme_status_to_string(err), + err); return nvme_status_to_errno(err, false); } @@ -1489,7 +1484,7 @@ static void GetCtrlIDDInfo(const char *dir, struct nvme_id_ctrl *ctrlp) static void GetSmartlogData(int fd, const char *dir) { struct nvme_smart_log smart_log; - if (nvme_smart_log(fd, -1, &smart_log) == 0) { + if (nvme_get_log_smart(fd, -1, false, &smart_log) == 0) { WriteData((__u8*)&smart_log, sizeof(smart_log), dir, "smart_data.bin", "smart log"); } @@ -1504,7 +1499,7 @@ static void GetErrorlogData(int fd, int entries, const char *dir) if (error_log == NULL) return; - if (nvme_error_log(fd, entries, error_log) == 0) { + if (nvme_get_log_error(fd, entries, false, error_log) == 0) { WriteData((__u8*)error_log, logSize, dir, "error_information_log.bin", "error log"); } @@ -1515,50 +1510,50 @@ static void GetErrorlogData(int fd, int entries, const char *dir) static void GetGenericLogs(int fd, const char *dir) { struct nvme_self_test_log self_test_log; - struct nvme_firmware_log_page fw_log; - struct nvme_effects_log_page effects; - struct nvme_persistent_event_log_head pevent_log_head; + struct nvme_firmware_slot fw_log; + struct nvme_cmd_effects_log effects; + struct nvme_persistent_event_log pevent_log; void *pevent_log_info = NULL; __u32 log_len = 0; int err = 0 ; bool huge = false; /* get self test log */ - if (nvme_self_test_log(fd, sizeof(self_test_log), &self_test_log) == 0) { + if (nvme_get_log_device_self_test(fd, &self_test_log) == 0) { WriteData((__u8*)&self_test_log, sizeof(self_test_log), dir, "drive_self_test.bin", "self test log"); } /* get fw slot info log */ - if (nvme_fw_log(fd, &fw_log) == 0) { + if (nvme_get_log_fw_slot(fd, 1, &fw_log) == 0) { WriteData((__u8*)&fw_log, sizeof(fw_log), dir, "firmware_slot_info_log.bin", "firmware log"); } /* get effects log */ - if (nvme_effects_log(fd, &effects) == 0) { + if (nvme_get_log_cmd_effects(fd, NVME_CSI_NVM, &effects) == 0) { WriteData((__u8*)&effects, sizeof(effects), dir, "command_effects_log.bin", "effects log"); } /* get persistent event log */ - (void)nvme_persistent_event_log(fd, NVME_PEVENT_LOG_RELEASE_CTX, - sizeof(pevent_log_head), &pevent_log_head); - memset(&pevent_log_head, 0, sizeof(pevent_log_head)); - err = nvme_persistent_event_log(fd, NVME_PEVENT_LOG_EST_CTX_AND_READ, - sizeof(pevent_log_head), &pevent_log_head); + (void)nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_RELEASE_CTX, + sizeof(pevent_log), &pevent_log); + memset(&pevent_log, 0, sizeof(pevent_log)); + err = nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_EST_CTX_AND_READ, + sizeof(pevent_log), &pevent_log); if (err) { - fprintf(stderr, "Setting persistent event log read ctx failed (ignored)!\n"); + fprintf(stderr, "Failed to set persistent event log read context"); return; } - log_len = le64_to_cpu(pevent_log_head.tll); + log_len = le64_to_cpu(pevent_log.tll); pevent_log_info = nvme_alloc(log_len, &huge); if (!pevent_log_info) { - perror("could not alloc buffer for persistent event log page (ignored)!\n"); + perror("could not alloc buffer for persistent event log page\n"); return; } - err = nvme_persistent_event_log(fd, NVME_PEVENT_LOG_READ, + err = nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_READ, log_len, pevent_log_info); if (err == 0) { WriteData((__u8*)pevent_log_info, log_len, dir, @@ -1573,7 +1568,7 @@ static void GetNSIDDInfo(int fd, const char *dir, int nsid) char file[PATH_MAX] = { 0 }; struct nvme_id_ns ns; - if (nvme_identify_ns(fd, nsid, 0, &ns) == 0) { + if (nvme_identify_ns(fd, nsid, &ns) == 0) { sprintf(file, "identify_namespace_%d_data.bin", nsid); WriteData((__u8*)&ns, sizeof(ns), dir, file, "id-ns"); } @@ -1619,7 +1614,7 @@ static void GetOSConfig(const char *strOSDirName) } } -static int micron_telemetry_log(int fd, __u8 gen, __u8 type, __u8 **data, +static int micron_telemetry_log(int fd, __u8 type, __u8 **data, int *logSize, int da) { int err, bs = 512, offset = bs; @@ -1629,7 +1624,10 @@ static int micron_telemetry_log(int fd, __u8 gen, __u8 type, __u8 **data, __u8 *buffer = (unsigned char *)calloc(bs, 1); if (buffer == NULL) return -1; - err = nvme_get_telemetry_log(fd, buffer, gen, ctrl_init, bs, 0); + if (ctrl_init) + err = nvme_get_log_telemetry_ctrl(fd, true, 0, bs, buffer); + else + err = nvme_get_log_telemetry_host(fd, 0, bs, buffer); if (err != 0) { fprintf(stderr, "Failed to get telemetry log header for 0x%X\n", type); if (buffer != NULL) { @@ -1659,7 +1657,10 @@ static int micron_telemetry_log(int fd, __u8 gen, __u8 type, __u8 **data, err = 0; if ((buffer = (unsigned char *)realloc(buffer, (size_t)(*logSize))) != NULL) { while (err == 0 && offset != *logSize) { - err = nvme_get_telemetry_log(fd, buffer + offset, gen, ctrl_init, bs, offset); + if (ctrl_init) + err = nvme_get_log_telemetry_ctrl(fd, true, 0, *logSize, buffer + offset); + else + err = nvme_get_log_telemetry_host(fd, 0, *logSize, buffer + offset); offset += bs; } } @@ -1689,8 +1690,7 @@ static int GetTelemetryData(int fd, const char *dir) }; for(i = 0; i < (int)(sizeof(tmap)/sizeof(tmap[0])); i++) { - err = micron_telemetry_log(fd, (tmap[i].log == 0x07), - tmap[i].log, &buffer, &logSize, 0); + err = micron_telemetry_log(fd, tmap[i].log, &buffer, &logSize, 0); if (err == 0 && logSize > 0 && buffer != NULL) { sprintf(msg, "telemetry log: 0x%X", tmap[i].log); WriteData(buffer, logSize, dir, tmap[i].file, msg); @@ -1737,7 +1737,7 @@ static int GetFeatureSettings(int fd, const char *dir) bufp = NULL; } - err = nvme_get_feature(fd, 1, fmap[i].id, 0, 0x0, 0, len, bufp, &attrVal); + err = nvme_get_features(fd, fmap[i].id, 1, 0, 0x0, 0, len, bufp, &attrVal); if (err == 0) { sprintf(msg, "feature: 0x%X", fmap[i].id); WriteData((__u8*)&attrVal, sizeof(attrVal), dir, fmap[i].file, msg); @@ -1745,7 +1745,7 @@ static int GetFeatureSettings(int fd, const char *dir) WriteData(bufp, len, dir, fmap[i].file, msg); } } else { - fprintf(stderr, "Feature 0x%x data not retrieved, error %d (ignored)!\n", + printf("Feature 0x%x data not retrieved, error %d (ignored)!\n", fmap[i].id, err); errcnt++; } @@ -1759,7 +1759,7 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd, const char *desc = "Get drive HW information"; int fd, err = 0; struct nvme_id_ctrl ctrl = { 0 }; - struct nvme_admin_cmd admin_cmd = { 0 }; + struct nvme_passthru_cmd admin_cmd = { 0 }; struct fb_drive_info { unsigned char hw_ver_major; unsigned char hw_ver_minor; @@ -1796,11 +1796,11 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd, is_json = true; if (model == M5407) { - admin_cmd.opcode = 0xDA, + admin_cmd.opcode = 0xD4, admin_cmd.addr = (__u64) (uintptr_t) &dinfo; admin_cmd.data_len = (__u32)sizeof(dinfo); admin_cmd.cdw12 = 3; - err = ioctl(fd, NVME_IOCTL_ADMIN_CMD, &admin_cmd); + err = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (err) { fprintf(stderr, "ERROR : drive-info opcode failed with 0x%x\n", err); return -1; @@ -2027,7 +2027,7 @@ static int micron_fw_activation_history(int argc, char **argv, struct command *c goto out; } - err = nvme_get_log(fd, NVME_NSID_ALL, 0xC2, false, NVME_NO_LOG_LSP, C2_log_size, logC2); + err = nvme_get_log_simple(fd, 0xC2, C2_log_size, logC2); if (err) { fprintf(stderr, "Failed to retrieve fw activation history log, error: %x\n", err); goto out; @@ -2108,8 +2108,8 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c __u8 nsze; if ((err = nvme_identify_ctrl(fd, &ctrl)) == 0) - err = nvme_get_log(fd, NVME_NSID_ALL, 0xFB, false, NVME_NO_LOG_LSP, - FB_log_size, logFB); + err = nvme_get_log_simple(fd, 0xFB, + FB_log_size, logFB); if (err) { if (err < 0) printf("Unable to retrieve smart log 0xFB for the drive\n"); @@ -2130,8 +2130,7 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c goto out; } - err = nvme_get_log(fd, NVME_NSID_ALL, 0xC0, false, NVME_NO_LOG_LSP, - C0_log_size, logC0); + err = nvme_get_log_simple(fd, 0xC0, C0_log_size, logC0); if (err == 0) { print_smart_cloud_health_log((__u8 *)logC0, is_json); } else if (err < 0) { @@ -2140,7 +2139,8 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c out: close(fd); if (err > 0) - nvme_show_status(err); + fprintf(stderr, "NVMe status: %s(%#x)\n", nvme_status_to_string(err), + err); return nvme_status_to_errno(err, false); } @@ -2166,7 +2166,7 @@ static int micron_clr_fw_activation_history(int argc, char **argv, } //err = nvme_set_feature(fd, 1, fid, cdw11, 0, opt.save, 0, 0, &result); - err = nvme_set_feature(fd, 1, fid, 0, 0, 0, 0, 0, 0, &result); + err = nvme_set_features_simple(fd, fid, 1, 0, 0, &result); if (err == 0) err = (int)result; return err; } @@ -2212,14 +2212,14 @@ static int micron_telemetry_cntrl_option(int argc, char **argv, } if (!strcmp(opt.option, "enable")) { - err = nvme_set_feature(fd, 1, fid, 1, 0, (opt.select & 0x1), 0, 0, 0, &result); + err = nvme_set_features(fd, fid, 1, 1, 0, (opt.select & 0x1), 0, 0, 0, 0, &result); if (err == 0) { printf("successfully set controller telemetry option\n"); } else { printf("Failed to set controller telemetry option\n"); } } else if (!strcmp(opt.option, "disable")) { - err = nvme_set_feature(fd, 1, fid, 0, 0, (opt.select & 0x1), 0, 0, 0, &result); + err = nvme_set_features(fd, fid, 1, 0, 0, (opt.select & 0x1), 0, 0, 0, 0, &result); if (err == 0) { printf("successfully disabled controller telemetry option\n"); } else { @@ -2227,7 +2227,7 @@ static int micron_telemetry_cntrl_option(int argc, char **argv, } } else if (!strcmp(opt.option, "status")) { opt.select &= 0x3; - err = nvme_get_feature(fd, 1, fid, opt.select, 0, 0, 0, 0, &result); + err = nvme_get_features(fd, fid, 1, opt.select, 0, 0, 0, 0, &result); if (err == 0) { printf("Controller telemetry option : %s\n", (result) ? "enabled" : "disabled"); @@ -2387,7 +2387,7 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, goto out; } int logSize = 0; __u8 *buffer = NULL; const char *dir = "."; - err = micron_telemetry_log(fd, 0, cfg.log, &buffer, &logSize, cfg.data_area); + err = micron_telemetry_log(fd, cfg.log, &buffer, &logSize, cfg.data_area); if (err == 0 && logSize > 0 && buffer != NULL) { sprintf(msg, "telemetry log: 0x%X", cfg.log); WriteData(buffer, logSize, dir, cfg.package, msg); @@ -2422,7 +2422,6 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, GetSmartlogData(fd, strCtrlDirName); GetErrorlogData(fd, ctrl.elpe, strCtrlDirName); GetGenericLogs(fd, strCtrlDirName); - // pull if telemetry log data is supported if ((ctrl.lpa & 0x8) == 0x8) GetTelemetryData(fd, strCtrlDirName); @@ -2467,8 +2466,8 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, if (eModel == M5410 || eModel == M5407) err = NVMEGetLogPage(fd, aVendorLogs[i].ucLogPage, dataBuffer, bSize); else - err = nvme_get_log(fd, NVME_NSID_ALL, aVendorLogs[i].ucLogPage, - false, NVME_NO_LOG_LSP, bSize, dataBuffer); + err = nvme_get_log_simple(fd, aVendorLogs[i].ucLogPage, + bSize, dataBuffer); } break; @@ -2486,14 +2485,14 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, break; } memset(dataBuffer, 0, bSize); - err = nvme_get_log(fd, NVME_NSID_ALL, aVendorLogs[i].ucLogPage, - false, NVME_NO_LOG_LSP, bSize, dataBuffer); + err = nvme_get_log_simple(fd, aVendorLogs[i].ucLogPage, + bSize, dataBuffer); maxSize = aVendorLogs[i].nMaxSize - bSize; while (err == 0 && maxSize > 0 && ((unsigned int *)dataBuffer)[0] != 0xdeadbeef) { sprintf(msg, "log 0x%x", aVendorLogs[i].ucLogPage); WriteData(dataBuffer, bSize, strCtrlDirName, aVendorLogs[i].strFileName, msg); - err = nvme_get_log(fd, NVME_NSID_ALL, aVendorLogs[i].ucLogPage, - false, NVME_NO_LOG_LSP, bSize, dataBuffer); + err = nvme_get_log_simple(fd, aVendorLogs[i].ucLogPage, + bSize, dataBuffer); if (err || (((unsigned int *)dataBuffer)[0] == 0xdeadbeef)) break; maxSize -= bSize; diff --git a/plugins/netapp/netapp-nvme.c b/plugins/netapp/netapp-nvme.c index 0fe2bedbda..07dfeff7a3 100644 --- a/plugins/netapp/netapp-nvme.c +++ b/plugins/netapp/netapp-nvme.c @@ -21,12 +21,10 @@ #include #include #include -#include +#include #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "suffix.h" @@ -58,17 +56,17 @@ enum { static const char *dev_path = "/dev/"; struct smdevice_info { - int nsid; + unsigned nsid; struct nvme_id_ctrl ctrl; struct nvme_id_ns ns; char dev[265]; }; struct ontapdevice_info { - int nsid; + unsigned nsid; struct nvme_id_ctrl ctrl; struct nvme_id_ns ns; - char nsdesc[4096]; + struct nvme_ns_id_desc nsdesc; unsigned char log_data[ONTAP_C2_LOG_SIZE]; char dev[265]; }; @@ -339,7 +337,7 @@ static void netapp_ontapdevices_print(struct ontapdevice_info *devices, for (i = 0; i < count; i++) { netapp_get_ns_size(size, &lba, &devices[i].ns); - netapp_uuid_to_str(uuid_str, devices[i].nsdesc); + netapp_uuid_to_str(uuid_str, &devices[i].nsdesc); netapp_get_ontap_labels(vsname, nspath, devices[i].log_data); if (format == NJSON) { @@ -361,11 +359,11 @@ static void netapp_ontapdevices_print(struct ontapdevice_info *devices, static int nvme_get_ontap_c2_log(int fd, __u32 nsid, void *buf, __u32 buflen) { - struct nvme_admin_cmd get_log; + struct nvme_passthru_cmd get_log; int err; memset(buf, 0, buflen); - memset(&get_log, 0, sizeof(struct nvme_admin_cmd)); + memset(&get_log, 0, sizeof(struct nvme_passthru_cmd)); get_log.opcode = nvme_admin_get_log_page; get_log.nsid = nsid; @@ -380,7 +378,7 @@ static int nvme_get_ontap_c2_log(int fd, __u32 nsid, void *buf, __u32 buflen) get_log.cdw10 |= ONTAP_C2_LOG_NSINFO_LSP << 8; get_log.cdw11 = numdu; - err = nvme_submit_admin_passthru(fd, &get_log); + err = nvme_submit_admin_passthru(fd, &get_log, NULL); if (err) { fprintf(stderr, "ioctl error %0x\n", err); return 1; @@ -404,8 +402,8 @@ static int netapp_smdevices_get_info(int fd, struct smdevice_info *item, if (strncmp("NetApp E-Series", item->ctrl.mn, 15) != 0) return 0; /* not the right model of controller */ - item->nsid = nvme_get_nsid(fd); - err = nvme_identify_ns(fd, item->nsid, 0, &item->ns); + err = nvme_get_nsid(fd, &item->nsid); + err = nvme_identify_ns(fd, item->nsid, &item->ns); if (err) { fprintf(stderr, "Unable to identify namespace for %s (%s)\n", dev, strerror(err)); @@ -432,16 +430,16 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item, /* not the right controller model */ return 0; - item->nsid = nvme_get_nsid(fd); + err = nvme_get_nsid(fd, &item->nsid); - err = nvme_identify_ns(fd, item->nsid, 0, &item->ns); + err = nvme_identify_ns(fd, item->nsid, &item->ns); if (err) { fprintf(stderr, "Unable to identify namespace for %s (%s)\n", dev, strerror(err)); return 0; } - err = nvme_identify_ns_descs(fd, item->nsid, item->nsdesc); + err = nvme_identify_ns_descs(fd, item->nsid, &item->nsdesc); if (err) { fprintf(stderr, "Unable to identify namespace descriptor for %s (%s)\n", dev, strerror(err)); diff --git a/plugins/nvidia/nvidia-nvme.c b/plugins/nvidia/nvidia-nvme.c index cb080d7b81..cb1ab9076e 100644 --- a/plugins/nvidia/nvidia-nvme.c +++ b/plugins/nvidia/nvidia-nvme.c @@ -5,14 +5,9 @@ #include #include -#include "linux/nvme_ioctl.h" - #include "common.h" #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" #include "argconfig.h" diff --git a/plugins/scaleflux/sfx-nvme.c b/plugins/scaleflux/sfx-nvme.c index 31b885233b..1f8b5b1023 100644 --- a/plugins/scaleflux/sfx-nvme.c +++ b/plugins/scaleflux/sfx-nvme.c @@ -6,19 +6,12 @@ #include #include #include -#include #include #include #include -#include "linux/nvme_ioctl.h" - #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" -#include "nvme-status.h" +#include "libnvme.h" #include "plugin.h" #include "argconfig.h" @@ -116,38 +109,38 @@ struct nvme_additional_smart_log { int nvme_change_cap(int fd, __u32 nsid, __u64 capacity) { - struct nvme_admin_cmd cmd = { + struct nvme_passthru_cmd cmd = { .opcode = nvme_admin_change_cap, .nsid = nsid, .cdw10 = (capacity & 0xffffffff), .cdw11 = (capacity >> 32), }; - return nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD,&cmd); + return nvme_submit_admin_passthru(fd, &cmd, NULL); } int nvme_sfx_set_features(int fd, __u32 nsid, __u32 fid, __u32 value) { - struct nvme_admin_cmd cmd = { + struct nvme_passthru_cmd cmd = { .opcode = nvme_admin_sfx_set_features, .nsid = nsid, .cdw10 = fid, .cdw11 = value, }; - return nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD,&cmd); + return nvme_submit_admin_passthru(fd, &cmd, NULL); } int nvme_sfx_get_features(int fd, __u32 nsid, __u32 fid, __u32 *result) { int err = 0; - struct nvme_admin_cmd cmd = { + struct nvme_passthru_cmd cmd = { .opcode = nvme_admin_sfx_get_features, .nsid = nsid, .cdw10 = fid, }; - err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD,&cmd); + err = nvme_submit_admin_passthru(fd, &cmd, NULL); if (!err && result) { *result = cmd.result; } @@ -363,7 +356,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, fd = parse_and_open(argc, argv, desc, opts); - err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, NVME_NO_LOG_LSP, + err = nvme_get_nsid_log(fd, 0xca, cfg.namespace_id, sizeof(smart_log), (void *)&smart_log); if (!err) { if (cfg.json) @@ -445,8 +438,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct fd = parse_and_open(argc, argv, desc, opts); - err = nvme_get_log(fd, 0xffffffff, cfg.write ? 0xc3 : 0xc1, false, NVME_NO_LOG_LSP, - sizeof(stats), (void *)&stats); + err = nvme_get_log_simple(fd, cfg.write ? 0xc3 : 0xc1, sizeof(stats), (void *)&stats); if (!err) { if (!cfg.raw_binary) show_lat_stats(&stats, cfg.write); @@ -460,7 +452,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct int sfx_nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data) { - struct nvme_admin_cmd cmd = { + struct nvme_passthru_cmd cmd = { .opcode = nvme_admin_get_log_page, .nsid = nsid, .addr = (__u64)(uintptr_t) data, @@ -472,7 +464,7 @@ int sfx_nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data cmd.cdw10 = log_id | (numdl << 16); cmd.cdw11 = numdu; - return nvme_submit_admin_passthru(fd, &cmd); + return nvme_submit_admin_passthru(fd, &cmd, NULL); } /** @@ -904,7 +896,7 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl if (cfg.feature_id == SFX_FEAT_ATOMIC && cfg.value != 0) { if (cfg.namespace_id != 0xffffffff) { - 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"); diff --git a/plugins/seagate/seagate-nvme.c b/plugins/seagate/seagate-nvme.c index 844594d8ed..73bb88ed84 100644 --- a/plugins/seagate/seagate-nvme.c +++ b/plugins/seagate/seagate-nvme.c @@ -26,15 +26,10 @@ #include #include #include -#include #include #include -#include "linux/nvme_ioctl.h" #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" #include "argconfig.h" #include "suffix.h" @@ -178,8 +173,7 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd, }; fd = parse_and_open(argc, argv, desc, opts); - err = nvme_get_log(fd, 1, 0xc5, false, NVME_NO_LOG_LSP, - sizeof(logPageMap), &logPageMap); + err = nvme_get_log_simple(fd, 0xc5, sizeof(logPageMap), &logPageMap); if (!err) { if (strcmp(cfg.output_format,"json")) { printf ("Seagate Supported Log-pages count :%d\n", @@ -741,8 +735,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi if (strcmp(cfg.output_format,"json")) printf("Seagate Extended SMART Information :\n"); - err = nvme_get_log(fd, 1, 0xC4, false, NVME_NO_LOG_LSP, - sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); + err = nvme_get_log_simple(fd, 0xC4, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); if (!err) { if (strcmp(cfg.output_format,"json")) { printf("%-39s %-15s %-19s \n", "Description", "Ext-Smart-Id", "Ext-Smart-Value"); @@ -764,8 +757,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi * Next get Log Page 0xCF */ - err = nvme_get_log(fd, 1, 0xCF, false, NVME_NO_LOG_LSP, - sizeof(logPageCF), &logPageCF); + err = nvme_get_log_simple(fd, 0xCF, sizeof(logPageCF), &logPageCF); if (!err) { if(strcmp(cfg.output_format,"json")) { /*printf("Seagate DRAM Supercap SMART Attributes :\n");*/ @@ -846,7 +838,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin if(strcmp(cfg.output_format,"json")) printf("Seagate Temperature Stats Information :\n"); /*STEP-1 : Get Current Temperature from SMART */ - err = nvme_smart_log(fd, 0xffffffff, &smart_log); + err = nvme_get_log_smart(fd, 0xffffffff, true, &smart_log); if (!err) { temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]); temperature = temperature ? temperature - 273 : 0; @@ -862,8 +854,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin } /* STEP-2 : Get Max temperature form Ext SMART-id 194 */ - err = nvme_get_log(fd, 1, 0xC4, false, NVME_NO_LOG_LSP, - sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); + err = nvme_get_log_simple(fd, 0xC4, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); if (!err) { for(index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) { if (ExtdSMARTInfo.vendorData[index].AttributeNumber == VS_ATTR_ID_MAX_LIFE_TEMPERATURE) { @@ -885,8 +876,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); - cf_err = nvme_get_log(fd, 1, 0xCF, false, NVME_NO_LOG_LSP, - sizeof(ExtdSMARTInfo), &logPageCF); + cf_err = nvme_get_log_simple(fd, 0xCF, sizeof(ExtdSMARTInfo), &logPageCF); if(!cf_err) { scCurrentTemp = logPageCF.AttrCF.SuperCapCurrentTemperature; @@ -1015,8 +1005,7 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct if(strcmp(cfg.output_format,"json")) printf("Seagate PCIe error counters Information :\n"); - err = nvme_get_log(fd, 1, 0xCB, false, NVME_NO_LOG_LSP, - sizeof(pcieErrorLog), &pcieErrorLog); + err = nvme_get_log_simple(fd, 0xCB, sizeof(pcieErrorLog), &pcieErrorLog); if (!err) { if(strcmp(cfg.output_format,"json")) { print_vs_pcie_error_log(pcieErrorLog); @@ -1036,7 +1025,6 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c const char *save = "specifies that the controller shall save the attribute"; int err, fd; __u32 result; - void *buf = NULL; struct config { int save; @@ -1053,7 +1041,7 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c fd = parse_and_open(argc, argv, desc, opts); - err = nvme_set_feature(fd, 0, 0xE1, 0xCB, 0, cfg.save, 0, 0, buf, &result); + err = nvme_set_features_simple(fd, 0xE1, 0, 0xCB, cfg.save, &result); if (err < 0) { perror("set-feature"); @@ -1103,8 +1091,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug dump_fd = STDOUT_FILENO; cfg.log_id = (cfg.log_id << 8) | 0x07; - err = nvme_get_log13(fd, cfg.namespace_id, cfg.log_id, - NVME_NO_LOG_LSP, offset, 0, false, + err = nvme_get_nsid_log(fd, cfg.log_id, cfg.namespace_id, sizeof(tele_log), (void *)(&tele_log)); if (!err) { maxBlk = tele_log.tele_data_area3; @@ -1143,9 +1130,8 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug memset(log, 0, blksToGet * 512); - err = nvme_get_log13(fd, cfg.namespace_id, cfg.log_id, - NVME_NO_LOG_LSP, offset, 0, false, - blksToGet * 512, (void *)log); + err = nvme_get_log(fd, cfg.log_id, cfg.namespace_id, offset, 0, 0, true, + 0, 0, blksToGet * 512, (void *)log); if (!err) { offset += blksToGet * 512; @@ -1204,8 +1190,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug dump_fd = STDOUT_FILENO; log_id = 0x08; - err = nvme_get_log13(fd, cfg.namespace_id, log_id, - NVME_NO_LOG_LSP, offset, 0, false, + err = nvme_get_nsid_log(fd, log_id, cfg.namespace_id, sizeof(tele_log), (void *)(&tele_log)); if (!err) { maxBlk = tele_log.tele_data_area3; @@ -1243,9 +1228,8 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug memset(log, 0, blksToGet * 512); - err = nvme_get_log13(fd, cfg.namespace_id, log_id, - NVME_NO_LOG_LSP, offset, 0, false, - blksToGet * 512, (void *)log); + err = nvme_get_log(fd, log_id, cfg.namespace_id, offset, 0, 0, true, + 0, 0, blksToGet * 512, (void *)log); if (!err) { offset += blksToGet * 512; @@ -1329,8 +1313,7 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl } log_id = 0x08; - err = nvme_get_log13(fd, cfg.namespace_id, log_id, - NVME_NO_LOG_LSP, offset, 0, false, + err = nvme_get_nsid_log(fd, log_id, cfg.namespace_id, sizeof(tele_log), (void *)(&tele_log)); if (!err) { maxBlk = tele_log.tele_data_area3; @@ -1365,9 +1348,8 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl memset(log, 0, blksToGet * 512); - err = nvme_get_log13(fd, cfg.namespace_id, log_id, - NVME_NO_LOG_LSP, offset, 0, false, - blksToGet * 512, (void *)log); + err = nvme_get_log(fd, log_id, cfg.namespace_id, offset, 0, 0, true, + 0, 0, blksToGet * 512, (void *)log); if (!err) { offset += blksToGet * 512; diff --git a/plugins/shannon/shannon-nvme.c b/plugins/shannon/shannon-nvme.c index fac29b4681..f8eddf4fa9 100644 --- a/plugins/shannon/shannon-nvme.c +++ b/plugins/shannon/shannon-nvme.c @@ -5,14 +5,9 @@ #include #include -#include "linux/nvme_ioctl.h" - #include "common.h" #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" #include "argconfig.h" @@ -143,8 +138,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, }; fd = parse_and_open(argc, argv, desc, opts); - err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, - NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log); + err = nvme_get_nsid_log(fd, 0xca, cfg.namespace_id, + sizeof(smart_log), &smart_log); if (!err) { if (!cfg.raw_binary) show_shannon_smart_log(&smart_log, cfg.namespace_id, devicename); @@ -183,7 +178,7 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st struct config { __u32 namespace_id; - enum nvme_feat feature_id; + enum nvme_features_id feature_id; __u8 sel; __u32 cdw11; __u32 data_len; @@ -193,7 +188,7 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st struct config cfg = { .namespace_id = 1, - .feature_id = NVME_FEAT_NONE, + .feature_id = 0, .sel = 0, .cdw11 = 0, .data_len = 0, @@ -233,9 +228,10 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st memset(buf, 0, cfg.data_len); } - err = nvme_get_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.sel, cfg.cdw11, 0, - cfg.data_len, buf, &result); + err = nvme_get_features(fd, cfg.feature_id, cfg.namespace_id, cfg.sel, + cfg.cdw11, 0, cfg.data_len, buf, &result); if (!err) { +#if 0 printf("get-feature:0x%02x (%s), %s value: %#08x\n", cfg.feature_id, nvme_feature_to_string(cfg.feature_id), nvme_select_to_string(cfg.sel), result); @@ -249,6 +245,7 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st d_raw(buf, cfg.data_len); } } +#endif } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); @@ -345,15 +342,17 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st } } - err = nvme_set_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.value, - 0, cfg.save, 0, cfg.data_len, buf, &result); + err = nvme_set_features(fd, cfg.feature_id, cfg.namespace_id, cfg.value, + 0, cfg.save, 0, 0, cfg.data_len, buf, &result); if (err < 0) { perror("set-feature"); goto free; } if (!err) { +#if 0 printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id, nvme_feature_to_string(cfg.feature_id), cfg.value); +#endif if (buf) d(buf, cfg.data_len, 16, 1); } else if (err > 0) diff --git a/plugins/shannon/shannon-nvme.h b/plugins/shannon/shannon-nvme.h index d40732e64f..019a3d6ef5 100644 --- a/plugins/shannon/shannon-nvme.h +++ b/plugins/shannon/shannon-nvme.h @@ -9,10 +9,10 @@ PLUGIN(NAME("shannon", "Shannon vendor specific extensions"), COMMAND_LIST( ENTRY("smart-log-add", "Retrieve Shannon SMART Log, show it", get_additional_smart_log) - ENTRY("get-feature-add", "Get Shannon feature and show the resulting value", get_additional_feature) - ENTRY("set-feature-add", "Set a Shannon feature and show the resulting value", set_additional_feature) - ENTRY("id-ctrl", "Shannon NVMe Identify Controller", shannon_id_ctrl) - ) + ENTRY("set-additioal-feature", "Set additional Shannon feature", set_additional_feature) + ENTRY("get-additional-feature", "Get additional Shannon feature", get_additional_feature) + ENTRY("id-ctrl", "Retrieve Shannon ctrl id, show it", shannon_id_ctrl) + ) ); #endif diff --git a/plugins/toshiba/toshiba-nvme.c b/plugins/toshiba/toshiba-nvme.c index 5a167d59e0..540e9d62c8 100644 --- a/plugins/toshiba/toshiba-nvme.c +++ b/plugins/toshiba/toshiba-nvme.c @@ -7,12 +7,8 @@ #include #include -#include "linux/nvme_ioctl.h" #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" #include "argconfig.h" #include "suffix.h" @@ -69,7 +65,7 @@ static int nvme_sct_op(int fd, __u32 opcode, __u32 cdw10, __u32 cdw11, void* da int err = 0; __u32 result; - err = nvme_passthru(fd, NVME_IOCTL_ADMIN_CMD, opcode, flags, rsvd, + err = nvme_admin_passthru(fd, opcode, flags, rsvd, namespace_id, cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, cdw14, cdw15, data_len, data, metadata_len, metadata, @@ -394,8 +390,7 @@ static int nvme_get_vendor_log(int fd, __u32 namespace_id, int log_page, if (err) { goto end; } - err = nvme_get_log(fd, namespace_id, log_page, false, - NVME_NO_LOG_LSP, log_len, log); + err = nvme_get_nsid_log(fd, log_page, namespace_id, log_len, log); if (err) { fprintf(stderr, "%s: couldn't get log 0x%x\n", __func__, log_page); @@ -552,8 +547,8 @@ static int clear_correctable_errors(int argc, char **argv, struct command *cmd, if (err) goto end; - err = nvme_set_feature(fd, namespace_id, feature_id, value, cdw12, save, - 0, 0, NULL, &result); + err = nvme_set_features(fd, feature_id, namespace_id, value, cdw12, save, + 0, 0, 0, NULL, &result); if (err) fprintf(stderr, "%s: couldn't clear PCIe correctable errors \n", __func__); diff --git a/plugins/transcend/transcend-nvme.c b/plugins/transcend/transcend-nvme.c index e7d021c70b..55d066f7ff 100644 --- a/plugins/transcend/transcend-nvme.c +++ b/plugins/transcend/transcend-nvme.c @@ -5,12 +5,8 @@ #include #include -#include "linux/nvme_ioctl.h" #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" #include "argconfig.h" #include "suffix.h" @@ -39,7 +35,7 @@ static int getHealthValue(int argc, char **argv, struct command *cmd, struct plu printf("\nDevice not found \n");; return -1; } - result = nvme_smart_log(fd, 0xffffffff, &smart_log); + result = nvme_get_log_smart(fd, 0xffffffff, true, &smart_log); if (!result) { printf("Transcend NVME heath value: "); percent_used =smart_log.percent_used; @@ -84,7 +80,7 @@ static int getBadblock(int argc, char **argv, struct command *cmd, struct plugin nvmecmd.cdw12=DW12_BAD_BLOCK; nvmecmd.addr = (__u64)(uintptr_t)data; nvmecmd.data_len = 0x1; - result = nvme_submit_admin_passthru(fd,&nvmecmd); + result = nvme_submit_admin_passthru(fd, &nvmecmd, NULL); if(!result) { int badblock = data[0]; printf("Transcend NVME badblock count: %d\n",badblock); diff --git a/plugins/virtium/virtium-nvme.c b/plugins/virtium/virtium-nvme.c index 249a7a8e4c..d4e255d7b4 100644 --- a/plugins/virtium/virtium-nvme.c +++ b/plugins/virtium/virtium-nvme.c @@ -9,12 +9,8 @@ #include #include -#include "linux/nvme_ioctl.h" #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" #include "argconfig.h" #include "suffix.h" @@ -37,7 +33,7 @@ struct vtview_log_header { char test_name[256]; long int time_stamp; struct nvme_id_ctrl raw_ctrl; - struct nvme_firmware_log_page raw_fw; + struct nvme_firmware_slot raw_fw; }; struct vtview_smart_log_entry { @@ -275,7 +271,7 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi struct vtview_smart_log_entry smart; char filename[256] = ""; int ret = 0; - int nsid = 0; + unsigned nsid = 0; memset(smart.path, 0, sizeof(smart.path)); strcpy(smart.path, path); @@ -285,14 +281,14 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi strcpy(filename, cfg->output_file); smart.time_stamp = time(NULL); - nsid = nvme_get_nsid(fd); + ret = nvme_get_nsid(fd, &nsid); - if (nsid <= 0) { + if (ret < 0) { printf("Cannot read namespace-id\n"); return -1; } - ret = nvme_identify_ns(fd, nsid, 0, &smart.raw_ns); + ret = nvme_identify_ns(fd, nsid, &smart.raw_ns); if (ret) { printf("Cannot read namespace identify\n"); return -1; @@ -304,7 +300,7 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi return -1; } - ret = nvme_smart_log(fd, NVME_NSID_ALL, &smart.raw_smart); + ret = nvme_get_log_smart(fd, NVME_NSID_ALL, true, &smart.raw_smart); if (ret) { printf("Cannot read device SMART log\n"); return -1; @@ -345,7 +341,7 @@ static int vt_update_vtview_log_header(const int fd, const char *path, const str return -1; } - ret = nvme_fw_log(fd, &header.raw_fw); + ret = nvme_get_log_fw_slot(fd, true, &header.raw_fw); if (ret) { printf("Cannot read device firmware log\n"); return -1; @@ -447,7 +443,7 @@ static void vt_build_power_state_descriptor(const struct nvme_id_ctrl *ctrl) vt_convert_data_buffer_to_hex_string(&buf[16], 4, true, s); printf("%9sh", s); - temp = ctrl->psd[i].idle_scale; + temp = ctrl->psd[i].ips; snprintf(s, sizeof(s), "%u%u", (((unsigned char)temp >> 6) & 0x01), (((unsigned char)temp >> 7) & 0x01)); printf("%3sb", s); @@ -456,7 +452,7 @@ static void vt_build_power_state_descriptor(const struct nvme_id_ctrl *ctrl) vt_convert_data_buffer_to_hex_string(&buf[20], 4, true, s); printf("%9sh", s); - temp = ctrl->psd[i].active_work_scale; + temp = ctrl->psd[i].aps; snprintf(s, sizeof(s), "%u%u", (((unsigned char)temp >> 6) & 0x01), (((unsigned char)temp >> 7) & 0x01)); printf("%3sb", s); snprintf(s, sizeof(s), "%u%u%u", (((unsigned char)temp) & 0x01), (((unsigned char)temp >> 1) & 0x01), (((unsigned char)temp >> 2) & 0x01)); diff --git a/plugins/wdc/wdc-nvme.c b/plugins/wdc/wdc-nvme.c index cdf77069c6..ce31eb0fd9 100644 --- a/plugins/wdc/wdc-nvme.c +++ b/plugins/wdc/wdc-nvme.c @@ -30,20 +30,13 @@ #include #include -#include "linux/nvme_ioctl.h" - #include "common.h" #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" -#include "nvme-status.h" #include "argconfig.h" #include "suffix.h" -#include #define CREATE_CMD #include "wdc-nvme.h" #include "wdc-utils.h" @@ -624,10 +617,10 @@ static int wdc_purge(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_purge_monitor(int argc, char **argv, struct command *command, struct plugin *plugin); -static bool wdc_nvme_check_supported_log_page(int fd, __u8 log_id); +static bool wdc_nvme_check_supported_log_page(nvme_root_t r, int fd, __u8 log_id); static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *command, struct plugin *plugin); -static int wdc_do_drive_essentials(int fd, char *dir, char *key); +static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key); static int wdc_drive_essentials(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_drive_status(int argc, char **argv, struct command *command, @@ -645,7 +638,6 @@ static int wdc_reason_identifier(int argc, char **argv, static int wdc_do_get_reason_id(int fd, char *file, int log_id); static int wdc_save_reason_id(int fd, __u8 *rsn_ident, int size); static int wdc_clear_reason_id(int fd); -static int wdc_dump_telemetry_hdr(int fd, int log_id, struct nvme_telemetry_log_page_hdr *log_hdr); static int wdc_log_page_directory(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_do_drive_info(int fd, __u32 *result); @@ -653,10 +645,10 @@ static int wdc_vs_drive_info(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_vs_temperature_stats(int argc, char **argv, struct command *command, struct plugin *plugin); -static __u64 wdc_get_enc_drive_capabilities(int fd); +static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, int fd); static int wdc_enc_get_nic_log(int fd, __u8 log_id, __u32 xfer_size, __u32 data_len, FILE *out); static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, FILE *out, int data_id, int cdw14, int cdw15); -static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data); +static bool get_dev_mgment_cbs_data(nvme_root_t r, int fd, __u8 log_id, void **cbs_data); /* Drive log data size */ struct wdc_log_size { @@ -993,80 +985,74 @@ static long double int128_to_double(__u8 *data) return result; } -static int wdc_get_pci_ids(uint32_t *device_id, uint32_t *vendor_id) +static int wdc_get_pci_ids(nvme_root_t r, uint32_t *device_id, + uint32_t *vendor_id) { - int fd, ret = -1; - char *block, path[512], *id; - - id = calloc(1, 32); - if (!id) { - fprintf(stderr, "ERROR : WDC : %s : calloc failed\n", __func__); - return -1; - } - - block = nvme_char_from_block((char *)devicename); + char vid[256], did[256], id[32]; + nvme_ctrl_t c = NULL; + nvme_ns_t n = NULL; + int fd, ret; - /* read the vendor ID from sys fs */ - sprintf(path, "/sys/class/nvme/%s/device/vendor", block); + c = nvme_scan_ctrl(r, devicename); + if (c) { + snprintf(vid, sizeof(vid), "%s/device/vendor", + nvme_ctrl_get_sysfs_dir(c)); + snprintf(did, sizeof(did), "%s/device/device", + 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 -1; + } - fd = open(path, O_RDONLY); - if (fd < 0) { - sprintf(path, "/sys/class/misc/%s/device/vendor", block); - fd = open(path, O_RDONLY); + snprintf(vid, sizeof(vid), "%s/device/device/vendor", + nvme_ns_get_sysfs_dir(n)); + snprintf(did, sizeof(did), "%s/device/device/device", + nvme_ns_get_sysfs_dir(n)); + nvme_free_ns(n); } + + fd = open(vid, O_RDONLY); if (fd < 0) { fprintf(stderr, "ERROR : WDC : %s : Open vendor file failed\n", __func__); - ret = -1; - goto free_id; + return -1; } ret = read(fd, id, 32); + close(fd); + if (ret < 0) { fprintf(stderr, "%s: Read of pci vendor id failed\n", __func__); - ret = -1; - goto close_fd; - } else { - if (id[strlen(id) - 1] == '\n') - id[strlen(id) - 1] = '\0'; - - /* convert the device id string to an int */ - *vendor_id = (int)strtol(&id[2], NULL, 16); - ret = 0; + return -1; } - /* read the device ID from sys fs */ - sprintf(path, "/sys/class/nvme/%s/device/device", block); + if (id[strlen(id) - 1] == '\n') + id[strlen(id) - 1] = '\0'; - fd = open(path, O_RDONLY); - if (fd < 0) { - sprintf(path, "/sys/class/misc/%s/device/device", block); - fd = open(path, O_RDONLY); - } + *vendor_id = strtol(id, NULL, 0); + ret = 0; + + fd = open(did, O_RDONLY); if (fd < 0) { fprintf(stderr, "ERROR : WDC : %s : Open device file failed\n", __func__); - ret = -1; - goto close_fd; + return -1; } ret = read(fd, id, 32); + close(fd); + if (ret < 0) { fprintf(stderr, "%s: Read of pci device id failed\n", __func__); - ret = -1; - } else { - if (id[strlen(id) - 1] == '\n') - id[strlen(id) - 1] = '\0'; - - /* convert the device id string to an int */ - *device_id = strtol(&id[2], NULL, 16); - ret = 0; + return -1; } -close_fd: - close(fd); -free_id: - free(block); - free(id); - return ret; + if (id[strlen(id) - 1] == '\n') + id[strlen(id) - 1] = '\0'; + + *device_id = strtol(id, NULL, 0); + return 0; } static int wdc_get_vendor_id(int fd, uint32_t *vendor_id) @@ -1114,13 +1100,13 @@ static int wdc_get_model_number(int fd, char *model) return ret; } -static bool wdc_check_device(int fd) +static bool wdc_check_device(nvme_root_t r, int fd) { int ret; bool supported; uint32_t read_device_id = -1, read_vendor_id = -1; - ret = wdc_get_pci_ids(&read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id); if (ret < 0) { /* Use the identify nvme command to get vendor id due to NVMeOF device. */ if (wdc_get_vendor_id(fd, &read_vendor_id) < 0) @@ -1160,14 +1146,14 @@ static bool wdc_enc_check_model(int fd) return supported; } -static __u64 wdc_get_drive_capabilities(int fd) { +static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) { int ret; uint32_t read_device_id = -1, read_vendor_id = -1; __u64 capabilities = 0; __u8 *data; __u32 *cust_id; - ret = wdc_get_pci_ids(&read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id); if (ret < 0) { if (wdc_get_vendor_id(fd, &read_vendor_id) < 0) @@ -1177,7 +1163,7 @@ static __u64 wdc_get_drive_capabilities(int fd) { /* below check condition is added due in NVMeOF device we dont have device_id so we need to use only vendor_id*/ if (read_device_id == -1 && read_vendor_id != -1) { - capabilities = wdc_get_enc_drive_capabilities(fd); + capabilities = wdc_get_enc_drive_capabilities(r, fd); return capabilities; } @@ -1195,11 +1181,11 @@ static __u64 wdc_get_drive_capabilities(int fd) { WDC_DRIVE_CAP_PURGE); /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xC1 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_ADD_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_ADD_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE; break; default: @@ -1215,11 +1201,11 @@ static __u64 wdc_get_drive_capabilities(int fd) { WDC_DRIVE_CAP_DRIVE_STATUS | WDC_DRIVE_CAP_CLEAR_ASSERT | WDC_DRIVE_CAP_RESIZE | WDC_DRIVE_CAP_CLEAR_PCIE); /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; break; case WDC_NVME_SN640_DEV_ID: @@ -1230,7 +1216,7 @@ static __u64 wdc_get_drive_capabilities(int fd) { /* FALLTHRU */ case WDC_NVME_SN640_DEV_ID_3: /* verify the 0xC0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE; } @@ -1241,14 +1227,14 @@ static __u64 wdc_get_drive_capabilities(int fd) { WDC_DRIVE_CAP_LOG_PAGE_DIR); /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; - if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) { + if (!get_dev_mgment_cbs_data(r, fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) { fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); return -1; } @@ -1267,7 +1253,7 @@ static __u64 wdc_get_drive_capabilities(int fd) { /* FALLTHRU */ case WDC_NVME_SN840_DEV_ID_1: /* verify the 0xC0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE; } /* FALLTHRU */ @@ -1283,11 +1269,11 @@ static __u64 wdc_get_drive_capabilities(int fd) { WDC_DRIVE_CAP_LOG_PAGE_DIR ); /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; break; case WDC_NVME_SN650_DEV_ID: @@ -1297,7 +1283,7 @@ static __u64 wdc_get_drive_capabilities(int fd) { case WDC_NVME_SN450_DEV_ID_1: case WDC_NVME_SN450_DEV_ID_2: /* verify the 0xC0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE; } @@ -1359,7 +1345,7 @@ static __u64 wdc_get_drive_capabilities(int fd) { return capabilities; } -static __u64 wdc_get_enc_drive_capabilities(int fd) { +static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, int fd) { int ret; uint32_t read_vendor_id; __u64 capabilities = 0; @@ -1376,11 +1362,11 @@ static __u64 wdc_get_enc_drive_capabilities(int fd) { WDC_DRIVE_CAP_DRIVE_LOG | WDC_DRIVE_CAP_CRASH_DUMP | WDC_DRIVE_CAP_PFAIL_DUMP); /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xC1 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_ADD_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_ADD_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE; break; case WDC_NVME_VID_2: @@ -1389,18 +1375,18 @@ static __u64 wdc_get_enc_drive_capabilities(int fd) { WDC_DRIVE_CAP_RESIZE); /* verify the 0xCB log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == true) capabilities |= WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY; /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; - if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) { + if (!get_dev_mgment_cbs_data(r, fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) { fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); return -1; } @@ -1596,10 +1582,10 @@ bool wdc_get_dev_mng_log_entry(__u32 log_length, return valid_log; } -static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data) +static bool get_dev_mgment_cbs_data(nvme_root_t r, int fd, __u8 log_id, void **cbs_data) { int ret = -1; - __u8* data; + void* data; struct wdc_c2_log_page_header *hdr_ptr; struct wdc_c2_log_subpage_header *sph; __u32 length = 0; @@ -1609,7 +1595,7 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data) *cbs_data = NULL; __u32 device_id, read_vendor_id; - ret = wdc_get_pci_ids(&device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, &device_id, &read_vendor_id); if(device_id == WDC_NVME_ZN350_DEV_ID || device_id == WDC_NVME_ZN350_DEV_ID_1) { lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE_C8; uuid_ix = 0; @@ -1623,7 +1609,7 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data) memset(data, 0, sizeof (__u8) * WDC_C2_LOG_BUF_LEN); /* get the log page length */ - ret = nvme_get_log14(fd, 0xFFFFFFFF, lid, NVME_NO_LOG_LSP, 0, 0, false, uuid_ix, WDC_C2_LOG_BUF_LEN, data); + ret = nvme_get_log(fd, lid, 0xFFFFFFFF, NVME_LOG_LSP_NONE, 0, 0, false, uuid_ix, 0, WDC_C2_LOG_BUF_LEN, data); if (ret) { fprintf(stderr, "ERROR : WDC : Unable to get 0x%x Log Page length, ret = 0x%x\n", lid, ret); goto end; @@ -1642,9 +1628,11 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data) } /* get the log page data */ - ret = nvme_get_log14(fd, 0xFFFFFFFF, lid, NVME_NO_LOG_LSP, 0, 0, false, uuid_ix, le32_to_cpu(hdr_ptr->length), data); + ret = nvme_get_log(fd, WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE, 0xFFFFFFFF, 0, + NVME_LOG_LSP_NONE, 0, false, uuid_ix, 0, le32_to_cpu(hdr_ptr->length), data); + if (ret) { - fprintf(stderr, "ERROR : WDC : Unable to read 0x%x Log Page data, ret = 0x%x\n", lid, ret); + fprintf(stderr, "ERROR : WDC : Unable to read C2 Log Page data, ret = 0x%x\n", ret); goto end; } @@ -1661,7 +1649,9 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data) /* not found with uuid = 1 try with uuid = 0 */ uuid_ix = 0; /* get the log page data */ - ret = nvme_get_log14(fd, 0xFFFFFFFF, lid, NVME_NO_LOG_LSP, 0, 0, false, uuid_ix, le32_to_cpu(hdr_ptr->length), data); + ret = nvme_get_log(fd, WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE, 0xFFFFFFFF, 0, + NVME_LOG_LSP_NONE, 0, false, uuid_ix, 0, le32_to_cpu(hdr_ptr->length), data); + hdr_ptr = (struct wdc_c2_log_page_header *)data; sph = (struct wdc_c2_log_subpage_header *)(data + length); found = wdc_get_dev_mng_log_entry(hdr_ptr->length, log_id, hdr_ptr, &sph); @@ -1677,13 +1667,13 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data) return found; } -static bool wdc_nvme_check_supported_log_page(int fd, __u8 log_id) +static bool wdc_nvme_check_supported_log_page(nvme_root_t r, int fd, __u8 log_id) { int i; bool found = false; struct wdc_c2_cbs_data *cbs_data = NULL; - if (get_dev_mgment_cbs_data(fd, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { + if (get_dev_mgment_cbs_data(r, fd, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { if (cbs_data != NULL) { for (i = 0; i < le32_to_cpu(cbs_data->length); i++) { if (log_id == cbs_data->data[i]) { @@ -1708,12 +1698,12 @@ static bool wdc_nvme_check_supported_log_page(int fd, __u8 log_id) return found; } -static bool wdc_nvme_get_dev_status_log_data(int fd, __le32 *ret_data, +static bool wdc_nvme_get_dev_status_log_data(nvme_root_t r, int fd, __le32 *ret_data, __u8 log_id) { __u32 *cbs_data = NULL; - if (get_dev_mgment_cbs_data(fd, log_id, (void *)&cbs_data)) { + if (get_dev_mgment_cbs_data(r, fd, log_id, (void *)&cbs_data)) { if (cbs_data != NULL) { memcpy((void *)ret_data, (void *)cbs_data, 4); return true; @@ -1727,12 +1717,12 @@ static bool wdc_nvme_get_dev_status_log_data(int fd, __le32 *ret_data, static int wdc_do_clear_dump(int fd, __u8 opcode, __u32 cdw12) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = opcode; admin_cmd.cdw12 = cdw12; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret != 0) { fprintf(stdout, "ERROR : WDC : Crash dump erase failed\n"); } @@ -1745,17 +1735,17 @@ static __u32 wdc_dump_length(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, __u int ret; __u8 buf[WDC_NVME_LOG_SIZE_DATA_LEN] = {0}; struct wdc_log_size *l; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; l = (struct wdc_log_size *) buf; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = opcode; admin_cmd.addr = (__u64)(uintptr_t)buf; admin_cmd.data_len = WDC_NVME_LOG_SIZE_DATA_LEN; admin_cmd.cdw10 = cdw10; admin_cmd.cdw12 = cdw12; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret != 0) { l->log_size = 0; ret = -1; @@ -1774,16 +1764,16 @@ static __u32 wdc_dump_length(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, __u static __u32 wdc_dump_length_e6(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, struct wdc_e6_log_hdr *dump_hdr) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = opcode; admin_cmd.addr = (__u64)(uintptr_t)dump_hdr; admin_cmd.data_len = WDC_NVME_LOG_SIZE_HDR_LEN; admin_cmd.cdw10 = cdw10; admin_cmd.cdw12 = cdw12; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret != 0) { fprintf(stderr, "ERROR : WDC : reading dump length failed\n"); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); @@ -1795,9 +1785,9 @@ static __u32 wdc_dump_length_e6(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, static __u32 wdc_dump_dui_data(int fd, __u32 dataLen, __u32 offset, __u8 *dump_data, bool last_xfer) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE; admin_cmd.nsid = 0xFFFFFFFF; admin_cmd.addr = (__u64)(uintptr_t)dump_data; @@ -1810,7 +1800,7 @@ static __u32 wdc_dump_dui_data(int fd, __u32 dataLen, __u32 offset, __u8 *dump_d admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret != 0) { fprintf(stderr, "ERROR : WDC : reading DUI data failed\n"); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); @@ -1822,10 +1812,10 @@ static __u32 wdc_dump_dui_data(int fd, __u32 dataLen, __u32 offset, __u8 *dump_d static __u32 wdc_dump_dui_data_v2(int fd, __u32 dataLen, __u64 offset, __u8 *dump_data, bool last_xfer) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; __u64 offset_lo, offset_hi; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE; admin_cmd.nsid = 0xFFFFFFFF; admin_cmd.addr = (__u64)(uintptr_t)dump_data; @@ -1841,7 +1831,7 @@ static __u32 wdc_dump_dui_data_v2(int fd, __u32 dataLen, __u64 offset, __u8 *dum else admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret != 0) { fprintf(stderr, "ERROR : WDC : reading DUI data V2 failed\n"); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); @@ -1857,7 +1847,7 @@ static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len, __u8 *dump_data; __u32 curr_data_offset, curr_data_len; int i; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; __u32 dump_length = data_len; dump_data = (__u8 *) malloc(sizeof (__u8) * dump_length); @@ -1866,7 +1856,7 @@ static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len, return -1; } memset(dump_data, 0, sizeof (__u8) * dump_length); - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); curr_data_offset = 0; curr_data_len = xfer_size; i = 0; @@ -1879,7 +1869,7 @@ static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len, admin_cmd.cdw13 = curr_data_offset; while (curr_data_offset < data_len) { - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret != 0) { fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret); @@ -1916,7 +1906,7 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len, __u8 *dump_data; __u32 curr_data_offset, log_size; int i; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; dump_data = (__u8 *) malloc(sizeof (__u8) * data_len); @@ -1925,7 +1915,7 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len, return -1; } memset(dump_data, 0, sizeof (__u8) * data_len); - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); curr_data_offset = WDC_NVME_LOG_SIZE_HDR_LEN; i = 0; @@ -1944,7 +1934,7 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len, admin_cmd.cdw10 = xfer_size >> 2; admin_cmd.cdw13 = curr_data_offset >> 2; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret != 0) { fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret); fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n", @@ -1973,7 +1963,7 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len, static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int data_area) { - struct nvme_telemetry_log_page_hdr *hdr; + struct nvme_telemetry_log *hdr; size_t full_size, offset = WDC_TELEMETRY_HEADER_LENGTH; int err = 0, output; void *page_log; @@ -1988,8 +1978,8 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int ctrl_init = 0; } else if (type == WDC_TELEMETRY_TYPE_CONTROLLER) { /* Verify the Controller Initiated Option is enabled */ - err = nvme_get_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 0, - 0, 4, buf, &result); + err = nvme_get_features_data(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, + 4, buf, &result); if (err == 0) { if (result == 0) { /* enabled */ @@ -2037,11 +2027,17 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int goto free_mem; } - err = nvme_get_telemetry_log(fd, hdr, host_gen, ctrl_init, WDC_TELEMETRY_HEADER_LENGTH, 0); + if (ctrl_init) + err = nvme_get_log_telemetry_ctrl(fd, true, 0, WDC_TELEMETRY_HEADER_LENGTH, hdr); + else if (host_gen) + err = nvme_get_log_create_telemetry_host(fd, hdr); + else + err = nvme_get_log_telemetry_host(fd, 0, WDC_TELEMETRY_HEADER_LENGTH, hdr); + if (err < 0) perror("get-telemetry-log"); else if (err > 0) { - nvme_show_status(err); + fprintf(stderr, "NVMe status: %s(%#x)\n", nvme_status_to_string(err), err); fprintf(stderr, "%s: Failed to acquire telemetry header!\n", __func__); goto close_output; } @@ -2076,15 +2072,17 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int if ((full_size - offset) < bs) bs = (full_size - offset); + if (ctrl_init) + err = nvme_get_log_telemetry_ctrl(fd, true, offset, bs, page_log); + else + err = nvme_get_log_telemetry_host(fd, offset, bs, page_log); - err = nvme_get_telemetry_log(fd, page_log, 0, ctrl_init, bs, offset); if (err < 0) { perror("get-telemetry-log"); break; } else if (err > 0) { - nvme_show_status(err); + fprintf(stderr, "NVMe status: %s(%#x)\n", nvme_status_to_string(err), err); fprintf(stderr, "%s: Failed to acquire full telemetry log!\n", __func__); - nvme_show_status(err); break; } @@ -2109,7 +2107,8 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int } -static int wdc_do_cap_diag(int fd, char *file, __u32 xfer_size, int type, int data_area) +static int wdc_do_cap_diag(nvme_root_t r, int fd, char *file, + __u32 xfer_size, int type, int data_area) { int ret = -1; __u32 e6_log_hdr_size = WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE; @@ -2533,6 +2532,7 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in static int wdc_cap_diag(int argc, char **argv, struct command *command, struct plugin *plugin) { + nvme_root_t r; char *desc = "Capture Diagnostics Log."; char *file = "Output file pathname."; char *size = "Data retrieval transfer size."; @@ -2557,6 +2557,8 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command, OPT_END() }; + r = nvme_scan(NULL); + fd = parse_and_open(argc, argv, desc, opts); if (fd < 0) return fd; @@ -2572,11 +2574,12 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command, if (cfg.file == NULL) snprintf(f + strlen(f), PATH_MAX, "%s", ".bin"); - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_CAP_DIAG) == WDC_DRIVE_CAP_CAP_DIAG) - return wdc_do_cap_diag(fd, f, xfer_size, 0, 0); + return wdc_do_cap_diag(r, fd, f, xfer_size, 0, 0); fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + nvme_free_tree(r); return 0; } @@ -2584,14 +2587,14 @@ static int wdc_do_get_sn730_log_len(int fd, uint32_t *len_buf, uint32_t subopcod { int ret; uint32_t *output = NULL; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; if ((output = (uint32_t*)malloc(sizeof(uint32_t))) == NULL) { fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); return -1; } memset(output, 0, sizeof (uint32_t)); - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.data_len = 8; admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE; @@ -2599,7 +2602,7 @@ static int wdc_do_get_sn730_log_len(int fd, uint32_t *len_buf, uint32_t subopcod admin_cmd.cdw12 = subopcode; admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE / 4; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret == 0) *len_buf = *output; free(output); @@ -2610,13 +2613,13 @@ static int wdc_do_get_sn730_log(int fd, void * log_buf, uint32_t offset, uint32_ { int ret; uint8_t *output = NULL; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; if ((output = (uint8_t*)calloc(SN730_LOG_CHUNK_SIZE, sizeof(uint8_t))) == NULL) { fprintf(stderr, "ERROR : WDC : calloc : %s\n", strerror(errno)); return -1; } - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.data_len = SN730_LOG_CHUNK_SIZE; admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE; admin_cmd.addr = (uintptr_t)output; @@ -2624,7 +2627,7 @@ static int wdc_do_get_sn730_log(int fd, void * log_buf, uint32_t offset, uint32_ admin_cmd.cdw13 = offset; admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE / 4; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (!ret) memcpy(log_buf, output, SN730_LOG_CHUNK_SIZE); return ret; @@ -2823,6 +2826,7 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command char *verbose = "Display more debug messages."; char f[PATH_MAX] = {0}; char fileSuffix[PATH_MAX] = {0}; + nvme_root_t r; __u32 xfer_size = 0; int fd; int telemetry_type = 0, telemetry_data_area = 0; @@ -2865,12 +2869,16 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command if (fd < 0) return fd; - if (!wdc_check_device(fd)) + r = nvme_scan(NULL); + if (!wdc_check_device(r, fd)) { + nvme_free_tree(r); return -1; + } if (cfg.xfer_size != 0) xfer_size = cfg.xfer_size; else { fprintf(stderr, "ERROR : WDC : Invalid length\n"); + nvme_free_tree(r); return -1; } @@ -2910,7 +2918,7 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command } } - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG) == WDC_DRIVE_CAP_INTERNAL_LOG) { if (cfg.data_area == 0) cfg.data_area = 3; /* Set the default DA to 3 if not specified */ @@ -2933,7 +2941,8 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command return -1; } - return wdc_do_cap_diag(fd, f, xfer_size, telemetry_type, telemetry_data_area); + return wdc_do_cap_diag(r, fd, f, xfer_size, + telemetry_type, telemetry_data_area); } if ((capabilities & WDC_DRIVE_CAP_DUI) == WDC_DRIVE_CAP_DUI) { if (cfg.data_area == 0) { @@ -2943,7 +2952,8 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command /* FW requirement - xfer size must be 256k for data area 4 */ if (cfg.data_area >= 4) xfer_size = 0x40000; - return wdc_do_cap_dui(fd, f, xfer_size, cfg.data_area, cfg.verbose, cfg.file_size, cfg.offset); + return wdc_do_cap_dui(fd, f, xfer_size, cfg.data_area, + cfg.verbose, cfg.file_size, cfg.offset); } if ((capabilities & WDC_DRIVE_CAP_DUI_DATA) == WDC_DRIVE_CAP_DUI_DATA) return wdc_do_cap_dui(fd, f, xfer_size, WDC_NVME_DUI_MAX_DATA_AREA, cfg.verbose, 0, 0); @@ -3051,7 +3061,7 @@ static int wdc_do_drive_log(int fd, char *file) int ret; __u8 *drive_log_data; __u32 drive_log_length; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; ret = wdc_dump_length(fd, WDC_NVME_DRIVE_LOG_SIZE_OPCODE, WDC_NVME_DRIVE_LOG_SIZE_NDT, @@ -3069,7 +3079,7 @@ static int wdc_do_drive_log(int fd, char *file) } memset(drive_log_data, 0, sizeof (__u8) * drive_log_length); - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_DRIVE_LOG_OPCODE; admin_cmd.addr = (__u64)(uintptr_t)drive_log_data; admin_cmd.data_len = drive_log_length; @@ -3077,7 +3087,7 @@ static int wdc_do_drive_log(int fd, char *file) admin_cmd.cdw12 = ((WDC_NVME_DRIVE_LOG_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_DRIVE_LOG_SIZE_CMD); - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); if (ret == 0) { @@ -3095,6 +3105,7 @@ static int wdc_drive_log(int argc, char **argv, struct command *command, char f[PATH_MAX] = {0}; int fd; int ret; + nvme_root_t r; __u64 capabilities = 0; struct config { char *file; @@ -3113,9 +3124,13 @@ static int wdc_drive_log(int argc, char **argv, struct command *command, if (fd < 0) return fd; - if (!wdc_check_device(fd)) + r = nvme_scan(NULL); + + if (!wdc_check_device(r, fd)) { + nvme_free_tree(r); return -1; - capabilities = wdc_get_drive_capabilities(fd); + } + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_DRIVE_LOG) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -3126,10 +3141,12 @@ static int wdc_drive_log(int argc, char **argv, struct command *command, } if (wdc_get_serial_name(fd, f, PATH_MAX, "drive_log") == -1) { fprintf(stderr, "ERROR : WDC : failed to generate file name\n"); + nvme_free_tree(r); return -1; } ret = wdc_do_drive_log(fd, f); } + nvme_free_tree(r); return ret; } @@ -3139,6 +3156,7 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command, const char *desc = "Get Crash Dump."; const char *file = "Output file pathname."; int fd, ret; + nvme_root_t r; __u64 capabilities = 0; struct config { @@ -3158,10 +3176,15 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command, if (fd < 0) return fd; - if (!wdc_check_device(fd)) + r = nvme_scan(NULL); + + if (!wdc_check_device(r, fd)) { + nvme_free_tree(r); return -1; - capabilities = wdc_get_drive_capabilities(fd); + } + + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_CRASH_DUMP) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -3172,6 +3195,7 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command, fprintf(stderr, "ERROR : WDC : failed to read crash dump\n"); } } + nvme_free_tree(r); return ret; } @@ -3182,6 +3206,7 @@ static int wdc_get_pfail_dump(int argc, char **argv, struct command *command, char *file = "Output file pathname."; int fd; int ret; + nvme_root_t r; __u64 capabilities = 0; struct config { char *file; @@ -3200,10 +3225,14 @@ static int wdc_get_pfail_dump(int argc, char **argv, struct command *command, if (fd < 0) return fd; - if (!wdc_check_device(fd)) + r = nvme_scan(NULL); + + if (!wdc_check_device(r, fd)) { + nvme_free_tree(r); return -1; + } - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_PFAIL_DUMP) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -3213,7 +3242,7 @@ static int wdc_get_pfail_dump(int argc, char **argv, struct command *command, fprintf(stderr, "ERROR : WDC : failed to read pfail crash dump\n"); } } - + nvme_free_tree(r); return ret; } @@ -3271,6 +3300,7 @@ static int wdc_purge(int argc, char **argv, const char *desc = "Send a Purge command."; char *err_str; int fd, ret; + nvme_root_t r; struct nvme_passthru_cmd admin_cmd; __u64 capabilities = 0; @@ -3282,10 +3312,14 @@ static int wdc_purge(int argc, char **argv, if (fd < 0) return fd; - if (!wdc_check_device(fd)) + r = nvme_scan(NULL); + + if (!wdc_check_device(r, fd)) { + nvme_free_tree(r); return -1; + } - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if((capabilities & WDC_DRIVE_CAP_PURGE) == 0) { ret = -1; fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -3294,7 +3328,7 @@ static int wdc_purge(int argc, char **argv, memset(&admin_cmd, 0, sizeof (admin_cmd)); admin_cmd.opcode = WDC_NVME_PURGE_CMD_OPCODE; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret > 0) { switch (ret) { case WDC_NVME_PURGE_CMD_SEQ_ERR: @@ -3312,6 +3346,7 @@ static int wdc_purge(int argc, char **argv, fprintf(stderr, "%s", err_str); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); } + nvme_free_tree(r); return ret; } @@ -3320,11 +3355,12 @@ static int wdc_purge_monitor(int argc, char **argv, { const char *desc = "Send a Purge Monitor command."; int fd, ret; + nvme_root_t r; __u8 output[WDC_NVME_PURGE_MONITOR_DATA_LEN]; double progress_percent; struct nvme_passthru_cmd admin_cmd; struct wdc_nvme_purge_monitor_data *mon; - __u64 capabilities = 0; + __u64 capabilities; OPT_ARGS(opts) = { OPT_END() @@ -3334,23 +3370,26 @@ static int wdc_purge_monitor(int argc, char **argv, if (fd < 0) return fd; - if (!wdc_check_device(fd)) + r = nvme_scan(NULL); + if (!wdc_check_device(r, fd)) { + nvme_free_tree(r); return -1; + } - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if((capabilities & WDC_DRIVE_CAP_PURGE) == 0) { ret = -1; fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); } else { memset(output, 0, sizeof (output)); - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_PURGE_MONITOR_OPCODE; admin_cmd.addr = (__u64)(uintptr_t)output; admin_cmd.data_len = WDC_NVME_PURGE_MONITOR_DATA_LEN; admin_cmd.cdw10 = WDC_NVME_PURGE_MONITOR_CMD_CDW10; admin_cmd.timeout_ms = WDC_NVME_PURGE_MONITOR_TIMEOUT; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret == 0) { mon = (struct wdc_nvme_purge_monitor_data *) output; printf("Purge state = 0x%0x\n", admin_cmd.result); @@ -3365,6 +3404,7 @@ static int wdc_purge_monitor(int argc, char **argv, fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); } + nvme_free_tree(r); return ret; } @@ -4597,7 +4637,8 @@ static int wdc_print_c0_eol_log(void *data, int fmt) return 0; } -static int wdc_get_c0_log_page(int fd, char *format, int uuid_index) +static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format, + int uuid_index) { int ret = 0; int fmt = -1; @@ -4606,7 +4647,7 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index) __u32 *cust_id; uint32_t device_id, read_vendor_id; - if (!wdc_check_device(fd)) + if (!wdc_check_device(r, fd)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -4614,7 +4655,7 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index) return fmt; } - ret = wdc_get_pci_ids(&device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, &device_id, &read_vendor_id); switch (device_id) { @@ -4624,15 +4665,14 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index) case WDC_NVME_SN640_DEV_ID_3: case WDC_NVME_SN840_DEV_ID: case WDC_NVME_SN840_DEV_ID_1: - if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) { + if (!get_dev_mgment_cbs_data(r, fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) { fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); return -1; } cust_id = (__u32*)data; - if ((*cust_id == WDC_CUSTOMER_ID_0x1004) || (*cust_id == WDC_CUSTOMER_ID_0x1008) || - (*cust_id == WDC_CUSTOMER_ID_0x1005) || (*cust_id == WDC_CUSTOMER_ID_0x1304)) + if ((*cust_id == WDC_CUSTOMER_ID_0x1004) || (*cust_id == WDC_CUSTOMER_ID_0x1008) || (*cust_id == WDC_CUSTOMER_ID_0x1005)) { if (uuid_index == 0) { @@ -4642,8 +4682,8 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index) } /* Get the 0xC0 log data */ - ret = nvme_get_log14(fd, 0xFFFFFFFF, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, - NVME_NO_LOG_LSP, 0, 0, false, uuid_index, WDC_NVME_SMART_CLOUD_ATTR_LEN, data); + ret = nvme_get_log(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, 0xFFFFFFFF, 0, + NVME_LOG_LSP_NONE, 0, false, uuid_index, 0, WDC_NVME_SMART_CLOUD_ATTR_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); @@ -4689,8 +4729,8 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index) } /* Get the 0xC0 log data */ - ret = nvme_get_log14(fd, 0xFFFFFFFF, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, - NVME_NO_LOG_LSP, 0, 0, false, uuid_index, WDC_NVME_EOL_STATUS_LOG_LEN, data); + ret = nvme_get_log(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, 0xFFFFFFFF, 0, + NVME_LOG_LSP_NONE, 0, false, uuid_index, 0, WDC_NVME_EOL_STATUS_LOG_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); @@ -4716,8 +4756,8 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index) } /* Get the 0xC0 log data */ - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, - false, NVME_NO_LOG_LSP, WDC_NVME_EOL_STATUS_LOG_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, + WDC_NVME_EOL_STATUS_LOG_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); @@ -4742,8 +4782,8 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index) } /* Get the 0xC0 log data */ - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE, - false, NVME_NO_LOG_LSP, WDC_NVME_SMART_CLOUD_ATTR_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE, + WDC_NVME_SMART_CLOUD_ATTR_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); @@ -4839,7 +4879,7 @@ static int wdc_print_fw_act_history_log(__u8 *data, int num_entries, int fmt, __ return 0; } -static int wdc_get_ca_log_page(int fd, char *format) +static int wdc_get_ca_log_page(nvme_root_t r, int fd, char *format) { int ret = 0; int fmt = -1; @@ -4848,7 +4888,7 @@ static int wdc_get_ca_log_page(int fd, char *format) struct wdc_ssd_ca_perf_stats *perf; uint32_t read_device_id, read_vendor_id; - if (!wdc_check_device(fd)) + if (!wdc_check_device(r, fd)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -4857,17 +4897,17 @@ static int wdc_get_ca_log_page(int fd, char *format) } /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == false) { + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == false) { fprintf(stderr, "ERROR : WDC : 0xCA Log Page not supported\n"); return -1; } - if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) { + if (!get_dev_mgment_cbs_data(r, fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) { fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); return -1; } - ret = wdc_get_pci_ids(&read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id); cust_id = (__u32*)data; @@ -4884,8 +4924,8 @@ static int wdc_get_ca_log_page(int fd, char *format) memset(data, 0, sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN); - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, - false, NVME_NO_LOG_LSP, WDC_FB_CA_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, + WDC_FB_CA_LOG_BUF_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); @@ -4920,8 +4960,8 @@ static int wdc_get_ca_log_page(int fd, char *format) memset(data, 0, sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN); - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, - false, NVME_NO_LOG_LSP, WDC_FB_CA_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, + WDC_FB_CA_LOG_BUF_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); @@ -4942,8 +4982,8 @@ static int wdc_get_ca_log_page(int fd, char *format) } memset(data, 0, sizeof (__u8) * WDC_BD_CA_LOG_BUF_LEN); - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, - false, NVME_NO_LOG_LSP, WDC_BD_CA_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, + WDC_BD_CA_LOG_BUF_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); @@ -4974,7 +5014,8 @@ static int wdc_get_ca_log_page(int fd, char *format) return ret; } -static int wdc_get_c1_log_page(int fd, char *format, uint8_t interval) +static int wdc_get_c1_log_page(nvme_root_t r, int fd, + char *format, uint8_t interval) { int ret = 0; int fmt = -1; @@ -4987,7 +5028,7 @@ static int wdc_get_c1_log_page(int fd, char *format, uint8_t interval) struct wdc_log_page_subpage_header *sph; struct wdc_ssd_perf_stats *perf; - if (!wdc_check_device(fd)) + if (!wdc_check_device(r, fd)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -5006,8 +5047,8 @@ static int wdc_get_c1_log_page(int fd, char *format, uint8_t interval) } memset(data, 0, sizeof (__u8) * WDC_ADD_LOG_BUF_LEN); - ret = nvme_get_log(fd, 0x01, WDC_NVME_ADD_LOG_OPCODE, false, - NVME_NO_LOG_LSP, WDC_ADD_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_ADD_LOG_OPCODE, + WDC_ADD_LOG_BUF_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); if (ret == 0) { @@ -5032,14 +5073,14 @@ static int wdc_get_c1_log_page(int fd, char *format, uint8_t interval) return ret; } -static int wdc_get_d0_log_page(int fd, char *format) +static int wdc_get_d0_log_page(nvme_root_t r, int fd, char *format) { int ret = 0; int fmt = -1; __u8 *data; struct wdc_ssd_d0_smart_log *perf; - if (!wdc_check_device(fd)) + if (!wdc_check_device(r, fd)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -5048,7 +5089,7 @@ static int wdc_get_d0_log_page(int fd, char *format) } /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == false) { + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == false) { fprintf(stderr, "ERROR : WDC : 0xD0 Log Page not supported\n"); return -1; } @@ -5059,8 +5100,8 @@ static int wdc_get_d0_log_page(int fd, char *format) } memset(data, 0, sizeof (__u8) * WDC_NVME_VU_SMART_LOG_LEN); - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_VU_SMART_LOG_OPCODE, - false, NVME_NO_LOG_LSP, WDC_NVME_VU_SMART_LOG_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE, + WDC_NVME_VU_SMART_LOG_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); @@ -5085,6 +5126,7 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, int fd; const char *log_page_version = "Log Page Version: 0 = vendor, 1 = WDC"; const char *log_page_mask = "Log Page Mask, comma separated list: 0xC0, 0xC1, 0xCA, 0xD0"; + nvme_root_t r; int ret = 0; int uuid_index = 0; int page_mask = 0, num, i; @@ -5117,6 +5159,7 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, if (fd < 0) return fd; + r = nvme_scan(NULL); if (cfg.log_page_version == 0) { uuid_index = 0; } else if (cfg.log_page_version == 1) { @@ -5161,7 +5204,7 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, fprintf(stderr, "ERROR : WDC: Unknown log page mask - %s\n", cfg.log_page_mask); - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -5172,34 +5215,34 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, if (((capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE) == WDC_DRIVE_CAP_C0_LOG_PAGE) && (page_mask & WDC_C0_PAGE_MASK)) { /* Get 0xC0 log page if possible. */ - ret = wdc_get_c0_log_page(fd, cfg.output_format, uuid_index); + ret = wdc_get_c0_log_page(r, fd, cfg.output_format, uuid_index); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the C0 Log Page, ret = %d\n", ret); } if (((capabilities & (WDC_DRIVE_CAP_CA_LOG_PAGE)) == (WDC_DRIVE_CAP_CA_LOG_PAGE)) && (page_mask & WDC_CA_PAGE_MASK)) { /* Get the CA Log Page */ - ret = wdc_get_ca_log_page(fd, cfg.output_format); + ret = wdc_get_ca_log_page(r, fd, cfg.output_format); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the CA Log Page, ret = %d\n", ret); } if (((capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE) == WDC_DRIVE_CAP_C1_LOG_PAGE) && (page_mask & WDC_C1_PAGE_MASK)) { /* Get the C1 Log Page */ - ret = wdc_get_c1_log_page(fd, cfg.output_format, cfg.interval); + ret = wdc_get_c1_log_page(r, fd, cfg.output_format, cfg.interval); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the C1 Log Page, ret = %d\n", ret); } if (((capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE) == WDC_DRIVE_CAP_D0_LOG_PAGE) && (page_mask & WDC_D0_PAGE_MASK)) { /* Get the D0 Log Page */ - ret = wdc_get_d0_log_page(fd, cfg.output_format); + ret = wdc_get_d0_log_page(r, fd, cfg.output_format); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the D0 Log Page, ret = %d\n", ret); } out: - + nvme_free_tree(r); return ret; } @@ -5213,7 +5256,7 @@ static int wdc_do_clear_pcie_correctable_errors(int fd) admin_cmd.cdw12 = ((WDC_NVME_CLEAR_PCIE_CORR_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CLEAR_PCIE_CORR_CMD); - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); return ret; } @@ -5226,7 +5269,7 @@ static int wdc_do_clear_pcie_correctable_errors_vuc(int fd) memset(&admin_cmd, 0, sizeof (admin_cmd)); admin_cmd.opcode = WDC_NVME_CLEAR_PCIE_CORR_OPCODE_VUC; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); return ret; } @@ -5237,8 +5280,8 @@ static int wdc_do_clear_pcie_correctable_errors_fid(int fd) __u32 result; __u32 value = 1 << 31; /* Bit 31 - clear PCIe correctable count */ - ret = nvme_set_feature(fd, 0, WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID, value, - 0, 0, 0, 0, NULL, &result); + ret = nvme_set_features_simple(fd, WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID, 0, value, + false, &result); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); return ret; @@ -5249,6 +5292,7 @@ static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct comma { char *desc = "Clear PCIE Correctable Errors."; int fd, ret; + nvme_root_t r; __u64 capabilities = 0; OPT_ARGS(opts) = { @@ -5259,12 +5303,13 @@ static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct comma if (fd < 0) return fd; - if (!wdc_check_device(fd)) { + r = nvme_scan(NULL); + if (!wdc_check_device(r, fd)) { ret = -1; goto out; } - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -5282,6 +5327,7 @@ static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct comma } out: + nvme_free_tree(r); return ret; } @@ -5291,6 +5337,7 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, char *desc = "Get Drive Status."; int fd; int ret = 0; + nvme_root_t r; __le32 system_eol_state; __le32 user_eol_state; __le32 format_corrupt_reason = cpu_to_le32(0xFFFFFFFF); @@ -5307,7 +5354,8 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, if (fd < 0) return fd; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_DRIVE_STATUS) != WDC_DRIVE_CAP_DRIVE_STATUS) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -5315,41 +5363,41 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, } /* verify the 0xC2 Device Manageability log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE) == false) { + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE) == false) { fprintf(stderr, "ERROR : WDC : 0xC2 Log Page not supported\n"); ret = -1; goto out; } /* Get the assert dump present status */ - if (!wdc_nvme_get_dev_status_log_data(fd, &assert_status, + if (!wdc_nvme_get_dev_status_log_data(r, fd, &assert_status, WDC_C2_ASSERT_DUMP_PRESENT_ID)) fprintf(stderr, "ERROR : WDC : Get Assert Status Failed\n"); /* Get the thermal throttling status */ - if (!wdc_nvme_get_dev_status_log_data(fd, &thermal_status, + if (!wdc_nvme_get_dev_status_log_data(r, fd, &thermal_status, WDC_C2_THERMAL_THROTTLE_STATUS_ID)) fprintf(stderr, "ERROR : WDC : Get Thermal Throttling Status Failed\n"); /* Get EOL status */ - if (!wdc_nvme_get_dev_status_log_data(fd, &eol_status, + if (!wdc_nvme_get_dev_status_log_data(r, fd, &eol_status, WDC_C2_USER_EOL_STATUS_ID)) { fprintf(stderr, "ERROR : WDC : Get User EOL Status Failed\n"); eol_status = cpu_to_le32(-1); } /* Get Customer EOL state */ - if (!wdc_nvme_get_dev_status_log_data(fd, &user_eol_state, + if (!wdc_nvme_get_dev_status_log_data(r, fd, &user_eol_state, WDC_C2_USER_EOL_STATE_ID)) fprintf(stderr, "ERROR : WDC : Get User EOL State Failed\n"); /* Get System EOL state*/ - if (!wdc_nvme_get_dev_status_log_data(fd, &system_eol_state, + if (!wdc_nvme_get_dev_status_log_data(r, fd, &system_eol_state, WDC_C2_SYSTEM_EOL_STATE_ID)) fprintf(stderr, "ERROR : WDC : Get System EOL State Failed\n"); /* Get format corrupt reason*/ - if (!wdc_nvme_get_dev_status_log_data(fd, &format_corrupt_reason, + if (!wdc_nvme_get_dev_status_log_data(r, fd, &format_corrupt_reason, WDC_C2_FORMAT_CORRUPT_REASON_ID)) fprintf(stderr, "ERROR : WDC : Get Format Corrupt Reason Failed\n"); @@ -5396,6 +5444,7 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, printf(" Format Corrupt Reason: Unknown : 0x%08x\n", le32_to_cpu(format_corrupt_reason)); out: + nvme_free_tree(r); return ret; } @@ -5405,6 +5454,7 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, char *desc = "Clear Assert Dump Present Status."; int fd; int ret = -1; + nvme_root_t r; __le32 assert_status = cpu_to_le32(0xFFFFFFFF); __u64 capabilities = 0; struct nvme_passthru_cmd admin_cmd; @@ -5417,13 +5467,14 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, if (fd < 0) return fd; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT) != WDC_DRIVE_CAP_CLEAR_ASSERT) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; goto out; } - if (!wdc_nvme_get_dev_status_log_data(fd, &assert_status, + if (!wdc_nvme_get_dev_status_log_data(r, fd, &assert_status, WDC_C2_ASSERT_DUMP_PRESENT_ID)) { fprintf(stderr, "ERROR : WDC : Get Assert Status Failed\n"); ret = -1; @@ -5437,23 +5488,24 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, admin_cmd.cdw12 = ((WDC_NVME_CLEAR_ASSERT_DUMP_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CLEAR_ASSERT_DUMP_CMD); - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); } else fprintf(stderr, "INFO : WDC : No Assert Dump Present\n"); out: + nvme_free_tree(r); return ret; } -static int wdc_get_fw_act_history(int fd, char *format) +static int wdc_get_fw_act_history(nvme_root_t r, int fd, char *format) { int ret = 0; int fmt = -1; __u8 *data; struct wdc_fw_act_history_log_hdr *fw_act_history_hdr; - if (!wdc_check_device(fd)) + if (!wdc_check_device(r, fd)) return -1; fmt = validate_output_format(format); @@ -5463,7 +5515,7 @@ static int wdc_get_fw_act_history(int fd, char *format) } /* verify the FW Activate History log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == false) { + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == false) { fprintf(stderr, "ERROR : WDC : %d Log Page not supported\n", WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID); return -1; } @@ -5475,8 +5527,8 @@ static int wdc_get_fw_act_history(int fd, char *format) memset(data, 0, sizeof (__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN); - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID, - false, NVME_NO_LOG_LSP, WDC_FW_ACT_HISTORY_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID, + WDC_FW_ACT_HISTORY_LOG_BUF_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); @@ -5504,7 +5556,7 @@ static int wdc_get_fw_act_history(int fd, char *format) return ret; } -static int wdc_get_fw_act_history_C2(int fd, char *format) +static int wdc_get_fw_act_history_C2(nvme_root_t r, int fd, char *format) { int ret = 0; int fmt = -1; @@ -5514,7 +5566,7 @@ static int wdc_get_fw_act_history_C2(int fd, char *format) __u32 tot_entries = 0, num_entries = 0; __u32 vendor_id = 0, device_id = 0; - if (!wdc_check_device(fd)) + if (!wdc_check_device(r, fd)) return -1; fmt = validate_output_format(format); @@ -5522,7 +5574,8 @@ static int wdc_get_fw_act_history_C2(int fd, char *format) fprintf(stderr, "ERROR : WDC : invalid output format\n"); return fmt; } - ret = wdc_get_pci_ids(&device_id, &vendor_id); + + ret = wdc_get_pci_ids(r, &device_id, &vendor_id); if ((data = (__u8*) malloc(sizeof (__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN)) == NULL) { fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); @@ -5531,8 +5584,8 @@ static int wdc_get_fw_act_history_C2(int fd, char *format) memset(data, 0, sizeof (__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN); - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID, - false, NVME_NO_LOG_LSP, WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(fd, WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID, + WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); @@ -5544,7 +5597,7 @@ static int wdc_get_fw_act_history_C2(int fd, char *format) if (tot_entries > 0) { /* get the FW customer id */ - if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&cust_id)) { + if (!get_dev_mgment_cbs_data(r, fd, WDC_C2_CUSTOMER_ID_ID, (void*)&cust_id)) { fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); ret = -1; goto freeData; @@ -5571,6 +5624,7 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com { int fd; int ret = 0; + nvme_root_t r; __u64 capabilities = 0; const char *desc = "Retrieve FW activate history table."; @@ -5593,7 +5647,8 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com if (fd < 0) return fd; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -5614,8 +5669,8 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com } /* Get the 0xC0 log data */ - ret = nvme_get_log14(fd, 0xFFFFFFFF, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE, - NVME_NO_LOG_LSP, 0, 0, false, uuid_index, WDC_NVME_SMART_CLOUD_ATTR_LEN, data); + ret = nvme_get_log(fd, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE, 0xFFFFFFFF, 0, + NVME_LOG_LSP_NONE, 0, false, uuid_index, 0, WDC_NVME_SMART_CLOUD_ATTR_LEN, data); if (ret == 0) { /* Verify GUID matches */ @@ -5632,19 +5687,21 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com } free(data); - if (c0GuidMatch) { - ret = wdc_get_fw_act_history_C2(fd, cfg.output_format); - } - else { - ret = wdc_get_fw_act_history(fd, cfg.output_format); - } + if (c0GuidMatch) { + ret = wdc_get_fw_act_history_C2(r, fd, + cfg.output_format); + } + else { + ret = wdc_get_fw_act_history(r, fd, cfg.output_format); + } } else { - ret = wdc_get_fw_act_history_C2(fd, cfg.output_format); + ret = wdc_get_fw_act_history_C2(r, fd, cfg.output_format); } if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the FW Activate History, ret = %d\n", ret); out: + nvme_free_tree(r); return ret; } @@ -5658,7 +5715,7 @@ static int wdc_do_clear_fw_activate_history_vuc(int fd) admin_cmd.cdw12 = ((WDC_NVME_CLEAR_FW_ACT_HIST_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CLEAR_FW_ACT_HIST_CMD); - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); return ret; @@ -5670,8 +5727,8 @@ static int wdc_do_clear_fw_activate_history_fid(int fd) __u32 result; __u32 value = 1 << 31; /* Bit 31 - Clear Firmware Update History Log */ - ret = nvme_set_feature(fd, 0, WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID, value, - 0, 0, 0, 0, NULL, &result); + ret = nvme_set_features_simple(fd, WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID, 0, value, + false, &result); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); return ret; @@ -5683,6 +5740,7 @@ static int wdc_clear_fw_activate_history(int argc, char **argv, struct command * char *desc = "Clear FW activate history table."; int fd; int ret = -1; + nvme_root_t r; __u64 capabilities = 0; OPT_ARGS(opts) = { @@ -5693,7 +5751,8 @@ static int wdc_clear_fw_activate_history(int argc, char **argv, struct command * if (fd < 0) return fd; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -5708,6 +5767,7 @@ static int wdc_clear_fw_activate_history(int argc, char **argv, struct command * } out: + nvme_free_tree(r); return ret; } @@ -5720,9 +5780,9 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm char *status = "Displays the current state of the controller initiated log page."; int fd; int ret = -1; + nvme_root_t r; __u64 capabilities = 0; __u32 result; - void *buf = NULL; struct config { @@ -5748,7 +5808,8 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm if (fd < 0) return fd; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG) != WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -5764,19 +5825,19 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm } if (cfg.disable) { - ret = nvme_set_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 1, - 0, 0, 0, 0, buf, &result); + ret = nvme_set_features_simple(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 1, + false, &result); wdc_clear_reason_id(fd); } else { if (cfg.enable) { - ret = nvme_set_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, - 0, 0, 0, 0, buf, &result); + ret = nvme_set_features_simple(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 0, + false, &result); } else if (cfg.status) { - ret = nvme_get_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 0, - 0, 4, buf, &result); + ret = nvme_get_features_simple(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, + &result); if (ret == 0) { if (result) fprintf(stderr, "Controller Option Telemetry Log Page State: Disabled\n"); @@ -5796,6 +5857,7 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm } out: + nvme_free_tree(r); return ret; } @@ -5850,7 +5912,7 @@ static int wdc_get_max_transfer_len(int fd, __u32 *maxTransferLen) static int wdc_de_VU_read_size(int fd, __u32 fileId, __u16 spiDestn, __u32* logSize) { int ret = WDC_STATUS_FAILURE; - struct nvme_admin_cmd cmd; + struct nvme_passthru_cmd cmd; if(!fd || !logSize ) { @@ -5858,13 +5920,13 @@ static int wdc_de_VU_read_size(int fd, __u32 fileId, __u16 spiDestn, __u32* logS goto end; } - memset(&cmd,0,sizeof(struct nvme_admin_cmd)); + memset(&cmd,0,sizeof(struct nvme_passthru_cmd)); cmd.opcode = WDC_DE_VU_READ_SIZE_OPCODE; cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID; cmd.cdw13 = fileId<<16; cmd.cdw14 = spiDestn; - ret = nvme_submit_admin_passthru(fd, &cmd); + ret = nvme_submit_admin_passthru(fd, &cmd, NULL); if (!ret && logSize) *logSize = cmd.result; @@ -5878,7 +5940,7 @@ static int wdc_de_VU_read_size(int fd, __u32 fileId, __u16 spiDestn, __u32* logS static int wdc_de_VU_read_buffer(int fd, __u32 fileId, __u16 spiDestn, __u32 offsetInDwords, __u8* dataBuffer, __u32* bufferSize) { int ret = WDC_STATUS_FAILURE; - struct nvme_admin_cmd cmd; + struct nvme_passthru_cmd cmd; __u32 noOfDwordExpected = 0; if(!fd || !dataBuffer || !bufferSize) @@ -5887,7 +5949,7 @@ static int wdc_de_VU_read_buffer(int fd, __u32 fileId, __u16 spiDestn, __u32 off goto end; } - memset(&cmd,0,sizeof(struct nvme_admin_cmd)); + memset(&cmd,0,sizeof(struct nvme_passthru_cmd)); noOfDwordExpected = *bufferSize/sizeof(__u32); cmd.opcode = WDC_DE_VU_READ_BUFFER_OPCODE; cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID; @@ -5899,7 +5961,7 @@ static int wdc_de_VU_read_buffer(int fd, __u32 fileId, __u16 spiDestn, __u32 off cmd.addr = (__u64)(__u64)(uintptr_t)dataBuffer; cmd.data_len = *bufferSize; - ret = nvme_submit_admin_passthru(fd, &cmd); + ret = nvme_submit_admin_passthru(fd, &cmd, NULL); if( ret != WDC_STATUS_SUCCESS) fprintf(stderr, "ERROR : WDC : VUReadBuffer() failed, status:%s(0x%x)\n", nvme_status_to_string(ret), ret); @@ -6209,7 +6271,7 @@ static int wdc_de_get_dump_trace(int fd, char * filePath, __u16 binFileNameLen, return ret; } -static int wdc_do_drive_essentials(int fd, char *dir, char *key) +static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key) { int ret = 0; void *retPtr; @@ -6238,7 +6300,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) struct nvme_id_ns ns; struct nvme_error_log_page *elogBuffer; struct nvme_smart_log smart_log; - struct nvme_firmware_log_page fw_log; + struct nvme_firmware_slot fw_log; PWDC_NVME_DE_VU_LOGPAGES vuLogInput = NULL; WDC_DE_VU_LOG_DIRECTORY deEssentialsList; @@ -6314,7 +6376,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) } memset(&ns, 0, sizeof (struct nvme_id_ns)); - ret = nvme_identify_ns(fd, 1, 0, &ns); + ret = nvme_identify_ns(fd, 1, &ns); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_identify_ns() failed, ret = %d\n", ret); } else { @@ -6329,7 +6391,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) dataBuffer = calloc(1, elogBufferSize); elogBuffer = (struct nvme_error_log_page *)dataBuffer; - ret = nvme_error_log(fd, elogNumEntries, elogBuffer); + ret = nvme_get_log_error(fd, elogNumEntries, false, elogBuffer); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_error_log() failed, ret = %d\n", ret); } else { @@ -6343,7 +6405,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) /* Get Smart log page */ memset(&smart_log, 0, sizeof (struct nvme_smart_log)); - ret = nvme_smart_log(fd, NVME_NSID_ALL, &smart_log); + ret = nvme_get_log_smart(fd, NVME_NSID_ALL, false, &smart_log); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_smart_log() failed, ret = %d\n", ret); } else { @@ -6353,14 +6415,14 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) } /* Get FW Slot log page */ - memset(&fw_log, 0, sizeof (struct nvme_firmware_log_page)); - ret = nvme_fw_log(fd, &fw_log); + memset(&fw_log, 0, sizeof (struct nvme_firmware_slot)); + ret = nvme_get_log_fw_slot(fd, true, &fw_log); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_fw_log() failed, ret = %d\n", ret); } else { wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char*)bufferFolderPath, WDC_DE_PATH_SEPARATOR, "FwSLotLog", (char*)serialNo, (char*)timeString); - wdc_WriteToFile(fileName, (char*)&fw_log, sizeof(struct nvme_firmware_log_page)); + wdc_WriteToFile(fileName, (char*)&fw_log, sizeof(struct nvme_firmware_slot)); } /* Get VU log pages */ @@ -6374,8 +6436,8 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) dataBuffer = calloc(1, dataBufferSize); memset(dataBuffer, 0, dataBufferSize); - ret = nvme_get_log(fd, WDC_DE_GLOBAL_NSID, deVULogPagesList[vuLogIdx].logPageId, - false, NVME_NO_LOG_LSP, dataBufferSize, dataBuffer); + ret = nvme_get_log_simple(fd, deVULogPagesList[vuLogIdx].logPageId, + dataBufferSize, dataBuffer); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_get_log() for log page 0x%x failed, ret = %d\n", deVULogPagesList[vuLogIdx].logPageId, ret); @@ -6399,8 +6461,8 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) /* skipping LbaRangeType as it is an optional nvme command and not supported */ if (deFeatureIdList[listIdx].featureId == FID_LBA_RANGE_TYPE) continue; - ret = nvme_get_feature(fd, WDC_DE_GLOBAL_NSID, deFeatureIdList[listIdx].featureId, FS_CURRENT, 0, - 0, sizeof(featureIdBuff), &featureIdBuff, &result); + ret = nvme_get_features_data(fd, deFeatureIdList[listIdx].featureId, WDC_DE_GLOBAL_NSID, + sizeof(featureIdBuff), &featureIdBuff, &result); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_get_feature id 0x%x failed, ret = %d\n", @@ -6494,6 +6556,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) } fprintf(stderr, "Get of Drive Essentials data successful\n"); + nvme_free_tree(r); return 0; } @@ -6506,6 +6569,7 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command, char k[PATH_MAX] = {0}; char *d_ptr; int fd; + nvme_root_t r; __u64 capabilities = 0; struct config { @@ -6526,9 +6590,11 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command, if (fd < 0) return fd; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS) != WDC_DRIVE_CAP_DRIVE_ESSENTIALS) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + nvme_free_tree(r); return -1; } @@ -6539,49 +6605,49 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command, d_ptr = NULL; } - return wdc_do_drive_essentials(fd, d_ptr, k); + return wdc_do_drive_essentials(r, fd, d_ptr, k); } static int wdc_do_drive_resize(int fd, uint64_t new_size) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_DRIVE_RESIZE_OPCODE; admin_cmd.cdw12 = ((WDC_NVME_DRIVE_RESIZE_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_DRIVE_RESIZE_CMD); admin_cmd.cdw13 = new_size; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); return ret; } static int wdc_do_namespace_resize(int fd, __u32 nsid, __u32 op_option) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_NAMESPACE_RESIZE_OPCODE; admin_cmd.nsid = nsid; admin_cmd.cdw10 = op_option; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); return ret; } static int wdc_do_drive_info(int fd, __u32 *result) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_DRIVE_INFO_OPCODE; admin_cmd.cdw12 = ((WDC_NVME_DRIVE_INFO_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_DRIVE_INFO_CMD); - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (!ret && result) *result = admin_cmd.result; @@ -6594,6 +6660,7 @@ static int wdc_drive_resize(int argc, char **argv, { const char *desc = "Send a Resize command."; const char *size = "The new size (in GB) to resize the drive to."; + nvme_root_t r; uint64_t capabilities = 0; int fd, ret; @@ -6614,8 +6681,9 @@ static int wdc_drive_resize(int argc, char **argv, if (fd < 0) return fd; - wdc_check_device(fd); - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + wdc_check_device(r, fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_RESIZE) == WDC_DRIVE_CAP_RESIZE) { ret = wdc_do_drive_resize(fd, cfg.size); } else { @@ -6627,6 +6695,7 @@ static int wdc_drive_resize(int argc, char **argv, printf("New size: %" PRIu64 " GB\n", cfg.size); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_free_tree(r); return ret; } @@ -6636,6 +6705,7 @@ static int wdc_namespace_resize(int argc, char **argv, const char *desc = "Send a Namespace Resize command."; const char *namespace_id = "The namespace id to resize."; const char *op_option = "The over provisioning option to set for namespace."; + nvme_root_t r; uint64_t capabilities = 0; int fd, ret; @@ -6668,8 +6738,9 @@ static int wdc_namespace_resize(int argc, char **argv, return -1; } - wdc_check_device(fd); - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + wdc_check_device(r, fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_NS_RESIZE) == WDC_DRIVE_CAP_NS_RESIZE) { ret = wdc_do_namespace_resize(fd, cfg.namespace_id, cfg.op_option); @@ -6681,6 +6752,7 @@ static int wdc_namespace_resize(int argc, char **argv, } fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_free_tree(r); return ret; } @@ -6690,6 +6762,7 @@ static int wdc_reason_identifier(int argc, char **argv, const char *desc = "Retrieve telemetry log reason identifier."; const char *log_id = "Log ID to retrieve - host - 7 or controller - 8"; const char *fname = "File name to save raw binary identifier"; + nvme_root_t r; int fd; int ret; uint64_t capabilities = 0; @@ -6719,7 +6792,9 @@ static int wdc_reason_identifier(int argc, char **argv, if (fd < 0) return fd; - if (cfg.log_id != NVME_LOG_TELEMETRY_HOST && cfg.log_id != NVME_LOG_TELEMETRY_CTRL) { + r = nvme_scan(NULL); + + if (cfg.log_id != NVME_LOG_LID_TELEMETRY_HOST&& cfg.log_id != NVME_LOG_LID_TELEMETRY_CTRL) { fprintf(stderr, "ERROR : WDC: Invalid Log ID. It must be 7 (Host) or 8 (Controller)\n"); ret = -1; goto close_fd; @@ -6743,7 +6818,7 @@ static int wdc_reason_identifier(int argc, char **argv, wdc_UtilsSnprintf((char*)timeStamp, MAX_PATH_LEN, "%02u%02u%02u_%02u%02u%02u", timeInfo.year, timeInfo.month, timeInfo.dayOfMonth, timeInfo.hour, timeInfo.minute, timeInfo.second); - if (cfg.log_id == NVME_LOG_TELEMETRY_CTRL) + if (cfg.log_id == NVME_LOG_LID_TELEMETRY_CTRL) snprintf(fileSuffix, PATH_MAX, "_error_reason_identifier_ctlr_%s", (char*)timeStamp); else snprintf(fileSuffix, PATH_MAX, "_error_reason_identifier_host_%s", (char*)timeStamp); @@ -6759,7 +6834,7 @@ static int wdc_reason_identifier(int argc, char **argv, fprintf(stderr, "%s: filename = %s\n", __func__, f); - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_REASON_ID) == WDC_DRIVE_CAP_REASON_ID) { ret = wdc_do_get_reason_id(fd, f, cfg.log_id); } else { @@ -6770,27 +6845,28 @@ static int wdc_reason_identifier(int argc, char **argv, fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); close_fd: - close(fd); - return ret; + close(fd); + nvme_free_tree(r); + return ret; } static const char *nvme_log_id_to_string(__u8 log_id) { switch (log_id) { - case NVME_LOG_ERROR: return "Error Information Log ID"; - case NVME_LOG_SMART: return "Smart/Health Information Log ID"; - case NVME_LOG_FW_SLOT: return "Firmware Slot Information Log ID"; - case NVME_LOG_CHANGED_NS: return "Namespace Changed Log ID"; - case NVME_LOG_CMD_EFFECTS: return "Commamds Supported and Effects Log ID"; - case NVME_LOG_DEVICE_SELF_TEST: return "Device Self Test Log ID"; - case NVME_LOG_TELEMETRY_HOST: return "Telemetry Host Initiated Log ID"; - case NVME_LOG_TELEMETRY_CTRL: return "Telemetry Controller Generated Log ID"; - case NVME_LOG_ENDURANCE_GROUP: return "Endurance Group Log ID"; - case NVME_LOG_ANA: return "ANA Log ID"; - case NVME_LOG_PERSISTENT_EVENT: return "Persistent Event Log ID"; - case NVME_LOG_DISC: return "Discovery Log ID"; - case NVME_LOG_RESERVATION: return "Reservation Notification Log ID"; - case NVME_LOG_SANITIZE: return "Sanitize Status Log ID"; + case NVME_LOG_LID_ERROR: return "Error Information Log ID"; + case NVME_LOG_LID_SMART: return "Smart/Health Information Log ID"; + case NVME_LOG_LID_FW_SLOT: return "Firmware Slot Information Log ID"; + case NVME_LOG_LID_CHANGED_NS: return "Namespace Changed Log ID"; + case NVME_LOG_LID_CMD_EFFECTS: return "Commamds Supported and Effects Log ID"; + case NVME_LOG_LID_DEVICE_SELF_TEST: return "Device Self Test Log ID"; + case NVME_LOG_LID_TELEMETRY_HOST: return "Telemetry Host Initiated Log ID"; + case NVME_LOG_LID_TELEMETRY_CTRL: return "Telemetry Controller Generated Log ID"; + case NVME_LOG_LID_ENDURANCE_GROUP: return "Endurance Group Log ID"; + case NVME_LOG_LID_ANA: return "ANA Log ID"; + case NVME_LOG_LID_PERSISTENT_EVENT: return "Persistent Event Log ID"; + case NVME_LOG_LID_DISCOVER: return "Discovery Log ID"; + case NVME_LOG_LID_RESERVATION: return "Reservation Notification Log ID"; + case NVME_LOG_LID_SANITIZE: return "Sanitize Status Log ID"; case WDC_LOG_ID_C0: return "WDC Vendor Unique Log ID"; case WDC_LOG_ID_C1: return "WDC Vendor Unique Log ID"; @@ -6822,11 +6898,10 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command const char *desc = "Retrieve Log Page Directory."; int fd; int ret = 0; + nvme_root_t r; __u64 capabilities = 0; struct wdc_c2_cbs_data *cbs_data = NULL; - int i; - __u8 log_id = 0; - __u32 device_id, read_vendor_id; + int i; struct config { char *output_format; @@ -6851,24 +6926,21 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command return ret; } - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; - } - else { - ret = wdc_get_pci_ids(&device_id, &read_vendor_id); - log_id = (device_id == WDC_NVME_ZN350_DEV_ID || device_id == WDC_NVME_ZN350_DEV_ID_1) ? - WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE_C8 : WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE; + } else { /* verify the 0xC2 Device Manageability log page is supported */ - if (wdc_nvme_check_supported_log_page(fd, log_id) == false) { - fprintf(stderr, "%s: ERROR : WDC : 0x%x Log Page not supported\n", __func__, log_id); + if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE) == false) { + fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page not supported\n", __func__); ret = -1; goto out; } - if (get_dev_mgment_cbs_data(fd, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { + if (get_dev_mgment_cbs_data(r, fd, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { if (cbs_data != NULL) { printf("Log Page Directory\n"); /* print the supported pages */ @@ -6902,6 +6974,7 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command } out: + nvme_free_tree(r); return ret; } @@ -7008,14 +7081,33 @@ static int wdc_clear_reason_id(int fd) return ret; } +static int wdc_dump_telemetry_hdr(int fd, int log_id, struct nvme_telemetry_log *log_hdr) +{ + int ret = 0; + + if (log_id == NVME_LOG_LID_TELEMETRY_HOST) + ret = nvme_get_log_create_telemetry_host(fd, log_hdr); + else + ret = nvme_get_log_telemetry_ctrl(fd, false, 0, 512, (void *)log_hdr); + + if (ret < 0) + perror("get-telemetry-log"); + else if (ret > 0) { + fprintf(stderr, "NVMe status: %s(%#x)\n", nvme_status_to_string(ret), ret); + fprintf(stderr, "%s: ERROR : Failed to acquire telemetry header, ret = %d!\n", __func__, ret); + } + + return ret; +} + static int wdc_do_get_reason_id(int fd, char *file, int log_id) { int ret; - struct nvme_telemetry_log_page_hdr *log_hdr; - __u32 log_hdr_size = sizeof(struct nvme_telemetry_log_page_hdr); + struct nvme_telemetry_log *log_hdr; + __u32 log_hdr_size = sizeof(struct nvme_telemetry_log); __u32 reason_id_size = 0; - log_hdr = (struct nvme_telemetry_log_page_hdr *) malloc(log_hdr_size); + log_hdr = (struct nvme_telemetry_log *) malloc(log_hdr_size); if (log_hdr == NULL) { fprintf(stderr, "%s: ERROR : malloc failed, size : 0x%x, status : %s\n", __func__, log_hdr_size, strerror(errno)); ret = -1; @@ -7032,7 +7124,7 @@ static int wdc_do_get_reason_id(int fd, char *file, int log_id) reason_id_size = sizeof(log_hdr->rsnident); - if (log_id == NVME_LOG_TELEMETRY_CTRL) + if (log_id == NVME_LOG_LID_TELEMETRY_CTRL) wdc_save_reason_id(fd, log_hdr->rsnident, reason_id_size); ret = wdc_create_log_file(file, (__u8 *)log_hdr->rsnident, reason_id_size); @@ -7042,27 +7134,6 @@ static int wdc_do_get_reason_id(int fd, char *file, int log_id) return ret; } -static int wdc_dump_telemetry_hdr(int fd, int log_id, struct nvme_telemetry_log_page_hdr *log_hdr) -{ - int ret = 0; - int host_gen = 0, ctrl_init = 0; - - if (log_id == NVME_LOG_TELEMETRY_HOST) - host_gen = 1; - else - ctrl_init = 1; - - ret = nvme_get_telemetry_log(fd, log_hdr, host_gen, ctrl_init, 512, 0); - if (ret < 0) - perror("get-telemetry-log"); - else if (ret > 0) { - nvme_show_status(ret); - fprintf(stderr, "%s: ERROR : Failed to acquire telemetry header, ret = %d!\n", __func__, ret); - } - - return ret; -} - static void wdc_print_nand_stats_normal(__u16 version, void *data) { struct wdc_nand_stats *nand_stats = (struct wdc_nand_stats *)(data); @@ -7422,8 +7493,8 @@ static int wdc_do_vs_nand_stats(int fd, char *format) goto out; } - ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_NAND_STATS_LOG_ID, - false, NVME_NO_LOG_LSP, WDC_NVME_NAND_STATS_SIZE, (void*)output); + ret = nvme_get_log_simple(fd, WDC_NVME_NAND_STATS_LOG_ID, + WDC_NVME_NAND_STATS_SIZE, (void*)output); if (ret) { fprintf(stderr, "ERROR : WDC : %s : Failed to retreive NAND stats\n", __func__); goto out; @@ -7460,6 +7531,7 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, int fd; int ret = 0; + nvme_root_t r; __u64 capabilities = 0; struct config { @@ -7479,7 +7551,8 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, if (fd < 0) return fd; - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_NAND_STATS) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -7490,6 +7563,7 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, fprintf(stderr, "ERROR : WDC : Failure reading NAND statistics, ret = %d\n", ret); } + nvme_free_tree(r); return ret; } @@ -7497,15 +7571,15 @@ static int wdc_do_vs_pcie_stats(int fd, struct wdc_vs_pcie_stats *pcieStatsPtr) { int ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; int pcie_stats_size = sizeof(struct wdc_vs_pcie_stats); - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_PCIE_STATS_OPCODE; admin_cmd.addr = (__u64)(uintptr_t)pcieStatsPtr; admin_cmd.data_len = pcie_stats_size; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); return ret; } @@ -7517,6 +7591,7 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, int fd; int ret = 0; + nvme_root_t r; __u64 capabilities = 0; int fmt = -1; struct wdc_vs_pcie_stats *pcieStatsPtr = NULL; @@ -7540,6 +7615,8 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, if (fd < 0) return fd; + + r = nvme_scan(NULL); fmt = validate_output_format(cfg.output_format); if (fmt < 0) { fprintf(stderr, "ERROR : WDC : invalid output format\n"); @@ -7556,7 +7633,7 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, memset((void *)pcieStatsPtr, 0, pcie_stats_size); - capabilities = wdc_get_drive_capabilities(fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_PCIE_STATS) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -7581,6 +7658,7 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, nvme_free(pcieStatsPtr, huge); out: + nvme_free_tree(r); return ret; } @@ -7588,6 +7666,7 @@ static int wdc_vs_drive_info(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Send a vs-drive-info command."; + nvme_root_t r; uint64_t capabilities = 0; int fd, ret; __le32 result; @@ -7632,8 +7711,9 @@ static int wdc_vs_drive_info(int argc, char **argv, return ret; } - wdc_check_device(fd); - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + wdc_check_device(r, fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_INFO) == WDC_DRIVE_CAP_INFO) { ret = wdc_do_drive_info(fd, &result); @@ -7686,11 +7766,13 @@ static int wdc_vs_drive_info(int argc, char **argv, } } else { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + nvme_free_tree(r); return -1; } fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_free_tree(r); return ret; } @@ -7700,6 +7782,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv, const char *desc = "Send a vs-temperature-stats command."; struct nvme_smart_log smart_log; struct nvme_id_ctrl id_ctrl; + nvme_root_t r; uint64_t capabilities = 0; __u32 hctm_tmt; int fd, ret; @@ -7723,6 +7806,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv, if (fd < 0) return fd; + r = nvme_scan(NULL); fmt = validate_output_format(cfg.output_format); if (fmt < 0) { fprintf(stderr, "ERROR : WDC : invalid output format\n"); @@ -7731,10 +7815,11 @@ static int wdc_vs_temperature_stats(int argc, char **argv, } /* check if command is supported */ - wdc_check_device(fd); - capabilities = wdc_get_drive_capabilities(fd); + wdc_check_device(r, fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_TEMP_STATS) != WDC_DRIVE_CAP_TEMP_STATS) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + nvme_free_tree(r); return -1; } @@ -7742,7 +7827,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv, ret = nvme_identify_ctrl(fd, &id_ctrl); if (ret != 0) goto END; - ret = nvme_smart_log(fd, NVME_NSID_ALL, &smart_log); + ret = nvme_get_log_smart(fd, NVME_NSID_ALL, false, &smart_log); if (ret != 0) goto END; @@ -7750,7 +7835,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv, temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]) - 273; /* retrieve HCTM Thermal Management Temperatures */ - nvme_get_feature(fd, 0, 0x10, 0, 0, 0, 0, 0, &hctm_tmt); + nvme_get_features_simple(fd, 0x10, 0, &hctm_tmt); temp_tmt1 = ((hctm_tmt >> 16) & 0xffff) ? ((hctm_tmt >> 16) & 0xffff) - 273 : 0; temp_tmt2 = (hctm_tmt & 0xffff) ? (hctm_tmt & 0xffff) - 273 : 0; @@ -7803,6 +7888,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv, END: fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + nvme_free_tree(r); return ret; } @@ -7810,6 +7896,7 @@ static int wdc_capabilities(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Send a capabilities command."; + nvme_root_t r; uint64_t capabilities = 0; int fd; @@ -7823,8 +7910,9 @@ static int wdc_capabilities(int argc, char **argv, return fd; /* get capabilities */ - wdc_check_device(fd); - capabilities = wdc_get_drive_capabilities(fd); + r = nvme_scan(NULL); + wdc_check_device(r, fd); + capabilities = wdc_get_drive_capabilities(r, fd); /* print command and supported status */ printf("WDC Plugin Capabilities for NVME device:%s\n", devicename); @@ -7886,28 +7974,30 @@ static int wdc_capabilities(int argc, char **argv, printf("vs-pcie-stats : %s\n", capabilities & WDC_DRIVE_CAP_PCIE_STATS ? "Supported" : "Not Supported"); printf("capabilities : Supported\n"); + nvme_free_tree(r); return 0; } static int wdc_cloud_ssd_plugin_version(int argc, char **argv, struct command *command, struct plugin *plugin) { - const char *desc = "Get Cloud SSD Plugin Version command."; - uint64_t capabilities = 0; - int fd; + const char *desc = "Get Cloud SSD Plugin Version command."; + nvme_root_t r; + uint64_t capabilities = 0; + int fd; - OPT_ARGS(opts) = - { - OPT_END() - }; + OPT_ARGS(opts) = { + OPT_END() + }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + return fd; - /* get capabilities */ - wdc_check_device(fd); - capabilities = wdc_get_drive_capabilities(fd); + /* get capabilities */ + r = nvme_scan(NULL); + wdc_check_device(r, fd); + capabilities = wdc_get_drive_capabilities(r, fd); if ((capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION) == WDC_DRIVE_CAP_CLOUD_SSD_VERSION) { /* print command and supported status */ @@ -7916,7 +8006,8 @@ static int wdc_cloud_ssd_plugin_version(int argc, char **argv, fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); } - return 0; + nvme_free_tree(r); + return 0; } static int wdc_enc_get_log(int argc, char **argv, struct command *command, @@ -8029,7 +8120,7 @@ static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, F cmd = (len) ? cmd : buf; len = (len) ? len : 0x20; - struct nvme_admin_cmd nvme_cmd = { + struct nvme_passthru_cmd nvme_cmd = { .opcode = WDC_NVME_ADMIN_ENC_MGMT_SND, .nsid = 0, .addr = (__u64)(uintptr_t) cmd, @@ -8062,7 +8153,7 @@ static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, F d); #endif nvme_cmd.result = 0; - err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd); + err = nvme_submit_admin_passthru(fd, &nvme_cmd, NULL); if (err == NVME_SC_INTERNAL) { fprintf(stderr, "%s: WARNING : WDC : No log ID:x%x available\n", __func__, log_id); @@ -8090,7 +8181,7 @@ static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, F nvme_cmd.cdw14 = cdw14; nvme_cmd.cdw15 = cdw15; nvme_cmd.result = 0; /* returned result !=0 indicates more data available */ - err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd); + err = nvme_submit_admin_passthru(fd, &nvme_cmd, NULL); if (err != 0) { more = 0; fprintf(stderr, "%s: ERROR : WDC : NVMe Rcv Mgmt Status:%s(x%x)\n", @@ -8117,7 +8208,7 @@ static int wdc_enc_get_nic_log(int fd, __u8 log_id, __u32 xfer_size, __u32 data_ __u8 *dump_data; __u32 curr_data_offset, curr_data_len; int i, ret; - struct nvme_admin_cmd admin_cmd; + struct nvme_passthru_cmd admin_cmd; __u32 dump_length = data_len; __u32 numd; __u16 numdu, numdl; @@ -8128,7 +8219,7 @@ static int wdc_enc_get_nic_log(int fd, __u8 log_id, __u32 xfer_size, __u32 data_ return -1; } memset(dump_data, 0, sizeof (__u8) * dump_length); - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); curr_data_offset = 0; curr_data_len = xfer_size; i = 0; @@ -8147,7 +8238,7 @@ static int wdc_enc_get_nic_log(int fd, __u8 log_id, __u32 xfer_size, __u32 data_ #ifdef WDC_NVME_CLI_DEBUG fprintf(stderr, "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x \n", admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd.cdw10, admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd.cdw14); #endif - ret = nvme_submit_admin_passthru(fd, &admin_cmd); + ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); if (ret !=0 ) { fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n",__func__, nvme_status_to_string(ret), ret); fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n", diff --git a/plugins/ymtc/ymtc-nvme.c b/plugins/ymtc/ymtc-nvme.c index d599f23137..2a6609b3ac 100644 --- a/plugins/ymtc/ymtc-nvme.c +++ b/plugins/ymtc/ymtc-nvme.c @@ -4,13 +4,8 @@ #include #include -#include "linux/nvme_ioctl.h" - #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" #include "argconfig.h" @@ -135,8 +130,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, if (fd < 0) return fd; - err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, - NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log); + err = nvme_get_nsid_log(fd, 0xca, cfg.namespace_id, + sizeof(smart_log), &smart_log); if (!err) { if (!cfg.raw_binary) err = show_ymtc_smart_log(fd, cfg.namespace_id, devicename, &smart_log); diff --git a/plugins/zns/zns.c b/plugins/zns/zns.c index 70959a35ad..a5929f4f72 100644 --- a/plugins/zns/zns.c +++ b/plugins/zns/zns.c @@ -8,11 +8,8 @@ #include #include "nvme.h" -#include "linux/nvme.h" -#include "nvme-private.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "nvme-print.h" -#include "nvme-status.h" #define CREATE_CMD #include "zns.h" @@ -107,14 +104,14 @@ 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"); goto close_fd; } } - err = nvme_identify_ns(fd, cfg.namespace_id, false, &id_ns); + err = nvme_identify_ns(fd, cfg.namespace_id, &id_ns); if (err) { nvme_show_status(err); goto close_fd; @@ -176,7 +173,7 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug 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"); goto free; @@ -207,7 +204,7 @@ static int get_zdes_bytes(int fd, __u32 nsid) __u8 lbaf; int err; - err = nvme_identify_ns(fd, nsid, false, &id_ns); + err = nvme_identify_ns(fd, nsid, &id_ns); if (err > 0) { nvme_show_status(err); return -1; @@ -267,7 +264,7 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu return errno; 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"); goto close_fd; @@ -407,7 +404,7 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug return errno; 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"); goto close_fd; @@ -512,7 +509,7 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu 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"); goto close_fd; @@ -604,7 +601,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi 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"); goto close_fd; @@ -736,14 +733,14 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin } 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"); goto close_fd; } } - err = nvme_identify_ns(fd, cfg.namespace_id, false, &ns); + err = nvme_identify_ns(fd, cfg.namespace_id, &ns); if (err) { nvme_show_status(err); goto close_fd; @@ -823,11 +820,11 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin nblocks = (cfg.data_size / lba_size) - 1; control |= (cfg.prinfo << 10); if (cfg.limited_retry) - control |= NVME_RW_LR; + control |= NVME_IO_LR; if (cfg.fua) - control |= NVME_RW_FUA; + control |= NVME_IO_FUA; if (cfg.piremap) - control |= NVME_RW_PIREMAP; + control |= NVME_IO_ZNS_APPEND_PIREMAP; gettimeofday(&start_time, NULL); err = nvme_zns_append(fd, cfg.namespace_id, cfg.zslba, nblocks, @@ -897,15 +894,15 @@ static int changed_zone_list(int argc, char **argv, struct command *cmd, struct 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"); goto close_fd; } } - err = nvme_get_log(fd, cfg.namespace_id, NVME_LOG_ZONE_CHANGED_LIST, - cfg.rae, NVME_NO_LOG_LSP, sizeof(log), &log); + err = nvme_get_nsid_log(fd, NVME_LOG_LID_ZNS_CHANGED_ZONES, cfg.namespace_id, + sizeof(log), &log); if (!err) nvme_show_zns_changed(&log, flags); else if (err > 0)