diff --git a/.github/cross/ubuntu-cross-armhf.txt b/.github/cross/ubuntu-cross-armhf.txt index 41c8328906..ac5dd62209 100644 --- a/.github/cross/ubuntu-cross-armhf.txt +++ b/.github/cross/ubuntu-cross-armhf.txt @@ -6,6 +6,9 @@ pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config' ld = '/usr/bin/arm-linux/gnueabihf-ld' exe_wrapper = '/usr/bin/qemu-arm-static' +c_native = 'gcc' +cpp_native = 'g++' + [properties] root = '/usr/arm-linux-gnueabihf' has_function_printf = true diff --git a/.github/cross/ubuntu-cross-ppc64le.txt b/.github/cross/ubuntu-cross-ppc64le.txt index 6baaefbc26..76b00e4c3f 100644 --- a/.github/cross/ubuntu-cross-ppc64le.txt +++ b/.github/cross/ubuntu-cross-ppc64le.txt @@ -6,6 +6,9 @@ pkgconfig = '/usr/bin/powerpc64le-linux-gnu-pkg-config' ld = '/usr/bin/powerpc64le-linux-gnu-ld' exe_wrapper = '/usr/bin/qemu-ppc64le-static' +c_native = 'gcc' +cpp_native = 'g++' + [properties] root = '/usr/powerpc64le-linux-gnu' has_function_printf = true diff --git a/.github/cross/ubuntu-cross-s390x.txt b/.github/cross/ubuntu-cross-s390x.txt index 51a3511fbe..dae5b76d51 100644 --- a/.github/cross/ubuntu-cross-s390x.txt +++ b/.github/cross/ubuntu-cross-s390x.txt @@ -6,6 +6,9 @@ pkgconfig = '/usr/bin/s390x-linux-gnu-pkg-config' ld = '/usr/bin/s390x-linux-gnu-ld' exe_wrapper = '/usr/bin/qemu-s390x-static' +c_native = 'gcc' +cpp_native = 'g++' + [properties] root = '/usr/s390x-linux-gnu' has_function_printf = true diff --git a/README.md b/README.md index 77f4b4344d..51f2874923 100644 --- a/README.md +++ b/README.md @@ -149,7 +149,7 @@ callback, and the plug-in structure that contains that command. The prototype looks like this: ```c - int f(int argc, char **argv, struct command *cmd, struct plugin *plugin); + int f(int argc, char **argv, struct command *command, struct plugin *plugin); ``` The argc and argv are adjusted from the command line arguments to start diff --git a/cmd_handler.h b/cmd_handler.h index c4b26f4d5c..e886a15270 100644 --- a/cmd_handler.h +++ b/cmd_handler.h @@ -10,7 +10,7 @@ #undef ENTRY #define ENTRY(n, h, f, ...) \ -static int f(int argc, char **argv, struct command *command, struct plugin *plugin); +static int f(int argc, char **argv, struct command *acmd, struct plugin *plugin); #undef COMMAND_LIST #define COMMAND_LIST(args...) args diff --git a/fabrics.c b/fabrics.c index a53cd4b1cc..6537610937 100644 --- a/fabrics.c +++ b/fabrics.c @@ -171,7 +171,6 @@ static int set_discovery_kato(struct nvme_fabrics_config *cfg) return tmo; } - static int nvme_add_ctrl(nvme_host_t h, nvme_ctrl_t c, struct nvme_fabrics_config *cfg) { @@ -182,31 +181,31 @@ static int nvme_add_ctrl(nvme_host_t h, nvme_ctrl_t c, * __create_discover_ctrl and callers depend on errno being set * in the error case. */ - errno = 0; ret = nvmf_add_ctrl(h, c, cfg); if (!ret) return 0; - if (errno == EAGAIN || (errno == EINTR && !nvme_sigint_received)) { - print_debug("nvmf_add_ctrl returned '%s'\n", strerror(errno)); + if (ret == -EAGAIN || (ret == -EINTR && !nvme_sigint_received)) { + print_debug("nvmf_add_ctrl returned '%s'\n", strerror(-ret)); goto retry; } - return -errno; + return ret; } -static nvme_ctrl_t __create_discover_ctrl(nvme_root_t r, nvme_host_t h, - struct nvme_fabrics_config *cfg, - struct tr_config *trcfg) +static int __create_discover_ctrl(struct nvme_global_ctx *ctx, nvme_host_t h, + struct nvme_fabrics_config *cfg, + struct tr_config *trcfg, + nvme_ctrl_t *ctrl) { nvme_ctrl_t c; int tmo, ret; - c = nvme_create_ctrl(r, trcfg->subsysnqn, trcfg->transport, + ret = nvme_create_ctrl(ctx, trcfg->subsysnqn, trcfg->transport, trcfg->traddr, trcfg->host_traddr, - trcfg->host_iface, trcfg->trsvcid); - if (!c) - return NULL; + trcfg->host_iface, trcfg->trsvcid, &c); + if (ret) + return ret; nvme_ctrl_set_discovery_ctrl(c, true); nvme_ctrl_set_unique_discovery_ctrl(c, @@ -217,41 +216,51 @@ static nvme_ctrl_t __create_discover_ctrl(nvme_root_t r, nvme_host_t h, cfg->keep_alive_tmo = tmo; if (ret) { nvme_free_ctrl(c); - return NULL; + return ret; } - return c; + *ctrl = c; + return 0; } -nvme_ctrl_t nvmf_create_discover_ctrl(nvme_root_t r, nvme_host_t h, - struct nvme_fabrics_config *cfg, - struct tr_config *trcfg) +int nvmf_create_discover_ctrl(struct nvme_global_ctx *ctx, nvme_host_t h, + struct nvme_fabrics_config *cfg, + struct tr_config *trcfg, + nvme_ctrl_t *ctrl) { _cleanup_free_ struct nvme_id_ctrl *id = NULL; nvme_ctrl_t c; + int ret; - c = __create_discover_ctrl(r, h, cfg, trcfg); - if (!c) - return NULL; + ret = __create_discover_ctrl(ctx, h, cfg, trcfg, &c); + if (ret) + return ret; - if (nvme_ctrl_is_unique_discovery_ctrl(c)) - return c; + if (nvme_ctrl_is_unique_discovery_ctrl(c)) { + *ctrl = c; + return 0; + } id = nvme_alloc(sizeof(*id)); - if (!id) - return NULL; + if (!id) { + nvme_free_ctrl(c); + return -ENOMEM; + } /* Find out the name of discovery controller */ - if (nvme_ctrl_identify(c, id)) { + ret = nvme_ctrl_identify(c, id); + if (ret) { fprintf(stderr, "failed to identify controller, error %s\n", - nvme_strerror(errno)); + nvme_strerror(-ret)); nvme_disconnect_ctrl(c); nvme_free_ctrl(c); - return NULL; + return ret; } - if (!strcmp(id->subnqn, NVME_DISC_SUBSYS_NAME)) - return c; + if (!strcmp(id->subnqn, NVME_DISC_SUBSYS_NAME)) { + *ctrl = c; + return 0; + } /* * The subsysnqn is not the well-known name. Prefer the unique @@ -261,7 +270,12 @@ nvme_ctrl_t nvmf_create_discover_ctrl(nvme_root_t r, nvme_host_t h, nvme_free_ctrl(c); trcfg->subsysnqn = id->subnqn; - return __create_discover_ctrl(r, h, cfg, trcfg); + ret = __create_discover_ctrl(ctx, h, cfg, trcfg, &c); + if (ret) + return ret; + + *ctrl = c; + return 0; } static void save_discovery_log(char *raw, struct nvmf_discovery_log *log) @@ -295,6 +309,7 @@ static int __discover(nvme_ctrl_t c, struct nvme_fabrics_config *defcfg, nvme_subsystem_t s = nvme_ctrl_get_subsystem(c); nvme_host_t h = nvme_subsystem_get_host(s); uint64_t numrec; + int err; struct nvme_get_discovery_args args = { .c = c, @@ -305,11 +320,11 @@ static int __discover(nvme_ctrl_t c, struct nvme_fabrics_config *defcfg, .lsp = 0, }; - log = nvmf_get_discovery_wargs(&args); - if (!log) { + err = nvmf_get_discovery_wargs(&args, &log); + if (err) { fprintf(stderr, "failed to get discovery log: %s\n", - nvme_strerror(errno)); - return -errno; + nvme_strerror(err)); + return err; } numrec = le64_to_cpu(log->numrec); @@ -377,13 +392,12 @@ static int __discover(nvme_ctrl_t c, struct nvme_fabrics_config *defcfg, disconnect = false; } - errno = 0; - child = nvmf_connect_disc_entry(h, e, defcfg, - &discover); + err = nvmf_connect_disc_entry(h, e, defcfg, + &discover, &child); defcfg->keep_alive_tmo = tmo; - if (child) { + if (!child) { if (discover) __discover(child, defcfg, raw, true, persistent, flags); @@ -392,7 +406,7 @@ static int __discover(nvme_ctrl_t c, struct nvme_fabrics_config *defcfg, nvme_disconnect_ctrl(child); nvme_free_ctrl(child); } - } else if (errno == ENVME_CONNECT_ALREADY && !quiet) { + } else if (err == -ENVME_CONNECT_ALREADY && !quiet) { const char *subnqn = log->entries[i].subnqn; const char *trtype = nvmf_trtype_str(log->entries[i].trtype); const char *traddr = log->entries[i].traddr; @@ -410,7 +424,7 @@ static int __discover(nvme_ctrl_t c, struct nvme_fabrics_config *defcfg, return 0; } -char *nvmf_get_default_trsvcid(const char *transport, bool discovery_ctrl) +char * nvmf_get_default_trsvcid(const char *transport, bool discovery_ctrl) { if (!transport) return NULL; @@ -428,7 +442,7 @@ char *nvmf_get_default_trsvcid(const char *transport, bool discovery_ctrl) return NULL; } -static int discover_from_conf_file(nvme_root_t r, nvme_host_t h, +static int discover_from_conf_file(struct nvme_global_ctx *ctx, nvme_host_t h, const char *desc, bool connect, const struct nvme_fabrics_config *defcfg) { @@ -514,8 +528,8 @@ static int discover_from_conf_file(nvme_root_t r, nvme_host_t h, } } - c = nvmf_create_discover_ctrl(r, h, &cfg, &trcfg); - if (!c) + ret = nvmf_create_discover_ctrl(ctx, h, &cfg, &trcfg, &c); + if (ret) goto next; __discover(c, &cfg, raw, connect, persistent, flags); @@ -531,11 +545,11 @@ static int discover_from_conf_file(nvme_root_t r, nvme_host_t h, return ret; } -static int _discover_from_json_config_file(nvme_root_t r, nvme_host_t h, - nvme_ctrl_t c, const char *desc, bool connect, - const struct nvme_fabrics_config *defcfg, - nvme_print_flags_t flags, - bool force) +static int _discover_from_json_config_file(struct nvme_global_ctx *ctx, + nvme_host_t h, nvme_ctrl_t c, + const char *desc, bool connect, + const struct nvme_fabrics_config *defcfg, + nvme_print_flags_t flags, bool force) { const char *transport, *traddr, *host_traddr; const char *host_iface, *trsvcid, *subsysnqn; @@ -605,8 +619,8 @@ static int _discover_from_json_config_file(nvme_root_t r, nvme_host_t h, } } - cn = nvmf_create_discover_ctrl(r, h, &cfg, &trcfg); - if (!cn) + ret = nvmf_create_discover_ctrl(ctx, h, &cfg, &trcfg, &cn); + if (ret) return 0; __discover(cn, &cfg, raw, connect, persistent, flags); @@ -617,12 +631,12 @@ static int _discover_from_json_config_file(nvme_root_t r, nvme_host_t h, return ret; } -static int discover_from_json_config_file(nvme_root_t r, const char *hostnqn, +static int discover_from_json_config_file(struct nvme_global_ctx *ctx, + const char *hostnqn, const char *hostid, const char *desc, bool connect, const struct nvme_fabrics_config *defcfg, - nvme_print_flags_t flags, - bool force) + nvme_print_flags_t flags, bool force) { const char *hnqn, *hid; nvme_host_t h; @@ -630,7 +644,7 @@ static int discover_from_json_config_file(nvme_root_t r, const char *hostnqn, nvme_ctrl_t c; int ret = 0, err; - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { hnqn = nvme_host_get_hostnqn(h); if (hostnqn && hnqn && strcmp(hostnqn, hnqn)) @@ -641,7 +655,7 @@ static int discover_from_json_config_file(nvme_root_t r, const char *hostnqn, nvme_subsystem_for_each_ctrl(s, c) { err = _discover_from_json_config_file( - r, h, c, desc, connect, defcfg, + ctx, h, c, desc, connect, defcfg, flags, force); if (err) { @@ -661,7 +675,7 @@ static int discover_from_json_config_file(nvme_root_t r, const char *hostnqn, return ret; } -static int nvme_read_volatile_config(nvme_root_t r) +static int nvme_read_volatile_config(struct nvme_global_ctx *ctx) { char *filename, *ext; struct dirent *dir; @@ -685,7 +699,7 @@ static int nvme_read_volatile_config(nvme_root_t r) break; } - if (nvme_read_config(r, filename)) + if (nvme_read_config(ctx, filename)) ret = 0; free(filename); @@ -695,13 +709,13 @@ static int nvme_read_volatile_config(nvme_root_t r) return ret; } -static int nvme_read_config_checked(nvme_root_t r, const char *filename) +static int nvme_read_config_checked(struct nvme_global_ctx *ctx, + const char *filename) { if (access(filename, F_OK)) return -errno; - if (nvme_read_config(r, filename)) - return -errno; - return 0; + + return nvme_read_config(ctx, filename); } /* returns negative errno values */ @@ -717,7 +731,7 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect) _cleanup_free_ char *hid = NULL; char *context = NULL; nvme_print_flags_t flags; - _cleanup_nvme_root_ nvme_root_t r = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; nvme_host_t h; nvme_ctrl_t c = NULL; unsigned int verbose = 0; @@ -762,33 +776,33 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect) log_level = map_log_level(verbose, quiet); - r = nvme_create_root(stderr, log_level); - if (!r) { + ctx = nvme_create_global_ctx(stderr, log_level); + if (!ctx) { fprintf(stderr, "Failed to create topology root: %s\n", nvme_strerror(errno)); - return -errno; + return -ENOMEM; } if (context) - nvme_root_set_application(r, context); + nvme_set_application(ctx, context); - if (!nvme_read_config_checked(r, config_file)) + if (!nvme_read_config_checked(ctx, config_file)) json_config = true; - if (!nvme_read_volatile_config(r)) + if (!nvme_read_volatile_config(ctx)) json_config = true; - nvme_root_skip_namespaces(r); - ret = nvme_scan_topology(r, NULL, NULL); + nvme_skip_namespaces(ctx); + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret < 0) { fprintf(stderr, "Failed to scan topology: %s\n", - nvme_strerror(errno)); - return -errno; + nvme_strerror(-ret)); + return ret; } - ret = nvme_host_get_ids(r, hostnqn, hostid, &hnqn, &hid); + ret = nvme_host_get_ids(ctx, hostnqn, hostid, &hnqn, &hid); if (ret < 0) - return -errno; + return ret; - h = nvme_lookup_host(r, hnqn, hid); + h = nvme_lookup_host(ctx, hnqn, hid); if (!h) { ret = -ENOMEM; goto out_free; @@ -805,20 +819,20 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect) if (!device && !transport && !traddr) { if (!nonbft) - ret = discover_from_nbft(r, hostnqn, hostid, + ret = discover_from_nbft(ctx, hostnqn, hostid, hnqn, hid, desc, connect, &cfg, nbft_path, flags, verbose); if (nbft) goto out_free; if (json_config) - ret = discover_from_json_config_file(r, hostnqn, hostid, + ret = discover_from_json_config_file(ctx, hostnqn, hostid, desc, connect, &cfg, flags, force); if (ret || access(PATH_NVMF_DISC, F_OK)) goto out_free; - ret = discover_from_conf_file(r, h, desc, connect, &cfg); + ret = discover_from_conf_file(ctx, h, desc, connect, &cfg); goto out_free; } @@ -835,8 +849,8 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect) }; if (device && !force) { - c = nvme_scan_ctrl(r, device); - if (c) { + ret = nvme_scan_ctrl(ctx, device, &c); + if (!ret) { /* Check if device matches command-line options */ if (!nvme_ctrl_config_match(c, transport, traddr, trsvcid, subsysnqn, cfg.host_traddr, cfg.host_iface)) { @@ -893,13 +907,12 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect) } if (!c) { /* No device or non-matching device, create a new controller */ - c = nvmf_create_discover_ctrl(r, h, &cfg, &trcfg); - if (!c) { - if (errno != ENVME_CONNECT_IGNORED) + ret = nvmf_create_discover_ctrl(ctx, h, &cfg, &trcfg, &c); + if (ret) { + if (ret != -ENVME_CONNECT_IGNORED) fprintf(stderr, "failed to add controller, error %s\n", - nvme_strerror(errno)); - ret = -errno; + nvme_strerror(-ret)); goto out_free; } } @@ -911,12 +924,13 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect) out_free: if (dump_config) - nvme_dump_config(r); + nvme_dump_config(ctx); return ret; } -static int nvme_connect_config(nvme_root_t r, const char *hostnqn, const char *hostid, +static int nvme_connect_config(struct nvme_global_ctx *ctx, const char *hostnqn, + const char *hostid, const struct nvme_fabrics_config *cfg) { const char *hnqn, *hid; @@ -926,7 +940,7 @@ static int nvme_connect_config(nvme_root_t r, const char *hostnqn, const char *h nvme_ctrl_t c, _c; int ret = 0, err; - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { hnqn = nvme_host_get_hostnqn(h); if (hostnqn && hnqn && strcmp(hostnqn, hnqn)) @@ -946,7 +960,7 @@ static int nvme_connect_config(nvme_root_t r, const char *hostnqn, const char *h err = nvmf_connect_ctrl(c); if (err) { - if (errno == ENVME_CONNECT_ALREADY) + if (err == -ENVME_CONNECT_ALREADY) continue; fprintf(stderr, @@ -1005,7 +1019,7 @@ int nvmf_connect(const char *desc, int argc, char **argv) char *config_file = NULL; char *context = NULL; unsigned int verbose = 0; - _cleanup_nvme_root_ nvme_root_t r = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; nvme_host_t h; _cleanup_nvme_ctrl_ nvme_ctrl_t c = NULL; int ret; @@ -1060,31 +1074,31 @@ int nvmf_connect(const char *desc, int argc, char **argv) do_connect: log_level = map_log_level(verbose, quiet); - r = nvme_create_root(stderr, log_level); - if (!r) { + ctx = nvme_create_global_ctx(stderr, log_level); + if (!ctx) { fprintf(stderr, "Failed to create topology root: %s\n", nvme_strerror(errno)); - return -errno; + return -ENOMEM; } if (context) - nvme_root_set_application(r, context); + nvme_set_application(ctx, context); - nvme_read_config(r, config_file); - nvme_read_volatile_config(r); + nvme_read_config(ctx, config_file); + nvme_read_volatile_config(ctx); - nvme_root_skip_namespaces(r); - ret = nvme_scan_topology(r, NULL, NULL); + nvme_skip_namespaces(ctx); + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret < 0) { fprintf(stderr, "Failed to scan topology: %s\n", - nvme_strerror(errno)); + nvme_strerror(-ret)); return ret; } - ret = nvme_host_get_ids(r, hostnqn, hostid, &hnqn, &hid); + ret = nvme_host_get_ids(ctx, hostnqn, hostid, &hnqn, &hid); if (ret < 0) - return -errno; + return ret; - h = nvme_lookup_host(r, hnqn, hid); + h = nvme_lookup_host(ctx, hnqn, hid); if (!h) return -ENOMEM; if (hostkey) @@ -1093,7 +1107,7 @@ int nvmf_connect(const char *desc, int argc, char **argv) trsvcid = nvmf_get_default_trsvcid(transport, false); if (config_file) - return nvme_connect_config(r, hostnqn, hostid, &cfg); + return nvme_connect_config(ctx, hostnqn, hostid, &cfg); struct tr_config trcfg = { .subsysnqn = subsysnqn, @@ -1110,10 +1124,10 @@ int nvmf_connect(const char *desc, int argc, char **argv) return -EALREADY; } - c = nvme_create_ctrl(r, subsysnqn, transport, traddr, - cfg.host_traddr, cfg.host_iface, trsvcid); - if (!c) - return -ENOMEM; + ret = nvme_create_ctrl(ctx, subsysnqn, transport, traddr, + cfg.host_traddr, cfg.host_iface, trsvcid, &c); + if (ret) + return ret; if (ctrlkey) nvme_ctrl_set_dhchap_key(c, ctrlkey); @@ -1141,18 +1155,19 @@ int nvmf_connect(const char *desc, int argc, char **argv) nvme_show_connect_msg(c, flags); if (dump_config) - nvme_dump_config(r); + nvme_dump_config(ctx); return 0; } -static nvme_ctrl_t lookup_nvme_ctrl(nvme_root_t r, const char *name) +static nvme_ctrl_t lookup_nvme_ctrl(struct nvme_global_ctx *ctx, + const char *name) { nvme_host_t h; nvme_subsystem_t s; nvme_ctrl_t c; - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { nvme_subsystem_for_each_ctrl(s, c) { if (!strcmp(nvme_ctrl_get_name(c), name)) @@ -1163,7 +1178,7 @@ static nvme_ctrl_t lookup_nvme_ctrl(nvme_root_t r, const char *name) return NULL; } -static void nvmf_disconnect_nqn(nvme_root_t r, char *nqn) +static void nvmf_disconnect_nqn(struct nvme_global_ctx *ctx, char *nqn) { int i = 0; char *n = nqn; @@ -1175,7 +1190,7 @@ static void nvmf_disconnect_nqn(nvme_root_t r, char *nqn) while ((p = strsep(&n, ",")) != NULL) { if (!strlen(p)) continue; - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { if (strcmp(nvme_subsystem_get_nqn(s), p)) continue; @@ -1192,7 +1207,7 @@ static void nvmf_disconnect_nqn(nvme_root_t r, char *nqn) int nvmf_disconnect(const char *desc, int argc, char **argv) { const char *device = "nvme device handle"; - _cleanup_nvme_root_ nvme_root_t r = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; nvme_ctrl_t c; char *p; int ret; @@ -1229,30 +1244,30 @@ int nvmf_disconnect(const char *desc, int argc, char **argv) log_level = map_log_level(cfg.verbose, false); - r = nvme_create_root(stderr, log_level); - if (!r) { + ctx = nvme_create_global_ctx(stderr, log_level); + if (!ctx) { fprintf(stderr, "Failed to create topology root: %s\n", nvme_strerror(errno)); - return -errno; + return -ENOMEM; } - nvme_root_skip_namespaces(r); - ret = nvme_scan_topology(r, NULL, NULL); + nvme_skip_namespaces(ctx); + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret < 0) { /* * Do not report an error when the modules are not * loaded, this allows the user to unconditionally call * disconnect. */ - if (errno == ENOENT) + if (ret == -ENOENT) return 0; fprintf(stderr, "Failed to scan topology: %s\n", - nvme_strerror(errno)); - return -errno; + nvme_strerror(-ret)); + return ret; } if (cfg.nqn) - nvmf_disconnect_nqn(r, cfg.nqn); + nvmf_disconnect_nqn(ctx, cfg.nqn); if (cfg.device) { char *d; @@ -1261,17 +1276,17 @@ int nvmf_disconnect(const char *desc, int argc, char **argv) while ((p = strsep(&d, ",")) != NULL) { if (!strncmp(p, "/dev/", 5)) p += 5; - c = lookup_nvme_ctrl(r, p); + c = lookup_nvme_ctrl(ctx, p); if (!c) { fprintf(stderr, "Did not find device %s\n", p); - return -errno; + return -ENODEV; } ret = nvme_disconnect_ctrl(c); if (ret) fprintf(stderr, "Failed to disconnect %s: %s\n", - p, nvme_strerror(errno)); + p, nvme_strerror(-ret)); } } @@ -1280,7 +1295,7 @@ int nvmf_disconnect(const char *desc, int argc, char **argv) int nvmf_disconnect_all(const char *desc, int argc, char **argv) { - _cleanup_nvme_root_ nvme_root_t r = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; nvme_host_t h; nvme_subsystem_t s; nvme_ctrl_t c; @@ -1305,29 +1320,29 @@ int nvmf_disconnect_all(const char *desc, int argc, char **argv) log_level = map_log_level(cfg.verbose, false); - r = nvme_create_root(stderr, log_level); - if (!r) { + ctx = nvme_create_global_ctx(stderr, log_level); + if (!ctx) { fprintf(stderr, "Failed to create topology root: %s\n", nvme_strerror(errno)); - return -errno; + return -ENOMEM; } - nvme_root_skip_namespaces(r); - ret = nvme_scan_topology(r, NULL, NULL); + nvme_skip_namespaces(ctx); + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret < 0) { /* * Do not report an error when the modules are not * loaded, this allows the user to unconditionally call * disconnect. */ - if (errno == ENOENT) + if (ret == -ENOENT) return 0; fprintf(stderr, "Failed to scan topology: %s\n", - nvme_strerror(errno)); - return -errno; + nvme_strerror(-ret)); + return ret; } - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { nvme_subsystem_for_each_ctrl(s, c) { if (cfg.transport && @@ -1359,7 +1374,7 @@ int nvmf_config(const char *desc, int argc, char **argv) char *keyring = NULL, *tls_key = NULL, *tls_key_identity = NULL; char *config_file = PATH_NVMF_CONFIG; unsigned int verbose = 0; - _cleanup_nvme_root_ nvme_root_t r = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; int ret; struct nvme_fabrics_config cfg; bool scan_tree = false, modify_config = false, update_config = false; @@ -1384,22 +1399,22 @@ int nvmf_config(const char *desc, int argc, char **argv) log_level = map_log_level(verbose, quiet); - r = nvme_create_root(stderr, log_level); - if (!r) { + ctx = nvme_create_global_ctx(stderr, log_level); + if (!ctx) { fprintf(stderr, "Failed to create topology root: %s\n", nvme_strerror(errno)); - return -errno; + return -ENOMEM; } - nvme_read_config(r, config_file); + nvme_read_config(ctx, config_file); if (scan_tree) { - nvme_root_skip_namespaces(r); - ret = nvme_scan_topology(r, NULL, NULL); + nvme_skip_namespaces(ctx); + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret < 0) { fprintf(stderr, "Failed to scan topology: %s\n", - nvme_strerror(errno)); - return -errno; + nvme_strerror(-ret)); + return -ret; } } @@ -1424,27 +1439,26 @@ int nvmf_config(const char *desc, int argc, char **argv) hostnqn = hnqn = nvmf_hostnqn_from_file(); if (!hostid && hnqn) hostid = hid = nvmf_hostid_from_file(); - h = nvme_lookup_host(r, hostnqn, hostid); + h = nvme_lookup_host(ctx, hostnqn, hostid); if (!h) { - fprintf(stderr, "Failed to lookup host '%s': %s\n", - hostnqn, nvme_strerror(errno)); - return -errno; + fprintf(stderr, "Failed to lookup host '%s'\n", + hostnqn); + return -ENODEV; } if (hostkey) nvme_host_set_dhchap_key(h, hostkey); s = nvme_lookup_subsystem(h, NULL, subsysnqn); if (!s) { - fprintf(stderr, "Failed to lookup subsystem '%s': %s\n", - subsysnqn, nvme_strerror(errno)); - return -errno; + fprintf(stderr, "Failed to lookup subsystem '%s'\n", + subsysnqn); + return -ENODEV; } c = nvme_lookup_ctrl(s, transport, traddr, cfg.host_traddr, cfg.host_iface, trsvcid, NULL); if (!c) { - fprintf(stderr, "Failed to lookup controller: %s\n", - nvme_strerror(errno)); - return -errno; + fprintf(stderr, "Failed to lookup controller\n"); + return -ENODEV; } if (ctrlkey) nvme_ctrl_set_dhchap_key(c, ctrlkey); @@ -1454,10 +1468,10 @@ int nvmf_config(const char *desc, int argc, char **argv) } if (update_config) - nvme_update_config(r); + nvme_update_config(ctx); if (dump_config) - nvme_dump_config(r); + nvme_dump_config(ctx); return 0; } @@ -1489,7 +1503,7 @@ static int dim_operation(nvme_ctrl_t c, enum nvmf_dim_tas tas, const char *name) int nvmf_dim(const char *desc, int argc, char **argv) { - _cleanup_nvme_root_ nvme_root_t r = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; enum nvmf_dim_tas tas; nvme_ctrl_t c; char *p; @@ -1538,18 +1552,18 @@ int nvmf_dim(const char *desc, int argc, char **argv) log_level = map_log_level(cfg.verbose, false); - r = nvme_create_root(stderr, log_level); - if (!r) { + ctx = nvme_create_global_ctx(stderr, log_level); + if (!ctx) { fprintf(stderr, "Failed to create topology root: %s\n", nvme_strerror(errno)); - return -errno; + return -ENODEV; } - nvme_root_skip_namespaces(r); - ret = nvme_scan_topology(r, NULL, NULL); + nvme_skip_namespaces(ctx); + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret < 0) { fprintf(stderr, "Failed to scan topology: %s\n", - nvme_strerror(errno)); - return -errno; + nvme_strerror(-ret)); + return ret; } if (cfg.nqn) { @@ -1560,7 +1574,7 @@ int nvmf_dim(const char *desc, int argc, char **argv) while ((p = strsep(&n, ",")) != NULL) { if (!strlen(p)) continue; - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { if (strcmp(nvme_subsystem_get_nqn(s), p)) continue; @@ -1577,12 +1591,12 @@ int nvmf_dim(const char *desc, int argc, char **argv) while ((p = strsep(&d, ",")) != NULL) { if (!strncmp(p, "/dev/", 5)) p += 5; - c = nvme_scan_ctrl(r, p); - if (!c) { + ret = nvme_scan_ctrl(ctx, p, &c); + if (ret) { fprintf(stderr, "Did not find device %s: %s\n", - p, nvme_strerror(errno)); - return -errno; + p, nvme_strerror(ret)); + return ret; } ret = dim_operation(c, tas, p); } diff --git a/fabrics.h b/fabrics.h index aec305dc31..50ff00dee4 100644 --- a/fabrics.h +++ b/fabrics.h @@ -18,9 +18,10 @@ extern int nvmf_disconnect(const char *desc, int argc, char **argv); extern int nvmf_disconnect_all(const char *desc, int argc, char **argv); extern int nvmf_config(const char *desc, int argc, char **argv); extern int nvmf_dim(const char *desc, int argc, char **argv); -extern nvme_ctrl_t nvmf_create_discover_ctrl(nvme_root_t r, nvme_host_t h, - struct nvme_fabrics_config *cfg, - struct tr_config *trcfg); +extern int nvmf_create_discover_ctrl(struct nvme_global_ctx *ctx, nvme_host_t h, + struct nvme_fabrics_config *cfg, + struct tr_config *trcfg, + nvme_ctrl_t *ctrl); extern char *nvmf_get_default_trsvcid(const char *transport, bool discovery_ctrl); diff --git a/libnvme-wrap.c b/libnvme-wrap.c index b5b48383b6..70ce5cb443 100644 --- a/libnvme-wrap.c +++ b/libnvme-wrap.c @@ -36,38 +36,3 @@ rtype __attribute__((weak)) name(proto) \ return fn(args); \ return defret; \ } - -FN(nvme_get_version, - const char *, PROTO(enum nvme_version type), - ARGS(type), "n/a") - -VOID_FN(nvme_init_copy_range_f1, - PROTO(struct nvme_copy_range_f1 *copy, __u16 *nlbs, - __u64 *slbas, __u64 *eilbrts, __u32 *elbatms, - __u32 *elbats, __u16 nr), - ARGS(copy, nlbs, slbas, eilbrts, elbatms, elbats, nr)) - -VOID_FN(nvme_init_copy_range_f2, - PROTO(struct nvme_copy_range_f2 *copy, __u32 *snsids, - __u16 *nlbs, __u64 *slbas, __u16 *sopts, __u32 *eilbrts, - __u32 *elbatms, __u32 *elbats, __u16 nr), - ARGS(copy, snsids, nlbs, slbas, sopts, eilbrts, elbatms, elbats, nr)) - -VOID_FN(nvme_init_copy_range_f3, - PROTO(struct nvme_copy_range_f3 *copy, __u32 *snsids, - __u16 *nlbs, __u64 *slbas, __u16 *sopts, __u64 *eilbrts, - __u32 *elbatms, __u32 *elbats, __u16 nr), - ARGS(copy, snsids, nlbs, slbas, sopts, eilbrts, elbatms, elbats, nr)) - -FN(nvme_get_feature_length2, - int, - PROTO(int fid, __u32 cdw11, enum nvme_data_tfr dir, - __u32 *len), - ARGS(fid, cdw11, dir, len), - -EEXIST) - -FN(nvme_ctrl_is_persistent, - bool, - PROTO(nvme_ctrl_t c), - ARGS(c), - false) diff --git a/libnvme/.github/cross/ubuntu-cross-armhf.txt b/libnvme/.github/cross/ubuntu-cross-armhf.txt index 41c8328906..ac5dd62209 100644 --- a/libnvme/.github/cross/ubuntu-cross-armhf.txt +++ b/libnvme/.github/cross/ubuntu-cross-armhf.txt @@ -6,6 +6,9 @@ pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config' ld = '/usr/bin/arm-linux/gnueabihf-ld' exe_wrapper = '/usr/bin/qemu-arm-static' +c_native = 'gcc' +cpp_native = 'g++' + [properties] root = '/usr/arm-linux-gnueabihf' has_function_printf = true diff --git a/libnvme/.github/cross/ubuntu-cross-ppc64le.txt b/libnvme/.github/cross/ubuntu-cross-ppc64le.txt index 6baaefbc26..76b00e4c3f 100644 --- a/libnvme/.github/cross/ubuntu-cross-ppc64le.txt +++ b/libnvme/.github/cross/ubuntu-cross-ppc64le.txt @@ -6,6 +6,9 @@ pkgconfig = '/usr/bin/powerpc64le-linux-gnu-pkg-config' ld = '/usr/bin/powerpc64le-linux-gnu-ld' exe_wrapper = '/usr/bin/qemu-ppc64le-static' +c_native = 'gcc' +cpp_native = 'g++' + [properties] root = '/usr/powerpc64le-linux-gnu' has_function_printf = true diff --git a/libnvme/.github/cross/ubuntu-cross-s390x.txt b/libnvme/.github/cross/ubuntu-cross-s390x.txt index 51a3511fbe..dae5b76d51 100644 --- a/libnvme/.github/cross/ubuntu-cross-s390x.txt +++ b/libnvme/.github/cross/ubuntu-cross-s390x.txt @@ -6,6 +6,9 @@ pkgconfig = '/usr/bin/s390x-linux-gnu-pkg-config' ld = '/usr/bin/s390x-linux-gnu-ld' exe_wrapper = '/usr/bin/qemu-s390x-static' +c_native = 'gcc' +cpp_native = 'g++' + [properties] root = '/usr/s390x-linux-gnu' has_function_printf = true diff --git a/libnvme/doc/meson.build b/libnvme/doc/meson.build index 945d7e80ed..f12f3b987d 100644 --- a/libnvme/doc/meson.build +++ b/libnvme/doc/meson.build @@ -9,7 +9,6 @@ # api_files = [ - 'api-types.h', 'fabrics.h', 'filters.h', 'ioctl.h', diff --git a/libnvme/examples/discover-loop.c b/libnvme/examples/discover-loop.c index 752806713b..c3aa7c0cb1 100644 --- a/libnvme/examples/discover-loop.c +++ b/libnvme/examples/discover-loop.c @@ -1,12 +1,12 @@ // SPDX-License-Identifier: LGPL-2.1-or-later -/** +/* * This file is part of libnvme. * Copyright (c) 2020 Western Digital Corporation or its affiliates. * * Authors: Keith Busch */ -/** +/* * discover-loop: Use fabrics commands to discover any loop targets and print * those records. You must have at least one configured nvme loop target on the * system (no existing connection required). The output will look more @@ -51,7 +51,7 @@ static void print_discover_log(struct nvmf_discovery_log *log) int main() { struct nvmf_discovery_log *log = NULL; - nvme_root_t r; + struct nvme_global_ctx *ctx; nvme_host_t h; nvme_ctrl_t c; int ret; @@ -59,22 +59,24 @@ int main() nvmf_default_config(&cfg); - r = nvme_scan(NULL); - h = nvme_default_host(r); - if (!h) { + ret = nvme_scan(NULL, &ctx); + if (ret) + return ret; + ret = nvme_default_host(ctx, &h); + if (ret) { fprintf(stderr, "Failed to allocated memory\n"); - return ENOMEM; + return ret; } - c = nvme_create_ctrl(r, NVME_DISC_SUBSYS_NAME, "loop", - NULL, NULL, NULL, NULL); - if (!c) { + ret = nvme_create_ctrl(ctx, NVME_DISC_SUBSYS_NAME, "loop", + NULL, NULL, NULL, NULL, &c); + if (ret) { fprintf(stderr, "Failed to allocate memory\n"); return ENOMEM; } ret = nvmf_add_ctrl(h, c, &cfg); - if (ret < 0) { + if (ret) { fprintf(stderr, "no controller found\n"); - return errno; + return ret; } ret = nvmf_get_discovery_log(c, &log, 4); @@ -86,7 +88,7 @@ int main() else print_discover_log(log); - nvme_free_tree(r); + nvme_free_global_ctx(ctx); free(log); return 0; } diff --git a/libnvme/examples/display-columnar.c b/libnvme/examples/display-columnar.c index db98bdfec8..777f8a94a8 100644 --- a/libnvme/examples/display-columnar.c +++ b/libnvme/examples/display-columnar.c @@ -1,12 +1,12 @@ // SPDX-License-Identifier: LGPL-2.1-or-later -/** +/* * This file is part of libnvme. * Copyright (c) 2020 Western Digital Corporation or its affiliates. * * Authors: Keith Busch */ -/** +/* * display-columnar: Scans the nvme topology, prints each record type in a * column format for easy visual scanning. */ @@ -17,22 +17,20 @@ static const char dash[101] = {[0 ... 99] = '-'}; int main() { - nvme_root_t r; + struct nvme_global_ctx *ctx; nvme_host_t h; nvme_subsystem_t s; nvme_ctrl_t c; nvme_path_t p; nvme_ns_t n; - r = nvme_scan(NULL); - if (!r) + if (nvme_scan(NULL, &ctx)) return -1; - printf("%-16s %-96s %-.16s\n", "Subsystem", "Subsystem-NQN", "Controllers"); printf("%-.16s %-.96s %-.16s\n", dash, dash, dash); - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { bool first = true; printf("%-16s %-96s ", nvme_subsystem_get_name(s), @@ -53,7 +51,7 @@ int main() printf("%-.8s %-.20s %-.40s %-.8s %-.6s %-.14s %-.12s %-.16s\n", dash, dash, dash, dash, dash, dash, dash, dash); - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { nvme_subsystem_for_each_ctrl(s, c) { bool first = true; @@ -87,7 +85,7 @@ int main() printf("%-12s %-8s %-16s %-8s %-16s\n", "Device", "NSID", "Sectors", "Format", "Controllers"); printf("%-.12s %-.8s %-.16s %-.8s %-.16s\n", dash, dash, dash, dash, dash); - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { nvme_subsystem_for_each_ctrl(s, c) { nvme_ctrl_for_each_ns(c, n) diff --git a/libnvme/examples/display-tree.c b/libnvme/examples/display-tree.c index b9ea75f894..b3e980ceaa 100644 --- a/libnvme/examples/display-tree.c +++ b/libnvme/examples/display-tree.c @@ -1,12 +1,12 @@ // SPDX-License-Identifier: LGPL-2.1-or-later -/** +/* * This file is part of libnvme. * Copyright (c) 2020 Western Digital Corporation or its affiliates. * * Authors: Keith Busch */ -/** +/* * display-tree: Scans the nvme topology, prints as an ascii tree with some * selected attributes for each component. */ @@ -16,19 +16,18 @@ int main() { - nvme_root_t r; + struct nvme_global_ctx *ctx; nvme_host_t h; nvme_subsystem_t s, _s; nvme_ctrl_t c, _c; nvme_path_t p, _p; nvme_ns_t n, _n; - r = nvme_scan(NULL); - if (!r) + if (nvme_scan(NULL, &ctx)) return -1; printf(".\n"); - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem_safe(h, s, _s) { printf("%c-- %s - NQN=%s\n", _s ? '|' : '`', nvme_subsystem_get_name(s), @@ -67,6 +66,6 @@ int main() } } } - nvme_free_tree(r); + nvme_free_global_ctx(ctx); return 0; } diff --git a/libnvme/examples/meson.build b/libnvme/examples/meson.build index 62fbe9ef39..0d36f28646 100644 --- a/libnvme/examples/meson.build +++ b/libnvme/examples/meson.build @@ -36,21 +36,21 @@ executable( executable( 'mi-mctp', ['mi-mctp.c'], - dependencies: libnvme_mi_dep, + dependencies: libnvme_dep, include_directories: [incdir, internal_incdir] ) executable( 'mi-mctp-csi-test', ['mi-mctp-csi-test.c'], - dependencies: [libnvme_mi_dep, threads_dep], + dependencies: [libnvme_dep, threads_dep], include_directories: [incdir, internal_incdir] ) executable( 'mi-mctp-ae', ['mi-mctp-ae.c'], - dependencies: libnvme_mi_dep, + dependencies: libnvme_dep, include_directories: [incdir, internal_incdir] ) @@ -58,7 +58,7 @@ if libdbus_dep.found() executable( 'mi-conf', ['mi-conf.c'], - dependencies: [libnvme_mi_dep, libdbus_dep], + dependencies: [libnvme_dep, libdbus_dep], include_directories: [incdir, internal_incdir] ) endif diff --git a/libnvme/examples/mi-conf.c b/libnvme/examples/mi-conf.c index e47d281f3e..1111a8e701 100644 --- a/libnvme/examples/mi-conf.c +++ b/libnvme/examples/mi-conf.c @@ -1,12 +1,12 @@ // SPDX-License-Identifier: LGPL-2.1-or-later -/** +/* * This file is part of libnvme. * Copyright (c) 2022 Code Construct Pty Ltd. * * Authors: Jeremy Kerr */ -/** +/* * mi-conf: query a device for optimal MTU and set for both the local MCTP * route (through dbus to mctpd) and the device itself (through NVMe-MI * configuration commands) @@ -137,11 +137,11 @@ int set_local_mtu(DBusConnection *bus, unsigned int net, uint8_t eid, int main(int argc, char **argv) { + struct nvme_global_ctx *ctx; uint16_t cur_mtu, mtu; DBusConnection *bus; const char *devstr; uint8_t eid, port; - nvme_root_t root; unsigned int net; nvme_mi_ep_t ep; DBusError berr; @@ -157,14 +157,14 @@ int main(int argc, char **argv) if (rc) errx(EXIT_FAILURE, "can't parse MI device string '%s'", devstr); - root = nvme_mi_create_root(stderr, DEFAULT_LOGLEVEL); - if (!root) - err(EXIT_FAILURE, "can't create NVMe root"); + ctx = nvme_mi_create_global_ctx(stderr, DEFAULT_LOGLEVEL); + if (!ctx) + err(EXIT_FAILURE, "can't create global context"); - ep = nvme_mi_open_mctp(root, net, eid); + ep = nvme_mi_open_mctp(ctx, net, eid); if (!ep) { warnx("can't open MCTP endpoint %d:%d", net, eid); - goto out_free_root; + goto out_free_ctx; } dbus_error_init(&berr); @@ -218,8 +218,8 @@ int main(int argc, char **argv) out_close_ep: dbus_error_free(&berr); nvme_mi_close(ep); -out_free_root: - nvme_mi_free_root(root); +out_free_ctx: + nvme_mi_free_global_ctx(ctx); return rc ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/libnvme/examples/mi-mctp-ae.c b/libnvme/examples/mi-mctp-ae.c index d73a359873..04dcbd2878 100644 --- a/libnvme/examples/mi-mctp-ae.c +++ b/libnvme/examples/mi-mctp-ae.c @@ -1,9 +1,9 @@ // SPDX-License-Identifier: LGPL-2.1-or-later -/** +/* * This file is part of libnvme. */ -/** +/* * mi-mctp-ae: open a MI connection over MCTP, supporting asynchronous event messages */ @@ -78,7 +78,7 @@ enum nvme_mi_aem_handler_next_action aem_handler(nvme_mi_ep_t ep, size_t num_eve int main(int argc, char **argv) { - nvme_root_t root; + struct nvme_global_ctx *ctx; nvme_mi_ep_t ep; uint8_t eid = 0; int rc = 0, net = 0; @@ -109,11 +109,11 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - root = nvme_mi_create_root(stderr, DEFAULT_LOGLEVEL); - if (!root) + ctx = nvme_mi_create_global_ctx(stderr, DEFAULT_LOGLEVEL); + if (!ctx) err(EXIT_FAILURE, "can't create NVMe root"); - ep = nvme_mi_open_mctp(root, net, eid); + ep = nvme_mi_open_mctp(ctx, net, eid); if (!ep) err(EXIT_FAILURE, "can't open MCTP endpoint %d:%d", net, eid); @@ -131,7 +131,7 @@ int main(int argc, char **argv) } rc = nvme_mi_aem_enable(ep, &aem_config, &data); - if (rc && errno == EOPNOTSUPP) + if (rc == EOPNOTSUPP) errx(EXIT_FAILURE, "MCTP Peer-Bind is required for AEM"); else if (rc) err(EXIT_FAILURE, "Can't enable aem:%d", rc); @@ -173,7 +173,7 @@ int main(int argc, char **argv) //Cleanup nvme_mi_aem_disable(ep); nvme_mi_close(ep); - nvme_mi_free_root(root); + nvme_mi_free_global_ctx(ctx); return rc ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/libnvme/examples/mi-mctp-csi-test.c b/libnvme/examples/mi-mctp-csi-test.c index 2ca7e629e4..b8ed0d0f47 100644 --- a/libnvme/examples/mi-mctp-csi-test.c +++ b/libnvme/examples/mi-mctp-csi-test.c @@ -1,9 +1,9 @@ // SPDX-License-Identifier: LGPL-2.1-or-later -/** +/* * This file is part of libnvme. */ -/** +/* * mi-mctp-csi-test: open a MI connection over MCTP, and send two commands * in parallel with different CSI buffers */ @@ -56,8 +56,9 @@ void hexdump(const unsigned char *buf, int len) int do_get_log_page(nvme_mi_ep_t ep, int argc, char **argv) { - struct nvme_get_log_args args = { 0 }; - struct nvme_mi_ctrl *ctrl; + struct nvme_transport_handle *hdl; + enum nvme_cmd_get_log_lid lid; + struct nvme_passthru_cmd cmd; uint8_t buf[4096]; uint16_t ctrl_id; int rc, tmp; @@ -75,31 +76,29 @@ int do_get_log_page(nvme_mi_ep_t ep, int argc, char **argv) ctrl_id = tmp & 0xffff; - args.args_size = sizeof(args); - args.log = buf; - args.len = sizeof(buf); - if (argc > 2) { tmp = atoi(argv[2]); - args.lid = tmp & 0xff; + lid = tmp & 0xff; } else { - args.lid = 0x1; + lid = 0x1; } - ctrl = nvme_mi_init_ctrl(ep, ctrl_id); - if (!ctrl) { + hdl = nvme_mi_init_transport_handle(ep, ctrl_id); + if (!hdl) { warn("can't create controller"); return -1; } - rc = nvme_mi_admin_get_log(ctrl, &args); + nvme_init_get_log(&cmd, NVME_NSID_NONE, lid, NVME_CSI_NVM, + buf, sizeof(buf)); + rc = nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); if (rc) { warn("can't perform Get Log page command"); return -1; } - printf("Get log page (log id = 0x%02x) data:\n", args.lid); - hexdump(buf, args.len); + printf("Get log page (log id = 0x%02x) data:\n", lid); + hexdump(buf, sizeof(buf)); return 0; } @@ -123,16 +122,16 @@ enum action { ACTION_CSI_TEST, }; -int do_csi_test(nvme_root_t root, int net, __u8 eid, +int do_csi_test(struct nvme_global_ctx *ctx, int net, __u8 eid, int argc, char **argv) { int rc = 0; nvme_mi_ep_t ep1, ep2; - ep1 = nvme_mi_open_mctp(root, net, eid); + ep1 = nvme_mi_open_mctp(ctx, net, eid); if (!ep1) errx(EXIT_FAILURE, "can't open MCTP endpoint %d:%d", net, eid); - ep2 = nvme_mi_open_mctp(root, net, eid); + ep2 = nvme_mi_open_mctp(ctx, net, eid); if (!ep2) errx(EXIT_FAILURE, "can't open MCTP endpoint %d:%d", net, eid); @@ -176,7 +175,7 @@ int do_csi_test(nvme_root_t root, int net, __u8 eid, } static int do_action_endpoint(enum action action, - nvme_root_t root, + struct nvme_global_ctx *ctx, int net, uint8_t eid, int argc, @@ -186,7 +185,7 @@ static int do_action_endpoint(enum action action, switch (action) { case ACTION_CSI_TEST: - rc = do_csi_test(root, net, eid, argc, argv); + rc = do_csi_test(ctx, net, eid, argc, argv); break; default: /* This shouldn't be possible, as we should be covering all @@ -201,8 +200,8 @@ static int do_action_endpoint(enum action action, int main(int argc, char **argv) { + struct nvme_global_ctx *ctx; enum action action; - nvme_root_t root; bool usage = true; uint8_t eid = 0; int rc = 0, net = 0; @@ -238,12 +237,12 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - root = nvme_mi_create_root(stderr, DEFAULT_LOGLEVEL); - if (!root) + ctx = nvme_mi_create_global_ctx(stderr, DEFAULT_LOGLEVEL); + if (!ctx) err(EXIT_FAILURE, "can't create NVMe root"); - rc = do_action_endpoint(action, root, net, eid, argc, argv); - nvme_mi_free_root(root); + rc = do_action_endpoint(action, ctx, net, eid, argc, argv); + nvme_mi_free_global_ctx(ctx); return rc ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/libnvme/examples/mi-mctp.c b/libnvme/examples/mi-mctp.c index cea7ed89f9..dab5a1a195 100644 --- a/libnvme/examples/mi-mctp.c +++ b/libnvme/examples/mi-mctp.c @@ -1,12 +1,12 @@ // SPDX-License-Identifier: LGPL-2.1-or-later -/** +/* * This file is part of libnvme. * Copyright (c) 2021 Code Construct Pty Ltd. * * Authors: Jeremy Kerr */ -/** +/* * mi-mctp: open a MI connection over MCTP, and query controller info */ @@ -178,8 +178,8 @@ static const char *__copy_id_str(const void *field, size_t size, int do_identify(nvme_mi_ep_t ep, int argc, char **argv) { - struct nvme_identify_args id_args = { 0 }; - struct nvme_mi_ctrl *ctrl; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; struct nvme_id_ctrl id; uint16_t ctrl_id; char buf[41]; @@ -201,31 +201,22 @@ int do_identify(nvme_mi_ep_t ep, int argc, char **argv) partial = argc > 2 && !strcmp(argv[2], "--partial"); - ctrl = nvme_mi_init_ctrl(ep, ctrl_id); - if (!ctrl) { + hdl = nvme_mi_init_transport_handle(ep, ctrl_id); + if (!hdl) { warn("can't create controller"); return -1; } - id_args.data = &id; - id_args.args_size = sizeof(id_args); - id_args.cns = NVME_IDENTIFY_CNS_CTRL; - id_args.nsid = NVME_NSID_NONE; - id_args.cntid = 0; - id_args.csi = NVME_CSI_NVM; - /* for this example code, we can either do a full or partial identify; * since we're only printing the fields before the 'rab' member, * these will be equivalent, aside from the size of the MI * response. */ - if (partial) { - rc = nvme_mi_admin_identify_partial(ctrl, &id_args, 0, - offsetof(struct nvme_id_ctrl, rab)); - } else { - rc = nvme_mi_admin_identify(ctrl, &id_args); - } + nvme_init_identify_ctrl(&cmd, &id); + if (partial) + cmd.data_len = offsetof(struct nvme_id_ctrl, rab); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (rc) { warn("can't perform Admin Identify command"); return -1; @@ -373,8 +364,9 @@ void hexdump(const unsigned char *buf, int len) int do_get_log_page(nvme_mi_ep_t ep, int argc, char **argv) { - struct nvme_get_log_args args = { 0 }; - struct nvme_mi_ctrl *ctrl; + struct nvme_transport_handle *hdl; + enum nvme_cmd_get_log_lid lid; + struct nvme_passthru_cmd cmd; uint8_t buf[512]; uint16_t ctrl_id; int rc, tmp; @@ -392,31 +384,29 @@ int do_get_log_page(nvme_mi_ep_t ep, int argc, char **argv) ctrl_id = tmp & 0xffff; - args.args_size = sizeof(args); - args.log = buf; - args.len = sizeof(buf); - if (argc > 2) { tmp = atoi(argv[2]); - args.lid = tmp & 0xff; + lid = tmp & 0xff; } else { - args.lid = 0x1; + lid = 0x1; } - ctrl = nvme_mi_init_ctrl(ep, ctrl_id); - if (!ctrl) { + hdl = nvme_mi_init_transport_handle(ep, ctrl_id); + if (!hdl) { warn("can't create controller"); return -1; } - rc = nvme_mi_admin_get_log(ctrl, &args); + nvme_init_get_log(&cmd, NVME_NSID_NONE, lid, NVME_CSI_NVM, + buf, sizeof(buf)); + rc = nvme_get_log(hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, NULL); if (rc) { warn("can't perform Get Log page command"); return -1; } - printf("Get log page (log id = 0x%02x) data:\n", args.lid); - hexdump(buf, args.len); + printf("Get log page (log id = 0x%02x) data:\n", lid); + hexdump(buf, sizeof(buf)); return 0; } @@ -425,7 +415,7 @@ int do_admin_raw(nvme_mi_ep_t ep, int argc, char **argv) { struct nvme_mi_admin_req_hdr req; struct nvme_mi_admin_resp_hdr *resp; - struct nvme_mi_ctrl *ctrl; + struct nvme_transport_handle *hdl; size_t resp_data_len; unsigned long tmp; uint8_t buf[512]; @@ -488,15 +478,15 @@ int do_admin_raw(nvme_mi_ep_t ep, int argc, char **argv) memset(buf, 0, sizeof(buf)); resp = (void *)buf; - ctrl = nvme_mi_init_ctrl(ep, ctrl_id); - if (!ctrl) { + hdl = nvme_mi_init_transport_handle(ep, ctrl_id); + if (!hdl) { warn("can't create controller"); return -1; } resp_data_len = sizeof(buf) - sizeof(*resp); - rc = nvme_mi_admin_xfer(ctrl, &req, 0, resp, 0, &resp_data_len); + rc = nvme_mi_admin_xfer(hdl, &req, 0, resp, 0, &resp_data_len); if (rc) { warn("nvme_admin_xfer failed: %d", rc); return -1; @@ -542,8 +532,8 @@ static const char *sec_proto_description(uint8_t id) int do_security_info(nvme_mi_ep_t ep, int argc, char **argv) { - struct nvme_security_receive_args args = { 0 }; - nvme_mi_ctrl_t ctrl; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; int i, rc, n_proto; unsigned long tmp; uint16_t ctrl_id; @@ -552,6 +542,9 @@ int do_security_info(nvme_mi_ep_t ep, int argc, char **argv) uint16_t len; uint8_t protocols[256]; } proto_info; + /* protocol 0x00, spsp 0x0000: retrieve supported protocols */ + void *data = &proto_info; + __u32 data_len = sizeof(proto_info); if (argc != 2) { fprintf(stderr, "no controller ID specified\n"); @@ -566,33 +559,23 @@ int do_security_info(nvme_mi_ep_t ep, int argc, char **argv) ctrl_id = tmp & 0xffff; - ctrl = nvme_mi_init_ctrl(ep, ctrl_id); - if (!ctrl) { + hdl = nvme_mi_init_transport_handle(ep, ctrl_id); + if (!hdl) { warn("can't create controller"); return -1; } - /* protocol 0x00, spsp 0x0000: retrieve supported protocols */ - args.args_size = sizeof(args); - args.data = &proto_info; - args.data_len = sizeof(proto_info); - - rc = nvme_mi_admin_security_recv(ctrl, &args); + nvme_init_security_receive(&cmd, 0, 0, 0, 0, 0, data, data_len); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (rc) { warnx("can't perform Security Receive command: rc %d", rc); return -1; } - if (args.data_len < 6) { - warnx("Short response in security receive command (%d bytes)", - args.data_len); - return -1; - } - n_proto = be16_to_cpu(proto_info.len); - if (args.data_len < 6 + n_proto) { + if (data_len < 6 + n_proto) { warnx("Short response in security receive command (%d bytes), " - "for %d protocols", args.data_len, n_proto); + "for %d protocols", data_len, n_proto); return -1; } @@ -775,8 +758,8 @@ static int do_action_endpoint(enum action action, nvme_mi_ep_t ep, int argc, cha int main(int argc, char **argv) { + struct nvme_global_ctx *ctx; enum action action; - nvme_root_t root; nvme_mi_ep_t ep; bool dbus = false, usage = true; uint8_t eid = 0; @@ -847,34 +830,34 @@ int main(int argc, char **argv) } } if (dbus) { - nvme_root_t root; + struct nvme_global_ctx *ctx; int i = 0; - root = nvme_mi_scan_mctp(); - if (!root) + ctx = nvme_mi_scan_mctp(); + if (!ctx) errx(EXIT_FAILURE, "can't scan D-Bus entries"); - nvme_mi_for_each_endpoint(root, ep) i++; + nvme_mi_for_each_endpoint(ctx, ep) i++; printf("Found %d endpoints in D-Bus:\n", i); - nvme_mi_for_each_endpoint(root, ep) { + nvme_mi_for_each_endpoint(ctx, ep) { char *desc = nvme_mi_endpoint_desc(ep); printf("%s\n", desc); rc = do_action_endpoint(action, ep, argc, argv); printf("---\n"); free(desc); } - nvme_mi_free_root(root); + nvme_mi_free_global_ctx(ctx); } else { - root = nvme_mi_create_root(stderr, DEFAULT_LOGLEVEL); - if (!root) + ctx = nvme_mi_create_global_ctx(stderr, DEFAULT_LOGLEVEL); + if (!ctx) err(EXIT_FAILURE, "can't create NVMe root"); - ep = nvme_mi_open_mctp(root, net, eid); + ep = nvme_mi_open_mctp(ctx, net, eid); if (!ep) errx(EXIT_FAILURE, "can't open MCTP endpoint %d:%d", net, eid); rc = do_action_endpoint(action, ep, argc, argv); nvme_mi_close(ep); - nvme_mi_free_root(root); + nvme_mi_free_global_ctx(ctx); } return rc ? EXIT_FAILURE : EXIT_SUCCESS; diff --git a/libnvme/examples/telemetry-listen.c b/libnvme/examples/telemetry-listen.c index e38a8adf95..9db65e3299 100644 --- a/libnvme/examples/telemetry-listen.c +++ b/libnvme/examples/telemetry-listen.c @@ -1,16 +1,17 @@ // SPDX-License-Identifier: LGPL-2.1-or-later -/** +/* * This file is part of libnvme. * Copyright (c) 2020 Western Digital Corporation or its affiliates. * * Authors: Keith Busch */ -/** +/* * Open all nvme controller's uevent and listen for changes. If NVME_AEN event * is observed with controller telemetry data, read the log and save it to a * file in /var/log/ with the device's unique name and epoch timestamp. */ +#include "nvme/tree.h" #include #include #include @@ -45,7 +46,8 @@ static void save_telemetry(nvme_ctrl_t c) time_t s; /* Clear the log (rae == false) at the end to see new telemetry events later */ - ret = nvme_get_ctrl_telemetry(nvme_ctrl_get_fd(c), false, &log, NVME_TELEMETRY_DA_3, &log_size); + ret = nvme_get_ctrl_telemetry(nvme_ctrl_get_transport_handle(c), false, &log, + NVME_TELEMETRY_DA_3, &log_size); if (ret) return; @@ -128,16 +130,15 @@ int main() fd_set fds; int i = 0; + struct nvme_global_ctx *ctx; nvme_subsystem_t s; nvme_ctrl_t c; nvme_host_t h; - nvme_root_t r; - r = nvme_scan(NULL); - if (!r) + if (nvme_scan(NULL, &ctx)) return EXIT_FAILURE; - nvme_for_each_host(r, h) + nvme_for_each_host(ctx, h) nvme_for_each_subsystem(h, s) nvme_subsystem_for_each_ctrl(s, c) i++; @@ -146,7 +147,7 @@ int main() FD_ZERO(&fds); i = 0; - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { nvme_subsystem_for_each_ctrl(s, c) { int fd = open_uevent(c); @@ -162,7 +163,7 @@ int main() } wait_events(&fds, e, i); - nvme_free_tree(r); + nvme_free_global_ctx(ctx); free(e); return EXIT_SUCCESS; diff --git a/libnvme/libnvme/README.md b/libnvme/libnvme/README.md index 31957155e4..d733271a6e 100644 --- a/libnvme/libnvme/README.md +++ b/libnvme/libnvme/README.md @@ -18,16 +18,16 @@ def disc_supp_str(dlp_supp_opts): } return [txt for msk, txt in bitmap.items() if dlp_supp_opts & msk] -root = nvme.root() # This is a singleton -root.log_level('debug') # Optional: extra debug info +ctx = nvme.global_ctx() # This is a singleton +ctx.log_level('debug') # Optional: extra debug info -host = nvme.host(root) # This "may be" a singleton. +host = nvme.host(ctx) # This "may be" a singleton. subsysnqn = [string] # e.g. nvme.NVME_DISC_SUBSYS_NAME, ... transport = [string] # One of: 'tcp', 'rdma', 'fc', 'loop'. traddr = [IPv4 or IPv6] # e.g. '192.168.10.10', 'fd2e:853b:3cad:e135:506a:65ee:29f2:1b18', ... trsvcid = [string] # e.g. '8009', '4420', ... host_iface = [interface] # e.g. 'eth1', ens256', ... -ctrl = nvme.ctrl(root, subsysnqn=subsysnqn, transport=transport, traddr=traddr, trsvcid=trsvcid, host_iface=host_iface) +ctrl = nvme.ctrl(ctx, subsysnqn=subsysnqn, transport=transport, traddr=traddr, trsvcid=trsvcid, host_iface=host_iface) try: cfg = { @@ -61,6 +61,6 @@ except Exception as e: ctrl = None host = None -root = None +ctx = None ``` diff --git a/libnvme/libnvme/nvme.i b/libnvme/libnvme/nvme.i index 9afa1d2bc0..b39ccff63d 100644 --- a/libnvme/libnvme/nvme.i +++ b/libnvme/libnvme/nvme.i @@ -13,7 +13,7 @@ %allowexception; -%rename(root) nvme_root; +%rename(global_ctx) nvme_global_ctx; %rename(host) nvme_host; %rename(ctrl) nvme_ctrl; %rename(subsystem) nvme_subsystem; @@ -55,12 +55,9 @@ PyObject *hostid_from_file(); %exception nvme_ctrl::connect { connect_err = 0; - errno = 0; $action /* $action sets connect_err to non-zero value on failure */ - if (connect_err == 1) { - SWIG_exception(SWIG_AttributeError, "Existing controller connection"); - } else if (connect_err) { - const char *errstr = nvme_errno_to_string(errno); + if (connect_err) { + const char *errstr = nvme_errno_to_string(-connect_err); if (errstr) { SWIG_exception(SWIG_RuntimeError, errstr); } else { @@ -76,7 +73,7 @@ PyObject *hostid_from_file(); if (connect_err == 1) { SWIG_exception(SWIG_AttributeError, "No controller connection"); } else if (connect_err) { - const char *errstr = nvme_errno_to_string(errno); + const char *errstr = nvme_errno_to_string(-connect_err); if (errstr) { SWIG_exception(SWIG_RuntimeError, errstr); } else { @@ -91,7 +88,12 @@ PyObject *hostid_from_file(); if (discover_err == 1) { SWIG_exception(SWIG_AttributeError, "No controller connection"); } else if (discover_err) { - SWIG_exception(SWIG_RuntimeError, "Discover failed"); + const char *errstr = nvme_errno_to_string(-discover_err); + if (errstr) { + SWIG_exception(SWIG_RuntimeError, errstr); + } else { + SWIG_exception(SWIG_RuntimeError, "Discover failed"); + } } } @@ -348,8 +350,8 @@ PyObject *hostid_from_file(); #include "fabrics.h" #define STR_OR_NONE(str) (!(str) ? "None" : str) -struct nvme_host * nvme_first_host(struct nvme_root * r); -struct nvme_host * nvme_next_host(struct nvme_root * r, struct nvme_host * h); +struct nvme_host * nvme_first_host(struct nvme_global_ctx * ctx); +struct nvme_host * nvme_next_host(struct nvme_global_ctx *ctx, struct nvme_host * h); struct nvme_subsystem * nvme_first_subsystem(struct nvme_host * h); struct nvme_subsystem * nvme_next_subsystem(struct nvme_host * h, struct nvme_subsystem * s); struct nvme_ctrl * nvme_subsystem_first_ctrl(struct nvme_subsystem * s); @@ -359,7 +361,7 @@ struct nvme_ns * nvme_subsystem_next_ns(struct nvme_subsystem * s, struct nvme_n struct nvme_ns * nvme_ctrl_first_ns(struct nvme_ctrl * c); struct nvme_ns * nvme_ctrl_next_ns(struct nvme_ctrl * c, struct nvme_ns * n); -struct nvme_root { +struct nvme_global_ctx { %immutable config_file; %immutable application; char *config_file; @@ -489,17 +491,20 @@ struct nvme_ns { uint8_t uuid[16]; }; -%extend nvme_root { - nvme_root(const char *config_file = NULL) { - return nvme_scan(config_file); +%extend nvme_global_ctx { + nvme_global_ctx(const char *config_file = NULL) { + struct nvme_global_ctx *ctx; + if (nvme_scan(config_file, &ctx)) + return NULL; + return ctx; } - ~nvme_root() { - nvme_free_tree($self); + ~nvme_global_ctx() { + nvme_free_global_ctx($self); } - struct nvme_root* __enter__() { + struct nvme_global_ctx* __enter__() { return $self; } - struct nvme_root* __exit__(PyObject *type, PyObject *value, PyObject *traceback) { + struct nvme_global_ctx* __exit__(PyObject *type, PyObject *value, PyObject *traceback) { return $self; } void log_level(const char *level) { @@ -543,19 +548,23 @@ struct nvme_ns { @return: None" %enddef -%pythonappend nvme_host::nvme_host(struct nvme_root *r, +%pythonappend nvme_host::nvme_host(struct nvme_global_ctx *ctx, const char *hostnqn, const char *hostid, const char *hostkey, const char *hostsymname) { - self.__parent = r # Keep a reference to parent to ensure garbage collection happens in the right order} + self.__parent = ctx # Keep a reference to parent to ensure garbage collection happens in the right order} %extend nvme_host { - nvme_host(struct nvme_root *r, + nvme_host(struct nvme_global_ctx *ctx, const char *hostnqn = NULL, const char *hostid = NULL, const char *hostkey = NULL, const char *hostsymname = NULL) { - nvme_host_t h = hostnqn ? nvme_lookup_host(r, hostnqn, hostid) : nvme_default_host(r); + nvme_host_t h; + if (hostnqn) + h = nvme_lookup_host(ctx, hostnqn, hostid); + if (nvme_default_host(ctx, &h)) + return NULL; if (hostsymname) nvme_host_set_hostsymname(h, hostsymname); if (hostkey) @@ -669,15 +678,18 @@ struct nvme_ns { %pythonappend nvme_ctrl::init(struct nvme_host *h, int instance) { self.__host = h # Keep a reference to parent to ensure ctrl obj gets GCed before host} %extend nvme_ctrl { - nvme_ctrl(struct nvme_root *r, + nvme_ctrl(struct nvme_global_ctx *ctx, const char *subsysnqn, const char *transport, const char *traddr = NULL, const char *host_traddr = NULL, const char *host_iface = NULL, const char *trsvcid = NULL) { - return nvme_create_ctrl(r, subsysnqn, transport, traddr, - host_traddr, host_iface, trsvcid); + struct nvme_ctrl *c; + if (nvme_create_ctrl(ctx, subsysnqn, transport, traddr, + host_traddr, host_iface, trsvcid, &c)) + return NULL; + return c; } ~nvme_ctrl() { nvme_free_ctrl($self); @@ -710,7 +722,7 @@ struct nvme_ns { dev = nvme_ctrl_get_name($self); if (dev && !cfg->duplicate_connect) { - connect_err = 1; + connect_err = -ENVME_CONNECT_ALREADY; return; } @@ -718,8 +730,8 @@ struct nvme_ns { ret = nvmf_add_ctrl(h, $self, cfg); Py_END_ALLOW_THREADS /* Reacquire Python GIL */ - if (ret < 0) { - connect_err = 2; + if (ret) { + connect_err = ret; return; } } @@ -780,7 +792,7 @@ struct nvme_ns { %newobject discover; struct nvmf_discovery_log *discover(int lsp = 0, int max_retries = 6) { const char *dev; - struct nvmf_discovery_log *logp; + struct nvmf_discovery_log *logp = NULL; struct nvme_get_discovery_args args = { .c = $self, .args_size = sizeof(args), @@ -796,7 +808,7 @@ struct nvme_ns { return NULL; } Py_BEGIN_ALLOW_THREADS /* Release Python GIL */ - logp = nvmf_get_discovery_wargs(&args); + discover_err = nvmf_get_discovery_wargs(&args, &logp); Py_END_ALLOW_THREADS /* Reacquire Python GIL */ if (logp == NULL) discover_err = 2; @@ -806,14 +818,16 @@ struct nvme_ns { %feature("autodoc", "@return: List of supported log pages") supported_log_pages; PyObject *supported_log_pages(bool rae = true) { struct nvme_supported_log_pages log; + struct nvme_passthru_cmd cmd; PyObject *obj = NULL; int ret = 0; Py_BEGIN_ALLOW_THREADS /* Release Python GIL */ - ret = nvme_get_log_supported_log_pages(nvme_ctrl_get_fd($self), rae, &log); + nvme_init_get_log_supported_log_pages(&cmd, NVME_CSI_NVM, &log); + ret = nvme_get_log(nvme_ctrl_get_transport_handle($self), &cmd, rae, NVME_LOG_PAGE_PDU_SIZE, NULL); Py_END_ALLOW_THREADS /* Reacquire Python GIL */ - if (ret < 0) { + if (ret) { Py_RETURN_NONE; } diff --git a/libnvme/libnvme/tests/create-ctrl-obj.py b/libnvme/libnvme/tests/create-ctrl-obj.py index f7b5f4198f..6c57d43f5e 100755 --- a/libnvme/libnvme/tests/create-ctrl-obj.py +++ b/libnvme/libnvme/tests/create-ctrl-obj.py @@ -4,12 +4,12 @@ import pprint from libnvme import nvme -root = nvme.root() -root.log_level('debug') +ctx = nvme.global_ctx() +ctx.log_level('debug') -host = nvme.host(root) +host = nvme.host(ctx) subsysnqn = nvme.NVME_DISC_SUBSYS_NAME transport = 'loop' traddr = '127.0.0.1' trsvcid = '8009' -ctrl = nvme.ctrl(root, subsysnqn=subsysnqn, transport=transport, traddr=traddr, trsvcid=trsvcid) +ctrl = nvme.ctrl(ctx, subsysnqn=subsysnqn, transport=transport, traddr=traddr, trsvcid=trsvcid) diff --git a/libnvme/libnvme/tests/gc.py b/libnvme/libnvme/tests/gc.py index 77c2c0316f..74a9dd1a7e 100755 --- a/libnvme/libnvme/tests/gc.py +++ b/libnvme/libnvme/tests/gc.py @@ -5,17 +5,17 @@ import pprint from libnvme import nvme -root = nvme.root() -root.log_level('debug') -print(f'root: {root}') +ctx = nvme.global_ctx() +ctx.log_level('debug') +print(f'ctx: {ctx}') -host = nvme.host(root) +host = nvme.host(ctx) print(f'host: {host}') ctrls = [] for i in range(10): ctrl = nvme.ctrl( - root, + ctx, subsysnqn=nvme.NVME_DISC_SUBSYS_NAME, transport='loop', ) @@ -30,7 +30,7 @@ # Deleting objects in the following order would create a segmentation # fault if it weren't for the %pythonappend in nvme.i. This test is to # make sure garbage collection is not impacted by object deletion order. -root = None +ctx = None host = None gc.collect() # Force garbage collection before controller/subsystem objects get deleted diff --git a/libnvme/scripts/release.sh b/libnvme/scripts/release.sh index 22b36b0ba7..0323ee536d 100755 --- a/libnvme/scripts/release.sh +++ b/libnvme/scripts/release.sh @@ -135,7 +135,6 @@ fi declare -A maps maps=( [src/libnvme.map]=LIBNVME - [src/libnvme-mi.map]=LIBNVME_MI ) lib_ver="${ver//./_}" diff --git a/libnvme/src/libnvme-mi.map b/libnvme/src/libnvme-mi.map deleted file mode 100644 index afc4ce9410..0000000000 --- a/libnvme/src/libnvme-mi.map +++ /dev/null @@ -1,100 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -LIBNVME_MI_UNRELEASED { -}; - -LIBNVME_MI_1_15 { - global: - nvme_mi_admin_get_features_arbitration; - nvme_mi_admin_get_features_power_mgmt; - nvme_mi_admin_set_features_power_mgmt; -}; - -LIBNVME_MI_1_14 { - global: - nvme_mi_aem_disable; - nvme_mi_aem_enable; - nvme_mi_aem_get_enabled; - nvme_mi_aem_get_fd; - nvme_mi_aem_get_next_event; - nvme_mi_aem_process; - nvme_mi_set_csi; - nvme_mi_submit_entry; - nvme_mi_submit_exit; -}; - -LIBNVME_MI_1_12 { - global: - nvme_mi_mi_xfer; -}; - -LIBNVME_MI_1_11 { - global: - nvme_mi_control; -}; - -LIBNVME_MI_1_10 { - global: - nvme_mi_admin_get_ana_log_atomic; -}; - -LIBNVME_MI_1_5 { - global: - nvme_mi_ctrl_id; -}; - -LIBNVME_MI_1_4 { - global: - nvme_mi_admin_get_log_page; -}; - -LIBNVME_MI_1_3 { - global: - nvme_mi_admin_admin_passthru; - nvme_mi_ep_get_timeout; - nvme_mi_ep_set_timeout; - nvme_mi_set_probe_enabled; -}; - -LIBNVME_MI_1_2 { - global: - nvme_mi_admin_get_features; - nvme_mi_admin_set_features; - nvme_mi_admin_ns_mgmt; - nvme_mi_admin_ns_attach; - nvme_mi_admin_format_nvm; - nvme_mi_admin_sanitize_nvm; - nvme_mi_admin_fw_download; - nvme_mi_admin_fw_commit; - nvme_mi_status_to_string; -}; - -LIBNVME_MI_1_1 { - global: - nvme_mi_create_root; - nvme_mi_free_root; - nvme_mi_init_ctrl; - nvme_mi_close_ctrl; - nvme_mi_close; - nvme_mi_mi_config_get; - nvme_mi_mi_config_set; - nvme_mi_mi_read_mi_data_subsys; - nvme_mi_mi_read_mi_data_port; - nvme_mi_mi_read_mi_data_ctrl_list; - nvme_mi_mi_read_mi_data_ctrl; - nvme_mi_mi_subsystem_health_status_poll; - nvme_mi_admin_identify_partial; - nvme_mi_admin_get_log; - nvme_mi_admin_xfer; - nvme_mi_admin_security_send; - nvme_mi_admin_security_recv; - nvme_mi_endpoint_desc; - nvme_mi_first_endpoint; - nvme_mi_next_endpoint; - nvme_mi_first_ctrl; - nvme_mi_next_ctrl; - nvme_mi_open_mctp; - nvme_mi_scan_mctp; - nvme_mi_scan_ep; - local: - *; -}; diff --git a/libnvme/src/libnvme.map b/libnvme/src/libnvme.map index b89302baac..db16b79199 100644 --- a/libnvme/src/libnvme.map +++ b/libnvme/src/libnvme.map @@ -11,261 +11,93 @@ LIBNVME_1_16 { nvme_generate_tls_key_identity_compat; }; -LIBNVME_1_14 { - global: - nvme_get_features_temp_thresh2; - nvme_set_features_temp_thresh2; - nvme_subsystem_get_serial; -}; - -LIBNVME_1.13 { - global: - nvme_subsystem_get_fw_rev; - nvme_subsystem_get_model; -}; - -LIBNVME_1.12 { - global: - nvme_lm_cdq; - nvme_lm_track_send; - nvme_lm_migration_send; - nvme_lm_migration_recv; - nvme_lm_set_features_ctrl_data_queue; - nvme_lm_get_features_ctrl_data_queue; - nvmf_exat_ptr_next; -}; - -LIBNVME_1.11 { - global: - nvme_ctrl_get_keyring; - nvme_ctrl_get_tls_key; - nvme_ctrl_get_tls_key_identity; - nvme_ctrl_set_keyring; - nvme_ctrl_set_tls_key; - nvme_ctrl_set_tls_key_identity; - nvme_export_tls_key_versioned; - nvme_import_tls_key_versioned; - nvmf_connect_ctrl; -}; - - -LIBNVME_1.10 { - global: - nvme_free_uri; - nvme_get_ana_log_atomic; - nvme_get_ana_log_len_from_id_ctrl; - nvme_host_get_ids; - nvme_init_default_logging; - nvme_parse_uri; - nvme_revoke_tls_key; - nvme_root_skip_namespaces; - nvmf_hostid_generate; - nvmf_hostnqn_generate_from_hostid; -}; - -LIBNVME_1.9 { - global: - nvme_ctrl_get_cntlid; - nvme_export_tls_key; - nvme_get_logging_level; - nvme_import_tls_key; - nvme_read_key; - nvme_scan_tls_keys; - nvme_submit_passthru64; - nvme_submit_passthru; - nvme_update_key; -}; - -LIBNVME_1_8 { - global: - nvme_uuid_find; -}; - -LIBNVME_1_7 { - global: - nvme_init_copy_range_f2; - nvme_init_copy_range_f3; - nvme_insert_tls_key_versioned; - nvme_generate_tls_key_identity; -}; - -LIBNVME_1_6 { - global: - nvme_ctrl_config_match; - nvme_ctrl_find; - nvme_ctrl_get_src_addr; - nvme_ctrl_release_fd; - nvme_get_debug; - nvme_get_features_err_recovery2; - nvme_get_features_host_mem_buf2; - nvme_get_features_iocs_profile; - nvme_get_features_lba_range2; - nvme_get_features_resv_mask2; - nvme_get_features_resv_persist2; - nvme_host_release_fds; - nvme_ns_release_fd; - nvme_root_release_fds; - nvme_set_debug; - nvme_set_features_iocs_profile; - nvme_set_features_resv_mask2; - nvme_set_features_resv_persist2; - nvme_set_features_write_protect2; - nvme_set_root; - nvme_subsystem_get_iopolicy; - nvme_subsystem_release_fds; -}; - -LIBNVME_1_5 { - global: - nvme_ctrl_get_phy_slot; - nvme_ipaddrs_eq; - nvme_nbft_free; - nvme_nbft_read; - nvme_root_get_application; - nvme_root_set_application; - nvme_subsystem_get_application; - nvme_subsystem_set_application; -}; - -LIBNVME_1_4 { - global: - nvme_lookup_keyring; - nvme_describe_key_serial; - nvme_lookup_key; - nvme_set_keyring; - nvme_insert_tls_key; -}; - -LIBNVME_1_3 { - global: - nvme_ctrl_is_unique_discovery_ctrl; - nvme_ctrl_set_unique_discovery_ctrl; - nvme_io_mgmt_recv; - nvme_io_mgmt_send; - nvme_host_is_pdc_enabled; - nvme_host_set_pdc_enabled; -}; - -LIBNVME_1_2 { - global: - nvme_ctrl_get_dhchap_host_key; - nvme_ctrl_set_dhchap_host_key; - nvmf_get_discovery_wargs; - nvme_get_feature_length2; - nvme_ctrl_is_persistent; - nvme_uuid_from_string; - nvme_uuid_to_string; - nvme_uuid_random; -}; - -LIBNVME_1_1 { - global: - nvme_get_version; - nvme_init_copy_range_f1; -}; - -LIBNVME_1_0 { +LIBNVME_2_0 { global: nvme_admin_passthru64; nvme_admin_passthru; - nvme_capacity_mgmt; - nvme_copy; - nvme_create_root; + nvme_close; nvme_create_ctrl; + nvme_create_global_ctx; + nvme_ctrl_config_match; + nvme_ctrl_find; nvme_ctrl_first_ns; nvme_ctrl_first_path; nvme_ctrl_get_address; + nvme_ctrl_get_cntlid; nvme_ctrl_get_config; + nvme_ctrl_get_dhchap_host_key; nvme_ctrl_get_dhchap_key; - nvme_ctrl_get_fd; nvme_ctrl_get_firmware; nvme_ctrl_get_host_iface; nvme_ctrl_get_host_traddr; + nvme_ctrl_get_keyring; nvme_ctrl_get_model; nvme_ctrl_get_name; nvme_ctrl_get_numa_node; + nvme_ctrl_get_phy_slot; nvme_ctrl_get_queue_count; nvme_ctrl_get_serial; nvme_ctrl_get_sqsize; + nvme_ctrl_get_src_addr; nvme_ctrl_get_state; nvme_ctrl_get_subsysnqn; nvme_ctrl_get_subsystem; nvme_ctrl_get_sysfs_dir; + nvme_ctrl_get_tls_key; + nvme_ctrl_get_tls_key_identity; nvme_ctrl_get_traddr; nvme_ctrl_get_transport; + nvme_ctrl_get_transport_handle; nvme_ctrl_get_trsvcid; nvme_ctrl_identify; nvme_ctrl_is_discovery_ctrl; + nvme_ctrl_is_persistent; + nvme_ctrl_is_unique_discovery_ctrl; nvme_ctrl_next_ns; nvme_ctrl_next_path; + nvme_ctrl_release_transport_handle; nvme_ctrl_reset; + nvme_ctrl_set_dhchap_host_key; nvme_ctrl_set_dhchap_key; nvme_ctrl_set_discovery_ctrl; + nvme_ctrl_set_keyring; nvme_ctrl_set_persistent; + nvme_ctrl_set_tls_key; + nvme_ctrl_set_tls_key_identity; + nvme_ctrl_set_unique_discovery_ctrl; nvme_ctrls_filter; nvme_default_host; - nvme_dev_self_test; - nvme_dim_send; - nvme_directive_recv; - nvme_directive_send; - nvme_directive_send_id_endir; + nvme_describe_key_serial; nvme_disconnect_ctrl; - nvme_dsm; nvme_dump_config; nvme_dump_tree; nvme_errno_to_string; + nvme_export_tls_key; + nvme_export_tls_key_versioned; nvme_first_host; nvme_first_subsystem; - nvme_format_nvm; nvme_free_ctrl; + nvme_free_global_ctx; nvme_free_host; nvme_free_ns; nvme_free_subsystem; - nvme_free_tree; - nvme_fw_commit; - nvme_fw_download; + nvme_free_uri; nvme_fw_download_seq; nvme_gen_dhchap_key; + nvme_generate_tls_key_identity; + nvme_get_ana_log_atomic; nvme_get_ana_log_len; + nvme_get_ana_log_len_from_id_ctrl; + nvme_get_application; nvme_get_attr; nvme_get_ctrl_attr; nvme_get_ctrl_telemetry; + nvme_get_debug; nvme_get_directive_receive_length; nvme_get_feature_length; - nvme_get_features; - nvme_get_features_arbitration; - nvme_get_features_async_event; - nvme_get_features_auto_pst; - nvme_get_features_endurance_event_cfg; - nvme_get_features_err_recovery; - nvme_get_features_hctm; - nvme_get_features_host_behavior; - nvme_get_features_host_id; - nvme_get_features_host_mem_buf; - nvme_get_features_irq_coalesce; - nvme_get_features_irq_config; - nvme_get_features_kato; - nvme_get_features_lba_range; - nvme_get_features_lba_sts_interval; - nvme_get_features_nopsc; - nvme_get_features_num_queues; - nvme_get_features_plm_config; - nvme_get_features_plm_window; - nvme_get_features_power_mgmt; - nvme_get_features_resv_mask; - nvme_get_features_resv_persist; - nvme_get_features_rrl; - nvme_get_features_sanitize; - nvme_get_features_sw_progress; - nvme_get_features_temp_thresh; - nvme_get_features_timestamp; - nvme_get_features_volatile_wc; - nvme_get_features_write_atomic; - nvme_get_features_write_protect; nvme_get_host_telemetry; - nvme_get_lba_status; nvme_get_log; - nvme_get_log_page; + nvme_get_logging_level; nvme_get_logical_block_size; nvme_get_new_host_telemetry; nvme_get_ns_attr; @@ -275,31 +107,84 @@ LIBNVME_1_0 { nvme_get_subsys_attr; nvme_get_telemetry_log; nvme_get_telemetry_max; + nvme_get_version; nvme_host_get_dhchap_key; + nvme_host_get_global_ctx; nvme_host_get_hostid; nvme_host_get_hostnqn; nvme_host_get_hostsymname; - nvme_host_get_root; + nvme_host_get_ids; + nvme_host_is_pdc_enabled; + nvme_host_release_fds; nvme_host_set_dhchap_key; nvme_host_set_hostsymname; - nvme_identify; + nvme_host_set_pdc_enabled; + nvme_import_tls_key; + nvme_import_tls_key_versioned; nvme_init_copy_range; + nvme_init_copy_range_f1; + nvme_init_copy_range_f2; + nvme_init_copy_range_f3; nvme_init_ctrl; nvme_init_ctrl_list; + nvme_init_default_logging; nvme_init_dsm_range; nvme_init_logging; - nvme_io; + nvme_insert_tls_key; + nvme_insert_tls_key_versioned; nvme_io_passthru64; nvme_io_passthru; - nvme_lockdown; + nvme_ipaddrs_eq; nvme_lookup_ctrl; nvme_lookup_host; + nvme_lookup_key; + nvme_lookup_keyring; nvme_lookup_subsystem; + nvme_mi_admin_admin_passthru; + nvme_mi_admin_xfer; + nvme_mi_aem_disable; + nvme_mi_aem_enable; + nvme_mi_aem_get_enabled; + nvme_mi_aem_get_fd; + nvme_mi_aem_get_next_event; + nvme_mi_aem_process; + nvme_mi_close; + nvme_mi_close_transport_handle; + nvme_mi_control; + nvme_mi_create_global_ctx; + nvme_mi_ctrl_id; + nvme_mi_endpoint_desc; + nvme_mi_ep_get_timeout; + nvme_mi_ep_set_timeout; + nvme_mi_first_ctrl; + nvme_mi_first_endpoint; + nvme_mi_free_global_ctx; + nvme_mi_init_transport_handle; + nvme_mi_mi_config_get; + nvme_mi_mi_config_set; + nvme_mi_mi_read_mi_data_ctrl; + nvme_mi_mi_read_mi_data_ctrl_list; + nvme_mi_mi_read_mi_data_port; + nvme_mi_mi_read_mi_data_subsys; + nvme_mi_mi_subsystem_health_status_poll; + nvme_mi_mi_xfer; + nvme_mi_next_ctrl; + nvme_mi_next_endpoint; + nvme_mi_open_mctp; + nvme_mi_scan_ep; + nvme_mi_scan_mctp; + nvme_mi_set_csi; + nvme_mi_set_probe_enabled; + nvme_mi_status_to_string; + nvme_mi_submit_entry; + nvme_mi_submit_exit; nvme_namespace_attach_ctrls; nvme_namespace_detach_ctrls; nvme_namespace_filter; nvme_namespace_first_path; nvme_namespace_next_path; + nvme_nbft_free; + nvme_nbft_read; nvme_next_host; nvme_next_subsystem; nvme_ns_attach; @@ -308,7 +193,6 @@ LIBNVME_1_0 { nvme_ns_get_csi; nvme_ns_get_ctrl; nvme_ns_get_eui64; - nvme_ns_get_fd; nvme_ns_get_firmware; nvme_ns_get_generic_name; nvme_ns_get_lba_count; @@ -322,16 +206,18 @@ LIBNVME_1_0 { nvme_ns_get_serial; nvme_ns_get_subsystem; nvme_ns_get_sysfs_dir; + nvme_ns_get_transport_handle; nvme_ns_get_uuid; nvme_ns_identify; - nvme_ns_mgmt; nvme_ns_read; + nvme_ns_release_transport_handle; nvme_ns_rescan; nvme_ns_verify; nvme_ns_write; nvme_ns_write_uncorrectable; nvme_ns_write_zeros; nvme_open; + nvme_parse_uri; nvme_path_get_ana_state; nvme_path_get_ctrl; nvme_path_get_name; @@ -341,86 +227,82 @@ LIBNVME_1_0 { nvme_path_get_sysfs_dir; nvme_paths_filter; nvme_read_config; + nvme_read_key; nvme_refresh_topology; + nvme_release_fds; nvme_rescan_ctrl; - nvme_resv_acquire; - nvme_resv_register; - nvme_resv_release; - nvme_resv_report; - nvme_sanitize_nvm; + nvme_revoke_tls_key; nvme_scan; nvme_scan_ctrl; - nvme_scan_ctrls; nvme_scan_ctrl_namespace_paths; nvme_scan_ctrl_namespaces; - nvme_scan_topology; + nvme_scan_ctrls; nvme_scan_namespace; nvme_scan_subsystem_namespaces; nvme_scan_subsystems; - nvme_security_receive; - nvme_security_send; - nvme_set_features; - nvme_set_features_arbitration; - nvme_set_features_async_event; - nvme_set_features_auto_pst; - nvme_set_features_endurance_evt_cfg; - nvme_set_features_err_recovery; - nvme_set_features_hctm; - nvme_set_features_host_behavior; - nvme_set_features_host_id; - nvme_set_features_irq_coalesce; - nvme_set_features_irq_config; - nvme_set_features_lba_range; - nvme_set_features_lba_sts_interval; - nvme_set_features_nopsc; - nvme_set_features_plm_config; - nvme_set_features_plm_window; - nvme_set_features_power_mgmt; - nvme_set_features_resv_mask; - nvme_set_features_resv_persist; - nvme_set_features_rrl; - nvme_set_features_sanitize; - nvme_set_features_sw_progress; - nvme_set_features_temp_thresh; - nvme_set_features_timestamp; - nvme_set_features_volatile_wc; - nvme_set_features_write_atomic; - nvme_set_features_write_protect; + nvme_scan_tls_keys; + nvme_scan_topology; + nvme_set_application; + nvme_set_debug; + nvme_set_keyring; nvme_set_property; + nvme_set_root; + nvme_skip_namespaces; nvme_status_to_errno; nvme_status_to_string; nvme_submit_admin_passthru64; nvme_submit_admin_passthru; nvme_submit_io_passthru64; nvme_submit_io_passthru; + nvme_submit_passthru64; + nvme_submit_passthru; nvme_subsys_filter; nvme_subsystem_first_ctrl; nvme_subsystem_first_ns; + nvme_subsystem_get_application; + nvme_subsystem_get_fw_rev; nvme_subsystem_get_host; + nvme_subsystem_get_iopolicy; + nvme_subsystem_get_model; nvme_subsystem_get_name; nvme_subsystem_get_nqn; + nvme_subsystem_get_serial; nvme_subsystem_get_sysfs_dir; nvme_subsystem_get_type; nvme_subsystem_lookup_namespace; nvme_subsystem_next_ctrl; nvme_subsystem_next_ns; + nvme_subsystem_release_fds; nvme_subsystem_reset; + nvme_subsystem_set_application; + nvme_transport_handle_get_fd; + nvme_transport_handle_get_name; + nvme_transport_handle_is_blkdev; + nvme_transport_handle_is_chardev; + nvme_transport_handle_is_direct; + nvme_transport_handle_is_mi; nvme_unlink_ctrl; nvme_update_config; - nvme_virtual_mgmt; - nvme_zns_append; - nvme_zns_mgmt_recv; - nvme_zns_mgmt_send; + nvme_update_key; + nvme_uuid_find; + nvme_uuid_from_string; + nvme_uuid_random; + nvme_uuid_to_string; nvmf_add_ctrl; nvmf_adrfam_str; nvmf_cms_str; + nvmf_connect_ctrl; nvmf_connect_disc_entry; nvmf_default_config; nvmf_eflags_str; + nvmf_exat_ptr_next; nvmf_get_discovery_log; + nvmf_get_discovery_wargs; nvmf_hostid_from_file; + nvmf_hostid_generate; nvmf_hostnqn_from_file; nvmf_hostnqn_generate; + nvmf_hostnqn_generate_from_hostid; nvmf_is_registration_supported; nvmf_prtype_str; nvmf_qptype_str; diff --git a/libnvme/src/meson.build b/libnvme/src/meson.build index ca27187fae..a8c9691278 100644 --- a/libnvme/src/meson.build +++ b/libnvme/src/meson.build @@ -6,23 +6,19 @@ # Authors: Martin Belanger # sources = [ - 'nvme/nbft.c', + 'nvme/base64.c', + 'nvme/crc32.c', 'nvme/fabrics.c', 'nvme/filters.c', 'nvme/ioctl.c', 'nvme/linux.c', 'nvme/log.c', + 'nvme/mi-mctp.c', + 'nvme/mi.c', + 'nvme/nbft.c', 'nvme/sysfs.c', 'nvme/tree.c', 'nvme/util.c', - 'nvme/base64.c', - 'nvme/crc32.c' -] - -mi_sources = [ - 'nvme/log.c', - 'nvme/mi.c', - 'nvme/mi-mctp.c', ] if json_c_dep.found() @@ -33,20 +29,15 @@ endif deps = [ json_c_dep, - openssl_dep, keyutils_dep, - liburing_dep, -] - -mi_deps = [ libdbus_dep, + liburing_dep, + openssl_dep, ] source_dir = meson.current_source_dir() mapfile = 'libnvme.map' version_script_arg = join_paths(source_dir, mapfile) -mi_mapfile = 'libnvme-mi.map' -mi_version_script_arg = join_paths(source_dir, mi_mapfile) libnvme = library( 'nvme', # produces libnvme.so @@ -78,54 +69,31 @@ libnvme_dep = declare_dependency( link_with: libnvme, ) -libnvme_mi = library( - 'nvme-mi', # produces libnvme-mi.so - mi_sources, - version: library_version, - c_args: config_h_arg, - link_args: ['-Wl,--version-script=' + mi_version_script_arg], - dependencies: mi_deps, - link_depends: mi_mapfile, - include_directories: [incdir, internal_incdir], - install: true, - link_with: libccan, -) - -libnvme_mi_dep = declare_dependency( - include_directories: ['.'], - link_with: libnvme_mi, -) - # test library with all symbols visible, to use for MI unit tests. Should -# match libnvme_mi above, but with no version script, and install: false. -libnvme_mi_test = library( - 'nvme-mi-test', # produces libnvme-mi-test.so - mi_sources, - dependencies: mi_deps, +# match libnvme above, but with no version script, and install: false. +libnvme_test = library( + 'nvme-test', # produces libnvme-test.so + sources, + dependencies: deps, c_args: config_h_arg, include_directories: [incdir, internal_incdir], install: false, link_with: libccan, ) -libnvme_mi_test_dep = declare_dependency( +libnvme_test_dep = declare_dependency( include_directories: ['.'], - link_with: libnvme_mi_test, -) - -pkg.generate(libnvme_mi, - filebase: 'libnvme-mi', - name: 'libnvme-mi', - version: meson.project_version(), - description: 'Manage "libnvme" subsystem devices (Non-volatile Memory Express) over Management Interface', - url: 'http://github.com/linux-nvme/libnvme/', + link_with: libnvme_test, ) mode = ['rw-r--r--', 0, 0] -install_headers('libnvme.h', install_mode: mode) -install_headers('libnvme-mi.h', install_mode: mode) install_headers([ - 'nvme/api-types.h', + 'libnvme.h', + 'libnvme-mi.h', + ], + install_mode: mode, +) +install_headers([ 'nvme/fabrics.h', 'nvme/filters.h', 'nvme/ioctl.h', diff --git a/libnvme/src/nvme/api-types.h b/libnvme/src/nvme/api-types.h deleted file mode 100644 index 149ba22c7d..0000000000 --- a/libnvme/src/nvme/api-types.h +++ /dev/null @@ -1,1107 +0,0 @@ -// SPDX-License-Identifier: LGPL-2.1-or-later -/* - * Types used as part of the libnvme/libnvme-mi API, rather than specified - * by the NVM Express specification. - * - * These are shared across both libnvme and libnvme-mi interfaces. - * - * This file is part of libnvme. - * Copyright (c) 2022 Code Construct - * - * Authors: Jeremy Kerr - */ -#ifndef _LIBNVME_API_TYPES_H -#define _LIBNVME_API_TYPES_H - -#include - -#include - -/* - * _args struct definitions. These are used by both the ioctl-based and - * MI-based interfaces, as the call interface for (admin/io/etc) NVMe commands, - * passed to the nvme_*() and nvme_mi_*() functions. - * - * On MI-based interfaces, the fd and timeout members are unused, and should - * be set to zero. - */ - -/** - * struct nvme_identify_args - Arguments for the NVMe Identify command - * @result: The command completion result from CQE dword0 - * @data: User space destination address to transfer the data - * @args_size: Size of &struct nvme_identify_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms (0 for default timeout) - * @cns: The Controller or Namespace structure, see @enum nvme_identify_cns - * @csi: Command Set Identifier - * @nsid: Namespace identifier, if applicable - * @cntid: The Controller Identifier, if applicable - * @cns_specific_id: Identifier that is required for a particular CNS value - * @uuidx: UUID Index if controller supports this id selection method - */ -struct nvme_identify_args { - __u32 *result; - void *data; - int args_size; - int fd; - __u32 timeout; - enum nvme_identify_cns cns; - enum nvme_csi csi; - __u32 nsid; - __u16 cntid; - __u16 cns_specific_id; - __u8 uuidx; -}; - -/** - * struct nvme_get_log_args - Arguments for the NVMe Admin Get Log command - * @lpo: Log page offset for partial log transfers - * @result: The command completion result from CQE dword0 - * @log: User space destination address to transfer the data - * @args_size: Length of the structure - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @lid: Log page identifier, see &enum nvme_cmd_get_log_lid for known - * values - * @len: Length of provided user buffer to hold the log data in bytes - * @nsid: Namespace identifier, if applicable - * @csi: Command set identifier, see &enum nvme_csi for known values - * @lsi: Log Specific Identifier - * @lsp: Log specific field - * @uuidx: UUID selection, if supported - * @rae: Retain asynchronous events - * @ot: Offset Type; if set @lpo specifies the index into the list - * of data structures, otherwise @lpo specifies the byte offset - * into the log page. - */ -struct nvme_get_log_args { - __u64 lpo; - __u32 *result; - void *log; - int args_size; - int fd; - __u32 timeout; - enum nvme_cmd_get_log_lid lid; - __u32 len; - __u32 nsid; - enum nvme_csi csi; - __u16 lsi; - __u8 lsp; - __u8 uuidx; - bool rae; - bool ot; -}; - -/** - * struct nvme_set_features_args - Arguments for the NVMe Admin Set Feature command - * @result: The command completion result from CQE dword0 - * @data: User address of feature data, if applicable - * @args_size: Size of &struct nvme_set_features_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @nsid: Namespace ID, if applicable - * @cdw11: Value to set the feature to - * @cdw12: Feature specific command dword12 field - * @cdw13: Feature specific command dword13 field - * @cdw15: Feature specific command dword15 field - * @data_len: Length of feature data, if applicable, in bytes - * @save: Save value across power states - * @uuidx: UUID Index for differentiating vendor specific encoding - * @fid: Feature identifier - */ -struct nvme_set_features_args { - __u32 *result; - void *data; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - __u32 cdw11; - __u32 cdw12; - __u32 cdw13; - __u32 cdw15; - __u32 data_len; - bool save; - __u8 uuidx; - __u8 fid; -}; - -/** - * struct nvme_get_features_args - Arguments for the NVMe Admin Get Feature command - * @args_size: Size of &struct nvme_get_features_args - * @fd: File descriptor of nvme device - * @result: The command completion result from CQE dword0 - * @timeout: Timeout in ms - * @nsid: Namespace ID, if applicable - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * @cdw11: Feature specific command dword11 field - * @data_len: Length of feature data, if applicable, in bytes - * @data: User address of feature data, if applicable - * @fid: Feature identifier, see &enum nvme_features_id - * @uuidx: UUID Index for differentiating vendor specific encoding - */ -struct nvme_get_features_args { - __u32 *result; - void *data; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - enum nvme_get_features_sel sel; - __u32 cdw11; - __u32 data_len; - __u8 fid; - __u8 uuidx; -}; - -/** - * struct nvme_format_nvm_args - Arguments for the Format Nvme Namespace command - * @result: The command completion result from CQE dword0 - * @args_size: Size of &struct nvme_format_nvm_args - * @fd: File descriptor of nvme device - * @timeout: Set to override default timeout to this value in milliseconds; - * useful for long running formats. 0 will use system default. - * @nsid: Namespace ID to format - * @mset: Metadata settings (extended or separated), true if extended - * @pi: Protection information type - * @pil: Protection information location (beginning or end), true if end - * @ses: Secure erase settings - * @lbaf: Logical block address format least significant 4 bits - * @rsvd1: Reserved - * @lbafu: Logical block address format most significant 2 bits - */ -struct nvme_format_nvm_args { - __u32 *result; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - enum nvme_cmd_format_mset mset; - enum nvme_cmd_format_pi pi; - enum nvme_cmd_format_pil pil; - enum nvme_cmd_format_ses ses; - __u8 lbaf; - __u8 rsvd1[7]; - __u8 lbafu; -}; - -/** - * struct nvme_ns_mgmt_args - Arguments for NVMe Namespace Management command - * @result: NVMe command result - * @ns: Namespace identification descriptors - * @args_size: Size of &struct nvme_ns_mgmt_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @nsid: Namespace identifier - * @sel: Type of management operation to perform - * @csi: Command Set Identifier - * @rsvd1: Reserved - * @rsvd2: Reserved - * @data: Host Software Specified Fields - */ -struct nvme_ns_mgmt_args { - __u32 *result; - struct nvme_id_ns *ns; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - enum nvme_ns_mgmt_sel sel; - __u8 csi; - __u8 rsvd1[3]; - void *rsvd2; - struct nvme_ns_mgmt_host_sw_specified *data; -}; - -/** - * struct nvme_ns_attach_args - Arguments for Nvme Namespace Management command - * @result: NVMe command result - * @ctrlist: Controller list to modify attachment state of nsid - * @args_size: Size of &struct nvme_ns_attach_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @nsid: Namespace ID to execute attach selection - * @sel: Attachment selection, see &enum nvme_ns_attach_sel - */ -struct nvme_ns_attach_args { - __u32 *result; - struct nvme_ctrl_list *ctrlist; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - enum nvme_ns_attach_sel sel; -}; - -/** - * struct nvme_fw_download_args - Arguments for the NVMe Firmware Download command - * @args_size: Size of &struct nvme_fw_download_args - * @fd: File descriptor of nvme device - * @result: The command completion result from CQE dword0 - * @timeout: Timeout in ms - * @offset: Offset in the firmware data - * @data: Userspace address of the firmware data - * @data_len: Length of data in this command in bytes - */ -struct nvme_fw_download_args { - __u32 *result; - void *data; - int args_size; - int fd; - __u32 timeout; - __u32 offset; - __u32 data_len; -}; - -/** - * struct nvme_fw_commit_args - Arguments for the NVMe Firmware Commit command - * @args_size: Size of &struct nvme_fw_commit_args - * @fd: File descriptor of nvme device - * @action: Action to use for the firmware image, see &enum nvme_fw_commit_ca - * @timeout: Timeout in ms - * @result: The command completion result from CQE dword0 - * @slot: Firmware slot to commit the downloaded image - * @bpid: Set to true to select the boot partition id - */ -struct nvme_fw_commit_args { - __u32 *result; - int args_size; - int fd; - __u32 timeout; - enum nvme_fw_commit_ca action; - __u8 slot; - bool bpid; -}; - -/** - * struct nvme_security_send_args - Arguments for the NVMe Security Send command - * @result: The command completion result from CQE dword0 - * @data: Security data payload to send - * @args_size: Size of &struct nvme_security_send_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @nsid: Namespace ID to issue security command on - * @tl: Protocol specific transfer length - * @data_len: Data length of the payload in bytes - * @nssf: NVMe Security Specific field - * @spsp0: Security Protocol Specific field - * @spsp1: Security Protocol Specific field - * @secp: Security Protocol - */ -struct nvme_security_send_args { - __u32 *result; - void *data; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - __u32 tl; - __u32 data_len; - __u8 nssf; - __u8 spsp0; - __u8 spsp1; - __u8 secp; -}; - -/** - * struct nvme_security_receive_args - Arguments for the NVMe Security Receive command - * @result: The command completion result from CQE dword0 - * @data: Security data payload to send - * @args_size: Size of &struct nvme_security_receive_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @nsid: Namespace ID to issue security command on - * @al: Protocol specific allocation length - * @data_len: Data length of the payload in bytes - * @nssf: NVMe Security Specific field - * @spsp0: Security Protocol Specific field - * @spsp1: Security Protocol Specific field - * @secp: Security Protocol - */ -struct nvme_security_receive_args { - __u32 *result; - void *data; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - __u32 al; - __u32 data_len; - __u8 nssf; - __u8 spsp0; - __u8 spsp1; - __u8 secp; -}; - -/** - * struct nvme_get_lba_status_args - Arguments for the NVMe Get LBA Status command - * @lbas: Data payload to return status descriptors - * @result: The command completion result from CQE dword0 - * @slba: Starting logical block address to check statuses - * @args_size: Size of &struct nvme_get_lba_status_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @nsid: Namespace ID to retrieve LBA status - * @mndw: Maximum number of dwords to return - * @atype: Action type mechanism to determine LBA status descriptors to - * return, see &enum nvme_lba_status_atype - * @rl: Range length from slba to perform the action - */ -struct nvme_get_lba_status_args { - __u64 slba; - __u32 *result; - struct nvme_lba_status *lbas; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - __u32 mndw; - enum nvme_lba_status_atype atype; - __u16 rl; -}; - -/** - * struct nvme_directive_send_args - Arguments for the NVMe Directive Send command - * @result: If successful, the CQE dword0 value - * @data: Data payload to be send - * @args_size: Size of &struct nvme_directive_send_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @nsid: Namespace ID, if applicable - * @doper: Directive send operation, see &enum nvme_directive_send_doper - * @dtype: Directive type, see &enum nvme_directive_dtype - * @cdw12: Directive specific command dword12 - * @data_len: Length of data payload in bytes - * @dspec: Directive specific field - */ -struct nvme_directive_send_args { - __u32 *result; - void *data; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - enum nvme_directive_send_doper doper; - enum nvme_directive_dtype dtype; - __u32 cdw12; - __u32 data_len; - __u16 dspec; -}; - -/** - * struct nvme_directive_recv_args - Arguments for the NVMe Directive Receive command - * @result: If successful, the CQE dword0 value - * @data: Userspace address of data payload - * @args_size: Size of &struct nvme_directive_recv_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @nsid: Namespace ID, if applicable - * @doper: Directive send operation, see &enum nvme_directive_send_doper - * @dtype: Directive type, see &enum nvme_directive_dtype - * @cdw12: Directive specific command dword12 - * @data_len: Length of data payload in bytes - * @dspec: Directive specific field - */ -struct nvme_directive_recv_args { - __u32 *result; - void *data; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - enum nvme_directive_receive_doper doper; - enum nvme_directive_dtype dtype; - __u32 cdw12; - __u32 data_len; - __u16 dspec; -}; - -/** - * struct nvme_capacity_mgmt_args - Arguments for the NVMe Capacity Management command - * @result: If successful, the CQE dword0 value - * @args_size: Size of &struct nvme_capacity_mgmt_args - * @fd: File descriptor of nvme device - * @cdw11: Least significant 32 bits of the capacity in bytes of the - * Endurance Group or NVM Set to be created - * @cdw12: Most significant 32 bits of the capacity in bytes of the - * Endurance Group or NVM Set to be created - * @timeout: Timeout in ms - * @element_id: Value specific to the value of the Operation field - * @op: Operation to be performed by the controller - */ -struct nvme_capacity_mgmt_args { - __u32 *result; - int args_size; - int fd; - __u32 timeout; - __u32 cdw11; - __u32 cdw12; - __u16 element_id; - __u8 op; -}; - -/** - * struct nvme_lockdown_args - Arguments for the NVME Lockdown command - * @args_size: Size of &struct nvme_lockdown_args - * @fd: File descriptor of nvme device - * @result: The command completion result from CQE dword0 - * @timeout: Timeout in ms (0 for default timeout) - * @scp: Scope of the command - * @prhbt: Prohibit or allow the command opcode or Set Features command - * @ifc: Affected interface - * @ofi: Opcode or Feature Identifier - * @uuidx: UUID Index if controller supports this id selection method - */ -struct nvme_lockdown_args { - __u32 *result; - int args_size; - int fd; - __u32 timeout; - __u8 scp; - __u8 prhbt; - __u8 ifc; - __u8 ofi; - __u8 uuidx; -}; - -/** - * struct nvme_set_property_args - Arguments for NVMe Set Property command - * @args_size: Size of &struct nvme_set_property_args - * @fd: File descriptor of nvme device - * @result: The command completion result from CQE dword0 - * @timeout: Timeout in ms - * @offset: Property offset from the base to set - * @value: The value to set the property - */ -struct nvme_set_property_args { - __u64 value; - __u32 *result; - int args_size; - int fd; - __u32 timeout; - int offset; -}; - -/** - * struct nvme_get_property_args - Arguments for NVMe Get Property command - * @value: Where the property's value will be stored on success - * @args_size: Size of &struct nvme_get_property_args - * @fd: File descriptor of nvme device - * @offset: Property offset from the base to retrieve - * @timeout: Timeout in ms - */ -struct nvme_get_property_args { - __u64 *value; - int args_size; - int fd; - __u32 timeout; - int offset; -}; - -/** - * struct nvme_sanitize_nvm_args - Arguments for the NVMe Sanitize NVM command - * @result: The command completion result from CQE dword0 - * @args_size: Size of &struct nvme_sanitize_nvm_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @ovrpat: Overwrite pattern - * @sanact: Sanitize action, see &enum nvme_sanitize_sanact - * @ause: Set to allow unrestricted sanitize exit - * @owpass: Overwrite pass count - * @oipbp: Set to overwrite invert pattern between passes - * @nodas: Set to not deallocate blocks after sanitizing - * @emvs: Set to enter media verification state - */ -struct nvme_sanitize_nvm_args { - __u32 *result; - int args_size; - int fd; - __u32 timeout; - enum nvme_sanitize_sanact sanact; - __u32 ovrpat; - bool ause; - __u8 owpass; - bool oipbp; - bool nodas; - bool emvs; -}; - -/** - * struct nvme_dev_self_test_args - Arguments for the NVMe Device Self Test command - * @result: The command completion result from CQE dword0 - * @args_size: Size of &struct nvme_dev_self_test_args - * @fd: File descriptor of nvme device - * @nsid: Namespace ID to test - * @stc: Self test code, see &enum nvme_dst_stc - * @timeout: Timeout in ms - */ -struct nvme_dev_self_test_args { - __u32 *result; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - enum nvme_dst_stc stc; -}; - -/** - * struct nvme_virtual_mgmt_args - Arguments for the NVMe Virtualization - * resource management command - * @args_size: Size of &struct nvme_virtual_mgmt_args - * @fd: File descriptor of nvme device - * @result: If successful, the CQE dword0 - * @timeout: Timeout in ms - * @act: Virtual resource action, see &enum nvme_virt_mgmt_act - * @rt: Resource type to modify, see &enum nvme_virt_mgmt_rt - * @cntlid: Controller id for which resources are bing modified - * @nr: Number of resources being allocated or assigned - */ -struct nvme_virtual_mgmt_args { - __u32 *result; - int args_size; - int fd; - __u32 timeout; - enum nvme_virt_mgmt_act act; - enum nvme_virt_mgmt_rt rt; - __u16 cntlid; - __u16 nr; -}; - -/** - * struct nvme_io_args - Arguments for NVMe I/O commands - * @slba: Starting logical block - * @storage_tag: This filed specifies Variable Sized Expected Logical Block - * Storage Tag (ELBST) or Logical Block Storage Tag (LBST) - * @result: The command completion result from CQE dword0 - * @data: Pointer to user address of the data buffer - * @metadata: Pointer to user address of the metadata buffer - * @args_size: Size of &struct nvme_io_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @nsid: Namespace ID - * @data_len: Length of user buffer, @data, in bytes - * @metadata_len:Length of user buffer, @metadata, in bytes - * @nlb: Number of logical blocks to send (0's based value) - * @control: Command control flags, see &enum nvme_io_control_flags. - * @apptag: This field specifies the Application Tag Mask expected value. - * Used only if the namespace is formatted to use end-to-end - * protection information. - * @appmask: This field specifies the Application Tag expected value. Used - * only if the namespace is formatted to use end-to-end protection - * information. - * @reftag: This field specifies the variable sized Expected Initial - * Logical Block Reference Tag (EILBRT) or Initial Logical Block - * Reference Tag (ILBRT). Used only if the namespace is formatted - * to use end-to-end protection information. - * @dspec: Directive specific value - * @dsm: Data set management attributes, see &enum nvme_io_dsm_flags - * @rsvd1: Reserved - * @reftag_u64: This field specifies the variable sized Expected Initial - * Logical Block Reference Tag (EILBRT) or Initial Logical Block - * Reference Tag (ILBRT). It is the 8 byte version required for - * enhanced protection information. Used only if the namespace is - * formatted to use end-to-end protection information. - * @sts: Storage tag size in bits, set by namespace Extended LBA Format - * @pif: Protection information format, determines how variable sized - * storage_tag and reftag are put into dwords 2, 3, and 14. Set by - * namespace Extended LBA Format. - */ -struct nvme_io_args { - __u64 slba; - __u64 storage_tag; - __u32 *result; - void *data; - void *metadata; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - __u32 reftag; - __u32 data_len; - __u32 metadata_len; - __u16 nlb; - __u16 control; - __u16 apptag; - __u16 appmask; - __u16 dspec; - __u8 dsm; - __u8 rsvd1[1]; - __u64 reftag_u64; - __u8 sts; - __u8 pif; -}; - -/** - * struct nvme_dsm_args - Arguments for the NVMe Dataset Management command - * @result: The command completion result from CQE dword0 - * @dsm: The data set management attributes - * @args_size: Size of &struct nvme_dsm_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @nsid: Namespace identifier - * @attrs: DSM attributes, see &enum nvme_dsm_attributes - * @nr_ranges: Number of block ranges in the data set management attributes - */ -struct nvme_dsm_args { - __u32 *result; - struct nvme_dsm_range *dsm; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - __u32 attrs; - __u16 nr_ranges; -}; - -/** - * struct nvme_copy_args - Arguments for the NVMe Copy command - * @sdlba: Start destination LBA - * @result: The command completion result from CQE dword0 - * @copy: Range description - * @args_size: Size of &struct nvme_copy_args - * @fd: File descriptor of the nvme device - * @timeout: Timeout in ms - * @nsid: Namespace identifier - * @ilbrt: Initial logical block reference tag - * @lr: Limited retry - * @fua: Force unit access - * @nr: Number of ranges - * @dspec: Directive specific value - * @lbatm: Logical block application tag mask - * @lbat: Logical block application tag - * @prinfor: Protection information field for read - * @prinfow: Protection information field for write - * @dtype: Directive type - * @format: Descriptor format - * @ilbrt_u64: Initial logical block reference tag - 8 byte - * version required for enhanced protection info - */ -struct nvme_copy_args { - __u64 sdlba; - __u32 *result; - struct nvme_copy_range *copy; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - __u32 ilbrt; - int lr; - int fua; - __u16 nr; - __u16 dspec; - __u16 lbatm; - __u16 lbat; - __u8 prinfor; - __u8 prinfow; - __u8 dtype; - __u8 format; - __u64 ilbrt_u64; -}; - -/** - * struct nvme_resv_acquire_args - Arguments for the NVMe Reservation Acquire Command - * @nrkey: The reservation key to be unregistered from the namespace if - * the action is preempt - * @iekey: Set to ignore the existing key - * @result: The command completion result from CQE dword0 - * @args_size: Size of &struct nvme_resv_acquire_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @nsid: Namespace identifier - * @rtype: The type of reservation to be create, see &enum nvme_resv_rtype - * @racqa: The action that is performed by the command, see &enum nvme_resv_racqa - * @crkey: The current reservation key associated with the host - */ -struct nvme_resv_acquire_args { - __u64 crkey; - __u64 nrkey; - __u32 *result; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - enum nvme_resv_rtype rtype; - enum nvme_resv_racqa racqa; - bool iekey; -}; - -/** - * struct nvme_resv_register_args - Arguments for the NVMe Reservation Register command - * @crkey: The current reservation key associated with the host - * @nrkey: The new reservation key to be register if action is register or - * replace - * @result: The command completion result from CQE dword0 - * @args_size: Size of &struct nvme_resv_register_args - * @fd: File descriptor of nvme device - * @nsid: Namespace identifier - * @rrega: The registration action, see &enum nvme_resv_rrega - * @cptpl: Change persist through power loss, see &enum nvme_resv_cptpl - * @iekey: Set to ignore the existing key - * @timeout: Timeout in ms - */ -struct nvme_resv_register_args { - __u64 crkey; - __u64 nrkey; - __u32 *result; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - enum nvme_resv_rrega rrega; - enum nvme_resv_cptpl cptpl; - bool iekey; -}; - -/** - * struct nvme_resv_release_args - Arguments for the NVMe Reservation Release Command - * @crkey: The current reservation key to release - * @result: The command completion result from CQE dword0 - * @args_size: Size of &struct nvme_resv_release_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @nsid: Namespace identifier - * @rtype: The type of reservation to be create, see &enum nvme_resv_rtype - * @rrela: Reservation release action, see &enum nvme_resv_rrela - * @iekey: Set to ignore the existing key - */ -struct nvme_resv_release_args { - __u64 crkey; - __u32 *result; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - enum nvme_resv_rtype rtype; - enum nvme_resv_rrela rrela; - bool iekey; -}; - -/** - * struct nvme_resv_report_args - Arguments for the NVMe Reservation Report command - * @result: The command completion result from CQE dword0 - * @report: The user space destination address to store the reservation - * report - * @args_size: Size of &struct nvme_resv_report_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @nsid: Namespace identifier - * @len: Number of bytes to request transferred with this command - * @eds: Request extended Data Structure - */ -struct nvme_resv_report_args { - __u32 *result; - struct nvme_resv_status *report; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - __u32 len; - bool eds; -}; - -/** - * struct nvme_io_mgmt_recv_args - Arguments for the NVMe I/O Management Receive command - * @data: Userspace address of the data - * @args_size: Size of &struct nvme_io_mgmt_recv_args - * @fd: File descriptor of nvme device - * @nsid: Namespace identifier - * @data_len: Length of @data - * @timeout: Timeout in ms - * @mos: Management Operation Specific - * @mo: Management Operation - */ -struct nvme_io_mgmt_recv_args { - void *data; - int args_size; - int fd; - __u32 nsid; - __u32 data_len; - __u32 timeout; - __u16 mos; - __u8 mo; -}; - -/** - * struct nvme_io_mgmt_send_args - Arguments for the NVMe I/O Management Send command - * @data: Userspace address of the data - * @args_size: Size of &struct nvme_io_mgmt_send_args - * @fd: File descriptor of nvme device - * @nsid: Namespace identifier - * @data_len: Length of @data - * @timeout: Timeout in ms - * @mos: Management Operation Specific - * @mo: Management Operation - */ -struct nvme_io_mgmt_send_args { - void *data; - int args_size; - int fd; - __u32 nsid; - __u32 data_len; - __u32 timeout; - __u16 mos; - __u8 mo; -}; - -/** - * struct nvme_zns_mgmt_send_args - Arguments for the NVMe ZNS Management Send command - * @slba: Starting logical block address - * @result: The command completion result from CQE dword0 - * @data: Userspace address of the data - * @args_size: Size of &struct nvme_zns_mgmt_send_args - * @fd: File descriptor of nvme device - * @timeout: timeout in ms - * @nsid: Namespace ID - * @zsa: Zone send action - * @data_len: Length of @data - * @select_all: Select all flag - * @zsaso: Zone Send Action Specific Option - */ -struct nvme_zns_mgmt_send_args { - __u64 slba; - __u32 *result; - void *data; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - enum nvme_zns_send_action zsa; - __u32 data_len; - bool select_all; - __u8 zsaso; -}; - -/** - * struct nvme_zns_mgmt_recv_args - Arguments for the NVMe ZNS Management Receive command - * @slba: Starting logical block address - * @result: The command completion result from CQE dword0 - * @data: Userspace address of the data - * @args_size: Size of &struct nvme_zns_mgmt_recv_args - * @fd: File descriptor of nvme device - * @timeout: timeout in ms - * @nsid: Namespace ID - * @zra: zone receive action - * @data_len: Length of @data - * @zrasf: Zone receive action specific field - * @zras_feat: Zone receive action specific features - */ -struct nvme_zns_mgmt_recv_args { - __u64 slba; - __u32 *result; - void *data; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - enum nvme_zns_recv_action zra; - __u32 data_len; - __u16 zrasf; - bool zras_feat; -}; - -/** - * struct nvme_zns_append_args - Arguments for the NVMe ZNS Append command - * @zslba: Zone start logical block address - * @result: The command completion result from CQE dword0 - * @data: Userspace address of the data - * @metadata: Userspace address of the metadata - * @args_size: Size of &struct nvme_zns_append_args - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @nsid: Namespace ID - * @ilbrt: Initial logical block reference tag - * @data_len: Length of @data - * @metadata_len: Length of @metadata - * @nlb: Number of logical blocks - * @control: - * @lbat: Logical block application tag - * @lbatm: Logical block application tag mask - * @rsvd1: Reserved - * @ilbrt_u64: Initial logical block reference tag - 8 byte - * version required for enhanced protection info - * - */ -struct nvme_zns_append_args { - __u64 zslba; - __u64 *result; - void *data; - void *metadata; - int args_size; - int fd; - __u32 timeout; - __u32 nsid; - __u32 ilbrt; - __u32 data_len; - __u32 metadata_len; - __u16 nlb; - __u16 control; - __u16 lbat; - __u16 lbatm; - __u8 rsvd1[4]; - __u64 ilbrt_u64; -}; - -/** - * struct nvme_dim_args - Arguments for the Discovery Information Management (DIM) command - * @result: Set on completion to the command's CQE DWORD 0 controller response. - * @data: Pointer to the DIM data - * @args_size: Length of the structure - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @data_len: Length of @data - * @tas: Task field of the Command Dword 10 (cdw10) - */ -struct nvme_dim_args { - __u32 *result; - void *data; - int args_size; - int fd; - __u32 timeout; - __u32 data_len; - __u8 tas; -}; - -/** - * struct nvme_lm_cdq_args - Arguments for Controller Data Queue (CDQ) command - * @result: Set on completion to the command's CQE DWORD 0 controller response - * @data: Pointer to data - * @args_size: Length of structure - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @mos: Management Operation Specific (MOS): This field is specific to the SEL type - * @cntlid: Controller ID: For Create CDQ, specifies the target migratable controller - * @cdqid: Controller Data Queue ID (CDQID): For Create CDQ, this field is the CDQID created - * by the controller if no error is present. For Delete CDQ, this field is the CDQID - * to delete. - * @sel: Select (SEL): This field specifies the type of management operation to perform. - * @sz_u8: For Create CDQ, specifies the size of CDQ, in dwords - 1 byte - * @rsvd1: Reserved - * @sz: For Create CDQ, specifies the size of CDQ, in dwords - 4 byte - */ -struct nvme_lm_cdq_args { - __u32 *result; - void *data; - int args_size; - int fd; - __u32 timeout; - __u16 mos; - __u16 cntlid; - __u16 cdqid; - __u8 sel; - __u8 sz_u8; - __u8 rsvd1[4]; - __u32 sz; -}; - -/** - * struct nvme_lm_track_send_args - Arguments for the Track Send command - * @result: Set on completion to the command's CQE DWORD 0 controller response - * @args_size: Length of structure - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @mos: Management Operation Specific (MOS): This field is specific to the SEL type - * @cdqid: Controller Data Queue ID (CDQID) - * @sel: Select (SEL): This field specifies the type of management operation to perform - */ -struct nvme_lm_track_send_args { - __u32 *result; - int args_size; - int fd; - __u32 timeout; - __u16 mos; - __u16 cdqid; - __u8 sel; -}; - -/** - * struct nvme_lm_migration_send_args - Arguments for the Migration Send command - * @offset: Offset: This field specifies the offset, in bytes, within the data available to be - * returned and specifies the starting point for that data for what is actually - * returned to the host. - * @result: Set on completion to the command's CQE DWORD 0 controller response - * @data: Pointer to data - * @args_size: Length of structure - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @numd: Number of Dwords (NUMD): This field specifies the number of dwords being transferred - * @mos: Management Operation Specific (MOS): This field is specific to the SEL type - * @cntlid: Controller ID: This field specifies the identifier of the controller to which the - * operation is performed. - * @csuuidi: Controller State UUID Index (CSUUIDI): A non-zero value in this field specifies the - * index to a specific entry in the Vendor Specific Controller State UUID Supported. - * list of the Supported Controller State Formats data structure. - * @sel: Select (SEL): This field specifies the type of management operation to perform. - * @uidx: UUID Index (UIDX): If this field is set to a non-zero value, then the value of this - * field is the index of a UUID in the UUID List (refer to Figure 320) that is used by - * the command. - * @stype: Suspend Type (STYPE): This field specifies the type of suspend. - * @seqind: Sequence Identifier (SEQIND): This field identified the sequences of this Migration - * Send command in relation to other Migration Send commands. - * @csvi: Controller State Version Index (CSVI): A non-zero value in this field specifies the - * index to a specific entry in the NVMe Controller State Version list of the Supported - * Controller State Formats data structure. - * @dudmq: Delete User Data Migration Queue (DUDMQ): If set, the migration queue is deleted - * is deleted as part of the Suspend operation. If cleared, it is retained. - */ -struct nvme_lm_migration_send_args { - __u64 offset; - __u32 *result; - void *data; - int args_size; - int fd; - __u32 timeout; - __u32 numd; - __u16 mos; - __u16 cntlid; - __u16 csuuidi; - __u8 sel; - __u8 uidx; - __u8 stype; - __u8 seqind; - __u8 csvi; - bool dudmq; -}; - -/** - * struct nvme_lm_migration_recv_args - Arguments for the Migration Receive command - * @offset: Offset: This field specifies the offset, in bytes, within the data available to be - * returned and specifies the starting point for that data for what is actually - * returned to the host. - * @result: Set on completion to the command's CQE DWORD 0 controller response - * @data: Pointer to data - * @args_size: Length of structure - * @fd: File descriptor of nvme device - * @timeout: Timeout in ms - * @numd: Number of Dwords (NUMD): This field specifies the number of dwords to return. This - * is a 0's based value. - * @mos: Management Operation Specific (MOS): This field is specific to the SEL type - * @cntlid: Controller ID: This field specifies the identifier of the controller to which the - * operation is performed. - * @csuuidi: Controller State UUID Index (CSUUIDI): A non-zero value in this field specifies the - * index to a specific entry in the Vendor Specific Controller State UUID Supported. - * list of the Supported Controller State Formats data structure. - * @sel: Select (SEL): This field specifies the type of management operation to perform - * @uidx: UUID Index (UIDX): If this field is set to a non-zero value, then the value of this - * field is the index of a UUID in the UUID List (refer to Figure 320) that is used by - * the command. - * @csuidxp: Controller State UUID Index Parameter (CSUIDXP): This field is vendor specific. - */ -struct nvme_lm_migration_recv_args { - __u64 offset; - __u32 *result; - void *data; - int args_size; - int fd; - __u32 timeout; - __u32 numd; - __u16 mos; - __u16 cntlid; - __u16 csuuidi; - __u8 sel; - __u8 uidx; - __u8 csuidxp; -}; - -#endif /* _LIBNVME_API_TYPES_H */ diff --git a/libnvme/src/nvme/cleanup.h b/libnvme/src/nvme/cleanup.h index 432760046c..4c275398d9 100644 --- a/libnvme/src/nvme/cleanup.h +++ b/libnvme/src/nvme/cleanup.h @@ -6,6 +6,9 @@ #include #include #include +#include +#include +#include #define __cleanup__(fn) __attribute__((cleanup(fn))) @@ -38,4 +41,7 @@ static inline void cleanup_fd(int *fd) } #define _cleanup_fd_ __cleanup__(cleanup_fd) +static inline DEFINE_CLEANUP_FUNC(cleanup_addrinfo, struct addrinfo *, freeaddrinfo) +#define _cleanup_addrinfo_ __cleanup__(cleanup_addrinfo) + #endif diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index b0821e9637..d9500eb6e6 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -36,6 +36,7 @@ #include "fabrics.h" #include "linux.h" #include "ioctl.h" +#include "nvme/tree.h" #include "util.h" #include "log.h" #include "private.h" @@ -300,8 +301,7 @@ static int __add_bool_argument(char **argstr, char *tok, bool arg) if (!arg) return 0; if (asprintf(&nstr, "%s,%s", *argstr, tok) < 0) { - errno = ENOMEM; - return -1; + return -ENOMEM; } free(*argstr); *argstr = nstr; @@ -316,8 +316,7 @@ static int __add_hex_argument(char **argstr, char *tok, int arg, bool allow_zero if (arg < 0 || (!arg && !allow_zero)) return 0; if (asprintf(&nstr, "%s,%s=0x%08x", *argstr, tok, arg) < 0) { - errno = ENOMEM; - return -1; + return -ENOMEM; } free(*argstr); *argstr = nstr; @@ -332,8 +331,7 @@ static int __add_int_argument(char **argstr, char *tok, int arg, bool allow_zero if (arg < 0 || (!arg && !allow_zero)) return 0; if (asprintf(&nstr, "%s,%s=%d", *argstr, tok, arg) < 0) { - errno = ENOMEM; - return -1; + return -ENOMEM; } free(*argstr); *argstr = nstr; @@ -348,8 +346,7 @@ static int __add_int_or_minus_one_argument(char **argstr, char *tok, int arg) if (arg < -1) return 0; if (asprintf(&nstr, "%s,%s=%d", *argstr, tok, arg) < 0) { - errno = ENOMEM; - return -1; + return -ENOMEM; } free(*argstr); *argstr = nstr; @@ -364,8 +361,7 @@ static int __add_argument(char **argstr, const char *tok, const char *arg) if (!arg || arg[0] == '\0' || !strcmp(arg, "none")) return 0; if (asprintf(&nstr, "%s,%s=%s", *argstr, tok, arg) < 0) { - errno = ENOMEM; - return -1; + return -ENOMEM; } free(*argstr); *argstr = nstr; @@ -373,21 +369,21 @@ static int __add_argument(char **argstr, const char *tok, const char *arg) return 0; } -static int __nvmf_supported_options(nvme_root_t r); -#define nvmf_check_option(r, tok) \ +static int __nvmf_supported_options(struct nvme_global_ctx *ctx); +#define nvmf_check_option(ctx, tok) \ ({ \ - !__nvmf_supported_options(r) && (r)->options->tok; \ + !__nvmf_supported_options(ctx) && ctx->options->tok; \ }) -#define add_bool_argument(r, argstr, tok, arg) \ +#define add_bool_argument(ctx, argstr, tok, arg) \ ({ \ int ret; \ - if (nvmf_check_option(r, tok)) { \ + if (nvmf_check_option(ctx, tok)) { \ ret = __add_bool_argument(argstr, \ stringify(tok), \ arg); \ } else { \ - nvme_msg(r, LOG_DEBUG, \ + nvme_msg(ctx, LOG_DEBUG, \ "option \"%s\" ignored\n", \ stringify(tok)); \ ret = 0; \ @@ -395,16 +391,16 @@ static int __nvmf_supported_options(nvme_root_t r); ret; \ }) -#define add_hex_argument(r, argstr, tok, arg, allow_zero) \ +#define add_hex_argument(ctx, argstr, tok, arg, allow_zero) \ ({ \ int ret; \ - if (nvmf_check_option(r, tok)) { \ + if (nvmf_check_option(ctx, tok)) { \ ret = __add_hex_argument(argstr, \ stringify(tok), \ arg, \ allow_zero); \ } else { \ - nvme_msg(r, LOG_DEBUG, \ + nvme_msg(ctx, LOG_DEBUG, \ "option \"%s\" ignored\n", \ stringify(tok)); \ ret = 0; \ @@ -412,16 +408,16 @@ static int __nvmf_supported_options(nvme_root_t r); ret; \ }) -#define add_int_argument(r, argstr, tok, arg, allow_zero) \ +#define add_int_argument(ctx, argstr, tok, arg, allow_zero) \ ({ \ int ret; \ - if (nvmf_check_option(r, tok)) { \ + if (nvmf_check_option(ctx, tok)) { \ ret = __add_int_argument(argstr, \ stringify(tok), \ arg, \ allow_zero); \ } else { \ - nvme_msg(r, LOG_DEBUG, \ + nvme_msg(ctx, LOG_DEBUG, \ "option \"%s\" ignored\n", \ stringify(tok)); \ ret = 0; \ @@ -429,15 +425,15 @@ static int __nvmf_supported_options(nvme_root_t r); ret; \ }) -#define add_int_or_minus_one_argument(r, argstr, tok, arg) \ +#define add_int_or_minus_one_argument(ctx, argstr, tok, arg) \ ({ \ int ret; \ - if (nvmf_check_option(r, tok)) { \ + if (nvmf_check_option(ctx, tok)) { \ ret = __add_int_or_minus_one_argument(argstr, \ stringify(tok), \ arg); \ } else { \ - nvme_msg(r, LOG_DEBUG, \ + nvme_msg(ctx, LOG_DEBUG, \ "option \"%s\" ignored\n", \ stringify(tok)); \ ret = 0; \ @@ -445,15 +441,15 @@ static int __nvmf_supported_options(nvme_root_t r); ret; \ }) -#define add_argument(r, argstr, tok, arg) \ +#define add_argument(ctx, argstr, tok, arg) \ ({ \ int ret; \ - if (nvmf_check_option(r, tok)) { \ + if (nvmf_check_option(ctx, tok)) { \ ret = __add_argument(argstr, \ stringify(tok), \ arg); \ } else { \ - nvme_msg(r, LOG_NOTICE, \ + nvme_msg(ctx, LOG_NOTICE, \ "option \"%s\" ignored\n", \ stringify(tok)); \ ret = 0; \ @@ -478,7 +474,7 @@ static int inet4_pton(const char *src, uint16_t port, return 0; } -static int inet6_pton(nvme_root_t r, const char *src, uint16_t port, +static int inet6_pton(struct nvme_global_ctx *ctx, const char *src, uint16_t port, struct sockaddr_storage *addr) { struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; @@ -490,7 +486,7 @@ static int inet6_pton(nvme_root_t r, const char *src, uint16_t port, _cleanup_free_ char *tmp = strdup(src); if (!tmp) { - nvme_msg(r, LOG_ERR, "cannot copy: %s\n", src); + nvme_msg(ctx, LOG_ERR, "cannot copy: %s\n", src); return -ENOMEM; } @@ -506,7 +502,7 @@ static int inet6_pton(nvme_root_t r, const char *src, uint16_t port, if (IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr) && scope) { addr6->sin6_scope_id = if_nametoindex(scope); if (addr6->sin6_scope_id == 0) { - nvme_msg(r, LOG_ERR, + nvme_msg(ctx, LOG_ERR, "can't find iface index for: %s (%m)\n", scope); return -EINVAL; } @@ -527,7 +523,7 @@ static int inet6_pton(nvme_root_t r, const char *src, uint16_t port, * * Return 0 on success, errno otherwise. */ -static int inet_pton_with_scope(nvme_root_t r, int af, +static int inet_pton_with_scope(struct nvme_global_ctx *ctx, int af, const char *src, const char * trsvcid, struct sockaddr_storage *addr) { @@ -538,7 +534,7 @@ static int inet_pton_with_scope(nvme_root_t r, int af, unsigned long long tmp = strtoull(trsvcid, NULL, 0); port = (uint16_t)tmp; if (tmp != port) { - nvme_msg(r, LOG_ERR, "trsvcid out of range: %s\n", + nvme_msg(ctx, LOG_ERR, "trsvcid out of range: %s\n", trsvcid); return -ERANGE; } @@ -551,21 +547,21 @@ static int inet_pton_with_scope(nvme_root_t r, int af, ret = inet4_pton(src, port, addr); break; case AF_INET6: - ret = inet6_pton(r, src, port, addr); + ret = inet6_pton(ctx, src, port, addr); break; case AF_UNSPEC: ret = inet4_pton(src, port, addr); if (ret) - ret = inet6_pton(r, src, port, addr); + ret = inet6_pton(ctx, src, port, addr); break; default: - nvme_msg(r, LOG_ERR, "unexpected address family %d\n", af); + nvme_msg(ctx, LOG_ERR, "unexpected address family %d\n", af); } return ret; } -static bool traddr_is_hostname(nvme_root_t r, nvme_ctrl_t c) +static bool traddr_is_hostname(struct nvme_global_ctx *ctx, nvme_ctrl_t c) { struct sockaddr_storage addr; @@ -573,7 +569,7 @@ static bool traddr_is_hostname(nvme_root_t r, nvme_ctrl_t c) return false; if (strcmp(c->transport, "tcp") && strcmp(c->transport, "rdma")) return false; - if (inet_pton_with_scope(r, AF_UNSPEC, c->traddr, c->trsvcid, &addr) == 0) + if (inet_pton_with_scope(ctx, AF_UNSPEC, c->traddr, c->trsvcid, &addr) == 0) return false; return true; } @@ -584,30 +580,27 @@ static int build_options(nvme_host_t h, nvme_ctrl_t c, char **argstr) const char *transport = nvme_ctrl_get_transport(c); const char *hostnqn, *hostid, *hostkey, *ctrlkey; bool discover = false, discovery_nqn = false; - nvme_root_t r = h->r; + struct nvme_global_ctx *ctx = h->ctx; long keyring_id = 0; long key_id = 0; int ret; if (!transport) { - nvme_msg(h->r, LOG_ERR, "need a transport (-t) argument\n"); - errno = ENVME_CONNECT_TARG; - return -1; + nvme_msg(ctx, LOG_ERR, "need a transport (-t) argument\n"); + return -ENVME_CONNECT_TARG; } if (strncmp(transport, "loop", 4)) { if (!nvme_ctrl_get_traddr(c)) { - nvme_msg(h->r, LOG_ERR, "need a address (-a) argument\n"); - errno = ENVME_CONNECT_AARG; - return -1; + nvme_msg(h->ctx, LOG_ERR, "need a address (-a) argument\n"); + return -ENVME_CONNECT_AARG; } } /* always specify nqn as first arg - this will init the string */ if (asprintf(argstr, "nqn=%s", nvme_ctrl_get_subsysnqn(c)) < 0) { - errno = ENOMEM; - return -1; + return -ENOMEM; } if (!strcmp(nvme_ctrl_get_subsysnqn(c), NVME_DISC_SUBSYS_NAME)) { @@ -629,10 +622,8 @@ static int build_options(nvme_host_t h, nvme_ctrl_t c, char **argstr) if (cfg->tls) { ret = __nvme_import_keys_from_config(h, c, &keyring_id, &key_id); - if (ret) { - errno = -ret; - return -1; - } + if (ret) + return ret; if (key_id == 0) { if (cfg->tls_configured_key) @@ -642,62 +633,62 @@ static int build_options(nvme_host_t h, nvme_ctrl_t c, char **argstr) } } - if (add_argument(r, argstr, transport, transport) || - add_argument(r, argstr, traddr, + if (add_argument(ctx, argstr, transport, transport) || + add_argument(ctx, argstr, traddr, nvme_ctrl_get_traddr(c)) || - add_argument(r, argstr, host_traddr, + add_argument(ctx, argstr, host_traddr, cfg->host_traddr) || - add_argument(r, argstr, host_iface, + add_argument(ctx, argstr, host_iface, cfg->host_iface) || - add_argument(r, argstr, trsvcid, + add_argument(ctx, argstr, trsvcid, nvme_ctrl_get_trsvcid(c)) || - (hostnqn && add_argument(r, argstr, hostnqn, hostnqn)) || - (hostid && add_argument(r, argstr, hostid, hostid)) || + (hostnqn && add_argument(ctx, argstr, hostnqn, hostnqn)) || + (hostid && add_argument(ctx, argstr, hostid, hostid)) || (discover && !discovery_nqn && - add_bool_argument(r, argstr, discovery, true)) || + add_bool_argument(ctx, argstr, discovery, true)) || (!discover && hostkey && - add_argument(r, argstr, dhchap_secret, hostkey)) || + add_argument(ctx, argstr, dhchap_secret, hostkey)) || (!discover && ctrlkey && - add_argument(r, argstr, dhchap_ctrl_secret, ctrlkey)) || + add_argument(ctx, argstr, dhchap_ctrl_secret, ctrlkey)) || (!discover && - add_int_argument(r, argstr, nr_io_queues, + add_int_argument(ctx, argstr, nr_io_queues, cfg->nr_io_queues, false)) || (!discover && - add_int_argument(r, argstr, nr_write_queues, + add_int_argument(ctx, argstr, nr_write_queues, cfg->nr_write_queues, false)) || (!discover && - add_int_argument(r, argstr, nr_poll_queues, + add_int_argument(ctx, argstr, nr_poll_queues, cfg->nr_poll_queues, false)) || (!discover && - add_int_argument(r, argstr, queue_size, + add_int_argument(ctx, argstr, queue_size, cfg->queue_size, false)) || - add_int_argument(r, argstr, keep_alive_tmo, + add_int_argument(ctx, argstr, keep_alive_tmo, cfg->keep_alive_tmo, false) || - add_int_argument(r, argstr, reconnect_delay, + add_int_argument(ctx, argstr, reconnect_delay, cfg->reconnect_delay, false) || (strcmp(transport, "loop") && - add_int_or_minus_one_argument(r, argstr, ctrl_loss_tmo, + add_int_or_minus_one_argument(ctx, argstr, ctrl_loss_tmo, cfg->ctrl_loss_tmo)) || (strcmp(transport, "loop") && - add_int_argument(r, argstr, fast_io_fail_tmo, + add_int_argument(ctx, argstr, fast_io_fail_tmo, cfg->fast_io_fail_tmo, false)) || (strcmp(transport, "loop") && - add_int_argument(r, argstr, tos, cfg->tos, true)) || - add_hex_argument(r, argstr, keyring, keyring_id, false) || + add_int_argument(ctx, argstr, tos, cfg->tos, true)) || + add_hex_argument(ctx, argstr, keyring, keyring_id, false) || (!strcmp(transport, "tcp") && - add_hex_argument(r, argstr, tls_key, key_id, false)) || - add_bool_argument(r, argstr, duplicate_connect, + add_hex_argument(ctx, argstr, tls_key, key_id, false)) || + add_bool_argument(ctx, argstr, duplicate_connect, cfg->duplicate_connect) || - add_bool_argument(r, argstr, disable_sqflow, + add_bool_argument(ctx, argstr, disable_sqflow, cfg->disable_sqflow) || (!strcmp(transport, "tcp") && - add_bool_argument(r, argstr, hdr_digest, cfg->hdr_digest)) || + add_bool_argument(ctx, argstr, hdr_digest, cfg->hdr_digest)) || (!strcmp(transport, "tcp") && - add_bool_argument(r, argstr, data_digest, cfg->data_digest)) || + add_bool_argument(ctx, argstr, data_digest, cfg->data_digest)) || (!strcmp(transport, "tcp") && - add_bool_argument(r, argstr, tls, cfg->tls)) || + add_bool_argument(ctx, argstr, tls, cfg->tls)) || (!strcmp(transport, "tcp") && - add_bool_argument(r, argstr, concat, cfg->concat))) { + add_bool_argument(ctx, argstr, concat, cfg->concat))) { free(*argstr); return -1; } @@ -705,28 +696,28 @@ static int build_options(nvme_host_t h, nvme_ctrl_t c, char **argstr) return 0; } -#define parse_option(r, v, name) \ - if (!strcmp(v, stringify(name))) { \ - r->options->name = true; \ - continue; \ +#define parse_option(ctx, v, name) \ + if (!strcmp(v, stringify(name))) { \ + ctx->options->name = true; \ + continue; \ } -static int __nvmf_supported_options(nvme_root_t r) +static int __nvmf_supported_options(struct nvme_global_ctx *ctx) { char buf[0x1000], *options, *p, *v; _cleanup_fd_ int fd = -1; ssize_t len; - if (r->options) + if (ctx->options) return 0; - r->options = calloc(1, sizeof(*r->options)); - if (!r->options) + ctx->options = calloc(1, sizeof(*ctx->options)); + if (!ctx->options) return -ENOMEM; fd = open(nvmf_dev, O_RDONLY); if (fd < 0) { - nvme_msg(r, LOG_ERR, "Failed to open %s: %s\n", + nvme_msg(ctx, LOG_ERR, "Failed to open %s: %s\n", nvmf_dev, strerror(errno)); return -ENVME_CONNECT_OPEN; } @@ -739,14 +730,14 @@ static int __nvmf_supported_options(nvme_root_t r) * Older Linux kernels don't allow reading from nvmf_dev * to get supported options, so use a default set */ - nvme_msg(r, LOG_DEBUG, + nvme_msg(ctx, LOG_DEBUG, "Cannot read %s, using default options\n", nvmf_dev); - *r->options = default_supported_options; + *ctx->options = default_supported_options; return 0; } - nvme_msg(r, LOG_ERR, "Failed to read from %s: %s\n", + nvme_msg(ctx, LOG_ERR, "Failed to read from %s: %s\n", nvmf_dev, strerror(errno)); return -ENVME_CONNECT_READ; } @@ -754,7 +745,7 @@ static int __nvmf_supported_options(nvme_root_t r) buf[len] = '\0'; options = buf; - nvme_msg(r, LOG_DEBUG, "kernel supports: "); + nvme_msg(ctx, LOG_DEBUG, "kernel supports: "); while ((p = strsep(&options, ",\n")) != NULL) { if (!*p) @@ -762,44 +753,44 @@ static int __nvmf_supported_options(nvme_root_t r) v = strsep(&p, "= "); if (!v) continue; - nvme_msg(r, LOG_DEBUG, "%s ", v); - - parse_option(r, v, cntlid); - parse_option(r, v, concat); - parse_option(r, v, ctrl_loss_tmo); - parse_option(r, v, data_digest); - parse_option(r, v, dhchap_ctrl_secret); - parse_option(r, v, dhchap_secret); - parse_option(r, v, disable_sqflow); - parse_option(r, v, discovery); - parse_option(r, v, duplicate_connect); - parse_option(r, v, fast_io_fail_tmo); - parse_option(r, v, hdr_digest); - parse_option(r, v, host_iface); - parse_option(r, v, host_traddr); - parse_option(r, v, hostid); - parse_option(r, v, hostnqn); - parse_option(r, v, instance); - parse_option(r, v, keep_alive_tmo); - parse_option(r, v, keyring); - parse_option(r, v, nqn); - parse_option(r, v, nr_io_queues); - parse_option(r, v, nr_poll_queues); - parse_option(r, v, nr_write_queues); - parse_option(r, v, queue_size); - parse_option(r, v, reconnect_delay); - parse_option(r, v, tls); - parse_option(r, v, tls_key); - parse_option(r, v, tos); - parse_option(r, v, traddr); - parse_option(r, v, transport); - parse_option(r, v, trsvcid); + nvme_msg(ctx, LOG_DEBUG, "%s ", v); + + parse_option(ctx, v, cntlid); + parse_option(ctx, v, concat); + parse_option(ctx, v, ctrl_loss_tmo); + parse_option(ctx, v, data_digest); + parse_option(ctx, v, dhchap_ctrl_secret); + parse_option(ctx, v, dhchap_secret); + parse_option(ctx, v, disable_sqflow); + parse_option(ctx, v, discovery); + parse_option(ctx, v, duplicate_connect); + parse_option(ctx, v, fast_io_fail_tmo); + parse_option(ctx, v, hdr_digest); + parse_option(ctx, v, host_iface); + parse_option(ctx, v, host_traddr); + parse_option(ctx, v, hostid); + parse_option(ctx, v, hostnqn); + parse_option(ctx, v, instance); + parse_option(ctx, v, keep_alive_tmo); + parse_option(ctx, v, keyring); + parse_option(ctx, v, nqn); + parse_option(ctx, v, nr_io_queues); + parse_option(ctx, v, nr_poll_queues); + parse_option(ctx, v, nr_write_queues); + parse_option(ctx, v, queue_size); + parse_option(ctx, v, reconnect_delay); + parse_option(ctx, v, tls); + parse_option(ctx, v, tls_key); + parse_option(ctx, v, tos); + parse_option(ctx, v, traddr); + parse_option(ctx, v, transport); + parse_option(ctx, v, trsvcid); } - nvme_msg(r, LOG_DEBUG, "\n"); + nvme_msg(ctx, LOG_DEBUG, "\n"); return 0; } -static int __nvmf_add_ctrl(nvme_root_t r, const char *argstr) +static int __nvmf_add_ctrl(struct nvme_global_ctx *ctx, const char *argstr) { _cleanup_fd_ int fd = -1; int ret, len = strlen(argstr); @@ -807,16 +798,16 @@ static int __nvmf_add_ctrl(nvme_root_t r, const char *argstr) fd = open(nvmf_dev, O_RDWR); if (fd < 0) { - nvme_msg(r, LOG_ERR, "Failed to open %s: %s\n", + nvme_msg(ctx, LOG_ERR, "Failed to open %s: %s\n", nvmf_dev, strerror(errno)); return -ENVME_CONNECT_OPEN; } - nvme_msg(r, LOG_DEBUG, "connect ctrl, '%.*s'\n", + nvme_msg(ctx, LOG_DEBUG, "connect ctrl, '%.*s'\n", (int)strcspn(argstr,"\n"), argstr); ret = write(fd, argstr, len); if (ret != len) { - nvme_msg(r, LOG_INFO, "Failed to write to %s: %s\n", + nvme_msg(ctx, LOG_INFO, "Failed to write to %s: %s\n", nvmf_dev, strerror(errno)); switch (errno) { case EALREADY: @@ -843,11 +834,11 @@ static int __nvmf_add_ctrl(nvme_root_t r, const char *argstr) memset(buf, 0x0, sizeof(buf)); len = read(fd, buf, sizeof(buf) - 1); if (len < 0) { - nvme_msg(r, LOG_ERR, "Failed to read from %s: %s\n", + nvme_msg(ctx, LOG_ERR, "Failed to read from %s: %s\n", nvmf_dev, strerror(errno)); return -ENVME_CONNECT_READ; } - nvme_msg(r, LOG_DEBUG, "connect ctrl, response '%.*s'\n", + nvme_msg(ctx, LOG_DEBUG, "connect ctrl, response '%.*s'\n", (int)strcspn(buf, "\n"), buf); buf[len] = '\0'; options = buf; @@ -858,17 +849,17 @@ static int __nvmf_add_ctrl(nvme_root_t r, const char *argstr) return ret; } - nvme_msg(r, LOG_ERR, "Failed to parse ctrl info for \"%s\"\n", argstr); + nvme_msg(ctx, LOG_ERR, "Failed to parse ctrl info for \"%s\"\n", argstr); return -ENVME_CONNECT_PARSE; } -static const char *lookup_context(nvme_root_t r, nvme_ctrl_t c) +static const char *lookup_context(struct nvme_global_ctx *ctx, nvme_ctrl_t c) { nvme_host_t h; nvme_subsystem_t s; - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { if (__nvme_lookup_ctrl(s, nvme_ctrl_get_transport(c), nvme_ctrl_get_traddr(c), @@ -935,11 +926,11 @@ int nvmf_add_ctrl(nvme_host_t h, nvme_ctrl_t c, } - root_app = nvme_root_get_application(h->r); + root_app = nvme_get_application(h->ctx); if (root_app) { app = nvme_subsystem_get_application(s); if (!app && nvme_ctrl_is_discovery_ctrl(c)) - app = lookup_context(h->r, c); + app = lookup_context(h->ctx, c); /* * configuration is managed by an application, @@ -948,22 +939,19 @@ int nvmf_add_ctrl(nvme_host_t h, nvme_ctrl_t c, * application string. */ if (app && strcmp(app, root_app)) { - nvme_msg(h->r, LOG_INFO, "skip %s, not managed by %s\n", + nvme_msg(h->ctx, LOG_INFO, "skip %s, not managed by %s\n", nvme_subsystem_get_nqn(s), root_app); - errno = ENVME_CONNECT_IGNORED; - return -1; + return -ENVME_CONNECT_IGNORED; } } nvme_ctrl_set_discovered(c, true); - if (traddr_is_hostname(h->r, c)) { + if (traddr_is_hostname(h->ctx, c)) { char *traddr = c->traddr; - c->traddr = hostname2traddr(h->r, traddr); - if (!c->traddr) { + if (hostname2traddr(h->ctx, traddr, &c->traddr)) { c->traddr = traddr; - errno = ENVME_CONNECT_TRADDR; - return -1; + return -ENVME_CONNECT_TRADDR; } free(traddr); } @@ -972,13 +960,11 @@ int nvmf_add_ctrl(nvme_host_t h, nvme_ctrl_t c, if (ret) return ret; - ret = __nvmf_add_ctrl(h->r, argstr); - if (ret < 0) { - errno = -ret; - return -1; - } + ret = __nvmf_add_ctrl(h->ctx, argstr); + if (ret < 0) + return ret; - nvme_msg(h->r, LOG_INFO, "nvme%d: %s connected\n", ret, + nvme_msg(h->ctx, LOG_INFO, "nvme%d: %s connected\n", ret, nvme_ctrl_get_subsysnqn(c)); return nvme_init_ctrl(h, c, ret); } @@ -992,19 +978,18 @@ int nvmf_connect_ctrl(nvme_ctrl_t c) if (ret) return ret; - ret = __nvmf_add_ctrl(c->s->h->r, argstr); - if (ret < 0) { - errno = -ret; - return -1; - } + ret = __nvmf_add_ctrl(c->s->h->ctx, argstr); + if (ret < 0) + return ret; return 0; } -nvme_ctrl_t nvmf_connect_disc_entry(nvme_host_t h, - struct nvmf_disc_log_entry *e, - const struct nvme_fabrics_config *cfg, - bool *discover) +int nvmf_connect_disc_entry(nvme_host_t h, + struct nvmf_disc_log_entry *e, + const struct nvme_fabrics_config *cfg, + bool *discover, + nvme_ctrl_t *cp) { const char *transport; char *traddr = NULL, *trsvcid = NULL; @@ -1021,11 +1006,10 @@ nvme_ctrl_t nvmf_connect_disc_entry(nvme_host_t h, trsvcid = e->trsvcid; break; default: - nvme_msg(h->r, LOG_ERR, + nvme_msg(h->ctx, LOG_ERR, "skipping unsupported adrfam %d\n", e->adrfam); - errno = EINVAL; - return NULL; + return -EINVAL; } break; case NVMF_TRTYPE_FC: @@ -1034,36 +1018,34 @@ nvme_ctrl_t nvmf_connect_disc_entry(nvme_host_t h, traddr = e->traddr; break; default: - nvme_msg(h->r, LOG_ERR, + nvme_msg(h->ctx, LOG_ERR, "skipping unsupported adrfam %d\n", e->adrfam); - errno = EINVAL; - return NULL; + return -EINVAL; } break; case NVMF_TRTYPE_LOOP: traddr = strlen(e->traddr) ? e->traddr : NULL; break; default: - nvme_msg(h->r, LOG_ERR, "skipping unsupported transport %d\n", + nvme_msg(h->ctx, LOG_ERR, "skipping unsupported transport %d\n", e->trtype); - errno = EINVAL; - return NULL; + return -EINVAL; } transport = nvmf_trtype_str(e->trtype); - nvme_msg(h->r, LOG_DEBUG, "lookup ctrl " + nvme_msg(h->ctx, LOG_DEBUG, "lookup ctrl " "(transport: %s, traddr: %s, trsvcid %s)\n", transport, traddr, trsvcid); - c = nvme_create_ctrl(h->r, e->subnqn, transport, traddr, - cfg->host_traddr, cfg->host_iface, trsvcid); - if (!c) { - nvme_msg(h->r, LOG_DEBUG, "skipping discovery entry, " + + ret = nvme_create_ctrl(h->ctx, e->subnqn, transport, traddr, + cfg->host_traddr, cfg->host_iface, trsvcid, &c); + if (!ret) { + nvme_msg(h->ctx, LOG_DEBUG, "skipping discovery entry, " "failed to allocate %s controller with traddr %s\n", transport, traddr); - errno = ENOMEM; - return NULL; + return ret; } switch (e->subtype) { @@ -1080,7 +1062,7 @@ nvme_ctrl_t nvmf_connect_disc_entry(nvme_host_t h, strcmp(e->subnqn, NVME_DISC_SUBSYS_NAME)); break; default: - nvme_msg(h->r, LOG_ERR, "unsupported subtype %d\n", + nvme_msg(h->ctx, LOG_ERR, "unsupported subtype %d\n", e->subtype); fallthrough; case NVME_NQN_NVME: @@ -1091,12 +1073,11 @@ nvme_ctrl_t nvmf_connect_disc_entry(nvme_host_t h, if (nvme_ctrl_is_discovered(c)) { nvme_free_ctrl(c); - errno = EAGAIN; - return NULL; + return -EAGAIN; } if (e->treq & NVMF_TREQ_DISABLE_SQFLOW && - nvmf_check_option(h->r, disable_sqflow)) + nvmf_check_option(h->ctx, disable_sqflow)) c->cfg.disable_sqflow = true; if (e->trtype == NVMF_TRTYPE_TCP && @@ -1104,21 +1085,24 @@ nvme_ctrl_t nvmf_connect_disc_entry(nvme_host_t h, c->cfg.tls = true; ret = nvmf_add_ctrl(h, c, cfg); - if (!ret) - return c; + if (!ret) { + *cp = c; + return 0; + } - if (errno == EINVAL && c->cfg.disable_sqflow) { - errno = 0; + if (ret == EINVAL && c->cfg.disable_sqflow) { /* disable_sqflow is unrecognized option on older kernels */ - nvme_msg(h->r, LOG_INFO, "failed to connect controller, " + nvme_msg(h->ctx, LOG_INFO, "failed to connect controller, " "retry with disabling SQ flow control\n"); c->cfg.disable_sqflow = false; ret = nvmf_add_ctrl(h, c, cfg); - if (!ret) - return c; + if (!ret) { + *cp = c; + return 0; + } } nvme_free_ctrl(c); - return NULL; + return -ENOENT; } /* @@ -1128,43 +1112,31 @@ nvme_ctrl_t nvmf_connect_disc_entry(nvme_host_t h, */ #define DISCOVERY_HEADER_LEN 20 -static struct nvmf_discovery_log *nvme_discovery_log( - const struct nvme_get_discovery_args *args) +static int nvme_discovery_log(const struct nvme_get_discovery_args *args, + struct nvmf_discovery_log **logp) { - nvme_root_t r = root_from_ctrl(args->c); + struct nvme_global_ctx *ctx = ctx_from_ctrl(args->c); struct nvmf_discovery_log *log; int retries = 0; int err; const char *name = nvme_ctrl_get_name(args->c); uint64_t genctr, numrec; - int fd = nvme_ctrl_get_fd(args->c); - struct nvme_get_log_args log_args = { - .result = args->result, - .args_size = sizeof(log_args), - .timeout = args->timeout, - .lid = NVME_LOG_LID_DISCOVER, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = args->lsp, - .uuidx = NVME_UUID_NONE, - }; + struct nvme_transport_handle *hdl = nvme_ctrl_get_transport_handle(args->c); + struct nvme_passthru_cmd cmd; log = __nvme_alloc(sizeof(*log)); if (!log) { - nvme_msg(r, LOG_ERR, + nvme_msg(ctx, LOG_ERR, "could not allocate memory for discovery log header\n"); - errno = ENOMEM; - return NULL; + return -ENOMEM; } - nvme_msg(r, LOG_DEBUG, "%s: get header (try %d/%d)\n", + nvme_msg(ctx, LOG_DEBUG, "%s: get header (try %d/%d)\n", name, retries, args->max_retries); - log_args.log = log; - log_args.len = DISCOVERY_HEADER_LEN; - err = nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &log_args); + nvme_init_get_log_discovery(&cmd, 0, log, DISCOVERY_HEADER_LEN); + err = nvme_get_log(hdl, &cmd, false, DISCOVERY_HEADER_LEN, NULL); if (err) { - nvme_msg(r, LOG_INFO, + nvme_msg(ctx, LOG_INFO, "%s: discover try %d/%d failed, errno %d status 0x%x\n", name, retries, args->max_retries, errno, err); goto out_free_log; @@ -1183,22 +1155,23 @@ static struct nvmf_discovery_log *nvme_discovery_log( entries_size = sizeof(*log->entries) * numrec; log = __nvme_alloc(sizeof(*log) + entries_size); if (!log) { - nvme_msg(r, LOG_ERR, + nvme_msg(ctx, LOG_ERR, "could not alloc memory for discovery log page\n"); - errno = ENOMEM; - return NULL; + return -ENOMEM; } - nvme_msg(r, LOG_DEBUG, + nvme_msg(ctx, LOG_DEBUG, "%s: get %" PRIu64 " records (genctr %" PRIu64 ")\n", name, numrec, genctr); - log_args.lpo = sizeof(*log); - log_args.log = log->entries; - log_args.len = entries_size; - err = nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &log_args); + nvme_init_get_log_discovery(&cmd, sizeof(*log), log->entries, entries_size); + cmd.cdw10 |= NVME_FIELD_ENCODE(args->lsp, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + err = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (err) { - nvme_msg(r, LOG_INFO, + nvme_msg(ctx, LOG_INFO, "%s: discover try %d/%d failed, errno %d status 0x%x\n", name, retries, args->max_retries, errno, err); goto out_free_log; @@ -1208,14 +1181,12 @@ static struct nvmf_discovery_log *nvme_discovery_log( * If the log page was read with multiple Get Log Page commands, * genctr must be checked afterwards to ensure atomicity */ - nvme_msg(r, LOG_DEBUG, "%s: get header again\n", name); + nvme_msg(ctx, LOG_DEBUG, "%s: get header again\n", name); - log_args.lpo = 0; - log_args.log = log; - log_args.len = DISCOVERY_HEADER_LEN; - err = nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &log_args); + nvme_init_get_log_discovery(&cmd, 0, log, DISCOVERY_HEADER_LEN); + err = nvme_get_log(hdl, &cmd, false, DISCOVERY_HEADER_LEN, NULL); if (err) { - nvme_msg(r, LOG_INFO, + nvme_msg(ctx, LOG_INFO, "%s: discover try %d/%d failed, errno %d status 0x%x\n", name, retries, args->max_retries, errno, err); goto out_free_log; @@ -1224,23 +1195,22 @@ static struct nvmf_discovery_log *nvme_discovery_log( ++retries < args->max_retries); if (genctr != le64_to_cpu(log->genctr)) { - nvme_msg(r, LOG_INFO, "%s: discover genctr mismatch\n", name); - errno = EAGAIN; + nvme_msg(ctx, LOG_INFO, "%s: discover genctr mismatch\n", name); + err = -EAGAIN; } else if (numrec != le64_to_cpu(log->numrec)) { - nvme_msg(r, LOG_INFO, + nvme_msg(ctx, LOG_INFO, "%s: numrec changed unexpectedly " "from %" PRIu64 " to %" PRIu64 "\n", name, numrec, le64_to_cpu(log->numrec)); - errno = EBADSLT; + err = -EBADSLT; } else { - return log; + *logp = log; + return 0; } out_free_log: free(log); - if (!errno) - errno = nvme_status_to_errno(err, true); - return NULL; + return err; } static void sanitize_discovery_log_entry(struct nvmf_disc_log_entry *e) @@ -1259,22 +1229,25 @@ int nvmf_get_discovery_log(nvme_ctrl_t c, struct nvmf_discovery_log **logp, .lsp = NVMF_LOG_DISC_LSP_NONE, }; - *logp = nvmf_get_discovery_wargs(&args); - return *logp ? 0 : -1; + + return nvmf_get_discovery_wargs(&args, logp); } -struct nvmf_discovery_log *nvmf_get_discovery_wargs(struct nvme_get_discovery_args *args) +int nvmf_get_discovery_wargs(struct nvme_get_discovery_args *args, + struct nvmf_discovery_log **logp) { struct nvmf_discovery_log *log; + int err; - log = nvme_discovery_log(args); - if (!log) - return NULL; + err = nvme_discovery_log(args, &log); + if (err) + return err; for (int i = 0; i < le64_to_cpu(log->numrec); i++) sanitize_discovery_log_entry(&log->entries[i]); - return log; + *logp = log; + return 0; } static int uuid_from_device_tree(char *system_uuid) @@ -1621,59 +1594,48 @@ static int nvmf_dim(nvme_ctrl_t c, enum nvmf_dim_tas tas, __u8 trtype, __u8 adrfam, const char *reg_addr, union nvmf_tsas *tsas, __u32 *result) { - nvme_root_t r = c->s && c->s->h ? c->s->h->r : NULL; + struct nvme_global_ctx *ctx = c->s && c->s->h ? c->s->h->ctx : NULL; _cleanup_free_ struct nvmf_dim_data *dim = NULL; + struct nvme_transport_handle *hdl = nvme_ctrl_get_transport_handle(c); + struct nvme_passthru_cmd cmd; struct nvmf_ext_die *die; __u32 tdl; __u32 tel; int ret; - struct nvme_dim_args args = { - .args_size = sizeof(args), - .fd = nvme_ctrl_get_fd(c), - .result = result, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .tas = tas - }; - if (!c->s) { - nvme_msg(r, LOG_ERR, + nvme_msg(ctx, LOG_ERR, "%s: failed to perform DIM. subsystem undefined.\n", c->name); - errno = EINVAL; - return -1; + return -EINVAL; } if (!c->s->h) { - nvme_msg(r, LOG_ERR, + nvme_msg(ctx, LOG_ERR, "%s: failed to perform DIM. host undefined.\n", c->name); - errno = EINVAL; - return -1; + return -EINVAL; } if (!c->s->h->hostid) { - nvme_msg(r, LOG_ERR, + nvme_msg(ctx, LOG_ERR, "%s: failed to perform DIM. hostid undefined.\n", c->name); - errno = EINVAL; - return -1; + return -EINVAL; } if (!c->s->h->hostnqn) { - nvme_msg(r, LOG_ERR, + nvme_msg(ctx, LOG_ERR, "%s: failed to perform DIM. hostnqn undefined.\n", c->name); - errno = EINVAL; - return -1; + return -EINVAL; } if (strcmp(c->transport, "tcp")) { - nvme_msg(r, LOG_ERR, + nvme_msg(ctx, LOG_ERR, "%s: DIM only supported for TCP connections.\n", c->name); - errno = EINVAL; - return -1; + return -EINVAL; } /* Register one Discovery Information Entry (DIE) of size TEL */ @@ -1682,8 +1644,7 @@ static int nvmf_dim(nvme_ctrl_t c, enum nvmf_dim_tas tas, __u8 trtype, dim = (struct nvmf_dim_data *)calloc(1, tdl); if (!dim) { - errno = ENOMEM; - return -1; + return -ENOMEM; } dim->tdl = cpu_to_le32(tdl); @@ -1697,19 +1658,18 @@ static int nvmf_dim(nvme_ctrl_t c, enum nvmf_dim_tas tas, __u8 trtype, ret = get_entity_name(dim->ename, sizeof(dim->ename)); if (ret <= 0) - nvme_msg(r, LOG_INFO, "%s: Failed to retrieve ENAME. %s.\n", - c->name, strerror(errno)); + nvme_msg(ctx, LOG_INFO, "%s: Failed to retrieve ENAME. %s.\n", + c->name, strerror(ret)); ret = get_entity_version(dim->ever, sizeof(dim->ever)); if (ret <= 0) - nvme_msg(r, LOG_INFO, "%s: Failed to retrieve EVER.\n", c->name); + nvme_msg(ctx, LOG_INFO, "%s: Failed to retrieve EVER.\n", c->name); die = &dim->die->extended; nvmf_fill_die(die, c->s->h, tel, trtype, adrfam, reg_addr, tsas); - args.data_len = tdl; - args.data = dim; - return nvme_dim_send(&args); + nvme_init_dim_send(&cmd, tas, dim, tdl); + return nvme_submit_admin_passthru(hdl, &cmd, NULL); } /** @@ -1720,7 +1680,7 @@ static int nvmf_dim(nvme_ctrl_t c, enum nvmf_dim_tas tas, __u8 trtype, * address from the socket, then we'll infer the address family from the * address of the DC since the DC address has the same address family. * - * @ctrl: Host NVMe controller instance maintaining the admin queue used to + * @c: Host NVMe controller instance maintaining the admin queue used to * submit the DIM command to the DC. * * Return: The address family of the source address associated with the @@ -1730,9 +1690,9 @@ static __u8 nvme_get_adrfam(nvme_ctrl_t c) { struct sockaddr_storage addr; __u8 adrfam = NVMF_ADDR_FAMILY_IP4; - nvme_root_t r = c->s && c->s->h ? c->s->h->r : NULL; + struct nvme_global_ctx *ctx = c->s && c->s->h ? c->s->h->ctx : NULL; - if (!inet_pton_with_scope(r, AF_UNSPEC, c->traddr, c->trsvcid, &addr)) { + if (!inet_pton_with_scope(ctx, AF_UNSPEC, c->traddr, c->trsvcid, &addr)) { if (addr.ss_family == AF_INET6) adrfam = NVMF_ADDR_FAMILY_IP6; } @@ -1767,10 +1727,8 @@ static int nvme_fetch_cntrltype_dctype_from_id(nvme_ctrl_t c) int ret; id = __nvme_alloc(sizeof(*id)); - if (!id) { - errno = ENOMEM; - return -1; - } + if (!id) + return -ENOMEM; ret = nvme_ctrl_identify(c, id); if (ret) @@ -1803,10 +1761,8 @@ bool nvmf_is_registration_supported(nvme_ctrl_t c) int nvmf_register_ctrl(nvme_ctrl_t c, enum nvmf_dim_tas tas, __u32 *result) { - if (!nvmf_is_registration_supported(c)) { - errno = ENOTSUP; - return -1; - } + if (!nvmf_is_registration_supported(c)) + return -ENOTSUP; /* We're registering our source address with the DC. To do * that, we can simply send an empty string. This tells the DC @@ -1844,7 +1800,7 @@ static char *unescape_uri(const char *str, int len) return dst; } -struct nvme_fabrics_uri *nvme_parse_uri(const char *str) +int nvme_parse_uri(const char *str, struct nvme_fabrics_uri **urip) { struct nvme_fabrics_uri *uri; _cleanup_free_ char *scheme = NULL; @@ -1869,20 +1825,18 @@ struct nvme_fabrics_uri *nvme_parse_uri(const char *str) uri = calloc(1, sizeof(struct nvme_fabrics_uri)); if (!uri) - return NULL; + return -ENOMEM; if (sscanf(str, "%m[^:/]://%m[^/?#]%ms", &scheme, &authority, &path) < 2) { nvme_free_uri(uri); - errno = EINVAL; - return NULL; + return -EINVAL; } if (sscanf(scheme, "%m[^+]+%ms", &uri->scheme, &uri->protocol) < 1) { nvme_free_uri(uri); - errno = EINVAL; - return NULL; + return -EINVAL; } /* split userinfo */ @@ -1900,8 +1854,7 @@ struct nvme_fabrics_uri *nvme_parse_uri(const char *str) if (sscanf(host, "%m[^:]:%d", &h, &uri->port) < 1) { nvme_free_uri(uri); - errno = EINVAL; - return NULL; + return -EINVAL; } uri->host = unescape_uri(h, 0); } @@ -1940,7 +1893,8 @@ struct nvme_fabrics_uri *nvme_parse_uri(const char *str) } } - return uri; + *urip = uri; + return 0; } void nvme_free_uri(struct nvme_fabrics_uri *uri) diff --git a/libnvme/src/nvme/fabrics.h b/libnvme/src/nvme/fabrics.h index 4c84bd32fd..01d3db6bda 100644 --- a/libnvme/src/nvme/fabrics.h +++ b/libnvme/src/nvme/fabrics.h @@ -219,7 +219,7 @@ void nvmf_update_config(nvme_ctrl_t c, const struct nvme_fabrics_config *cfg); * into the topology using @h as parent. * @c must be initialized and not connected to the topology. * - * Return: 0 on success; on failure errno is set and -1 is returned. + * Return: 0 on success, or an error code on failure. */ int nvmf_add_ctrl(nvme_host_t h, nvme_ctrl_t c, const struct nvme_fabrics_config *cfg); @@ -231,14 +231,14 @@ int nvmf_add_ctrl(nvme_host_t h, nvme_ctrl_t c, * Issues a 'connect' command to the NVMe-oF controller. * @c must be initialized and not connected to the topology. * - * Return: 0 on success; on failure errno is set and -1 is returned. + * Return: 0 on success, or an error code on failure. */ int nvmf_connect_ctrl(nvme_ctrl_t c); /** * nvmf_get_discovery_log() - Return the discovery log page * @c: Discovery controller to use - * @logp: Pointer to the log page to be returned + * @logp: Log page object to return * @max_retries: Number of retries in case of failure * * The memory allocated for the log page and returned in @logp @@ -246,7 +246,7 @@ int nvmf_connect_ctrl(nvme_ctrl_t c); * * Note: Consider using nvmf_get_discovery_wargs() instead. * - * Return: 0 on success; on failure -1 is returned and errno is set + * Return: 0 on success, or an error code on failure. */ int nvmf_get_discovery_log(nvme_ctrl_t c, struct nvmf_discovery_log **logp, int max_retries); @@ -272,6 +272,7 @@ struct nvme_get_discovery_args { /** * nvmf_get_discovery_wargs() - Get the discovery log page with args * @args: Argument structure + * @log: Discovery log page object to return * * This function is similar to nvmf_get_discovery_log(), but * takes an extensible @args parameter. @args provides more @@ -281,10 +282,10 @@ struct nvme_get_discovery_args { * and returns the DLP. The memory allocated for the returned * DLP must be freed by the caller using free(). * - * Return: Pointer to the discovery log page (to be freed). NULL - * on failure and errno is set. + * Return: 0 on success, or an error code on failure. */ -struct nvmf_discovery_log *nvmf_get_discovery_wargs(struct nvme_get_discovery_args *args); +int nvmf_get_discovery_wargs(struct nvme_get_discovery_args *args, + struct nvmf_discovery_log **log); /** * nvmf_hostnqn_generate() - Generate a machine specific host nqn @@ -343,12 +344,15 @@ char *nvmf_hostid_from_file(); * @e: Discovery log page entry * @defcfg: Default configuration to be used for the new controller * @discover: Set to 'true' if the new controller is a discovery controller + * @c: crtl object to return * - * Return: Pointer to the new controller + * Return: 0 on success, or an error code on failure. */ -nvme_ctrl_t nvmf_connect_disc_entry(nvme_host_t h, - struct nvmf_disc_log_entry *e, - const struct nvme_fabrics_config *defcfg, bool *discover); +int nvmf_connect_disc_entry(nvme_host_t h, + struct nvmf_disc_log_entry *e, + const struct nvme_fabrics_config *defcfg, + bool *discover, + nvme_ctrl_t *c); /** * nvmf_is_registration_supported - check whether registration can be performed. @@ -376,13 +380,14 @@ bool nvmf_is_registration_supported(nvme_ctrl_t c); * Perform registration task with a Discovery Controller (DC). Three * tasks are supported: register, deregister, and registration update. * - * Return: 0 on success; on failure -1 is returned and errno is set + * Return: 0 on success, or an error code on failure. */ int nvmf_register_ctrl(nvme_ctrl_t c, enum nvmf_dim_tas tas, __u32 *result); /** * nvme_parse_uri() - Parse the URI string * @str: URI string + * @uri: URI object to return * * Parse the URI string as defined in the NVM Express Boot Specification. * Supported URI elements looks as follows: @@ -392,7 +397,7 @@ int nvmf_register_ctrl(nvme_ctrl_t c, enum nvmf_dim_tas tas, __u32 *result); * Return: &nvme_fabrics_uri structure on success; NULL on failure with errno * set. */ -struct nvme_fabrics_uri *nvme_parse_uri(const char *str); +int nvme_parse_uri(const char *str, struct nvme_fabrics_uri **uri); /** * nvme_free_uri() - Free the URI structure diff --git a/libnvme/src/nvme/ioctl.c b/libnvme/src/nvme/ioctl.c index a887ae4835..796c105b02 100644 --- a/libnvme/src/nvme/ioctl.c +++ b/libnvme/src/nvme/ioctl.c @@ -29,83 +29,104 @@ #include "ioctl.h" #include "util.h" #include "log.h" +#include "private.h" -static int nvme_verify_chr(int fd) +static int nvme_verify_chr(struct nvme_transport_handle *hdl) { static struct stat nvme_stat; - int err = fstat(fd, &nvme_stat); + int err = fstat(hdl->fd, &nvme_stat); if (err < 0) - return errno; + return -errno; - if (!S_ISCHR(nvme_stat.st_mode)) { - errno = ENOTBLK; - return -1; - } + if (!S_ISCHR(nvme_stat.st_mode)) + return -ENOTBLK; return 0; } -int nvme_subsystem_reset(int fd) +int nvme_subsystem_reset(struct nvme_transport_handle *hdl) { int ret; - ret = nvme_verify_chr(fd); + ret = nvme_verify_chr(hdl); if (ret) return ret; - return ioctl(fd, NVME_IOCTL_SUBSYS_RESET); + + ret = ioctl(hdl->fd, NVME_IOCTL_SUBSYS_RESET); + if (ret < 0) + return -errno; + return ret; } -int nvme_ctrl_reset(int fd) +int nvme_ctrl_reset(struct nvme_transport_handle *hdl) { int ret; - ret = nvme_verify_chr(fd); + ret = nvme_verify_chr(hdl); if (ret) return ret; - return ioctl(fd, NVME_IOCTL_RESET); + + ret = ioctl(hdl->fd, NVME_IOCTL_RESET); + if (ret < 0) + return -errno; + return ret; } -int nvme_ns_rescan(int fd) +int nvme_ns_rescan(struct nvme_transport_handle *hdl) { int ret; - ret = nvme_verify_chr(fd); + ret = nvme_verify_chr(hdl); if (ret) return ret; - return ioctl(fd, NVME_IOCTL_RESCAN); + + ret = ioctl(hdl->fd, NVME_IOCTL_RESCAN); + if (ret < 0) + return -errno; + return ret; } -int nvme_get_nsid(int fd, __u32 *nsid) +int nvme_get_nsid(struct nvme_transport_handle *hdl, __u32 *nsid) { + __u32 tmp; + errno = 0; - *nsid = ioctl(fd, NVME_IOCTL_ID); - return -1 * (errno != 0); + tmp = ioctl(hdl->fd, NVME_IOCTL_ID); + if (errno) + return -errno; + + *nsid = tmp; + return 0; } __attribute__((weak)) -int nvme_submit_passthru64(int fd, unsigned long ioctl_cmd, +int nvme_submit_passthru64(struct nvme_transport_handle *hdl, unsigned long ioctl_cmd, struct nvme_passthru_cmd64 *cmd, __u64 *result) { - int err = ioctl(fd, ioctl_cmd, cmd); + int err = ioctl(hdl->fd, ioctl_cmd, cmd); if (err >= 0 && result) *result = cmd->result; + if (err < 0) + return -errno; return err; } __attribute__((weak)) -int nvme_submit_passthru(int fd, unsigned long ioctl_cmd, +int nvme_submit_passthru(struct nvme_transport_handle *hdl, unsigned long ioctl_cmd, struct nvme_passthru_cmd *cmd, __u32 *result) { - int err = ioctl(fd, ioctl_cmd, cmd); + int err = ioctl(hdl->fd, ioctl_cmd, cmd); if (err >= 0 && result) *result = cmd->result; + if (err < 0) + return -errno; return err; } -static int nvme_passthru64(int fd, unsigned long ioctl_cmd, __u8 opcode, +static int nvme_passthru64(struct nvme_transport_handle *hdl, 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, @@ -132,10 +153,10 @@ static int nvme_passthru64(int fd, unsigned long ioctl_cmd, __u8 opcode, .timeout_ms = timeout_ms, }; - return nvme_submit_passthru64(fd, ioctl_cmd, &cmd, result); + return nvme_submit_passthru64(hdl, ioctl_cmd, &cmd, result); } -static int nvme_passthru(int fd, unsigned long ioctl_cmd, __u8 opcode, +static int nvme_passthru(struct nvme_transport_handle *hdl, 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, @@ -162,164 +183,62 @@ static int nvme_passthru(int fd, unsigned long ioctl_cmd, __u8 opcode, .timeout_ms = timeout_ms, }; - return nvme_submit_passthru(fd, ioctl_cmd, &cmd, result); + return nvme_submit_passthru(hdl, ioctl_cmd, &cmd, result); } -int nvme_submit_admin_passthru64(int fd, struct nvme_passthru_cmd64 *cmd, +int nvme_submit_admin_passthru64(struct nvme_transport_handle *hdl, struct nvme_passthru_cmd64 *cmd, __u64 *result) { - return nvme_submit_passthru64(fd, NVME_IOCTL_ADMIN64_CMD, cmd, result); + return nvme_submit_passthru64(hdl, NVME_IOCTL_ADMIN64_CMD, cmd, result); } -int nvme_admin_passthru64(int fd, __u8 opcode, __u8 flags, __u16 rsvd, +int nvme_admin_passthru64(struct nvme_transport_handle *hdl, __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, __u64 *result) { - return nvme_passthru64(fd, NVME_IOCTL_ADMIN64_CMD, opcode, flags, rsvd, + return nvme_passthru64(hdl, NVME_IOCTL_ADMIN64_CMD, opcode, flags, rsvd, nsid, cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, cdw14, cdw15, data_len, data, metadata_len, metadata, timeout_ms, result); } -int nvme_submit_admin_passthru(int fd, struct nvme_passthru_cmd *cmd, __u32 *result) -{ - return nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, cmd, result); +int nvme_submit_admin_passthru(struct nvme_transport_handle *hdl, struct nvme_passthru_cmd *cmd, __u32 *result) +{ + switch (hdl->type) { + case NVME_TRANSPORT_HANDLE_TYPE_DIRECT: + return nvme_submit_passthru(hdl, NVME_IOCTL_ADMIN_CMD, cmd, result); + case NVME_TRANSPORT_HANDLE_TYPE_MI: + return nvme_mi_admin_admin_passthru( + hdl, cmd->opcode, cmd->flags, cmd->rsvd1, + cmd->nsid, cmd->cdw2, cmd->cdw3, cmd->cdw10, + cmd->cdw11, cmd->cdw12, cmd->cdw13, + cmd->cdw14, cmd->cdw15, + cmd->data_len, (void *)(uintptr_t)cmd->addr, + cmd->metadata_len, (void *)(uintptr_t)cmd->metadata, + cmd->timeout_ms, result); + default: + break; + } + + return -ENOTSUP; } -int nvme_admin_passthru(int fd, __u8 opcode, __u8 flags, __u16 rsvd, +int nvme_admin_passthru(struct nvme_transport_handle *hdl, __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) { - return nvme_passthru(fd, NVME_IOCTL_ADMIN_CMD, opcode, flags, rsvd, + return nvme_passthru(hdl, NVME_IOCTL_ADMIN_CMD, opcode, flags, rsvd, nsid, cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, cdw14, cdw15, data_len, data, metadata_len, metadata, timeout_ms, result); } -enum features { - NVME_FEATURES_ARBITRATION_BURST_SHIFT = 0, - NVME_FEATURES_ARBITRATION_LPW_SHIFT = 8, - NVME_FEATURES_ARBITRATION_MPW_SHIFT = 16, - NVME_FEATURES_ARBITRATION_HPW_SHIFT = 24, - NVME_FEATURES_ARBITRATION_BURST_MASK = 0x7, - NVME_FEATURES_ARBITRATION_LPW_MASK = 0xff, - NVME_FEATURES_ARBITRATION_MPW_MASK = 0xff, - NVME_FEATURES_ARBITRATION_HPW_MASK = 0xff, - NVME_FEATURES_PWRMGMT_PS_SHIFT = 0, - NVME_FEATURES_PWRMGMT_WH_SHIFT = 5, - NVME_FEATURES_PWRMGMT_PS_MASK = 0x1f, - NVME_FEATURES_PWRMGMT_WH_MASK = 0x7, - NVME_FEATURES_TMPTH_SHIFT = 0, - NVME_FEATURES_TMPSEL_SHIFT = 16, - NVME_FEATURES_THSEL_SHIFT = 20, - NVME_FEATURES_TMPTH_MASK = 0xff, - NVME_FEATURES_TMPSEL_MASK = 0xf, - NVME_FEATURES_THSEL_MASK = 0x3, - NVME_FEATURES_ERROR_RECOVERY_TLER_SHIFT = 0, - NVME_FEATURES_ERROR_RECOVERY_DULBE_SHIFT = 16, - NVME_FEATURES_ERROR_RECOVERY_TLER_MASK = 0xff, - NVME_FEATURES_ERROR_RECOVERY_DULBE_MASK = 0x1, - NVME_FEATURES_VWC_WCE_SHIFT = 0, - NVME_FEATURES_VWC_WCE_MASK = 0x1, - NVME_FEATURES_IRQC_THR_SHIFT = 0, - NVME_FEATURES_IRQC_TIME_SHIFT = 8, - NVME_FEATURES_IRQC_THR_MASK = 0xff, - NVME_FEATURES_IRQC_TIME_MASK = 0xff, - NVME_FEATURES_IVC_IV_SHIFT = 0, - NVME_FEATURES_IVC_CD_SHIFT = 16, - NVME_FEATURES_IVC_IV_MASK = 0xffff, - NVME_FEATURES_IVC_CD_MASK = 0x1, - NVME_FEATURES_WAN_DN_SHIFT = 0, - NVME_FEATURES_WAN_DN_MASK = 0x1, - NVME_FEATURES_APST_APSTE_SHIFT = 0, - NVME_FEATURES_APST_APSTE_MASK = 0x1, - NVME_FEATURES_HCTM_TMT2_SHIFT = 0, - NVME_FEATURES_HCTM_TMT1_SHIFT = 16, - NVME_FEATURES_HCTM_TMT2_MASK = 0xffff, - NVME_FEATURES_HCTM_TMT1_MASK = 0xffff, - NVME_FEATURES_NOPS_NOPPME_SHIFT = 0, - NVME_FEATURES_NOPS_NOPPME_MASK = 0x1, - NVME_FEATURES_PLM_PLE_SHIFT = 0, - NVME_FEATURES_PLM_PLE_MASK = 0x1, - NVME_FEATURES_PLM_WINDOW_SELECT_SHIFT = 0, - NVME_FEATURES_PLM_WINDOW_SELECT_MASK = 0xf, - NVME_FEATURES_LBAS_LSIRI_SHIFT = 0, - NVME_FEATURES_LBAS_LSIPI_SHIFT = 16, - NVME_FEATURES_LBAS_LSIRI_MASK = 0xffff, - NVME_FEATURES_LBAS_LSIPI_MASK = 0xffff, - NVME_FEATURES_IOCSP_IOCSCI_SHIFT = 0, - NVME_FEATURES_IOCSP_IOCSCI_MASK = 0xff, -}; - -int nvme_identify(struct nvme_identify_args *args) -{ - __u32 cdw10 = NVME_SET(args->cntid, IDENTIFY_CDW10_CNTID) | - NVME_SET(args->cns, IDENTIFY_CDW10_CNS); - __u32 cdw11 = NVME_SET(args->cns_specific_id, IDENTIFY_CDW11_CNSSPECID) | - NVME_SET(args->csi, IDENTIFY_CDW11_CSI); - __u32 cdw14 = NVME_SET(args->uuidx, IDENTIFY_CDW14_UUID); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_identify, - .nsid = args->nsid, - .addr = (__u64)(uintptr_t)args->data, - .data_len = NVME_IDENTIFY_DATA_SIZE, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw14 = cdw14, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_get_log(struct nvme_get_log_args *args) -{ - __u32 numd = (args->len >> 2) - 1; - __u16 numdu = numd >> 16, numdl = numd & 0xffff; - - __u32 cdw10 = NVME_SET(args->lid, LOG_CDW10_LID) | - NVME_SET(args->lsp, LOG_CDW10_LSP) | - NVME_SET(!!args->rae, LOG_CDW10_RAE) | - NVME_SET(numdl, LOG_CDW10_NUMDL); - __u32 cdw11 = NVME_SET(numdu, LOG_CDW11_NUMDU) | - NVME_SET(args->lsi, LOG_CDW11_LSI); - __u32 cdw12 = args->lpo & 0xffffffff; - __u32 cdw13 = args->lpo >> 32; - __u32 cdw14 = NVME_SET(args->uuidx, LOG_CDW14_UUID) | - NVME_SET(!!args->ot, LOG_CDW14_OT) | - NVME_SET(args->csi, LOG_CDW14_CSI); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_get_log_page, - .nsid = args->nsid, - .addr = (__u64)(uintptr_t)args->log, - .data_len = args->len, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw13 = cdw13, - .cdw14 = cdw14, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(struct nvme_get_log_args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - static bool force_4k; __attribute__((constructor)) @@ -362,8 +281,10 @@ static void nvme_uring_cmd_probe() static int nvme_uring_cmd_setup(struct io_uring *ring) { - return io_uring_queue_init(NVME_URING_ENTRIES, ring, - IORING_SETUP_SQE128 | IORING_SETUP_CQE32); + if (io_uring_queue_init(NVME_URING_ENTRIES, ring, + IORING_SETUP_SQE128 | IORING_SETUP_CQE32)) + return -errno; + return 0; } static void nvme_uring_cmd_exit(struct io_uring *ring) @@ -371,79 +292,45 @@ static void nvme_uring_cmd_exit(struct io_uring *ring) io_uring_queue_exit(ring); } -static int nvme_uring_cmd_admin_passthru_async(struct io_uring *ring, struct nvme_get_log_args *args) +static int nvme_uring_cmd_admin_passthru_async(struct nvme_transport_handle *hdl, + struct io_uring *ring, struct nvme_passthru_cmd *cmd, __u32 *result) { struct io_uring_sqe *sqe; - struct nvme_uring_cmd *cmd; int ret; - __u32 numd = (args->len >> 2) - 1; - __u16 numdu = numd >> 16, numdl = numd & 0xffff; - - __u32 cdw10 = NVME_SET(args->lid, LOG_CDW10_LID) | - NVME_SET(args->lsp, LOG_CDW10_LSP) | - NVME_SET(!!args->rae, LOG_CDW10_RAE) | - NVME_SET(numdl, LOG_CDW10_NUMDL); - __u32 cdw11 = NVME_SET(numdu, LOG_CDW11_NUMDU) | - NVME_SET(args->lsi, LOG_CDW11_LSI); - __u32 cdw12 = args->lpo & 0xffffffff; - __u32 cdw13 = args->lpo >> 32; - __u32 cdw14 = NVME_SET(args->uuidx, LOG_CDW14_UUID) | - NVME_SET(!!args->ot, LOG_CDW14_OT) | - NVME_SET(args->csi, LOG_CDW14_CSI); - - if (args->args_size < sizeof(struct nvme_get_log_args)) { - errno = EINVAL; - return -1; - } - sqe = io_uring_get_sqe(ring); if (!sqe) return -1; - cmd = (void *)&sqe->cmd; - cmd->opcode = nvme_admin_get_log_page, - cmd->nsid = args->nsid, - cmd->addr = (__u64)(uintptr_t)args->log, - cmd->data_len = args->len, - cmd->cdw10 = cdw10, - cmd->cdw11 = cdw11, - cmd->cdw12 = cdw12, - cmd->cdw13 = cdw13, - cmd->cdw14 = cdw14, - cmd->timeout_ms = args->timeout, - - sqe->fd = args->fd; + memcpy(&sqe->cmd, cmd, sizeof(*cmd)); + + sqe->fd = hdl->fd; sqe->opcode = IORING_OP_URING_CMD; sqe->cmd_op = NVME_URING_CMD_ADMIN; - sqe->user_data = (__u64)(uintptr_t)args; + sqe->user_data = (__u64)(uintptr_t)result; ret = io_uring_submit(ring); - if (ret < 0) { - errno = -ret; - return -1; - } + if (ret < 0) + return -errno; return 0; } static int nvme_uring_cmd_wait_complete(struct io_uring *ring, int n) { - struct nvme_get_log_args *args; struct io_uring_cqe *cqe; int i, ret = 0; + __u32 *result; for (i = 0; i < n; i++) { ret = io_uring_wait_cqe(ring, &cqe); - if (ret) { - errno = -ret; + if (ret) return -1; - } if (cqe->res) { - args = (struct nvme_get_log_args *)cqe->user_data; - if (args->result) - *args->result = cqe->res; + result = (__u32 *)cqe->user_data; + if (result) + *result = cqe->res; ret = cqe->res; break; } @@ -453,36 +340,50 @@ static int nvme_uring_cmd_wait_complete(struct io_uring *ring, int n) return ret; } -#endif -int nvme_get_log_page(int fd, __u32 xfer_len, struct nvme_get_log_args *args) +static bool nvme_uring_is_usable(struct nvme_transport_handle *hdl) { - __u64 offset = 0, xfer, data_len = args->len; - __u64 start = args->lpo; - bool retain = args->rae; - void *ptr = args->log; - int ret; + struct stat st; - args->fd = fd; + if (io_uring_kernel_support != IO_URING_AVAILABLE || + hdl->type != NVME_TRANSPORT_HANDLE_TYPE_DIRECT || + fstat(hdl->fd, &st) || !S_ISCHR(st.st_mode)) + return false; - if (force_4k) - xfer_len = NVME_LOG_PAGE_PDU_SIZE; + return true; +} +#endif /* CONFIG_LIBURING */ +int nvme_get_log(struct nvme_transport_handle *hdl, + struct nvme_passthru_cmd *cmd, bool rae, + __u32 xfer_len, __u32 *result) +{ + __u64 offset = 0, xfer, data_len = cmd->data_len; + __u64 start = (__u64)cmd->cdw13 << 32 | cmd->cdw12; + __u64 lpo; + void *ptr = (void *)(uintptr_t)cmd->addr; + int ret; + bool _rae; + __u32 numd; + __u16 numdu, numdl; + __u32 cdw10 = cmd->cdw10 & (NVME_VAL(LOG_CDW10_LID) | + NVME_VAL(LOG_CDW10_LSP)); + __u32 cdw11 = cmd->cdw11 & NVME_VAL(LOG_CDW11_LSI); #ifdef CONFIG_LIBURING - int n = 0; + bool use_uring = nvme_uring_is_usable(hdl); struct io_uring ring; - struct stat st; - bool use_uring = false; - - if (io_uring_kernel_support == IO_URING_AVAILABLE) { - if (fstat(fd, &st) == 0 && S_ISCHR(st.st_mode)) { - use_uring = true; + int n = 0; - if (nvme_uring_cmd_setup(&ring)) - return -1; - } + if (use_uring) { + ret = nvme_uring_cmd_setup(&ring); + if (ret) + return ret; } -#endif +#endif /* CONFIG_LIBURING */ + + if (force_4k) + xfer_len = NVME_LOG_PAGE_PDU_SIZE; + /* * 4k is the smallest possible transfer unit, so restricting to 4k * avoids having to check the MDTS value of the controller. @@ -501,24 +402,42 @@ int nvme_get_log_page(int fd, __u32 xfer_len, struct nvme_get_log_args *args) * last portion of this log page so the data remains latched * during the fetch sequence. */ - args->lpo = start + offset; - args->len = xfer; - args->log = ptr; - args->rae = offset + xfer < data_len || retain; + lpo = start + offset; + numd = (xfer >> 2) - 1; + numdu = numd >> 16; + numdl = numd & 0xffff; + _rae = offset + xfer < data_len || rae; + + cmd->cdw10 = cdw10 | + NVME_SET(!!_rae, LOG_CDW10_RAE) | + NVME_SET(numdl, LOG_CDW10_NUMDL); + cmd->cdw11 = cdw11 | + NVME_SET(numdu, LOG_CDW11_NUMDU); + cmd->cdw12 = lpo & 0xffffffff; + cmd->cdw13 = lpo >> 32; + cmd->data_len = xfer; + cmd->addr = (__u64)(uintptr_t)ptr; + #ifdef CONFIG_LIBURING - if (io_uring_kernel_support == IO_URING_AVAILABLE && use_uring) { + if (use_uring) { if (n >= NVME_URING_ENTRIES) { - ret = nvme_uring_cmd_wait_complete(&ring, n); + nvme_uring_cmd_wait_complete(&ring, n); n = 0; } n += 1; - ret = nvme_uring_cmd_admin_passthru_async(&ring, args); + ret = nvme_uring_cmd_admin_passthru_async(hdl, &ring, + cmd, result); if (ret) nvme_uring_cmd_exit(&ring); - } else -#endif - ret = nvme_get_log(args); + } else { + ret = nvme_submit_admin_passthru(hdl, cmd, result); + if (ret) + return ret; + } +#else /* CONFIG_LIBURING */ + ret = nvme_submit_admin_passthru(hdl, cmd, result); +#endif /* CONFIG_LIBURING */ if (ret) return ret; @@ -527,29 +446,31 @@ int nvme_get_log_page(int fd, __u32 xfer_len, struct nvme_get_log_args *args) } while (offset < data_len); #ifdef CONFIG_LIBURING - if (io_uring_kernel_support == IO_URING_AVAILABLE && use_uring) { - ret = nvme_uring_cmd_wait_complete(&ring, n); + if (use_uring) { + nvme_uring_cmd_wait_complete(&ring, n); nvme_uring_cmd_exit(&ring); if (ret) return ret; } -#endif +#endif /* CONFIG_LIBURING */ + return 0; } -static int read_ana_chunk(int fd, enum nvme_log_ana_lsp lsp, bool rae, +static int read_ana_chunk(struct nvme_transport_handle *hdl, enum nvme_log_ana_lsp lsp, bool rae, __u8 *log, __u8 **read, __u8 *to_read, __u8 *log_end) { - if (to_read > log_end) { - errno = ENOSPC; - return -1; - } + struct nvme_passthru_cmd cmd; + + if (to_read > log_end) + return -ENOSPC; while (*read < to_read) { __u32 len = min_t(__u32, log_end - *read, NVME_LOG_PAGE_PDU_SIZE); int ret; - ret = nvme_get_log_ana(fd, lsp, rae, *read - log, len, *read); + nvme_init_get_log_ana(&cmd, lsp, *read - log, *read, len); + ret = nvme_get_log(hdl, &cmd, rae, NVME_LOG_PAGE_PDU_SIZE, NULL); if (ret) return ret; @@ -558,7 +479,7 @@ static int read_ana_chunk(int fd, enum nvme_log_ana_lsp lsp, bool rae, return 0; } -static int try_read_ana(int fd, enum nvme_log_ana_lsp lsp, bool rae, +static int try_read_ana(struct nvme_transport_handle *hdl, enum nvme_log_ana_lsp lsp, bool rae, struct nvme_ana_log *log, __u8 *log_end, __u8 *read, __u8 **to_read, bool *may_retry) { @@ -570,7 +491,7 @@ static int try_read_ana(int fd, enum nvme_log_ana_lsp lsp, bool rae, __le32 nnsids; *to_read += sizeof(*log->descs); - ret = read_ana_chunk(fd, lsp, rae, + ret = read_ana_chunk(hdl, lsp, rae, (__u8 *)log, &read, *to_read, log_end); if (ret) { /* @@ -579,7 +500,7 @@ static int try_read_ana(int fd, enum nvme_log_ana_lsp lsp, bool rae, * and the computed length was inaccurate. * Have the caller check chgcnt and retry. */ - *may_retry = errno == ENOSPC; + *may_retry = ret == -ENOSPC; return ret; } @@ -592,10 +513,10 @@ static int try_read_ana(int fd, enum nvme_log_ana_lsp lsp, bool rae, group + offsetof(struct nvme_ana_group_desc, nnsids), sizeof(nnsids)); *to_read += le32_to_cpu(nnsids) * sizeof(__le32); - ret = read_ana_chunk(fd, lsp, rae, + ret = read_ana_chunk(hdl, lsp, rae, (__u8 *)log, &read, *to_read, log_end); if (ret) { - *may_retry = errno == ENOSPC; + *may_retry = ret == -ENOSPC; return ret; } } @@ -604,8 +525,9 @@ static int try_read_ana(int fd, enum nvme_log_ana_lsp lsp, bool rae, return 0; } -int nvme_get_ana_log_atomic(int fd, bool rgo, bool rae, unsigned int retries, - struct nvme_ana_log *log, __u32 *len) +int nvme_get_ana_log_atomic(struct nvme_transport_handle *hdl, bool rae, bool rgo, + struct nvme_ana_log *log, __u32 *len, + unsigned int retries) { const enum nvme_log_ana_lsp lsp = rgo ? NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY : 0; @@ -615,13 +537,11 @@ int nvme_get_ana_log_atomic(int fd, bool rgo, bool rae, unsigned int retries, __u8 *to_read; int ret; - if (!retries) { - errno = EINVAL; - return -1; - } + if (!retries) + return -EINVAL; to_read = (__u8 *)log->descs; - ret = read_ana_chunk(fd, lsp, rae, + ret = read_ana_chunk(hdl, lsp, rae, (__u8 *)log, &read, to_read, log_end); if (ret) return ret; @@ -632,7 +552,7 @@ int nvme_get_ana_log_atomic(int fd, bool rgo, bool rae, unsigned int retries, int saved_errno; __le64 chgcnt; - saved_ret = try_read_ana(fd, lsp, rae, log, log_end, + saved_ret = try_read_ana(hdl, lsp, rae, log, log_end, read, &to_read, &may_retry); /* * If the log page was read with multiple Get Log Page commands, @@ -646,7 +566,7 @@ int nvme_get_ana_log_atomic(int fd, bool rgo, bool rae, unsigned int retries, chgcnt = log->chgcnt; read = (__u8 *)log; to_read = (__u8 *)log->descs; - ret = read_ana_chunk(fd, lsp, rae, + ret = read_ana_chunk(hdl, lsp, rae, (__u8 *)log, &read, to_read, log_end); if (ret) return ret; @@ -658,1906 +578,40 @@ int nvme_get_ana_log_atomic(int fd, bool rgo, bool rae, unsigned int retries, } } while (--retries); - errno = EAGAIN; - return -1; -} - -int nvme_set_features(struct nvme_set_features_args *args) -{ - __u32 cdw10 = NVME_SET(args->fid, FEATURES_CDW10_FID) | - NVME_SET(!!args->save, SET_FEATURES_CDW10_SAVE); - __u32 cdw14 = NVME_SET(args->uuidx, FEATURES_CDW14_UUID); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_set_features, - .nsid = args->nsid, - .addr = (__u64)(uintptr_t)args->data, - .data_len = args->data_len, - .cdw10 = cdw10, - .cdw11 = args->cdw11, - .cdw12 = args->cdw12, - .cdw13 = args->cdw13, - .cdw14 = cdw14, - .cdw15 = args->cdw15, - .timeout_ms = args->timeout, - }; - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -static int __nvme_set_features(int fd, __u8 fid, __u32 cdw11, bool save, - __u32 *result) -{ - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = fid, - .nsid = NVME_NSID_NONE, - .cdw11 = cdw11, - .cdw12 = 0, - .save = save, - .uuidx = NVME_UUID_NONE, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - return nvme_set_features(&args); -} - -int nvme_set_features_arbitration(int fd, __u8 ab, __u8 lpw, __u8 mpw, - __u8 hpw, bool save, __u32 *result) -{ - __u32 value = NVME_SET(ab, FEAT_ARBITRATION_BURST) | - NVME_SET(lpw, FEAT_ARBITRATION_LPW) | - NVME_SET(mpw, FEAT_ARBITRATION_MPW) | - NVME_SET(hpw, FEAT_ARBITRATION_HPW); - - return __nvme_set_features(fd, NVME_FEAT_FID_ARBITRATION, value, save, - result); -} - -int nvme_set_features_power_mgmt(int fd, __u8 ps, __u8 wh, bool save, - __u32 *result) -{ - __u32 value = NVME_SET(ps, FEAT_PWRMGMT_PS) | - NVME_SET(wh, FEAT_PWRMGMT_WH); - - return __nvme_set_features(fd, NVME_FEAT_FID_POWER_MGMT, value, save, - result); -} - -int nvme_set_features_lba_range(int fd, __u32 nsid, __u8 nr_ranges, bool save, - struct nvme_lba_range_type *data, __u32 *result) -{ - return nvme_set_features_data( - fd, NVME_FEAT_FID_LBA_RANGE, nsid, nr_ranges - 1, save, - sizeof(*data), data, result); -} - -int nvme_set_features_temp_thresh(int fd, __u16 tmpth, __u8 tmpsel, - enum nvme_feat_tmpthresh_thsel thsel, - bool save, __u32 *result) -{ - __u32 value = NVME_SET(tmpth, FEAT_TT_TMPTH) | - NVME_SET(tmpsel, FEAT_TT_TMPSEL) | - NVME_SET(thsel, FEAT_TT_THSEL); - - return __nvme_set_features(fd, NVME_FEAT_FID_TEMP_THRESH, value, save, - result); -} - -int nvme_set_features_temp_thresh2(int fd, __u16 tmpth, __u8 tmpsel, - enum nvme_feat_tmpthresh_thsel thsel, __u8 tmpthh, - bool save, __u32 *result) -{ - __u32 value = NVME_SET(tmpth, FEAT_TT_TMPTH) | - NVME_SET(tmpsel, FEAT_TT_TMPSEL) | - NVME_SET(thsel, FEAT_TT_THSEL) | - NVME_SET(tmpthh, FEAT_TT_TMPTHH); - - return __nvme_set_features(fd, NVME_FEAT_FID_TEMP_THRESH, value, save, - result); -} - -int nvme_set_features_err_recovery(int fd, __u32 nsid, __u16 tler, bool dulbe, - bool save, __u32 *result) -{ - __u32 value = NVME_SET(tler, FEAT_ERROR_RECOVERY_TLER) | - NVME_SET(!!dulbe, FEAT_ERROR_RECOVERY_DULBE); - - return nvme_set_features_simple( - fd, NVME_FEAT_FID_ERR_RECOVERY, nsid, value, save, result); + return -EAGAIN; } -int nvme_set_features_volatile_wc(int fd, bool wce, bool save, __u32 *result) -{ - __u32 value = NVME_SET(!!wce, FEAT_VWC_WCE); - - return __nvme_set_features(fd, NVME_FEAT_FID_VOLATILE_WC, value, save, - result); -} - -int nvme_set_features_irq_coalesce(int fd, __u8 thr, __u8 time, bool save, - __u32 *result) -{ - __u32 value = NVME_SET(thr, FEAT_IRQC_THR) | - NVME_SET(time, FEAT_IRQC_TIME); - - return __nvme_set_features(fd, NVME_FEAT_FID_IRQ_COALESCE, value, save, - result); -} - -int nvme_set_features_irq_config(int fd, __u16 iv, bool cd, bool save, - __u32 *result) -{ - __u32 value = NVME_SET(iv, FEAT_ICFG_IV) | - NVME_SET(!!cd, FEAT_ICFG_CD); - - return __nvme_set_features(fd, NVME_FEAT_FID_IRQ_CONFIG, value, save, - result); -} - -int nvme_set_features_write_atomic(int fd, bool dn, bool save, __u32 *result) -{ - __u32 value = NVME_SET(!!dn, FEAT_WA_DN); - - return __nvme_set_features(fd, NVME_FEAT_FID_WRITE_ATOMIC, value, save, - result); -} - -int nvme_set_features_async_event(int fd, __u32 events, - bool save, __u32 *result) -{ - return __nvme_set_features(fd, NVME_FEAT_FID_ASYNC_EVENT, events, save, - result); -} - -int nvme_set_features_auto_pst(int fd, bool apste, bool save, - struct nvme_feat_auto_pst *apst, __u32 *result) -{ - return nvme_set_features_data(fd, NVME_FEAT_FID_AUTO_PST, - NVME_NSID_NONE, NVME_SET(!!apste, FEAT_APST_APSTE), save, - sizeof(*apst), apst, result); -} - -int nvme_set_features_timestamp(int fd, bool save, __u64 timestamp) -{ - __le64 t = cpu_to_le64(timestamp); - struct nvme_timestamp ts = {}; - memcpy(ts.timestamp, &t, sizeof(ts.timestamp)); - - return nvme_set_features_data(fd, NVME_FEAT_FID_TIMESTAMP, - NVME_NSID_NONE, 0, save, sizeof(ts), &ts, NULL); -} - -int nvme_set_features_hctm(int fd, __u16 tmt2, __u16 tmt1, - bool save, __u32 *result) -{ - __u32 value = NVME_SET(tmt2, FEAT_HCTM_TMT2) | - NVME_SET(tmt1, FEAT_HCTM_TMT1); - - return __nvme_set_features(fd, NVME_FEAT_FID_HCTM, value, save, - result); -} - -int nvme_set_features_nopsc(int fd, bool noppme, bool save, __u32 *result) -{ - __u32 value = NVME_SET(noppme, FEAT_NOPS_NOPPME); - - return __nvme_set_features(fd, NVME_FEAT_FID_NOPSC, value, save, - result); -} - -int nvme_set_features_rrl(int fd, __u8 rrl, __u16 nvmsetid, - bool save, __u32 *result) -{ - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_RRL, - .nsid = NVME_NSID_NONE, - .cdw11 = nvmsetid, - .cdw12 = rrl, - .save = save, - .uuidx = NVME_UUID_NONE, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_set_features(&args); -} - -int nvme_set_features_plm_config(int fd, bool plm, __u16 nvmsetid, bool save, - struct nvme_plm_config *data, __u32 *result) -{ - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_PLM_CONFIG, - .nsid = NVME_NSID_NONE, - .cdw11 = nvmsetid, - .cdw12 = !!plm, - .save = save, - .uuidx = NVME_UUID_NONE, - .cdw15 = 0, - .data_len = sizeof(*data), - .data = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_set_features(&args); -} - -int nvme_set_features_plm_window(int fd, enum nvme_feat_plm_window_select sel, - __u16 nvmsetid, bool save, __u32 *result) -{ - __u32 cdw12 = NVME_SET(sel, FEAT_PLMW_WS); - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_PLM_WINDOW, - .nsid = NVME_NSID_NONE, - .cdw11 = nvmsetid, - .cdw12 = cdw12, - .save = save, - .uuidx = NVME_UUID_NONE, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_set_features(&args); -} - -int nvme_set_features_lba_sts_interval(int fd, __u16 lsiri, __u16 lsipi, - bool save, __u32 *result) -{ - __u32 value = NVME_SET(lsiri, FEAT_LBAS_LSIRI) | - NVME_SET(lsipi, FEAT_LBAS_LSIPI); - - return __nvme_set_features(fd, NVME_FEAT_FID_LBA_STS_INTERVAL, value, - save, result); -} - -int nvme_set_features_host_behavior(int fd, bool save, - struct nvme_feat_host_behavior *data) -{ - return nvme_set_features_data(fd, NVME_FEAT_FID_HOST_BEHAVIOR, - NVME_NSID_NONE, 0, false, sizeof(*data), data, NULL); -} - -int nvme_set_features_sanitize(int fd, bool nodrm, bool save, __u32 *result) -{ - return __nvme_set_features(fd, NVME_FEAT_FID_SANITIZE, !!nodrm, save, - result); -} - -int nvme_set_features_endurance_evt_cfg(int fd, __u16 endgid, __u8 egwarn, - bool save, __u32 *result) -{ - __u32 value = endgid | egwarn << 16; - - return __nvme_set_features(fd, NVME_FEAT_FID_ENDURANCE_EVT_CFG, value, - save, result); -} - -int nvme_set_features_sw_progress(int fd, __u8 pbslc, bool save, - __u32 *result) -{ - return __nvme_set_features(fd, NVME_FEAT_FID_SW_PROGRESS, pbslc, save, - result); -} - -int nvme_set_features_host_id(int fd, bool exhid, bool save, __u8 *hostid) -{ - __u32 len = exhid ? 16 : 8; - __u32 value = !!exhid; - - return nvme_set_features_data(fd, NVME_FEAT_FID_HOST_ID, - NVME_NSID_NONE, value, save, len, hostid, NULL); -} - -int nvme_set_features_resv_mask(int fd, __u32 mask, bool save, __u32 *result) -{ - return __nvme_set_features(fd, NVME_FEAT_FID_RESV_MASK, mask, save, - result); -} - -int nvme_set_features_resv_mask2(int fd, __u32 nsid, __u32 mask, bool save, - __u32 *result) -{ - return nvme_set_features_simple( - fd, NVME_FEAT_FID_RESV_MASK, nsid, mask, save, result); -} - -int nvme_set_features_resv_persist(int fd, bool ptpl, bool save, __u32 *result) -{ - return __nvme_set_features(fd, NVME_FEAT_FID_RESV_PERSIST, !!ptpl, save, - result); -} - -int nvme_set_features_resv_persist2(int fd, __u32 nsid, bool ptpl, bool save, - __u32 *result) -{ - return nvme_set_features_simple( - fd, NVME_FEAT_FID_RESV_PERSIST, nsid, !!ptpl, save, result); -} - -int nvme_set_features_write_protect(int fd, enum nvme_feat_nswpcfg_state state, - bool save, __u32 *result) -{ - return __nvme_set_features(fd, NVME_FEAT_FID_WRITE_PROTECT, state, - false, result); -} - -int nvme_set_features_write_protect2(int fd, __u32 nsid, - enum nvme_feat_nswpcfg_state state, - bool save, __u32 *result) -{ - return nvme_set_features_simple( - fd, NVME_FEAT_FID_WRITE_PROTECT, nsid, state, false, result); -} - -int nvme_set_features_iocs_profile(int fd, __u16 iocsi, bool save) -{ - __u32 value = NVME_SET(iocsi, FEAT_IOCSP_IOCSCI); - - return __nvme_set_features(fd, NVME_FEAT_FID_IOCS_PROFILE, value, - save, NULL); -} - -int nvme_get_features(struct nvme_get_features_args *args) -{ - __u32 cdw10 = NVME_SET(args->fid, FEATURES_CDW10_FID) | - NVME_SET(args->sel, GET_FEATURES_CDW10_SEL); - __u32 cdw14 = NVME_SET(args->uuidx, FEATURES_CDW14_UUID); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_get_features, - .nsid = args->nsid, - .addr = (__u64)(uintptr_t)args->data, - .data_len = args->data_len, - .cdw10 = cdw10, - .cdw11 = args->cdw11, - .cdw14 = cdw14, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -static int __nvme_get_features(int fd, enum nvme_features_id fid, - enum nvme_get_features_sel sel, __u32 *result) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = fid, - .nsid = NVME_NSID_NONE, - .sel = sel, - .cdw11 = 0, - .uuidx = NVME_UUID_NONE, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); -} - -int nvme_get_features_arbitration(int fd, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_ARBITRATION, sel, result); -} - -int nvme_get_features_power_mgmt(int fd, enum nvme_get_features_sel sel, - __u32 *result) +int nvme_submit_io_passthru64(struct nvme_transport_handle *hdl, struct nvme_passthru_cmd64 *cmd, + __u64 *result) { - return __nvme_get_features(fd, NVME_FEAT_FID_POWER_MGMT, sel, result); + return nvme_submit_passthru64(hdl, NVME_IOCTL_IO64_CMD, cmd, result); } -int nvme_get_features_lba_range(int fd, enum nvme_get_features_sel sel, - struct nvme_lba_range_type *data, - __u32 *result) +int nvme_io_passthru64(struct nvme_transport_handle *hdl, __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, __u64 *result) { - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_LBA_RANGE, - .nsid = NVME_NSID_NONE, - .sel = sel, - .cdw11 = 0, - .uuidx = NVME_UUID_NONE, - .data_len = sizeof(*data), - .data = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); + return nvme_passthru64(hdl, NVME_IOCTL_IO64_CMD, opcode, flags, rsvd, + nsid, cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, + cdw14, cdw15, data_len, data, metadata_len, metadata, + timeout_ms, result); } -int nvme_get_features_lba_range2(int fd, enum nvme_get_features_sel sel, - __u32 nsid, struct nvme_lba_range_type *data, - __u32 *result) +int nvme_submit_io_passthru(struct nvme_transport_handle *hdl, struct nvme_passthru_cmd *cmd, __u32 *result) { - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_LBA_RANGE, - .nsid = nsid, - .sel = sel, - .uuidx = NVME_UUID_NONE, - .data = data, - .data_len = sizeof(*data), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); + return nvme_submit_passthru(hdl, NVME_IOCTL_IO_CMD, cmd, result); } -int nvme_get_features_temp_thresh(int fd, enum nvme_get_features_sel sel, - __u32 *result) +int nvme_io_passthru(struct nvme_transport_handle *hdl, __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) { - return __nvme_get_features(fd, NVME_FEAT_FID_TEMP_THRESH, sel, result); -} - -int nvme_get_features_temp_thresh2(int fd, enum nvme_get_features_sel sel, __u8 tmpsel, - enum nvme_feat_tmpthresh_thsel thsel, __u32 *result) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_TEMP_THRESH, - .nsid = NVME_NSID_NONE, - .sel = sel, - .cdw11 = NVME_SET(tmpsel, FEAT_TT_TMPSEL) | NVME_SET(thsel, FEAT_TT_THSEL), - .uuidx = NVME_UUID_NONE, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); -} - -int nvme_get_features_err_recovery(int fd, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_ERR_RECOVERY, sel, - result); -} - -int nvme_get_features_err_recovery2(int fd, enum nvme_get_features_sel sel, - __u32 nsid, __u32 *result) -{ - - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_ERR_RECOVERY, - .nsid = nsid, - .sel = sel, - .uuidx = NVME_UUID_NONE, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); -} - -int nvme_get_features_volatile_wc(int fd, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_VOLATILE_WC, sel, result); -} - -int nvme_get_features_num_queues(int fd, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_NUM_QUEUES, sel, result); -} - -int nvme_get_features_irq_coalesce(int fd, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_IRQ_COALESCE, sel, - result); -} - -int nvme_get_features_irq_config(int fd, enum nvme_get_features_sel sel, - __u16 iv, __u32 *result) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_IRQ_CONFIG, - .nsid = NVME_NSID_NONE, - .sel = sel, - .cdw11 = iv, - .uuidx = NVME_UUID_NONE, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); -} - -int nvme_get_features_write_atomic(int fd, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_WRITE_ATOMIC, sel, - result); -} - -int nvme_get_features_async_event(int fd, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_ASYNC_EVENT, sel, result); -} - -int nvme_get_features_auto_pst(int fd, enum nvme_get_features_sel sel, - struct nvme_feat_auto_pst *apst, __u32 *result) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_AUTO_PST, - .nsid = NVME_NSID_NONE, - .sel = sel, - .cdw11 = 0, - .uuidx = NVME_UUID_NONE, - .data_len = sizeof(*apst), - .data = apst, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); -} - -int nvme_get_features_host_mem_buf(int fd, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_HOST_MEM_BUF, sel, result); -} - -int nvme_get_features_host_mem_buf2(int fd, enum nvme_get_features_sel sel, - struct nvme_host_mem_buf_attrs *attrs, - __u32 *result) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_HOST_MEM_BUF, - .nsid = NVME_NSID_NONE, - .sel = sel, - .uuidx = NVME_UUID_NONE, - .data = attrs, - .data_len = sizeof(*attrs), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); -} - -int nvme_get_features_timestamp(int fd, enum nvme_get_features_sel sel, - struct nvme_timestamp *ts) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_TIMESTAMP, - .nsid = NVME_NSID_NONE, - .sel = sel, - .cdw11 = 0, - .uuidx = NVME_UUID_NONE, - .data_len = sizeof(*ts), - .data = ts, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - - return nvme_get_features(&args); -} - -int nvme_get_features_kato(int fd, enum nvme_get_features_sel sel, __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_KATO, sel, result); -} - -int nvme_get_features_hctm(int fd, enum nvme_get_features_sel sel, __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_HCTM, sel, result); -} - -int nvme_get_features_nopsc(int fd, enum nvme_get_features_sel sel, __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_NOPSC, sel, result); -} - -int nvme_get_features_rrl(int fd, enum nvme_get_features_sel sel, __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_RRL, sel, result); -} - -int nvme_get_features_plm_config(int fd, enum nvme_get_features_sel sel, - __u16 nvmsetid, struct nvme_plm_config *data, - __u32 *result) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_PLM_CONFIG, - .nsid = NVME_NSID_NONE, - .sel = sel, - .cdw11 = nvmsetid, - .uuidx = NVME_UUID_NONE, - .data_len = sizeof(*data), - .data = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); -} - -int nvme_get_features_plm_window(int fd, enum nvme_get_features_sel sel, - __u16 nvmsetid, __u32 *result) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_PLM_WINDOW, - .nsid = NVME_NSID_NONE, - .sel = sel, - .cdw11 = nvmsetid, - .uuidx = NVME_UUID_NONE, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); -} - -int nvme_get_features_lba_sts_interval(int fd, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_LBA_STS_INTERVAL, sel, - result); -} - -int nvme_get_features_host_behavior(int fd, enum nvme_get_features_sel sel, - struct nvme_feat_host_behavior *data, - __u32 *result) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_HOST_BEHAVIOR, - .nsid = NVME_NSID_NONE, - .sel = sel, - .cdw11 = 0, - .uuidx = NVME_UUID_NONE, - .data_len = sizeof(*data), - .data = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); -} - -int nvme_get_features_sanitize(int fd, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_SANITIZE, sel, result); -} - -int nvme_get_features_endurance_event_cfg(int fd, enum nvme_get_features_sel sel, - __u16 endgid, __u32 *result) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_ENDURANCE_EVT_CFG, - .nsid = NVME_NSID_NONE, - .sel = sel, - .cdw11 = endgid, - .uuidx = NVME_UUID_NONE, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); -} - -int nvme_get_features_sw_progress(int fd, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_SW_PROGRESS, sel, result); -} - -int nvme_get_features_host_id(int fd, enum nvme_get_features_sel sel, - bool exhid, __u32 len, __u8 *hostid) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_HOST_ID, - .nsid = NVME_NSID_NONE, - .sel = sel, - .cdw11 = !!exhid, - .uuidx = NVME_UUID_NONE, - .data_len = len, - .data = hostid, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - - return nvme_get_features(&args); -} - -int nvme_get_features_resv_mask(int fd, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_RESV_MASK, sel, result); -} - -int nvme_get_features_resv_mask2(int fd, enum nvme_get_features_sel sel, - __u32 nsid, __u32 *result) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_RESV_MASK, - .nsid = nsid, - .sel = sel, - .uuidx = NVME_UUID_NONE, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); -} - -int nvme_get_features_resv_persist(int fd, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_RESV_PERSIST, sel, result); -} - -int nvme_get_features_resv_persist2(int fd, enum nvme_get_features_sel sel, - __u32 nsid, __u32 *result) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_RESV_PERSIST, - .nsid = nsid, - .sel = sel, - .uuidx = NVME_UUID_NONE, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); -} - -int nvme_get_features_write_protect(int fd, __u32 nsid, - enum nvme_get_features_sel sel, - __u32 *result) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_WRITE_PROTECT, - .nsid = nsid, - .sel = sel, - .cdw11 = 0, - .uuidx = NVME_UUID_NONE, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); -} - -int nvme_get_features_iocs_profile(int fd, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_get_features(fd, NVME_FEAT_FID_IOCS_PROFILE, sel, result); -} - -int nvme_format_nvm(struct nvme_format_nvm_args *args) -{ - const size_t size_v1 = sizeof_args(struct nvme_format_nvm_args, lbaf, __u64); - const size_t size_v2 = sizeof_args(struct nvme_format_nvm_args, lbafu, __u64); - __u32 cdw10; - - if (args->args_size < size_v1 || args->args_size > size_v2) { - errno = EINVAL; - return -1; - } - - cdw10 = NVME_SET(args->lbaf, FORMAT_CDW10_LBAF) | - NVME_SET(args->mset, FORMAT_CDW10_MSET) | - NVME_SET(args->pi, FORMAT_CDW10_PI) | - NVME_SET(args->pil, FORMAT_CDW10_PIL) | - NVME_SET(args->ses, FORMAT_CDW10_SES); - - if (args->args_size == size_v2) { - /* set lbafu extension */ - cdw10 |= NVME_SET(args->lbafu, FORMAT_CDW10_LBAFU); - } - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_format_nvm, - .nsid = args->nsid, - .cdw10 = cdw10, - .timeout_ms = args->timeout, - }; - - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_ns_mgmt(struct nvme_ns_mgmt_args *args) -{ - const size_t size_v1 = sizeof_args(struct nvme_ns_mgmt_args, csi, __u64); - const size_t size_v2 = sizeof_args(struct nvme_ns_mgmt_args, data, __u64); - __u32 cdw10 = NVME_SET(args->sel, NAMESPACE_MGMT_CDW10_SEL); - __u32 cdw11 = NVME_SET(args->csi, NAMESPACE_MGMT_CDW11_CSI); - - if (args->args_size < size_v1 || args->args_size > size_v2) { - errno = EINVAL; - return -1; - } - - struct nvme_passthru_cmd cmd = { - .nsid = args->nsid, - .opcode = nvme_admin_ns_mgmt, - .cdw10 = cdw10, - .cdw11 = cdw11, - .timeout_ms = args->timeout, - }; - - if (args->args_size == size_v2) { - if (args->data) { - cmd.data_len = sizeof(*args->data); - cmd.addr = (__u64)(uintptr_t)args->data; - } - } - else { - if (args->ns) { - cmd.data_len = sizeof(*args->ns); - cmd.addr = (__u64)(uintptr_t)args->ns; - } - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_ns_attach(struct nvme_ns_attach_args *args) -{ - __u32 cdw10 = NVME_SET(args->sel, NAMESPACE_ATTACH_CDW10_SEL); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_ns_attach, - .nsid = args->nsid, - .cdw10 = cdw10, - .data_len = sizeof(*args->ctrlist), - .addr = (__u64)(uintptr_t)args->ctrlist, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_fw_download(struct nvme_fw_download_args *args) -{ - __u32 cdw10 = (args->data_len >> 2) - 1; - __u32 cdw11 = args->offset >> 2; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_fw_download, - .cdw10 = cdw10, - .cdw11 = cdw11, - .data_len = args->data_len, - .addr = (__u64)(uintptr_t)args->data, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_fw_commit(struct nvme_fw_commit_args *args) -{ - __u32 cdw10 = NVME_SET(args->slot, FW_COMMIT_CDW10_FS) | - NVME_SET(args->action, FW_COMMIT_CDW10_CA) | - NVME_SET(args->bpid, FW_COMMIT_CDW10_BPID); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_fw_commit, - .cdw10 = cdw10, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_security_send(struct nvme_security_send_args *args) -{ - __u32 cdw10 = NVME_SET(args->secp, SECURITY_SECP) | - NVME_SET(args->spsp0, SECURITY_SPSP0) | - NVME_SET(args->spsp1, SECURITY_SPSP1) | - NVME_SET(args->nssf, SECURITY_NSSF); - __u32 cdw11 = args->tl; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_security_send, - .nsid = args->nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .data_len = args->data_len, - .addr = (__u64)(uintptr_t)args->data, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_security_receive(struct nvme_security_receive_args *args) -{ - __u32 cdw10 = NVME_SET(args->secp, SECURITY_SECP) | - NVME_SET(args->spsp0, SECURITY_SPSP0) | - NVME_SET(args->spsp1, SECURITY_SPSP1) | - NVME_SET(args->nssf, SECURITY_NSSF); - __u32 cdw11 = args->al; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_security_recv, - .nsid = args->nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .data_len = args->data_len, - .addr = (__u64)(uintptr_t)args->data, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_get_lba_status(struct nvme_get_lba_status_args *args) -{ - __u32 cdw10 = args->slba & 0xffffffff; - __u32 cdw11 = args->slba >> 32; - __u32 cdw12 = args->mndw; - __u32 cdw13 = NVME_SET(args->rl, GET_LBA_STATUS_CDW13_RL) | - NVME_SET(args->atype, GET_LBA_STATUS_CDW13_ATYPE); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_get_lba_status, - .nsid = args->nsid, - .addr = (__u64)(uintptr_t)args->lbas, - .data_len = (args->mndw + 1) << 2, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw13 = cdw13, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_directive_send(struct nvme_directive_send_args *args) -{ - __u32 cdw10 = args->data_len ? (args->data_len >> 2) - 1 : 0; - __u32 cdw11 = NVME_SET(args->doper, DIRECTIVE_CDW11_DOPER) | - NVME_SET(args->dtype, DIRECTIVE_CDW11_DTYPE) | - NVME_SET(args->dspec, DIRECTIVE_CDW11_DPSEC); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_directive_send, - .nsid = args->nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = args->cdw12, - .data_len = args->data_len, - .addr = (__u64)(uintptr_t)args->data, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_directive_send_id_endir(int fd, __u32 nsid, bool endir, - enum nvme_directive_dtype dtype, - struct nvme_id_directives *id) -{ - __u32 cdw12 = NVME_SET(dtype, DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE) | - NVME_SET(endir, DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR); - struct nvme_directive_send_args args = { - .args_size = sizeof(args), - .fd = fd, - .nsid = nsid, - .dspec = 0, - .dtype = NVME_DIRECTIVE_DTYPE_IDENTIFY, - .doper = NVME_DIRECTIVE_SEND_IDENTIFY_DOPER_ENDIR, - .cdw12 = cdw12, - .data_len = sizeof(*id), - .data = id, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - - return nvme_directive_send(&args); -} - -int nvme_directive_recv(struct nvme_directive_recv_args *args) -{ - __u32 cdw10 = args->data_len ? (args->data_len >> 2) - 1 : 0; - __u32 cdw11 = NVME_SET(args->doper, DIRECTIVE_CDW11_DOPER) | - NVME_SET(args->dtype, DIRECTIVE_CDW11_DTYPE) | - NVME_SET(args->dspec, DIRECTIVE_CDW11_DPSEC); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_directive_recv, - .nsid = args->nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = args->cdw12, - .data_len = args->data_len, - .addr = (__u64)(uintptr_t)args->data, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_capacity_mgmt(struct nvme_capacity_mgmt_args *args) -{ - __u32 cdw10 = args->op | args->element_id << 16; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_capacity_mgmt, - .cdw10 = cdw10, - .cdw11 = args->cdw11, - .cdw12 = args->cdw12, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_lockdown(struct nvme_lockdown_args *args) -{ - __u32 cdw10 = args->ofi << 8 | - (args->ifc & 0x3) << 5 | - (args->prhbt & 0x1) << 4 | - (args->scp & 0xF); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_lockdown, - .cdw10 = cdw10, - .cdw14 = args->uuidx & 0x3F, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_set_property(struct nvme_set_property_args *args) -{ - __u32 cdw10 = nvme_is_64bit_reg(args->offset); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_fabrics, - .nsid = nvme_fabrics_type_property_set, - .cdw10 = cdw10, - .cdw11 = args->offset, - .cdw12 = args->value & 0xffffffff, - .cdw13 = args->value >> 32, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_get_property(struct nvme_get_property_args *args) -{ - __u32 cdw10 = nvme_is_64bit_reg(args->offset); - - struct nvme_passthru_cmd64 cmd = { - .opcode = nvme_admin_fabrics, - .nsid = nvme_fabrics_type_property_get, - .cdw10 = cdw10, - .cdw11 = args->offset, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru64(args->fd, &cmd, args->value); -} - -int nvme_sanitize_nvm(struct nvme_sanitize_nvm_args *args) -{ - const size_t size_v1 = sizeof_args(struct nvme_sanitize_nvm_args, nodas, __u64); - const size_t size_v2 = sizeof_args(struct nvme_sanitize_nvm_args, emvs, __u64); - __u32 cdw10, cdw11; - - if (args->args_size < size_v1 || args->args_size > size_v2) { - errno = EINVAL; - return -1; - } - - cdw10 = NVME_SET(args->sanact, SANITIZE_CDW10_SANACT) | - NVME_SET(!!args->ause, SANITIZE_CDW10_AUSE) | - NVME_SET(args->owpass, SANITIZE_CDW10_OWPASS) | - NVME_SET(!!args->oipbp, SANITIZE_CDW10_OIPBP) | - NVME_SET(!!args->nodas, SANITIZE_CDW10_NODAS); - - if (args->args_size == size_v2) - cdw10 |= NVME_SET(!!args->emvs, SANITIZE_CDW10_EMVS); - - cdw11 = args->ovrpat; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_sanitize_nvm, - .cdw10 = cdw10, - .cdw11 = cdw11, - .timeout_ms = args->timeout, - }; - - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_dev_self_test(struct nvme_dev_self_test_args *args) -{ - __u32 cdw10 = NVME_SET(args->stc, DEVICE_SELF_TEST_CDW10_STC); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_dev_self_test, - .nsid = args->nsid, - .cdw10 = cdw10, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_virtual_mgmt(struct nvme_virtual_mgmt_args *args) -{ - __u32 cdw10 = NVME_SET(args->act, VIRT_MGMT_CDW10_ACT) | - NVME_SET(args->rt, VIRT_MGMT_CDW10_RT) | - NVME_SET(args->cntlid, VIRT_MGMT_CDW10_CNTLID); - __u32 cdw11 = NVME_SET(args->nr, VIRT_MGMT_CDW11_NR); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_virtual_mgmt, - .cdw10 = cdw10, - .cdw11 = cdw11, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_submit_io_passthru64(int fd, struct nvme_passthru_cmd64 *cmd, - __u64 *result) -{ - return nvme_submit_passthru64(fd, NVME_IOCTL_IO64_CMD, cmd, result); -} - -int nvme_io_passthru64(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, __u64 *result) -{ - return nvme_passthru64(fd, NVME_IOCTL_IO64_CMD, opcode, flags, rsvd, - nsid, cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, - cdw14, cdw15, data_len, data, metadata_len, metadata, - timeout_ms, result); -} - -int nvme_submit_io_passthru(int fd, struct nvme_passthru_cmd *cmd, __u32 *result) -{ - return nvme_submit_passthru(fd, NVME_IOCTL_IO_CMD, cmd, result); -} - -int nvme_io_passthru(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, __u32 *result) -{ - return nvme_passthru(fd, NVME_IOCTL_IO_CMD, opcode, flags, rsvd, nsid, + return nvme_passthru(hdl, NVME_IOCTL_IO_CMD, opcode, flags, rsvd, nsid, cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, cdw14, cdw15, data_len, data, metadata_len, metadata, timeout_ms, result); } - -static int nvme_set_var_size_tags(__u32 *cmd_dw2, __u32 *cmd_dw3, __u32 *cmd_dw14, - __u8 pif, __u8 sts, __u64 reftag, __u64 storage_tag) -{ - __u32 cdw2 = 0, cdw3 = 0, cdw14; - - switch (pif) { - case NVME_NVM_PIF_16B_GUARD: - cdw14 = reftag & 0xffffffff; - cdw14 |= ((storage_tag << (32 - sts)) & 0xffffffff); - break; - case NVME_NVM_PIF_32B_GUARD: - cdw14 = reftag & 0xffffffff; - cdw3 = reftag >> 32; - cdw14 |= ((storage_tag << (80 - sts)) & 0xffff0000); - if (sts >= 48) - cdw3 |= ((storage_tag >> (sts - 48)) & 0xffffffff); - else - cdw3 |= ((storage_tag << (48 - sts)) & 0xffffffff); - cdw2 = (storage_tag >> (sts - 16)) & 0xffff; - break; - case NVME_NVM_PIF_64B_GUARD: - cdw14 = reftag & 0xffffffff; - cdw3 = (reftag >> 32) & 0xffff; - cdw14 |= ((storage_tag << (48 - sts)) & 0xffffffff); - if (sts >= 16) - cdw3 |= ((storage_tag >> (sts - 16)) & 0xffff); - else - cdw3 |= ((storage_tag << (16 - sts)) & 0xffff); - break; - default: - perror("Unsupported Protection Information Format"); - errno = EINVAL; - return -1; - } - - *cmd_dw2 = cdw2; - *cmd_dw3 = cdw3; - *cmd_dw14 = cdw14; - return 0; -} - -int nvme_io(struct nvme_io_args *args, __u8 opcode) -{ - const size_t size_v1 = sizeof_args(struct nvme_io_args, dsm, __u64); - const size_t size_v2 = sizeof_args(struct nvme_io_args, pif, __u64); - __u32 cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, cdw14, cdw15; - - if (args->args_size < size_v1 || args->args_size > size_v2) { - errno = EINVAL; - return -1; - } - - cdw10 = args->slba & 0xffffffff; - cdw11 = args->slba >> 32; - cdw12 = args->nlb | (args->control << 16); - cdw13 = args->dsm | (args->dspec << 16); - cdw15 = args->apptag | (args->appmask << 16); - - if (args->args_size == size_v1) { - cdw2 = (args->storage_tag >> 32) & 0xffff; - cdw3 = args->storage_tag & 0xffffffff; - cdw14 = args->reftag; - } else { - if (nvme_set_var_size_tags(&cdw2, &cdw3, &cdw14, - args->pif, - args->sts, - args->reftag_u64, - args->storage_tag)) { - errno = EINVAL; - return -1; - } - } - - struct nvme_passthru_cmd cmd = { - .opcode = opcode, - .nsid = args->nsid, - .cdw2 = cdw2, - .cdw3 = cdw3, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw13 = cdw13, - .cdw14 = cdw14, - .cdw15 = cdw15, - .data_len = args->data_len, - .metadata_len = args->metadata_len, - .addr = (__u64)(uintptr_t)args->data, - .metadata = (__u64)(uintptr_t)args->metadata, - .timeout_ms = args->timeout, - }; - - return nvme_submit_io_passthru(args->fd, &cmd, args->result); -} - -int nvme_dsm(struct nvme_dsm_args *args) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_dsm, - .nsid = args->nsid, - .addr = (__u64)(uintptr_t)args->dsm, - .data_len = args->nr_ranges * sizeof(*args->dsm), - .cdw10 = args->nr_ranges - 1, - .cdw11 = args->attrs, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_io_passthru(args->fd, &cmd, args->result); -} - -int nvme_copy(struct nvme_copy_args *args) -{ - const size_t size_v1 = sizeof_args(struct nvme_copy_args, format, __u64); - const size_t size_v2 = sizeof_args(struct nvme_copy_args, ilbrt_u64, __u64); - __u32 cdw3, cdw12, cdw14, data_len; - - if (args->args_size < size_v1 || args->args_size > size_v2) { - errno = EINVAL; - return -1; - } - - cdw12 = ((args->nr - 1) & 0xff) | ((args->format & 0xf) << 8) | - ((args->prinfor & 0xf) << 12) | ((args->dtype & 0xf) << 20) | - ((args->prinfow & 0xf) << 26) | ((args->fua & 0x1) << 30) | - ((args->lr & 0x1) << 31); - - if (args->args_size == size_v1) { - cdw3 = 0; - cdw14 = args->ilbrt; - } else { - cdw3 = (args->ilbrt_u64 >> 32) & 0xffffffff; - cdw14 = args->ilbrt_u64 & 0xffffffff; - } - - if (args->format == 1) - data_len = args->nr * sizeof(struct nvme_copy_range_f1); - else if (args->format == 2) - data_len = args->nr * sizeof(struct nvme_copy_range_f2); - else if (args->format == 3) - data_len = args->nr * sizeof(struct nvme_copy_range_f3); - else - data_len = args->nr * sizeof(struct nvme_copy_range); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_copy, - .nsid = args->nsid, - .addr = (__u64)(uintptr_t)args->copy, - .data_len = data_len, - .cdw3 = cdw3, - .cdw10 = args->sdlba & 0xffffffff, - .cdw11 = args->sdlba >> 32, - .cdw12 = cdw12, - .cdw13 = (args->dspec & 0xffff) << 16, - .cdw14 = cdw14, - .cdw15 = (args->lbatm << 16) | args->lbat, - .timeout_ms = args->timeout, - }; - - return nvme_submit_io_passthru(args->fd, &cmd, args->result); -} - -int nvme_resv_acquire(struct nvme_resv_acquire_args *args) -{ - __le64 payload[2] = { - cpu_to_le64(args->crkey), - cpu_to_le64(args->nrkey) - }; - __u32 cdw10 = (args->racqa & 0x7) | - (args->iekey ? 1 << 3 : 0) | - (args->rtype << 8); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_resv_acquire, - .nsid = args->nsid, - .cdw10 = cdw10, - .data_len = sizeof(payload), - .addr = (__u64)(uintptr_t)(payload), - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_io_passthru(args->fd, &cmd, args->result); -} - -int nvme_resv_register(struct nvme_resv_register_args *args) -{ - __le64 payload[2] = { - cpu_to_le64(args->crkey), - cpu_to_le64(args->nrkey) - }; - __u32 cdw10 = (args->rrega & 0x7) | - (args->iekey ? 1 << 3 : 0) | - (args->cptpl << 30); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_resv_register, - .nsid = args->nsid, - .cdw10 = cdw10, - .data_len = sizeof(payload), - .addr = (__u64)(uintptr_t)(payload), - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_io_passthru(args->fd, &cmd, args->result); -} - -int nvme_resv_release(struct nvme_resv_release_args *args) -{ - __le64 payload[1] = { cpu_to_le64(args->crkey) }; - __u32 cdw10 = (args->rrela & 0x7) | - (args->iekey ? 1 << 3 : 0) | - (args->rtype << 8); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_resv_release, - .nsid = args->nsid, - .cdw10 = cdw10, - .addr = (__u64)(uintptr_t)(payload), - .data_len = sizeof(payload), - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_io_passthru(args->fd, &cmd, args->result); -} - -int nvme_resv_report(struct nvme_resv_report_args *args) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_resv_report, - .nsid = args->nsid, - .cdw10 = (args->len >> 2) - 1, - .cdw11 = args->eds ? 1 : 0, - .addr = (__u64)(uintptr_t)args->report, - .data_len = args->len, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_io_passthru(args->fd, &cmd, args->result); -} - -int nvme_io_mgmt_recv(struct nvme_io_mgmt_recv_args *args) -{ - __u32 cdw10 = args->mo | (args->mos << 16); - __u32 cdw11 = (args->data_len >> 2) - 1; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_io_mgmt_recv, - .nsid = args->nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .addr = (__u64)(uintptr_t)args->data, - .data_len = args->data_len, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - return nvme_submit_io_passthru(args->fd, &cmd, NULL); -} - -int nvme_io_mgmt_send(struct nvme_io_mgmt_send_args *args) -{ - __u32 cdw10 = args->mo | (args->mos << 16); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_io_mgmt_send, - .nsid = args->nsid, - .cdw10 = cdw10, - .addr = (__u64)(uintptr_t)args->data, - .data_len = args->data_len, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - return nvme_submit_io_passthru(args->fd, &cmd, NULL); -} - -int nvme_zns_mgmt_send(struct nvme_zns_mgmt_send_args *args) -{ - __u32 cdw10 = args->slba & 0xffffffff; - __u32 cdw11 = args->slba >> 32; - __u32 cdw13 = NVME_SET(args->zsaso, ZNS_MGMT_SEND_ZSASO) | - NVME_SET(!!args->select_all, ZNS_MGMT_SEND_SEL) | - NVME_SET(args->zsa, ZNS_MGMT_SEND_ZSA); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_zns_cmd_mgmt_send, - .nsid = args->nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw13 = cdw13, - .addr = (__u64)(uintptr_t)args->data, - .data_len = args->data_len, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_io_passthru(args->fd, &cmd, args->result); -} - -int nvme_zns_mgmt_recv(struct nvme_zns_mgmt_recv_args *args) -{ - __u32 cdw10 = args->slba & 0xffffffff; - __u32 cdw11 = args->slba >> 32; - __u32 cdw12 = (args->data_len >> 2) - 1; - __u32 cdw13 = NVME_SET(args->zra, ZNS_MGMT_RECV_ZRA) | - NVME_SET(args->zrasf, ZNS_MGMT_RECV_ZRASF) | - NVME_SET(args->zras_feat, ZNS_MGMT_RECV_ZRAS_FEAT); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_zns_cmd_mgmt_recv, - .nsid = args->nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw13 = cdw13, - .addr = (__u64)(uintptr_t)args->data, - .data_len = args->data_len, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - return nvme_submit_io_passthru(args->fd, &cmd, args->result); -} - -int nvme_zns_append(struct nvme_zns_append_args *args) -{ - const size_t size_v1 = sizeof_args(struct nvme_zns_append_args, lbatm, __u64); - const size_t size_v2 = sizeof_args(struct nvme_zns_append_args, ilbrt_u64, __u64); - __u32 cdw3, cdw10, cdw11, cdw12, cdw14, cdw15; - - if (args->args_size < size_v1 || args->args_size > size_v2) { - errno = EINVAL; - return -1; - } - - cdw10 = args->zslba & 0xffffffff; - cdw11 = args->zslba >> 32; - cdw12 = args->nlb | (args->control << 16); - cdw15 = args->lbat | (args->lbatm << 16); - - if (args->args_size == size_v1) { - cdw3 = 0; - cdw14 = args->ilbrt; - } else { - cdw3 = (args->ilbrt_u64 >> 32) & 0xffffffff; - cdw14 = args->ilbrt_u64 & 0xffffffff; - } - - struct nvme_passthru_cmd64 cmd = { - .opcode = nvme_zns_cmd_append, - .nsid = args->nsid, - .cdw3 = cdw3, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw14 = cdw14, - .cdw15 = cdw15, - .data_len = args->data_len, - .addr = (__u64)(uintptr_t)args->data, - .metadata_len = args->metadata_len, - .metadata = (__u64)(uintptr_t)args->metadata, - .timeout_ms = args->timeout, - }; - - return nvme_submit_io_passthru64(args->fd, &cmd, args->result); -} - -int nvme_dim_send(struct nvme_dim_args *args) -{ - __u32 cdw10 = NVME_SET(args->tas, DIM_TAS); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_discovery_info_mgmt, - .cdw10 = cdw10, - .addr = (__u64)(uintptr_t)args->data, - .data_len = args->data_len, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - - -int nvme_lm_cdq(struct nvme_lm_cdq_args *args) -{ - const size_t size_v1 = sizeof_args(struct nvme_lm_cdq_args, sz_u8, __u64); - const size_t size_v2 = sizeof_args(struct nvme_lm_cdq_args, sz, __u64); - __u32 cdw10 = NVME_SET(args->sel, LM_CDQ_SEL) | - NVME_SET(args->mos, LM_CDQ_MOS); - __u32 cdw11 = 0, data_len = 0, sz = 0; - int err; - - if (args->args_size < size_v1 || args->args_size > size_v2) { - errno = EINVAL; - return -1; - } - - if (args->args_size == size_v1) - sz = args->sz_u8; - else - sz = args->sz; - - if (args->sel == NVME_LM_SEL_CREATE_CDQ) { - cdw11 = NVME_SET(NVME_SET(args->cntlid, LM_CREATE_CDQ_CNTLID), LM_CQS) | - NVME_LM_CREATE_CDQ_PC; - data_len = sz << 2; - } else if (args->sel == NVME_LM_SEL_DELETE_CDQ) { - cdw11 = NVME_SET(args->cdqid, LM_DELETE_CDQ_CDQID); - } - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_ctrl_data_queue, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = sz, - .addr = (__u64)(uintptr_t)args->data, - .data_len = data_len, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - err = nvme_submit_admin_passthru(args->fd, &cmd, args->result); - - if (!err) - args->cdqid = NVME_GET(cmd.result, LM_CREATE_CDQ_CDQID); - - return err; -} - -int nvme_lm_track_send(struct nvme_lm_track_send_args *args) -{ - __u32 cdw10 = NVME_SET(args->sel, LM_TRACK_SEND_SEL) | - NVME_SET(args->mos, LM_TRACK_SEND_MOS); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_track_send, - .cdw10 = cdw10, - .cdw11 = args->cdqid, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_lm_migration_send(struct nvme_lm_migration_send_args *args) -{ - __u32 cdw10 = NVME_SET(args->sel, LM_MIGRATION_SEND_SEL) | - NVME_SET(args->mos, LM_MIGRATION_SEND_MOS); - __u32 cdw11 = 0; - - if (args->sel == NVME_LM_SEL_SUSPEND) { - cdw11 = NVME_SET(args->stype, LM_STYPE) | - NVME_SET(args->cntlid, LM_SUSPEND_CNTLID); - if (args->dudmq) - cdw11 |= NVME_LM_DUDMQ; - } else if (args->sel == NVME_LM_SEL_RESUME) { - cdw11 = NVME_SET(args->cntlid, LM_RESUME_CNTLID); - } else if (args->sel == NVME_LM_SEL_SET_CONTROLLER_STATE) { - cdw11 = NVME_SET(args->csuuidi, LM_SET_CONTROLLER_STATE_CSUUIDI) | - NVME_SET(args->csvi, LM_SET_CONTROLLER_STATE_CSVI) | - NVME_SET(args->cntlid, LM_SET_CONTROLLER_STATE_CNTLID); - } - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_migration_send, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = (__u32)args->offset, - .cdw13 = (__u32)(args->offset >> 32), - .cdw14 = NVME_SET(args->uidx, LM_MIGRATION_SEND_UIDX), - .cdw15 = args->numd, - .addr = (__u64)(uintptr_t)args->data, - .data_len = args->numd << 2, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_lm_migration_recv(struct nvme_lm_migration_recv_args *args) -{ - __u32 cdw10 = NVME_SET(args->sel, LM_MIGRATION_RECV_SEL) | - NVME_SET(args->mos, LM_MIGRATION_RECV_MOS); - __u32 cdw11 = 0, data_len = 0; - - if (args->sel == NVME_LM_SEL_GET_CONTROLLER_STATE) { - cdw11 = NVME_SET(args->csuidxp, LM_GET_CONTROLLER_STATE_CSUIDXP) | - NVME_SET(args->csuuidi, LM_GET_CONTROLLER_STATE_CSUUIDI) | - NVME_SET(args->cntlid, LM_GET_CONTROLLER_STATE_CNTLID); - data_len = (args->numd + 1 /*0's based*/) << 2; - } - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_migration_receive, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = (__u32)args->offset, - .cdw13 = (__u32)(args->offset >> 32), - .cdw14 = NVME_SET(args->uidx, LM_MIGRATION_RECV_UIDX), - .cdw15 = args->numd, - .addr = (__u64)(uintptr_t)args->data, - .data_len = data_len, - .timeout_ms = args->timeout, - }; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - return nvme_submit_admin_passthru(args->fd, &cmd, args->result); -} - -int nvme_lm_set_features_ctrl_data_queue(int fd, __u16 cdqid, __u32 hp, __u32 tpt, bool etpt, - __u32 *result) -{ - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_CTRL_DATA_QUEUE, - .nsid = NVME_NSID_NONE, - .cdw11 = cdqid | NVME_SET(etpt, LM_CTRL_DATA_QUEUE_ETPT), - .cdw12 = hp, - .cdw13 = tpt, - .save = false, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_set_features(&args); -} - -int nvme_lm_get_features_ctrl_data_queue(int fd, __u16 cdqid, - struct nvme_lm_ctrl_data_queue_fid_data *data, - __u32 *result) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = NVME_FEAT_FID_CTRL_DATA_QUEUE, - .nsid = NVME_NSID_NONE, - .cdw11 = cdqid, - .data = data, - .data_len = sizeof(*data), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_get_features(&args); -} diff --git a/libnvme/src/nvme/ioctl.h b/libnvme/src/nvme/ioctl.h index 7d326e0128..a2420dd868 100644 --- a/libnvme/src/nvme/ioctl.h +++ b/libnvme/src/nvme/ioctl.h @@ -10,12 +10,14 @@ #ifndef _LIBNVME_IOCTL_H #define _LIBNVME_IOCTL_H +#include +#include #include #include +#include #include #include -#include /* * We can not always count on the kernel UAPI being installed. Use the same @@ -194,20 +196,6 @@ struct nvme_uring_cmd { #endif /* _LINUX_NVME_IOCTL_H */ -/** - * sizeof_args - Helper function used to determine structure sizes - * @type: Argument structure type - * @member: Member inside the type - * @align: Alignment information - */ -#define sizeof_args(type, member, align) \ -({ \ - type s; \ - size_t t = offsetof(type, member) + sizeof(s.member); \ - size_t p = (sizeof(align) - (t % sizeof(align))) % sizeof(align); \ - t + p; \ -}) - enum nvme_cmd_dword_fields { NVME_DEVICE_SELF_TEST_CDW10_STC_SHIFT = 0, NVME_DEVICE_SELF_TEST_CDW10_STC_MASK = 0xf, @@ -229,12 +217,18 @@ enum nvme_cmd_dword_fields { NVME_FW_COMMIT_CDW10_BPID_MASK = 0x1, NVME_GET_FEATURES_CDW10_SEL_SHIFT = 8, NVME_GET_FEATURES_CDW10_SEL_MASK = 0x7, - NVME_SET_FEATURES_CDW10_SAVE_SHIFT = 31, - NVME_SET_FEATURES_CDW10_SAVE_MASK = 0x1, - NVME_FEATURES_CDW10_FID_SHIFT = 0, - NVME_FEATURES_CDW14_UUID_SHIFT = 0, - NVME_FEATURES_CDW10_FID_MASK = 0xff, - NVME_FEATURES_CDW14_UUID_MASK = 0x7f, + NVME_GET_FEATURES_CDW10_FID_SHIFT = 0, + NVME_GET_FEATURES_CDW10_FID_MASK = 0xff, + NVME_GET_FEATURES_CDW14_UUID_SHIFT = 0, + NVME_GET_FEATURES_CDW14_UUID_MASK = 0x7f, + NVME_SET_FEATURES_CDW10_SV_SHIFT = 31, + NVME_SET_FEATURES_CDW10_SV_MASK = 0x1, + NVME_SET_FEATURES_CDW10_FID_SHIFT = 0, + NVME_SET_FEATURES_CDW10_FID_MASK = 0xff, + NVME_SET_FEATURES_CDW11_NUM_SHIFT = 0, + NVME_SET_FEATURES_CDW11_NUM_MASK = 0x3f, + NVME_SET_FEATURES_CDW14_UUID_SHIFT = 0, + NVME_SET_FEATURES_CDW14_UUID_MASK = 0x7f, NVME_LOG_CDW10_LID_SHIFT = 0, NVME_LOG_CDW10_LSP_SHIFT = 8, NVME_LOG_CDW10_RAE_SHIFT = 15, @@ -256,11 +250,17 @@ enum nvme_cmd_dword_fields { NVME_IDENTIFY_CDW10_CNS_SHIFT = 0, NVME_IDENTIFY_CDW10_CNTID_SHIFT = 16, NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT = 0, + NVME_IDENTIFY_CDW11_FIDX_SHIFT = 0, + NVME_IDENTIFY_CDW11_DOMID_SHIFT = 0, + NVME_IDENTIFY_CDW11_ENGGID_SHIFT = 0, NVME_IDENTIFY_CDW14_UUID_SHIFT = 0, NVME_IDENTIFY_CDW11_CSI_SHIFT = 24, NVME_IDENTIFY_CDW10_CNS_MASK = 0xff, NVME_IDENTIFY_CDW10_CNTID_MASK = 0xffff, NVME_IDENTIFY_CDW11_CNSSPECID_MASK = 0xffff, + NVME_IDENTIFY_CDW11_FIDX_MASK = 0xffff, + NVME_IDENTIFY_CDW11_DOMID_MASK = 0xffff, + NVME_IDENTIFY_CDW11_ENGGID_MASK = 0xffff, NVME_IDENTIFY_CDW14_UUID_MASK = 0x7f, NVME_IDENTIFY_CDW11_CSI_MASK = 0xff, NVME_NAMESPACE_ATTACH_CDW10_SEL_SHIFT = 0, @@ -277,13 +277,13 @@ enum nvme_cmd_dword_fields { NVME_VIRT_MGMT_CDW10_RT_MASK = 0x7, NVME_VIRT_MGMT_CDW10_CNTLID_MASK = 0xffff, NVME_VIRT_MGMT_CDW11_NR_MASK = 0xffff, - NVME_FORMAT_CDW10_LBAF_SHIFT = 0, + NVME_FORMAT_CDW10_LBAFL_SHIFT = 0, NVME_FORMAT_CDW10_MSET_SHIFT = 4, NVME_FORMAT_CDW10_PI_SHIFT = 5, NVME_FORMAT_CDW10_PIL_SHIFT = 8, NVME_FORMAT_CDW10_SES_SHIFT = 9, NVME_FORMAT_CDW10_LBAFU_SHIFT = 12, - NVME_FORMAT_CDW10_LBAF_MASK = 0xf, + NVME_FORMAT_CDW10_LBAFL_MASK = 0xf, NVME_FORMAT_CDW10_MSET_MASK = 0x1, NVME_FORMAT_CDW10_PI_MASK = 0x7, NVME_FORMAT_CDW10_PIL_MASK = 0x1, @@ -293,13 +293,13 @@ enum nvme_cmd_dword_fields { NVME_SANITIZE_CDW10_AUSE_SHIFT = 3, NVME_SANITIZE_CDW10_OWPASS_SHIFT = 4, NVME_SANITIZE_CDW10_OIPBP_SHIFT = 8, - NVME_SANITIZE_CDW10_NODAS_SHIFT = 9, + NVME_SANITIZE_CDW10_NDAS_SHIFT = 9, NVME_SANITIZE_CDW10_EMVS_SHIFT = 10, NVME_SANITIZE_CDW10_SANACT_MASK = 0x7, NVME_SANITIZE_CDW10_AUSE_MASK = 0x1, NVME_SANITIZE_CDW10_OWPASS_MASK = 0xf, NVME_SANITIZE_CDW10_OIPBP_MASK = 0x1, - NVME_SANITIZE_CDW10_NODAS_MASK = 0x1, + NVME_SANITIZE_CDW10_NDAS_MASK = 0x1, NVME_SANITIZE_CDW10_EMVS_MASK = 0x1, NVME_SECURITY_NSSF_SHIFT = 0, NVME_SECURITY_SPSP0_SHIFT = 8, @@ -313,40 +313,205 @@ enum nvme_cmd_dword_fields { NVME_GET_LBA_STATUS_CDW13_ATYPE_SHIFT = 24, NVME_GET_LBA_STATUS_CDW13_RL_MASK = 0xffff, NVME_GET_LBA_STATUS_CDW13_ATYPE_MASK = 0xff, + NVME_ZNS_MGMT_SEND_ZM_SHIFT = 16, + NVME_ZNS_MGMT_SEND_ZM_MASK = 0xff, NVME_ZNS_MGMT_SEND_ZSASO_SHIFT = 9, NVME_ZNS_MGMT_SEND_ZSASO_MASK = 0x1, NVME_ZNS_MGMT_SEND_SEL_SHIFT = 8, NVME_ZNS_MGMT_SEND_SEL_MASK = 0x1, NVME_ZNS_MGMT_SEND_ZSA_SHIFT = 0, NVME_ZNS_MGMT_SEND_ZSA_MASK = 0xff, + NVME_ZNS_MGMT_RECV_ZRASPF_SHIFT = 16, + NVME_ZNS_MGMT_RECV_ZRASPF_MASK = 0x1, + NVME_ZNS_MGMT_RECV_ZRAS_SHIFT = 8, + NVME_ZNS_MGMT_RECV_ZRAS_MASK = 0xff, NVME_ZNS_MGMT_RECV_ZRA_SHIFT = 0, NVME_ZNS_MGMT_RECV_ZRA_MASK = 0xff, - NVME_ZNS_MGMT_RECV_ZRASF_SHIFT = 8, - NVME_ZNS_MGMT_RECV_ZRASF_MASK = 0xff, - NVME_ZNS_MGMT_RECV_ZRAS_FEAT_SHIFT = 16, - NVME_ZNS_MGMT_RECV_ZRAS_FEAT_MASK = 0x1, NVME_DIM_TAS_SHIFT = 0, - NVME_DIM_TAS_MASK = 0xF, + NVME_DIM_TAS_MASK = 0xf, + NVME_DSM_CDW10_NR_SHIFT = 0, + NVME_DSM_CDW10_NR_MASK = 0xff, + NVME_DSM_CDW11_IDR_SHIFT = 0, + NVME_DSM_CDW11_IDR_MASK = 0x1, + NVME_DSM_CDW11_IDW_SHIFT = 1, + NVME_DSM_CDW11_IDW_MASK = 0x1, + NVME_DSM_CDW11_AD_SHIFT = 2, + NVME_DSM_CDW11_AD_MASK = 0x1, + NVME_CAPACITY_MGMT_CDW10_OPER_SHIFT = 0, + NVME_CAPACITY_MGMT_CDW10_OPER_MASK = 0xf, + NVME_CAPACITY_MGMT_CDW10_ELID_SHIFT = 16, + NVME_CAPACITY_MGMT_CDW10_ELID_MASK = 0xffff, + NVME_CAPACITY_MGMT_CDW11_CAPL_SHIFT = 0, + NVME_CAPACITY_MGMT_CDW11_CAPL_MASK = 0xffffffff, + NVME_CAPACITY_MGMT_CDW12_CAPU_SHIFT = 0, + NVME_CAPACITY_MGMT_CDW12_CAPU_MASK = 0xffffffff, + NVME_LOCKDOWN_CDW10_SCP_SHIFT = 0, + NVME_LOCKDOWN_CDW10_SCP_MASK = 0xf, + NVME_LOCKDOWN_CDW10_PRHBT_SHIFT = 4, + NVME_LOCKDOWN_CDW10_PRHBT_MASK = 0x1, + NVME_LOCKDOWN_CDW10_IFC_SHIFT = 5, + NVME_LOCKDOWN_CDW10_IFC_MASK = 0x3, + NVME_LOCKDOWN_CDW10_OFI_SHIFT = 8, + NVME_LOCKDOWN_CDW10_OFI_MASK = 0xff, + NVME_LOCKDOWN_CDW14_UIDX_SHIFT = 0, + NVME_LOCKDOWN_CDW14_UIDX_MASK = 0x3f, + NVME_RESV_ACQUIRE_CDW10_RACQA_SHIFT = 0, + NVME_RESV_ACQUIRE_CDW10_RACQA_MASK = 0x7, + NVME_RESV_ACQUIRE_CDW10_IEKEY_SHIFT = 3, + NVME_RESV_ACQUIRE_CDW10_IEKEY_MASK = 0x1, + NVME_RESV_ACQUIRE_CDW10_DISNSRS_SHIFT = 4, + NVME_RESV_ACQUIRE_CDW10_DISNSRS_MASK = 0x1, + NVME_RESV_ACQUIRE_CDW10_RTYPE_SHIFT = 8, + NVME_RESV_ACQUIRE_CDW10_RTYPE_MASK = 0xff, + NVME_RESV_REGISTER_CDW10_RREGA_SHIFT = 0, + NVME_RESV_REGISTER_CDW10_RREGA_MASK = 0x7, + NVME_RESV_REGISTER_CDW10_IEKEY_SHIFT = 3, + NVME_RESV_REGISTER_CDW10_IEKEY_MASK = 0x1, + NVME_RESV_REGISTER_CDW10_DISNSRS_SHIFT = 4, + NVME_RESV_REGISTER_CDW10_DISNSRS_MASK = 0x1, + NVME_RESV_REGISTER_CDW10_CPTPL_SHIFT = 30, + NVME_RESV_REGISTER_CDW10_CPTPL_MASK = 0x3, + NVME_RESV_RELEASE_CDW10_RRELA_SHIFT = 0, + NVME_RESV_RELEASE_CDW10_RRELA_MASK = 0x7, + NVME_RESV_RELEASE_CDW10_IEKEY_SHIFT = 3, + NVME_RESV_RELEASE_CDW10_IEKEY_MASK = 0x1, + NVME_RESV_RELEASE_CDW10_DISNSRS_SHIFT = 4, + NVME_RESV_RELEASE_CDW10_DISNSRS_MASK = 0x1, + NVME_RESV_RELEASE_CDW10_RTYPE_SHIFT = 8, + NVME_RESV_RELEASE_CDW10_RTYPE_MASK = 0xff, + NVME_RESV_REPORT_CDW11_EDS_SHIFT = 0, + NVME_RESV_REPORT_CDW11_EDS_MASK = 0x1, + NVME_RESV_REPORT_CDW11_DISNSRS_SHIFT = 1, + NVME_RESV_REPORT_CDW11_DISNSRS_MASK = 0x1, + NVME_IO_MGMT_RECV_CDW10_MO_SHIFT = 0, + NVME_IO_MGMT_RECV_CDW10_MO_MASK = 0xff, + NVME_IO_MGMT_RECV_CDW10_MOS_SHIFT = 16, + NVME_IO_MGMT_RECV_CDW10_MOS_MASK = 0xffff, + NVME_IO_MGMT_SEND_CDW10_MO_SHIFT = 0, + NVME_IO_MGMT_SEND_CDW10_MO_MASK = 0xff, + NVME_IO_MGMT_SEND_CDW10_MOS_SHIFT = 16, + NVME_IO_MGMT_SEND_CDW10_MOS_MASK = 0xffff, + NVME_IOCS_COMMON_CDW2_ELBTU_SHIFT = 0, + NVME_IOCS_COMMON_CDW2_ELBTU_MASK = 0xffff, + NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT = 0, + NVME_IOCS_COMMON_CDW3_ELBTU_MASK = 0xffffffff, + NVME_IOCS_COMMON_CDW10_SLBAL_SHIFT = 0, + NVME_IOCS_COMMON_CDW10_SLBAL_MASK = 0xffffffff, + NVME_IOCS_COMMON_CDW11_SLBAU_SHIFT = 0, + NVME_IOCS_COMMON_CDW11_SLBAU_MASK = 0xffffffff, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT = 0, + NVME_IOCS_COMMON_CDW12_NLB_MASK = 0xffff, + NVME_IOCS_COMMON_CDW12_CETYPE_SHIFT = 16, + NVME_IOCS_COMMON_CDW12_CETYPE_MASK = 0xf, + NVME_IOCS_COMMON_CDW12_DTYPE_SHIFT = 20, + NVME_IOCS_COMMON_CDW12_DTYPE_MASK = 0xf, + NVME_IOCS_COMMON_CDW12_STC_SHIFT = 24, + NVME_IOCS_COMMON_CDW12_STC_MASK = 0x1, + NVME_IOCS_COMMON_CDW12_DEAC_SHIFT = 25, + NVME_IOCS_COMMON_CDW12_DEAC_MASK = 0x1, + NVME_IOCS_COMMON_CDW12_PIREMAP_SHIFT = 25, + NVME_IOCS_COMMON_CDW12_PIREMAP_MASK = 0x1, + NVME_IOCS_COMMON_CDW12_PRINFO_SHIFT = 26, + NVME_IOCS_COMMON_CDW12_PRINFO_MASK = 0xf, + NVME_IOCS_COMMON_CDW12_FUA_SHIFT = 30, + NVME_IOCS_COMMON_CDW12_FUA_MASK = 0x1, + NVME_IOCS_COMMON_CDW12_LR_SHIFT = 31, + NVME_IOCS_COMMON_CDW12_LR_MASK = 0x1, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT = + NVME_IOCS_COMMON_CDW12_CETYPE_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK = + (NVME_VAL(IOCS_COMMON_CDW12_CETYPE) | + NVME_VAL(IOCS_COMMON_CDW12_DTYPE) | + NVME_VAL(IOCS_COMMON_CDW12_STC) | + NVME_VAL(IOCS_COMMON_CDW12_DEAC) | + NVME_VAL(IOCS_COMMON_CDW12_PRINFO) | + NVME_VAL(IOCS_COMMON_CDW12_FUA) | + NVME_VAL(IOCS_COMMON_CDW12_LR)) >> + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW13_DSM_AF_SHIFT = 0, + NVME_IOCS_COMMON_CDW13_DSM_AF_MASK = 0xf, + NVME_IOCS_COMMON_CDW13_DSM_AL_SHIFT = 4, + NVME_IOCS_COMMON_CDW13_DSM_AL_MASK = 0x3, + NVME_IOCS_COMMON_CDW13_DSM_SEQREQ_SHIFT = 6, + NVME_IOCS_COMMON_CDW13_DSM_SEQREQ_MASK = 0x1, + NVME_IOCS_COMMON_CDW13_DSM_INCPRS_SHIFT = 7, + NVME_IOCS_COMMON_CDW13_DSM_INCPRS_MASK = 0x1, + NVME_IOCS_COMMON_CDW13_DSM_SHIFT = + NVME_IOCS_COMMON_CDW13_DSM_AF_SHIFT, + NVME_IOCS_COMMON_CDW13_DSM_MASK = + (NVME_VAL(IOCS_COMMON_CDW13_DSM_AF) | + NVME_VAL(IOCS_COMMON_CDW13_DSM_AL) | + NVME_VAL(IOCS_COMMON_CDW13_DSM_SEQREQ) | + NVME_VAL(IOCS_COMMON_CDW13_DSM_INCPRS)) >> + NVME_IOCS_COMMON_CDW13_DSM_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT = 0, + NVME_IOCS_COMMON_CDW13_CEV_MASK = 0xffff, + NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT = 16, + NVME_IOCS_COMMON_CDW13_DSPEC_MASK = 0xffff, + NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT = 0, + NVME_IOCS_COMMON_CDW14_ELBTL_MASK = 0xffffffff, + NVME_IOCS_COMMON_CDW15_ELBAT_SHIFT = 0, + NVME_IOCS_COMMON_CDW15_ELBAT_MASK = 0xffff, + NVME_IOCS_COMMON_CDW15_ELBATM_SHIFT = 16, + NVME_IOCS_COMMON_CDW15_ELBATM_MASK = 0xffff, + NVME_COPY_CDW3_LBTU_SHIFT = 0, + NVME_COPY_CDW3_LBTU_MASK = 0xffffffff, + NVME_COPY_CDW10_SDLBAL_SHIFT = 0, + NVME_COPY_CDW10_SDLBAL_MASK = 0xffffffff, + NVME_COPY_CDW11_SDLBAU_SHIFT = 0, + NVME_COPY_CDW11_SDLBAU_MASK = 0xffffffff, + NVME_COPY_CDW12_NR_SHIFT = 0, + NVME_COPY_CDW12_NR_MASK = 0xff, + NVME_COPY_CDW12_DESFMT_SHIFT = 8, + NVME_COPY_CDW12_DESFMT_MASK = 0xf, + NVME_COPY_CDW12_PRINFOR_SHIFT = 12, + NVME_COPY_CDW12_PRINFOR_MASK = 0xf, + NVME_COPY_CDW12_CETYPE_SHIFT = 16, + NVME_COPY_CDW12_CETYPE_MASK = 0xf, + NVME_COPY_CDW12_DTYPE_SHIFT = 20, + NVME_COPY_CDW12_DTYPE_MASK = 0xf, + NVME_COPY_CDW12_STCW_SHIFT = 24, + NVME_COPY_CDW12_STCW_MASK = 0x1, + NVME_COPY_CDW12_STCR_SHIFT = 25, + NVME_COPY_CDW12_STCR_MASK = 0x1, + NVME_COPY_CDW12_PRINFOW_SHIFT = 26, + NVME_COPY_CDW12_PRINFOW_MASK = 0xf, + NVME_COPY_CDW12_FUA_SHIFT = 30, + NVME_COPY_CDW12_FUA_MASK = 0x1, + NVME_COPY_CDW12_LR_SHIFT = 31, + NVME_COPY_CDW12_LR_MASK = 0x1, + NVME_COPY_CDW14_LBTL_SHIFT = 0, + NVME_COPY_CDW14_LBTL_MASK = 0xffffffff, + NVME_COPY_CDW15_LBAT_SHIFT = 0, + NVME_COPY_CDW15_LBAT_MASK = 0xffff, + NVME_COPY_CDW15_LBATM_SHIFT = 16, + NVME_COPY_CDW15_LBATM_MASK = 0xffff, }; +#define NVME_FIELD_ENCODE(value, shift, mask) \ + (((__u32)(value) & (mask)) << (shift)) + +#define NVME_FIELD_DECODE(value, shift, mask) \ + (((value) >> (shift)) & (mask)) + /** * nvme_submit_admin_passthru64() - Submit a 64-bit nvme passthrough admin * command - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @cmd: The nvme admin command to send * @result: Optional field to return the result from the CQE DW0-1 * * Uses NVME_IOCTL_ADMIN64_CMD for the ioctl request. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_submit_admin_passthru64(int fd, struct nvme_passthru_cmd64 *cmd, +int nvme_submit_admin_passthru64(struct nvme_transport_handle *hdl, struct nvme_passthru_cmd64 *cmd, __u64 *result); /** * nvme_admin_passthru64() - Submit a 64-bit nvme passthrough command - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @opcode: The nvme io command to send * @flags: NVMe command flags (not used) * @rsvd: Reserved for future use @@ -371,10 +536,10 @@ int nvme_submit_admin_passthru64(int fd, struct nvme_passthru_cmd64 *cmd, * * Known values for @opcode are defined in &enum nvme_admin_opcode. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_admin_passthru64(int fd, __u8 opcode, __u8 flags, __u16 rsvd, +int nvme_admin_passthru64(struct nvme_transport_handle *hdl, __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, @@ -382,21 +547,21 @@ int nvme_admin_passthru64(int fd, __u8 opcode, __u8 flags, __u16 rsvd, /** * nvme_submit_admin_passthru() - Submit an nvme passthrough admin command - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @cmd: The nvme admin command to send * @result: Optional field to return the result from the CQE DW0 * * Uses NVME_IOCTL_ADMIN_CMD for the ioctl request. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_submit_admin_passthru(int fd, struct nvme_passthru_cmd *cmd, +int nvme_submit_admin_passthru(struct nvme_transport_handle *hdl, struct nvme_passthru_cmd *cmd, __u32 *result); /** * nvme_admin_passthru() - Submit an nvme passthrough command - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @opcode: The nvme io command to send * @flags: NVMe command flags (not used) * @rsvd: Reserved for future use @@ -421,10 +586,10 @@ int nvme_submit_admin_passthru(int fd, struct nvme_passthru_cmd *cmd, * * Known values for @opcode are defined in &enum nvme_admin_opcode. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_admin_passthru(int fd, __u8 opcode, __u8 flags, __u16 rsvd, +int nvme_admin_passthru(struct nvme_transport_handle *hdl, __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, @@ -432,21 +597,21 @@ int nvme_admin_passthru(int fd, __u8 opcode, __u8 flags, __u16 rsvd, /** * nvme_submit_io_passthru64() - Submit a 64-bit nvme passthrough command - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @cmd: The nvme io command to send * @result: Optional field to return the result from the CQE DW0-1 * * Uses NVME_IOCTL_IO64_CMD for the ioctl request. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_submit_io_passthru64(int fd, struct nvme_passthru_cmd64 *cmd, +int nvme_submit_io_passthru64(struct nvme_transport_handle *hdl, struct nvme_passthru_cmd64 *cmd, __u64 *result); /** * nvme_io_passthru64() - Submit an nvme io passthrough command - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @opcode: The nvme io command to send * @flags: NVMe command flags (not used) * @rsvd: Reserved for future use @@ -471,10 +636,10 @@ int nvme_submit_io_passthru64(int fd, struct nvme_passthru_cmd64 *cmd, * * Known values for @opcode are defined in &enum nvme_io_opcode. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_io_passthru64(int fd, __u8 opcode, __u8 flags, __u16 rsvd, +int nvme_io_passthru64(struct nvme_transport_handle *hdl, __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, @@ -482,22 +647,22 @@ int nvme_io_passthru64(int fd, __u8 opcode, __u8 flags, __u16 rsvd, /** * nvme_submit_io_passthru() - Submit an nvme passthrough command - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @cmd: The nvme io command to send * @result: Optional field to return the result from the CQE dword 0 * @result: Optional field to return the result from the CQE DW0 * * Uses NVME_IOCTL_IO_CMD for the ioctl request. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_submit_io_passthru(int fd, struct nvme_passthru_cmd *cmd, +int nvme_submit_io_passthru(struct nvme_transport_handle *hdl, struct nvme_passthru_cmd *cmd, __u32 *result); /** * nvme_io_passthru() - Submit an nvme io passthrough command - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @opcode: The nvme io command to send * @flags: NVMe command flags (not used) * @rsvd: Reserved for future use @@ -522,10 +687,10 @@ int nvme_submit_io_passthru(int fd, struct nvme_passthru_cmd *cmd, * * Known values for @opcode are defined in &enum nvme_io_opcode. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_io_passthru(int fd, __u8 opcode, __u8 flags, __u16 rsvd, +int nvme_io_passthru(struct nvme_transport_handle *hdl, __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, @@ -533,38 +698,38 @@ int nvme_io_passthru(int fd, __u8 opcode, __u8 flags, __u16 rsvd, /** * nvme_subsystem_reset() - Initiate a subsystem reset - * @fd: File descriptor of nvme device + * @hdl: Transport handle * * This should only be sent to controller handles, not to namespaces. * * Return: Zero if a subsystem reset was initiated or -1 with errno set * otherwise. */ -int nvme_subsystem_reset(int fd); +int nvme_subsystem_reset(struct nvme_transport_handle *hdl); /** * nvme_ctrl_reset() - Initiate a controller reset - * @fd: File descriptor of nvme device + * @hdl: Transport handle * * This should only be sent to controller handles, not to namespaces. * * Return: 0 if a reset was initiated or -1 with errno set otherwise. */ -int nvme_ctrl_reset(int fd); +int nvme_ctrl_reset(struct nvme_transport_handle *hdl); /** * nvme_ns_rescan() - Initiate a controller rescan - * @fd: File descriptor of nvme device + * @hdl: Transport handle * * This should only be sent to controller handles, not to namespaces. * * Return: 0 if a rescan was initiated or -1 with errno set otherwise. */ -int nvme_ns_rescan(int fd); +int nvme_ns_rescan(struct nvme_transport_handle *hdl); /** * nvme_get_nsid() - Retrieve the NSID from a namespace file descriptor - * @fd: File descriptor of nvme namespace + * @hdl: Transport handle * @nsid: User pointer to namespace id * * This should only be sent to namespace handles, not to controllers. The @@ -574,4024 +739,6544 @@ int nvme_ns_rescan(int fd); * * Return: 0 if @nsid was set successfully or -1 with errno set otherwise. */ -int nvme_get_nsid(int fd, __u32 *nsid); +int nvme_get_nsid(struct nvme_transport_handle *hdl, __u32 *nsid); /** - * nvme_identify() - Send the NVMe Identify command - * @args: &struct nvme_identify_args argument structure - * - * The Identify command returns a data buffer that describes information about - * the NVM subsystem, the controller or the namespace(s). + * nvme_init_identify() - Initialize passthru command for + * NVMe Identify + * @cmd: Command data structure to initialize + * @nsid: Namespace identifier + * @csi: Command Set Identifier + * @cns: The Controller or Namespace structure, + * see @enum nvme_identify_cns + * @data: User space destination address to transfer the data + * @len: Length of provided user buffer to hold the data in bytes * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Prepare the @cmd data structure for the NVMe Identify command. */ -int nvme_identify(struct nvme_identify_args *args); - -static inline int nvme_identify_cns_nsid(int fd, enum nvme_identify_cns cns, - __u32 nsid, void *data) +static inline void +nvme_init_identify(struct nvme_passthru_cmd *cmd, + __u32 nsid, enum nvme_csi csi, enum nvme_identify_cns cns, + void *data, __u32 len) { - struct nvme_identify_args args = { - .result = NULL, - .data = data, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cns = cns, - .csi = NVME_CSI_NVM, - .nsid = nsid, - .cntid = NVME_CNTLID_NONE, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_identify(&args); + __u32 cdw10 = NVME_FIELD_ENCODE(cns, + NVME_IDENTIFY_CDW10_CNS_SHIFT, + NVME_IDENTIFY_CDW10_CNS_MASK); + __u32 cdw11 = NVME_FIELD_ENCODE(csi, + NVME_IDENTIFY_CDW11_CSI_SHIFT, + NVME_IDENTIFY_CDW11_CSI_MASK); + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_identify; + cmd->nsid = nsid; + cmd->cdw10 = cdw10; + cmd->cdw11 = cdw11; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; } /** - * nvme_identify_ctrl() - Retrieves nvme identify controller - * @fd: File descriptor of nvme device - * @id: User space destination address to transfer the data, - * - * Sends nvme identify with CNS value %NVME_IDENTIFY_CNS_CTRL. - * - * See &struct nvme_id_ctrl for details on the data returned. + * nvme_init_identify_ns() - Initialize passthru command for + * NVMe Identify Namespace data structure + * @cmd: Command data structure to initialize + * @nsid: Namespace identifier + * @id: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_NS. */ -static inline int nvme_identify_ctrl(int fd, struct nvme_id_ctrl *id) +static inline void +nvme_init_identify_ns(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_id_ns *id) { - return nvme_identify_cns_nsid(fd, NVME_IDENTIFY_CNS_CTRL, - NVME_NSID_NONE, id); + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_NS, + id, sizeof(*id)); } /** - * nvme_identify_ns() - Retrieves nvme identify namespace - * @fd: File descriptor of nvme device - * @nsid: Namespace to identify - * @ns: User space destination address to transfer the data - * - * If the Namespace Identifier (NSID) field specifies an active NSID, then the - * Identify Namespace data structure is returned to the host for that specified - * namespace. - * - * If the controller supports the Namespace Management capability and the NSID - * field is set to %NVME_NSID_ALL, then the controller returns an Identify Namespace - * data structure that specifies capabilities that are common across namespaces - * for this controller. - * - * See &struct nvme_id_ns for details on the structure returned. + * nvme_init_identify_ctrl() - Initialize passthru command for + * NVMe Identify Controller data structure + * @cmd: Command data structure to initialize + * @id: User space destination address to transfer the data, * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CTRL. */ -static inline int nvme_identify_ns(int fd, __u32 nsid, struct nvme_id_ns *ns) +static inline void +nvme_init_identify_ctrl(struct nvme_passthru_cmd *cmd, struct nvme_id_ctrl *id) { - return nvme_identify_cns_nsid(fd, NVME_IDENTIFY_CNS_NS, nsid, ns); + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_CTRL, + id, sizeof(*id)); } /** - * nvme_identify_allocated_ns() - Same as nvme_identify_ns, but only for - * allocated namespaces - * @fd: File descriptor of nvme device - * @nsid: Namespace to identify - * @ns: User space destination address to transfer the data + * nvme_init_identify_active_ns_list() - Initialize passthru command for + * Active Namespaces ID list + * @cmd: Command data structure to initialize + * @nsid: Namespace identifier + * @list: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_NS_ACTIVE_LIST. */ -static inline int nvme_identify_allocated_ns(int fd, __u32 nsid, - struct nvme_id_ns *ns) +static inline void +nvme_init_identify_active_ns_list(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_ns_list *list) { - return nvme_identify_cns_nsid(fd, NVME_IDENTIFY_CNS_ALLOCATED_NS, - nsid, ns); + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_NS_ACTIVE_LIST, + list, sizeof(*list)); } /** - * nvme_identify_active_ns_list() - Retrieves active namespaces id list - * @fd: File descriptor of nvme device - * @nsid: Return namespaces greater than this identifier - * @list: User space destination address to transfer the data - * - * A list of 1024 namespace IDs is returned to the host containing NSIDs in - * increasing order that are greater than the value specified in the Namespace - * Identifier (nsid) field of the command. - * - * See &struct nvme_ns_list for the definition of the returned structure. + * nvme_init_identify_ns_descs_list() - Initialize passthru command for + * Namespace Descriptor list + * @cmd: Command data structure to initialize + * @nsid: The namespace id to retrieve descriptors + * @descs: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_NS_DESC_LIST. */ -static inline int nvme_identify_active_ns_list(int fd, __u32 nsid, - struct nvme_ns_list *list) +static inline void +nvme_init_identify_ns_descs_list(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_ns_id_desc *descs) { - return nvme_identify_cns_nsid(fd, NVME_IDENTIFY_CNS_NS_ACTIVE_LIST, - nsid, list); + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_NS_DESC_LIST, + descs, NVME_IDENTIFY_DATA_SIZE); } /** - * nvme_identify_allocated_ns_list() - Retrieves allocated namespace id list - * @fd: File descriptor of nvme device - * @nsid: Return namespaces greater than this identifier - * @list: User space destination address to transfer the data - * - * A list of 1024 namespace IDs is returned to the host containing NSIDs in - * increasing order that are greater than the value specified in the Namespace - * Identifier (nsid) field of the command. - * - * See &struct nvme_ns_list for the definition of the returned structure. + * nvme_init_identify_nvmset_list() - Initialize passthru command for + * NVM Set List data structure + * @cmd: Command data structure to initialize + * @nsid: Namespace identifier + * @nvmsetid: NVM Set Identifier + * @nvmset: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_NS_ACTIVE_LIST. */ -static inline int nvme_identify_allocated_ns_list(int fd, __u32 nsid, - struct nvme_ns_list *list) +static inline void +nvme_init_identify_nvmset_list(struct nvme_passthru_cmd *cmd, + __u32 nsid, __u16 nvmsetid, struct nvme_id_nvmset_list *nvmset) { - return nvme_identify_cns_nsid(fd, NVME_IDENTIFY_CNS_ALLOCATED_NS_LIST, - nsid, list); + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_NVMSET_LIST, + nvmset, sizeof(*nvmset)); + cmd->cdw11 |= NVME_FIELD_ENCODE(nvmsetid, + NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT, + NVME_IDENTIFY_CDW11_CNSSPECID_MASK); } /** - * nvme_identify_ctrl_list() - Retrieves identify controller list - * @fd: File descriptor of nvme device - * @cntid: Starting CNTLID to return in the list - * @cntlist: User space destination address to transfer the data - * - * Up to 2047 controller identifiers is returned containing a controller - * identifier greater than or equal to the controller identifier specified in - * @cntid. - * - * See &struct nvme_ctrl_list for a definition of the structure returned. + * nvme_init_identify_csi_ns() - Initialize passthru command for + * I/O Command Set specific Identify Namespace data structure + * @cmd: Command data structure to initialize + * @nsid: Namespace identifier + * @csi: Command Set Identifier + * @uidx: UUID Index for differentiating vendor specific encoding + * @data: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CSI_NS. */ -static inline int nvme_identify_ctrl_list(int fd, __u16 cntid, - struct nvme_ctrl_list *cntlist) +static inline void +nvme_init_identify_csi_ns(struct nvme_passthru_cmd *cmd, + __u32 nsid, enum nvme_csi csi, __u8 uidx, void *data) { - struct nvme_identify_args args = { - .result = NULL, - .data = cntlist, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cns = NVME_IDENTIFY_CNS_CTRL_LIST, - .csi = NVME_CSI_NVM, - .nsid = NVME_NSID_NONE, - .cntid = cntid, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_identify(&args); + nvme_init_identify(cmd, nsid, csi, + NVME_IDENTIFY_CNS_CSI_NS, + data, NVME_IDENTIFY_DATA_SIZE); + cmd->cdw14 |= NVME_FIELD_ENCODE(uidx, + NVME_IDENTIFY_CDW14_UUID_SHIFT, + NVME_IDENTIFY_CDW14_UUID_MASK); } /** - * nvme_identify_nsid_ctrl_list() - Retrieves controller list attached to an nsid - * @fd: File descriptor of nvme device - * @nsid: Return controllers that are attached to this nsid - * @cntid: Starting CNTLID to return in the list - * @cntlist: User space destination address to transfer the data - * - * Up to 2047 controller identifiers are returned containing a controller - * identifier greater than or equal to the controller identifier specified in - * @cntid attached to @nsid. - * - * See &struct nvme_ctrl_list for a definition of the structure returned. + * nvme_init_identify_csi_ctrl() - Initialize passthru command for + * I/O Command Set specific Identify Controller data structure + * @cmd: Command data structure to initialize + * @csi: Command Set Identifier + * @data: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CSI_CTRL. */ -static inline int nvme_identify_nsid_ctrl_list(int fd, __u32 nsid, __u16 cntid, - struct nvme_ctrl_list *cntlist) +static inline void +nvme_init_identify_csi_ctrl(struct nvme_passthru_cmd *cmd, + enum nvme_csi csi, void *data) { - struct nvme_identify_args args = { - .result = NULL, - .data = cntlist, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cns = NVME_IDENTIFY_CNS_NS_CTRL_LIST, - .csi = NVME_CSI_NVM, - .nsid = nsid, - .cntid = cntid, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_identify(&args); + nvme_init_identify(cmd, NVME_NSID_NONE, csi, + NVME_IDENTIFY_CNS_CSI_CTRL, + data, NVME_IDENTIFY_DATA_SIZE); } /** - * nvme_identify_ns_descs() - Retrieves namespace descriptor list - * @fd: File descriptor of nvme device - * @nsid: The namespace id to retrieve descriptors - * @descs: User space destination address to transfer the data - * - * A list of Namespace Identification Descriptor structures is returned to the - * host for the namespace specified in the Namespace Identifier (NSID) field if - * it is an active NSID. - * - * The data returned is in the form of an array of 'struct nvme_ns_id_desc'. - * - * See &struct nvme_ns_id_desc for the definition of the returned structure. + * nvme_init_identify_csi_active_ns_list() - Initialize passthru command + * for Active namespace ID list + * @cmd: Command data structure to initialize + * @nsid: Return namespaces greater than this identifier + * @csi: Command Set Identifier + * @ns_list: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CSI_NS_ACTIVE_LIST. */ -static inline int nvme_identify_ns_descs(int fd, __u32 nsid, - struct nvme_ns_id_desc *descs) +static inline void +nvme_init_identify_csi_active_ns_list(struct nvme_passthru_cmd *cmd, + __u32 nsid, enum nvme_csi csi, struct nvme_ns_list *ns_list) { - return nvme_identify_cns_nsid(fd, NVME_IDENTIFY_CNS_NS_DESC_LIST, - nsid, descs); + nvme_init_identify(cmd, nsid, csi, + NVME_IDENTIFY_CNS_CSI_NS_ACTIVE_LIST, + ns_list, sizeof(*ns_list)); } /** - * nvme_identify_nvmset_list() - Retrieves NVM Set List - * @fd: File descriptor of nvme device - * @nvmsetid: NVM Set Identifier - * @nvmset: User space destination address to transfer the data - * - * Retrieves an NVM Set List, &struct nvme_id_nvmset_list. The data structure - * is an ordered list by NVM Set Identifier, starting with the first NVM Set - * Identifier supported by the NVM subsystem that is equal to or greater than - * the NVM Set Identifier. - * - * See &struct nvme_id_nvmset_list for the definition of the returned structure. + * nvme_init_identify_csi_independent_identify_id_ns() -Initialize passthru + * command for I/O Command Set Independent Identify Namespace data structure + * @cmd: Command data structure to initialize + * @nsid: Return namespaces greater than this identifier + * @ns: I/O Command Set Independent Identify Namespace data + * structure * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CSI_INDEPENDENT_ID_NS. */ -static inline int nvme_identify_nvmset_list(int fd, __u16 nvmsetid, - struct nvme_id_nvmset_list *nvmset) +static inline void +nvme_init_identify_csi_independent_identify_id_ns(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_id_independent_id_ns *ns) { - struct nvme_identify_args args = { - .result = NULL, - .data = nvmset, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cns = NVME_IDENTIFY_CNS_NVMSET_LIST, - .csi = NVME_CSI_NVM, - .nsid = NVME_NSID_NONE, - .cntid = NVME_CNTLID_NONE, - .cns_specific_id = nvmsetid, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_identify(&args); + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_CSI_INDEPENDENT_ID_NS, + ns, sizeof(*ns)); } /** - * nvme_identify_primary_ctrl() - Retrieve NVMe Primary Controller - * identification - * @fd: File descriptor of nvme device - * @cntid: Return controllers starting at this identifier - * @cap: User space destination buffer address to transfer the data - * - * See &struct nvme_primary_ctrl_cap for the definition of the returned structure, @cap. + * nvme_init_identify_ns_user_data_format() - Initialize passthru command + * for Identify namespace user data format + * @cmd: Command data structure to initialize + * @csi: Command Set Identifier + * @fidx: Format Index + * @uidx: UUID selection, if supported + * @data: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_NS_USER_DATA_FORMAT. */ -static inline int nvme_identify_primary_ctrl(int fd, __u16 cntid, - struct nvme_primary_ctrl_cap *cap) +static inline void +nvme_init_identify_ns_user_data_format(struct nvme_passthru_cmd *cmd, + enum nvme_csi csi, __u16 fidx, __u8 uidx, void *data) { - struct nvme_identify_args args = { - .result = NULL, - .data = cap, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cns = NVME_IDENTIFY_CNS_PRIMARY_CTRL_CAP, - .csi = NVME_CSI_NVM, - .nsid = NVME_NSID_NONE, - .cntid = cntid, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_identify(&args); + nvme_init_identify(cmd, NVME_NSID_NONE, csi, + NVME_IDENTIFY_CNS_NS_USER_DATA_FORMAT, + data, NVME_IDENTIFY_DATA_SIZE); + cmd->cdw11 |= NVME_FIELD_ENCODE(fidx, + NVME_IDENTIFY_CDW11_FIDX_SHIFT, + NVME_IDENTIFY_CDW11_FIDX_MASK); + cmd->cdw14 |= NVME_FIELD_ENCODE(uidx, + NVME_IDENTIFY_CDW14_UUID_SHIFT, + NVME_IDENTIFY_CDW14_UUID_MASK); } /** - * nvme_identify_secondary_ctrl_list() - Retrieves secondary controller list - * @fd: File descriptor of nvme device - * @cntid: Return controllers starting at this identifier - * @sc_list: User space destination address to transfer the data - * - * A Secondary Controller List is returned to the host for up to 127 secondary - * controllers associated with the primary controller processing this command. - * The list contains entries for controller identifiers greater than or equal - * to the value specified in the Controller Identifier (cntid). - * - * See &struct nvme_secondary_ctrls_list for a definition of the returned - * structure. + * nvme_init_identify_csi_ns_user_data_format() - Initialize passthru + * command for Identify namespace user data format + * @cmd: Command data structure to initialize + * @csi: Command Set Identifier + * @fidx: Format Index + * @uidx: UUID selection, if supported + * @data: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CSI_NS_USER_DATA_FORMAT. */ -static inline int nvme_identify_secondary_ctrl_list(int fd, - __u16 cntid, struct nvme_secondary_ctrl_list *sc_list) +static inline void +nvme_init_identify_csi_ns_user_data_format(struct nvme_passthru_cmd *cmd, + enum nvme_csi csi, __u16 fidx, __u8 uidx, void *data) { - struct nvme_identify_args args = { - .result = NULL, - .data = sc_list, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cns = NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST, - .csi = NVME_CSI_NVM, - .nsid = NVME_NSID_NONE, - .cntid = cntid, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_identify(&args); + nvme_init_identify(cmd, NVME_NSID_NONE, csi, + NVME_IDENTIFY_CNS_CSI_NS_USER_DATA_FORMAT, + data, NVME_IDENTIFY_DATA_SIZE); + cmd->cdw11 |= NVME_FIELD_ENCODE(fidx, + NVME_IDENTIFY_CDW11_FIDX_SHIFT, + NVME_IDENTIFY_CDW11_FIDX_MASK); + cmd->cdw14 |= NVME_FIELD_ENCODE(uidx, + NVME_IDENTIFY_CDW14_UUID_SHIFT, + NVME_IDENTIFY_CDW14_UUID_MASK); } /** - * nvme_identify_ns_granularity() - Retrieves namespace granularity - * identification - * @fd: File descriptor of nvme device - * @gr_list: User space destination address to transfer the data - * - * If the controller supports reporting of Namespace Granularity, then a - * Namespace Granularity List is returned to the host for up to sixteen - * namespace granularity descriptors - * - * See &struct nvme_id_ns_granularity_list for the definition of the returned - * structure. + * nvme_init_identify_allocated_ns_list() - Initialize passthru command + * for Allocated namespace ID list + * @cmd: Command data structure to initialize + * @nsid: Return namespaces greater than this identifier + * @ns_list: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_ALLOCATED_NS_LIST. */ -static inline int nvme_identify_ns_granularity(int fd, - struct nvme_id_ns_granularity_list *gr_list) +static inline void +nvme_init_identify_allocated_ns_list(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_ns_list *ns_list) { - return nvme_identify_cns_nsid(fd, NVME_IDENTIFY_CNS_NS_GRANULARITY, - NVME_NSID_NONE, gr_list); + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_ALLOCATED_NS_LIST, + ns_list, sizeof(*ns_list)); } /** - * nvme_identify_uuid() - Retrieves device's UUIDs - * @fd: File descriptor of nvme device - * @uuid_list: User space destination address to transfer the data - * - * Each UUID List entry is either 0h, the NVMe Invalid UUID, or a valid UUID. - * Valid UUIDs are those which are non-zero and are not the NVMe Invalid UUID. - * - * See &struct nvme_id_uuid_list for the definition of the returned structure. + * nvme_init_identify_allocated_ns() - Initialize passthru command + * for allocated Namespace ID list + * @cmd: Command data structure to initialize + * @nsid: Namespace to identify + * @ns: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_ALLOCATED_NS. */ -static inline int nvme_identify_uuid(int fd, struct nvme_id_uuid_list *uuid_list) +static inline void +nvme_init_identify_allocated_ns(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_id_ns *ns) { - return nvme_identify_cns_nsid(fd, NVME_IDENTIFY_CNS_UUID_LIST, - NVME_NSID_NONE, uuid_list); + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_ALLOCATED_NS, + ns, sizeof(*ns)); } /** - * nvme_identify_ns_csi() - I/O command set specific identify namespace data - * @fd: File descriptor of nvme device - * @nsid: Namespace to identify - * @uuidx: UUID Index for differentiating vendor specific encoding - * @csi: Command Set Identifier - * @data: User space destination address to transfer the data - * - * An I/O Command Set specific Identify Namespace data structure is returned - * for the namespace specified in @nsid. + * nvme_init_identify_ns_ctrl_list() - Initialize passhtru command + * for Controller List + * @cmd: Command data structure to initialize + * @nsid: Return controllers that are attached to this nsid + * @cntid: Starting CNTLID to return in the list + * @cntlist: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_NS_CTRL_LIST. */ -static inline int nvme_identify_ns_csi(int fd, __u32 nsid, __u8 uuidx, - enum nvme_csi csi, void *data) +static inline void +nvme_init_identify_ns_ctrl_list(struct nvme_passthru_cmd *cmd, + __u32 nsid, __u16 cntid, struct nvme_ctrl_list *cntlist) { - struct nvme_identify_args args = { - .result = NULL, - .data = data, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cns = NVME_IDENTIFY_CNS_CSI_NS, - .csi = csi, - .nsid = nsid, - .cntid = NVME_CNTLID_NONE, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = uuidx, - }; - - return nvme_identify(&args); + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_NS_CTRL_LIST, + cntlist, sizeof(*cntlist)); + cmd->cdw10 |= NVME_FIELD_ENCODE(cntid, + NVME_IDENTIFY_CDW10_CNTID_SHIFT, + NVME_IDENTIFY_CDW10_CNTID_MASK); } /** - * nvme_identify_ctrl_csi() - I/O command set specific Identify Controller data - * @fd: File descriptor of nvme device - * @csi: Command Set Identifier - * @data: User space destination address to transfer the data - * - * An I/O Command Set specific Identify Controller data structure is returned - * to the host for the controller processing the command. The specific Identify - * Controller data structure to be returned is specified by @csi. + * nvme_init_identify_ctrl_list() - Initialize passthru command for + * Controller List of controllers + * @cmd: Command data structure to initialize + * @cntid: Starting CNTLID to return in the list + * @cntlist: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CTRL_LIST. */ -static inline int nvme_identify_ctrl_csi(int fd, enum nvme_csi csi, void *data) +static inline void +nvme_init_identify_ctrl_list(struct nvme_passthru_cmd *cmd, + __u16 cntid, struct nvme_ctrl_list *cntlist) { - struct nvme_identify_args args = { - .result = NULL, - .data = data, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cns = NVME_IDENTIFY_CNS_CSI_CTRL, - .csi = csi, - .nsid = NVME_NSID_NONE, - .cntid = NVME_CNTLID_NONE, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_identify(&args); + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_CTRL_LIST, + cntlist, sizeof(*cntlist)); + cmd->cdw10 |= NVME_FIELD_ENCODE(cntid, + NVME_IDENTIFY_CDW10_CNTID_SHIFT, + NVME_IDENTIFY_CDW10_CNTID_MASK); } /** - * nvme_identify_active_ns_list_csi() - Active namespace ID list associated with a specified I/O command set - * @fd: File descriptor of nvme device - * @nsid: Return namespaces greater than this identifier - * @csi: Command Set Identifier - * @ns_list: User space destination address to transfer the data - * - * A list of 1024 namespace IDs is returned to the host containing active - * NSIDs in increasing order that are greater than the value specified in - * the Namespace Identifier (nsid) field of the command and matching the - * I/O Command Set specified in the @csi argument. - * - * See &struct nvme_ns_list for the definition of the returned structure. + * nvme_init_identify_primary_ctrl_cap() - Initialize passthru command + * for Primary Controller Capabilities data + * @cmd: Command data structure to initialize + * @cntid: Return controllers starting at this identifier + * @cap: User space destination buffer address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_PRIMARY_CTRL_CAP. */ -static inline int nvme_identify_active_ns_list_csi(int fd, __u32 nsid, - enum nvme_csi csi, struct nvme_ns_list *ns_list) +static inline void +nvme_init_identify_primary_ctrl_cap(struct nvme_passthru_cmd *cmd, + __u16 cntid, struct nvme_primary_ctrl_cap *cap) { - struct nvme_identify_args args = { - .result = NULL, - .data = ns_list, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cns = NVME_IDENTIFY_CNS_CSI_NS_ACTIVE_LIST, - .csi = csi, - .nsid = nsid, - .cntid = NVME_CNTLID_NONE, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_identify(&args); + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_PRIMARY_CTRL_CAP, + cap, sizeof(*cap)); + cmd->cdw10 |= NVME_FIELD_ENCODE(cntid, + NVME_IDENTIFY_CDW10_CNTID_SHIFT, + NVME_IDENTIFY_CDW10_CNTID_MASK); } /** - * nvme_identify_allocated_ns_list_csi() - Allocated namespace ID list associated with a specified I/O command set - * @fd: File descriptor of nvme device - * @nsid: Return namespaces greater than this identifier - * @csi: Command Set Identifier - * @ns_list: User space destination address to transfer the data - * - * A list of 1024 namespace IDs is returned to the host containing allocated - * NSIDs in increasing order that are greater than the value specified in - * the @nsid field of the command and matching the I/O Command Set - * specified in the @csi argument. - * - * See &struct nvme_ns_list for the definition of the returned structure. + * nvme_init_identify_secondary_ctrl_list() - Initialize passhru command + * for Secondary Controller list + * @cmd: Command data structure to initialize + * @cntid: Return controllers starting at this identifier + * @sc_list: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST. */ -static inline int nvme_identify_allocated_ns_list_csi(int fd, __u32 nsid, - enum nvme_csi csi, struct nvme_ns_list *ns_list) +static inline void +nvme_init_identify_secondary_ctrl_list(struct nvme_passthru_cmd *cmd, + __u16 cntid, struct nvme_secondary_ctrl_list *sc_list) { - struct nvme_identify_args args = { - .result = NULL, - .data = ns_list, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cns = NVME_IDENTIFY_CNS_CSI_ALLOCATED_NS_LIST, - .csi = csi, - .nsid = nsid, - .cntid = NVME_CNTLID_NONE, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_identify(&args); + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST, + sc_list, sizeof(*sc_list)); + cmd->cdw10 |= NVME_FIELD_ENCODE(cntid, + NVME_IDENTIFY_CDW10_CNTID_SHIFT, + NVME_IDENTIFY_CDW10_CNTID_MASK); } + /** - * nvme_identify_independent_identify_ns() - I/O command set independent Identify namespace data - * @fd: File descriptor of nvme device - * @nsid: Return namespaces greater than this identifier - * @ns: I/O Command Set Independent Identify Namespace data - * structure - * - * The I/O command set independent Identify namespace data structure for - * the namespace identified with @ns is returned to the host. + * nvme_init_identify_ns_granularity() - Initialize passthru command for + * Namespace Granularity list + * @cmd: Command data structure to initialize + * @gr_list: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST. */ -static inline int nvme_identify_independent_identify_ns(int fd, __u32 nsid, - struct nvme_id_independent_id_ns *ns) +static inline void +nvme_init_identify_ns_granularity(struct nvme_passthru_cmd *cmd, + struct nvme_id_ns_granularity_list *gr_list) { - return nvme_identify_cns_nsid( - fd, NVME_IDENTIFY_CNS_CSI_INDEPENDENT_ID_NS, nsid, ns); + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_NS_GRANULARITY, + gr_list, sizeof(*gr_list)); } /** - * nvme_identify_ns_csi_user_data_format() - Identify namespace user data format - * @fd: File descriptor of nvme device - * @user_data_format: Return namespaces capability of identifier - * @uuidx: UUID selection, if supported - * @csi: Command Set Identifier - * @data: User space destination address to transfer the data - * - * Identify Namespace data structure for the specified User Data Format - * index containing the namespace capabilities for the NVM Command Set. + * nvme_init_identify_uuid_list() - Initialize passthru command for + * UUID list + * @cmd: Command data structure to initialize + * @uuid_list: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_UUID_LIST. */ -static inline int nvme_identify_ns_csi_user_data_format(int fd, - __u16 user_data_format, __u8 uuidx, - enum nvme_csi csi, void *data) +static inline void +nvme_init_identify_uuid_list(struct nvme_passthru_cmd *cmd, + struct nvme_id_uuid_list *uuid_list) { - struct nvme_identify_args args = { - .result = NULL, - .data = data, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cns = NVME_IDENTIFY_CNS_NS_USER_DATA_FORMAT, - .csi = csi, - .nsid = NVME_NSID_NONE, - .cntid = NVME_CNTLID_NONE, - .cns_specific_id = user_data_format, - .uuidx = uuidx, - }; - - return nvme_identify(&args); + nvme_init_identify(cmd, NVME_UUID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_UUID_LIST, + uuid_list, sizeof(*uuid_list)); } /** - * nvme_identify_iocs_ns_csi_user_data_format() - Identify I/O command set namespace data structure - * @fd: File descriptor of nvme device - * @user_data_format: Return namespaces capability of identifier - * @uuidx: UUID selection, if supported - * @csi: Command Set Identifier - * @data: User space destination address to transfer the data - * - * I/O Command Set specific Identify Namespace data structure for - * the specified User Data Format index containing the namespace - * capabilities for the I/O Command Set specified in the CSI field. + * nvme_init_identify_domain_list() - Initialize passthru command for + * Domain list + * @cmd: Command data structure to initialize + * @domid: Domain ID + * @list: User space destination address to transfer data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_DOMAIN_LIST. */ -static inline int nvme_identify_iocs_ns_csi_user_data_format(int fd, - __u16 user_data_format, __u8 uuidx, - enum nvme_csi csi, void *data) +static inline void +nvme_init_identify_domain_list(struct nvme_passthru_cmd *cmd, + __u16 domid, struct nvme_id_domain_list *list) { - struct nvme_identify_args args = { - .result = NULL, - .data = data, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cns = NVME_IDENTIFY_CNS_CSI_NS_USER_DATA_FORMAT, - .csi = csi, - .nsid = NVME_NSID_NONE, - .cntid = NVME_CNTLID_NONE, - .cns_specific_id = user_data_format, - .uuidx = uuidx, - }; - - return nvme_identify(&args); + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_DOMAIN_LIST, + list, sizeof(*list)); + cmd->cdw11 |= NVME_FIELD_ENCODE(domid, + NVME_IDENTIFY_CDW11_DOMID_SHIFT, + NVME_IDENTIFY_CDW11_DOMID_MASK); } /** - * nvme_nvm_identify_ctrl() - Identify controller data - * @fd: File descriptor of nvme device - * @id: User space destination address to transfer the data - * - * Return an identify controller data structure to the host of - * processing controller. + * nvme_init_identify_endurance_group_id() - Initialize passthru command for + * Endurance group list + * @cmd: Command data structure to initialize + * @enggid: Endurance group identifier + * @list: Array of endurance group identifiers * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -static inline int nvme_nvm_identify_ctrl(int fd, struct nvme_id_ctrl_nvm *id) +static inline void +nvme_init_identify_endurance_group_id(struct nvme_passthru_cmd *cmd, + __u16 enggid, struct nvme_id_endurance_group_list *list) { - return nvme_identify_ctrl_csi(fd, NVME_CSI_NVM, id); + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_ENDURANCE_GROUP_ID, + list, sizeof(*list)); + cmd->cdw11 |= NVME_FIELD_ENCODE(enggid, + NVME_IDENTIFY_CDW11_ENGGID_SHIFT, + NVME_IDENTIFY_CDW11_ENGGID_MASK); } /** - * nvme_identify_domain_list() - Domain list data - * @fd: File descriptor of nvme device - * @domid: Domain ID - * @list: User space destination address to transfer data - * - * A list of 31 domain IDs is returned to the host containing domain - * attributes in increasing order that are greater than the value - * specified in the @domid field. - * - * See &struct nvme_identify_domain_attr for the definition of the - * returned structure. + * nvme_init_identify_csi_allocated_ns_list() - Initialize passthru command for + * I/O Command Set specific Allocated Namespace Id list + * @cmd: Command data structure to initialize + * @nsid: Return namespaces greater than this identifier + * @csi: Command Set Identifier + * @ns_list: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CSI_ALLOCATED_NS_LIST. */ -static inline int nvme_identify_domain_list(int fd, __u16 domid, - struct nvme_id_domain_list *list) +static inline void +nvme_init_identify_csi_allocated_ns_list(struct nvme_passthru_cmd *cmd, + __u32 nsid, enum nvme_csi csi, struct nvme_ns_list *ns_list) { - struct nvme_identify_args args = { - .result = NULL, - .data = list, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cns = NVME_IDENTIFY_CNS_DOMAIN_LIST, - .csi = NVME_CSI_NVM, - .nsid = NVME_NSID_NONE, - .cntid = NVME_CNTLID_NONE, - .cns_specific_id = domid, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_identify(&args); + nvme_init_identify(cmd, nsid, csi, + NVME_IDENTIFY_CNS_CSI_ALLOCATED_NS_LIST, + ns_list, sizeof(*ns_list)); } /** - * nvme_identify_endurance_group_list() - Endurance group list data - * @fd: File descriptor of nvme device - * @endgrp_id: Endurance group identifier - * @list: Array of endurance group identifiers + * nvme_init_identify_csi_id_ns_data_structure() - Initialize passthru command for + * I/O Command Set specific Identify Namespace data structure + * @cmd: Command data structure to initialize + * @nsid: Return namespaces greater than this identifier + * @csi: Command Set Identifier + * @data: User space destination address to transfer the data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CSI_ID_NS_DATA_STRUCTURE. */ -static inline int nvme_identify_endurance_group_list(int fd, __u16 endgrp_id, - struct nvme_id_endurance_group_list *list) +static inline void +nvme_init_identify_csi_id_ns_data_structure(struct nvme_passthru_cmd *cmd, + __u32 nsid, enum nvme_csi csi, void *data) { - struct nvme_identify_args args = { - .result = NULL, - .data = list, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cns = NVME_IDENTIFY_CNS_ENDURANCE_GROUP_ID, - .csi = NVME_CSI_NVM, - .nsid = NVME_NSID_NONE, - .cntid = NVME_CNTLID_NONE, - .cns_specific_id = endgrp_id, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_identify(&args); + nvme_init_identify(cmd, nsid, csi, + NVME_IDENTIFY_CNS_CSI_ID_NS_DATA_STRUCTURE, + data, NVME_IDENTIFY_DATA_SIZE); } /** - * nvme_identify_iocs() - I/O command set data structure - * @fd: File descriptor of nvme device - * @cntlid: Controller ID + * nvme_init_identify_command_set_structure() - Initialize passthru command for + * I/O Command Set data structure + * @cmd: Command data structure to initialize + * @cntid: Controller ID * @iocs: User space destination address to transfer the data * * Retrieves list of the controller's supported io command set vectors. See * &struct nvme_id_iocs. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -static inline int nvme_identify_iocs(int fd, __u16 cntlid, - struct nvme_id_iocs *iocs) +static inline void +nvme_init_identify_command_set_structure(struct nvme_passthru_cmd *cmd, + __u16 cntid, struct nvme_id_iocs *iocs) { - struct nvme_identify_args args = { - .result = NULL, - .data = iocs, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cns = NVME_IDENTIFY_CNS_COMMAND_SET_STRUCTURE, - .csi = NVME_CSI_NVM, - .nsid = NVME_NSID_NONE, - .cntid = cntlid, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_identify(&args); + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_COMMAND_SET_STRUCTURE, + iocs, sizeof(*iocs)); + cmd->cdw10 |= NVME_FIELD_ENCODE(cntid, + NVME_IDENTIFY_CDW10_CNTID_SHIFT, + NVME_IDENTIFY_CDW10_CNTID_MASK); } /** - * nvme_zns_identify_ns() - ZNS identify namespace data - * @fd: File descriptor of nvme device + * nvme_init_zns_identify_ns() - Initialize passthru command for + * ZNS identify namespace data + * @cmd: Command data structure to initialize * @nsid: Namespace to identify * @data: User space destination address to transfer the data - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. */ -static inline int nvme_zns_identify_ns(int fd, __u32 nsid, - struct nvme_zns_id_ns *data) +static inline void +nvme_init_zns_identify_ns(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_zns_id_ns *data) { - return nvme_identify_ns_csi( - fd, nsid, NVME_UUID_NONE, NVME_CSI_ZNS, data); + nvme_init_identify(cmd, nsid, NVME_CSI_ZNS, + NVME_IDENTIFY_CNS_CSI_NS, + data, sizeof(*data)); } /** - * nvme_zns_identify_ctrl() - ZNS identify controller data - * @fd: File descriptor of nvme device + * nvme_init_zns_identify_ctrl() - Initialize passthru command for + * ZNS identify controller data + * @cmd: Command data structure to initialize * @id: User space destination address to transfer the data - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. */ -static inline int nvme_zns_identify_ctrl(int fd, struct nvme_zns_id_ctrl *id) +static inline void +nvme_init_zns_identify_ctrl(struct nvme_passthru_cmd *cmd, + struct nvme_zns_id_ctrl *id) { - return nvme_identify_ctrl_csi(fd, NVME_CSI_ZNS, id); + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_ZNS, + NVME_IDENTIFY_CNS_CSI_CTRL, + id, sizeof(*id)); } /** - * nvme_get_log() - NVMe Admin Get Log command - * @args: &struct nvme_get_log_args argument structure + * nvme_get_log() - Get log page data + * @hdl: Transport handle + * @cmd: Passthru command + * @rae: Retain asynchronous events + * @xfer_len: Max log transfer size per request to split the total. + * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_get_log(struct nvme_get_log_args *args); +int nvme_get_log(struct nvme_transport_handle *hdl, + struct nvme_passthru_cmd *cmd, bool rae, + __u32 xfer_len, __u32 *result); /** - * nvme_get_log_page() - Get log page data - * @fd: File descriptor of nvme device - * @xfer_len: Max log transfer size per request to split the total. - * @args: &struct nvme_get_log_args argument structure - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_get_log_page(int fd, __u32 xfer_len, struct nvme_get_log_args *args); - -static inline int nvme_get_nsid_log(int fd, bool rae, - enum nvme_cmd_get_log_lid lid, - __u32 nsid, __u32 len, void *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = lid, - .len = len, - .nsid = nsid, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -static inline int nvme_get_endgid_log(int fd, bool rae, enum nvme_cmd_get_log_lid lid, __u16 endgid, - __u32 len, void *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = lid, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = endgid, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_LOG_LSP_NONE, - .rae = rae, - .ot = false, - }; - - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -static inline int nvme_get_log_simple(int fd, enum nvme_cmd_get_log_lid lid, - __u32 len, void *log) -{ - return nvme_get_nsid_log(fd, false, lid, NVME_NSID_ALL, len, log); -} - -/** - * nvme_get_log_supported_log_pages() - Retrieve nmve supported log pages - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events + * nvme_init_get_log_lpo() - Initializes passthru command with a + * Log Page Offset + * @cmd: Passthru command + * @lpo: Log Page Offset to set set + */ +static inline void +nvme_init_get_log_lpo(struct nvme_passthru_cmd *cmd, __u64 lpo) +{ + cmd->cdw12 = lpo & 0xffffffff; + cmd->cdw13 = lpo >> 32; +} + +/** + * nvme_init_get_log() - Initialize passthru command for + * NVMe Admin Get Log + * @cmd: Passthru command to use + * @nsid: Namespace identifier, if applicable + * @lid: Log Page Identifier, see &enum nvme_cmd_get_log_lid + * @csi: Command set identifier, see &enum nvme_csi for known values + * @data: User space destination address to transfer the data + * @len: Length of provided user buffer to hold the log data in bytes + */ +static inline void +nvme_init_get_log(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_cmd_get_log_lid lid, enum nvme_csi csi, + void *data, __u32 len) +{ + __u32 numd = (len >> 2) - 1; + __u16 numdu = numd >> 16; + __u16 numdl = numd & 0xffff; + __u32 cdw10 = NVME_FIELD_ENCODE(lid, + NVME_LOG_CDW10_LID_SHIFT, + NVME_LOG_CDW10_LID_MASK) | + NVME_FIELD_ENCODE(numdl, + NVME_LOG_CDW10_NUMDL_SHIFT, + NVME_LOG_CDW10_NUMDL_MASK); + __u32 cdw11 = NVME_FIELD_ENCODE(numdu, + NVME_LOG_CDW11_NUMDU_SHIFT, + NVME_LOG_CDW11_NUMDU_MASK); + __u32 cdw14 = NVME_FIELD_ENCODE(csi, + NVME_LOG_CDW14_CSI_SHIFT, + NVME_LOG_CDW14_CSI_MASK); + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_get_log_page; + cmd->nsid = nsid; + cmd->cdw10 = cdw10; + cmd->cdw11 = cdw11; + cmd->cdw14 = cdw14; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; +} + +/** + * nvme_init_get_log_supported_log_pages() - Initialize passthru command for + * Supported Log Pages + * @cmd: Passthru command to use + * @csi: Command set identifier, see &enum nvme_csi for known values * @log: Array of LID supported and Effects data structures * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_SUPPORTED_LOG_PAGES. */ -static inline int nvme_get_log_supported_log_pages(int fd, bool rae, - struct nvme_supported_log_pages *log) +static inline void +nvme_init_get_log_supported_log_pages(struct nvme_passthru_cmd *cmd, + enum nvme_csi csi, struct nvme_supported_log_pages *log) { - return nvme_get_nsid_log(fd, rae, NVME_LOG_LID_SUPPORTED_LOG_PAGES, - NVME_NSID_ALL, sizeof(*log), log); + nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_SUPPORTED_LOG_PAGES, + csi, log, sizeof(*log)); } /** - * nvme_get_log_error() - Retrieve nvme error log - * @fd: File descriptor of nvme device + * nvme_init_get_log_error() - Initialize passthru command for Error Information + * @cmd: Passthru command to use * @nr_entries: Number of error log entries allocated - * @rae: Retain asynchronous events * @err_log: Array of error logs of size 'entries' * - * This log page describes extended error information for a command that - * completed with error, or may report an error that is not specific to a - * particular command. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_ERROR. */ -static inline int nvme_get_log_error(int fd, unsigned int nr_entries, bool rae, - struct nvme_error_log_page *err_log) +static inline void +nvme_init_get_log_error(struct nvme_passthru_cmd *cmd, unsigned int nr_entries, + struct nvme_error_log_page *err_log) { - return nvme_get_nsid_log(fd, rae, NVME_LOG_LID_ERROR, - NVME_NSID_ALL, sizeof(*err_log) * nr_entries, - err_log); + nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_ERROR, + NVME_CSI_NVM, err_log, sizeof(*err_log) * nr_entries); } /** - * nvme_get_log_smart() - Retrieve nvme smart log - * @fd: File descriptor of nvme device + * nvme_init_get_log_smart() - Initialize passthru command for + * SMART / Health Information + * @cmd: Passthru command to use * @nsid: Optional namespace identifier - * @rae: Retain asynchronous events * @smart_log: User address to store the smart log * - * This log page provides SMART and general health information. The information - * provided is over the life of the controller and is retained across power - * cycles. To request the controller log page, the namespace identifier - * specified is FFFFFFFFh. The controller may also support requesting the log - * page on a per namespace basis, as indicated by bit 0 of the LPA field in the - * Identify Controller data structure. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_SMART. */ -static inline int nvme_get_log_smart(int fd, __u32 nsid, bool rae, - struct nvme_smart_log *smart_log) +static inline void +nvme_init_get_log_smart(struct nvme_passthru_cmd *cmd, __u32 nsid, + struct nvme_smart_log *smart_log) { - return nvme_get_nsid_log(fd, rae, NVME_LOG_LID_SMART, - nsid, sizeof(*smart_log), smart_log); + nvme_init_get_log(cmd, nsid, NVME_LOG_LID_SMART, NVME_CSI_NVM, + smart_log, sizeof(*smart_log)); } /** - * nvme_get_log_fw_slot() - Retrieves the controller firmware log - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events + * nvme_init_get_log_fw_slot() - Initialize passthru command for + * Firmware Slot Information + * @cmd: Passthru command to use * @fw_log: User address to store the log page * - * This log page describes the firmware revision stored in each firmware slot - * supported. The firmware revision is indicated as an ASCII string. The log - * page also indicates the active slot number. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_SMART. */ -static inline int nvme_get_log_fw_slot(int fd, bool rae, - struct nvme_firmware_slot *fw_log) +static inline void +nvme_init_get_log_fw_slot(struct nvme_passthru_cmd *cmd, + struct nvme_firmware_slot *fw_log) { - return nvme_get_nsid_log(fd, rae, NVME_LOG_LID_FW_SLOT, - NVME_NSID_ALL, sizeof(*fw_log), fw_log); + nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_FW_SLOT, + NVME_CSI_NVM, fw_log, sizeof(*fw_log)); } /** - * nvme_get_log_changed_ns_list() - Retrieve namespace changed list - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events + * nvme_init_get_log_changed_ns() - Initialize passthru command for + * Changed Attached Namespace List + * @cmd: Passthru command to use * @ns_log: User address to store the log page * - * This log page describes namespaces attached to this controller that have - * changed since the last time the namespace was identified, been added, or - * deleted. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_CHANGED_NS. */ -static inline int nvme_get_log_changed_ns_list(int fd, bool rae, +static inline void +nvme_init_get_log_changed_ns(struct nvme_passthru_cmd *cmd, struct nvme_ns_list *ns_log) { - return nvme_get_nsid_log(fd, rae, NVME_LOG_LID_CHANGED_NS, - NVME_NSID_ALL, sizeof(*ns_log), ns_log); + nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_CHANGED_NS, + NVME_CSI_NVM, ns_log, sizeof(*ns_log)); } + /** - * nvme_get_log_cmd_effects() - Retrieve nvme command effects log - * @fd: File descriptor of nvme device + * nvme_init_get_log_cmd_effects() - Initialize passthru command for + * Commands Supported and Effects + * @cmd: Passthru command to use * @csi: Command Set Identifier * @effects_log:User address to store the effects log * - * This log page describes the commands that the controller supports and the - * effects of those commands on the state of the NVM subsystem. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_get_log_cmd_effects(int fd, enum nvme_csi csi, - struct nvme_cmd_effects_log *effects_log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = effects_log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_CMD_EFFECTS, - .len = sizeof(*effects_log), - .nsid = NVME_NSID_ALL, - .csi = csi, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_device_self_test() - Retrieve the device self test log - * @fd: File descriptor of nvme device + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_CMD_EFFECTS. + */ +static inline void +nvme_init_get_log_cmd_effects(struct nvme_passthru_cmd *cmd, + enum nvme_csi csi, struct nvme_cmd_effects_log *effects_log) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_CMD_EFFECTS, csi, + effects_log, sizeof(*effects_log)); +} + +/** + * nvme_init_get_log_device_self_test() - Initialize passthru command for + * Device Self-test + * @cmd: Passthru command to use * @log: Userspace address of the log payload * - * The log page indicates the status of an in progress self test and the - * percent complete of that operation, and the results of the previous 20 - * self-test operations. + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_DEVICE_SELF_TEST. + */ +static inline void +nvme_init_get_log_device_self_test(struct nvme_passthru_cmd *cmd, + struct nvme_self_test_log *log) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_DEVICE_SELF_TEST, + NVME_CSI_NVM, log, sizeof(*log)); +} + +/** + * nvme_init_get_log_telemetry_host() - Initialize passthru command for + * Telemetry Host-Initiated + * @cmd: Passthru command to use + * @lpo: Offset into the telemetry data + * @log: User address for log page data + * @len: Length of provided user buffer to hold the log data in bytes * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_TELEMETRY_HOST. */ -static inline int nvme_get_log_device_self_test(int fd, - struct nvme_self_test_log *log) +static inline void +nvme_init_get_log_telemetry_host(struct nvme_passthru_cmd *cmd, __u64 lpo, + void *log, __u32 len) { - return nvme_get_nsid_log(fd, false, NVME_LOG_LID_DEVICE_SELF_TEST, - NVME_NSID_ALL, sizeof(*log), log); + nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_TELEMETRY_HOST, + NVME_CSI_NVM, log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE(NVME_LOG_TELEM_HOST_LSP_RETAIN, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + nvme_init_get_log_lpo(cmd, lpo); } /** - * nvme_get_log_create_telemetry_host_mcda() - Create host telemetry log - * @fd: File descriptor of nvme device + * nvme_init_get_log_create_telemetry_host_mcda() - Initialize passthru + * command for Create Telemetry Host-Initiated + * @cmd: Passthru command to use * @mcda: Maximum Created Data Area * @log: Userspace address of the log payload * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_TELEMETRY_HOST and + * LSP value %NVME_LOG_TELEM_HOST_LSP_CREATE. */ -static inline int nvme_get_log_create_telemetry_host_mcda(int fd, - enum nvme_telemetry_da mcda, - struct nvme_telemetry_log *log) +static inline void +nvme_init_get_log_create_telemetry_host_mcda(struct nvme_passthru_cmd *cmd, + enum nvme_telemetry_da mcda, struct nvme_telemetry_log *log) { - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_TELEMETRY_HOST, - .len = sizeof(*log), - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = (__u8)((mcda << 1) | NVME_LOG_TELEM_HOST_LSP_CREATE), - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_create_telemetry_host() - Create host telemetry log - * @fd: File descriptor of nvme device + nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_TELEMETRY_HOST, + NVME_CSI_NVM, log, sizeof(*log)); + cmd->cdw10 |= NVME_FIELD_ENCODE( + mcda << 1 | NVME_LOG_TELEM_HOST_LSP_CREATE, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); +} + +/** + * nvme_init_get_log_create_telemetry_host() - Initialize passthru command for + * Create Telemetry Host-Initiated + * @cmd: Passthru command to use * @log: Userspace address of the log payload * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_TELEMETRY_HOST and + * LSP value %NVME_LOG_TELEM_HOST_LSP_CREATE. */ -static inline int nvme_get_log_create_telemetry_host(int fd, +static inline void +nvme_init_get_log_create_telemetry_host(struct nvme_passthru_cmd *cmd, struct nvme_telemetry_log *log) { - return nvme_get_log_create_telemetry_host_mcda(fd, NVME_TELEMETRY_DA_CTRL_DETERMINE, log); + nvme_init_get_log_create_telemetry_host_mcda(cmd, + NVME_TELEMETRY_DA_CTRL_DETERMINE, log); } /** - * nvme_get_log_telemetry_host() - Get Telemetry Host-Initiated log page - * @fd: File descriptor of nvme device - * @offset: Offset into the telemetry data - * @len: Length of provided user buffer to hold the log data in bytes + * nvme_init_get_log_telemetry_ctrl() - Initialize passthru command for + * Telemetry Controller-Initiated + * @cmd: Passthru command to use + * @lpo: Offset into the telemetry data * @log: User address for log page data - * - * Retrieves the Telemetry Host-Initiated log page at the requested offset - * using the previously existing capture. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_get_log_telemetry_host(int fd, __u64 offset, - __u32 len, void *log) -{ - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_TELEMETRY_HOST, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_TELEM_HOST_LSP_RETAIN, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_telemetry_ctrl() - Get Telemetry Controller-Initiated log page - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events - * @offset: Offset into the telemetry data * @len: Length of provided user buffer to hold the log data in bytes - * @log: User address for log page data * - * Retrieves the Telemetry Controller-Initiated log page at the requested offset - * using the previously existing capture. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_get_log_telemetry_ctrl(int fd, bool rae, - __u64 offset, __u32 len, void *log) -{ - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_TELEMETRY_CTRL, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_endurance_group() - Get Endurance Group log - * @fd: File descriptor of nvme device + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_TELEMETRY_CTRL. + */ +static inline void +nvme_init_get_log_telemetry_ctrl(struct nvme_passthru_cmd *cmd, + __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_TELEMETRY_CTRL, + NVME_CSI_NVM, log, len); + nvme_init_get_log_lpo(cmd, lpo); +} + +/** + * nvme_init_get_log_endurance_group() - Initialize passthru command for + * Endurance Group Information + * @cmd: Passthru command to use * @endgid: Starting group identifier to return in the list * @log: User address to store the endurance log * - * This log page indicates if an Endurance Group Event has occurred for a - * particular Endurance Group. If an Endurance Group Event has occurred, the - * details of the particular event are included in the Endurance Group - * Information log page for that Endurance Group. An asynchronous event is - * generated when an entry for an Endurance Group is newly added to this log - * page. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_get_log_endurance_group(int fd, __u16 endgid, - struct nvme_endurance_group_log *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_ENDURANCE_GROUP, - .len = sizeof(*log), - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = endgid, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_predictable_lat_nvmset() - Predictable Latency Per NVM Set - * @fd: File descriptor of nvme device + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_ENDURANCE_GROUP. + */ +static inline void +nvme_init_get_log_endurance_group(struct nvme_passthru_cmd *cmd, __u16 endgid, + struct nvme_endurance_group_log *log) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_ENDURANCE_GROUP, + NVME_CSI_NVM, log, sizeof(*log)); + cmd->cdw11 |= NVME_FIELD_ENCODE(endgid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); +} + +/** + * nvme_init_get_log_predictable_lat_nvmset() - Initialize passthru command for + * Predictable Latency Per NVM Set + * @cmd: Passthru command to use * @nvmsetid: NVM set id * @log: User address to store the predictable latency log * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_get_log_predictable_lat_nvmset(int fd, __u16 nvmsetid, - struct nvme_nvmset_predictable_lat_log *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_PREDICTABLE_LAT_NVMSET, - .len = sizeof(*log), - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = nvmsetid, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_predictable_lat_event() - Retrieve Predictable Latency Event Aggregate Log Page - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events - * @offset: Offset into the predictable latency event - * @len: Length of provided user buffer to hold the log data in bytes + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_PREDICTABLE_LAT_NVMSET. + */ +static inline void +nvme_init_get_log_predictable_lat_nvmset(struct nvme_passthru_cmd *cmd, + __u16 nvmsetid, struct nvme_nvmset_predictable_lat_log *log) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_PREDICTABLE_LAT_NVMSET, NVME_CSI_NVM, + log, sizeof(*log)); + cmd->cdw11 |= NVME_FIELD_ENCODE(nvmsetid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); +} + +/** + * nvme_init_get_log_predictable_lat_event() - Initialize passthru command for + * Predictable Latency Event Aggregate + * @cmd: Passthru command to use + * @lpo: Offset into the predictable latency event * @log: User address for log page data + * @len: Length of provided user buffer to hold the log data in bytes * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_get_log_predictable_lat_event(int fd, bool rae, - __u32 offset, __u32 len, void *log) -{ - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_PREDICTABLE_LAT_AGG, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_fdp_configurations() - Get list of Flexible Data Placement configurations - * @fd: File descriptor of nvme device - * @egid: Endurance group identifier - * @offset: Offset into log page - * @len: Length (in bytes) of provided user buffer to hold the log data - * @log: Log page data buffer + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_PREDICTABLE_LAT_AGG. */ -static inline int nvme_get_log_fdp_configurations(int fd, __u16 egid, - __u32 offset, __u32 len, void *log) +static inline void +nvme_init_get_log_predictable_lat_event(struct nvme_passthru_cmd *cmd, + __u64 lpo, void *log, __u32 len) { - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_FDP_CONFIGS, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = egid, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_get_log(&args); + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_PREDICTABLE_LAT_AGG, NVME_CSI_NVM, + log, len); + cmd->cdw12 = lpo & 0xffffffff; + cmd->cdw13 = lpo >> 32; } /** - * nvme_get_log_reclaim_unit_handle_usage() - Get reclaim unit handle usage - * @fd: File descriptor of nvme device - * @egid: Endurance group identifier - * @offset: Offset into log page - * @len: Length (in bytes) of provided user buffer to hold the log data - * @log: Log page data buffer + * nvme_init_get_log_ana() - Initialize passthru command for + * Asymmetric Namespace Access + * @cmd: Passthru command to use + * @lsp: Log specific, see &enum nvme_get_log_ana_lsp + * @lpo: Offset to the start of the log page + * @log: User address to store the ana log + * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_ANA. */ -static inline int nvme_get_log_reclaim_unit_handle_usage(int fd, __u16 egid, - __u32 offset, __u32 len, void *log) +static inline void +nvme_init_get_log_ana(struct nvme_passthru_cmd *cmd, + enum nvme_log_ana_lsp lsp, __u64 lpo, void *log, __u32 len) { - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_FDP_RUH_USAGE, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = egid, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_get_log(&args); + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_ANA, NVME_CSI_NVM, + log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE(lsp, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + cmd->cdw12 = lpo & 0xffffffff; + cmd->cdw13 = lpo >> 32; } /** - * nvme_get_log_fdp_stats() - Get Flexible Data Placement statistics - * @fd: File descriptor of nvme device - * @egid: Endurance group identifier - * @offset: Offset into log page - * @len: Length (in bytes) of provided user buffer to hold the log data - * @log: Log page data buffer + * nvme_init_get_log_ana_groups() - Initialize passthru command for + * Asymmetric Namespace Access groups + * @cmd: Passthru command to use + * @log: User address to store the ana group log + * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_ANA and LSP value %NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY */ -static inline int nvme_get_log_fdp_stats(int fd, __u16 egid, __u32 offset, __u32 len, void *log) +static inline void +nvme_init_get_log_ana_groups(struct nvme_passthru_cmd *cmd, + struct nvme_ana_log *log, __u32 len) { - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_FDP_STATS, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = egid, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_get_log(&args); + nvme_init_get_log_ana(cmd, NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY, + 0, log, len); } /** - * nvme_get_log_fdp_events() - Get Flexible Data Placement events - * @fd: File descriptor of nvme device - * @egid: Endurance group identifier - * @host_events: Whether to report host or controller events - * @offset: Offset into log page - * @len: Length (in bytes) of provided user buffer to hold the log data - * @log: Log page data buffer + * nvme_init_get_log_persistent_event() - Initialize passthru command for + * Persistent Event Log + * @cmd: Passthru command to use + * @action: Action the controller should take during processing this command + * @pevent_log: User address to store the persistent event log + * @len: Size of @pevent_log + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_PERSISTENT_EVENT */ -static inline int nvme_get_log_fdp_events(int fd, __u16 egid, bool host_events, __u32 offset, - __u32 len, void *log) +static inline void +nvme_init_get_log_persistent_event(struct nvme_passthru_cmd *cmd, + enum nvme_pevent_log_action action, + void *pevent_log, __u32 len) { - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_FDP_EVENTS, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = egid, - .lsp = (__u8)(host_events ? 0x1 : 0x0), - .uuidx = NVME_UUID_NONE, - }; - - return nvme_get_log(&args); + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_PERSISTENT_EVENT, NVME_CSI_NVM, + pevent_log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE(action, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); } /** - * nvme_get_log_ana() - Retrieve Asymmetric Namespace Access log page - * @fd: File descriptor of nvme device - * @lsp: Log specific, see &enum nvme_get_log_ana_lsp - * @rae: Retain asynchronous events - * @offset: Offset to the start of the log page + * nvme_init_get_log_lba_status() - Initialize passthru command for + * Retrieve LBA Status + * @cmd: Passthru command to use + * @lpo: Offset to the start of the log page + * @log: User address to store the log page * @len: The allocated length of the log page - * @log: User address to store the ana log - * - * This log consists of a header describing the log and descriptors containing - * the asymmetric namespace access information for ANA Groups that contain - * namespaces that are attached to the controller processing the command. - * - * See &struct nvme_ana_log for the definition of the returned structure. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_get_log_ana(int fd, enum nvme_log_ana_lsp lsp, bool rae, - __u64 offset, __u32 len, void *log) -{ - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_ANA, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = (__u8)lsp, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_ana_groups() - Retrieve Asymmetric Namespace Access groups only log page - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_LBA_STATUS + */ +static inline void +nvme_init_get_log_lba_status(struct nvme_passthru_cmd *cmd, + __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_LBA_STATUS, NVME_CSI_NVM, + log, len); + cmd->cdw12 = lpo & 0xffffffff; + cmd->cdw13 = lpo >> 32; +} + +/** + * nvme_init_get_log_endurance_grp_evt() - Initialize passthru command for + * Endurance Group Event Aggregate + * @cmd: Passthru command to use + * @lpo: Offset to the start of the log page + * @log: User address to store the log page * @len: The allocated length of the log page - * @log: User address to store the ana group log - * - * See &struct nvme_ana_log for the definition of the returned structure. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_ENDURANCE_GRP_EVT */ -static inline int nvme_get_log_ana_groups(int fd, bool rae, __u32 len, - struct nvme_ana_log *log) +static inline void +nvme_init_get_log_endurance_grp_evt(struct nvme_passthru_cmd *cmd, + __u64 lpo, void *log, __u32 len) { - return nvme_get_log_ana(fd, NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY, rae, 0, - len, log); + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_ENDURANCE_GRP_EVT, NVME_CSI_NVM, + log, len); + nvme_init_get_log_lpo(cmd, lpo); } /** - * nvme_get_ana_log_atomic() - Retrieve Asymmetric Namespace Access log page atomically - * @fd: File descriptor of nvme device - * @rgo: Whether to retrieve ANA groups only (no NSIDs) - * @rae: Whether to retain asynchronous events - * @retries: The maximum number of times to retry on log page changes - * @log: Pointer to a buffer to receive the ANA log page - * @len: Input: the length of the log page buffer. - * Output: the actual length of the ANA log page. - * - * See &struct nvme_ana_log for the definition of the returned structure. + * nvme_init_get_log_media_unit_stat() - Initialize passthru command for + * Media Unit Status + * @cmd: Passthru command to use + * @domid: Domain Identifier selection, if supported + * @mus: User address to store the Media Unit statistics log * - * Return: If successful, returns 0 and sets *len to the actual log page length. - * If unsuccessful, returns the nvme command status if a response was received - * (see &enum nvme_status_field) or -1 with errno set otherwise. - * Sets errno = EINVAL if retries == 0. - * Sets errno = EAGAIN if unable to read the log page atomically - * because chgcnt changed during each of the retries attempts. - * Sets errno = ENOSPC if the full log page does not fit in the provided buffer. + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_MEDIA_UNIT_STATUS */ -int nvme_get_ana_log_atomic(int fd, bool rgo, bool rae, unsigned int retries, - struct nvme_ana_log *log, __u32 *len); +static inline void +nvme_init_get_log_media_unit_stat(struct nvme_passthru_cmd *cmd, + __u16 domid, struct nvme_media_unit_stat_log *mus) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_MEDIA_UNIT_STATUS, NVME_CSI_NVM, + mus, sizeof(*mus)); + cmd->cdw11 |= NVME_FIELD_ENCODE(domid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); +} /** - * nvme_get_log_lba_status() - Retrieve LBA Status - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events - * @offset: Offset to the start of the log page - * @len: The allocated length of the log page - * @log: User address to store the log page - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_get_log_lba_status(int fd, bool rae, - __u64 offset, __u32 len, void *log) -{ - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_LBA_STATUS, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_endurance_grp_evt() - Retrieve Endurance Group Event Aggregate - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events - * @offset: Offset to the start of the log page - * @len: The allocated length of the log page - * @log: User address to store the log page + * nvme_init_get_log_support_cap_config_list() - Initialize passthru command for + * Supported Capacity Configuration List + * @cmd: Passthru command to use + * @domid: Domain Identifier selection, if supported + * @cap: User address to store supported capabilities config list * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_get_log_endurance_grp_evt(int fd, bool rae, - __u32 offset, __u32 len, void *log) -{ - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_ENDURANCE_GRP_EVT, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_fid_supported_effects() - Retrieve Feature Identifiers Supported and Effects - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_SUPPORTED_CAP_CONFIG_LIST + */ +static inline void +nvme_init_get_log_support_cap_config_list(struct nvme_passthru_cmd *cmd, + __u16 domid, struct nvme_supported_cap_config_list_log *cap) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_SUPPORTED_CAP_CONFIG_LIST, NVME_CSI_NVM, + cap, sizeof(*cap)); + cmd->cdw11 |= NVME_FIELD_ENCODE(domid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); +} + +/** + * nvme_init_get_log_fid_supported_effects() - Initialize passthru command for + * Feature Identifiers Supported and Effects + * @cmd: Passthru command to use + * @csi: Command set identifier, see &enum nvme_csi for known values * @log: FID Supported and Effects data structure * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_FID_SUPPORTED_EFFECTS */ -static inline int nvme_get_log_fid_supported_effects(int fd, bool rae, - struct nvme_fid_supported_effects_log *log) +static inline void +nvme_init_get_log_fid_supported_effects(struct nvme_passthru_cmd *cmd, + enum nvme_csi csi, struct nvme_fid_supported_effects_log *log) { - return nvme_get_nsid_log(fd, rae, NVME_LOG_LID_FID_SUPPORTED_EFFECTS, - NVME_NSID_NONE, sizeof(*log), log); + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_FID_SUPPORTED_EFFECTS, csi, + log, sizeof(*log)); } /** - * nvme_get_log_mi_cmd_supported_effects() - displays the MI Commands Supported by the controller - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events - * @log: MI Command Supported and Effects data structure + * nvme_init_get_log_mi_cmd_supported_effects() - Initialize passthru command + * for MI Commands Supported by the controller + * @cmd: Passthru command to use + * @log: MI Command Supported and Effects data structure * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_MI_CMD_SUPPORTED_EFFECTS */ -static inline int nvme_get_log_mi_cmd_supported_effects(int fd, bool rae, - struct nvme_mi_cmd_supported_effects_log *log) +static inline void +nvme_init_get_log_mi_cmd_supported_effects(struct nvme_passthru_cmd *cmd, + struct nvme_mi_cmd_supported_effects_log *log) { - return nvme_get_nsid_log(fd, rae, NVME_LOG_LID_MI_CMD_SUPPORTED_EFFECTS, - NVME_NSID_NONE, sizeof(*log), log); + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_MI_CMD_SUPPORTED_EFFECTS, NVME_CSI_NVM, + log, sizeof(*log)); } /** - * nvme_get_log_boot_partition() - Retrieve Boot Partition - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events + * nvme_init_get_log_lockdown() - Initialize passthru command for + * Command and Feature Lockdown + * @cmd: Passthru command to use + * @cnscp: Contents and Scope of Command and Feature Identifier + * Lists + * @lockdown_log: Buffer to store the lockdown log + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN + */ +static inline void +nvme_init_get_log_lockdown(struct nvme_passthru_cmd *cmd, + __u8 cnscp, struct nvme_lockdown_log *lockdown_log) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN, NVME_CSI_NVM, + lockdown_log, sizeof(*lockdown_log)); + cmd->cdw10 |= NVME_FIELD_ENCODE(cnscp, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); +} + +/** + * nvme_init_get_log_boot_partition() - Initialize passthru command for + * Boot Partition + * @cmd: Passthru command to use * @lsp: The log specified field of LID + * @part: User address to store the log page * @len: The allocated size, minimum * struct nvme_boot_partition - * @part: User address to store the log page * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise - */ -static inline int nvme_get_log_boot_partition(int fd, bool rae, - __u8 lsp, __u32 len, struct nvme_boot_partition *part) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = part, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_BOOT_PARTITION, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = lsp, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_rotational_media_info() - Retrieve Rotational Media Information Log - * @fd: File descriptor of nvme device + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_BOOT_PARTITION + */ +static inline void +nvme_init_get_log_boot_partition(struct nvme_passthru_cmd *cmd, + __u8 lsp, struct nvme_boot_partition *part, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_BOOT_PARTITION, NVME_CSI_NVM, + part, len); + cmd->cdw10 |= NVME_FIELD_ENCODE(lsp, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); +} + +/** + * nvme_init_get_log_rotational_media_info() - Initialize passthru command for + * Rotational Media Information Log + * @cmd: Passthru command to use * @endgid: Endurance Group Identifier - * @len: The allocated length of the log page * @log: User address to store the log page + * @len: The allocated length of the log page * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_ROTATIONAL_MEDIA_INFO */ -static inline int nvme_get_log_rotational_media_info(int fd, __u16 endgid, __u32 len, - struct nvme_rotational_media_info_log *log) +static inline void +nvme_init_get_log_rotational_media_info(struct nvme_passthru_cmd *cmd, + __u16 endgid, struct nvme_rotational_media_info_log *log, + __u32 len) { - return nvme_get_endgid_log(fd, false, NVME_LOG_LID_ROTATIONAL_MEDIA_INFO, endgid, len, log); + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_ROTATIONAL_MEDIA_INFO, NVME_CSI_NVM, + log, len); + cmd->cdw11 |= NVME_FIELD_ENCODE(endgid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); } /** - * nvme_get_log_dispersed_ns_participating_nss() - Retrieve Dispersed Namespace Participating NVM - * Subsystems Log - * @fd: File descriptor of nvme device + * nvme_init_get_log_dispersed_ns_participating_nss() - Initialize passthru + * command for Dispersed Namespace Participating NVM Subsystems + * @cmd: Passthru command to use * @nsid: Namespace Identifier - * @len: The allocated length of the log page * @log: User address to store the log page + * @len: The allocated length of the log page * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_DISPERSED_NS_PARTICIPATING_NSS */ -static inline int nvme_get_log_dispersed_ns_participating_nss(int fd, __u32 nsid, __u32 len, - struct nvme_dispersed_ns_participating_nss_log *log) +static inline void +nvme_init_get_log_dispersed_ns_participating_nss(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_dispersed_ns_participating_nss_log *log, + __u32 len) { - return nvme_get_nsid_log(fd, false, NVME_LOG_LID_DISPERSED_NS_PARTICIPATING_NSS, nsid, len, - log); + nvme_init_get_log(cmd, nsid, + NVME_LOG_LID_DISPERSED_NS_PARTICIPATING_NSS, NVME_CSI_NVM, + log, len); } /** - * nvme_get_log_mgmt_addr_list() - Retrieve Management Address List Log - * @fd: File descriptor of nvme device - * @len: The allocated length of the log page + * nvme_init_get_log_mgmt_addr_list() - Initialize passthru command for + * Management Address List + * @cmd: Passthru command to use * @log: User address to store the log page + * @len: The allocated length of the log page * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_MGMT_ADDR_LIST */ -static inline int nvme_get_log_mgmt_addr_list(int fd, __u32 len, - struct nvme_mgmt_addr_list_log *log) +static inline void +nvme_init_get_log_mgmt_addr_list(struct nvme_passthru_cmd *cmd, + struct nvme_mgmt_addr_list_log *log, __u32 len) { - return nvme_get_log_simple(fd, NVME_LOG_LID_MGMT_ADDR_LIST, len, log); + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_MGMT_ADDR_LIST, NVME_CSI_NVM, + log, len); } /** - * nvme_get_log_phy_rx_eom() - Retrieve Physical Interface Receiver Eye Opening Measurement Log - * @fd: File descriptor of nvme device + * nvme_init_get_log_phy_rx_eom() - Initialize passthru command for + * Physical Interface Receiver Eye Opening Measurement + * @cmd: Passthru command to use * @lsp: Log specific, controls action and measurement quality * @controller: Target controller ID + * @log: User address to store the log page * @len: The allocated size, minimum * struct nvme_phy_rx_eom_log - * @log: User address to store the log page * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise - */ -static inline int nvme_get_log_phy_rx_eom(int fd, __u8 lsp, __u16 controller, - __u32 len, struct nvme_phy_rx_eom_log *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_PHY_RX_EOM, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = controller, - .lsp = lsp, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_reachability_groups() - Retrieve Reachability Groups Log - * @fd: File descriptor of nvme device + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_PHY_RX_EOM + */ +static inline void +nvme_init_get_log_phy_rx_eom(struct nvme_passthru_cmd *cmd, + __u8 lsp, __u16 controller, struct nvme_phy_rx_eom_log *log, + __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_PHY_RX_EOM, NVME_CSI_NVM, + log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE(lsp, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + cmd->cdw11 |= NVME_FIELD_ENCODE(controller, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); +} + +/** + * nvme_init_get_log_reachability_groups() - Initialize passthru command for + * Retrieve Reachability Groups + * @cmd: Passthru command to use * @rgo: Return groups only - * @rae: Retain asynchronous events - * @len: The allocated length of the log page * @log: User address to store the log page + * @len: The allocated length of the log page * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_REACHABILITY_GROUPS */ -static inline int nvme_get_log_reachability_groups(int fd, bool rgo, bool rae, __u32 len, - struct nvme_reachability_groups_log *log) +static inline void +nvme_init_get_log_reachability_groups(struct nvme_passthru_cmd *cmd, + bool rgo, struct nvme_reachability_groups_log *log, __u32 len) { - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_REACHABILITY_GROUPS, - .len = len, - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = rgo, - .uuidx = NVME_LOG_LSP_NONE, - .rae = rae, - .ot = false, - }; - - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_REACHABILITY_GROUPS, NVME_CSI_NVM, + log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE((__u8)rgo, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); } /** - * nvme_get_log_reachability_associations() - Retrieve Reachability Associations Log - * @fd: File descriptor of nvme device + * nvme_init_get_log_reachability_associations() - Initialize passthru command + * for Reachability Associations Log + * @cmd: Passthru command to use * @rao: Return associations only - * @rae: Retain asynchronous events + * @log: User address to store the log page * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_REACHABILITY_ASSOCIATIONS + */ +static inline void +nvme_init_get_log_reachability_associations(struct nvme_passthru_cmd *cmd, + bool rao, struct nvme_reachability_associations_log *log, + __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_REACHABILITY_ASSOCIATIONS, NVME_CSI_NVM, + log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE((__u8)rao, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); +} + +/** + * nvme_init_get_log_changed_alloc_ns() - Initialize passthru command for + * Changed Allocated Namespace List + * @cmd: Passthru command to use * @log: User address to store the log page + * @len: The allocated length of the log page * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_CHANGED_ALLOC_NS */ -static inline int nvme_get_log_reachability_associations(int fd, bool rao, bool rae, __u32 len, - struct nvme_reachability_associations_log *log) +static inline void +nvme_init_get_log_changed_alloc_ns(struct nvme_passthru_cmd *cmd, + struct nvme_ns_list *log, __u32 len) { - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_REACHABILITY_ASSOCIATIONS, - .len = len, - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = rao, - .uuidx = NVME_LOG_LSP_NONE, - .rae = rae, - .ot = false, - }; + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_CHANGED_ALLOC_NS, NVME_CSI_NVM, + log, len); +} - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); +/** + * nvme_init_get_log_fdp_configurations() - Initialize passthru command for + * Flexible Data Placement Configurations + * @cmd: Passthru command to use + * @egid: Endurance group identifier + * @lpo: Offset into log page + * @log: Log page data buffer + * @len: Length (in bytes) of provided user buffer to hold the log data + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_FDP_CONFIGS + */ +static inline void +nvme_init_get_log_fdp_configurations(struct nvme_passthru_cmd *cmd, + __u16 egid, __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_FDP_CONFIGS, NVME_CSI_NVM, + log, len); + cmd->cdw11 |= NVME_FIELD_ENCODE(egid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); + nvme_init_get_log_lpo(cmd, lpo); } /** - * nvme_get_log_changed_alloc_ns_list() - Retrieve Changed Allocated Namespace List Log - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events - * @len: The allocated length of the log page - * @log: User address to store the log page + * nvme_init_get_log_reclaim_unit_handle_usage() - Initialize passthru + * command for Reclaim Unit Handle Usage + * @cmd: Passthru command to use + * @egid: Endurance group identifier + * @lpo: Offset into log page + * @log: Log page data buffer + * @len: Length (in bytes) of provided user buffer to hold the log data * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_RUH_USAGE */ -static inline int nvme_get_log_changed_alloc_ns_list(int fd, bool rae, __u32 len, - struct nvme_ns_list *log) +static inline void +nvme_init_get_log_reclaim_unit_handle_usage(struct nvme_passthru_cmd *cmd, + __u16 egid, __u64 lpo, void *log, __u32 len) { - return nvme_get_nsid_log(fd, rae, NVME_LOG_LID_CHANGED_ALLOC_NS_LIST, NVME_NSID_ALL, len, - log); + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_FDP_RUH_USAGE, NVME_CSI_NVM, + log, len); + cmd->cdw11 |= NVME_FIELD_ENCODE(egid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); + nvme_init_get_log_lpo(cmd, lpo); } /** - * nvme_get_log_discovery() - Retrieve Discovery log page - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events - * @offset: Offset of this log to retrieve - * @len: The allocated size for this portion of the log + * nvme_init_get_log_fdp_stats() - Initialize passthru command for + * Get Flexible Data Placement Statistics + * @cmd: Passthru command to use + * @egid: Endurance group identifier + * @lpo: Offset into log page + * @log: Log page data buffer + * @len: Length (in bytes) of provided user buffer to hold the log data + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_FDP_STATS + */ +static inline +void nvme_init_get_log_fdp_stats(struct nvme_passthru_cmd *cmd, + __u16 egid, __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_FDP_STATS, NVME_CSI_NVM, + log, len); + cmd->cdw11 |= NVME_FIELD_ENCODE(egid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); + nvme_init_get_log_lpo(cmd, lpo); +} + +/** + * nvme_init_get_log_fdp_events() - Initialize passthru command for + * Flexible Data Placement Events + * @cmd: Passthru command to use + * @host_events: Whether to report host or controller events + * @egid: Endurance group identifier + * @lpo: Offset into log page + * @log: Log page data buffer + * @len: Length (in bytes) of provided user buffer to hold + * the log data + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_FDP_EVENTS + */ +static inline void +nvme_init_get_log_fdp_events(struct nvme_passthru_cmd *cmd, + bool host_events, __u16 egid, __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_FDP_EVENTS, NVME_CSI_NVM, + log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE((__u8)(host_events ? 0x1 : 0x0), + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + cmd->cdw11 |= NVME_FIELD_ENCODE(egid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); + nvme_init_get_log_lpo(cmd, lpo); +} + + +/** + * nvme_init_get_log_discovery() - Initialize passthru command for Discovery + * @cmd: Passthru command to use + * @lpo: Offset of this log to retrieve * @log: User address to store the discovery log + * @len: The allocated size for this portion of the log * - * Supported only by fabrics discovery controllers, returning discovery - * records. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_get_log_discovery(int fd, bool rae, - __u32 offset, __u32 len, void *log) -{ - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_DISCOVER, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_host_discover() - Retrieve Host Discovery Log - * @fd: File descriptor of nvme device + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_DISCOVERY + */ +static inline void +nvme_init_get_log_discovery(struct nvme_passthru_cmd *cmd, + __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_DISCOVERY, NVME_CSI_NVM, + log, len); + nvme_init_get_log_lpo(cmd, lpo); +} + +/** + * nvme_init_get_log_host_discovery() - Initialize passthru command for + * Host Discover + * @cmd: Passthru command to use * @allhoste: All host entries - * @rae: Retain asynchronous events - * @len: The allocated length of the log page * @log: User address to store the log page + * @len: The allocated length of the log page * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_HOST_DISCOVERY */ -static inline int nvme_get_log_host_discover(int fd, bool allhoste, bool rae, __u32 len, - struct nvme_host_discover_log *log) +static inline void +nvme_init_get_log_host_discovery(struct nvme_passthru_cmd *cmd, + bool allhoste, struct nvme_host_discover_log *log, __u32 len) { - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_HOST_DISCOVER, - .len = len, - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = allhoste, - .uuidx = NVME_LOG_LSP_NONE, - .rae = rae, - .ot = false, - }; - - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_HOST_DISCOVERY, NVME_CSI_NVM, + log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE((__u8)allhoste, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); } /** - * nvme_get_log_ave_discover() - Retrieve AVE Discovery Log - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events - * @len: The allocated length of the log page + * nvme_init_get_log_ave_discovery() - Initialize passthru command for + * AVE Discovery + * @cmd: Passthru command to use * @log: User address to store the log page + * @len: The allocated length of the log page * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_AVE_DISCOVERY */ -static inline int nvme_get_log_ave_discover(int fd, bool rae, __u32 len, - struct nvme_ave_discover_log *log) +static inline void +nvme_init_get_log_ave_discovery(struct nvme_passthru_cmd *cmd, + struct nvme_ave_discover_log *log, __u32 len) { - return nvme_get_nsid_log(fd, rae, NVME_LOG_LID_AVE_DISCOVER, NVME_NSID_ALL, len, log); + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_AVE_DISCOVERY, NVME_CSI_NVM, + log, len); } /** - * nvme_get_log_pull_model_ddc_req() - Retrieve Pull Model DDC Request Log - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events - * @len: The allocated length of the log page + * nvme_init_get_log_pull_model_ddc_req() - Initialize passthru command for + * Pull Model DDC Request + * @cmd: Passthru command to use * @log: User address to store the log page + * @len: The allocated length of the log page * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_PULL_MODEL_DDC_REQ */ -static inline int nvme_get_log_pull_model_ddc_req(int fd, bool rae, __u32 len, - struct nvme_pull_model_ddc_req_log *log) +static inline void +nvme_init_get_log_pull_model_ddc_req(struct nvme_passthru_cmd *cmd, + struct nvme_pull_model_ddc_req_log *log, __u32 len) { - return nvme_get_nsid_log(fd, rae, NVME_LOG_LID_PULL_MODEL_DDC_REQ, NVME_NSID_ALL, len, log); + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_PULL_MODEL_DDC_REQ, NVME_CSI_NVM, + log, len); } /** - * nvme_get_log_media_unit_stat() - Retrieve Media Unit Status - * @fd: File descriptor of nvme device - * @domid: Domain Identifier selection, if supported - * @mus: User address to store the Media Unit statistics log - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise - */ -static inline int nvme_get_log_media_unit_stat(int fd, __u16 domid, - struct nvme_media_unit_stat_log *mus) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = mus, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_MEDIA_UNIT_STATUS, - .len = sizeof(*mus), - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = domid, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_support_cap_config_list() - Retrieve Supported Capacity Configuration List - * @fd: File descriptor of nvme device - * @domid: Domain Identifier selection, if supported - * @cap: User address to store supported capabilities config list - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise - */ -static inline int nvme_get_log_support_cap_config_list(int fd, __u16 domid, - struct nvme_supported_cap_config_list_log *cap) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = cap, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_SUPPORTED_CAP_CONFIG_LIST, - .len = sizeof(*cap), - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = domid, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_reservation() - Retrieve Reservation Notification - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events + * nvme_init_get_log_reservation() - Initialize passthru command for + * Reservation Notification + * @cmd: Passthru command to use * @log: User address to store the reservation log * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_RESERVATION */ -static inline int nvme_get_log_reservation(int fd, bool rae, +static inline void +nvme_init_get_log_reservation(struct nvme_passthru_cmd *cmd, struct nvme_resv_notification_log *log) { - return nvme_get_nsid_log(fd, rae, NVME_LOG_LID_RESERVATION, - NVME_NSID_ALL, sizeof(*log), log); + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_RESERVATION, NVME_CSI_NVM, + log, sizeof(*log)); } /** - * nvme_get_log_sanitize() - Retrieve Sanitize Status - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events + * nvme_init_get_log_sanitize() - Initialize passthru command for + * Sanitize Status + * @cmd: Passthru command to use * @log: User address to store the sanitize log * - * The Sanitize Status log page reports sanitize operation time estimates and - * information about the most recent sanitize operation. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_SANITIZE */ -static inline int nvme_get_log_sanitize(int fd, bool rae, - struct nvme_sanitize_log_page *log) +static inline void +nvme_init_get_log_sanitize(struct nvme_passthru_cmd *cmd, + struct nvme_sanitize_log_page *log) { - return nvme_get_nsid_log(fd, rae, NVME_LOG_LID_SANITIZE, - NVME_NSID_ALL, sizeof(*log), log); + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_SANITIZE, NVME_CSI_NVM, + log, sizeof(*log)); } /** - * nvme_get_log_zns_changed_zones() - Retrieve list of zones that have changed - * @fd: File descriptor of nvme device + * nvme_init_get_log_zns_changed_zones() - Initialize passthru command for + * list of zones that have changed + * @cmd: Passthru command to use * @nsid: Namespace ID - * @rae: Retain asynchronous events * @log: User address to store the changed zone log * - * The list of zones that have changed state due to an exceptional event. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_get_log_zns_changed_zones(int fd, __u32 nsid, bool rae, - struct nvme_zns_changed_zone_log *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_ZNS_CHANGED_ZONES, - .len = sizeof(*log), - .nsid = nsid, - .csi = NVME_CSI_ZNS, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_persistent_event() - Retrieve Persistent Event Log - * @fd: File descriptor of nvme device - * @action: Action the controller should take during processing this command - * @size: Size of @pevent_log - * @pevent_log: User address to store the persistent event log - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_get_log_persistent_event(int fd, - enum nvme_pevent_log_action action, - __u32 size, void *pevent_log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = pevent_log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_PERSISTENT_EVENT, - .len = size, - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = (__u8)action, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_get_log_lockdown() - Retrieve lockdown Log - * @fd: File descriptor of nvme device - * @cnscp: Contents and Scope of Command and Feature Identifier Lists - * @lockdown_log: Buffer to store the lockdown log - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_ZNS_CHANGED_ZONES */ -static inline int nvme_get_log_lockdown(int fd, - __u8 cnscp, struct nvme_lockdown_log *lockdown_log) +static inline void +nvme_init_get_log_zns_changed_zones(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_zns_changed_zone_log *log) { - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = lockdown_log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN, - .len = sizeof(*lockdown_log), - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = cnscp, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); + nvme_init_get_log(cmd, nsid, + NVME_LOG_LID_ZNS_CHANGED_ZONES, NVME_CSI_ZNS, + log, sizeof(*log)); } /** - * nvme_set_features() - Set a feature attribute - * @args: &struct nvme_set_features_args argument structure + * nvme_get_ana_log_atomic() - Retrieve Asymmetric Namespace Access + * log page atomically + * @hdl: Transport handle + * @rae: Whether to retain asynchronous events + * @rgo: Whether to retrieve ANA groups only (no NSIDs) + * @log: Pointer to a buffer to receive the ANA log page + * @len: Input: the length of the log page buffer. + * Output: the actual length of the ANA log page. + * @retries: The maximum number of times to retry on log page changes + * + * See &struct nvme_ana_log for the definition of the returned structure. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: If successful, returns 0 and sets *len to the actual log page length. + * If unsuccessful, returns the nvme command status if a response was received + * (see &enum nvme_status_field) or -1 with errno set otherwise. + * Sets errno = EINVAL if retries == 0. + * Sets errno = EAGAIN if unable to read the log page atomically + * because chgcnt changed during each of the retries attempts. + * Sets errno = ENOSPC if the full log page does not fit in the provided buffer. */ -int nvme_set_features(struct nvme_set_features_args *args); +int +nvme_get_ana_log_atomic(struct nvme_transport_handle *hdl, bool rae, bool rgo, + struct nvme_ana_log *log, __u32 *len, unsigned int retries); /** - * nvme_set_features_data() - Helper function for @nvme_set_features() - * @fd: File descriptor of nvme device - * @fid: Feature identifier - * @nsid: Namespace ID, if applicable - * @cdw11: Value to set the feature to - * @save: Save value across power states - * @data_len: Length of feature data, if applicable, in bytes - * @data: User address of feature data, if applicable - * @result: The command completion result from CQE dword0 - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_set_features_data(int fd, __u8 fid, __u32 nsid, - __u32 cdw11, bool save, __u32 data_len, void *data, - __u32 *result) -{ - struct nvme_set_features_args args = { - .result = result, - .data = data, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .nsid = nsid, - .cdw11 = cdw11, - .cdw12 = 0, - .cdw13 = 0, - .cdw15 = 0, - .data_len = data_len, - .save = save, - .uuidx = NVME_UUID_NONE, - .fid = fid, - }; - return nvme_set_features(&args); -} - -/** - * nvme_set_features_simple() - Helper function for @nvme_set_features() - * @fd: File descriptor of nvme device + * nvme_init_set_features() - Initialize passthru command for + * Set Features + * @cmd: Passthru command to use * @fid: Feature identifier - * @nsid: Namespace ID, if applicable - * @cdw11: Value to set the feature to - * @save: Save value across power states - * @result: The command completion result from CQE dword0 - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * @sv: Save value across power states */ -static inline int nvme_set_features_simple(int fd, __u8 fid, __u32 nsid, - __u32 cdw11, bool save, __u32 *result) +static inline void +nvme_init_set_features(struct nvme_passthru_cmd *cmd, __u8 fid, bool sv) { - return nvme_set_features_data(fd, fid, nsid, cdw11, save, 0, NULL, - result); + __u32 cdw10 = NVME_FIELD_ENCODE(fid, + NVME_SET_FEATURES_CDW10_FID_SHIFT, + NVME_SET_FEATURES_CDW10_FID_MASK) | + NVME_FIELD_ENCODE(sv, + NVME_SET_FEATURES_CDW10_SV_SHIFT, + NVME_SET_FEATURES_CDW10_SV_MASK); + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_set_features; + cmd->cdw10 = cdw10; } /** - * nvme_set_features_arbitration() - Set arbitration features - * @fd: File descriptor of nvme device + * nvme_init_set_features_arbitration() -Initialize passthru command for + * Arbitration Features + * @cmd: Passthru command to use + * @sv: Save value across power states * @ab: Arbitration Burst * @lpw: Low Priority Weight * @mpw: Medium Priority Weight * @hpw: High Priority Weight - * @save: Save value across power states - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_ARBRITARTION */ -int nvme_set_features_arbitration(int fd, __u8 ab, __u8 lpw, __u8 mpw, - __u8 hpw, bool save, __u32 *result); +static inline void +nvme_init_set_features_arbitration(struct nvme_passthru_cmd *cmd, + bool sv, __u8 ab, __u8 lpw, __u8 mpw, __u8 hpw) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_ARBITRATION, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(ab, + NVME_FEAT_ARBITRATION_BURST_SHIFT, + NVME_FEAT_ARBITRATION_BURST_MASK) | + NVME_FIELD_ENCODE(lpw, + NVME_FEAT_ARBITRATION_LPW_SHIFT, + NVME_FEAT_ARBITRATION_LPW_MASK) | + NVME_FIELD_ENCODE(mpw, + NVME_FEAT_ARBITRATION_MPW_SHIFT, + NVME_FEAT_ARBITRATION_MPW_MASK) | + NVME_FIELD_ENCODE(hpw, + NVME_FEAT_ARBITRATION_HPW_SHIFT, + NVME_FEAT_ARBITRATION_HPW_MASK); +} /** - * nvme_set_features_power_mgmt() - Set power management feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_power_mgmt() - Initialize passthru command for + * Power Management + * @cmd: Passthru command to use + * @sv: Save value across power states * @ps: Power State * @wh: Workload Hint - * @save: Save value across power states - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_PWRMGMT_PS */ -int nvme_set_features_power_mgmt(int fd, __u8 ps, __u8 wh, bool save, - __u32 *result); +static inline void +nvme_init_set_features_power_mgmt(struct nvme_passthru_cmd *cmd, + bool sv, __u8 ps, __u8 wh) +{ + + nvme_init_set_features(cmd, NVME_FEAT_FID_POWER_MGMT, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(ps, + NVME_FEAT_PWRMGMT_PS_SHIFT, + NVME_FEAT_PWRMGMT_PS_MASK) | + NVME_FIELD_ENCODE(wh, + NVME_FEAT_PWRMGMT_WH_SHIFT, + NVME_FEAT_PWRMGMT_WH_MASK); +} /** - * nvme_set_features_lba_range() - Set LBA range feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_lba_range() - Initialize passthru command for + * LBA Range + * @cmd: Passthru command to use * @nsid: Namespace ID - * @nr_ranges: Number of ranges in @data - * @save: Save value across power states + * @sv: Save value across power states + * @num: Number of ranges in @data * @data: User address of feature data - * @result: The command completion result from CQE dword0 - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_set_features_lba_range(int fd, __u32 nsid, __u8 nr_ranges, bool save, - struct nvme_lba_range_type *data, __u32 *result); - -/** - * nvme_set_features_temp_thresh() - Set temperature threshold feature - * @fd: File descriptor of nvme device - * @tmpth: Temperature Threshold - * @tmpsel: Threshold Temperature Select - * @thsel: Threshold Type Select - * @save: Save value across power states - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_LBA_RANGE */ -int nvme_set_features_temp_thresh(int fd, __u16 tmpth, __u8 tmpsel, - enum nvme_feat_tmpthresh_thsel thsel, - bool save, __u32 *result); +static inline void +nvme_init_set_features_lba_range(struct nvme_passthru_cmd *cmd, + __u32 nsid, bool sv, __u8 num, + struct nvme_lba_range_type *data) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_LBA_RANGE, sv); + cmd->nsid = nsid; + cmd->cdw11 = NVME_FIELD_ENCODE(num - 1, + NVME_SET_FEATURES_CDW11_NUM_SHIFT, + NVME_SET_FEATURES_CDW11_NUM_MASK); + cmd->data_len = sizeof(*data); + cmd->addr = (__u64)(uintptr_t)data; +} /** - * nvme_set_features_temp_thresh2() - Set temperature threshold feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_temp_thresh() - Initialize passthru command for + * Temperature Threshold + * @cmd: Passthru command to use + * @sv: Save value across power states * @tmpth: Temperature Threshold * @tmpsel: Threshold Temperature Select * @thsel: Threshold Type Select * @tmpthh: Temperature Threshold Hysteresis - * @save: Save value across power states - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_TEMP_THRESH */ -int nvme_set_features_temp_thresh2(int fd, __u16 tmpth, __u8 tmpsel, - enum nvme_feat_tmpthresh_thsel thsel, __u8 tmpthh, - bool save, __u32 *result); +static inline void +nvme_init_set_features_temp_thresh(struct nvme_passthru_cmd *cmd, + bool sv, __u16 tmpth, __u8 tmpsel, + enum nvme_feat_tmpthresh_thsel thsel, __u8 tmpthh) +{ + + nvme_init_set_features(cmd, NVME_FEAT_FID_TEMP_THRESH, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(tmpth, + NVME_FEAT_TT_TMPTH_SHIFT, + NVME_FEAT_TT_TMPTH_MASK) | + NVME_FIELD_ENCODE(tmpsel, + NVME_FEAT_TT_TMPSEL_SHIFT, + NVME_FEAT_TT_TMPSEL_MASK) | + NVME_FIELD_ENCODE(thsel, + NVME_FEAT_TT_THSEL_SHIFT, + NVME_FEAT_TT_THSEL_MASK) | + NVME_FIELD_ENCODE(tmpthh, + NVME_FEAT_TT_TMPTHH_SHIFT, + NVME_FEAT_TT_TMPTHH_MASK); +} /** - * nvme_set_features_err_recovery() - Set error recovery feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_err_recovery() - Initialize passthru command for + * Error Recovery + * @cmd: Passthru command to use * @nsid: Namespace ID + * @sv: Save value across power states * @tler: Time-limited error recovery value * @dulbe: Deallocated or Unwritten Logical Block Error Enable - * @save: Save value across power states - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_ERR_RECOVERY */ -int nvme_set_features_err_recovery(int fd, __u32 nsid, __u16 tler, - bool dulbe, bool save, __u32 *result); +static inline void +nvme_init_set_features_err_recovery(struct nvme_passthru_cmd *cmd, + __u32 nsid, bool sv, __u16 tler, bool dulbe) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_ERR_RECOVERY, sv); + cmd->nsid = nsid; + cmd->cdw11 = NVME_FIELD_ENCODE(tler, + NVME_FEAT_ERROR_RECOVERY_TLER_SHIFT, + NVME_FEAT_ERROR_RECOVERY_TLER_MASK) | + NVME_FIELD_ENCODE(dulbe, + NVME_FEAT_ERROR_RECOVERY_DULBE_SHIFT, + NVME_FEAT_ERROR_RECOVERY_DULBE_MASK); +} /** - * nvme_set_features_volatile_wc() - Set volatile write cache feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_volatile_wc() - Initialize passthru command for + * Volatile Write Cache + * @cmd: Passthru command to use + * @sv: Save value across power states * @wce: Write cache enable - * @save: Save value across power states - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_VOLATILE_WC */ -int nvme_set_features_volatile_wc(int fd, bool wce, bool save, - __u32 *result); +static inline void +nvme_init_set_features_volatile_wc(struct nvme_passthru_cmd *cmd, + bool sv, bool wce) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_VOLATILE_WC, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(wce, + NVME_FEAT_VWC_WCE_SHIFT, + NVME_FEAT_VWC_WCE_MASK); +} /** - * nvme_set_features_irq_coalesce() - Set IRQ coalesce feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_irq_coalesce() - Initialize passthru command for + * IRQ Coalescing + * @cmd: Passthru command to use + * @sv: Save value across power states * @thr: Aggregation Threshold * @time: Aggregation Time - * @save: Save value across power states - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_IRQ_COALESCE */ -int nvme_set_features_irq_coalesce(int fd, __u8 thr, __u8 time, - bool save, __u32 *result); +static inline void +nvme_init_set_features_irq_coalesce(struct nvme_passthru_cmd *cmd, + bool sv, __u8 thr, __u8 time) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_IRQ_COALESCE, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(thr, + NVME_FEAT_IRQC_THR_SHIFT, + NVME_FEAT_IRQC_THR_MASK) | + NVME_FIELD_ENCODE(time, + NVME_FEAT_IRQC_TIME_SHIFT, + NVME_FEAT_IRQC_TIME_MASK); +} /** - * nvme_set_features_irq_config() - Set IRQ config feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_irq_config() - Initialize passthru command for + * IRQ Config + * @cmd: Passthru command to use + * @sv: Save value across power states * @iv: Interrupt Vector * @cd: Coalescing Disable - * @save: Save value across power states - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_IRQ_CONFIG */ -int nvme_set_features_irq_config(int fd, __u16 iv, bool cd, bool save, - __u32 *result); +static inline void +nvme_init_set_features_irq_config(struct nvme_passthru_cmd *cmd, + bool sv, __u16 iv, bool cd) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_IRQ_CONFIG, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(iv, + NVME_FEAT_ICFG_IV_SHIFT, + NVME_FEAT_ICFG_IV_MASK) | + NVME_FIELD_ENCODE(cd, + NVME_FEAT_ICFG_CD_SHIFT, + NVME_FEAT_ICFG_CD_MASK); +} /** - * nvme_set_features_write_atomic() - Set write atomic feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_write_atomic() - Initialize passthru command for + * Write Atomic + * @cmd: Passthru command to use + * @sv: Save value across power states * @dn: Disable Normal - * @save: Save value across power states - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_WRITE_ATOMIC */ -int nvme_set_features_write_atomic(int fd, bool dn, bool save, - __u32 *result); +static inline void +nvme_init_set_features_write_atomic(struct nvme_passthru_cmd *cmd, + bool sv, bool dn) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_WRITE_ATOMIC, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(dn, + NVME_FEAT_WA_DN_SHIFT, + NVME_FEAT_WA_DN_MASK); +} /** - * nvme_set_features_async_event() - Set asynchronous event feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_async_event() - Initialize passthru command for + * Asynchronous Event Configuration + * @cmd: Passthru command to use + * @sv: Save value across power states * @events: Events to enable - * @save: Save value across power states - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_ASYNC_EVENT */ -int nvme_set_features_async_event(int fd, __u32 events, bool save, - __u32 *result); +static inline void +nvme_init_set_features_async_event(struct nvme_passthru_cmd *cmd, + bool sv, __u32 events) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_ASYNC_EVENT, sv); + cmd->cdw11 = events; +} /** - * nvme_set_features_auto_pst() - Set autonomous power state feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_auto_pst() - Initialize passthru command for + * Autonomous Power State Transition + * @cmd: Passthru command to use + * @sv: Save value across power states * @apste: Autonomous Power State Transition Enable - * @apst: Autonomous Power State Transition - * @save: Save value across power states - * @result: The command completion result from CQE dword0 + * @apst: Autonomous Power State Transition data buffer * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_AUTO_PST */ -int nvme_set_features_auto_pst(int fd, bool apste, bool save, - struct nvme_feat_auto_pst *apst, - __u32 *result); +static inline void +nvme_init_set_features_auto_pst(struct nvme_passthru_cmd *cmd, + bool sv, bool apste, struct nvme_feat_auto_pst *apst) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_AUTO_PST, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(apste, + NVME_FEAT_APST_APSTE_SHIFT, + NVME_FEAT_APST_APSTE_MASK); + cmd->data_len = sizeof(*apst); + cmd->addr = (__u64)(uintptr_t)apst; +} /** - * nvme_set_features_timestamp() - Set timestamp feature - * @fd: File descriptor of nvme device - * @save: Save value across power states - * @timestamp: The current timestamp value to assign to this feature + * nvme_init_set_features_timestamp() - Initialize passthru command for + * Timestamp + * @cmd: Passthru command to use + * @sv: Save value across power states + * @tstmp: The current timestamp value to assign to this feature + * @ts: Timestamp data buffer (populated by this function) * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_TIMESTAMP. The caller must provide a valid + * buffer via @ts, which this function will populate. */ -int nvme_set_features_timestamp(int fd, bool save, __u64 timestamp); +static inline void +nvme_init_set_features_timestamp(struct nvme_passthru_cmd *cmd, + bool sv, __u64 tstmp, struct nvme_timestamp *ts) +{ + __le64 t = htole64(tstmp); + + memcpy(ts, &t, sizeof(__le64)); + + nvme_init_set_features(cmd, NVME_FEAT_FID_TIMESTAMP, sv); + cmd->data_len = sizeof(*ts); + cmd->addr = (__u64)(uintptr_t)ts; +} /** - * nvme_set_features_hctm() - Set thermal management feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_hctm() - Initialize passthru command for + * Host Controlled Thermal Management + * @cmd: Passthru command to use + * @sv: Save value across power states * @tmt2: Thermal Management Temperature 2 * @tmt1: Thermal Management Temperature 1 - * @save: Save value across power states - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_HCTM */ -int nvme_set_features_hctm(int fd, __u16 tmt2, __u16 tmt1, bool save, - __u32 *result); +static inline void +nvme_init_set_features_hctm(struct nvme_passthru_cmd *cmd, + bool sv, __u16 tmt2, __u16 tmt1) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_HCTM, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(tmt2, + NVME_FEAT_HCTM_TMT2_SHIFT, + NVME_FEAT_HCTM_TMT2_MASK) | + NVME_FIELD_ENCODE(tmt1, + NVME_FEAT_HCTM_TMT1_SHIFT, + NVME_FEAT_HCTM_TMT1_MASK); +} /** - * nvme_set_features_nopsc() - Set non-operational power state feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_nopsc() - Initialize passthru command for + * Non-Operational Power State Config + * @cmd: Passthru command to use + * @sv: Save value across power states * @noppme: Non-Operational Power State Permissive Mode Enable - * @save: Save value across power states - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_NOPSC */ -int nvme_set_features_nopsc(int fd, bool noppme, bool save, __u32 *result); +static inline void +nvme_init_set_features_nopsc(struct nvme_passthru_cmd *cmd, + bool sv, bool noppme) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_NOPSC, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(noppme, + NVME_FEAT_NOPS_NOPPME_SHIFT, + NVME_FEAT_NOPS_NOPPME_MASK); +} /** - * nvme_set_features_rrl() - Set read recovery level feature - * @fd: File descriptor of nvme device - * @rrl: Read recovery level setting + * nvme_init_set_features_rrl() - Initialize passthru command for + * Read Recovery Level + * @cmd: Passthru command to use + * @sv: Save value across power states * @nvmsetid: NVM set id - * @save: Save value across power states - * @result: The command completion result from CQE dword0 + * @rrl: Read recovery level setting * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_RRL */ -int nvme_set_features_rrl(int fd, __u8 rrl, __u16 nvmsetid, bool save, - __u32 *result); +static inline void +nvme_init_set_features_rrl(struct nvme_passthru_cmd *cmd, + bool sv, __u16 nvmsetid, __u8 rrl) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_RRL, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid, + NVME_FEAT_RRL_NVMSETID_SHIFT, + NVME_FEAT_RRL_NVMSETID_MASK); + cmd->cdw12 = NVME_FIELD_ENCODE(rrl, + NVME_FEAT_RRL_RRL_SHIFT, + NVME_FEAT_RRL_RRL_MASK); +} /** - * nvme_set_features_plm_config() - Set predictable latency feature - * @fd: File descriptor of nvme device - * @enable: Predictable Latency Enable + * nvme_init_set_features_plm_config() - Initialize passthru command for + * Predictable Latency Mode Config + * @cmd: Passthru command to use + * @sv: Save value across power states * @nvmsetid: NVM Set Identifier - * @save: Save value across power states + * @lpe: Predictable Latency Enable * @data: Pointer to structure nvme_plm_config - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_PLM_CONFIG */ -int nvme_set_features_plm_config(int fd, bool enable, __u16 nvmsetid, - bool save, struct nvme_plm_config *data, - __u32 *result); +static inline void +nvme_init_set_features_plm_config(struct nvme_passthru_cmd *cmd, + bool sv, __u16 nvmsetid, bool lpe, struct nvme_plm_config *data) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_PLM_CONFIG, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid, + NVME_FEAT_PLM_NVMSETID_SHIFT, + NVME_FEAT_PLM_NVMSETID_MASK); + cmd->cdw12 = NVME_FIELD_ENCODE(lpe, + NVME_FEAT_PLM_LPE_SHIFT, + NVME_FEAT_PLM_LPE_MASK); + cmd->data_len = sizeof(*data); + cmd->addr = (__u64)(uintptr_t)data; +} /** - * nvme_set_features_plm_window() - Set window select feature - * @fd: File descriptor of nvme device - * @sel: Window Select + * nvme_init_set_features_plm_window() - Initialize passthru command for + * Predictable Latency Mode Window + * @cmd: Passthru command to use + * @sv: Save value across power states * @nvmsetid: NVM Set Identifier - * @save: Save value across power states - * @result: The command completion result from CQE dword0 + * @wsel: Window Select * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_PLM_WINDOW */ -int nvme_set_features_plm_window(int fd, enum nvme_feat_plm_window_select sel, - __u16 nvmsetid, bool save, __u32 *result); +static inline void +nvme_init_set_features_plm_window(struct nvme_passthru_cmd *cmd, + bool sv, __u16 nvmsetid, + enum nvme_feat_plm_window_select wsel) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_PLM_WINDOW, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid, + NVME_FEAT_PLM_NVMSETID_SHIFT, + NVME_FEAT_PLM_NVMSETID_MASK); + cmd->cdw12 = NVME_FIELD_ENCODE(wsel, + NVME_FEAT_PLMW_WS_SHIFT, + NVME_FEAT_PLMW_WS_MASK); +} /** - * nvme_set_features_lba_sts_interval() - Set LBA status information feature - * @fd: File descriptor of nvme device - * @save: Save value across power states - * @lsiri: LBA Status Information Report Interval - * @lsipi: LBA Status Information Poll Interval - * @result: The command completion result from CQE dword0 + * nvme_init_set_features_lba_sts_interval() - Initialize passthru command for + * LBA Status Information Interval + * @cmd: Passthru command to use + * @sv: Save value across power states + * @lsiri: LBA Status Information Report Interval + * @lsipi: LBA Status Information Poll Interval * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_LBA_STS_INTERVAL */ -int nvme_set_features_lba_sts_interval(int fd, __u16 lsiri, __u16 lsipi, - bool save, __u32 *result); - +static inline void +nvme_init_set_features_lba_sts_interval(struct nvme_passthru_cmd *cmd, + bool sv, __u16 lsiri, __u16 lsipi) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_LBA_STS_INTERVAL, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(lsiri, + NVME_FEAT_LBAS_LSIRI_SHIFT, + NVME_FEAT_LBAS_LSIRI_MASK) | + NVME_FIELD_ENCODE(lsipi, + NVME_FEAT_LBAS_LSIPI_SHIFT, + NVME_FEAT_LBAS_LSIPI_MASK); +} + /** - * nvme_set_features_host_behavior() - Set host behavior feature - * @fd: File descriptor of nvme device - * @save: Save value across power states + * nvme_init_set_features_host_behavior() - Initialize passthru command for + * Host Behavior + * @cmd: Passthru command to use + * @sv: Save value across power states * @data: Pointer to structure nvme_feat_host_behavior * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_HOST_BEHAVIOR */ -int nvme_set_features_host_behavior(int fd, bool save, - struct nvme_feat_host_behavior *data); +static inline void +nvme_init_set_features_host_behavior(struct nvme_passthru_cmd *cmd, + bool sv, struct nvme_feat_host_behavior *data) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_HOST_BEHAVIOR, sv); + cmd->data_len = sizeof(*data); + cmd->addr = (__u64)(uintptr_t)data; +} /** - * nvme_set_features_sanitize() - Set sanitize feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_sanitize() - Initialize passthru command for + * Sanitize + * @cmd: Passthru command to use + * @sv: Save value across power states * @nodrm: No-Deallocate Response Mode - * @save: Save value across power states - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_SANITIZE */ -int nvme_set_features_sanitize(int fd, bool nodrm, bool save, __u32 *result); +static inline void +nvme_init_set_features_sanitize(struct nvme_passthru_cmd *cmd, + bool sv, bool nodrm) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_SANITIZE, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(nodrm, + NVME_FEAT_SANITIZE_NODRM_SHIFT, + NVME_FEAT_SANITIZE_NODRM_MASK); +} /** - * nvme_set_features_endurance_evt_cfg() - Set endurance event config feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_endurance_evt_cfg() - Initialize passthru command for + * Endurance Group Event Configuration + * @cmd: Passthru command to use + * @sv: Save value across power states * @endgid: Endurance Group Identifier - * @egwarn: Flags to enable warning, see &enum nvme_eg_critical_warning_flags - * @save: Save value across power states - * @result: The command completion result from CQE dword0 + * @egcw: Flags to enable warning, + * see &enum nvme_eg_critical_warning_flags * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_ENDURANCE_EVT_CFG */ -int nvme_set_features_endurance_evt_cfg(int fd, __u16 endgid, __u8 egwarn, - bool save, __u32 *result); +static inline void +nvme_init_set_features_endurance_evt_cfg(struct nvme_passthru_cmd *cmd, + bool sv, __u16 endgid, __u8 egcw) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_ENDURANCE_EVT_CFG, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(endgid, + NVME_FEAT_EG_ENDGID_SHIFT, + NVME_FEAT_EG_ENDGID_MASK) | + NVME_FIELD_ENCODE(egcw, + NVME_FEAT_EG_EGCW_SHIFT, + NVME_FEAT_EG_EGCW_MASK); +} /** - * nvme_set_features_sw_progress() - Set pre-boot software load count feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_sw_progress() - Initialize passthru command for + * Software Pogress Marker + * @cmd: Passthru command to use + * @sv: Save value across power states * @pbslc: Pre-boot Software Load Count - * @save: Save value across power states - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_SW_PROGRESS */ -int nvme_set_features_sw_progress(int fd, __u8 pbslc, bool save, - __u32 *result); +static inline void +nvme_init_set_features_sw_progress(struct nvme_passthru_cmd *cmd, + bool sv, __u8 pbslc) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_SW_PROGRESS, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(pbslc, + NVME_FEAT_SPM_PBSLC_SHIFT, + NVME_FEAT_SPM_PBSLC_MASK); +} /** - * nvme_set_features_host_id() - Set enable extended host identifiers feature - * @fd: File descriptor of nvme device - * @exhid: Enable Extended Host Identifier - * @save: Save value across power states - * @hostid: Host ID to set + * nvme_init_set_features_host_id() - Initialize passthru command for + * Host Identifier + * @cmd: Passthru command to use + * @sv: Save value across power states + * @exhid: Enable Extended Host Identifier + * @hostid: Host ID buffer to set * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_HOST_ID. */ -int nvme_set_features_host_id(int fd, bool exhid, bool save, __u8 *hostid); +static inline void +nvme_init_set_features_host_id(struct nvme_passthru_cmd *cmd, + bool sv, bool exhid, __u8 *hostid) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_HOST_ID, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(exhid, + NVME_FEAT_HOSTID_EXHID_SHIFT, + NVME_FEAT_HOSTID_EXHID_MASK); + cmd->data_len = exhid ? 16 : 8; + cmd->addr = (__u64)(uintptr_t)hostid; +} /** - * nvme_set_features_resv_mask() - Set reservation notification mask feature - * - * Deprecated: doesn't support specifying a NSID. - * Use nvme_set_features_resv_mask2() instead. - * - * @fd: File descriptor of nvme device + * nvme_init_set_features_resv_mask() - Initialize passthru command for + * Reservation Notification Mask + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sv: Save value across power states * @mask: Reservation Notification Mask Field - * @save: Save value across power states - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_RESV_MASK */ -int nvme_set_features_resv_mask(int fd, __u32 mask, bool save, __u32 *result) - __attribute__((deprecated)); +static inline void +nvme_init_set_features_resv_mask(struct nvme_passthru_cmd *cmd, __u32 nsid, + bool sv, __u32 mask) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_RESV_MASK, sv); + cmd->nsid = nsid; + cmd->cdw11 = mask; +} /** - * nvme_set_features_resv_mask2() - Set reservation notification mask feature - * @fd: File descriptor of nvme device + * nvme_init_set_features_resv_persist() - Initialize passthru command for + * Reservation Persistence + * @cmd: Passthru command to use * @nsid: Namespace ID - * @mask: Reservation Notification Mask Field - * @save: Save value across power states - * @result: The command completion result from CQE dword0 + * @sv: Save value across power states + * @ptpl: Persist Through Power Loss * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_RESV_PERSIST */ -int nvme_set_features_resv_mask2(int fd, __u32 nsid, __u32 mask, bool save, - __u32 *result); +static inline void +nvme_init_set_features_resv_persist(struct nvme_passthru_cmd *cmd, __u32 nsid, + bool sv, bool ptpl) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_RESV_PERSIST, sv); + cmd->nsid = nsid; + cmd->cdw11 = NVME_FIELD_ENCODE(ptpl, + NVME_FEAT_RESP_PTPL_SHIFT, + NVME_FEAT_RESP_PTPL_MASK); +} /** - * nvme_set_features_resv_persist() - Set persist through power loss feature - * - * Deprecated: doesn't support specifying a NSID. - * Use nvme_set_features_resv_persist2() instead. - * - * @fd: File descriptor of nvme device - * @ptpl: Persist Through Power Loss - * @save: Save value across power states - * @result: The command completion result from CQE dword0 + * nvme_init_set_features_write_protect() - Initialize passthru command for + * Write Protect + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sv: Save value across power states + * @wps: Write Protection State * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_WRITE_PROTECT */ -int nvme_set_features_resv_persist(int fd, bool ptpl, bool save, __u32 *result) - __attribute__((deprecated)); +static inline void +nvme_init_set_features_write_protect(struct nvme_passthru_cmd *cmd, __u32 nsid, + bool sv, enum nvme_feat_nswpcfg_state wps) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_WRITE_PROTECT, sv); + cmd->nsid = nsid; + cmd->cdw11 = NVME_FIELD_ENCODE(wps, + NVME_FEAT_WP_WPS_SHIFT, + NVME_FEAT_WP_WPS_MASK); +} /** - * nvme_set_features_resv_persist2() - Set persist through power loss feature - * @fd: File descriptor of nvme device - * @nsid: Namespace ID - * @ptpl: Persist Through Power Loss - * @save: Save value across power states - * @result: The command completion result from CQE dword0 + * nvme_init_set_features_iocs_profile() - Initialize passthru command for + * I/O Command Set Profile + * @cmd: Passthru command to use + * @sv: Save value across power states + * @iocsci: I/O Command Set Combination Index * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_IOCS_PROFILE */ -int nvme_set_features_resv_persist2(int fd, __u32 nsid, bool ptpl, bool save, - __u32 *result); +static inline void +nvme_init_set_features_iocs_profile(struct nvme_passthru_cmd *cmd, + bool sv, __u16 iocsci) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_IOCS_PROFILE, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(iocsci, + NVME_FEAT_IOCSP_IOCSCI_SHIFT, + NVME_FEAT_IOCSP_IOCSCI_MASK); +} /** - * nvme_set_features_write_protect() - Set write protect feature - * - * Deprecated: doesn't support specifying a NSID. - * Use nvme_set_features_write_protect2() instead. - * - * @fd: File descriptor of nvme device - * @state: Write Protection State - * @save: Save value across power states - * @result: The command completion result from CQE dword0 - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * nvme_init_get_features() - Initialize passthru command for + * Get Features + * @cmd: Passthru command to use + * @fid: Feature identifier, see &enum nvme_features_id + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel */ -int nvme_set_features_write_protect(int fd, enum nvme_feat_nswpcfg_state state, - bool save, __u32 *result) - __attribute__((deprecated)); +static inline void +nvme_init_get_features(struct nvme_passthru_cmd *cmd, __u8 fid, + enum nvme_get_features_sel sel) +{ + __u32 cdw10 = NVME_FIELD_ENCODE(fid, + NVME_GET_FEATURES_CDW10_FID_SHIFT, + NVME_GET_FEATURES_CDW10_FID_MASK) | + NVME_FIELD_ENCODE(sel, + NVME_GET_FEATURES_CDW10_SEL_SHIFT, + NVME_GET_FEATURES_CDW10_SEL_MASK); + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_get_features; + cmd->cdw10 = cdw10; +} /** - * nvme_set_features_write_protect2() - Set write protect feature - * @fd: File descriptor of nvme device - * @nsid: Namespace ID - * @state: Write Protection State - * @save: Save value across power states - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_arbitration() - Initialize passthru command for + * Get Features - Arbitration + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_ARBITRATION */ -int nvme_set_features_write_protect2(int fd, __u32 nsid, - enum nvme_feat_nswpcfg_state state, - bool save, __u32 *result); +static inline void +nvme_init_get_features_arbitration(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_ARBITRATION, sel); +} /** - * nvme_set_features_iocs_profile() - Set I/O command set profile feature - * @fd: File descriptor of nvme device - * @iocsi: I/O Command Set Combination Index - * @save: Save value across power states + * nvme_init_get_features_power_mgmt() - Initialize passthru command for + * Get Features - Power Management + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_POWER_MGMT */ -int nvme_set_features_iocs_profile(int fd, __u16 iocsi, bool save); +static inline void +nvme_init_get_features_power_mgmt(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_POWER_MGMT, sel); +} /** - * nvme_get_features() - Retrieve a feature attribute - * @args: &struct nvme_get_features_args argument structure + * nvme_init_get_features_lba_range() - Initialize passthru command for + * Get Features - LBA Range + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @lrt: Buffer to receive LBA Range Type data structure * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_LBA_RANGE */ -int nvme_get_features(struct nvme_get_features_args *args); +static inline void +nvme_init_get_features_lba_range(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_get_features_sel sel, struct nvme_lba_range_type *lrt) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_LBA_RANGE, sel); + cmd->nsid = nsid; + cmd->data_len = sizeof(*lrt); + cmd->addr = (__u64)(uintptr_t)lrt; +} /** - * nvme_get_features_data() - Helper function for @nvme_get_features() - * @fd: File descriptor of nvme device - * @fid: Feature identifier - * @nsid: Namespace ID, if applicable - * @data_len: Length of feature data, if applicable, in bytes - * @data: User address of feature data, if applicable - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_temp_thresh() - Initialize passthru command for + * Get Features - Temperature Threshold + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @tmpsel: Threshold Temperature Select + * @thsel: Threshold Type Select * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_TEMP_THRESH */ -static inline int nvme_get_features_data(int fd, enum nvme_features_id fid, - __u32 nsid, __u32 data_len, void *data, __u32 *result) +static inline void +nvme_init_get_features_temp_thresh(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, + __u8 tmpsel, enum nvme_feat_tmpthresh_thsel thsel) { - struct nvme_get_features_args args = { - .result = result, - .data = data, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .nsid = nsid, - .sel = NVME_GET_FEATURES_SEL_CURRENT, - .cdw11 = 0, - .data_len = data_len, - .fid = (__u8)fid, - .uuidx = NVME_UUID_NONE, - }; - return nvme_get_features(&args); + nvme_init_get_features(cmd, NVME_FEAT_FID_TEMP_THRESH, sel); + cmd->cdw11 = NVME_FIELD_ENCODE(tmpsel, + NVME_FEAT_TT_TMPSEL_SHIFT, + NVME_FEAT_TT_TMPSEL_MASK) | + NVME_FIELD_ENCODE(thsel, + NVME_FEAT_TT_THSEL_SHIFT, + NVME_FEAT_TT_THSEL_MASK); } /** - * nvme_get_features_simple() - Helper function for @nvme_get_features() - * @fd: File descriptor of nvme device - * @fid: Feature identifier - * @nsid: Namespace ID, if applicable - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_err_recovery() - Initialize passthru command for + * Get Features - Error Recovery + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_ERR_RECOVERY */ -static inline int nvme_get_features_simple(int fd, enum nvme_features_id fid, - __u32 nsid, __u32 *result) +static inline void +nvme_init_get_features_err_recovery(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_get_features_sel sel) { - return nvme_get_features_data(fd, fid, nsid, 0, NULL, result); + nvme_init_get_features(cmd, NVME_FEAT_FID_ERR_RECOVERY, sel); + cmd->nsid = nsid; } /** - * nvme_get_features_arbitration() - Get arbitration feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_volatile_wc() - Initialize passthru command for + * Get Features - Volatile Write Cache + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_VOLATILE_WC */ -int nvme_get_features_arbitration(int fd, enum nvme_get_features_sel sel, - __u32 *result); +static inline void +nvme_init_get_features_volatile_wc(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_VOLATILE_WC, sel); +} /** - * nvme_get_features_power_mgmt() - Get power management feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_num_queues() - Initialize passthru command for + * Get Features - Number of Queues + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_NUM_QUEUES */ -int nvme_get_features_power_mgmt(int fd, enum nvme_get_features_sel sel, - __u32 *result); +static inline void +nvme_init_get_features_num_queues(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_NUM_QUEUES, sel); +} /** - * nvme_get_features_lba_range() - Get LBA range feature + * nvme_init_get_features_irq_coalesce() - Initialize passthru command for + * Get Features - IRQ Coalesce + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Deprecated: doesn't support specifying a NSID. - * Use nvme_get_features_lba_range2() instead. - * - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @data: User address of feature data, if applicable - * @result: The command completion result from CQE dword0 - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_IRQ_COALESCE */ -int nvme_get_features_lba_range(int fd, enum nvme_get_features_sel sel, - struct nvme_lba_range_type *data, - __u32 *result) __attribute__((deprecated)); +static inline void +nvme_init_get_features_irq_coalesce(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_IRQ_COALESCE, sel); +} /** - * nvme_get_features_lba_range2() - Get LBA range feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @nsid: Namespace ID - * @data: Buffer to receive LBA Range Type data structure - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_irq_config() - Initialize passthru command for + * Get Features - IRQ Config + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @iv: Interrupt Vector + * @cd: Coalescing Disable * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_IRQ_CONFIG */ -int nvme_get_features_lba_range2(int fd, enum nvme_get_features_sel sel, - __u32 nsid, struct nvme_lba_range_type *data, - __u32 *result); +static inline void +nvme_init_get_features_irq_config(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, + __u16 iv, bool cd) +{ + __u32 cdw11 = NVME_FIELD_ENCODE(iv, + NVME_FEAT_ICFG_IV_SHIFT, + NVME_FEAT_ICFG_IV_MASK) | + NVME_FIELD_ENCODE(cd, + NVME_FEAT_ICFG_CD_SHIFT, + NVME_FEAT_ICFG_CD_MASK); + + nvme_init_get_features(cmd, NVME_FEAT_FID_IRQ_CONFIG, sel); + cmd->cdw11 = cdw11; +} /** - * nvme_get_features_temp_thresh() - Get temperature threshold feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_write_atomic() - Initialize passthru command for + * Get Features - Write Atomic + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_WRITE_ATOMIC */ -int nvme_get_features_temp_thresh(int fd, enum nvme_get_features_sel sel, - __u32 *result); +static inline void +nvme_init_get_features_write_atomic(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_WRITE_ATOMIC, sel); +} /** - * nvme_get_features_temp_thresh2() - Get temperature threshold feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @tmpsel: Threshold Temperature Select - * @thsel: Threshold Type Select - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_async_event() - Initialize passthru command for + * Get Features - Asynchronous Event Configuration + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_ASYNC_EVENT */ -int nvme_get_features_temp_thresh2(int fd, enum nvme_get_features_sel sel, __u8 tmpsel, - enum nvme_feat_tmpthresh_thsel thsel, __u32 *result); +static inline void +nvme_init_get_features_async_event(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_ASYNC_EVENT, sel); +} /** - * nvme_get_features_err_recovery() - Get error recovery feature + * nvme_init_get_features_auto_pst() - Initialize passthru command for + * Get Features - Autonomous Power State Transition + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @apst: Autonomous Power State Transition data buffer * - * Deprecated: doesn't support specifying a NSID. - * Use nvme_get_features_err_recovery2() instead. - * - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_AUTO_PST */ -int nvme_get_features_err_recovery(int fd, enum nvme_get_features_sel sel, - __u32 *result) __attribute__((deprecated)); +static inline void +nvme_init_get_features_auto_pst(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, struct nvme_feat_auto_pst *apst) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_AUTO_PST, sel); + cmd->data_len = sizeof(*apst); + cmd->addr = (__u64)(uintptr_t)apst; +} /** - * nvme_get_features_err_recovery2() - Get error recovery feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @nsid: Namespace ID - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_host_mem_buf() - Initialize passthru command for + * Get Features - Host Memory Buffer + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @attrs: Buffer for returned Host Memory Buffer Attributes * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_HOST_MEM_BUF */ -int nvme_get_features_err_recovery2(int fd, enum nvme_get_features_sel sel, - __u32 nsid, __u32 *result); +static inline void +nvme_init_get_features_host_mem_buf(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, + struct nvme_host_mem_buf_attrs *attrs) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_HOST_MEM_BUF, sel); + cmd->data_len = sizeof(*attrs); + cmd->addr = (__u64)(uintptr_t)attrs; +} /** - * nvme_get_features_volatile_wc() - Get volatile write cache feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_timestamp() - Initialize passthru command for + * Get Features - Timestamp + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @ts: Current timestamp buffer * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_TIMESTAMP */ -int nvme_get_features_volatile_wc(int fd, enum nvme_get_features_sel sel, - __u32 *result); +static inline void +nvme_init_get_features_timestamp(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, struct nvme_timestamp *ts) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_TIMESTAMP, sel); + cmd->data_len = sizeof(*ts); + cmd->addr = (__u64)(uintptr_t)ts; +} /** - * nvme_get_features_num_queues() - Get number of queues feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_kato() - Initialize passthru command for + * Get Features - Keep Alive Timeout + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_KATO */ -int nvme_get_features_num_queues(int fd, enum nvme_get_features_sel sel, - __u32 *result); +static inline void +nvme_init_get_features_kato(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_KATO, sel); +} /** - * nvme_get_features_irq_coalesce() - Get IRQ coalesce feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_hctm() - Initialize passthru command for + * Get Features - Host Controlled Thermal Management + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_HCTM */ -int nvme_get_features_irq_coalesce(int fd, enum nvme_get_features_sel sel, - __u32 *result); +static inline void +nvme_init_get_features_hctm(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_HCTM, sel); +} /** - * nvme_get_features_irq_config() - Get IRQ config feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @iv: - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_nopsc() - Initialize passthru command for + * Get Features - Non-Operational Power State Config + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_NOPSC */ -int nvme_get_features_irq_config(int fd, enum nvme_get_features_sel sel, - __u16 iv, __u32 *result); +static inline void +nvme_init_get_features_nopsc(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_NOPSC, sel); +} /** - * nvme_get_features_write_atomic() - Get write atomic feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_rrl() - Initialize passthru command for + * Get Features - Read Recovery Level + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_RRL */ -int nvme_get_features_write_atomic(int fd, enum nvme_get_features_sel sel, - __u32 *result); +static inline void +nvme_init_get_features_rrl(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_RRL, sel); +} /** - * nvme_get_features_async_event() - Get asynchronous event feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_plm_config() - Initialize passthru command for + * Get Features - Predictable Latency Mode Config + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @nvmsetid: NVM set id + * @plmc: Buffer for returned Predictable Latency Mode Config * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_PLM_CONFIG */ -int nvme_get_features_async_event(int fd, enum nvme_get_features_sel sel, - __u32 *result); +static inline void +nvme_init_get_features_plm_config(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, __u16 nvmsetid, + struct nvme_plm_config *plmc) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_PLM_CONFIG, sel); + cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid, + NVME_FEAT_PLM_NVMSETID_SHIFT, + NVME_FEAT_PLM_NVMSETID_MASK); + cmd->data_len = sizeof(*plmc); + cmd->addr = (__u64)(uintptr_t)plmc; +} /** - * nvme_get_features_auto_pst() - Get autonomous power state feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @apst: - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_plm_window() - Initialize passthru command for + * Get Features - Predictable Latency Mode Window + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @nvmsetid: NVM set id * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_PLM_WINDOW */ -int nvme_get_features_auto_pst(int fd, enum nvme_get_features_sel sel, - struct nvme_feat_auto_pst *apst, __u32 *result); +static inline void +nvme_init_get_features_plm_window(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, __u16 nvmsetid) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_PLM_WINDOW, sel); + cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid, + NVME_FEAT_PLM_NVMSETID_SHIFT, + NVME_FEAT_PLM_NVMSETID_MASK); +} /** - * nvme_get_features_host_mem_buf() - Get host memory buffer feature + * nvme_init_get_features_lba_sts_interval() - Initialize passthru command for + * Get Features - LBA Status Information Interval + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Deprecated: doesn't fetch the Host Memory Buffer Attributes data structure. - * Use nvme_get_features_host_mem_buf2() instead. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_LBA_STS_INTERVAL + */ +static inline void +nvme_init_get_features_lba_sts_interval(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_LBA_STS_INTERVAL, sel); +} + +/** + * nvme_init_get_features_host_behavior() - Initialize passthru command for + * Get Features - Host Behavior + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @fhb: Pointer to structure nvme_feat_host_behavior * - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_HOST_BEHAVIOR + */ +static inline void +nvme_init_get_features_host_behavior(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, + struct nvme_feat_host_behavior *fhb) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_HOST_BEHAVIOR, sel); + cmd->data_len = sizeof(*fhb); + cmd->addr = (__u64)(uintptr_t)fhb; +} + +/** + * nvme_init_get_features_sanitize() - Initialize passthru command for + * Get Features - Sanitize + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_SANITIZE */ -int nvme_get_features_host_mem_buf(int fd, enum nvme_get_features_sel sel, - __u32 *result) __attribute__((deprecated)); +static inline void +nvme_init_get_features_sanitize(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_SANITIZE, sel); +} /** - * nvme_get_features_host_mem_buf2() - Get host memory buffer feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @attrs: Buffer for returned Host Memory Buffer Attributes - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_endurance_event_cfg() - Initialize passthru command + * for Get Features - Endurance Group Event Configuration + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @endgid: Endurance Group Identifier * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_ENDURANCE_EVT_CFG */ -int nvme_get_features_host_mem_buf2(int fd, enum nvme_get_features_sel sel, - struct nvme_host_mem_buf_attrs *attrs, - __u32 *result); +static inline void +nvme_init_get_features_endurance_event_cfg(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, __u16 endgid) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_ENDURANCE_EVT_CFG, sel); + cmd->cdw11 = NVME_FIELD_ENCODE(endgid, + NVME_FEAT_EG_ENDGID_SHIFT, + NVME_FEAT_EG_ENDGID_MASK); +} /** - * nvme_get_features_timestamp() - Get timestamp feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @ts: Current timestamp + * nvme_init_get_features_sw_progress() - Initialize passthru command for + * Get Features - Software Progress + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_SW_PROGRESS */ -int nvme_get_features_timestamp(int fd, enum nvme_get_features_sel sel, - struct nvme_timestamp *ts); +static inline void +nvme_init_get_features_sw_progress(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_SW_PROGRESS, sel); +} /** - * nvme_get_features_kato() - Get keep alive timeout feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_host_id() - Initialize passthru command for + * Get Features - Host Identifier + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @exhid: Enable Extended Host Identifier + * @hostid: Buffer for returned host ID + * @len: Length of @hostid * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_HOST_ID */ -int nvme_get_features_kato(int fd, enum nvme_get_features_sel sel, __u32 *result); +static inline void +nvme_init_get_features_host_id(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, bool exhid, + void *hostid, __u32 len) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_HOST_ID, sel); + cmd->cdw11 = NVME_FIELD_ENCODE(exhid, + NVME_FEAT_HOSTID_EXHID_SHIFT, + NVME_FEAT_HOSTID_EXHID_MASK); + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)hostid; +} /** - * nvme_get_features_hctm() - Get thermal management feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_resv_mask() - Initialize passthru command for + * Get Features - Reservation Notification Mask + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_RESV_MASK */ -int nvme_get_features_hctm(int fd, enum nvme_get_features_sel sel, __u32 *result); +static inline void +nvme_init_get_features_resv_mask(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_RESV_MASK, sel); + cmd->nsid = nsid; +} /** - * nvme_get_features_nopsc() - Get non-operational power state feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_resv_persist() - Initialize passthru command for + * Get Features - Reservation Persistence + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_RESV_PERSIST */ -int nvme_get_features_nopsc(int fd, enum nvme_get_features_sel sel, __u32 *result); +static inline void +nvme_init_get_features_resv_persist(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_RESV_PERSIST, sel); + cmd->nsid = nsid; +} /** - * nvme_get_features_rrl() - Get read recovery level feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_write_protect() - Initialize passthru command for + * Get Features - Write Protect + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_WRITE_PROTECT */ -int nvme_get_features_rrl(int fd, enum nvme_get_features_sel sel, __u32 *result); +static inline void +nvme_init_get_features_write_protect(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_WRITE_PROTECT, sel); + cmd->nsid = nsid; +} /** - * nvme_get_features_plm_config() - Get predictable latency feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @nvmsetid: NVM set id - * @data: - * @result: The command completion result from CQE dword0 + * nvme_init_get_features_iocs_profile() - Initialize passthru command for + * Get Features - I/O Command Set Profile + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_IOCS_PROFILE */ -int nvme_get_features_plm_config(int fd, enum nvme_get_features_sel sel, - __u16 nvmsetid, struct nvme_plm_config *data, - __u32 *result); +static inline void +nvme_init_get_features_iocs_profile(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_IOCS_PROFILE, sel); +} /** - * nvme_get_features_plm_window() - Get window select feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @nvmsetid: NVM set id - * @result: The command completion result from CQE dword0 + * nvme_init_format_nvm() - Initialize passthru command for Format NVM + * @cmd: Passthru command to use + * @nsid: Namespace ID to format + * @lbaf: Logical block address format + * @mset: Metadata settings (extended or separated) + * @pi: Protection information type + * @pil: Protection information location (beginning or end) + * @ses: Secure erase settings * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Format NVM command. */ -int nvme_get_features_plm_window(int fd, enum nvme_get_features_sel sel, - __u16 nvmsetid, __u32 *result); +static inline void +nvme_init_format_nvm(struct nvme_passthru_cmd *cmd, __u32 nsid, __u8 lbaf, + enum nvme_cmd_format_mset mset, enum nvme_cmd_format_pi pi, + enum nvme_cmd_format_pil pil, enum nvme_cmd_format_ses ses) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_format_nvm; + cmd->nsid = nsid; + cmd->cdw10 = NVME_FIELD_ENCODE(lbaf, + NVME_FORMAT_CDW10_LBAFL_SHIFT, + NVME_FORMAT_CDW10_LBAFL_MASK) | + NVME_FIELD_ENCODE(mset, + NVME_FORMAT_CDW10_MSET_SHIFT, + NVME_FORMAT_CDW10_MSET_MASK) | + NVME_FIELD_ENCODE(pi, + NVME_FORMAT_CDW10_PI_SHIFT, + NVME_FORMAT_CDW10_PI_MASK) | + NVME_FIELD_ENCODE(pil, + NVME_FORMAT_CDW10_PIL_SHIFT, + NVME_FORMAT_CDW10_PIL_MASK) | + NVME_FIELD_ENCODE(ses, + NVME_FORMAT_CDW10_SES_SHIFT, + NVME_FORMAT_CDW10_SES_MASK) | + NVME_FIELD_ENCODE((lbaf >> 4), + NVME_FORMAT_CDW10_LBAFU_SHIFT, + NVME_FORMAT_CDW10_LBAFU_MASK); +} /** - * nvme_get_features_lba_sts_interval() - Get LBA status information feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_ns_mgmt() - Initialize passthru command for Namespace Management + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @sel: Type of management operation to perform + * @csi: Command Set Identifier + * @data: Host Software Specified Fields buffer * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Namespace Management command. */ -int nvme_get_features_lba_sts_interval(int fd, enum nvme_get_features_sel sel, - __u32 *result); +static inline void +nvme_init_ns_mgmt(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_ns_mgmt_sel sel, __u8 csi, + struct nvme_ns_mgmt_host_sw_specified *data) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_ns_mgmt; + cmd->nsid = nsid; + cmd->data_len = data ? sizeof(*data) : 0; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(sel, + NVME_NAMESPACE_MGMT_CDW10_SEL_SHIFT, + NVME_NAMESPACE_MGMT_CDW10_SEL_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(csi, + NVME_NAMESPACE_MGMT_CDW11_CSI_SHIFT, + NVME_NAMESPACE_MGMT_CDW11_CSI_MASK); +} /** - * nvme_get_features_host_behavior() - Get host behavior feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @data: Pointer to structure nvme_feat_host_behavior - * @result: The command completion result from CQE dword0 + * nvme_init_ns_mgmt_create() - Initialize passthru command to create a + * non attached namespace + * @cmd: Passthru command to use + * @csi: Command Set Identifier + * @data: Host Software Specified Fields buffer that defines NS + * creation parameters * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Namespace Management - Create + * command. The command uses NVME_NSID_NONE as the target NSID. */ -int nvme_get_features_host_behavior(int fd, enum nvme_get_features_sel sel, - struct nvme_feat_host_behavior *data, - __u32 *result); +static inline void +nvme_init_ns_mgmt_create(struct nvme_passthru_cmd *cmd, __u8 csi, + struct nvme_ns_mgmt_host_sw_specified *data) +{ + nvme_init_ns_mgmt(cmd, NVME_NSID_NONE, NVME_NS_MGMT_SEL_CREATE, + csi, data); +} /** - * nvme_get_features_sanitize() - Get sanitize feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_ns_mgmt_delete() - Initialize passthru command to delete a + * non attached namespace + * @cmd: Passthru command to use + * @nsid: Namespace identifier to delete * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Namespace Management - Delete + * command (NVME_NS_MGMT_SEL_DELETE). The command uses the provided @nsid as + * the target NSID. */ -int nvme_get_features_sanitize(int fd, enum nvme_get_features_sel sel, - __u32 *result); +static inline void +nvme_init_ns_mgmt_delete(struct nvme_passthru_cmd *cmd, __u32 nsid) +{ + nvme_init_ns_mgmt(cmd, nsid, NVME_NS_MGMT_SEL_DELETE, + NVME_CSI_NVM, NULL); +} /** - * nvme_get_features_endurance_event_cfg() - Get endurance event config feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @endgid: Endurance Group Identifier - * @result: The command completion result from CQE dword0 + * nvme_init_ns_attach() - Initialize passthru command for + * Namespace Attach/Detach + * @cmd: Passthru command to use + * @nsid: Namespace ID to execute attach selection + * @sel: Attachment selection, see &enum nvme_ns_attach_sel + * @ctrlist: Controller list buffer to modify attachment state of nsid * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Namespace Attach/Detach command. */ -int nvme_get_features_endurance_event_cfg(int fd, enum nvme_get_features_sel sel, - __u16 endgid, __u32 *result); +static inline void +nvme_init_ns_attach(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_ns_attach_sel sel, struct nvme_ctrl_list *ctrlist) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_ns_attach; + cmd->nsid = nsid; + cmd->data_len = sizeof(*ctrlist); + cmd->addr = (__u64)(uintptr_t)ctrlist; + cmd->cdw10 = NVME_FIELD_ENCODE(sel, + NVME_NAMESPACE_ATTACH_CDW10_SEL_SHIFT, + NVME_NAMESPACE_ATTACH_CDW10_SEL_MASK); +} /** - * nvme_get_features_sw_progress() - Get software progress feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_ns_attach_ctrls() - Initialize passthru command to attach + * namespace to controllers + * @cmd: Passthru command to use + * @nsid: Namespace ID to attach + * @ctrlist: Controller list buffer to modify attachment state of nsid * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Namespace Attach command + * (NVME_NS_ATTACH_SEL_CTRL_ATTACH). */ -int nvme_get_features_sw_progress(int fd, enum nvme_get_features_sel sel, - __u32 *result); +static inline void +nvme_init_ns_attach_ctrls(struct nvme_passthru_cmd *cmd, __u32 nsid, + struct nvme_ctrl_list *ctrlist) +{ + nvme_init_ns_attach(cmd, nsid, NVME_NS_ATTACH_SEL_CTRL_ATTACH, + ctrlist); +} /** - * nvme_get_features_host_id() - Get host id feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @exhid: Enable Extended Host Identifier - * @len: Length of @hostid - * @hostid: Buffer for returned host ID + * nvme_init_ns_detach_ctrls() - Initialize passthru command to detach + * namespace from controllers + * @cmd: Passthru command to use + * @nsid: Namespace ID to detach + * @ctrlist: Controller list buffer to modify attachment state of nsid * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Namespace Detach command + * (NVME_NS_ATTACH_SEL_CTRL_DEATTACH). */ -int nvme_get_features_host_id(int fd, enum nvme_get_features_sel sel, - bool exhid, __u32 len, __u8 *hostid); +static inline void +nvme_init_ns_detach_ctrls(struct nvme_passthru_cmd *cmd, __u32 nsid, + struct nvme_ctrl_list *ctrlist) +{ + nvme_init_ns_attach(cmd, nsid, NVME_NS_ATTACH_SEL_CTRL_DEATTACH, + ctrlist); +} /** - * nvme_get_features_resv_mask() - Get reservation mask feature + * nvme_init_fw_download() - Initialize passthru command to download part or + * all of a firmware image to the controller + * @cmd: Passthru command to use + * @data: Userspace address of the firmware data buffer + * @len: Length of data in this command in bytes + * @offset: Offset in the firmware data * - * Deprecated: doesn't support specifying a NSID. - * Use nvme_get_features_resv_mask2() instead. + * Initializes the passthru command buffer for the Firmware Image + * Download command. * - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * Note: Caller must ensure data_len and offset are DWord-aligned (0x4). * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Returns: 0 on success, or error code if arguments are invalid. */ -int nvme_get_features_resv_mask(int fd, enum nvme_get_features_sel sel, - __u32 *result) __attribute__((deprecated)); +static inline int +nvme_init_fw_download(struct nvme_passthru_cmd *cmd, void *data, + __u32 len, __u32 offset) +{ + if (len & 0x3 || !len) + return -EINVAL; + + if (offset & 0x3) + return -EINVAL; + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_fw_download; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = (len >> 2) - 1;; + cmd->cdw11 = offset >> 2; + + return 0; +} /** - * nvme_get_features_resv_mask2() - Get reservation mask feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @nsid: Namespace ID - * @result: The command completion result from CQE dword0 + * nvme_init_fw_commit() - Initialize passthru command to commit firmware + * using the specified action + * @cmd: Passthru command to use + * @fs: Firmware slot to commit the downloaded image + * @ca: Action to use for the firmware image, + * see &enum nvme_fw_commit_ca + * @bpid: Set to true to select the boot partition id + * + * Initializes the passthru command buffer for the Firmware Commit command. + */ +static inline void +nvme_init_fw_commit(struct nvme_passthru_cmd *cmd, __u8 fs, + enum nvme_fw_commit_ca ca, bool bpid) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_fw_commit; + cmd->cdw10 = NVME_FIELD_ENCODE(fs, + NVME_FW_COMMIT_CDW10_FS_SHIFT, + NVME_FW_COMMIT_CDW10_FS_MASK) | + NVME_FIELD_ENCODE(ca, + NVME_FW_COMMIT_CDW10_CA_SHIFT, + NVME_FW_COMMIT_CDW10_CA_MASK) | + NVME_FIELD_ENCODE(bpid, + NVME_FW_COMMIT_CDW10_BPID_SHIFT, + NVME_FW_COMMIT_CDW10_BPID_MASK); +} + +/** + * nvme_init_security_send() - Initialize passthru command for Security Send + * @cmd: Passthru command to use + * @nsid: Namespace ID to issue security command on + * @nssf: NVMe Security Specific field + * @spsp: Security Protocol Specific field + * @secp: Security Protocol + * @tl: Protocol specific transfer length + * @data: Security data payload buffer to send + * @len: Data length of the payload in bytes * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Security Send command. */ -int nvme_get_features_resv_mask2(int fd, enum nvme_get_features_sel sel, - __u32 nsid, __u32 *result); +static inline void +nvme_init_security_send(struct nvme_passthru_cmd *cmd, __u32 nsid, __u8 nssf, + __u16 spsp, __u8 secp, __u32 tl, void *data, __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_security_send; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(secp, + NVME_SECURITY_SECP_SHIFT, + NVME_SECURITY_SECP_MASK) | + NVME_FIELD_ENCODE(spsp, + NVME_SECURITY_SPSP0_SHIFT, + NVME_SECURITY_SPSP0_MASK) | + NVME_FIELD_ENCODE(spsp >> 8, + NVME_SECURITY_SPSP1_SHIFT, + NVME_SECURITY_SPSP1_MASK) | + NVME_FIELD_ENCODE(nssf, + NVME_SECURITY_NSSF_SHIFT, + NVME_SECURITY_NSSF_MASK); + cmd->cdw11 = tl; +} /** - * nvme_get_features_resv_persist() - Get reservation persist feature + * nvme_init_security_receive() - Initialize passthru command for + * Security Receive + * @cmd: Passthru command to use + * @nsid: Namespace ID to issue security command on + * @nssf: NVMe Security Specific field + * @spsp: Security Protocol Specific field + * @secp: Security Protocol + * @al: Protocol specific allocation length + * @data: Security data payload buffer to receive data into + * @len: Data length of the payload in bytes (must match @al) * - * Deprecated: doesn't support specifying a NSID. - * Use nvme_get_features_resv_persist2() instead. + * Initializes the passthru command buffer for the Security Receive command. + */ +static inline void +nvme_init_security_receive(struct nvme_passthru_cmd *cmd, __u32 nsid, __u8 nssf, + __u16 spsp, __u8 secp, __u32 al, void *data, __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_security_recv; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(secp, + NVME_SECURITY_SECP_SHIFT, + NVME_SECURITY_SECP_MASK) | + NVME_FIELD_ENCODE(spsp, + NVME_SECURITY_SPSP0_SHIFT, + NVME_SECURITY_SPSP0_MASK) | + NVME_FIELD_ENCODE(spsp >> 8, + NVME_SECURITY_SPSP1_SHIFT, + NVME_SECURITY_SPSP1_MASK) | + NVME_FIELD_ENCODE(nssf, + NVME_SECURITY_NSSF_SHIFT, + NVME_SECURITY_NSSF_MASK); + cmd->cdw11 = al; +} + +/** + * nvme_init_get_lba_status() - Initialize passthru command to retrieve + * information on possibly unrecoverable LBAs + * @cmd: Passthru command to use + * @nsid: Namespace ID to retrieve LBA status + * @slba: Starting logical block address to check statuses + * @mndw: Maximum number of dwords to return + * @atype: Action type mechanism to determine LBA status descriptors to + * return, see &enum nvme_lba_status_atype + * @rl: Range length from slba to perform the action + * @lbas: Data payload buffer to return status descriptors * - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * Initializes the passthru command buffer for the Get LBA Status command. + */ +static inline void +nvme_init_get_lba_status(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, + __u32 mndw, enum nvme_lba_status_atype atype, __u16 rl, + struct nvme_lba_status *lbas) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_get_lba_status; + cmd->nsid = nsid; + cmd->data_len = (mndw + 1) << 2; + cmd->addr = (__u64)(uintptr_t)lbas; + cmd->cdw10 = slba & 0xffffffff; + cmd->cdw11 = slba >> 32; + cmd->cdw12 = mndw; + cmd->cdw13 = NVME_FIELD_ENCODE(rl, + NVME_GET_LBA_STATUS_CDW13_RL_SHIFT, + NVME_GET_LBA_STATUS_CDW13_RL_MASK) | + NVME_FIELD_ENCODE(atype, + NVME_GET_LBA_STATUS_CDW13_ATYPE_SHIFT, + NVME_GET_LBA_STATUS_CDW13_ATYPE_MASK); +} + +/** + * nvme_init_directive_send() - Initialize passthru command for Directive Send + * @cmd: Passthru command to use + * @nsid: Namespace ID, if applicable + * @doper: Directive send operation, see &enum nvme_directive_send_doper + * @dtype: Directive type, see &enum nvme_directive_dtype + * @dspec: Directive specific field + * @data: Data payload buffer to be send + * @len: Length of data payload in bytes + * + * Initializes the passthru command buffer for the Directive Send command. + */ +static inline void +nvme_init_directive_send(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_directive_send_doper doper, + enum nvme_directive_dtype dtype, __u16 dspec, + void *data, __u32 len) +{ + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_directive_send; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = len? (len >> 2) - 1 : 0; + cmd->cdw11 = NVME_FIELD_ENCODE(doper, + NVME_DIRECTIVE_CDW11_DOPER_SHIFT, + NVME_DIRECTIVE_CDW11_DOPER_MASK) | + NVME_FIELD_ENCODE(dtype, + NVME_DIRECTIVE_CDW11_DTYPE_SHIFT, + NVME_DIRECTIVE_CDW11_DTYPE_MASK) | + NVME_FIELD_ENCODE(dspec, + NVME_DIRECTIVE_CDW11_DPSEC_SHIFT, + NVME_DIRECTIVE_CDW11_DPSEC_MASK); +} + +/** + * nvme_init_directive_send_id_endir() - Initialize passthru command for + * Directive Send Enable Directive + * @cmd: Passthru command to use + * @nsid: Namespace Identifier + * @endir: Enable Directive + * @dtype: Directive Type + * @id: Pointer to structure nvme_id_directives * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Directive Send - Identify + * (Enable Directive) command. */ -int nvme_get_features_resv_persist(int fd, enum nvme_get_features_sel sel, - __u32 *result) __attribute__((deprecated)); +static inline void +nvme_init_directive_send_id_endir(struct nvme_passthru_cmd *cmd, __u32 nsid, + bool endir, enum nvme_directive_dtype dtype, + struct nvme_id_directives *id) +{ + nvme_init_directive_send(cmd, nsid, + NVME_DIRECTIVE_SEND_IDENTIFY_DOPER_ENDIR, + NVME_DIRECTIVE_DTYPE_IDENTIFY, 0, id, sizeof(*id)); + cmd->cdw12 = NVME_FIELD_ENCODE(dtype, + NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_SHIFT, + NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_MASK) | + NVME_FIELD_ENCODE(endir, + NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_SHIFT, + NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_MASK); +} /** - * nvme_get_features_resv_persist2() - Get reservation persist feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel + * nvme_init_directive_send_stream_release_identifier() - Initialize passthru + * command for Directive Send Stream release identifier + * @cmd: Passthru command to use * @nsid: Namespace ID - * @result: The command completion result from CQE dword0 + * @stream_id: Stream identifier * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Directive Send - Stream + * Release Identifier command. */ -int nvme_get_features_resv_persist2(int fd, enum nvme_get_features_sel sel, - __u32 nsid, __u32 *result); +static inline void +nvme_init_directive_send_stream_release_identifier(struct nvme_passthru_cmd *cmd, + __u32 nsid, __u16 stream_id) +{ + nvme_init_directive_send(cmd, nsid, + NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_IDENTIFIER, + NVME_DIRECTIVE_DTYPE_STREAMS, stream_id, NULL, 0); +} /** - * nvme_get_features_write_protect() - Get write protect feature - * @fd: File descriptor of nvme device + * nvme_init_directive_send_stream_release_resource() - Initialize passthru + * command for Directive Send Stream release resources + * @cmd: Passthru command to use * @nsid: Namespace ID - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Directive Send - Stream + * Release Resource command. */ -int nvme_get_features_write_protect(int fd, __u32 nsid, - enum nvme_get_features_sel sel, - __u32 *result); +static inline void +nvme_init_directive_send_stream_release_resource(struct nvme_passthru_cmd *cmd, + __u32 nsid) +{ + nvme_init_directive_send(cmd, nsid, + NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_RESOURCE, + NVME_DIRECTIVE_DTYPE_STREAMS, 0, NULL, 0); +} /** - * nvme_get_features_iocs_profile() - Get IOCS profile feature - * @fd: File descriptor of nvme device - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The command completion result from CQE dword0 + * nvme_init_directive_recv() - Initialize passthru command for + * Directive Receive + * @cmd: Passthru command to use + * @nsid: Namespace ID, if applicable + * @doper: Directive receive operation, + * see &enum nvme_directive_receive_doper + * @dtype: Directive type, see &enum nvme_directive_dtype + * @dspec: Directive specific field + * @data: Userspace address of data payload buffer + * @len: Length of data payload in bytes + * + * Initializes the passthru command buffer for the Directive Receive command. + */ +static inline void +nvme_init_directive_recv(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_directive_receive_doper doper, + enum nvme_directive_dtype dtype, __u16 dspec, + void *data, __u32 len) +{ + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_directive_recv; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = len ? (len >> 2) - 1 : 0; + cmd->cdw11 = NVME_FIELD_ENCODE(doper, + NVME_DIRECTIVE_CDW11_DOPER_SHIFT, + NVME_DIRECTIVE_CDW11_DOPER_MASK) | + NVME_FIELD_ENCODE(dtype, + NVME_DIRECTIVE_CDW11_DTYPE_SHIFT, + NVME_DIRECTIVE_CDW11_DTYPE_MASK) | + NVME_FIELD_ENCODE(dspec, + NVME_DIRECTIVE_CDW11_DPSEC_SHIFT, + NVME_DIRECTIVE_CDW11_DPSEC_MASK); +} + +/** + * nvme_init_directive_recv_identify_parameters() - Initialize passthru command + * for Directive Receive Identify Parameters + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @id: Identify parameters buffer * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Initializes the passthru command buffer for the Directive Receive - Identify + * Parameters command. */ -int nvme_get_features_iocs_profile(int fd, enum nvme_get_features_sel sel, - __u32 *result); +static inline void +nvme_init_directive_recv_identify_parameters(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_id_directives *id) +{ + nvme_init_directive_recv(cmd, nsid, + NVME_DIRECTIVE_RECEIVE_IDENTIFY_DOPER_PARAM, + NVME_DIRECTIVE_DTYPE_IDENTIFY, 0, id, sizeof(*id)); +} /** - * nvme_format_nvm() - Format nvme namespace(s) - * @args: &struct nvme_format_nvme_args argument structure + * nvme_init_directive_recv_stream_parameters() - Initialize passthru command + * for Directive Receive Stream Parameters + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @parms: Streams directive parameters buffer + * + * Initializes the passthru command buffer for the Directive Receive - Stream + * Parameters command. + */ +static inline void +nvme_init_directive_recv_stream_parameters(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_streams_directive_params *parms) +{ + nvme_init_directive_recv(cmd, nsid, + NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM, + NVME_DIRECTIVE_DTYPE_STREAMS, 0, parms, sizeof(*parms)); +} + +/** + * nvme_init_directive_recv_stream_status() - Initialize passthru command for + * Directive Receive Stream Status + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @nr_entries: Number of streams to receive + * @id: Stream status buffer + * + * Initializes the passthru command buffer for the Directive Receive - Stream + * Status command. + * + * Return: 0 on success, or error code if arguments are invalid. + */ +static inline int +nvme_init_directive_recv_stream_status(struct nvme_passthru_cmd *cmd, + __u32 nsid, unsigned int nr_entries, + struct nvme_streams_directive_status *id) +{ + if (nr_entries > NVME_STREAM_ID_MAX) + return -EINVAL; + + nvme_init_directive_recv(cmd, nsid, + NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_STATUS, + NVME_DIRECTIVE_DTYPE_STREAMS, 0, id, + (__u32)(sizeof(*id) + nr_entries * sizeof(__le16))); + + return 0; +} + +/** + * nvme_init_directive_recv_stream_allocate() - Initialize passthru command for + * Directive Receive Stream Allocate + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @nsr: Namespace Streams Requested + * + * Initializes the passthru command buffer for the Directive Receive - Stream + * Allocate command. + */ +static inline void +nvme_init_directive_recv_stream_allocate(struct nvme_passthru_cmd *cmd, + __u32 nsid, __u16 nsr) +{ + nvme_init_directive_recv(cmd, nsid, + NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_RESOURCE, + NVME_DIRECTIVE_DTYPE_STREAMS, 0, NULL, 0); + cmd->cdw12 = nsr; +} + +/** + * nvme_init_capacity_mgmt() - Initialize passthru command for + * Capacity Management + * @cmd: Passthru command to use + * @oper: Operation to be performed by the controller + * @elid: Value specific to the value of the Operation field + * @cap: Capacity in bytes of the Endurance Group or NVM Set to + * be created + * + * Initializes the passthru command buffer for the Capacity Management command. + */ +static inline void +nvme_init_capacity_mgmt(struct nvme_passthru_cmd *cmd, + __u8 oper, __u16 elid, __u64 cap) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_capacity_mgmt; + cmd->cdw10 = NVME_FIELD_ENCODE(oper, + NVME_CAPACITY_MGMT_CDW10_OPER_SHIFT, + NVME_CAPACITY_MGMT_CDW10_OPER_MASK) | + NVME_FIELD_ENCODE(elid, + NVME_CAPACITY_MGMT_CDW10_ELID_SHIFT, + NVME_CAPACITY_MGMT_CDW10_ELID_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(cap, + NVME_CAPACITY_MGMT_CDW11_CAPL_SHIFT, + NVME_CAPACITY_MGMT_CDW11_CAPL_MASK); + cmd->cdw12 = NVME_FIELD_ENCODE(cap >> 32, + NVME_CAPACITY_MGMT_CDW12_CAPU_SHIFT, + NVME_CAPACITY_MGMT_CDW12_CAPU_MASK); +} + + /** + * nvme_init_lockdown() - Initialize passthru command for Lockdown + * @cmd: Passthru command to use + * @scp: Scope of the command + * @prhbt: Prohibit or allow the command opcode or Set Features command + * @ifc: Affected interface + * @ofi: Opcode or Feature Identifier + * @uidx: UUID Index if controller supports this id selection method + * + * Initializes the passthru command buffer for the Lockdown command. + */ +static inline void +nvme_init_lockdown(struct nvme_passthru_cmd *cmd, __u8 scp, __u8 prhbt, + __u8 ifc, __u8 ofi, __u8 uidx) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_lockdown; + cmd->cdw10 = NVME_FIELD_ENCODE(ofi, + NVME_LOCKDOWN_CDW10_OFI_SHIFT, + NVME_LOCKDOWN_CDW10_OFI_MASK) | + NVME_FIELD_ENCODE(ifc, + NVME_LOCKDOWN_CDW10_IFC_SHIFT, + NVME_LOCKDOWN_CDW10_IFC_MASK) | + NVME_FIELD_ENCODE(prhbt, + NVME_LOCKDOWN_CDW10_PRHBT_SHIFT, + NVME_LOCKDOWN_CDW10_PRHBT_MASK) | + NVME_FIELD_ENCODE(scp, + NVME_LOCKDOWN_CDW10_SCP_SHIFT, + NVME_LOCKDOWN_CDW10_SCP_MASK); + cmd->cdw14 = NVME_FIELD_ENCODE(uidx, + NVME_LOCKDOWN_CDW14_UIDX_SHIFT, + NVME_LOCKDOWN_CDW14_UIDX_MASK); +} + +/** + * nvme_init_set_property() - Initialize passthru command to set + * controller property + * @cmd: Passthru command to use + * @offset: Property offset from the base to set + * @value: The value to set the property + * + * Initializes the passthru command buffer for the Fabrics Set Property command. + * This is an NVMe-over-Fabrics specific command. + */ +static inline void +nvme_init_set_property(struct nvme_passthru_cmd *cmd, __u32 offset, __u64 value) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_fabrics; + cmd->nsid = nvme_fabrics_type_property_set; + cmd->cdw10 = nvme_is_64bit_reg(offset); + cmd->cdw11 = (__u32)offset; + cmd->cdw12 = (__u32)(value & 0xffffffff); + cmd->cdw13 = (__u32)(value >> 32); +} + +/** + * nvme_init_get_property() - Initialize passthru command to get + * a controller property + * @cmd: Passthru command to use + * @offset: Property offset from the base to retrieve + * + * Initializes the passthru command buffer for the Fabrics Get Property command. + * This is an NVMe-over-Fabrics specific command. + */ +static inline void +nvme_init_get_property(struct nvme_passthru_cmd64 *cmd, __u32 offset) +{ + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_fabrics; + cmd->nsid = nvme_fabrics_type_property_get; + cmd->cdw10 = nvme_is_64bit_reg(offset); + cmd->cdw11 = (__u32)offset; +} + +/** + * nvme_init_sanitize_nvm() - Initialize passthru command to start a + * sanitize operation + * @cmd: Passthru command to use + * @sanact: Sanitize action, see &enum nvme_sanitize_sanact + * @ause: Set to allow unrestricted sanitize exit + * @owpass: Overwrite pass count + * @oipbp: Set to overwrite invert pattern between passes + * @ndas: Set to not deallocate blocks after sanitizing + * @emvs: Set to enter media verification state + * @ovrpat: Overwrite pattern + * + * Initializes the passthru command buffer for the Sanitize NVM command. + */ +static inline void +nvme_init_sanitize_nvm(struct nvme_passthru_cmd *cmd, + enum nvme_sanitize_sanact sanact, bool ause, __u8 owpass, + bool oipbp, bool ndas, bool emvs, __u32 ovrpat) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_sanitize_nvm; + cmd->cdw10 = NVME_FIELD_ENCODE(sanact, + NVME_SANITIZE_CDW10_SANACT_SHIFT, + NVME_SANITIZE_CDW10_SANACT_MASK) | + NVME_FIELD_ENCODE(ause, + NVME_SANITIZE_CDW10_AUSE_SHIFT, + NVME_SANITIZE_CDW10_AUSE_MASK) | + NVME_FIELD_ENCODE(owpass, + NVME_SANITIZE_CDW10_OWPASS_SHIFT, + NVME_SANITIZE_CDW10_OWPASS_MASK) | + NVME_FIELD_ENCODE(oipbp, + NVME_SANITIZE_CDW10_OIPBP_SHIFT, + NVME_SANITIZE_CDW10_OIPBP_MASK) | + NVME_FIELD_ENCODE(ndas, + NVME_SANITIZE_CDW10_NDAS_SHIFT, + NVME_SANITIZE_CDW10_NDAS_MASK) | + NVME_FIELD_ENCODE(emvs, + NVME_SANITIZE_CDW10_EMVS_SHIFT, + NVME_SANITIZE_CDW10_EMVS_MASK); + cmd->cdw11 = ovrpat; +} + +/** + * nvme_init_dev_self_test() - Initialize passthru command to start or + * abort a self test + * @cmd: Passthru command to use + * @nsid: Namespace ID to test + * @stc: Self test code, see &enum nvme_dst_stc + * + * Initializes the passthru command buffer for the Device Self-test command. + */ +static inline void +nvme_init_dev_self_test(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_dst_stc stc) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_dev_self_test; + cmd->nsid = nsid; + cmd->cdw10 = NVME_FIELD_ENCODE(stc, + NVME_DEVICE_SELF_TEST_CDW10_STC_SHIFT, + NVME_DEVICE_SELF_TEST_CDW10_STC_MASK); +} + +/** + * nvme_init_virtual_mgmt() - Initialize passthru command for + * Virtualization Resource Management + * @cmd: Passthru command to use + * @act: Virtual resource action, see &enum nvme_virt_mgmt_act + * @rt: Resource type to modify, see &enum nvme_virt_mgmt_rt + * @cntlid: Controller id for which resources are bing modified + * @nr: Number of resources being allocated or assigned + * + * Initializes the passthru command buffer for the Virtualization + * Management command. + */ +static inline void +nvme_init_virtual_mgmt(struct nvme_passthru_cmd *cmd, + enum nvme_virt_mgmt_act act, enum nvme_virt_mgmt_rt rt, + __u16 cntlid, __u16 nr) +{ + memset(cmd, 0, sizeof(*cmd)); + cmd->opcode = nvme_admin_virtual_mgmt; + cmd->cdw10 = NVME_FIELD_ENCODE(act, + NVME_VIRT_MGMT_CDW10_ACT_SHIFT, + NVME_VIRT_MGMT_CDW10_ACT_MASK) | + NVME_FIELD_ENCODE(rt, + NVME_VIRT_MGMT_CDW10_RT_SHIFT, + NVME_VIRT_MGMT_CDW10_RT_MASK) | + NVME_FIELD_ENCODE(cntlid, + NVME_VIRT_MGMT_CDW10_CNTLID_SHIFT, + NVME_VIRT_MGMT_CDW10_CNTLID_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(nr, + NVME_VIRT_MGMT_CDW11_NR_SHIFT, + NVME_VIRT_MGMT_CDW11_NR_MASK); +} + +/** + * nvme_flush() - Send an nvme flush command + * @hdl: Transport handle + * @nsid: Namespace identifier + * + * The Flush command requests that the contents of volatile write cache be made + * non-volatile. + * + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. + */ +static inline int nvme_flush(struct nvme_transport_handle *hdl, __u32 nsid) +{ + struct nvme_passthru_cmd cmd = {}; + + cmd.opcode = nvme_cmd_flush; + cmd.nsid = nsid; + + return nvme_submit_io_passthru(hdl, &cmd, NULL); +} + +/** + * nvme_init_dsm() - Initialize passthru command for + * NVMEe I/O Data Set Management + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @nr: Number of block ranges in the data set management attributes + * @idr: DSM Deallocate attribute + * @idw: DSM Integral Dataset for Read attribute + * @ad: DSM Integral Dataset for Read attribute + * @data: User space destination address to transfer the data + * @len: Length of provided user buffer to hold the log data in bytes + */ +static inline void +nvme_init_dsm(struct nvme_passthru_cmd *cmd, + __u32 nsid, __u16 nr, __u8 idr, __u8 idw, __u8 ad, void *data, + __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_cmd_dsm; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(nr, + NVME_DSM_CDW10_NR_SHIFT, + NVME_DSM_CDW10_NR_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(idr, + NVME_DSM_CDW11_IDR_SHIFT, + NVME_DSM_CDW11_IDR_MASK) | + NVME_FIELD_ENCODE(idw, + NVME_DSM_CDW11_IDW_SHIFT, + NVME_DSM_CDW11_IDW_MASK) | + NVME_FIELD_ENCODE(ad, + NVME_DSM_CDW11_AD_SHIFT, + NVME_DSM_CDW11_AD_MASK); +} + +/** + * nvme_init_var_size_tags() - Initialize Command Dword fields + * for Extended LBA based on Variable Sized Tags + * @cmd: Passthru command to use + * @pif: Protection information format, determines tag placement + * @sts: Storage tag size in bits + * @reftag: Expected Initial Logical Block Reference Tag (EILBRT) + * @storage_tag: Expected Logical Block Storage Tag (ELBST) + * + * Initializes the passthru command buffer fields cdw2, cdw3, and cdw14 + * for commands supporting Extended LBA. This logic is usually called from + * the command-specific init function (like nvme_init_zns_append). + */ +static inline int +nvme_init_var_size_tags(struct nvme_passthru_cmd64 *cmd, + __u8 pif, __u8 sts, __u64 reftag, __u64 storage_tag) +{ + __u32 cdw2 = 0, cdw3 = 0, cdw14 = 0; + + /* + * Ignore warning about array subscript is out of bounds, + * which is not correct + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" + + switch (pif) { + case NVME_NVM_PIF_16B_GUARD: + cdw14 = NVME_FIELD_ENCODE(reftag, + NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, + NVME_IOCS_COMMON_CDW14_ELBTL_MASK); + cdw14 |= NVME_FIELD_ENCODE(storage_tag << (32 - sts), + NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, + NVME_IOCS_COMMON_CDW14_ELBTL_MASK); + break; + case NVME_NVM_PIF_32B_GUARD: + cdw14 = NVME_FIELD_ENCODE(reftag, + NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, + NVME_IOCS_COMMON_CDW14_ELBTL_MASK); + cdw3 = NVME_FIELD_ENCODE(reftag >> 32, + NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, + NVME_IOCS_COMMON_CDW3_ELBTU_MASK); + cdw14 |= NVME_FIELD_ENCODE((storage_tag << (80 - sts)) & 0xffff0000, + NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, + NVME_IOCS_COMMON_CDW14_ELBTL_MASK); + if (sts >= 48) + cdw3 |= NVME_FIELD_ENCODE(storage_tag >> (sts - 48), + NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, + NVME_IOCS_COMMON_CDW3_ELBTU_MASK); + else + cdw3 |= NVME_FIELD_ENCODE(storage_tag << (48 - sts), + NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, + NVME_IOCS_COMMON_CDW3_ELBTU_MASK); + cdw2 = NVME_FIELD_ENCODE(storage_tag >> (sts - 16), + NVME_IOCS_COMMON_CDW2_ELBTU_SHIFT, + NVME_IOCS_COMMON_CDW2_ELBTU_MASK); + break; + case NVME_NVM_PIF_64B_GUARD: + cdw14 = NVME_FIELD_ENCODE(reftag, + NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, + NVME_IOCS_COMMON_CDW14_ELBTL_MASK); + cdw3 = NVME_FIELD_ENCODE((reftag >> 32) & 0xffff, + NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, + NVME_IOCS_COMMON_CDW3_ELBTU_MASK); + cdw14 |= NVME_FIELD_ENCODE(storage_tag << (48 - sts), + NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, + NVME_IOCS_COMMON_CDW14_ELBTL_MASK); + if (sts >= 16) + cdw3 |= NVME_FIELD_ENCODE((storage_tag >> (sts - 16)) & 0xffff, + NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, + NVME_IOCS_COMMON_CDW3_ELBTU_MASK); + else + cdw3 |= NVME_FIELD_ENCODE((storage_tag << (16 - sts)) & 0xffff, + NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, + NVME_IOCS_COMMON_CDW3_ELBTU_MASK); + break; + default: + return -EINVAL; + } + + cmd->cdw2 = cdw2; + cmd->cdw3 = cdw3; + cmd->cdw14 = cdw14; + + return 0; + +#pragma GCC diagnostic pop +} + +/** + * nvme_init_app_tag() - Initialize Command Dword fields for + * Logical Block Application Tag/Mask + * @cmd: Passthru command to use + * @lbat: Logical block application tag + * @lbatm: Logical block application tag mask + */ +static inline void +nvme_init_app_tag(struct nvme_passthru_cmd64 *cmd, + __u16 lbat, __u16 lbatm) +{ + /* + * Ignore warning about array subscript is out of bounds, + * which is not correct + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" + + cmd->cdw15 = NVME_FIELD_ENCODE(lbat, + NVME_IOCS_COMMON_CDW15_ELBAT_SHIFT, + NVME_IOCS_COMMON_CDW15_ELBAT_MASK) | + NVME_FIELD_ENCODE(lbatm, + NVME_IOCS_COMMON_CDW15_ELBATM_SHIFT, + NVME_IOCS_COMMON_CDW15_ELBATM_MASK); + +#pragma GCC diagnostic pop +} + +/** + * nvme_init_io() - Initialize passthru command for a generic user I/O command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @opcode: Opcode to execute + * @slba: Starting logical block + * @data: Pointer to user address of the data buffer + * @data_len: Length of user buffer, @data, in bytes + * @metadata: Pointer to user address of the metadata buffer + * @metadata_len:Length of user buffer, @metadata, in bytes + * + * Initializes the passthru command buffer for a generic NVM I/O command. + * Note: If @elbas is true, the caller must ensure the definition/logic for + * nvme_init_set_var_size_tags is available and that the return value from + * that function is checked for error. + */ +static inline void +nvme_init_io(struct nvme_passthru_cmd *cmd, __u8 opcode, __u32 nsid, __u64 slba, + void *data, __u32 data_len, void *metadata, __u32 metadata_len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = opcode; + cmd->nsid = nsid; + cmd->metadata = (__u64)(uintptr_t)metadata; + cmd->addr = (__u64)(uintptr_t)data; + cmd->metadata_len = metadata_len; + cmd->data_len = data_len; + cmd->cdw10 = NVME_FIELD_ENCODE(slba, + NVME_IOCS_COMMON_CDW10_SLBAL_SHIFT, + NVME_IOCS_COMMON_CDW10_SLBAL_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(slba >> 32, + NVME_IOCS_COMMON_CDW11_SLBAU_SHIFT, + NVME_IOCS_COMMON_CDW11_SLBAU_MASK); +} + +/** + * nvme_init_read() - Initialize passthru command for a user read command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block + * @nlb: Number of logical blocks (0-based) + * @control: Upper 16 bits of cdw12 + * @dsm: Data set management attributes (CETYPE is zero), + * see &enum nvme_io_dsm_flags + * @cev: Command Extension Value (CETYPE is non-zero) + * @data: Pointer to user address of the data buffer + * @data_len: Length of user buffer, @data, in bytes + * @metadata: Pointer to user address of the metadata buffer + * @metadata_len:Length of user buffer, @metadata, in bytes + * + * Initializes the passthru command buffer for the Read command. + * Note: Assumes a macro or separate function exists to translate the combined + * NLB/control/prinfo fields into cdw12/cdw13. This transformation assumes + * the parameters are used for a generic nvme_init_io wrapper. + */ +static inline void +nvme_init_read(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, + __u16 nlb, __u16 control, __u8 dsm, __u16 cev, + void *data, __u32 data_len, void *metadata, __u32 metadata_len) +{ + nvme_init_io(cmd, nvme_cmd_read, nsid, slba, + data, data_len, metadata, metadata_len); + cmd->cdw12 = NVME_FIELD_ENCODE(nlb, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT, + NVME_IOCS_COMMON_CDW12_NLB_MASK) | + NVME_FIELD_ENCODE(control, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(dsm, + NVME_IOCS_COMMON_CDW13_DSM_SHIFT, + NVME_IOCS_COMMON_CDW13_DSM_MASK) | + NVME_FIELD_ENCODE(cev, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_MASK); +} + +/** + * nvme_init_write() - Initialize passthru command for a user write command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block + * @nlb: Number of logical blocks (0-based) + * @control: Upper 16 bits of cdw12 + * @dspec: Directive specific value + * @dsm: Data set management attributes (CETYPE is zero), + * see &enum nvme_io_dsm_flags + * @cev: Command Extension Value (CETYPE is non-zero) + * @data: Pointer to user address of the data buffer + * @data_len: Length of user buffer, @data, in bytes + * @metadata: Pointer to user address of the metadata buffer + * @metadata_len:Length of user buffer, @metadata, in bytes + * + * Initializes the passthru command buffer for the Write command. + */ +static inline void +nvme_init_write(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, + __u16 nlb, __u16 control, __u16 dspec, __u8 dsm, __u8 cev, + void *data, __u32 data_len, void *metadata, __u32 metadata_len) +{ + nvme_init_io(cmd, nvme_cmd_write, nsid, slba, + data, data_len, metadata, metadata_len); + cmd->cdw12 = NVME_FIELD_ENCODE(nlb, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT, + NVME_IOCS_COMMON_CDW12_NLB_MASK) | + NVME_FIELD_ENCODE(control, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(dspec, + NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, + NVME_IOCS_COMMON_CDW13_DSPEC_MASK) | + NVME_FIELD_ENCODE(dsm, + NVME_IOCS_COMMON_CDW13_DSM_SHIFT, + NVME_IOCS_COMMON_CDW13_DSM_MASK) | + NVME_FIELD_ENCODE(cev, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_MASK); +} +/** + * nvme_init_compare() - Initialize passthru command for a user compare command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block + * @nlb: Number of logical blocks (0-based) + * @control: Command control flags, see &enum nvme_io_control_flags. + * @cev: Command Extension Value (CETYPE is non-zero) + * @data: Pointer to user address of the data buffer + * @data_len: Length of user buffer, @data, in bytes + * @metadata: Pointer to user address of the metadata buffer + * @metadata_len:Length of user buffer, @metadata, in bytes + * + * Initializes the passthru command buffer for the Compare command. + */ +static inline void +nvme_init_compare(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, + __u16 nlb, __u16 control, __u8 cev, void *data, __u32 data_len, + void *metadata, __u32 metadata_len) +{ + nvme_init_io(cmd, nvme_cmd_compare, nsid, slba, + data, data_len, metadata, metadata_len); + cmd->cdw12 = NVME_FIELD_ENCODE(nlb, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT, + NVME_IOCS_COMMON_CDW12_NLB_MASK) | + NVME_FIELD_ENCODE(control, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(cev, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_MASK); +} + +/** + * nvme_init_write_zeros() - Initialize passthru command for a + * write zeroes command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block + * @nlb: Number of logical blocks (0-based) + * @control: Upper 16 bits of cdw12 + * @dspec: Directive specific value + * @dsm: Data set management attributes (CETYPE is zero), + * see &enum nvme_io_dsm_flags + * @cev: Command Extension Value (CETYPE is non-zero) + * + * Initializes the passthru command buffer for the Write Zeroes command. + * Note: Write Zeroes command does not transfer data or metadata. + */ +static inline void +nvme_init_write_zeros(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, + __u16 nlb, __u16 control, __u16 dspec, __u8 dsm, __u8 cev) +{ + nvme_init_io(cmd, nvme_cmd_write_zeroes, nsid, slba, NULL, 0, NULL, 0); + cmd->cdw12 = NVME_FIELD_ENCODE(nlb, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT, + NVME_IOCS_COMMON_CDW12_NLB_MASK) | + NVME_FIELD_ENCODE(control, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(dspec, + NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, + NVME_IOCS_COMMON_CDW13_DSPEC_MASK) | + NVME_FIELD_ENCODE(dsm, + NVME_IOCS_COMMON_CDW13_DSM_SHIFT, + NVME_IOCS_COMMON_CDW13_DSM_MASK) | + NVME_FIELD_ENCODE(cev, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_MASK); +} + +/** + * nvme_init_write_uncorrectable() - Initialize passthru command for a + * write uncorrectable command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block + * @nlb: Number of logical blocks (0-based) + * @control: Upper 16 bits of cdw12 + * @dspec: Directive specific value + * + * Initializes the passthru command buffer for the Write Uncorrectable command. + * Note: This command transfers no data or metadata. + */ +static inline void +nvme_init_write_uncorrectable(struct nvme_passthru_cmd *cmd, __u32 nsid, + __u64 slba, __u16 nlb, __u16 control, __u16 dspec) +{ + nvme_init_io(cmd, nvme_cmd_write_uncor, nsid, slba, NULL, 0, NULL, 0); + cmd->cdw12 = NVME_FIELD_ENCODE(nlb, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT, + NVME_IOCS_COMMON_CDW12_NLB_MASK) | + NVME_FIELD_ENCODE(control, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(dspec, + NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, + NVME_IOCS_COMMON_CDW13_DSPEC_MASK); +} + +/** + * nvme_init_verify() - Initialize passthru command for a verify command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block + * @nlb: Number of logical blocks (0-based) + * @control: Upper 16 bits of cdw12 + * @cev: Command Extension Value (CETYPE is non-zero) + * @data: Pointer to user address of the data buffer + * @data_len: Length of user buffer, @data, in bytes + * @metadata: Pointer to user address of the metadata buffer + * @metadata_len:Length of user buffer, @metadata, in bytes + * + * Initializes the passthru command buffer for the Verify command. + * Note: Verify command transfers data or metadata to the controller to perform + * the verification but not back to the host. + */ +static inline void +nvme_init_verify(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, + __u16 nlb, __u16 control, __u8 cev, void *data, __u32 data_len, + void *metadata, __u32 metadata_len) +{ + nvme_init_io(cmd, nvme_cmd_verify, nsid, slba, + data, data_len, metadata, metadata_len); + cmd->cdw12 = NVME_FIELD_ENCODE(nlb, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT, + NVME_IOCS_COMMON_CDW12_NLB_MASK) | + NVME_FIELD_ENCODE(control, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(cev, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_MASK); +} + +/** + * nvme_init_copy() - Initialize passthru command for Copy command + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @sdlba: Start destination LBA + * @nr: Number of ranges (1-based, 0-based in command) + * @desfmt: Descriptor format + * @prinfor: Protection information field for read + * @prinfow: Protection information field for write + * @cetype: Command Extension Type + * @dtype: Directive Type + * @stcw: Storage Tag Check Write + * @stcr: Storage Tag Check Read + * @fua: Force unit access + * @lr: Limited retry + * @cev: Command Extension Value + * @dspec: Directive specific value + * @cpydsc: Range description buffer + * + * Initializes the passthru command buffer for the Copy command by calculating + * the data length and calling the generic I/O initializer. + */ +static inline void +nvme_init_copy(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 sdlba, + __u16 nr, __u8 desfmt, __u8 prinfor, __u8 prinfow, + __u8 cetype, __u8 dtype, bool stcw, bool stcr, bool fua, + bool lr, __u16 cev, __u16 dspec, void *cpydsc) +{ + __u32 data_len; + + switch (desfmt) { + case 1: + data_len = nr * sizeof(struct nvme_copy_range_f1); + break; + case 2: + data_len = nr * sizeof(struct nvme_copy_range_f2); + break; + case 3: + data_len = nr * sizeof(struct nvme_copy_range_f3); + break; + default: + data_len = nr * sizeof(struct nvme_copy_range); + break; + } + + nvme_init_io(cmd, nvme_cmd_copy, nsid, sdlba, cpydsc, + data_len, NULL, 0); + cmd->cdw12 = NVME_FIELD_ENCODE(nr - 1, + NVME_COPY_CDW12_NR_SHIFT, + NVME_COPY_CDW12_NR_MASK) | + NVME_FIELD_ENCODE(desfmt, + NVME_COPY_CDW12_DESFMT_SHIFT, + NVME_COPY_CDW12_DESFMT_MASK) | + NVME_FIELD_ENCODE(prinfor, + NVME_COPY_CDW12_PRINFOR_SHIFT, + NVME_COPY_CDW12_PRINFOR_MASK) | + NVME_FIELD_ENCODE(cetype, + NVME_COPY_CDW12_CETYPE_SHIFT, + NVME_COPY_CDW12_CETYPE_MASK) | + NVME_FIELD_ENCODE(dtype, + NVME_COPY_CDW12_DTYPE_SHIFT, + NVME_COPY_CDW12_DTYPE_MASK) | + NVME_FIELD_ENCODE(stcw, + NVME_COPY_CDW12_STCW_SHIFT, + NVME_COPY_CDW12_STCW_MASK) | + NVME_FIELD_ENCODE(stcr, + NVME_COPY_CDW12_STCR_SHIFT, + NVME_COPY_CDW12_STCR_MASK) | + NVME_FIELD_ENCODE(prinfow, + NVME_COPY_CDW12_PRINFOW_SHIFT, + NVME_COPY_CDW12_PRINFOW_MASK) | + NVME_FIELD_ENCODE(fua, + NVME_COPY_CDW12_FUA_SHIFT, + NVME_COPY_CDW12_FUA_MASK) | + NVME_FIELD_ENCODE(lr, + NVME_COPY_CDW12_LR_SHIFT, + NVME_COPY_CDW12_LR_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(cev, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_MASK) | + NVME_FIELD_ENCODE(dspec, + NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, + NVME_IOCS_COMMON_CDW13_DSPEC_MASK); +} + +/** + * nvme_init_resv_acquire() - Initialize passthru command for + * Reservation Acquire + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @racqa: The action that is performed by the command, + * see &enum nvme_resv_racqa + * @iekey: Set to ignore the existing key + * @disnsrs: Disperse Namespace Reservation Support + * @rtype: The type of reservation to be create, see &enum nvme_resv_rtype + * @crkey: The current reservation key associated with the host + * @prkey: Preempt Reservation Key + * @payload: Data payload buffer to hold crkey and prkey + * + * Initializes the passthru command buffer for the Reservation Acquire command. + */ +static inline void +nvme_init_resv_acquire(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_resv_racqa racqa, bool iekey, bool disnsrs, + enum nvme_resv_rtype rtype, __u64 crkey, __u64 prkey, + __le64 *payload) +{ + memset(cmd, 0, sizeof(*cmd)); + + payload[0] = htole64(crkey); + payload[1] = htole64(prkey); + + cmd->opcode = nvme_cmd_resv_acquire; + cmd->nsid = nsid; + cmd->data_len = 2 * sizeof(__le64); + cmd->addr = (__u64)(uintptr_t)payload; + cmd->cdw10 = NVME_FIELD_ENCODE(racqa, + NVME_RESV_ACQUIRE_CDW10_RACQA_SHIFT, + NVME_RESV_ACQUIRE_CDW10_RACQA_MASK) | + NVME_FIELD_ENCODE(iekey, + NVME_RESV_ACQUIRE_CDW10_IEKEY_SHIFT, + NVME_RESV_ACQUIRE_CDW10_IEKEY_MASK) | + NVME_FIELD_ENCODE(disnsrs, + NVME_RESV_ACQUIRE_CDW10_DISNSRS_SHIFT, + NVME_RESV_ACQUIRE_CDW10_DISNSRS_MASK) | + NVME_FIELD_ENCODE(rtype, + NVME_RESV_ACQUIRE_CDW10_RTYPE_SHIFT, + NVME_RESV_ACQUIRE_CDW10_RTYPE_MASK); +} + +/** + * nvme_init_resv_register() - Initialize passthru command for + * Reservation Register + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @rrega: The registration action, see &enum nvme_resv_rrega + * @iekey: Set to ignore the existing key + * @disnsrs: Disperse Namespace Reservation Support + * @cptpl: Change persist through power loss, see &enum nvme_resv_cptpl + * @crkey: The current reservation key associated with the host + * @nrkey: The new reservation key to be register if action is register or + * replace + * @payload: Data payload buffer to hold crkey and nrkey + * + * Initializes the passthru command buffer for the Reservation Register command. + */ +static inline void +nvme_init_resv_register(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_resv_rrega rrega, bool iekey, bool disnsrs, + enum nvme_resv_cptpl cptpl, __u64 crkey, __u64 nrkey, + __le64 *payload) +{ + memset(cmd, 0, sizeof(*cmd)); + + payload[0] = htole64(crkey); + payload[1] = htole64(nrkey); + + cmd->opcode = nvme_cmd_resv_register; + cmd->nsid = nsid; + cmd->data_len = 2 * sizeof(__le64); + cmd->addr = (__u64)(uintptr_t)payload; + cmd->cdw10 = NVME_FIELD_ENCODE(rrega, + NVME_RESV_REGISTER_CDW10_RREGA_SHIFT, + NVME_RESV_REGISTER_CDW10_RREGA_MASK) | + NVME_FIELD_ENCODE(iekey, + NVME_RESV_REGISTER_CDW10_IEKEY_SHIFT, + NVME_RESV_REGISTER_CDW10_IEKEY_MASK) | + NVME_FIELD_ENCODE(disnsrs, + NVME_RESV_REGISTER_CDW10_DISNSRS_SHIFT, + NVME_RESV_REGISTER_CDW10_DISNSRS_MASK) | + NVME_FIELD_ENCODE(cptpl, + NVME_RESV_REGISTER_CDW10_CPTPL_SHIFT, + NVME_RESV_REGISTER_CDW10_CPTPL_MASK); +} + +/** + * nvme_init_resv_release() - Initialize passthru command for + * Reservation Release + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @rrela: Reservation release action, see &enum nvme_resv_rrela + * @iekey: Set to ignore the existing key + * @disnsrs: Disperse Namespace Reservation Support + * @rtype: The type of reservation to be create, see &enum nvme_resv_rtype + * @crkey: The current reservation key to release + * @payload: Data payload buffer to hold crkey + * + * Initializes the passthru command buffer for the Reservation Release command. + */ +static inline void +nvme_init_resv_release(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_resv_rrela rrela, bool iekey, bool disnsrs, + enum nvme_resv_rtype rtype, __u64 crkey, __le64 *payload) +{ + memset(cmd, 0, sizeof(*cmd)); + + payload[0] = htole64(crkey); + + cmd->opcode = nvme_cmd_resv_release; + cmd->nsid = nsid; + cmd->data_len = sizeof(__le64); + cmd->addr = (__u64)(uintptr_t)payload; + cmd->cdw10 = NVME_FIELD_ENCODE(rrela, + NVME_RESV_RELEASE_CDW10_RRELA_SHIFT, + NVME_RESV_RELEASE_CDW10_RRELA_MASK) | + NVME_FIELD_ENCODE(iekey, + NVME_RESV_RELEASE_CDW10_IEKEY_SHIFT, + NVME_RESV_RELEASE_CDW10_IEKEY_MASK) | + NVME_FIELD_ENCODE(disnsrs, + NVME_RESV_RELEASE_CDW10_DISNSRS_SHIFT, + NVME_RESV_RELEASE_CDW10_DISNSRS_MASK) | + NVME_FIELD_ENCODE(rtype, + NVME_RESV_RELEASE_CDW10_RTYPE_SHIFT, + NVME_RESV_RELEASE_CDW10_RTYPE_MASK); +} + +/** + * nvme_init_resv_report() - Initialize passthru command for + * Reservation Report + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @eds: Request extended Data Structure + * @disnsrs: Disperse Namespace Reservation Support + * @report: The user space destination address to store the reservation + * report buffer + * @len: Number of bytes to request transferred with this command + * + * Initializes the passthru command buffer for the Reservation Report command. + */ +static inline void +nvme_init_resv_report(struct nvme_passthru_cmd *cmd, __u32 nsid, + bool eds, bool disnsrs, struct nvme_resv_status *report, + __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_cmd_resv_report; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)report; + cmd->cdw10 = (len >> 2) - 1; + cmd->cdw11 = NVME_FIELD_ENCODE(eds, + NVME_RESV_REPORT_CDW11_EDS_SHIFT, + NVME_RESV_REPORT_CDW11_EDS_MASK) | + NVME_FIELD_ENCODE(disnsrs, + NVME_RESV_REPORT_CDW11_DISNSRS_SHIFT, + NVME_RESV_REPORT_CDW11_DISNSRS_MASK); +} + +/** + * nvme_init_io_mgmt_recv() - Initialize passthru command for + * I/O Management Receive command + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @mo: Management Operation + * @mos: Management Operation Specific + * @data: Userspace address of the data buffer + * @len: Length of @data + * + * Initializes the passthru command buffer for the I/O Management + * Receive command. + */ +static inline void +nvme_init_io_mgmt_recv(struct nvme_passthru_cmd *cmd, __u32 nsid, + __u8 mo, __u16 mos, void *data, __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_cmd_io_mgmt_recv; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(mo, + NVME_IO_MGMT_RECV_CDW10_MO_SHIFT, + NVME_IO_MGMT_RECV_CDW10_MO_MASK) | + NVME_FIELD_ENCODE(mos, + NVME_IO_MGMT_RECV_CDW10_MOS_SHIFT, + NVME_IO_MGMT_RECV_CDW10_MOS_MASK); + cmd->cdw11 = (len >> 2) - 1; +} + +/** + * nvme_init_fdp_reclaim_unit_handle_status() - Initialize passthru command + * to get reclaim unit handle status + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @data: Response buffer + * @len: Length of response buffer + * + * Initializes the passthru command buffer for the I/O Management Receive - + * Reclaim Unit Handle Status command. + */ +static inline void +nvme_init_fdp_reclaim_unit_handle_status(struct nvme_passthru_cmd *cmd, + __u32 nsid, void *data, __u32 len) +{ + nvme_init_io_mgmt_recv(cmd, nsid, NVME_IO_MGMT_RECV_RUH_STATUS, 0, + data, len); +} + +/** + * nvme_init_io_mgmt_send() - Initialize passthru command for + * I/O Management Send command + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @mo: Management Operation + * @mos: Management Operation Specific + * @data: Userspace address of the data buffer + * @len: Length of @data + * + * Initializes the passthru command buffer for the I/O Management Send command. + */ +static inline void +nvme_init_io_mgmt_send(struct nvme_passthru_cmd *cmd, __u32 nsid, + __u8 mo, __u16 mos, void *data, __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_cmd_io_mgmt_send; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(mo, + NVME_IO_MGMT_SEND_CDW10_MO_SHIFT, + NVME_IO_MGMT_SEND_CDW10_MO_MASK) | + NVME_FIELD_ENCODE(mos, + NVME_IO_MGMT_SEND_CDW10_MOS_SHIFT, + NVME_IO_MGMT_SEND_CDW10_MOS_MASK); +} + +/** + * nvme_init_fdp_reclaim_unit_handle_update() - Initialize passthru command to + * update a list of reclaim unit handles + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @pids: List of placement identifiers buffer + * @npids: Number of placement identifiers + * + * Initializes the passthru command buffer for the I/O Management Send - + * Reclaim Unit Handle Update command. + */ +static inline void +nvme_init_fdp_reclaim_unit_handle_update(struct nvme_passthru_cmd *cmd, + __u32 nsid, void *pids, unsigned int npids) +{ + __u16 mos = npids - 1; /* MOS = NPI - 1 */ + __u32 len = npids * sizeof(__u16); + + nvme_init_io_mgmt_send(cmd, nsid, NVME_IO_MGMT_SEND_RUH_UPDATE, + mos, pids, len); +} + +/** + * nvme_init_zns_mgmt_send() - Initialize passthru command for + * ZNS management send command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block address + * @zsa: Zone send action + * @selall: Select all flag + * @zsaso: Zone Send Action Specific Option + * @zm: Zone Management + * @data: Userspace address of the data buffer + * @len: Length of @data + * + * Initializes the passthru command buffer for the ZNS Management Send command. + */ +static inline void +nvme_init_zns_mgmt_send(struct nvme_passthru_cmd *cmd, __u32 nsid, + __u64 slba, enum nvme_zns_send_action zsa, bool selall, + __u8 zsaso, __u8 zm, void *data, __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_zns_cmd_mgmt_send; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = slba & 0xffffffff; + cmd->cdw11 = slba >> 32; + cmd->cdw13 = NVME_FIELD_ENCODE(zsa, + NVME_ZNS_MGMT_SEND_ZSA_SHIFT, + NVME_ZNS_MGMT_SEND_ZSA_MASK) | + NVME_FIELD_ENCODE(selall, + NVME_ZNS_MGMT_SEND_SEL_SHIFT, + NVME_ZNS_MGMT_SEND_SEL_MASK) | + NVME_FIELD_ENCODE(zsaso, + NVME_ZNS_MGMT_SEND_ZSASO_SHIFT, + NVME_ZNS_MGMT_SEND_ZSASO_MASK) | + NVME_FIELD_ENCODE(zm, + NVME_ZNS_MGMT_SEND_ZM_SHIFT, + NVME_ZNS_MGMT_SEND_ZM_MASK); +} + +/** + * nvme_init_zns_mgmt_recv() - Initialize passthru command for + * ZNS management receive command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block address + * @zra: zone receive action + * @zras: Zone receive action specific field + * @zraspf: Zone receive action specific features + * @data: Userspace address of the data buffer + * @len: Length of @data + * + * Initializes the passthru command buffer for the ZNS Management + * Receive command. + */ +static inline void +nvme_init_zns_mgmt_recv(struct nvme_passthru_cmd *cmd, __u32 nsid, + __u64 slba, enum nvme_zns_recv_action zra, __u16 zras, + bool zraspf, void *data, __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_zns_cmd_mgmt_recv; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = slba & 0xffffffff; + cmd->cdw11 = slba >> 32; + cmd->cdw12 = (len >> 2) - 1; + cmd->cdw13 = NVME_FIELD_ENCODE(zra, + NVME_ZNS_MGMT_RECV_ZRA_SHIFT, + NVME_ZNS_MGMT_RECV_ZRA_MASK) | + NVME_FIELD_ENCODE(zras, + NVME_ZNS_MGMT_RECV_ZRAS_SHIFT, + NVME_ZNS_MGMT_RECV_ZRAS_MASK) | + NVME_FIELD_ENCODE(zraspf, + NVME_ZNS_MGMT_RECV_ZRASPF_SHIFT, + NVME_ZNS_MGMT_RECV_ZRASPF_MASK); +} + +/** + * nvme_init_zns_report_zones() - Initialize passthru command to return + * the list of zones + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting LBA + * @opts: Reporting options + * @extended: Extended report + * @partial: Partial report requested + * @data: Userspace address of the report zones data buffer + * @len: Length of the data buffer + * + * Initializes the passthru command buffer for the ZNS Management Receive - + * Report Zones command. + */ +static inline void +nvme_init_zns_report_zones(struct nvme_passthru_cmd *cmd, __u32 nsid, + __u64 slba, enum nvme_zns_report_options opts, + bool extended, bool partial, + void *data, __u32 len) +{ + enum nvme_zns_recv_action zra = extended ? + NVME_ZNS_ZRA_EXTENDED_REPORT_ZONES : NVME_ZNS_ZRA_REPORT_ZONES; + __u16 zras = (__u16)opts; + bool zraspf = partial; /* ZRASPF is Partial Report Requested */ + + nvme_init_zns_mgmt_recv(cmd, nsid, slba, zra, zras, zraspf, data, len); +} + +/** + * nvme_init_zns_append() - Initialize passthru command to append data to a zone + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @zslba: Zone start logical block address + * @nlb: Number of logical blocks + * @control: Upper 16 bits of cdw12 + * @cev: Command Extension Value + * @dspec: Directive Specific + * @data: Userspace address of the data buffer + * @data_len: Length of @data + * @metadata: Userspace address of the metadata buffer + * @metadata_len: Length of @metadata + * + * Initializes the passthru command buffer for the ZNS Append command. + */ +static inline void +nvme_init_zns_append(struct nvme_passthru_cmd64 *cmd, __u32 nsid, + __u64 zslba, __u16 nlb, __u16 control, __u16 cev, __u16 dspec, + void *data, __u32 data_len, void *metadata, __u32 metadata_len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_zns_cmd_append; + cmd->nsid = nsid; + cmd->metadata = (__u64)(uintptr_t)metadata; + cmd->addr = (__u64)(uintptr_t)data; + cmd->metadata_len = metadata_len; + cmd->data_len = data_len; + cmd->cdw10 = NVME_FIELD_ENCODE(zslba, + NVME_IOCS_COMMON_CDW10_SLBAL_SHIFT, + NVME_IOCS_COMMON_CDW10_SLBAL_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(zslba >> 32, + NVME_IOCS_COMMON_CDW11_SLBAU_SHIFT, + NVME_IOCS_COMMON_CDW11_SLBAU_MASK); + cmd->cdw12 = NVME_FIELD_ENCODE(nlb, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT, + NVME_IOCS_COMMON_CDW12_NLB_MASK) | + NVME_FIELD_ENCODE(control, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(dspec, + NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, + NVME_IOCS_COMMON_CDW13_DSPEC_MASK); + if (control & NVME_IOCS_COMMON_CDW12_CETYPE_MASK) + cmd->cdw13 |= NVME_FIELD_ENCODE(cev, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_MASK); +} + +/** + * nvme_init_dim_send() - Initialize passthru command for + * Discovery Information Management (DIM) Send + * @cmd: Passthru command to use + * @tas: Task field of the Command Dword 10 (cdw10) + * @data: Pointer to the DIM data buffer + * @len: Length of @data + * + * Initializes the passthru command buffer for the Discovery Information + * Management Send command. + */ +static inline void +nvme_init_dim_send(struct nvme_passthru_cmd *cmd, + __u8 tas, void *data, __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_discovery_info_mgmt; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(tas, + NVME_DIM_TAS_SHIFT, + NVME_DIM_TAS_MASK); + +} + +/** + * nvme_init_lm_cdq_create() - Initialize passthru command for + * Controller Data Queue create - Controller Data Queue command + * @cmd: Passthru command to use + * @mos: Management Operation Specific (MOS): This field is + * specific to the SEL type + * @cntlid: Controller ID: For Create CDQ, specifies the target + * migratable controller + * @cdqsize: For Create CDQ, specifies the size of CDQ, in dwords - 4 byte + * @data: Pointer to data buffer + * + * Initializes the passthru command buffer for the Controller Data Queue + * command. Note: The result CDQID is returned in the CQE dword0, which the + * submission function must handle. + */ +static inline void +nvme_init_lm_cdq_create(struct nvme_passthru_cmd *cmd, + __u16 mos, __u16 cntlid, __u32 cdqsize, void *data) +{ + __u16 cqs; + + memset(cmd, 0, sizeof(*cmd)); + + cqs = NVME_FIELD_ENCODE(cntlid, + NVME_LM_CREATE_CDQ_CNTLID_SHIFT, + NVME_LM_CREATE_CDQ_CNTLID_MASK); + + cmd->opcode = nvme_admin_ctrl_data_queue; + cmd->data_len = cdqsize << 2; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(NVME_LM_SEL_CREATE_CDQ, + NVME_LM_CDQ_SEL_SHIFT, + NVME_LM_CDQ_SEL_MASK) | + NVME_FIELD_ENCODE(mos, + NVME_LM_CDQ_MOS_SHIFT, + NVME_LM_CDQ_MOS_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(NVME_LM_CREATE_CDQ_PC, + NVME_LM_CREATE_CDQ_PC_SHIFT, + NVME_LM_CREATE_CDQ_PC_MASK) | + NVME_FIELD_ENCODE(cqs, + NVME_LM_CQS_SHIFT, + NVME_LM_CQS_MASK); + cmd->cdw12 = cdqsize; +} + +/** + * nvme_init_lm_cdq_delete() - Initialize passthru command for + * Controller Data Queue delete - Controller Data Queue command + * @cmd: Passthru command to use + * @mos: Management Operation Specific (MOS): This field is + * specific to the SEL type + * @cdqid: Controller Data Queue ID (CDQID): For Delete CDQ, this + * field is the CDQID to delete. + * + * Initializes the passthru command buffer for the Controller Data Queue delete + * command. + */ +static inline void +nvme_init_lm_cdq_delete(struct nvme_passthru_cmd *cmd, + __u16 mos, __u16 cdqid) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_ctrl_data_queue; + cmd->cdw10 = NVME_FIELD_ENCODE(NVME_LM_SEL_DELETE_CDQ, + NVME_LM_CDQ_SEL_SHIFT, + NVME_LM_CDQ_SEL_MASK) | + NVME_FIELD_ENCODE(mos, + NVME_LM_CDQ_MOS_SHIFT, + NVME_LM_CDQ_MOS_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(cdqid, + NVME_LM_DELETE_CDQ_CDQID_SHIFT, + NVME_LM_DELETE_CDQ_CDQID_MASK); +} + +/** + * nvme_init_lm_track_send() - Initialize passthru command for + * Track Send command + * @cmd: Passthru command to use + * @sel: Select (SEL): This field specifies the type of + * management operation to perform + * @mos: Management Operation Specific (MOS): This field + * is specific to the SEL type + * @cdqid: Controller Data Queue ID (CDQID) + * + * Initializes the passthru command buffer for the Track Send command. + */ +static inline void +nvme_init_lm_track_send(struct nvme_passthru_cmd *cmd, + __u8 sel, __u16 mos, __u16 cdqid) +{ + + memset(cmd, 0, sizeof(*cmd)); + cmd->opcode = nvme_admin_track_send; + cmd->cdw10 = NVME_FIELD_ENCODE(sel, + NVME_LM_TRACK_SEND_SEL_SHIFT, + NVME_LM_TRACK_SEND_SEL_MASK) | + NVME_FIELD_ENCODE(mos, + NVME_LM_TRACK_SEND_MOS_SHIFT, + NVME_LM_TRACK_SEND_MOS_MASK); + cmd->cdw11 = cdqid; +} + +/** + * nvme_init_lm_migration_send() - Initialize passthru command for + * Migration Send command + * @cmd: Passthru command to use + * @sel: Select (SEL): This field specifies the type of management + * operation to perform. + * @mos: Management Operation Specific (MOS): This field is specific + * to the SEL type + * @cntlid: Controller ID: This field specifies the identifier of the + * controller to which the operation is performed. + * @stype: Suspend Type (STYPE): This field specifies the type of suspend. + * @dudmq: Delete User Data Migration Queue (DUDMQ): If set, the migration + * queue is deleted is deleted as part of the Suspend operation. + * @csvi: Controller State Version Index (CSVI) + * @csuuidi: Controller State UUID Index (CSUUIDI) + * @cso: Offset: This field specifies the offset, in bytes, within + * the data available to be returned and specifies the starting + * point for that data for what is actually returned to the host. + * @uidx: UUID Index (UIDX) + * @data: Pointer to data buffer + * @len: Length of @data + * + * Initializes the passthru command buffer for the Migration Send command. + */ +static inline void +nvme_init_lm_migration_send(struct nvme_passthru_cmd *cmd, + __u16 sel, __u16 mos, __u16 cntlid, __u8 stype, bool dudmq, + __u8 csvi, __u16 csuuidi, __u64 cso, __u8 uidx, + void *data, __u32 len) +{ + __u32 cdw10 = NVME_FIELD_ENCODE(sel, + NVME_LM_MIGRATION_SEND_SEL_SHIFT, + NVME_LM_MIGRATION_SEND_SEL_MASK) | + NVME_FIELD_ENCODE(mos, + NVME_LM_MIGRATION_SEND_MOS_SHIFT, + NVME_LM_MIGRATION_SEND_MOS_MASK); + __u32 cdw11 = 0; + __u32 cdw14 = NVME_FIELD_ENCODE(uidx, + NVME_LM_MIGRATION_SEND_UIDX_SHIFT, + NVME_LM_MIGRATION_SEND_UIDX_MASK); + + if (sel == NVME_LM_SEL_SUSPEND) { + cdw11 = NVME_FIELD_ENCODE(stype, + NVME_LM_STYPE_SHIFT, + NVME_LM_STYPE_MASK) | + NVME_FIELD_ENCODE(cntlid, + NVME_LM_SUSPEND_CNTLID_SHIFT, + NVME_LM_SUSPEND_CNTLID_MASK); + if (dudmq) + cdw11 |= NVME_LM_DUDMQ; + } else if (sel == NVME_LM_SEL_RESUME) { + cdw11 = NVME_FIELD_ENCODE(cntlid, + NVME_LM_RESUME_CNTLID_SHIFT, + NVME_LM_RESUME_CNTLID_MASK); + } else if (sel == NVME_LM_SEL_SET_CONTROLLER_STATE) { + cdw11 = NVME_FIELD_ENCODE(csuuidi, + NVME_LM_SET_CONTROLLER_STATE_CSUUIDI_SHIFT, + NVME_LM_SET_CONTROLLER_STATE_CSUUIDI_MASK) | + NVME_FIELD_ENCODE(csvi, + NVME_LM_SET_CONTROLLER_STATE_CSVI_SHIFT, + NVME_LM_SET_CONTROLLER_STATE_CSVI_MASK) | + NVME_FIELD_ENCODE(cntlid, + NVME_LM_SET_CONTROLLER_STATE_CNTLID_SHIFT, + NVME_LM_SET_CONTROLLER_STATE_CNTLID_MASK); + } + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_migration_send; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = cdw10; + cmd->cdw11 = cdw11; + cmd->cdw12 = (__u32)cso; + cmd->cdw13 = (__u32)(cso >> 32); + cmd->cdw14 = cdw14; + cmd->cdw15 = len / sizeof(__u32); +} + +/** + * nvme_init_lm_migration_recv() - Initialize passthru command for + * Migration Receive command + * @cmd: Passthru command to use + * @offset: Offset: This field specifies the offset, in bytes, within + * the data available to be returned and specifies the starting + * point for that data for what is actually returned to the host. + * @mos: Management Operation Specific (MOS): This field is specific to + * the SEL type + * @cntlid: Controller ID: This field specifies the identifier of the + * controller to which the operation is performed. + * @csuuidi: Controller State UUID Index (CSUUIDI) + * @sel: Select (SEL): This field specifies the type of management + * operation to perform + * @uidx: UUID Index (UIDX) + * @csuidxp: Controller State UUID Index Parameter (CSUIDXP) + * @data: Pointer to data buffer + * @len: Length of @data + * + * Initializes the passthru command buffer for the Migration Receive command. + */ +static inline void +nvme_init_lm_migration_recv(struct nvme_passthru_cmd *cmd, + __u64 offset, __u16 mos, __u16 cntlid, __u16 csuuidi, __u8 sel, + __u8 uidx, __u8 csuidxp, void *data, __u32 len) +{ + __u32 cdw11 = 0; + __u32 data_len = 0; + + if (sel == NVME_LM_SEL_GET_CONTROLLER_STATE) { + cdw11 = NVME_FIELD_ENCODE(csuidxp, + NVME_LM_GET_CONTROLLER_STATE_CSUIDXP_SHIFT, + NVME_LM_GET_CONTROLLER_STATE_CSUIDXP_MASK) | + NVME_FIELD_ENCODE(csuuidi, + NVME_LM_GET_CONTROLLER_STATE_CSUUIDI_SHIFT, + NVME_LM_GET_CONTROLLER_STATE_CSUUIDI_MASK) | + NVME_FIELD_ENCODE(cntlid, + NVME_LM_GET_CONTROLLER_STATE_CNTLID_SHIFT, + NVME_LM_GET_CONTROLLER_STATE_CNTLID_MASK); + data_len = len; + } + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_migration_receive; + cmd->data_len = data_len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(sel, + NVME_LM_MIGRATION_RECV_SEL_SHIFT, + NVME_LM_MIGRATION_RECV_SEL_MASK) | + NVME_FIELD_ENCODE(mos, + NVME_LM_MIGRATION_RECV_MOS_SHIFT, + NVME_LM_MIGRATION_RECV_MOS_MASK); + cmd->cdw11 = cdw11; + cmd->cdw12 = (__u32)offset; + cmd->cdw13 = (__u32)(offset >> 32); + cmd->cdw14 = NVME_FIELD_ENCODE(uidx, + NVME_LM_MIGRATION_RECV_UIDX_SHIFT, + NVME_LM_MIGRATION_RECV_UIDX_MASK); + cmd->cdw15 = len ? (__u32)((len - 1) / sizeof(__u32)) : 0; +} + +/** + * nvme_init_lm_set_features_ctrl_data_queue() - Initialize passthru command for + * Set Controller Data Queue feature + * @cmd: Passthru command to use + * @cdqid: Controller Data Queue ID (CDQID) + * @hp: Head Pointer (passed in cdw12) + * @tpt: Tail Pointer Trigger (passed in cdw13) + * @etpt: Enable Tail Pointer Trigger + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_CTRL_DATA_QUEUE. + */ +static inline void +nvme_init_lm_set_features_ctrl_data_queue(struct nvme_passthru_cmd *cmd, + __u16 cdqid, __u32 hp, __u32 tpt, bool etpt) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_CTRL_DATA_QUEUE, false); + cmd->cdw11 = cdqid | + NVME_FIELD_ENCODE(etpt, + NVME_LM_CTRL_DATA_QUEUE_ETPT_SHIFT, + NVME_LM_CTRL_DATA_QUEUE_ETPT_MASK); + cmd->cdw12 = hp; + cmd->cdw13 = tpt; +} + +/** + * nvme_init_lm_get_features_ctrl_data_queue() - Initialize passthru command for + * Get Controller Data Queue feature + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @cdqid: Controller Data Queue ID (CDQID) + * @qfd: Get Controller Data Queue feature data buffer + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_CTRL_DATA_QUEUE. + */ +static inline void +nvme_init_lm_get_features_ctrl_data_queue(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, __u16 cdqid, + struct nvme_lm_ctrl_data_queue_fid_data *qfd) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_CTRL_DATA_QUEUE, sel); + cmd->data_len = sizeof(*qfd); + cmd->addr = (__u64)(uintptr_t)qfd; + cmd->cdw11 = cdqid; +} + +/** + * nvme_identify() - Submit a generic Identify command + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID (if applicable to the requested CNS). + * @csi: Command Set Identifier. + * @cns: Identify Controller or Namespace Structure (CNS) value, + * specifying the type of data to be returned. + * @data: Pointer to the buffer where the identification data will + * be stored. + * @len: Length of the data buffer in bytes. + * + * The generic wrapper for submitting an Identify command, allowing the host + * to specify any combination of Identify parameters. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify(struct nvme_transport_handle *hdl, __u32 nsid, enum nvme_csi csi, + enum nvme_identify_cns cns, void *data, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify(&cmd, nsid, csi, cns, data, len); + + return nvme_submit_admin_passthru(hdl, &cmd, NULL); +} +/** + * nvme_identify_ctrl() - Submit an Identify Controller command + * @hdl: Transport handle for the controller. + * @id: Pointer to the buffer (&struct nvme_id_ctrl) where the + * controller identification data will be stored upon + * successful completion. + * + * Submits the Identify Controller command to retrieve the controller's + * capabilities and configuration data. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify_ctrl(struct nvme_transport_handle *hdl, + struct nvme_id_ctrl *id) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_ctrl(&cmd, id); + + return nvme_submit_admin_passthru(hdl, &cmd, NULL); +} + +/** + * nvme_identify_active_ns_list() - Submit an Identify Active Namespace + * List command + * @hdl: Transport handle for the controller. + * @nsid: The Namespace ID to query + * @ns_list: Pointer to the buffer (&struct nvme_ns_list) where the + * active namespace list will be stored. + * + * Submits the Identify command to retrieve a list of active Namespace IDs. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify_active_ns_list(struct nvme_transport_handle *hdl, + __u32 nsid, struct nvme_ns_list *ns_list) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_active_ns_list(&cmd, nsid, ns_list); + + return nvme_submit_admin_passthru(hdl, &cmd, NULL); +} + +/** + * nvme_identify_ns() - Submit an Identify Namespace command + * @hdl: Transport handle for the controller. + * @nsid: The Namespace ID to identify. + * @ns: Pointer to the buffer (&struct nvme_id_ns) where the namespace + * identification data will be stored. + * + * Submits the Identify command to retrieve the Namespace Identification + * data structure for a specified namespace. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ + +static inline int +nvme_identify_ns(struct nvme_transport_handle *hdl, + __u32 nsid, struct nvme_id_ns *ns) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_ns(&cmd, nsid, ns); + + return nvme_submit_admin_passthru(hdl, &cmd, NULL); +} + +/** + * nvme_identify_csi_ns() - Submit a CSI-specific Identify Namespace command + * @hdl: Transport handle for the controller. + * @nsid: The Namespace ID to identify. + * @csi: The Command Set Identifier + * @uidx: The UUID Index for the command. + * @id_ns: Pointer to the buffer (@struct nvme_nvm_id_ns) where the + * CSI-specific namespace identification data will be stored. + * + * Submits the Identify command to retrieve Namespace Identification data + * specific to a Command Set Identifier (CSI). + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify_csi_ns(struct nvme_transport_handle *hdl, __u32 nsid, + enum nvme_csi csi, __u8 uidx, struct nvme_nvm_id_ns *id_ns) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_csi_ns(&cmd, nsid, csi, uidx, id_ns); + + return nvme_submit_admin_passthru(hdl, &cmd, NULL); +} + +/** + * nvme_identify_uuid_list() - Submit an Identify UUID List command + * @hdl: Transport handle for the controller. + * @uuid_list: Pointer to the buffer (&struct nvme_id_uuid_list) where the + * UUID list will be stored. + * + * Submits the Identify command to retrieve a list of UUIDs associated + * with the controller. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify_uuid_list(struct nvme_transport_handle *hdl, + struct nvme_id_uuid_list *uuid_list) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_uuid_list(&cmd, uuid_list); + + return nvme_submit_admin_passthru(hdl, &cmd, NULL); +} + +/** + * nvme_identify_csi_ns_user_data_format() - Submit an Identify CSI Namespace + * User Data Format command + * @hdl: Transport handle for the controller. + * @csi: Command Set Identifier. + * @fidx: Format Index, specifying which format entry to return. + * @uidx: The UUID Index for the command. + * @data: Pointer to the buffer where the format data will be stored. + * + * Submits the Identify command to retrieve a CSI-specific Namespace User + * Data Format data structure. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify_csi_ns_user_data_format(struct nvme_transport_handle *hdl, + enum nvme_csi csi, __u16 fidx, __u8 uidx, void *data) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_csi_ns_user_data_format(&cmd, csi, fidx, uidx, data); + + return nvme_submit_admin_passthru(hdl, &cmd, NULL); +} + +/** + * nvme_identify_ns_granularity() - Submit an Identify Namespace Granularity + * List command + * @hdl: Transport handle for the controller. + * @gr_list: Pointer to the buffer (&struct nvme_id_ns_granularity_list) + * where the granularity list will be stored. + * + * Submits the Identify command to retrieve the Namespace Granularity List. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify_ns_granularity(struct nvme_transport_handle *hdl, + struct nvme_id_ns_granularity_list *gr_list) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_ns_granularity(&cmd, gr_list); + + return nvme_submit_admin_passthru(hdl, &cmd, NULL); +} + +/** + * nvme_identify_ns_descs_list() - Submit an Identify Namespace ID Descriptor + * List command + * @hdl: Transport handle for the controller. + * @nsid: The Namespace ID to query. + * @descs: Pointer to the buffer (&struct nvme_ns_id_desc) where the + * descriptor list will be stored. + * + * Submits the Identify command to retrieve the Namespace ID Descriptor List + * for a specified namespace. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify_ns_descs_list(struct nvme_transport_handle *hdl, + __u32 nsid, struct nvme_ns_id_desc *descs) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_ns_descs_list(&cmd, nsid, descs); + + return nvme_submit_admin_passthru(hdl, &cmd, NULL); +} + +/** + * nvme_zns_identify_ns() - Submit a ZNS-specific Identify Namespace command + * @hdl: Transport handle for the controller. + * @nsid: The Namespace ID to identify. + * @data: Pointer to the buffer (&struct nvme_zns_id_ns) where the ZNS + * namespace identification data will be stored. + * + * Submits the Identify command to retrieve the Zoned Namespace (ZNS) + * specific identification data structure for a specified namespace. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_zns_identify_ns(struct nvme_transport_handle *hdl, + __u32 nsid, struct nvme_zns_id_ns *data) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_zns_identify_ns(&cmd, nsid, data); + + return nvme_submit_admin_passthru(hdl, &cmd, NULL); +} + +/** + * nvme_get_log_simple() - Retrieve a log page using default parameters + * @hdl: Transport handle for the controller. + * @lid: Log Identifier, specifying the log page to retrieve + * (@enum nvme_cmd_get_log_lid). + * @data: Pointer to the buffer where the log page data will be stored. + * @len: Length of the data buffer in bytes. + * + * Submits the Get Log Page command using the common settings: + * NVME\_NSID\_ALL, Retain Asynchronous Event (RAE) set to false, + * and assuming the NVM Command Set. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_simple(struct nvme_transport_handle *hdl, + enum nvme_cmd_get_log_lid lid, void *data, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log(&cmd, NVME_NSID_ALL, lid, NVME_CSI_NVM, data, len); + + return nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); +} + +/** + * nvme_get_log_supported_log_pages() - Retrieve the Supported Log Pages Log Page + * @hdl: Transport handle for the controller. + * @log: Pointer to the buffer (@struct nvme_supported_log_pages) where + * the log page data will be stored. + * + * Submits the Get Log Page command specifically for the Supported Log Pages + * Log. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_supported_log_pages(struct nvme_transport_handle *hdl, + struct nvme_supported_log_pages *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_SUPPORTED_LOG_PAGES, + NVME_CSI_NVM, log, sizeof(*log)); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log), NULL); +} + + +/** + * nvme_get_log_error() - Retrieve the Error Information Log Page + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to request the log for (usually NVME_NSID_ALL). + * @nr_entries: The maximum number of error log entries to retrieve. + * @err_log: Pointer to the buffer (array of @struct nvme_error_log_page) + * where the log page data will be stored. + * + * This log page describes extended error information for a command that + * completed with error, or may report an error that is not specific to a + * particular command. The total size requested is determined by + * @nr_entries * sizeof(@struct nvme_error_log_page). + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_error(struct nvme_transport_handle *hdl, __u32 nsid, + unsigned int nr_entries, struct nvme_error_log_page *err_log) +{ + struct nvme_passthru_cmd cmd; + size_t len = sizeof(*err_log) * nr_entries; + + nvme_init_get_log(&cmd, nsid, NVME_LOG_LID_ERROR, + NVME_CSI_NVM, err_log, len); + + return nvme_get_log(hdl, &cmd, false, len, NULL); +} + +/** + * nvme_get_log_fw_slot() - Retrieve the Firmware Slot Information Log Page + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to request the log for (use NVME_NSID_ALL). + * @fw_log: Pointer to the buffer (@struct nvme_firmware_slot) where the log + * page data will be stored. + * + * This log page describes the firmware revision stored in each firmware slot + * supported. The firmware revision is indicated as an ASCII string. The log + * page also indicates the active slot number. + * + * This command is typically issued for the controller scope, thus using + * NVME_NSID_ALL. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_fw_slot(struct nvme_transport_handle *hdl, __u32 nsid, + struct nvme_firmware_slot *fw_log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log(&cmd, nsid, NVME_LOG_LID_FW_SLOT, + NVME_CSI_NVM, fw_log, sizeof(*fw_log)); + + return nvme_get_log(hdl, &cmd, false, sizeof(*fw_log), NULL); +} + +/** + * nvme_get_log_changed_ns_list() - Retrieve the Namespace Change Log Page + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to request the log for (use NVME_NSID_ALL). + * @ns_log: Pointer to the buffer (@struct nvme_ns_list) where the log + * page data will be stored. + * + * This log page describes namespaces attached to this controller that have + * changed since the last time the namespace was identified, been added, or + * deleted. + * + * This command is typically issued for the controller scope, thus using + * NVME_NSID_ALL. The Retain Asynchronous Event (RAE) is true to retain + * asynchronous events associated with the log page + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_changed_ns_list(struct nvme_transport_handle *hdl, __u32 nsid, + struct nvme_ns_list *ns_log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log(&cmd, nsid, NVME_LOG_LID_CHANGED_NS, + NVME_CSI_NVM, ns_log, sizeof(*ns_log)); + + return nvme_get_log(hdl, &cmd, true, sizeof(*ns_log), NULL); +} + +/** + * nvme_get_log_cmd_effects() - Retrieve the Command Effects Log Page + * @hdl: Transport handle for the controller. + * @csi: Command Set Identifier for the requested log page. + * @effects_log:Pointer to the buffer (@struct nvme_cmd_effects_log) where the + * log page data will be stored. + * + * This log page describes the commands that the controller supports and the + * effects of those commands on the state of the NVM subsystem. * - * The Format NVM command low level formats the NVM media. This command is used - * by the host to change the LBA data size and/or metadata size. A low level - * format may destroy all data and metadata associated with all namespaces or - * only the specific namespace associated with the command + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_ALL. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_format_nvm(struct nvme_format_nvm_args *args); +static inline int +nvme_get_log_cmd_effects(struct nvme_transport_handle *hdl, + enum nvme_csi csi, struct nvme_cmd_effects_log *effects_log) +{ + struct nvme_passthru_cmd cmd; + size_t len = sizeof(*effects_log); -/** - * nvme_ns_mgmt() - Issue a Namespace management command - * @args: &struct nvme_ns_mgmt_args Argument structure - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_ns_mgmt(struct nvme_ns_mgmt_args *args); + nvme_init_get_log_cmd_effects(&cmd, csi, effects_log); + + return nvme_get_log(hdl, &cmd, false, len, NULL); +} /** - * nvme_ns_mgmt_create() - Create a non attached namespace - * @fd: File descriptor of nvme device - * @ns: Namespace identification that defines ns creation parameters - * @nsid: On success, set to the namespace id that was created - * @timeout: Override the default timeout to this value in milliseconds; - * set to 0 to use the system default. - * @csi: Command Set Identifier - * @data: Host Software Specified Fields that defines ns creation parameters + * nvme_get_log_device_self_test() - Retrieve the Device Self-Test Log Page + * @hdl: Transport handle for the controller. + * @log: Pointer to the buffer (@struct nvme_self_test_log) where the log + * page data will be stored. + * + * This log page indicates the status of an in-progress self-test and the + * percent complete of that operation, and the results of the previous 20 + * self-test operations. * - * On successful creation, the namespace exists in the subsystem, but is not - * attached to any controller. Use the nvme_ns_attach_ctrls() to assign the - * namespace to one or more controllers. + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_ALL. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_ns_mgmt_create(int fd, struct nvme_id_ns *ns, - __u32 *nsid, __u32 timeout, __u8 csi, - struct nvme_ns_mgmt_host_sw_specified *data) +static inline int +nvme_get_log_device_self_test(struct nvme_transport_handle *hdl, + struct nvme_self_test_log *log) { - struct nvme_ns_mgmt_args args = { - .result = nsid, - .ns = ns, - .args_size = sizeof(args), - .fd = fd, - .timeout = timeout, - .nsid = NVME_NSID_NONE, - .sel = NVME_NS_MGMT_SEL_CREATE, - .csi = csi, - .rsvd1 = { 0, }, - .rsvd2 = NULL, - .data = data, - }; + struct nvme_passthru_cmd cmd; + size_t len = sizeof(*log); + + nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_DEVICE_SELF_TEST, + NVME_CSI_NVM, log, len); - return nvme_ns_mgmt(&args); + return nvme_get_log(hdl, &cmd, false, len, NULL); } /** - * nvme_ns_mgmt_delete_timeout() - Delete a non attached namespace with timeout - * @fd: File descriptor of nvme device - * @nsid: Namespace identifier to delete - * @timeout: Override the default timeout to this value in milliseconds; - * set to 0 to use the system default. + * nvme_get_log_create_telemetry_host_mcda() - Create the Host Initiated + * Telemetry Log + * @hdl: Transport handle for the controller. + * @mcda: Maximum Created Data Area. Specifies the maximum amount of data + * that may be returned by the controller. + * @log: Pointer to the buffer (@struct nvme_telemetry_log) where the log + * page data will be stored. + * + * Submits the Get Log Page command to initiate the creation of a Host Initiated + * Telemetry Log. It sets the Log Identifier (LID) to Telemetry Host and + * includes the Maximum Created Data Area (MCDA) in the Log Specific Parameter + * (LSP) field along with the Create bit. * - * It is recommended that a namespace being deleted is not attached to any - * controller. Use the nvme_ns_detach_ctrls() first if the namespace is still - * attached. + * It automatically sets Retain Asynchronous Event (RAE) to false. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_ns_mgmt_delete_timeout(int fd, __u32 nsid, __u32 timeout) +static inline int +nvme_get_log_create_telemetry_host_mcda(struct nvme_transport_handle *hdl, + enum nvme_telemetry_da mcda, struct nvme_telemetry_log *log) { - struct nvme_ns_mgmt_args args = { - .result = NULL, - .ns = NULL, - .args_size = sizeof(args), - .fd = fd, - .timeout = timeout, - .nsid = nsid, - .sel = NVME_NS_MGMT_SEL_DELETE, - .csi = 0, - .rsvd1 = { 0, }, - .rsvd2 = NULL, - .data = NULL, - }; + struct nvme_passthru_cmd cmd; - return nvme_ns_mgmt(&args); + nvme_init_get_log_create_telemetry_host_mcda(&cmd, mcda, log); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log), NULL); } /** - * nvme_ns_mgmt_delete() - Delete a non attached namespace - * @fd: File descriptor of nvme device - * @nsid: Namespace identifier to delete + * nvme_get_log_create_telemetry_host() - Create the Host Initiated Telemetry + * Log (Controller Determined Size) + * @hdl: Transport handle for the controller. + * @log: Pointer to the buffer (@struct nvme_telemetry_log) where the log + * page data will be stored. * - * It is recommended that a namespace being deleted is not attached to any - * controller. Use the nvme_ns_detach_ctrls() first if the namespace is still - * attached. + * Submits the Get Log Page command to initiate the creation of a Host Initiated + * Telemetry Log. This is a convenience wrapper that automatically uses the + * Controller Determined size for the Maximum Created Data Area (MCDA). * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * It automatically sets Retain Asynchronous Event (RAE) to false. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_ns_mgmt_delete(int fd, __u32 nsid) +static inline int +nvme_get_log_create_telemetry_host(struct nvme_transport_handle *hdl, + struct nvme_telemetry_log *log) { - return nvme_ns_mgmt_delete_timeout(fd, nsid, 0); + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_create_telemetry_host(&cmd, log); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log), NULL); } /** - * nvme_ns_attach() - Attach or detach namespace to controller(s) - * @args: &struct nvme_ns_attach_args Argument structure + * nvme_get_log_telemetry_host() - Retrieve the Host-Initiated + * Telemetry Log Page (Retain) + * @hdl: Transport handle for the controller. + * @lpo: Offset (in bytes) into the telemetry data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_ns_attach(struct nvme_ns_attach_args *args); - -/** - * nvme_ns_attach_ctrls() - Attach namespace to controllers - * @fd: File descriptor of nvme device - * @nsid: Namespace ID to attach - * @ctrlist: Controller list to modify attachment state of nsid + * Submits the Get Log Page command to retrieve a previously captured + * Host-Initiated Telemetry Log, starting at a specified offset (@lpo). The Log + * Specific Parameter (LSP) field is set to indicate the capture should be + * retained (not deleted after read). + * + * It automatically sets the Log Identifier (LID) and Retain Asynchronous Event + * (RAE) to false. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_ns_attach_ctrls(int fd, __u32 nsid, - struct nvme_ctrl_list *ctrlist) +static inline int +nvme_get_log_telemetry_host(struct nvme_transport_handle *hdl, + __u64 lpo, void *log, __u32 len) { - struct nvme_ns_attach_args args = { - .result = NULL, - .ctrlist = ctrlist, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .nsid = nsid, - .sel = NVME_NS_ATTACH_SEL_CTRL_ATTACH, - }; + struct nvme_passthru_cmd cmd; - return nvme_ns_attach(&args); + nvme_init_get_log_telemetry_host(&cmd, lpo, log, len); + + return nvme_get_log(hdl, &cmd, false, len, NULL); } /** - * nvme_ns_detach_ctrls() - Detach namespace from controllers - * @fd: File descriptor of nvme device - * @nsid: Namespace ID to detach - * @ctrlist: Controller list to modify attachment state of nsid + * nvme_get_log_telemetry_ctrl() - Retrieve the Controller-Initiated + * Telemetry Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @lpo: Offset (in bytes) into the telemetry data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Controller-Initiated + * Telemetry Log, allowing retrieval of data starting at a specified offset + * (@lpo). * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * It automatically sets the Log Identifier (LID). + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_ns_detach_ctrls(int fd, __u32 nsid, - struct nvme_ctrl_list *ctrlist) +static inline int +nvme_get_log_telemetry_ctrl(struct nvme_transport_handle *hdl, bool rae, + __u64 lpo, void *log, __u32 len) { - struct nvme_ns_attach_args args = { - .result = NULL, - .ctrlist = ctrlist, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .nsid = nsid, - .sel = NVME_NS_ATTACH_SEL_CTRL_DEATTACH, - }; + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_telemetry_ctrl(&cmd, lpo, log, len); - return nvme_ns_attach(&args); + return nvme_get_log(hdl, &cmd, rae, len, NULL); } /** - * nvme_fw_download() - Download part or all of a firmware image to the - * controller - * @args: &struct nvme_fw_download_args argument structure + * nvme_get_log_endurance_group() - Retrieve the Endurance Group Log Page + * @hdl: Transport handle for the controller. + * @endgid: Starting Endurance Group Identifier (ENDGID) to return in + * the list. + * @log: Pointer to the buffer (@struct nvme_endurance_group_log) where + * the log page data will be stored. * - * The Firmware Image Download command downloads all or a portion of an image - * for a future update to the controller. The Firmware Image Download command - * downloads a new image (in whole or in part) to the controller. - * - * The image may be constructed of multiple pieces that are individually - * downloaded with separate Firmware Image Download commands. Each Firmware - * Image Download command includes a Dword Offset and Number of Dwords that - * specify a dword range. + * This log page indicates if an Endurance Group Event has occurred for a + * particular Endurance Group. The ENDGID is placed in the Log Specific + * Identifier (LSI) field of the Get Log Page command. * - * The new firmware image is not activated as part of the Firmware Image - * Download command. Use the nvme_fw_commit() to activate a newly downloaded - * image. + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_NONE. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_fw_download(struct nvme_fw_download_args *args); +static inline int +nvme_get_log_endurance_group(struct nvme_transport_handle *hdl, + __u16 endgid, struct nvme_endurance_group_log *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_endurance_group(&cmd, endgid, log); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log), NULL); +} /** - * nvme_fw_commit() - Commit firmware using the specified action - * @args: &struct nvme_fw_commit_args argument structure + * nvme_get_log_predictable_lat_nvmset() - Retrieve the Predictable Latency + * Per NVM Set Log Page + * @hdl: Transport handle for the controller. + * @nvmsetid: The NVM Set Identifier (NVMSETID) for which to retrieve the log. + * @log: Pointer to the buffer (@struct nvme_nvmset_predictable_lat_log) + * where the log page data will be stored. * - * The Firmware Commit command modifies the firmware image or Boot Partitions. + * Submits the Get Log Page command specifically for the Predictable Latency Per + * NVM Set Log. The NVMSETID is placed in the Log Specific Identifier (LSI) + * field of the command. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. The command - * status response may specify additional reset actions required to complete - * the commit process. + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_fw_commit(struct nvme_fw_commit_args *args); +static inline int +nvme_get_log_predictable_lat_nvmset(struct nvme_transport_handle *hdl, + __u16 nvmsetid, struct nvme_nvmset_predictable_lat_log *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_predictable_lat_nvmset(&cmd, nvmsetid, log); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log), NULL); +} /** - * nvme_security_send() - Security Send command - * @args: &struct nvme_security_send argument structure + * nvme_get_log_predictable_lat_event() - Retrieve the Predictable Latency Event + * Aggregate Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. * - * The Security Send command transfers security protocol data to the - * controller. The data structure transferred to the controller as part of this - * command contains security protocol specific commands to be performed by the - * controller. The data structure transferred may also contain data or - * parameters associated with the security protocol commands. + * Submits the Get Log Page command specifically for the Predictable Latency + * Event Aggregate Log, allowing retrieval of data starting at a specified + * offset (@lpo). * - * The security data is protocol specific and is not defined by the NVMe - * specification. + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_PREDICTABLE_LAT_AGG. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_security_send(struct nvme_security_send_args *args); +static inline int +nvme_get_log_predictable_lat_event(struct nvme_transport_handle *hdl, + bool rae, __u64 lpo, void *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; -/** - * nvme_security_receive() - Security Receive command - * @args: &struct nvme_security_receive argument structure - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_security_receive(struct nvme_security_receive_args *args); + nvme_init_get_log_predictable_lat_event(&cmd, lpo, log, len); + + return nvme_get_log(hdl, &cmd, rae, len, NULL); +} /** - * nvme_get_lba_status() - Retrieve information on possibly unrecoverable LBAs - * @args: &struct nvme_get_lba_status_args argument structure + * nvme_get_log_fdp_configurations() - Retrieve the Flexible Data Placement + * (FDP) Configurations Log Page + * @hdl: Transport handle for the controller. + * @egid: Endurance Group Identifier (EGID) to return in the + * list (used in LSI). + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. * - * The Get LBA Status command requests information about Potentially - * Unrecoverable LBAs. Refer to the specification for action type descriptions. + * Submits the Get Log Page command specifically for the FDP Configurations Log. + * The EGID is placed in the Log Specific Identifier (LSI) field. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_get_lba_status(struct nvme_get_lba_status_args *args); +static inline int +nvme_get_log_fdp_configurations(struct nvme_transport_handle *hdl, + __u16 egid, __u64 lpo, void *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_fdp_configurations(&cmd, egid, lpo, log, len); + + return nvme_get_log(hdl, &cmd, false, len, NULL); +} /** - * nvme_directive_send() - Send directive command - * @args: &struct nvme_directive_send_args argument structure + * nvme_get_log_reclaim_unit_handle_usage() - Retrieve the FDP Reclaim Unit + * Handle (RUH) Usage Log Page + * @hdl: Transport handle for the controller. + * @egid: Endurance Group Identifier (EGID) (used in LSI). + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. * - * Directives is a mechanism to enable host and NVM subsystem or controller - * information exchange. The Directive Send command transfers data related to a - * specific Directive Type from the host to the controller. + * Submits the Get Log Page command specifically for the FDP Reclaim Unit Handle + * Usage Log. The EGID is placed in the Log Specific Identifier (LSI) field. * - * See the NVMe specification for more information. + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_NONE. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_directive_send(struct nvme_directive_send_args *args); +static inline int +nvme_get_log_reclaim_unit_handle_usage(struct nvme_transport_handle *hdl, + __u16 egid, __u64 lpo, void *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; -/** - * nvme_directive_send_id_endir() - Directive Send Enable Directive - * @fd: File descriptor of nvme device - * @nsid: Namespace Identifier - * @endir: Enable Directive - * @dtype: Directive Type - * @id: Pointer to structure nvme_id_directives - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_directive_send_id_endir(int fd, __u32 nsid, bool endir, - enum nvme_directive_dtype dtype, - struct nvme_id_directives *id); + nvme_init_get_log_reclaim_unit_handle_usage(&cmd, egid, lpo, log, len); + + return nvme_get_log(hdl, &cmd, false, len, NULL); +} /** - * nvme_directive_send_stream_release_identifier() - Directive Send Stream release - * @fd: File descriptor of nvme device - * @nsid: Namespace ID - * @stream_id: Stream identifier + * nvme_get_log_fdp_stats() - Retrieve the Flexible Data Placement (FDP) + * Statistics Log Page + * @hdl: Transport handle for the controller. + * @egid: Endurance Group Identifier (EGID) (used in LSI). + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the FDP Statistics Log. + * The EGID is placed in the Log Specific Identifier (LSI) field. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_directive_send_stream_release_identifier(int fd, - __u32 nsid, __u16 stream_id) +static inline int +nvme_get_log_fdp_stats(struct nvme_transport_handle *hdl, + __u16 egid, __u64 lpo, void *log, __u32 len) { - struct nvme_directive_send_args args = { - .result = NULL, - .data = NULL, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .nsid = nsid, - .doper = NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_IDENTIFIER, - .dtype = NVME_DIRECTIVE_DTYPE_STREAMS, - .cdw12 = 0, - .data_len = 0, - .dspec = stream_id, - }; + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_fdp_stats(&cmd, egid, lpo, log, len); - return nvme_directive_send(&args); + return nvme_get_log(hdl, &cmd, false, len, NULL); } /** - * nvme_directive_send_stream_release_resource() - Directive Send Stream release resources - * @fd: File descriptor of nvme device - * @nsid: Namespace ID + * nvme_get_log_fdp_events() - Retrieve the Flexible Data Placement (FDP) + * Events Log Page + * @hdl: Transport handle for the controller. + * @egid: Endurance Group Identifier (EGID) (used in LSI). + * @host_events:Whether to report host-initiated events (true) or + * controller-initiated events (false). + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the FDP Events Log. + * The EGID is placed in the Log Specific Identifier (LSI) field, and the + * @host_events flag is used to set the Log Specific Parameter (LSP) field. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_directive_send_stream_release_resource(int fd, __u32 nsid) +static inline int +nvme_get_log_fdp_events(struct nvme_transport_handle *hdl, + __u16 egid, bool host_events, __u64 lpo, void *log, __u32 len) { - struct nvme_directive_send_args args = { - .result = NULL, - .data = NULL, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .nsid = nsid, - .doper = NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_RESOURCE, - .dtype = NVME_DIRECTIVE_DTYPE_STREAMS, - .cdw12 = 0, - .data_len = 0, - .dspec = 0, - }; + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_fdp_events(&cmd, egid, host_events, lpo, log, len); - return nvme_directive_send(&args); + return nvme_get_log(hdl, &cmd, false, len, NULL); } /** - * nvme_directive_recv() - Receive directive specific data - * @args: &struct nvme_directive_recv_args argument structure + * nvme_get_log_ana() - Retrieve the Asymmetric Namespace Access (ANA) Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @lsp: Log specific parameter, see &enum nvme_get_log_ana_lsp. + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_directive_recv(struct nvme_directive_recv_args *args); - -/** - * nvme_directive_recv_identify_parameters() - Directive receive identifier parameters - * @fd: File descriptor of nvme device - * @nsid: Namespace ID - * @id: Identify parameters buffer + * This log consists of a header describing the log and descriptors containing + * the ANA information for groups that contain namespaces attached to the + * controller. The @lsp parameter is placed in the Log Specific Parameter field + * of the command. + * + * See &struct nvme_ana_log for the definition of the returned structure. + * + * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_ANA. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_directive_recv_identify_parameters(int fd, __u32 nsid, - struct nvme_id_directives *id) +static inline int +nvme_get_log_ana(struct nvme_transport_handle *hdl, bool rae, + enum nvme_log_ana_lsp lsp, __u64 lpo, void *log, __u32 len) { - struct nvme_directive_recv_args args = { - .result = NULL, - .data = id, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .nsid = nsid, - .doper = NVME_DIRECTIVE_RECEIVE_IDENTIFY_DOPER_PARAM, - .dtype = NVME_DIRECTIVE_DTYPE_IDENTIFY, - .cdw12 = 0, - .data_len = sizeof(*id), - .dspec = 0, - }; + struct nvme_passthru_cmd cmd; - return nvme_directive_recv(&args); + nvme_init_get_log_ana(&cmd, lsp, lpo, log, len); + + return nvme_get_log(hdl, &cmd, rae, len, NULL); } /** - * nvme_directive_recv_stream_parameters() - Directive receive stream parameters - * @fd: File descriptor of nvme device - * @nsid: Namespace ID - * @parms: Streams directive parameters buffer + * nvme_get_log_ana_groups() - Retrieve the Asymmetric Namespace Access (ANA) + * Groups Only Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @log: Pointer to the buffer (@struct nvme_ana_log) where the log page + * data will be stored. + * @len: Length of the buffer provided in @log. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * This function retrieves only the ANA Group Descriptors by setting the Log + * Specific Parameter (LSP) field to NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY. It is a + * convenience wrapper around nvme_get_log_ana, using a Log Page Offset (LPO) of + * 0. + * + * See &struct nvme_ana_log for the definition of the returned structure. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_directive_recv_stream_parameters(int fd, __u32 nsid, - struct nvme_streams_directive_params *parms) +static inline int +nvme_get_log_ana_groups(struct nvme_transport_handle *hdl, bool rae, + struct nvme_ana_log *log, __u32 len) { - struct nvme_directive_recv_args args = { - .result = NULL, - .data = parms, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .nsid = nsid, - .doper = NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM, - .dtype = NVME_DIRECTIVE_DTYPE_STREAMS, - .cdw12 = 0, - .data_len = sizeof(*parms), - .dspec = 0, - }; - - return nvme_directive_recv(&args); + return nvme_get_log_ana(hdl, rae, NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY, + 0, log, len); } /** - * nvme_directive_recv_stream_status() - Directive receive stream status - * @fd: File descriptor of nvme device - * @nsid: Namespace ID - * @nr_entries: Number of streams to receive - * @id: Stream status buffer + * nvme_get_log_lba_status() - Retrieve the LBA Status Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Submits the Get Log Page command specifically for the LBA Status Log. + * + * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_LBA_STATUS. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_directive_recv_stream_status(int fd, __u32 nsid, - unsigned int nr_entries, - struct nvme_streams_directive_status *id) +static inline int +nvme_get_log_lba_status(struct nvme_transport_handle *hdl, + bool rae, __u64 lpo, void *log, __u32 len) { - if (nr_entries > NVME_STREAM_ID_MAX) { - errno = EINVAL; - return -1; - } + struct nvme_passthru_cmd cmd; - struct nvme_directive_recv_args args = { - .result = NULL, - .data = id, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .nsid = nsid, - .doper = NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_STATUS, - .dtype = NVME_DIRECTIVE_DTYPE_STREAMS, - .cdw12 = 0, - .data_len = (__u32)(sizeof(*id) + nr_entries * sizeof(__le16)), - .dspec = 0, - }; + nvme_init_get_log_lba_status(&cmd, lpo, log, len); - return nvme_directive_recv(&args); + return nvme_get_log(hdl, &cmd, rae, len, NULL); } /** - * nvme_directive_recv_stream_allocate() - Directive receive stream allocate - * @fd: File descriptor of nvme device - * @nsid: Namespace ID - * @nsr: Namespace Streams Requested - * @result: If successful, the CQE dword0 value + * nvme_get_log_endurance_grp_evt() - Retrieve the Endurance Group Event + * Aggregate Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Endurance Group Event + * Aggregate Log, allowing retrieval of data starting at a specified offset + * (@lpo). + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_ENDURANCE_GRP_EVT. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_directive_recv_stream_allocate(int fd, __u32 nsid, - __u16 nsr, __u32 *result) +static inline int +nvme_get_log_endurance_grp_evt(struct nvme_transport_handle *hdl, + bool rae, __u64 lpo, void *log, __u32 len) { - struct nvme_directive_recv_args args = { - .result = result, - .data = NULL, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .nsid = nsid, - .doper = NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_RESOURCE, - .dtype = NVME_DIRECTIVE_DTYPE_STREAMS, - .cdw12 = nsr, - .data_len = 0, - .dspec = 0, - }; + struct nvme_passthru_cmd cmd; - return nvme_directive_recv(&args); + nvme_init_get_log_endurance_grp_evt(&cmd, lpo, log, len); + + return nvme_get_log(hdl, &cmd, rae, len, NULL); } /** - * nvme_capacity_mgmt() - Capacity management command - * @args: &struct nvme_capacity_mgmt_args argument structure + * nvme_get_log_fid_supported_effects() - Retrieve the Feature Identifiers + * Supported and Effects Log Page + * @hdl: Transport handle for the controller. + * @csi: Command set identifier, see &enum nvme_csi for known values + * @log: Pointer to the buffer (@struct nvme_fid_supported_effects_log) + * where the log page data will be stored. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_capacity_mgmt(struct nvme_capacity_mgmt_args *args); - -/** - * nvme_lockdown() - Issue lockdown command - * @args: &struct nvme_lockdown_args argument structure + * Submits the Get Log Page command specifically for the Feature Identifiers + * Supported and Effects Log. It automatically sets the Log Identifier (LID). * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_lockdown(struct nvme_lockdown_args *args); +static inline int +nvme_get_log_fid_supported_effects(struct nvme_transport_handle *hdl, + enum nvme_csi csi, struct nvme_fid_supported_effects_log *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_fid_supported_effects(&cmd, csi, log); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log), NULL); +} /** - * nvme_set_property() - Set controller property - * @args: &struct nvme_set_property_args argument structure + * nvme_get_log_mi_cmd_supported_effects() - Retrieve the Management Interface + * (MI) Commands Supported and Effects Log Page + * @hdl: Transport handle for the controller. + * @log: Pointer to the buffer (@struct nvme_mi_cmd_supported_effects_log) + * where the log page data will be stored. * - * This is an NVMe-over-Fabrics specific command, not applicable to PCIe. These - * properties align to the PCI MMIO controller registers. + * Submits the Get Log Page command specifically for the MI Commands Supported + * and Effects Log. It automatically sets the Log Identifier (LID). This command + * is typically issued with a namespace ID of 0xFFFFFFFF (NVME_NSID_NONE). * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_set_property(struct nvme_set_property_args *args); +static inline int +nvme_get_log_mi_cmd_supported_effects(struct nvme_transport_handle *hdl, + struct nvme_mi_cmd_supported_effects_log *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_mi_cmd_supported_effects(&cmd, log); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log), NULL); +} /** - * nvme_get_property() - Get a controller property - * @args: &struct nvme_get_propert_args argument structure + * nvme_get_log_boot_partition() - Retrieve the Boot Partition Log Page + * @hdl: Transport handle for the controller. + * @lsp: The Log Specific Parameter (LSP) field for this Log + * Identifier (LID). + * @part: Pointer to the buffer (@struct nvme_boot_partition) where the log + * page data will be stored. + * @len: Length of the buffer provided in @part. * - * This is an NVMe-over-Fabrics specific command, not applicable to PCIe. These - * properties align to the PCI MMIO controller registers. + * Submits the Get Log Page command specifically for the Boot Partition Log. + * The LSP field is set based on the @lsp parameter. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_BOOT_PARTITION. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_get_property(struct nvme_get_property_args *args); +static inline int +nvme_get_log_boot_partition(struct nvme_transport_handle *hdl, + __u8 lsp, struct nvme_boot_partition *part, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_boot_partition(&cmd, lsp, part, len); + + return nvme_get_log(hdl, &cmd, false, len, NULL); +} /** - * nvme_sanitize_nvm() - Start a sanitize operation - * @args: &struct nvme_sanitize_nvm_args argument structure + * nvme_get_log_rotational_media_info() - Retrieve the Rotational Media + * Information Log Page + * @hdl: Transport handle for the controller. + * @endgid: The Endurance Group Identifier (ENDGID) to retrieve the + * log for (used in LSI). + * @log: Pointer to the buffer (@struct nvme_rotational_media_info_log) + * where the log page data will be stored. + * @len: Length of the buffer provided in @log. * - * A sanitize operation alters all user data in the NVM subsystem such that - * recovery of any previous user data from any cache, the non-volatile media, - * or any Controller Memory Buffer is not possible. + * Submits the Get Log Page command specifically for the Rotational Media + * Information Log. The ENDGID is placed in the Log Specific Identifier (LSI) + * field of the command. * - * The Sanitize command starts a sanitize operation or to recover from a - * previously failed sanitize operation. The sanitize operation types that may - * be supported are Block Erase, Crypto Erase, and Overwrite. All sanitize - * operations are processed in the background, i.e., completion of the sanitize - * command does not indicate completion of the sanitize operation. + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_NONE. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_sanitize_nvm(struct nvme_sanitize_nvm_args *args); +static inline int +nvme_get_log_rotational_media_info(struct nvme_transport_handle *hdl, + __u16 endgid, struct nvme_rotational_media_info_log *log, + __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_rotational_media_info(&cmd, endgid, log, len); + + return nvme_get_log(hdl, &cmd, false, len, NULL); +} /** - * nvme_dev_self_test() - Start or abort a self test - * @args: &struct nvme_dev_self_test argument structure - * - * The Device Self-test command starts a device self-test operation or abort a - * device self-test operation. A device self-test operation is a diagnostic - * testing sequence that tests the integrity and functionality of the - * controller and may include testing of the media associated with namespaces. - * The controller may return a response to this command immediately while - * running the self-test in the background. + * nvme_get_log_dispersed_ns_participating_nss() - Retrieve the Dispersed + * Namespace Participating NVM Subsystems Log Page + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to request the log for. + * @log: Pointer to the buffer + * (@struct nvme_dispersed_ns_participating_nss_log) + * where the log page data will be stored. + * @len: Length of the buffer provided in @log. * - * Set the 'nsid' field to 0 to not include namespaces in the test. Set to - * 0xffffffff to test all namespaces. All other values tests a specific - * namespace, if present. + * Submits the Get Log Page command specifically for the Dispersed Namespace + * Participating NVM Subsystems Log. It automatically sets the Log Identifier + * (LID) and Retain Asynchronous Event (RAE) to false. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_dev_self_test(struct nvme_dev_self_test_args *args); +static inline int +nvme_get_log_dispersed_ns_participating_nss(struct nvme_transport_handle *hdl, + __u32 nsid, struct nvme_dispersed_ns_participating_nss_log *log, + __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_dispersed_ns_participating_nss(&cmd, nsid, log, len); + + return nvme_get_log(hdl, &cmd, false, len, NULL); +} /** - * nvme_virtual_mgmt() - Virtualization resource management - * @args: &struct nvme_virtual_mgmt_args argument structure + * nvme_get_log_mgmt_addr_list() - Retrieve the Management Address List Log Page + * @hdl: Transport handle for the controller. + * @log: Pointer to the buffer (@struct nvme_mgmt_addr_list_log) where + * the log page data will be stored. + * @len: Length of the buffer provided in @log. * - * The Virtualization Management command is supported by primary controllers - * that support the Virtualization Enhancements capability. This command is - * used for several functions: + * Submits the Get Log Page command specifically for the Management Address List Log. * - * - Modifying Flexible Resource allocation for the primary controller - * - Assigning Flexible Resources for secondary controllers - * - Setting the Online and Offline state for secondary controllers + * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_MGMT_ADDR_LIST, + * Retain Asynchronous Event (RAE) to false, and uses NVME_NSID_NONE. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_virtual_mgmt(struct nvme_virtual_mgmt_args *args); +static inline int +nvme_get_log_mgmt_addr_list(struct nvme_transport_handle *hdl, + struct nvme_mgmt_addr_list_log *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_mgmt_addr_list(&cmd, log, len); + + return nvme_get_log(hdl, &cmd, false, len, NULL); +} /** - * nvme_flush() - Send an nvme flush command - * @fd: File descriptor of nvme device - * @nsid: Namespace identifier + * nvme_get_log_phy_rx_eom() - Retrieve the Physical Interface Receiver Eye + * Opening Measurement Log Page + * @hdl: Transport handle for the controller. + * @lsp: Log Specific Parameter (LSP), which controls the action + * and measurement quality. + * @controller: Target Controller ID (used in LSI). + * @log: Pointer to the buffer (@struct nvme_phy_rx_eom_log) where the log + * page data will be stored. + * @len: Length of the buffer provided in @log. * - * The Flush command requests that the contents of volatile write cache be made - * non-volatile. + * Submits the Get Log Page command specifically for the Physical Interface + * Receiver Eye Opening Measurement Log. The Controller ID is placed in the + * Log Specific Identifier (LSI) field. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_PHY_RX_EOM, + * and Retain Asynchronous Event (RAE) to false. This command is typically + * issued for the controller scope, thus using NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_flush(int fd, __u32 nsid) +static inline int +nvme_get_log_phy_rx_eom(struct nvme_transport_handle *hdl, + __u8 lsp, __u16 controller, struct nvme_phy_rx_eom_log *log, + __u32 len) { - struct nvme_passthru_cmd cmd = {}; + struct nvme_passthru_cmd cmd; - cmd.opcode = nvme_cmd_flush; - cmd.nsid = nsid; + nvme_init_get_log_phy_rx_eom(&cmd, lsp, controller, log, len); - return nvme_submit_io_passthru(fd, &cmd, NULL); + return nvme_get_log(hdl, &cmd, false, len, NULL); } /** - * nvme_io() - Submit an nvme user I/O command - * @args: &struct nvme_io_args argument structure - * @opcode: Opcode to execute + * nvme_get_log_reachability_groups() - Retrieve the Reachability Groups Log Page + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to request the log for. + * @rgo: Return Groups Only. Set to true to return only the Reachability + * Group Descriptors. + * @log: Pointer to the buffer (@struct nvme_reachability_groups_log) + * where the log page data will be stored. + * @len: Length of the buffer provided in @log. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_io(struct nvme_io_args *args, __u8 opcode); - -/** - * nvme_read() - Submit an nvme user read command - * @args: &struct nvme_io_args argument structure + * Submits the Get Log Page command specifically for the Reachability Groups Log. + * The @rgo parameter is placed in the Log Specific Parameter (LSP) field. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_REACHABILITY_GROUPS. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_read(struct nvme_io_args *args) +static inline int +nvme_get_log_reachability_groups(struct nvme_transport_handle *hdl, + __u32 nsid, bool rgo, struct nvme_reachability_groups_log *log, + __u32 len) { - return nvme_io(args, nvme_cmd_read); + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_reachability_groups(&cmd, rgo, log, len); + + return nvme_get_log(hdl, &cmd, false, len, NULL); } /** - * nvme_write() - Submit an nvme user write command - * @args: &struct nvme_io_args argument structure - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_write(struct nvme_io_args *args) + * nvme_get_log_reachability_associations() - Retrieve the Reachability + * Associations Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @rao: Return Associations Only. Set to true to return only the + * Reachability Association Descriptors. + * @log: Pointer to the buffer + * (@struct nvme_reachability_associations_log) where the log + * page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Reachability + * Associations Log. The @rao parameter is placed in the Log Specific Parameter + * (LSP) field. + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_REACHABILITY_ASSOCIATIONS. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_reachability_associations(struct nvme_transport_handle *hdl, + bool rae, bool rao, + struct nvme_reachability_associations_log *log, __u32 len) { - return nvme_io(args, nvme_cmd_write); + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_reachability_associations(&cmd, rao, log, len); + + return nvme_get_log(hdl, &cmd, rae, len, NULL); } /** - * nvme_compare() - Submit an nvme user compare command - * @args: &struct nvme_io_args argument structure + * nvme_get_log_changed_alloc_ns_list() - Retrieve the Changed Allocated + * Namespace List Log Page + * @hdl: Transport handle for the controller. + * @log: Pointer to the buffer (@struct nvme_ns_list) where the log page + * data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Changed Allocated + * Namespace List Log. + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_CHANGED_ALLOC_NS_LIST. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_compare(struct nvme_io_args *args) +static inline int +nvme_get_log_changed_alloc_ns_list(struct nvme_transport_handle *hdl, + struct nvme_ns_list *log, __u32 len) { - return nvme_io(args, nvme_cmd_compare); + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_changed_ns(&cmd, log); + + return nvme_get_log(hdl, &cmd, true, len, NULL); } /** - * nvme_write_zeros() - Submit an nvme write zeroes command - * @args: &struct nvme_io_args argument structure + * nvme_get_log_discovery() - Retrieve the Discovery Log Page + * @hdl: Transport handle for the controller. + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. * - * The Write Zeroes command sets a range of logical blocks to zero. After - * successful completion of this command, the value returned by subsequent - * reads of logical blocks in this range shall be all bytes cleared to 0h until - * a write occurs to this LBA range. + * Submits the Get Log Page command specifically for the Discovery Log. + * Supported only by NVMe-oF Discovery controllers, returning discovery records. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_DISCOVERY. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_write_zeros(struct nvme_io_args *args) +static inline int +nvme_get_log_discovery(struct nvme_transport_handle *hdl, + __u64 lpo, __u32 len, void *log) { - return nvme_io(args, nvme_cmd_write_zeroes); + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_discovery(&cmd, lpo, log, len); + + return nvme_get_log(hdl, &cmd, false, len, NULL); } /** - * nvme_write_uncorrectable() - Submit an nvme write uncorrectable command - * @args: &struct nvme_io_args argument structure + * nvme_get_log_host_discovery() - Retrieve the Host Discovery Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @allhoste: All Host Entries. Set to true to report all host entries. + * @log: Pointer to the buffer (@struct nvme_host_discover_log) + * where the log page data will be stored. + * @len: Length of the buffer provided in @log. * - * The Write Uncorrectable command marks a range of logical blocks as invalid. - * When the specified logical block(s) are read after this operation, a failure - * is returned with Unrecovered Read Error status. To clear the invalid logical - * block status, a write operation on those logical blocks is required. + * Submits the Get Log Page command specifically for the Host Discovery Log. + * The @allhoste parameter is placed in the Log Specific Parameter (LSP) field. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_HOST_DISCOVER. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_write_uncorrectable(struct nvme_io_args *args) +static inline int +nvme_get_log_host_discovery(struct nvme_transport_handle *hdl, + bool rae, bool allhoste, + struct nvme_host_discover_log *log, __u32 len) { - return nvme_io(args, nvme_cmd_write_uncor); + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_host_discovery(&cmd, allhoste, log, len); + + return nvme_get_log(hdl, &cmd, false, len, NULL); } /** - * nvme_verify() - Send an nvme verify command - * @args: &struct nvme_io_args argument structure + * nvme_get_log_ave_discovery() - Retrieve the Asynchronous Event + * Group (AVE) Discovery Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @log: Pointer to the buffer (@struct nvme_ave_discover_log) where + * the log page data will be stored. + * @len: Length of the buffer provided in @log. * - * The Verify command verifies integrity of stored information by reading data - * and metadata, if applicable, for the LBAs indicated without transferring any - * data or metadata to the host. + * Submits the Get Log Page command specifically for the Asynchronous Event + * Group (AVE) Discovery Log. It automatically sets the Log Identifier (LID). * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_verify(struct nvme_io_args *args) +static inline int +nvme_get_log_ave_discovery(struct nvme_transport_handle *hdl, + bool rae, struct nvme_ave_discover_log *log, __u32 len) { - return nvme_io(args, nvme_cmd_verify); + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_ave_discovery(&cmd, log, len); + + return nvme_get_log(hdl, &cmd, rae, len, NULL); } /** - * nvme_dsm() - Send an nvme data set management command - * @args: &struct nvme_dsm_args argument structure + * nvme_get_log_pull_model_ddc_req() - Retrieve the Pull Model DDC Request + * Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @log: Pointer to the buffer (@struct nvme_pull_model_ddc_req_log) + * where the log page data will be stored. + * @len: Length of the buffer provided in @log. * - * The Dataset Management command is used by the host to indicate attributes - * for ranges of logical blocks. This includes attributes like frequency that - * data is read or written, access size, and other information that may be used - * to optimize performance and reliability, and may be used to - * deallocate/unmap/trim those logical blocks. + * Submits the Get Log Page command specifically for the Pull Model DDC Request + * Log. It automatically sets the Log Identifier (LID). * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_dsm(struct nvme_dsm_args *args); +static inline int +nvme_get_log_pull_model_ddc_req(struct nvme_transport_handle *hdl, + bool rae, struct nvme_pull_model_ddc_req_log *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_pull_model_ddc_req(&cmd, log, len); + + return nvme_get_log(hdl, &cmd, rae, len, NULL); +} /** - * nvme_copy() - Copy command + * nvme_get_log_media_unit_stat() - Retrieve the Media Unit Status Log Page + * @hdl: Transport handle for the controller. + * @domid: The Domain Identifier (DOMID) selection, if supported + * (used in LSI). + * @mus: Pointer to the buffer (@struct nvme_media_unit_stat_log) + * where the log page data will be stored. + * + * Submits the Get Log Page command specifically for the Media Unit Status Log. + * The DOMID is placed in the Log Specific Identifier (LSI) field of the + * command. * - * @args: &struct nvme_copy_args argument structure + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_MEDIA_UNIT_STATUS, and Retain Asynchronous Event (RAE) to false. + * This command is typically issued for the controller scope, thus using + * NVME_NSID_NONE. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_copy(struct nvme_copy_args *args); +static inline int +nvme_get_log_media_unit_stat(struct nvme_transport_handle *hdl, + __u16 domid, struct nvme_media_unit_stat_log *mus) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_media_unit_stat(&cmd, domid, mus); + + return nvme_get_log(hdl, &cmd, false, sizeof(*mus), NULL); +} /** - * nvme_resv_acquire() - Send an nvme reservation acquire - * @args: &struct nvme_resv_acquire argument structure + * nvme_get_log_support_cap_config_list() - Retrieve the Supported Capacity + * Configuration List Log Page + * @hdl: Transport handle for the controller. + * @domid: The Domain Identifier (DOMID) selection, if + * supported (used in LSI). + * @cap: Pointer to the buffer + * (@struct nvme_supported_cap_config_list_log) where the log + * page data will be stored. * - * The Reservation Acquire command acquires a reservation on a namespace, - * preempt a reservation held on a namespace, and abort a reservation held on a - * namespace. + * Submits the Get Log Page command specifically for the Supported Capacity + * Configuration List Log. The DOMID is placed in the Log Specific Identifier + * (LSI) field of the command. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_SUPPORTED_CAP_CONFIG_LIST, and Retain Asynchronous Event (RAE) + * to false. This command is typically issued for the controller scope, thus + * using NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_resv_acquire(struct nvme_resv_acquire_args *args); +static inline int +nvme_get_log_support_cap_config_list(struct nvme_transport_handle *hdl, + __u16 domid, struct nvme_supported_cap_config_list_log *cap) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_support_cap_config_list(&cmd, domid, cap); + + return nvme_get_log(hdl, &cmd, false, sizeof(*cap), NULL); +} /** - * nvme_resv_register() - Send an nvme reservation register - * @args: &struct nvme_resv_register_args argument structure + * nvme_get_log_reservation() - Retrieve the Reservation Notification Log Page + * @hdl: Transport handle for the controller. + * @log: Pointer to the buffer (@struct nvme_resv_notification_log) + * where the log page data will be stored. * - * The Reservation Register command registers, unregisters, or replaces a - * reservation key. + * Submits the Get Log Page command specifically for the Reservation + * Notification Log. It automatically sets the Log Identifier (LID). * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_resv_register(struct nvme_resv_register_args *args); +static inline int +nvme_get_log_reservation(struct nvme_transport_handle *hdl, + struct nvme_resv_notification_log *log) +{ + struct nvme_passthru_cmd cmd; -/** - * nvme_resv_release() - Send an nvme reservation release - * @args: &struct nvme_resv_release_args argument structure - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_resv_release(struct nvme_resv_release_args *args); + nvme_init_get_log_reservation(&cmd, log); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log), NULL); +} /** - * nvme_resv_report() - Send an nvme reservation report - * @args: struct nvme_resv_report_args argument structure + * nvme_get_log_sanitize() - Retrieve the Sanitize Status Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @log: Pointer to the buffer (@struct nvme_sanitize_log_page) + * where the log page data will be stored. * - * Returns a Reservation Status data structure to memory that describes the - * registration and reservation status of a namespace. See the definition for - * the returned structure, &struct nvme_reservation_status, for more details. + * Submits the Get Log Page command specifically for the Sanitize Status Log. + * The log page reports sanitize operation time estimates and information about + * the most recent sanitize operation. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_resv_report(struct nvme_resv_report_args *args); - -/** - * nvme_io_mgmt_recv() - I/O Management Receive command - * @args: &struct nvme_io_mgmt_recv_args argument structure + * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_SANITIZE. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_io_mgmt_recv(struct nvme_io_mgmt_recv_args *args); +static inline int +nvme_get_log_sanitize(struct nvme_transport_handle *hdl, + bool rae, struct nvme_sanitize_log_page *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_sanitize(&cmd, log); + + return nvme_get_log(hdl, &cmd, rae, sizeof(*log), NULL); +} /** - * nvme_fdp_reclaim_unit_handle_status() - Get reclaim unit handle status - * @fd: File descriptor of nvme device - * @nsid: Namespace identifier - * @data_len: Length of response buffer - * @data: Response buffer + * nvme_get_log_zns_changed_zones() - Retrieve the ZNS Changed Zones Log Page + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to request the log for. + * @rae: Retain asynchronous events + * @log: Pointer to the buffer (@struct nvme_zns_changed_zone_log) + * where the log page data will be stored. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Submits the Get Log Page command specifically for the ZNS Changed Zones Log. + * This log lists zones that have changed state due to an exceptional event. + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_ZNS_CHANGED_ZONES. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_fdp_reclaim_unit_handle_status(int fd, __u32 nsid, - __u32 data_len, void *data) +static inline int +nvme_get_log_zns_changed_zones(struct nvme_transport_handle *hdl, + __u32 nsid, bool rae, struct nvme_zns_changed_zone_log *log) { - struct nvme_io_mgmt_recv_args args = { - .data = data, - .args_size = sizeof(args), - .fd = fd, - .nsid = nsid, - .data_len = data_len, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .mos = 0, - .mo = NVME_IO_MGMT_RECV_RUH_STATUS, - }; + struct nvme_passthru_cmd cmd; - return nvme_io_mgmt_recv(&args); + nvme_init_get_log_zns_changed_zones(&cmd, nsid, log); + + return nvme_get_log(hdl, &cmd, rae, sizeof(*log), NULL); } /** - * nvme_io_mgmt_send() - I/O Management Send command - * @args: &struct nvme_io_mgmt_send_args argument structure + * nvme_get_log_persistent_event() - Retrieve the Persistent Event Log Page + * @hdl: Transport handle for the controller. + * @action: Action the controller should take during processing this + * command, see &enum nvme_pevent_log_action (used in LSP). + * @pevent_log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @pevent_log. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_io_mgmt_send(struct nvme_io_mgmt_send_args *args); - -/** - * nvme_fdp_reclaim_unit_handle_update() - Update a list of reclaim unit handles - * @fd: File descriptor of nvme device - * @nsid: Namespace identifier - * @npids: Number of placement identifiers - * @pids: List of placement identifiers + * Submits the Get Log Page command specifically for the Persistent Event Log. + * The @action parameter is placed in the Log Specific Parameter (LSP) field. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_PERSISTENT_EVENT and Retain Asynchronous Event (RAE) to false. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_fdp_reclaim_unit_handle_update(int fd, __u32 nsid, - unsigned int npids, __u16 *pids) +static inline int +nvme_get_log_persistent_event(struct nvme_transport_handle *hdl, + enum nvme_pevent_log_action action, void *pevent_log, __u32 len) { - struct nvme_io_mgmt_send_args args = { - .data = (void *)pids, - .args_size = sizeof(args), - .fd = fd, - .nsid = nsid, - .data_len = (__u32)(npids * sizeof(__u16)), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .mos = (__u16)(npids - 1), - .mo = NVME_IO_MGMT_SEND_RUH_UPDATE, - }; + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_persistent_event(&cmd, action, pevent_log, len); - return nvme_io_mgmt_send(&args); + /* + * Call the generic log execution function. + * The data length is determined by the 'len' parameter. + */ + return nvme_get_log(hdl, &cmd, false, len, NULL); } /** - * nvme_zns_mgmt_send() - ZNS management send command - * @args: &struct nvme_zns_mgmt_send_args argument structure + * nvme_get_log_lockdown() - Retrieve the Command and Feature Lockdown Log Page + * @hdl: Transport handle for the controller. + * @cnscp: Contents and Scope (CNSCP) of Command and Feature + * Identifier Lists (used in LSP). + * @log: Pointer to the buffer (@struct nvme_lockdown_log) where the log + * page data will be stored. + * + * Submits the Get Log Page command specifically for the Command and Feature + * Lockdown Log. The @cnscp parameter is placed in the Log Specific Parameter + * (LSP) field. + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN and Retain Asynchronous Event (RAE) to + * false. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_zns_mgmt_send(struct nvme_zns_mgmt_send_args *args); +static inline int +nvme_get_log_lockdown(struct nvme_transport_handle *hdl, + __u8 cnscp, struct nvme_lockdown_log *log) +{ + struct nvme_passthru_cmd cmd; + nvme_init_get_log_lockdown(&cmd, cnscp, log); -/** - * nvme_zns_mgmt_recv() - ZNS management receive command - * @args: &struct nvme_zns_mgmt_recv_args argument structure - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_zns_mgmt_recv(struct nvme_zns_mgmt_recv_args *args); + return nvme_get_log(hdl, &cmd, false, sizeof(*log), NULL); +} /** - * nvme_zns_report_zones() - Return the list of zones - * @fd: File descriptor of nvme device - * @nsid: Namespace ID - * @slba: Starting LBA - * @opts: Reporting options - * @extended: Extended report - * @partial: Partial report requested - * @data_len: Length of the data buffer - * @data: Userspace address of the report zones data - * @timeout: timeout in ms - * @result: The command completion result from CQE dword0 + * nvme_get_log_smart() - Retrieve the SMART / Health Information Log Page + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to request the log for. + * @smart_log: Pointer to the buffer (@struct nvme_smart_log) where the log + * page data will be stored. + * + * Submits the Get Log Page command specifically for the SMART / Health + * Information Log. It automatically sets the Log Identifier (LID) and + * Retain Asynchronous Event (RAE) to false. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -static inline int nvme_zns_report_zones(int fd, __u32 nsid, __u64 slba, - enum nvme_zns_report_options opts, - bool extended, bool partial, - __u32 data_len, void *data, - __u32 timeout, __u32 *result) +static inline int +nvme_get_log_smart(struct nvme_transport_handle *hdl, + __u32 nsid, struct nvme_smart_log *smart_log) { - struct nvme_zns_mgmt_recv_args args = { - .slba = slba, - .result = result, - .data = data, - .args_size = sizeof(args), - .fd = fd, - .timeout = timeout, - .nsid = nsid, - .zra = extended ? NVME_ZNS_ZRA_EXTENDED_REPORT_ZONES : - NVME_ZNS_ZRA_REPORT_ZONES, - .data_len = data_len, - .zrasf = (__u16)opts, - .zras_feat = partial, - }; + struct nvme_passthru_cmd cmd; - return nvme_zns_mgmt_recv(&args); + nvme_init_get_log_smart(&cmd, nsid, smart_log); + + return nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); } /** - * nvme_zns_append() - Append data to a zone - * @args: &struct nvme_zns_append_args argument structure - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_zns_append(struct nvme_zns_append_args *args); + * nvme_set_features() - Submit a generic Set Features command + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID sto apply the feature to. + * @fid: Feature Identifier (FID) to be set. + * @sv: Save Value (SV): If true, the feature value persists + * across power states. + * @cdw11: Command Dword 11 parameter (feature-specific). + * @cdw12: Command Dword 12 parameter (feature-specific). + * @cdw13: Command Dword 13 parameter (feature-specific). + * @uidx: UUID Index (UIDX) for the command, encoded into cdw14 + * @cdw15: Command Dword 15 parameter (feature-specific). + * @data: Pointer to the data buffer to transfer (if applicable). + * @len: Length of the data buffer in bytes. + * @result: The command completion result (CQE dword0) on success. + * + * Submits the Set Features command, allowing all standard command + * fields (cdw11-cdw15) and data buffer fields to be specified directly. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_set_features(struct nvme_transport_handle *hdl, __u32 nsid, __u8 fid, + bool sv, __u32 cdw11, __u32 cdw12, __u32 cdw13, __u8 uidx, + __u32 cdw15, void *data, __u32 len, __u32 *result) +{ + struct nvme_passthru_cmd cmd; -/** - * nvme_dim_send - Send a Discovery Information Management (DIM) command - * @args: &struct nvme_dim_args argument structure - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_dim_send(struct nvme_dim_args *args); + nvme_init_set_features(&cmd, fid, sv); + cmd.nsid = nsid; + cmd.cdw11 = cdw11; + cmd.cdw12 = cdw12; + cmd.cdw13 = cdw13; + cmd.cdw14 = NVME_FIELD_ENCODE(uidx, + NVME_IDENTIFY_CDW14_UUID_SHIFT, + NVME_IDENTIFY_CDW14_UUID_MASK); + cmd.cdw15 = cdw15; + cmd.data_len = len; + cmd.addr = (__u64)(uintptr_t)data; + + return nvme_submit_admin_passthru(hdl, &cmd, result); +} /** - * nvme_lm_cdq() - Controller Data Queue - Controller Data Queue command - * @args: &struct nvme_lm_cdq_args argument structure + * nvme_set_features_simple() - Submit a Set Features command using only cdw11 + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to apply the feature to. + * @fid: Feature Identifier (FID) to be set. + * @sv: Save Value (SV): If true, the feature value persists across + * power states. + * @cdw11: Command Dword 11 parameter (feature-specific value). + * @result: The command completion result (CQE dword0) on success. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise.) - */ -int nvme_lm_cdq(struct nvme_lm_cdq_args *args); - -/** - * nvme_lm_track_send() - Track Send command - * @args: &struct nvme_lm_track_send_args argument structure + * Submits the Set Features command for features that only require + * parameters in cdw11. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_lm_track_send(struct nvme_lm_track_send_args *args); +static inline int +nvme_set_features_simple(struct nvme_transport_handle *hdl, + __u32 nsid, __u8 fid, bool sv, __u32 cdw11, __u32 *result) +{ + struct nvme_passthru_cmd cmd; -/** - * nvme_lm_migration_send() - Migration Send command - * @args: &struct nvme_lm_migration_send_args argument structure - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_lm_migration_send(struct nvme_lm_migration_send_args *args); + nvme_init_set_features(&cmd, fid, sv); + cmd.nsid = nsid; + cmd.cdw11 = cdw11; -/** - * nvme_lm_migration_recv - Migration Receive command - * @args: &struct nvme_lm_migration_rev_args argument structure - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_lm_migration_recv(struct nvme_lm_migration_recv_args *args); + return nvme_submit_admin_passthru(hdl, &cmd, result); +} /** - * nvme_lm_set_features_ctrl_data_queue - Set Controller Datea Queue feature - * @fd: File descriptor of nvme device - * @cdqid: Controller Data Queue ID (CDQID) - * @hp: Head Pointer - * @tpt: Tail Pointer Trigger - * @etpt: Enable Tail Pointer Trigger - * @result: The command completions result from CQE dword0 + * nvme_get_features() - Submit a Get Features command + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID, if applicable + * @fid: Feature identifier, see &enum nvme_features_id + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @cdw11: Feature specific command dword11 field + * @uidx: UUID Index for differentiating vendor specific encoding + * @data: User address of feature data, if applicable + * @len: Length of feature data, if applicable, in bytes + * @result: The command completion result (CQE dword0) on success. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_lm_set_features_ctrl_data_queue(int fd, __u16 cdqid, __u32 hp, __u32 tpt, bool etpt, - __u32 *result); +static inline int +nvme_get_features(struct nvme_transport_handle *hdl, __u32 nsid, + __u8 fid, enum nvme_get_features_sel sel, + __u32 cdw11, __u8 uidx, void *data, + __u32 len, __u32 *result) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_features(&cmd, fid, sel); + + cmd.nsid = nsid; + cmd.cdw11 = cdw11; + cmd.cdw14 = NVME_FIELD_ENCODE(uidx, + NVME_GET_FEATURES_CDW14_UUID_SHIFT, + NVME_GET_FEATURES_CDW14_UUID_MASK); + cmd.data_len = len; + cmd.addr = (__u64)(uintptr_t)data; + + return nvme_submit_admin_passthru(hdl, &cmd, result); +} /** - * nvme_lm_get_features_ctrl_data_queue - Get Controller Data Queue feature - * @fd: File descriptor of nvme device - * @cdqid: Controller Data Queue ID (CDQID) - * @data: Get Controller Data Queue feature data - * @result: The command completions result from CQE dword0 + * nvme_get_features_simple() - Submit a simple Get Features command + * @hdl: Transport handle for the controller. + * @fid: Feature Identifier (FID) to be retrieved. + * @sel: Select (SEL), specifying which feature value + * to return (&struct nvme_get_features_sel). + * @result: The command completion result (CQE dword0) on success. + * + * Submits the Get Features command for features that only require parameters in + * the CQE dword0 and do not need any parameters in cdw11 through cdw15. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. */ -int nvme_lm_get_features_ctrl_data_queue(int fd, __u16 cdqid, - struct nvme_lm_ctrl_data_queue_fid_data *data, - __u32 *result); +static inline int +nvme_get_features_simple(struct nvme_transport_handle *hdl, __u8 fid, + enum nvme_get_features_sel sel, __u32 *result) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_features(&cmd, fid, sel); + + return nvme_submit_admin_passthru(hdl, &cmd, result); +} #endif /* _LIBNVME_IOCTL_H */ diff --git a/libnvme/src/nvme/json.c b/libnvme/src/nvme/json.c index 992a543730..41f7862b25 100644 --- a/libnvme/src/nvme/json.c +++ b/libnvme/src/nvme/json.c @@ -161,7 +161,7 @@ static void json_parse_subsys(nvme_host_t h, struct json_object *subsys_obj) } } -static void json_parse_host(nvme_root_t r, struct json_object *host_obj) +static void json_parse_host(struct nvme_global_ctx *ctx, struct json_object *host_obj) { struct json_object *attr_obj, *subsys_array, *subsys_obj; nvme_host_t h; @@ -175,7 +175,7 @@ static void json_parse_host(nvme_root_t r, struct json_object *host_obj) attr_obj = json_object_object_get(host_obj, "hostid"); if (attr_obj) hostid = json_object_get_string(attr_obj); - h = nvme_lookup_host(r, hostnqn, hostid); + h = nvme_lookup_host(ctx, hostnqn, hostid); attr_obj = json_object_object_get(host_obj, "dhchap_key"); if (attr_obj) nvme_host_set_dhchap_key(h, json_object_get_string(attr_obj)); @@ -198,7 +198,7 @@ static void json_parse_host(nvme_root_t r, struct json_object *host_obj) static DEFINE_CLEANUP_FUNC(cleanup_tokener, json_tokener *, json_tokener_free) #define _cleanup_tokener_ __cleanup__(cleanup_tokener) -static struct json_object *parse_json(nvme_root_t r, int fd) +static struct json_object *parse_json(struct nvme_global_ctx *ctx, int fd) { char buf[JSON_FILE_BUF_SIZE]; struct json_object *obj; @@ -229,39 +229,36 @@ static struct json_object *parse_json(nvme_root_t r, int fd) obj = json_tokener_parse_ex(tok, str, len); if (!obj) - nvme_msg(r, LOG_DEBUG, "JSON parsing failed: %s\n", + nvme_msg(ctx, LOG_DEBUG, "JSON parsing failed: %s\n", json_util_get_last_err()); return obj; } -int json_read_config(nvme_root_t r, const char *config_file) +int json_read_config(struct nvme_global_ctx *ctx, const char *config_file) { struct json_object *json_root, *host_obj; int fd, h; fd = open(config_file, O_RDONLY); if (fd < 0) { - nvme_msg(r, LOG_DEBUG, "Error opening %s, %s\n", + nvme_msg(ctx, LOG_DEBUG, "Error opening %s, %s\n", config_file, strerror(errno)); return fd; } - json_root = parse_json(r, fd); + json_root = parse_json(ctx, fd); close(fd); - if (!json_root) { - errno = EPROTO; - return -1; - } + if (!json_root) + return -EPROTO; if (!json_object_is_type(json_root, json_type_array)) { - nvme_msg(r, LOG_DEBUG, "Wrong format, expected array\n"); + nvme_msg(ctx, LOG_DEBUG, "Wrong format, expected array\n"); json_object_put(json_root); - errno = EPROTO; - return -1; + return -EPROTO; } for (h = 0; h < json_object_array_length(json_root); h++) { host_obj = json_object_array_get_idx(json_root, h); if (host_obj) - json_parse_host(r, host_obj); + json_parse_host(ctx, host_obj); } json_object_put(json_root); return 0; @@ -389,7 +386,7 @@ static void json_update_subsys(struct json_object *subsys_array, } } -int json_update_config(nvme_root_t r, const char *config_file) +int json_update_config(struct nvme_global_ctx *ctx, const char *config_file) { nvme_host_t h; struct json_object *json_root, *host_obj; @@ -397,7 +394,7 @@ int json_update_config(nvme_root_t r, const char *config_file) int ret = 0; json_root = json_object_new_array(); - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_subsystem_t s; const char *hostnqn, *hostid, *dhchap_key, *hostsymname; @@ -445,11 +442,10 @@ int json_update_config(nvme_root_t r, const char *config_file) JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_NOSLASHESCAPE); if (ret < 0) { - nvme_msg(r, LOG_ERR, "Failed to write to %s, %s\n", + nvme_msg(ctx, LOG_ERR, "Failed to write to %s, %s\n", config_file ? "stdout" : config_file, json_util_get_last_err()); - ret = -1; - errno = EIO; + ret = -EIO; } json_object_put(json_root); @@ -629,7 +625,7 @@ static void json_dump_subsys(struct json_object *subsys_array, json_object_array_add(subsys_array, subsys_obj); } -int json_dump_tree(nvme_root_t r) +int json_dump_tree(struct nvme_global_ctx *ctx) { nvme_host_t h; struct json_object *json_root, *host_obj; @@ -638,7 +634,7 @@ int json_dump_tree(nvme_root_t r) json_root = json_object_new_object(); host_array = json_object_new_array(); - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_subsystem_t s; const char *hostid, *dhchap_key; @@ -669,14 +665,13 @@ int json_dump_tree(nvme_root_t r) } json_object_object_add(json_root, "hosts", host_array); - ret = json_object_to_fd(r->log.fd, json_root, + ret = json_object_to_fd(ctx->log.fd, json_root, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_NOSLASHESCAPE); if (ret < 0) { - nvme_msg(r, LOG_ERR, "Failed to write, %s\n", + nvme_msg(ctx, LOG_ERR, "Failed to write, %s\n", json_util_get_last_err()); - ret = -1; - errno = EIO; + ret = -EIO; } json_object_put(json_root); diff --git a/libnvme/src/nvme/linux.c b/libnvme/src/nvme/linux.c index f2243db881..f1fc7f6a27 100644 --- a/libnvme/src/nvme/linux.c +++ b/libnvme/src/nvme/linux.c @@ -41,92 +41,180 @@ #include "base64.h" #include "crc32.h" -static int __nvme_open(const char *name) +static int __nvme_transport_handle_open_direct(struct nvme_transport_handle *hdl, const char *devname) { _cleanup_free_ char *path = NULL; - int ret; + char *name = basename(devname); + int ret, id, ns; + bool c; + + hdl->type = NVME_TRANSPORT_HANDLE_TYPE_DIRECT; + + ret = sscanf(name, "nvme%dn%d", &id, &ns); + if (ret != 1 && ret != 2) + return -EINVAL; + c = ret == 1; ret = asprintf(&path, "%s/%s", "/dev", name); - if (ret < 0) { - errno = ENOMEM; - return -1; + if (ret < 0) + return -ENOMEM; + + hdl->fd = open(path, O_RDONLY); + if (hdl->fd < 0) + return -errno; + + ret = fstat(hdl->fd, &hdl->stat); + if (ret < 0) + return -errno; + + if (c) { + if (!S_ISCHR(hdl->stat.st_mode)) + return -EINVAL; + } else if (!S_ISBLK(hdl->stat.st_mode)) { + return -EINVAL; } - return open(path, O_RDONLY); + return 0; } -int nvme_open(const char *name) +void __nvme_transport_handle_close_direct(struct nvme_transport_handle *hdl) { - int ret, fd, id, ns; - struct stat stat; - bool c; + close(hdl->fd); + free(hdl); +} - ret = sscanf(name, "nvme%dn%d", &id, &ns); - if (ret != 1 && ret != 2) { - errno = EINVAL; - return -1; +struct nvme_transport_handle *__nvme_create_transport_handle(struct nvme_global_ctx *ctx) +{ + struct nvme_transport_handle *hdl; + + hdl = calloc(1, sizeof(*hdl)); + if (!hdl) + return NULL; + + hdl->ctx = ctx; + + return hdl; +} + +int nvme_open(struct nvme_global_ctx *ctx, const char *name, + struct nvme_transport_handle **hdlp) +{ + struct nvme_transport_handle *hdl; + int ret; + + hdl = __nvme_create_transport_handle(ctx); + if (!hdl) + return -ENOMEM; + + hdl->name = strdup(name); + if (!hdl->name) { + free(hdl); + return -ENOMEM; } - c = ret == 1; - fd = __nvme_open(name); - if (fd < 0) - return fd; + if (!strcmp(name, "NVME_TEST_FD")) { + hdl->type = NVME_TRANSPORT_HANDLE_TYPE_DIRECT; + hdl->fd = 0xFD; + *hdlp = hdl; + return 0; + } - ret = fstat(fd, &stat); - if (ret < 0) - goto close_fd; + if (!strncmp(name, "mctp:", strlen("mctp:"))) + ret = __nvme_transport_handle_open_mi(hdl, name); + else + ret = __nvme_transport_handle_open_direct(hdl, name); - if (c) { - if (!S_ISCHR(stat.st_mode)) { - errno = EINVAL; - goto close_fd; - } - } else if (!S_ISBLK(stat.st_mode)) { - errno = EINVAL; - goto close_fd; + if (ret) { + nvme_close(hdl); + return ret; } - return fd; + *hdlp = hdl; -close_fd: - close(fd); - return -1; + return 0; +} + +void nvme_close(struct nvme_transport_handle *hdl) +{ + if (!hdl) + return; + + free(hdl->name); + + switch (hdl->type) { + case NVME_TRANSPORT_HANDLE_TYPE_DIRECT: + __nvme_transport_handle_close_direct(hdl); + break; + case NVME_TRANSPORT_HANDLE_TYPE_MI: + __nvme_transport_handle_close_mi(hdl); + break; + case NVME_TRANSPORT_HANDLE_TYPE_UNKNOWN: + free(hdl); + break; + } } -int nvme_fw_download_seq(int fd, __u32 size, __u32 xfer, __u32 offset, - void *buf) +int nvme_transport_handle_get_fd(struct nvme_transport_handle *hdl) { + return hdl->fd; +} + +const char *nvme_transport_handle_get_name(struct nvme_transport_handle *hdl) +{ + return basename(hdl->name); +} + +bool nvme_transport_handle_is_blkdev(struct nvme_transport_handle *hdl) +{ + return S_ISBLK(hdl->stat.st_mode); +} + +bool nvme_transport_handle_is_chardev(struct nvme_transport_handle *hdl) +{ + return S_ISCHR(hdl->stat.st_mode); +} + +bool nvme_transport_handle_is_direct(struct nvme_transport_handle *hdl) +{ + return hdl->type == NVME_TRANSPORT_HANDLE_TYPE_DIRECT; +} + +bool nvme_transport_handle_is_mi(struct nvme_transport_handle *hdl) +{ + return hdl->type == NVME_TRANSPORT_HANDLE_TYPE_MI; +} + +int nvme_fw_download_seq(struct nvme_transport_handle *hdl, __u32 size, + __u32 xfer, __u32 offset, void *buf) +{ + struct nvme_passthru_cmd cmd; + void *data = buf; int err = 0; - struct nvme_fw_download_args args = { - .args_size = sizeof(args), - .fd = fd, - .offset = offset, - .data_len = xfer, - .data = buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; while (size > 0) { - args.data_len = MIN(xfer, size); - err = nvme_fw_download(&args); + err = nvme_init_fw_download(&cmd, data, MIN(xfer, size), offset); + if (err) + break; + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err) break; - args.data += xfer; + data += xfer; size -= xfer; - args.offset += xfer; + offset += xfer; } return err; } -int nvme_set_etdas(int fd, bool *changed) +int nvme_set_etdas(struct nvme_transport_handle *hdl, bool *changed) { struct nvme_feat_host_behavior da4; + struct nvme_passthru_cmd cmd; int err; - err = nvme_get_features_host_behavior(fd, 0, &da4, NULL); + nvme_init_get_features_host_behavior(&cmd, 0, &da4); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err) return err; @@ -137,7 +225,8 @@ int nvme_set_etdas(int fd, bool *changed) da4.etdas = 1; - err = nvme_set_features_host_behavior(fd, 0, &da4); + nvme_init_set_features_host_behavior(&cmd, false, &da4); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err) return err; @@ -145,12 +234,14 @@ int nvme_set_etdas(int fd, bool *changed) return 0; } -int nvme_clear_etdas(int fd, bool *changed) +int nvme_clear_etdas(struct nvme_transport_handle *hdl, bool *changed) { struct nvme_feat_host_behavior da4; + struct nvme_passthru_cmd cmd; int err; - err = nvme_get_features_host_behavior(fd, 0, &da4, NULL); + nvme_init_get_features_host_behavior(&cmd, 0, &da4); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err) return err; @@ -160,7 +251,8 @@ int nvme_clear_etdas(int fd, bool *changed) } da4.etdas = 0; - err = nvme_set_features_host_behavior(fd, 0, &da4); + nvme_init_set_features_host_behavior(&cmd, false, &da4); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err) return err; @@ -168,35 +260,40 @@ int nvme_clear_etdas(int fd, bool *changed) return 0; } -int nvme_get_uuid_list(int fd, struct nvme_id_uuid_list *uuid_list) +int nvme_get_uuid_list(struct nvme_transport_handle *hdl, struct nvme_id_uuid_list *uuid_list) { - int err; + struct nvme_passthru_cmd cmd; struct nvme_id_ctrl ctrl; + int err; memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - err = nvme_identify_ctrl(fd, &ctrl); + nvme_init_identify_ctrl(&cmd, &ctrl); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err) { fprintf(stderr, "ERROR: nvme_identify_ctrl() failed 0x%x\n", err); return err; } - if ((ctrl.ctratt & NVME_CTRL_CTRATT_UUID_LIST) == NVME_CTRL_CTRATT_UUID_LIST) - err = nvme_identify_uuid(fd, uuid_list); + if ((ctrl.ctratt & NVME_CTRL_CTRATT_UUID_LIST) == NVME_CTRL_CTRATT_UUID_LIST) { + nvme_init_identify_uuid_list(&cmd, uuid_list); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); + } return err; } -int nvme_get_telemetry_max(int fd, enum nvme_telemetry_da *da, size_t *data_tx) +int nvme_get_telemetry_max(struct nvme_transport_handle *hdl, enum nvme_telemetry_da *da, size_t *data_tx) { - _cleanup_free_ struct nvme_id_ctrl *id_ctrl = NULL; + struct nvme_id_ctrl *id_ctrl = NULL; + struct nvme_passthru_cmd cmd; int err; id_ctrl = __nvme_alloc(sizeof(*id_ctrl)); - if (!id_ctrl) { - errno = ENOMEM; - return -1; - } - err = nvme_identify_ctrl(fd, id_ctrl); + if (!id_ctrl) + return -ENOMEM; + + nvme_init_identify_ctrl(&cmd, id_ctrl); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err) return err; @@ -219,49 +316,35 @@ int nvme_get_telemetry_max(int fd, enum nvme_telemetry_da *da, size_t *data_tx) return err; } -int nvme_get_telemetry_log(int fd, bool create, bool ctrl, bool rae, size_t max_data_tx, +int nvme_get_telemetry_log(struct nvme_transport_handle *hdl, bool create, bool ctrl, bool rae, size_t max_data_tx, enum nvme_telemetry_da da, struct nvme_telemetry_log **buf, size_t *size) { static const __u32 xfer = NVME_LOG_TELEM_BLOCK_SIZE; - struct nvme_telemetry_log *telem; - enum nvme_cmd_get_log_lid lid; + struct nvme_passthru_cmd cmd; _cleanup_free_ void *log = NULL; void *tmp; int err; size_t dalb; - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = fd, - .nsid = NVME_NSID_NONE, - .lsp = NVME_LOG_LSP_NONE, - .lsi = NVME_LOG_LSI_NONE, - .uuidx = NVME_UUID_NONE, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - .csi = NVME_CSI_NVM, - .rae = rae, - .ot = false, - }; *size = 0; log = __nvme_alloc(xfer); - if (!log) { - errno = ENOMEM; - return -1; - } + if (!log) + return -ENOMEM; if (ctrl) { - err = nvme_get_log_telemetry_ctrl(fd, true, 0, xfer, log); - lid = NVME_LOG_LID_TELEMETRY_CTRL; + nvme_init_get_log_telemetry_ctrl(&cmd, 0, log, xfer); + err = nvme_get_log(hdl, &cmd, true, xfer, NULL); } else { - lid = NVME_LOG_LID_TELEMETRY_HOST; - if (create) - err = nvme_get_log_create_telemetry_host_mcda(fd, da, log); - else - err = nvme_get_log_telemetry_host(fd, 0, xfer, log); + if (create) { + nvme_init_get_log_create_telemetry_host_mcda(&cmd, da, log); + err = nvme_get_log(hdl, &cmd, false, xfer, NULL); + } else { + nvme_init_get_log_telemetry_host(&cmd, 0, log, xfer); + err = nvme_get_log(hdl, &cmd, false, xfer, NULL); + } } if (err) @@ -290,27 +373,23 @@ int nvme_get_telemetry_log(int fd, bool create, bool ctrl, bool rae, size_t max_ dalb = le32_to_cpu(telem->dalb4); break; default: - errno = EINVAL; - return -1; + return -EINVAL; } - if (dalb == 0) { - errno = ENOENT; - return -1; - } + if (dalb == 0) + return -ENOENT; *size = (dalb + 1) * xfer; tmp = __nvme_realloc(log, *size); - if (!tmp) { - errno = ENOMEM; - return -1; - } + if (!tmp) + return -ENOMEM; log = tmp; - args.lid = lid; - args.log = log; - args.len = *size; - err = nvme_get_log_page(fd, max_data_tx, &args); + if (ctrl) + nvme_init_get_log_telemetry_ctrl(&cmd, 0, log, *size); + else + nvme_init_get_log_telemetry_host(&cmd, 0, log, *size); + err = nvme_get_log(hdl, &cmd, rae, max_data_tx, NULL); if (err) return err; @@ -320,66 +399,56 @@ int nvme_get_telemetry_log(int fd, bool create, bool ctrl, bool rae, size_t max_ } -static int nvme_check_get_telemetry_log(int fd, bool create, bool ctrl, bool rae, +static int nvme_check_get_telemetry_log(struct nvme_transport_handle *hdl, bool create, bool ctrl, bool rae, struct nvme_telemetry_log **log, enum nvme_telemetry_da da, size_t *size) { enum nvme_telemetry_da max_da = 0; - int err = nvme_get_telemetry_max(fd, &max_da, NULL); + int err; + err = nvme_get_telemetry_max(hdl, &max_da, NULL); if (err) return err; - if (da > max_da) { - errno = ENOENT; - return -1; - } - return nvme_get_telemetry_log(fd, create, ctrl, rae, 4096, da, log, size); + + if (da > max_da) + return -ENOENT; + + return nvme_get_telemetry_log(hdl, create, ctrl, rae, 4096, da, log, size); } -int nvme_get_ctrl_telemetry(int fd, bool rae, struct nvme_telemetry_log **log, +int nvme_get_ctrl_telemetry(struct nvme_transport_handle *hdl, bool rae, struct nvme_telemetry_log **log, enum nvme_telemetry_da da, size_t *size) { - return nvme_check_get_telemetry_log(fd, false, true, rae, log, da, size); + return nvme_check_get_telemetry_log(hdl, false, true, rae, log, da, size); } -int nvme_get_host_telemetry(int fd, struct nvme_telemetry_log **log, +int nvme_get_host_telemetry(struct nvme_transport_handle *hdl, struct nvme_telemetry_log **log, enum nvme_telemetry_da da, size_t *size) { - return nvme_check_get_telemetry_log(fd, false, false, false, log, da, size); + return nvme_check_get_telemetry_log(hdl, false, false, false, log, da, size); } -int nvme_get_new_host_telemetry(int fd, struct nvme_telemetry_log **log, +int nvme_get_new_host_telemetry(struct nvme_transport_handle *hdl, struct nvme_telemetry_log **log, enum nvme_telemetry_da da, size_t *size) { - return nvme_check_get_telemetry_log(fd, true, false, false, log, da, size); + return nvme_check_get_telemetry_log(hdl, true, false, false, log, da, size); } -int nvme_get_lba_status_log(int fd, bool rae, struct nvme_lba_status_log **log) +int nvme_get_lba_status_log(struct nvme_transport_handle *hdl, bool rae, struct nvme_lba_status_log **log) { _cleanup_free_ struct nvme_lba_status_log *buf = NULL; + struct nvme_passthru_cmd cmd; __u32 size; void *tmp; int err; - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = fd, - .nsid = NVME_NSID_NONE, - .lsp = NVME_LOG_LSP_NONE, - .lsi = NVME_LOG_LSI_NONE, - .uuidx = NVME_UUID_NONE, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - .csi = NVME_CSI_NVM, - .rae = rae, - .ot = false, - }; buf = malloc(sizeof(*buf)); if (!buf) - return -1; + return -ENOMEM; - err = nvme_get_log_lba_status(fd, true, 0, sizeof(*buf), buf); + nvme_init_get_log_lba_status(&cmd, 0, log, sizeof(*buf)); + err = nvme_get_log(hdl, &cmd, true, sizeof(*buf), NULL); if (err) { *log = NULL; return err; @@ -395,14 +464,12 @@ int nvme_get_lba_status_log(int fd, bool rae, struct nvme_lba_status_log **log) tmp = realloc(buf, size); if (!tmp) { *log = NULL; - return -1; + return -ENOMEM; } buf = tmp; - args.lid = NVME_LOG_LID_LBA_STATUS; - args.log = buf; - args.len = size; - err = nvme_get_log_page(fd, 4096, &args); + nvme_init_get_log_lba_status(&cmd, 0, buf, size); + err = nvme_get_log(hdl, &cmd, rae, NVME_LOG_PAGE_PDU_SIZE, NULL); if (err) { *log = NULL; return err; @@ -413,38 +480,31 @@ int nvme_get_lba_status_log(int fd, bool rae, struct nvme_lba_status_log **log) return 0; } -static int nvme_ns_attachment(int fd, __u32 nsid, __u16 num_ctrls, - __u16 *ctrlist, bool attach, __u32 timeout) +static int nvme_ns_attachment(struct nvme_transport_handle *hdl, __u32 nsid, + __u16 num_ctrls, __u16 *ctrlist, bool attach) { struct nvme_ctrl_list cntlist = { 0 }; - struct nvme_ns_attach_args args = { - .args_size = sizeof(args), - .fd = fd, - .nsid = nsid, - .sel = NVME_NS_ATTACH_SEL_CTRL_DEATTACH, - .ctrlist = &cntlist, - .timeout = timeout, - }; + struct nvme_passthru_cmd cmd; + nvme_init_ctrl_list(&cntlist, num_ctrls, ctrlist); if (attach) - args.sel = NVME_NS_ATTACH_SEL_CTRL_ATTACH; + nvme_init_ns_attach_ctrls(&cmd, nsid, &cntlist); + else + nvme_init_ns_detach_ctrls(&cmd, nsid, &cntlist); - nvme_init_ctrl_list(args.ctrlist, num_ctrls, ctrlist); - return nvme_ns_attach(&args); + return nvme_submit_admin_passthru(hdl, &cmd, NULL); } -int nvme_namespace_attach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, - __u16 *ctrlist) +int nvme_namespace_attach_ctrls(struct nvme_transport_handle *hdl, __u32 nsid, + __u16 num_ctrls, __u16 *ctrlist) { - return nvme_ns_attachment(fd, nsid, num_ctrls, ctrlist, true, - NVME_DEFAULT_IOCTL_TIMEOUT); + return nvme_ns_attachment(hdl, nsid, num_ctrls, ctrlist, true); } -int nvme_namespace_detach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, - __u16 *ctrlist) +int nvme_namespace_detach_ctrls(struct nvme_transport_handle *hdl, __u32 nsid, + __u16 num_ctrls, __u16 *ctrlist) { - return nvme_ns_attachment(fd, nsid, num_ctrls, ctrlist, false, - NVME_DEFAULT_IOCTL_TIMEOUT); + return nvme_ns_attachment(hdl, nsid, num_ctrls, ctrlist, false); } size_t nvme_get_ana_log_len_from_id_ctrl(const struct nvme_id_ctrl *id_ctrl, @@ -457,17 +517,18 @@ size_t nvme_get_ana_log_len_from_id_ctrl(const struct nvme_id_ctrl *id_ctrl, return rgo ? size : size + le32_to_cpu(id_ctrl->mnan) * sizeof(__le32); } -int nvme_get_ana_log_len(int fd, size_t *analen) +int nvme_get_ana_log_len(struct nvme_transport_handle *hdl, size_t *analen) { _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; + struct nvme_passthru_cmd cmd; int ret; ctrl = __nvme_alloc(sizeof(*ctrl)); - if (!ctrl) { - errno = ENOMEM; - return -1; - } - ret = nvme_identify_ctrl(fd, ctrl); + if (!ctrl) + return -ENOMEM; + + nvme_init_identify_ctrl(&cmd, ctrl); + ret = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (ret) return ret; @@ -475,18 +536,19 @@ int nvme_get_ana_log_len(int fd, size_t *analen) return 0; } -int nvme_get_logical_block_size(int fd, __u32 nsid, int *blksize) +int nvme_get_logical_block_size(struct nvme_transport_handle *hdl, __u32 nsid, int *blksize) { _cleanup_free_ struct nvme_id_ns *ns = NULL; + struct nvme_passthru_cmd cmd; __u8 flbas; int ret; ns = __nvme_alloc(sizeof(*ns)); - if (!ns) { - errno = ENOMEM; - return -1; - } - ret = nvme_identify_ns(fd, nsid, ns); + if (!ns) + return -ENOMEM; + + nvme_init_identify_ns(&cmd, nsid, ns); + ret = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (ret) return ret; @@ -506,7 +568,7 @@ static int __nvme_set_attr(const char *path, const char *value) nvme_msg(LOG_DEBUG, "Failed to open %s: %s\n", path, strerror(errno)); #endif - return -1; + return -errno; } return write(fd, value, strlen(value)); } @@ -518,7 +580,7 @@ int nvme_set_attr(const char *dir, const char *attr, const char *value) ret = asprintf(&path, "%s/%s", dir, attr); if (ret < 0) - return -1; + return -ENOMEM; return __nvme_set_attr(path, value); } @@ -558,10 +620,8 @@ char *nvme_get_attr(const char *dir, const char *attr) int ret; ret = asprintf(&path, "%s/%s", dir, attr); - if (ret < 0) { - errno = ENOMEM; + if (ret < 0) return NULL; - } return __nvme_get_attr(path); } @@ -599,8 +659,7 @@ int nvme_gen_dhchap_key(char *hostnqn, enum nvme_hmac_alg hmac, if (hmac != NVME_HMAC_ALG_NONE) { nvme_msg(NULL, LOG_ERR, "HMAC transformation not supported; " \ "recompile with OpenSSL support.\n"); - errno = -EINVAL; - return -1; + return -EINVAL; } memcpy(key, secret, key_len); @@ -614,8 +673,7 @@ static int derive_retained_key(int hmac, const char *hostnqn, { nvme_msg(NULL, LOG_ERR, "NVMe TLS is not supported; " "recompile with OpenSSL support.\n"); - errno = ENOTSUP; - return -1; + return -ENOTSUP; } static int derive_retained_key_compat(int hmac, const char *hostnqn, @@ -625,8 +683,7 @@ static int derive_retained_key_compat(int hmac, const char *hostnqn, { nvme_msg(NULL, LOG_ERR, "NVMe TLS is not supported; " "recompile with OpenSSL support.\n"); - errno = ENOTSUP; - return -1; + return -ENOTSUP; } static int derive_psk_digest(const char *hostnqn, const char *subsysnqn, @@ -636,8 +693,7 @@ static int derive_psk_digest(const char *hostnqn, const char *subsysnqn, { nvme_msg(NULL, LOG_ERR, "NVMe TLS 2.0 is not supported; " "recompile with OpenSSL support.\n"); - errno = ENOTSUP; - return -1; + return -ENOTSUP; } static int derive_tls_key(int version, int cipher, const char *context, @@ -646,8 +702,7 @@ static int derive_tls_key(int version, int cipher, const char *context, { nvme_msg(NULL, LOG_ERR, "NVMe TLS is not supported; " "recompile with OpenSSL support.\n"); - errno = ENOTSUP; - return -1; + return -ENOTSUP; } static int derive_tls_key_compat(int version, int cipher, const char *context, @@ -656,8 +711,7 @@ static int derive_tls_key_compat(int version, int cipher, const char *context, { nvme_msg(NULL, LOG_ERR, "NVMe TLS is not supported; " "recompile with OpenSSL support.\n"); - errno = ENOTSUP; - return -1; + return -ENOTSUP; } #else /* CONFIG_OPENSSL */ static unsigned char default_hmac(size_t key_len) @@ -752,10 +806,8 @@ static int derive_retained_key(int hmac, const char *hostnqn, /* +1 byte so that the snprintf terminating null can not overflow */ hkdf_info = malloc(HKDF_INFO_MAX_LEN + 1); - if (!hkdf_info) { - errno = ENOMEM; - return -1; - } + if (!hkdf_info) + return -ENOMEM; if (hmac == NVME_HMAC_ALG_NONE) { memcpy(retained, configured, key_len); @@ -763,34 +815,25 @@ static int derive_retained_key(int hmac, const char *hostnqn, } md = select_hmac(hmac, &hmac_len); - if (!md || !hmac_len) { - errno = EINVAL; - return -1; - } + if (!md || !hmac_len) + return -EINVAL; ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); - if (!ctx) { - errno = ENOMEM; - return -1; - } + if (!ctx) + return -ENOMEM; - if (EVP_PKEY_derive_init(ctx) <= 0) { - errno = ENOMEM; - return -1; - } - if (EVP_PKEY_CTX_set_hkdf_md(ctx, md) <= 0) { - errno = ENOKEY; - return -1; - } - if (EVP_PKEY_CTX_set1_hkdf_key(ctx, configured, key_len) <= 0) { - errno = ENOKEY; - return -1; - } + if (EVP_PKEY_derive_init(ctx) <= 0) + return -ENOMEM; + + if (EVP_PKEY_CTX_set_hkdf_md(ctx, md) <= 0) + return -ENOKEY; + + if (EVP_PKEY_CTX_set1_hkdf_key(ctx, configured, key_len) <= 0) + return -ENOKEY; + + if (key_len > USHRT_MAX) + return -EINVAL; - if (key_len > USHRT_MAX) { - errno = EINVAL; - return -1; - } pos = (char *)hkdf_info; *(uint16_t *)pos = htons(key_len & 0xFFFF); pos += sizeof(uint16_t); @@ -798,30 +841,22 @@ static int derive_retained_key(int hmac, const char *hostnqn, hkdf_label = "tls13 HostNQN"; ret = snprintf(pos, HKDF_INFO_LABEL_MAX + 1, "%c%s", (int)strlen(hkdf_label), hkdf_label); - if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX) { - errno = ENOKEY; - return -1; - } + if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX) + return -ENOKEY; pos += ret; ret = snprintf(pos, HKDF_INFO_CONTEXT_MAX + 1, "%c%s", (int)strlen(hostnqn), hostnqn); - if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX) { - errno = ENOKEY; - return -1; - } + if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX) + return -ENOKEY; pos += ret; if (EVP_PKEY_CTX_add1_hkdf_info(ctx, hkdf_info, - (pos - (char *)hkdf_info)) <= 0) { - errno = ENOKEY; - return -1; - } + (pos - (char *)hkdf_info)) <= 0) + return -ENOKEY; - if (EVP_PKEY_derive(ctx, retained, &key_len) <= 0) { - errno = ENOKEY; - return -1; - } + if (EVP_PKEY_derive(ctx, retained, &key_len) <= 0) + return -ENOKEY; return key_len; } @@ -844,36 +879,26 @@ static int derive_retained_key_compat(int hmac, const char *hostnqn, } md = select_hmac(hmac, &hmac_len); - if (!md || !hmac_len) { - errno = EINVAL; - return -1; - } + if (!md || !hmac_len) + return -EINVAL; ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); - if (!ctx) { - errno = ENOMEM; - return -1; - } + if (!ctx) + return -ENOMEM; - if (EVP_PKEY_derive_init(ctx) <= 0) { - errno = ENOMEM; - return -1; - } - if (EVP_PKEY_CTX_set_hkdf_md(ctx, md) <= 0) { - errno = ENOKEY; - return -1; - } - if (EVP_PKEY_CTX_set1_hkdf_key(ctx, configured, key_len) <= 0) { - errno = ENOKEY; - return -1; - } + if (EVP_PKEY_derive_init(ctx) <= 0) + return -ENOMEM; + + if (EVP_PKEY_CTX_set_hkdf_md(ctx, md) <= 0) + return -ENOKEY; + + if (EVP_PKEY_CTX_set1_hkdf_key(ctx, configured, key_len) <= 0) + return -ENOKEY; /* +1 byte so that the snprintf terminating null can not overflow */ hkdf_info = malloc(HKDF_INFO_MAX_LEN + 1); - if (!hkdf_info) { - errno = ENOMEM; - return -1; - } + if (!hkdf_info) + return -ENOMEM; pos = (char *)hkdf_info; *(uint16_t *)pos = cpu_to_le16(key_len); @@ -881,22 +906,16 @@ static int derive_retained_key_compat(int hmac, const char *hostnqn, ret = snprintf(pos, HKDF_INFO_LABEL_MAX + 1, "tls13 HostNQN%s", hostnqn); - if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX) { - errno = ENOKEY; - return -1; - } + if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX) + return -ENOKEY; pos += ret; if (EVP_PKEY_CTX_add1_hkdf_info(ctx, hkdf_info, - (pos - (char *)hkdf_info)) <= 0) { - errno = ENOKEY; - return -1; - } + (pos - (char *)hkdf_info)) <= 0) + return -ENOKEY; - if (EVP_PKEY_derive(ctx, retained, &key_len) <= 0) { - errno = ENOKEY; - return -1; - } + if (EVP_PKEY_derive(ctx, retained, &key_len) <= 0) + return -ENOKEY; return key_len; } @@ -938,40 +957,29 @@ static int derive_tls_key(int version, unsigned char cipher, /* +1 byte so that the snprintf terminating null can not overflow */ hkdf_info = malloc(HKDF_INFO_MAX_LEN + 1); - if (!hkdf_info) { - errno = ENOMEM; - return -1; - } + if (!hkdf_info) + return -ENOMEM; md = select_hmac(cipher, &hmac_len); - if (!md || !hmac_len) { - errno = EINVAL; - return -1; - } + if (!md || !hmac_len) + return -EINVAL; ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); - if (!ctx) { - errno = ENOMEM; - return -1; - } + if (!ctx) + return -ENOMEM; - if (EVP_PKEY_derive_init(ctx) <= 0) { - errno = ENOMEM; - return -1; - } - if (EVP_PKEY_CTX_set_hkdf_md(ctx, md) <= 0) { - errno = ENOKEY; - return -1; - } - if (EVP_PKEY_CTX_set1_hkdf_key(ctx, retained, key_len) <= 0) { - errno = ENOKEY; - return -1; - } + if (EVP_PKEY_derive_init(ctx) <= 0) + return -ENOMEM; + + if (EVP_PKEY_CTX_set_hkdf_md(ctx, md) <= 0) + return -ENOKEY; + + if (EVP_PKEY_CTX_set1_hkdf_key(ctx, retained, key_len) <= 0) + return -ENOKEY; + + if (key_len > USHRT_MAX) + return -EINVAL; - if (key_len > USHRT_MAX) { - errno = EINVAL; - return -1; - } pos = (char *)hkdf_info; *(uint16_t *)pos = htons(key_len & 0xFFFF); pos += sizeof(uint16_t); @@ -979,45 +987,35 @@ static int derive_tls_key(int version, unsigned char cipher, hkdf_label = "tls13 nvme-tls-psk"; ret = snprintf(pos, HKDF_INFO_LABEL_MAX + 1, "%c%s", (int)strlen(hkdf_label), hkdf_label); - if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX) { - errno = ENOKEY; - return -1; - } + if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX) + return -ENOKEY; pos += ret; switch (version) { case 0: ret = snprintf(pos, HKDF_INFO_CONTEXT_MAX + 1, "%c%s", (int)strlen(context), context); - if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX) { - errno = ENOKEY; - return -1; - } + if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX) + return -ENOKEY; pos += ret; break; case 1: ret = snprintf(pos, HKDF_INFO_CONTEXT_MAX + 1, "%c%02d %s", (int)strlen(context) + 3, cipher, context); - if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX) { - errno = ENOKEY; - return -1; - } + if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX) + return -ENOKEY; pos += ret; break; default: - errno = ENOKEY; - return -1; + return -ENOKEY; } if (EVP_PKEY_CTX_add1_hkdf_info(ctx, hkdf_info, - (pos - (char *)hkdf_info)) <= 0) { - errno = ENOKEY; - return -1; - } - if (EVP_PKEY_derive(ctx, psk, &key_len) <= 0) { - errno = ENOKEY; - return -1; - } + (pos - (char *)hkdf_info)) <= 0) + return -ENOKEY; + + if (EVP_PKEY_derive(ctx, psk, &key_len) <= 0) + return -ENOKEY; return key_len; } @@ -1034,81 +1032,60 @@ static int derive_tls_key_compat(int version, unsigned char cipher, int ret; md = select_hmac(cipher, &hmac_len); - if (!md || !hmac_len) { - errno = EINVAL; - return -1; - } + if (!md || !hmac_len) + return -EINVAL; ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); - if (!ctx) { - errno = ENOMEM; - return -1; - } + if (!ctx) + return -ENOMEM; - if (EVP_PKEY_derive_init(ctx) <= 0) { - errno = ENOMEM; - return -1; - } - if (EVP_PKEY_CTX_set_hkdf_md(ctx, md) <= 0) { - errno = ENOKEY; - return -1; - } - if (EVP_PKEY_CTX_set1_hkdf_key(ctx, retained, key_len) <= 0) { - errno = ENOKEY; - return -1; - } + if (EVP_PKEY_derive_init(ctx) <= 0) + return -ENOMEM; + + if (EVP_PKEY_CTX_set_hkdf_md(ctx, md) <= 0) + return -ENOKEY; + + if (EVP_PKEY_CTX_set1_hkdf_key(ctx, retained, key_len) <= 0) + return -ENOKEY; /* +1 byte so that the snprintf terminating null can not overflow */ hkdf_info = malloc(HKDF_INFO_MAX_LEN + 1); - if (!hkdf_info) { - errno = ENOMEM; - return -1; - } + if (!hkdf_info) + return -ENOMEM; pos = (char *)hkdf_info; *(uint16_t *)pos = cpu_to_le16(key_len); pos += sizeof(uint16_t); ret = snprintf(pos, HKDF_INFO_LABEL_MAX + 1, "tls13 nvme-tls-psk"); - if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX) { - errno = ENOKEY; - return -1; - } + if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX) + return -ENOKEY; pos += ret; switch (version) { case 0: ret = snprintf(pos, HKDF_INFO_CONTEXT_MAX + 1, "%s", context); - if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX) { - errno = ENOKEY; - return -1; - } + if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX) + return -ENOKEY; pos += ret; break; case 1: ret = snprintf(pos, HKDF_INFO_CONTEXT_MAX + 1, "%02d %s", cipher, context); - if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX) { - errno = ENOKEY; - return -1; - } + if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX) + return -ENOKEY; pos += ret; break; default: - errno = ENOKEY; - return -1; + return -ENOKEY; } if (EVP_PKEY_CTX_add1_hkdf_info(ctx, hkdf_info, - (pos - (char *)hkdf_info)) <= 0) { - errno = ENOKEY; - return -1; - } + (pos - (char *)hkdf_info)) <= 0) + return -ENOKEY; - if (EVP_PKEY_derive(ctx, psk, &key_len) <= 0) { - errno = ENOKEY; - return -1; - } + if (EVP_PKEY_derive(ctx, psk, &key_len) <= 0) + return -ENOKEY; return key_len; } @@ -1135,22 +1112,16 @@ int nvme_gen_dhchap_key(char *hostnqn, enum nvme_hmac_alg hmac, size_t len; lib_ctx = OSSL_LIB_CTX_new(); - if (!lib_ctx) { - errno = ENOMEM; - return -1; - } + if (!lib_ctx) + return -ENOMEM; mac = EVP_MAC_fetch(lib_ctx, OSSL_MAC_NAME_HMAC, progq); - if (!mac) { - errno = ENOMEM; - return -1; - } + if (!mac) + return -ENOMEM; mac_ctx = EVP_MAC_CTX_new(mac); - if (!mac_ctx) { - errno = ENOMEM; - return -1; - } + if (!mac_ctx) + return -ENOMEM; switch (hmac) { case NVME_HMAC_ALG_NONE: @@ -1166,40 +1137,29 @@ int nvme_gen_dhchap_key(char *hostnqn, enum nvme_hmac_alg hmac, digest = OSSL_DIGEST_NAME_SHA2_512; break; default: - errno = EINVAL; - return -1; + return -EINVAL; } *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, digest, 0); *p = OSSL_PARAM_construct_end(); - if (!EVP_MAC_init(mac_ctx, secret, key_len, params)) { - errno = ENOKEY; - return -1; - } + if (!EVP_MAC_init(mac_ctx, secret, key_len, params)) + return -ENOKEY; if (!EVP_MAC_update(mac_ctx, (unsigned char *)hostnqn, - strlen(hostnqn))) { - errno = ENOKEY; - return -1; - } + strlen(hostnqn))) + return -ENOKEY; if (!EVP_MAC_update(mac_ctx, (unsigned char *)hmac_seed, - strlen(hmac_seed))) { - errno = ENOKEY; - return -1; - } + strlen(hmac_seed))) + return -ENOKEY; - if (!EVP_MAC_final(mac_ctx, key, &len, key_len)) { - errno = ENOKEY; - return -1; - } + if (!EVP_MAC_final(mac_ctx, key, &len, key_len)) + return -ENOKEY; - if (len != key_len) { - errno = EMSGSIZE; - return -1; - } + if (len != key_len) + return -EMSGSIZE; return 0; } @@ -1221,21 +1181,17 @@ static int derive_psk_digest(const char *hostnqn, const char *subsysnqn, size_t len; lib_ctx = OSSL_LIB_CTX_new(); - if (!lib_ctx) { - errno = ENOMEM; - return -1; - } + if (!lib_ctx) + return -ENOMEM; + mac = EVP_MAC_fetch(lib_ctx, OSSL_MAC_NAME_HMAC, progq); - if (!mac) { - errno = ENOMEM; - return -1; - } + if (!mac) + return -ENOMEM; mac_ctx = EVP_MAC_CTX_new(mac); - if (!mac_ctx) { - errno = ENOMEM; - return -1; - } + if (!mac_ctx) + return -ENOMEM; + switch (cipher) { case NVME_HMAC_ALG_SHA2_256: dig = OSSL_DIGEST_NAME_SHA2_256; @@ -1244,66 +1200,52 @@ static int derive_psk_digest(const char *hostnqn, const char *subsysnqn, dig = OSSL_DIGEST_NAME_SHA2_384; break; default: - errno = EINVAL; - break; + return -EINVAL; } - if (!dig) - return -1; + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, dig, 0); *p = OSSL_PARAM_construct_end(); psk_ctx = malloc(key_len); - if (!psk_ctx) { - errno = ENOMEM; - return -1; - } + if (!psk_ctx) + return -ENOMEM; + + if (!EVP_MAC_init(mac_ctx, retained, key_len, params)) + return -ENOKEY; - if (!EVP_MAC_init(mac_ctx, retained, key_len, params)) { - errno = ENOKEY; - return -1; - } if (!EVP_MAC_update(mac_ctx, (unsigned char *)hostnqn, - strlen(hostnqn))) { - errno = ENOKEY; - return -1; - } - if (!EVP_MAC_update(mac_ctx, (unsigned char *)" ", 1)) { - errno = ENOKEY; - return -1; - } + strlen(hostnqn))) + return -ENOKEY; + + if (!EVP_MAC_update(mac_ctx, (unsigned char *)" ", 1)) + return -ENOKEY; + if (!EVP_MAC_update(mac_ctx, (unsigned char *)subsysnqn, - strlen(subsysnqn))) { - errno = ENOKEY; - return -1; - } - if (!EVP_MAC_update(mac_ctx, (unsigned char *)" ", 1)) { - errno = ENOKEY; - return -1; - } + strlen(subsysnqn))) + return -ENOKEY; + + if (!EVP_MAC_update(mac_ctx, (unsigned char *)" ", 1)) + return -ENOKEY; + if (!EVP_MAC_update(mac_ctx, (unsigned char *)hmac_seed, - strlen(hmac_seed))) { - errno = ENOKEY; - return -1; - } - if (!EVP_MAC_final(mac_ctx, psk_ctx, &hmac_len, key_len)) { - errno = ENOKEY; - return -1; - } - if (hmac_len > key_len) { - errno = EMSGSIZE; - return -1; - } - if (hmac_len * 2 > digest_len) { - errno = EINVAL; - return -1; - } + strlen(hmac_seed))) + return -ENOKEY; + + if (!EVP_MAC_final(mac_ctx, psk_ctx, &hmac_len, key_len)) + return -ENOKEY; + + if (hmac_len > key_len) + return -EMSGSIZE; + + if (hmac_len * 2 > digest_len) + return -EINVAL; + memset(digest, 0, digest_len); len = base64_encode(psk_ctx, hmac_len, digest); - if (len < 0) { - errno = ENOKEY; + if (len < 0) return len; - } + return strlen(digest); } #endif /* !CONFIG_OPENSSL */ @@ -1317,10 +1259,8 @@ static int gen_tls_identity(const char *hostnqn, const char *subsysnqn, version, cipher, hostnqn, subsysnqn); return strlen(identity); } - if (version > 1 || !digest) { - errno = EINVAL; - return -1; - } + if (version > 1 || !digest) + return -EINVAL; sprintf(identity, "NVMe%01dR%02d %s %s %s", version, cipher, hostnqn, subsysnqn, digest); @@ -1338,16 +1278,13 @@ static int derive_nvme_keys(const char *hostnqn, const char *subsysnqn, unsigned char cipher; int ret = -1; - if (!hostnqn || !subsysnqn || !identity || !psk) { - errno = EINVAL; - return -1; - } + if (!hostnqn || !subsysnqn || !identity || !psk) + return -EINVAL; retained = malloc(key_len); - if (!retained) { - errno = ENOMEM; - return -1; - } + if (!retained) + return -ENOMEM; + if (compat) ret = derive_retained_key_compat(hmac, hostnqn, configured, retained, key_len); @@ -1366,10 +1303,9 @@ static int derive_nvme_keys(const char *hostnqn, const char *subsysnqn, size_t digest_len = 2 * key_len; digest = malloc(digest_len); - if (!digest) { - errno = ENOMEM; - return -1; - } + if (!digest) + return -ENOMEM; + ret = derive_psk_digest(hostnqn, subsysnqn, version, cipher, retained, key_len, digest, digest_len); @@ -1393,10 +1329,8 @@ static ssize_t nvme_identity_len(int hmac, int version, const char *hostnqn, { ssize_t len; - if (!hostnqn || !subsysnqn) { - errno = EINVAL; - return -1; - } + if (!hostnqn || !subsysnqn) + return -EINVAL; len = strlen(hostnqn) + strlen(subsysnqn) + 12; if (version == 1) { @@ -1404,90 +1338,87 @@ static ssize_t nvme_identity_len(int hmac, int version, const char *hostnqn, if (hmac == NVME_HMAC_ALG_SHA2_384) len += 32; } else if (version > 1) { - errno = EINVAL; - return -1; + return -EINVAL; } return len; } -char *nvme_generate_tls_key_identity(const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len) +int nvme_generate_tls_key_identity(const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + char **ident) { _cleanup_free_ unsigned char *psk = NULL; - char *identity; + _cleanup_free_ char *identity = NULL; ssize_t identity_len; - int ret = -1; + int ret; identity_len = nvme_identity_len(hmac, version, hostnqn, subsysnqn); - if (identity_len < 0) { - errno = EINVAL; - return NULL; - } + if (identity_len < 0) + return -EINVAL; identity = malloc(identity_len); - if (!identity) { - errno = ENOMEM; - return NULL; - } + if (!identity) + return -ENOMEM; psk = malloc(key_len); - if (!psk) { - errno = ENOMEM; - goto out_free_identity; - } + if (!psk) + return -ENOMEM; memset(psk, 0, key_len); ret = derive_nvme_keys(hostnqn, subsysnqn, identity, version, hmac, configured_key, psk, key_len, false); -out_free_identity: - if (ret < 0) { - free(identity); - identity = NULL; + if (ret != key_len) { + if (ret < 0) + return ret; + return -ENOKEY; } - return identity; + + *ident = identity; + identity = NULL; + + return 0; } -char *nvme_generate_tls_key_identity_compat(const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len) +int nvme_generate_tls_key_identity_compat(const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + char **ident) { _cleanup_free_ unsigned char *psk = NULL; - char *identity; + _cleanup_free_ char *identity = NULL; ssize_t identity_len; - int ret = -1; + int ret; identity_len = nvme_identity_len(hmac, version, hostnqn, subsysnqn); - if (identity_len < 0) { - errno = EINVAL; - return NULL; - } + if (identity_len < 0) + return -EINVAL; identity = malloc(identity_len); - if (!identity) { - errno = ENOMEM; - return NULL; - } + if (!identity) + return -ENOMEM; psk = malloc(key_len); - if (!psk) { - errno = ENOMEM; - goto out_free_identity; - } + if (!psk) + return -ENOMEM; memset(psk, 0, key_len); ret = derive_nvme_keys(hostnqn, subsysnqn, identity, version, hmac, configured_key, psk, key_len, true); -out_free_identity: - if (ret < 0) { - free(identity); - identity = NULL; + if (ret != key_len) { + if (ret < 0) + return ret; + return -ENOKEY; } - return identity; + + *ident = identity; + identity = NULL; + + return 0; } #ifdef CONFIG_KEYUTILS -long nvme_lookup_keyring(const char *keyring) +int nvme_lookup_keyring(const char *keyring, long *key) { key_serial_t keyring_id; @@ -1495,8 +1426,10 @@ long nvme_lookup_keyring(const char *keyring) keyring = NVME_TLS_DEFAULT_KEYRING; keyring_id = find_key_by_type_and_desc("keyring", keyring, 0); if (keyring_id < 0) - return 0; - return keyring_id; + return -errno; + + *key = keyring_id; + return 0; } char *nvme_describe_key_serial(long key_id) @@ -1518,13 +1451,13 @@ char *nvme_describe_key_serial(long key_id) return strdup(last); } -long nvme_lookup_key(const char *type, const char *identity) +int nvme_lookup_key(const char *type, const char *identity, long *keyp) { key_serial_t key; key = keyctl_search(KEY_SPEC_SESSION_KEYRING, type, identity, 0); if (key < 0) - return 0; + return -errno; return key; } @@ -1533,55 +1466,53 @@ int nvme_set_keyring(long key_id) long err; if (key_id == 0) { - key_id = nvme_lookup_keyring(NULL); - if (key_id == 0) { - errno = ENOKEY; - return -1; - } + if (nvme_lookup_keyring(NULL, &key_id)) + return -ENOKEY; } err = keyctl_link(key_id, KEY_SPEC_SESSION_KEYRING); if (err < 0) - return -1; + return -errno; return 0; } -unsigned char *nvme_read_key(long keyring_id, long key_id, int *len) +int nvme_read_key(long keyring_id, long key_id, int *len, + unsigned char **key) { void *buffer; int ret; ret = nvme_set_keyring(keyring_id); - if (ret < 0) { - errno = -ret; - return NULL; - } + if (ret < 0) + return ret; + ret = keyctl_read_alloc(key_id, &buffer); - if (ret < 0) { - errno = -ret; - buffer = NULL; - } else - *len = ret; + if (ret < 0) + return ret; - return buffer; + *len = ret; + *key = buffer; + return 0; } -long nvme_update_key(long keyring_id, const char *key_type, - const char *identity, unsigned char *key_data, - int key_len) +int nvme_update_key(long keyring_id, const char *key_type, + const char *identity, unsigned char *key_data, + int key_len, long *keyp) { long key; key = keyctl_search(keyring_id, key_type, identity, 0); if (key > 0) { if (keyctl_revoke(key) < 0) - return 0; + return -errno; } key = add_key(key_type, identity, key_data, key_len, keyring_id); if (key < 0) - key = 0; - return key; + return -errno; + + *keyp = key; + return 0; } struct __scan_keys_data { @@ -1627,13 +1558,16 @@ int nvme_scan_tls_keys(const char *keyring, nvme_scan_tls_keys_cb_t cb, void *data) { struct __scan_keys_data d; - key_serial_t keyring_id = nvme_lookup_keyring(keyring); + long keyring_id; int ret; - if (!keyring_id) { - errno = EINVAL; - return -1; - } + ret = nvme_lookup_keyring(keyring, &keyring_id); + if (ret) + return ret; + + if (!keyring_id) + return -EINVAL; + ret = nvme_set_keyring(keyring_id); if (ret < 0) return ret; @@ -1645,125 +1579,130 @@ int nvme_scan_tls_keys(const char *keyring, nvme_scan_tls_keys_cb_t cb, return ret; } -static long __nvme_insert_tls_key(key_serial_t keyring_id, const char *key_type, - const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len, - bool compat) +static int __nvme_insert_tls_key(key_serial_t keyring_id, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + bool compat, long *keyp) { _cleanup_free_ unsigned char *psk = NULL; _cleanup_free_ char *identity = NULL; ssize_t identity_len; - key_serial_t key; + long key; int ret; identity_len = nvme_identity_len(hmac, version, hostnqn, subsysnqn); if (identity_len < 0) - return 0; + return identity_len; identity = malloc(identity_len); - if (!identity) { - errno = ENOMEM; - return 0; - } + if (!identity) + return -ENOMEM; memset(identity, 0, identity_len); psk = malloc(key_len); - if (!psk) { - errno = ENOMEM; - return 0; - } + if (!psk) + return -ENOMEM; memset(psk, 0, key_len); ret = derive_nvme_keys(hostnqn, subsysnqn, identity, version, hmac, configured_key, psk, key_len, compat); if (ret != key_len) { - errno = ENOKEY; - return 0; + if (ret < 0) + return ret; + return -ENOKEY; } - key = nvme_update_key(keyring_id, key_type, identity, - psk, key_len); - return key; + ret = nvme_update_key(keyring_id, key_type, identity, + psk, key_len, &key); + if (ret) + return ret; + + *keyp = key; + return 0; } -long nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, - const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len) +int nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + long *key) { - key_serial_t keyring_id; + long keyring_id; int ret; - keyring_id = nvme_lookup_keyring(keyring); - if (keyring_id == 0) { - errno = ENOKEY; - return 0; - } + ret = nvme_lookup_keyring(keyring, &keyring_id); + if (ret) + return ret; ret = nvme_set_keyring(keyring_id); if (ret < 0) return 0; + return __nvme_insert_tls_key(keyring_id, key_type, hostnqn, subsysnqn, version, hmac, - configured_key, key_len, false); + configured_key, key_len, false, key); } -long nvme_insert_tls_key_compat(const char *keyring, const char *key_type, - const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len) +int nvme_insert_tls_key_compat(const char *keyring, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + long *key) { - key_serial_t keyring_id; + long keyring_id; int ret; - keyring_id = nvme_lookup_keyring(keyring); - if (keyring_id == 0) { - errno = ENOKEY; - return 0; - } + ret = nvme_lookup_keyring(keyring, &keyring_id); + if (ret) + return ret; ret = nvme_set_keyring(keyring_id); if (ret < 0) return 0; + return __nvme_insert_tls_key(keyring_id, key_type, hostnqn, subsysnqn, version, hmac, - configured_key, key_len, true); + configured_key, key_len, true, key); } -long nvme_revoke_tls_key(const char *keyring, const char *key_type, - const char *identity) +int nvme_revoke_tls_key(const char *keyring, const char *key_type, + const char *identity) { - key_serial_t keyring_id; - long key; + long keyring_id, key; + int ret; - keyring_id = nvme_lookup_keyring(keyring); - if (keyring_id == 0) { - errno = ENOKEY; - return 0; - } + ret = nvme_lookup_keyring(keyring, &keyring_id); + if (ret) + return ret; key = keyctl_search(keyring_id, key_type, identity, 0); if (key < 0) - return -1; + return -errno; + + key = keyctl_revoke(key); + if (key < 0) + return -errno; - return keyctl_revoke(key); + return 0; } -static long __nvme_import_tls_key(long keyring_id, - const char *hostnqn, const char *subsysnqn, - const char *identity, const char *key) +static int __nvme_import_tls_key(long keyring_id, + const char *hostnqn, const char *subsysnqn, + const char *identity, const char *key, + long *keyp) { _cleanup_free_ unsigned char *key_data = NULL; unsigned char version; unsigned char hmac; size_t key_len; + int ret; - key_data = nvme_import_tls_key_versioned(key, &version, - &hmac, &key_len); - if (!key_data) - return -EINVAL; + ret = nvme_import_tls_key_versioned(key, &version, + &hmac, &key_len, &key_data); + if (ret) + return ret; if (hmac == NVME_HMAC_ALG_NONE || !identity) { /* @@ -1775,11 +1714,11 @@ static long __nvme_import_tls_key(long keyring_id, return __nvme_insert_tls_key(keyring_id, "psk", hostnqn, subsysnqn, version, hmac, - key_data, key_len, false); + key_data, key_len, false, keyp); } return nvme_update_key(keyring_id, "psk", identity, - key_data, key_len); + key_data, key_len, keyp); } int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c, @@ -1789,9 +1728,10 @@ int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c, const char *subsysnqn = nvme_ctrl_get_subsysnqn(c); const char *keyring, *key, *identity; long kr_id = 0, id = 0; + int ret; if (!hostnqn || !subsysnqn) { - nvme_msg(h->r, LOG_ERR, "Invalid NQNs (%s, %s)\n", + nvme_msg(h->ctx, LOG_ERR, "Invalid NQNs (%s, %s)\n", hostnqn, subsysnqn); return -EINVAL; } @@ -1803,9 +1743,9 @@ int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c, keyring = nvme_ctrl_get_keyring(c); if (keyring) { - kr_id = nvme_lookup_keyring(keyring); - if (kr_id == 0) - return -errno; + ret = nvme_lookup_keyring(keyring, &kr_id); + if (ret) + return ret; } else kr_id = c->cfg.keyring; @@ -1815,28 +1755,35 @@ int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c, * That means we are explicitly selecting the keyring. */ if (!kr_id) { - kr_id = nvme_lookup_keyring(".nvme"); - if (kr_id == 0) - return -errno; + ret = nvme_lookup_keyring(".nvme", &kr_id); + if (ret) + return ret; } if (nvme_set_keyring(kr_id) < 0) { - nvme_msg(h->r, LOG_ERR, "Failed to set keyring\n"); + nvme_msg(h->ctx, LOG_ERR, "Failed to set keyring\n"); return -errno; } identity = nvme_ctrl_get_tls_key_identity(c); - if (identity) - id = nvme_lookup_key("psk", identity); - - if (!id) - id = __nvme_import_tls_key(kr_id, hostnqn, - subsysnqn, identity, key); + if (identity) { + ret = nvme_lookup_key("psk", identity, &id); + if (ret) { + nvme_msg(h->ctx, LOG_ERR, + "Failed to lookup key for identity %s, error %d\n", + identity, ret); + return ret; + } + } - if (id <= 0) { - nvme_msg(h->r, LOG_ERR, "Failed to insert TLS KEY, error %d\n", - errno); - return -errno; + if (!id) { + ret = __nvme_import_tls_key(kr_id, hostnqn, + subsysnqn, identity, key, &id); + if (ret) { + nvme_msg(h->ctx, LOG_ERR, + "Failed to insert TLS KEY, error %d\n", ret); + return ret; + } } out: @@ -1846,88 +1793,81 @@ int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c, return 0; } #else -long nvme_lookup_keyring(const char *keyring) +int nvme_lookup_keyring(const char *keyring, long *key) { nvme_msg(NULL, LOG_ERR, "key operations not supported; "\ "recompile with keyutils support.\n"); - errno = ENOTSUP; - return 0; + return -ENOTSUP; } char *nvme_describe_key_serial(long key_id) { nvme_msg(NULL, LOG_ERR, "key operations not supported; "\ "recompile with keyutils support.\n"); - errno = ENOTSUP; return NULL; } -long nvme_lookup_key(const char *type, const char *identity) +int nvme_lookup_key(const char *type, const char *identity, long *key) { nvme_msg(NULL, LOG_ERR, "key operations not supported; "\ "recompile with keyutils support.\n"); - errno = ENOTSUP; - return 0; + return -ENOTSUP; } int nvme_set_keyring(long key_id) { nvme_msg(NULL, LOG_ERR, "key operations not supported; "\ "recompile with keyutils support.\n"); - errno = ENOTSUP; - return -1; + return -ENOTSUP; } -unsigned char *nvme_read_key(long keyring_id, long key_id, int *len) +int nvme_read_key(long keyring_id, long key_id, int *len, + unsigned char **key) { - errno = ENOTSUP; - return NULL; + return -ENOTSUP; } -long nvme_update_key(long keyring_id, const char *key_type, +int nvme_update_key(long keyring_id, const char *key_type, const char *identity, unsigned char *key_data, - int key_len) + int key_len, long *key) { - errno = ENOTSUP; - return 0; + return -ENOTSUP; } int nvme_scan_tls_keys(const char *keyring, nvme_scan_tls_keys_cb_t cb, void *data) { - errno = ENOTSUP; - return -1; + return -ENOTSUP; } -long nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, - const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len) +int nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + long *keyp) { nvme_msg(NULL, LOG_ERR, "key operations not supported; " "recompile with keyutils support.\n"); - errno = ENOTSUP; - return -1; + return -ENOTSUP; } -long nvme_insert_tls_key_compat(const char *keyring, const char *key_type, - const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len) +int nvme_insert_tls_key_compat(const char *keyring, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + long *keyp) { nvme_msg(NULL, LOG_ERR, "key operations not supported; " "recompile with keyutils support.\n"); - errno = ENOTSUP; - return -1; + return -ENOTSUP; } -long nvme_revoke_tls_key(const char *keyring, const char *key_type, - const char *identity) +int nvme_revoke_tls_key(const char *keyring, const char *key_type, + const char *identity) { nvme_msg(NULL, LOG_ERR, "key operations not supported; " "recompile with keyutils support.\n"); - errno = ENOTSUP; - return -1; + return -ENOTSUP; } int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c, @@ -1940,13 +1880,13 @@ int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c, } #endif -long nvme_insert_tls_key(const char *keyring, const char *key_type, +int nvme_insert_tls_key(const char *keyring, const char *key_type, const char *hostnqn, const char *subsysnqn, int hmac, - unsigned char *configured_key, int key_len) + unsigned char *configured_key, int key_len, long *key) { return nvme_insert_tls_key_versioned(keyring, key_type, hostnqn, subsysnqn, 0, hmac, - configured_key, key_len); + configured_key, key_len, key); } /* @@ -1961,9 +1901,9 @@ long nvme_insert_tls_key(const char *keyring, const char *key_type, * s: 32 or 48 bytes binary followed by a CRC-32 of the configured PSK * (4 bytes) encoded as base64 */ -char *nvme_export_tls_key_versioned(unsigned char version, unsigned char hmac, - const unsigned char *key_data, - size_t key_len) +int nvme_export_tls_key_versioned(unsigned char version, unsigned char hmac, + const unsigned char *key_data, + size_t key_len, char **encoded_keyp) { unsigned int raw_len, encoded_len, len; unsigned long crc = crc32(0L, NULL, 0); @@ -1973,18 +1913,18 @@ char *nvme_export_tls_key_versioned(unsigned char version, unsigned char hmac, switch (hmac) { case NVME_HMAC_ALG_NONE: if (key_len != 32 && key_len != 48) - goto err_inval; + return -EINVAL; break; case NVME_HMAC_ALG_SHA2_256: if (key_len != 32) - goto err_inval; + return -EINVAL; break; case NVME_HMAC_ALG_SHA2_384: if (key_len != 48) - goto err_inval; + return -EINVAL; break; default: - goto err_inval; + return -EINVAL; } raw_len = key_len; @@ -1997,25 +1937,20 @@ char *nvme_export_tls_key_versioned(unsigned char version, unsigned char hmac, encoded_len = (raw_len * 2) + 20; encoded_key = malloc(encoded_len); - if (!encoded_key) { - errno = ENOMEM; - return NULL; - } + if (!encoded_key) + return -ENOMEM; + memset(encoded_key, 0, encoded_len); len = sprintf(encoded_key, "NVMeTLSkey-%x:%02x:", version, hmac); len += base64_encode(raw_secret, raw_len, encoded_key + len); encoded_key[len++] = ':'; encoded_key[len++] = '\0'; - return encoded_key; - -err_inval: - errno = EINVAL; - return NULL; - + *encoded_keyp = encoded_key; + return 0; } -char *nvme_export_tls_key(const unsigned char *key_data, int key_len) +int nvme_export_tls_key(const unsigned char *key_data, int key_len, char **key) { unsigned char hmac; @@ -2024,13 +1959,14 @@ char *nvme_export_tls_key(const unsigned char *key_data, int key_len) else hmac = NVME_HMAC_ALG_SHA2_384; - return nvme_export_tls_key_versioned(1, hmac, key_data, key_len); + return nvme_export_tls_key_versioned(1, hmac, key_data, key_len, key); } -unsigned char *nvme_import_tls_key_versioned(const char *encoded_key, - unsigned char *version, - unsigned char *hmac, - size_t *key_len) +int nvme_import_tls_key_versioned(const char *encoded_key, + unsigned char *version, + unsigned char *hmac, + size_t *key_len, + unsigned char **keyp) { unsigned char decoded_key[128], *key_data; unsigned int crc = crc32(0L, NULL, 0); @@ -2039,48 +1975,42 @@ unsigned char *nvme_import_tls_key_versioned(const char *encoded_key, size_t len; if (sscanf(encoded_key, "NVMeTLSkey-%d:%02x:*s", - &_version, &_hmac) != 2) { - errno = EINVAL; - return NULL; - } + &_version, &_hmac) != 2) + return -EINVAL; + + if (_version != 1) + return -EINVAL; - if (_version != 1) { - errno = EINVAL; - return NULL; - } *version = _version; len = strlen(encoded_key); switch (_hmac) { case NVME_HMAC_ALG_NONE: if (len != 65 && len != 89) - goto err_inval; + return -EINVAL; break; case NVME_HMAC_ALG_SHA2_256: if (len != 65) - goto err_inval; + return -EINVAL; break; case NVME_HMAC_ALG_SHA2_384: if (len != 89) - goto err_inval; + return -EINVAL; break; default: - errno = EINVAL; - return NULL; + return -EINVAL; } *hmac = _hmac; err = base64_decode(encoded_key + 16, len - 17, decoded_key); - if (err < 0) { - errno = ENOKEY; - return NULL; - } + if (err < 0) + return -ENOKEY; + decoded_len = err; decoded_len -= 4; - if (decoded_len != 32 && decoded_len != 48) { - errno = ENOKEY; - return NULL; - } + if (decoded_len != 32 && decoded_len != 48) + return -ENOKEY; + crc = crc32(crc, decoded_key, decoded_len); key_crc = ((uint32_t)decoded_key[decoded_len]) | ((uint32_t)decoded_key[decoded_len + 1] << 8) | @@ -2089,38 +2019,34 @@ unsigned char *nvme_import_tls_key_versioned(const char *encoded_key, if (key_crc != crc) { nvme_msg(NULL, LOG_ERR, "CRC mismatch (key %08x, crc %08x)", key_crc, crc); - errno = ENOKEY; - return NULL; + return -ENOKEY; } key_data = malloc(decoded_len); - if (!key_data) { - errno = ENOMEM; - return NULL; - } + if (!key_data) + return -ENOMEM; memcpy(key_data, decoded_key, decoded_len); *key_len = decoded_len; - return key_data; - -err_inval: - errno = EINVAL; - return NULL; + *keyp = key_data; + return 0; } -unsigned char *nvme_import_tls_key(const char *encoded_key, int *key_len, - unsigned int *hmac) +int nvme_import_tls_key(const char *encoded_key, int *key_len, + unsigned int *hmac, unsigned char **keyp) { unsigned char version, _hmac; unsigned char *psk; size_t len; + int ret; - psk = nvme_import_tls_key_versioned(encoded_key, &version, - &_hmac, &len); - if (!psk) - return NULL; + ret = nvme_import_tls_key_versioned(encoded_key, &version, + &_hmac, &len, &psk); + if (ret) + return ret; *hmac = _hmac; *key_len = len; - return psk; + *keyp = psk; + return 0; } diff --git a/libnvme/src/nvme/linux.h b/libnvme/src/nvme/linux.h index 38bea3cec3..6149c14339 100644 --- a/libnvme/src/nvme/linux.h +++ b/libnvme/src/nvme/linux.h @@ -10,6 +10,7 @@ #define _LIBNVME_LINUX_H #include +#include #include #include @@ -22,65 +23,65 @@ /** * nvme_fw_download_seq() - Firmware download sequence - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @size: Total size of the firmware image to transfer * @xfer: Maximum size to send with each partial transfer * @offset: Starting offset to send with this firmware download * @buf: Address of buffer containing all or part of the firmware image. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_fw_download_seq(int fd, __u32 size, __u32 xfer, __u32 offset, +int nvme_fw_download_seq(struct nvme_transport_handle *hdl, __u32 size, __u32 xfer, __u32 offset, void *buf); /** * nvme_set_etdas() - Set the Extended Telemetry Data Area 4 Supported bit - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @changed: boolean to indicate whether or not the host * behavior support feature had been changed * * Return: The nvme command status if a response was received (see * &enum nvme_status_field) or -1 with errno set otherwise. */ -int nvme_set_etdas(int fd, bool *changed); +int nvme_set_etdas(struct nvme_transport_handle *hdl, bool *changed); /** * nvme_clear_etdas() - Clear the Extended Telemetry Data Area 4 Supported bit - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @changed: boolean to indicate whether or not the host * behavior support feature had been changed * * Return: The nvme command status if a response was received (see * &enum nvme_status_field) or -1 with errno set otherwise. */ -int nvme_clear_etdas(int fd, bool *changed); +int nvme_clear_etdas(struct nvme_transport_handle *hdl, bool *changed); /** * nvme_get_uuid_list - Returns the uuid list (if supported) - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @uuid_list: UUID list returned by identify UUID * * Return: The nvme command status if a response was received (see * &enum nvme_status_field) or -1 with errno set otherwise. */ -int nvme_get_uuid_list(int fd, +int nvme_get_uuid_list(struct nvme_transport_handle *hdl, struct nvme_id_uuid_list *uuid_list); /** * nvme_get_telemetry_max() - Get telemetry limits - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @da: On success return max supported data area * @max_data_tx: On success set to max transfer chunk supported by the controller * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_get_telemetry_max(int fd, enum nvme_telemetry_da *da, size_t *max_data_tx); +int nvme_get_telemetry_max(struct nvme_transport_handle *hdl, enum nvme_telemetry_da *da, size_t *max_data_tx); /** * nvme_get_telemetry_log() - Get specified telemetry log - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @create: Generate new host initated telemetry capture * @ctrl: Get controller Initiated log * @rae: Retain asynchronous events @@ -92,15 +93,15 @@ int nvme_get_telemetry_max(int fd, enum nvme_telemetry_da *da, size_t *max_data_ * The total size allocated can be calculated as: * (nvme_telemetry_log da size + 1) * NVME_LOG_TELEM_BLOCK_SIZE. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_get_telemetry_log(int fd, bool create, bool ctrl, bool rae, size_t max_data_tx, +int nvme_get_telemetry_log(struct nvme_transport_handle *hdl, bool create, bool ctrl, bool rae, size_t max_data_tx, enum nvme_telemetry_da da, struct nvme_telemetry_log **log, size_t *size); /** * nvme_get_ctrl_telemetry() - Get controller telemetry log - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @rae: Retain asynchronous events * @log: On success, set to the value of the allocated and retrieved log. * @da: Log page data area, valid values: &enum nvme_telemetry_da @@ -109,15 +110,15 @@ int nvme_get_telemetry_log(int fd, bool create, bool ctrl, bool rae, size_t max_ * The total size allocated can be calculated as: * (nvme_telemetry_log da size + 1) * NVME_LOG_TELEM_BLOCK_SIZE. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_get_ctrl_telemetry(int fd, bool rae, struct nvme_telemetry_log **log, +int nvme_get_ctrl_telemetry(struct nvme_transport_handle *hdl, bool rae, struct nvme_telemetry_log **log, enum nvme_telemetry_da da, size_t *size); /** * nvme_get_host_telemetry() - Get host telemetry log - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @log: On success, set to the value of the allocated and retrieved log. * @da: Log page data area, valid values: &enum nvme_telemetry_da * @size: Ptr to the telemetry log size, so it can be returned @@ -125,15 +126,15 @@ int nvme_get_ctrl_telemetry(int fd, bool rae, struct nvme_telemetry_log **log, * The total size allocated can be calculated as: * (nvme_telemetry_log da size + 1) * NVME_LOG_TELEM_BLOCK_SIZE. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_get_host_telemetry(int fd, struct nvme_telemetry_log **log, +int nvme_get_host_telemetry(struct nvme_transport_handle *hdl, struct nvme_telemetry_log **log, enum nvme_telemetry_da da, size_t *size); /** * nvme_get_new_host_telemetry() - Get new host telemetry log - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @log: On success, set to the value of the allocated and retrieved log. * @da: Log page data area, valid values: &enum nvme_telemetry_da * @size: Ptr to the telemetry log size, so it can be returned @@ -141,10 +142,10 @@ int nvme_get_host_telemetry(int fd, struct nvme_telemetry_log **log, * The total size allocated can be calculated as: * (nvme_telemetry_log da size + 1) * NVME_LOG_TELEM_BLOCK_SIZE. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_get_new_host_telemetry(int fd, struct nvme_telemetry_log **log, +int nvme_get_new_host_telemetry(struct nvme_transport_handle *hdl, struct nvme_telemetry_log **log, enum nvme_telemetry_da da, size_t *size); /** @@ -159,71 +160,132 @@ size_t nvme_get_ana_log_len_from_id_ctrl(const struct nvme_id_ctrl *id_ctrl, /** * nvme_get_ana_log_len() - Retrieve size of the current ANA log - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @analen: Pointer to where the length will be set on success * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_get_ana_log_len(int fd, size_t *analen); +int nvme_get_ana_log_len(struct nvme_transport_handle *hdl, size_t *analen); /** * nvme_get_logical_block_size() - Retrieve block size - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @nsid: Namespace id * @blksize: Pointer to where the block size will be set on success * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_get_logical_block_size(int fd, __u32 nsid, int *blksize); +int nvme_get_logical_block_size(struct nvme_transport_handle *hdl, __u32 nsid, int *blksize); /** * nvme_get_lba_status_log() - Retrieve the LBA Status log page - * @fd: File descriptor of the nvme device + * @hdl: Transport handle * @rae: Retain asynchronous events * @log: On success, set to the value of the allocated and retrieved log. * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_get_lba_status_log(int fd, bool rae, struct nvme_lba_status_log **log); +int nvme_get_lba_status_log(struct nvme_transport_handle *hdl, bool rae, struct nvme_lba_status_log **log); /** * nvme_namespace_attach_ctrls() - Attach namespace to controller(s) - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @nsid: Namespace ID to attach * @num_ctrls: Number of controllers in ctrlist * @ctrlist: List of controller IDs to perform the attach action * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_namespace_attach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); +int nvme_namespace_attach_ctrls(struct nvme_transport_handle *hdl, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); /** * nvme_namespace_detach_ctrls() - Detach namespace from controller(s) - * @fd: File descriptor of nvme device + * @hdl: Transport handle * @nsid: Namespace ID to detach * @num_ctrls: Number of controllers in ctrlist * @ctrlist: List of controller IDs to perform the detach action * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. + * Return: 0 on success, the nvme command status if a response was + * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_namespace_detach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); +int nvme_namespace_detach_ctrls(struct nvme_transport_handle *hdl, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); /** * nvme_open() - Open an nvme controller or namespace device + * @ctx: struct nvme_global_ctx object * @name: The basename of the device to open + * @hdl: Transport handle to return * * This will look for the handle in /dev/ and validate the name and filetype * match linux conventions. * - * Return: A file descriptor for the device on a successful open, or -1 with - * errno set otherwise. + * Return: 0 on success or negative error code otherwise + */ +int nvme_open(struct nvme_global_ctx *ctx, const char *name, + struct nvme_transport_handle **hdl); + +/** + * nvme_close() - Close transport handle + * @hdl: Transport handle + */ +void nvme_close(struct nvme_transport_handle *hdl); + +/** + * nvme_transport_handle_get_fd - Return file descriptor from transport handle + * @hdl: Transport handle + * + * If the device handle is for a ioctl based device, + * nvme_transport_handle_get_fd will return a valid file descriptor. + * + * Return: File descriptor for an IOCTL based transport handle, otherwise -1. + */ +int nvme_transport_handle_get_fd(struct nvme_transport_handle *hdl); + +/** + * nvme_transport_handle_get_name - Return name of the device transport handle + * @hdl: Transport handle + * + * Return: Device file name, otherwise -1. */ -int nvme_open(const char *name); +const char *nvme_transport_handle_get_name(struct nvme_transport_handle *hdl); + +/** + * nvme_transport_handle_is_blkdev - Check if transport handle is a block device + * @hdl: Transport handle + * + * Return: Return true if transport handle is a block device, otherwise false. + */ +bool nvme_transport_handle_is_blkdev(struct nvme_transport_handle *hdl); + +/** + * nvme_transport_handle_is_chardev - Check if transport handle is a char device + * @hdl: Transport handle + * + * Return: Return true if transport handle is a char device, otherwise false. + */ +bool nvme_transport_handle_is_chardev(struct nvme_transport_handle *hdl); + +/** + * nvme_transport_handle_is_direct - Check if transport handle is using IOCTL interface + * @hdl: Transport handle + * + * Return: Return true if transport handle is using IOCTL itnerface, + * otherwise false. + */ +bool nvme_transport_handle_is_direct(struct nvme_transport_handle *hdl); + +/** + * nvme_transport_handle_is_mi - Check if transport handle is a using MI interface + * @hdl: Transport handle + * + * Return: Return true if transport handle is using MI interface, + * otherwise false. + */ +bool nvme_transport_handle_is_mi(struct nvme_transport_handle *hdl); /** * enum nvme_hmac_alg - HMAC algorithm @@ -248,7 +310,7 @@ enum nvme_hmac_alg { * @key: Generated DH-HMAC-CHAP key * * Return: If key generation was successful the function returns 0 or - * -1 with errno set otherwise. + * a negative error code otherwise. */ int nvme_gen_dhchap_key(char *hostnqn, enum nvme_hmac_alg hmac, unsigned int key_len, unsigned char *secret, @@ -257,13 +319,13 @@ int nvme_gen_dhchap_key(char *hostnqn, enum nvme_hmac_alg hmac, /** * nvme_lookup_keyring() - Lookup keyring serial number * @keyring: Keyring name + * @key: Key serial number to return * * Looks up the serial number of the keyring @keyring. * - * Return: The key serial number of the keyring - * or 0 with errno set otherwise. + * Return: 0 on success or negative error code otherwise */ -long nvme_lookup_keyring(const char *keyring); +int nvme_lookup_keyring(const char *keyring, long *key); /** * nvme_describe_key_serial() - Return key description @@ -279,16 +341,16 @@ char *nvme_describe_key_serial(long key_id); /** * nvme_lookup_key() - Lookup key serial number - * @type: Key type - * @identity: Key description + * @type: Key type + * @identity: Key description + * @key: Key serial number to return * * Looks up the serial number of the key @identity * with type %type in the current session keyring. * - * Return: The key serial number of the key - * or 0 with errno set otherwise. + * Return: 0 on success or negative error code otherwise */ -long nvme_lookup_key(const char *type, const char *identity); +int nvme_lookup_key(const char *type, const char *identity, long *key); /** * nvme_set_keyring() - Link keyring for lookup @@ -297,45 +359,46 @@ long nvme_lookup_key(const char *type, const char *identity); * Links @keyring_id into the session keyring such that * its keys are available for further key lookups. * - * Return: 0 on success, a negative number on error - * with errno set. + * Return: 0 on success or negative error code otherwise */ int nvme_set_keyring(long keyring_id); /** * nvme_read_key() - Read key raw data - * @keyring_id: Id of the keyring holding %key_id - * @key_id: Key id - * @len: Length of the returned data + * @keyring_id: Id of the keyring holding %key_id + * @key_id: Key id + * @len: Length of the returned data + * @key: Key serial to return * * Links the keyring specified by @keyring_id into the session * keyring and reads the payload of the key specified by @key_id. * @len holds the size of the returned buffer. * If @keyring is 0 the default keyring '.nvme' is used. * - * Return: Pointer to the payload on success, - * or NULL with errno set otherwise. + * Return: 0 on success or negative error code otherwise */ -unsigned char *nvme_read_key(long keyring_id, long key_id, int *len); +int nvme_read_key(long keyring_id, long key_id, int *len, + unsigned char **key); /** * nvme_update_key() - Update key raw data - * @keyring_id: Id of the keyring holding %key_id - * @key_type: Type of the key to insert - * @identity: Key identity string - * @key_data: Raw data of the key - * @key_len: Length of @key_data + * @keyring_id: Id of the keyring holding %key_id + * @key_type: Type of the key to insert + * @identity: Key identity string + * @key_data: Raw data of the key + * @key_len: Length of @key_data + * @key: Key serial to return * * Links the keyring specified by @keyring_id into the session * keyring and updates the key reference by @identity with @key_data. * The old key with identity @identity will be revoked to make it * inaccessible. * - * Return: Key id of the new key or 0 with errno set otherwise. + * Return: 0 on success or negative error code otherwise */ -long nvme_update_key(long keyring_id, const char *key_type, - const char *identity, unsigned char *key_data, - int key_len); +int nvme_update_key(long keyring_id, const char *key_type, + const char *identity, unsigned char *key_data, + int key_len, long *key); /** * typedef nvme_scan_tls_keys_cb_t - Callback for iterating TLS keys @@ -362,31 +425,30 @@ typedef void (*nvme_scan_tls_keys_cb_t)(long keyring, long key, * form 'NVMe<0|1>0<1|2> ', otherwise it will be skipped * during iteration. * - * Return: Number of keys for which @cb was called, or -1 with errno set - * on error. + * Return: Number of keys for which @cb was called, or negative error code */ int nvme_scan_tls_keys(const char *keyring, nvme_scan_tls_keys_cb_t cb, void *data); /** * nvme_insert_tls_key() - Derive and insert TLS key - * @keyring: Keyring to use + * @keyring: Keyring to use * @key_type: Type of the resulting key * @hostnqn: Host NVMe Qualified Name * @subsysnqn: Subsystem NVMe Qualified Name * @hmac: HMAC algorithm * @configured_key: Configured key data to derive the key from * @key_len: Length of @configured_key + * @key: Key serial to return * * Derives a 'retained' TLS key as specified in NVMe TCP 1.0a and * stores it as type @key_type in the keyring specified by @keyring. * - * Return: The key serial number if the key could be inserted into - * the keyring or 0 with errno otherwise. + * Return: 0 on success or negative error code otherwise */ -long nvme_insert_tls_key(const char *keyring, const char *key_type, +int nvme_insert_tls_key(const char *keyring, const char *key_type, const char *hostnqn, const char *subsysnqn, int hmac, - unsigned char *configured_key, int key_len); + unsigned char *configured_key, int key_len, long *key); /** * nvme_insert_tls_key_versioned() - Derive and insert TLS key @@ -398,18 +460,19 @@ long nvme_insert_tls_key(const char *keyring, const char *key_type, * @hmac: HMAC algorithm * @configured_key: Configured key data to derive the key from * @key_len: Length of @configured_key + * @key: Key serial to return * * Derives a 'retained' TLS key as specified in NVMe TCP 1.0a (if * @version s set to '0') or NVMe TP8028 (if @version is set to '1) and * stores it as type @key_type in the keyring specified by @keyring. * - * Return: The key serial number if the key could be inserted into - * the keyring or 0 with errno otherwise. + * Return: 0 on success or negative error code otherwise */ -long nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, - const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len); +int nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + long *key); /** * nvme_insert_tls_key_compat() - Derive and insert TLS key @@ -421,6 +484,7 @@ long nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, * @hmac: HMAC algorithm * @configured_key: Configured key data to derive the key from * @key_len: Length of @configured_key + * @key: Key serial to return * * Derives a 'retained' TLS key as specified in NVMe TCP 1.0a (if * @version s set to '0') or NVMe TP8028 (if @version is set to '1) and @@ -432,10 +496,11 @@ long nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, * Return: The key serial number if the key could be inserted into * the keyring or 0 with errno otherwise. */ -long nvme_insert_tls_key_compat(const char *keyring, const char *key_type, - const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len); +int nvme_insert_tls_key_compat(const char *keyring, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + long *key); /** * nvme_generate_tls_key_identity() - Generate the TLS key identity @@ -445,17 +510,19 @@ long nvme_insert_tls_key_compat(const char *keyring, const char *key_type, * @hmac: HMAC algorithm * @configured_key: Configured key data to derive the key from * @key_len: Length of @configured_key + * @identity: TLS identity to return * * Derives a 'retained' TLS key as specified in NVMe TCP and * generate the corresponding TLs identity. * - * Return: The string containing the TLS identity. It is the responsibility - * of the caller to free the returned string. On error NULL is returned with - * errno set. + * It is the responsibility of the caller to free the returned string. + * + * Return: 0 on success or negative error code otherwise */ -char *nvme_generate_tls_key_identity(const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len); +int nvme_generate_tls_key_identity(const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + char **identity); /** * nvme_generate_tls_key_identity_compat() - Generate the TLS key identity @@ -465,6 +532,7 @@ char *nvme_generate_tls_key_identity(const char *hostnqn, const char *subsysnqn, * @hmac: HMAC algorithm * @configured_key: Configured key data to derive the key from * @key_len: Length of @configured_key + * @identity: TLS identity to return * * Derives a 'retained' TLS key as specified in NVMe TCP and * generate the corresponding TLs identity. This version differs @@ -472,14 +540,15 @@ char *nvme_generate_tls_key_identity(const char *hostnqn, const char *subsysnqn, * implementation for HKDF-Expand-Label which does not prefix the 'info' * and 'label' string with the length. * - * Return: The string containing the TLS identity. It is the responsibility - * of the caller to free the returned string. + * It is the responsibility of the caller to free the returned string. + * + * Return: 0 on success or negative error code otherwise */ -char *nvme_generate_tls_key_identity_compat(const char *hostnqn, - const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, - int key_len); +int nvme_generate_tls_key_identity_compat(const char *hostnqn, + const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, + int key_len, char **identity); /** * nvme_revoke_tls_key() - Revoke TLS key from keyring @@ -487,24 +556,26 @@ char *nvme_generate_tls_key_identity_compat(const char *hostnqn, * @key_type: Type of the key to revoke * @identity: Key identity string * - * Return: 0 on success or on failure -1 with errno set. + * Return: 0 on success or negative error code otherwise */ -long nvme_revoke_tls_key(const char *keyring, const char *key_type, - const char *identity); +int nvme_revoke_tls_key(const char *keyring, const char *key_type, + const char *identity); /** * nvme_export_tls_key() - Export a TLS key * @key_data: Raw data of the key * @key_len: Length of @key_data + * @identity: TLS identity * * Returns @key_data in the PSK Interchange format as defined in section * 3.6.1.5 of the NVMe TCP Transport specification. * - * Return: The string containing the TLS identity or NULL with errno set - * on error. It is the responsibility of the caller to free the returned + * It is the responsibility of the caller to free the returned * string. + * + * Return: 0 on success or negative error code otherwise */ -char *nvme_export_tls_key(const unsigned char *key_data, int key_len); +int nvme_export_tls_key(const unsigned char *key_data, int key_len, char **identity); /** * nvme_export_tls_key_versioned() - Export a TLS pre-shared key @@ -513,32 +584,36 @@ char *nvme_export_tls_key(const unsigned char *key_data, int key_len); * in a retained PSK * @key_data: Raw data of the key * @key_len: Length of @key_data + * @identity: TLS identity to return * * Returns @key_data in the PSK Interchange format as defined in section * 3.6.1.5 of the NVMe TCP Transport specification. * - * Return: The string containing the TLS identity or NULL with errno set - * on error. It is the responsibility of the caller to free the returned + * It is the responsibility of the caller to free the returned * string. + * + * Return: 0 on success or negative error code otherwise */ -char *nvme_export_tls_key_versioned(unsigned char version, unsigned char hmac, - const unsigned char *key_data, - size_t key_len); +int nvme_export_tls_key_versioned(unsigned char version, unsigned char hmac, + const unsigned char *key_data, + size_t key_len, char **identity); /** * nvme_import_tls_key() - Import a TLS key * @encoded_key: TLS key in PSK interchange format * @key_len: Length of the resulting key data * @hmac: HMAC algorithm + * @key: Key serial to return * * Imports @key_data in the PSK Interchange format as defined in section * 3.6.1.5 of the NVMe TCP Transport specification. * - * Return: The raw data of the PSK or NULL with errno set on error. It is - * the responsibility of the caller to free the returned string. + * It is the responsibility of the caller to free the returned string. + * + * Return: 0 on success or negative error code otherwise */ -unsigned char *nvme_import_tls_key(const char *encoded_key, int *key_len, - unsigned int *hmac); +int nvme_import_tls_key(const char *encoded_key, int *key_len, + unsigned int *hmac, unsigned char **key); /** * nvme_import_tls_key_versioned() - Import a TLS key @@ -547,20 +622,23 @@ unsigned char *nvme_import_tls_key(const char *encoded_key, int *key_len, * @hmac: HMAC algorithm used to transfor the configured * PSK in a retained PSK * @key_len: Length of the resulting key data + * @key: Key serial to return * * Imports @key_data in the PSK Interchange format as defined in section * 3.6.1.5 of the NVMe TCP Transport specification. * - * Return: The raw data of the PSK or NULL with errno set on error. It is - * the responsibility of the caller to free the returned string. + * It is the responsibility of the caller to free the returned string. + * + * Return: 0 on success or negative error code otherwise */ -unsigned char *nvme_import_tls_key_versioned(const char *encoded_key, - unsigned char *version, - unsigned char *hmac, - size_t *key_len); +int nvme_import_tls_key_versioned(const char *encoded_key, + unsigned char *version, + unsigned char *hmac, + size_t *key_len, + unsigned char **key); /** * nvme_submit_passthru - Low level ioctl wrapper for passthru commands - * @fd: File descriptor of the nvme device + * @hdl: Transport handle * @ioctl_cmd: IOCTL command id * @cmd: Passhtru command * @result: Optional field to return the result @@ -569,15 +647,16 @@ unsigned char *nvme_import_tls_key_versioned(const char *encoded_key, * exposed as weak symbol so that the user application is able to provide their own * implementation of this function with additional debugging or logging code. * - * Return: The value from the ioctl system call (see ioctl documentation) + * Return: The value from the ioctl system call (see ioctl documentation) or + * a negative error code otherwise. */ __attribute__((weak)) -int nvme_submit_passthru(int fd, unsigned long ioctl_cmd, +int nvme_submit_passthru(struct nvme_transport_handle *hdl, unsigned long ioctl_cmd, struct nvme_passthru_cmd *cmd, __u32 *result); /** * nvme_submit_passthru64 - Low level ioctl wrapper for passthru commands - * @fd: File descriptor of the nvme device + * @hdl: Transport handle * @ioctl_cmd: IOCTL command id * @cmd: Passhtru command * @result: Optional field to return the result @@ -586,10 +665,11 @@ int nvme_submit_passthru(int fd, unsigned long ioctl_cmd, * exposed as weak symbol so that the user application is able to provide their own * implementation of this function with additional debugging or logging code. * - * Return: The value from the ioctl system call (see ioctl documentation) + * Return: The value from the ioctl system call (see ioctl documentation) or + * a negative error code otherwise. */ __attribute__((weak)) -int nvme_submit_passthru64(int fd, unsigned long ioctl_cmd, +int nvme_submit_passthru64(struct nvme_transport_handle *hdl, unsigned long ioctl_cmd, struct nvme_passthru_cmd64 *cmd, __u64 *result); diff --git a/libnvme/src/nvme/log.c b/libnvme/src/nvme/log.c index eaf74e1d0c..3cec7c2727 100644 --- a/libnvme/src/nvme/log.c +++ b/libnvme/src/nvme/log.c @@ -34,7 +34,7 @@ static struct nvme_log def_log = { }; void __attribute__((format(printf, 4, 5))) -__nvme_msg(nvme_root_t r, int level, +__nvme_msg(struct nvme_global_ctx *ctx, int level, const char *func, const char *format, ...) { struct nvme_log *l; @@ -55,8 +55,8 @@ __nvme_msg(nvme_root_t r, int level, _cleanup_free_ char *message = NULL; int idx = 0; - if (r) - l = &r->log; + if (ctx) + l = &ctx->log; else l = &def_log; @@ -96,19 +96,19 @@ __nvme_msg(nvme_root_t r, int level, message ? message : ""); } -void nvme_init_logging(nvme_root_t r, int lvl, bool log_pid, bool log_tstamp) +void nvme_init_logging(struct nvme_global_ctx *ctx, int lvl, bool log_pid, bool log_tstamp) { - r->log.level = lvl; - r->log.pid = log_pid; - r->log.timestamp = log_tstamp; + ctx->log.level = lvl; + ctx->log.pid = log_pid; + ctx->log.timestamp = log_tstamp; } -int nvme_get_logging_level(nvme_root_t r, bool *log_pid, bool *log_tstamp) +int nvme_get_logging_level(struct nvme_global_ctx *ctx, bool *log_pid, bool *log_tstamp) { struct nvme_log *l; - if (r) - l = &r->log; + if (ctx) + l = &ctx->log; else l = &def_log; @@ -127,12 +127,12 @@ void nvme_init_default_logging(FILE *fp, int level, bool log_pid, bool log_tstam def_log.timestamp = log_tstamp; } -void nvme_set_root(nvme_root_t r) +void nvme_set_global_ctx(struct nvme_global_ctx *ctx) { - def_log.fd = r->log.fd; - def_log.level = r->log.level; - def_log.pid = r->log.pid; - def_log.timestamp = r->log.timestamp; + def_log.fd = ctx->log.fd; + def_log.level = ctx->log.level; + def_log.pid = ctx->log.pid; + def_log.timestamp = ctx->log.timestamp; } void nvme_set_debug(bool debug) diff --git a/libnvme/src/nvme/log.h b/libnvme/src/nvme/log.h index 5a2f81c1b7..7f3b8c11fb 100644 --- a/libnvme/src/nvme/log.h +++ b/libnvme/src/nvme/log.h @@ -26,14 +26,14 @@ /** * nvme_init_logging() - Initialize logging - * @r: nvme_root_t context + * @ctx: struct nvme_global_ctx object * @lvl: Logging level to set * @log_pid: Boolean to enable logging of the PID * @log_tstamp: Boolean to enable logging of the timestamp * * Sets the default logging variables for the library. */ -void nvme_init_logging(nvme_root_t r, int lvl, bool log_pid, bool log_tstamp); +void nvme_init_logging(struct nvme_global_ctx *ctx, int lvl, bool log_pid, bool log_tstamp); /** * nvme_init_default_logging() - Initialize default (fallback) logging @@ -49,7 +49,7 @@ void nvme_init_default_logging(FILE *fp, int lvl, bool log_pid, bool log_tstamp) /** * nvme_get_logging_level() - Get current logging level - * @r: nvme_root_t context + * @ctx: struct nvme_global_ctx object * @log_pid: Pointer to store a current value of logging of * the PID flag at (optional). * @log_tstamp: Pointer to store a current value of logging of @@ -59,23 +59,24 @@ void nvme_init_default_logging(FILE *fp, int lvl, bool log_pid, bool log_tstamp) * * Return: current log level value or DEFAULT_LOGLEVEL if not initialized. */ -int nvme_get_logging_level(nvme_root_t r, bool *log_pid, bool *log_tstamp); +int nvme_get_logging_level(struct nvme_global_ctx *ctx, bool *log_pid, bool *log_tstamp); /** - * nvme_set_root() - Set nvme_root_t context - * @r: nvme_root_t context + * nvme_set_global_ctx() - Set global context + * @ctx: struct nvme_global_ctx object * - * In order to be able to log from code paths where no root object is passed in - * via the arguments use the the default one which can be set via this call. - * When creating a new root object with @nvme_create_root the global root object - * will be set as well. This means the global root object is always pointing to - * the latest created root object. Note the first @nvme_free_tree call will reset - * the global root object. + * In order to be able to log from code paths where no global context + * object is passed in via the arguments use the the default one which + * can be set via this call. When creating a new global context object + * with @nvme_create_global_ctx the global context object will be set as + * well. This means the global context object is always pointing to the + * latest created global context object. Note the first + * @nvme_free_global_ctx call will reset the global context object. * * This function is deprecated. Use nvme_init_default_logging or/and * nvme_init_logging instead. */ -void nvme_set_root(nvme_root_t r) __attribute__((deprecated)); +void nvme_set_global_ctx(struct nvme_global_ctx *ctx) __attribute__((deprecated)); /** * nvme_set_debug - Set NVMe command debugging output diff --git a/libnvme/src/nvme/mi-mctp.c b/libnvme/src/nvme/mi-mctp.c index 187d4a190a..492b924cf9 100644 --- a/libnvme/src/nvme/mi-mctp.c +++ b/libnvme/src/nvme/mi-mctp.c @@ -162,7 +162,7 @@ static __u8 nvme_mi_mctp_tag_alloc(struct nvme_mi_ep *ep) if (!logged) { /* not necessarily fatal, just means we can't handle * "more processing required" messages */ - nvme_msg(ep->root, LOG_INFO, + nvme_msg(ep->ctx, LOG_INFO, "System does not support explicit tag allocation\n"); logged = true; } @@ -303,7 +303,7 @@ static int nvme_mi_mctp_aem_read(struct nvme_mi_ep *ep, if (!tmp) { errno_save = errno; - nvme_msg(ep->root, LOG_ERR, + nvme_msg(ep->ctx, LOG_ERR, "Failure allocating response buffer: %m\n"); errno = errno_save; rc = -1; @@ -331,7 +331,7 @@ static int nvme_mi_mctp_aem_read(struct nvme_mi_ep *ep, goto out; errno_save = errno; - nvme_msg(ep->root, LOG_ERR, + nvme_msg(ep->ctx, LOG_ERR, "Failure receiving MCTP message: %m\n"); errno = errno_save; goto out; @@ -339,13 +339,13 @@ static int nvme_mi_mctp_aem_read(struct nvme_mi_ep *ep, if (len == 0) { - nvme_msg(ep->root, LOG_WARNING, "No data from MCTP endpoint\n"); + nvme_msg(ep->ctx, LOG_WARNING, "No data from MCTP endpoint\n"); errno = EIO; goto out; } if (resp_msg.msg_namelen < sizeof(src_addr)) { - nvme_msg(ep->root, LOG_WARNING, "Unexpected src address length\n"); + nvme_msg(ep->ctx, LOG_WARNING, "Unexpected src address length\n"); errno = EIO; goto out; } @@ -364,7 +364,7 @@ static int nvme_mi_mctp_aem_read(struct nvme_mi_ep *ep, * plus four bytes of error data (excluding MIC). Ensure we have enough. */ if (len < 8 + sizeof(mic)) { - nvme_msg(ep->root, LOG_ERR, + nvme_msg(ep->ctx, LOG_ERR, "Invalid MCTP response: too short (%zd bytes, needed %zd)\n", len, 8 + sizeof(mic)); errno = EPROTO; @@ -463,7 +463,7 @@ static int nvme_mi_mctp_submit(struct nvme_mi_ep *ep, len = ops.sendmsg(mctp->sd, &req_msg, 0); if (len < 0) { errno_save = errno; - nvme_msg(ep->root, LOG_ERR, + nvme_msg(ep->ctx, LOG_ERR, "Failure sending MCTP message: %m\n"); errno = errno_save; rc = -1; @@ -475,7 +475,7 @@ static int nvme_mi_mctp_submit(struct nvme_mi_ep *ep, void *tmp = realloc(mctp->resp_buf, resp_len); if (!tmp) { errno_save = errno; - nvme_msg(ep->root, LOG_ERR, + nvme_msg(ep->ctx, LOG_ERR, "Failure allocating response buffer: %m\n"); errno = errno_save; rc = -1; @@ -504,14 +504,14 @@ static int nvme_mi_mctp_submit(struct nvme_mi_ep *ep, if (errno == EINTR) goto retry; errno_save = errno; - nvme_msg(ep->root, LOG_ERR, + nvme_msg(ep->ctx, LOG_ERR, "Failed polling on MCTP socket: %m"); errno = errno_save; goto out; } if (rc == 0) { - nvme_msg(ep->root, LOG_DEBUG, "Timeout on MCTP socket"); + nvme_msg(ep->ctx, LOG_DEBUG, "Timeout on MCTP socket"); errno = ETIMEDOUT; rc = -1; goto out; @@ -522,7 +522,7 @@ static int nvme_mi_mctp_submit(struct nvme_mi_ep *ep, if (len < 0) { errno_save = errno; - nvme_msg(ep->root, LOG_ERR, + nvme_msg(ep->ctx, LOG_ERR, "Failure receiving MCTP message: %m\n"); errno = errno_save; goto out; @@ -530,7 +530,7 @@ static int nvme_mi_mctp_submit(struct nvme_mi_ep *ep, if (len == 0) { - nvme_msg(ep->root, LOG_WARNING, "No data from MCTP endpoint\n"); + nvme_msg(ep->ctx, LOG_WARNING, "No data from MCTP endpoint\n"); errno = EIO; goto out; } @@ -543,7 +543,7 @@ static int nvme_mi_mctp_submit(struct nvme_mi_ep *ep, * plus four bytes of error data (excluding MIC). Ensure we have enough. */ if (len < 8 + sizeof(mic)) { - nvme_msg(ep->root, LOG_ERR, + nvme_msg(ep->ctx, LOG_ERR, "Invalid MCTP response: too short (%zd bytes, needed %zd)\n", len, 8 + sizeof(mic)); errno = EPROTO; @@ -565,7 +565,7 @@ static int nvme_mi_mctp_submit(struct nvme_mi_ep *ep, * to keep the tag allocated and retry the recvmsg */ if (nvme_mi_mctp_resp_is_mpr(mctp->resp_buf, len, mic, &mpr_time)) { - nvme_msg(ep->root, LOG_DEBUG, + nvme_msg(ep->ctx, LOG_DEBUG, "Received More Processing Required, waiting for response\n"); /* if the controller hasn't set MPRT, fall back to our command/ @@ -672,13 +672,14 @@ int nvme_mi_aem_open(nvme_mi_ep_t ep) return 0; } -nvme_mi_ep_t nvme_mi_open_mctp(nvme_root_t root, unsigned int netid, __u8 eid) +nvme_mi_ep_t nvme_mi_open_mctp(struct nvme_global_ctx *ctx, + unsigned int netid, __u8 eid) { struct nvme_mi_transport_mctp *mctp; struct nvme_mi_ep *ep; int errno_save; - ep = nvme_mi_init_ep(root); + ep = nvme_mi_init_ep(ctx); if (!ep) return NULL; @@ -743,13 +744,13 @@ nvme_mi_ep_t nvme_mi_open_mctp(nvme_root_t root, unsigned int netid, __u8 eid) #ifdef CONFIG_DBUS -static int nvme_mi_mctp_add(nvme_root_t root, unsigned int netid, __u8 eid) +static int nvme_mi_mctp_add(struct nvme_global_ctx *ctx, unsigned int netid, __u8 eid) { nvme_mi_ep_t ep = NULL; /* ensure we don't already have an endpoint with the same net/eid. if * we do, just skip, no need to re-add. */ - list_for_each(&root->endpoints, ep, root_entry) { + list_for_each(&ctx->endpoints, ep, root_entry) { if (ep->transport != &nvme_mi_transport_mctp) { continue; } @@ -758,7 +759,7 @@ static int nvme_mi_mctp_add(nvme_root_t root, unsigned int netid, __u8 eid) return 0; } - ep = nvme_mi_open_mctp(root, netid, eid); + ep = nvme_mi_open_mctp(ctx, netid, eid); if (!ep) return -1; @@ -808,7 +809,7 @@ static bool has_message_type(DBusMessageIter *prop, uint8_t type) return false; } -static int handle_mctp_endpoint(nvme_root_t root, const char* objpath, +static int handle_mctp_endpoint(struct nvme_global_ctx *ctx, const char* objpath, DBusMessageIter *props) { bool have_eid = false, have_net = false, have_nvmemi = false; @@ -824,7 +825,7 @@ static int handle_mctp_endpoint(nvme_root_t root, const char* objpath, dbus_message_iter_recurse(props, &prop); if (!dbus_object_is_type(&prop, DBUS_TYPE_STRING)) { - nvme_msg(root, LOG_ERR, + nvme_msg(ctx, LOG_ERR, "error unmashalling object (propname)\n"); return -1; } @@ -834,7 +835,7 @@ static int handle_mctp_endpoint(nvme_root_t root, const char* objpath, dbus_message_iter_next(&prop); if (!dbus_object_is_type(&prop, DBUS_TYPE_VARIANT)) { - nvme_msg(root, LOG_ERR, + nvme_msg(ctx, LOG_ERR, "error unmashalling object (propval)\n"); return -1; } @@ -862,15 +863,15 @@ static int handle_mctp_endpoint(nvme_root_t root, const char* objpath, if (have_nvmemi) { if (!(have_eid && have_net)) { - nvme_msg(root, LOG_ERR, + nvme_msg(ctx, LOG_ERR, "Missing property for %s\n", objpath); errno = ENOENT; return -1; } - rc = nvme_mi_mctp_add(root, net, eid); + rc = nvme_mi_mctp_add(ctx, net, eid); if (rc < 0) { int errno_save = errno; - nvme_msg(root, LOG_ERR, + nvme_msg(ctx, LOG_ERR, "Error adding net %d eid %d: %m\n", net, eid); errno = errno_save; } @@ -884,13 +885,13 @@ static int handle_mctp_endpoint(nvme_root_t root, const char* objpath, /* obj is an array of (object path, interfaces) dict entries - ie., dbus type * a{oa{sa{sv}}} */ -static int handle_mctp_obj(nvme_root_t root, DBusMessageIter *obj) +static int handle_mctp_obj(struct nvme_global_ctx *ctx, DBusMessageIter *obj) { const char *objpath = NULL; DBusMessageIter intfs; if (!dbus_object_is_type(obj, DBUS_TYPE_OBJECT_PATH)) { - nvme_msg(root, LOG_ERR, "error unmashalling object (path)\n"); + nvme_msg(ctx, LOG_ERR, "error unmashalling object (path)\n"); return -1; } @@ -899,7 +900,7 @@ static int handle_mctp_obj(nvme_root_t root, DBusMessageIter *obj) dbus_message_iter_next(obj); if (!dbus_object_is_dict(obj)) { - nvme_msg(root, LOG_ERR, "error unmashalling object (intfs)\n"); + nvme_msg(ctx, LOG_ERR, "error unmashalling object (intfs)\n"); return -1; } @@ -913,7 +914,7 @@ static int handle_mctp_obj(nvme_root_t root, DBusMessageIter *obj) dbus_message_iter_recurse(&intfs, &intf); if (!dbus_object_is_type(&intf, DBUS_TYPE_STRING)) { - nvme_msg(root, LOG_ERR, + nvme_msg(ctx, LOG_ERR, "error unmashalling object (intf)\n"); return -1; } @@ -929,30 +930,30 @@ static int handle_mctp_obj(nvme_root_t root, DBusMessageIter *obj) dbus_message_iter_next(&intf); if (!dbus_object_is_dict(&intf)) { - nvme_msg(root, LOG_ERR, + nvme_msg(ctx, LOG_ERR, "error unmarshalling object (props)\n"); return -1; } dbus_message_iter_recurse(&intf, &props); - return handle_mctp_endpoint(root, objpath, &props); + return handle_mctp_endpoint(ctx, objpath, &props); } return 0; } -nvme_root_t nvme_mi_scan_mctp(void) +struct nvme_global_ctx *nvme_mi_scan_mctp(void) { DBusMessage *msg, *resp = NULL; DBusConnection *bus = NULL; DBusMessageIter args, objs; int errno_save, rc = -1; - nvme_root_t root; + struct nvme_global_ctx *ctx; dbus_bool_t drc; DBusError berr; - root = nvme_mi_create_root(NULL, DEFAULT_LOGLEVEL); - if (!root) { + ctx = nvme_mi_create_global_ctx(NULL, DEFAULT_LOGLEVEL); + if (!ctx) { errno = ENOMEM; return NULL; } @@ -961,7 +962,7 @@ nvme_root_t nvme_mi_scan_mctp(void) bus = dbus_bus_get(DBUS_BUS_SYSTEM, &berr); if (!bus) { - nvme_msg(root, LOG_ERR, "Failed connecting to D-Bus: %s (%s)\n", + nvme_msg(ctx, LOG_ERR, "Failed connecting to D-Bus: %s (%s)\n", berr.message, berr.name); goto out; } @@ -971,7 +972,7 @@ nvme_root_t nvme_mi_scan_mctp(void) "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); if (!msg) { - nvme_msg(root, LOG_ERR, "Failed creating call message\n"); + nvme_msg(ctx, LOG_ERR, "Failed creating call message\n"); goto out; } @@ -980,7 +981,7 @@ nvme_root_t nvme_mi_scan_mctp(void) &berr); dbus_message_unref(msg); if (!resp) { - nvme_msg(root, LOG_ERR, "Failed querying MCTP D-Bus: %s (%s)\n", + nvme_msg(ctx, LOG_ERR, "Failed querying MCTP D-Bus: %s (%s)\n", berr.message, berr.name); goto out; } @@ -988,12 +989,12 @@ nvme_root_t nvme_mi_scan_mctp(void) /* argument container */ drc = dbus_message_iter_init(resp, &args); if (!drc) { - nvme_msg(root, LOG_ERR, "can't read dbus reply args\n"); + nvme_msg(ctx, LOG_ERR, "can't read dbus reply args\n"); goto out; } if (!dbus_object_is_dict(&args)) { - nvme_msg(root, LOG_ERR, "error unmashalling args\n"); + nvme_msg(ctx, LOG_ERR, "error unmashalling args\n"); goto out; } @@ -1007,7 +1008,7 @@ nvme_root_t nvme_mi_scan_mctp(void) dbus_message_iter_recurse(&objs, &ent); - rc = handle_mctp_obj(root, &ent); + rc = handle_mctp_obj(ctx, &ent); if (rc) break; @@ -1024,18 +1025,18 @@ nvme_root_t nvme_mi_scan_mctp(void) dbus_error_free(&berr); if (rc < 0) { - if (root) { - nvme_mi_free_root(root); + if (ctx) { + nvme_mi_free_global_ctx(ctx); } errno = errno_save; - root = NULL; + ctx = NULL; } - return root; + return ctx; } #else /* CONFIG_DBUS */ -nvme_root_t nvme_mi_scan_mctp(void) +struct nvme_global_ctx *nvme_mi_scan_mctp(void) { return NULL; } diff --git a/libnvme/src/nvme/mi.c b/libnvme/src/nvme/mi.c index 14c71d75e6..c988dbc52f 100644 --- a/libnvme/src/nvme/mi.c +++ b/libnvme/src/nvme/mi.c @@ -19,6 +19,7 @@ #include "log.h" #include "mi.h" +#include "linux.h" #include "private.h" #define NUM_ENABLES (256u) @@ -56,53 +57,107 @@ static bool nvme_mi_probe_enabled_default(void) } +static int parse_devname(const char *dev, unsigned int *net, uint8_t *eid, + unsigned int *ctrl) +{ + int rc; + + /* ,: form */ + rc = sscanf(dev, "mctp:%u,%hhu:%u", net, eid, ctrl); + if (rc == 3) + return 0; + + /* , form, implicit ctrl-id = 0 */ + *ctrl = 0; + rc = sscanf(dev, "mctp:%u,%hhu", net, eid); + if (rc == 2) + return 0; + + return -EINVAL; +} + +int __nvme_transport_handle_init_mi(struct nvme_transport_handle *hdl) +{ + if (hdl->type != NVME_TRANSPORT_HANDLE_TYPE_UNKNOWN) + return -EALREADY; + + hdl->type = NVME_TRANSPORT_HANDLE_TYPE_MI; + + return 0; +} + +int __nvme_transport_handle_open_mi(struct nvme_transport_handle *hdl, const char *devname) +{ + unsigned int rc, net, ctrl_id; + unsigned char eid; + struct nvme_mi_ep *ep; + + rc = __nvme_transport_handle_init_mi(hdl); + if (rc) + return rc; + + rc = parse_devname(devname, &net, &eid, &ctrl_id); + if (rc) + return rc; + + ep = nvme_mi_open_mctp(hdl->ctx, net, eid); + if (!ep) + return -EINVAL; + + return 0; +} + +void __nvme_transport_handle_close_mi(struct nvme_transport_handle *hdl) +{ + list_del(&hdl->ep_entry); + free(hdl); +} + /* MI-equivalent of nvme_create_root, but avoids clashing symbol names * when linking against both libnvme and libnvme-mi. */ -nvme_root_t nvme_mi_create_root(FILE *fp, int log_level) +struct nvme_global_ctx *nvme_mi_create_global_ctx(FILE *fp, int log_level) { - struct nvme_root *r; + struct nvme_global_ctx *ctx; int fd; - r = calloc(1, sizeof(*r)); - if (!r) { - errno = ENOMEM; + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) return NULL; - } if (fp) { fd = fileno(fp); if (fd < 0) { - free(r); + free(ctx); return NULL; } } else fd = STDERR_FILENO; - r->log.fd = fd; - r->log.level = log_level; + ctx->log.fd = fd; + ctx->log.level = log_level; - r->mi_probe_enabled = nvme_mi_probe_enabled_default(); + ctx->mi_probe_enabled = nvme_mi_probe_enabled_default(); - list_head_init(&r->hosts); - list_head_init(&r->endpoints); + list_head_init(&ctx->hosts); + list_head_init(&ctx->endpoints); - return r; + return ctx; } -void nvme_mi_free_root(nvme_root_t root) +void nvme_mi_free_global_ctx(struct nvme_global_ctx *ctx) { nvme_mi_ep_t ep, tmp; - nvme_mi_for_each_endpoint_safe(root, ep, tmp) + nvme_mi_for_each_endpoint_safe(ctx, ep, tmp) nvme_mi_close(ep); - free(root); + free(ctx); } -void nvme_mi_set_probe_enabled(nvme_root_t root, bool enabled) +void nvme_mi_set_probe_enabled(struct nvme_global_ctx *ctx, bool enabled) { - root->mi_probe_enabled = enabled; + ctx->mi_probe_enabled = enabled; } static void nvme_mi_record_resp_time(struct nvme_mi_ep *ep) @@ -122,7 +177,7 @@ static bool nvme_mi_compare_vid_mn(struct nvme_mi_ep *ep, len = strlen(mn); if (len >= sizeof(id->mn)) { - nvme_msg(ep->root, LOG_ERR, + nvme_msg(ep->ctx, LOG_ERR, "Internal error: invalid model number for %s\n", __func__); return false; @@ -157,9 +212,9 @@ static void __nvme_mi_format_mn(struct nvme_id_ctrl *id, void nvme_mi_ep_probe(struct nvme_mi_ep *ep) { - struct nvme_identify_args id_args = { 0 }; struct nvme_id_ctrl id = { 0 }; - struct nvme_mi_ctrl *ctrl; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; int rc; /* Ensure the probe occurs at most once. This isn't just to mitigate doubling @@ -176,14 +231,14 @@ void nvme_mi_ep_probe(struct nvme_mi_ep *ep) */ ep->quirks_probed = true; - if (!ep->root->mi_probe_enabled) + if (!ep->ctx->mi_probe_enabled) return; /* start with no quirks, detect as we go */ ep->quirks = 0; - ctrl = nvme_mi_init_ctrl(ep, 0); - if (!ctrl) + hdl = nvme_mi_init_transport_handle(ep, 0); + if (!hdl) return; /* Do enough of an identify (assuming controller 0) to retrieve @@ -198,17 +253,11 @@ void nvme_mi_ep_probe(struct nvme_mi_ep *ep) * * all other fields - rab and onwards - will be zero! */ - id_args.args_size = sizeof(id_args); - id_args.data = &id; - id_args.cns = NVME_IDENTIFY_CNS_CTRL; - id_args.nsid = NVME_NSID_NONE; - id_args.cntid = 0; - id_args.csi = NVME_CSI_NVM; - - rc = nvme_mi_admin_identify_partial(ctrl, &id_args, 0, - offsetof(struct nvme_id_ctrl, rab)); + nvme_init_identify_ctrl(&cmd, &id); + cmd.data_len = offsetof(struct nvme_id_ctrl, rab); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (rc) { - nvme_msg(ep->root, LOG_WARNING, + nvme_msg(ep->ctx, LOG_WARNING, "Identify Controller failed, no quirks applied\n"); goto out_close; } @@ -232,13 +281,13 @@ void nvme_mi_ep_probe(struct nvme_mi_ep *ep) char tmp[sizeof(id.mn) + 1]; nvme_mi_format_mn(&id, tmp); - nvme_msg(ep->root, LOG_DEBUG, + nvme_msg(ep->ctx, LOG_DEBUG, "device %02x:%s: applying quirks 0x%08lx\n", id.vid, tmp, ep->quirks); } out_close: - nvme_mi_close_ctrl(ctrl); + nvme_close(hdl); } static const int nsec_per_sec = 1000 * 1000 * 1000; @@ -288,7 +337,7 @@ static void nvme_mi_insert_delay(struct nvme_mi_ep *ep) nanosleep(&delay, NULL); } -struct nvme_mi_ep *nvme_mi_init_ep(nvme_root_t root) +struct nvme_mi_ep *nvme_mi_init_ep(struct nvme_global_ctx *ctx) { struct nvme_mi_ep *ep; @@ -297,14 +346,14 @@ struct nvme_mi_ep *nvme_mi_init_ep(nvme_root_t root) return NULL; list_node_init(&ep->root_entry); - ep->root = root; + ep->ctx = ctx; ep->quirks_probed = false; ep->controllers_scanned = false; ep->timeout = default_timeout; ep->mprt_max = 0; list_head_init(&ep->controllers); - list_add(&root->endpoints, &ep->root_entry); + list_add(&ctx->endpoints, &ep->root_entry); return ep; } @@ -337,25 +386,27 @@ static bool nvme_mi_ep_has_quirk(nvme_mi_ep_t ep, unsigned long quirk) return ep->quirks & quirk; } -struct nvme_mi_ctrl *nvme_mi_init_ctrl(nvme_mi_ep_t ep, __u16 ctrl_id) +struct nvme_transport_handle *nvme_mi_init_transport_handle(nvme_mi_ep_t ep, __u16 ctrl_id) { - struct nvme_mi_ctrl *ctrl; + struct nvme_transport_handle *hdl; - ctrl = malloc(sizeof(*ctrl)); - if (!ctrl) + hdl = __nvme_create_transport_handle(ep->ctx); + if (!hdl) return NULL; - ctrl->ep = ep; - ctrl->id = ctrl_id; + __nvme_transport_handle_init_mi(hdl); - list_add_tail(&ep->controllers, &ctrl->ep_entry); + hdl->ep = ep; + hdl->id = ctrl_id; - return ctrl; + list_add_tail(&ep->controllers, &hdl->ep_entry); + + return hdl; } -__u16 nvme_mi_ctrl_id(nvme_mi_ctrl_t ctrl) +__u16 nvme_mi_ctrl_id(struct nvme_transport_handle *hdl) { - return ctrl->id; + return hdl->id; } int nvme_mi_scan_ep(nvme_mi_ep_t ep, bool force_rescan) @@ -366,9 +417,10 @@ int nvme_mi_scan_ep(nvme_mi_ep_t ep, bool force_rescan) if (ep->controllers_scanned) { if (force_rescan) { - struct nvme_mi_ctrl *ctrl, *tmp; - nvme_mi_for_each_ctrl_safe(ep, ctrl, tmp) - nvme_mi_close_ctrl(ctrl); + struct nvme_transport_handle *hdl, *tmp; + + nvme_mi_for_each_transport_handle_safe(ep, hdl, tmp) + nvme_close(hdl); } else { return 0; } @@ -379,19 +431,17 @@ int nvme_mi_scan_ep(nvme_mi_ep_t ep, bool force_rescan) return rc; n_ctrl = le16_to_cpu(list.num); - if (n_ctrl > NVME_ID_CTRL_LIST_MAX) { - errno = EPROTO; - return -1; - } + if (n_ctrl > NVME_ID_CTRL_LIST_MAX) + return -EPROTO; for (i = 0; i < n_ctrl; i++) { - struct nvme_mi_ctrl *ctrl; + struct nvme_transport_handle *hdl; __u16 id; id = le16_to_cpu(list.identifier[i]); - ctrl = nvme_mi_init_ctrl(ep, id); - if (!ctrl) + hdl = nvme_mi_init_transport_handle(ep, id); + if (!hdl) break; } @@ -450,22 +500,21 @@ int nvme_mi_async_read(nvme_mi_ep_t ep, struct nvme_mi_resp *resp) int rc = ep->transport->aem_read(ep, resp); - if (rc && errno == EWOULDBLOCK) { + if (rc == EWOULDBLOCK) { //Sometimes we might get owned tag data from the wrong endpoint. //This isn't an error, but we shouldn't process it here resp->data_len = 0;//No data to process return 0; } else if (rc) { - nvme_msg(ep->root, LOG_INFO, "transport failure\n"); + nvme_msg(ep->ctx, LOG_INFO, "transport failure\n"); return rc; } if (ep->transport->mic_enabled) { rc = nvme_mi_verify_resp_mic(resp); if (rc) { - nvme_msg(ep->root, LOG_WARNING, "crc mismatch\n"); - errno = EBADMSG; - return -1; + nvme_msg(ep->ctx, LOG_WARNING, "crc mismatch\n"); + return -EBADMSG; } } @@ -473,28 +522,25 @@ int nvme_mi_async_read(nvme_mi_ep_t ep, struct nvme_mi_resp *resp) /* basic response checks */ if (resp->hdr_len < sizeof(struct nvme_mi_msg_hdr)) { - nvme_msg(ep->root, LOG_DEBUG, + nvme_msg(ep->ctx, LOG_DEBUG, "Bad response header len: %zd\n", resp->hdr_len); - errno = EPROTO; - return -1; + return -EPROTO; } if (resp->hdr->type != NVME_MI_MSGTYPE_NVME) { - nvme_msg(ep->root, LOG_DEBUG, + nvme_msg(ep->ctx, LOG_DEBUG, "Invalid message type 0x%02x\n", resp->hdr->type); - errno = EPROTO; - return -1; + return -EPROTO; } if (!(resp->hdr->nmp & ~(NVME_MI_ROR_REQ << 7))) { - nvme_msg(ep->root, LOG_DEBUG, + nvme_msg(ep->ctx, LOG_DEBUG, "ROR value in response indicates a response\n"); - errno = EIO; - return -1; + return -EIO; } if (!(resp->hdr->nmp & (NVME_MI_MT_AE << 3))) { - nvme_msg(ep->root, LOG_DEBUG, + nvme_msg(ep->ctx, LOG_DEBUG, "NMIMT does not indicate AEM\n"); resp->data_len = 0;//No data to process return 0; @@ -513,25 +559,17 @@ int nvme_mi_submit(nvme_mi_ep_t ep, struct nvme_mi_req *req, user_data = nvme_mi_submit_entry(req->hdr->type, req->hdr, req->hdr_len, req->data, req->data_len); - if (req->hdr_len < sizeof(struct nvme_mi_msg_hdr)) { - errno = EINVAL; - return -1; - } + if (req->hdr_len < sizeof(struct nvme_mi_msg_hdr)) + return -EINVAL; - if (req->hdr_len & 0x3) { - errno = EINVAL; - return -1; - } + if (req->hdr_len & 0x3) + return -EINVAL; - if (resp->hdr_len < sizeof(struct nvme_mi_msg_hdr)) { - errno = EINVAL; - return -1; - } + if (resp->hdr_len < sizeof(struct nvme_mi_msg_hdr)) + return -EINVAL; - if (resp->hdr_len & 0x3) { - errno = EINVAL; - return -1; - } + if (resp->hdr_len & 0x3) + return -EINVAL; nvme_mi_ep_probe(ep); @@ -547,48 +585,43 @@ int nvme_mi_submit(nvme_mi_ep_t ep, struct nvme_mi_req *req, nvme_mi_record_resp_time(ep); if (rc) { - nvme_msg(ep->root, LOG_INFO, "transport failure\n"); + nvme_msg(ep->ctx, LOG_INFO, "transport failure\n"); return rc; } if (ep->transport->mic_enabled) { rc = nvme_mi_verify_resp_mic(resp); if (rc) { - nvme_msg(ep->root, LOG_WARNING, "crc mismatch\n"); - errno = EBADMSG; - return -1; + nvme_msg(ep->ctx, LOG_WARNING, "crc mismatch\n"); + return -EBADMSG; } } /* basic response checks */ if (resp->hdr_len < sizeof(struct nvme_mi_msg_hdr)) { - nvme_msg(ep->root, LOG_DEBUG, + nvme_msg(ep->ctx, LOG_DEBUG, "Bad response header len: %zd\n", resp->hdr_len); - errno = EPROTO; - return -1; + return -EPROTO; } if (resp->hdr->type != NVME_MI_MSGTYPE_NVME) { - nvme_msg(ep->root, LOG_DEBUG, + nvme_msg(ep->ctx, LOG_DEBUG, "Invalid message type 0x%02x\n", resp->hdr->type); - errno = EPROTO; - return -1; + return -EPROTO; } if (!(resp->hdr->nmp & (NVME_MI_ROR_RSP << 7))) { - nvme_msg(ep->root, LOG_DEBUG, + nvme_msg(ep->ctx, LOG_DEBUG, "ROR value in response indicates a request\n"); - errno = EIO; - return -1; + return -EIO; } if ((resp->hdr->nmp & 0x1) != (req->hdr->nmp & 0x1)) { - nvme_msg(ep->root, LOG_WARNING, + nvme_msg(ep->ctx, LOG_WARNING, "Command slot mismatch: req %d, resp %d\n", req->hdr->nmp & 0x1, resp->hdr->nmp & 0x1); - errno = EIO; - return -1; + return -EIO; } nvme_mi_submit_exit(resp->hdr->type, resp->hdr, resp->hdr_len, resp->data, resp->data_len, @@ -676,10 +709,8 @@ static int nvme_mi_admin_parse_status(struct nvme_mi_resp *resp, __u32 *result) * the former two generate return values here */ - if (resp->hdr_len < sizeof(*resp_hdr)) { - errno = -EPROTO; - return -1; - } + if (resp->hdr_len < sizeof(*resp_hdr)) + return -EPROTO; resp_hdr = (struct nvme_mi_msg_resp *)resp->hdr; /* If we have a MI error, we can't be sure there's an admin header @@ -693,10 +724,8 @@ static int nvme_mi_admin_parse_status(struct nvme_mi_resp *resp, __u32 *result) /* We shouldn't hit this, as we'd have an error reported earlier. * However, for pointer safety, ensure we have a full admin header */ - if (resp->hdr_len < sizeof(*admin_hdr)) { - errno = EPROTO; - return -1; - } + if (resp->hdr_len < sizeof(*admin_hdr)) + return -EPROTO; admin_hdr = (struct nvme_mi_admin_resp_hdr *)resp->hdr; nvme_result = le32_to_cpu(admin_hdr->cdw0); @@ -718,10 +747,8 @@ static int nvme_mi_control_parse_status(struct nvme_mi_resp *resp, __u16 *cpsr) { struct nvme_mi_control_resp *control_resp; - if (resp->hdr_len < sizeof(*control_resp)) { - errno = -EPROTO; - return -1; - } + if (resp->hdr_len < sizeof(*control_resp)) + return -EPROTO; control_resp = (struct nvme_mi_control_resp *)resp->hdr; if (control_resp->status) @@ -756,7 +783,7 @@ static int nvme_mi_get_async_message(nvme_mi_ep_t ep, } -int nvme_mi_admin_xfer(nvme_mi_ctrl_t ctrl, +int nvme_mi_admin_xfer(struct nvme_transport_handle *hdl, struct nvme_mi_admin_req_hdr *admin_req, size_t req_data_size, struct nvme_mi_admin_resp_hdr *admin_resp, @@ -774,42 +801,32 @@ int nvme_mi_admin_xfer(nvme_mi_ctrl_t ctrl, */ /* NVMe-MI v1.2 imposes a limit of 4096 bytes on the dlen field */ - if (*resp_data_size > 4096) { - errno = EINVAL; - return -1; - } + if (*resp_data_size > 4096) + return -EINVAL; /* we only have 32 bits of offset */ - if (resp_data_offset > 0xffffffff) { - errno = EINVAL; - return -1; - } + if (resp_data_offset > 0xffffffff) + return -EINVAL; /* request and response lengths & offset must be aligned */ if ((req_data_size & 0x3) || (*resp_data_size & 0x3) || - (resp_data_offset & 0x3)) { - errno = EINVAL; - return -1; - } + (resp_data_offset & 0x3)) + return -EINVAL; /* bidirectional not permitted (see DLEN definition) */ - if (req_data_size && *resp_data_size) { - errno = EINVAL; - return -1; - } + if (req_data_size && *resp_data_size) + return -EINVAL; - if (!*resp_data_size && resp_data_offset) { - errno = EINVAL; - return -1; - } + if (!*resp_data_size && resp_data_offset) + return -EINVAL; admin_req->hdr.type = NVME_MI_MSGTYPE_NVME; admin_req->hdr.nmp = (NVME_MI_ROR_REQ << 7) | (NVME_MI_MT_ADMIN << 3) | - (ctrl->ep->csi & 1); + (hdl->ep->csi & 1); - admin_req->ctrl_id = cpu_to_le16(ctrl->id); + admin_req->ctrl_id = cpu_to_le16(hdl->id); memset(&req, 0, sizeof(req)); req.hdr = &admin_req->hdr; req.hdr_len = sizeof(*admin_req); @@ -836,7 +853,7 @@ int nvme_mi_admin_xfer(nvme_mi_ctrl_t ctrl, admin_req->dlen = cpu_to_le32(dlen); admin_req->doff = cpu_to_le32(doff); - rc = nvme_mi_submit(ctrl->ep, &req, &resp); + rc = nvme_mi_submit(hdl->ep, &req, &resp); if (rc) return rc; @@ -845,7 +862,7 @@ int nvme_mi_admin_xfer(nvme_mi_ctrl_t ctrl, return 0; } -int nvme_mi_admin_admin_passthru(nvme_mi_ctrl_t ctrl, __u8 opcode, __u8 flags, +int nvme_mi_admin_admin_passthru(struct nvme_transport_handle *hdl, __u8 opcode, __u8 flags, __u16 rsvd, __u32 nsid, __u32 cdw2, __u32 cdw3, __u32 cdw10, __u32 cdw11, __u32 cdw12, __u32 cdw13, __u32 cdw14, __u32 cdw15, @@ -864,17 +881,15 @@ int nvme_mi_admin_admin_passthru(nvme_mi_ctrl_t ctrl, __u8 opcode, __u8 flags, bool has_read_data = false; if (direction == NVME_DATA_TFR_BIDIRECTIONAL) { - nvme_msg(ctrl->ep->root, LOG_ERR, + nvme_msg(hdl->ctx, LOG_ERR, "nvme_mi_admin_admin_passthru doesn't support bidirectional commands\n"); - errno = EINVAL; - return -1; + return -EINVAL; } if (data_len > 4096) { - nvme_msg(ctrl->ep->root, LOG_ERR, + nvme_msg(hdl->ctx, LOG_ERR, "nvme_mi_admin_admin_passthru doesn't support data_len over 4096 bytes.\n"); - errno = EINVAL; - return -1; + return -EINVAL; } if (data != NULL && data_len != 0) { @@ -884,7 +899,7 @@ int nvme_mi_admin_admin_passthru(nvme_mi_ctrl_t ctrl, __u8 opcode, __u8 flags, has_read_data = true; } - nvme_mi_admin_init_req(ctrl->ep, &req, &req_hdr, ctrl->id, opcode); + nvme_mi_admin_init_req(hdl->ep, &req, &req_hdr, hdl->id, opcode); req_hdr.cdw1 = cpu_to_le32(nsid); req_hdr.cdw2 = cpu_to_le32(cdw2); req_hdr.cdw3 = cpu_to_le32(cdw3); @@ -917,12 +932,12 @@ int nvme_mi_admin_admin_passthru(nvme_mi_ctrl_t ctrl, __u8 opcode, __u8 flags, * timeout and override */ if (timeout_ms != 0) { - timeout_save = nvme_mi_ep_get_timeout(ctrl->ep); - nvme_mi_ep_set_timeout(ctrl->ep, timeout_ms); + timeout_save = nvme_mi_ep_get_timeout(hdl->ep); + nvme_mi_ep_set_timeout(hdl->ep, timeout_ms); } - rc = nvme_mi_submit(ctrl->ep, &req, &resp); + rc = nvme_mi_submit(hdl->ep, &req, &resp); if (timeout_ms != 0) - nvme_mi_ep_set_timeout(ctrl->ep, timeout_save); + nvme_mi_ep_set_timeout(hdl->ep, timeout_save); if (rc) return rc; @@ -931,65 +946,8 @@ int nvme_mi_admin_admin_passthru(nvme_mi_ctrl_t ctrl, __u8 opcode, __u8 flags, if (rc) return rc; - if (has_read_data && (resp.data_len != data_len)) { - errno = EPROTO; - return -1; - } - - return 0; -} - -int nvme_mi_admin_identify_partial(nvme_mi_ctrl_t ctrl, - struct nvme_identify_args *args, - off_t offset, size_t size) -{ - struct nvme_mi_admin_resp_hdr resp_hdr; - struct nvme_mi_admin_req_hdr req_hdr; - struct nvme_mi_resp resp; - struct nvme_mi_req req; - int rc; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - if (!size || size > 0xffffffff) { - errno = EINVAL; - return -1; - } - - nvme_mi_admin_init_req(ctrl->ep, &req, &req_hdr, ctrl->id, nvme_admin_identify); - req_hdr.cdw1 = cpu_to_le32(args->nsid); - req_hdr.cdw10 = cpu_to_le32(args->cntid << 16 | args->cns); - req_hdr.cdw11 = cpu_to_le32((args->csi & 0xff) << 24 | - args->cns_specific_id); - req_hdr.cdw14 = cpu_to_le32(args->uuidx); - req_hdr.dlen = cpu_to_le32(size & 0xffffffff); - req_hdr.flags = 0x1; - if (offset) { - req_hdr.flags |= 0x2; - req_hdr.doff = cpu_to_le32(offset); - } - - nvme_mi_admin_init_resp(&resp, &resp_hdr); - resp.data = args->data; - resp.data_len = size; - - rc = nvme_mi_submit(ctrl->ep, &req, &resp); - if (rc) - return rc; - - rc = nvme_mi_admin_parse_status(&resp, args->result); - if (rc) - return rc; - - /* callers will expect a full response; if the data buffer isn't - * fully valid, return an error */ - if (resp.data_len != size) { - errno = EPROTO; - return -1; - } + if (has_read_data && (resp.data_len != data_len)) + return -EPROTO; return 0; } @@ -1017,714 +975,6 @@ int nvme_mi_control(nvme_mi_ep_t ep, __u8 opcode, return 0; } -/* retrieves a MCTP-messsage-sized chunk of log page data. offset and len are - * specified within the args->data area. The `offset` parameter is a relative - * offset to the args->lpo ! - * - * What's more, we change the LPO of original command to chunk the request - * message into proper size which is allowed by MI interface. One reason is that - * this option seems to be supported better by devices. For more information - * about this option, please check https://github.com/linux-nvme/libnvme/pull/539 - * */ -static int __nvme_mi_admin_get_log(nvme_mi_ctrl_t ctrl, - const struct nvme_get_log_args *args, - off_t offset, size_t *lenp, bool final) -{ - __u64 log_page_offset = args->lpo + offset; - struct nvme_mi_admin_resp_hdr resp_hdr; - struct nvme_mi_admin_req_hdr req_hdr; - struct nvme_mi_resp resp; - struct nvme_mi_req req; - size_t len; - __u32 ndw; - int rc; - - /* MI spec requires that the data length field is less than or equal - * to 4096 */ - len = *lenp; - if (!len || len > 4096 || len < 4) { - errno = EINVAL; - return -1; - } - - if (offset < 0 || offset >= args->len || offset + len > args->len) { - errno = EINVAL; - return -1; - } - - ndw = (len >> 2) - 1; - - nvme_mi_admin_init_req(ctrl->ep, &req, &req_hdr, ctrl->id, - nvme_admin_get_log_page); - req_hdr.cdw1 = cpu_to_le32(args->nsid); - req_hdr.cdw10 = cpu_to_le32((ndw & 0xffff) << 16 | - ((!final || args->rae) ? 1 : 0) << 15 | - args->lsp << 8 | - (args->lid & 0xff)); - req_hdr.cdw11 = cpu_to_le32(args->lsi << 16 | - ndw >> 16); - req_hdr.cdw12 = cpu_to_le32(log_page_offset & 0xffffffff); - req_hdr.cdw13 = cpu_to_le32(log_page_offset >> 32); - req_hdr.cdw14 = cpu_to_le32(args->csi << 24 | - (args->ot ? 1 : 0) << 23 | - args->uuidx); - req_hdr.flags = 0x1; - req_hdr.dlen = cpu_to_le32(len & 0xffffffff); - - nvme_mi_admin_init_resp(&resp, &resp_hdr); - resp.data = args->log + offset; - resp.data_len = len; - - rc = nvme_mi_submit(ctrl->ep, &req, &resp); - if (rc) - return rc; - - rc = nvme_mi_admin_parse_status(&resp, args->result); - if (!rc) - *lenp = resp.data_len; - - return rc; -} - -int nvme_mi_admin_get_log_page(nvme_mi_ctrl_t ctrl, __u32 xfer_size, - struct nvme_get_log_args *args) -{ - const size_t max_xfer_size = xfer_size; - off_t xfer_offset; - int rc = 0; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - if (args->ot && (args->len > max_xfer_size)) { - errno = EINVAL; - return -1; - } - - for (xfer_offset = 0; xfer_offset < args->len;) { - size_t xfered_size, cur_xfer_size = max_xfer_size; - bool final; - - if (xfer_offset + cur_xfer_size > args->len) - cur_xfer_size = args->len - xfer_offset; - - xfered_size = cur_xfer_size; - - final = xfer_offset + cur_xfer_size >= args->len; - - /* xfered_size is used as both input and output parameter */ - rc = __nvme_mi_admin_get_log(ctrl, args, xfer_offset, - &xfered_size, final); - if (rc) - break; - - xfer_offset += xfered_size; - /* if we returned less data than expected, consider that - * the end of the log page */ - if (xfered_size != cur_xfer_size) - break; - } - - if (!rc) - args->len = xfer_offset; - - return rc; -} - -int nvme_mi_admin_get_log(nvme_mi_ctrl_t ctrl, struct nvme_get_log_args *args) -{ - return nvme_mi_admin_get_log_page(ctrl, 4096, args); -} - -static int read_ana_chunk(nvme_mi_ctrl_t ctrl, enum nvme_log_ana_lsp lsp, bool rae, - __u8 *log, __u8 **read, __u8 *to_read, __u8 *log_end) -{ - if (to_read > log_end) { - errno = ENOSPC; - return -1; - } - - while (*read < to_read) { - __u32 len = min_t(__u32, log_end - *read, NVME_LOG_PAGE_PDU_SIZE); - int ret; - - ret = nvme_mi_admin_get_log_ana(ctrl, lsp, rae, - *read - log, len, *read); - if (ret) - return ret; - - *read += len; - } - return 0; -} - -static int try_read_ana(nvme_mi_ctrl_t ctrl, enum nvme_log_ana_lsp lsp, bool rae, - struct nvme_ana_log *log, __u8 *log_end, - __u8 *read, __u8 **to_read, bool *may_retry) -{ - __u16 ngrps = le16_to_cpu(log->ngrps); - - while (ngrps--) { - __u8 *group = *to_read; - int ret; - __le32 nnsids; - - *to_read += sizeof(*log->descs); - ret = read_ana_chunk(ctrl, lsp, rae, - (__u8 *)log, &read, *to_read, log_end); - if (ret) { - /* - * If the provided buffer isn't long enough, - * the log page may have changed while reading it - * and the computed length was inaccurate. - * Have the caller check chgcnt and retry. - */ - *may_retry = errno == ENOSPC; - return ret; - } - - /* - * struct nvme_ana_group_desc has 8-byte alignment - * but the group pointer is only 4-byte aligned. - * Don't dereference the misaligned pointer. - */ - memcpy(&nnsids, - group + offsetof(struct nvme_ana_group_desc, nnsids), - sizeof(nnsids)); - *to_read += le32_to_cpu(nnsids) * sizeof(__le32); - ret = read_ana_chunk(ctrl, lsp, rae, - (__u8 *)log, &read, *to_read, log_end); - if (ret) { - *may_retry = errno == ENOSPC; - return ret; - } - } - - *may_retry = true; - return 0; -} - -int nvme_mi_admin_get_ana_log_atomic(nvme_mi_ctrl_t ctrl, bool rgo, bool rae, - unsigned int retries, - struct nvme_ana_log *log, __u32 *len) -{ - const enum nvme_log_ana_lsp lsp = - rgo ? NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY : 0; - /* Get Log Page can only fetch multiples of dwords */ - __u8 * const log_end = (__u8 *)log + (*len & -4); - __u8 *read = (__u8 *)log; - __u8 *to_read; - int ret; - - if (!retries) { - errno = EINVAL; - return -1; - } - - to_read = (__u8 *)log->descs; - ret = read_ana_chunk(ctrl, lsp, rae, - (__u8 *)log, &read, to_read, log_end); - if (ret) - return ret; - - do { - bool may_retry = false; - int saved_ret; - int saved_errno; - __le64 chgcnt; - - saved_ret = try_read_ana(ctrl, lsp, rae, log, log_end, - read, &to_read, &may_retry); - /* - * If the log page was read with multiple Get Log Page commands, - * chgcnt must be checked afterwards to ensure atomicity - */ - *len = to_read - (__u8 *)log; - if (*len <= NVME_LOG_PAGE_PDU_SIZE || !may_retry) - return saved_ret; - - saved_errno = errno; - chgcnt = log->chgcnt; - read = (__u8 *)log; - to_read = (__u8 *)log->descs; - ret = read_ana_chunk(ctrl, lsp, rae, - (__u8 *)log, &read, to_read, log_end); - if (ret) - return ret; - - if (log->chgcnt == chgcnt) { - /* Log hasn't changed; return try_read_ana() result */ - errno = saved_errno; - return saved_ret; - } - } while (--retries); - - errno = EAGAIN; - return -1; -} - -int nvme_mi_admin_security_send(nvme_mi_ctrl_t ctrl, - struct nvme_security_send_args *args) -{ - - struct nvme_mi_admin_resp_hdr resp_hdr; - struct nvme_mi_admin_req_hdr req_hdr; - struct nvme_mi_resp resp; - struct nvme_mi_req req; - int rc; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - if (args->data_len > 4096) { - errno = EINVAL; - return -1; - } - - nvme_mi_admin_init_req(ctrl->ep, &req, &req_hdr, ctrl->id, - nvme_admin_security_send); - - req_hdr.cdw10 = cpu_to_le32(args->secp << 24 | - args->spsp1 << 16 | - args->spsp0 << 8 | - args->nssf); - - req_hdr.cdw11 = cpu_to_le32(args->data_len & 0xffffffff); - - req_hdr.flags = 0x1; - req_hdr.dlen = cpu_to_le32(args->data_len & 0xffffffff); - req.data = args->data; - req.data_len = args->data_len; - - nvme_mi_admin_init_resp(&resp, &resp_hdr); - - rc = nvme_mi_submit(ctrl->ep, &req, &resp); - if (rc) - return rc; - - return nvme_mi_admin_parse_status(&resp, args->result); -} - -int nvme_mi_admin_security_recv(nvme_mi_ctrl_t ctrl, - struct nvme_security_receive_args *args) -{ - - struct nvme_mi_admin_resp_hdr resp_hdr; - struct nvme_mi_admin_req_hdr req_hdr; - struct nvme_mi_resp resp; - struct nvme_mi_req req; - int rc; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - if (args->data_len > 4096) { - errno = EINVAL; - return -1; - } - - nvme_mi_admin_init_req(ctrl->ep, &req, &req_hdr, ctrl->id, - nvme_admin_security_recv); - - req_hdr.cdw10 = cpu_to_le32(args->secp << 24 | - args->spsp1 << 16 | - args->spsp0 << 8 | - args->nssf); - - req_hdr.cdw11 = cpu_to_le32(args->data_len & 0xffffffff); - - req_hdr.flags = 0x1; - req_hdr.dlen = cpu_to_le32(args->data_len & 0xffffffff); - - nvme_mi_admin_init_resp(&resp, &resp_hdr); - resp.data = args->data; - resp.data_len = args->data_len; - - rc = nvme_mi_submit(ctrl->ep, &req, &resp); - if (rc) - return rc; - - rc = nvme_mi_admin_parse_status(&resp, args->result); - if (rc) - return rc; - - args->data_len = resp.data_len; - - return 0; -} - -int nvme_mi_admin_get_features(nvme_mi_ctrl_t ctrl, - struct nvme_get_features_args *args) -{ - struct nvme_mi_admin_resp_hdr resp_hdr; - struct nvme_mi_admin_req_hdr req_hdr; - struct nvme_mi_resp resp; - struct nvme_mi_req req; - int rc; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - nvme_mi_admin_init_req(ctrl->ep, &req, &req_hdr, ctrl->id, - nvme_admin_get_features); - - req_hdr.cdw1 = cpu_to_le32(args->nsid); - req_hdr.cdw10 = cpu_to_le32((args->sel & 0x7) << 8 | args->fid); - req_hdr.cdw14 = cpu_to_le32(args->uuidx & 0x7f); - req_hdr.cdw11 = cpu_to_le32(args->cdw11); - - nvme_mi_admin_init_resp(&resp, &resp_hdr); - resp.data = args->data; - resp.data_len = args->data_len; - - rc = nvme_mi_submit(ctrl->ep, &req, &resp); - if (rc) - return rc; - - rc = nvme_mi_admin_parse_status(&resp, args->result); - if (rc) - return rc; - - args->data_len = resp.data_len; - - return 0; -} - -static int __nvme_mi_admin_get_features(nvme_mi_ctrl_t ctrl, enum nvme_features_id fid, - enum nvme_get_features_sel sel, __u32 *result) -{ - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fid = fid, - .nsid = NVME_NSID_NONE, - .sel = sel, - .cdw11 = 0, - .uuidx = NVME_UUID_NONE, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_mi_admin_get_features(ctrl, &args); -} - -int nvme_mi_admin_get_features_arbitration(nvme_mi_ctrl_t ctrl, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_mi_admin_get_features(ctrl, NVME_FEAT_FID_ARBITRATION, sel, result); -} - -int nvme_mi_admin_get_features_power_mgmt(nvme_mi_ctrl_t ctrl, enum nvme_get_features_sel sel, - __u32 *result) -{ - return __nvme_mi_admin_get_features(ctrl, NVME_FEAT_FID_POWER_MGMT, sel, result); -} - -int nvme_mi_admin_set_features(nvme_mi_ctrl_t ctrl, - struct nvme_set_features_args *args) -{ - struct nvme_mi_admin_resp_hdr resp_hdr; - struct nvme_mi_admin_req_hdr req_hdr; - struct nvme_mi_resp resp; - struct nvme_mi_req req; - int rc; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - nvme_mi_admin_init_req(ctrl->ep, &req, &req_hdr, ctrl->id, - nvme_admin_set_features); - - req_hdr.cdw1 = cpu_to_le32(args->nsid); - req_hdr.cdw10 = cpu_to_le32((__u32)!!args->save << 31 | - (args->fid & 0xff)); - req_hdr.cdw14 = cpu_to_le32(args->uuidx & 0x7f); - req_hdr.cdw11 = cpu_to_le32(args->cdw11); - req_hdr.cdw12 = cpu_to_le32(args->cdw12); - req_hdr.cdw13 = cpu_to_le32(args->cdw13); - req_hdr.cdw15 = cpu_to_le32(args->cdw15); - - req.data_len = args->data_len; - req.data = args->data; - - nvme_mi_admin_init_resp(&resp, &resp_hdr); - - rc = nvme_mi_submit(ctrl->ep, &req, &resp); - if (rc) - return rc; - - rc = nvme_mi_admin_parse_status(&resp, args->result); - if (rc) - return rc; - - args->data_len = resp.data_len; - - return 0; -} - -static int __nvme_mi_admin_set_features(nvme_mi_ctrl_t ctrl, __u8 fid, __u32 cdw11, bool save, - __u32 *result) -{ - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .nsid = NVME_NSID_NONE, - .cdw11 = cdw11, - .cdw12 = 0, - .save = save, - .uuidx = NVME_UUID_NONE, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - return nvme_mi_admin_set_features(ctrl, &args); -} - -int nvme_mi_admin_set_features_power_mgmt(nvme_mi_ctrl_t ctrl, __u8 ps, __u8 wh, bool save, - __u32 *result) -{ - __u32 value = NVME_SET(ps, FEAT_PWRMGMT_PS) | NVME_SET(wh, FEAT_PWRMGMT_WH); - - return __nvme_mi_admin_set_features(ctrl, NVME_FEAT_FID_POWER_MGMT, value, save, result); -} - -int nvme_mi_admin_ns_mgmt(nvme_mi_ctrl_t ctrl, - struct nvme_ns_mgmt_args *args) -{ - const size_t size_v1 = sizeof_args(struct nvme_ns_mgmt_args, csi, __u64); - const size_t size_v2 = sizeof_args(struct nvme_ns_mgmt_args, data, __u64); - struct nvme_mi_admin_resp_hdr resp_hdr; - struct nvme_mi_admin_req_hdr req_hdr; - struct nvme_mi_resp resp; - struct nvme_mi_req req; - int rc; - size_t data_len; - - if (args->args_size < size_v1 || args->args_size > size_v2) { - errno = EINVAL; - return -1; - } - - nvme_mi_admin_init_req(ctrl->ep, &req, &req_hdr, ctrl->id, - nvme_admin_ns_mgmt); - - req_hdr.cdw1 = cpu_to_le32(args->nsid); - req_hdr.cdw10 = cpu_to_le32(args->sel & 0xf); - req_hdr.cdw11 = cpu_to_le32(args->csi << 24); - - if (args->args_size == size_v2) { - if (args->data) { - req.data = args->data; - data_len = sizeof(*args->data); - } - } - else { - if (args->ns) { - req.data = args->ns; - data_len = sizeof(*args->ns); - } - } - - if (req.data) { - req.data_len = data_len; - req_hdr.dlen = cpu_to_le32(data_len); - req_hdr.flags = 0x1; - } - - nvme_mi_admin_init_resp(&resp, &resp_hdr); - - rc = nvme_mi_submit(ctrl->ep, &req, &resp); - if (rc) - return rc; - - return nvme_mi_admin_parse_status(&resp, args->result); -} - -int nvme_mi_admin_ns_attach(nvme_mi_ctrl_t ctrl, - struct nvme_ns_attach_args *args) -{ - struct nvme_mi_admin_resp_hdr resp_hdr; - struct nvme_mi_admin_req_hdr req_hdr; - struct nvme_mi_resp resp; - struct nvme_mi_req req; - int rc; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - nvme_mi_admin_init_req(ctrl->ep, &req, &req_hdr, ctrl->id, - nvme_admin_ns_attach); - - req_hdr.cdw1 = cpu_to_le32(args->nsid); - req_hdr.cdw10 = cpu_to_le32(args->sel & 0xf); - req.data = args->ctrlist; - req.data_len = sizeof(*args->ctrlist); - req_hdr.dlen = cpu_to_le32(sizeof(*args->ctrlist)); - req_hdr.flags = 0x1; - - nvme_mi_admin_init_resp(&resp, &resp_hdr); - - rc = nvme_mi_submit(ctrl->ep, &req, &resp); - if (rc) - return rc; - - return nvme_mi_admin_parse_status(&resp, args->result); -} - -int nvme_mi_admin_fw_download(nvme_mi_ctrl_t ctrl, - struct nvme_fw_download_args *args) -{ - struct nvme_mi_admin_resp_hdr resp_hdr; - struct nvme_mi_admin_req_hdr req_hdr; - struct nvme_mi_resp resp; - struct nvme_mi_req req; - int rc; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - if ((args->data_len & 0x3) || (!args->data_len)) { - errno = EINVAL; - return -1; - } - - if (args->offset & 0x3) { - errno = EINVAL; - return -1; - } - - nvme_mi_admin_init_req(ctrl->ep, &req, &req_hdr, ctrl->id, - nvme_admin_fw_download); - - req_hdr.cdw10 = cpu_to_le32((args->data_len >> 2) - 1); - req_hdr.cdw11 = cpu_to_le32(args->offset >> 2); - req.data = args->data; - req.data_len = args->data_len; - req_hdr.dlen = cpu_to_le32(args->data_len); - req_hdr.flags = 0x1; - - nvme_mi_admin_init_resp(&resp, &resp_hdr); - - rc = nvme_mi_submit(ctrl->ep, &req, &resp); - if (rc) - return rc; - - return nvme_mi_admin_parse_status(&resp, NULL); -} - -int nvme_mi_admin_fw_commit(nvme_mi_ctrl_t ctrl, - struct nvme_fw_commit_args *args) -{ - struct nvme_mi_admin_resp_hdr resp_hdr; - struct nvme_mi_admin_req_hdr req_hdr; - struct nvme_mi_resp resp; - struct nvme_mi_req req; - int rc; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - nvme_mi_admin_init_req(ctrl->ep, &req, &req_hdr, ctrl->id, - nvme_admin_fw_commit); - - req_hdr.cdw10 = cpu_to_le32(((__u32)(args->bpid & 0x1) << 31) | - ((args->action & 0x7) << 3) | - ((args->slot & 0x7) << 0)); - - nvme_mi_admin_init_resp(&resp, &resp_hdr); - - rc = nvme_mi_submit(ctrl->ep, &req, &resp); - if (rc) - return rc; - - return nvme_mi_admin_parse_status(&resp, NULL); -} - -int nvme_mi_admin_format_nvm(nvme_mi_ctrl_t ctrl, - struct nvme_format_nvm_args *args) -{ - struct nvme_mi_admin_resp_hdr resp_hdr; - struct nvme_mi_admin_req_hdr req_hdr; - struct nvme_mi_resp resp; - struct nvme_mi_req req; - int rc; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - nvme_mi_admin_init_req(ctrl->ep, &req, &req_hdr, ctrl->id, - nvme_admin_format_nvm); - - req_hdr.cdw1 = cpu_to_le32(args->nsid); - req_hdr.cdw10 = cpu_to_le32(((args->lbafu & 0x3) << 12) - | ((args->ses & 0x7) << 9) - | ((args->pil & 0x1) << 8) - | ((args->pi & 0x7) << 5) - | ((args->mset & 0x1) << 4) - | ((args->lbaf & 0xf) << 0)); - - nvme_mi_admin_init_resp(&resp, &resp_hdr); - - rc = nvme_mi_submit(ctrl->ep, &req, &resp); - if (rc) - return rc; - - return nvme_mi_admin_parse_status(&resp, args->result); -} - -int nvme_mi_admin_sanitize_nvm(nvme_mi_ctrl_t ctrl, - struct nvme_sanitize_nvm_args *args) -{ - struct nvme_mi_admin_resp_hdr resp_hdr; - struct nvme_mi_admin_req_hdr req_hdr; - struct nvme_mi_resp resp; - struct nvme_mi_req req; - int rc; - - if (args->args_size < sizeof(*args)) { - errno = EINVAL; - return -1; - } - - nvme_mi_admin_init_req(ctrl->ep, &req, &req_hdr, ctrl->id, - nvme_admin_sanitize_nvm); - - req_hdr.cdw10 = cpu_to_le32(((args->nodas ? 1 : 0) << 9) - | ((args->oipbp ? 1 : 0) << 8) - | ((args->owpass & 0xf) << 4) - | ((args->ause ? 1 : 0) << 3) - | ((args->sanact & 0x7) << 0)); - req_hdr.cdw11 = cpu_to_le32(args->ovrpat); - - nvme_mi_admin_init_resp(&resp, &resp_hdr); - - rc = nvme_mi_submit(ctrl->ep, &req, &resp); - if (rc) - return rc; - - return nvme_mi_admin_parse_status(&resp, args->result); -} - static void nvme_mi_mi_init_req(nvme_mi_ep_t ep, struct nvme_mi_req *req, struct nvme_mi_mi_req_hdr *hdr, @@ -1795,10 +1045,8 @@ int nvme_mi_mi_xfer(nvme_mi_ep_t ep, * to the requirements of the particular command set */ - if (*resp_data_size > mi_data_xfer_size_limit) { - errno = EINVAL; - return -1; - } + if (*resp_data_size > mi_data_xfer_size_limit) + return -EINVAL; mi_req->hdr.type = NVME_MI_MSGTYPE_NVME; mi_req->hdr.nmp = (NVME_MI_ROR_REQ << 7) | @@ -1841,12 +1089,11 @@ int nvme_mi_mi_read_mi_data_subsys(nvme_mi_ep_t ep, return rc; if (len != sizeof(*s)) { - nvme_msg(ep->root, LOG_WARNING, + nvme_msg(ep->ctx, LOG_WARNING, "MI read data length mismatch: " "got %zd bytes, expected %zd\n", len, sizeof(*s)); - errno = EPROTO; - return -1; + return -EPROTO; } return 0; @@ -1866,10 +1113,8 @@ int nvme_mi_mi_read_mi_data_port(nvme_mi_ep_t ep, __u8 portid, if (rc) return rc; - if (len != sizeof(*p)) { - errno = EPROTO; - return -1; - } + if (len != sizeof(*p)) + return -EPROTO; return 0; } @@ -1905,10 +1150,8 @@ int nvme_mi_mi_read_mi_data_ctrl(nvme_mi_ep_t ep, __u16 ctrl_id, if (rc) return rc; - if (len != sizeof(*ctrl)) { - errno = EPROTO; - return -1; - } + if (len != sizeof(*ctrl)) + return -EPROTO; return 0; } @@ -1940,12 +1183,11 @@ int nvme_mi_mi_subsystem_health_status_poll(nvme_mi_ep_t ep, bool clear, return resp_hdr.status; if (resp.data_len != sizeof(*sshs)) { - nvme_msg(ep->root, LOG_WARNING, + nvme_msg(ep->ctx, LOG_WARNING, "MI Subsystem Health Status length mismatch: " "got %zd bytes, expected %zd\n", resp.data_len, sizeof(*sshs)); - errno = EPROTO; - return -1; + return -EPROTO; } return 0; @@ -2066,22 +1308,17 @@ int nvme_mi_mi_config_set_async_event(nvme_mi_ep_t ep, ((__u32)aemd << 16) | ((__u16) aerd << 8) | NVME_MI_CONFIG_AE; - //Basic checks here on lengths + // Basic checks here on lengths if (enable_list_size < sizeof(struct nvme_mi_aem_enable_list) || - (sizeof(struct nvme_mi_aem_enable_list) + - enable_list->hdr.numaee * sizeof(struct nvme_mi_aem_enable_item) - > enable_list_size) - ) { - errno = EINVAL; - return -1; - } + (sizeof(struct nvme_mi_aem_enable_list) + + enable_list->hdr.numaee * sizeof(struct nvme_mi_aem_enable_item) + > enable_list_size)) + return -EINVAL; - //Some very baseic header checks + // Some very baseic header checks if (enable_list->hdr.aeelhl != sizeof(struct nvme_mi_aem_enable_list_header) || - enable_list->hdr.aeelver != 0) { - errno = EINVAL; - return -1; - } + enable_list->hdr.aeelver != 0) + return -EINVAL; return nvme_mi_mi_config_set_get_ex(ep, nvme_mi_mi_opcode_configuration_set, @@ -2097,13 +1334,13 @@ int nvme_mi_mi_config_set_async_event(nvme_mi_ep_t ep, void nvme_mi_close(nvme_mi_ep_t ep) { - struct nvme_mi_ctrl *ctrl, *tmp; + struct nvme_transport_handle *hdl, *tmp; /* don't look for controllers during destruction */ ep->controllers_scanned = true; - nvme_mi_for_each_ctrl_safe(ep, ctrl, tmp) - nvme_mi_close_ctrl(ctrl); + nvme_mi_for_each_transport_handle_safe(ep, hdl, tmp) + nvme_close(hdl); if (ep->transport && ep->transport->close) ep->transport->close(ep); @@ -2111,12 +1348,6 @@ void nvme_mi_close(nvme_mi_ep_t ep) free(ep); } -void nvme_mi_close_ctrl(nvme_mi_ctrl_t ctrl) -{ - list_del(&ctrl->ep_entry); - free(ctrl); -} - char *nvme_mi_endpoint_desc(nvme_mi_ep_t ep) { char tsbuf[101], *s = NULL; @@ -2147,27 +1378,27 @@ char *nvme_mi_endpoint_desc(nvme_mi_ep_t ep) return s; } -nvme_mi_ep_t nvme_mi_first_endpoint(nvme_root_t m) +nvme_mi_ep_t nvme_mi_first_endpoint(struct nvme_global_ctx *ctx) { - return list_top(&m->endpoints, struct nvme_mi_ep, root_entry); + return list_top(&ctx->endpoints, struct nvme_mi_ep, root_entry); } -nvme_mi_ep_t nvme_mi_next_endpoint(nvme_root_t m, nvme_mi_ep_t ep) +nvme_mi_ep_t nvme_mi_next_endpoint(struct nvme_global_ctx *ctx, nvme_mi_ep_t ep) { - return ep ? list_next(&m->endpoints, ep, root_entry) : NULL; + return ep ? list_next(&ctx->endpoints, ep, root_entry) : NULL; } -nvme_mi_ctrl_t nvme_mi_first_ctrl(nvme_mi_ep_t ep) +struct nvme_transport_handle *nvme_mi_first_transport_handle(nvme_mi_ep_t ep) { - return list_top(&ep->controllers, struct nvme_mi_ctrl, ep_entry); + return list_top(&ep->controllers, struct nvme_transport_handle, ep_entry); } -nvme_mi_ctrl_t nvme_mi_next_ctrl(nvme_mi_ep_t ep, nvme_mi_ctrl_t c) +struct nvme_transport_handle *nvme_mi_next_transport_handle(nvme_mi_ep_t ep, + struct nvme_transport_handle *hdl) { - return c ? list_next(&ep->controllers, c, ep_entry) : NULL; + return hdl ? list_next(&ep->controllers, hdl, ep_entry) : NULL; } - static const char *const mi_status[] = { [NVME_MI_RESP_MPR] = "More Processing Required: The command message is in progress and requires more time to complete processing", [NVME_MI_RESP_INTERNAL_ERR] = "Internal Error: The request message could not be processed due to a vendor-specific error", @@ -2273,19 +1504,14 @@ void nvme_mi_aem_aeolli_set_aeoltl(struct nvme_mi_aem_occ_list_hdr *hdr, __u32 a static int validate_enabled_list(struct nvme_mi_aem_supported_list *list, size_t len) { - if (list->hdr.aeslver != 0) { - errno = EPROTO; - return -1; - } - if (list->hdr.aeslhl != sizeof(struct nvme_mi_aem_supported_list)) { - errno = EPROTO; - return -1; - } + if (list->hdr.aeslver != 0) + return -EPROTO; + if (list->hdr.aeslhl != sizeof(struct nvme_mi_aem_supported_list)) + return -EPROTO; if (list->hdr.aest > len || list->hdr.aest != list->hdr.aeslhl + list->hdr.numaes * sizeof(struct nvme_mi_aem_supported_item)) { - errno = EPROTO; - return -1; + return -EPROTO; } return 0; } @@ -2295,18 +1521,20 @@ static int validate_occ_list_update_ctx( struct nvme_mi_aem_ctx *ctx, bool check_generation_num) { + int err; + //Make sure header fields have valid data if (len < sizeof(*occ_header)) { - errno = EPROTO; + err = -EPROTO; goto err_cleanup; } else if (occ_header->aelver != 0 || occ_header->aeolhl != sizeof(*occ_header)) { //Make sure header is the right version and length - errno = EPROTO; + err = -EPROTO; goto err_cleanup; } else if (nvme_mi_aem_aeolli_get_aeoltl(occ_header->aeolli) > len) { //Full length is bigger than the data that was received - errno = EPROTO; + err = -EPROTO; goto err_cleanup; } else if (check_generation_num && ctx->last_generation_num == @@ -2334,11 +1562,11 @@ static int validate_occ_list_update_ctx( for (int i = 0; i < occ_header->numaeo; i++) { //Validate this item if (current->aelhlen != sizeof(*current)) { - errno = EPROTO; + err = -EPROTO; goto err_cleanup; } else if (!ctx->callbacks.enabled_map.enabled[current->aeoui.aeoi]) { //This is unexpected as this AE shouldn't be enabled - errno = EPROTO; + err = -EPROTO; goto err_cleanup; } @@ -2347,7 +1575,7 @@ static int validate_occ_list_update_ctx( bytes_so_far += offset; if (bytes_so_far > nvme_mi_aem_aeolli_get_aeoltl(occ_header->aeolli)) { - errno = EPROTO; + err = -EPROTO; goto err_cleanup; } @@ -2357,7 +1585,7 @@ static int validate_occ_list_update_ctx( return 0; err_cleanup: - return -1; + return err; } int nvme_mi_aem_get_fd(nvme_mi_ep_t ep) diff --git a/libnvme/src/nvme/mi.h b/libnvme/src/nvme/mi.h index 52190636dd..813427d393 100644 --- a/libnvme/src/nvme/mi.h +++ b/libnvme/src/nvme/mi.h @@ -655,36 +655,36 @@ struct nvme_mi_control_resp { const char *nvme_mi_status_to_string(int status); /** - * nvme_mi_create_root() - Create top-level MI (root) handle. + * nvme_mi_create_global_ctx() - Create top-level MI (ctx) handle. * @fp: File descriptor for logging messages * @log_level: Logging level to use * * Create the top-level (library) handle for creating subsequent endpoint - * objects. Similar to nvme_create_root(), but we provide this to allow linking - * without the core libnvme. + * objects. Similar to nvme_create_global_ctx(), but we provide this to + * allow linking without the core libnvme. * - * Return: new root object, or NULL on failure. + * Return: new nvme_global_ctx object, or NULL on failure. * - * See &nvme_create_root. + * See &nvme_create_global_ctx. */ -nvme_root_t nvme_mi_create_root(FILE *fp, int log_level); +struct nvme_global_ctx *nvme_mi_create_global_ctx(FILE *fp, int log_level); /** - * nvme_mi_free_root() - Free root object. - * @root: root to free + * nvme_mi_free_global_ctx() - Free nvme_global_ctx object. + * @ctx: &struct nvme_global_ctx object */ -void nvme_mi_free_root(nvme_root_t root); +void nvme_mi_free_global_ctx(struct nvme_global_ctx *ctx); /** * nvme_mi_set_probe_enabled() - enable/disable the probe for new endpoints - * @root: &nvme_root_t object + * @ctx: &struct nvme_global_ctx object * @enabled: whether to probe new endpoints * * Controls whether newly-created endpoints are probed for quirks on creation. * Defaults to enabled, which results in some initial messaging with the * endpoint to determine model-specific details. */ -void nvme_mi_set_probe_enabled(nvme_root_t root, bool enabled); +void nvme_mi_set_probe_enabled(struct nvme_global_ctx *ctx, bool enabled); /* Top level management object: NVMe-MI Management Endpoint */ struct nvme_mi_ep; @@ -716,18 +716,18 @@ int nvme_mi_set_csi(nvme_mi_ep_t ep, uint8_t csi); /** * nvme_mi_first_endpoint - Start endpoint iterator - * @m: &nvme_root_t object + * @ctx: &struct nvme_global_ctx object * * Return: first MI endpoint object under this root, or NULL if no endpoints * are present. * * See: &nvme_mi_next_endpoint, &nvme_mi_for_each_endpoint */ -nvme_mi_ep_t nvme_mi_first_endpoint(nvme_root_t m); +nvme_mi_ep_t nvme_mi_first_endpoint(struct nvme_global_ctx *ctx); /** * nvme_mi_next_endpoint - Continue endpoint iterator - * @m: &nvme_root_t object + * @ctx: &struct nvme_global_ctx object * @e: &nvme_mi_ep_t current position of iterator * * Return: next endpoint MI endpoint object after @e under this root, or NULL @@ -735,28 +735,28 @@ nvme_mi_ep_t nvme_mi_first_endpoint(nvme_root_t m); * * See: &nvme_mi_first_endpoint, &nvme_mi_for_each_endpoint */ -nvme_mi_ep_t nvme_mi_next_endpoint(nvme_root_t m, nvme_mi_ep_t e); +nvme_mi_ep_t nvme_mi_next_endpoint(struct nvme_global_ctx *ctx, nvme_mi_ep_t e); /** * nvme_mi_for_each_endpoint - Iterator for NVMe-MI endpoints. - * @m: &nvme_root_t containing endpoints + * @c: &struct nvme_global_ctx object * @e: &nvme_mi_ep_t object, set on each iteration */ -#define nvme_mi_for_each_endpoint(m, e) \ - for (e = nvme_mi_first_endpoint(m); e != NULL; \ - e = nvme_mi_next_endpoint(m, e)) +#define nvme_mi_for_each_endpoint(c, e) \ + for (e = nvme_mi_first_endpoint(c); e != NULL; \ + e = nvme_mi_next_endpoint(c, e)) /** * nvme_mi_for_each_endpoint_safe - Iterator for NVMe-MI endpoints, allowing * deletion during traversal - * @m: &nvme_root_t containing endpoints + * @c: &struct nvme_global_ctx object * @e: &nvme_mi_ep_t object, set on each iteration * @_e: &nvme_mi_ep_t object used as temporary storage */ -#define nvme_mi_for_each_endpoint_safe(m, e, _e) \ - for (e = nvme_mi_first_endpoint(m), _e = nvme_mi_next_endpoint(m, e); \ +#define nvme_mi_for_each_endpoint_safe(c, e, _e) \ + for (e = nvme_mi_first_endpoint(c), _e = nvme_mi_next_endpoint(c, e); \ e != NULL; \ - e = _e, _e = nvme_mi_next_endpoint(m, e)) + e = _e, _e = nvme_mi_next_endpoint(c, e)) /** * nvme_mi_ep_set_timeout - set a timeout for NVMe-MI responses @@ -791,42 +791,34 @@ void nvme_mi_ep_set_mprt_max(nvme_mi_ep_t ep, unsigned int mprt_max_ms); */ unsigned int nvme_mi_ep_get_timeout(nvme_mi_ep_t ep); -struct nvme_mi_ctrl; - -/** - * typedef nvme_mi_ctrl_t - NVMe-MI Controller object. - * - * Provides NVMe command functionality, through the MI interface. - */ -typedef struct nvme_mi_ctrl * nvme_mi_ctrl_t; - /** - * nvme_mi_first_ctrl - Start controller iterator + * nvme_mi_first_transport_handle - Start transport handle iterator * @ep: &nvme_mi_ep_t object * - * Return: first MI controller object under this root, or NULL if no controllers - * are present. + * Return: first transport handle to a MI controller object under this + * root, or NULL if no controllers are present. * - * See: &nvme_mi_next_ctrl, &nvme_mi_for_each_ctrl + * See: &nvme_mi_next_transport_handle, &nvme_mi_for_each_transport_handle */ -nvme_mi_ctrl_t nvme_mi_first_ctrl(nvme_mi_ep_t ep); +struct nvme_transport_handle *nvme_mi_first_transport_handle(nvme_mi_ep_t ep); /** - * nvme_mi_next_ctrl - Continue ctrl iterator + * nvme_mi_next_transport_handle - Continue transport handle iterator * @ep: &nvme_mi_ep_t object - * @c: &nvme_mi_ctrl_t current position of iterator + * @hdl: &nvme_transport_handle current position of iterator * - * Return: next MI controller object after @c under this endpoint, or NULL - * if no further controllers are present. + * Return: next transport handle to MI controller object after @c under + * this endpoint, or NULL if no further controllers are present. * - * See: &nvme_mi_first_ctrl, &nvme_mi_for_each_ctrl + * See: &nvme_mi_first_transport_handle, &nvme_mi_for_each_transport_handle */ -nvme_mi_ctrl_t nvme_mi_next_ctrl(nvme_mi_ep_t ep, nvme_mi_ctrl_t c); +struct nvme_transport_handle *nvme_mi_next_transport_handle(nvme_mi_ep_t ep, + struct nvme_transport_handle *hdl); /** - * nvme_mi_for_each_ctrl - Iterator for NVMe-MI controllers. + * nvme_mi_for_each_transport_handle - Iterator for transport handle to NVMe-MI controllers. * @ep: &nvme_mi_ep_t containing endpoints - * @c: &nvme_mi_ctrl_t object, set on each iteration + * @hdl: &nvme_trasnport_handle object, set on each iteration * * Allows iteration of the list of controllers behind an endpoint. Unless the * controllers have already been created explicitly, you'll probably want to @@ -834,16 +826,16 @@ nvme_mi_ctrl_t nvme_mi_next_ctrl(nvme_mi_ep_t ep, nvme_mi_ctrl_t c); * * See: &nvme_mi_scan_ep() */ -#define nvme_mi_for_each_ctrl(ep, c) \ - for (c = nvme_mi_first_ctrl(ep); c != NULL; \ - c = nvme_mi_next_ctrl(ep, c)) +#define nvme_mi_for_each_transport_handle(ep, hdl) \ + for (hdl = nvme_mi_first_transport_handle(ep); hdl != NULL; \ + hdl = nvme_mi_next_transport_handle(ep, hdl)) /** - * nvme_mi_for_each_ctrl_safe - Iterator for NVMe-MI controllers, allowing + * nvme_mi_for_each_transport_handle_safe - Iterator for transport handle to NVMe-MI controllers, allowing * deletion during traversal * @ep: &nvme_mi_ep_t containing controllers - * @c: &nvme_mi_ctrl_t object, set on each iteration - * @_c: &nvme_mi_ctrl_t object used as temporary storage + * @hdl: &nvme_transport_handle object, set on each iteration + * @_hdl: &nvme_transport_handle object used as temporary storage * * Allows iteration of the list of controllers behind an endpoint, safe against * deletion during iteration. Unless the controllers have already been created @@ -852,14 +844,15 @@ nvme_mi_ctrl_t nvme_mi_next_ctrl(nvme_mi_ep_t ep, nvme_mi_ctrl_t c); * * See: &nvme_mi_scan_ep() */ -#define nvme_mi_for_each_ctrl_safe(ep, c, _c) \ - for (c = nvme_mi_first_ctrl(ep), _c = nvme_mi_next_ctrl(ep, c); \ - c != NULL; \ - c = _c, _c = nvme_mi_next_ctrl(ep, c)) +#define nvme_mi_for_each_transport_handle_safe(ep, hdl, _hdl) \ + for (hdl = nvme_mi_first_transport_handle(ep), \ + _hdl = nvme_mi_next_transport_handle(ep, hdl); \ + hdl != NULL; \ + hdl = _hdl, _hdl = nvme_mi_next_transport_handle(ep, hdl)) /** * nvme_mi_open_mctp() - Create an endpoint using a MCTP connection. - * @root: root object to create under + * @ctx: &struct nvme_global_ctx object * @netid: MCTP network ID on this system * @eid: MCTP endpoint ID * @@ -870,7 +863,8 @@ nvme_mi_ctrl_t nvme_mi_next_ctrl(nvme_mi_ep_t ep, nvme_mi_ctrl_t c); * * See &nvme_mi_close */ -nvme_mi_ep_t nvme_mi_open_mctp(nvme_root_t root, unsigned int netid, uint8_t eid); +nvme_mi_ep_t nvme_mi_open_mctp(struct nvme_global_ctx *ctx, + unsigned int netid, uint8_t eid); /** * nvme_mi_aem_open() - Prepare an existing endpoint to receive AEMs @@ -897,10 +891,10 @@ void nvme_mi_close(nvme_mi_ep_t ep); * This requires libvnme-mi to be compiled with D-Bus support; if not, this * will return NULL. * - * Return: A @nvme_root_t populated with a set of MCTP-connected endpoints, - * or NULL on failure + * Return: A @struct nvme_global_ctx populated with a set of + * MCTP-connected endpoints, or NULL on failure */ -nvme_root_t nvme_mi_scan_mctp(void); +struct nvme_global_ctx *nvme_mi_scan_mctp(void); /** * nvme_mi_scan_ep - query an endpoint for its NVMe controllers. @@ -924,7 +918,7 @@ nvme_root_t nvme_mi_scan_mctp(void); int nvme_mi_scan_ep(nvme_mi_ep_t ep, bool force_rescan); /** - * nvme_mi_init_ctrl() - initialise a NVMe controller. + * nvme_mi_init_transport_handle() - initialise a transport handle to NVMe controller. * @ep: Endpoint to create under * @ctrl_id: ID of controller to initialize. * @@ -932,31 +926,24 @@ int nvme_mi_scan_ep(nvme_mi_ep_t ep, bool force_rescan); * Controller IDs may be queried from the endpoint through * &nvme_mi_mi_read_mi_data_ctrl_list. * - * Return: New controller object, or NULL on failure. + * Return: New transport handle object, or NULL on failure. * - * See &nvme_mi_close_ctrl - */ -nvme_mi_ctrl_t nvme_mi_init_ctrl(nvme_mi_ep_t ep, __u16 ctrl_id); - -/** - * nvme_mi_close_ctrl() - free a controller - * @ctrl: controller to free + * See &nvme_mi_close_transport_handle */ -void nvme_mi_close_ctrl(nvme_mi_ctrl_t ctrl); +struct nvme_transport_handle *nvme_mi_init_transport_handle(nvme_mi_ep_t ep, __u16 ctrl_id); /** * nvme_mi_ctrl_id() - get the ID of a controller - * @ctrl: controller to query + * @hdl: transport handle to controller to query * * Retrieve the ID of the controller, as defined by hardware, and available * in the Identify (Controller List) data. This is the value passed to - * @nvme_mi_init_ctrl, but may have been created internally via + * @nvme_mi_init_transport_handle, but may have been created internally via * @nvme_mi_scan_ep. * * Return: the (locally-stored) ID of this controller. */ -__u16 nvme_mi_ctrl_id(nvme_mi_ctrl_t ctrl); - +__u16 nvme_mi_ctrl_id(struct nvme_transport_handle *hdl); /** * nvme_mi_endpoint_desc - Get a string describing a MI endpoint. @@ -1342,7 +1329,7 @@ static inline int nvme_mi_aem_ack(nvme_mi_ep_t ep, /** * nvme_mi_admin_xfer() - Raw admin transfer interface. - * @ctrl: controller to send the admin command to + * @hdl: transport handle to send the admin command to * @admin_req: request data * @req_data_size: size of request data payload * @admin_resp: buffer for response data @@ -1367,7 +1354,7 @@ static inline int nvme_mi_aem_ack(nvme_mi_ep_t ep, * Return: The nvme command status if a response was received (see * &enum nvme_status_field) or -1 with errno set otherwise.. */ -int nvme_mi_admin_xfer(nvme_mi_ctrl_t ctrl, +int nvme_mi_admin_xfer(struct nvme_transport_handle *hdl, struct nvme_mi_admin_req_hdr *admin_req, size_t req_data_size, struct nvme_mi_admin_resp_hdr *admin_resp, @@ -1376,7 +1363,7 @@ int nvme_mi_admin_xfer(nvme_mi_ctrl_t ctrl, /** * nvme_mi_admin_admin_passthru() - Submit an nvme admin passthrough command - * @ctrl: Controller to send command to + * @hdl: Transport handle to send command to * @opcode: The nvme admin command to send * @flags: NVMe command flags (not used) * @rsvd: Reserved for future use @@ -1407,68 +1394,13 @@ int nvme_mi_admin_xfer(nvme_mi_ctrl_t ctrl, * Return: The nvme command status if a response was received (see * &enum nvme_status_field) or -1 with errno set otherwise. */ -int nvme_mi_admin_admin_passthru(nvme_mi_ctrl_t ctrl, __u8 opcode, __u8 flags, +int nvme_mi_admin_admin_passthru(struct nvme_transport_handle *hdl, __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_mi_admin_identify_partial() - Perform an Admin identify command, - * and retrieve partial response data. - * @ctrl: Controller to process identify command - * @args: Identify command arguments - * @offset: offset of identify data to retrieve from response - * @size: size of identify data to return - * - * Perform an Identify command, using the Identify command parameters in @args. - * The @offset and @size arguments allow the caller to retrieve part of - * the identify response. See NVMe-MI section 6.2 for the semantics (and some - * handy diagrams) of the offset & size parameters. - * - * Will return an error if the length of the response data (from the controller) - * did not match @size. - * - * Unless you're performing a vendor-unique identify command, You'll probably - * want to use one of the identify helpers (nvme_mi_admin_identify, - * nvme_mi_admin_identify_cns_nsid, or nvme_mi_admin_identify_) instead - * of this. If the type of your identify command is standardized but not - * yet supported by libnvme-mi, please contact the maintainers. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - * - * See: &struct nvme_identify_args - */ -int nvme_mi_admin_identify_partial(nvme_mi_ctrl_t ctrl, - struct nvme_identify_args *args, - off_t offset, size_t size); - -/** - * nvme_mi_admin_identify() - Perform an Admin identify command. - * @ctrl: Controller to process identify command - * @args: Identify command arguments - * - * Perform an Identify command, using the Identify command parameters in @args. - * Stores the identify data in ->data, and (if set) the result from cdw0 - * into args->result. - * - * Will return an error if the length of the response data (from the - * controller) is not a full &NVME_IDENTIFY_DATA_SIZE. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - * - * See: &struct nvme_identify_args - */ -static inline int nvme_mi_admin_identify(nvme_mi_ctrl_t ctrl, - struct nvme_identify_args *args) -{ - return nvme_mi_admin_identify_partial(ctrl, args, - 0, NVME_IDENTIFY_DATA_SIZE); -} - /** * nvme_mi_control() - Perform a Control Primitive command * @ep: endpoint for MI communication @@ -1487,1961 +1419,6 @@ static inline int nvme_mi_admin_identify(nvme_mi_ctrl_t ctrl, int nvme_mi_control(nvme_mi_ep_t ep, __u8 opcode, __u16 cpsp, __u16 *result_cpsr); -/** - * nvme_mi_admin_identify_cns_nsid() - Perform an Admin identify command using - * specific CNS/NSID parameters. - * @ctrl: Controller to process identify command - * @cns: Controller or Namespace Structure, specifying identified object - * @nsid: namespace ID - * @data: buffer for identify data response - * - * Perform an Identify command, using the CNS specifier @cns, and the - * namespace ID @nsid if required by the CNS type. - * - * Stores the identify data in @data, which is expected to be a buffer of - * &NVME_IDENTIFY_DATA_SIZE bytes. - * - * Will return an error if the length of the response data (from the - * controller) is not a full &NVME_IDENTIFY_DATA_SIZE. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_identify_cns_nsid(nvme_mi_ctrl_t ctrl, - enum nvme_identify_cns cns, - __u32 nsid, void *data) -{ - struct nvme_identify_args args = { - .result = NULL, - .data = data, - .args_size = sizeof(args), - .cns = cns, - .csi = NVME_CSI_NVM, - .nsid = nsid, - .cntid = NVME_CNTLID_NONE, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_mi_admin_identify(ctrl, &args); -} - -/** - * nvme_mi_admin_identify_ns() - Perform an Admin identify command for a - * namespace - * @ctrl: Controller to process identify command - * @nsid: namespace ID - * @ns: Namespace identification to populate - * - * Perform an Identify (namespace) command, setting the namespace id data - * in @ns. The namespace is expected to active and allocated. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_identify_ns(nvme_mi_ctrl_t ctrl, __u32 nsid, - struct nvme_id_ns *ns) -{ - return nvme_mi_admin_identify_cns_nsid(ctrl, NVME_IDENTIFY_CNS_NS, - nsid, ns); -} - -/** - * nvme_mi_admin_identify_ns_descs() - Perform an Admin identify Namespace - * Identification Descriptor list command for a namespace - * @ctrl: Controller to process identify command - * @nsid: Namespace ID - * @descs: Namespace Identification Descriptor list to populate - * - * Perform an Identify namespace identification description list command, - * setting the namespace identification description list in @descs - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_identify_ns_descs(nvme_mi_ctrl_t ctrl, - __u32 nsid, - struct nvme_ns_id_desc *descs) -{ - return nvme_mi_admin_identify_cns_nsid(ctrl, NVME_IDENTIFY_CNS_NS_DESC_LIST, - nsid, descs); -} - -/** - * nvme_mi_admin_identify_allocated_ns() - Perform an Admin identify command - * for an allocated namespace - * @ctrl: Controller to process identify command - * @nsid: namespace ID - * @ns: Namespace identification to populate - * - * Perform an Identify (namespace) command, setting the namespace id data - * in @ns. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_identify_allocated_ns(nvme_mi_ctrl_t ctrl, - __u32 nsid, - struct nvme_id_ns *ns) -{ - return nvme_mi_admin_identify_cns_nsid(ctrl, - NVME_IDENTIFY_CNS_ALLOCATED_NS, - nsid, ns); -} - -/** - * nvme_mi_admin_identify_ctrl() - Perform an Admin identify for a controller - * @ctrl: Controller to process identify command - * @id: Controller identify data to populate - * - * Perform an Identify command, for the controller specified by @ctrl, - * writing identify data to @id. - * - * Will return an error if the length of the response data (from the - * controller) is not a full &NVME_IDENTIFY_DATA_SIZE, so @id will be - * fully populated on success. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - * - * See: &struct nvme_id_ctrl - */ -static inline int nvme_mi_admin_identify_ctrl(nvme_mi_ctrl_t ctrl, - struct nvme_id_ctrl *id) -{ - return nvme_mi_admin_identify_cns_nsid(ctrl, NVME_IDENTIFY_CNS_CTRL, - NVME_NSID_NONE, id); -} - -/** - * nvme_mi_admin_identify_ctrl_list() - Perform an Admin identify for a - * controller list. - * @ctrl: Controller to process identify command - * @cntid: Controller ID to specify list start - * @list: List data to populate - * - * Perform an Identify command, for the controller list starting with - * IDs greater than or equal to @cntid. - * - * Will return an error if the length of the response data (from the - * controller) is not a full &NVME_IDENTIFY_DATA_SIZE, so @id will be - * fully populated on success. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - * - * See: &struct nvme_ctrl_list - */ -static inline int nvme_mi_admin_identify_ctrl_list(nvme_mi_ctrl_t ctrl, - __u16 cntid, - struct nvme_ctrl_list *list) -{ - struct nvme_identify_args args = { - .result = NULL, - .data = list, - .args_size = sizeof(args), - .cns = NVME_IDENTIFY_CNS_CTRL_LIST, - .csi = NVME_CSI_NVM, - .nsid = NVME_NSID_NONE, - .cntid = cntid, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_mi_admin_identify(ctrl, &args); -} - -/** - * nvme_mi_admin_identify_nsid_ctrl_list() - Perform an Admin identify for a - * controller list with specific namespace ID - * @ctrl: Controller to process identify command - * @nsid: Namespace identifier - * @cntid: Controller ID to specify list start - * @list: List data to populate - * - * Perform an Identify command, for the controller list for @nsid, starting - * with IDs greater than or equal to @cntid. - * - * Will return an error if the length of the response data (from the - * controller) is not a full &NVME_IDENTIFY_DATA_SIZE, so @id will be - * fully populated on success. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - * - * See: &struct nvme_ctrl_list - */ -static inline int nvme_mi_admin_identify_nsid_ctrl_list(nvme_mi_ctrl_t ctrl, - __u32 nsid, __u16 cntid, - struct nvme_ctrl_list *list) -{ - struct nvme_identify_args args = { - .result = NULL, - .data = list, - .args_size = sizeof(args), - .cns = NVME_IDENTIFY_CNS_NS_CTRL_LIST, - .csi = NVME_CSI_NVM, - .nsid = nsid, - .cntid = cntid, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_mi_admin_identify(ctrl, &args); -} - -/** - * nvme_mi_admin_identify_allocated_ns_list() - Perform an Admin identify for - * an allocated namespace list - * @ctrl: Controller to process identify command - * @nsid: Namespace ID to specify list start - * @list: List data to populate - * - * Perform an Identify command, for the allocated namespace list starting with - * IDs greater than or equal to @nsid. Specify &NVME_NSID_NONE for the start - * of the list. - * - * Will return an error if the length of the response data (from the - * controller) is not a full &NVME_IDENTIFY_DATA_SIZE, so @list will be - * be fully populated on success. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - * - * See: &struct nvme_ns_list - */ -static inline int nvme_mi_admin_identify_allocated_ns_list(nvme_mi_ctrl_t ctrl, - __u32 nsid, - struct nvme_ns_list *list) -{ - struct nvme_identify_args args = { - .result = NULL, - .data = list, - .args_size = sizeof(args), - .cns = NVME_IDENTIFY_CNS_ALLOCATED_NS_LIST, - .csi = NVME_CSI_NVM, - .nsid = nsid, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_mi_admin_identify(ctrl, &args); -} - -/** - * nvme_mi_admin_identify_active_ns_list() - Perform an Admin identify for an - * active namespace list - * @ctrl: Controller to process identify command - * @nsid: Namespace ID to specify list start - * @list: List data to populate - * - * Perform an Identify command, for the active namespace list starting with - * IDs greater than or equal to @nsid. Specify &NVME_NSID_NONE for the start - * of the list. - * - * Will return an error if the length of the response data (from the - * controller) is not a full &NVME_IDENTIFY_DATA_SIZE, so @list will be - * be fully populated on success. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - * - * See: &struct nvme_ns_list - */ -static inline int nvme_mi_admin_identify_active_ns_list(nvme_mi_ctrl_t ctrl, - __u32 nsid, - struct nvme_ns_list *list) -{ - struct nvme_identify_args args = { - .result = NULL, - .data = list, - .args_size = sizeof(args), - .cns = NVME_IDENTIFY_CNS_NS_ACTIVE_LIST, - .csi = NVME_CSI_NVM, - .nsid = nsid, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_mi_admin_identify(ctrl, &args); -} - -/** - * nvme_mi_admin_identify_primary_ctrl() - Perform an Admin identify for - * primary controller capabilities data structure. - * @ctrl: Controller to process identify command - * @cntid: Controller ID to specify - * @cap: Primary Controller Capabilities data structure to populate - * - * Perform an Identify command to get the Primary Controller Capabilities data - * for the controller specified by @cntid - * - * Will return an error if the length of the response data (from the - * controller) is not a full &NVME_IDENTIFY_DATA_SIZE, so @cap will be - * be fully populated on success. - * - * Return: 0 on success, non-zero on failure - * - * See: &struct nvme_primary_ctrl_cap - */ -static inline int nvme_mi_admin_identify_primary_ctrl(nvme_mi_ctrl_t ctrl, - __u16 cntid, - struct nvme_primary_ctrl_cap *cap) -{ - struct nvme_identify_args args = { - .result = NULL, - .data = cap, - .args_size = sizeof(args), - .cns = NVME_IDENTIFY_CNS_PRIMARY_CTRL_CAP, - .csi = NVME_CSI_NVM, - .nsid = NVME_NSID_NONE, - .cntid = cntid, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_mi_admin_identify(ctrl, &args); -} - -/** - * nvme_mi_admin_identify_secondary_ctrl_list() - Perform an Admin identify for - * a secondary controller list. - * @ctrl: Controller to process identify command - * @cntid: Controller ID to specify list start - * @list: List data to populate - * - * Perform an Identify command, for the secondary controllers associated with - * the current primary controller. Only entries with IDs greater than or - * equal to @cntid are returned. - * - * Will return an error if the length of the response data (from the - * controller) is not a full &NVME_IDENTIFY_DATA_SIZE, so @list will be - * be fully populated on success. - * - * Return: 0 on success, non-zero on failure - * - * See: &struct nvme_secondary_ctrl_list - */ -static inline int nvme_mi_admin_identify_secondary_ctrl_list(nvme_mi_ctrl_t ctrl, - __u16 cntid, - struct nvme_secondary_ctrl_list *list) -{ - struct nvme_identify_args args = { - .result = NULL, - .data = list, - .args_size = sizeof(args), - .cns = NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST, - .csi = NVME_CSI_NVM, - .nsid = NVME_NSID_NONE, - .cntid = cntid, - .cns_specific_id = NVME_CNSSPECID_NONE, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_mi_admin_identify(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_page() - Retrieve log page data from controller - * @ctrl: Controller to query - * @xfer_len: The chunk size of the read - * @args: Get Log Page command arguments - * - * Performs a Get Log Page Admin command as specified by @args. Response data - * is stored in @args->data, which should be a buffer of @args->data_len bytes. - * Resulting data length is stored in @args->data_len on successful - * command completion. - * - * This request may be implemented as multiple log page commands, in order - * to fit within MI message-size limits. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - * - * See: &struct nvme_get_log_args - */ -int nvme_mi_admin_get_log_page(nvme_mi_ctrl_t ctrl, __u32 xfer_len, - struct nvme_get_log_args *args); - -/** - * nvme_mi_admin_get_log() - Retrieve log page data from controller - * @ctrl: Controller to query - * @args: Get Log Page command arguments - * - * Performs a Get Log Page Admin command as specified by @args. Response data - * is stored in @args->data, which should be a buffer of @args->data_len bytes. - * Resulting data length is stored in @args->data_len on successful - * command completion. - * - * This request may be implemented as multiple log page commands, in order - * to fit within MI message-size limits. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - * - * See: &struct nvme_get_log_args - */ -int nvme_mi_admin_get_log(nvme_mi_ctrl_t ctrl, struct nvme_get_log_args *args); - -/** - * nvme_mi_admin_get_nsid_log() - Helper for Get Log Page functions - * @ctrl: Controller to query - * @rae: Retain Asynchronous Events - * @lid: Log identifier - * @nsid: Namespace ID - * @len: length of log buffer - * @log: pointer for resulting log data - * - * Performs a Get Log Page Admin command for a specific log ID @lid and - * namespace ID @nsid. Log data is expected to be @len bytes, and is stored - * in @log on success. The @rae flag is passed as-is to the Get Log Page - * command, and is specific to the Log Page requested. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_nsid_log(nvme_mi_ctrl_t ctrl, bool rae, - enum nvme_cmd_get_log_lid lid, - __u32 nsid, __u32 len, void *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .lid = lid, - .len = len, - .nsid = nsid, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_endgid_log() - Helper for Get Endurance Group ID Log Page functions - * @ctrl: Controller to query - * @rae: Retain Asynchronous Events - * @lid: Log identifier - * @endgid: Endurance Group ID - * @len: length of log buffer - * @log: pointer for resulting log data - * - * Performs a Get Log Page Admin command for a specific log ID @lid and - * endurance group ID @endgid. Log data is expected to be @len bytes, and is stored - * in @log on success. The @rae flag is passed as-is to the Get Log Page - * command, and is specific to the Log Page requested. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_endgid_log(nvme_mi_ctrl_t ctrl, bool rae, - enum nvme_cmd_get_log_lid lid, __u16 endgid, - __u32 len, void *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = lid, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = endgid, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_LOG_LSP_NONE, - .rae = rae, - .ot = false, - }; - - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_simple() - Helper for Get Log Page functions with no - * NSID or RAE requirements - * @ctrl: Controller to query - * @lid: Log identifier - * @len: length of log buffer - * @log: pointer for resulting log data - * - * Performs a Get Log Page Admin command for a specific log ID @lid, using - * NVME_NSID_ALL for the namespace identifier, and rae set to false. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_simple(nvme_mi_ctrl_t ctrl, - enum nvme_cmd_get_log_lid lid, - __u32 len, void *log) -{ - return nvme_mi_admin_get_nsid_log(ctrl, false, lid, NVME_NSID_ALL, - len, log); -} - -/** - * nvme_mi_admin_get_log_supported_log_pages() - Retrieve nmve supported log - * pages - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @log: Array of LID supported and Effects data structures - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_supported_log_pages(nvme_mi_ctrl_t ctrl, - bool rae, - struct nvme_supported_log_pages *log) -{ - return nvme_mi_admin_get_nsid_log(ctrl, rae, - NVME_LOG_LID_SUPPORTED_LOG_PAGES, - NVME_NSID_ALL, sizeof(*log), log); -} - -/** - * nvme_mi_admin_get_log_error() - Retrieve nvme error log - * @ctrl: Controller to query - * @nr_entries: Number of error log entries allocated - * @rae: Retain asynchronous events - * @err_log: Array of error logs of size 'entries' - * - * This log page describes extended error information for a command that - * completed with error, or may report an error that is not specific to a - * particular command. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_error(nvme_mi_ctrl_t ctrl, - unsigned int nr_entries, bool rae, - struct nvme_error_log_page *err_log) -{ - return nvme_mi_admin_get_nsid_log(ctrl, rae, NVME_LOG_LID_ERROR, - NVME_NSID_ALL, sizeof(*err_log) * nr_entries, - err_log); -} - -/** - * nvme_mi_admin_get_log_smart() - Retrieve nvme smart log - * @ctrl: Controller to query - * @nsid: Optional namespace identifier - * @rae: Retain asynchronous events - * @smart_log: User address to store the smart log - * - * This log page provides SMART and general health information. The information - * provided is over the life of the controller and is retained across power - * cycles. To request the controller log page, the namespace identifier - * specified is FFFFFFFFh. The controller may also support requesting the log - * page on a per namespace basis, as indicated by bit 0 of the LPA field in the - * Identify Controller data structure. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_smart(nvme_mi_ctrl_t ctrl, __u32 nsid, - bool rae, - struct nvme_smart_log *smart_log) -{ - return nvme_mi_admin_get_nsid_log(ctrl, rae, NVME_LOG_LID_SMART, - nsid, sizeof(*smart_log), smart_log); -} - -/** - * nvme_mi_admin_get_log_fw_slot() - Retrieves the controller firmware log - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @fw_log: User address to store the log page - * - * This log page describes the firmware revision stored in each firmware slot - * supported. The firmware revision is indicated as an ASCII string. The log - * page also indicates the active slot number. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_fw_slot(nvme_mi_ctrl_t ctrl, bool rae, - struct nvme_firmware_slot *fw_log) -{ - return nvme_mi_admin_get_nsid_log(ctrl, rae, NVME_LOG_LID_FW_SLOT, - NVME_NSID_ALL, sizeof(*fw_log), fw_log); -} - -/** - * nvme_mi_admin_get_log_changed_ns_list() - Retrieve namespace changed list - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @ns_log: User address to store the log page - * - * This log page describes namespaces attached to this controller that have - * changed since the last time the namespace was identified, been added, or - * deleted. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_changed_ns_list(nvme_mi_ctrl_t ctrl, - bool rae, - struct nvme_ns_list *ns_log) -{ - return nvme_mi_admin_get_nsid_log(ctrl, rae, NVME_LOG_LID_CHANGED_NS, - NVME_NSID_ALL, sizeof(*ns_log), ns_log); -} - -/** - * nvme_mi_admin_get_log_cmd_effects() - Retrieve nvme command effects log - * @ctrl: Controller to query - * @csi: Command Set Identifier - * @effects_log: User address to store the effects log - * - * This log page describes the commands that the controller supports and the - * effects of those commands on the state of the NVM subsystem. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_cmd_effects(nvme_mi_ctrl_t ctrl, - enum nvme_csi csi, - struct nvme_cmd_effects_log *effects_log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = effects_log, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_CMD_EFFECTS, - .len = sizeof(*effects_log), - .nsid = NVME_NSID_ALL, - .csi = csi, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_device_self_test() - Retrieve the device self test log - * @ctrl: Controller to query - * @log: Userspace address of the log payload - * - * The log page indicates the status of an in progress self test and the - * percent complete of that operation, and the results of the previous 20 - * self-test operations. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_device_self_test(nvme_mi_ctrl_t ctrl, - struct nvme_self_test_log *log) -{ - return nvme_mi_admin_get_nsid_log(ctrl, false, - NVME_LOG_LID_DEVICE_SELF_TEST, - NVME_NSID_ALL, sizeof(*log), log); -} - -/** - * nvme_mi_admin_get_log_create_telemetry_host_mcda() - Create host telemetry log - * @ctrl: Controller to query - * @mcda: Maximum Created Data Area - * @log: Userspace address of the log payload - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_create_telemetry_host_mcda(nvme_mi_ctrl_t ctrl, - enum nvme_telemetry_da mcda, - struct nvme_telemetry_log *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_TELEMETRY_HOST, - .len = sizeof(*log), - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = (__u8)((mcda << 1) | NVME_LOG_TELEM_HOST_LSP_CREATE), - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_create_telemetry_host() - Create host telemetry log - * @ctrl: Controller to query - * @log: Userspace address of the log payload - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_create_telemetry_host(nvme_mi_ctrl_t ctrl, - struct nvme_telemetry_log *log) -{ - return nvme_mi_admin_get_log_create_telemetry_host_mcda(ctrl, NVME_TELEMETRY_DA_CTRL_DETERMINE, log); -} - -/** - * nvme_mi_admin_get_log_telemetry_host() - Get Telemetry Host-Initiated log - * page - * @ctrl: Controller to query - * @offset: Offset into the telemetry data - * @len: Length of provided user buffer to hold the log data in bytes - * @log: User address for log page data - * - * Retrieves the Telemetry Host-Initiated log page at the requested offset - * using the previously existing capture. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_telemetry_host(nvme_mi_ctrl_t ctrl, - __u64 offset, __u32 len, - void *log) -{ - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_TELEMETRY_HOST, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_TELEM_HOST_LSP_RETAIN, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_telemetry_ctrl() - Get Telemetry Controller-Initiated - * log page - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @offset: Offset into the telemetry data - * @len: Length of provided user buffer to hold the log data in bytes - * @log: User address for log page data - * - * Retrieves the Telemetry Controller-Initiated log page at the requested offset - * using the previously existing capture. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_telemetry_ctrl(nvme_mi_ctrl_t ctrl, - bool rae, - __u64 offset, __u32 len, - void *log) -{ - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_TELEMETRY_CTRL, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_endurance_group() - Get Endurance Group log - * @ctrl: Controller to query - * @endgid: Starting group identifier to return in the list - * @log: User address to store the endurance log - * - * This log page indicates if an Endurance Group Event has occurred for a - * particular Endurance Group. If an Endurance Group Event has occurred, the - * details of the particular event are included in the Endurance Group - * Information log page for that Endurance Group. An asynchronous event is - * generated when an entry for an Endurance Group is newly added to this log - * page. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_endurance_group(nvme_mi_ctrl_t ctrl, - __u16 endgid, - struct nvme_endurance_group_log *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_ENDURANCE_GROUP, - .len = sizeof(*log), - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = endgid, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_predictable_lat_nvmset() - Predictable Latency Per NVM - * Set - * @ctrl: Controller to query - * @nvmsetid: NVM set id - * @log: User address to store the predictable latency log - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_predictable_lat_nvmset(nvme_mi_ctrl_t ctrl, - __u16 nvmsetid, - struct nvme_nvmset_predictable_lat_log *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_PREDICTABLE_LAT_NVMSET, - .len = sizeof(*log), - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = nvmsetid, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_predictable_lat_event() - Retrieve Predictable Latency - * Event Aggregate Log Page - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @offset: Offset into the predictable latency event - * @len: Length of provided user buffer to hold the log data in bytes - * @log: User address for log page data - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_predictable_lat_event(nvme_mi_ctrl_t ctrl, - bool rae, - __u32 offset, - __u32 len, - void *log) -{ - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_PREDICTABLE_LAT_AGG, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_ana() - Retrieve Asymmetric Namespace Access log page - * @ctrl: Controller to query - * @lsp: Log specific, see &enum nvme_get_log_ana_lsp - * @rae: Retain asynchronous events - * @offset: Offset to the start of the log page - * @len: The allocated length of the log page - * @log: User address to store the ana log - * - * This log consists of a header describing the log and descriptors containing - * the asymmetric namespace access information for ANA Groups that contain - * namespaces that are attached to the controller processing the command. - * - * See &struct nvme_ana_log for the definition of the returned structure. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_ana(nvme_mi_ctrl_t ctrl, - enum nvme_log_ana_lsp lsp, bool rae, - __u64 offset, __u32 len, void *log) -{ - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_ANA, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = (__u8)lsp, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_ana_groups() - Retrieve Asymmetric Namespace Access - * groups only log page - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @len: The allocated length of the log page - * @log: User address to store the ana group log - * - * See &struct nvme_ana_group_desc for the definition of the returned structure. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_ana_groups(nvme_mi_ctrl_t ctrl, - bool rae, __u32 len, - struct nvme_ana_group_desc *log) -{ - return nvme_mi_admin_get_log_ana(ctrl, NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY, rae, 0, - len, log); -} - -/** - * nvme_mi_admin_get_ana_log_atomic() - Retrieve Asymmetric Namespace Access - * log page atomically - * @ctrl: Controller to query - * @rgo: Whether to retrieve ANA groups only (no NSIDs) - * @rae: Whether to retain asynchronous events - * @retries: The maximum number of times to retry on log page changes - * @log: Pointer to a buffer to receive the ANA log page - * @len: Input: the length of the log page buffer. - * Output: the actual length of the ANA log page. - * - * See &struct nvme_ana_log for the definition of the returned structure. - * - * Return: If successful, returns 0 and sets *len to the actual log page length. - * If unsuccessful, returns the nvme command status if a response was received - * (see &enum nvme_status_field) or -1 with errno set otherwise. - * Sets errno = EINVAL if retries == 0. - * Sets errno = EAGAIN if unable to read the log page atomically - * because chgcnt changed during each of the retries attempts. - * Sets errno = ENOSPC if the full log page does not fit in the provided buffer. - */ -int nvme_mi_admin_get_ana_log_atomic(nvme_mi_ctrl_t ctrl, bool rgo, bool rae, - unsigned int retries, - struct nvme_ana_log *log, __u32 *len); - -/** - * nvme_mi_admin_get_log_lba_status() - Retrieve LBA Status - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @offset: Offset to the start of the log page - * @len: The allocated length of the log page - * @log: User address to store the log page - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_lba_status(nvme_mi_ctrl_t ctrl, bool rae, - __u64 offset, __u32 len, - void *log) -{ - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_LBA_STATUS, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_endurance_grp_evt() - Retrieve Rotational Media - * Information - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @offset: Offset to the start of the log page - * @len: The allocated length of the log page - * @log: User address to store the log page - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_endurance_grp_evt(nvme_mi_ctrl_t ctrl, - bool rae, - __u32 offset, - __u32 len, - void *log) -{ - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_ENDURANCE_GRP_EVT, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_fid_supported_effects() - Retrieve Feature Identifiers - * Supported and Effects - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @log: FID Supported and Effects data structure - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_fid_supported_effects(nvme_mi_ctrl_t ctrl, - bool rae, - struct nvme_fid_supported_effects_log *log) -{ - return nvme_mi_admin_get_nsid_log(ctrl, rae, - NVME_LOG_LID_FID_SUPPORTED_EFFECTS, - NVME_NSID_NONE, sizeof(*log), log); -} - -/** - * nvme_mi_admin_get_log_mi_cmd_supported_effects() - displays the MI Commands - * Supported by the controller - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @log: MI Command Supported and Effects data structure - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_mi_cmd_supported_effects(nvme_mi_ctrl_t ctrl, - bool rae, - struct nvme_mi_cmd_supported_effects_log *log) -{ - return nvme_mi_admin_get_nsid_log(ctrl, rae, NVME_LOG_LID_MI_CMD_SUPPORTED_EFFECTS, - NVME_NSID_NONE, sizeof(*log), log); -} - -/** - * nvme_mi_admin_get_log_boot_partition() - Retrieve Boot Partition - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @lsp: The log specified field of LID - * @len: The allocated size, minimum - * struct nvme_boot_partition - * @part: User address to store the log page - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_boot_partition(nvme_mi_ctrl_t ctrl, - bool rae, __u8 lsp, - __u32 len, - struct nvme_boot_partition *part) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = part, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_BOOT_PARTITION, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_rotational_media_info() - Retrieve Rotational Media Information Log - * @ctrl: Controller to query - * @endgid: Endurance Group Identifier - * @len: The allocated length of the log page - * @log: User address to store the log page - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise - */ -static inline int nvme_mi_admin_get_log_rotational_media_info(nvme_mi_ctrl_t ctrl, __u16 endgid, - __u32 len, - struct nvme_rotational_media_info_log *log) -{ - return nvme_mi_admin_get_endgid_log(ctrl, false, NVME_LOG_LID_ROTATIONAL_MEDIA_INFO, endgid, - len, log); -} - -/** - * nvme_mi_admin_get_log_dispersed_ns_participating_nss() - Retrieve Dispersed Namespace - * Participating NVM Subsystems Log - * @ctrl: Controller to query - * @nsid: Namespace Identifier - * @len: The allocated length of the log page - * @log: User address to store the log page - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise - */ -static inline int nvme_mi_admin_get_log_dispersed_ns_participating_nss(nvme_mi_ctrl_t ctrl, - __u32 nsid, __u32 len, - struct nvme_dispersed_ns_participating_nss_log *log) -{ - return nvme_mi_admin_get_nsid_log(ctrl, false, NVME_LOG_LID_DISPERSED_NS_PARTICIPATING_NSS, - nsid, len, log); -} - -/** - * nvme_mi_admin_get_log_mgmt_addr_list() - Retrieve Management Address List Log - * @ctrl: Controller to query - * @len: The allocated length of the log page - * @log: User address to store the log page - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise - */ -static inline int nvme_mi_admin_get_log_mgmt_addr_list(nvme_mi_ctrl_t ctrl, __u32 len, - struct nvme_mgmt_addr_list_log *log) -{ - return nvme_mi_admin_get_log_simple(ctrl, NVME_LOG_LID_MGMT_ADDR_LIST, len, log); -} - -/** - * nvme_mi_admin_get_log_phy_rx_eom() - Retrieve Physical Interface Receiver Eye Opening Measurement Log - * @ctrl: Controller to query - * @lsp: Log specific, controls action and measurement quality - * @controller: Target controller ID - * @len: The allocated size, minimum - * struct nvme_phy_rx_eom_log - * @log: User address to store the log page - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise - */ -static inline int nvme_mi_admin_get_log_phy_rx_eom(nvme_mi_ctrl_t ctrl, - __u8 lsp, __u16 controller, - __u32 len, - struct nvme_phy_rx_eom_log *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_PHY_RX_EOM, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = controller, - .lsp = lsp, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_reachability_groups() - Retrieve Reachability Groups Log - * @ctrl: Controller to query - * @rgo: Return groups only - * @rae: Retain asynchronous events - * @len: The allocated length of the log page - * @log: User address to store the log page - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise - */ -static inline int nvme_mi_admin_get_log_reachability_groups(nvme_mi_ctrl_t ctrl, bool rgo, bool rae, - __u32 len, struct nvme_reachability_groups_log *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_REACHABILITY_GROUPS, - .len = len, - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = rgo, - .uuidx = NVME_LOG_LSP_NONE, - .rae = rae, - .ot = false, - }; - - return nvme_mi_admin_get_log_page(ctrl, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_mi_admin_get_log_reachability_associations() - Retrieve Reachability Associations Log - * @ctrl: Controller to query - * @rao: Return associations only - * @rae: Retain asynchronous events - * @len: The allocated length of the log page - * @log: User address to store the log page - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise - */ -static inline int nvme_mi_admin_get_log_reachability_associations(nvme_mi_ctrl_t ctrl, bool rao, - bool rae, __u32 len, - struct nvme_reachability_associations_log *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_REACHABILITY_ASSOCIATIONS, - .len = len, - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = rao, - .uuidx = NVME_LOG_LSP_NONE, - .rae = rae, - .ot = false, - }; - - return nvme_mi_admin_get_log_page(ctrl, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_mi_admin_get_log_changed_alloc_ns_list() - Retrieve Changed Allocated Namespace List Log - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @len: The allocated length of the log page - * @log: User address to store the log page - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise - */ -static inline int nvme_mi_admin_get_log_changed_alloc_ns_list(nvme_mi_ctrl_t ctrl, bool rae, - __u32 len, struct nvme_ns_list *log) -{ - return nvme_mi_admin_get_nsid_log(ctrl, rae, NVME_LOG_LID_CHANGED_ALLOC_NS_LIST, - NVME_NSID_ALL, len, log); -} - -/** - * nvme_mi_admin_get_log_discovery() - Retrieve Discovery log page - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @offset: Offset of this log to retrieve - * @len: The allocated size for this portion of the log - * @log: User address to store the discovery log - * - * Supported only by fabrics discovery controllers, returning discovery - * records. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_discovery(nvme_mi_ctrl_t ctrl, bool rae, - __u32 offset, __u32 len, - void *log) -{ - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_DISCOVER, - .len = len, - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_host_discover() - Retrieve Host Discovery Log - * @ctrl: Controller to query - * @allhoste: All host entries - * @rae: Retain asynchronous events - * @len: The allocated length of the log page - * @log: User address to store the log page - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise - */ -static inline int nvme_mi_admin_get_log_host_discover(nvme_mi_ctrl_t ctrl, bool allhoste, bool rae, - __u32 len, struct nvme_host_discover_log *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_HOST_DISCOVER, - .len = len, - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = allhoste, - .uuidx = NVME_LOG_LSP_NONE, - .rae = rae, - .ot = false, - }; - - return nvme_mi_admin_get_log_page(ctrl, NVME_LOG_PAGE_PDU_SIZE, &args); -} - -/** - * nvme_mi_admin_get_log_ave_discover() - Retrieve AVE Discovery Log - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @len: The allocated length of the log page - * @log: User address to store the log page - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise - */ -static inline int nvme_mi_admin_get_log_ave_discover(nvme_mi_ctrl_t ctrl, bool rae, __u32 len, - struct nvme_ave_discover_log *log) -{ - return nvme_mi_admin_get_nsid_log(ctrl, rae, NVME_LOG_LID_AVE_DISCOVER, NVME_NSID_ALL, len, - log); -} - -/** - * nvme_mi_admin_get_log_pull_model_ddc_req() - Retrieve Pull Model DDC Request Log - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @len: The allocated length of the log page - * @log: User address to store the log page - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise - */ -static inline int nvme_mi_admin_get_log_pull_model_ddc_req(nvme_mi_ctrl_t ctrl, bool rae, __u32 len, - struct nvme_pull_model_ddc_req_log *log) -{ - return nvme_mi_admin_get_nsid_log(ctrl, rae, NVME_LOG_LID_PULL_MODEL_DDC_REQ, NVME_NSID_ALL, - len, log); -} - -/** - * nvme_mi_admin_get_log_media_unit_stat() - Retrieve Media Unit Status - * @ctrl: Controller to query - * @domid: Domain Identifier selection, if supported - * @mus: User address to store the Media Unit statistics log - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_media_unit_stat(nvme_mi_ctrl_t ctrl, - __u16 domid, - struct nvme_media_unit_stat_log *mus) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = mus, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_MEDIA_UNIT_STATUS, - .len = sizeof(*mus), - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = domid, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_support_cap_config_list() - Retrieve Supported - * Capacity Configuration List - * @ctrl: Controller to query - * @domid: Domain Identifier selection, if supported - * @cap: User address to store supported capabilities config list - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_support_cap_config_list(nvme_mi_ctrl_t ctrl, - __u16 domid, - struct nvme_supported_cap_config_list_log *cap) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = cap, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_SUPPORTED_CAP_CONFIG_LIST, - .len = sizeof(*cap), - .nsid = NVME_NSID_NONE, - .csi = NVME_CSI_NVM, - .lsi = domid, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_reservation() - Retrieve Reservation Notification - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @log: User address to store the reservation log - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_reservation(nvme_mi_ctrl_t ctrl, - bool rae, - struct nvme_resv_notification_log *log) -{ - return nvme_mi_admin_get_nsid_log(ctrl, rae, NVME_LOG_LID_RESERVATION, - NVME_NSID_ALL, sizeof(*log), log); -} - -/** - * nvme_mi_admin_get_log_sanitize() - Retrieve Sanitize Status - * @ctrl: Controller to query - * @rae: Retain asynchronous events - * @log: User address to store the sanitize log - * - * The Sanitize Status log page reports sanitize operation time estimates and - * information about the most recent sanitize operation. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_sanitize(nvme_mi_ctrl_t ctrl, bool rae, - struct nvme_sanitize_log_page *log) -{ - return nvme_mi_admin_get_nsid_log(ctrl, rae, NVME_LOG_LID_SANITIZE, - NVME_NSID_ALL, sizeof(*log), log); -} - -/** - * nvme_mi_admin_get_log_zns_changed_zones() - Retrieve list of zones that have - * changed - * @ctrl: Controller to query - * @nsid: Namespace ID - * @rae: Retain asynchronous events - * @log: User address to store the changed zone log - * - * The list of zones that have changed state due to an exceptional event. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_zns_changed_zones(nvme_mi_ctrl_t ctrl, - __u32 nsid, bool rae, - struct nvme_zns_changed_zone_log *log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_ZNS_CHANGED_ZONES, - .len = sizeof(*log), - .nsid = nsid, - .csi = NVME_CSI_ZNS, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = rae, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_persistent_event() - Retrieve Persistent Event Log - * @ctrl: Controller to query - * @action: Action the controller should take during processing this command - * @size: Size of @pevent_log - * @pevent_log: User address to store the persistent event log - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_persistent_event(nvme_mi_ctrl_t ctrl, - enum nvme_pevent_log_action action, - __u32 size, void *pevent_log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = pevent_log, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_PERSISTENT_EVENT, - .len = size, - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = (__u8)action, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_get_log_lockdown() - Retrieve lockdown Log - * @ctrl: Controller to query - * @cnscp: Contents and Scope of Command and Feature Identifier Lists - * @lockdown_log: Buffer to store the lockdown log - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_log_lockdown(nvme_mi_ctrl_t ctrl, - __u8 cnscp, struct nvme_lockdown_log *lockdown_log) -{ - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = lockdown_log, - .args_size = sizeof(args), - .lid = NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN, - .len = sizeof(*lockdown_log), - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = cnscp, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - return nvme_mi_admin_get_log(ctrl, &args); -} - -/** - * nvme_mi_admin_security_send() - Perform a Security Send command on a - * controller. - * @ctrl: Controller to send command to - * @args: Security Send command arguments - * - * Performs a Security Send Admin command as specified by @args. Response data - * is stored in @args->data, which should be a buffer of @args->data_len bytes. - * Resulting data length is stored in @args->data_len on successful - * command completion. - * - * Security Send data length should not be greater than 4096 bytes to - * comply with specification limits. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - * - * See: &struct nvme_get_log_args - */ -int nvme_mi_admin_security_send(nvme_mi_ctrl_t ctrl, - struct nvme_security_send_args *args); - -/** - * nvme_mi_admin_security_recv() - Perform a Security Receive command on a - * controller. - * @ctrl: Controller to send command to - * @args: Security Receive command arguments - * - * Performs a Security Receive Admin command as specified by @args. Response - * data is stored in @args->data, which should be a buffer of @args->data_len - * bytes. Resulting data length is stored in @args->data_len on successful - * command completion. - * - * Security Receive data length should not be greater than 4096 bytes to - * comply with specification limits. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - * - * See: &struct nvme_get_log_args - */ -int nvme_mi_admin_security_recv(nvme_mi_ctrl_t ctrl, - struct nvme_security_receive_args *args); - -/** - * nvme_mi_admin_get_features - Perform a Get Feature command on a controller - * @ctrl: Controller to send command to - * @args: Get Features command arguments - * - * Performs a Get Features Admin command as specified by @args. Returned - * feature data will be stored in @args->result and @args->data, depending - * on the specification of the feature itself; most features do not return - * additional data. See section 5.27.1 of the NVMe spec (v2.0b) for - * feature-specific information. - * - * On success, @args->data_len will be updated with the actual data length - * received. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_mi_admin_get_features(nvme_mi_ctrl_t ctrl, - struct nvme_get_features_args *args); - -/** - * nvme_mi_admin_get_features_arbitration() - Get arbitration feature - * @ctrl: Controller to send command to - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The feature data is returned in this argument - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_mi_admin_get_features_arbitration(nvme_mi_ctrl_t ctrl, enum nvme_get_features_sel sel, - __u32 *result); - -/** - * nvme_mi_admin_get_features_power_mgmt() - Get power management feature - * @ctrl: Controller to send command to - * @sel: Select which type of attribute to return, see &enum nvme_get_features_sel - * @result: The feature data is returned in this argument - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_mi_admin_get_features_power_mgmt(nvme_mi_ctrl_t ctrl, enum nvme_get_features_sel sel, - __u32 *result); - -/** - * nvme_mi_admin_get_features_data() - Helper function for &nvme_mi_admin_get_features() - * @ctrl: Controller to send command to - * @fid: Feature identifier - * @nsid: Namespace ID, if applicable for @fid - * @data_len: Length of feature data, if applicable for @fid, in bytes - * @data: User address of feature data, if applicable - * @result: The command completion result from CQE dword0 - * - * Helper for optionally features that optionally return data, using the - * SEL_CURRENT selector value. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_get_features_data(nvme_mi_ctrl_t ctrl, - enum nvme_features_id fid, - __u32 nsid, __u32 data_len, - void *data, __u32 *result) -{ - struct nvme_get_features_args args = { - .result = result, - .data = data, - .args_size = sizeof(args), - .nsid = nsid, - .sel = NVME_GET_FEATURES_SEL_CURRENT, - .cdw11 = 0, - .data_len = data_len, - .fid = (__u8)fid, - .uuidx = NVME_UUID_NONE, - }; - - return nvme_mi_admin_get_features(ctrl, &args); -} - -/** - * nvme_mi_admin_get_features_simple - Get a simple feature value with no data - * @ctrl: Controller to send command to - * @fid: Feature identifier - * @nsid: Namespace id, if required by @fid - * @result: output feature data - */ -static inline int nvme_mi_admin_get_features_simple(nvme_mi_ctrl_t ctrl, - enum nvme_features_id fid, - __u32 nsid, - __u32 *result) -{ - return nvme_mi_admin_get_features_data(ctrl, fid, nsid, - 0, NULL, result); -} - -/** - * nvme_mi_admin_set_features - Perform a Set Features command on a controller - * @ctrl: Controller to send command to - * @args: Set Features command arguments - * - * Performs a Set Features Admin command as specified by @args. Result - * data will be stored in @args->result. - * on the specification of the feature itself; most features do not return - * additional data. See section 5.27.1 of the NVMe spec (v2.0b) for - * feature-specific information. - * - * On success, @args->data_len will be updated with the actual data length - * received. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_mi_admin_set_features(nvme_mi_ctrl_t ctrl, - struct nvme_set_features_args *args); - -/** - * nvme_mi_admin_set_features_power_mgmt() - Set power management feature - * @ctrl: Controller to send command to - * @ps: Power State - * @wh: Workload Hint - * @save: Save value across power states - * @result: The feature data is returned in this argument - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_mi_admin_set_features_power_mgmt(nvme_mi_ctrl_t ctrl, __u8 ps, __u8 wh, bool save, - __u32 *result); - -/** - * nvme_mi_admin_ns_mgmt - Issue a Namespace Management command - * @ctrl: Controller to send command to - * @args: Namespace management command arguments - * - * Issues a Namespace Management command to @ctrl, with arguments specified - * from @args. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_mi_admin_ns_mgmt(nvme_mi_ctrl_t ctrl, - struct nvme_ns_mgmt_args *args); - -/** - * nvme_mi_admin_ns_mgmt_create - Helper for Namespace Management Create command - * @ctrl: Controller to send command to - * @ns: New namespace parameters - * @csi: Command Set Identifier for new NS - * @nsid: Set to new namespace ID on create - * @data: Host Software Specified Fields that defines ns creation parameters - * - * Issues a Namespace Management (Create) command to @ctrl, to create a - * new namespace specified by @ns, using command set @csi. On success, - * the new namespace ID will be written to @nsid. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_ns_mgmt_create(nvme_mi_ctrl_t ctrl, - struct nvme_id_ns *ns, __u8 csi, __u32 *nsid, - struct nvme_ns_mgmt_host_sw_specified *data) -{ - struct nvme_ns_mgmt_args args = { - .result = nsid, - .ns = ns, - .args_size = sizeof(args), - .nsid = NVME_NSID_NONE, - .sel = NVME_NS_MGMT_SEL_CREATE, - .csi = csi, - .data = data, - }; - - return nvme_mi_admin_ns_mgmt(ctrl, &args); -} - -/** - * nvme_mi_admin_ns_mgmt_delete - Helper for Namespace Management Delete command - * @ctrl: Controller to send command to - * @nsid: Namespace ID to delete - * - * Issues a Namespace Management (Delete) command to @ctrl, to delete the - * namespace with id @nsid. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_ns_mgmt_delete(nvme_mi_ctrl_t ctrl, __u32 nsid) -{ - struct nvme_ns_mgmt_args args = { - .args_size = sizeof(args), - .nsid = nsid, - .sel = NVME_NS_MGMT_SEL_DELETE, - }; - - return nvme_mi_admin_ns_mgmt(ctrl, &args); -} - -/** - * nvme_mi_admin_ns_attach() - Attach or detach namespace to controller(s) - * @ctrl: Controller to send command to - * @args: Namespace Attach command arguments - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_mi_admin_ns_attach(nvme_mi_ctrl_t ctrl, - struct nvme_ns_attach_args *args); - -/** - * nvme_mi_admin_ns_attach_ctrls() - Attach namespace to controllers - * @ctrl: Controller to send command to - * @nsid: Namespace ID to attach - * @ctrlist: Controller list to modify attachment state of nsid - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_ns_attach_ctrls(nvme_mi_ctrl_t ctrl, __u32 nsid, - struct nvme_ctrl_list *ctrlist) -{ - struct nvme_ns_attach_args args = { - .result = NULL, - .ctrlist = ctrlist, - .args_size = sizeof(args), - .nsid = nsid, - .sel = NVME_NS_ATTACH_SEL_CTRL_ATTACH, - }; - - return nvme_mi_admin_ns_attach(ctrl, &args); -} - -/** - * nvme_mi_admin_ns_detach_ctrls() - Detach namespace from controllers - * @ctrl: Controller to send command to - * @nsid: Namespace ID to detach - * @ctrlist: Controller list to modify attachment state of nsid - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -static inline int nvme_mi_admin_ns_detach_ctrls(nvme_mi_ctrl_t ctrl, __u32 nsid, - struct nvme_ctrl_list *ctrlist) -{ - struct nvme_ns_attach_args args = { - .result = NULL, - .ctrlist = ctrlist, - .args_size = sizeof(args), - .nsid = nsid, - .sel = NVME_NS_ATTACH_SEL_CTRL_DEATTACH, - }; - - return nvme_mi_admin_ns_attach(ctrl, &args); -} - -/** - * nvme_mi_admin_fw_download() - Download part or all of a firmware image to - * the controller - * @ctrl: Controller to send firmware data to - * @args: &struct nvme_fw_download_args argument structure - * - * The Firmware Image Download command downloads all or a portion of an image - * for a future update to the controller. The Firmware Image Download command - * downloads a new image (in whole or in part) to the controller. - * - * The image may be constructed of multiple pieces that are individually - * downloaded with separate Firmware Image Download commands. Each Firmware - * Image Download command includes a Dword Offset and Number of Dwords that - * specify a dword range. - * - * The new firmware image is not activated as part of the Firmware Image - * Download command. Use the nvme_mi_admin_fw_commit() to activate a newly - * downloaded image. - * - * Return: 0 on success, non-zero on failure - */ -int nvme_mi_admin_fw_download(nvme_mi_ctrl_t ctrl, - struct nvme_fw_download_args *args); - -/** - * nvme_mi_admin_fw_commit() - Commit firmware using the specified action - * @ctrl: Controller to send firmware data to - * @args: &struct nvme_fw_download_args argument structure - * - * The Firmware Commit command modifies the firmware image or Boot Partitions. - * - * Return: 0 on success, non-zero on failure - */ -int nvme_mi_admin_fw_commit(nvme_mi_ctrl_t ctrl, - struct nvme_fw_commit_args *args); - -/** - * nvme_mi_admin_format_nvm() - Format NVMe namespace - * @ctrl: Controller to send command to - * @args: Format NVM command arguments - * - * Perform a low-level format to set the LBA data & metadata size. May destroy - * data & metadata on the specified namespaces - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_mi_admin_format_nvm(nvme_mi_ctrl_t ctrl, - struct nvme_format_nvm_args *args); - -/** - * nvme_mi_admin_sanitize_nvm() - Start a subsystem Sanitize operation - * @ctrl: Controller to send command to - * @args: Sanitize command arguments - * - * A sanitize operation alters all user data in the NVM subsystem such that - * recovery of any previous user data from any cache, the non-volatile media, - * or any Controller Memory Buffer is not possible. - * - * The Sanitize command starts a sanitize operation or to recover from a - * previously failed sanitize operation. The sanitize operation types that may - * be supported are Block Erase, Crypto Erase, and Overwrite. All sanitize - * operations are processed in the background, i.e., completion of the sanitize - * command does not indicate completion of the sanitize operation. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_mi_admin_sanitize_nvm(nvme_mi_ctrl_t ctrl, - struct nvme_sanitize_nvm_args *args); - /** * enum nvme_mi_aem_handler_next_action - Next action for the AEM state machine handler * @NVME_MI_AEM_HNA_ACK: Send an ack for the AEM diff --git a/libnvme/src/nvme/nbft.c b/libnvme/src/nvme/nbft.c index b7d0dc84db..fd94a450eb 100644 --- a/libnvme/src/nvme/nbft.c +++ b/libnvme/src/nvme/nbft.c @@ -700,8 +700,7 @@ int nvme_nbft_read(struct nbft_info **nbft, const char *filename) if (raw_nbft_fp == NULL) { nvme_msg(NULL, LOG_ERR, "Failed to open %s: %s\n", filename, strerror(errno)); - errno = EINVAL; - return 1; + return -EINVAL; } i = fseek(raw_nbft_fp, 0L, SEEK_END); @@ -709,8 +708,7 @@ int nvme_nbft_read(struct nbft_info **nbft, const char *filename) nvme_msg(NULL, LOG_ERR, "Failed to read from %s: %s\n", filename, strerror(errno)); fclose(raw_nbft_fp); - errno = EINVAL; - return 1; + return -EINVAL; } raw_nbft_size = ftell(raw_nbft_fp); @@ -720,8 +718,7 @@ int nvme_nbft_read(struct nbft_info **nbft, const char *filename) if (!raw_nbft) { nvme_msg(NULL, LOG_ERR, "Failed to allocate memory for NBFT table"); fclose(raw_nbft_fp); - errno = ENOMEM; - return 1; + return -ENOMEM; } i = fread(raw_nbft, sizeof(*raw_nbft), raw_nbft_size, raw_nbft_fp); @@ -730,8 +727,7 @@ int nvme_nbft_read(struct nbft_info **nbft, const char *filename) filename, strerror(errno)); fclose(raw_nbft_fp); free(raw_nbft); - errno = EINVAL; - return 1; + return -EINVAL; } fclose(raw_nbft_fp); @@ -742,8 +738,7 @@ int nvme_nbft_read(struct nbft_info **nbft, const char *filename) if (!*nbft) { nvme_msg(NULL, LOG_ERR, "Could not allocate memory for NBFT\n"); free(raw_nbft); - errno = ENOMEM; - return 1; + return -ENOMEM; } (*nbft)->filename = strdup(filename); @@ -753,8 +748,7 @@ int nvme_nbft_read(struct nbft_info **nbft, const char *filename) if (parse_raw_nbft(*nbft)) { nvme_msg(NULL, LOG_ERR, "Failed to parse %s\n", filename); nvme_nbft_free(*nbft); - errno = EINVAL; - return 1; + return -EINVAL; } return 0; } diff --git a/libnvme/src/nvme/no-json.c b/libnvme/src/nvme/no-json.c index 171144ef9a..3427f42bda 100644 --- a/libnvme/src/nvme/no-json.c +++ b/libnvme/src/nvme/no-json.c @@ -10,17 +10,17 @@ #include -int json_read_config(nvme_root_t r, const char *config_file) +int json_read_config(struct nvme_global_ctx *ctx, const char *config_file) { return -ENOTSUP; } -int json_update_config(nvme_root_t r, const char *config_file) +int json_update_config(struct nvme_global_ctx *ctx, const char *config_file) { return -ENOTSUP; } -int json_dump_tree(nvme_root_t r) +int json_dump_tree(struct nvme_global_ctx *ctx) { return -ENOTSUP; } diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index f2ba299b6f..84b9103806 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -23,6 +24,36 @@ const char *nvme_slots_sysfs_dir(void); const char *nvme_uuid_ibm_filename(void); const char *nvme_dmi_entries_dir(void); +struct nvme_log { + int fd; + int level; + bool pid; + bool timestamp; +}; + +enum nvme_transport_handle_type { + NVME_TRANSPORT_HANDLE_TYPE_UNKNOWN = 0, + NVME_TRANSPORT_HANDLE_TYPE_DIRECT, + NVME_TRANSPORT_HANDLE_TYPE_MI, +}; + +struct nvme_transport_handle { + struct nvme_global_ctx *ctx; + enum nvme_transport_handle_type type; + char *name; + + /* direct */ + int fd; + struct stat stat; + + /* mi */ + struct nvme_mi_ep *ep; + __u16 id; + struct list_node ep_entry; + + struct nvme_log *log; +}; + struct nvme_path { struct list_node entry; struct list_node nentry; @@ -52,7 +83,7 @@ struct nvme_ns { struct nvme_ctrl *c; struct nvme_ns_head *head; - int fd; + struct nvme_transport_handle *hdl; __u32 nsid; char *name; char *generic_name; @@ -76,7 +107,7 @@ struct nvme_ctrl { struct list_head namespaces; struct nvme_subsystem *s; - int fd; + struct nvme_transport_handle *hdl; char *name; char *sysfs_dir; char *address; @@ -127,7 +158,7 @@ struct nvme_subsystem { struct nvme_host { struct list_node entry; struct list_head subsystems; - struct nvme_root *r; + struct nvme_global_ctx *ctx; char *hostnqn; char *hostid; @@ -171,18 +202,11 @@ struct nvme_fabric_options { bool trsvcid; }; -struct nvme_log { - int fd; - int level; - bool pid; - bool timestamp; -}; - -struct nvme_root { +struct nvme_global_ctx { char *config_file; char *application; - struct list_head hosts; struct list_head endpoints; /* MI endpoints */ + struct list_head hosts; struct nvme_log log; bool modified; bool mi_probe_enabled; @@ -192,11 +216,17 @@ struct nvme_root { int nvme_set_attr(const char *dir, const char *attr, const char *value); -int json_read_config(nvme_root_t r, const char *config_file); +int json_read_config(struct nvme_global_ctx *ctx, const char *config_file); -int json_update_config(nvme_root_t r, const char *config_file); +int json_update_config(struct nvme_global_ctx *ctx, const char *config_file); -int json_dump_tree(nvme_root_t r); +int json_dump_tree(struct nvme_global_ctx *ctx); + +struct nvme_transport_handle *__nvme_open(struct nvme_global_ctx *ctx, const char *name); +struct nvme_transport_handle *__nvme_create_transport_handle(struct nvme_global_ctx *ctx); +int __nvme_transport_handle_open_mi(struct nvme_transport_handle *hdl, const char *devname); +int __nvme_transport_handle_init_mi(struct nvme_transport_handle *hdl); +void __nvme_transport_handle_close_mi(struct nvme_transport_handle *hdl); nvme_ctrl_t __nvme_lookup_ctrl(nvme_subsystem_t s, const char *transport, const char *traddr, const char *host_traddr, @@ -214,14 +244,14 @@ void *__nvme_realloc(void *p, size_t len); #endif void __attribute__((format(printf, 4, 5))) -__nvme_msg(nvme_root_t r, int level, const char *func, const char *format, ...); +__nvme_msg(struct nvme_global_ctx *ctx, int level, const char *func, const char *format, ...); -#define nvme_msg(r, level, format, ...) \ - __nvme_msg(r, level, __nvme_log_func, format, ##__VA_ARGS__) +#define nvme_msg(ctx, level, format, ...) \ + __nvme_msg(ctx, level, __nvme_log_func, format, ##__VA_ARGS__) -#define root_from_ctrl(c) ((c)->s && (c)->s->h ? (c)->s->h->r : NULL) -#define root_from_ns(n) ((n)->s && (n)->s->h ? (n)->s->h->r : \ - (n)->c && (n)->c->s && (n)->c->s->h ? (n)->c->s->h->r : \ +#define ctx_from_ctrl(c) ((c)->s && (c)->s->h ? (c)->s->h->ctx : NULL) +#define ctx_from_ns(n) ((n)->s && (n)->s->h ? (n)->s->h->ctx : \ + (n)->c && (n)->c->s && (n)->c->s->h ? (n)->c->s->h->ctx : \ NULL) /* mi internal headers */ @@ -243,6 +273,7 @@ struct nvme_mi_resp { __u32 mic; }; +struct nvme_mi_ep; struct nvme_mi_transport { const char *name; bool mic_enabled; @@ -282,7 +313,7 @@ struct nvme_mi_aem_ctx { #define NVME_QUIRK_CSI_1_NOT_SUPPORTED (1 << 1) struct nvme_mi_ep { - struct nvme_root *root; + struct nvme_global_ctx *ctx; const struct nvme_mi_transport *transport; void *transport_data; struct list_node root_entry; @@ -303,13 +334,7 @@ struct nvme_mi_ep { struct nvme_mi_aem_ctx *aem_ctx; }; -struct nvme_mi_ctrl { - struct nvme_mi_ep *ep; - __u16 id; - struct list_node ep_entry; -}; - -struct nvme_mi_ep *nvme_mi_init_ep(struct nvme_root *root); +struct nvme_mi_ep *nvme_mi_init_ep(struct nvme_global_ctx *ctx); void nvme_mi_ep_probe(struct nvme_mi_ep *ep); /* for tests, we need to calculate the correct MICs */ diff --git a/libnvme/src/nvme/tree.c b/libnvme/src/nvme/tree.c index bc836487df..3d841553b3 100644 --- a/libnvme/src/nvme/tree.c +++ b/libnvme/src/nvme/tree.c @@ -65,13 +65,13 @@ static struct nvme_host *default_host; static void __nvme_free_host(nvme_host_t h); static void __nvme_free_ctrl(nvme_ctrl_t c); -static int nvme_subsystem_scan_namespace(nvme_root_t r, +static int nvme_subsystem_scan_namespace(struct nvme_global_ctx *ctx, struct nvme_subsystem *s, char *name); static int nvme_init_subsystem(nvme_subsystem_t s, const char *name); -static int nvme_scan_subsystem(nvme_root_t r, const char *name); -static int nvme_ctrl_scan_namespace(nvme_root_t r, struct nvme_ctrl *c, +static int nvme_scan_subsystem(struct nvme_global_ctx *ctx, const char *name); +static int nvme_ctrl_scan_namespace(struct nvme_global_ctx *ctx, struct nvme_ctrl *c, char *name); -static int nvme_ctrl_scan_path(nvme_root_t r, struct nvme_ctrl *c, char *name); +static int nvme_ctrl_scan_path(struct nvme_global_ctx *ctx, struct nvme_ctrl *c, char *name); /** * Compare two C strings and handle NULL pointers gracefully. @@ -126,7 +126,7 @@ static char *nvme_hostid_from_hostnqn(const char *hostnqn) return strdup(uuid + strlen("uuid:")); } -int nvme_host_get_ids(nvme_root_t r, +int nvme_host_get_ids(struct nvme_global_ctx *ctx, char *hostnqn_arg, char *hostid_arg, char **hostnqn, char **hostid) { @@ -142,7 +142,7 @@ int nvme_host_get_ids(nvme_root_t r, hnqn = strdup(hostnqn_arg); /* JSON config: assume the first entry is the default host */ - h = nvme_first_host(r); + h = nvme_first_host(ctx); if (h) { if (!hid) hid = strdup(nvme_host_get_hostid(h)); @@ -166,28 +166,24 @@ int nvme_host_get_ids(nvme_root_t r, */ if (!hid) { hid = nvmf_hostid_generate(); - if (!hid) { - errno = -ENOMEM; - return -1; - } + if (!hid) + return -ENOMEM; - nvme_msg(r, LOG_DEBUG, + nvme_msg(ctx, LOG_DEBUG, "warning: using auto generated hostid and hostnqn\n"); } /* incomplete configuration, thus derive hostnqn from hostid */ if (!hnqn) { hnqn = nvmf_hostnqn_generate_from_hostid(hid); - if (!hnqn) { - errno = -ENOMEM; - return -1; - } + if (!hnqn) + return -ENOMEM; } /* sanity checks */ nqn = nvme_hostid_from_hostnqn(hnqn); if (nqn && strcmp(nqn, hid)) { - nvme_msg(r, LOG_DEBUG, + nvme_msg(ctx, LOG_DEBUG, "warning: use hostid '%s' which does not match uuid in hostnqn '%s'\n", hid, hnqn); } @@ -200,57 +196,60 @@ int nvme_host_get_ids(nvme_root_t r, return 0; } -nvme_host_t nvme_default_host(nvme_root_t r) +int nvme_default_host(struct nvme_global_ctx *ctx, nvme_host_t *hp) { _cleanup_free_ char *hostnqn = NULL; _cleanup_free_ char *hostid = NULL; struct nvme_host *h; + int err; - if (nvme_host_get_ids(r, NULL, NULL, &hostnqn, &hostid)) - return NULL; + err = nvme_host_get_ids(ctx, NULL, NULL, &hostnqn, &hostid); + if (err) + return err; - h = nvme_lookup_host(r, hostnqn, hostid); + h = nvme_lookup_host(ctx, hostnqn, hostid); nvme_host_set_hostsymname(h, NULL); default_host = h; - return h; + *hp = h; + return 0; } -static void nvme_filter_subsystem(nvme_root_t r, nvme_subsystem_t s, +static void nvme_filter_subsystem(struct nvme_global_ctx *ctx, nvme_subsystem_t s, nvme_scan_filter_t f, void *f_args) { if (f(s, NULL, NULL, f_args)) return; - nvme_msg(r, LOG_DEBUG, "filter out subsystem %s\n", + nvme_msg(ctx, LOG_DEBUG, "filter out subsystem %s\n", nvme_subsystem_get_name(s)); nvme_free_subsystem(s); } -static void nvme_filter_ns(nvme_root_t r, nvme_ns_t n, +static void nvme_filter_ns(struct nvme_global_ctx *ctx, nvme_ns_t n, nvme_scan_filter_t f, void *f_args) { if (f(NULL, NULL, n, f_args)) return; - nvme_msg(r, LOG_DEBUG, "filter out namespace %s\n", + nvme_msg(ctx, LOG_DEBUG, "filter out namespace %s\n", nvme_ns_get_name(n)); nvme_free_ns(n); } -static void nvme_filter_ctrl(nvme_root_t r, nvme_ctrl_t c, +static void nvme_filter_ctrl(struct nvme_global_ctx *ctx, nvme_ctrl_t c, nvme_scan_filter_t f, void *f_args) { if (f(NULL, c, NULL, f_args)) return; - nvme_msg(r, LOG_DEBUG, "filter out controller %s\n", + nvme_msg(ctx, LOG_DEBUG, "filter out controller %s\n", nvme_ctrl_get_name(c)); nvme_free_ctrl(c); } -static void nvme_filter_tree(nvme_root_t r, nvme_scan_filter_t f, void *f_args) +static void nvme_filter_tree(struct nvme_global_ctx *ctx, nvme_scan_filter_t f, void *f_args) { nvme_host_t h, _h; nvme_subsystem_t s, _s; @@ -261,61 +260,63 @@ static void nvme_filter_tree(nvme_root_t r, nvme_scan_filter_t f, void *f_args) if (!f) return; - nvme_for_each_host_safe(r, h, _h) { + nvme_for_each_host_safe(ctx, h, _h) { nvme_for_each_subsystem_safe(h, s, _s) { nvme_subsystem_for_each_ctrl_safe(s, c, _c) - nvme_filter_ctrl(r, c, f, f_args); + nvme_filter_ctrl(ctx, c, f, f_args); nvme_subsystem_for_each_ns_safe(s, n, _n) { nvme_namespace_for_each_path_safe(n, p, _p) { - nvme_filter_ctrl(r, nvme_path_get_ctrl(p), + nvme_filter_ctrl(ctx, nvme_path_get_ctrl(p), f, f_args); } - nvme_filter_ns(r, n, f, f_args); + nvme_filter_ns(ctx, n, f, f_args); } - nvme_filter_subsystem(r, s, f, f_args); + nvme_filter_subsystem(ctx, s, f, f_args); } } } -int nvme_scan_topology(struct nvme_root *r, nvme_scan_filter_t f, void *f_args) +int nvme_scan_topology(struct nvme_global_ctx *ctx, nvme_scan_filter_t f, void *f_args) { _cleanup_dirents_ struct dirents subsys = {}, ctrls = {}; int i, ret; - if (!r) + if (!ctx) return 0; ctrls.num = nvme_scan_ctrls(&ctrls.ents); if (ctrls.num < 0) { - nvme_msg(r, LOG_DEBUG, "failed to scan ctrls: %s\n", - strerror(errno)); + nvme_msg(ctx, LOG_DEBUG, "failed to scan ctrls: %s\n", + strerror(ctrls.num)); return ctrls.num; } for (i = 0; i < ctrls.num; i++) { - nvme_ctrl_t c = nvme_scan_ctrl(r, ctrls.ents[i]->d_name); - if (!c) { - nvme_msg(r, LOG_DEBUG, "failed to scan ctrl %s: %s\n", - ctrls.ents[i]->d_name, strerror(errno)); + nvme_ctrl_t c; + + ret = nvme_scan_ctrl(ctx, ctrls.ents[i]->d_name, &c); + if (!ret) { + nvme_msg(ctx, LOG_DEBUG, "failed to scan ctrl %s: %s\n", + ctrls.ents[i]->d_name, strerror(ret)); continue; } } subsys.num = nvme_scan_subsystems(&subsys.ents); if (subsys.num < 0) { - nvme_msg(r, LOG_DEBUG, "failed to scan subsystems: %s\n", - strerror(errno)); + nvme_msg(ctx, LOG_DEBUG, "failed to scan subsystems: %s\n", + strerror(subsys.num)); return subsys.num; } for (i = 0; i < subsys.num; i++) { - ret = nvme_scan_subsystem(r, subsys.ents[i]->d_name); + ret = nvme_scan_subsystem(ctx, subsys.ents[i]->d_name); if (ret < 0) { - nvme_msg(r, LOG_DEBUG, + nvme_msg(ctx, LOG_DEBUG, "failed to scan subsystem %s: %s\n", - subsys.ents[i]->d_name, strerror(errno)); + subsys.ents[i]->d_name, strerror(ret)); } } @@ -323,129 +324,136 @@ int nvme_scan_topology(struct nvme_root *r, nvme_scan_filter_t f, void *f_args) * Filter the tree after it has been fully populated and * updated */ - nvme_filter_tree(r, f, f_args); + nvme_filter_tree(ctx, f, f_args); return 0; } -nvme_root_t nvme_create_root(FILE *fp, int log_level) +struct nvme_global_ctx *nvme_create_global_ctx(FILE *fp, int log_level) { - struct nvme_root *r; + struct nvme_global_ctx *ctx; int fd; - r = calloc(1, sizeof(*r)); - if (!r) { - errno = ENOMEM; + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) return NULL; - } if (fp) { fd = fileno(fp); if (fd < 0) { - free(r); + free(ctx); return NULL; } } else fd = STDERR_FILENO; - r->log.fd = fd; - r->log.level = log_level; + ctx->log.fd = fd; + ctx->log.level = log_level; - list_head_init(&r->hosts); - list_head_init(&r->endpoints); + list_head_init(&ctx->hosts); + list_head_init(&ctx->endpoints); - return r; + return ctx; } -int nvme_read_config(nvme_root_t r, const char *config_file) +int nvme_read_config(struct nvme_global_ctx *ctx, const char *config_file) { - int err = -1; - int tmp; + int err; - if (!r || !config_file) { - errno = ENODEV; - return err; - } + if (!ctx || !config_file) + return -ENODEV; - r->config_file = strdup(config_file); - if (!r->config_file) { - errno = ENOMEM; - return err; - } + ctx->config_file = strdup(config_file); + if (!ctx->config_file) + return -ENOMEM; - tmp = errno; - err = json_read_config(r, config_file); + err = json_read_config(ctx, config_file); /* * The json configuration file is optional, * so ignore errors when opening the file. */ - if (err < 0 && errno != EPROTO) { - errno = tmp; + if (err < 0 && err != -EPROTO) return 0; - } return err; } -nvme_root_t nvme_scan(const char *config_file) +int nvme_scan(const char *config_file, struct nvme_global_ctx **ctxp) { - nvme_root_t r = nvme_create_root(NULL, DEFAULT_LOGLEVEL); + struct nvme_global_ctx *ctx = + nvme_create_global_ctx(NULL, DEFAULT_LOGLEVEL); + int ret; + + if (!ctx) + return -ENOMEM; + + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret) + goto err; + if (config_file) { + ret = nvme_read_config(ctx, config_file); + if (ret) + goto err; + } + + *ctxp = ctx; + return 0; - nvme_scan_topology(r, NULL, NULL); - nvme_read_config(r, config_file); - return r; +err: + nvme_free_global_ctx(ctx); + return ret; } -int nvme_update_config(nvme_root_t r) +int nvme_update_config(struct nvme_global_ctx *ctx) { - if (!r->modified || !r->config_file) + if (!ctx->modified || !ctx->config_file) return 0; - return json_update_config(r, r->config_file); + return json_update_config(ctx, ctx->config_file); } -int nvme_dump_config(nvme_root_t r) +int nvme_dump_config(struct nvme_global_ctx *ctx) { - return json_update_config(r, NULL); + return json_update_config(ctx, NULL); } -int nvme_dump_tree(nvme_root_t r) +int nvme_dump_tree(struct nvme_global_ctx *ctx) { - return json_dump_tree(r); + return json_dump_tree(ctx); } -const char *nvme_root_get_application(nvme_root_t r) +const char *nvme_get_application(struct nvme_global_ctx *ctx) { - return r->application; + return ctx->application; } -void nvme_root_set_application(nvme_root_t r, const char *a) +void nvme_set_application(struct nvme_global_ctx *ctx, const char *a) { - free(r->application); - r->application = NULL; + free(ctx->application); + ctx->application = NULL; if (a) - r->application = strdup(a); + ctx->application = strdup(a); } -void nvme_root_skip_namespaces(nvme_root_t r) +void nvme_skip_namespaces(struct nvme_global_ctx *ctx) { - r->create_only = true; + ctx->create_only = true; } -nvme_host_t nvme_first_host(nvme_root_t r) +nvme_host_t nvme_first_host(struct nvme_global_ctx *ctx) { - return list_top(&r->hosts, struct nvme_host, entry); + return list_top(&ctx->hosts, struct nvme_host, entry); } -nvme_host_t nvme_next_host(nvme_root_t r, nvme_host_t h) +nvme_host_t nvme_next_host(struct nvme_global_ctx *ctx, nvme_host_t h) { - return h ? list_next(&r->hosts, h, entry) : NULL; + return h ? list_next(&ctx->hosts, h, entry) : NULL; } -nvme_root_t nvme_host_get_root(nvme_host_t h) +struct nvme_global_ctx *nvme_host_get_global_ctx(nvme_host_t h) { - return h->r; + return h->ctx; } const char *nvme_host_get_hostnqn(nvme_host_t h) @@ -509,35 +517,35 @@ nvme_subsystem_t nvme_next_subsystem(nvme_host_t h, nvme_subsystem_t s) return s ? list_next(&h->subsystems, s, entry) : NULL; } -void nvme_refresh_topology(nvme_root_t r) +void nvme_refresh_topology(struct nvme_global_ctx *ctx) { struct nvme_host *h, *_h; - nvme_for_each_host_safe(r, h, _h) + nvme_for_each_host_safe(ctx, h, _h) __nvme_free_host(h); - nvme_scan_topology(r, NULL, NULL); + nvme_scan_topology(ctx, NULL, NULL); } -void nvme_free_tree(nvme_root_t r) +void nvme_free_global_ctx(struct nvme_global_ctx *ctx) { struct nvme_host *h, *_h; - if (!r) + if (!ctx) return; - free(r->options); - nvme_for_each_host_safe(r, h, _h) + free(ctx->options); + nvme_for_each_host_safe(ctx, h, _h) __nvme_free_host(h); - free(r->config_file); - free(r->application); - free(r); + free(ctx->config_file); + free(ctx->application); + free(ctx); } -void nvme_root_release_fds(nvme_root_t r) +void nvme_root_release_fds(struct nvme_global_ctx *ctx) { struct nvme_host *h, *_h; - nvme_for_each_host_safe(r, h, _h) + nvme_for_each_host_safe(ctx, h, _h) nvme_host_release_fds(h); } @@ -633,7 +641,7 @@ nvme_path_t nvme_namespace_next_path(nvme_ns_t ns, nvme_path_t p) static void __nvme_free_ns(struct nvme_ns *n) { list_del_init(&n->entry); - nvme_ns_release_fd(n); + nvme_ns_release_transport_handle(n); free(n->generic_name); free(n->name); free(n->sysfs_dir); @@ -678,10 +686,10 @@ void nvme_subsystem_release_fds(struct nvme_subsystem *s) struct nvme_ns *n, *_n; nvme_subsystem_for_each_ctrl_safe(s, c, _c) - nvme_ctrl_release_fd(c); + nvme_ctrl_release_transport_handle(c); nvme_subsystem_for_each_ns_safe(s, n, _n) - nvme_ns_release_fd(n); + nvme_ns_release_transport_handle(n); } /* @@ -709,7 +717,7 @@ struct nvme_subsystem *nvme_alloc_subsystem(struct nvme_host *h, list_head_init(&s->namespaces); list_node_init(&s->entry); list_add_tail(&h->subsystems, &s->entry); - h->r->modified = true; + h->ctx->modified = true; return s; } @@ -726,10 +734,10 @@ struct nvme_subsystem *nvme_lookup_subsystem(struct nvme_host *h, if (name && s->name && strcmp(s->name, name)) continue; - if (h->r->application) { + if (h->ctx->application) { if (!s->application) continue; - if (strcmp(h->r->application, s->application)) + if (strcmp(h->ctx->application, s->application)) continue; } return s; @@ -748,7 +756,7 @@ static void __nvme_free_host(struct nvme_host *h) free(h->hostid); free(h->dhchap_key); nvme_host_set_hostsymname(h, NULL); - h->r->modified = true; + h->ctx->modified = true; free(h); } @@ -766,14 +774,14 @@ void nvme_free_host(struct nvme_host *h) __nvme_free_host(h); } -struct nvme_host *nvme_lookup_host(nvme_root_t r, const char *hostnqn, +struct nvme_host *nvme_lookup_host(struct nvme_global_ctx *ctx, const char *hostnqn, const char *hostid) { struct nvme_host *h; if (!hostnqn) return NULL; - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { if (strcmp(h->hostnqn, hostnqn)) continue; if (hostid && (!h->hostid || @@ -789,39 +797,39 @@ struct nvme_host *nvme_lookup_host(nvme_root_t r, const char *hostnqn, h->hostid = strdup(hostid); list_head_init(&h->subsystems); list_node_init(&h->entry); - h->r = r; - list_add_tail(&r->hosts, &h->entry); - r->modified = true; + h->ctx = ctx; + list_add_tail(&ctx->hosts, &h->entry); + ctx->modified = true; return h; } -static int nvme_subsystem_scan_namespaces(nvme_root_t r, nvme_subsystem_t s) +static int nvme_subsystem_scan_namespaces(struct nvme_global_ctx *ctx, nvme_subsystem_t s) { _cleanup_dirents_ struct dirents namespaces = {}; int i, ret; - if (r->create_only) { - nvme_msg(r, LOG_DEBUG, + if (ctx->create_only) { + nvme_msg(ctx, LOG_DEBUG, "skipping namespace scan for subsys %s\n", s->subsysnqn); return 0; } namespaces.num = nvme_scan_subsystem_namespaces(s, &namespaces.ents); if (namespaces.num < 0) { - nvme_msg(r, LOG_DEBUG, + nvme_msg(ctx, LOG_DEBUG, "failed to scan namespaces for subsys %s: %s\n", - s->subsysnqn, strerror(errno)); + s->subsysnqn, strerror(namespaces.num)); return namespaces.num; } for (i = 0; i < namespaces.num; i++) { - ret = nvme_subsystem_scan_namespace(r, s, + ret = nvme_subsystem_scan_namespace(ctx, s, namespaces.ents[i]->d_name); if (ret < 0) - nvme_msg(r, LOG_DEBUG, + nvme_msg(ctx, LOG_DEBUG, "failed to scan namespace %s: %s\n", - namespaces.ents[i]->d_name, strerror(errno)); + namespaces.ents[i]->d_name, strerror(ret)); } return 0; @@ -832,7 +840,7 @@ static int nvme_init_subsystem(nvme_subsystem_t s, const char *name) char *path; if (asprintf(&path, "%s/%s", nvme_subsys_sysfs_dir(), name) < 0) - return -1; + return -ENOMEM; s->model = nvme_get_attr(path, "model"); if (!s->model) @@ -848,31 +856,29 @@ static int nvme_init_subsystem(nvme_subsystem_t s, const char *name) } s->name = strdup(name); s->sysfs_dir = (char *)path; - if (s->h->r->application) - s->application = strdup(s->h->r->application); + if (s->h->ctx->application) + s->application = strdup(s->h->ctx->application); s->iopolicy = nvme_get_attr(path, "iopolicy"); return 0; } -static int nvme_scan_subsystem(struct nvme_root *r, const char *name) +static int nvme_scan_subsystem(struct nvme_global_ctx *ctx, const char *name) { struct nvme_subsystem *s = NULL, *_s; _cleanup_free_ char *path = NULL, *subsysnqn = NULL; nvme_host_t h = NULL; int ret; - nvme_msg(r, LOG_DEBUG, "scan subsystem %s\n", name); + nvme_msg(ctx, LOG_DEBUG, "scan subsystem %s\n", name); ret = asprintf(&path, "%s/%s", nvme_subsys_sysfs_dir(), name); if (ret < 0) - return ret; + return -ENOMEM; subsysnqn = nvme_get_attr(path, "subsysnqn"); - if (!subsysnqn) { - errno = ENODEV; - return -1; - } - nvme_for_each_host(r, h) { + if (!subsysnqn) + return -ENODEV; + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, _s) { /* * We are always called after nvme_scan_ctrl(), @@ -883,10 +889,8 @@ static int nvme_scan_subsystem(struct nvme_root *r, const char *name) continue; if (strcmp(_s->name, name)) continue; - if (!nvme_subsystem_scan_namespaces(r, _s)) { - errno = EINVAL; - return -1; - } + if (!nvme_subsystem_scan_namespaces(ctx, _s)) + return -EINVAL; s = _s; } } @@ -896,23 +900,20 @@ static int nvme_scan_subsystem(struct nvme_root *r, const char *name) * Create a subsystem with the default host * and hope for the best. */ - nvme_msg(r, LOG_DEBUG, "creating detached subsystem '%s'\n", + nvme_msg(ctx, LOG_DEBUG, "creating detached subsystem '%s'\n", name); - h = nvme_default_host(r); + ret = nvme_default_host(ctx, &h); + if (ret) + return ret; s = nvme_alloc_subsystem(h, name, subsysnqn); - if (!s) { - errno = ENOMEM; - return -1; - } - if (!nvme_subsystem_scan_namespaces(r, s)) { - errno = EINVAL; - return -1; - } + if (!s) + return -ENOMEM; + if (!nvme_subsystem_scan_namespaces(ctx, s)) + return -EINVAL; } else if (strcmp(s->subsysnqn, subsysnqn)) { - nvme_msg(r, LOG_DEBUG, "NQN mismatch for subsystem '%s'\n", + nvme_msg(ctx, LOG_DEBUG, "NQN mismatch for subsystem '%s'\n", name); - errno = EINVAL; - return -1; + return -EINVAL; } return 0; @@ -971,29 +972,24 @@ void nvme_free_path(struct nvme_path *p) free(p); } -static int nvme_ctrl_scan_path(nvme_root_t r, struct nvme_ctrl *c, char *name) +static int nvme_ctrl_scan_path(struct nvme_global_ctx *ctx, struct nvme_ctrl *c, char *name) { struct nvme_path *p; _cleanup_free_ char *path = NULL, *grpid = NULL, *queue_depth = NULL; int ret; - nvme_msg(r, LOG_DEBUG, "scan controller %s path %s\n", + nvme_msg(ctx, LOG_DEBUG, "scan controller %s path %s\n", c->name, name); - if (!c->s) { - errno = ENXIO; - return -1; - } + if (!c->s) + return -ENXIO; + ret = asprintf(&path, "%s/%s", c->sysfs_dir, name); - if (ret < 0) { - errno = ENOMEM; - return -1; - } + if (ret < 0) + return -ENOMEM; p = calloc(1, sizeof(*p)); - if (!p) { - errno = ENOMEM; - return -1; - } + if (!p) + return -ENOMEM; p->c = c; p->name = strdup(name); @@ -1023,25 +1019,28 @@ static int nvme_ctrl_scan_path(nvme_root_t r, struct nvme_ctrl *c, char *name) return 0; } -int nvme_ctrl_get_fd(nvme_ctrl_t c) +struct nvme_transport_handle *nvme_ctrl_get_transport_handle(nvme_ctrl_t c) { - if (c->fd < 0) { - c->fd = nvme_open(c->name); - if (c->fd < 0) - nvme_msg(root_from_ctrl(c), LOG_ERR, + if (!c->hdl) { + struct nvme_global_ctx *ctx = ctx_from_ctrl(c); + int err; + + err = nvme_open(ctx, c->name, &c->hdl); + if (err) + nvme_msg(ctx, LOG_ERR, "Failed to open ctrl %s, errno %d\n", - c->name, errno); + c->name, err); } - return c->fd; + return c->hdl; } -void nvme_ctrl_release_fd(nvme_ctrl_t c) +void nvme_ctrl_release_transport_handle(nvme_ctrl_t c) { - if (c->fd < 0) + if (!c->hdl) return; - close(c->fd); - c->fd = -1; + nvme_close(c->hdl); + c->hdl = NULL; } nvme_subsystem_t nvme_ctrl_get_subsystem(nvme_ctrl_t c) @@ -1084,7 +1083,7 @@ char *nvme_ctrl_get_src_addr(nvme_ctrl_t c, char *src_addr, size_t src_addr_len) p += strlen("src_addr="); l = strcspn(p, ",%"); /* % to eliminate IPv6 scope (if present) */ if (l >= src_addr_len) { - nvme_msg(root_from_ctrl(c), LOG_ERR, + nvme_msg(ctx_from_ctrl(c), LOG_ERR, "Buffer for src_addr is too small (%zu must be > %zu)\n", src_addr_len, l); return NULL; @@ -1286,7 +1285,11 @@ bool nvme_ctrl_is_unique_discovery_ctrl(nvme_ctrl_t c) int nvme_ctrl_identify(nvme_ctrl_t c, struct nvme_id_ctrl *id) { - return nvme_identify_ctrl(nvme_ctrl_get_fd(c), id); + struct nvme_transport_handle *hdl = nvme_ctrl_get_transport_handle(c); + struct nvme_passthru_cmd cmd; + + nvme_init_identify_ctrl(&cmd, id); + return nvme_submit_admin_passthru(hdl, &cmd, NULL); } nvme_ns_t nvme_ctrl_first_ns(nvme_ctrl_t c) @@ -1313,7 +1316,7 @@ nvme_path_t nvme_ctrl_next_path(nvme_ctrl_t c, nvme_path_t p) do { free(a); (a) = NULL; } while (0) void nvme_deconfigure_ctrl(nvme_ctrl_t c) { - nvme_ctrl_release_fd(c); + nvme_ctrl_release_transport_handle(c); FREE_CTRL_ATTR(c->name); FREE_CTRL_ATTR(c->sysfs_dir); FREE_CTRL_ATTR(c->firmware); @@ -1337,17 +1340,17 @@ void nvme_deconfigure_ctrl(nvme_ctrl_t c) int nvme_disconnect_ctrl(nvme_ctrl_t c) { - nvme_root_t r = c->s && c->s->h ? c->s->h->r : NULL; + struct nvme_global_ctx *ctx = c->s && c->s->h ? c->s->h->ctx : NULL; int ret; ret = nvme_set_attr(nvme_ctrl_get_sysfs_dir(c), "delete_controller", "1"); if (ret < 0) { - nvme_msg(r, LOG_ERR, "%s: failed to disconnect, error %d\n", + nvme_msg(ctx, LOG_ERR, "%s: failed to disconnect, error %d\n", c->name, errno); return ret; } - nvme_msg(r, LOG_INFO, "%s: %s disconnected\n", c->name, c->subsysnqn); + nvme_msg(ctx, LOG_INFO, "%s: %s disconnected\n", c->name, c->subsysnqn); nvme_deconfigure_ctrl(c); return 0; } @@ -1404,37 +1407,34 @@ static bool traddr_is_hostname(const char *transport, const char *traddr) return true; } -struct nvme_ctrl *nvme_create_ctrl(nvme_root_t r, - const char *subsysnqn, const char *transport, - const char *traddr, const char *host_traddr, - const char *host_iface, const char *trsvcid) +int nvme_create_ctrl(struct nvme_global_ctx *ctx, + const char *subsysnqn, const char *transport, + const char *traddr, const char *host_traddr, + const char *host_iface, const char *trsvcid, + nvme_ctrl_t *cp) { struct nvme_ctrl *c; if (!transport) { - nvme_msg(r, LOG_ERR, "No transport specified\n"); - errno = EINVAL; - return NULL; + nvme_msg(ctx, LOG_ERR, "No transport specified\n"); + return -EINVAL; } if (strncmp(transport, "loop", 4) && strncmp(transport, "pcie", 4) && strncmp(transport, "apple-nvme", 10) && !traddr) { - nvme_msg(r, LOG_ERR, "No transport address for '%s'\n", + nvme_msg(ctx, LOG_ERR, "No transport address for '%s'\n", transport); - errno = EINVAL; - return NULL; + return -EINVAL; } if (!subsysnqn) { - nvme_msg(r, LOG_ERR, "No subsystem NQN specified\n"); - errno = EINVAL; - return NULL; + nvme_msg(ctx, LOG_ERR, "No subsystem NQN specified\n"); + return -EINVAL; } c = calloc(1, sizeof(*c)); - if (!c) { - errno = ENOMEM; - return NULL; - } - c->fd = -1; + if (!c) + return -ENOMEM; + + c->hdl = NULL; nvmf_default_config(&c->cfg); list_head_init(&c->namespaces); list_head_init(&c->paths); @@ -1445,7 +1445,7 @@ struct nvme_ctrl *nvme_create_ctrl(nvme_root_t r, c->traddr = strdup(traddr); if (host_traddr) { if (traddr_is_hostname(transport, host_traddr)) - c->cfg.host_traddr = hostname2traddr(r, host_traddr); + hostname2traddr(ctx, host_traddr, &c->cfg.host_traddr); if (!c->cfg.host_traddr) c->cfg.host_traddr = strdup(host_traddr); } @@ -1454,7 +1454,8 @@ struct nvme_ctrl *nvme_create_ctrl(nvme_root_t r, if (trsvcid) c->trsvcid = strdup(trsvcid); - return c; + *cp = c; + return 0; } /** @@ -1491,7 +1492,7 @@ static bool _tcp_ctrl_match_host_traddr_no_src_addr(struct nvme_ctrl *c, struct * 100% positive match. Regardless, let's be optimistic * and assume that we have a match. */ - nvme_msg(root_from_ctrl(c), LOG_DEBUG, + nvme_msg(ctx_from_ctrl(c), LOG_DEBUG, "Not enough data, but assume %s matches candidate's host_traddr: %s\n", nvme_ctrl_get_name(c), candidate->host_traddr); @@ -1531,7 +1532,7 @@ static bool _tcp_ctrl_match_host_iface_no_src_addr(struct nvme_ctrl *c, struct c * 100% positive match. Regardless, let's be optimistic * and assume that we have a match. */ - nvme_msg(root_from_ctrl(c), LOG_DEBUG, + nvme_msg(ctx_from_ctrl(c), LOG_DEBUG, "Not enough data, but assume %s matches candidate's host_iface: %s\n", nvme_ctrl_get_name(c), candidate->host_iface); @@ -1849,8 +1850,9 @@ nvme_ctrl_t nvme_lookup_ctrl(nvme_subsystem_t s, const char *transport, const char *host_iface, const char *trsvcid, nvme_ctrl_t p) { - nvme_root_t r; + struct nvme_global_ctx *ctx; struct nvme_ctrl *c; + int ret; if (!s || !transport) return NULL; @@ -1860,24 +1862,26 @@ nvme_ctrl_t nvme_lookup_ctrl(nvme_subsystem_t s, const char *transport, if (c) return c; - r = s->h ? s->h->r : NULL; - c = nvme_create_ctrl(r, s->subsysnqn, transport, traddr, - host_traddr, host_iface, trsvcid); - if (c) { - c->s = s; - list_add_tail(&s->ctrls, &c->entry); - s->h->r->modified = true; - } + ctx = s->h ? s->h->ctx : NULL; + ret = nvme_create_ctrl(ctx, s->subsysnqn, transport, traddr, + host_traddr, host_iface, trsvcid, &c); + if (ret) + return NULL; + + c->s = s; + list_add_tail(&s->ctrls, &c->entry); + s->h->ctx->modified = true; + return c; } -static int nvme_ctrl_scan_paths(nvme_root_t r, struct nvme_ctrl *c) +static int nvme_ctrl_scan_paths(struct nvme_global_ctx *ctx, struct nvme_ctrl *c) { _cleanup_dirents_ struct dirents paths = {}; int i; - if (r->create_only) { - nvme_msg(r, LOG_DEBUG, + if (ctx->create_only) { + nvme_msg(ctx, LOG_DEBUG, "skipping path scan for ctrl %s\n", c->name); return 0; } @@ -1886,30 +1890,31 @@ static int nvme_ctrl_scan_paths(nvme_root_t r, struct nvme_ctrl *c) return paths.num; for (i = 0; i < paths.num; i++) - nvme_ctrl_scan_path(r, c, paths.ents[i]->d_name); + nvme_ctrl_scan_path(ctx, c, paths.ents[i]->d_name); return 0; } -static int nvme_ctrl_scan_namespaces(nvme_root_t r, struct nvme_ctrl *c) +static int nvme_ctrl_scan_namespaces(struct nvme_global_ctx *ctx, struct nvme_ctrl *c) { _cleanup_dirents_ struct dirents namespaces = {}; int i; - if (r->create_only) { - nvme_msg(r, LOG_DEBUG, "skipping namespace scan for ctrl %s\n", + if (ctx->create_only) { + nvme_msg(ctx, LOG_DEBUG, "skipping namespace scan for ctrl %s\n", c->name); return 0; } namespaces.num = nvme_scan_ctrl_namespaces(c, &namespaces.ents); for (i = 0; i < namespaces.num; i++) - nvme_ctrl_scan_namespace(r, c, namespaces.ents[i]->d_name); + nvme_ctrl_scan_namespace(ctx, c, namespaces.ents[i]->d_name); return 0; } -static char *nvme_ctrl_lookup_subsystem_name(nvme_root_t r, - const char *ctrl_name) +static int nvme_ctrl_lookup_subsystem_name(struct nvme_global_ctx *ctx, + const char *ctrl_name, + char **name) { const char *subsys_dir = nvme_subsys_sysfs_dir(); _cleanup_dirents_ struct dirents subsys = {}; @@ -1917,41 +1922,48 @@ static char *nvme_ctrl_lookup_subsystem_name(nvme_root_t r, subsys.num = nvme_scan_subsystems(&subsys.ents); if (subsys.num < 0) - return NULL; + return subsys.num; + for (i = 0; i < subsys.num; i++) { struct stat st; _cleanup_free_ char *path = NULL; if (asprintf(&path, "%s/%s/%s", subsys_dir, - subsys.ents[i]->d_name, ctrl_name) < 0) { - errno = ENOMEM; - return NULL; - } - nvme_msg(r, LOG_DEBUG, "lookup subsystem %s\n", path); + subsys.ents[i]->d_name, ctrl_name) < 0) + return -ENOMEM; + nvme_msg(ctx, LOG_DEBUG, "lookup subsystem %s\n", path); if (stat(path, &st) < 0) { continue; } - return strdup(subsys.ents[i]->d_name); + + *name = strdup(subsys.ents[i]->d_name); + if (!*name) + return -ENOMEM; + + return 0; } - return NULL; + return -ENOENT; } -static char *nvme_ctrl_lookup_phy_slot(nvme_root_t r, const char *address) +static int nvme_ctrl_lookup_phy_slot(struct nvme_global_ctx *ctx, + const char *address, + char **slotp) { const char *slots_sysfs_dir = nvme_slots_sysfs_dir(); _cleanup_free_ char *target_addr = NULL; _cleanup_dir_ DIR *slots_dir = NULL; - int ret; struct dirent *entry; + char *slot; + int ret; if (!address) - return NULL; + return -EINVAL; slots_dir = opendir(slots_sysfs_dir); if (!slots_dir) { - nvme_msg(r, LOG_WARNING, "failed to open slots dir %s\n", + nvme_msg(ctx, LOG_WARNING, "failed to open slots dir %s\n", slots_sysfs_dir); - return NULL; + return -errno; } target_addr = strndup(address, 10); @@ -1964,23 +1976,28 @@ static char *nvme_ctrl_lookup_phy_slot(nvme_root_t r, const char *address) ret = asprintf(&path, "%s/%s", slots_sysfs_dir, entry->d_name); - if (ret < 0) { - errno = ENOMEM; - return NULL; - } + if (ret < 0) + return -ENOMEM; addr = nvme_get_attr(path, "address"); /* some directories don't have an address entry */ if (!addr) continue; - if (strcmp(addr, target_addr) == 0) - return strdup(entry->d_name); + if (strcmp(addr, target_addr)) + continue; + + slot = strdup(entry->d_name); + if (!slot) + return -ENOMEM; + + *slotp = slot; + return 0; } } - return NULL; + return -ENOENT; } -static void nvme_read_sysfs_dhchap(nvme_root_t r, nvme_ctrl_t c) +static void nvme_read_sysfs_dhchap(struct nvme_global_ctx *ctx, nvme_ctrl_t c) { char *host_key, *ctrl_key; @@ -2005,7 +2022,7 @@ static void nvme_read_sysfs_dhchap(nvme_root_t r, nvme_ctrl_t c) } } -static void nvme_read_sysfs_tls(nvme_root_t r, nvme_ctrl_t c) +static void nvme_read_sysfs_tls(struct nvme_global_ctx *ctx, nvme_ctrl_t c) { char *endptr; long key_id; @@ -2041,7 +2058,7 @@ static void nvme_read_sysfs_tls(nvme_root_t r, nvme_ctrl_t c) free(key); } -static int nvme_reconfigure_ctrl(nvme_root_t r, nvme_ctrl_t c, const char *path, +static int nvme_reconfigure_ctrl(struct nvme_global_ctx *ctx, nvme_ctrl_t c, const char *path, const char *name) { DIR *d; @@ -2050,7 +2067,7 @@ static int nvme_reconfigure_ctrl(nvme_root_t r, nvme_ctrl_t c, const char *path, * It's necesssary to release any resources first because a ctrl * can be reused. */ - nvme_ctrl_release_fd(c); + nvme_ctrl_release_transport_handle(c); FREE_CTRL_ATTR(c->name); FREE_CTRL_ATTR(c->sysfs_dir); FREE_CTRL_ATTR(c->firmware); @@ -2067,13 +2084,13 @@ static int nvme_reconfigure_ctrl(nvme_root_t r, nvme_ctrl_t c, const char *path, d = opendir(path); if (!d) { - nvme_msg(r, LOG_ERR, "Failed to open ctrl dir %s, error %d\n", + nvme_msg(ctx, LOG_ERR, "Failed to open ctrl dir %s, error %d\n", path, errno); - errno = ENODEV; - return -1; + return -ENODEV; } closedir(d); + c->hdl = NULL; c->name = xstrdup(name); c->sysfs_dir = xstrdup(path); c->firmware = nvme_get_ctrl_attr(c, "firmware_rev"); @@ -2086,11 +2103,10 @@ static int nvme_reconfigure_ctrl(nvme_root_t r, nvme_ctrl_t c, const char *path, c->cntrltype = nvme_get_ctrl_attr(c, "cntrltype"); c->cntlid = nvme_get_ctrl_attr(c, "cntlid"); c->dctype = nvme_get_ctrl_attr(c, "dctype"); - c->phy_slot = nvme_ctrl_lookup_phy_slot(r, c->address); - nvme_read_sysfs_dhchap(r, c); - nvme_read_sysfs_tls(r, c); + nvme_ctrl_lookup_phy_slot(ctx, c->address, &c->phy_slot); + nvme_read_sysfs_dhchap(ctx, c); + nvme_read_sysfs_tls(ctx, c); - errno = 0; /* cleanup after nvme_get_ctrl_attr() */ return 0; } @@ -2101,48 +2117,45 @@ int nvme_init_ctrl(nvme_host_t h, nvme_ctrl_t c, int instance) int ret; ret = asprintf(&name, "nvme%d", instance); - if (ret < 0) { - errno = ENOMEM; - return -1; - } + if (ret < 0) + return -ENOMEM; + ret = asprintf(&path, "%s/%s", nvme_ctrl_sysfs_dir(), name); - if (ret < 0) { - errno = ENOMEM; - return ret; - } + if (ret < 0) + return -ENOMEM; - ret = nvme_reconfigure_ctrl(h->r, c, path, name); + ret = nvme_reconfigure_ctrl(h->ctx, c, path, name); if (ret < 0) return ret; c->address = nvme_get_attr(path, "address"); - if (!c->address && strcmp(c->transport, "loop")) { - errno = ENVME_CONNECT_INVAL_TR; - return -1; - } + if (!c->address && strcmp(c->transport, "loop")) + return -ENVME_CONNECT_INVAL_TR; - subsys_name = nvme_ctrl_lookup_subsystem_name(h->r, name); - if (!subsys_name) { - nvme_msg(h->r, LOG_ERR, + ret = nvme_ctrl_lookup_subsystem_name(h->ctx, name, &subsys_name); + if (ret) { + nvme_msg(h->ctx, LOG_ERR, "Failed to lookup subsystem name for %s\n", c->name); - errno = ENVME_CONNECT_LOOKUP_SUBSYS_NAME; - return -1; + return ENVME_CONNECT_LOOKUP_SUBSYS_NAME; } + s = nvme_lookup_subsystem(h, subsys_name, c->subsysnqn); - if (!s) { - errno = ENVME_CONNECT_LOOKUP_SUBSYS; - return -1; - } + if (!s) + return -ENVME_CONNECT_LOOKUP_SUBSYS; + if (s->subsystype && !strcmp(s->subsystype, "discovery")) c->discovery_ctrl = true; + c->s = s; list_add_tail(&s->ctrls, &c->entry); + return ret; } -static nvme_ctrl_t nvme_ctrl_alloc(nvme_root_t r, nvme_subsystem_t s, - const char *path, const char *name) +int nvme_ctrl_alloc(struct nvme_global_ctx *ctx, nvme_subsystem_t s, + const char *path, const char *name, + nvme_ctrl_t *cp) { _cleanup_free_ char *addr = NULL, *address = NULL, *transport = NULL; char *host_traddr = NULL, *host_iface = NULL; @@ -2152,10 +2165,9 @@ static nvme_ctrl_t nvme_ctrl_alloc(nvme_root_t r, nvme_subsystem_t s, int ret; transport = nvme_get_attr(path, "transport"); - if (!transport) { - errno = ENXIO; - return NULL; - } + if (!transport) + return -ENXIO; + /* Parse 'address' string into components */ addr = nvme_get_attr(path, "address"); if (!addr) { @@ -2168,16 +2180,12 @@ static nvme_ctrl_t nvme_ctrl_alloc(nvme_root_t r, nvme_subsystem_t s, /* Older kernel don't support pcie transport addresses */ if (strcmp(transport, "pcie") && - strcmp(transport, "apple-nvme")) { - errno = ENXIO; - return NULL; - } + strcmp(transport, "apple-nvme")) + return -ENXIO; /* Figure out the PCI address from the attribute path */ rpath = realpath(path, NULL); - if (!rpath) { - errno = ENOMEM; - return NULL; - } + if (!rpath) + return -ENOMEM; a = strtok_r(rpath, "/", &e); while(a && strlen(a)) { if (_a) @@ -2217,30 +2225,34 @@ static nvme_ctrl_t nvme_ctrl_alloc(nvme_root_t r, nvme_subsystem_t s, if (!c->name) break; if (!strcmp(c->name, name)) { - nvme_msg(r, LOG_DEBUG, + nvme_msg(ctx, LOG_DEBUG, "found existing ctrl %s\n", c->name); break; } - nvme_msg(r, LOG_DEBUG, "skipping ctrl %s\n", c->name); + nvme_msg(ctx, LOG_DEBUG, "skipping ctrl %s\n", c->name); p = c; } } while (c); if (!c) c = p; if (!c && !p) { - nvme_msg(r, LOG_ERR, "failed to lookup ctrl\n"); - errno = ENODEV; - return NULL; + nvme_msg(ctx, LOG_ERR, "failed to lookup ctrl\n"); + return -ENODEV; } FREE_CTRL_ATTR(c->address); c->address = xstrdup(addr); if (s->subsystype && !strcmp(s->subsystype, "discovery")) c->discovery_ctrl = true; - ret = nvme_reconfigure_ctrl(r, c, path, name); - return (ret < 0) ? NULL : c; + ret = nvme_reconfigure_ctrl(ctx, c, path, name); + if (ret) + return ret; + + *cp = c; + return 0; } -nvme_ctrl_t nvme_scan_ctrl(nvme_root_t r, const char *name) +int nvme_scan_ctrl(struct nvme_global_ctx *ctx, const char *name, + nvme_ctrl_t *cp) { _cleanup_free_ char *subsysnqn = NULL, *subsysname = NULL; _cleanup_free_ char *hostnqn = NULL, *hostid = NULL; @@ -2251,16 +2263,14 @@ nvme_ctrl_t nvme_scan_ctrl(nvme_root_t r, const char *name) nvme_ctrl_t c; int ret; - nvme_msg(r, LOG_DEBUG, "scan controller %s\n", name); + nvme_msg(ctx, LOG_DEBUG, "scan controller %s\n", name); ret = asprintf(&path, "%s/%s", nvme_ctrl_sysfs_dir(), name); - if (ret < 0) { - errno = ENOMEM; - return NULL; - } + if (ret < 0) + return -ENOMEM; hostnqn = nvme_get_attr(path, "hostnqn"); hostid = nvme_get_attr(path, "hostid"); - h = nvme_lookup_host(r, hostnqn, hostid); + h = nvme_lookup_host(ctx, hostnqn, hostid); if (h) { host_key = nvme_get_attr(path, "dhchap_secret"); if (host_key && strcmp(host_key, "none")) { @@ -2271,50 +2281,46 @@ nvme_ctrl_t nvme_scan_ctrl(nvme_root_t r, const char *name) free(host_key); } if (!h) { - h = nvme_default_host(r); - if (!h) { - errno = ENOMEM; - return NULL; - } + ret = nvme_default_host(ctx, &h); + if (ret) + return ret; } subsysnqn = nvme_get_attr(path, "subsysnqn"); - if (!subsysnqn) { - errno = ENXIO; - return NULL; - } - subsysname = nvme_ctrl_lookup_subsystem_name(r, name); - if (!subsysname) { - nvme_msg(r, LOG_DEBUG, + if (!subsysnqn) + return -ENXIO; + + ret = nvme_ctrl_lookup_subsystem_name(ctx, name, &subsysname); + if (ret) { + nvme_msg(ctx, LOG_DEBUG, "failed to lookup subsystem for controller %s\n", name); - errno = ENXIO; - return NULL; + return ret; } + s = nvme_lookup_subsystem(h, subsysname, subsysnqn); + if (!s) + return -ENOMEM; - if (!s) { - errno = ENOMEM; - return NULL; - } + ret = nvme_ctrl_alloc(ctx, s, path, name, &c); + if (ret) + return ret; - c = nvme_ctrl_alloc(r, s, path, name); - if (!c) - return NULL; + nvme_ctrl_scan_paths(ctx, c); + nvme_ctrl_scan_namespaces(ctx, c); - nvme_ctrl_scan_paths(r, c); - nvme_ctrl_scan_namespaces(r, c); - return c; + *cp = c; + return 0; } void nvme_rescan_ctrl(struct nvme_ctrl *c) { - nvme_root_t r = c->s && c->s->h ? c->s->h->r : NULL; + struct nvme_global_ctx *ctx = c->s && c->s->h ? c->s->h->ctx : NULL; if (!c->s) return; - nvme_ctrl_scan_namespaces(r, c); - nvme_ctrl_scan_paths(r, c); - nvme_subsystem_scan_namespaces(r, c->s); + nvme_ctrl_scan_namespaces(ctx, c); + nvme_ctrl_scan_paths(ctx, c); + nvme_subsystem_scan_namespaces(ctx, c->s); } static int nvme_bytes_to_lba(nvme_ns_t n, off_t offset, size_t count, @@ -2323,36 +2329,38 @@ static int nvme_bytes_to_lba(nvme_ns_t n, off_t offset, size_t count, int bs; bs = nvme_ns_get_lba_size(n); - if (!count || offset & (bs - 1) || count & (bs - 1)) { - errno = EINVAL; - return -1; - } + if (!count || offset & (bs - 1) || count & (bs - 1)) + return -EINVAL; *lba = offset >> n->lba_shift; *nlb = (count >> n->lba_shift) - 1; + return 0; } -int nvme_ns_get_fd(nvme_ns_t n) +struct nvme_transport_handle *nvme_ns_get_transport_handle(nvme_ns_t n) { - if (n->fd < 0) { - n->fd = nvme_open(n->name); - if (n->fd < 0) - nvme_msg(root_from_ns(n), LOG_ERR, - "Failed to open ns %s, errno %d\n", - n->name, errno); + if (!n->hdl) { + struct nvme_global_ctx *ctx = ctx_from_ns(n); + int err; + + err = nvme_open(ctx, n->name, &n->hdl); + if (err) + nvme_msg(ctx, LOG_ERR, + "Failed to open ns %s, error %d\n", + n->name, err); } - return n->fd; + return n->hdl; } -void nvme_ns_release_fd(nvme_ns_t n) +void nvme_ns_release_transport_handle(nvme_ns_t n) { - if (n->fd < 0) + if (!n->hdl) return; - close(n->fd); - n->fd = -1; + nvme_close(n->hdl); + n->hdl = NULL; } nvme_subsystem_t nvme_ns_get_subsystem(nvme_ns_t n) @@ -2447,179 +2455,121 @@ void nvme_ns_get_uuid(nvme_ns_t n, unsigned char out[NVME_UUID_LEN]) int nvme_ns_identify(nvme_ns_t n, struct nvme_id_ns *ns) { - return nvme_identify_ns(nvme_ns_get_fd(n), nvme_ns_get_nsid(n), ns); + struct nvme_transport_handle *hdl = nvme_ns_get_transport_handle(n); + struct nvme_passthru_cmd cmd; + + nvme_init_identify_ns(&cmd, nvme_ns_get_nsid(n), ns); + return nvme_submit_admin_passthru(hdl, &cmd, NULL); } int nvme_ns_identify_descs(nvme_ns_t n, struct nvme_ns_id_desc *descs) { - return nvme_identify_ns_descs(nvme_ns_get_fd(n), nvme_ns_get_nsid(n), descs); + struct nvme_transport_handle *hdl = nvme_ns_get_transport_handle(n); + struct nvme_passthru_cmd cmd; + + nvme_init_identify_ns_descs_list(&cmd, nvme_ns_get_nsid(n), descs); + return nvme_submit_admin_passthru(hdl, &cmd, NULL); } int nvme_ns_verify(nvme_ns_t n, off_t offset, size_t count) { - struct nvme_io_args args = { - .args_size = sizeof(args), - .fd = nvme_ns_get_fd(n), - .nsid = nvme_ns_get_nsid(n), - .control = 0, - .dsm = 0, - .dspec = 0, - .reftag = 0, - .apptag = 0, - .appmask = 0, - .storage_tag = 0, - .data_len = 0, - .data = NULL, - .metadata_len = 0, - .metadata = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; + struct nvme_transport_handle *hdl = nvme_ns_get_transport_handle(n); + struct nvme_passthru_cmd cmd; + __u64 slba; + __u16 nlb; - if (nvme_bytes_to_lba(n, offset, count, &args.slba, &args.nlb)) + if (nvme_bytes_to_lba(n, offset, count, &slba, &nlb)) return -1; - return nvme_verify(&args); + nvme_init_verify(&cmd, nvme_ns_get_nsid(n), slba, nlb, + 0, 0, NULL, 0, NULL, 0); + + return nvme_submit_io_passthru(hdl, &cmd, NULL); } int nvme_ns_write_uncorrectable(nvme_ns_t n, off_t offset, size_t count) { - struct nvme_io_args args = { - .args_size = sizeof(args), - .fd = nvme_ns_get_fd(n), - .nsid = nvme_ns_get_nsid(n), - .control = 0, - .dsm = 0, - .dspec = 0, - .reftag = 0, - .apptag = 0, - .appmask = 0, - .storage_tag = 0, - .data_len = 0, - .data = NULL, - .metadata_len = 0, - .metadata = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; + struct nvme_transport_handle *hdl = nvme_ns_get_transport_handle(n); + struct nvme_passthru_cmd cmd; + __u64 slba; + __u16 nlb; - if (nvme_bytes_to_lba(n, offset, count, &args.slba, &args.nlb)) + if (nvme_bytes_to_lba(n, offset, count, &slba, &nlb)) return -1; - return nvme_write_uncorrectable(&args); + nvme_init_write_uncorrectable(&cmd, nvme_ns_get_nsid(n), slba, nlb, + 0, 0); + + return nvme_submit_io_passthru(hdl, &cmd, NULL); } int nvme_ns_write_zeros(nvme_ns_t n, off_t offset, size_t count) { - struct nvme_io_args args = { - .args_size = sizeof(args), - .fd = nvme_ns_get_fd(n), - .nsid = nvme_ns_get_nsid(n), - .control = 0, - .dsm = 0, - .dspec = 0, - .reftag = 0, - .apptag = 0, - .appmask = 0, - .storage_tag = 0, - .data_len = 0, - .data = NULL, - .metadata_len = 0, - .metadata = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; + struct nvme_transport_handle *hdl = nvme_ns_get_transport_handle(n); + struct nvme_passthru_cmd cmd; + __u64 slba; + __u16 nlb; - if (nvme_bytes_to_lba(n, offset, count, &args.slba, &args.nlb)) + if (nvme_bytes_to_lba(n, offset, count, &slba, &nlb)) return -1; - return nvme_write_zeros(&args); + nvme_init_write_zeros(&cmd, nvme_ns_get_nsid(n), slba, nlb, 0, 0, 0, 0); + + return nvme_submit_io_passthru(hdl, &cmd, NULL); } int nvme_ns_write(nvme_ns_t n, void *buf, off_t offset, size_t count) { - struct nvme_io_args args = { - .args_size = sizeof(args), - .fd = nvme_ns_get_fd(n), - .nsid = nvme_ns_get_nsid(n), - .control = 0, - .dsm = 0, - .dspec = 0, - .reftag = 0, - .apptag = 0, - .appmask = 0, - .storage_tag = 0, - .data_len = count, - .data = buf, - .metadata_len = 0, - .metadata = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; + struct nvme_transport_handle *hdl = nvme_ns_get_transport_handle(n); + struct nvme_passthru_cmd cmd; + __u64 slba; + __u16 nlb; - if (nvme_bytes_to_lba(n, offset, count, &args.slba, &args.nlb)) + if (nvme_bytes_to_lba(n, offset, count, &slba, &nlb)) return -1; - return nvme_write(&args); + nvme_init_write(&cmd, nvme_ns_get_nsid(n), slba, nlb, + 0, 0, 0, 0, buf, count, NULL, 0); + + return nvme_submit_io_passthru(hdl, &cmd, NULL); } int nvme_ns_read(nvme_ns_t n, void *buf, off_t offset, size_t count) { - struct nvme_io_args args = { - .args_size = sizeof(args), - .fd = nvme_ns_get_fd(n), - .nsid = nvme_ns_get_nsid(n), - .control = 0, - .dsm = 0, - .dspec = 0, - .reftag = 0, - .apptag = 0, - .appmask = 0, - .storage_tag = 0, - .data_len = count, - .data = buf, - .metadata_len = 0, - .metadata = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; + struct nvme_transport_handle *hdl = nvme_ns_get_transport_handle(n); + struct nvme_passthru_cmd cmd; + __u64 slba; + __u16 nlb; - if (nvme_bytes_to_lba(n, offset, count, &args.slba, &args.nlb)) + if (nvme_bytes_to_lba(n, offset, count, &slba, &nlb)) return -1; - return nvme_read(&args); + nvme_init_read(&cmd, nvme_ns_get_nsid(n), slba, nlb, + 0, 0, 0, buf, count, NULL, 0); + + return nvme_submit_io_passthru(hdl, &cmd, NULL); } int nvme_ns_compare(nvme_ns_t n, void *buf, off_t offset, size_t count) { - struct nvme_io_args args = { - .args_size = sizeof(args), - .fd = nvme_ns_get_fd(n), - .nsid = nvme_ns_get_nsid(n), - .control = 0, - .dsm = 0, - .dspec = 0, - .reftag = 0, - .apptag = 0, - .appmask = 0, - .storage_tag = 0, - .data_len = count, - .data = buf, - .metadata_len = 0, - .metadata = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; + struct nvme_transport_handle *hdl = nvme_ns_get_transport_handle(n); + struct nvme_passthru_cmd cmd; + __u64 slba; + __u16 nlb; - if (nvme_bytes_to_lba(n, offset, count, &args.slba, &args.nlb)) + if (nvme_bytes_to_lba(n, offset, count, &slba, &nlb)) return -1; - return nvme_compare(&args); + nvme_init_compare(&cmd, nvme_ns_get_nsid(n), slba, nlb, + 0, 0, buf, count, NULL, 0); + + return nvme_submit_io_passthru(hdl, &cmd, NULL); } int nvme_ns_flush(nvme_ns_t n) { - return nvme_flush(nvme_ns_get_fd(n), nvme_ns_get_nsid(n)); + return nvme_flush(nvme_ns_get_transport_handle(n), + nvme_ns_get_nsid(n)); } static int nvme_strtou64(const char *str, void *res) @@ -2755,7 +2705,8 @@ static int nvme_ns_init(const char *path, struct nvme_ns *ns) ns->lba_count = size >> (ns->lba_shift - SECTOR_SHIFT); if (asprintf(&attr, "%s/csi", path) < 0) - return -errno; + return -ENOMEM; + ret = stat(attr, &sb); if (ret == 0) { /* only available on kernels >= 6.8 */ @@ -2804,7 +2755,7 @@ static void nvme_ns_set_generic_name(struct nvme_ns *n, const char *name) n->generic_name = strdup(generic_name); } -static nvme_ns_t nvme_ns_open(const char *sys_path, const char *name) +int nvme_ns_open(const char *sys_path, const char *name, nvme_ns_t *ns) { int ret; struct nvme_ns *n; @@ -2813,25 +2764,23 @@ static nvme_ns_t nvme_ns_open(const char *sys_path, const char *name) _cleanup_free_ char *path = NULL; n = calloc(1, sizeof(*n)); - if (!n) { - errno = ENOMEM; - return NULL; - } + if (!n) + return -ENOMEM; head = calloc(1, sizeof(*head)); if (!head) { - errno = ENOMEM; free(n); - return NULL; + return -ENOMEM; } head->n = n; list_head_init(&head->paths); ret = asprintf(&path, "%s/%s", sys_path, "multipath"); if (ret < 0) { - errno = ENOMEM; + ret = -ENOMEM; goto free_ns_head; } + /* * The sysfs-dir "multipath" is available only when nvme multipath * is configured and we're running kernel version >= 6.14. @@ -2844,19 +2793,21 @@ static nvme_ns_t nvme_ns_open(const char *sys_path, const char *name) head->sysfs_dir = NULL; n->head = head; - n->fd = -1; + n->hdl = NULL; n->name = strdup(name); nvme_ns_set_generic_name(n, name); - if (nvme_ns_init(sys_path, n) != 0) + ret = nvme_ns_init(sys_path, n); + if (ret) goto free_ns; list_node_init(&n->entry); - nvme_ns_release_fd(n); /* Do not leak fds */ + nvme_ns_release_transport_handle(n); - return n; + *ns = n; + return 0; free_ns: free(n->generic_name); @@ -2864,7 +2815,7 @@ static nvme_ns_t nvme_ns_open(const char *sys_path, const char *name) free_ns_head: free(head); free(n); - return NULL; + return ret; } static inline bool nvme_ns_is_generic(const char *name) @@ -2891,38 +2842,35 @@ static char *nvme_ns_generic_to_blkdev(const char *generic) return strdup(blkdev); } -static struct nvme_ns *__nvme_scan_namespace(const char *sysfs_dir, const char *name) +static int __nvme_scan_namespace(const char *sysfs_dir, const char *name, nvme_ns_t *ns) { - struct nvme_ns *n; + _cleanup_free_ char *blkdev = NULL; _cleanup_free_ char *path = NULL; + struct nvme_ns *n; int ret; - _cleanup_free_ char *blkdev = NULL; blkdev = nvme_ns_generic_to_blkdev(name); - if (!blkdev) { - errno = ENOMEM; - return NULL; - } + if (!blkdev) + return -ENOMEM; ret = asprintf(&path, "%s/%s", sysfs_dir, blkdev); - if (ret < 0) { - errno = ENOMEM; - return NULL; - } + if (ret < 0) + return -ENOMEM; - n = nvme_ns_open(path, blkdev); - if (!n) - return NULL; + ret = nvme_ns_open(path, blkdev, &n); + if (ret) + return ret; n->sysfs_dir = path; path = NULL; - return n; + *ns = n; + return 0; } -nvme_ns_t nvme_scan_namespace(const char *name) +int nvme_scan_namespace(const char *name, nvme_ns_t *ns) { - return __nvme_scan_namespace(nvme_ns_sysfs_dir(), name); + return __nvme_scan_namespace(nvme_ns_sysfs_dir(), name, ns); } @@ -2990,22 +2938,22 @@ static void nvme_subsystem_set_ns_path(nvme_subsystem_t s, nvme_ns_t n) } } -static int nvme_ctrl_scan_namespace(nvme_root_t r, struct nvme_ctrl *c, +static int nvme_ctrl_scan_namespace(struct nvme_global_ctx *ctx, struct nvme_ctrl *c, char *name) { struct nvme_ns *n, *_n, *__n; + int ret; - nvme_msg(r, LOG_DEBUG, "scan controller %s namespace %s\n", + nvme_msg(ctx, LOG_DEBUG, "scan controller %s namespace %s\n", c->name, name); if (!c->s) { - nvme_msg(r, LOG_DEBUG, "no subsystem for %s\n", name); - errno = EINVAL; - return -1; + nvme_msg(ctx, LOG_DEBUG, "no subsystem for %s\n", name); + return -EINVAL; } - n = __nvme_scan_namespace(c->sysfs_dir, name); - if (!n) { - nvme_msg(r, LOG_DEBUG, "failed to scan namespace %s\n", name); - return -1; + ret = __nvme_scan_namespace(c->sysfs_dir, name, &n); + if (ret) { + nvme_msg(ctx, LOG_DEBUG, "failed to scan namespace %s\n", name); + return ret; } nvme_ctrl_for_each_ns_safe(c, _n, __n) { if (strcmp(n->name, _n->name)) @@ -3020,17 +2968,18 @@ static int nvme_ctrl_scan_namespace(nvme_root_t r, struct nvme_ctrl *c, return 0; } -static int nvme_subsystem_scan_namespace(nvme_root_t r, nvme_subsystem_t s, +static int nvme_subsystem_scan_namespace(struct nvme_global_ctx *ctx, nvme_subsystem_t s, char *name) { struct nvme_ns *n, *_n, *__n; + int ret; - nvme_msg(r, LOG_DEBUG, "scan subsystem %s namespace %s\n", + nvme_msg(ctx, LOG_DEBUG, "scan subsystem %s namespace %s\n", s->name, name); - n = __nvme_scan_namespace(s->sysfs_dir, name); - if (!n) { - nvme_msg(r, LOG_DEBUG, "failed to scan namespace %s\n", name); - return -1; + ret = __nvme_scan_namespace(s->sysfs_dir, name, &n); + if (ret) { + nvme_msg(ctx, LOG_DEBUG, "failed to scan namespace %s\n", name); + return ret; } nvme_subsystem_for_each_ns_safe(s, _n, __n) { struct nvme_path *p, *_p; diff --git a/libnvme/src/nvme/tree.h b/libnvme/src/nvme/tree.h index e0377b2315..c1622d3454 100644 --- a/libnvme/src/nvme/tree.h +++ b/libnvme/src/nvme/tree.h @@ -10,7 +10,6 @@ #ifndef _LIBNVME_TREE_H #define _LIBNVME_TREE_H -#include #include #include @@ -32,92 +31,74 @@ typedef struct nvme_path *nvme_path_t; typedef struct nvme_ctrl *nvme_ctrl_t; typedef struct nvme_subsystem *nvme_subsystem_t; typedef struct nvme_host *nvme_host_t; -typedef struct nvme_root *nvme_root_t; typedef bool (*nvme_scan_filter_t)(nvme_subsystem_t, nvme_ctrl_t, nvme_ns_t, void *); /** - * nvme_create_root() - Initialize root object - * @fp: File descriptor for logging messages - * @log_level: Logging level to use - * - * Return: Initialized &nvme_root_t object - */ -nvme_root_t nvme_create_root(FILE *fp, int log_level); - -/** - * nvme_root_set_application - Specify managing application - * @r: &nvme_root_t object + * nvme_set_application - Specify managing application + * @ctx: struct nvme_global_ctx object * @a: Application string * * Sets the managing application string for @r. */ -void nvme_root_set_application(nvme_root_t r, const char *a); +void nvme_set_application(struct nvme_global_ctx *ctx, const char *a); /** - * nvme_root_get_application - Get managing application - * @r: &nvme_root_t object + * nvme_get_application - Get managing application + * @ctx: struct nvme_global_ctx object * * Returns the managing application string for @r or NULL if not set. */ -const char *nvme_root_get_application(nvme_root_t r); +const char *nvme_get_application(struct nvme_global_ctx *ctx); /** - * nvme_root_skip_namespaces - Skip namespace scanning - * @r: &nvme_root_t object + * nvme_skip_namespaces - Skip namespace scanning + * @ctx: struct nvme_global_ctx object * * Sets a flag to skip namespaces during scanning. */ -void nvme_root_skip_namespaces(nvme_root_t r); +void nvme_skip_namespaces(struct nvme_global_ctx *ctx); /** - * nvme_root_release_fds - Close all opened file descriptors in the tree - * @r: &nvme_root_t object + * nvme_release_fds - Close all opened file descriptors in the tree + * @ctx: struct nvme_global_ctx object * * Controller and Namespace objects cache the file descriptors * of opened nvme devices. This API can be used to close and * clear all cached fds in the tree. * */ -void nvme_root_release_fds(nvme_root_t r); - -/** - * nvme_free_tree() - Free root object - * @r: &nvme_root_t object - * - * Free an &nvme_root_t object and all attached objects - */ -void nvme_free_tree(nvme_root_t r); +void nvme_release_fds(struct nvme_global_ctx *ctx); /** * nvme_first_host() - Start host iterator - * @r: &nvme_root_t object + * @ctx: struct nvme_global_ctx object * * Return: First &nvme_host_t object in an iterator */ -nvme_host_t nvme_first_host(nvme_root_t r); +nvme_host_t nvme_first_host(struct nvme_global_ctx *ctx); /** * nvme_next_host() - Next host iterator - * @r: &nvme_root_t object + * @ctx: struct nvme_global_ctx object * @h: Previous &nvme_host_t iterator * * Return: Next &nvme_host_t object in an iterator */ -nvme_host_t nvme_next_host(nvme_root_t r, nvme_host_t h); +nvme_host_t nvme_next_host(struct nvme_global_ctx *ctx, nvme_host_t h); /** - * nvme_host_get_root() - Returns nvme_root_t object + * nvme_host_get_global_ctx() - Returns nvme_global_ctx object * @h: &nvme_host_t object * - * Return: &nvme_root_t object from @h + * Return: &struct nvme_global_ctx object from @h */ -nvme_root_t nvme_host_get_root(nvme_host_t h); +struct nvme_global_ctx *nvme_host_get_global_ctx(nvme_host_t h); /** * nvme_lookup_host() - Lookup nvme_host_t object - * @r: &nvme_root_t object + * @ctx: struct nvme_global_ctx object * @hostnqn: Host NQN * @hostid: Host ID * @@ -126,7 +107,7 @@ nvme_root_t nvme_host_get_root(nvme_host_t h); * * Return: &nvme_host_t object */ -nvme_host_t nvme_lookup_host(nvme_root_t r, const char *hostnqn, +nvme_host_t nvme_lookup_host(struct nvme_global_ctx *ctx, const char *hostnqn, const char *hostid); /** @@ -168,19 +149,20 @@ bool nvme_host_is_pdc_enabled(nvme_host_t h, bool fallback); /** * nvme_default_host() - Initializes the default host - * @r: &nvme_root_t object + * @ctx: struct nvme_global_ctx object + * @h: &nvme_host_t object to return * * Initializes the default host object based on the hostnqn/hostid * values returned by nvme_host_get_ids() and attaches it to @r. * - * Return: &nvme_host_t object + * Return: 0 on success or negative error code otherwise */ -nvme_host_t nvme_default_host(nvme_root_t r); +int nvme_default_host(struct nvme_global_ctx *ctx, nvme_host_t *h); /** * nvme_host_get_ids - Retrieve host ids from various sources * - * @r: &nvme_root_t object + * @ctx: struct nvme_global_ctx object * @hostnqn_arg: Input hostnqn (command line) argument * @hostid_arg: Input hostid (command line) argument * @hostnqn: Output hostnqn @@ -206,9 +188,9 @@ nvme_host_t nvme_default_host(nvme_root_t r); * NVMe implementation expects a 1:1 matching between the IDs. * * Return: 0 on success (@hostnqn and @hostid contain valid strings - * which the caller needs to free), -1 otherwise and errno is set. + * which the caller needs to free), or negative error code otherwise. */ -int nvme_host_get_ids(nvme_root_t r, +int nvme_host_get_ids(struct nvme_global_ctx *ctx, char *hostnqn_arg, char *hostid_arg, char **hostnqn, char **hostid); @@ -399,22 +381,24 @@ bool nvme_ctrl_config_match(struct nvme_ctrl *c, const char *transport, /** * nvme_create_ctrl() - Allocate an unconnected NVMe controller - * @r: NVMe root element + * @ctx: struct nvme_global_ctx object * @subsysnqn: Subsystem NQN * @transport: Transport type * @traddr: Transport address * @host_traddr: Host transport address * @host_iface: Host interface name * @trsvcid: Transport service ID + * @c: @nvme_ctrl_t object to return * * Creates an unconnected controller to be used for nvme_add_ctrl(). * - * Return: Controller instance + * Return: 0 on success or negative error code otherwise */ -nvme_ctrl_t nvme_create_ctrl(nvme_root_t r, - const char *subsysnqn, const char *transport, - const char *traddr, const char *host_traddr, - const char *host_iface, const char *trsvcid); +int nvme_create_ctrl(struct nvme_global_ctx *ctx, + const char *subsysnqn, const char *transport, + const char *traddr, const char *host_traddr, + const char *host_iface, const char *trsvcid, + nvme_ctrl_t *c); /** @@ -582,26 +566,26 @@ nvme_ns_t nvme_subsystem_next_ns(nvme_subsystem_t s, nvme_ns_t n); p = nvme_namespace_next_path(n, p)) /** - * nvme_ns_get_fd() - Get associated file descriptor + * nvme_ns_get_transport_handle() - Get associated transport handle * @n: Namespace instance * * libnvme will open() the file (if not already opened) and keep - * an internal copy of the file descriptor. Following calls to - * this API retrieve the internal cached copy of the file - * descriptor. The file will remain opened and the fd will + * an internal copy of the link handle. Following calls to + * this API retrieve the internal cached copy of the link + * handle. The file will remain opened and the device handle will * remain cached until the ns object is deleted or - * nvme_ns_release_fd() is called. + * nvme_ns_release_transport_handle() is called. * - * Return: File descriptor associated with @n or -1 + * Return: Link handle with @n or NULL */ -int nvme_ns_get_fd(nvme_ns_t n); +struct nvme_transport_handle *nvme_ns_get_transport_handle(nvme_ns_t n); /** - * nvme_ns_release_fd() - Close fd and clear fd from ns object + * nvme_ns_release_transport_handle() - Free transport handle from ns object * @n: Namespace instance * */ -void nvme_ns_release_fd(nvme_ns_t n); +void nvme_ns_release_transport_handle(nvme_ns_t n); /** * nvme_ns_get_nsid() - NSID of a namespace @@ -900,26 +884,25 @@ nvme_ctrl_t nvme_path_get_ctrl(nvme_path_t p); nvme_ns_t nvme_path_get_ns(nvme_path_t p); /** - * nvme_ctrl_get_fd() - Get associated file descriptor + * nvme_ctrl_get_transport_handle() - Get associated transport handle * @c: Controller instance * - * libnvme will open() the file (if not already opened) and keep - * an internal copy of the file descriptor. Following calls to - * this API retrieve the internal cached copy of the file - * descriptor. The file will remain opened and the fd will - * remain cached until the controller object is deleted or - * nvme_ctrl_release_fd() is called. + * libnvme will open() the device (if not already opened) and keep an + * internal copy of the link handle. Following calls to this API retrieve + * the internal cached copy of the link handle. The file will remain + * opened and the handle will remain cached until the controller object + * is deleted or nvme_ctrl_release_transport_handle() is called. * - * Return: File descriptor associated with @c or -1 + * Return: Link handle associated with @c or NULL */ -int nvme_ctrl_get_fd(nvme_ctrl_t c); +struct nvme_transport_handle *nvme_ctrl_get_transport_handle(nvme_ctrl_t c); /** - * nvme_ctrl_release_fd() - Close fd and clear fd from controller object + * nvme_ctrl_release_transport_handle() - Free transport handle from controller object * @c: Controller instance * */ -void nvme_ctrl_release_fd(nvme_ctrl_t c); +void nvme_ctrl_release_transport_handle(nvme_ctrl_t c); /** * nvme_ctrl_get_name() - sysfs name of a controller @@ -1275,14 +1258,15 @@ int nvme_disconnect_ctrl(nvme_ctrl_t c); /** * nvme_scan_ctrl() - Scan on a controller - * @r: nvme_root_t object + * @ctx: struct nvme_global_ctx object * @name: Name of the controller + * @c: @nvme_ctrl_t object to return * * Scans a controller with sysfs name @name and add it to @r. * - * Return: nvme_ctrl_t object + * Return: 0 on success or negative error code otherwise */ -nvme_ctrl_t nvme_scan_ctrl(nvme_root_t r, const char *name); +int nvme_scan_ctrl(struct nvme_global_ctx *ctx, const char *name, nvme_ctrl_t *c); /** * nvme_rescan_ctrl() - Rescan an existing controller @@ -1296,7 +1280,7 @@ void nvme_rescan_ctrl(nvme_ctrl_t c); * @c: nvme_ctrl_t object * @instance: Instance number (e.g. 1 for nvme1) * - * Return: The ioctl() return code. Typically 0 on success. + * Return: 0 on success or negative error code otherwise */ int nvme_init_ctrl(nvme_host_t h, nvme_ctrl_t c, int instance); @@ -1397,16 +1381,16 @@ const char *nvme_subsystem_get_fw_rev(nvme_subsystem_t s); /** * nvme_scan_topology() - Scan NVMe topology and apply filter - * @r: nvme_root_t object + * @ctx: struct nvme_global_ctx object * @f: filter to apply * @f_args: user-specified argument to @f * * Scans the NVMe topology and filters out the resulting elements * by applying @f. * - * Returns: 0 on success, -1 on failure with errno set. + * Return: 0 on success, or negative error code otherwise. */ -int nvme_scan_topology(nvme_root_t r, nvme_scan_filter_t f, void *f_args); +int nvme_scan_topology(struct nvme_global_ctx *ctx, nvme_scan_filter_t f, void *f_args); /** * nvme_host_get_hostnqn() - Host NQN of an nvme_host_t object @@ -1443,70 +1427,71 @@ void nvme_free_host(nvme_host_t h); /** * nvme_scan() - Scan NVMe topology * @config_file: Configuration file + * @ctx: &nvme_global_ctx object to return * - * Return: nvme_root_t object of found elements + * Return: 0 on success or negative error code otherwise */ -nvme_root_t nvme_scan(const char *config_file); +int nvme_scan(const char *config_file, struct nvme_global_ctx **ctx); /** * nvme_read_config() - Read NVMe JSON configuration file - * @r: nvme_root_t object + * @ctx: &struct nvme_global_ctx object * @config_file: JSON configuration file * * Read in the contents of @config_file and merge them with * the elements in @r. * - * Returns: 0 on success, -1 on failure with errno set. + * Return: 0 on success or negative error code otherwise */ -int nvme_read_config(nvme_root_t r, const char *config_file); +int nvme_read_config(struct nvme_global_ctx *ctx, const char *config_file); /** * nvme_refresh_topology() - Refresh nvme_root_t object contents - * @r: nvme_root_t object + * @ctx: &struct nvme_global_ctx object * * Removes all elements in @r and rescans the existing topology. */ -void nvme_refresh_topology(nvme_root_t r); +void nvme_refresh_topology(struct nvme_global_ctx *ctx); /** * nvme_update_config() - Update JSON configuration - * @r: nvme_root_t object + * @ctx: &struct nvme_global_ctx object * * Updates the JSON configuration file with the contents of @r. * * Return: 0 on success, -1 on failure. */ -int nvme_update_config(nvme_root_t r); +int nvme_update_config(struct nvme_global_ctx *ctx); /** * nvme_dump_config() - Print the JSON configuration - * @r: nvme_root_t object + * @ctx: &struct nvme_global_ctx object * * Prints the current contents of the JSON configuration * file to stdout. * - * Return: 0 on success, -1 on failure. + * Return: 0 on success, or negative error code otherwise. */ -int nvme_dump_config(nvme_root_t r); +int nvme_dump_config(struct nvme_global_ctx *ctx); /** * nvme_dump_tree() - Dump internal object tree - * @r: nvme_root_t object + * @ctx: &struct nvme_global_ctx object * * Prints the internal object tree in JSON format * to stdout. * - * Return: 0 on success, -1 on failure. + * Return: 0 on success or negative error code otherwise */ -int nvme_dump_tree(nvme_root_t r); +int nvme_dump_tree(struct nvme_global_ctx *ctx); /** * nvme_get_attr() - Read sysfs attribute * @d: sysfs directory * @attr: sysfs attribute name * - * Return: String with the contents of @attr or %NULL in case of an empty value - * or in case of an error (indicated by non-zero errno code). + * Return: String with the contents of @attr or %NULL in case of an empty + * value or error. */ char *nvme_get_attr(const char *d, const char *attr); @@ -1515,8 +1500,8 @@ char *nvme_get_attr(const char *d, const char *attr); * @s: nvme_subsystem_t object * @attr: sysfs attribute name * - * Return: String with the contents of @attr or %NULL in case of an empty value - * or in case of an error (indicated by non-zero errno code). + * Return: String with the contents of @attr or %NULL in case of an empty + * value or error. */ char *nvme_get_subsys_attr(nvme_subsystem_t s, const char *attr); @@ -1526,7 +1511,7 @@ char *nvme_get_subsys_attr(nvme_subsystem_t s, const char *attr); * @attr: sysfs attribute name * * Return: String with the contents of @attr or %NULL in case of an empty value - * or in case of an error (indicated by non-zero errno code). + * or in case of an error. */ char *nvme_get_ctrl_attr(nvme_ctrl_t c, const char *attr); @@ -1536,7 +1521,7 @@ char *nvme_get_ctrl_attr(nvme_ctrl_t c, const char *attr); * @attr: sysfs attribute name * * Return: String with the contents of @attr or %NULL in case of an empty value - * or in case of an error (indicated by non-zero errno code). + * or in case of an error. */ char *nvme_get_ns_attr(nvme_ns_t n, const char *attr); @@ -1568,17 +1553,18 @@ void nvme_subsystem_release_fds(struct nvme_subsystem *s); * @attr: sysfs attribute name * * Return: String with the contents of @attr or %NULL in case of an empty value - * or in case of an error (indicated by non-zero errno code). + * or in case of an error. */ char *nvme_get_path_attr(nvme_path_t p, const char *attr); /** * nvme_scan_namespace() - scan namespace based on sysfs name * @name: sysfs name of the namespace to scan + * @ns: &nvme_ns_t object to return * - * Return: nvme_ns_t object or NULL if not found. + * Return: 0 on success or negative error code otherwise */ -nvme_ns_t nvme_scan_namespace(const char *name); +int nvme_scan_namespace(const char *name, nvme_ns_t *ns); /** * nvme_host_get_hostsymname() - Get the host's symbolic name diff --git a/libnvme/src/nvme/types.h b/libnvme/src/nvme/types.h index 4943e00f4c..64a7bf9772 100644 --- a/libnvme/src/nvme/types.h +++ b/libnvme/src/nvme/types.h @@ -12,9 +12,30 @@ #include #include +#include #include +struct nvme_global_ctx; +struct nvme_transport_handle; + +/** + * nvme_create_global_ctx() - Initialize global context object + * @fp: File descriptor for logging messages + * @log_level: Logging level to use + * + * Return: Initialized &struct nvme_global_ctx object + */ +struct nvme_global_ctx *nvme_create_global_ctx(FILE *fp, int log_level); + +/** + * nvme_free_global_ctx() - Free global context object + * @ctx: &struct nvme_global_ctx object + * + * Free an &struct nvme_global_ctx object and all attached objects + */ +void nvme_free_global_ctx(struct nvme_global_ctx *ctx); + /** * DOC: types.h * @@ -8681,14 +8702,14 @@ enum nvme_identify_cns { * @NVME_LOG_LID_PHY_RX_EOM: Physical Interface Receiver Eye Opening Measurement * @NVME_LOG_LID_REACHABILITY_GROUPS: Reachability Groups * @NVME_LOG_LID_REACHABILITY_ASSOCIATIONS: Reachability Associations - * @NVME_LOG_LID_CHANGED_ALLOC_NS_LIST: Changed Allocated Namespace List + * @NVME_LOG_LID_CHANGED_ALLOC_NS: Changed Allocated Namespace List * @NVME_LOG_LID_FDP_CONFIGS: FDP Configurations * @NVME_LOG_LID_FDP_RUH_USAGE: Reclaim Unit Handle Usage * @NVME_LOG_LID_FDP_STATS: FDP Statistics * @NVME_LOG_LID_FDP_EVENTS: FDP Events - * @NVME_LOG_LID_DISCOVER: Discovery - * @NVME_LOG_LID_HOST_DISCOVER: Host Discovery - * @NVME_LOG_LID_AVE_DISCOVER: AVE Discovery + * @NVME_LOG_LID_DISCOVERY: Discovery + * @NVME_LOG_LID_HOST_DISCOVERY: Host Discovery + * @NVME_LOG_LID_AVE_DISCOVERY: AVE Discovery * @NVME_LOG_LID_PULL_MODEL_DDC_REQ: Pull Model DDC Request * @NVME_LOG_LID_RESERVATION: Reservation Notification * @NVME_LOG_LID_SANITIZE: Sanitize Status @@ -8723,14 +8744,14 @@ enum nvme_cmd_get_log_lid { NVME_LOG_LID_PHY_RX_EOM = 0x19, NVME_LOG_LID_REACHABILITY_GROUPS = 0x1a, NVME_LOG_LID_REACHABILITY_ASSOCIATIONS = 0x1b, - NVME_LOG_LID_CHANGED_ALLOC_NS_LIST = 0x1c, + NVME_LOG_LID_CHANGED_ALLOC_NS = 0x1c, NVME_LOG_LID_FDP_CONFIGS = 0x20, NVME_LOG_LID_FDP_RUH_USAGE = 0x21, NVME_LOG_LID_FDP_STATS = 0x22, NVME_LOG_LID_FDP_EVENTS = 0x23, - NVME_LOG_LID_DISCOVER = 0x70, - NVME_LOG_LID_HOST_DISCOVER = 0x71, - NVME_LOG_LID_AVE_DISCOVER = 0x72, + NVME_LOG_LID_DISCOVERY = 0x70, + NVME_LOG_LID_HOST_DISCOVERY = 0x71, + NVME_LOG_LID_AVE_DISCOVERY = 0x72, NVME_LOG_LID_PULL_MODEL_DDC_REQ = 0x73, NVME_LOG_LID_RESERVATION = 0x80, NVME_LOG_LID_SANITIZE = 0x81, @@ -8923,8 +8944,8 @@ enum nvme_features_id { * @NVME_FEAT_NOPS_NOPPME_MASK: * @NVME_FEAT_RRL_RRL_SHIFT: * @NVME_FEAT_RRL_RRL_MASK: - * @NVME_FEAT_PLM_PLME_SHIFT: - * @NVME_FEAT_PLM_PLME_MASK: + * @NVME_FEAT_PLM_LPE_SHIFT: + * @NVME_FEAT_PLM_LPE_MASK: * @NVME_FEAT_PLMW_WS_SHIFT: * @NVME_FEAT_PLMW_WS_MASK: * @NVME_FEAT_LBAS_LSIRI_SHIFT: @@ -8977,7 +8998,15 @@ enum nvme_features_id { * @NVME_FEAT_BPWPC_BP0WPS_MASK: * @NVME_FEAT_BPWPC_BP1WPS_SHIFT: * @NVME_FEAT_BPWPC_BP1WPS_MASK: - */ + * @NVME_FEAT_SANITIZE_NODRM_SHIFT: + * @NVME_FEAT_SANITIZE_NODRM_MASK: + * @NVME_FEAT_RESP_PTPL_SHIFT: + * @NVME_FEAT_RESP_PTPL_MASK: + * @NVME_FEAT_RRL_NVMSETID_SHIFT: + * @NVME_FEAT_RRL_NVMSETID_MASK: + * @NVME_FEAT_PLM_NVMSETID_SHIFT: + * @NVME_FEAT_PLM_NVMSETID_MASK: + **/ enum nvme_feat { NVME_FEAT_ARBITRATION_BURST_SHIFT = 0, NVME_FEAT_ARBITRATION_BURST_MASK = 0x7, @@ -9067,10 +9096,14 @@ enum nvme_feat { NVME_FEAT_HCTM_TMT1_MASK = 0xffff, NVME_FEAT_NOPS_NOPPME_SHIFT = 0, NVME_FEAT_NOPS_NOPPME_MASK = 0x1, + NVME_FEAT_RRL_NVMSETID_SHIFT = 0, + NVME_FEAT_RRL_NVMSETID_MASK = 0xffff, NVME_FEAT_RRL_RRL_SHIFT = 0, NVME_FEAT_RRL_RRL_MASK = 0xff, - NVME_FEAT_PLM_PLME_SHIFT = 0, - NVME_FEAT_PLM_PLME_MASK = 0x1, + NVME_FEAT_PLM_NVMSETID_SHIFT = 0, + NVME_FEAT_PLM_NVMSETID_MASK = 0xffff, + NVME_FEAT_PLM_LPE_SHIFT = 0, + NVME_FEAT_PLM_LPE_MASK = 0x1, NVME_FEAT_PLMW_WS_SHIFT = 0, NVME_FEAT_PLMW_WS_MASK = 0x7, NVME_FEAT_LBAS_LSIRI_SHIFT = 0, @@ -9123,6 +9156,10 @@ enum nvme_feat { NVME_FEAT_BPWPC_BP0WPS_MASK = 0x7, NVME_FEAT_BPWPC_BP1WPS_SHIFT = 3, NVME_FEAT_BPWPC_BP1WPS_MASK = 0x7, + NVME_FEAT_SANITIZE_NODRM_SHIFT = 0, + NVME_FEAT_SANITIZE_NODRM_MASK = 0x1, + NVME_FEAT_RESP_PTPL_SHIFT = 0, + NVME_FEAT_RESP_PTPL_MASK = 0x1, }; /** @@ -10000,6 +10037,8 @@ struct nvme_ns_mgmt_host_sw_specified { * @NVME_LM_CQS_SHIFT: Shift amount for Create Queue Specific (CQS) field * @NVME_LM_CQS_MASK: Mask to set CQS field * @NVME_LM_CREATE_CDQ_PC: Physically Contiguous (PC) + * @NVME_LM_CREATE_CDQ_PC_SHIFT: Shift amount to set the PC field + * @NVME_LM_CREATE_CDQ_PC_MASK: Mask to set PC field * @NVME_LM_CREATE_CDQ_CNTLID_SHIFT: Shift amount to set CNTLID field relative to MOS * @NVME_LM_CREATE_CDQ_CNTLID_MASK: Mask to set CNTLID field relative to MOS * @NVME_LM_DELETE_CDQ_CDQID_SHIFT: Shift amount to set CDQID field for deletion @@ -10024,6 +10063,8 @@ enum nvme_lm_cdq_fields { NVME_LM_CQS_MASK = 0xffff, NVME_LM_QT_USER_DATA_MIGRATION_QUEUE = 0, NVME_LM_CREATE_CDQ_PC = 1, + NVME_LM_CREATE_CDQ_PC_SHIFT = 0, + NVME_LM_CREATE_CDQ_PC_MASK = 0x1, NVME_LM_CREATE_CDQ_CNTLID_SHIFT = 0, NVME_LM_CREATE_CDQ_CNTLID_MASK = 0xffff, diff --git a/libnvme/src/nvme/util.c b/libnvme/src/nvme/util.c index 42c646a065..927a4c9f18 100644 --- a/libnvme/src/nvme/util.c +++ b/libnvme/src/nvme/util.c @@ -180,7 +180,7 @@ __u8 nvme_status_to_errno(int status, bool fabrics) if (!status) return 0; if (status < 0) - return errno; + return -status; sc = nvme_status_code(status); switch (nvme_status_code_type(status)) { @@ -378,7 +378,7 @@ const char *nvme_status_to_string(int status, bool fabrics) __u16 sc, sct; if (status < 0) - return strerror(errno); + return strerror(-status); sc = nvme_status_code(status); sct = nvme_status_code_type(status); @@ -509,7 +509,8 @@ void nvme_init_ctrl_list(struct nvme_ctrl_list *cntlist, __u16 num_ctrls, cntlist->identifier[i] = cpu_to_le16(ctrlist[i]); } -int nvme_get_feature_length(int fid, __u32 cdw11, __u32 *len) +int nvme_get_feature_length(int fid, __u32 cdw11, enum nvme_data_tfr dir, + __u32 *len) { switch (fid) { case NVME_FEAT_FID_LBA_RANGE: @@ -531,6 +532,10 @@ int nvme_get_feature_length(int fid, __u32 cdw11, __u32 *len) *len = (cdw11 & 0x1) ? 16 : 8; break; case NVME_FEAT_FID_HOST_MEM_BUF: + if (dir == NVME_DATA_TFR_HOST_TO_CTRL) { + *len = 0; + break; + } *len = sizeof(struct nvme_host_mem_buf_attrs); break; case NVME_FEAT_FID_ARBITRATION: @@ -569,24 +574,7 @@ int nvme_get_feature_length(int fid, __u32 cdw11, __u32 *len) *len = NVME_FEAT_FDPE_NOET_MASK * sizeof(struct nvme_fdp_supported_event_desc); break; default: - errno = EINVAL; - return -1; - } - return 0; -} - -int nvme_get_feature_length2(int fid, __u32 cdw11, enum nvme_data_tfr dir, - __u32 *len) -{ - switch (fid) { - case NVME_FEAT_FID_HOST_MEM_BUF: - if (dir == NVME_DATA_TFR_HOST_TO_CTRL) { - *len = 0; - break; - } - fallthrough; - default: - return nvme_get_feature_length(fid, cdw11, len); + return -EINVAL; } return 0; } @@ -601,8 +589,7 @@ int nvme_get_directive_receive_length(enum nvme_directive_dtype dtype, *len = sizeof(struct nvme_id_directives); return 0; default: - errno = EINVAL; - return -1; + return -EINVAL; } case NVME_DIRECTIVE_DTYPE_STREAMS: switch (doper) { @@ -616,12 +603,10 @@ int nvme_get_directive_receive_length(enum nvme_directive_dtype dtype, *len = 0; return 0; default: - errno = EINVAL; - return -1; + return -EINVAL; } default: - errno = EINVAL; - return -1; + return -EINVAL; } } @@ -657,19 +642,20 @@ const char *nvme_errno_to_string(int status) } #ifdef HAVE_NETDB -char *hostname2traddr(struct nvme_root *r, const char *traddr) +int hostname2traddr(struct nvme_global_ctx *ctx, const char *traddr, + char **hostname) { - struct addrinfo *host_info, hints = {.ai_family = AF_UNSPEC}; + _cleanup_addrinfo_ struct addrinfo *host_info = NULL; + struct addrinfo hints = {.ai_family = AF_UNSPEC}; char addrstr[NVMF_TRADDR_SIZE]; const char *p; - char *ret_traddr = NULL; int ret; ret = getaddrinfo(traddr, NULL, &hints, &host_info); if (ret) { - nvme_msg(r, LOG_ERR, "failed to resolve host %s info\n", + nvme_msg(ctx, LOG_ERR, "failed to resolve host %s info\n", traddr); - return NULL; + return -errno; } switch (host_info->ai_family) { @@ -684,30 +670,29 @@ char *hostname2traddr(struct nvme_root *r, const char *traddr) addrstr, NVMF_TRADDR_SIZE); break; default: - nvme_msg(r, LOG_ERR, "unrecognized address family (%d) %s\n", + nvme_msg(ctx, LOG_ERR, "unrecognized address family (%d) %s\n", host_info->ai_family, traddr); - goto free_addrinfo; + return -EINVAL; } if (!p) { - nvme_msg(r, LOG_ERR, "failed to get traddr for %s\n", + nvme_msg(ctx, LOG_ERR, "failed to get traddr for %s\n", traddr); - goto free_addrinfo; + return -EIO; } - ret_traddr = strdup(addrstr); + *hostname = strdup(addrstr); + if (!*hostname) + return -ENOMEM; -free_addrinfo: - freeaddrinfo(host_info); - return ret_traddr; + return 0; } #else /* HAVE_NETDB */ -char *hostname2traddr(struct nvme_root *r, const char *traddr) +int hostname2traddr(struct nvme_global_ctx *ctx, const char *traddr, char **hostname) { - nvme_msg(NULL, LOG_ERR, "No support for hostname IP address resolution; " \ + nvme_msg(ctx, LOG_ERR, "No support for hostname IP address resolution; " \ "recompile with libnss support.\n"); - errno = -ENOTSUP; - return NULL; + return -ENOTSUP; } #endif /* HAVE_NETDB */ @@ -983,10 +968,8 @@ int nvme_uuid_find(struct nvme_id_uuid_list *uuid_list, const unsigned char uuid { const unsigned char uuid_end[NVME_UUID_LEN] = {0}; - if ((!uuid_list) || (!uuid)) { - errno = EINVAL; - return -1; - } + if ((!uuid_list) || (!uuid)) + return -EINVAL; for (int i = 0; i < NVME_ID_UUID_LIST_MAX; i++) { if (memcmp(uuid, &uuid_list->entry[i].uuid, NVME_UUID_LEN) == 0) @@ -994,8 +977,7 @@ int nvme_uuid_find(struct nvme_id_uuid_list *uuid_list, const unsigned char uuid if (memcmp(uuid_end, &uuid_list->entry[i].uuid, NVME_UUID_LEN) == 0) break; } - errno = ENOENT; - return -1; + return -ENOENT; } #ifdef HAVE_NETDB diff --git a/libnvme/src/nvme/util.h b/libnvme/src/nvme/util.h index 4c97652df2..0bb7fe0a4d 100644 --- a/libnvme/src/nvme/util.h +++ b/libnvme/src/nvme/util.h @@ -192,19 +192,6 @@ void nvme_init_copy_range_f3(struct nvme_copy_range_f3 *copy, __u32 *snsids, * @fid: Feature identifier, see &enum nvme_features_id. * @cdw11: The cdw11 value may affect the transfer (only known fid is * %NVME_FEAT_FID_HOST_ID) - * @len: On success, set to this features payload length in bytes. - * - * Return: 0 on success, -1 with errno set to EINVAL if the function did not - * recognize &fid. - */ -int nvme_get_feature_length(int fid, __u32 cdw11, __u32 *len); - -/** - * nvme_get_feature_length2() - Retreive the command payload length for a - * specific feature identifier - * @fid: Feature identifier, see &enum nvme_features_id. - * @cdw11: The cdw11 value may affect the transfer (only known fid is - * %NVME_FEAT_FID_HOST_ID) * @dir: Data transfer direction: false - host to controller, true - * controller to host may affect the transfer (only known fid is * %NVME_FEAT_FID_HOST_MEM_BUF). @@ -213,8 +200,8 @@ int nvme_get_feature_length(int fid, __u32 cdw11, __u32 *len); * Return: 0 on success, -1 with errno set to EINVAL if the function did not * recognize &fid. */ -int nvme_get_feature_length2(int fid, __u32 cdw11, enum nvme_data_tfr dir, - __u32 *len); +int nvme_get_feature_length(int fid, __u32 cdw11, enum nvme_data_tfr dir, + __u32 *len); /** * nvme_get_directive_receive_length() - Get directive receive length @@ -407,12 +394,12 @@ static inline void nvme_feature_decode_read_recovery_level_config(__u32 value, *rrl = NVME_FEAT_RRL_RRL(value); } -#define NVME_FEAT_PLM_PLME(v) NVME_GET(v, FEAT_PLM_PLME) +#define NVME_FEAT_PLM_LPE(v) NVME_GET(v, FEAT_PLM_LPE) static inline void nvme_feature_decode_predictable_latency_mode_config(__u32 value, - bool *plme) + bool *lpe) { - *plme = NVME_FEAT_PLM_PLME(value); + *lpe = NVME_FEAT_PLM_LPE(value); } #define NVME_FEAT_PLMW_WS(v) NVME_GET(v, FEAT_PLMW_WS) @@ -516,7 +503,7 @@ static inline void nvme_id_ns_flbas_to_lbaf_inuse(__u8 flbas, __u8 *lbaf_inuse) struct nvme_root; -char *hostname2traddr(struct nvme_root *r, const char *traddr); +int hostname2traddr(struct nvme_global_ctx *ctx, const char *traddr, char **hostname); /** * get_entity_name - Get Entity Name (ENAME). diff --git a/libnvme/test/config/config-dump.c b/libnvme/test/config/config-dump.c index c0c8e73130..bf8318ee77 100644 --- a/libnvme/test/config/config-dump.c +++ b/libnvme/test/config/config-dump.c @@ -13,32 +13,30 @@ static bool config_dump(const char *file) { + struct nvme_global_ctx *ctx; bool pass = false; - nvme_root_t r; int err; - r = nvme_create_root(stderr, LOG_ERR); - if (!r) + ctx = nvme_create_global_ctx(stderr, LOG_ERR); + if (!ctx) return false; - err = nvme_scan_topology(r, NULL, NULL); - if (err) { - if (errno != ENOENT) - goto out; - } + err = nvme_scan_topology(ctx, NULL, NULL); + if (err < 0 && err != -ENOENT) + goto out; - err = nvme_read_config(r, file); + err = nvme_read_config(ctx, file); if (err) goto out; - err = nvme_dump_config(r); + err = nvme_dump_config(ctx); if (err) goto out; pass = true; out: - nvme_free_tree(r); + nvme_free_global_ctx(ctx); return pass; } diff --git a/libnvme/test/config/hostnqn-order.c b/libnvme/test/config/hostnqn-order.c index 22fc2278e9..52d1ae4166 100644 --- a/libnvme/test/config/hostnqn-order.c +++ b/libnvme/test/config/hostnqn-order.c @@ -13,25 +13,23 @@ static bool command_line(void) { + struct nvme_global_ctx *ctx; bool pass = false; - nvme_root_t r; int err; char *hostnqn, *hostid, *hnqn, *hid; - r = nvme_create_root(stderr, LOG_ERR); - if (!r) + ctx = nvme_create_global_ctx(stderr, LOG_ERR); + if (!ctx) return false; - err = nvme_scan_topology(r, NULL, NULL); - if (err) { - if (errno != ENOENT) - goto out; - } + err = nvme_scan_topology(ctx, NULL, NULL); + if (err && err != ENOENT) + goto out; hostnqn = "nqn.2014-08.org.nvmexpress:uuid:ce4fee3e-c02c-11ee-8442-830d068a36c6"; hostid = "ce4fee3e-c02c-11ee-8442-830d068a36c6"; - err = nvme_host_get_ids(r, hostnqn, hostid, &hnqn, &hid); + err = nvme_host_get_ids(ctx, hostnqn, hostid, &hnqn, &hid); if (err) goto out; @@ -50,39 +48,37 @@ static bool command_line(void) pass = true; out: - nvme_free_tree(r); + nvme_free_global_ctx(ctx); return pass; } static bool json_config(char *file) { + struct nvme_global_ctx *ctx; bool pass = false; - nvme_root_t r; int err; char *hostnqn, *hostid, *hnqn, *hid; setenv("LIBNVME_HOSTNQN", "", 1); setenv("LIBNVME_HOSTID", "", 1); - r = nvme_create_root(stderr, LOG_ERR); - if (!r) + ctx = nvme_create_global_ctx(stderr, LOG_ERR); + if (!ctx) return false; /* We need to read the config in before we scan */ - err = nvme_read_config(r, file); + err = nvme_read_config(ctx, file); if (err) goto out; - err = nvme_scan_topology(r, NULL, NULL); - if (err) { - if (errno != ENOENT) - goto out; - } + err = nvme_scan_topology(ctx, NULL, NULL); + if (err && err != ENOENT) + goto out; hostnqn = "nqn.2014-08.org.nvmexpress:uuid:2cd2c43b-a90a-45c1-a8cd-86b33ab273b5"; hostid = "2cd2c43b-a90a-45c1-a8cd-86b33ab273b5"; - err = nvme_host_get_ids(r, NULL, NULL, &hnqn, &hid); + err = nvme_host_get_ids(ctx, NULL, NULL, &hnqn, &hid); if (err) goto out; @@ -101,14 +97,14 @@ static bool json_config(char *file) pass = true; out: - nvme_free_tree(r); + nvme_free_global_ctx(ctx); return pass; } static bool from_file(void) { + struct nvme_global_ctx *ctx; bool pass = false; - nvme_root_t r; int err; char *hostnqn, *hostid, *hnqn, *hid; @@ -118,17 +114,15 @@ static bool from_file(void) setenv("LIBNVME_HOSTNQN", hostnqn, 1); setenv("LIBNVME_HOSTID", hostid, 1); - r = nvme_create_root(stderr, LOG_ERR); - if (!r) + ctx = nvme_create_global_ctx(stderr, LOG_ERR); + if (!ctx) return false; - err = nvme_scan_topology(r, NULL, NULL); - if (err) { - if (errno != ENOENT) - goto out; - } + err = nvme_scan_topology(ctx, NULL, NULL); + if (err && err != ENOENT) + goto out; - err = nvme_host_get_ids(r, NULL, NULL, &hnqn, &hid); + err = nvme_host_get_ids(ctx, NULL, NULL, &hnqn, &hid); if (err) goto out; @@ -147,7 +141,7 @@ static bool from_file(void) pass = true; out: - nvme_free_tree(r); + nvme_free_global_ctx(ctx); return pass; } diff --git a/libnvme/test/config/psk-json.c b/libnvme/test/config/psk-json.c index a96ebf1b89..1469dac520 100644 --- a/libnvme/test/config/psk-json.c +++ b/libnvme/test/config/psk-json.c @@ -18,21 +18,23 @@ static bool import_export_key(nvme_ctrl_t c) unsigned char version, hmac, *key; char *encoded_key; size_t len; + int ret; - key = nvme_import_tls_key_versioned(nvme_ctrl_get_tls_key(c), - &version, &hmac, &len); - if (!key) { + ret = nvme_import_tls_key_versioned(nvme_ctrl_get_tls_key(c), + &version, &hmac, &len, &key); + if (ret) { printf("ERROR: nvme_import_tls_key_versioned failed with %d\n", - errno); + ret); return false; } - encoded_key = nvme_export_tls_key_versioned(version, hmac, key, len); + ret = nvme_export_tls_key_versioned(version, hmac, key, len, + &encoded_key); free(key); - if (!encoded_key) { + if (ret) { printf("ERROR: nvme_export_tls_key_versioned failed with %d\n", - errno); + ret); return false; } @@ -45,36 +47,36 @@ static bool import_export_key(nvme_ctrl_t c) static bool psk_json_test(char *file) { + struct nvme_global_ctx *ctx; bool pass = false; - nvme_root_t r; nvme_host_t h; nvme_subsystem_t s; nvme_ctrl_t c; int err; - r = nvme_create_root(stderr, LOG_ERR); - if (!r) + ctx = nvme_create_global_ctx(stderr, LOG_ERR); + if (!ctx) return false; - err = nvme_read_config(r, file); + err = nvme_read_config(ctx, file); if (err) goto out; - nvme_for_each_host(r, h) + nvme_for_each_host(ctx, h) nvme_for_each_subsystem(h, s) nvme_subsystem_for_each_ctrl(s, c) if (!import_export_key(c)) goto out; - err = nvme_dump_config(r); + err = nvme_dump_config(ctx); if (err) goto out; pass = true; out: - nvme_free_tree(r); + nvme_free_global_ctx(ctx); return pass; } diff --git a/libnvme/test/cpp.cc b/libnvme/test/cpp.cc index a6bbf42fd5..48ac9cec54 100644 --- a/libnvme/test/cpp.cc +++ b/libnvme/test/cpp.cc @@ -12,18 +12,17 @@ int main() { - nvme_root_t r; + struct nvme_global_ctx *ctx; nvme_host_t h; nvme_subsystem_t s; nvme_ctrl_t c; nvme_path_t p; nvme_ns_t n; - r = nvme_scan(NULL); - if (!r) + if (nvme_scan(NULL, &ctx)) return -1; - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { std::cout << nvme_subsystem_get_name(s) << " - NQN=" << nvme_subsystem_get_nqn(s) @@ -61,7 +60,7 @@ int main() } } std::cout << "\n"; - nvme_free_tree(r); + nvme_free_global_ctx(ctx); return 0; } diff --git a/libnvme/test/ioctl/ana.c b/libnvme/test/ioctl/ana.c index 1e2cffb793..411e15324c 100644 --- a/libnvme/test/ioctl/ana.c +++ b/libnvme/test/ioctl/ana.c @@ -16,15 +16,17 @@ #define TEST_FD 0xFD #define PDU_SIZE NVME_LOG_PAGE_PDU_SIZE +static struct nvme_transport_handle *test_hdl; + static void test_no_retries(void) { struct nvme_ana_log log; __u32 len = sizeof(log); /* max_retries = 0 is nonsensical */ - check(nvme_get_ana_log_atomic(TEST_FD, false, false, 0, &log, &len), + check(nvme_get_ana_log_atomic(test_hdl, false, false, + &log, &len, 0) == -EINVAL, "get log page succeeded"); - check(errno == EINVAL, "unexpected error: %m"); } static void test_len_too_short(void) @@ -33,9 +35,9 @@ static void test_len_too_short(void) __u32 len = sizeof(log) - 1; /* Provided buffer doesn't have enough space to read the header */ - check(nvme_get_ana_log_atomic(TEST_FD, false, false, 1, &log, &len), + check(nvme_get_ana_log_atomic(test_hdl, false, false, + &log, &len, 1) == -ENOSPC, "get log page succeeded"); - check(errno == ENOSPC, "unexpected error: %m"); } static void test_no_groups(void) @@ -56,8 +58,8 @@ static void test_no_groups(void) arbitrary(&header, sizeof(header)); header.ngrps = cpu_to_le16(0); set_mock_admin_cmds(&mock_admin_cmd, 1); - check(!nvme_get_ana_log_atomic(TEST_FD, false, false, 1, &log, &len), - "get log page failed: %m"); + check(!nvme_get_ana_log_atomic(test_hdl, false, false, &log, &len, 1), + "get log page failed"); end_mock_cmds(); cmp(&log, &header, sizeof(header), "incorrect header"); check(len == sizeof(header), @@ -79,7 +81,7 @@ static void test_one_group_rgo(void) .opcode = nvme_admin_get_log_page, .data_len = len_dwords * 4, .cdw10 = (len_dwords - 1) << 16 /* NUMDL */ - | NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY << 8 /* LSP */ + | NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY << 8 /* LSP */ | NVME_LOG_LID_ANA, /* LID */ .out_data = log_page, .out_data_len = sizeof(log_page), @@ -94,8 +96,8 @@ static void test_one_group_rgo(void) memcpy(log_page, &header, sizeof(header)); memcpy(log_page + sizeof(header), &group, sizeof(group)); set_mock_admin_cmds(&mock_admin_cmd, 1); - check(!nvme_get_ana_log_atomic(TEST_FD, true, false, 1, log, &len), - "get log page failed: %m"); + check(!nvme_get_ana_log_atomic(test_hdl, false, true, log, &len, 1), + "get log page failed"); end_mock_cmds(); cmp(log, log_page, sizeof(log_page), "incorrect log page"); check(len == sizeof(log_page), @@ -135,8 +137,8 @@ static void test_one_group_nsids(void) memcpy(log_page + sizeof(header), &group, sizeof(group)); memcpy(log_page + sizeof(header) + sizeof(group), nsids, sizeof(nsids)); set_mock_admin_cmds(&mock_admin_cmd, 1); - check(!nvme_get_ana_log_atomic(TEST_FD, false, false, 1, log, &len), - "get log page failed: %m"); + check(!nvme_get_ana_log_atomic(test_hdl, false, false, log, &len, 1), + "get log page failed"); end_mock_cmds(); cmp(log, log_page, sizeof(log_page), "incorrect log page"); check(len == sizeof(log_page), @@ -176,8 +178,8 @@ static void test_multiple_groups_rgo(void) memcpy(log_page, &header, sizeof(header)); memcpy(log_page + sizeof(header), groups, sizeof(groups)); set_mock_admin_cmds(&mock_admin_cmd, 1); - check(!nvme_get_ana_log_atomic(TEST_FD, true, true, 1, log, &len), - "get log page failed: %m"); + check(!nvme_get_ana_log_atomic(test_hdl, true, true, log, &len, 1), + "get log page failed"); end_mock_cmds(); cmp(log, log_page, sizeof(log_page), "incorrect log page"); check(len == sizeof(log_page), @@ -242,8 +244,8 @@ static void test_multiple_groups_nsids(void) sizeof(group2) + sizeof(nsids2) + sizeof(group3), nsids3, sizeof(nsids3)); set_mock_admin_cmds(&mock_admin_cmd, 1); - check(!nvme_get_ana_log_atomic(TEST_FD, false, false, 1, log, &len), - "get log page failed: %m"); + check(!nvme_get_ana_log_atomic(test_hdl, false, false, log, &len, 1), + "get log page failed"); end_mock_cmds(); cmp(log, log_page, sizeof(log_page), "incorrect log page"); check(len == sizeof(log_page), @@ -314,8 +316,8 @@ static void test_long_log(void) memcpy(log_page + sizeof(header), &group, sizeof(group)); memcpy(log_page + sizeof(header) + sizeof(group), nsids, sizeof(nsids)); set_mock_admin_cmds(mock_admin_cmds, ARRAY_SIZE(mock_admin_cmds)); - check(!nvme_get_ana_log_atomic(TEST_FD, false, true, 1, log, &len), - "get log page failed: %m"); + check(!nvme_get_ana_log_atomic(test_hdl, true, false, log, &len, 1), + "get log page failed"); end_mock_cmds(); cmp(log, log_page, sizeof(log_page), "incorrect log page"); check(len == sizeof(log_page), @@ -390,8 +392,8 @@ static void test_chgcnt_change(void) memcpy(log_page2, &header2, sizeof(header2)); memcpy(log_page2 + sizeof(header2), &group2, sizeof(group2)); set_mock_admin_cmds(mock_admin_cmds, ARRAY_SIZE(mock_admin_cmds)); - check(!nvme_get_ana_log_atomic(TEST_FD, true, true, 2, log, &len), - "get log page failed: %m"); + check(!nvme_get_ana_log_atomic(test_hdl, true, true, log, &len, 2), + "get log page failed"); end_mock_cmds(); cmp(log, log_page2, sizeof(log_page2), "incorrect log page"); check(len == sizeof(log_page2), @@ -472,8 +474,8 @@ static void test_buffer_too_short_chgcnt_change(void) memcpy(log_page2 + sizeof(header2) + sizeof(group2), &nsid2, sizeof(nsid2)); set_mock_admin_cmds(mock_admin_cmds, ARRAY_SIZE(mock_admin_cmds)); - check(!nvme_get_ana_log_atomic(TEST_FD, false, false, 2, log, &len), - "get log page failed: %m"); + check(!nvme_get_ana_log_atomic(test_hdl, false, false, log, &len, 2), + "get log page failed"); end_mock_cmds(); cmp(log, log_page2, sizeof(log_page2), "incorrect log page"); check(len == sizeof(log_page2), @@ -568,10 +570,9 @@ static void test_chgcnt_max_retries(void) memcpy(log_page2 + sizeof(header2) + sizeof(group), nsids, sizeof(nsids)); set_mock_admin_cmds(mock_admin_cmds, ARRAY_SIZE(mock_admin_cmds)); - check(nvme_get_ana_log_atomic(TEST_FD, false, true, 2, log, &len) == -1, + check(nvme_get_ana_log_atomic(test_hdl, true, false, log, &len, 2) == -EAGAIN, "get log page succeeded"); end_mock_cmds(); - check(errno == EAGAIN, "unexpected error: %m"); free(log); } @@ -609,10 +610,9 @@ static void test_buffer_too_short(void) memcpy(log_page + sizeof(header), &group, sizeof(group)); memcpy(log_page + sizeof(header) + sizeof(group), nsids, sizeof(nsids)); set_mock_admin_cmds(&mock_admin_cmd, 1); - check(nvme_get_ana_log_atomic(TEST_FD, false, true, 2, log, &len) == -1, - "get log page succeeded"); + check(nvme_get_ana_log_atomic(test_hdl, true, false, log, &len, 2) == -ENOSPC, + "log page succeeded"); end_mock_cmds(); - check(errno == ENOSPC, "unexpected error: %m"); free(log); } @@ -628,7 +628,13 @@ static void run_test(const char *test_name, void (*test_fn)(void)) int main(void) { + struct nvme_global_ctx *ctx = + nvme_create_global_ctx(stdout, DEFAULT_LOGLEVEL); + set_mock_fd(TEST_FD); + check(!nvme_open(ctx, "NVME_TEST_FD", &test_hdl), + "opening test link failed"); + RUN_TEST(no_retries); RUN_TEST(len_too_short); RUN_TEST(no_groups); @@ -641,4 +647,6 @@ int main(void) RUN_TEST(buffer_too_short_chgcnt_change); RUN_TEST(chgcnt_max_retries); RUN_TEST(buffer_too_short); + + nvme_free_global_ctx(ctx); } diff --git a/libnvme/test/ioctl/discovery.c b/libnvme/test/ioctl/discovery.c index 457acb0a8a..b49fe5e8df 100644 --- a/libnvme/test/ioctl/discovery.c +++ b/libnvme/test/ioctl/discovery.c @@ -16,6 +16,8 @@ #define TEST_FD 0xFD #define HEADER_LEN 20 +static struct nvme_transport_handle *test_hdl; + static void arbitrary_ascii_string(size_t max_len, char *str, char *log_str) { size_t len; @@ -65,16 +67,16 @@ static void test_no_entries(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = HEADER_LEN, .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .out_data = &header, }, }; struct nvmf_discovery_log *log = NULL; set_mock_admin_cmds(mock_admin_cmds, ARRAY_SIZE(mock_admin_cmds)); - check(nvmf_get_discovery_log(c, &log, 1) == 0, "discovery failed: %m"); + check(nvmf_get_discovery_log(c, &log, 1) == 0, "discovery failed"); end_mock_cmds(); - cmp(log, &header, sizeof(header), "incorrect header"); + cmp(log, &header, HEADER_LEN, "incorrect header"); free(log); } @@ -93,14 +95,14 @@ static void test_four_entries(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = HEADER_LEN, .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .out_data = &header, }, { .opcode = nvme_admin_get_log_page, .data_len = sizeof(entries), .cdw10 = (sizeof(entries) / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .cdw12 = sizeof(header), /* LPOL */ .out_data = log_entries, }, @@ -108,7 +110,7 @@ static void test_four_entries(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = HEADER_LEN, .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .out_data = &header, }, }; @@ -116,10 +118,10 @@ static void test_four_entries(nvme_ctrl_t c) arbitrary_entries(num_entries, entries, log_entries); set_mock_admin_cmds(mock_admin_cmds, ARRAY_SIZE(mock_admin_cmds)); - check(nvmf_get_discovery_log(c, &log, 1) == 0, "discovery failed: %m"); + check(nvmf_get_discovery_log(c, &log, 1) == 0, "discovery failed"); end_mock_cmds(); - cmp(log, &header, sizeof(header), "incorrect header"); - cmp(log->entries, entries, sizeof(entries), "incorrect entries"); + cmp(log, &header, HEADER_LEN, "incorrect header"); + cmp(log->entries, entries, 0x16 /* sizeof(entries)*/, "incorrect entries"); free(log); } @@ -143,7 +145,7 @@ static void test_five_entries(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = HEADER_LEN, .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .out_data = &header, }, { @@ -151,7 +153,7 @@ static void test_five_entries(nvme_ctrl_t c) .data_len = first_data_len, .cdw10 = (first_data_len / 4 - 1) << 16 /* NUMDL */ | 1 << 15 /* RAE */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .cdw12 = sizeof(header), /* LPOL */ .out_data = log_entries, }, @@ -159,7 +161,7 @@ static void test_five_entries(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = second_data_len, .cdw10 = (second_data_len / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .cdw12 = sizeof(header) + first_data_len, /* LPOL */ .out_data = log_entries + first_entries, }, @@ -167,7 +169,7 @@ static void test_five_entries(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = HEADER_LEN, .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .out_data = &header, }, }; @@ -175,7 +177,7 @@ static void test_five_entries(nvme_ctrl_t c) arbitrary_entries(num_entries, entries, log_entries); set_mock_admin_cmds(mock_admin_cmds, ARRAY_SIZE(mock_admin_cmds)); - check(nvmf_get_discovery_log(c, &log, 1) == 0, "discovery failed: %m"); + check(nvmf_get_discovery_log(c, &log, 1) == 0, "discovery failed"); end_mock_cmds(); cmp(log, &header, sizeof(header), "incorrect header"); cmp(log->entries, entries, sizeof(entries), "incorrect entries"); @@ -204,14 +206,14 @@ static void test_genctr_change(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = HEADER_LEN, .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .out_data = &header1, }, { .opcode = nvme_admin_get_log_page, .data_len = sizeof(entries1), .cdw10 = (sizeof(entries1) / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* NUMDL */ + | NVME_LOG_LID_DISCOVERY, /* NUMDL */ .cdw12 = sizeof(header1), /* LPOL */ .out_data = entries1, }, @@ -219,14 +221,14 @@ static void test_genctr_change(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = HEADER_LEN, .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .out_data = &header2, }, { .opcode = nvme_admin_get_log_page, .data_len = sizeof(entries2), .cdw10 = (sizeof(entries2) / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .cdw12 = sizeof(header2), /* LPOL */ .out_data = log_entries2, }, @@ -234,7 +236,7 @@ static void test_genctr_change(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = HEADER_LEN, .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .out_data = &header2, }, }; @@ -243,7 +245,7 @@ static void test_genctr_change(nvme_ctrl_t c) arbitrary(entries1, sizeof(entries1)); arbitrary_entries(num_entries2, entries2, log_entries2); set_mock_admin_cmds(mock_admin_cmds, ARRAY_SIZE(mock_admin_cmds)); - check(nvmf_get_discovery_log(c, &log, 2) == 0, "discovery failed: %m"); + check(nvmf_get_discovery_log(c, &log, 2) == 0, "discovery failed"); end_mock_cmds(); cmp(log, &header2, sizeof(header2), "incorrect header"); cmp(log->entries, entries2, sizeof(entries2), "incorrect entries"); @@ -268,14 +270,14 @@ static void test_max_retries(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = HEADER_LEN, .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .out_data = &header1, }, { .opcode = nvme_admin_get_log_page, .data_len = sizeof(entry), .cdw10 = (sizeof(entry) / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .cdw12 = sizeof(header1), /* LPOL */ .out_data = &entry, }, @@ -283,14 +285,14 @@ static void test_max_retries(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = HEADER_LEN, .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .out_data = &header2, }, { .opcode = nvme_admin_get_log_page, .data_len = sizeof(entry), .cdw10 = (sizeof(entry) / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .cdw12 = sizeof(header2), /* LPOL */ .out_data = &entry, }, @@ -298,7 +300,7 @@ static void test_max_retries(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = HEADER_LEN, .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .out_data = &header3, }, }; @@ -306,9 +308,8 @@ static void test_max_retries(nvme_ctrl_t c) arbitrary(&entry, sizeof(entry)); set_mock_admin_cmds(mock_admin_cmds, ARRAY_SIZE(mock_admin_cmds)); - check(nvmf_get_discovery_log(c, &log, 2) == -1, "discovery succeeded"); + check(nvmf_get_discovery_log(c, &log, 2) == -EAGAIN, "discovery succeeded"); end_mock_cmds(); - check(errno == EAGAIN, "discovery failed: %m"); check(!log, "unexpected log page returned"); } @@ -320,14 +321,14 @@ static void test_header_error(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = HEADER_LEN, .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ - .err = NVME_SC_INVALID_OPCODE, + | NVME_LOG_LID_DISCOVERY, /* LID */ + .err = -EAGAIN, }, }; struct nvmf_discovery_log *log = NULL; set_mock_admin_cmds(mock_admin_cmds, ARRAY_SIZE(mock_admin_cmds)); - check(nvmf_get_discovery_log(c, &log, 1) == -1, "discovery succeeded"); + check(nvmf_get_discovery_log(c, &log, 1) == -EAGAIN, "discovery succeeded"); end_mock_cmds(); check(!log, "unexpected log page returned"); } @@ -342,14 +343,14 @@ static void test_entries_error(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = HEADER_LEN, .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .out_data = &header, }, { .opcode = nvme_admin_get_log_page, .data_len = entry_size, .cdw10 = (entry_size / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .cdw12 = sizeof(header), /* LPOL */ .err = -EIO, }, @@ -357,9 +358,8 @@ static void test_entries_error(nvme_ctrl_t c) struct nvmf_discovery_log *log = NULL; set_mock_admin_cmds(mock_admin_cmds, ARRAY_SIZE(mock_admin_cmds)); - check(nvmf_get_discovery_log(c, &log, 1) == -1, "discovery succeeded"); + check(nvmf_get_discovery_log(c, &log, 1) == -EIO, "discovery succeeded"); end_mock_cmds(); - check(errno == EIO, "discovery failed: %m"); check(!log, "unexpected log page returned"); } @@ -373,14 +373,14 @@ static void test_genctr_error(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = HEADER_LEN, .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .out_data = &header, }, { .opcode = nvme_admin_get_log_page, .data_len = sizeof(entry), .cdw10 = (sizeof(entry) / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .cdw12 = sizeof(header), /* LPOL */ .out_data = &entry, }, @@ -388,7 +388,7 @@ static void test_genctr_error(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = HEADER_LEN, .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ + | NVME_LOG_LID_DISCOVERY, /* LID */ .err = NVME_SC_INTERNAL, }, }; @@ -396,14 +396,14 @@ static void test_genctr_error(nvme_ctrl_t c) arbitrary(&entry, sizeof(entry)); set_mock_admin_cmds(mock_admin_cmds, ARRAY_SIZE(mock_admin_cmds)); - check(nvmf_get_discovery_log(c, &log, 1) == -1, "discovery succeeded"); + check(nvmf_get_discovery_log(c, &log, 1) == NVME_SC_INTERNAL, "discovery succeeded"); end_mock_cmds(); check(!log, "unexpected log page returned"); } static void run_test(const char *test_name, void (*test_fn)(nvme_ctrl_t)) { - struct nvme_ctrl c = {.fd = TEST_FD}; + struct nvme_ctrl c = { .hdl = test_hdl }; printf("Running test %s...", test_name); fflush(stdout); @@ -417,7 +417,13 @@ static void run_test(const char *test_name, void (*test_fn)(nvme_ctrl_t)) int main(void) { + struct nvme_global_ctx *ctx = + nvme_create_global_ctx(stdout, DEFAULT_LOGLEVEL); + set_mock_fd(TEST_FD); + check(!nvme_open(ctx, "NVME_TEST_FD", &test_hdl), + "opening test link failed"); + RUN_TEST(no_entries); RUN_TEST(four_entries); RUN_TEST(five_entries); @@ -426,4 +432,6 @@ int main(void) RUN_TEST(header_error); RUN_TEST(entries_error); RUN_TEST(genctr_error); + + nvme_free_global_ctx(ctx); } diff --git a/libnvme/test/ioctl/features.c b/libnvme/test/ioctl/features.c index e0b6b93bf4..ed81ff297a 100644 --- a/libnvme/test/ioctl/features.c +++ b/libnvme/test/ioctl/features.c @@ -22,26 +22,12 @@ #define TEST_SEL NVME_GET_FEATURES_SEL_SAVED #define TEST_SC NVME_SC_INVALID_FIELD +static struct nvme_transport_handle *test_hdl; + static void test_set_features(void) { uint32_t result = 0; uint8_t data[256]; - struct nvme_set_features_args args = { - .result = &result, - .data = data, - .args_size = sizeof(args), - .fd = TEST_FD, - .timeout = TEST_TIMEOUT, - .nsid = TEST_NSID, - .cdw11 = TEST_CDW11, - .cdw12 = TEST_CDW12, - .cdw13 = TEST_CDW13, - .cdw15 = TEST_CDW15, - .data_len = sizeof(data), - .save = true, - .uuidx = TEST_UUIDX, - .fid = TEST_FID, - }; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_set_features, .nsid = TEST_NSID, @@ -57,13 +43,24 @@ static void test_set_features(void) .timeout_ms = TEST_TIMEOUT, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(data, sizeof(data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features(&args); - end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + nvme_init_set_features(&cmd, TEST_FID, true); + cmd.nsid = TEST_NSID; + cmd.cdw11 = TEST_CDW11; + cmd.cdw12 = TEST_CDW12; + cmd.cdw13 = TEST_CDW13; + cmd.cdw14 = TEST_UUIDX; + cmd.cdw15 = TEST_CDW15; + cmd.data_len = sizeof(data); + cmd.addr = (__u64)(uintptr_t)data; + cmd.timeout_ms = TEST_TIMEOUT; + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); + end_mock_cmds(); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -72,19 +69,6 @@ static void test_get_features(void) { uint32_t result = 0; uint8_t data[256], get_data[sizeof(data)] = {}; - struct nvme_get_features_args args = { - .result = &result, - .data = get_data, - .args_size = sizeof(args), - .fd = TEST_FD, - .timeout = TEST_TIMEOUT, - .nsid = TEST_NSID, - .sel = TEST_SEL, - .cdw11 = TEST_CDW11, - .data_len = sizeof(data), - .fid = TEST_FID, - .uuidx = TEST_UUIDX, - }; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_get_features, .nsid = TEST_NSID, @@ -96,44 +80,26 @@ static void test_get_features(void) .out_data = data, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(data, sizeof(data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features(&args); + nvme_init_get_features(&cmd, TEST_FID, TEST_SEL); + cmd.nsid = TEST_NSID; + cmd.cdw11 = TEST_CDW11; + cmd.cdw14 = TEST_UUIDX; + cmd.data_len = sizeof(get_data); + cmd.addr = (__u64)(uintptr_t)get_data; + cmd.timeout_ms = TEST_TIMEOUT; + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); cmp(get_data, data, sizeof(data), "incorrect data"); } -static void test_set_features_data(void) -{ - uint8_t data[128]; - struct mock_cmd mock_admin_cmd = { - .opcode = nvme_admin_set_features, - .nsid = TEST_NSID, - .in_data = data, - .data_len = sizeof(data), - .cdw10 = TEST_FID, - .cdw11 = TEST_CDW11, - .result = TEST_RESULT, - }; - uint32_t result = 0; - int err; - - arbitrary(data, sizeof(data)); - set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_data( - TEST_FD, TEST_FID, TEST_NSID, TEST_CDW11, false, - sizeof(data), data, &result); - end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); - check(result == TEST_RESULT, - "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); -} - static void test_get_features_data(void) { uint8_t data[128], get_data[sizeof(data)] = {}; @@ -145,61 +111,24 @@ static void test_get_features_data(void) .out_data = data, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; arbitrary(data, sizeof(data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_data( - TEST_FD, TEST_FID, TEST_NSID, sizeof(data), get_data, &result); + nvme_init_get_features(&cmd, TEST_FID, 0); + cmd.nsid = TEST_NSID; + cmd.data_len = sizeof(get_data); + cmd.addr = (__u64)(uintptr_t)get_data; + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); cmp(get_data, data, sizeof(data), "incorrect data"); } -static void test_set_features_simple(void) -{ - struct mock_cmd mock_admin_cmd = { - .opcode = nvme_admin_set_features, - .nsid = TEST_NSID, - .cdw10 = (uint32_t)1 << 31 /* SAVE */ - | TEST_FID, - .cdw11 = TEST_CDW11, - .result = TEST_RESULT, - }; - uint32_t result = 0; - int err; - - set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_simple( - TEST_FD, TEST_FID, TEST_NSID, TEST_CDW11, true, &result); - end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); - check(result == TEST_RESULT, - "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); -} - -static void test_get_features_simple(void) -{ - struct mock_cmd mock_admin_cmd = { - .opcode = nvme_admin_get_features, - .nsid = TEST_NSID, - .cdw10 = NVME_GET_FEATURES_SEL_CURRENT << 8 | TEST_FID, - .result = TEST_RESULT, - }; - uint32_t result = 0; - int err; - - set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_simple(TEST_FD, TEST_FID, TEST_NSID, &result); - end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); - check(result == TEST_RESULT, - "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); -} - static void test_set_arbitration(void) { uint8_t HPW = 0xAA, MPW = 0xBB, LPW = 0xCC, AB = 0b111; @@ -209,14 +138,15 @@ static void test_set_arbitration(void) .cdw11 = (uint32_t)HPW << 24 | MPW << 16 | LPW << 8 | AB, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_arbitration( - TEST_FD, AB, LPW, MPW, HPW, false, &result); + nvme_init_set_features_arbitration(&cmd, false, AB, LPW, MPW, HPW); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -228,13 +158,15 @@ static void test_get_arbitration(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_ARBITRATION, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_arbitration(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_arbitration(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -249,13 +181,15 @@ static void test_set_power_mgmt(void) .cdw11 = WH << 5 | PS, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_power_mgmt(TEST_FD, PS, WH, true, &result); + nvme_init_set_features_power_mgmt(&cmd, true, PS, WH); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -267,13 +201,15 @@ static void test_get_power_mgmt(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_POWER_MGMT, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_power_mgmt(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_power_mgmt(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -291,15 +227,17 @@ static void test_set_lba_range(void) .cdw11 = NUM - 1, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; arbitrary(&range_types, sizeof(range_types)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_lba_range( - TEST_FD, TEST_NSID, NUM, false, &range_types, &result); + nvme_init_set_features_lba_range(&cmd, TEST_NSID, false, + NUM, &range_types); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -315,15 +253,17 @@ static void test_get_lba_range(void) .out_data = &range_types, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; arbitrary(&range_types, sizeof(range_types)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_lba_range2( - TEST_FD, TEST_SEL, TEST_NSID, &get_range_types, &result); + nvme_init_get_features_lba_range(&cmd, TEST_NSID, TEST_SEL, + &get_range_types); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); cmp(&get_range_types, &range_types, sizeof(range_types), @@ -343,14 +283,15 @@ static void test_set_temp_thresh(void) .cdw11 = THSEL << 20 | TMPSEL << 16 | TMPTH, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_temp_thresh( - TEST_FD, TMPTH, TMPSEL, THSEL, true, &result); + nvme_init_set_features_temp_thresh(&cmd, true, TMPTH, TMPSEL, THSEL, 0); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -367,13 +308,15 @@ static void test_get_temp_thresh(void) .cdw11 = NVME_FEATURE_TEMPTHRESH_THSEL_OVER << 20, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_temp_thresh(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_temp_thresh(&cmd, TEST_SEL, 0, 0); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -389,14 +332,15 @@ static void test_set_err_recovery(void) | TLER, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_err_recovery( - TEST_FD, TEST_NSID, TLER, true, false, &result); + nvme_init_set_features_err_recovery(&cmd, TEST_NSID, false, TLER, true); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -409,14 +353,15 @@ static void test_get_err_recovery(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_ERR_RECOVERY, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_err_recovery2( - TEST_FD, TEST_SEL, TEST_NSID, &result); + nvme_init_get_features_err_recovery(&cmd, TEST_NSID, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -430,13 +375,15 @@ static void test_set_volatile_wc(void) .cdw11 = 1 << 0, /* WCE */ .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_volatile_wc(TEST_FD, true, true, &result); + nvme_init_set_features_volatile_wc(&cmd, true, true); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -449,13 +396,15 @@ static void test_get_volatile_wc(void) | NVME_FEAT_FID_VOLATILE_WC, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_volatile_wc(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_volatile_wc(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -467,13 +416,15 @@ static void test_get_num_queues(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_NUM_QUEUES, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_num_queues(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_num_queues(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -487,14 +438,15 @@ static void test_set_irq_coalesce(void) .cdw11 = TIME << 8 | THR, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_irq_coalesce( - TEST_FD, THR, TIME, false, &result); + nvme_init_set_features_irq_coalesce(&cmd, false, THR, TIME); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -506,13 +458,15 @@ static void test_get_irq_coalesce(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_IRQ_COALESCE, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_irq_coalesce(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_irq_coalesce(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -528,13 +482,15 @@ static void test_set_irq_config(void) | IV, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_irq_config(TEST_FD, IV, true, true, &result); + nvme_init_set_features_irq_config(&cmd, true, IV, true); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -548,13 +504,15 @@ static void test_get_irq_config(void) .cdw11 = IV, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_irq_config(TEST_FD, TEST_SEL, IV, &result); + nvme_init_get_features_irq_config(&cmd, TEST_SEL, IV, false); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -567,13 +525,15 @@ static void test_set_write_atomic(void) .cdw11 = 1 << 0, /* DN */ .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_write_atomic(TEST_FD, true, false, &result); + nvme_init_set_features_write_atomic(&cmd, false, true); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -585,13 +545,15 @@ static void test_get_write_atomic(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_WRITE_ATOMIC, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_write_atomic(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_write_atomic(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -606,13 +568,15 @@ static void test_set_async_event(void) .cdw11 = EVENTS, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_async_event(TEST_FD, EVENTS, true, &result); + nvme_init_set_features_async_event(&cmd, true, EVENTS); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -624,13 +588,15 @@ static void test_get_async_event(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_ASYNC_EVENT, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_async_event(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_async_event(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -646,14 +612,16 @@ static void test_set_auto_pst(void) .cdw11 = 1 << 0, /* APSTE */ .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; arbitrary(&apst, sizeof(apst)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_auto_pst(TEST_FD, true, false, &apst, &result); + nvme_init_set_features_auto_pst(&cmd, false, true, &apst); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -668,14 +636,16 @@ static void test_get_auto_pst(void) .out_data = &apst, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; arbitrary(&apst, sizeof(apst)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_auto_pst(TEST_FD, TEST_SEL, &get_apst, &result); + nvme_init_get_features_auto_pst(&cmd, TEST_SEL, &get_apst); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); cmp(&get_apst, &apst, sizeof(apst), "incorrect apst"); @@ -691,15 +661,16 @@ static void test_get_host_mem_buf(void) .out_data = &attrs, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; arbitrary(&attrs, sizeof(attrs)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_host_mem_buf2( - TEST_FD, TEST_SEL, &get_attrs, &result); + nvme_init_get_features_host_mem_buf(&cmd, TEST_SEL, &get_attrs); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); cmp(&get_attrs, &attrs, sizeof(attrs), "incorrect attrs"); @@ -708,6 +679,7 @@ static void test_get_host_mem_buf(void) static void test_set_timestamp(void) { struct nvme_timestamp ts = {.timestamp = {1, 2, 3, 4, 5, 6}}; + struct nvme_timestamp buf; uint64_t timestamp = ts.timestamp[0] | (uint64_t) ts.timestamp[1] << 8 | (uint64_t) ts.timestamp[2] << 16 @@ -721,12 +693,15 @@ static void test_set_timestamp(void) .cdw10 = (uint32_t)1 << 31 /* SAVE */ | NVME_FEAT_FID_TIMESTAMP, }; + uint32_t result = 0; + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_timestamp(TEST_FD, true, timestamp); + nvme_init_set_features_timestamp(&cmd, true, timestamp, &buf); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); } static void test_get_timestamp(void) @@ -738,13 +713,16 @@ static void test_get_timestamp(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_TIMESTAMP, .out_data = &ts, }; + struct nvme_passthru_cmd cmd; + uint32_t result = 0; int err; arbitrary(&ts, sizeof(ts)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_timestamp(TEST_FD, TEST_SEL, &get_ts); + nvme_init_get_features_timestamp(&cmd, TEST_SEL, &get_ts); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); cmp(&get_ts, &ts, sizeof(ts), "incorrect timestamp"); } @@ -755,13 +733,15 @@ static void test_get_kato(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_KATO, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_kato(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_kato(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -775,13 +755,15 @@ static void test_set_hctm(void) .cdw11 = (uint32_t)TMT1 << 16 | TMT2, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_hctm(TEST_FD, TMT2, TMT1, false, &result); + nvme_init_set_features_hctm(&cmd, false, TMT2, TMT1); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -793,13 +775,15 @@ static void test_get_hctm(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_HCTM, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_hctm(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_hctm(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -813,13 +797,15 @@ static void test_set_nopsc(void) .cdw11 = 1 << 0 /* NOPPME */, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_nopsc(TEST_FD, true, true, &result); + nvme_init_set_features_nopsc(&cmd, true, true); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -831,13 +817,15 @@ static void test_get_nopsc(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_NOPSC, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_nopsc(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_nopsc(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -853,13 +841,15 @@ static void test_set_rrl(void) .cdw12 = RRL, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_rrl(TEST_FD, RRL, NVMSETID, false, &result); + nvme_init_set_features_rrl(&cmd, false, NVMSETID, RRL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -872,13 +862,15 @@ static void test_get_rrl(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_RRL, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_rrl(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_rrl(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -897,15 +889,16 @@ static void test_set_plm_config(void) .cdw12 = 1 << 0 /* Predictable Latency Enable */, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; arbitrary(&config, sizeof(config)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_plm_config( - TEST_FD, true, NVMSETID, true, &config, &result); + nvme_init_set_features_plm_config(&cmd, true, NVMSETID, true, &config); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -922,15 +915,17 @@ static void test_get_plm_config(void) .out_data = &config, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; arbitrary(&config, sizeof(config)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_plm_config( - TEST_FD, TEST_SEL, NVMSETID, &get_config, &result); + nvme_init_get_features_plm_config(&cmd, TEST_SEL, NVMSETID, + &get_config); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); cmp(&get_config, &config, sizeof(config), "incorrect PLM config"); @@ -947,14 +942,15 @@ static void test_set_plm_window(void) .cdw12 = SEL, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_plm_window( - TEST_FD, SEL, NVMSETID, false, &result); + nvme_init_set_features_plm_window(&cmd, false, NVMSETID, SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -968,14 +964,15 @@ static void test_get_plm_window(void) .cdw11 = NVMSETID, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_plm_window( - TEST_FD, TEST_SEL, NVMSETID, &result); + nvme_init_get_features_plm_window(&cmd, TEST_SEL, NVMSETID); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -990,14 +987,15 @@ static void test_set_lba_sts_interval(void) .cdw11 = LSIPI << 16 | LSIRI, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_lba_sts_interval( - TEST_FD, LSIRI, LSIPI, true, &result); + nvme_init_set_features_lba_sts_interval(&cmd, true, LSIRI, LSIPI); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -1009,13 +1007,15 @@ static void test_get_lba_sts_interval(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_LBA_STS_INTERVAL, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_lba_sts_interval(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_lba_sts_interval(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -1030,13 +1030,16 @@ static void test_set_host_behavior(void) .data_len = sizeof(behavior), .cdw10 = NVME_FEAT_FID_HOST_BEHAVIOR, }; + struct nvme_passthru_cmd cmd; + uint32_t result = 0; int err; arbitrary(&behavior, sizeof(behavior)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_host_behavior(TEST_FD, true, &behavior); + nvme_init_set_features_host_behavior(&cmd, false, &behavior); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); } static void test_get_host_behavior(void) @@ -1049,15 +1052,16 @@ static void test_get_host_behavior(void) .out_data = &behavior, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; arbitrary(&behavior, sizeof(behavior)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_host_behavior( - TEST_FD, TEST_SEL, &get_behavior, &result); + nvme_init_get_features_host_behavior(&cmd, TEST_SEL, &get_behavior); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); cmp(&get_behavior, &behavior, sizeof(behavior), "incorrect behavior"); @@ -1071,13 +1075,15 @@ static void test_set_sanitize(void) .cdw11 = 1 << 0, /* NODRM */ .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_sanitize(TEST_FD, true, false, &result); + nvme_init_set_features_sanitize(&cmd, false, true); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -1089,13 +1095,15 @@ static void test_get_sanitize(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_SANITIZE, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_sanitize(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_sanitize(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -1111,14 +1119,15 @@ static void test_set_endurance_evt_cfg(void) .cdw11 = EGWARN << 16 | ENDGID, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_endurance_evt_cfg( - TEST_FD, ENDGID, EGWARN, true, &result); + nvme_init_set_features_endurance_evt_cfg(&cmd, true, ENDGID, EGWARN); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -1132,14 +1141,15 @@ static void test_get_endurance_event_cfg(void) .cdw11 = ENDGID, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_endurance_event_cfg( - TEST_FD, TEST_SEL, ENDGID, &result); + nvme_init_get_features_endurance_event_cfg(&cmd, TEST_SEL, ENDGID); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -1152,12 +1162,14 @@ static void test_set_iocs_profile(void) .cdw10 = NVME_FEAT_FID_IOCS_PROFILE, .cdw11 = IOCSI, }; + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_iocs_profile(TEST_FD, IOCSI, false); + nvme_init_set_features_iocs_profile(&cmd, false, IOCSI); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); } static void test_get_iocs_profile(void) @@ -1167,13 +1179,15 @@ static void test_get_iocs_profile(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_IOCS_PROFILE, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_iocs_profile(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_iocs_profile(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -1188,13 +1202,15 @@ static void test_set_sw_progress(void) .cdw11 = PBSLC, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_sw_progress(TEST_FD, PBSLC, true, &result); + nvme_init_set_features_sw_progress(&cmd, true, PBSLC); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -1206,13 +1222,15 @@ static void test_get_sw_progress(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_SW_PROGRESS, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_sw_progress(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_sw_progress(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -1228,13 +1246,16 @@ static void test_set_host_id(void) | NVME_FEAT_FID_HOST_ID, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; + uint32_t result = 0; int err; arbitrary(hostid, sizeof(hostid)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_host_id(TEST_FD, false, true, hostid); + nvme_init_set_features_host_id(&cmd, true, false,hostid); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); } static void test_set_host_id_extended(void) @@ -1248,13 +1269,15 @@ static void test_set_host_id_extended(void) .cdw11 = 1 << 0, /* EXHID */ .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(hostid, sizeof(hostid)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_host_id(TEST_FD, true, false, hostid); + nvme_init_set_features_host_id(&cmd, false, true, hostid); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); } static void test_get_host_id(void) @@ -1267,14 +1290,17 @@ static void test_get_host_id(void) .out_data = hostid, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; + uint32_t result = 0; int err; arbitrary(hostid, sizeof(hostid)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_host_id( - TEST_FD, TEST_SEL, false, sizeof(hostid), get_hostid); + nvme_init_get_features_host_id(&cmd, TEST_SEL, false, + get_hostid, sizeof(hostid)); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); cmp(get_hostid, hostid, sizeof(hostid), "incorrect host identifier"); } @@ -1289,14 +1315,17 @@ static void test_get_host_id_extended(void) .out_data = hostid, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; + uint32_t result = 0; int err; arbitrary(hostid, sizeof(hostid)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_host_id( - TEST_FD, TEST_SEL, true, sizeof(hostid), get_hostid); + nvme_init_get_features_host_id(&cmd, TEST_SEL, true, + get_hostid, sizeof(hostid)); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); cmp(get_hostid, hostid, sizeof(hostid), "incorrect host identifier"); } @@ -1311,14 +1340,15 @@ static void test_set_resv_mask(void) .cdw11 = MASK, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_resv_mask2( - TEST_FD, TEST_NSID, MASK, true, &result); + nvme_init_set_features_resv_mask(&cmd, TEST_NSID, true, MASK); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -1331,14 +1361,15 @@ static void test_get_resv_mask(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_RESV_MASK, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_resv_mask2( - TEST_FD, TEST_SEL, TEST_NSID, &result); + nvme_init_get_features_resv_mask(&cmd, TEST_NSID, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -1352,14 +1383,15 @@ static void test_set_resv_persist(void) .cdw11 = 1 << 0, /* PTPL */ .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_resv_persist2( - TEST_FD, TEST_NSID, true, false, &result); + nvme_init_set_features_resv_persist(&cmd, TEST_NSID, false, true); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -1372,14 +1404,15 @@ static void test_get_resv_persist(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_RESV_PERSIST, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_resv_persist2( - TEST_FD, TEST_SEL, TEST_NSID, &result); + nvme_init_get_features_resv_persist(&cmd, TEST_NSID, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -1389,21 +1422,23 @@ static void test_set_write_protect(void) /* nvme_set_features_write_protect() ignores SAVE */ enum nvme_feat_nswpcfg_state STATE = NVME_FEAT_NS_WRITE_PROTECT_PERMANENT; + bool save = true; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_set_features, .nsid = TEST_NSID, - .cdw10 = NVME_FEAT_FID_WRITE_PROTECT, + .cdw10 = NVME_FEAT_FID_WRITE_PROTECT | (!!save << 31), .cdw11 = STATE, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_write_protect2( - TEST_FD, TEST_NSID, STATE, true, &result); + nvme_init_set_features_write_protect(&cmd, TEST_NSID, true, STATE); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "set features returned error %d, errno %m", err); + check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -1416,14 +1451,15 @@ static void test_get_write_protect(void) .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_WRITE_PROTECT, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_write_protect( - TEST_FD, TEST_NSID, TEST_SEL, &result); + nvme_init_get_features_write_protect(&cmd, TEST_NSID, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "get features returned error %d, errno %m", err); + check(err == 0, "get features returned error %d", err); check(result == TEST_RESULT, "got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT); } @@ -1443,11 +1479,13 @@ static void test_set_status_code_error(void) .result = TEST_RESULT, .err = TEST_SC, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_async_event(TEST_FD, EVENTS, false, &result); + nvme_init_set_features_async_event(&cmd, false, EVENTS); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); check(err == TEST_SC, "got error %d, expected %d", err, TEST_SC); check(result == TEST_RESULT, @@ -1465,15 +1503,15 @@ static void test_set_kernel_error(void) .result = TEST_RESULT, .err = -EIO, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_resv_mask2( - TEST_FD, TEST_NSID, MASK, false, &result); + nvme_init_set_features_resv_mask(&cmd, TEST_NSID, false, MASK); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == -1, "got error %d, expected -1", err); - check(errno == EIO, "unexpected error %m"); + check(err == -EIO, "got error %d, expected -EIO", err); check(!result, "result unexpectedly set to %" PRIu32, result); } @@ -1490,11 +1528,13 @@ static void test_get_status_code_error(void) .result = TEST_RESULT, .err = TEST_SC, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_kato(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_kato(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); check(err == TEST_SC, "got error %d, expected %d", err, TEST_SC); check(result == TEST_RESULT, @@ -1509,14 +1549,15 @@ static void test_get_kernel_error(void) .result = TEST_RESULT, .err = -EBUSY, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_features_num_queues(TEST_FD, TEST_SEL, &result); + nvme_init_get_features_num_queues(&cmd, TEST_SEL); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == -1, "got error %d, expected -1", err); - check(errno == EBUSY, "unexpected error %m"); + check(err == -EBUSY, "got error %d, expected -EBUSY", err); check(!result, "result unexpectedly set to %" PRIu32, result); } @@ -1533,12 +1574,14 @@ static void test_lm_set_features_ctrl_data_queue(void) .cdw13 = tpt, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_lm_set_features_ctrl_data_queue(TEST_FD, TEST_CDQID, hp, tpt, - etpt, &result); + nvme_init_lm_set_features_ctrl_data_queue(&cmd, TEST_CDQID, + hp, tpt, etpt); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); check(err == 0, "set features returned error %d, errno %m", err); check(result == TEST_RESULT, @@ -1551,19 +1594,21 @@ static void test_lm_get_features_ctrl_data_queue(void) struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_get_features, .nsid = NVME_NSID_NONE, - .cdw10 = NVME_FEAT_FID_CTRL_DATA_QUEUE, + .cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_CTRL_DATA_QUEUE, .cdw11 = TEST_CDQID, .data_len = sizeof(expected_data), .out_data = &expected_data, .result = TEST_RESULT, }; + struct nvme_passthru_cmd cmd; uint32_t result = 0; int err; arbitrary(&expected_data, sizeof(expected_data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_lm_get_features_ctrl_data_queue(TEST_FD, TEST_CDQID, &data, - &result); + nvme_init_lm_get_features_ctrl_data_queue(&cmd, TEST_SEL, + TEST_CDQID, &data); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); check(err == 0, "get features returned error %d, errno %m", err); check(result == TEST_RESULT, @@ -1583,13 +1628,16 @@ static void run_test(const char *test_name, void (*test_fn)(void)) int main(void) { + struct nvme_global_ctx *ctx = + nvme_create_global_ctx(stdout, DEFAULT_LOGLEVEL); + set_mock_fd(TEST_FD); + check(!nvme_open(ctx, "NVME_TEST_FD", &test_hdl), + "opening test link failed"); + RUN_TEST(set_features); RUN_TEST(get_features); - RUN_TEST(set_features_data); RUN_TEST(get_features_data); - RUN_TEST(set_features_simple); - RUN_TEST(get_features_simple); RUN_TEST(set_arbitration); RUN_TEST(get_arbitration); RUN_TEST(set_power_mgmt); @@ -1655,4 +1703,6 @@ int main(void) RUN_TEST(get_kernel_error); RUN_TEST(lm_set_features_ctrl_data_queue); RUN_TEST(lm_get_features_ctrl_data_queue); + + nvme_free_global_ctx(ctx); } diff --git a/libnvme/test/ioctl/identify.c b/libnvme/test/ioctl/identify.c index bec2a11fea..3bf3b1247b 100644 --- a/libnvme/test/ioctl/identify.c +++ b/libnvme/test/ioctl/identify.c @@ -19,6 +19,8 @@ #define TEST_FIDX 0xF #define TEST_SC NVME_SC_INVALID_FIELD +static struct nvme_transport_handle *test_hdl; + static void test_ns(void) { struct nvme_id_ns expected_id, id = {}; @@ -29,11 +31,13 @@ static void test_ns(void) .cdw10 = NVME_IDENTIFY_CNS_NS, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_ns(TEST_FD, TEST_NSID, &id); + nvme_init_identify_ns(&cmd, TEST_NSID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); check(err == 0, "identify returned error %d, errno %m", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); @@ -48,13 +52,15 @@ static void test_ctrl(void) .cdw10 = NVME_IDENTIFY_CNS_CTRL, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_ctrl(TEST_FD, &id); + nvme_init_identify_ctrl(&cmd, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -68,13 +74,15 @@ static void test_active_ns_list(void) .cdw10 = NVME_IDENTIFY_CNS_NS_ACTIVE_LIST, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_active_ns_list(TEST_FD, TEST_NSID, &id); + nvme_init_identify_active_ns_list(&cmd, TEST_NSID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -89,15 +97,17 @@ static void test_ns_descs(void) .cdw10 = NVME_IDENTIFY_CNS_NS_DESC_LIST, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(expected_id, sizeof(expected_id)); id = calloc(1, NVME_IDENTIFY_DATA_SIZE); check(id, "memory allocation failed"); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_ns_descs(TEST_FD, TEST_NSID, id); + nvme_init_identify_ns_descs_list(&cmd, TEST_NSID, id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(id, expected_id, sizeof(expected_id), "incorrect identify data"); free(id); } @@ -112,13 +122,15 @@ static void test_nvmset_list(void) .cdw11 = TEST_NVMSETID, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_nvmset_list(TEST_FD, TEST_NVMSETID, &id); + nvme_init_identify_nvmset_list(&cmd, NVME_NSID_NONE, TEST_NVMSETID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -135,13 +147,15 @@ static void test_ns_csi(void) .cdw14 = TEST_UUID, .out_data = expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_ns_csi(TEST_FD, TEST_NSID, TEST_UUID, TEST_CSI, id); + nvme_init_identify_csi_ns(&cmd, TEST_NSID, TEST_CSI, TEST_UUID, id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(id, expected_id, sizeof(id), "incorrect identify data"); } @@ -156,13 +170,15 @@ static void test_zns_identify_ns(void) .cdw11 = NVME_CSI_ZNS << 24, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_zns_identify_ns(TEST_FD, TEST_NSID, &id); + nvme_init_zns_identify_ns(&cmd, TEST_NSID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -176,13 +192,15 @@ static void test_nvm_identify_ctrl(void) .cdw11 = NVME_CSI_NVM << 24, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_nvm_identify_ctrl(TEST_FD, &id); + nvme_init_identify_csi_ctrl(&cmd, NVME_CSI_NVM, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -196,13 +214,15 @@ static void test_zns_identify_ctrl(void) .cdw11 = NVME_CSI_ZNS << 24, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_zns_identify_ctrl(TEST_FD, &id); + nvme_init_zns_identify_ctrl(&cmd, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -217,14 +237,15 @@ static void test_active_ns_list_csi(void) .cdw11 = TEST_CSI << 24, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_active_ns_list_csi( - TEST_FD, TEST_NSID, TEST_CSI, &id); + nvme_init_identify_csi_active_ns_list(&cmd, TEST_NSID, TEST_CSI, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -238,14 +259,16 @@ static void test_independent_identify_ns(void) .cdw10 = NVME_IDENTIFY_CNS_CSI_INDEPENDENT_ID_NS, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); /* That's a mouthful! */ - err = nvme_identify_independent_identify_ns(TEST_FD, TEST_NSID, &id); + nvme_init_identify_csi_independent_identify_id_ns(&cmd, TEST_NSID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -259,13 +282,15 @@ static void test_allocated_ns_list(void) .cdw10 = NVME_IDENTIFY_CNS_ALLOCATED_NS_LIST, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_allocated_ns_list(TEST_FD, TEST_NSID, &id); + nvme_init_identify_allocated_ns_list(&cmd, TEST_NSID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -279,13 +304,15 @@ static void test_allocated_ns(void) .cdw10 = NVME_IDENTIFY_CNS_ALLOCATED_NS, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_allocated_ns(TEST_FD, TEST_NSID, &id); + nvme_init_identify_allocated_ns(&cmd, TEST_NSID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -300,13 +327,15 @@ static void test_nsid_ctrl_list(void) | NVME_IDENTIFY_CNS_NS_CTRL_LIST, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_nsid_ctrl_list(TEST_FD, TEST_NSID, TEST_CNTID, &id); + nvme_init_identify_ns_ctrl_list(&cmd, TEST_NSID, TEST_CNTID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -320,13 +349,15 @@ static void test_ctrl_list(void) | NVME_IDENTIFY_CNS_CTRL_LIST, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_ctrl_list(TEST_FD, TEST_CNTID, &id); + nvme_init_identify_ctrl_list(&cmd, TEST_CNTID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -340,13 +371,15 @@ static void test_primary_ctrl(void) | NVME_IDENTIFY_CNS_PRIMARY_CTRL_CAP, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_primary_ctrl(TEST_FD, TEST_CNTID, &id); + nvme_init_identify_primary_ctrl_cap(&cmd, TEST_CNTID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -360,13 +393,15 @@ static void test_secondary_ctrl_list(void) | NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_secondary_ctrl_list(TEST_FD, TEST_CNTID, &id); + nvme_init_identify_secondary_ctrl_list(&cmd, TEST_CNTID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -379,13 +414,15 @@ static void test_ns_granularity(void) .cdw10 = NVME_IDENTIFY_CNS_NS_GRANULARITY, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_ns_granularity(TEST_FD, &id); + nvme_init_identify_ns_granularity(&cmd, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -398,13 +435,15 @@ static void test_uuid(void) .cdw10 = NVME_IDENTIFY_CNS_UUID_LIST, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_uuid(TEST_FD, &id); + nvme_init_identify_uuid_list(&cmd, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -418,13 +457,15 @@ static void test_domain_list(void) .cdw11 = TEST_DOMID, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_domain_list(TEST_FD, TEST_DOMID, &id); + nvme_init_identify_domain_list(&cmd, TEST_DOMID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -438,13 +479,15 @@ static void test_endurance_group_list(void) .cdw11 = TEST_ENDGID, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_endurance_group_list(TEST_FD, TEST_ENDGID, &id); + nvme_init_identify_endurance_group_id(&cmd, TEST_ENDGID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -459,14 +502,15 @@ static void test_allocated_ns_list_csi(void) .cdw11 = TEST_CSI << 24, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_allocated_ns_list_csi( - TEST_FD, TEST_NSID, TEST_CSI, &id); + nvme_init_identify_csi_allocated_ns_list(&cmd, TEST_NSID, TEST_CSI, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -480,13 +524,15 @@ static void test_iocs(void) | NVME_IDENTIFY_CNS_COMMAND_SET_STRUCTURE, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_iocs(TEST_FD, TEST_CNTID, &id); + nvme_init_identify_command_set_structure(&cmd, TEST_CNTID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "identify returned error %d, errno %m", err); + check(err == 0, "identify returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); } @@ -505,12 +551,14 @@ static void test_status_code_error(void) .cdw11 = TEST_NVMSETID, .err = TEST_SC, }; + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_nvmset_list(TEST_FD, TEST_NVMSETID, &id); + nvme_init_identify_nvmset_list(&cmd, NVME_NSID_NONE, TEST_NVMSETID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == TEST_SC, "got error %d, expected %d", err, TEST_SC); + check(err == TEST_SC, "got error %d, expected TEST_SC", err); } static void test_kernel_error(void) @@ -523,13 +571,14 @@ static void test_kernel_error(void) .cdw10 = NVME_IDENTIFY_CNS_NS, .err = -EIO, }; + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_ns(TEST_FD, TEST_NSID, &id); + nvme_init_identify_ns(&cmd, TEST_NSID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == -1, "got error %d, expected -1", err); - check(errno == EIO, "unexpected error %m"); + check(err == -EIO, "got error %d, expected -EIO", err); } static void test_identify_ns_csi_user_data_format(void) @@ -545,12 +594,14 @@ static void test_identify_ns_csi_user_data_format(void) .cdw14 = TEST_UUID, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_ns_csi_user_data_format( - TEST_FD, TEST_FIDX, TEST_UUID, NVME_CSI_NVM, &id); + nvme_init_identify_ns_user_data_format(&cmd, NVME_CSI_NVM, + TEST_FIDX, TEST_UUID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); check(err == 0, "identify returned error %d, errno %m", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); @@ -568,12 +619,14 @@ static void test_identify_iocs_ns_csi_user_data_format(void) .cdw14 = TEST_UUID, .out_data = &expected_id, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_identify_iocs_ns_csi_user_data_format( - TEST_FD, TEST_FIDX, TEST_UUID, TEST_CSI, &id); + nvme_init_identify_csi_ns_user_data_format(&cmd, TEST_CSI, + TEST_FIDX, TEST_UUID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); check(err == 0, "identify returned error %d, errno %m", err); cmp(&id, &expected_id, sizeof(id), "incorrect identify data"); @@ -591,7 +644,13 @@ static void run_test(const char *test_name, void (*test_fn)(void)) int main(void) { + struct nvme_global_ctx * ctx = + nvme_create_global_ctx(stdout, DEFAULT_LOGLEVEL); + set_mock_fd(TEST_FD); + check(!nvme_open(ctx, "NVME_TEST_FD", &test_hdl), + "opening test link failed"); + RUN_TEST(ns); RUN_TEST(ctrl); RUN_TEST(active_ns_list); @@ -619,4 +678,6 @@ int main(void) RUN_TEST(kernel_error); RUN_TEST(identify_ns_csi_user_data_format); RUN_TEST(identify_iocs_ns_csi_user_data_format); + + nvme_free_global_ctx(ctx); } diff --git a/libnvme/test/ioctl/logs.c b/libnvme/test/ioctl/logs.c index c3822991a7..9955a3fbe9 100644 --- a/libnvme/test/ioctl/logs.c +++ b/libnvme/test/ioctl/logs.c @@ -23,6 +23,8 @@ #define TEST_LSP NVME_LOG_CDW10_LSP_MASK #define TEST_PEVENT NVME_PEVENT_LOG_RELEASE_CTX +static struct nvme_transport_handle *test_hdl; + static void test_get_log_sanitize(void) { struct nvme_sanitize_log_page expected_log, log = {}; @@ -34,11 +36,13 @@ static void test_get_log_sanitize(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_sanitize(TEST_FD, true, &log); + nvme_init_get_log_sanitize(&cmd, &log); + err = nvme_get_log(test_hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); check(err == 0, "get log returned error %d, errno %m", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); @@ -55,13 +59,15 @@ static void test_get_log_mgmt_addr_list(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_mgmt_addr_list(TEST_FD, sizeof(log), &log); + nvme_init_get_log_mgmt_addr_list(&cmd, &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -77,13 +83,16 @@ static void test_get_log_supported_log_pages(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_supported_log_pages(TEST_FD, !TEST_RAE, &log); + nvme_init_get_log_supported_log_pages(&cmd, NVME_CSI_NVM, &log); + err = nvme_get_log(test_hdl, &cmd, !TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -98,13 +107,16 @@ static void test_get_log_error(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_error(TEST_FD, 1, TEST_RAE, &log); + nvme_init_get_log_error(&cmd, 1, &log); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -119,13 +131,16 @@ static void test_get_log_smart(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_smart(TEST_FD, TEST_NSID, TEST_RAE, &log); + nvme_init_get_log_smart(&cmd, TEST_NSID, &log); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -140,13 +155,16 @@ static void test_get_log_fw_slot(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_fw_slot(TEST_FD, TEST_RAE, &log); + nvme_init_get_log_fw_slot(&cmd, &log); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -161,13 +179,16 @@ static void test_get_log_changed_ns_list(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_changed_ns_list(TEST_FD, TEST_RAE, &log); + nvme_init_get_log_changed_ns(&cmd, &log); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -183,13 +204,15 @@ static void test_get_log_cmd_effects(void) .cdw14 = (TEST_CSI << 24), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_cmd_effects(TEST_FD, TEST_CSI, &log); + nvme_init_get_log_cmd_effects(&cmd, TEST_CSI, &log); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -204,13 +227,15 @@ static void test_get_log_device_self_test(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_device_self_test(TEST_FD, &log); + nvme_init_get_log_device_self_test(&cmd, &log); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -227,13 +252,15 @@ static void test_get_log_create_telemetry_host_mcda(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_create_telemetry_host_mcda(TEST_FD, TEST_MCDA, &log); + nvme_init_get_log_create_telemetry_host_mcda(&cmd, TEST_MCDA, &log); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -251,13 +278,15 @@ static void test_get_log_create_telemetry_host(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_create_telemetry_host(TEST_FD, &log); + nvme_init_get_log_create_telemetry_host(&cmd, &log); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -277,14 +306,15 @@ static void test_get_log_telemetry_host(void) .cdw13 = TEST_OFFSET >> 32, .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_telemetry_host(TEST_FD, TEST_OFFSET, sizeof(log), - &log); + nvme_init_get_log_telemetry_host(&cmd, TEST_OFFSET, &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -305,14 +335,16 @@ static void test_get_log_telemetry_ctrl(void) .cdw13 = TEST_OFFSET >> 32, .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_telemetry_ctrl(TEST_FD, TEST_RAE, TEST_OFFSET, - sizeof(log), &log); + nvme_init_get_log_telemetry_ctrl(&cmd, TEST_OFFSET, &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -328,13 +360,15 @@ static void test_get_log_endurance_group(void) .cdw11 = (TEST_ENDGID << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_endurance_group(TEST_FD, TEST_ENDGID, &log); + nvme_init_get_log_endurance_group(&cmd, TEST_ENDGID, &log); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -350,13 +384,15 @@ static void test_get_log_predictable_lat_nvmset(void) .cdw11 = (TEST_NVMSETID << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_predictable_lat_nvmset(TEST_FD, TEST_NVMSETID, &log); + nvme_init_get_log_predictable_lat_nvmset(&cmd, TEST_NVMSETID, &log); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -373,14 +409,17 @@ static void test_get_log_predictable_lat_event(void) .cdw12 = TEST_OFFSET_32, .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_predictable_lat_event( - TEST_FD, TEST_RAE, TEST_OFFSET_32, sizeof(log), &log); + nvme_init_get_log_predictable_lat_event(&cmd, TEST_OFFSET_32, + &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -397,14 +436,16 @@ static void test_get_log_fdp_configurations(void) .cdw12 = TEST_OFFSET_32, .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_fdp_configurations( - TEST_FD, TEST_ENDGID, TEST_OFFSET_32, sizeof(log), &log); + nvme_init_get_log_fdp_configurations(&cmd, TEST_ENDGID, + TEST_OFFSET_32, &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -421,14 +462,17 @@ static void test_get_log_reclaim_unit_handle_usage(void) .cdw12 = TEST_OFFSET_32, .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_reclaim_unit_handle_usage( - TEST_FD, TEST_ENDGID, TEST_OFFSET_32, sizeof(log), &log); + nvme_init_get_log_reclaim_unit_handle_usage(&cmd, TEST_ENDGID, + TEST_OFFSET_32, &log, + sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -445,14 +489,16 @@ static void test_get_log_fdp_stats(void) .cdw12 = TEST_OFFSET_32, .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_fdp_stats(TEST_FD, TEST_ENDGID, TEST_OFFSET_32, - sizeof(log), &log); + nvme_init_get_log_fdp_stats(&cmd, TEST_ENDGID, TEST_OFFSET_32, + &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -470,14 +516,16 @@ static void test_get_log_fdp_events(void) .cdw12 = TEST_OFFSET_32, .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_fdp_events(TEST_FD, TEST_ENDGID, TEST_EVENTS, - TEST_OFFSET_32, sizeof(log), &log); + nvme_init_get_log_fdp_events(&cmd, TEST_EVENTS, TEST_ENDGID, + TEST_OFFSET_32, &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -495,14 +543,17 @@ static void test_get_log_ana(void) .cdw13 = TEST_OFFSET >> 32, .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_ana(TEST_FD, TEST_ANA_LSP, TEST_RAE, TEST_OFFSET, - sizeof(log), &log); + nvme_init_get_log_ana(&cmd, TEST_ANA_LSP, TEST_OFFSET, + &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -519,13 +570,16 @@ static void test_get_log_ana_groups(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_ana_groups(TEST_FD, TEST_RAE, sizeof(log), &log); + nvme_init_get_log_ana_groups(&cmd, &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -542,14 +596,16 @@ static void test_get_log_lba_status(void) .cdw13 = TEST_OFFSET >> 32, .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_lba_status(TEST_FD, TEST_RAE, TEST_OFFSET, - sizeof(log), &log); + nvme_init_get_log_lba_status(&cmd, TEST_OFFSET, &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -566,14 +622,17 @@ static void test_get_log_endurance_grp_evt(void) .cdw12 = TEST_OFFSET_32, .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_endurance_grp_evt(TEST_FD, TEST_RAE, TEST_OFFSET_32, - sizeof(log), &log); + nvme_init_get_log_endurance_grp_evt(&cmd, TEST_OFFSET_32, + &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -589,13 +648,16 @@ static void test_get_log_fid_supported_effects(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_fid_supported_effects(TEST_FD, TEST_RAE, &log); + nvme_init_get_log_fid_supported_effects(&cmd, NVME_CSI_NVM, &log); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -611,13 +673,16 @@ static void test_get_log_mi_cmd_supported_effects(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_mi_cmd_supported_effects(TEST_FD, TEST_RAE, &log); + nvme_init_get_log_mi_cmd_supported_effects(&cmd, &log); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -633,14 +698,16 @@ static void test_get_log_boot_partition(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_boot_partition(TEST_FD, TEST_RAE, TEST_LSP, - sizeof(log), &log); + nvme_init_get_log_boot_partition(&cmd, TEST_LSP, &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -656,14 +723,16 @@ static void test_get_log_rotational_media_info(void) .cdw11 = (TEST_ENDGID << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_rotational_media_info(TEST_FD, TEST_ENDGID, - sizeof(log), &log); + nvme_init_get_log_rotational_media_info(&cmd, TEST_ENDGID, + &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -678,14 +747,16 @@ static void test_get_log_dispersed_ns_participating_nss(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_dispersed_ns_participating_nss(TEST_FD, TEST_NSID, - sizeof(log), &log); + nvme_init_get_log_dispersed_ns_participating_nss(&cmd, TEST_NSID, + &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -701,14 +772,16 @@ static void test_get_log_phy_rx_eom(void) .cdw11 = (TEST_CNTID << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_phy_rx_eom(TEST_FD, TEST_LSP, TEST_CNTID, - sizeof(log), &log); + nvme_init_get_log_phy_rx_eom(&cmd, TEST_LSP, TEST_CNTID, + &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -720,18 +793,21 @@ static void test_get_log_reachability_groups(void) .nsid = NVME_NSID_ALL, .data_len = sizeof(expected_log), .cdw10 = (NVME_LOG_LID_REACHABILITY_GROUPS << 0) | - (!!TEST_LSP << 8) | (!!TEST_RAE << 15) | + ((TEST_LSP != 0) << 8) | (!!TEST_RAE << 15) | (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_reachability_groups(TEST_FD, !!TEST_LSP, TEST_RAE, - sizeof(log), &log); + nvme_init_get_log_reachability_groups(&cmd, TEST_LSP != 0, &log, + sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -743,41 +819,46 @@ static void test_get_log_reachability_associations(void) .nsid = NVME_NSID_ALL, .data_len = sizeof(expected_log), .cdw10 = (NVME_LOG_LID_REACHABILITY_ASSOCIATIONS << 0) | - (!!TEST_LSP << 8) | (!!TEST_RAE << 15) | + ((TEST_LSP != 0) << 8) | (!!TEST_RAE << 15) | (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_reachability_associations( - TEST_FD, !!TEST_LSP, TEST_RAE, sizeof(log), &log); + nvme_init_get_log_reachability_associations(&cmd, TEST_LSP != 0, &log, + sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } -static void test_get_log_changed_alloc_ns_list(void) +static void test_get_log_changed_alloc_ns(void) { struct nvme_ns_list expected_log, log = {}; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_get_log_page, .nsid = NVME_NSID_ALL, .data_len = sizeof(expected_log), - .cdw10 = (NVME_LOG_LID_CHANGED_ALLOC_NS_LIST << 0) | + .cdw10 = (NVME_LOG_LID_CHANGED_ALLOC_NS << 0) | (!!TEST_RAE << 15) | (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_changed_alloc_ns_list(TEST_FD, TEST_RAE, sizeof(log), - &log); + nvme_init_get_log_changed_alloc_ns(&cmd, &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -788,19 +869,21 @@ static void test_get_log_discovery(void) .opcode = nvme_admin_get_log_page, .nsid = NVME_NSID_NONE, .data_len = sizeof(expected_log), - .cdw10 = (NVME_LOG_LID_DISCOVER << 0) | (!!TEST_RAE << 15) | + .cdw10 = (NVME_LOG_LID_DISCOVERY << 0) | (!!TEST_RAE << 15) | (((sizeof(expected_log) >> 2) - 1) << 16), .cdw12 = TEST_OFFSET_32, .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_discovery(TEST_FD, TEST_RAE, TEST_OFFSET_32, - sizeof(log), &log); + nvme_init_get_log_discovery(&cmd, TEST_OFFSET_32, &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -811,19 +894,23 @@ static void test_get_log_host_discover(void) .opcode = nvme_admin_get_log_page, .nsid = NVME_NSID_ALL, .data_len = sizeof(expected_log), - .cdw10 = (NVME_LOG_LID_HOST_DISCOVER << 0) | (!!TEST_LSP << 8) | + .cdw10 = (NVME_LOG_LID_HOST_DISCOVERY << 0) | + ((TEST_LSP != 0) << 8) | (!!TEST_RAE << 15) | (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_host_discover(TEST_FD, !!TEST_LSP, TEST_RAE, - sizeof(log), &log); + nvme_init_get_log_host_discovery(&cmd, TEST_LSP != 0, + &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -834,17 +921,21 @@ static void test_get_log_ave_discover(void) .opcode = nvme_admin_get_log_page, .nsid = NVME_NSID_ALL, .data_len = sizeof(expected_log), - .cdw10 = (NVME_LOG_LID_AVE_DISCOVER << 0) | (!!TEST_RAE << 15) | + .cdw10 = (NVME_LOG_LID_AVE_DISCOVERY << 0) | + (!!TEST_RAE << 15) | (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_ave_discover(TEST_FD, TEST_RAE, sizeof(log), &log); + nvme_init_get_log_ave_discovery(&cmd, &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -860,14 +951,16 @@ static void test_get_log_pull_model_ddc_req(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_pull_model_ddc_req(TEST_FD, TEST_RAE, sizeof(log), - &log); + nvme_init_get_log_pull_model_ddc_req(&cmd, &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -883,13 +976,15 @@ static void test_get_log_media_unit_stat(void) .cdw11 = (TEST_DOMID << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_media_unit_stat(TEST_FD, TEST_DOMID, &log); + nvme_init_get_log_media_unit_stat(&cmd, TEST_DOMID, &log); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -905,13 +1000,15 @@ static void test_get_log_support_cap_config_list(void) .cdw11 = (TEST_DOMID << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_support_cap_config_list(TEST_FD, TEST_DOMID, &log); + nvme_init_get_log_support_cap_config_list(&cmd, TEST_DOMID, &log); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -926,13 +1023,16 @@ static void test_get_log_reservation(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_reservation(TEST_FD, TEST_RAE, &log); + nvme_init_get_log_reservation(&cmd, &log); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -949,14 +1049,16 @@ static void test_get_log_zns_changed_zones(void) .cdw14 = NVME_CSI_ZNS << 24, .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_zns_changed_zones(TEST_FD, TEST_NSID, TEST_RAE, - &log); + nvme_init_get_log_zns_changed_zones(&cmd, TEST_NSID, &log); + err = nvme_get_log(test_hdl, &cmd, TEST_RAE, + NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -972,14 +1074,16 @@ static void test_get_log_persistent_event(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_persistent_event(TEST_FD, TEST_PEVENT, sizeof(log), - &log); + nvme_init_get_log_persistent_event(&cmd, TEST_PEVENT, + &log, sizeof(log)); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -995,13 +1099,15 @@ static void test_get_log_lockdown(void) (((sizeof(expected_log) >> 2) - 1) << 16), .out_data = &expected_log, }; + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_log, sizeof(expected_log)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_log_lockdown(TEST_FD, TEST_LSP, &log); + nvme_init_get_log_lockdown(&cmd, TEST_LSP, &log); + err = nvme_get_log(test_hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); end_mock_cmds(); - check(err == 0, "get log returned error %d, errno %m", err); + check(err == 0, "get log returned error %d", err); cmp(&log, &expected_log, sizeof(log), "incorrect log data"); } @@ -1017,7 +1123,13 @@ static void run_test(const char *test_name, void (*test_fn)(void)) int main(void) { + struct nvme_global_ctx * ctx = + nvme_create_global_ctx(stdout, DEFAULT_LOGLEVEL); + set_mock_fd(TEST_FD); + check(!nvme_open(ctx, "NVME_TEST_FD", &test_hdl), + "opening test link failed"); + RUN_TEST(get_log_sanitize); RUN_TEST(get_log_mgmt_addr_list); RUN_TEST(get_log_supported_log_pages); @@ -1050,7 +1162,7 @@ int main(void) RUN_TEST(get_log_phy_rx_eom); RUN_TEST(get_log_reachability_groups); RUN_TEST(get_log_reachability_associations); - RUN_TEST(get_log_changed_alloc_ns_list); + RUN_TEST(get_log_changed_alloc_ns); RUN_TEST(get_log_discovery); RUN_TEST(get_log_host_discover); RUN_TEST(get_log_ave_discover); @@ -1061,4 +1173,6 @@ int main(void) RUN_TEST(get_log_zns_changed_zones); RUN_TEST(get_log_persistent_event); RUN_TEST(get_log_lockdown); + + nvme_free_global_ctx(ctx); } diff --git a/libnvme/test/ioctl/meson.build b/libnvme/test/ioctl/meson.build index f97925fe58..e086cbf4af 100644 --- a/libnvme/test/ioctl/meson.build +++ b/libnvme/test/ioctl/meson.build @@ -15,7 +15,7 @@ mock_ioctl = library( 'mock-ioctl', ['mock.c', 'util.c'], include_directories: [incdir, internal_incdir], - dependencies: [dl_dep], + dependencies: [libnvme_dep, dl_dep], c_args: ['-DHAVE_GLIBC_IOCTL=' + (mock_conf.get('HAVE_GLIBC_IOCTL') ? '1' : '0')]) # Add mock-ioctl to the LD_PRELOAD path so it overrides libc. diff --git a/libnvme/test/ioctl/misc.c b/libnvme/test/ioctl/misc.c index 755cea6032..135c8f350c 100644 --- a/libnvme/test/ioctl/misc.c +++ b/libnvme/test/ioctl/misc.c @@ -4,7 +4,6 @@ #include "mock.h" #include "util.h" -#include #include #include #include @@ -13,71 +12,60 @@ #define TEST_NSID 0x12345678 #define TEST_CSI NVME_CSI_KV +static struct nvme_transport_handle *test_hdl; + static void test_format_nvm(void) { + enum nvme_cmd_format_mset mset = NVME_FORMAT_MSET_EXTENDED; + enum nvme_cmd_format_pi pi = NVME_FORMAT_PI_TYPE2; + enum nvme_cmd_format_pil pil = NVME_FORMAT_PIL_FIRST; + enum nvme_cmd_format_ses ses = NVME_FORMAT_SES_USER_DATA_ERASE; + __u32 nsid = TEST_NSID; + __u8 lbaf = 0x1F; __u32 result = 0; - struct nvme_format_nvm_args args = { - .result = &result, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .mset = NVME_FORMAT_MSET_EXTENDED, - .pi = NVME_FORMAT_PI_TYPE2, - .pil = NVME_FORMAT_PIL_FIRST, - .ses = NVME_FORMAT_SES_USER_DATA_ERASE, - .lbaf = 0xF, - .lbafu = 0x1, - }; - struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_format_nvm, - .nsid = TEST_NSID, - .cdw10 = args.lbaf | (args.mset << 4) | (args.pi << 5) | - (args.pil << 8) | (args.ses << 9) | (args.lbafu << 12), + .nsid = nsid, + .cdw10 = lbaf | (mset << 4) | (pi << 5) | + (pil << 8) | (ses << 9) | ((lbaf >> 4) << 12), .result = 0, }; - + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_format_nvm(&args); + nvme_init_format_nvm(&cmd, nsid, lbaf, mset, pi, pil, ses); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } static void test_ns_mgmt(void) { struct nvme_ns_mgmt_host_sw_specified expected_data, data = {}; + enum nvme_ns_mgmt_sel sel = NVME_NS_MGMT_SEL_CREATE; + __u32 nsid = TEST_NSID; + __u8 csi = TEST_CSI; __u32 result = 0; - struct nvme_ns_mgmt_args args = { - .result = &result, - .ns = NULL, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .sel = NVME_NS_MGMT_SEL_CREATE, - .csi = TEST_CSI, - .data = &data, - }; - struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_ns_mgmt, - .nsid = TEST_NSID, - .cdw10 = args.sel, - .cdw11 = args.csi << 24, + .nsid = nsid, + .cdw10 = sel, + .cdw11 = csi << 24, .result = 0, .data_len = sizeof(expected_data), .out_data = &expected_data, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_ns_mgmt(&args); + nvme_init_ns_mgmt(&cmd, nsid, sel, csi, &data); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } @@ -85,25 +73,28 @@ static void test_ns_mgmt(void) static void test_ns_mgmt_create(void) { struct nvme_ns_mgmt_host_sw_specified expected_data, data = {}; + enum nvme_ns_mgmt_sel sel = NVME_NS_MGMT_SEL_CREATE; + __u32 nsid = NVME_NSID_NONE; + __u8 csi = NVME_CSI_ZNS; __u32 result = 0; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_ns_mgmt, - .nsid = NVME_NSID_NONE, - .cdw10 = NVME_NS_MGMT_SEL_CREATE, - .cdw11 = NVME_CSI_ZNS << 24, + .nsid = nsid, + .cdw10 = sel, + .cdw11 = csi << 24, .result = TEST_NSID, .data_len = sizeof(expected_data), .out_data = &expected_data, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_ns_mgmt_create(TEST_FD, NULL, &result, 0, NVME_CSI_ZNS, - &data); + nvme_init_ns_mgmt_create(&cmd, NVME_CSI_ZNS, &data); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == TEST_NSID, "returned result %u", result); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } @@ -115,41 +106,35 @@ static void test_ns_mgmt_delete(void) .nsid = TEST_NSID, .cdw10 = NVME_NS_MGMT_SEL_DELETE, }; - + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_ns_mgmt_delete(TEST_FD, TEST_NSID); + nvme_init_ns_mgmt_delete(&cmd, TEST_NSID); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); } static void test_get_property(void) { __u64 expected_result, result; - struct nvme_get_property_args args = { - .value = &result, - .args_size = sizeof(args), - .fd = TEST_FD, - .offset = NVME_REG_ACQ, - }; - arbitrary(&expected_result, sizeof(expected_result)); - struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_fabrics, .nsid = nvme_fabrics_type_property_get, - .cdw10 = !!true, + .cdw10 = true, .cdw11 = NVME_REG_ACQ, .result = expected_result, }; - + struct nvme_passthru_cmd64 cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_property(&args); + nvme_init_get_property(&cmd, NVME_REG_ACQ); + err = nvme_submit_admin_passthru64(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == expected_result, "returned wrong result"); } @@ -157,60 +142,47 @@ static void test_set_property(void) { __u64 value = 0xffffffff; __u32 result; - struct nvme_set_property_args args = { - .value = value, - .result = &result, - .args_size = sizeof(args), - .fd = TEST_FD, - .offset = NVME_REG_BPMBL, - }; - struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_fabrics, .nsid = nvme_fabrics_type_property_set, - .cdw10 = !!true, + .cdw10 = true, .cdw11 = NVME_REG_BPMBL, .cdw12 = value & 0xffffffff, .cdw13 = value >> 32, }; - + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_property(&args); + nvme_init_set_property(&cmd, NVME_REG_BPMBL, value); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } static void test_ns_attach(void) { - __u32 result; struct nvme_ctrl_list expected_ctrlist, ctrlist; - struct nvme_ns_attach_args args = { - .result = &result, - .ctrlist = &ctrlist, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .sel = NVME_NS_ATTACH_SEL_CTRL_DEATTACH, - }; - + enum nvme_ns_attach_sel sel = NVME_NS_ATTACH_SEL_CTRL_ATTACH; + __u32 nsid = TEST_NSID; + __u32 result; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_ns_attach, - .nsid = TEST_NSID, - .cdw10 = NVME_NS_ATTACH_SEL_CTRL_DEATTACH, + .nsid = nsid, + .cdw10 = sel, .data_len = sizeof(expected_ctrlist), .out_data = &expected_ctrlist, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_ctrlist, sizeof(expected_ctrlist)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_ns_attach(&args); + nvme_init_ns_attach(&cmd, nsid, sel, &ctrlist); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); cmp(&expected_ctrlist, &ctrlist, sizeof(expected_ctrlist), "incorrect data"); @@ -219,7 +191,6 @@ static void test_ns_attach(void) static void test_ns_attach_ctrls(void) { struct nvme_ctrl_list ctrlist; - struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_ns_attach, .nsid = TEST_NSID, @@ -227,20 +198,20 @@ static void test_ns_attach_ctrls(void) .data_len = sizeof(ctrlist), .out_data = &ctrlist, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&ctrlist, sizeof(ctrlist)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_ns_attach_ctrls(TEST_FD, TEST_NSID, &ctrlist); + nvme_init_ns_attach_ctrls(&cmd, TEST_NSID, &ctrlist); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); } static void test_ns_detach_ctrls(void) { struct nvme_ctrl_list ctrlist; - struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_ns_attach, .nsid = TEST_NSID, @@ -248,113 +219,95 @@ static void test_ns_detach_ctrls(void) .data_len = sizeof(ctrlist), .out_data = &ctrlist, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&ctrlist, sizeof(ctrlist)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_ns_detach_ctrls(TEST_FD, TEST_NSID, &ctrlist); + nvme_init_ns_detach_ctrls(&cmd, TEST_NSID, &ctrlist); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); } static void test_fw_download(void) { __u32 result = 0; __u8 expected_data[8], data[8]; - - struct nvme_fw_download_args args = { - .result = &result, - .data = &expected_data, - .args_size = sizeof(args), - .fd = TEST_FD, - .offset = 123, - .data_len = sizeof(expected_data), - }; - + __u32 data_len = sizeof(expected_data); + __u32 offset = 120; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_fw_download, - .cdw10 = (args.data_len >> 2) - 1, - .cdw11 = args.offset >> 2, - .data_len = args.data_len, + .cdw10 = (data_len >> 2) - 1, + .cdw11 = offset >> 2, + .data_len = data_len, .in_data = &data, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); memcpy(&data, &expected_data, sizeof(expected_data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_fw_download(&args); + err = nvme_init_fw_download(&cmd, data, data_len, offset); + check(err == 0, "download initializing error %d", err); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } static void test_fw_commit(void) { - __u32 result = 0; - - struct nvme_fw_commit_args args = { - .result = &result, - .args_size = sizeof(args), - .fd = TEST_FD, - .action = NVME_FW_COMMIT_CA_REPLACE_AND_ACTIVATE_IMMEDIATE, - .slot = 0xf, - .bpid = true, - }; - + enum nvme_fw_commit_ca action = + NVME_FW_COMMIT_CA_REPLACE_AND_ACTIVATE_IMMEDIATE; + __u8 slot = 0xf; + bool bpid = true; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_fw_commit, - .cdw10 = (!!args.bpid << 31) | (args.action << 3) | args.slot, + .cdw10 = (bpid << 31) | (action << 3) | slot, }; - + struct nvme_passthru_cmd cmd; + __u32 result = 0; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_fw_commit(&args); + nvme_init_fw_commit(&cmd, slot, action, bpid); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } static void test_security_send(void) { __u8 expected_data[8], data[8]; + __u32 data_len = sizeof(expected_data); + __u32 nsid = TEST_NSID; + __u32 tl = 0xffff; __u32 result = 0; - - struct nvme_security_send_args args = { - .result = &result, - .data = &expected_data, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .tl = 0xffff, - .data_len = sizeof(expected_data), - .nssf = 0x1, - .spsp0 = 0x1, - .spsp1 = 0x1, - .secp = 0xE9, - }; - + __u8 nssf = 0x1; + __u16 spsp = 0x0101; + __u8 secp = 0xE9; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_security_send, .nsid = TEST_NSID, - .cdw10 = args.nssf | (args.spsp0 << 8) | (args.spsp1 << 16) | - (args.secp << 24), - .cdw11 = args.tl, - .data_len = args.data_len, - .in_data = &data, + .cdw10 = nssf | (spsp << 8) | (secp << 24), + .cdw11 = tl, + .data_len = data_len, + .in_data = &expected_data, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); memcpy(&data, &expected_data, sizeof(expected_data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_security_send(&args); + nvme_init_security_send(&cmd, nsid, nssf, spsp, secp, tl, + data, data_len); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } @@ -363,48 +316,43 @@ static void test_security_receive(void) { __u8 expected_data[8], data[8]; __u32 result = 0; - - struct nvme_security_receive_args args = { - .result = &result, - .data = &data, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .al = 0xffff, - .data_len = sizeof(data), - .nssf = 0x1, - .spsp0 = 0x1, - .spsp1 = 0x1, - .secp = 0xE9, - }; - + __u32 al = 0xffff; + __u16 spsp = 0x0101; + __u8 secp = 0xE9; + __u8 nssf = 0x1; + int err; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_security_recv, .nsid = TEST_NSID, - .cdw10 = args.nssf | (args.spsp0 << 8) | (args.spsp1 << 16) | - (args.secp << 24), - .cdw11 = args.al, - .data_len = args.data_len, + .cdw10 = nssf | (spsp << 8) | (secp << 24), + .cdw11 = al, + .data_len = sizeof(expected_data), .out_data = &expected_data, }; - - int err; + struct nvme_passthru_cmd cmd; arbitrary(&expected_data, sizeof(expected_data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_security_receive(&args); + nvme_init_security_receive(&cmd, TEST_NSID, nssf, spsp, secp, al, + data, sizeof(data)); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } static void test_get_lba_status(void) { - __u32 result = 0; __u8 nlsd = 3; int lba_status_size = sizeof(struct nvme_lba_status) + nlsd * sizeof(struct nvme_lba_status_desc); + enum nvme_lba_status_atype atype = 0x11; + __u32 mndw = (lba_status_size - 1) >> 2; + __u64 slba = 0x123456789; + __u32 result = 0; + __u16 rl = 0x42; + int err; _cleanup_free_ struct nvme_lba_status *lbas = NULL; _cleanup_free_ struct nvme_lba_status *expected_lbas = NULL; @@ -414,76 +362,57 @@ static void test_get_lba_status(void) expected_lbas = malloc(lba_status_size); check(expected_lbas, "expected_lbas: ENOMEM"); - struct nvme_get_lba_status_args args = { - .slba = 0x123456789, - .result = &result, - .lbas = lbas, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .mndw = ((lba_status_size - 1) >> 2), - .atype = 0x11, - .rl = 0x42, - }; - struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_get_lba_status, .nsid = TEST_NSID, - .cdw10 = args.slba & 0xffffffff, - .cdw11 = args.slba >> 32, - .cdw12 = args.mndw, - .cdw13 = args.rl | (args.atype << 24), - .data_len = (args.mndw + 1) << 2, + .cdw10 = slba & 0xffffffff, + .cdw11 = slba >> 32, + .cdw12 = mndw, + .cdw13 = rl | (atype << 24), + .data_len = (mndw + 1) << 2, .out_data = expected_lbas, }; - - int err; + struct nvme_passthru_cmd cmd; arbitrary(expected_lbas, lba_status_size); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_get_lba_status(&args); + nvme_init_get_lba_status(&cmd, TEST_NSID, slba, mndw, atype, + rl, lbas); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned wrong result"); cmp(lbas, expected_lbas, lba_status_size, "incorrect lbas"); } static void test_directive_send(void) { + enum nvme_directive_send_doper doper = + NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_RESOURCE; + enum nvme_directive_dtype dtype = NVME_DIRECTIVE_DTYPE_STREAMS; __u8 expected_data[8], data[8]; + __u32 data_len = sizeof(expected_data); + __u16 dspec = 0x0; __u32 result = 0; - - struct nvme_directive_send_args args = { - .result = &result, - .data = &expected_data, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .doper = NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_RESOURCE, - .dtype = NVME_DIRECTIVE_DTYPE_STREAMS, - .cdw12 = 0xffff, - .data_len = sizeof(expected_data), - .dspec = 0x0, - }; - struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_directive_send, .nsid = TEST_NSID, - .cdw10 = args.data_len ? (args.data_len >> 2) - 1 : 0, - .cdw11 = args.doper | (args.dtype << 8) | (args.dspec << 16), - .cdw12 = args.cdw12, - .data_len = args.data_len, + .cdw10 = data_len ? (data_len >> 2) - 1 : 0, + .cdw11 = doper | (dtype << 8) | (dspec << 16), + .data_len = data_len, .in_data = &data, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); memcpy(&data, &expected_data, sizeof(expected_data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_directive_send(&args); + nvme_init_directive_send(&cmd, TEST_NSID, doper, dtype, dspec, + expected_data, data_len); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned wrong result"); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } @@ -491,7 +420,6 @@ static void test_directive_send(void) static void test_directive_send_id_endir(void) { struct nvme_id_directives expected_id, id; - struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_directive_send, .nsid = TEST_NSID, @@ -502,16 +430,17 @@ static void test_directive_send_id_endir(void) .data_len = sizeof(id), .in_data = &id, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); memcpy(&id, &expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_directive_send_id_endir(TEST_FD, TEST_NSID, true, - NVME_DIRECTIVE_DTYPE_STREAMS, &id); + nvme_init_directive_send_id_endir(&cmd, TEST_NSID, true, + NVME_DIRECTIVE_DTYPE_STREAMS, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect id"); } @@ -525,14 +454,15 @@ static void test_directive_send_stream_release_identifier(void) (NVME_DIRECTIVE_DTYPE_STREAMS << 8) | (stream_id << 16), }; - + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_directive_send_stream_release_identifier(TEST_FD, TEST_NSID, - stream_id); + nvme_init_directive_send_stream_release_identifier(&cmd, TEST_NSID, + stream_id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); } static void test_directive_send_stream_release_resource(void) @@ -543,50 +473,42 @@ static void test_directive_send_stream_release_resource(void) .cdw11 = NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_RESOURCE | (NVME_DIRECTIVE_DTYPE_STREAMS << 8), }; - + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_directive_send_stream_release_resource(TEST_FD, TEST_NSID); + nvme_init_directive_send_stream_release_resource(&cmd, TEST_NSID); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); } static void test_directive_recv(void) { - __u8 expected_data[8], data[8]; - __u32 result = 0; - - struct nvme_directive_recv_args args = { - .result = &result, - .data = &data, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .doper = NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM, - .dtype = NVME_DIRECTIVE_DTYPE_STREAMS, - .cdw12 = 0xffff, - .data_len = sizeof(data), - .dspec = 0x0, - }; - + enum nvme_directive_receive_doper doper = NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM; + enum nvme_directive_dtype dtype = NVME_DIRECTIVE_DTYPE_STREAMS; + __u8 expected_data[8], data[8]; + __u32 data_len = sizeof(data); + __u16 dspec = 0x0; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_directive_recv, .nsid = TEST_NSID, - .cdw10 = args.data_len ? (args.data_len >> 2) - 1 : 0, - .cdw11 = args.doper | (args.dtype << 8) | (args.dspec << 16), - .cdw12 = args.cdw12, + .cdw10 = data_len ? (data_len >> 2) - 1 : 0, + .cdw11 = doper | (dtype << 8) | (dspec << 16), .data_len = sizeof(expected_data), .out_data = &expected_data, }; - + struct nvme_passthru_cmd cmd; + uint32_t result = 0; int err; arbitrary(&expected_data, sizeof(expected_data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_directive_recv(&args); + nvme_init_directive_recv(&cmd, TEST_NSID, doper, dtype, dspec, + data, data_len); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned wrong result"); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } @@ -594,7 +516,6 @@ static void test_directive_recv(void) static void test_directive_recv_identify_parameters(void) { struct nvme_id_directives expected_id, id; - struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_directive_recv, .nsid = TEST_NSID, @@ -604,21 +525,21 @@ static void test_directive_recv_identify_parameters(void) .data_len = sizeof(expected_id), .out_data = &expected_id, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_id, sizeof(expected_id)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_directive_recv_identify_parameters(TEST_FD, TEST_NSID, &id); + nvme_init_directive_recv_identify_parameters(&cmd, TEST_NSID, &id); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); cmp(&id, &expected_id, sizeof(id), "incorrect id"); } static void test_directive_recv_stream_parameters(void) { struct nvme_streams_directive_params expected_params, params; - struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_directive_recv, .nsid = TEST_NSID, @@ -628,15 +549,15 @@ static void test_directive_recv_stream_parameters(void) .data_len = sizeof(expected_params), .out_data = &expected_params, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_params, sizeof(expected_params)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_directive_recv_stream_parameters(TEST_FD, TEST_NSID, - ¶ms); + nvme_init_directive_recv_stream_parameters(&cmd, TEST_NSID, ¶ms); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); cmp(¶ms, &expected_params, sizeof(params), "incorrect params"); } @@ -665,15 +586,16 @@ static void test_directive_recv_stream_status(void) .data_len = stream_status_size, .out_data = expected_status, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(expected_status, stream_status_size); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_directive_recv_stream_status(TEST_FD, TEST_NSID, nr_entries, - status); + nvme_init_directive_recv_stream_status(&cmd, TEST_NSID, nr_entries, + status); + err = nvme_submit_admin_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); cmp(status, expected_status, stream_status_size, "incorrect status"); } @@ -681,7 +603,6 @@ static void test_directive_recv_stream_allocate(void) { __u32 expected_result = 0x45, result = 0; __u16 nsr = 0x67; - struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_directive_recv, .nsid = TEST_NSID, @@ -690,170 +611,139 @@ static void test_directive_recv_stream_allocate(void) .cdw12 = nsr, .result = expected_result, }; - + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_directive_recv_stream_allocate(TEST_FD, TEST_NSID, nsr, - &result); + nvme_init_directive_recv_stream_allocate(&cmd, TEST_NSID, nsr); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == expected_result, "wrong result"); } -static void test_capacity_mgmt(void) +void test_capacity_mgmt(void) { __u32 expected_result = 0x45, result = 0; - - struct nvme_capacity_mgmt_args args = { - .result = &result, - .args_size = sizeof(args), - .fd = TEST_FD, - .cdw11 = 0x1234, - .cdw12 = 0x5678, - .element_id = 0x12, - .op = 0x3, - }; - + __u16 elid = 0x12; + __u64 cap = 0x0000567800001234; + __u8 op = 0x3; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_capacity_mgmt, .nsid = NVME_NSID_NONE, - .cdw10 = args.op | args.element_id << 16, - .cdw11 = args.cdw11, - .cdw12 = args.cdw12, + .cdw10 = op | elid << 16, + .cdw11 = cap & 0xffffffff, + .cdw12 = cap >> 32, .result = expected_result, }; - + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_capacity_mgmt(&args); + nvme_init_capacity_mgmt(&cmd, op, elid, cap); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == expected_result, "wrong result"); } static void test_lockdown(void) { __u32 expected_result = 0x45, result = 0; - - struct nvme_lockdown_args args = { - .result = &result, - .args_size = sizeof(args), - .fd = TEST_FD, - .scp = 0x2, - .prhbt = !!true, - .ifc = 0x1, - .ofi = 0x12, - .uuidx = 0x34, - }; - + __u8 prhbt = !!true; + __u8 uuidx = 0x34; + __u8 ofi = 0x12; + __u8 scp = 0x2; + __u8 ifc = 0x1; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_lockdown, - .cdw10 = args.ofi << 8 | (args.ifc & 0x3) << 5 | - (args.prhbt & 0x1) << 4 | (args.scp & 0xF), - .cdw14 = args.uuidx & 0x3F, + .cdw10 = ofi << 8 | (ifc & 0x3) << 5 | + (prhbt & 0x1) << 4 | (scp & 0xF), + .cdw14 = uuidx & 0x3F, .result = expected_result, }; - + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_lockdown(&args); + nvme_init_lockdown(&cmd, scp, prhbt, ifc, ofi, uuidx); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == expected_result, "wrong result"); } static void test_sanitize_nvm(void) { + enum nvme_sanitize_sanact sanact = + NVME_SANITIZE_SANACT_START_CRYPTO_ERASE; __u32 expected_result = 0x45, result = 0; - - struct nvme_sanitize_nvm_args args = { - .result = &result, - .args_size = sizeof(args), - .fd = TEST_FD, - .sanact = NVME_SANITIZE_SANACT_START_CRYPTO_ERASE, - .ovrpat = 0x101010, - .ause = true, - .owpass = 0x2, - .oipbp = false, - .nodas = true, - .emvs = false, - }; - + __u32 ovrpat = 0x101010; + bool oipbp = false; + __u8 owpass = 0x2; + bool ndas = true; + bool emvs = false; + bool ause = true; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_sanitize_nvm, - .cdw10 = args.sanact | (!!args.ause << 3) | (args.owpass << 4) | - (!!args.oipbp << 8) | (!!args.nodas << 9), - .cdw11 = args.ovrpat, + .cdw10 = sanact | (ause << 3) | (owpass << 4) | + (oipbp << 8) | (ndas << 9), + .cdw11 = ovrpat, .result = expected_result, }; - + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_sanitize_nvm(&args); + nvme_init_sanitize_nvm(&cmd, sanact, ause, owpass, oipbp, ndas, + emvs, ovrpat); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == expected_result, "wrong result"); } static void test_dev_self_test(void) { __u32 expected_result = 0x45, result = 0; - - struct nvme_dev_self_test_args args = { - .result = &result, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .stc = NVME_DST_STC_ABORT, - }; - struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_dev_self_test, - .nsid = args.nsid, - .cdw10 = args.stc, + .nsid = TEST_NSID, + .cdw10 = NVME_DST_STC_ABORT, .result = expected_result, }; - + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_dev_self_test(&args); + nvme_init_dev_self_test(&cmd, TEST_NSID, NVME_DST_STC_ABORT); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == expected_result, "wrong result"); } static void test_virtual_mgmt(void) { + enum nvme_virt_mgmt_act act = NVME_VIRT_MGMT_ACT_ASSIGN_SEC_CTRL; + enum nvme_virt_mgmt_rt rt = NVME_VIRT_MGMT_RT_VI_RESOURCE; __u32 expected_result = 0x45, result = 0; - - struct nvme_virtual_mgmt_args args = { - .result = &result, - .args_size = sizeof(args), - .fd = TEST_FD, - .act = NVME_VIRT_MGMT_ACT_ASSIGN_SEC_CTRL, - .rt = NVME_VIRT_MGMT_RT_VI_RESOURCE, - .cntlid = 0x0, - .nr = 0xff, - }; - + __u16 cntlid = 0x0; + __u16 nr = 0xff; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_virtual_mgmt, - .cdw10 = args.act | (args.rt << 8) | (args.cntlid << 16), - .cdw11 = args.nr, + .cdw10 = act | (rt << 8) | (cntlid << 16), + .cdw11 = nr, .result = expected_result, }; - + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_virtual_mgmt(&args); + nvme_init_virtual_mgmt(&cmd, act, rt, cntlid, nr); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == expected_result, "wrong result"); } @@ -867,99 +757,79 @@ static void test_flush(void) int err; set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_flush(TEST_FD, TEST_NSID); + err = nvme_flush(test_hdl, TEST_NSID); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); } static void test_read(void) { __u8 expected_data[512], data[512] = {}; __u32 result = 0; - - struct nvme_io_args args = { - .slba = 0xffffffffff, - .storage_tag = 0xef, - .result = &result, - .data = &data, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .reftag = 0xab, - .data_len = sizeof(data), - .nlb = 0x3, - .control = NVME_IO_FUA, - .apptag = 0x12, - .appmask = 0x34, - .dspec = 0x0, - .dsm = NVME_IO_DSM_LATENCY_LOW, - }; - + __u64 slba = 0xffffffffff; + __u16 nlb = 0x3; + __u16 control = NVME_IO_FUA; + __u8 dsm = NVME_IO_DSM_LATENCY_LOW; + __u16 apptag = 0x12; + __u16 appmask = 0x34; struct mock_cmd mock_io_cmd = { .opcode = nvme_cmd_read, .nsid = TEST_NSID, - .cdw10 = args.slba & 0xffffffff, - .cdw11 = args.slba >> 32, - .cdw12 = args.nlb | (args.control << 16), - .cdw13 = args.dsm | (args.dspec << 16), - .cdw15 = args.apptag | (args.appmask << 16), + .cdw10 = slba & 0xffffffff, + .cdw11 = slba >> 32, + .cdw12 = nlb | (control << 16), + .cdw13 = dsm, + .cdw15 = apptag | (appmask << 16), .data_len = sizeof(expected_data), .out_data = &expected_data, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_read(&args); + nvme_init_read(&cmd, TEST_NSID, slba, nlb, control, dsm, 0, + data, sizeof(data), NULL, 0); + nvme_init_app_tag((struct nvme_passthru_cmd64 *)&cmd, apptag, appmask); + err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } static void test_write(void) { - __u8 expected_data[512], data[512] = {}; + __u8 expected_data[512]; __u32 result = 0; - - struct nvme_io_args args = { - .slba = 0xfffffffabcde, - .storage_tag = 0xab, - .result = &result, - .data = &expected_data, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .reftag = 0xef, - .data_len = sizeof(expected_data), - .nlb = 0x5, - .control = NVME_IO_FUA, - .apptag = 0x59, - .appmask = 0x94, - .dspec = 0xa, - .dsm = NVME_IO_DSM_COMPRESSED, - }; - + __u64 slba = 0xfffffffabcde; + __u16 nlb = 0x5; + __u16 control = NVME_IO_FUA; + __u8 dsm = NVME_IO_DSM_COMPRESSED; + __u16 dspec = 0xa; + __u16 apptag = 0x59; + __u16 appmask = 0x94; struct mock_cmd mock_io_cmd = { .opcode = nvme_cmd_write, .nsid = TEST_NSID, - .cdw10 = args.slba & 0xffffffff, - .cdw11 = args.slba >> 32, - .cdw12 = args.nlb | (args.control << 16), - .cdw13 = args.dsm | (args.dspec << 16), - .cdw15 = args.apptag | (args.appmask << 16), - .data_len = sizeof(data), - .in_data = &data, + .cdw10 = slba & 0xffffffff, + .cdw11 = slba >> 32, + .cdw12 = nlb | (control << 16), + .cdw13 = dsm | (dspec << 16), + .cdw15 = apptag | (appmask << 16), + .data_len = sizeof(expected_data), + .in_data = &expected_data, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); - memcpy(&data, &expected_data, sizeof(expected_data)); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_write(&args); + nvme_init_write(&cmd, TEST_NSID, slba, nlb, control, dspec, dsm, 0, + expected_data, sizeof(expected_data), NULL, 0); + nvme_init_app_tag((struct nvme_passthru_cmd64 *)&cmd, apptag, appmask); + err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } @@ -967,188 +837,136 @@ static void test_compare(void) { __u8 expected_data[512], data[512] = {}; __u32 result = 0; - - struct nvme_io_args args = { - .slba = 0xabcde, - .storage_tag = 0xab, - .result = &result, - .data = &expected_data, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .reftag = 0xff, - .data_len = sizeof(expected_data), - .nlb = 0x0, - .control = NVME_IO_LR, - .apptag = 0x59, - .appmask = 0x94, - .dspec = 0xa, - .dsm = NVME_IO_DSM_COMPRESSED, - }; - + __u64 slba = 0xabcde; + __u16 nlb = 0x0; + __u16 control = NVME_IO_LR; + __u16 cev = 0; + __u16 apptag = 0x59; + __u16 appmask = 0x94; struct mock_cmd mock_io_cmd = { .opcode = nvme_cmd_compare, .nsid = TEST_NSID, - .cdw10 = args.slba & 0xffffffff, - .cdw11 = args.slba >> 32, - .cdw12 = args.nlb | (args.control << 16), - .cdw13 = args.dsm | (args.dspec << 16), - .cdw15 = args.apptag | (args.appmask << 16), - .data_len = sizeof(data), - .in_data = &data, + .cdw10 = slba & 0xffffffff, + .cdw11 = slba >> 32, + .cdw12 = nlb | (control << 16), + .cdw15 = apptag | (appmask << 16), + .data_len = sizeof(expected_data), + .in_data = &expected_data, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); memcpy(&data, &expected_data, sizeof(expected_data)); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_compare(&args); + nvme_init_compare(&cmd, TEST_NSID, slba, nlb, control, cev, data, + sizeof(data), NULL, 0); + nvme_init_app_tag((struct nvme_passthru_cmd64 *)&cmd, apptag, appmask); + err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } static void test_write_zeros(void) { - __u8 expected_data[512], data[512] = {}; __u32 result = 0; - - struct nvme_io_args args = { - .slba = 0x0, - .storage_tag = 0xab, - .result = &result, - .data = &expected_data, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .reftag = 0xff, - .data_len = sizeof(expected_data), - .nlb = 0xffff, - .control = NVME_IO_LR, - .apptag = 0xfa, - .appmask = 0x72, - .dspec = 0xbb, - .dsm = NVME_IO_DSM_FREQ_ONCE, - }; - + __u64 slba = 0x0; + __u16 nlb = 0xffff; + __u16 control = NVME_IO_LR; + __u8 dsm = NVME_IO_DSM_FREQ_ONCE; + __u16 cev = 0; + __u16 dspec = 0xbb; + __u16 apptag = 0xfa; + __u16 appmask = 0x72; struct mock_cmd mock_io_cmd = { .opcode = nvme_cmd_write_zeroes, .nsid = TEST_NSID, - .cdw10 = args.slba & 0xffffffff, - .cdw11 = args.slba >> 32, - .cdw12 = args.nlb | (args.control << 16), - .cdw13 = args.dsm | (args.dspec << 16), - .cdw15 = args.apptag | (args.appmask << 16), - .data_len = sizeof(data), - .in_data = &data, + .cdw10 = slba & 0xffffffff, + .cdw11 = slba >> 32, + .cdw12 = nlb | (control << 16), + .cdw13 = dsm | (dspec << 16), + .cdw15 = apptag | (appmask << 16), }; - + struct nvme_passthru_cmd cmd; int err; - arbitrary(&expected_data, sizeof(expected_data)); - memcpy(&data, &expected_data, sizeof(expected_data)); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_write_zeros(&args); + nvme_init_write_zeros(&cmd, TEST_NSID, slba, nlb, control, + dspec, dsm, cev); + nvme_init_app_tag((struct nvme_passthru_cmd64 *)&cmd, apptag, appmask); + err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } static void test_write_uncorrectable(void) { - __u8 expected_data[512], data[512] = {}; __u32 result = 0; - - struct nvme_io_args args = { - .slba = 0x0, - .storage_tag = 0x0, - .result = &result, - .data = &expected_data, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .reftag = 0x0, - .data_len = sizeof(expected_data), - .nlb = 0x0, - .control = 0x0, - .apptag = 0x0, - .appmask = 0x0, - .dspec = 0x0, - .dsm = 0x0, - }; - + __u64 slba = 0x0; + __u16 nlb = 0x0; + __u16 control = 0x0; + __u8 dsm = 0x0; + __u16 dspec = 0x0; + __u16 apptag = 0x0; + __u16 appmask = 0x0; struct mock_cmd mock_io_cmd = { .opcode = nvme_cmd_write_uncor, .nsid = TEST_NSID, - .cdw10 = args.slba & 0xffffffff, - .cdw11 = args.slba >> 32, - .cdw12 = args.nlb | (args.control << 16), - .cdw13 = args.dsm | (args.dspec << 16), - .cdw15 = args.apptag | (args.appmask << 16), - .data_len = sizeof(data), - .in_data = &data, + .cdw10 = slba & 0xffffffff, + .cdw11 = slba >> 32, + .cdw12 = nlb | (control << 16), + .cdw13 = dsm | (dspec << 16), + .cdw15 = apptag | (appmask << 16), }; - + struct nvme_passthru_cmd cmd; int err; - arbitrary(&expected_data, sizeof(expected_data)); - memcpy(&data, &expected_data, sizeof(expected_data)); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_write_uncorrectable(&args); + nvme_init_write_uncorrectable(&cmd, TEST_NSID, slba, nlb, + control, dspec); + nvme_init_app_tag((struct nvme_passthru_cmd64 *)&cmd, apptag, appmask); + err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } static void test_verify(void) { - __u8 expected_data[512], data[512] = {}; __u32 result = 0; - - struct nvme_io_args args = { - .slba = 0xffffffffffffffff, - .storage_tag = 0xffffffffffffffff, - .result = &result, - .data = &expected_data, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .reftag = 0xffffffff, - .data_len = sizeof(expected_data), - .nlb = 0xffff, - .control = 0xffff, - .apptag = 0xffff, - .appmask = 0xffff, - .dspec = 0xffff, - .dsm = 0xff, - }; - + __u64 slba = 0xffffffffffffffff; + __u16 nlb = 0xffff; + __u16 control = 0xffff; + __u16 cev = 0; + __u16 apptag = 0xffff; + __u16 appmask = 0xffff; struct mock_cmd mock_io_cmd = { .opcode = nvme_cmd_verify, .nsid = TEST_NSID, - .cdw10 = args.slba & 0xffffffff, - .cdw11 = args.slba >> 32, - .cdw12 = args.nlb | (args.control << 16), - .cdw13 = args.dsm | (args.dspec << 16), - .cdw15 = args.apptag | (args.appmask << 16), - .data_len = sizeof(data), - .in_data = &data, + .cdw10 = slba & 0xffffffff, + .cdw11 = slba >> 32, + .cdw12 = nlb | (control << 16), + .cdw13 = cev, + .cdw15 = apptag | (appmask << 16), }; - + struct nvme_passthru_cmd cmd; int err; - arbitrary(&expected_data, sizeof(expected_data)); - memcpy(&data, &expected_data, sizeof(expected_data)); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_verify(&args); + nvme_init_verify(&cmd, TEST_NSID, slba, nlb, control, cev, + NULL, 0, NULL, 0); + nvme_init_app_tag((struct nvme_passthru_cmd64 *)&cmd, apptag, appmask); + err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } static void test_dsm(void) { + struct nvme_passthru_cmd cmd; __u32 result = 0; __u16 nr_ranges = 0xab; int dsm_size = sizeof(struct nvme_dsm_range) * nr_ranges; @@ -1158,219 +976,174 @@ static void test_dsm(void) dsm = malloc(dsm_size); check(dsm, "dsm: ENOMEM"); - struct nvme_dsm_args args = { - .result = &result, - .dsm = dsm, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .attrs = NVME_DSMGMT_AD, - .nr_ranges = nr_ranges, - }; - struct mock_cmd mock_io_cmd = { .opcode = nvme_cmd_dsm, .nsid = TEST_NSID, - .cdw10 = args.nr_ranges - 1, - .cdw11 = args.attrs, + .cdw10 = nr_ranges - 1, + .cdw11 = NVME_DSMGMT_AD, .data_len = dsm_size, - .in_data = args.dsm, + .in_data = dsm, }; int err; arbitrary(dsm, dsm_size); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_dsm(&args); + nvme_init_dsm(&cmd, TEST_NSID, nr_ranges - 1, 0, 0, 1, dsm, dsm_size); + err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } static void test_copy(void) { + __u16 nr = 0x12, cev = 0, dspec = 0; + int copy_size = sizeof(struct nvme_copy_range) * nr, err; + bool prinfor = false, prinfow = false, stcw = false, + stcr = false, fua = false, lr = false; + __u8 cetype = 0, dtype = 0, desfmt = 0xf; + __u64 sdlba = 0xfffff; __u32 result = 0; - __u16 nr = 0x12; - int copy_size = sizeof(struct nvme_copy_range) * nr; _cleanup_free_ struct nvme_copy_range *copy = NULL; copy = malloc(copy_size); check(copy, "copy: ENOMEM"); - struct nvme_copy_args args = { - .sdlba = 0xfffff, - .result = &result, - .copy = copy, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .nr = nr, - .format = 0xf, - }; - struct mock_cmd mock_io_cmd = { .opcode = nvme_cmd_copy, .nsid = TEST_NSID, - .cdw10 = args.sdlba & 0xffffffff, - .cdw11 = args.sdlba >> 32, - .cdw12 = ((args.nr - 1) & 0xff) | ((args.format & 0xf) << 8) | - ((args.prinfor & 0xf) << 12) | - ((args.dtype & 0xf) << 20) | - ((args.prinfow & 0xf) << 26) | - ((args.fua & 0x1) << 30) | ((args.lr & 0x1) << 31), - .data_len = args.nr * sizeof(struct nvme_copy_range), - .in_data = args.copy, - }; - - int err; + .cdw10 = sdlba & 0xffffffff, + .cdw11 = sdlba >> 32, + .cdw12 = ((nr - 1) & 0xff) | ((desfmt & 0xf) << 8) | + ((prinfor & 0xf) << 12) | + ((dtype & 0xf) << 20) | + ((prinfow & 0xf) << 26) | + ((fua & 0x1) << 30) | ((lr & 0x1) << 31), + .data_len = nr * sizeof(struct nvme_copy_range), + .in_data = copy, + }; + struct nvme_passthru_cmd cmd; set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_copy(&args); + nvme_init_copy(&cmd, TEST_NSID, sdlba, nr, desfmt, + prinfor, prinfow, cetype, dtype, stcw, stcr, + fua, lr, cev, dspec, (void *)copy); + err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } static void test_resv_acquire(void) { + enum nvme_resv_rtype rtype = NVME_RESERVATION_RTYPE_EAAR; + enum nvme_resv_racqa racqa = NVME_RESERVATION_RACQA_PREEMPT; + __le64 expected_payload[2] = { htole64(1), htole64(2) }; + __le64 payload[2]; + bool iekey = true; __u32 result = 0; - - struct nvme_resv_acquire_args args = { - .crkey = 0, - .nrkey = 0, - .result = &result, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .rtype = NVME_RESERVATION_RTYPE_EAAR, - .racqa = NVME_RESERVATION_RACQA_PREEMPT, - .iekey = true, - }; - - __le64 payload[2] = { 0 }; - struct mock_cmd mock_io_cmd = { .opcode = nvme_cmd_resv_acquire, .nsid = TEST_NSID, - .cdw10 = (args.racqa & 0x7) | (args.iekey ? 1 << 3 : 0) | - (args.rtype << 8), - .data_len = sizeof(payload), - .in_data = payload, + .cdw10 = (racqa & 0x7) | (iekey ? 1 << 3 : 0) | + (rtype << 8), + .data_len = sizeof(expected_payload), + .in_data = expected_payload, }; - + struct nvme_passthru_cmd cmd; int err; set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_resv_acquire(&args); + nvme_init_resv_acquire(&cmd, TEST_NSID, racqa, iekey, false, rtype, + 1, 2, payload); + err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } static void test_resv_register(void) { + enum nvme_resv_rrega rrega = NVME_RESERVATION_RREGA_UNREGISTER_KEY; + enum nvme_resv_cptpl cptpl = NVME_RESERVATION_CPTPL_PERSIST; + __le64 expected_payload[2] = { 0xffffffffffffffff, 0 }; + __le64 payload[2]; + bool iekey = true; __u32 result = 0; - - struct nvme_resv_register_args args = { - .crkey = 0xffffffffffffffff, - .nrkey = 0, - .result = &result, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .rrega = NVME_RESERVATION_RREGA_UNREGISTER_KEY, - .cptpl = NVME_RESERVATION_CPTPL_PERSIST, - .iekey = true, - }; - - __le64 payload[2] = { 0xffffffffffffffff, 0 }; - struct mock_cmd mock_io_cmd = { .opcode = nvme_cmd_resv_register, .nsid = TEST_NSID, - .cdw10 = (args.rrega & 0x7) | (args.iekey ? 1 << 3 : 0) | - (args.cptpl << 30), - .data_len = sizeof(payload), - .in_data = payload, + .cdw10 = (rrega & 0x7) | (iekey ? 1 << 3 : 0) | + (cptpl << 30), + .data_len = sizeof(expected_payload), + .in_data = expected_payload, }; - + struct nvme_passthru_cmd cmd; int err; set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_resv_register(&args); + nvme_init_resv_register(&cmd, TEST_NSID, rrega, iekey, false, cptpl, + 0xffffffffffffffff, 0, payload); + err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } static void test_resv_release(void) { + enum nvme_resv_rtype rtype = NVME_RESERVATION_RTYPE_WE; + enum nvme_resv_rrela rrela = NVME_RESERVATION_RRELA_RELEASE; + __le64 expected_payload[1] = { 0xffffffffffffffff }; + __le64 payload[1]; + bool iekey = true; __u32 result = 0; - - struct nvme_resv_release_args args = { - .crkey = 0xffffffffffffffff, - .result = &result, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .rtype = NVME_RESERVATION_RTYPE_WE, - .rrela = NVME_RESERVATION_RRELA_RELEASE, - .iekey = true, - }; - - __le64 payload[1] = { 0xffffffffffffffff }; - struct mock_cmd mock_io_cmd = { .opcode = nvme_cmd_resv_release, .nsid = TEST_NSID, - .cdw10 = (args.rrela & 0x7) | (args.iekey ? 1 << 3 : 0) | - (args.rtype << 8), - .data_len = sizeof(payload), - .in_data = payload, + .cdw10 = (rrela & 0x7) | (iekey ? 1 << 3 : 0) | + (rtype << 8), + .data_len = sizeof(expected_payload), + .in_data = expected_payload, }; - + struct nvme_passthru_cmd cmd; int err; set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_resv_release(&args); + nvme_init_resv_release(&cmd, TEST_NSID, rrela, iekey, false, rtype, + 0xffffffffffffffff, payload); + err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } static void test_resv_report(void) { - __u32 result = 0; - struct nvme_resv_status expected_status, status = {}; - - struct nvme_resv_report_args args = { - .result = &result, - .report = &status, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .len = sizeof(status), - .eds = false, - }; - + __u32 len = sizeof(status); + __u32 result = 0; + bool eds = false; + bool disnsrs = true; struct mock_cmd mock_io_cmd = { .opcode = nvme_cmd_resv_report, .nsid = TEST_NSID, - .cdw10 = (args.len >> 2) - 1, - .cdw11 = args.eds ? 1 : 0, - .data_len = args.len, + .cdw10 = (len >> 2) - 1, + .cdw11 = eds | disnsrs << 1, + .data_len = len, .out_data = &expected_status, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_status, sizeof(expected_status)); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_resv_report(&args); + nvme_init_resv_report(&cmd, TEST_NSID, eds, disnsrs, &status, len); + err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); cmp(&status, &expected_status, sizeof(status), "incorrect status"); } @@ -1378,64 +1151,52 @@ static void test_resv_report(void) static void test_io_mgmt_recv(void) { __u8 expected_data[8], data[8] = {}; - struct nvme_io_mgmt_recv_args args = { - .data = &data, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .data_len = sizeof(data), - .mos = 0x1, - .mo = 0x2, - }; - + __u32 data_len = sizeof(data); + __u16 mos = 0x1; + __u8 mo = 0x2; struct mock_cmd mock_io_cmd = { .opcode = nvme_cmd_io_mgmt_recv, .nsid = TEST_NSID, - .cdw10 = args.mo | (args.mos << 16), - .cdw11 = (args.data_len >> 2) - 1, - .data_len = args.data_len, + .cdw10 = mo | (mos << 16), + .cdw11 = (data_len >> 2) - 1, + .data_len = data_len, .out_data = &expected_data, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_io_mgmt_recv(&args); + nvme_init_io_mgmt_recv(&cmd, TEST_NSID, mo, mos, data, data_len); + err = nvme_submit_io_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } static void test_io_mgmt_send(void) { __u8 expected_data[8], data[8] = {}; - struct nvme_io_mgmt_send_args args = { - .data = &expected_data, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .data_len = sizeof(expected_data), - .mos = 0x1, - .mo = 0x2, - }; - + __u32 data_len = sizeof(data); + __u16 mos = 0x1; + __u8 mo = 0x2; struct mock_cmd mock_io_cmd = { .opcode = nvme_cmd_io_mgmt_send, .nsid = TEST_NSID, - .cdw10 = args.mo | (args.mos << 16), - .data_len = args.data_len, - .in_data = &data, + .cdw10 = mo | (mos << 16), + .data_len = data_len, + .in_data = &expected_data, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); memcpy(&data, &expected_data, sizeof(expected_data)); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_io_mgmt_send(&args); + nvme_init_io_mgmt_send(&cmd, TEST_NSID, mo, mos, data, data_len); + err = nvme_submit_io_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } @@ -1451,15 +1212,16 @@ static void test_fdp_reclaim_unit_handle_status(void) .data_len = data_len, .out_data = &expected_data, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_fdp_reclaim_unit_handle_status(TEST_FD, TEST_NSID, data_len, - &data); + nvme_init_fdp_reclaim_unit_handle_status(&cmd, TEST_NSID, + &data, data_len); + err = nvme_submit_io_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } @@ -1474,198 +1236,169 @@ static void test_fdp_reclaim_unit_handle_update(void) .data_len = npids * sizeof(__u16), .in_data = &pids, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&pids, sizeof(pids)); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_fdp_reclaim_unit_handle_update(TEST_FD, TEST_NSID, npids, - &pids); + nvme_init_fdp_reclaim_unit_handle_update(&cmd, TEST_NSID, &pids, npids); + err = nvme_submit_io_passthru(test_hdl, &cmd, NULL); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); } static void test_dim_send(void) { - __u32 result = 0; __u8 expected_data[8], data[8] = {}; - struct nvme_dim_args args = { - .result = 0, - .data = &data, - .args_size = sizeof(args), - .fd = TEST_FD, - .data_len = sizeof(data), - .tas = 0xf, - }; - + __u32 data_len = sizeof(data); + __u32 result = 0; + __u8 tas = 0xf; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_discovery_info_mgmt, - .cdw10 = args.tas, - .data_len = args.data_len, + .cdw10 = tas, + .data_len =data_len, .in_data = &expected_data, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); memcpy(&data, &expected_data, sizeof(expected_data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_dim_send(&args); + nvme_init_dim_send(&cmd, tas, data, data_len); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } -static void test_lm_cdq(void) +static void test_lm_cdq_delete(void) { __u32 result = 0; __u8 expected_data[8], data[8] = {}; - struct nvme_lm_cdq_args args = { - .result = 0, - .data = &data, - .args_size = sizeof(args), - .fd = TEST_FD, - .mos = 0x1, - .cntlid = 0x2, - .cdqid = 0x3, - .sel = NVME_LM_SEL_DELETE_CDQ, - .sz = 0x4, - }; - + __u16 mos = 0x1; + __u16 cdqid = 0x3; + __u8 sel = NVME_LM_SEL_DELETE_CDQ; + __u32 sz = 0; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_ctrl_data_queue, - .cdw10 = args.sel | (args.mos << 16), - .cdw11 = args.cdqid, - .cdw12 = args.sz, + .cdw10 = sel | (mos << 16), + .cdw11 = cdqid, + .cdw12 = sz, .data_len = 0, .in_data = &expected_data, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); memcpy(&data, &expected_data, sizeof(expected_data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_lm_cdq(&args); + nvme_init_lm_cdq_delete(&cmd, mos, cdqid); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } static void test_lm_track_send(void) { + __u8 sel = NVME_LM_SEL_DELETE_CDQ; + __u16 cdqid = 0x3; __u32 result = 0; - struct nvme_lm_track_send_args args = { - .result = 0, - .args_size = sizeof(args), - .fd = TEST_FD, - .mos = 0x1, - .cdqid = 0x3, - .sel = NVME_LM_SEL_DELETE_CDQ, - }; - + __u16 mos = 0x1; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_track_send, - .cdw10 = args.sel | (args.mos << 16), - .cdw11 = args.cdqid, + .cdw10 = sel | (mos << 16), + .cdw11 = cdqid, }; - + struct nvme_passthru_cmd cmd; int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_lm_track_send(&args); + nvme_init_lm_track_send(&cmd, sel, mos, cdqid); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); } static void test_lm_migration_send(void) { - __u32 result = 0; __u32 expected_data[8], data[8] = {}; - struct nvme_lm_migration_send_args args = { - .offset = 0xffffffffff, - .result = 0, - .data = &expected_data, - .args_size = sizeof(args), - .fd = TEST_FD, - .numd = 8 - 1, - .mos = 0x1, - .cntlid = 0x2, - .csuuidi = 0x3, - .sel = NVME_LM_SEL_RESUME, - .uidx = 0x4, - .stype = 0x5, - .seqind = 0x6, - .csvi = 0x7, - .dudmq = true, - }; - + __u8 sel = NVME_LM_SEL_RESUME; + __u64 offset = 0xffffffffff; + __u32 numd = 8; + __u16 cntlid = 0x2; + __u32 result = 0; + __u16 mos = 0x1; + __u8 uidx = 0x4; + __u8 stype = 0x1; + __u8 csvi = 0x2; + __u16 csuuidi = 0x13; + bool dudmq = false; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_migration_send, - .cdw10 = args.sel | (args.mos << 16), - .cdw11 = args.cntlid, - .cdw12 = (__u32)args.offset, - .cdw13 = (__u32)(args.offset >> 32), - .cdw14 = args.uidx, - .cdw15 = args.numd, - .data_len = args.numd << 2, - .in_data = &data, + .cdw10 = sel | (mos << 16), + .cdw11 = cntlid, + .cdw12 = (__u32)offset, + .cdw13 = (__u32)(offset >> 32), + .cdw14 = uidx, + .cdw15 = numd, + .data_len = numd << 2, + .in_data = &expected_data, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); memcpy(&data, &expected_data, sizeof(expected_data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_lm_migration_send(&args); + nvme_init_lm_migration_send(&cmd, sel, mos, cntlid, stype, dudmq, + csvi, csuuidi, offset, uidx, &data, sizeof(data)); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } static void test_lm_migration_recv(void) { - __u32 result = 0; + __u8 sel = NVME_LM_SEL_GET_CONTROLLER_STATE; __u32 expected_data[8], data[8] = {}; - struct nvme_lm_migration_recv_args args = { - .offset = 0xffffffffff, - .result = 0, - .data = &data, - .args_size = sizeof(args), - .fd = TEST_FD, - .numd = 8 - 1, - .mos = 0x1, - .cntlid = 0x2, - .csuuidi = 0x3, - .sel = NVME_LM_SEL_GET_CONTROLLER_STATE, - .uidx = 0x4, - .csuidxp = 0x5, - }; - + __u64 offset = 0xffffffffff; + __u16 csuuidi = 0x3; + __u32 numd = 8 - 1; + __u16 cntlid = 0x2; + __u8 csuidxp = 0x5; + __u32 result = 0; + __u16 mos = 0x1; + __u8 uidx = 0x4; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_migration_receive, - .cdw10 = args.sel | (args.mos << 16), - .cdw11 = args.cntlid | (args.csuuidi << 16) | - (args.csuidxp << 24), - .cdw12 = (__u32)args.offset, - .cdw13 = (__u32)(args.offset >> 32), - .cdw14 = args.uidx, - .cdw15 = args.numd, - .data_len = (args.numd + 1) << 2, + .cdw10 = sel | (mos << 16), + .cdw11 = cntlid | (csuuidi << 16) | + (csuidxp << 24), + .cdw12 = (__u32)offset, + .cdw13 = (__u32)(offset >> 32), + .cdw14 = uidx, + .cdw15 = numd, + .data_len = (numd + 1) << 2, .out_data = &expected_data, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_lm_migration_recv(&args); + nvme_init_lm_migration_recv(&cmd, offset, mos, cntlid, csuuidi, sel, + uidx, csuidxp, data, sizeof(data)); + err = nvme_submit_admin_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } @@ -1682,7 +1415,13 @@ static void run_test(const char *test_name, void (*test_fn)(void)) int main(void) { + struct nvme_global_ctx *ctx = + nvme_create_global_ctx(stdout, DEFAULT_LOGLEVEL); + set_mock_fd(TEST_FD); + check(!nvme_open(ctx, "NVME_TEST_FD", &test_hdl), + "opening test link failed"); + RUN_TEST(format_nvm); RUN_TEST(ns_mgmt); RUN_TEST(ns_mgmt_create); @@ -1729,8 +1468,10 @@ int main(void) RUN_TEST(fdp_reclaim_unit_handle_status); RUN_TEST(fdp_reclaim_unit_handle_update); RUN_TEST(dim_send); - RUN_TEST(lm_cdq); + RUN_TEST(lm_cdq_delete); RUN_TEST(lm_track_send); RUN_TEST(lm_migration_send); RUN_TEST(lm_migration_recv); + + nvme_free_global_ctx(ctx); } diff --git a/libnvme/test/ioctl/zns.c b/libnvme/test/ioctl/zns.c index 204093535b..1697ad377f 100644 --- a/libnvme/test/ioctl/zns.c +++ b/libnvme/test/ioctl/zns.c @@ -4,7 +4,6 @@ #include "mock.h" #include "util.h" -#include #include #include @@ -12,166 +11,141 @@ #define TEST_NSID 0x12345678 #define TEST_SLBA 0xffffffff12345678 +static struct nvme_transport_handle *test_hdl; + static void test_zns_append(void) { __u8 expected_data[8], data[8] = {}; + __u64 zslba = TEST_SLBA; + __u16 control = 0xcd; + __u16 cev = 0; + __u16 dspec = 0; + __u16 lbatm = 0x98; + __u16 lbat = 0xef; + __u16 nlb = 0xab; __u64 result = 0; - struct nvme_zns_append_args args = { - .zslba = TEST_SLBA, - .result = &result, - .data = &data, - .args_size = sizeof(args), - .fd = TEST_FD, - .nsid = TEST_NSID, - .data_len = sizeof(data), - .nlb = 0xab, - .control = 0xcd, - .lbat = 0xef, - .lbatm = 0x98, - .ilbrt_u64 = 0x76, - }; - + bool elbas = true; + __u8 sts = 48; + __u8 pif = NVME_NVM_PIF_32B_GUARD; + __u64 storage_tag = 0x12; + __u64 reftag = 0x1234; struct mock_cmd mock_io_cmd = { .opcode = nvme_zns_cmd_append, .nsid = TEST_NSID, - .cdw3 = (args.ilbrt_u64 >> 32) & 0xffffffff, - .cdw10 = args.zslba & 0xffffffff, - .cdw11 = args.zslba >> 32, - .cdw12 = args.nlb | (args.control << 16), - .cdw14 = args.ilbrt_u64 & 0xffffffff, - .cdw15 = args.lbat | (args.lbatm << 16), + .cdw3 = storage_tag, + .cdw10 = zslba & 0xffffffff, + .cdw11 = zslba >> 32, + .cdw12 = nlb | (control << 16), + .cdw14 = reftag, + .cdw15 = lbat | (lbatm << 16), .data_len = sizeof(expected_data), .out_data = &expected_data, }; - + struct nvme_passthru_cmd64 cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_zns_append(&args); + nvme_init_zns_append(&cmd, TEST_NSID, zslba, nlb, control, cev, dspec, + data, sizeof(data), NULL, 0); + if (elbas) + nvme_init_var_size_tags(&cmd, pif, sts, reftag, storage_tag); + nvme_init_app_tag(&cmd, lbat, lbatm); + err = nvme_submit_io_passthru64(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "wrong result"); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } static void test_zns_report_zones(void) { + enum nvme_zns_report_options opts = NVME_ZNS_ZRAS_REPORT_CLOSED; __u8 expected_data[8], data[8] = {}; - __u32 result = 0; - uint32_t timeout = 1234; bool extended = true; bool partial = true; - enum nvme_zns_report_options opts = NVME_ZNS_ZRAS_REPORT_CLOSED; - + __u32 result = 0; struct mock_cmd mock_io_cmd = { .opcode = nvme_zns_cmd_mgmt_recv, .nsid = TEST_NSID, .cdw10 = TEST_SLBA & 0xffffffff, .cdw11 = TEST_SLBA >> 32, .cdw12 = (sizeof(expected_data) >> 2) - 1, - .cdw13 = (!!extended << 0) | ((__u16)opts << 8) | - (!!partial << 16), + .cdw13 = (extended << 0) | ((__u16)opts << 8) | (partial << 16), .data_len = sizeof(expected_data), .out_data = &expected_data, - .timeout_ms = timeout, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_zns_report_zones(TEST_FD, TEST_NSID, TEST_SLBA, opts, - extended, partial, sizeof(data), &data, - timeout, &result); + nvme_init_zns_report_zones(&cmd, TEST_NSID, TEST_SLBA, opts, + extended, partial, &data, sizeof(data)); + err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } static void test_zns_mgmt_send(void) { + enum nvme_zns_send_action zsa = NVME_ZNS_ZSA_OPEN; __u8 expected_data[8], data[8] = {}; + __u64 slba = TEST_SLBA; + bool select_all = true; + __u8 zsaso = 0x1; __u32 result = 0; - uint32_t timeout = 1234; - - struct nvme_zns_mgmt_send_args args = { - .slba = TEST_SLBA, - .result = &result, - .data = data, - .args_size = sizeof(args), - .fd = TEST_FD, - .timeout = timeout, - .nsid = TEST_NSID, - .zsa = NVME_ZNS_ZSA_OPEN, - .data_len = sizeof(data), - .select_all = true, - .zsaso = !!true, - }; - struct mock_cmd mock_io_cmd = { .opcode = nvme_zns_cmd_mgmt_send, .nsid = TEST_NSID, - .cdw10 = args.slba & 0xffffffff, - .cdw11 = args.slba >> 32, - .cdw13 = (args.zsaso << 9) | (!!args.select_all << 8) | - (args.zsa << 0), + .cdw10 = slba & 0xffffffff, + .cdw11 = slba >> 32, + .cdw13 = (zsaso << 9) | (select_all << 8) | + (zsa << 0), .data_len = sizeof(expected_data), .out_data = &expected_data, - .timeout_ms = timeout, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_zns_mgmt_send(&args); + nvme_init_zns_mgmt_send(&cmd, TEST_NSID, slba, zsa, select_all, zsaso, + false, data, sizeof(data)); + err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } static void test_zns_mgmt_recv(void) { + enum nvme_zns_recv_action zra = NVME_ZNS_ZRA_REPORT_ZONES; __u8 expected_data[8], data[8] = {}; + __u16 zrasf = (__u16)NVME_ZNS_ZRAS_REPORT_ALL; + bool zras_feat = false; __u32 result = 0; - uint32_t timeout = 1234; - bool partial = false; - - struct nvme_zns_mgmt_recv_args args = { - .slba = 0, - .result = &result, - .data = data, - .args_size = sizeof(args), - .fd = TEST_FD, - .timeout = timeout, - .nsid = TEST_NSID, - .zra = NVME_ZNS_ZRA_REPORT_ZONES, - .data_len = sizeof(data), - .zrasf = (__u16)NVME_ZNS_ZRAS_REPORT_ALL, - .zras_feat = partial, - }; - struct mock_cmd mock_io_cmd = { .opcode = nvme_zns_cmd_mgmt_recv, .nsid = TEST_NSID, .cdw12 = (sizeof(expected_data) >> 2) - 1, - .cdw13 = (!!args.zra << 0) | ((__u16)args.zrasf << 8) | - (!!args.zras_feat << 16), + .cdw13 = (zra << 0) | (zrasf << 8) | (zras_feat << 16), .data_len = sizeof(expected_data), .out_data = &expected_data, - .timeout_ms = timeout, }; - + struct nvme_passthru_cmd cmd; int err; arbitrary(&expected_data, sizeof(expected_data)); set_mock_io_cmds(&mock_io_cmd, 1); - err = nvme_zns_mgmt_recv(&args); + nvme_init_zns_mgmt_recv(&cmd, TEST_NSID, 0, zra, zrasf, zras_feat, + data, sizeof(data)); + err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); - check(err == 0, "returned error %d, errno %m", err); + check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); cmp(&data, &expected_data, sizeof(data), "incorrect data"); } @@ -188,9 +162,17 @@ static void run_test(const char *test_name, void (*test_fn)(void)) int main(void) { + struct nvme_global_ctx *ctx = + nvme_create_global_ctx(stdout, DEFAULT_LOGLEVEL); + set_mock_fd(TEST_FD); + check(!nvme_open(ctx, "NVME_TEST_FD", &test_hdl), + "opening test link failed"); + RUN_TEST(zns_append); RUN_TEST(zns_report_zones); RUN_TEST(zns_mgmt_send); RUN_TEST(zns_mgmt_recv); + + nvme_free_global_ctx(ctx); } diff --git a/libnvme/test/meson.build b/libnvme/test/meson.build index 464d1ba105..4d2e6466b7 100644 --- a/libnvme/test/meson.build +++ b/libnvme/test/meson.build @@ -53,7 +53,7 @@ zns = executable( mi = executable( 'test-mi', ['mi.c', 'utils.c'], - dependencies: libnvme_mi_test_dep, + dependencies: libnvme_test_dep, include_directories: [incdir, internal_incdir] ) @@ -62,7 +62,7 @@ test('mi', mi) mi_mctp = executable( 'test-mi-mctp', ['mi-mctp.c', 'utils.c'], - dependencies: libnvme_mi_test_dep, + dependencies: libnvme_test_dep, include_directories: [incdir, internal_incdir], ) @@ -110,6 +110,7 @@ if conf.get('HAVE_NETDB') test_util = executable( 'test-util', ['test-util.c'], + dependencies: libnvme_dep, include_directories: [incdir, internal_incdir] ) test('util', test_util) diff --git a/libnvme/test/mi-mctp.c b/libnvme/test/mi-mctp.c index 2a6e1f04c5..7571abd6e9 100644 --- a/libnvme/test/mi-mctp.c +++ b/libnvme/test/mi-mctp.c @@ -19,6 +19,7 @@ #include #include "libnvme-mi.h" +#include "nvme/linux.h" #include "nvme/private.h" #include "utils.h" @@ -410,19 +411,21 @@ static void test_mi_resp_unaligned_expected(nvme_mi_ep_t ep, static void test_admin_resp_err(nvme_mi_ep_t ep, struct test_peer *peer) { + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; struct nvme_id_ctrl id; - nvme_mi_ctrl_t ctrl; int rc; - ctrl = nvme_mi_init_ctrl(ep, 1); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 1); + assert(hdl); /* Simple error response, will be shorter than the expected Admin * command response header. */ peer->tx_buf[4] = 0x02; /* internal error */ peer->tx_buf_len = 8; - rc = nvme_mi_admin_identify_ctrl(ctrl, &id); + nvme_init_identify_ctrl(&cmd, &id); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(nvme_status_get_type(rc) == NVME_STATUS_TYPE_MI); assert(nvme_status_get_value(rc) == NVME_MI_RESP_INTERNAL_ERR); } @@ -435,24 +438,26 @@ static void test_admin_resp_err(nvme_mi_ep_t ep, struct test_peer *peer) */ static void test_admin_resp_sizes(nvme_mi_ep_t ep, struct test_peer *peer) { + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; struct nvme_id_ctrl id; - nvme_mi_ctrl_t ctrl; unsigned int i; int rc; - ctrl = nvme_mi_init_ctrl(ep, 1); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 1); + assert(hdl); peer->tx_buf[4] = 0x02; /* internal error */ for (i = 8; i <= 4096 + 8; i+=4) { peer->tx_buf_len = i; - rc = nvme_mi_admin_identify_ctrl(ctrl, &id); + nvme_init_identify_ctrl(&cmd, &id); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(nvme_status_get_type(rc) == NVME_STATUS_TYPE_MI); assert(nvme_status_get_value(rc) == NVME_MI_RESP_INTERNAL_ERR); } - nvme_mi_close_ctrl(ctrl); + nvme_close(hdl); } /* test: timeout value passed to poll */ @@ -556,9 +561,10 @@ static void test_mpr_mi(nvme_mi_ep_t ep, struct test_peer *peer) static void test_mpr_admin(nvme_mi_ep_t ep, struct test_peer *peer) { + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; struct mpr_tx_info tx_info; struct nvme_id_ctrl id; - nvme_mi_ctrl_t ctrl; int rc; tx_info.msg_no = 1; @@ -568,12 +574,13 @@ static void test_mpr_admin(nvme_mi_ep_t ep, struct test_peer *peer) peer->tx_fn = tx_mpr; peer->tx_data = &tx_info; - ctrl = nvme_mi_init_ctrl(ep, 1); + hdl = nvme_mi_init_transport_handle(ep, 1); - rc = nvme_mi_admin_identify_ctrl(ctrl, &id); + nvme_init_identify_ctrl(&cmd, &id); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(rc == 0); - nvme_mi_close_ctrl(ctrl); + nvme_close(hdl); } /* We have seen drives that send a MPR response as a full Admin message, @@ -581,9 +588,10 @@ static void test_mpr_admin(nvme_mi_ep_t ep, struct test_peer *peer) */ static void test_mpr_admin_quirked(nvme_mi_ep_t ep, struct test_peer *peer) { + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; struct mpr_tx_info tx_info; struct nvme_id_ctrl id; - nvme_mi_ctrl_t ctrl; int rc; tx_info.msg_no = 1; @@ -593,12 +601,13 @@ static void test_mpr_admin_quirked(nvme_mi_ep_t ep, struct test_peer *peer) peer->tx_fn = tx_mpr; peer->tx_data = &tx_info; - ctrl = nvme_mi_init_ctrl(ep, 1); + hdl = nvme_mi_init_transport_handle(ep, 1); - rc = nvme_mi_admin_identify_ctrl(ctrl, &id); + nvme_init_identify_ctrl(&cmd, &id); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(rc == 0); - nvme_mi_close_ctrl(ctrl); + nvme_close(hdl); } /* helpers for the MPR + poll tests */ @@ -1173,16 +1182,14 @@ static void test_mi_aem_ep_based_failure_helper(nvme_mi_ep_t ep, case AEM_FC_BAD_OCC_RSP_TOTAL_LEN_SYNC: case AEM_FC_BAD_OCC_RSP_BUFFER_LEN_SYNC: //These all should fail before processing - assert(nvme_mi_aem_enable(ep, &config, &fn_data) == -1); - assert(errno == EPROTO); + assert(nvme_mi_aem_enable(ep, &config, &fn_data) == -EPROTO); break; case AEM_FC_BAD_OCC_RSP_HDR_LEN_AEM: case AEM_FC_BAD_OCC_RSP_TOTAL_LEN_AEM: case AEM_FC_BAD_OCC_RSP_BUFFER_LEN_AEM: //These should fail on the processing assert(nvme_mi_aem_enable(ep, &config, &fn_data) == 0); - assert(nvme_mi_aem_process(ep, &fn_data) == -1); - assert(errno == EPROTO); + assert(nvme_mi_aem_process(ep, &fn_data) == -EPROTO); break; default: assert(false);//Unexpected @@ -1443,7 +1450,7 @@ static void run_test(struct test *test, FILE *logfd, nvme_mi_ep_t ep, int main(void) { - nvme_root_t root; + struct nvme_global_ctx *ctx; nvme_mi_ep_t ep; unsigned int i; FILE *fd; @@ -1452,10 +1459,10 @@ int main(void) __nvme_mi_mctp_set_ops(&ops); - root = nvme_mi_create_root(fd, DEFAULT_LOGLEVEL); - assert(root); + ctx = nvme_mi_create_global_ctx(fd, DEFAULT_LOGLEVEL); + assert(ctx); - ep = nvme_mi_open_mctp(root, 0, 0); + ep = nvme_mi_open_mctp(ctx, 0, 0); assert(ep); for (i = 0; i < ARRAY_SIZE(tests); i++) { @@ -1464,7 +1471,7 @@ int main(void) } nvme_mi_close(ep); - nvme_mi_free_root(root); + nvme_mi_free_global_ctx(ctx); test_close_log(fd); diff --git a/libnvme/test/mi.c b/libnvme/test/mi.c index e80bd1be5c..95b648fe4c 100644 --- a/libnvme/test/mi.c +++ b/libnvme/test/mi.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-2.1-or-later -/** +/* * This file is part of libnvme. * Copyright (c) 2022 Code Construct */ @@ -14,6 +14,7 @@ #include /* we define a custom transport, so need the internal headers */ +#include "nvme/linux.h" #include "nvme/private.h" #include "libnvme-mi.h" @@ -111,12 +112,12 @@ static void test_set_transport_callback(nvme_mi_ep_t ep, test_submit_cb cb, tpd->submit_cb_data = data; } -nvme_mi_ep_t nvme_mi_open_test(nvme_root_t root) +nvme_mi_ep_t nvme_mi_open_test(struct nvme_global_ctx *ctx) { struct test_transport_data *tpd; struct nvme_mi_ep *ep; - ep = nvme_mi_init_ep(root); + ep = nvme_mi_init_ep(ctx); assert(ep); /* preempt the quirk probe to avoid clutter */ @@ -134,12 +135,12 @@ nvme_mi_ep_t nvme_mi_open_test(nvme_root_t root) return ep; } -unsigned int count_root_eps(nvme_root_t root) +unsigned int count_root_eps(struct nvme_global_ctx *ctx) { unsigned int i = 0; nvme_mi_ep_t ep; - nvme_mi_for_each_endpoint(root, ep) + nvme_mi_for_each_endpoint(ctx, ep) i++; return i; @@ -149,28 +150,28 @@ unsigned int count_root_eps(nvme_root_t root) * creation/destruction */ static void test_endpoint_lifetime(nvme_mi_ep_t ep) { - nvme_root_t root = ep->root; + struct nvme_global_ctx *ctx= ep->ctx; unsigned int count; nvme_mi_ep_t ep2; - count = count_root_eps(root); + count = count_root_eps(ctx); assert(count == 1); - ep2 = nvme_mi_open_test(root); - count = count_root_eps(root); + ep2 = nvme_mi_open_test(ctx); + count = count_root_eps(ctx); assert(count == 2); nvme_mi_close(ep2); - count = count_root_eps(root); + count = count_root_eps(ctx); assert(count == 1); } unsigned int count_ep_controllers(nvme_mi_ep_t ep) { + struct nvme_transport_handle *hdl; unsigned int i = 0; - nvme_mi_ctrl_t ctrl; - nvme_mi_for_each_ctrl(ep, ctrl) + nvme_mi_for_each_transport_handle(ep, hdl) i++; return i; @@ -180,7 +181,7 @@ unsigned int count_ep_controllers(nvme_mi_ep_t ep) * creation/destruction */ static void test_ctrl_lifetime(nvme_mi_ep_t ep) { - nvme_mi_ctrl_t c1, c2; + struct nvme_transport_handle *hdl1, *hdl2; int count; ep->controllers_scanned = true; @@ -188,19 +189,19 @@ static void test_ctrl_lifetime(nvme_mi_ep_t ep) count = count_ep_controllers(ep); assert(count == 0); - c1 = nvme_mi_init_ctrl(ep, 1); + hdl1 = nvme_mi_init_transport_handle(ep, 1); count = count_ep_controllers(ep); assert(count == 1); - c2 = nvme_mi_init_ctrl(ep, 2); + hdl2 = nvme_mi_init_transport_handle(ep, 2); count = count_ep_controllers(ep); assert(count == 2); - nvme_mi_close_ctrl(c1); + nvme_close(hdl1); count = count_ep_controllers(ep); assert(count == 1); - nvme_mi_close_ctrl(c2); + nvme_close(hdl2); count = count_ep_controllers(ep); assert(count == 0); } @@ -361,7 +362,7 @@ static int test_scan_ctrl_list_cb(struct nvme_mi_ep *ep, static void test_scan_ctrl_list(nvme_mi_ep_t ep) { - struct nvme_mi_ctrl *ctrl; + struct nvme_transport_handle *hdl; ep->controllers_scanned = false; @@ -369,20 +370,20 @@ static void test_scan_ctrl_list(nvme_mi_ep_t ep) nvme_mi_scan_ep(ep, false); - ctrl = nvme_mi_first_ctrl(ep); - assert(ctrl); - assert(ctrl->id == 1); + hdl = nvme_mi_first_transport_handle(ep); + assert(hdl); + assert(hdl->id == 1); - ctrl = nvme_mi_next_ctrl(ep, ctrl); - assert(ctrl); - assert(ctrl->id == 4); + hdl = nvme_mi_next_transport_handle(ep, hdl); + assert(hdl); + assert(hdl->id == 4); - ctrl = nvme_mi_next_ctrl(ep, ctrl); - assert(ctrl); - assert(ctrl->id == 5); + hdl = nvme_mi_next_transport_handle(ep, hdl); + assert(hdl); + assert(hdl->id == 5); - ctrl = nvme_mi_next_ctrl(ep, ctrl); - assert(ctrl == NULL); + hdl = nvme_mi_next_transport_handle(ep, hdl); + assert(hdl == NULL); } /* test: simple NVMe admin request/response */ @@ -437,16 +438,18 @@ static int test_admin_id_cb(struct nvme_mi_ep *ep, static void test_admin_id(nvme_mi_ep_t ep) { + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; struct nvme_id_ctrl id; - nvme_mi_ctrl_t ctrl; int rc; test_set_transport_callback(ep, test_admin_id_cb, NULL); - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); - rc = nvme_mi_admin_identify_ctrl(ctrl, &id); + nvme_init_identify_ctrl(&cmd, &id); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(rc == 0); } @@ -491,16 +494,18 @@ static int test_admin_err_mi_resp_cb(struct nvme_mi_ep *ep, static void test_admin_err_mi_resp(nvme_mi_ep_t ep) { + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; struct nvme_id_ctrl id; - nvme_mi_ctrl_t ctrl; int rc; test_set_transport_callback(ep, test_admin_err_mi_resp_cb, NULL); - ctrl = nvme_mi_init_ctrl(ep, 1); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 1); + assert(hdl); - rc = nvme_mi_admin_identify_ctrl(ctrl, &id); + nvme_init_identify_ctrl(&cmd, &id); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(rc != 0); assert(nvme_status_get_type(rc) == NVME_STATUS_TYPE_MI); assert(nvme_status_get_value(rc) == NVME_MI_RESP_INTERNAL_ERR); @@ -554,15 +559,17 @@ static int test_admin_err_nvme_resp_cb(struct nvme_mi_ep *ep, static void test_admin_err_nvme_resp(nvme_mi_ep_t ep) { struct nvme_id_ctrl id; - nvme_mi_ctrl_t ctrl; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; int rc; test_set_transport_callback(ep, test_admin_err_nvme_resp_cb, NULL); - ctrl = nvme_mi_init_ctrl(ep, 1); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 1); + assert(hdl); - rc = nvme_mi_admin_identify_ctrl(ctrl, &id); + nvme_init_identify_ctrl(&cmd, &id); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(rc != 0); assert(nvme_status_get_type(rc) == NVME_STATUS_TYPE_NVME); assert(nvme_status_get_value(rc) == @@ -588,48 +595,48 @@ static void test_admin_invalid_formats(nvme_mi_ep_t ep) uint8_t data[4]; } req = { 0 }; struct nvme_mi_admin_resp_hdr resp = { 0 }; - nvme_mi_ctrl_t ctrl; + struct nvme_transport_handle *hdl; size_t len; int rc; test_set_transport_callback(ep, test_rejected_command_cb, NULL); - ctrl = nvme_mi_init_ctrl(ep, 1); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 1); + assert(link); /* unaligned req size */ len = 0; - rc = nvme_mi_admin_xfer(ctrl, &req.hdr, 1, &resp, 0, &len); + rc = nvme_mi_admin_xfer(hdl, &req.hdr, 1, &resp, 0, &len); assert(rc != 0); /* unaligned resp size */ len = 1; - rc = nvme_mi_admin_xfer(ctrl, &req.hdr, 0, &resp, 0, &len); + rc = nvme_mi_admin_xfer(hdl, &req.hdr, 0, &resp, 0, &len); assert(rc != 0); /* unaligned resp offset */ len = 4; - rc = nvme_mi_admin_xfer(ctrl, &req.hdr, 0, &resp, 1, &len); + rc = nvme_mi_admin_xfer(hdl, &req.hdr, 0, &resp, 1, &len); assert(rc != 0); /* resp too large */ len = 4096 + 4; - rc = nvme_mi_admin_xfer(ctrl, &req.hdr, 0, &resp, 0, &len); + rc = nvme_mi_admin_xfer(hdl, &req.hdr, 0, &resp, 0, &len); assert(rc != 0); /* resp offset too large */ len = 4; - rc = nvme_mi_admin_xfer(ctrl, &req.hdr, 0, &resp, (off_t)1 << 32, &len); + rc = nvme_mi_admin_xfer(hdl, &req.hdr, 0, &resp, (off_t)1 << 32, &len); assert(rc != 0); /* resp offset with no len */ len = 0; - rc = nvme_mi_admin_xfer(ctrl, &req.hdr, 0, &resp, 4, &len); + rc = nvme_mi_admin_xfer(hdl, &req.hdr, 0, &resp, 4, &len); assert(rc != 0); /* req and resp payloads */ len = 4; - rc = nvme_mi_admin_xfer(ctrl, &req.hdr, 4, &resp, 0, &len); + rc = nvme_mi_admin_xfer(hdl, &req.hdr, 4, &resp, 0, &len); assert(rc != 0); } @@ -640,14 +647,14 @@ static void test_mi_invalid_formats(nvme_mi_ep_t ep) uint8_t data[4]; } req = { 0 }; struct nvme_mi_mi_resp_hdr resp = { 0 }; - nvme_mi_ctrl_t ctrl; + struct nvme_transport_handle *hdl; size_t len; int rc; test_set_transport_callback(ep, test_rejected_command_cb, NULL); - ctrl = nvme_mi_init_ctrl(ep, 1); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 1); + assert(hdl); /* resp too large */ len = 4096 + 4; @@ -958,61 +965,24 @@ static int test_admin_get_features_cb(struct nvme_mi_ep *ep, return 0; } -static void test_get_features_nodata(nvme_mi_ep_t ep) +static void test_get_features(nvme_mi_ep_t ep) { - struct nvme_get_features_args args = { 0 }; - nvme_mi_ctrl_t ctrl; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; uint32_t res; int rc; test_set_transport_callback(ep, test_admin_get_features_cb, NULL); - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); - args.args_size = sizeof(args); - args.fid = NVME_FEAT_FID_ARBITRATION; - args.sel = 0; - args.result = &res; - - rc = nvme_mi_admin_get_features(ctrl, &args); + nvme_init_get_features(&cmd, NVME_FEAT_FID_ARBITRATION, 0); + rc = nvme_submit_admin_passthru(hdl, &cmd, &res); assert(rc == 0); - assert(args.data_len == 0); assert(res == 0x04030201); } -static void test_get_features_data(nvme_mi_ep_t ep) -{ - struct nvme_get_features_args args = { 0 }; - struct nvme_timestamp tstamp; - nvme_mi_ctrl_t ctrl; - uint8_t exp[6]; - uint32_t res; - int rc, i; - - test_set_transport_callback(ep, test_admin_get_features_cb, NULL); - - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); - - args.args_size = sizeof(args); - args.fid = NVME_FEAT_FID_TIMESTAMP; - args.sel = 0; - args.result = &res; - args.data = &tstamp; - args.data_len = sizeof(tstamp); - - /* expected timestamp value */ - for (i = 0; i < sizeof(tstamp.timestamp); i++) - exp[i] = i; - - rc = nvme_mi_admin_get_features(ctrl, &args); - assert(rc == 0); - assert(args.data_len == sizeof(tstamp)); - assert(tstamp.attr == 1); - assert(!memcmp(tstamp.timestamp, exp, sizeof(tstamp.timestamp))); -} - /* Set Features callback for timestamp */ static int test_admin_set_features_cb(struct nvme_mi_ep *ep, struct nvme_mi_req *req, @@ -1067,30 +1037,20 @@ static int test_admin_set_features_cb(struct nvme_mi_ep *ep, static void test_set_features(nvme_mi_ep_t ep) { - struct nvme_set_features_args args = { 0 }; - struct nvme_timestamp tstamp = { 0 }; - nvme_mi_ctrl_t ctrl; + struct nvme_timestamp tstmp = { 0 }; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; uint32_t res; - int rc, i; + int rc; test_set_transport_callback(ep, test_admin_set_features_cb, NULL); - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); - - for (i = 0; i < sizeof(tstamp.timestamp); i++) - tstamp.timestamp[i] = i; + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); - args.args_size = sizeof(args); - args.fid = NVME_FEAT_FID_TIMESTAMP; - args.save = 1; - args.result = &res; - args.data = &tstamp; - args.data_len = sizeof(tstamp); - - rc = nvme_mi_admin_set_features(ctrl, &args); + nvme_init_set_features_timestamp(&cmd, true, 0x050403020100, &tstmp); + rc = nvme_submit_admin_passthru(hdl, &cmd, &res); assert(rc == 0); - assert(args.data_len == 0); } enum ns_type { @@ -1146,18 +1106,20 @@ static int test_admin_id_ns_list_cb(struct nvme_mi_ep *ep, static void test_admin_id_alloc_ns_list(struct nvme_mi_ep *ep) { + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; struct nvme_ns_list list; - nvme_mi_ctrl_t ctrl; enum ns_type type; int rc; type = NS_ALLOC; test_set_transport_callback(ep, test_admin_id_ns_list_cb, &type); - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); - rc = nvme_mi_admin_identify_allocated_ns_list(ctrl, 1, &list); + nvme_init_identify_allocated_ns_list(&cmd, 1, &list); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); assert(le32_to_cpu(list.ns[0]) == 2); @@ -1167,18 +1129,20 @@ static void test_admin_id_alloc_ns_list(struct nvme_mi_ep *ep) static void test_admin_id_active_ns_list(struct nvme_mi_ep *ep) { + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; struct nvme_ns_list list; - nvme_mi_ctrl_t ctrl; enum ns_type type; int rc; type = NS_ACTIVE; test_set_transport_callback(ep, test_admin_id_ns_list_cb, &type); - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); - rc = nvme_mi_admin_identify_active_ns_list(ctrl, 1, &list); + nvme_init_identify_active_ns_list(&cmd, 1, &list); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); assert(le32_to_cpu(list.ns[0]) == 4); @@ -1230,44 +1194,48 @@ static int test_admin_id_ns_cb(struct nvme_mi_ep *ep, static void test_admin_id_alloc_ns(struct nvme_mi_ep *ep) { + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; struct nvme_id_ns id; - nvme_mi_ctrl_t ctrl; enum ns_type type; int rc; type = NS_ALLOC; test_set_transport_callback(ep, test_admin_id_ns_cb, &type); - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); - rc = nvme_mi_admin_identify_allocated_ns(ctrl, 1, &id); + nvme_init_identify_allocated_ns(&cmd, 1, &id); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); assert(le64_to_cpu(id.nsze) == 1); } static void test_admin_id_active_ns(struct nvme_mi_ep *ep) { + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; struct nvme_id_ns id; - nvme_mi_ctrl_t ctrl; enum ns_type type; int rc; type = NS_ACTIVE; test_set_transport_callback(ep, test_admin_id_ns_cb, &type); - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); - rc = nvme_mi_admin_identify_ns(ctrl, 1, &id); + nvme_init_identify_ns(&cmd, 1, &id); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); assert(le64_to_cpu(id.nsze) == 1); } -static int test_admin_id_nsid_ctrl_list_cb(struct nvme_mi_ep *ep, - struct nvme_mi_req *req, - struct nvme_mi_resp *resp, - void *data) +static int test_admin_id_ns_ctrl_list_cb(struct nvme_mi_ep *ep, + struct nvme_mi_req *req, + struct nvme_mi_resp *resp, + void *data) { __u16 cns, ctrlid; __u32 nsid; @@ -1293,18 +1261,20 @@ static int test_admin_id_nsid_ctrl_list_cb(struct nvme_mi_ep *ep, return 0; } -static void test_admin_id_nsid_ctrl_list(struct nvme_mi_ep *ep) +static void test_admin_id_ns_ctrl_list(struct nvme_mi_ep *ep) { + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; struct nvme_ctrl_list list; - nvme_mi_ctrl_t ctrl; int rc; - test_set_transport_callback(ep, test_admin_id_nsid_ctrl_list_cb, NULL); + test_set_transport_callback(ep, test_admin_id_ns_ctrl_list_cb, NULL); - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); - rc = nvme_mi_admin_identify_nsid_ctrl_list(ctrl, 0x01020304, 5, &list); + nvme_init_identify_ns_ctrl_list(&cmd, 0x01020304, 5, &list); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); } @@ -1336,16 +1306,18 @@ static int test_admin_id_secondary_ctrl_list_cb(struct nvme_mi_ep *ep, static void test_admin_id_secondary_ctrl_list(struct nvme_mi_ep *ep) { struct nvme_secondary_ctrl_list list; - nvme_mi_ctrl_t ctrl; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; int rc; test_set_transport_callback(ep, test_admin_id_secondary_ctrl_list_cb, NULL); - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); - rc = nvme_mi_admin_identify_secondary_ctrl_list(ctrl, 5, &list); + nvme_init_identify_secondary_ctrl_list(&cmd, 5, &list); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); } @@ -1407,35 +1379,40 @@ static int test_admin_ns_mgmt_cb(struct nvme_mi_ep *ep, static void test_admin_ns_mgmt_create(struct nvme_mi_ep *ep) { struct nvme_ns_mgmt_host_sw_specified data = { 0 }; - nvme_mi_ctrl_t ctrl; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; __u32 ns; int rc; test_set_transport_callback(ep, test_admin_ns_mgmt_cb, NULL); - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); - rc = nvme_mi_admin_ns_mgmt_create(ctrl, NULL, 0, &ns, &data); + nvme_init_ns_mgmt_create(&cmd, NVME_CSI_NVM, &data); + rc = nvme_submit_admin_passthru(hdl, &cmd, &ns); assert(!rc); assert(ns == 0x01020304); data.nsze = cpu_to_le64(42); - rc = nvme_mi_admin_ns_mgmt_create(ctrl, NULL, 0, &ns, &data); + nvme_init_ns_mgmt_create(&cmd, NVME_CSI_NVM, &data); + rc = nvme_submit_admin_passthru(hdl, &cmd, &ns); assert(rc); } static void test_admin_ns_mgmt_delete(struct nvme_mi_ep *ep) { - nvme_mi_ctrl_t ctrl; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; int rc; test_set_transport_callback(ep, test_admin_ns_mgmt_cb, NULL); - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); - rc = nvme_mi_admin_ns_mgmt_delete(ctrl, 0x05060708); + nvme_init_ns_mgmt_delete(&cmd, 0x05060708); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); } @@ -1487,7 +1464,8 @@ static void test_admin_ns_attach(struct nvme_mi_ep *ep) { struct nvme_ctrl_list list = { 0 }; struct attach_op aop; - nvme_mi_ctrl_t ctrl; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; int rc; list.num = cpu_to_le16(2); @@ -1499,10 +1477,11 @@ static void test_admin_ns_attach(struct nvme_mi_ep *ep) test_set_transport_callback(ep, test_admin_ns_attach_cb, &aop); - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); - rc = nvme_mi_admin_ns_attach_ctrls(ctrl, 0x02030405, &list); + nvme_init_ns_attach_ctrls(&cmd, 0x02030405, &list); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); } @@ -1510,7 +1489,8 @@ static void test_admin_ns_detach(struct nvme_mi_ep *ep) { struct nvme_ctrl_list list = { 0 }; struct attach_op aop; - nvme_mi_ctrl_t ctrl; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; int rc; list.num = cpu_to_le16(2); @@ -1522,10 +1502,11 @@ static void test_admin_ns_detach(struct nvme_mi_ep *ep) test_set_transport_callback(ep, test_admin_ns_attach_cb, &aop); - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); - rc = nvme_mi_admin_ns_detach_ctrls(ctrl, 0x02030405, &list); + nvme_init_ns_detach_ctrls(&cmd, 0x02030405, &list); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); } @@ -1565,10 +1546,10 @@ static int test_admin_fw_download_cb(struct nvme_mi_ep *ep, static void test_admin_fw_download(struct nvme_mi_ep *ep) { - struct nvme_fw_download_args args = { 0 }; struct fw_download_info info; unsigned char fw[4096]; - nvme_mi_ctrl_t ctrl; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; int rc, i; for (i = 0; i < sizeof(fw); i++) @@ -1577,48 +1558,52 @@ static void test_admin_fw_download(struct nvme_mi_ep *ep) info.offset = 0; info.len = 0; info.data = fw; - args.data = fw; - args.args_size = sizeof(args); test_set_transport_callback(ep, test_admin_fw_download_cb, &info); - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); /* invalid (zero) len */ - args.data_len = info.len = 1; - args.offset = info.offset = 0; - rc = nvme_mi_admin_fw_download(ctrl, &args); + info.len = 1; + info.offset = 0; + rc = nvme_init_fw_download(&cmd, fw, info.len, info.offset); assert(rc); /* invalid (unaligned) len */ - args.data_len = info.len = 1; - args.offset = info.offset = 0; - rc = nvme_mi_admin_fw_download(ctrl, &args); + info.len = 1; + info.offset = 0; + rc = nvme_init_fw_download(&cmd, fw, info.len, info.offset); assert(rc); /* invalid offset */ - args.data_len = info.len = 4; - args.offset = info.offset = 1; - rc = nvme_mi_admin_fw_download(ctrl, &args); + info.len = 4; + info.offset = 1; + rc = nvme_init_fw_download(&cmd, fw, info.len, info.offset); assert(rc); /* smallest len */ - args.data_len = info.len = 4; - args.offset = info.offset = 0; - rc = nvme_mi_admin_fw_download(ctrl, &args); + info.len = 4; + info.offset = 0; + rc = nvme_init_fw_download(&cmd, fw, info.len, info.offset); + assert(!rc); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); /* largest len */ - args.data_len = info.len = 4096; - args.offset = info.offset = 0; - rc = nvme_mi_admin_fw_download(ctrl, &args); + info.len = 4096; + info.offset = 0; + rc = nvme_init_fw_download(&cmd, fw, info.len, info.offset); + assert(!rc); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); /* offset value */ - args.data_len = info.len = 4096; - args.offset = info.offset = 4096; - rc = nvme_mi_admin_fw_download(ctrl, &args); + info.len = 4096; + info.offset = 4096; + rc = nvme_init_fw_download(&cmd, fw, info.len, info.offset); + assert(!rc); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); } @@ -1655,49 +1640,50 @@ static int test_admin_fw_commit_cb(struct nvme_mi_ep *ep, static void test_admin_fw_commit(struct nvme_mi_ep *ep) { - struct nvme_fw_commit_args args = { 0 }; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; struct fw_commit_info info; - nvme_mi_ctrl_t ctrl; int rc; - args.args_size = sizeof(args); - info.bpid = args.bpid = 0; + info.bpid = 0; test_set_transport_callback(ep, test_admin_fw_commit_cb, &info); - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); /* all zeros */ - info.bpid = args.bpid = 0; - info.slot = args.slot = 0; - info.action = args.action = 0; - rc = nvme_mi_admin_fw_commit(ctrl, &args); + info.bpid = 0; + info.slot = 0; + info.action = 0; + nvme_init_fw_commit(&cmd, info.slot, info.action, info.bpid); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); /* all ones */ - info.bpid = args.bpid = 1; - info.slot = args.slot = 0x7; - info.action = args.action = 0x7; - rc = nvme_mi_admin_fw_commit(ctrl, &args); + info.bpid = 1; + info.slot = 0x7; + info.action = 0x7; + nvme_init_fw_commit(&cmd, info.slot, info.action, info.bpid); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); /* correct fields */ - info.bpid = args.bpid = 1; - info.slot = args.slot = 2; - info.action = args.action = 3; - rc = nvme_mi_admin_fw_commit(ctrl, &args); + info.bpid = 1; + info.slot = 2; + info.action = 3; + nvme_init_fw_commit(&cmd, info.slot, info.action, info.bpid); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); } struct format_data { __u32 nsid; - __u8 lbafu; __u8 ses; __u8 pil; __u8 pi; __u8 mset; - __u8 lbafl; + __u8 lbaf; }; static int test_admin_format_nvm_cb(struct nvme_mi_ep *ep, @@ -1705,7 +1691,7 @@ static int test_admin_format_nvm_cb(struct nvme_mi_ep *ep, struct nvme_mi_resp *resp, void *data) { - struct nvme_format_nvm_args *args = data; + struct format_data *args = data; __u8 *rq_hdr; __u32 nsid; @@ -1721,13 +1707,13 @@ static int test_admin_format_nvm_cb(struct nvme_mi_ep *ep, | rq_hdr[8]; assert(nsid == args->nsid); - assert(((rq_hdr[44] >> 0) & 0xf) == args->lbaf); + assert(((rq_hdr[44] >> 0) & 0xf) == (args->lbaf & 0xf)); assert(((rq_hdr[44] >> 4) & 0x1) == args->mset); assert(((rq_hdr[44] >> 5) & 0x7) == args->pi); assert(((rq_hdr[45] >> 0) & 0x1) == args->pil); assert(((rq_hdr[45] >> 1) & 0x7) == args->ses); - assert(((rq_hdr[45] >> 4) & 0x3) == args->lbafu); + assert(((rq_hdr[45] >> 4) & 0x3) == (args->lbaf >> 4)); test_transport_resp_calc_mic(resp); @@ -1736,41 +1722,53 @@ static int test_admin_format_nvm_cb(struct nvme_mi_ep *ep, static void test_admin_format_nvm(struct nvme_mi_ep *ep) { - struct nvme_format_nvm_args args = { 0 }; - nvme_mi_ctrl_t ctrl; + struct format_data args = { 0 }; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; int rc; - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); test_set_transport_callback(ep, test_admin_format_nvm_cb, &args); /* ensure we have the cdw0 bit field encoding correct, by testing twice * with inverted bit values */ - args.args_size = sizeof(args); args.nsid = 0x04030201; - args.lbafu = 0x3; args.ses = 0x0; args.pil = 0x1; args.pi = 0x0; args.mset = 0x1; - args.lbaf = 0x0; + args.lbaf = 0x30; - rc = nvme_mi_admin_format_nvm(ctrl, &args); + nvme_init_format_nvm(&cmd, args.nsid, args.lbaf, args.mset, + args.pi, args.pil, args.ses); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); args.nsid = ~args.nsid; - args.lbafu = 0; args.ses = 0x7; args.pil = 0x0; args.pi = 0x7; args.mset = 0x0; - args.lbaf = 0xf; + args.lbaf = 0x0f; - rc = nvme_mi_admin_format_nvm(ctrl, &args); + nvme_init_format_nvm(&cmd, args.nsid, args.lbaf, args.mset, + args.pi, args.pil, args.ses); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); } +struct nvme_sanitize_nvm_args { + enum nvme_sanitize_sanact sanact; + __u32 ovrpat; + bool ause; + __u8 owpass; + bool oipbp; + bool ndas; + bool emvs; +}; + static int test_admin_sanitize_nvm_cb(struct nvme_mi_ep *ep, struct nvme_mi_req *req, struct nvme_mi_resp *resp, @@ -1791,7 +1789,7 @@ static int test_admin_sanitize_nvm_cb(struct nvme_mi_ep *ep, assert(((rq_hdr[44] >> 4) & 0xf) == args->owpass); assert(((rq_hdr[45] >> 0) & 0x1) == args->oipbp); - assert(((rq_hdr[45] >> 1) & 0x1) == args->nodas); + assert(((rq_hdr[45] >> 1) & 0x1) == args->ndas); ovrpat = (__u32)rq_hdr[51] << 24 | rq_hdr[50] << 16 | rq_hdr[49] << 8 | rq_hdr[48]; @@ -1805,33 +1803,37 @@ static int test_admin_sanitize_nvm_cb(struct nvme_mi_ep *ep, static void test_admin_sanitize_nvm(struct nvme_mi_ep *ep) { struct nvme_sanitize_nvm_args args = { 0 }; - nvme_mi_ctrl_t ctrl; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; int rc; - ctrl = nvme_mi_init_ctrl(ep, 5); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 5); + assert(hdl); test_set_transport_callback(ep, test_admin_sanitize_nvm_cb, &args); - args.args_size = sizeof(args); args.sanact = 0x7; args.ause = 0x0; args.owpass = 0xf; args.oipbp = 0x0; - args.nodas = 0x1; + args.ndas = 0x1; args.ovrpat = ~0x04030201; - rc = nvme_mi_admin_sanitize_nvm(ctrl, &args); + nvme_init_sanitize_nvm(&cmd, args.sanact, args.ause, args.owpass, + args.oipbp, args.ndas, args.emvs, args.ovrpat); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); args.sanact = 0x0; args.ause = 0x1; args.owpass = 0x0; args.oipbp = 0x1; - args.nodas = 0x0; + args.ndas = 0x0; args.ovrpat = 0x04030201; - rc = nvme_mi_admin_sanitize_nvm(ctrl, &args); + nvme_init_sanitize_nvm(&cmd, args.sanact, args.ause, args.owpass, + args.oipbp, args.ndas, args.emvs, args.ovrpat); + rc = nvme_submit_admin_passthru(hdl, &cmd, NULL); assert(!rc); } @@ -1898,26 +1900,20 @@ static int test_admin_get_log_split_cb(struct nvme_mi_ep *ep, static void test_admin_get_log_split(struct nvme_mi_ep *ep) { - struct nvme_get_log_args args = { 0 }; unsigned char buf[4096 * 2 + 4]; struct log_data ldata; - nvme_mi_ctrl_t ctrl; + struct nvme_transport_handle *hdl; + struct nvme_passthru_cmd cmd; int rc; ldata.n = 0; test_set_transport_callback(ep, test_admin_get_log_split_cb, &ldata); - ctrl = nvme_mi_init_ctrl(ep, 5); - - args.args_size = sizeof(args); - args.lid = 1; - args.log = buf; - args.len = sizeof(buf); - args.lpo = 0; - args.ot = false; - - rc = nvme_mi_admin_get_log(ctrl, &args); + hdl = nvme_mi_init_transport_handle(ep, 5); + nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_ERROR, + NVME_CSI_NVM, buf, sizeof(buf)); + rc = nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); assert(!rc); /* we should have sent three commands */ @@ -2024,7 +2020,7 @@ static void test_admin_dlen_doff_req(struct nvme_mi_ep *ep) struct nvme_mi_admin_resp_hdr admin_resp = { 0 }; struct req_dlen_doff_data data = { 0 }; size_t resp_sz = 0; - nvme_mi_ctrl_t ctrl; + struct nvme_transport_handle *hdl; int rc; data.direction = DATA_DIR_OUT; @@ -2032,10 +2028,10 @@ static void test_admin_dlen_doff_req(struct nvme_mi_ep *ep) test_set_transport_callback(ep, test_admin_dlen_doff_cb, &data); - ctrl = nvme_mi_init_ctrl(ep, 0); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 0); + assert(hdl); - rc = nvme_mi_admin_xfer(ctrl, &admin_req.hdr, sizeof(admin_req.data), + rc = nvme_mi_admin_xfer(hdl, &admin_req.hdr, sizeof(admin_req.data), &admin_resp, 0, &resp_sz); assert(!rc); @@ -2051,7 +2047,7 @@ static void test_admin_dlen_doff_resp(struct nvme_mi_ep *ep) } admin_resp = { 0 }; struct nvme_mi_admin_req_hdr admin_req = { 0 }; struct req_dlen_doff_data data = { 0 }; - nvme_mi_ctrl_t ctrl; + struct nvme_transport_handle *hdl; size_t resp_sz; int rc; @@ -2061,10 +2057,10 @@ static void test_admin_dlen_doff_resp(struct nvme_mi_ep *ep) test_set_transport_callback(ep, test_admin_dlen_doff_cb, &data); - ctrl = nvme_mi_init_ctrl(ep, 0); - assert(ctrl); + hdl = nvme_mi_init_transport_handle(ep, 0); + assert(hdl); - rc = nvme_mi_admin_xfer(ctrl, &admin_req, 0, &admin_resp.hdr, 0, + rc = nvme_mi_admin_xfer(hdl, &admin_req, 0, &admin_resp.hdr, 0, &resp_sz); assert(!rc); @@ -2094,14 +2090,13 @@ struct test { DEFINE_TEST(mi_config_get_mtu), DEFINE_TEST(mi_config_set_freq), DEFINE_TEST(mi_config_set_freq_invalid), - DEFINE_TEST(get_features_nodata), - DEFINE_TEST(get_features_data), + DEFINE_TEST(get_features), DEFINE_TEST(set_features), DEFINE_TEST(admin_id_alloc_ns_list), DEFINE_TEST(admin_id_active_ns_list), DEFINE_TEST(admin_id_alloc_ns), DEFINE_TEST(admin_id_active_ns), - DEFINE_TEST(admin_id_nsid_ctrl_list), + DEFINE_TEST(admin_id_ns_ctrl_list), DEFINE_TEST(admin_id_secondary_ctrl_list), DEFINE_TEST(admin_ns_mgmt_create), DEFINE_TEST(admin_ns_mgmt_delete), @@ -2130,17 +2125,17 @@ static void run_test(struct test *test, FILE *logfd, nvme_mi_ep_t ep) int main(void) { - nvme_root_t root; + struct nvme_global_ctx *ctx; nvme_mi_ep_t ep; unsigned int i; FILE *fd; fd = test_setup_log(); - root = nvme_mi_create_root(fd, DEFAULT_LOGLEVEL); - assert(root); + ctx = nvme_mi_create_global_ctx(fd, DEFAULT_LOGLEVEL); + assert(ctx); - ep = nvme_mi_open_test(root); + ep = nvme_mi_open_test(ctx); assert(ep); for (i = 0; i < ARRAY_SIZE(tests); i++) { @@ -2148,7 +2143,7 @@ int main(void) } nvme_mi_close(ep); - nvme_mi_free_root(root); + nvme_mi_free_global_ctx(ctx); test_close_log(fd); diff --git a/libnvme/test/psk.c b/libnvme/test/psk.c index c9112e9ee4..3efa141607 100644 --- a/libnvme/test/psk.c +++ b/libnvme/test/psk.c @@ -4,7 +4,6 @@ * Copyright (c) 2024 Daniel Wagner, SUSE Software Solutions */ -#include "nvme/linux.h" #include #include #include @@ -141,6 +140,7 @@ static void check_str(const char *exp, const char *res) static void export_test(struct test_data_psk *test) { char *psk; + int ret; if (test->version != 1 || !(test->hmac == NVME_HMAC_ALG_SHA2_256 || @@ -150,10 +150,10 @@ static void export_test(struct test_data_psk *test) printf("test nvme_export_tls_key hmac %d %s\n", test->hmac, test->exported_psk); - psk = nvme_export_tls_key(test->configured_psk, test->psk_length); - if (!psk) { + ret = nvme_export_tls_key(test->configured_psk, test->psk_length, &psk); + if (ret) { test_rc = 1; - printf("ERROR: nvme_export_tls_key() failed with %d\n", errno); + printf("ERROR: nvme_export_tls_key() failed with %d\n", ret); return; } check_str(test->exported_psk, psk); @@ -165,6 +165,7 @@ static void import_test(struct test_data_psk *test) unsigned char *psk; int psk_length; unsigned int hmac; + int ret; if (test->version != 1 || !(test->hmac == NVME_HMAC_ALG_SHA2_256 || @@ -174,10 +175,10 @@ static void import_test(struct test_data_psk *test) printf("test nvme_import_tls_key hmac %d %s\n", test->hmac, test->exported_psk); - psk = nvme_import_tls_key(test->exported_psk, &psk_length, &hmac); - if (!psk) { + ret = nvme_import_tls_key(test->exported_psk, &psk_length, &hmac, &psk); + if (ret) { test_rc = 1; - printf("ERROR: nvme_import_tls_key() failed with %d\n", errno); + printf("ERROR: nvme_import_tls_key() failed with %d\n", ret); return; } @@ -204,6 +205,7 @@ static void import_test(struct test_data_psk *test) static void export_versioned_test(struct test_data_psk *test) { char *psk; + int ret; if (test->version != 1) return; @@ -211,13 +213,13 @@ static void export_versioned_test(struct test_data_psk *test) printf("test nvme_export_tls_key_versioned hmac %d %s\n", test->hmac, test->exported_psk); - psk = nvme_export_tls_key_versioned(test->version, test->hmac, + ret = nvme_export_tls_key_versioned(test->version, test->hmac, test->configured_psk, - test->psk_length); - if (!psk) { + test->psk_length, &psk); + if (ret) { test_rc = 1; printf("ERROR: nvme_export_tls_key_versioned() failed with %d\n", - errno); + ret); return; } @@ -232,6 +234,7 @@ static void import_versioned_test(struct test_data_psk *test) unsigned char version; unsigned char hmac; size_t psk_length; + int ret; if (test->version != 1) return; @@ -239,12 +242,12 @@ static void import_versioned_test(struct test_data_psk *test) printf("test nvme_import_tls_key_versioned hmac %d %s\n", test->hmac, test->exported_psk); - psk = nvme_import_tls_key_versioned(test->exported_psk, &version, - &hmac, &psk_length); - if (!psk) { + ret = nvme_import_tls_key_versioned(test->exported_psk, &version, + &hmac, &psk_length, &psk); + if (ret) { test_rc = 1; printf("ERROR: nvme_import_tls_key_versioned() failed with %d\n", - errno); + ret); return; } @@ -278,6 +281,7 @@ static void import_versioned_test(struct test_data_psk *test) static void identity_test(struct test_data_identity *test) { char *id; + int ret; if (test->version != 1 || !(test->hmac == NVME_HMAC_ALG_SHA2_256 || @@ -287,15 +291,15 @@ static void identity_test(struct test_data_identity *test) printf("test nvme_generate_tls_key_identity host %s subsys %s hmac %d %s\n", test->hostnqn, test->subsysnqn, test->hmac, test->identity); - id = nvme_generate_tls_key_identity(test->hostnqn, test->subsysnqn, - test->version, test->hmac, - (unsigned char *)test->configured_psk, - test->psk_length); - if (!id) { - if (errno == ENOTSUP) + ret = nvme_generate_tls_key_identity(test->hostnqn, test->subsysnqn, + test->version, test->hmac, + (unsigned char *)test->configured_psk, + test->psk_length, &id); + if (ret) { + if (ret == -ENOTSUP) return; test_rc = 1; - printf("ERROR: nvme_generate_tls_key_identity() failed with %d\n", errno); + printf("ERROR: nvme_generate_tls_key_identity() failed with %d\n", ret); return; } check_str(test->identity, id); @@ -305,6 +309,7 @@ static void identity_test(struct test_data_identity *test) static void identity_test_compat(struct test_data_identity *test) { char *id; + int ret; if (test->version != 1 || !(test->hmac == NVME_HMAC_ALG_SHA2_256 || @@ -314,16 +319,16 @@ static void identity_test_compat(struct test_data_identity *test) printf("test nvme_generate_tls_key_identity_compat host %s subsys %s hmac %d %s\n", test->hostnqn, test->subsysnqn, test->hmac, test->identity); - id = nvme_generate_tls_key_identity_compat(test->hostnqn, - test->subsysnqn, - test->version, test->hmac, - (unsigned char *)test->configured_psk, - test->psk_length); - if (!id) { - if (errno == ENOTSUP) + ret = nvme_generate_tls_key_identity_compat(test->hostnqn, + test->subsysnqn, + test->version, test->hmac, + (unsigned char *)test->configured_psk, + test->psk_length, &id); + if (ret) { + if (ret == -ENOTSUP) return; test_rc = 1; - printf("ERROR: nvme_generate_tls_key_identity_compat() failed with %d\n", errno); + printf("ERROR: nvme_generate_tls_key_identity_compat() failed with %d\n", ret); return; } check_str(test->identity, id); diff --git a/libnvme/test/sysfs/tree-dump.c b/libnvme/test/sysfs/tree-dump.c index bcf871b36f..1cd6d3a99a 100644 --- a/libnvme/test/sysfs/tree-dump.c +++ b/libnvme/test/sysfs/tree-dump.c @@ -13,28 +13,26 @@ static bool tree_dump(void) { + struct nvme_global_ctx *ctx; bool pass = false; - nvme_root_t r; int err; - r = nvme_create_root(stdout, LOG_ERR); - if (!r) + ctx = nvme_create_global_ctx(stdout, LOG_ERR); + if (!ctx) return false; - err = nvme_scan_topology(r, NULL, NULL); - if (err) { - if (errno != ENOENT) - goto out; - } + err = nvme_scan_topology(ctx, NULL, NULL); + if (err && err != ENOENT) + goto out; - if (nvme_dump_tree(r)) + if (nvme_dump_tree(ctx)) goto out; printf("\n"); pass = true; out: - nvme_free_tree(r); + nvme_free_global_ctx(ctx); return pass; } diff --git a/libnvme/test/test.c b/libnvme/test/test.c index c0146d31b2..e39e9477b8 100644 --- a/libnvme/test/test.c +++ b/libnvme/test/test.c @@ -15,6 +15,8 @@ * program exists successfully; an ungraceful exit means a bug exists * somewhere. */ +#include "nvme/ioctl.h" +#include "nvme/tree.h" #include #include #include @@ -39,8 +41,10 @@ static int test_ctrl(nvme_ctrl_t c) static __u8 buf[0x1000]; enum nvme_get_features_sel sel = NVME_GET_FEATURES_SEL_CURRENT; - int ret, temp, fd = nvme_ctrl_get_fd(c); - struct nvme_error_log_page error[64]; + struct nvme_transport_handle *hdl = nvme_ctrl_get_transport_handle(c); + struct nvme_passthru_cmd cmd; + int ret, temp; + struct nvme_error_log_page error[64]; struct nvme_smart_log smart = { 0 }; struct nvme_firmware_slot fw = { 0 }; struct nvme_ns_list ns_list = { 0 }; @@ -60,7 +64,8 @@ static int test_ctrl(nvme_ctrl_t c) __u32 result; - ret = nvme_ctrl_identify(c, &id); + nvme_init_identify_ctrl(&cmd, &id); + ret = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (ret) { printf("ERROR: no identify for:%s\n", nvme_ctrl_get_name(c)); return ret; @@ -69,7 +74,8 @@ static int test_ctrl(nvme_ctrl_t c) printf("PASSED: Identify controller\n"); } - ret = nvme_get_log_smart(fd, NVME_NSID_ALL, true, &smart); + nvme_init_get_log_smart(&cmd, NVME_NSID_ALL, &smart); + ret = nvme_get_log(hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, NULL); if (ret) { printf("ERROR: no smart log for:%s %#x\n", nvme_ctrl_get_name(c), ret); return ret; @@ -88,42 +94,50 @@ static int test_ctrl(nvme_ctrl_t c) printf(" sn:%-.20s\n", id.sn); printf(" model:%-.40s\n", id.mn); - ret = nvme_identify_allocated_ns_list(fd, 0, &ns_list); + nvme_init_identify_allocated_ns_list(&cmd, 0, &ns_list); + ret = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!ret) printf(" PASSED: Allocated NS List\n"); else printf(" ERROR: Allocated NS List:%x\n", ret); - ret = nvme_identify_active_ns_list(fd, 0, &ns_list); + nvme_init_identify_active_ns_list(&cmd, 0, &ns_list); + ret = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!ret) printf(" PASSED: Active NS List\n"); else printf(" ERROR: Active NS List:%x\n", ret); - ret = nvme_identify_ctrl_list(fd, 0, &ctrlist); + nvme_init_identify_ctrl_list(&cmd, 0, &ctrlist); + ret = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!ret) printf(" PASSED: Ctrl List\n"); else printf(" ERROR: CtrlList:%x\n", ret); - ret = nvme_identify_nsid_ctrl_list(fd, 1, 0, &ctrlist); + nvme_init_identify_ctrl_list(&cmd, 1, &ctrlist); + ret = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!ret) printf(" PASSED: NSID Ctrl List\n"); else printf(" ERROR: NSID CtrlList:%x\n", ret); - ret = nvme_identify_primary_ctrl(fd, 0, &prim); + nvme_init_identify_primary_ctrl_cap(&cmd, 0, &prim); + ret = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!ret) printf(" PASSED: Identify Primary\n"); else printf(" ERROR: Identify Primary:%x\n", ret); - ret = nvme_identify_secondary_ctrl_list(fd, 0, &sec); + nvme_init_identify_secondary_ctrl_list(&cmd, 0, &sec); + ret = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!ret) printf(" PASSED: Identify Secondary\n"); else printf(" ERROR: Identify Secondary:%x\n", ret); - ret = nvme_identify_ns_granularity(fd, &gran); + nvme_init_identify_ns_granularity(&cmd, &gran); + ret = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!ret) printf(" PASSED: Identify NS granularity\n"); else printf(" ERROR: Identify NS granularity:%x\n", ret); - ret = nvme_identify_uuid(fd, &uuid); + nvme_init_identify_uuid_list(&cmd, &uuid); + ret = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!ret) printf(" PASSED: Identify UUID List\n"); else @@ -132,138 +146,160 @@ static int test_ctrl(nvme_ctrl_t c) printf("\nLogs\n"); printf(" SMART: Current temperature:%d percent used:%d%%\n", temp, smart.percent_used); - ret = nvme_get_log_sanitize(fd, true, &sanlog); + nvme_init_get_log_sanitize(&cmd, &sanlog); + ret = nvme_get_log(hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, NULL); if (!ret) printf(" Sanitize Log:\n"); else printf(" ERROR: Sanitize Log:%x\n", ret); - ret = nvme_get_log_reservation(fd, true, &resvnotify); + nvme_init_get_log_reservation(&cmd, &resvnotify); + ret = nvme_get_log(hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, NULL); if (!ret) printf(" Reservation Log\n"); else printf(" ERROR: Reservation Log:%x\n", ret); - ret = nvme_get_log_ana_groups(fd, true, sizeof(buf), analog); + nvme_init_get_log_ana_groups(&cmd, analog, sizeof(buf)); + ret = nvme_get_log(hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, NULL); if (!ret) printf(" ANA Groups\n"); else printf(" ERROR: ANA Groups:%x\n", ret); - ret = nvme_get_log_endurance_group(fd, 0, &eglog); + nvme_init_get_log_endurance_group(&cmd, 0, &eglog); + ret = nvme_get_log(hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, NULL); if (!ret) printf(" Endurance Group\n"); else printf(" ERROR: Endurance Group:%x\n", ret); - ret = nvme_get_log_telemetry_ctrl(fd, true, 0, sizeof(buf), telem); + nvme_init_get_log_telemetry_ctrl(&cmd, 0, telem, sizeof(buf)); + ret = nvme_get_log(hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, NULL); if (!ret) printf(" Telemetry Controller\n"); else printf(" ERROR: Telemetry Controller:%x\n", ret); - ret = nvme_get_log_device_self_test(fd, &st); + nvme_init_get_log_device_self_test(&cmd, &st); + ret = nvme_get_log(hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, NULL); if (!ret) printf(" Device Self Test\n"); else printf(" ERROR: Device Self Test:%x\n", ret); - ret = nvme_get_log_cmd_effects(fd, NVME_CSI_NVM, &cfx); + nvme_init_get_log_cmd_effects(&cmd, NVME_CSI_NVM, &cfx); + ret = nvme_get_log(hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, NULL); if (!ret) printf(" Command Effects\n"); else printf(" ERROR: Command Effects:%x\n", ret); - ret = nvme_get_log_changed_ns_list(fd, true, &ns_list); + nvme_init_get_log_changed_alloc_ns(&cmd, &ns_list, sizeof(ns_list)); + ret = nvme_get_log(hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, NULL); if (!ret) printf(" Change NS List\n"); else printf(" ERROR: Change NS List:%x\n", ret); - ret = nvme_get_log_fw_slot(fd, true, &fw); + nvme_init_get_log_fw_slot(&cmd, &fw); + ret = nvme_get_log(hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, NULL); if (!ret) printf(" FW Slot\n"); else printf(" ERROR: FW Slot%x\n", ret); - ret = nvme_get_log_error(fd, 64, true, error); + nvme_init_get_log_error(&cmd, 64, error); + ret = nvme_get_log(hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, NULL); if (!ret) printf(" Error Log\n"); else printf(" ERROR: Error Log:%x\n", ret); printf("\nFeatures\n"); - ret = nvme_get_features_arbitration(fd, sel, &result); + nvme_init_get_features_arbitration(&cmd, sel); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" Arbitration:%x\n", result); else if (ret > 0) printf(" ERROR: Arbitration:%x\n", ret); - ret = nvme_get_features_power_mgmt(fd, sel, &result); + nvme_init_get_features_power_mgmt(&cmd, sel); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" Power Management:%x\n", result); else if (ret > 0) printf(" ERROR: Power Management:%x\n", ret); - ret = nvme_get_features_temp_thresh(fd, sel, &result); + + nvme_init_get_features_temp_thresh(&cmd, sel, 0, 0); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" Temperature Threshold:%x\n", result); else if (ret > 0) printf(" ERROR: Temperature Threshold:%x\n", ret); - ret = nvme_get_features_err_recovery2(fd, sel, 0, &result); - if (!ret) - printf(" Error Recovery:%x\n", result); - else if (ret > 0) - printf(" ERROR: Error Recovery:%x\n", ret); - ret = nvme_get_features_volatile_wc(fd, sel, &result); + nvme_init_get_features_volatile_wc(&cmd, sel); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" Volatile Write Cache:%x\n", result); else if (ret > 0) printf(" ERROR: Volatile Write Cache:%x\n", ret); - ret = nvme_get_features_num_queues(fd, sel, &result); + nvme_init_get_features_num_queues(&cmd, sel); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" Number of Queues:%x\n", result); else if (ret > 0) printf(" ERROR: Number of Queues:%x\n", ret); - ret = nvme_get_features_irq_coalesce(fd, sel, &result); + nvme_init_get_features_irq_coalesce(&cmd, sel); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" IRQ Coalescing:%x\n", result); else if (ret > 0) printf(" ERROR: IRQ Coalescing:%x\n", ret); - ret = nvme_get_features_write_atomic(fd, sel, &result); + nvme_init_get_features_write_atomic(&cmd, sel); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" Write Atomic:%x\n", result); else if (ret > 0) printf(" ERROR: Write Atomic:%x\n", ret); - ret = nvme_get_features_async_event(fd, sel, &result); + nvme_init_get_features_async_event(&cmd, sel); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" Asycn Event Config:%x\n", result); else if (ret > 0) printf(" ERROR: Asycn Event Config:%x\n", ret); - ret = nvme_get_features_hctm(fd, sel, &result); + nvme_init_get_features_hctm(&cmd, sel); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" HCTM:%x\n", result); else if (ret > 0) printf(" ERROR: HCTM:%x\n", ret); - ret = nvme_get_features_nopsc(fd, sel, &result); + nvme_init_get_features_nopsc(&cmd, sel); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" NOP Power State Config:%x\n", result); else if (ret > 0) printf(" ERROR: NOP Power State Configrbitration:%x\n", ret); - ret = nvme_get_features_rrl(fd, sel, &result); + nvme_init_get_features_rrl(&cmd, sel); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" Read Recover Levels:%x\n", result); else if (ret > 0) printf(" ERROR: Read Recover Levels:%x\n", ret); - ret = nvme_get_features_lba_sts_interval(fd, sel, &result); + nvme_init_get_features_lba_sts_interval(&cmd, sel); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" LBA Status Interval:%x\n", result); else if (ret > 0) printf(" ERROR: LBA Status Interval:%x\n", ret); - ret = nvme_get_features_sanitize(fd, sel, &result); + nvme_init_get_features_sanitize(&cmd, sel); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" Sanitize:%x\n", result); else if (ret > 0) printf(" ERROR: SW Progress Marker:%x\n", ret); - ret = nvme_get_features_sw_progress(fd, sel, &result); + nvme_init_get_features_sw_progress(&cmd, sel); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" SW Progress Marker:%x\n", result); else if (ret > 0) printf(" ERROR: Sanitize:%x\n", ret); - ret = nvme_get_features_resv_mask2(fd, sel, 0, &result); + nvme_init_get_features_resv_mask(&cmd, 0, sel); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" Reservation Mask:%x\n", result); else if (ret > 0) printf(" ERROR: Reservation Mask:%x\n", ret); - ret = nvme_get_features_resv_persist2(fd, sel, 0, &result); + nvme_init_get_features_resv_persist(&cmd, 0, sel); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" Reservation Persistence:%x\n", result); else if (ret > 0) @@ -273,7 +309,9 @@ static int test_ctrl(nvme_ctrl_t c) static int test_namespace(nvme_ns_t n) { - int ret, nsid = nvme_ns_get_nsid(n), fd = nvme_ns_get_fd(n); + int ret, nsid = nvme_ns_get_nsid(n); + struct nvme_transport_handle *hdl = nvme_ns_get_transport_handle(n); + struct nvme_passthru_cmd cmd; struct nvme_id_ns ns = { 0 }, allocated = { 0 }; struct nvme_ns_id_desc *descs; __u32 result = 0; @@ -288,7 +326,8 @@ static int test_namespace(nvme_ns_t n) nvme_ns_get_name(n), le64_to_cpu(ns.nsze), 1 << ns.lbaf[flbas].ds); - ret = nvme_identify_allocated_ns(fd, nsid, &allocated); + nvme_init_identify_allocated_ns(&cmd, nsid, &allocated); + ret = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!ret) printf(" Identify allocated ns\n"); else @@ -297,14 +336,16 @@ static int test_namespace(nvme_ns_t n) if (!descs) return -1; - ret = nvme_identify_ns_descs(fd, nsid, descs); + nvme_init_identify_ns_descs_list(&cmd, nsid, descs); + ret = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!ret) printf(" Identify NS Descriptors\n"); else printf(" ERROR: Identify NS Descriptors:%x\n", ret); free(descs); - ret = nvme_get_features_write_protect(fd, nsid, - NVME_GET_FEATURES_SEL_CURRENT, &result); + nvme_init_get_features_write_protect(&cmd, nsid, + NVME_GET_FEATURES_SEL_CURRENT); + ret = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!ret) printf(" Write Protect:%x\n", result); else if (ret > 0) @@ -322,7 +363,7 @@ static void print_hex(const uint8_t *x, int len) int main(int argc, char **argv) { - nvme_root_t r; + struct nvme_global_ctx *ctx; nvme_host_t h; nvme_subsystem_t s; nvme_ctrl_t c; @@ -332,11 +373,11 @@ int main(int argc, char **argv) const char *nqn_match = "testnqn"; printf("Test filter for common loop back target\n"); - r = nvme_create_root(NULL, DEFAULT_LOGLEVEL); - if (!r) + ctx = nvme_create_global_ctx(NULL, DEFAULT_LOGLEVEL); + if (!ctx) return 1; - nvme_scan_topology(r, nvme_match_subsysnqn_filter, (void *)nqn_match); - nvme_for_each_host(r, h) { + nvme_scan_topology(ctx, nvme_match_subsysnqn_filter, (void *)nqn_match); + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { printf("%s - NQN=%s\n", nvme_subsystem_get_name(s), nvme_subsystem_get_nqn(s)); @@ -354,8 +395,7 @@ int main(int argc, char **argv) ctrl = argv[1]; printf("Test scan specific controller\n"); - c = nvme_scan_ctrl(r, ctrl); - if (c) { + if (!nvme_scan_ctrl(ctx, ctrl, &c)) { printf("%s %s %s %s\n", nvme_ctrl_get_name(c), nvme_ctrl_get_transport(c), nvme_ctrl_get_address(c), @@ -363,14 +403,13 @@ int main(int argc, char **argv) nvme_free_ctrl(c); } printf("\n"); - nvme_free_tree(r); + nvme_free_global_ctx(ctx); - r = nvme_scan(NULL); - if (!r) + if (nvme_scan(NULL, &ctx)) return -1; printf("Test walking the topology\n"); - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { printf("%s - NQN=%s\n", nvme_subsystem_get_name(s), nvme_subsystem_get_nqn(s)); @@ -415,7 +454,7 @@ int main(int argc, char **argv) } printf("Test identification, logs, and features\n"); - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { nvme_subsystem_for_each_ctrl(s, c) { test_ctrl(c); @@ -431,7 +470,7 @@ int main(int argc, char **argv) } } } - nvme_free_tree(r); + nvme_free_global_ctx(ctx); return 0; } diff --git a/libnvme/test/tree.c b/libnvme/test/tree.c index c9370f9713..a8191e8124 100644 --- a/libnvme/test/tree.c +++ b/libnvme/test/tree.c @@ -118,14 +118,14 @@ static bool match_ctrl(struct test_data *d, nvme_ctrl_t c) return pass; } -static nvme_root_t create_tree() +static struct nvme_global_ctx *create_tree() { - nvme_root_t r; + struct nvme_global_ctx *ctx; nvme_host_t h; - r = nvme_create_root(stdout, LOG_DEBUG); - assert(r); - h = nvme_default_host(r); + ctx = nvme_create_global_ctx(stdout, LOG_DEBUG); + assert(ctx); + nvme_default_host(ctx, &h); assert(h); printf(" ctrls created:\n"); @@ -147,17 +147,17 @@ static nvme_root_t create_tree() } printf("\n"); - return r; + return ctx; } -static unsigned int count_entries(nvme_root_t r) +static unsigned int count_entries(struct nvme_global_ctx *ctx) { nvme_host_t h; nvme_subsystem_t s; nvme_ctrl_t c; unsigned int i = 0; - nvme_for_each_host(r, h) + nvme_for_each_host(ctx, h) nvme_for_each_subsystem(h, s) nvme_subsystem_for_each_ctrl(s, c) i++; @@ -222,13 +222,13 @@ static bool default_ctrl_lookup(nvme_subsystem_t s, struct test_data *d) return pass; } -static bool ctrl_lookups(nvme_root_t r) +static bool ctrl_lookups(struct nvme_global_ctx *ctx) { nvme_host_t h; nvme_subsystem_t s; bool pass = true; - h = nvme_first_host(r); + h = nvme_first_host(ctx); s = nvme_lookup_subsystem(h, DEFAULT_SUBSYSNAME, DEFAULT_SUBSYSNQN); printf(" lookup controller:\n"); @@ -252,24 +252,24 @@ static bool ctrl_lookups(nvme_root_t r) static bool test_lookup(void) { - nvme_root_t r; + struct nvme_global_ctx *ctx; bool pass; printf("test_lookup:\n"); - r = create_tree(); - pass = count_entries(r) == ARRAY_SIZE(test_data); - pass &= ctrl_lookups(r); + ctx = create_tree(); + pass = count_entries(ctx) == ARRAY_SIZE(test_data); + pass &= ctrl_lookups(ctx); - nvme_free_tree(r); + nvme_free_global_ctx(ctx); return pass; } static bool test_src_addr() { + struct nvme_global_ctx *ctx; bool pass = true; - nvme_root_t r; nvme_host_t h; nvme_ctrl_t c; nvme_subsystem_t s; @@ -278,10 +278,10 @@ static bool test_src_addr() printf("\n" "test_src_addr:\n"); - r = nvme_create_root(stdout, LOG_DEBUG); - assert(r); + ctx = nvme_create_global_ctx(stdout, LOG_DEBUG); + assert(ctx); - h = nvme_default_host(r); + nvme_default_host(ctx, &h); assert(h); s = nvme_lookup_subsystem(h, DEFAULT_SUBSYSNAME, DEFAULT_SUBSYSNQN); @@ -407,7 +407,7 @@ static bool test_src_addr() c->address = NULL; /* Needed to avoid freeing non-malloced memory (see above) */ - nvme_free_tree(r); + nvme_free_global_ctx(ctx); return pass; } @@ -447,17 +447,17 @@ static bool ctrl_match(const char *tag, struct ctrl_args *candidate, bool should_match) { - nvme_root_t r; + struct nvme_global_ctx *ctx; nvme_host_t h; nvme_ctrl_t reference_ctrl; /* Existing controller (from sysfs) */ nvme_ctrl_t candidate_ctrl; nvme_ctrl_t found_ctrl; nvme_subsystem_t s; - r = nvme_create_root(stdout, LOG_INFO); - assert(r); + ctx = nvme_create_global_ctx(stdout, LOG_INFO); + assert(ctx); - h = nvme_default_host(r); + nvme_default_host(ctx, &h); assert(h); s = nvme_lookup_subsystem(h, DEFAULT_SUBSYSNAME, reference->subsysnqn ? reference->subsysnqn : DEFAULT_SUBSYSNQN); @@ -524,7 +524,7 @@ static bool ctrl_match(const char *tag, reference_ctrl->name = NULL; reference_ctrl->address = NULL; - nvme_free_tree(r); + nvme_free_global_ctx(ctx); return true; } @@ -1061,16 +1061,16 @@ static bool ctrl_config_match(const char *tag, struct ctrl_args *candidate, bool should_match) { + struct nvme_global_ctx *ctx; bool match; - nvme_root_t r; nvme_host_t h; nvme_ctrl_t reference_ctrl; /* Existing controller (from sysfs) */ nvme_subsystem_t s; - r = nvme_create_root(stdout, LOG_INFO); - assert(r); + ctx = nvme_create_global_ctx(stdout, LOG_INFO); + assert(ctx); - h = nvme_default_host(r); + nvme_default_host(ctx, &h); assert(h); s = nvme_lookup_subsystem(h, DEFAULT_SUBSYSNAME, reference->subsysnqn ? reference->subsysnqn : DEFAULT_SUBSYSNQN); @@ -1111,7 +1111,7 @@ static bool ctrl_config_match(const char *tag, reference_ctrl->name = NULL; reference_ctrl->address = NULL; - nvme_free_tree(r); + nvme_free_global_ctx(ctx); return true; } diff --git a/libnvme/test/uriparser.c b/libnvme/test/uriparser.c index 09b2a732b9..428c5495da 100644 --- a/libnvme/test/uriparser.c +++ b/libnvme/test/uriparser.c @@ -159,8 +159,7 @@ static void test_uriparser(void) int i; printf(" '%s'...", d->uri); - parsed_data = nvme_parse_uri(d->uri); - assert(parsed_data); + assert(!nvme_parse_uri(d->uri, &parsed_data)); assert(strcmp(d->scheme, parsed_data->scheme) == 0); if (d->proto) { @@ -201,10 +200,10 @@ static void test_uriparser_bad(void) { printf("Testing malformed URI strings:\n"); for (int i = 0; i < ARRAY_SIZE(test_data_bad); i++) { - struct nvme_fabrics_uri *parsed_data; + struct nvme_fabrics_uri *parsed_data = NULL; printf(" '%s'...", test_data_bad[i]); - parsed_data = nvme_parse_uri(test_data_bad[i]); + assert(nvme_parse_uri(test_data_bad[i], &parsed_data)); assert(parsed_data == NULL); printf(" OK\n"); } diff --git a/libnvme/test/zns.c b/libnvme/test/zns.c index 6d06d72572..5296b757e9 100644 --- a/libnvme/test/zns.c +++ b/libnvme/test/zns.c @@ -1,14 +1,15 @@ // SPDX-License-Identifier: LGPL-2.1-or-later -/** +/* * This file is part of libnvme. * Copyright (c) 2020 Western Digital Corporation or its affiliates. * * Authors: Keith Busch */ -/** +/* * Search out for ZNS type namespaces, and if found, report their properties. */ +#include "nvme/tree.h" #include #include #include @@ -20,6 +21,8 @@ static void show_zns_properties(nvme_ns_t n) { + struct nvme_transport_handle *hdl = nvme_ns_get_transport_handle(n); + struct nvme_passthru_cmd cmd; struct nvme_zns_id_ns zns_ns; struct nvme_zns_id_ctrl zns_ctrl; struct nvme_zone_report *zr; @@ -29,27 +32,30 @@ static void show_zns_properties(nvme_ns_t n) if (!zr) return; - if (nvme_zns_identify_ns(nvme_ns_get_fd(n), nvme_ns_get_nsid(n), - &zns_ns)) { - fprintf(stderr, "failed to identify zns ns\n");; + nvme_init_zns_identify_ns(&cmd, nvme_ns_get_nsid(n), &zns_ns); + if (nvme_submit_admin_passthru(hdl, &cmd, &result)) { + fprintf(stderr, "failed to identify zns ns, result %x\n", + le32_to_cpu(result)); + free(zr); + return; } printf("zoc:%x ozcs:%x mar:%x mor:%x\n", le16_to_cpu(zns_ns.zoc), le16_to_cpu(zns_ns.ozcs), le32_to_cpu(zns_ns.mar), le32_to_cpu(zns_ns.mor)); - if (nvme_zns_identify_ctrl(nvme_ns_get_fd(n), &zns_ctrl)) { + nvme_init_zns_identify_ctrl(&cmd, &zns_ctrl); + if (nvme_submit_admin_passthru(hdl, &cmd, &result)) { fprintf(stderr, "failed to identify zns ctrl\n");; free(zr); return; } printf("zasl:%u\n", zns_ctrl.zasl); - - if (nvme_zns_report_zones(nvme_ns_get_fd(n), nvme_ns_get_nsid(n), 0, + nvme_init_zns_report_zones(&cmd, nvme_ns_get_nsid(n), 0, NVME_ZNS_ZRAS_REPORT_ALL, false, - true, 0x1000, (void *)zr, - NVME_DEFAULT_IOCTL_TIMEOUT, &result)) { + true, (void *)zr, 0x1000); + if (nvme_submit_io_passthru(hdl, &cmd, &result)) { fprintf(stderr, "failed to report zones, result %x\n", le32_to_cpu(result)); free(zr); @@ -62,17 +68,16 @@ static void show_zns_properties(nvme_ns_t n) int main() { + struct nvme_global_ctx *ctx; nvme_subsystem_t s; - nvme_root_t r; nvme_host_t h; nvme_ctrl_t c; nvme_ns_t n; - r = nvme_scan(NULL); - if (!r) + if (nvme_scan(NULL, &ctx)) return -1; - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { nvme_subsystem_for_each_ctrl(s, c) { nvme_ctrl_for_each_ns(c, n) { @@ -86,5 +91,5 @@ int main() } } } - nvme_free_tree(r); + nvme_free_global_ctx(ctx); } diff --git a/logging.c b/logging.c index e037a851aa..a8b1bd16cd 100644 --- a/logging.c +++ b/logging.c @@ -107,7 +107,7 @@ static void nvme_log_retry(int errnum) printf("passthru command returned '%s'\n", strerror(errnum)); } -int nvme_submit_passthru(int fd, unsigned long ioctl_cmd, +int nvme_submit_passthru(struct nvme_transport_handle *hdl, unsigned long ioctl_cmd, struct nvme_passthru_cmd *cmd, __u32 *result) { struct timeval start; @@ -119,7 +119,7 @@ int nvme_submit_passthru(int fd, unsigned long ioctl_cmd, if (!nvme_cfg.dry_run) { retry: - err = ioctl(fd, ioctl_cmd, cmd); + err = ioctl(nvme_transport_handle_get_fd(hdl), ioctl_cmd, cmd); if ((err && (errno == EAGAIN || (errno == EINTR && !nvme_sigint_received))) && !nvme_cfg.no_retries) { @@ -140,7 +140,7 @@ int nvme_submit_passthru(int fd, unsigned long ioctl_cmd, return err; } -int nvme_submit_passthru64(int fd, unsigned long ioctl_cmd, +int nvme_submit_passthru64(struct nvme_transport_handle *hdl, unsigned long ioctl_cmd, struct nvme_passthru_cmd64 *cmd, __u64 *result) { @@ -153,7 +153,7 @@ int nvme_submit_passthru64(int fd, unsigned long ioctl_cmd, if (!nvme_cfg.dry_run) { retry: - err = ioctl(fd, ioctl_cmd, cmd); + err = ioctl(nvme_transport_handle_get_fd(hdl), ioctl_cmd, cmd); if ((err && (errno == EAGAIN || (errno == EINTR && !nvme_sigint_received))) && !nvme_cfg.no_retries) { diff --git a/meson.build b/meson.build index 37372f045f..cf0a0d4dc0 100644 --- a/meson.build +++ b/meson.build @@ -51,8 +51,6 @@ conf.set('RUNDIR', '"@0@"'.format(rundir)) # Check for libnvme availability libnvme_dep = dependency('libnvme', version: '>=1.16', required: true, fallback : ['libnvme', 'libnvme_dep']) -libnvme_mi_dep = dependency('libnvme-mi', required: true, - fallback : ['libnvme', 'libnvme_mi_dep']) # Check for libjson-c availability if get_option('json-c').disabled() @@ -296,7 +294,6 @@ sources = [ 'nvme-print-stdout.c', 'nvme-print-binary.c', 'nvme-rpmb.c', - 'nvme-wrap.c', 'plugin.c', 'libnvme-wrap.c', 'logging.c', @@ -319,7 +316,7 @@ subdir('Documentation') executable( 'nvme', sources, - dependencies: [ libnvme_dep, libnvme_mi_dep, json_c_dep ], + dependencies: [ libnvme_dep, json_c_dep ], link_args: '-ldl', include_directories: incdir, install: true, diff --git a/nbft.c b/nbft.c index b5c82b07ca..f683f2dfa4 100644 --- a/nbft.c +++ b/nbft.c @@ -103,8 +103,7 @@ static bool validate_uri(struct nbft_info_discovery *dd, return true; } -/* returns 0 for success or negative errno otherwise */ -static int do_connect(nvme_root_t r, +static int do_connect(struct nvme_global_ctx *ctx, nvme_host_t h, struct nvmf_disc_log_entry *e, struct nbft_info_subsystem_ns *ss, @@ -124,18 +123,18 @@ static int do_connect(nvme_root_t r, if (c && nvme_ctrl_get_name(c)) return 0; - c = nvme_create_ctrl(r, trcfg->subsysnqn, trcfg->transport, + ret = nvme_create_ctrl(ctx, trcfg->subsysnqn, trcfg->transport, trcfg->traddr, trcfg->host_traddr, - trcfg->host_iface, trcfg->trsvcid); - if (!c) - return -ENOMEM; + trcfg->host_iface, trcfg->trsvcid, &c); + if (ret) + return ret; /* Pause logging for unavailable SSNSs */ if (ss && ss->unavailable && verbose < 1) { - saved_log_level = nvme_get_logging_level(r, + saved_log_level = nvme_get_logging_level(ctx, &saved_log_pid, &saved_log_tstamp); - nvme_init_logging(r, -1, false, false); + nvme_init_logging(ctx, -1, false, false); } if (e) { @@ -144,17 +143,16 @@ static int do_connect(nvme_root_t r, cfg->tls = true; } - errno = 0; ret = nvmf_add_ctrl(h, c, cfg); /* Resume logging */ if (ss && ss->unavailable && verbose < 1) - nvme_init_logging(r, + nvme_init_logging(ctx, saved_log_level, saved_log_pid, saved_log_tstamp); - if (ret == -1) { + if (ret) { nvme_free_ctrl(c); /* * In case this SSNS was marked as 'unavailable' and @@ -167,7 +165,7 @@ static int do_connect(nvme_root_t r, ss->index); return 0; } - return -errno; + return ret; } if (flags == NORMAL) @@ -179,7 +177,7 @@ static int do_connect(nvme_root_t r, } static int do_discover(struct nbft_info_discovery *dd, - nvme_root_t r, + struct nvme_global_ctx *ctx, nvme_host_t h, nvme_ctrl_t c, struct nvme_fabrics_config *defcfg, @@ -188,8 +186,8 @@ static int do_discover(struct nbft_info_discovery *dd, unsigned int verbose) { struct nvmf_discovery_log *log = NULL; - int i; int ret; + int i; struct nvme_get_discovery_args args = { .c = c, @@ -200,12 +198,12 @@ static int do_discover(struct nbft_info_discovery *dd, .lsp = 0, }; - log = nvmf_get_discovery_wargs(&args); - if (!log) { + ret = nvmf_get_discovery_wargs(&args, &log); + if (ret) { fprintf(stderr, "Discovery Descriptor %d: failed to get discovery log: %s\n", - dd->index, nvme_strerror(errno)); - return -errno; + dd->index, nvme_strerror(ret)); + return ret; } for (i = 0; i < le64_to_cpu(log->numrec); i++) { @@ -238,13 +236,15 @@ static int do_discover(struct nbft_info_discovery *dd, if (e->subtype == NVME_NQN_DISC) { nvme_ctrl_t child; - child = nvmf_connect_disc_entry(h, e, defcfg, NULL); - do_discover(dd, r, h, child, defcfg, &trcfg, + ret = nvmf_connect_disc_entry(h, e, defcfg, NULL, &child); + if (ret) + continue; + do_discover(dd, ctx, h, child, defcfg, &trcfg, flags, verbose); nvme_disconnect_ctrl(child); nvme_free_ctrl(child); } else { - ret = do_connect(r, h, e, NULL, &trcfg, + ret = do_connect(ctx, h, e, NULL, &trcfg, defcfg, flags, verbose); /* @@ -258,7 +258,7 @@ static int do_discover(struct nbft_info_discovery *dd, const char *htradr = trcfg.host_traddr; trcfg.host_traddr = NULL; - ret = do_connect(r, h, e, NULL, &trcfg, + ret = do_connect(ctx, h, e, NULL, &trcfg, defcfg, flags, verbose); if (ret == 0 && verbose >= 1) @@ -282,9 +282,8 @@ static int do_discover(struct nbft_info_discovery *dd, return 0; } -/* returns negative errno values */ -int discover_from_nbft(nvme_root_t r, char *hostnqn_arg, char *hostid_arg, - char *hostnqn_sys, char *hostid_sys, +int discover_from_nbft(struct nvme_global_ctx *ctx, char *hostnqn_arg, + char *hostid_arg, char *hostnqn_sys, char *hostid_sys, const char *desc, bool connect, struct nvme_fabrics_config *cfg, char *nbft_path, nvme_print_flags_t flags, unsigned int verbose) @@ -329,7 +328,7 @@ int discover_from_nbft(nvme_root_t r, char *hostnqn_arg, char *hostid_arg, hostid = hostid_sys; } - h = nvme_lookup_host(r, hostnqn, hostid); + h = nvme_lookup_host(ctx, hostnqn, hostid); if (!h) { ret = -ENOENT; goto out_free; @@ -363,7 +362,7 @@ int discover_from_nbft(nvme_root_t r, char *hostnqn_arg, char *hostid_arg, .trsvcid = (*ss)->trsvcid, }; - rr = do_connect(r, h, NULL, *ss, &trcfg, + rr = do_connect(ctx, h, NULL, *ss, &trcfg, cfg, flags, verbose); /* @@ -376,7 +375,7 @@ int discover_from_nbft(nvme_root_t r, char *hostnqn_arg, char *hostid_arg, strlen(hfi->tcp_info.dhcp_server_ipaddr) > 0) { trcfg.host_traddr = NULL; - rr = do_connect(r, h, NULL, *ss, &trcfg, + rr = do_connect(ctx, h, NULL, *ss, &trcfg, cfg, flags, verbose); if (rr == 0 && verbose >= 1) @@ -421,7 +420,9 @@ int discover_from_nbft(nvme_root_t r, char *hostnqn_arg, char *hostid_arg, continue; hfi = (*dd)->hfi; - uri = nvme_parse_uri((*dd)->uri); + ret = nvme_parse_uri((*dd)->uri, &uri); + if (ret) + continue; if (!validate_uri(*dd, uri)) continue; @@ -452,28 +453,24 @@ int discover_from_nbft(nvme_root_t r, char *hostnqn_arg, char *hostid_arg, persistent = true; if (!c) { - c = nvmf_create_discover_ctrl(r, h, cfg, &trcfg); - if (!c && errno == ENVME_CONNECT_ADDRNOTAVAIL && + ret = nvmf_create_discover_ctrl(ctx, h, cfg, &trcfg, &c); + if (ret == -ENVME_CONNECT_ADDRNOTAVAIL && !strcmp(trcfg.transport, "tcp") && strlen(hfi->tcp_info.dhcp_server_ipaddr) > 0) { trcfg.host_traddr = NULL; - c = nvmf_create_discover_ctrl(r, h, cfg, &trcfg); + ret = nvmf_create_discover_ctrl(ctx, h, cfg, &trcfg, &c); } - } + } else + ret = 0; - if (!c) { + if (ret) { fprintf(stderr, "Discovery Descriptor %d: failed to add discovery controller: %s\n", - (*dd)->index, - nvme_strerror(errno)); - if (errno == ENOMEM) { - ret = -ENOMEM; - goto out_free; - } - continue; + (*dd)->index, nvme_strerror(-ret)); + goto out_free; } - rr = do_discover(*dd, r, h, c, cfg, &trcfg, + rr = do_discover(*dd, ctx, h, c, cfg, &trcfg, flags, verbose); if (!persistent) nvme_disconnect_ctrl(c); diff --git a/nbft.h b/nbft.h index 88e0f357ae..412ce67f6e 100644 --- a/nbft.h +++ b/nbft.h @@ -12,8 +12,8 @@ struct nbft_file_entry { int read_nbft_files(struct list_head *nbft_list, char *path); void free_nbfts(struct list_head *nbft_list); -extern int discover_from_nbft(nvme_root_t r, char *hostnqn_arg, char *hostid_arg, - char *hostnqn_sys, char *hostid_sys, - const char *desc, bool connect, +extern int discover_from_nbft(struct nvme_global_ctx *ctx, char *hostnqn_arg, + char *hostid_arg, char *hostnqn_sys, + char *hostid_sys, const char *desc, bool connect, struct nvme_fabrics_config *cfg, char *nbft_path, nvme_print_flags_t flags, unsigned int verbose); diff --git a/nvme-print-json.c b/nvme-print-json.c index bb94dad670..b3ad275f68 100644 --- a/nvme-print-json.c +++ b/nvme-print-json.c @@ -1781,7 +1781,7 @@ static void json_pel_set_feature(void *pevent_log_info, __u32 offset, struct json_object *valid_attrs) { struct nvme_set_feature_event *set_feat_event = pevent_log_info + offset; - int fid = NVME_GET(le32_to_cpu(set_feat_event->cdw_mem[0]), FEATURES_CDW10_FID); + int fid = NVME_GET(le32_to_cpu(set_feat_event->cdw_mem[0]), SET_FEATURES_CDW10_FID); int cdw11 = le32_to_cpu(set_feat_event->cdw_mem[1]); int dword_cnt = NVME_SET_FEAT_EVENT_DW_COUNT(set_feat_event->layout); unsigned char *mem_buf; @@ -2611,14 +2611,15 @@ static void json_print_nvme_subsystem_ctrls(nvme_subsystem_t s, } } -static void json_print_nvme_subsystem_list(nvme_root_t r, bool show_ana) +static void json_print_nvme_subsystem_list(struct nvme_global_ctx *ctx, + bool show_ana) { struct json_object *host_attrs, *subsystem_attrs; struct json_object *subsystems, *paths; struct json_object *a = json_create_array(); nvme_host_t h; - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_subsystem_t s; const char *hostid; @@ -4519,7 +4520,7 @@ static void json_print_detail_list(nvme_subsystem_t s, struct json_object *jss) obj_add_obj(jss, "Controllers", jctrls); } -static void json_detail_list_v2(nvme_root_t t) +static void json_detail_list_v2(struct nvme_global_ctx *ctx) { struct json_object *r = json_create_object(); struct json_object *jdev = json_create_array(); @@ -4527,7 +4528,7 @@ static void json_detail_list_v2(nvme_root_t t) nvme_host_t h; nvme_subsystem_t s; - nvme_for_each_host(t, h) { + nvme_for_each_host(ctx, h) { struct json_object *hss = json_create_object(); struct json_object *jsslist = json_create_array(); const char *hostid; @@ -4560,7 +4561,7 @@ static void json_detail_list_v2(nvme_root_t t) json_print(r); } -static void json_detail_list(nvme_root_t t) +static void json_detail_list(struct nvme_global_ctx *ctx) { struct json_object *r = json_create_object(); struct json_object *jdev = json_create_array(); @@ -4571,7 +4572,7 @@ static void json_detail_list(nvme_root_t t) nvme_path_t p; nvme_ns_t n; - nvme_for_each_host(t, h) { + nvme_for_each_host(ctx, h) { struct json_object *hss = json_create_object(); struct json_object *jsslist = json_create_array(); const char *hostid; @@ -4692,7 +4693,7 @@ static struct json_object *json_list_item_obj(nvme_ns_t n) return r; } -static void json_simple_list(nvme_root_t t) +static void json_simple_list(struct nvme_global_ctx *ctx) { struct json_object *r = json_create_object(); struct json_object *jdevices = json_create_array(); @@ -4702,7 +4703,7 @@ static void json_simple_list(nvme_root_t t) nvme_ctrl_t c; nvme_ns_t n; - nvme_for_each_host(t, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { nvme_subsystem_for_each_ns(s, n) array_add_obj(jdevices, json_list_item_obj(n)); @@ -4726,15 +4727,15 @@ static void json_list_item(nvme_ns_t n, struct table *t) json_print(r); } -static void json_print_list_items(nvme_root_t t) +static void json_print_list_items(struct nvme_global_ctx *ctx) { if (json_print_ops.flags & VERBOSE) { if (nvme_cfg.output_format_ver == 2) - json_detail_list_v2(t); + json_detail_list_v2(ctx); else - json_detail_list(t); + json_detail_list(ctx); } else - json_simple_list(t); + json_simple_list(ctx); } static unsigned int json_subsystem_topology_multipath(nvme_subsystem_t s, @@ -4829,14 +4830,14 @@ static void json_print_nvme_subsystem_topology(nvme_subsystem_t s, } } -static void json_simple_topology(nvme_root_t r) +static void json_simple_topology(struct nvme_global_ctx *ctx) { struct json_object *host_attrs, *subsystem_attrs; struct json_object *subsystems, *namespaces; struct json_object *a = json_create_array(); nvme_host_t h; - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_subsystem_t s; const char *hostid; @@ -4919,7 +4920,7 @@ static void json_directive_show_fields_identify(__u8 doper, __u8 *field, struct } } -static void json_directive_show_fields_streams(__u8 doper, unsigned int result, __u16 *field, +static void json_directive_show_fields_streams(__u8 doper, unsigned int result, __u16 *field, struct json_object *r) { int count; diff --git a/nvme-print-stdout.c b/nvme-print-stdout.c index e7a7dfb95f..d5437e6172 100644 --- a/nvme-print-stdout.c +++ b/nvme-print-stdout.c @@ -105,7 +105,7 @@ static void htable_ns_add_unique(struct htable_ns *ht, nvme_ns_t n) } struct nvme_resources { - nvme_root_t r; + struct nvme_global_ctx *ctx; struct htable_subsys ht_s; struct htable_ctrl ht_c; @@ -120,7 +120,7 @@ struct nvme_resources_table { struct table *t; }; -static int nvme_resources_init(nvme_root_t r, struct nvme_resources *res) +static int nvme_resources_init(struct nvme_global_ctx *ctx, struct nvme_resources *res) { nvme_host_t h; nvme_subsystem_t s; @@ -128,7 +128,7 @@ static int nvme_resources_init(nvme_root_t r, struct nvme_resources *res) nvme_ns_t n; nvme_path_t p; - res->r = r; + res->ctx = ctx; htable_subsys_init(&res->ht_s); htable_ctrl_init(&res->ht_c); htable_ns_init(&res->ht_n); @@ -136,7 +136,7 @@ static int nvme_resources_init(nvme_root_t r, struct nvme_resources *res) strset_init(&res->ctrls); strset_init(&res->namespaces); - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { htable_subsys_add(&res->ht_s, s); strset_add(&res->subsystems, nvme_subsystem_get_name(s)); @@ -466,7 +466,7 @@ static void pel_set_feature_event(void *pevent_log_info, __u32 offset) printf("Set Feature Event Entry:\n"); dword_cnt = NVME_SET_FEAT_EVENT_DW_COUNT(set_feat_event->layout); - fid = NVME_GET(le32_to_cpu(set_feat_event->cdw_mem[0]), FEATURES_CDW10_FID); + fid = NVME_GET(le32_to_cpu(set_feat_event->cdw_mem[0]), SET_FEATURES_CDW10_FID); cdw11 = le32_to_cpu(set_feat_event->cdw_mem[1]); printf("Set Feature ID: 0x%02x (%s), value: 0x%08x\n", fid, nvme_feature_to_string(fid), @@ -1158,12 +1158,12 @@ static void stdout_subsys_config(nvme_subsystem_t s) } } -static void stdout_subsystem(nvme_root_t r, bool show_ana) +static void stdout_subsystem(struct nvme_global_ctx *ctx, bool show_ana) { nvme_host_t h; bool first = true; - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_subsystem_t s; nvme_for_each_subsystem(h, s) { @@ -1188,9 +1188,9 @@ static void stdout_subsystem(nvme_root_t r, bool show_ana) } } -static void stdout_subsystem_list(nvme_root_t r, bool show_ana) +static void stdout_subsystem_list(struct nvme_global_ctx *ctx, bool show_ana) { - stdout_subsystem(r, show_ana); + stdout_subsystem(ctx, show_ana); } static void stdout_registers_cap(struct nvme_bar_cap *cap) @@ -4324,7 +4324,7 @@ static void stdout_support_log_human(__u32 support, __u8 lid) printf(" Establish Context and Read 512 Bytes of Header is %s\n", (lidsp & 0x1) ? set : clr); break; - case NVME_LOG_LID_DISCOVER: + case NVME_LOG_LID_DISCOVERY: printf(" Extended Discovery Log Page Entry is %s\n", (lidsp & 0x1) ? set : clr); printf(" Port Local Entries Only is %s\n", @@ -4332,7 +4332,7 @@ static void stdout_support_log_human(__u32 support, __u8 lid) printf(" All NVM Subsystem Entries is %s\n", (lidsp & 0x4) ? set : clr); break; - case NVME_LOG_LID_HOST_DISCOVER: + case NVME_LOG_LID_HOST_DISCOVERY: printf(" All Host Entries is %s\n", (lidsp & 0x1) ? set : clr); break; @@ -5176,7 +5176,7 @@ static void stdout_feature_show_fields(enum nvme_features_id fid, break; case NVME_FEAT_FID_PLM_CONFIG: printf("\tPredictable Latency Window Enabled: %s\n", - NVME_FEAT_PLM_PLME(result) ? "True" : "False"); + NVME_FEAT_PLM_LPE(result) ? "True" : "False"); if (buf) stdout_plm_config((struct nvme_plm_config *)buf); break; @@ -5460,7 +5460,7 @@ static bool stdout_simple_ns(const char *name, void *arg) return true; } -static void stdout_simple_list(nvme_root_t r) +static void stdout_simple_list(struct nvme_global_ctx *ctx) { struct nvme_resources res; struct table_column columns[] = { @@ -5481,7 +5481,7 @@ static void stdout_simple_list(nvme_root_t r) return; } - nvme_resources_init(r, &res); + nvme_resources_init(ctx, &res); strset_iterate(&res.namespaces, stdout_simple_ns, &res_t); @@ -5646,11 +5646,11 @@ static bool stdout_detailed_ns(const char *name, void *arg) return true; } -static void stdout_detailed_list(nvme_root_t r) +static void stdout_detailed_list(struct nvme_global_ctx *ctx) { struct nvme_resources res; - nvme_resources_init(r, &res); + nvme_resources_init(ctx, &res); printf("%-16s %-96s %-.16s\n", "Subsystem", "Subsystem-NQN", "Controllers"); printf("%-.16s %-.96s %-.16s\n", dash, dash, dash); @@ -5674,12 +5674,12 @@ static void stdout_detailed_list(nvme_root_t r) nvme_resources_free(&res); } -static void stdout_list_items(nvme_root_t r) +static void stdout_list_items(struct nvme_global_ctx *ctx) { if (stdout_print_ops.flags & VERBOSE) - stdout_detailed_list(r); + stdout_detailed_list(ctx); else - stdout_simple_list(r); + stdout_simple_list(ctx); } static bool subsystem_iopolicy_filter(const char *name, void *arg) @@ -6022,13 +6022,13 @@ static void stdout_subsystem_topology(nvme_subsystem_t s, } } -static void stdout_topology_tabular(nvme_root_t r) +static void stdout_topology_tabular(struct nvme_global_ctx *ctx) { nvme_host_t h; nvme_subsystem_t s; bool first = true; - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { bool no_ctrl = true; nvme_ctrl_t c; @@ -6054,14 +6054,14 @@ static void stdout_topology_tabular(nvme_root_t r) } } -static void stdout_simple_topology(nvme_root_t r, +static void stdout_simple_topology(struct nvme_global_ctx *ctx, enum nvme_cli_topo_ranking ranking) { nvme_host_t h; nvme_subsystem_t s; bool first = true; - nvme_for_each_host(r, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { bool no_ctrl = true; nvme_ctrl_t c; @@ -6087,19 +6087,19 @@ static void stdout_simple_topology(nvme_root_t r, } } -static void stdout_topology_namespace(nvme_root_t r) +static void stdout_topology_namespace(struct nvme_global_ctx *ctx) { - stdout_simple_topology(r, NVME_CLI_TOPO_NAMESPACE); + stdout_simple_topology(ctx, NVME_CLI_TOPO_NAMESPACE); } -static void stdout_topology_ctrl(nvme_root_t r) +static void stdout_topology_ctrl(struct nvme_global_ctx *ctx) { - stdout_simple_topology(r, NVME_CLI_TOPO_CTRL); + stdout_simple_topology(ctx, NVME_CLI_TOPO_CTRL); } -static void stdout_topology_multipath(nvme_root_t r) +static void stdout_topology_multipath(struct nvme_global_ctx *ctx) { - stdout_simple_topology(r, NVME_CLI_TOPO_MULTIPATH); + stdout_simple_topology(ctx, NVME_CLI_TOPO_MULTIPATH); } static void stdout_message(bool error, const char *msg, va_list ap) @@ -6387,7 +6387,7 @@ static void stdout_pull_model_ddc_req_log(struct nvme_pull_model_ddc_req_log *lo d((unsigned char *)log->osp, osp_len, 16, 1); } -static void stdout_relatives(nvme_root_t r, const char *name) +static void stdout_relatives(struct nvme_global_ctx *ctx, const char *name) { struct nvme_resources res; struct htable_ns_iter it; @@ -6412,7 +6412,7 @@ static void stdout_relatives(nvme_root_t r, const char *name) return; } - nvme_resources_init(r, &res); + nvme_resources_init(ctx, &res); if (block) { fprintf(stderr, "Namespace %s has parent controller(s):", name); @@ -6546,7 +6546,7 @@ static void stdout_log(const char *devname, struct nvme_get_log_args *args) case NVME_LOG_LID_REACHABILITY_ASSOCIATIONS: stdout_reachability_associations_log(reachability_associations_log, args->len); break; - case NVME_LOG_LID_CHANGED_ALLOC_NS_LIST: + case NVME_LOG_LID_CHANGED_ALLOC_NS: stdout_changed_ns_list_log((struct nvme_ns_list *)args->log, devname, true); break; case NVME_LOG_LID_FDP_CONFIGS: @@ -6561,13 +6561,13 @@ static void stdout_log(const char *devname, struct nvme_get_log_args *args) case NVME_LOG_LID_FDP_EVENTS: stdout_fdp_events((struct nvme_fdp_events_log *)args->log); break; - case NVME_LOG_LID_DISCOVER: + case NVME_LOG_LID_DISCOVERY: stdout_discovery_log(discovery_log, le64_to_cpu(discovery_log->numrec)); break; - case NVME_LOG_LID_HOST_DISCOVER: + case NVME_LOG_LID_HOST_DISCOVERY: stdout_host_discovery_log((struct nvme_host_discover_log *)args->log); break; - case NVME_LOG_LID_AVE_DISCOVER: + case NVME_LOG_LID_AVE_DISCOVERY: stdout_ave_discovery_log((struct nvme_ave_discover_log *)args->log); break; case NVME_LOG_LID_PULL_MODEL_DDC_REQ: diff --git a/nvme-print.c b/nvme-print.c index d1448348e7..1bdcbb27bc 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -376,10 +376,10 @@ void nvme_show_supported_cap_config_log( nvme_print(supported_cap_config_list_log, flags, cap); } -void nvme_show_subsystem_list(nvme_root_t r, bool show_ana, +void nvme_show_subsystem_list(struct nvme_global_ctx *ctx, bool show_ana, nvme_print_flags_t flags) { - nvme_print(print_nvme_subsystem_list, flags, r, show_ana); + nvme_print(print_nvme_subsystem_list, flags, ctx, show_ana); } const char *nvme_register_szu_to_string(__u8 szu) @@ -491,9 +491,10 @@ void nvme_show_single_property(int offset, uint64_t value64, nvme_print_flags_t nvme_print(single_property, flags, offset, value64); } -void nvme_show_relatives(nvme_root_t r, const char *name, nvme_print_flags_t flags) +void nvme_show_relatives(struct nvme_global_ctx *ctx, const char *name, + nvme_print_flags_t flags) { - nvme_print(relatives, flags, r, name); + nvme_print(relatives, flags, ctx, name); } void d(unsigned char *buf, int len, int width, int group) @@ -786,14 +787,14 @@ const char *nvme_log_to_string(__u8 lid) case NVME_LOG_LID_PHY_RX_EOM: return "Physical Interface Receiver Eye Opening Measurement"; case NVME_LOG_LID_REACHABILITY_GROUPS: return "Reachability Groups"; case NVME_LOG_LID_REACHABILITY_ASSOCIATIONS: return "Reachability Associations"; - case NVME_LOG_LID_CHANGED_ALLOC_NS_LIST: return "Changed Allocated Namespace List"; + case NVME_LOG_LID_CHANGED_ALLOC_NS: return "Changed Allocated Namespace List"; case NVME_LOG_LID_FDP_CONFIGS: return "FDP Configurations"; case NVME_LOG_LID_FDP_RUH_USAGE: return "Reclaim Unit Handle Usage"; case NVME_LOG_LID_FDP_STATS: return "FDP Statistics"; case NVME_LOG_LID_FDP_EVENTS: return "FDP Events"; - case NVME_LOG_LID_DISCOVER: return "Discovery"; - case NVME_LOG_LID_HOST_DISCOVER: return "Host Discovery"; - case NVME_LOG_LID_AVE_DISCOVER: return "AVE Discovery"; + case NVME_LOG_LID_DISCOVERY: return "Discovery"; + case NVME_LOG_LID_HOST_DISCOVERY: return "Host Discovery"; + case NVME_LOG_LID_AVE_DISCOVERY: return "AVE Discovery"; case NVME_LOG_LID_PULL_MODEL_DDC_REQ: return "Pull Model DDC Request"; case NVME_LOG_LID_RESERVATION: return "Reservation Notification"; case NVME_LOG_LID_SANITIZE: return "Sanitize Status"; @@ -1509,26 +1510,26 @@ void nvme_show_list_item(nvme_ns_t n, struct table *t) nvme_print(list_item, NORMAL, n, t); } -void nvme_show_list_items(nvme_root_t r, nvme_print_flags_t flags) +void nvme_show_list_items(struct nvme_global_ctx *ctx, nvme_print_flags_t flags) { - nvme_print(list_items, flags, r); + nvme_print(list_items, flags, ctx); } -void nvme_show_topology(nvme_root_t r, +void nvme_show_topology(struct nvme_global_ctx *ctx, enum nvme_cli_topo_ranking ranking, nvme_print_flags_t flags) { if (ranking == NVME_CLI_TOPO_NAMESPACE) - nvme_print(topology_namespace, flags, r); + nvme_print(topology_namespace, flags, ctx); else if (ranking == NVME_CLI_TOPO_CTRL) - nvme_print(topology_ctrl, flags, r); + nvme_print(topology_ctrl, flags, ctx); else - nvme_print(topology_multipath, flags, r); + nvme_print(topology_multipath, flags, ctx); } -void nvme_show_topology_tabular(nvme_root_t r, nvme_print_flags_t flags) +void nvme_show_topology_tabular(struct nvme_global_ctx *ctx, nvme_print_flags_t flags) { - nvme_print(topology_tabular, flags, r); + nvme_print(topology_tabular, flags, ctx); } void nvme_show_message(bool error, const char *msg, ...) diff --git a/nvme-print.h b/nvme-print.h index edb57fa4c1..708e8cd330 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -3,6 +3,7 @@ #define NVME_PRINT_H #include "nvme.h" +#include "types.h" #include "util/table.h" #include @@ -65,7 +66,7 @@ struct print_ops { void (*predictable_latency_event_agg_log)(struct nvme_aggregate_predictable_lat_event *pea_log, __u64 log_entries, __u32 size, const char *devname); void (*predictable_latency_per_nvmset)(struct nvme_nvmset_predictable_lat_log *plpns_log, __u16 nvmset_id, const char *devname); void (*primary_ctrl_cap)(const struct nvme_primary_ctrl_cap *caps); - void (*relatives)(nvme_root_t r, const char *name); + void (*relatives)(struct nvme_global_ctx *ctx, const char *name); void (*resv_notification_log)(struct nvme_resv_notification_log *resv, const char *devname); void (*resv_report)(struct nvme_resv_status *status, int bytes, bool eds); void (*sanitize_log_page)(struct nvme_sanitize_log_page *sanitize_log, const char *devname); @@ -103,12 +104,12 @@ struct print_ops { /* libnvme tree print functions */ void (*list_item)(nvme_ns_t n, struct table *t); - void (*list_items)(nvme_root_t t); - void (*print_nvme_subsystem_list)(nvme_root_t r, bool show_ana); - void (*topology_ctrl)(nvme_root_t r); - void (*topology_namespace)(nvme_root_t r); - void (*topology_multipath)(nvme_root_t r); - void (*topology_tabular)(nvme_root_t r); + void (*list_items)(struct nvme_global_ctx *ctx); + void (*print_nvme_subsystem_list)(struct nvme_global_ctx *ctx, bool show_ana); + void (*topology_ctrl)(struct nvme_global_ctx *ctx); + void (*topology_namespace)(struct nvme_global_ctx *ctx); + void (*topology_multipath)(struct nvme_global_ctx *ctx); + void (*topology_tabular)(struct nvme_global_ctx *ctx); /* status and error messages */ void (*connect_msg)(nvme_ctrl_t c); @@ -158,7 +159,7 @@ struct print_ops *nvme_get_binary_print_ops(nvme_print_flags_t flags); void nvme_show_status(int status); void nvme_show_lba_status_info(__u32 result); -void nvme_show_relatives(nvme_root_t r, const char *name, nvme_print_flags_t flags); +void nvme_show_relatives(struct nvme_global_ctx *ctx, const char *name, nvme_print_flags_t flags); void nvme_show_id_iocs(struct nvme_id_iocs *iocs, nvme_print_flags_t flags); void nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, nvme_print_flags_t flags, @@ -229,8 +230,8 @@ void nvme_show_single_property(int offset, uint64_t prop, nvme_print_flags_t fla void nvme_show_id_ns_descs(void *data, unsigned int nsid, nvme_print_flags_t flags); void nvme_show_lba_status(struct nvme_lba_status *list, unsigned long len, nvme_print_flags_t flags); -void nvme_show_list_items(nvme_root_t t, nvme_print_flags_t flags); -void nvme_show_subsystem_list(nvme_root_t t, bool show_ana, +void nvme_show_list_items(struct nvme_global_ctx *ctx, nvme_print_flags_t flags); +void nvme_show_subsystem_list(struct nvme_global_ctx *ctx, bool show_ana, nvme_print_flags_t flags); void nvme_show_id_nvmset(struct nvme_id_nvmset_list *nvmset, unsigned nvmset_id, nvme_print_flags_t flags); @@ -250,10 +251,10 @@ void nvme_show_endurance_group_list(struct nvme_id_endurance_group_list *endgrp_ nvme_print_flags_t flags); void nvme_show_list_ns(struct nvme_ns_list *ns_list, nvme_print_flags_t flags); -void nvme_show_topology(nvme_root_t t, +void nvme_show_topology(struct nvme_global_ctx *ctx, enum nvme_cli_topo_ranking ranking, nvme_print_flags_t flags); -void nvme_show_topology_tabular(nvme_root_t t, nvme_print_flags_t flags); +void nvme_show_topology_tabular(struct nvme_global_ctx *ctx, nvme_print_flags_t flags); void nvme_feature_show(enum nvme_features_id fid, int sel, unsigned int result); void nvme_feature_show_fields(enum nvme_features_id fid, unsigned int result, unsigned char *buf); diff --git a/nvme-rpmb.c b/nvme-rpmb.c index ece313c29a..040781725c 100644 --- a/nvme-rpmb.c +++ b/nvme-rpmb.c @@ -132,8 +132,8 @@ unsigned char *create_hash(const char *algo, /* Function that computes hmac-sha256 hash of given data and key pair. Returns * byte stream (non-null terminated) upon success, NULL otherwise. */ -unsigned char * -hmac_sha256(unsigned char *data, int datalen, unsigned char *key, int keylen) +unsigned char *hmac_sha256(unsigned char *data, int datalen, unsigned char *key, + int keylen) { return create_hash(HMAC_SHA256_ALGO_NAME, HMAC_SHA256_HASH_SIZE, @@ -146,8 +146,7 @@ hmac_sha256(unsigned char *data, int datalen, unsigned char *key, int keylen) /* Function that computes md5 of given buffer - md5 hash is used as nonce * Returns byte stream (non-null terminated) upon success, NULL otherwise. */ -unsigned char * -rpmb_md5(unsigned char *data, int datalen) +unsigned char *rpmb_md5(unsigned char *data, int datalen) { return create_hash(MD5_HASH_ALGO_NAME, MD5_HASH_HASH_SIZE, @@ -204,7 +203,7 @@ static int read_file(const char *file, unsigned char **data, unsigned int *len) /* Write given buffer data to specified file */ static void write_file(unsigned char *data, size_t len, const char *dir, - const char *file, const char *msg) + const char *file, const char *msg) { char temp_folder[PATH_MAX] = { 0 }; _cleanup_file_ FILE *fp = NULL; @@ -272,47 +271,24 @@ struct rpmb_config_block_t { #define RPMB_NVME_SECP 0xEA #define RPMB_NVME_SPSP 0x0001 -static int send_rpmb_req(int fd, unsigned char tgt, int size, - struct rpmb_data_frame_t *req) +static int send_rpmb_req(struct nvme_transport_handle *hdl, unsigned char tgt, + int size, struct rpmb_data_frame_t *req) { - struct nvme_security_send_args args = { - .args_size = sizeof(args), - .fd = fd, - .nsid = 0, - .nssf = tgt, - .spsp0 = RPMB_NVME_SPSP, - .spsp1 = 0, - .secp = RPMB_NVME_SECP, - .tl = 0, - .data_len = size, - .data = (void *)req, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; + struct nvme_passthru_cmd cmd; - return nvme_security_send(&args); + nvme_init_security_send(&cmd, NVME_NSID_NONE, tgt, RPMB_NVME_SPSP, + RPMB_NVME_SECP, 0, req, size); + return nvme_submit_admin_passthru(hdl, &cmd, NULL); } -static int recv_rpmb_rsp(int fd, int tgt, int size, +static int recv_rpmb_rsp(struct nvme_transport_handle *hdl, int tgt, int size, struct rpmb_data_frame_t *rsp) { + struct nvme_passthru_cmd cmd; - struct nvme_security_receive_args args = { - .args_size = sizeof(args), - .fd = fd, - .nsid = 0, - .nssf = tgt, - .spsp0 = RPMB_NVME_SPSP, - .spsp1 = 0, - .secp = RPMB_NVME_SECP, - .al = 0, - .data_len = size, - .data = (void *)rsp, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - - return nvme_security_receive(&args); + nvme_init_security_receive(&cmd, 0, tgt, RPMB_NVME_SPSP, + RPMB_NVME_SECP, 0, rsp, size); + return nvme_submit_admin_passthru(hdl, &cmd, NULL); } /* Initialize nonce value in rpmb request frame */ @@ -375,9 +351,8 @@ rpmb_request_init(unsigned int req_size, } /* Process rpmb response and print appropriate error message */ -static int check_rpmb_response( struct rpmb_data_frame_t *req, - struct rpmb_data_frame_t *rsp, - char *msg) +static int check_rpmb_response(struct rpmb_data_frame_t *req, + struct rpmb_data_frame_t *rsp, char *msg) { const char *rpmb_result_string [] = { "Operation successful", @@ -419,10 +394,10 @@ static int check_rpmb_response( struct rpmb_data_frame_t *req, * successful completion (caller must free), NULL otherwise */ static struct rpmb_data_frame_t * -rpmb_read_request(int fd, +rpmb_read_request(struct nvme_transport_handle *hdl, struct rpmb_data_frame_t *req, - int req_size, - int rsp_size) + int req_size, + int rsp_size) { struct rpmb_data_frame_t *rsp = NULL; unsigned char msg[1024] = { 0 }; @@ -431,7 +406,7 @@ rpmb_read_request(int fd, sprintf((char *)msg, "RPMB request 0x%04x to target 0x%x", req->type, req->target); - error = send_rpmb_req(fd, req->target, req_size, req); + error = send_rpmb_req(hdl, req->target, req_size, req); if (error != 0) { fprintf(stderr, "%s failed with error = 0x%x\n", msg, error); @@ -446,7 +421,7 @@ rpmb_read_request(int fd, } /* Read result of previous request */ - error = recv_rpmb_rsp(fd, req->target, rsp_size, rsp); + error = recv_rpmb_rsp(hdl, req->target, rsp_size, rsp); if (error) { fprintf(stderr, "error 0x%x receiving response for %s\n", error, msg); @@ -463,7 +438,7 @@ rpmb_read_request(int fd, } /* read current write counter value from controller */ -static int rpmb_read_write_counter(int fd, +static int rpmb_read_write_counter(struct nvme_transport_handle *hdl, unsigned char target, unsigned int *counter) { @@ -475,7 +450,7 @@ static int rpmb_read_write_counter(int fd, req = rpmb_request_init(req_size, RPMB_REQ_READ_WRITE_CNTR, target, 1, 0, 0, NULL, 0, 0); if (req == NULL) goto out; - if ((rsp = rpmb_read_request(fd, req, req_size, req_size)) == NULL) { + if ((rsp = rpmb_read_request(hdl, req, req_size, req_size)) == NULL) { goto out; } *counter = rsp->write_counter; @@ -491,7 +466,8 @@ static int rpmb_read_write_counter(int fd, * current write counter value returned as part of response, in case of error it * returns 0 */ -static unsigned int rpmb_read_config_block(int fd, unsigned char **config_buf) +static unsigned int rpmb_read_config_block(struct nvme_transport_handle *hdl, + unsigned char **config_buf) { int req_size = sizeof(struct rpmb_data_frame_t); int cfg_size = sizeof(struct rpmb_config_block_t); @@ -507,7 +483,7 @@ static unsigned int rpmb_read_config_block(int fd, unsigned char **config_buf) 0, 0, 0); if (!req) return 0; - if ((rsp = rpmb_read_request(fd, req, req_size, rsp_size)) == NULL) + if ((rsp = rpmb_read_request(hdl, req, req_size, rsp_size)) == NULL) { free(req); return 0; @@ -531,7 +507,8 @@ static unsigned int rpmb_read_config_block(int fd, unsigned char **config_buf) } -static int rpmb_auth_data_read(int fd, unsigned char target, +static int rpmb_auth_data_read(struct nvme_transport_handle *hdl, + unsigned char target, unsigned int offset, unsigned char **msg_buf, int msg_size, int acc_size) @@ -557,7 +534,7 @@ static int rpmb_auth_data_read(int fd, unsigned char target, target, 1, offset, xfer, 0, 0, 0); if (req == NULL) break; - if ((rsp = rpmb_read_request(fd, req, req_size, rsp_size)) == NULL) + if ((rsp = rpmb_read_request(hdl, req, req_size, rsp_size)) == NULL) { fprintf(stderr, "read_request failed\n"); free(req); @@ -583,8 +560,9 @@ static int rpmb_auth_data_read(int fd, unsigned char target, } /* Implementation of programming authentication key to given RPMB target */ -static int rpmb_program_auth_key(int fd, unsigned char target, - unsigned char *key_buf, int key_size) +static int rpmb_program_auth_key(struct nvme_transport_handle *hdl, + unsigned char target, unsigned char *key_buf, + int key_size) { int req_size = sizeof(struct rpmb_data_frame_t); int rsp_size = sizeof(struct rpmb_data_frame_t); @@ -602,7 +580,7 @@ static int rpmb_program_auth_key(int fd, unsigned char target, } /* send the request and get response */ - err = send_rpmb_req(fd, req->target, req_size, req); + err = send_rpmb_req(hdl, req->target, req_size, req); if (err) { fprintf(stderr, "RPMB request 0x%04x for 0x%x, err: %d\n", req->type, req->target, err); @@ -619,7 +597,7 @@ static int rpmb_program_auth_key(int fd, unsigned char target, rsp->target = req->target; rsp->type = RPMB_REQ_READ_RESULT; - err = send_rpmb_req(fd, req->target, rsp_size, rsp); + err = send_rpmb_req(hdl, req->target, rsp_size, rsp); if (err || rsp->result) { fprintf(stderr, "Program auth key read result 0x%x, error = 0x%x\n", rsp->result, err); @@ -628,7 +606,7 @@ static int rpmb_program_auth_key(int fd, unsigned char target, /* reuse response buffer */ memset(rsp, 0, rsp_size); - err = recv_rpmb_rsp(fd, req->target, rsp_size, rsp); + err = recv_rpmb_rsp(hdl, req->target, rsp_size, rsp); if (err != 0) fprintf(stderr, "Program Key recv error = 0x%x\n", err); else @@ -646,7 +624,8 @@ static int rpmb_program_auth_key(int fd, unsigned char target, * number of bytes actually written to, otherwise negetive error code * on failures. */ -static int auth_data_write_chunk(int fd, unsigned char tgt, unsigned int addr, +static int auth_data_write_chunk(struct nvme_transport_handle *hdl, + unsigned char tgt, unsigned int addr, unsigned char *msg_buf, int msg_size, unsigned char *keybuf, int keysize) { @@ -661,7 +640,7 @@ static int auth_data_write_chunk(int fd, unsigned char tgt, unsigned int addr, int error = -ENOMEM; /* get current write counter and copy to the request */ - error = rpmb_read_write_counter(fd, tgt, &write_cntr); + error = rpmb_read_write_counter(hdl, tgt, &write_cntr); if (error != 0) { fprintf(stderr, "Failed to read write counter for write-data\n"); goto out; @@ -689,7 +668,7 @@ static int auth_data_write_chunk(int fd, unsigned char tgt, unsigned int addr, memcpy(req->mac, mac, 32); /* send the request and get response */ - error = send_rpmb_req(fd, tgt, req_size, req); + error = send_rpmb_req(hdl, tgt, req_size, req); if (error != 0) { fprintf(stderr, "RPMB request 0x%04x for 0x%x, error: %d\n", req->type, tgt, error); @@ -700,7 +679,7 @@ static int auth_data_write_chunk(int fd, unsigned char tgt, unsigned int addr, rsp = (struct rpmb_data_frame_t *)calloc(rsp_size, 1); rsp->target = req->target; rsp->type = RPMB_REQ_READ_RESULT; - error = send_rpmb_req(fd, tgt, rsp_size, rsp); + error = send_rpmb_req(hdl, tgt, rsp_size, rsp); if (error != 0 || rsp->result != 0) { fprintf(stderr, "Write-data read result 0x%x, error = 0x%x\n", rsp->result, error); @@ -709,7 +688,7 @@ static int auth_data_write_chunk(int fd, unsigned char tgt, unsigned int addr, /* Read final response */ memset(rsp, 0, rsp_size); - error = recv_rpmb_rsp(fd, tgt, rsp_size, rsp); + error = recv_rpmb_rsp(hdl, tgt, rsp_size, rsp); if (error != 0) fprintf(stderr, "Auth data write recv error = 0x%x\n", error); else @@ -723,17 +702,18 @@ static int auth_data_write_chunk(int fd, unsigned char tgt, unsigned int addr, } /* send the request and get response */ -static int rpmb_auth_data_write(int fd, unsigned char target, - unsigned int addr, int acc_size, - unsigned char *msg_buf, int msg_size, - unsigned char *keybuf, int keysize) +static int rpmb_auth_data_write(struct nvme_transport_handle *hdl, + unsigned char target, unsigned int addr, + int acc_size, unsigned char *msg_buf, + int msg_size, unsigned char *keybuf, + int keysize) { int chunk_size = acc_size < msg_size ? acc_size : msg_size; int xfer = chunk_size; int offset = 0; while (xfer > 0 ) { - if (auth_data_write_chunk(fd, target, (addr + offset / 512), + if (auth_data_write_chunk(hdl, target, (addr + offset / 512), msg_buf + offset, xfer, keybuf, keysize) != 0) { @@ -752,7 +732,8 @@ static int rpmb_auth_data_write(int fd, unsigned char target, } /* writes given config_block buffer to the drive target 0 */ -static int rpmb_write_config_block(int fd, unsigned char *cfg_buf, +static int rpmb_write_config_block(struct nvme_transport_handle *hdl, + unsigned char *cfg_buf, unsigned char *keybuf, int keysize) { int cfg_size = sizeof(struct rpmb_config_block_t); @@ -775,7 +756,7 @@ static int rpmb_write_config_block(int fd, unsigned char *cfg_buf, } /* read config block write_counter from controller */ - write_cntr = rpmb_read_config_block(fd, &cfg_buf_read); + write_cntr = rpmb_read_config_block(hdl, &cfg_buf_read); if (cfg_buf_read == NULL) { fprintf(stderr, "failed to read config block write counter\n"); error = -EIO; @@ -794,7 +775,7 @@ static int rpmb_write_config_block(int fd, unsigned char *cfg_buf, memcpy(req->mac, mac, sizeof(req->mac)); - error = send_rpmb_req(fd, 0, req_size, req); + error = send_rpmb_req(hdl, 0, req_size, req); if (error != 0) { fprintf(stderr, "Write-config RPMB request, error = 0x%x\n", error); @@ -814,7 +795,7 @@ static int rpmb_write_config_block(int fd, unsigned char *cfg_buf, rsp->target = req->target; rsp->type = RPMB_REQ_READ_RESULT; /* get the response and validate */ - error = recv_rpmb_rsp(fd, req->target, rsp_size, rsp); + error = recv_rpmb_rsp(hdl, req->target, rsp_size, rsp); if (error != 0) { fprintf(stderr,"Failed getting write-config response\ error = 0x%x\n", error); @@ -837,7 +818,7 @@ static bool invalid_xfer_size(int blocks, unsigned int bpsz) } /* Handling rpmb sub-command */ -int rpmb_cmd_option(int argc, char **argv, struct command *cmd, struct plugin *plugin) +int rpmb_cmd_option(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Run RPMB command on the supporting controller"; const char *msg = "data to be written on write-data or write-config commands"; @@ -886,13 +867,14 @@ int rpmb_cmd_option(int argc, char **argv, struct command *cmd, struct plugin *p OPT_END() }; + _cleanup_free_ unsigned char *key_buf = NULL; + _cleanup_free_ unsigned char *msg_buf = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; unsigned int write_cntr = 0; - unsigned char *key_buf = NULL; - unsigned char *msg_buf = NULL; unsigned int msg_size = 0; unsigned int key_size = 0; struct nvme_id_ctrl ctrl; - struct nvme_dev *dev; int err = -1; union ctrl_rpmbs_reg { @@ -905,25 +887,25 @@ int rpmb_cmd_option(int argc, char **argv, struct command *cmd, struct plugin *p }; unsigned int rpmbs; } regs; - - if ((err = parse_and_open(&dev, argc, argv, desc, opts))) + + if ((err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts))) return err; /* before parsing commands, check if controller supports any RPMB targets */ - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err) - goto out; + return err; regs.rpmbs = le32_to_cpu(ctrl.rpmbs); if (regs.num_targets == 0) { fprintf(stderr, "No RPMB targets are supported by the drive\n"); - goto out; + return -1; } /* parse and validate options; default print rpmb support info */ if (cfg.cmd == 0 || strcmp(cfg.cmd, "info") == 0) { nvme_show_id_ctrl_rpmbs(regs.rpmbs, 0); - goto out; + return -1; } if (strcmp(cfg.cmd, "program-key") == 0) @@ -940,7 +922,7 @@ int rpmb_cmd_option(int argc, char **argv, struct command *cmd, struct plugin *p cfg.opt = RPMB_REQ_AUTH_DCB_READ; else { fprintf(stderr, "Invalid option %s for rpmb command\n", cfg.cmd); - goto out; + return -1; } /* input file/data processing */ @@ -951,13 +933,13 @@ int rpmb_cmd_option(int argc, char **argv, struct command *cmd, struct plugin *p key_buf = read_rpmb_key(cfg.key, cfg.keyfile, &key_size); if (key_buf == NULL) { fprintf(stderr, "Failed to read key\n"); - goto out; + return -1; } if (key_size > 223 || key_size <= 0) { fprintf(stderr, "Invalid key size %d, valid input 1 to 223\n", key_size); - goto out; + return -1; } if (cfg.opt == RPMB_REQ_AUTH_DCB_WRITE || @@ -971,7 +953,7 @@ int rpmb_cmd_option(int argc, char **argv, struct command *cmd, struct plugin *p if (err || msg_size <= 0) { fprintf(stderr, "Failed to read file %s\n", cfg.msgfile); - goto out; + return -1; } } } @@ -979,18 +961,16 @@ int rpmb_cmd_option(int argc, char **argv, struct command *cmd, struct plugin *p switch (cfg.opt) { case RPMB_REQ_READ_WRITE_CNTR: - err = rpmb_read_write_counter(dev_fd(dev), cfg.target, - &write_cntr); + err = rpmb_read_write_counter(hdl, cfg.target, &write_cntr); if (err == 0) printf("Write Counter is: %u\n", write_cntr); break; case RPMB_REQ_AUTH_DCB_READ: - write_cntr = rpmb_read_config_block(dev_fd(dev), - &msg_buf); + write_cntr = rpmb_read_config_block(hdl, &msg_buf); if (msg_buf == NULL) { fprintf(stderr, "failed read config blk\n"); - goto out; + return -1; } /* no output file is given, print the data on stdout */ @@ -1019,7 +999,7 @@ int rpmb_cmd_option(int argc, char **argv, struct command *cmd, struct plugin *p msg_size); break; } - err = rpmb_auth_data_read(dev_fd(dev), cfg.target, + err = rpmb_auth_data_read(hdl, cfg.target, cfg.address, &msg_buf, cfg.blocks, (regs.access_size + 1)); @@ -1040,7 +1020,7 @@ int rpmb_cmd_option(int argc, char **argv, struct command *cmd, struct plugin *p } else if ((cfg.blocks * 512) < msg_size) { msg_size = cfg.blocks * 512; } - err = rpmb_auth_data_write(dev_fd(dev), cfg.target, + err = rpmb_auth_data_write(hdl, cfg.target, cfg.address, ((regs.access_size + 1) * 512), msg_buf, msg_size, @@ -1052,25 +1032,17 @@ int rpmb_cmd_option(int argc, char **argv, struct command *cmd, struct plugin *p break; case RPMB_REQ_AUTH_DCB_WRITE: - err = rpmb_write_config_block(dev_fd(dev), msg_buf, + err = rpmb_write_config_block(hdl, msg_buf, key_buf, key_size); break; case RPMB_REQ_AUTH_KEY_PROGRAM: - err = rpmb_program_auth_key(dev_fd(dev), cfg.target, + err = rpmb_program_auth_key(hdl, cfg.target, key_buf, key_size); break; default: break; } - -out: - /* release memory */ - free(key_buf); - free(msg_buf); - - /* close device */ - dev_close(dev); - + return err; } diff --git a/nvme-wrap.c b/nvme-wrap.c deleted file mode 100644 index 99467a1607..0000000000 --- a/nvme-wrap.c +++ /dev/null @@ -1,515 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Definitions for the NVM Express interface: libnvme/libnvme-mi device - * wrappers. - */ - -#include - -#include -#include - -#include "nvme.h" -#include "nvme-wrap.h" - -/* - * Helper for libnvme functions that pass the fd/ep separately. These just - * pass the correct handle to the direct/MI function. - * @op: the name of the libnvme function, without the nvme_/nvme_mi prefix - * @d: device handle: struct nvme_dev - */ -#define do_admin_op(op, d, ...) ({ \ - int __rc; \ - if (d->type == NVME_DEV_DIRECT) \ - __rc = nvme_ ## op(d->direct.fd, __VA_ARGS__); \ - else if (d->type == NVME_DEV_MI) \ - __rc = nvme_mi_admin_ ## op (d->mi.ctrl, __VA_ARGS__); \ - else \ - __rc = -ENODEV; \ - __rc; }) - -/* - * Helper for libnvme functions use the 'struct _args' pattern. These need - * the fd and timeout set for the direct interface, and pass the ep as - * an argument for the MI interface - * @op: the name of the libnvme function, without the nvme_/nvme_mi prefix - * @d: device handle: struct nvme_dev - * @args: op-specific args struct - */ -#define do_admin_args_op(op, d, args) ({ \ - int __rc; \ - if (d->type == NVME_DEV_DIRECT) { \ - args->fd = d->direct.fd; \ - __rc = nvme_ ## op(args); \ - } else if (d->type == NVME_DEV_MI) \ - __rc = nvme_mi_admin_ ## op (d->mi.ctrl, args); \ - else \ - __rc = -ENODEV; \ - __rc; }) - -int nvme_cli_identify(struct nvme_dev *dev, struct nvme_identify_args *args) -{ - return do_admin_args_op(identify, dev, args); -} - -int nvme_cli_identify_ctrl(struct nvme_dev *dev, struct nvme_id_ctrl *ctrl) -{ - return do_admin_op(identify_ctrl, dev, ctrl); -} - -int nvme_cli_identify_ctrl_list(struct nvme_dev *dev, __u16 ctrl_id, - struct nvme_ctrl_list *list) -{ - return do_admin_op(identify_ctrl_list, dev, ctrl_id, list); -} - -int nvme_cli_identify_nsid_ctrl_list(struct nvme_dev *dev, __u32 nsid, - __u16 ctrl_id, - struct nvme_ctrl_list *list) -{ - return do_admin_op(identify_nsid_ctrl_list, dev, nsid, ctrl_id, list); -} - -int nvme_cli_identify_ns(struct nvme_dev *dev, __u32 nsid, - struct nvme_id_ns *ns) -{ - return do_admin_op(identify_ns, dev, nsid, ns); -} - -int nvme_cli_identify_ns_descs(struct nvme_dev *dev, __u32 nsid, - struct nvme_ns_id_desc *descs) -{ - return do_admin_op(identify_ns_descs, dev, nsid, descs); -} - -int nvme_cli_identify_allocated_ns(struct nvme_dev *dev, __u32 nsid, - struct nvme_id_ns *ns) -{ - return do_admin_op(identify_allocated_ns, dev, nsid, ns); -} - -int nvme_cli_identify_active_ns_list(struct nvme_dev *dev, __u32 nsid, - struct nvme_ns_list *list) -{ - return do_admin_op(identify_active_ns_list, dev, nsid, list); -} - -int nvme_cli_identify_allocated_ns_list(struct nvme_dev *dev, __u32 nsid, - struct nvme_ns_list *list) -{ - return do_admin_op(identify_allocated_ns_list, dev, nsid, list); -} - -int nvme_cli_identify_primary_ctrl(struct nvme_dev *dev, __u16 cntid, - struct nvme_primary_ctrl_cap *cap) -{ - return do_admin_op(identify_primary_ctrl, dev, cntid, cap); -} - -int nvme_cli_identify_secondary_ctrl_list(struct nvme_dev *dev, __u16 cntid, - struct nvme_secondary_ctrl_list *sc_list) -{ - return do_admin_op(identify_secondary_ctrl_list, dev, cntid, - sc_list); -} - -int nvme_cli_get_features(struct nvme_dev *dev, - struct nvme_get_features_args *args) -{ - return do_admin_args_op(get_features, dev, args); -} - -int nvme_cli_get_features_arbitration(struct nvme_dev *dev, enum nvme_get_features_sel sel, - __u32 *result) -{ - return do_admin_op(get_features_arbitration, dev, sel, result); -} - -int nvme_cli_get_features_power_mgmt(struct nvme_dev *dev, enum nvme_get_features_sel sel, - __u32 *result) -{ - return do_admin_op(get_features_power_mgmt, dev, sel, result); -} - -int nvme_cli_set_features(struct nvme_dev *dev, struct nvme_set_features_args *args) -{ - return do_admin_args_op(set_features, dev, args); -} - -int nvme_cli_set_features_arbitration(struct nvme_dev *dev, __u8 ab, __u8 lpw, __u8 mpw, __u8 hpw, - bool save, __u32 *result) -{ - if (dev->type == NVME_DEV_DIRECT) - return nvme_set_features_arbitration(dev_fd(dev), ab, lpw, mpw, hpw, save, result); - - return -ENODEV; -} - -int nvme_cli_features_power_mgmt(struct nvme_dev *dev, __u8 ps, __u8 wh, bool save, __u32 *result) -{ - return do_admin_op(set_features_power_mgmt, dev, ps, wh, save, result); -} - -int nvme_cli_ns_mgmt_delete(struct nvme_dev *dev, __u32 nsid, __u32 timeout) -{ - if (dev->type == NVME_DEV_DIRECT) - return nvme_ns_mgmt_delete_timeout(dev_fd(dev), nsid, timeout); - - return do_admin_op(ns_mgmt_delete, dev, nsid); -} - -int nvme_cli_ns_attach(struct nvme_dev *dev, struct nvme_ns_attach_args *args) -{ - return do_admin_args_op(ns_attach, dev, args); -} - -int nvme_cli_ns_attach_ctrls(struct nvme_dev *dev, __u32 nsid, - struct nvme_ctrl_list *ctrlist) -{ - return do_admin_op(ns_attach_ctrls, dev, nsid, ctrlist); -} - -int nvme_cli_ns_detach_ctrls(struct nvme_dev *dev, __u32 nsid, - struct nvme_ctrl_list *ctrlist) -{ - return do_admin_op(ns_detach_ctrls, dev, nsid, ctrlist); -} - -int nvme_cli_format_nvm(struct nvme_dev *dev, struct nvme_format_nvm_args *args) -{ - return do_admin_args_op(format_nvm, dev, args); -} - -int nvme_cli_sanitize_nvm(struct nvme_dev *dev, struct nvme_sanitize_nvm_args *args) -{ - return do_admin_args_op(sanitize_nvm, dev, args); -} - -int nvme_cli_get_log(struct nvme_dev *dev, struct nvme_get_log_args *args) -{ - return do_admin_args_op(get_log, dev, args); -} - -int nvme_cli_get_log_page(struct nvme_dev *dev, __u32 xfer_len, - struct nvme_get_log_args *args) -{ - return do_admin_op(get_log_page, dev, xfer_len, args); -} - -int nvme_cli_get_nsid_log(struct nvme_dev *dev, bool rae, - enum nvme_cmd_get_log_lid lid, - __u32 nsid, __u32 len, void *log) -{ - return do_admin_op(get_nsid_log, dev, rae, lid, nsid, len, log); -} - -int nvme_cli_get_log_simple(struct nvme_dev *dev, - enum nvme_cmd_get_log_lid lid, - __u32 len, void *log) -{ - return do_admin_op(get_log_simple, dev, lid, len, log); -} - -int nvme_cli_get_log_supported_log_pages(struct nvme_dev *dev, bool rae, - struct nvme_supported_log_pages *log) -{ - return do_admin_op(get_log_supported_log_pages, dev, rae, log); -} - -int nvme_cli_get_log_error(struct nvme_dev *dev, unsigned int nr_entries, - bool rae, struct nvme_error_log_page *err_log) -{ - return do_admin_op(get_log_error, dev, nr_entries, rae, err_log); -} - -int nvme_cli_get_log_smart(struct nvme_dev *dev, __u32 nsid, bool rae, - struct nvme_smart_log *smart_log) -{ - return do_admin_op(get_log_smart, dev, nsid, rae, smart_log); -} - -int nvme_cli_get_log_fw_slot(struct nvme_dev *dev, bool rae, - struct nvme_firmware_slot *fw_log) -{ - return do_admin_op(get_log_fw_slot, dev, rae, fw_log); -} - -int nvme_cli_get_log_changed_ns_list(struct nvme_dev *dev, bool rae, - struct nvme_ns_list *ns_log) -{ - return do_admin_op(get_log_changed_ns_list, dev, rae, ns_log); -} - -int nvme_cli_get_log_changed_alloc_ns_list(struct nvme_dev *dev, bool rae, __u32 len, - struct nvme_ns_list *ns_log) -{ - return do_admin_op(get_log_changed_alloc_ns_list, dev, rae, len, ns_log); -} - -int nvme_cli_get_log_cmd_effects(struct nvme_dev *dev, enum nvme_csi csi, - struct nvme_cmd_effects_log *effects_log) -{ - return do_admin_op(get_log_cmd_effects, dev, csi, effects_log); -} - -int nvme_cli_get_log_device_self_test(struct nvme_dev *dev, - struct nvme_self_test_log *log) -{ - return do_admin_op(get_log_device_self_test, dev, log); -} - -int nvme_cli_get_log_create_telemetry_host_mcda(struct nvme_dev *dev, - enum nvme_telemetry_da mcda, - struct nvme_telemetry_log *log) -{ - return do_admin_op(get_log_create_telemetry_host_mcda, dev, mcda, log); -} - -int nvme_cli_get_log_telemetry_host(struct nvme_dev *dev, __u64 offset, - __u32 len, void *log) -{ - return do_admin_op(get_log_telemetry_host, dev, offset, len, log); -} - -int nvme_cli_get_log_telemetry_ctrl(struct nvme_dev *dev, bool rae, - __u64 offset, __u32 len, void *log) -{ - return do_admin_op(get_log_telemetry_ctrl, dev, rae, offset, len, log); -} - -int nvme_cli_get_log_endurance_group(struct nvme_dev *dev, __u16 endgid, - struct nvme_endurance_group_log *log) -{ - return do_admin_op(get_log_endurance_group, dev, endgid, log); -} - -int nvme_cli_get_log_predictable_lat_nvmset(struct nvme_dev *dev, - __u16 nvmsetid, - struct nvme_nvmset_predictable_lat_log *log) -{ - return do_admin_op(get_log_predictable_lat_nvmset, dev, nvmsetid, log); -} - -int nvme_cli_get_log_predictable_lat_event(struct nvme_dev *dev, bool rae, - __u32 offset, __u32 len, void *log) -{ - return do_admin_op(get_log_predictable_lat_event, dev, rae, offset, - len, log); -} - -int nvme_cli_get_ana_log_atomic(struct nvme_dev *dev, bool rgo, bool rae, - unsigned int retries, - struct nvme_ana_log *log, __u32 *len) -{ - return do_admin_op(get_ana_log_atomic, dev, rgo, rae, retries, log, len); -} - -int nvme_cli_get_log_lba_status(struct nvme_dev *dev, bool rae, - __u64 offset, __u32 len, void *log) -{ - return do_admin_op(get_log_lba_status, dev, rae, offset, len, log); -} - -int nvme_cli_get_log_endurance_grp_evt(struct nvme_dev *dev, bool rae, - __u32 offset, __u32 len, void *log) -{ - return do_admin_op(get_log_endurance_grp_evt, dev, rae, offset, len, - log); -} - -int nvme_cli_get_log_fid_supported_effects(struct nvme_dev *dev, bool rae, - struct nvme_fid_supported_effects_log *log) -{ - return do_admin_op(get_log_fid_supported_effects, dev, rae, log); -} - -int nvme_cli_get_log_mi_cmd_supported_effects(struct nvme_dev *dev, bool rae, - struct nvme_mi_cmd_supported_effects_log *log) -{ - return do_admin_op(get_log_mi_cmd_supported_effects, dev, rae, log); -} - -int nvme_cli_get_log_boot_partition(struct nvme_dev *dev, bool rae, __u8 lsp, - __u32 len, - struct nvme_boot_partition *part) -{ - return do_admin_op(get_log_boot_partition, dev, rae, lsp, len, part); -} - -int nvme_cli_get_log_phy_rx_eom(struct nvme_dev *dev, __u8 lsp, __u16 controller, - __u32 len, struct nvme_phy_rx_eom_log *part) -{ - return do_admin_op(get_log_phy_rx_eom, dev, lsp, controller, len, part); -} - -int nvme_cli_get_log_discovery(struct nvme_dev *dev, bool rae, - __u32 offset, __u32 len, void *log) -{ - return do_admin_op(get_log_discovery, dev, rae, offset, len, log); -} - -int nvme_cli_get_log_media_unit_stat(struct nvme_dev *dev, __u16 domid, - struct nvme_media_unit_stat_log *mus) -{ - return do_admin_op(get_log_media_unit_stat, dev, domid, mus); -} - -int nvme_cli_get_log_support_cap_config_list(struct nvme_dev *dev, - __u16 domid, - struct nvme_supported_cap_config_list_log *cap) -{ - return do_admin_op(get_log_support_cap_config_list, dev, domid, cap); -} - -int nvme_cli_get_log_reservation(struct nvme_dev *dev, bool rae, - struct nvme_resv_notification_log *log) -{ - return do_admin_op(get_log_reservation, dev, rae, log); -} - -int nvme_cli_get_log_sanitize(struct nvme_dev *dev, bool rae, - struct nvme_sanitize_log_page *log) -{ - return do_admin_op(get_log_sanitize, dev, rae, log); -} - -int nvme_cli_get_log_zns_changed_zones(struct nvme_dev *dev, __u32 nsid, - bool rae, - struct nvme_zns_changed_zone_log *log) -{ - return do_admin_op(get_log_zns_changed_zones, dev, nsid, rae, log); -} - -int nvme_cli_get_log_persistent_event(struct nvme_dev *dev, - enum nvme_pevent_log_action action, - __u32 size, void *pevent_log) -{ - return do_admin_op(get_log_persistent_event, dev, action, size, - pevent_log); -} - -int nvme_cli_fw_download(struct nvme_dev *dev, - struct nvme_fw_download_args *args) -{ - return do_admin_args_op(fw_download, dev, args); -} - -int nvme_cli_fw_commit(struct nvme_dev *dev, - struct nvme_fw_commit_args *args) -{ - return do_admin_args_op(fw_commit, dev, args); -} - -int nvme_cli_admin_passthru(struct nvme_dev *dev, __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) -{ - return do_admin_op(admin_passthru, dev, opcode, flags, rsvd, nsid, - cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, cdw14, cdw15, - data_len, data, metadata_len, metadata, timeout_ms, - result); -} - -/* The MI & direct interfaces don't have an exactly-matching API for - * ns_mgmt_create, as we don't support a timeout for MI. - */ -int nvme_cli_ns_mgmt_create(struct nvme_dev *dev, - struct nvme_ns_mgmt_host_sw_specified *data, - __u32 *nsid, __u32 timeout, __u8 csi) -{ - if (dev->type == NVME_DEV_DIRECT) - return nvme_ns_mgmt_create(dev_fd(dev), NULL, nsid, timeout, - csi, data); - if (dev->type == NVME_DEV_MI) - return nvme_mi_admin_ns_mgmt_create(dev->mi.ctrl, NULL, - csi, nsid, data); - - return -ENODEV; -} - -int nvme_cli_get_feature_length2(int fid, __u32 cdw11, enum nvme_data_tfr dir, - __u32 *len) -{ - int err; - - err = nvme_get_feature_length2(fid, cdw11, dir, len); - if (err != -EEXIST) - return err; - return nvme_get_feature_length(fid, cdw11, len); -} - -int nvme_cli_security_send(struct nvme_dev *dev, - struct nvme_security_send_args* args) -{ - return do_admin_args_op(security_send, dev, args); -} - -int nvme_cli_security_receive(struct nvme_dev *dev, - struct nvme_security_receive_args* args) -{ - /* Cannot use do_admin_args_op here because the API have different suffix*/ - if (dev->type == NVME_DEV_DIRECT) { - args->fd = dev->direct.fd; - args->timeout = NVME_DEFAULT_IOCTL_TIMEOUT; - return nvme_security_receive(args); - } - - if (dev->type == NVME_DEV_MI) - return nvme_mi_admin_security_recv(dev->mi.ctrl, args); - - return -ENODEV; -} - -int nvme_cli_get_log_mgmt_addr_list(struct nvme_dev *dev, __u32 len, - struct nvme_mgmt_addr_list_log *ma_list) -{ - return do_admin_op(get_log_mgmt_addr_list, dev, len, ma_list); -} - -int nvme_cli_get_log_rotational_media_info(struct nvme_dev *dev, __u16 endgid, __u32 len, - struct nvme_rotational_media_info_log *info) -{ - if (dev->type == NVME_DEV_DIRECT) - return nvme_get_log_rotational_media_info(dev->direct.fd, endgid, len, info); - - return -ENODEV; -} - -int nvme_cli_get_log_dispersed_ns_participating_nss(struct nvme_dev *dev, __u32 nsid, __u32 len, - struct nvme_dispersed_ns_participating_nss_log *log) -{ - return do_admin_op(get_log_dispersed_ns_participating_nss, dev, nsid, len, log); -} - -int nvme_cli_get_log_reachability_groups(struct nvme_dev *dev, bool rgo, bool rae, __u32 len, - struct nvme_reachability_groups_log *log) -{ - return do_admin_op(get_log_reachability_groups, dev, rgo, rae, len, log); -} - -int nvme_cli_get_log_reachability_associations(struct nvme_dev *dev, bool rao, bool rae, __u32 len, - struct nvme_reachability_associations_log *log) -{ - return do_admin_op(get_log_reachability_associations, dev, rao, rae, len, log); -} - -int nvme_cli_get_log_host_discovery(struct nvme_dev *dev, bool allhoste, bool rae, __u32 len, - struct nvme_host_discover_log *log) -{ - return do_admin_op(get_log_host_discover, dev, allhoste, rae, len, log); -} - -int nvme_cli_get_log_ave_discovery(struct nvme_dev *dev, bool rae, __u32 len, - struct nvme_ave_discover_log *log) -{ - return do_admin_op(get_log_ave_discover, dev, rae, len, log); -} - -int nvme_cli_get_log_pull_model_ddc_req(struct nvme_dev *dev, bool rae, __u32 len, - struct nvme_pull_model_ddc_req_log *log) -{ - return do_admin_op(get_log_pull_model_ddc_req, dev, rae, len, log); -} diff --git a/nvme-wrap.h b/nvme-wrap.h deleted file mode 100644 index 4f46c0afc7..0000000000 --- a/nvme-wrap.h +++ /dev/null @@ -1,180 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Definitions for the NVM Express interface: libnvme/libnvme-mi device - * wrappers. - */ - -#ifndef _NVME_WRAP_H -#define _NVME_WRAP_H - -#include "nvme.h" - -int nvme_cli_identify(struct nvme_dev *dev, struct nvme_identify_args *args); -int nvme_cli_identify_ctrl(struct nvme_dev *dev, struct nvme_id_ctrl *ctrl); -int nvme_cli_identify_ctrl_list(struct nvme_dev *dev, __u16 ctrl_id, - struct nvme_ctrl_list *list); -int nvme_cli_identify_nsid_ctrl_list(struct nvme_dev *dev, __u32 nsid, - __u16 ctrl_id, - struct nvme_ctrl_list *list); -int nvme_cli_identify_ns(struct nvme_dev *dev, __u32 nsid, - struct nvme_id_ns *ns); -int nvme_cli_identify_ns_descs(struct nvme_dev *dev, __u32 nsid, - struct nvme_ns_id_desc *descs); -int nvme_cli_identify_allocated_ns(struct nvme_dev *dev, __u32 nsid, - struct nvme_id_ns *ns); -int nvme_cli_identify_active_ns_list(struct nvme_dev *dev, __u32 nsid, - struct nvme_ns_list *list); -int nvme_cli_identify_allocated_ns_list(struct nvme_dev *dev, __u32 nsid, - struct nvme_ns_list *list); -int nvme_cli_identify_primary_ctrl(struct nvme_dev *dev, __u16 cntid, - struct nvme_primary_ctrl_cap *cap); -int nvme_cli_identify_secondary_ctrl_list(struct nvme_dev *dev, __u16 cntid, - struct nvme_secondary_ctrl_list *sc_list); -int nvme_cli_ns_mgmt_delete(struct nvme_dev *dev, __u32 nsid, __u32 timeout); -int nvme_cli_ns_mgmt_create(struct nvme_dev *dev, - struct nvme_ns_mgmt_host_sw_specified *data, - __u32 *nsid, __u32 timeout, __u8 csi); - -int nvme_cli_ns_attach(struct nvme_dev *dev, struct nvme_ns_attach_args *args); - -int nvme_cli_ns_attach_ctrls(struct nvme_dev *dev, __u32 nsid, - struct nvme_ctrl_list *ctrlist); -int nvme_cli_ns_detach_ctrls(struct nvme_dev *dev, __u32 nsid, - struct nvme_ctrl_list *ctrlist); - -int nvme_cli_format_nvm(struct nvme_dev *dev, struct nvme_format_nvm_args *args); -int nvme_cli_sanitize_nvm(struct nvme_dev *dev, - struct nvme_sanitize_nvm_args *args); - -int nvme_cli_get_features(struct nvme_dev *dev, - struct nvme_get_features_args *args); -int nvme_cli_get_features_arbitration(struct nvme_dev *dev, enum nvme_get_features_sel sel, - __u32 *result); -int nvme_cli_get_features_power_mgmt(struct nvme_dev *dev, enum nvme_get_features_sel sel, - __u32 *result); -int nvme_cli_set_features(struct nvme_dev *dev, struct nvme_set_features_args *args); -int nvme_cli_set_features_arbitration(struct nvme_dev *dev, __u8 ab, __u8 lpw, __u8 mpw, __u8 hpw, - bool save, __u32 *result); -int nvme_set_features_power_mgmt(int fd, __u8 ps, __u8 wh, bool save, __u32 *result); - -int nvme_cli_get_log(struct nvme_dev *dev, struct nvme_get_log_args *args); -int nvme_cli_get_log_page(struct nvme_dev *dev, - __u32 xfer_len, - struct nvme_get_log_args *args); - -int nvme_cli_get_nsid_log(struct nvme_dev *dev, bool rae, - enum nvme_cmd_get_log_lid lid, - __u32 nsid, __u32 len, void *log); -int nvme_cli_get_log_simple(struct nvme_dev *dev, - enum nvme_cmd_get_log_lid lid, - __u32 len, void *log); -int nvme_cli_get_log_supported_log_pages(struct nvme_dev *dev, bool rae, - struct nvme_supported_log_pages *log); -int nvme_cli_get_log_error(struct nvme_dev *dev, unsigned int nr_entries, - bool rae, struct nvme_error_log_page *err_log); -int nvme_cli_get_log_smart(struct nvme_dev *dev, __u32 nsid, bool rae, - struct nvme_smart_log *smart_log); -int nvme_cli_get_log_fw_slot(struct nvme_dev *dev, bool rae, - struct nvme_firmware_slot *fw_log); -int nvme_cli_get_log_changed_ns_list(struct nvme_dev *dev, bool rae, - struct nvme_ns_list *ns_log); -int nvme_cli_get_log_changed_alloc_ns_list(struct nvme_dev *dev, bool rae, __u32 len, - struct nvme_ns_list *ns_log); -int nvme_cli_get_log_cmd_effects(struct nvme_dev *dev, enum nvme_csi csi, - struct nvme_cmd_effects_log *effects_log); -int nvme_cli_get_log_device_self_test(struct nvme_dev *dev, - struct nvme_self_test_log *log); -int nvme_cli_get_log_create_telemetry_host_mcda(struct nvme_dev *dev, - enum nvme_telemetry_da mcda, - struct nvme_telemetry_log *log); -int nvme_cli_get_log_telemetry_host(struct nvme_dev *dev, __u64 offset, - __u32 len, void *log); -int nvme_cli_get_log_telemetry_ctrl(struct nvme_dev *dev, bool rae, - __u64 offset, __u32 len, void *log); -int nvme_cli_get_log_endurance_group(struct nvme_dev *dev, __u16 endgid, - struct nvme_endurance_group_log *log); -int nvme_cli_get_log_predictable_lat_nvmset(struct nvme_dev *dev, - __u16 nvmsetid, - struct nvme_nvmset_predictable_lat_log *log); -int nvme_cli_get_log_predictable_lat_event(struct nvme_dev *dev, bool rae, - __u32 offset, __u32 len, void *log); -int nvme_cli_get_ana_log_atomic(struct nvme_dev *dev, bool rgo, bool rae, - unsigned int retries, - struct nvme_ana_log *log, __u32 *len); -int nvme_cli_get_log_lba_status(struct nvme_dev *dev, bool rae, - __u64 offset, __u32 len, void *log); -int nvme_cli_get_log_endurance_grp_evt(struct nvme_dev *dev, bool rae, - __u32 offset, __u32 len, void *log); -int nvme_cli_get_log_fid_supported_effects(struct nvme_dev *dev, bool rae, - struct nvme_fid_supported_effects_log *log); -int nvme_cli_get_log_mi_cmd_supported_effects(struct nvme_dev *dev, bool rae, - struct nvme_mi_cmd_supported_effects_log *log); -int nvme_cli_get_log_boot_partition(struct nvme_dev *dev, bool rae, __u8 lsp, - __u32 len, - struct nvme_boot_partition *part); -int nvme_cli_get_log_phy_rx_eom(struct nvme_dev *dev, __u8 lsp, __u16 controller, - __u32 len, struct nvme_phy_rx_eom_log *part); -int nvme_cli_get_log_discovery(struct nvme_dev *dev, bool rae, - __u32 offset, __u32 len, void *log); -int nvme_cli_get_log_media_unit_stat(struct nvme_dev *dev, __u16 domid, - struct nvme_media_unit_stat_log *mus); -int nvme_cli_get_log_support_cap_config_list(struct nvme_dev *dev, - __u16 domid, - struct nvme_supported_cap_config_list_log *cap); -int nvme_cli_get_log_reservation(struct nvme_dev *dev, bool rae, - struct nvme_resv_notification_log *log); -int nvme_cli_get_log_sanitize(struct nvme_dev *dev, bool rae, - struct nvme_sanitize_log_page *log); -int nvme_cli_get_log_zns_changed_zones(struct nvme_dev *dev, __u32 nsid, - bool rae, - struct nvme_zns_changed_zone_log *log); -int nvme_cli_get_log_persistent_event(struct nvme_dev *dev, - enum nvme_pevent_log_action action, - __u32 size, void *pevent_log); - -int nvme_cli_fw_download(struct nvme_dev *dev, - struct nvme_fw_download_args *args); - -int nvme_cli_fw_commit(struct nvme_dev *dev, - struct nvme_fw_commit_args *args); - -int nvme_cli_admin_passthru(struct nvme_dev *dev, __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); - -int nvme_cli_get_feature_length2(int fid, __u32 cdw11, enum nvme_data_tfr dir, - __u32 *len); - -int nvme_cli_security_send(struct nvme_dev *dev, - struct nvme_security_send_args* args); - -int nvme_cli_security_receive(struct nvme_dev *dev, - struct nvme_security_receive_args* args); - -int nvme_cli_get_log_mgmt_addr_list(struct nvme_dev *dev, __u32 len, - struct nvme_mgmt_addr_list_log *ma_list); - -int nvme_cli_get_log_rotational_media_info(struct nvme_dev *dev, __u16 endgid, __u32 len, - struct nvme_rotational_media_info_log *info); - -int nvme_cli_get_log_dispersed_ns_participating_nss(struct nvme_dev *dev, __u32 nsid, __u32 len, - struct nvme_dispersed_ns_participating_nss_log *log); - -int nvme_cli_get_log_reachability_groups(struct nvme_dev *dev, bool rgo, bool rae, __u32 len, - struct nvme_reachability_groups_log *log); - -int nvme_cli_get_log_reachability_associations(struct nvme_dev *dev, bool rgo, bool rae, __u32 len, - struct nvme_reachability_associations_log *log); - -int nvme_cli_get_log_host_discovery(struct nvme_dev *dev, bool allhoste, bool rae, __u32 len, - struct nvme_host_discover_log *log); - -int nvme_cli_get_log_ave_discovery(struct nvme_dev *dev, bool rae, __u32 len, - struct nvme_ave_discover_log *log); - -int nvme_cli_get_log_pull_model_ddc_req(struct nvme_dev *dev, bool rae, __u32 len, - struct nvme_pull_model_ddc_req_log *log); -#endif /* _NVME_WRAP_H */ diff --git a/nvme.c b/nvme.c index 2e20358144..78e3c83559 100644 --- a/nvme.c +++ b/nvme.c @@ -61,7 +61,6 @@ #include "plugin.h" #include "util/base64.h" #include "util/crc32.h" -#include "nvme-wrap.h" #include "util/argconfig.h" #include "util/suffix.h" #include "logging.h" @@ -264,7 +263,7 @@ struct nvme_config nvme_cfg = { .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, }; -static void *mmap_registers(struct nvme_dev *dev, bool writable); +static void *mmap_registers(struct nvme_transport_handle *hdl, bool writable); static OPT_VALS(feature_name) = { VAL_BYTE("arbitration", NVME_FEAT_FID_ARBITRATION), @@ -323,135 +322,20 @@ const char *nvme_strerror(int errnum) static ssize_t getrandom_bytes(void *buf, size_t buflen) { + ssize_t result; #if HAVE_SYS_RANDOM - return getrandom(buf, buflen, GRND_NONBLOCK); + result = getrandom(buf, buflen, GRND_NONBLOCK); #else - ssize_t result; - int fd, err = 0; + _cleanup_fd_ int fd = -1; fd = open("/dev/urandom", O_RDONLY); if (fd < 0) - return fd; + return -errno; result = read(fd, buf, buflen); +#endif if (result < 0) - err = errno; - close(fd); - errno = err; + return -errno; return result; -#endif -} - -static bool is_chardev(struct nvme_dev *dev) -{ - return S_ISCHR(dev->direct.stat.st_mode); -} - -static bool is_blkdev(struct nvme_dev *dev) -{ - return S_ISBLK(dev->direct.stat.st_mode); -} - -static int open_dev_direct(struct nvme_dev **devp, char *devstr, int flags) -{ - struct nvme_dev *dev; - int err; - - dev = calloc(1, sizeof(*dev)); - if (!dev) - return -1; - - dev->type = NVME_DEV_DIRECT; - dev->name = basename(devstr); - err = open(devstr, flags); - if (err < 0) { - nvme_show_perror(devstr); - goto err_free; - } - dev->direct.fd = err; - - err = fstat(dev_fd(dev), &dev->direct.stat); - if (err < 0) { - nvme_show_perror(devstr); - goto err_close; - } - if (!is_chardev(dev) && !is_blkdev(dev)) { - nvme_show_error("%s is not a block or character device", devstr); - errno = ENODEV; - err = -1; - goto err_close; - } - *devp = dev; - return 0; - -err_close: - close(dev_fd(dev)); -err_free: - free(dev); - return err; -} - -static int parse_mi_dev(char *dev, unsigned int *net, uint8_t *eid, - unsigned int *ctrl) -{ - int rc; - - /* ,: form */ - rc = sscanf(dev, "mctp:%u,%hhu:%u", net, eid, ctrl); - if (rc == 3) - return 0; - - /* , form, implicit ctrl-id = 0 */ - *ctrl = 0; - rc = sscanf(dev, "mctp:%u,%hhu", net, eid); - if (rc == 2) - return 0; - - return -1; -} - -static int open_dev_mi_mctp(struct nvme_dev **devp, char *devstr) -{ - unsigned int net, ctrl_id; - struct nvme_dev *dev; - unsigned char eid; - int rc; - - rc = parse_mi_dev(devstr, &net, &eid, &ctrl_id); - if (rc) { - nvme_show_error("invalid device specifier '%s'", devstr); - return rc; - } - - dev = calloc(1, sizeof(*dev)); - if (!dev) - return -1; - - dev->type = NVME_DEV_MI; - dev->name = devstr; - - /* todo: verbose argument */ - dev->mi.root = nvme_mi_create_root(stderr, LOG_WARNING); - if (!dev->mi.root) - goto err_free; - - dev->mi.ep = nvme_mi_open_mctp(dev->mi.root, net, eid); - if (!dev->mi.ep) - goto err_free_root; - - dev->mi.ctrl = nvme_mi_init_ctrl(dev->mi.ep, ctrl_id); - if (!dev->mi.ctrl) - goto err_close_ep; - - *devp = dev; - return 0; - -err_close_ep: - nvme_mi_close(dev->mi.ep); -err_free_root: - nvme_mi_free_root(dev->mi.root); -err_free: - free(dev); - return -1; } static int check_arg_dev(int argc, char **argv) @@ -464,7 +348,9 @@ static int check_arg_dev(int argc, char **argv) return 0; } -static int get_dev(struct nvme_dev **dev, int argc, char **argv, int flags) +static int get_transport_handle(struct nvme_global_ctx *ctx, int argc, + char **argv, int flags, + struct nvme_transport_handle **hdl) { char *devname; int ret; @@ -474,17 +360,12 @@ static int get_dev(struct nvme_dev **dev, int argc, char **argv, int flags) return ret; devname = argv[optind]; - errno = ENXIO; - - if (!strncmp(devname, "mctp:", strlen("mctp:"))) - ret = open_dev_mi_mctp(dev, devname); - else - ret = open_dev_direct(dev, devname, flags); + ret = nvme_open(ctx, devname, hdl); if (!ret && log_level >= LOG_DEBUG) nvme_show_init(); - return ret ? -errno : 0; + return ret; } static int parse_args(int argc, char *argv[], const char *desc, @@ -502,32 +383,59 @@ static int parse_args(int argc, char *argv[], const char *desc, return 0; } -int parse_and_open(struct nvme_dev **dev, int argc, char **argv, - const char *desc, - struct argconfig_commandline_options *opts) +int parse_and_open(struct nvme_global_ctx **ctx, + struct nvme_transport_handle **hdl, int argc, char **argv, + const char *desc, struct argconfig_commandline_options *opts) { + struct nvme_transport_handle *hdl_new; + struct nvme_global_ctx *ctx_new; int ret; ret = parse_args(argc, argv, desc, opts); if (ret) return ret; - ret = get_dev(dev, argc, argv, O_RDONLY); - if (ret < 0) + ctx_new = nvme_create_global_ctx(stdout, log_level); + if (!ctx_new) + return -ENOMEM; + + ret = get_transport_handle(ctx_new, argc, argv, O_RDONLY, &hdl_new); + if (ret) { + nvme_free_global_ctx(ctx_new); argconfig_print_help(desc, opts); + return -ENXIO; + } - return ret; + *ctx = ctx_new; + *hdl = hdl_new; + return 0; } -int open_exclusive(struct nvme_dev **dev, int argc, char **argv, +int open_exclusive(struct nvme_global_ctx **ctx, + struct nvme_transport_handle **hdl, int argc, char **argv, int ignore_exclusive) { + struct nvme_transport_handle *hdl_new; + struct nvme_global_ctx *ctx_new; int flags = O_RDONLY; + int ret; if (!ignore_exclusive) flags |= O_EXCL; - return get_dev(dev, argc, argv, flags); + ctx_new = nvme_create_global_ctx(stdout, log_level); + if (!ctx_new) + return -ENOMEM; + + ret = get_transport_handle(ctx_new, argc, argv, flags, &hdl_new); + if (ret) { + nvme_free_global_ctx(ctx_new); + return -ENXIO; + } + + *ctx = ctx_new; + *hdl = hdl_new; + return 0; } int validate_output_format(const char *format, nvme_print_flags_t *flags) @@ -565,31 +473,15 @@ bool nvme_is_output_format_json(void) return flags == JSON; } -void dev_close(struct nvme_dev *dev) -{ - if (log_level >= LOG_DEBUG) - nvme_show_finish(); - - switch (dev->type) { - case NVME_DEV_DIRECT: - close(dev_fd(dev)); - break; - case NVME_DEV_MI: - nvme_mi_close(dev->mi.ep); - nvme_mi_free_root(dev->mi.root); - break; - } - free(dev); -} - -static int get_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_smart_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve SMART log for the given device " "(or optionally a namespace) in either decoded format " "(default) or binary."; _cleanup_free_ struct nvme_smart_log *smart_log = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; const char *namespace = "(optional) desired namespace"; nvme_print_flags_t flags; int err = -1; @@ -611,7 +503,7 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_output), OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable_info)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -631,27 +523,27 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug if (!smart_log) return -ENOMEM; - err = nvme_cli_get_log_smart(dev, cfg.namespace_id, false, - smart_log); + err = nvme_get_log_smart(hdl, cfg.namespace_id, smart_log); if (!err) nvme_show_smart_log(smart_log, cfg.namespace_id, - dev->name, flags); + nvme_transport_handle_get_name(hdl), flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("smart log: %s", nvme_strerror(errno)); + nvme_show_error("smart log: %s", nvme_strerror(err)); return err; } -static int get_ana_log(int argc, char **argv, struct command *cmd, +static int get_ana_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve ANA log for the given device in " "decoded format (default), json or binary."; const char *groups = "Return ANA groups only."; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; _cleanup_free_ struct nvme_ana_log *ana_log = NULL; size_t max_ana_log_len; @@ -670,7 +562,8 @@ static int get_ana_log(int argc, char **argv, struct command *cmd, NVME_ARGS(opts, OPT_FLAG("groups", 'g', &cfg.groups, groups)); - err = parse_and_open(&dev, argc, argv, desc, opts); + + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -684,10 +577,10 @@ static int get_ana_log(int argc, char **argv, struct command *cmd, if (!ctrl) return -ENOMEM; - err = nvme_cli_identify_ctrl(dev, ctrl); + err = nvme_identify_ctrl(hdl, ctrl); if (err) { nvme_show_error("ERROR : nvme_identify_ctrl() failed: %s", - nvme_strerror(errno)); + nvme_strerror(err)); return err; } @@ -702,19 +595,18 @@ static int get_ana_log(int argc, char **argv, struct command *cmd, if (!ana_log) return -ENOMEM; - err = nvme_cli_get_ana_log_atomic(dev, cfg.groups, true, 10, - ana_log, &ana_log_len); + err = nvme_get_ana_log_atomic(hdl, true, cfg.groups, ana_log, &ana_log_len, 10); if (!err) - nvme_show_ana_log(ana_log, dev->name, ana_log_len, flags); + nvme_show_ana_log(ana_log, nvme_transport_handle_get_name(hdl), ana_log_len, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("ana-log: %s", nvme_strerror(errno)); + nvme_show_error("ana-log: %s", nvme_strerror(err)); return err; } -static int parse_telemetry_da(struct nvme_dev *dev, +static int parse_telemetry_da(struct nvme_transport_handle *hdl, enum nvme_telemetry_da da, struct nvme_telemetry_log *telem, size_t *size, @@ -763,7 +655,7 @@ static int parse_telemetry_da(struct nvme_dev *dev, return 0; } -static int get_log_telemetry_ctrl(struct nvme_dev *dev, bool rae, size_t size, +static int get_log_telemetry_ctrl(struct nvme_transport_handle *hdl, bool rae, size_t size, struct nvme_telemetry_log **buf) { struct nvme_telemetry_log *log; @@ -771,22 +663,19 @@ static int get_log_telemetry_ctrl(struct nvme_dev *dev, bool rae, size_t size, log = nvme_alloc(size); if (!log) - return -errno; + return -ENOMEM; - err = nvme_cli_get_log_telemetry_ctrl(dev, rae, 0, size, log); + err = nvme_get_log_telemetry_ctrl(hdl, rae, 0, log, size); if (err) { free(log); - if (errno) - return -errno; - else - return err; + return err; } *buf = log; return 0; } -static int get_log_telemetry_host(struct nvme_dev *dev, size_t size, +static int get_log_telemetry_host(struct nvme_transport_handle *hdl, size_t size, struct nvme_telemetry_log **buf) { struct nvme_telemetry_log *log; @@ -794,22 +683,19 @@ static int get_log_telemetry_host(struct nvme_dev *dev, size_t size, log = nvme_alloc(size); if (!log) - return -errno; + return -ENOMEM; - err = nvme_cli_get_log_telemetry_host(dev, 0, size, log); + err = nvme_get_log_telemetry_host(hdl, 0, log, size); if (err) { free(log); - if (errno) - return -errno; - else - return err; + return err; } *buf = log; return 0; } -static int __create_telemetry_log_host(struct nvme_dev *dev, +static int __create_telemetry_log_host(struct nvme_transport_handle *hdl, enum nvme_telemetry_da da, size_t *size, struct nvme_telemetry_log **buf, @@ -822,22 +708,18 @@ static int __create_telemetry_log_host(struct nvme_dev *dev, if (!log) return -ENOMEM; - err = nvme_cli_get_log_create_telemetry_host_mcda(dev, da, log); - if (err) { - if (errno) - return -errno; - else - return err; - } + err = nvme_get_log_create_telemetry_host_mcda(hdl, da, log); + if (err) + return err; - err = parse_telemetry_da(dev, da, log, size, da4_support); + err = parse_telemetry_da(hdl, da, log, size, da4_support); if (err) return err; - return get_log_telemetry_host(dev, *size, buf); + return get_log_telemetry_host(hdl, *size, buf); } -static int __get_telemetry_log_ctrl(struct nvme_dev *dev, +static int __get_telemetry_log_ctrl(struct nvme_transport_handle *hdl, bool rae, enum nvme_telemetry_da da, size_t *size, @@ -849,23 +731,21 @@ static int __get_telemetry_log_ctrl(struct nvme_dev *dev, log = nvme_alloc(NVME_LOG_TELEM_BLOCK_SIZE); if (!log) - return -errno; + return -ENOMEM; /* * set rae = true so it won't clear the current telemetry log in * controller */ - err = nvme_cli_get_log_telemetry_ctrl(dev, true, 0, - NVME_LOG_TELEM_BLOCK_SIZE, - log); + err = nvme_get_log_telemetry_ctrl(hdl, true, 0, log, + NVME_LOG_TELEM_BLOCK_SIZE); if (err) goto free; if (!log->ctrlavail) { if (!rae) { - err = nvme_cli_get_log_telemetry_ctrl(dev, rae, 0, - NVME_LOG_TELEM_BLOCK_SIZE, - log); + err = nvme_get_log_telemetry_ctrl(hdl, rae, 0, log, + NVME_LOG_TELEM_BLOCK_SIZE); goto free; } @@ -876,18 +756,18 @@ static int __get_telemetry_log_ctrl(struct nvme_dev *dev, return 0; } - err = parse_telemetry_da(dev, da, log, size, da4_support); + err = parse_telemetry_da(hdl, da, log, size, da4_support); if (err) goto free; - return get_log_telemetry_ctrl(dev, rae, *size, buf); + return get_log_telemetry_ctrl(hdl, rae, *size, buf); free: free(log); return err; } -static int __get_telemetry_log_host(struct nvme_dev *dev, +static int __get_telemetry_log_host(struct nvme_transport_handle *hdl, enum nvme_telemetry_da da, size_t *size, struct nvme_telemetry_log **buf, @@ -898,22 +778,21 @@ static int __get_telemetry_log_host(struct nvme_dev *dev, log = nvme_alloc(sizeof(*log)); if (!log) - return -errno; + return -ENOMEM; - err = nvme_cli_get_log_telemetry_host(dev, 0, - NVME_LOG_TELEM_BLOCK_SIZE, - log); + err = nvme_get_log_telemetry_host(hdl, 0, log, + NVME_LOG_TELEM_BLOCK_SIZE); if (err) return err; - err = parse_telemetry_da(dev, da, log, size, da4_support); + err = parse_telemetry_da(hdl, da, log, size, da4_support); if (err) return err; - return get_log_telemetry_host(dev, *size, buf); + return get_log_telemetry_host(hdl, *size, buf); } -static int get_telemetry_log(int argc, char **argv, struct command *cmd, +static int get_telemetry_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve telemetry log and write to binary file"; @@ -926,7 +805,8 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, _cleanup_free_ struct nvme_telemetry_log *log = NULL; _cleanup_free_ struct nvme_id_ctrl *id_ctrl = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_fd_ int output = -1; int err = 0; size_t total_size = 0; @@ -961,7 +841,8 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, OPT_FLAG("rae", 'r', &cfg.rae, rae), OPT_BYTE("mcda", 'm', &cfg.mcda, mcda)); - err = parse_and_open(&dev, argc, argv, desc, opts); + + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -991,9 +872,10 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, if (!id_ctrl) return -ENOMEM; - if (nvme_cli_identify_ctrl(dev, id_ctrl)) { - perror("identify-ctrl"); - return -errno; + err = nvme_identify_ctrl(hdl, id_ctrl); + if (err) { + nvme_show_error("identify-ctrl"); + return err; } da4_support = id_ctrl->lpa & 0x40; @@ -1004,7 +886,7 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, return -EINVAL; } - err = nvme_set_etdas(dev_fd(dev), &host_behavior_changed); + err = nvme_set_etdas(hdl, &host_behavior_changed); if (err) { fprintf(stderr, "%s: Failed to set ETDAS bit\n", __func__); return err; @@ -1023,17 +905,17 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, return -ENOMEM; if (cfg.ctrl_init) - err = __get_telemetry_log_ctrl(dev, cfg.rae, cfg.data_area, + err = __get_telemetry_log_ctrl(hdl, cfg.rae, cfg.data_area, &total_size, &log, da4_support); else if (cfg.host_gen) - err = __create_telemetry_log_host(dev, cfg.data_area, + err = __create_telemetry_log_host(hdl, cfg.data_area, &total_size, &log, da4_support); else - err = __get_telemetry_log_host(dev, cfg.data_area, + err = __get_telemetry_log_host(hdl, cfg.data_area, &total_size, &log, da4_support); if (err < 0) { - nvme_show_error("get-telemetry-log: %s", nvme_strerror(errno)); + nvme_show_error("get-telemetry-log: %s", nvme_strerror(err)); return err; } else if (err > 0) { nvme_show_status(err); @@ -1071,7 +953,7 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, if (host_behavior_changed) { host_behavior_changed = false; - err = nvme_clear_etdas(dev_fd(dev), &host_behavior_changed); + err = nvme_clear_etdas(hdl, &host_behavior_changed); if (err) { fprintf(stderr, "%s: Failed to clear ETDAS bit\n", __func__); return err; @@ -1081,13 +963,14 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, return err; } -static int get_endurance_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_endurance_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieves endurance groups log page and prints the log."; const char *group_id = "The endurance group identifier"; _cleanup_free_ struct nvme_endurance_group_log *endurance_log = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err; @@ -1102,7 +985,8 @@ static int get_endurance_log(int argc, char **argv, struct command *cmd, struct NVME_ARGS(opts, OPT_SHRT("group-id", 'g', &cfg.group_id, group_id)); - err = parse_and_open(&dev, argc, argv, desc, opts); + + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -1116,20 +1000,20 @@ static int get_endurance_log(int argc, char **argv, struct command *cmd, struct if (!endurance_log) return -ENOMEM; - err = nvme_cli_get_log_endurance_group(dev, cfg.group_id, - endurance_log); + err = nvme_get_log_endurance_group(hdl, cfg.group_id, + endurance_log); if (!err) nvme_show_endurance_log(endurance_log, cfg.group_id, - dev->name, flags); + nvme_transport_handle_get_name(hdl), flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("endurance log: %s", nvme_strerror(errno)); + nvme_show_error("endurance log: %s", nvme_strerror(err)); return err; } -static int collect_effects_log(struct nvme_dev *dev, enum nvme_csi csi, +static int collect_effects_log(struct nvme_transport_handle *hdl, enum nvme_csi csi, struct list_head *list, int flags) { nvme_effects_log_node_t *node; @@ -1141,7 +1025,7 @@ static int collect_effects_log(struct nvme_dev *dev, enum nvme_csi csi, node->csi = csi; - err = nvme_cli_get_log_cmd_effects(dev, csi, &node->effects); + err = nvme_get_log_cmd_effects(hdl, csi, &node->effects); if (err) { free(node); return err; @@ -1150,11 +1034,13 @@ static int collect_effects_log(struct nvme_dev *dev, enum nvme_csi csi, return 0; } -static int get_effects_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_effects_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve command effects log page and print the table."; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd64 cmd; struct list_head log_pages; nvme_effects_log_node_t *node; @@ -1180,7 +1066,8 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_log), OPT_INT("csi", 'c', &cfg.csi, csi)); - err = parse_and_open(&dev, argc, argv, desc, opts); + + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -1200,37 +1087,31 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl if (cfg.csi < 0) { __u64 cap; - if (is_blkdev(dev)) { + if (nvme_transport_handle_is_blkdev(hdl)) { nvme_show_error("Block device isn't allowed without csi"); return -EINVAL; } - bar = mmap_registers(dev, false); + bar = mmap_registers(hdl, false); if (bar) { cap = mmio_read64(bar + NVME_REG_CAP); munmap(bar, getpagesize()); } else { - struct nvme_get_property_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .offset = NVME_REG_CAP, - .value = &cap, - .timeout = nvme_cfg.timeout, - }; - err = nvme_get_property(&args); + nvme_init_get_property(&cmd, NVME_REG_CAP); + err = nvme_submit_admin_passthru64(hdl, &cmd, &cap); if (err) goto cleanup_list; } if (NVME_CAP_CSS(cap) & NVME_CAP_CSS_NVM) - err = collect_effects_log(dev, NVME_CSI_NVM, + err = collect_effects_log(hdl, NVME_CSI_NVM, &log_pages, flags); if (!err && (NVME_CAP_CSS(cap) & NVME_CAP_CSS_CSI)) - err = collect_effects_log(dev, NVME_CSI_ZNS, + err = collect_effects_log(hdl, NVME_CSI_ZNS, &log_pages, flags); } else { - err = collect_effects_log(dev, cfg.csi, &log_pages, flags); + err = collect_effects_log(hdl, cfg.csi, &log_pages, flags); } if (!err) @@ -1247,19 +1128,20 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl return err; } -static int get_supported_log_pages(int argc, char **argv, struct command *cmd, +static int get_supported_log_pages(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve supported logs and print the table."; _cleanup_free_ struct nvme_supported_log_pages *supports = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err = -1; NVME_ARGS(opts); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -1276,18 +1158,18 @@ static int get_supported_log_pages(int argc, char **argv, struct command *cmd, if (!supports) return -ENOMEM; - err = nvme_cli_get_log_supported_log_pages(dev, false, supports); + err = nvme_get_log_supported_log_pages(hdl, supports); if (!err) - nvme_show_supported_log(supports, dev->name, flags); + nvme_show_supported_log(supports, nvme_transport_handle_get_name(hdl), flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("supported log pages: %s", nvme_strerror(errno)); + nvme_show_error("supported log pages: %s", nvme_strerror(err)); return err; } -static int get_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_error_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve specified number of " "error log entries from a given device " @@ -1296,7 +1178,8 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug const char *raw = "dump in binary format"; _cleanup_free_ struct nvme_error_log_page *err_log = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct nvme_id_ctrl ctrl = { 0 }; nvme_print_flags_t flags; int err = -1; @@ -1315,7 +1198,7 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug OPT_UINT("log-entries", 'e', &cfg.log_entries, log_entries), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -1333,7 +1216,7 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug return -1; } - err = nvme_cli_identify_ctrl(dev, &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err < 0) { nvme_show_perror("identify controller"); return err; @@ -1347,10 +1230,10 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug if (!err_log) return -ENOMEM; - err = nvme_cli_get_log_error(dev, cfg.log_entries, false, err_log); + err = nvme_get_log_error(hdl, NVME_NSID_ALL, cfg.log_entries, err_log); if (!err) nvme_show_error_log(err_log, cfg.log_entries, - dev->name, flags); + nvme_transport_handle_get_name(hdl), flags); else if (err > 0) nvme_show_status(err); else @@ -1359,13 +1242,14 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug return err; } -static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_fw_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve the firmware log for the " "specified device in either decoded format (default) or binary."; _cleanup_free_ struct nvme_firmware_slot *fw_log = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err; @@ -1380,7 +1264,7 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin NVME_ARGS(opts, OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_use)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -1397,13 +1281,13 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin if (!fw_log) return -ENOMEM; - err = nvme_cli_get_log_fw_slot(dev, false, fw_log); + err = nvme_get_log_fw_slot(hdl, false, fw_log); if (!err) - nvme_show_fw_log(fw_log, dev->name, flags); + nvme_show_fw_log(fw_log, nvme_transport_handle_get_name(hdl), flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("fw log: %s", nvme_strerror(errno)); + nvme_show_error("fw log: %s", nvme_strerror(err)); return err; } @@ -1411,9 +1295,9 @@ 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, bool alloc) { _cleanup_free_ char *desc = NULL; - _cleanup_free_ struct nvme_ns_list *changed_ns_list_log = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err; @@ -1433,7 +1317,7 @@ static int get_changed_ns_list_log(int argc, char **argv, bool alloc) "in either decoded format (default) or binary.") < 0) desc = NULL; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -1451,37 +1335,37 @@ static int get_changed_ns_list_log(int argc, char **argv, bool alloc) return -ENOMEM; if (alloc) - err = nvme_cli_get_log_changed_alloc_ns_list(dev, true, - sizeof(*changed_ns_list_log), - changed_ns_list_log); + err = nvme_get_log_changed_alloc_ns_list(hdl, + changed_ns_list_log, sizeof(*changed_ns_list_log)); else - err = nvme_cli_get_log_changed_ns_list(dev, true, - changed_ns_list_log); + err = nvme_get_log_changed_ns_list(hdl, NVME_NSID_NONE, + changed_ns_list_log); if (!err) - nvme_show_changed_ns_list_log(changed_ns_list_log, dev->name, flags, alloc); + nvme_show_changed_ns_list_log(changed_ns_list_log, nvme_transport_handle_get_name(hdl), + flags, alloc); else if (err > 0) nvme_show_status(err); else nvme_show_error("changed %s ns list log: %s", alloc ? "allocated" : "attached", - nvme_strerror(errno)); + nvme_strerror(err)); return err; } -static int get_changed_attach_ns_list_log(int argc, char **argv, struct command *cmd, +static int get_changed_attach_ns_list_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { return get_changed_ns_list_log(argc, argv, false); } -static int get_changed_alloc_ns_list_log(int argc, char **argv, struct command *cmd, +static int get_changed_alloc_ns_list_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { return get_changed_ns_list_log(argc, argv, true); } static int get_pred_lat_per_nvmset_log(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { const char *desc = "Retrieve Predictable latency per nvm set log " "page and prints it for the given device in either decoded " @@ -1489,7 +1373,8 @@ static int get_pred_lat_per_nvmset_log(int argc, char **argv, const char *nvmset_id = "NVM Set Identifier"; _cleanup_free_ struct nvme_nvmset_predictable_lat_log *plpns_log = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err; @@ -1507,7 +1392,7 @@ static int get_pred_lat_per_nvmset_log(int argc, char **argv, OPT_SHRT("nvmset-id", 'i', &cfg.nvmset_id, nvmset_id), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_use)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -1524,28 +1409,30 @@ static int get_pred_lat_per_nvmset_log(int argc, char **argv, if (!plpns_log) return -ENOMEM; - err = nvme_cli_get_log_predictable_lat_nvmset(dev, cfg.nvmset_id, - plpns_log); + err = nvme_get_log_predictable_lat_nvmset(hdl, cfg.nvmset_id, + plpns_log); if (!err) - nvme_show_predictable_latency_per_nvmset(plpns_log, cfg.nvmset_id, dev->name, + nvme_show_predictable_latency_per_nvmset(plpns_log, cfg.nvmset_id, + nvme_transport_handle_get_name(hdl), flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("predictable latency per nvm set: %s", nvme_strerror(errno)); + nvme_show_error("predictable latency per nvm set: %s", nvme_strerror(err)); return err; } static int get_pred_lat_event_agg_log(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { const char *desc = "Retrieve Predictable Latency Event " "Aggregate Log page and prints it, for the given " "device in either decoded format(default), json or binary."; const char *log_entries = "Number of pending NVM Set log Entries list"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; _cleanup_free_ void *pea_log = NULL; nvme_print_flags_t flags; @@ -1569,7 +1456,7 @@ static int get_pred_lat_event_agg_log(int argc, char **argv, OPT_FLAG("rae", 'r', &cfg.rae, rae), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_use)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -1591,9 +1478,9 @@ static int get_pred_lat_event_agg_log(int argc, char **argv, if (!ctrl) return -ENOMEM; - err = nvme_cli_identify_ctrl(dev, ctrl); + err = nvme_identify_ctrl(hdl, ctrl); if (err < 0) { - nvme_show_error("identify controller: %s", nvme_strerror(errno)); + nvme_show_error("identify controller: %s", nvme_strerror(err)); return err; } else if (err) { nvme_show_status(err); @@ -1607,22 +1494,22 @@ static int get_pred_lat_event_agg_log(int argc, char **argv, if (!pea_log) return -ENOMEM; - err = nvme_cli_get_log_predictable_lat_event(dev, cfg.rae, 0, - log_size, pea_log); + err = nvme_get_log_predictable_lat_event(hdl, cfg.rae, 0, + pea_log, log_size); if (!err) nvme_show_predictable_latency_event_agg_log(pea_log, cfg.log_entries, log_size, - dev->name, flags); + nvme_transport_handle_get_name(hdl), flags); else if (err > 0) nvme_show_status(err); else nvme_show_error("predictable latency event aggregate log page: %s", - nvme_strerror(errno)); + nvme_strerror(err)); return err; } static int get_persistent_event_log(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { const char *desc = "Retrieve Persistent Event log info for " "the given device in either decoded format(default), json or binary."; @@ -1633,7 +1520,8 @@ static int get_persistent_event_log(int argc, char **argv, _cleanup_free_ struct nvme_persistent_event_log *pevent = NULL; struct nvme_persistent_event_log *pevent_collected = NULL; _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; void *pevent_log_info; int err; @@ -1655,7 +1543,7 @@ static int get_persistent_event_log(int argc, char **argv, OPT_UINT("log_len", 'l', &cfg.log_len, log_len), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_use)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -1672,10 +1560,10 @@ static int get_persistent_event_log(int argc, char **argv, if (!pevent) return -ENOMEM; - err = nvme_cli_get_log_persistent_event(dev, cfg.action, - sizeof(*pevent), pevent); + err = nvme_get_log_persistent_event(hdl, cfg.action, + pevent, sizeof(*pevent)); if (err < 0) { - nvme_show_error("persistent event log: %s", nvme_strerror(errno)); + nvme_show_error("persistent event log: %s", nvme_strerror(err)); return err; } else if (err) { nvme_show_status(err); @@ -1710,14 +1598,14 @@ static int get_persistent_event_log(int argc, char **argv, return -ENOMEM; } - err = nvme_cli_get_log_persistent_event(dev, cfg.action, - cfg.log_len, pevent_log_info); + err = nvme_get_log_persistent_event(hdl, cfg.action, + pevent_log_info, cfg.log_len); if (!err) { - err = nvme_cli_get_log_persistent_event(dev, cfg.action, - sizeof(*pevent), - pevent); + err = nvme_get_log_persistent_event(hdl, cfg.action, + pevent, + sizeof(*pevent)); if (err < 0) { - nvme_show_error("persistent event log: %s", nvme_strerror(errno)); + nvme_show_error("persistent event log: %s", nvme_strerror(err)); return err; } else if (err) { nvme_show_status(err); @@ -1731,25 +1619,26 @@ static int get_persistent_event_log(int argc, char **argv, } nvme_show_persistent_event_log(pevent_log_info, cfg.action, - cfg.log_len, dev->name, flags); + cfg.log_len, nvme_transport_handle_get_name(hdl), flags); } else if (err > 0) { nvme_show_status(err); } else { - nvme_show_error("persistent event log: %s", nvme_strerror(errno)); + nvme_show_error("persistent event log: %s", nvme_strerror(err)); } return err; } static int get_endurance_event_agg_log(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { const char *desc = "Retrieve Retrieve Predictable Latency " "Event Aggregate page and prints it, for the given " "device in either decoded format(default), json or binary."; const char *log_entries = "Number of pending Endurance Group Event log Entries list"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; _cleanup_free_ void *endurance_log = NULL; nvme_print_flags_t flags; @@ -1773,7 +1662,7 @@ static int get_endurance_event_agg_log(int argc, char **argv, OPT_FLAG("rae", 'r', &cfg.rae, rae), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_use)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -1795,9 +1684,9 @@ static int get_endurance_event_agg_log(int argc, char **argv, if (!ctrl) return -ENOMEM; - err = nvme_cli_identify_ctrl(dev, ctrl); + err = nvme_identify_ctrl(hdl, ctrl); if (err < 0) { - nvme_show_error("identify controller: %s", nvme_strerror(errno)); + nvme_show_error("identify controller: %s", nvme_strerror(err)); return err; } else if (err) { nvme_show_error("could not identify controller"); @@ -1811,27 +1700,28 @@ static int get_endurance_event_agg_log(int argc, char **argv, if (!endurance_log) return -ENOMEM; - err = nvme_cli_get_log_endurance_grp_evt(dev, cfg.rae, 0, log_size, - endurance_log); + err = nvme_get_log_endurance_grp_evt(hdl, cfg.rae, 0, + endurance_log, log_size); if (!err) nvme_show_endurance_group_event_agg_log(endurance_log, cfg.log_entries, log_size, - dev->name, flags); + nvme_transport_handle_get_name(hdl), flags); else if (err > 0) nvme_show_status(err); else nvme_show_error("endurance group event aggregate log page: %s", - nvme_strerror(errno)); + nvme_strerror(err)); return err; } static int get_lba_status_log(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { const char *desc = "Retrieve Get LBA Status Info Log and prints it, " "for the given device in either decoded format(default),json or binary."; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ void *lba_status = NULL; nvme_print_flags_t flags; __u32 lslplen; @@ -1848,7 +1738,7 @@ static int get_lba_status_log(int argc, char **argv, NVME_ARGS(opts, OPT_FLAG("rae", 'r', &cfg.rae, rae)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -1858,10 +1748,9 @@ static int get_lba_status_log(int argc, char **argv, return err; } - err = nvme_cli_get_log_lba_status(dev, true, 0, sizeof(__u32), - &lslplen); + err = nvme_get_log_lba_status(hdl, false, 0, &lslplen, sizeof(__u32)); if (err < 0) { - nvme_show_error("lba status log page: %s", nvme_strerror(errno)); + nvme_show_error("lba status log page: %s", nvme_strerror(err)); return err; } else if (err) { nvme_show_status(err); @@ -1872,19 +1761,19 @@ static int get_lba_status_log(int argc, char **argv, if (!lba_status) return -ENOMEM; - err = nvme_cli_get_log_lba_status(dev, cfg.rae, 0, lslplen, lba_status); + err = nvme_get_log_lba_status(hdl, cfg.rae, 0, lba_status, lslplen); if (!err) - nvme_show_lba_status_log(lba_status, lslplen, dev->name, flags); + nvme_show_lba_status_log(lba_status, lslplen, nvme_transport_handle_get_name(hdl), flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("lba status log page: %s", nvme_strerror(errno)); + nvme_show_error("lba status log page: %s", nvme_strerror(err)); return err; } static int get_resv_notif_log(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { const char *desc = "Retrieve Reservation Notification " @@ -1892,13 +1781,14 @@ static int get_resv_notif_log(int argc, char **argv, "device in either decoded format(default), json or binary."; _cleanup_free_ struct nvme_resv_notification_log *resv = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err; NVME_ARGS(opts); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -1912,26 +1802,27 @@ static int get_resv_notif_log(int argc, char **argv, if (!resv) return -ENOMEM; - err = nvme_cli_get_log_reservation(dev, false, resv); + err = nvme_get_log_reservation(hdl, resv); if (!err) - nvme_show_resv_notif_log(resv, dev->name, flags); + nvme_show_resv_notif_log(resv, nvme_transport_handle_get_name(hdl), flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("resv notifi log: %s", nvme_strerror(errno)); + nvme_show_error("resv notifi log: %s", nvme_strerror(err)); return err; } -static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_boot_part_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Boot Partition " "log page and prints it, for the given " "device in either decoded format(default), json or binary."; const char *fname = "boot partition data output file name"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ struct nvme_boot_partition *boot = NULL; _cleanup_free_ __u8 *bp_log = NULL; nvme_print_flags_t flags; @@ -1953,7 +1844,7 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct OPT_BYTE("lsp", 's', &cfg.lsp, lsp), OPT_FILE("output-file", 'f', &cfg.file_name, fname)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -1984,10 +1875,9 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct if (!boot) return -ENOMEM; - err = nvme_cli_get_log_boot_partition(dev, false, cfg.lsp, - sizeof(*boot), boot); + err = nvme_get_log_boot_partition(hdl, cfg.lsp, boot, sizeof(*boot)); if (err < 0) { - nvme_show_error("boot partition log: %s", nvme_strerror(errno)); + nvme_show_error("boot partition log: %s", nvme_strerror(err)); return err; } else if (err) { nvme_show_status(err); @@ -1999,15 +1889,16 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct if (!bp_log) return -ENOMEM; - err = nvme_cli_get_log_boot_partition(dev, false, cfg.lsp, - sizeof(*boot) + bpsz, - (struct nvme_boot_partition *)bp_log); + err = nvme_get_log_boot_partition(hdl, cfg.lsp, + (struct nvme_boot_partition *)bp_log, + sizeof(*boot) + bpsz); if (!err) - nvme_show_boot_part_log(&bp_log, dev->name, sizeof(*boot) + bpsz, flags); + nvme_show_boot_part_log(&bp_log, nvme_transport_handle_get_name(hdl), + sizeof(*boot) + bpsz, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("boot partition log: %s", nvme_strerror(errno)); + nvme_show_error("boot partition log: %s", nvme_strerror(err)); err = write(output, (void *) bp_log + sizeof(*boot), bpsz); if (err != bpsz) @@ -2019,7 +1910,7 @@ static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct return err; } -static int get_phy_rx_eom_log(int argc, char **argv, struct command *cmd, +static int get_phy_rx_eom_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Physical Interface Receiver Eye Opening " @@ -2029,7 +1920,8 @@ static int get_phy_rx_eom_log(int argc, char **argv, struct command *cmd, _cleanup_free_ struct nvme_phy_rx_eom_log *phy_rx_eom_log = NULL; size_t phy_rx_eom_log_len; nvme_print_flags_t flags; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err = -1; __u8 lsp_tmp; @@ -2047,7 +1939,7 @@ static int get_phy_rx_eom_log(int argc, char **argv, struct command *cmd, OPT_BYTE("lsp", 's', &cfg.lsp, lsp), OPT_SHRT("controller", 'c', &cfg.controller, controller)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -2077,13 +1969,13 @@ static int get_phy_rx_eom_log(int argc, char **argv, struct command *cmd, /* Just read measurement, take given action when fetching full log */ lsp_tmp = cfg.lsp & 0xf3; - err = nvme_cli_get_log_phy_rx_eom(dev, lsp_tmp, cfg.controller, phy_rx_eom_log_len, - phy_rx_eom_log); + err = nvme_get_log_phy_rx_eom(hdl, lsp_tmp, cfg.controller, phy_rx_eom_log, + phy_rx_eom_log_len); if (err) { if (err > 0) nvme_show_status(err); else - nvme_show_error("phy-rx-eom-log: %s", nvme_strerror(errno)); + nvme_show_error("phy-rx-eom-log: %s", nvme_strerror(err)); return err; } @@ -2099,25 +1991,26 @@ static int get_phy_rx_eom_log(int argc, char **argv, struct command *cmd, if (!phy_rx_eom_log) return -ENOMEM; - err = nvme_cli_get_log_phy_rx_eom(dev, cfg.lsp, cfg.controller, phy_rx_eom_log_len, - phy_rx_eom_log); + err = nvme_get_log_phy_rx_eom(hdl, cfg.lsp, cfg.controller, phy_rx_eom_log, + phy_rx_eom_log_len); if (!err) nvme_show_phy_rx_eom_log(phy_rx_eom_log, cfg.controller, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("phy-rx-eom-log: %s", nvme_strerror(errno)); + nvme_show_error("phy-rx-eom-log: %s", nvme_strerror(err)); return err; } -static int get_media_unit_stat_log(int argc, char **argv, struct command *cmd, +static int get_media_unit_stat_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve the configuration and wear of media units and print it"; _cleanup_free_ struct nvme_media_unit_stat_log *mus = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err = -1; @@ -2135,7 +2028,7 @@ static int get_media_unit_stat_log(int argc, char **argv, struct command *cmd, OPT_UINT("domain-id", 'd', &cfg.domainid, domainid), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_use)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -2152,24 +2045,25 @@ static int get_media_unit_stat_log(int argc, char **argv, struct command *cmd, if (!mus) return -ENOMEM; - err = nvme_cli_get_log_media_unit_stat(dev, cfg.domainid, mus); + err = nvme_get_log_media_unit_stat(hdl, cfg.domainid, mus); if (!err) nvme_show_media_unit_stat_log(mus, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("media unit status log: %s", nvme_strerror(errno)); + nvme_show_error("media unit status log: %s", nvme_strerror(err)); return err; } -static int get_supp_cap_config_log(int argc, char **argv, struct command *cmd, +static int get_supp_cap_config_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve the list of Supported Capacity Configuration Descriptors"; _cleanup_free_ struct nvme_supported_cap_config_list_log *cap_log = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err = -1; @@ -2187,7 +2081,7 @@ static int get_supp_cap_config_log(int argc, char **argv, struct command *cmd, OPT_UINT("domain-id", 'd', &cfg.domainid, domainid), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_use)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -2204,8 +2098,8 @@ static int get_supp_cap_config_log(int argc, char **argv, struct command *cmd, if (!cap_log) return -ENOMEM; - err = nvme_cli_get_log_support_cap_config_list(dev, cfg.domainid, - cap_log); + err = nvme_get_log_support_cap_config_list(hdl, cfg.domainid, + cap_log); if (!err) nvme_show_supported_cap_config_log(cap_log, flags); else if (err > 0) @@ -2216,20 +2110,22 @@ static int get_supp_cap_config_log(int argc, char **argv, struct command *cmd, return err; } -static int io_mgmt_send(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int io_mgmt_send(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "I/O Management Send"; const char *data = "optional file for data (default stdin)"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_fd_ int dfd = STDIN_FILENO; _cleanup_free_ void *buf = NULL; + struct nvme_passthru_cmd cmd; int err = -1; - _cleanup_fd_ int dfd = STDIN_FILENO; struct config { + __u32 nsid; __u16 mos; __u8 mo; - __u32 namespace_id; char *file; __u32 data_len; }; @@ -2239,18 +2135,18 @@ static int io_mgmt_send(int argc, char **argv, struct command *cmd, struct plugi }; NVME_ARGS(opts, - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), - OPT_SHRT("mos", 's', &cfg.mos, mos), - OPT_BYTE("mo", 'm', &cfg.mo, mo), - OPT_FILE("data", 'd', &cfg.file, data), - OPT_UINT("data-len", 'l', &cfg.data_len, buf_len)); + OPT_UINT("namespace-id", 'n', &cfg.nsid, namespace_id_desired), + OPT_SHRT("mos", 's', &cfg.mos, mos), + OPT_BYTE("mo", 'm', &cfg.mo, mo), + OPT_FILE("data", 'd', &cfg.file, data), + OPT_UINT("data-len", 'l', &cfg.data_len, buf_len)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + if (!cfg.nsid) { + err = nvme_get_nsid(hdl, &cfg.nsid); if (err < 0) { nvme_show_perror("get-namespace-id"); return err; @@ -2277,21 +2173,11 @@ static int io_mgmt_send(int argc, char **argv, struct command *cmd, struct plugi return err; } - struct nvme_io_mgmt_send_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .mos = cfg.mos, - .mo = cfg.mo, - .data_len = cfg.data_len, - .data = buf, - .timeout = nvme_cfg.timeout, - }; - - err = nvme_io_mgmt_send(&args); + nvme_init_io_mgmt_send(&cmd, cfg.nsid, cfg.mo, cfg.mos, buf, cfg.data_len); + err = nvme_submit_io_passthru(hdl, &cmd, NULL); if (!err) printf("io-mgmt-send: Success, mos:%u mo:%u nsid:%d\n", - cfg.mos, cfg.mo, cfg.namespace_id); + cfg.mos, cfg.mo, cfg.nsid); else if (err > 0) nvme_show_status(err); else @@ -2300,20 +2186,22 @@ static int io_mgmt_send(int argc, char **argv, struct command *cmd, struct plugi return err; } -static int io_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int io_mgmt_recv(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "I/O Management Receive"; const char *data = "optional file for data (default stdout)"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; _cleanup_free_ void *buf = NULL; - int err = -1; + struct nvme_passthru_cmd cmd; _cleanup_fd_ int dfd = -1; + int err = -1; struct config { __u16 mos; __u8 mo; - __u32 namespace_id; + __u32 nsid; char *file; __u32 data_len; }; @@ -2323,18 +2211,18 @@ static int io_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugi }; NVME_ARGS(opts, - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), - OPT_SHRT("mos", 's', &cfg.mos, mos), - OPT_BYTE("mo", 'm', &cfg.mo, mo), - OPT_FILE("data", 'd', &cfg.file, data), - OPT_UINT("data-len", 'l', &cfg.data_len, buf_len)); + OPT_UINT("namespace-id", 'n', &cfg.nsid, namespace_id_desired), + OPT_SHRT("mos", 's', &cfg.mos, mos), + OPT_BYTE("mo", 'm', &cfg.mo, mo), + OPT_FILE("data", 'd', &cfg.file, data), + OPT_UINT("data-len", 'l', &cfg.data_len, buf_len)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + if (!cfg.nsid) { + err = nvme_get_nsid(hdl, &cfg.nsid); if (err < 0) { nvme_show_perror("get-namespace-id"); return err; @@ -2347,21 +2235,12 @@ static int io_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugi return -ENOMEM; } - struct nvme_io_mgmt_recv_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .mos = cfg.mos, - .mo = cfg.mo, - .data_len = cfg.data_len, - .data = buf, - .timeout = nvme_cfg.timeout, - }; - - err = nvme_io_mgmt_recv(&args); + nvme_init_io_mgmt_recv(&cmd, cfg.nsid, cfg.mo, cfg.mos, buf, + cfg.data_len); + err = nvme_submit_io_passthru(hdl, &cmd, NULL); if (!err) { printf("io-mgmt-recv: Success, mos:%u mo:%u nsid:%d\n", - cfg.mos, cfg.mo, cfg.namespace_id); + cfg.mos, cfg.mo, cfg.nsid); if (cfg.file) { dfd = open(cfg.file, O_WRONLY | O_CREAT, 0644); @@ -2387,7 +2266,7 @@ static int io_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugi return err; } -static int get_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve desired number of bytes " "from a given log on a specified device in either " @@ -2401,8 +2280,10 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl const char *offset_type = "offset type"; const char *xfer_len = "read chunk size (default 4k)"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ unsigned char *log = NULL; + struct nvme_passthru_cmd cmd; int err; nvme_print_flags_t flags; @@ -2469,14 +2350,14 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl VAL_BYTE("phy-rx-eom", NVME_LOG_LID_PHY_RX_EOM), VAL_BYTE("reachability-groups", NVME_LOG_LID_REACHABILITY_GROUPS), VAL_BYTE("reachability-associations", NVME_LOG_LID_REACHABILITY_ASSOCIATIONS), - VAL_BYTE("changed-alloc-ns-list", NVME_LOG_LID_CHANGED_ALLOC_NS_LIST), + VAL_BYTE("changed-alloc-ns-list", NVME_LOG_LID_CHANGED_ALLOC_NS), VAL_BYTE("fdp-configs", NVME_LOG_LID_FDP_CONFIGS), VAL_BYTE("fdp-ruh-usage", NVME_LOG_LID_FDP_RUH_USAGE), VAL_BYTE("fdp-stats", NVME_LOG_LID_FDP_STATS), VAL_BYTE("fdp-events", NVME_LOG_LID_FDP_EVENTS), - VAL_BYTE("discover", NVME_LOG_LID_DISCOVER), - VAL_BYTE("host-discover", NVME_LOG_LID_HOST_DISCOVER), - VAL_BYTE("ave-discover", NVME_LOG_LID_AVE_DISCOVER), + VAL_BYTE("discover", NVME_LOG_LID_DISCOVERY), + VAL_BYTE("host-discover", NVME_LOG_LID_HOST_DISCOVERY), + VAL_BYTE("ave-discover", NVME_LOG_LID_AVE_DISCOVERY), VAL_BYTE("pull-model-ddc-req", NVME_LOG_LID_PULL_MODEL_DDC_REQ), VAL_BYTE("reservation", NVME_LOG_LID_RESERVATION), VAL_BYTE("sanitize", NVME_LOG_LID_SANITIZE), @@ -2499,7 +2380,7 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl OPT_FLAG("ot", 'O', &cfg.ot, offset_type), OPT_UINT("xfer-len", 'x', &cfg.xfer_len, xfer_len)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -2539,46 +2420,63 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl return -ENOMEM; struct nvme_get_log_args args = { - .args_size = sizeof(args), - .lid = cfg.log_id, .nsid = cfg.namespace_id, - .lpo = cfg.lpo, + .rae = cfg.rae, .lsp = cfg.lsp, + .lid = cfg.log_id, .lsi = cfg.lsi, - .rae = cfg.rae, - .uuidx = cfg.uuid_index, .csi = cfg.csi, .ot = cfg.ot, - .len = cfg.log_len, + .uidx = cfg.uuid_index, + .lpo = cfg.lpo, .log = log, + .len = cfg.log_len, .result = NULL, }; - err = nvme_cli_get_log_page(dev, cfg.xfer_len, &args); + nvme_init_get_log(&cmd, cfg.namespace_id, cfg.log_id, + cfg.csi, log, cfg.log_len); + cmd.cdw10 |= NVME_FIELD_ENCODE(cfg.lsp, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + cmd.cdw11 |= NVME_FIELD_ENCODE(cfg.lsi, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); + cmd.cdw12 = cfg.lpo & 0xffffffff; + cmd.cdw13 = cfg.lpo >> 32; + cmd.cdw14 |= NVME_FIELD_ENCODE(cfg.uuid_index, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK) | + NVME_FIELD_ENCODE(cfg.ot, + NVME_LOG_CDW14_OT_SHIFT, + NVME_LOG_CDW14_OT_MASK); + + err = nvme_get_log(hdl, &cmd, cfg.rae, NVME_LOG_PAGE_PDU_SIZE, NULL); if (!err) { if (!cfg.raw_binary) { - printf("Device:%s log-id:%d namespace-id:%#x\n", dev->name, cfg.log_id, - cfg.namespace_id); + printf("Device:%s log-id:%d namespace-id:%#x\n", nvme_transport_handle_get_name(hdl), + cfg.log_id, cfg.namespace_id); d(log, cfg.log_len, 16, 1); if (argconfig_parse_seen(opts, "verbose")) - nvme_show_log(dev->name, &args, VERBOSE); + nvme_show_log(nvme_transport_handle_get_name(hdl), &args, VERBOSE); } else { d_raw((unsigned char *)log, cfg.log_len); } } else if (err > 0) { nvme_show_status(err); } else { - nvme_show_error("log page: %s", nvme_strerror(errno)); + nvme_show_error("log page: %s", nvme_strerror(err)); } return err; } -static int sanitize_log(int argc, char **argv, struct command *command, struct plugin *plugin) +static int sanitize_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve sanitize log and show it."; _cleanup_free_ struct nvme_sanitize_log_page *sanitize_log = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err; @@ -2599,7 +2497,7 @@ static int sanitize_log(int argc, char **argv, struct command *command, struct p OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable_log), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_log)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -2619,24 +2517,25 @@ static int sanitize_log(int argc, char **argv, struct command *command, struct p if (!sanitize_log) return -ENOMEM; - err = nvme_cli_get_log_sanitize(dev, cfg.rae, sanitize_log); + err = nvme_get_log_sanitize(hdl, cfg.rae, sanitize_log); if (!err) - nvme_show_sanitize_log(sanitize_log, dev->name, flags); + nvme_show_sanitize_log(sanitize_log, nvme_transport_handle_get_name(hdl), flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("sanitize status log: %s", nvme_strerror(errno)); + nvme_show_error("sanitize status log: %s", nvme_strerror(err)); return err; } -static int get_fid_support_effects_log(int argc, char **argv, struct command *cmd, +static int get_fid_support_effects_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve FID Support and Effects log and show it."; _cleanup_free_ struct nvme_fid_supported_effects_log *fid_support_log = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err = -1; @@ -2651,7 +2550,7 @@ static int get_fid_support_effects_log(int argc, char **argv, struct command *cm NVME_ARGS(opts, OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable_log)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -2668,24 +2567,25 @@ static int get_fid_support_effects_log(int argc, char **argv, struct command *cm if (!fid_support_log) return -ENOMEM; - err = nvme_cli_get_log_fid_supported_effects(dev, false, fid_support_log); + err = nvme_get_log_fid_supported_effects(hdl, false, fid_support_log); if (!err) - nvme_show_fid_support_effects_log(fid_support_log, dev->name, flags); + nvme_show_fid_support_effects_log(fid_support_log, nvme_transport_handle_get_name(hdl), flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("fid support effects log: %s", nvme_strerror(errno)); + nvme_show_error("fid support effects log: %s", nvme_strerror(err)); return err; } -static int get_mi_cmd_support_effects_log(int argc, char **argv, struct command *cmd, +static int get_mi_cmd_support_effects_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve NVMe-MI Command Support and Effects log and show it."; _cleanup_free_ struct nvme_mi_cmd_supported_effects_log *mi_cmd_support_log = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err = -1; @@ -2700,7 +2600,7 @@ static int get_mi_cmd_support_effects_log(int argc, char **argv, struct command NVME_ARGS(opts, OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable_log)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -2717,25 +2617,27 @@ static int get_mi_cmd_support_effects_log(int argc, char **argv, struct command if (!mi_cmd_support_log) return -ENOMEM; - err = nvme_cli_get_log_mi_cmd_supported_effects(dev, false, mi_cmd_support_log); + err = nvme_get_log_mi_cmd_supported_effects(hdl, mi_cmd_support_log); if (!err) - nvme_show_mi_cmd_support_effects_log(mi_cmd_support_log, dev->name, flags); + nvme_show_mi_cmd_support_effects_log(mi_cmd_support_log, nvme_transport_handle_get_name(hdl), flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("mi command support effects log: %s", nvme_strerror(errno)); + nvme_show_error("mi command support effects log: %s", nvme_strerror(err)); return err; } -static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int list_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Show controller list information for the subsystem the " "given device is part of, or optionally controllers attached to a specific namespace."; const char *controller = "controller to display"; _cleanup_free_ struct nvme_ctrl_list *cntlist = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; int err; @@ -2753,7 +2655,7 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin * OPT_SHRT("cntid", 'c', &cfg.cntid, controller), OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_optional)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -2768,21 +2670,23 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin * return -ENOMEM; if (cfg.namespace_id == NVME_NSID_NONE) - err = nvme_cli_identify_ctrl_list(dev, cfg.cntid, cntlist); + nvme_init_identify_ctrl_list(&cmd, cfg.cntid, cntlist); else - err = nvme_cli_identify_nsid_ctrl_list(dev, cfg.namespace_id, - cfg.cntid, cntlist); + nvme_init_identify_ns_ctrl_list(&cmd, cfg.namespace_id, + cfg.cntid, cntlist); + + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) nvme_show_list_ctrl(cntlist, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("id controller list: %s", nvme_strerror(errno)); + nvme_show_error("id controller list: %s", nvme_strerror(err)); return err; } -static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int list_ns(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "For the specified controller handle, show the " "namespace list in the associated NVMe subsystem, optionally starting with a given nsid."; @@ -2791,7 +2695,9 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl const char *all = "show all namespaces in the subsystem, whether attached or inactive"; _cleanup_free_ struct nvme_ns_list *ns_list = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + enum nvme_identify_cns cns; nvme_print_flags_t flags; int err; @@ -2812,7 +2718,7 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl OPT_INT("csi", 'y', &cfg.csi, csi), OPT_FLAG("all", 'a', &cfg.all, all)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -2834,39 +2740,35 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl if (!ns_list) return -ENOMEM; - struct nvme_identify_args args = { - .args_size = sizeof(args), - .timeout = nvme_cfg.timeout, - .data = ns_list, - .nsid = cfg.namespace_id - 1. - }; if (cfg.csi < 0) { - args.cns = cfg.all ? NVME_IDENTIFY_CNS_ALLOCATED_NS_LIST : + cns = cfg.all ? NVME_IDENTIFY_CNS_ALLOCATED_NS_LIST : NVME_IDENTIFY_CNS_NS_ACTIVE_LIST; - } else { - args.cns = cfg.all ? NVME_IDENTIFY_CNS_CSI_ALLOCATED_NS_LIST : + cfg.csi = 0; + } else { + cns = cfg.all ? NVME_IDENTIFY_CNS_CSI_ALLOCATED_NS_LIST : NVME_IDENTIFY_CNS_CSI_NS_ACTIVE_LIST; - args.csi = cfg.csi; } - err = nvme_cli_identify(dev, &args); + err = nvme_identify(hdl, cfg.namespace_id - 1, cfg.csi, cns, ns_list, + sizeof(*ns_list)); if (!err) nvme_show_list_ns(ns_list, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("id namespace list: %s", nvme_strerror(errno)); + nvme_show_error("id namespace list: %s", nvme_strerror(err)); return err; } -static int id_ns_lba_format(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int id_ns_lba_format(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send an Identify Namespace command to the given " "device, returns capability field properties of the specified " "LBA Format index in various formats."; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ struct nvme_id_ns *ns = NULL; nvme_print_flags_t flags; int err = -1; @@ -2885,7 +2787,7 @@ static int id_ns_lba_format(int argc, char **argv, struct command *cmd, struct p OPT_UINT("lba-format-index", 'i', &cfg.lba_format_index, lba_format_index), OPT_BYTE("uuid-index", 'U', &cfg.uuid_index, uuid_index)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -2902,9 +2804,9 @@ static int id_ns_lba_format(int argc, char **argv, struct command *cmd, struct p if (!ns) return -ENOMEM; - err = nvme_identify_ns_csi_user_data_format(dev_fd(dev), + err = nvme_identify_csi_ns_user_data_format(hdl, NVME_CSI_NVM, cfg.lba_format_index, - cfg.uuid_index, NVME_CSI_NVM, ns); + cfg.uuid_index, ns); if (!err) nvme_show_id_ns(ns, 0, cfg.lba_format_index, true, flags); else if (err > 0) @@ -2915,14 +2817,16 @@ static int id_ns_lba_format(int argc, char **argv, struct command *cmd, struct p return err; } -static int id_endurance_grp_list(int argc, char **argv, struct command *cmd, +static int id_endurance_grp_list(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Show endurance group list information for the given endurance group id"; const char *endurance_grp_id = "Endurance Group ID"; _cleanup_free_ struct nvme_id_endurance_group_list *endgrp_list = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; int err = -1; @@ -2937,7 +2841,7 @@ static int id_endurance_grp_list(int argc, char **argv, struct command *cmd, NVME_ARGS(opts, OPT_SHRT("endgrp-id", 'i', &cfg.endgrp_id, endurance_grp_id)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -2951,18 +2855,20 @@ static int id_endurance_grp_list(int argc, char **argv, struct command *cmd, if (!endgrp_list) return -ENOMEM; - err = nvme_identify_endurance_group_list(dev_fd(dev), cfg.endgrp_id, endgrp_list); + nvme_init_identify_endurance_group_id(&cmd, cfg.endgrp_id, + endgrp_list); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) nvme_show_endurance_group_list(endgrp_list, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("Id endurance group list: %s", nvme_strerror(errno)); + nvme_show_error("Id endurance group list: %s", nvme_strerror(err)); return err; } -static bool is_ns_mgmt_support(struct nvme_dev *dev) +static bool is_ns_mgmt_support(struct nvme_transport_handle *hdl) { int err; @@ -2971,17 +2877,17 @@ static bool is_ns_mgmt_support(struct nvme_dev *dev) if (ctrl) return false; - err = nvme_cli_identify_ctrl(dev, ctrl); + err = nvme_identify_ctrl(hdl, ctrl); if (err) return false; return le16_to_cpu(ctrl->oacs) & NVME_CTRL_OACS_NS_MGMT; } -static void ns_mgmt_show_status(struct nvme_dev *dev, int err, char *cmd, __u32 nsid) +static void ns_mgmt_show_status(struct nvme_transport_handle *hdl, int err, char *cmd, __u32 nsid) { if (err < 0) { - nvme_show_error("%s: %s", cmd, nvme_strerror(errno)); + nvme_show_error("%s: %s", cmd, nvme_strerror(err)); return; } @@ -2992,14 +2898,14 @@ static void ns_mgmt_show_status(struct nvme_dev *dev, int err, char *cmd, __u32 nvme_show_key_value("nsid", "%d", nsid); } else { nvme_show_status(err); - if (!is_ns_mgmt_support(dev)) + if (!is_ns_mgmt_support(hdl)) nvme_show_error("NS management and attachment not supported"); } nvme_show_finish(); } -static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int delete_ns(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Delete the given namespace by " "sending a namespace management command to " @@ -3009,9 +2915,11 @@ 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"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - int err; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; + int err; struct config { __u32 namespace_id; @@ -3024,7 +2932,7 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin * NVME_ARGS(opts, OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -3035,45 +2943,49 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin * } if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return err; } } - err = nvme_cli_ns_mgmt_delete(dev, cfg.namespace_id, nvme_cfg.timeout); - ns_mgmt_show_status(dev, err, cmd->name, cfg.namespace_id); + nvme_init_ns_mgmt_delete(&cmd, cfg.namespace_id); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); + ns_mgmt_show_status(hdl, err, acmd->name, cfg.namespace_id); return err; } -static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, struct command *cmd) +static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, struct command *acmd) { + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_free_ struct nvme_ctrl_list *cntlist = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - int err, num; __u16 list[NVME_ID_CTRL_LIST_MAX]; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; + int err, num; const char *namespace_id = "namespace to attach"; const char *cont = "optional comma-sep controller id list"; struct config { - __u32 namespace_id; + __u32 nsid; char *cntlist; }; struct config cfg = { - .namespace_id = 0, + .nsid = 0, .cntlist = "", }; NVME_ARGS(opts, - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), - OPT_LIST("controllers", 'c', &cfg.cntlist, cont)); + OPT_UINT("namespace-id", 'n', &cfg.nsid, namespace_id), + OPT_LIST("controllers", 'c', &cfg.cntlist, cont)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -3083,21 +2995,21 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s return err; } - if (is_blkdev(dev)) { - nvme_show_error("%s: a block device opened (dev: %s, nsid: %d)", cmd->name, - dev->name, cfg.namespace_id); + if (nvme_transport_handle_is_blkdev(hdl)) { + nvme_show_error("%s: a block device opened (dev: %s, nsid: %d)", acmd->name, + nvme_transport_handle_get_name(hdl), cfg.nsid); return -EINVAL; } - if (!cfg.namespace_id) { - nvme_show_error("%s: namespace-id parameter required", cmd->name); + if (!cfg.nsid) { + nvme_show_error("%s: namespace-id parameter required", acmd->name); return -EINVAL; } num = argconfig_parse_comma_sep_array_u16(cfg.cntlist, list, ARRAY_SIZE(list)); if (num == -1) { - nvme_show_error("%s: controller id list is malformed", cmd->name); + nvme_show_error("%s: controller id list is malformed", acmd->name); return -EINVAL; } @@ -3110,27 +3022,27 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s } else { struct nvme_id_ctrl ctrl = { 0 }; - if (nvme_cli_identify_ctrl(dev, &ctrl)) { - perror("identify-ctrl"); - return -errno; + err = nvme_identify_ctrl(hdl, &ctrl); + if (err) { + fprintf(stderr, "identify-ctrl %s\n", nvme_strerror(-err)); + return err; } cntlist->num = cpu_to_le16(1); cntlist->identifier[0] = ctrl.cntlid; } if (attach) - err = nvme_cli_ns_attach_ctrls(dev, cfg.namespace_id, - cntlist); + nvme_init_ns_attach_ctrls(&cmd, cfg.nsid, cntlist); else - err = nvme_cli_ns_detach_ctrls(dev, cfg.namespace_id, - cntlist); + nvme_init_ns_detach_ctrls(&cmd, cfg.nsid, cntlist); - ns_mgmt_show_status(dev, err, cmd->name, cfg.namespace_id); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); + ns_mgmt_show_status(hdl, err, acmd->name, cfg.nsid); return err; } -static int attach_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int attach_ns(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Attach the given namespace to the " "given controller or comma-sep list of controllers. ID of the " @@ -3138,20 +3050,20 @@ static int attach_ns(int argc, char **argv, struct command *cmd, struct plugin * "controller. A namespace must be attached to a controller " "before IO commands may be directed to that namespace."; - return nvme_attach_ns(argc, argv, 1, desc, cmd); + return nvme_attach_ns(argc, argv, 1, desc, acmd); } -static int detach_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int detach_ns(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Detach the given namespace from the " "given controller; de-activates the given namespace's ID. A " "namespace must be attached to a controller before IO " "commands may be directed to that namespace."; - return nvme_attach_ns(argc, argv, 0, desc, cmd); + return nvme_attach_ns(argc, argv, 0, desc, acmd); } -static int parse_lba_num_si(struct nvme_dev *dev, const char *opt, +static int parse_lba_num_si(struct nvme_transport_handle *hdl, const char *opt, const char *val, __u8 flbas, __u64 *num, __u64 align) { _cleanup_free_ struct nvme_ns_list *ns_list = NULL; @@ -3164,13 +3076,6 @@ static int parse_lba_num_si(struct nvme_dev *dev, const char *opt, int err = -EINVAL; int lbas; - struct nvme_identify_args args = { - .args_size = sizeof(args), - .timeout = nvme_cfg.timeout, - .cns = NVME_IDENTIFY_CNS_NS_ACTIVE_LIST, - .nsid = nsid - 1. - }; - if (!val) return 0; @@ -3185,10 +3090,10 @@ static int parse_lba_num_si(struct nvme_dev *dev, const char *opt, if (!ctrl) return -ENOMEM; - err = nvme_cli_identify_ctrl(dev, ctrl); + err = nvme_identify_ctrl(hdl, ctrl); if (err) { if (err < 0) - nvme_show_error("identify controller: %s", nvme_strerror(errno)); + nvme_show_error("identify controller: %s", nvme_strerror(err)); else nvme_show_status(err); return err; @@ -3197,16 +3102,15 @@ static int parse_lba_num_si(struct nvme_dev *dev, const char *opt, ns_list = nvme_alloc(sizeof(*ns_list)); if (!ns_list) return -ENOMEM; - args.data = ns_list; - if ((ctrl->oacs & 0x8) >> 3) + if ((ctrl->oacs & 0x8) >> 3) { nsid = NVME_NSID_ALL; - else { - err = nvme_cli_identify(dev, &args); + } else { + err = nvme_identify_active_ns_list(hdl, nsid - 1, ns_list); if (err) { if (err < 0) nvme_show_error("identify namespace list: %s", - nvme_strerror(errno)); + nvme_strerror(err)); else nvme_show_status(err); return err; @@ -3218,10 +3122,10 @@ static int parse_lba_num_si(struct nvme_dev *dev, const char *opt, if (!ns) return -ENOMEM; - err = nvme_cli_identify_ns(dev, nsid, ns); + err = nvme_identify_ns(hdl, nsid, ns); if (err) { if (err < 0) - nvme_show_error("identify namespace: %s", nvme_strerror(errno)); + nvme_show_error("identify namespace: %s", nvme_strerror(err)); else nvme_show_status(err); return err; @@ -3230,10 +3134,11 @@ static int parse_lba_num_si(struct nvme_dev *dev, const char *opt, nvme_id_ns_flbas_to_lbaf_inuse(flbas, &lbaf); lbas = (1 << ns->lbaf[lbaf].ds) + le16_to_cpu(ns->lbaf[lbaf].ms); - if (suffix_si_parse(val, &endptr, (uint64_t *)num)) { + err = suffix_si_parse(val, &endptr, (uint64_t *)num); + if (err) { nvme_show_error("Expected long suffixed integer argument for '%s-si' but got '%s'!", opt, val); - return -errno; + return -err; } if (endptr[0]) { @@ -3248,7 +3153,7 @@ static int parse_lba_num_si(struct nvme_dev *dev, const char *opt, return 0; } -static int create_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int create_ns(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send a namespace management command " "to the specified device to create a namespace with the given " @@ -3276,18 +3181,20 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * "Requested Number of ZRWA Resources (RNUMZRWA) for Zoned Namespace Command Set"; const char *phndls = "Comma separated list of Placement Handle Associated RUH"; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ struct nvme_ns_mgmt_host_sw_specified *data = NULL; - _cleanup_free_ struct nvme_id_ns *ns = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - int err = 0, i; - __u32 nsid; - uint16_t num_phandle; - uint16_t phndl[128] = { 0, }; - _cleanup_free_ struct nvme_id_ctrl *id = NULL; _cleanup_free_ struct nvme_id_ns_granularity_list *gr_list = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_free_ struct nvme_id_ctrl *id = NULL; + _cleanup_free_ struct nvme_id_ns *ns = NULL; __u64 align_nsze = 1 << 20; /* Default 1 MiB */ __u64 align_ncap = align_nsze; + struct nvme_passthru_cmd cmd; + uint16_t phndl[128] = { 0, }; nvme_print_flags_t flags; + uint16_t num_phandle; + int err = 0, i; + __u32 nsid; struct config { __u64 nsze; @@ -3354,7 +3261,7 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * OPT_UINT("rnumzrwa", 'u', &cfg.rnumzrwa, rnumzrwa), OPT_LIST("phndls", 'p', &cfg.phndls, phndls)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -3382,10 +3289,10 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * if (!ns) return -ENOMEM; - err = nvme_cli_identify_ns(dev, NVME_NSID_ALL, ns); + err = nvme_identify_ns(hdl, NVME_NSID_ALL, ns); if (err) { if (err < 0) { - nvme_show_error("identify-namespace: %s", nvme_strerror(errno)); + nvme_show_error("identify-namespace: %s", nvme_strerror(err)); } else { fprintf(stderr, "identify failed\n"); nvme_show_status(err); @@ -3412,10 +3319,10 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * if (!id) return -ENOMEM; - err = nvme_identify_ctrl(dev_fd(dev), id); + err = nvme_identify_ctrl(hdl, id); if (err) { if (err < 0) { - nvme_show_error("identify-controller: %s", nvme_strerror(errno)); + nvme_show_error("identify-controller: %s", nvme_strerror(err)); } else { fprintf(stderr, "identify controller failed\n"); nvme_show_status(err); @@ -3428,7 +3335,7 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * if (!gr_list) return -ENOMEM; - if (!nvme_identify_ns_granularity(dev_fd(dev), gr_list)) { + if (!nvme_identify_ns_granularity(hdl, gr_list)) { struct nvme_id_ns_granularity_desc *desc; int index = cfg.flbas; @@ -3461,11 +3368,11 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * } parse_lba: - err = parse_lba_num_si(dev, "nsze", cfg.nsze_si, cfg.flbas, &cfg.nsze, align_nsze); + err = parse_lba_num_si(hdl, "nsze", cfg.nsze_si, cfg.flbas, &cfg.nsze, align_nsze); if (err) return err; - err = parse_lba_num_si(dev, "ncap", cfg.ncap_si, cfg.flbas, &cfg.ncap, align_ncap); + err = parse_lba_num_si(hdl, "ncap", cfg.ncap_si, cfg.flbas, &cfg.ncap, align_ncap); if (err) return err; @@ -3502,8 +3409,9 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * for (i = 0; i < num_phandle; i++) data->phndl[i] = cpu_to_le16(phndl[i]); - err = nvme_cli_ns_mgmt_create(dev, data, &nsid, nvme_cfg.timeout, cfg.csi); - ns_mgmt_show_status(dev, err, cmd->name, nsid); + nvme_init_ns_mgmt_create(&cmd, cfg.csi, data); + err = nvme_submit_admin_passthru(hdl, &cmd, &nsid); + ns_mgmt_show_status(hdl, err, acmd->name, nsid); return err; } @@ -3534,10 +3442,10 @@ static bool nvme_match_device_filter(nvme_subsystem_t s, return false; } -static int list_subsys(int argc, char **argv, struct command *cmd, +static int list_subsys(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - _cleanup_nvme_root_ nvme_root_t r = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; nvme_print_flags_t flags; const char *desc = "Retrieve information for subsystems"; nvme_scan_filter_t filter = NULL; @@ -3564,14 +3472,13 @@ static int list_subsys(int argc, char **argv, struct command *cmd, if (argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; - - r = nvme_create_root(stderr, log_level); - if (!r) { + ctx = nvme_create_global_ctx(stdout, log_level); + if (!ctx) { if (devname) nvme_show_error("Failed to scan nvme subsystem for %s", devname); else nvme_show_error("Failed to scan nvme subsystem"); - return -errno; + return -ENOMEM; } if (devname) { @@ -3584,22 +3491,22 @@ static int list_subsys(int argc, char **argv, struct command *cmd, filter = nvme_match_device_filter; } - err = nvme_scan_topology(r, filter, (void *)devname); + err = nvme_scan_topology(ctx, filter, (void *)devname); if (err) { - nvme_show_error("Failed to scan topology: %s", nvme_strerror(errno)); + nvme_show_error("Failed to scan topology: %s", nvme_strerror(err)); return -errno; } - nvme_show_subsystem_list(r, nsid != NVME_NSID_ALL, flags); + nvme_show_subsystem_list(ctx, nsid != NVME_NSID_ALL, flags); return 0; } -static int list(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int list(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve basic information for all NVMe namespaces"; nvme_print_flags_t flags; - _cleanup_nvme_root_ nvme_root_t r = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; int err = 0; NVME_ARGS(opts); @@ -3617,23 +3524,23 @@ static int list(int argc, char **argv, struct command *cmd, struct plugin *plugi if (argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; - r = nvme_create_root(stderr, log_level); - if (!r) { - nvme_show_error("Failed to create topology root: %s", nvme_strerror(errno)); - return -errno; + ctx = nvme_create_global_ctx(stdout, log_level); + if (!ctx) { + nvme_show_error("Failed to create global context"); + return -ENOMEM; } - err = nvme_scan_topology(r, NULL, NULL); + err = nvme_scan_topology(ctx, NULL, NULL); if (err < 0) { - nvme_show_error("Failed to scan topology: %s", nvme_strerror(errno)); + nvme_show_error("Failed to scan topology: %s", nvme_strerror(err)); return err; } - nvme_show_list_items(r, flags); + nvme_show_list_items(ctx, flags); return err; } -int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, +int __id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin, void (*vs)(__u8 *vs, struct json_object *root)) { const char *desc = "Send an Identify Controller command to " @@ -3644,7 +3551,8 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, const char *vendor_specific = "dump binary vendor field"; _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err; @@ -3665,7 +3573,7 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_identify), OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable_identify)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -3688,23 +3596,23 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin, if (!ctrl) return -ENOMEM; - err = nvme_cli_identify_ctrl(dev, ctrl); + err = nvme_identify_ctrl(hdl, ctrl); if (!err) nvme_show_id_ctrl(ctrl, flags, vs); else if (err > 0) nvme_show_status(err); else - nvme_show_error("identify controller: %s", nvme_strerror(errno)); + nvme_show_error("identify controller: %s", nvme_strerror(err)); return err; } -static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return __id_ctrl(argc, argv, cmd, plugin, NULL); + return __id_ctrl(argc, argv, acmd, plugin, NULL); } -static int nvm_id_ctrl(int argc, char **argv, struct command *cmd, +static int nvm_id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send an Identify Controller NVM Command Set " @@ -3712,13 +3620,15 @@ static int nvm_id_ctrl(int argc, char **argv, struct command *cmd, "the specified controller in various formats."; _cleanup_free_ struct nvme_id_ctrl_nvm *ctrl_nvm = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; int err = -1; NVME_ARGS(opts); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -3735,18 +3645,19 @@ static int nvm_id_ctrl(int argc, char **argv, struct command *cmd, if (!ctrl_nvm) return -ENOMEM; - err = nvme_nvm_identify_ctrl(dev_fd(dev), ctrl_nvm); + nvme_init_identify_csi_ctrl(&cmd, NVME_CSI_NVM, ctrl_nvm); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) nvme_show_id_ctrl_nvm(ctrl_nvm, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("nvm identify controller: %s", nvme_strerror(errno)); + nvme_show_error("nvm identify controller: %s", nvme_strerror(err)); return err; } -static int nvm_id_ns(int argc, char **argv, struct command *cmd, +static int nvm_id_ns(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send an Identify Namespace NVM Command Set " @@ -3755,7 +3666,8 @@ static int nvm_id_ns(int argc, char **argv, struct command *cmd, _cleanup_free_ struct nvme_nvm_id_ns *id_ns = NULL; _cleanup_free_ struct nvme_id_ns *ns = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err = -1; @@ -3773,7 +3685,7 @@ static int nvm_id_ns(int argc, char **argv, struct command *cmd, OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), OPT_BYTE("uuid-index", 'U', &cfg.uuid_index, uuid_index)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -3787,7 +3699,7 @@ static int nvm_id_ns(int argc, char **argv, struct command *cmd, flags |= VERBOSE; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { nvme_show_perror("get-namespace-id"); return err; @@ -3798,7 +3710,7 @@ static int nvm_id_ns(int argc, char **argv, struct command *cmd, if (!ns) return -ENOMEM; - err = nvme_cli_identify_ns(dev, cfg.namespace_id, ns); + err = nvme_identify_ns(hdl, cfg.namespace_id, ns); if (err) { nvme_show_status(err); return err; @@ -3808,9 +3720,8 @@ static int nvm_id_ns(int argc, char **argv, struct command *cmd, if (!id_ns) return -ENOMEM; - err = nvme_identify_ns_csi(dev_fd(dev), cfg.namespace_id, - cfg.uuid_index, - NVME_CSI_NVM, id_ns); + err = nvme_identify_csi_ns(hdl, cfg.namespace_id, NVME_CSI_NVM, + cfg.uuid_index, id_ns); if (!err) nvme_show_nvm_id_ns(id_ns, cfg.namespace_id, ns, 0, false, flags); else if (err > 0) @@ -3821,7 +3732,7 @@ static int nvm_id_ns(int argc, char **argv, struct command *cmd, return err; } -static int nvm_id_ns_lba_format(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int nvm_id_ns_lba_format(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send an NVM Command Set specific Identify Namespace " "command to the given device, returns capability field properties of " @@ -3829,7 +3740,8 @@ static int nvm_id_ns_lba_format(int argc, char **argv, struct command *cmd, stru _cleanup_free_ struct nvme_nvm_id_ns *nvm_ns = NULL; _cleanup_free_ struct nvme_id_ns *ns = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err = -1; @@ -3847,7 +3759,7 @@ static int nvm_id_ns_lba_format(int argc, char **argv, struct command *cmd, stru OPT_UINT("lba-format-index", 'i', &cfg.lba_format_index, lba_format_index), OPT_BYTE("uuid-index", 'U', &cfg.uuid_index, uuid_index)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -3864,7 +3776,7 @@ static int nvm_id_ns_lba_format(int argc, char **argv, struct command *cmd, stru if (!ns) return -ENOMEM; - err = nvme_cli_identify_ns(dev, NVME_NSID_ALL, ns); + err = nvme_identify_ns(hdl, NVME_NSID_ALL, ns); if (err) { ns->nlbaf = NVME_FEAT_LBA_RANGE_MAX - 1; ns->nulbaf = 0; @@ -3874,8 +3786,9 @@ static int nvm_id_ns_lba_format(int argc, char **argv, struct command *cmd, stru if (!nvm_ns) return -ENOMEM; - err = nvme_identify_iocs_ns_csi_user_data_format(dev_fd(dev), cfg.lba_format_index, - cfg.uuid_index, NVME_CSI_NVM, nvm_ns); + err = nvme_identify_csi_ns_user_data_format(hdl, NVME_CSI_NVM, + cfg.lba_format_index, + cfg.uuid_index, nvm_ns); if (!err) nvme_show_nvm_id_ns(nvm_ns, 0, ns, cfg.lba_format_index, true, flags); else if (err > 0) @@ -3886,14 +3799,15 @@ static int nvm_id_ns_lba_format(int argc, char **argv, struct command *cmd, stru return err; } -static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int ns_descs(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send Namespace Identification Descriptors command to the " "given device, returns the namespace identification descriptors " "of the specific namespace in either human-readable or binary format."; const char *raw = "show descriptors in binary format"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ void *nsdescs = NULL; nvme_print_flags_t flags; int err; @@ -3912,7 +3826,7 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -3929,9 +3843,9 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p flags |= VERBOSE; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return err; } } @@ -3940,18 +3854,18 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p if (!nsdescs) return -ENOMEM; - err = nvme_cli_identify_ns_descs(dev, cfg.namespace_id, nsdescs); + err = nvme_identify_ns_descs_list(hdl, cfg.namespace_id, nsdescs); if (!err) nvme_show_id_ns_descs(nsdescs, cfg.namespace_id, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("identify namespace: %s", nvme_strerror(errno)); + nvme_show_error("identify namespace: %s", nvme_strerror(err)); return err; } -static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int id_ns(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send an Identify Namespace command to the " "given device, returns properties of the specified namespace " @@ -3960,8 +3874,10 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug const char *force = "Return this namespace, even if not attached (1.2 devices only)"; const char *vendor_specific = "dump binary vendor fields"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ struct nvme_id_ns *ns = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; int err; @@ -3988,7 +3904,7 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_identify), OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable_identify)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -4008,9 +3924,9 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug flags |= VERBOSE; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return err; } } @@ -4019,22 +3935,24 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug if (!ns) return -ENOMEM; - if (cfg.force) - err = nvme_cli_identify_allocated_ns(dev, cfg.namespace_id, ns); - else - err = nvme_cli_identify_ns(dev, cfg.namespace_id, ns); + if (cfg.force) { + nvme_init_identify_allocated_ns(&cmd, cfg.namespace_id, ns); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); + } else { + err = nvme_identify_ns(hdl, cfg.namespace_id, ns); + } if (!err) nvme_show_id_ns(ns, cfg.namespace_id, 0, false, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("identify namespace: %s", nvme_strerror(errno)); + nvme_show_error("identify namespace: %s", nvme_strerror(err)); return err; } -static int cmd_set_independent_id_ns(int argc, char **argv, struct command *cmd, +static int cmd_set_independent_id_ns(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send an I/O Command Set Independent Identify " @@ -4042,7 +3960,9 @@ static int cmd_set_independent_id_ns(int argc, char **argv, struct command *cmd, "specified namespace in human-readable or binary or json format."; _cleanup_free_ struct nvme_id_independent_id_ns *ns = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; int err = -1; @@ -4063,7 +3983,7 @@ static int cmd_set_independent_id_ns(int argc, char **argv, struct command *cmd, OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_identify), OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable_identify)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -4080,7 +4000,7 @@ static int cmd_set_independent_id_ns(int argc, char **argv, struct command *cmd, flags |= VERBOSE; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { nvme_show_perror("get-namespace-id"); return err; @@ -4091,32 +4011,35 @@ static int cmd_set_independent_id_ns(int argc, char **argv, struct command *cmd, if (!ns) return -ENOMEM; - err = nvme_identify_independent_identify_ns(dev_fd(dev), cfg.namespace_id, ns); + nvme_init_identify_csi_independent_identify_id_ns(&cmd, + cfg.namespace_id, ns); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) nvme_show_cmd_set_independent_id_ns(ns, cfg.namespace_id, flags); else if (err > 0) nvme_show_status(err); else nvme_show_error("I/O command set independent identify namespace: %s", - nvme_strerror(errno)); + nvme_strerror(err)); return err; } -static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int id_ns_granularity(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send an Identify Namespace Granularity List command to the " "given device, returns namespace granularity list " "in either human-readable or binary format."; _cleanup_free_ struct nvme_id_ns_granularity_list *granularity_list = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err; NVME_ARGS(opts); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -4130,18 +4053,18 @@ static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct if (!granularity_list) return -ENOMEM; - err = nvme_identify_ns_granularity(dev_fd(dev), granularity_list); + err = nvme_identify_ns_granularity(hdl, granularity_list); if (!err) nvme_show_id_ns_granularity_list(granularity_list, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("identify namespace granularity: %s", nvme_strerror(errno)); + nvme_show_error("identify namespace granularity: %s", nvme_strerror(err)); return err; } -static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int id_nvmset(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send an Identify NVM Set List command to the " "given device, returns entries for NVM Set identifiers greater " @@ -4150,7 +4073,9 @@ static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin * const char *nvmset_id = "NVM Set Identify value"; _cleanup_free_ struct nvme_id_nvmset_list *nvmset = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; int err; @@ -4165,7 +4090,7 @@ static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin * NVME_ARGS(opts, OPT_SHRT("nvmset_id", 'i', &cfg.nvmset_id, nvmset_id)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -4179,18 +4104,20 @@ static int id_nvmset(int argc, char **argv, struct command *cmd, struct plugin * if (!nvmset) return -ENOMEM; - err = nvme_identify_nvmset_list(dev_fd(dev), cfg.nvmset_id, nvmset); + nvme_init_identify_nvmset_list(&cmd, NVME_NSID_NONE, + cfg.nvmset_id, nvmset); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) nvme_show_id_nvmset(nvmset, cfg.nvmset_id, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("identify nvm set list: %s", nvme_strerror(errno)); + nvme_show_error("identify nvm set list: %s", nvme_strerror(err)); return err; } -static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int id_uuid(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send an Identify UUID List command to the " "given device, returns list of supported Vendor Specific UUIDs " @@ -4199,7 +4126,8 @@ static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *pl const char *human_readable = "show uuid in readable format"; _cleanup_free_ struct nvme_id_uuid_list *uuid_list = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err; @@ -4217,7 +4145,7 @@ static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *pl OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -4237,18 +4165,18 @@ static int id_uuid(int argc, char **argv, struct command *cmd, struct plugin *pl if (!uuid_list) return -ENOMEM; - err = nvme_identify_uuid(dev_fd(dev), uuid_list); + err = nvme_identify_uuid_list(hdl, uuid_list); if (!err) nvme_show_id_uuid_list(uuid_list, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("identify UUID list: %s", nvme_strerror(errno)); + nvme_show_error("identify UUID list: %s", nvme_strerror(err)); return err; } -static int id_iocs(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int id_iocs(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send an Identify Command Set Data command to " "the given device, returns properties of the specified controller " @@ -4256,7 +4184,9 @@ static int id_iocs(int argc, char **argv, struct command *cmd, struct plugin *pl const char *controller_id = "identifier of desired controller"; _cleanup_free_ struct nvme_id_iocs *iocs = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; int err; @@ -4271,7 +4201,7 @@ static int id_iocs(int argc, char **argv, struct command *cmd, struct plugin *pl NVME_ARGS(opts, OPT_SHRT("controller-id", 'c', &cfg.cntid, controller_id)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -4288,20 +4218,21 @@ static int id_iocs(int argc, char **argv, struct command *cmd, struct plugin *pl if (!iocs) return -ENOMEM; - err = nvme_identify_iocs(dev_fd(dev), cfg.cntid, iocs); + nvme_init_identify_command_set_structure(&cmd, cfg.cntid, iocs); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) { printf("NVMe Identify I/O Command Set:\n"); nvme_show_id_iocs(iocs, flags); } else if (err > 0) { nvme_show_status(err); } else { - nvme_show_error("NVMe Identify I/O Command Set: %s", nvme_strerror(errno)); + nvme_show_error("NVMe Identify I/O Command Set: %s", nvme_strerror(err)); } return err; } -static int id_domain(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int id_domain(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send an Identify Domain List command to the " "given device, returns properties of the specified domain " @@ -4309,7 +4240,9 @@ static int id_domain(int argc, char **argv, struct command *cmd, struct plugin * const char *domain_id = "identifier of desired domain"; _cleanup_free_ struct nvme_id_domain_list *id_domain = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; int err; @@ -4324,7 +4257,7 @@ static int id_domain(int argc, char **argv, struct command *cmd, struct plugin * NVME_ARGS(opts, OPT_SHRT("dom-id", 'd', &cfg.dom_id, domain_id)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -4338,7 +4271,8 @@ static int id_domain(int argc, char **argv, struct command *cmd, struct plugin * if (!id_domain) return -ENOMEM; - err = nvme_identify_domain_list(dev_fd(dev), cfg.dom_id, id_domain); + nvme_init_identify_domain_list(&cmd, cfg.dom_id, id_domain); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) { printf("NVMe Identify command for Domain List is successful:\n"); printf("NVMe Identify Domain List:\n"); @@ -4346,24 +4280,25 @@ static int id_domain(int argc, char **argv, struct command *cmd, struct plugin * } else if (err > 0) { nvme_show_status(err); } else { - nvme_show_error("NVMe Identify Domain List: %s", nvme_strerror(errno)); + nvme_show_error("NVMe Identify Domain List: %s", nvme_strerror(err)); } return err; } -static int get_ns_id(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_ns_id(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get namespace ID of a the block device."; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; unsigned int nsid; int err; nvme_print_flags_t flags; NVME_ARGS(opts); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -4373,18 +4308,18 @@ static int get_ns_id(int argc, char **argv, struct command *cmd, struct plugin * return err; } - err = nvme_get_nsid(dev_fd(dev), &nsid); + err = nvme_get_nsid(hdl, &nsid); if (err < 0) { - nvme_show_error("get namespace ID: %s", nvme_strerror(errno)); + nvme_show_error("get namespace ID: %s", nvme_strerror(err)); return -errno; } - printf("%s: namespace-id:%d\n", dev->name, nsid); + printf("%s: namespace-id:%d\n", nvme_transport_handle_get_name(hdl), nsid); return 0; } -static int virtual_mgmt(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int virtual_mgmt(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "The Virtualization Management command is supported by primary controllers " "that support the Virtualization Enhancements capability. This command is used for:\n" @@ -4402,7 +4337,9 @@ static int virtual_mgmt(int argc, char **argv, struct command *cmd, struct plugi "9h: Secondary Online"; const char *nr = "Number of Controller Resources(NR)"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_passthru_cmd cmd; __u32 result; int err; @@ -4426,32 +4363,23 @@ static int virtual_mgmt(int argc, char **argv, struct command *cmd, struct plugi OPT_BYTE("act", 'a', &cfg.act, act), OPT_SHRT("nr", 'n', &cfg.nr, nr)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - struct nvme_virtual_mgmt_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .act = cfg.act, - .rt = cfg.rt, - .cntlid = cfg.cntlid, - .nr = cfg.nr, - .timeout = nvme_cfg.timeout, - .result = &result, - }; - err = nvme_virtual_mgmt(&args); + nvme_init_virtual_mgmt(&cmd, cfg.act, cfg.rt, cfg.cntlid, cfg.nr); + err = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!err) printf("success, Number of Controller Resources Modified (NRM):%#x\n", result); else if (err > 0) nvme_show_status(err); else - nvme_show_error("virt-mgmt: %s", nvme_strerror(errno)); + nvme_show_error("virt-mgmt: %s", nvme_strerror(err)); return err; } -static int primary_ctrl_caps(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int primary_ctrl_caps(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *cntlid = "Controller ID"; const char *desc = "Send an Identify Primary Controller Capabilities " @@ -4459,7 +4387,9 @@ static int primary_ctrl_caps(int argc, char **argv, struct command *cmd, struct "decoded format (default), json or binary."; _cleanup_free_ struct nvme_primary_ctrl_cap *caps = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; int err; @@ -4477,7 +4407,7 @@ static int primary_ctrl_caps(int argc, char **argv, struct command *cmd, struct OPT_UINT("cntlid", 'c', &cfg.cntlid, cntlid), OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable_info)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -4494,19 +4424,20 @@ static int primary_ctrl_caps(int argc, char **argv, struct command *cmd, struct if (!caps) return -ENOMEM; - err = nvme_cli_identify_primary_ctrl(dev, cfg.cntlid, caps); + nvme_init_identify_primary_ctrl_cap(&cmd, cfg.cntlid, caps); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) nvme_show_primary_ctrl_cap(caps, flags); else if (err > 0) nvme_show_status(err); else nvme_show_error("identify primary controller capabilities: %s", - nvme_strerror(errno)); + nvme_strerror(err)); return err; } -static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int list_secondary_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Show secondary controller list associated with the primary controller of the given device."; @@ -4514,7 +4445,9 @@ static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struc const char *num_entries = "number of entries to retrieve"; _cleanup_free_ struct nvme_secondary_ctrl_list *sc_list = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; int err; @@ -4532,7 +4465,7 @@ static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struc OPT_SHRT("cntid", 'c', &cfg.cntid, controller), OPT_UINT("num-entries", 'e', &cfg.num_entries, num_entries)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -4551,13 +4484,14 @@ static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struc if (!sc_list) return -ENOMEM; - err = nvme_cli_identify_secondary_ctrl_list(dev, cfg.cntid, sc_list); + nvme_init_identify_secondary_ctrl_list(&cmd, cfg.cntid, sc_list); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) nvme_show_list_secondary_ctrl(sc_list, cfg.num_entries, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("id secondary controller list: %s", nvme_strerror(errno)); + nvme_show_error("id secondary controller list: %s", nvme_strerror(err)); return err; } @@ -4576,7 +4510,7 @@ static int sleep_self_test(unsigned int seconds) return 0; } -static int wait_self_test(struct nvme_dev *dev) +static int wait_self_test(struct nvme_transport_handle *hdl) { static const char spin[] = {'-', '\\', '|', '/' }; _cleanup_free_ struct nvme_self_test_log *log = NULL; @@ -4592,9 +4526,9 @@ static int wait_self_test(struct nvme_dev *dev) if (!log) return -ENOMEM; - err = nvme_cli_identify_ctrl(dev, ctrl); + err = nvme_identify_ctrl(hdl, ctrl); if (err) { - nvme_show_error("identify-ctrl: %s", nvme_strerror(errno)); + nvme_show_error("identify-ctrl: %s", nvme_strerror(err)); return err; } @@ -4608,7 +4542,7 @@ static int wait_self_test(struct nvme_dev *dev) if (err) return err; - err = nvme_cli_get_log_device_self_test(dev, log); + err = nvme_get_log_device_self_test(hdl, log); if (err) { printf("\n"); if (err < 0) @@ -4643,22 +4577,22 @@ static int wait_self_test(struct nvme_dev *dev) return 0; } -static void abort_self_test(struct nvme_dev_self_test_args *args) +static void abort_self_test(struct nvme_transport_handle *hdl, __u32 nsid) { + struct nvme_passthru_cmd cmd; int err; - args->stc = NVME_DST_STC_ABORT; - - err = nvme_dev_self_test(args); + nvme_init_dev_self_test(&cmd, nsid, NVME_DST_STC_ABORT); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) printf("Aborting device self-test operation\n"); else if (err > 0) nvme_show_status(err); else - nvme_show_error("Device self-test: %s", nvme_strerror(errno)); + nvme_show_error("Device self-test: %s", nvme_strerror(err)); } -static int device_self_test(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int device_self_test(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Implementing the device self-test feature " "which provides the necessary log to determine the state of the device"; @@ -4674,9 +4608,11 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p "fh Abort the device self-test operation"; const char *wait = "Wait for the test to finish"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - int err; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; + int err; struct config { __u32 namespace_id; @@ -4695,7 +4631,7 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p OPT_BYTE("self-test-code", 's', &cfg.stc, self_test_code), OPT_FLAG("wait", 'w', &cfg.wait, wait)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -4712,7 +4648,7 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p if (!log) return -ENOMEM; - err = nvme_cli_get_log_device_self_test(dev, log); + err = nvme_get_log_device_self_test(hdl, log); if (err) { printf("\n"); if (err < 0) @@ -4725,7 +4661,7 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p printf("no self test running\n"); } else { if (cfg.wait) - err = wait_self_test(dev); + err = wait_self_test(hdl); else printf("progress %d%%\n", log->completion); } @@ -4733,15 +4669,8 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p goto check_abort; } - struct nvme_dev_self_test_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .stc = cfg.stc, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; - err = nvme_dev_self_test(&args); + nvme_init_dev_self_test(&cmd, cfg.namespace_id, cfg.stc); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) { if (cfg.stc == NVME_ST_CODE_ABORT) printf("Aborting device self-test operation\n"); @@ -4753,21 +4682,21 @@ static int device_self_test(int argc, char **argv, struct command *cmd, struct p printf("Host-Initiated Refresh started\n"); if (cfg.wait && cfg.stc != NVME_ST_CODE_ABORT) - err = wait_self_test(dev); + err = wait_self_test(hdl); } else if (err > 0) { nvme_show_status(err); } else { - nvme_show_error("Device self-test: %s", nvme_strerror(errno)); + nvme_show_error("Device self-test: %s", nvme_strerror(err)); } check_abort: if (err == -EINTR) - abort_self_test(&args); + abort_self_test(hdl, cfg.namespace_id); return err; } -static int self_test_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int self_test_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve the self-test log for the given device and given test " "(or optionally a namespace) in either decoded format (default) or binary."; @@ -4775,7 +4704,8 @@ static int self_test_log(int argc, char **argv, struct command *cmd, struct plug "by default all the 20 entries will be retrieved"; _cleanup_free_ struct nvme_self_test_log *log = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err; @@ -4790,7 +4720,7 @@ static int self_test_log(int argc, char **argv, struct command *cmd, struct plug NVME_ARGS(opts, OPT_BYTE("dst-entries", 'e', &cfg.dst_entries, dst_entries)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -4807,22 +4737,23 @@ static int self_test_log(int argc, char **argv, struct command *cmd, struct plug if (!log) return -ENOMEM; - err = nvme_cli_get_log_device_self_test(dev, log); + err = nvme_get_log_device_self_test(hdl, log); if (!err) - nvme_show_self_test_log(log, cfg.dst_entries, 0, dev->name, flags); + nvme_show_self_test_log(log, cfg.dst_entries, 0, nvme_transport_handle_get_name(hdl), flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("self test log: %s", nvme_strerror(errno)); + nvme_show_error("self test log: %s", nvme_strerror(err)); return err; } -static int get_feature_id(struct nvme_dev *dev, struct feat_cfg *cfg, +static int get_feature_id(struct nvme_transport_handle *hdl, struct feat_cfg *cfg, void **buf, __u32 *result) { if (!cfg->data_len) nvme_get_feature_length(cfg->feature_id, cfg->cdw11, + NVME_DATA_TFR_CTRL_TO_HOST, &cfg->data_len); if (cfg->feature_id == NVME_FEAT_FID_FDP_EVENTS) { @@ -4839,19 +4770,8 @@ static int get_feature_id(struct nvme_dev *dev, struct feat_cfg *cfg, return -1; } - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fid = cfg->feature_id, - .nsid = cfg->namespace_id, - .sel = cfg->sel, - .cdw11 = cfg->cdw11, - .uuidx = cfg->uuid_index, - .data_len = cfg->data_len, - .data = *buf, - .timeout = nvme_cfg.timeout, - .result = result, - }; - return nvme_cli_get_features(dev, &args); + return nvme_get_features(hdl, cfg->namespace_id, cfg->feature_id, cfg->sel, + cfg->cdw11, cfg->uuid_index, *buf, cfg->data_len, result); } static int filter_out_flags(int status) @@ -4883,7 +4803,7 @@ static void get_feature_id_print(struct feat_cfg cfg, int err, __u32 result, !nvme_status_equals(status, type, NVME_SC_INVALID_NS)) nvme_show_status(err); } else { - nvme_show_error("get-feature: %s", nvme_strerror(errno)); + nvme_show_error("get-feature: %s", nvme_strerror(err)); } } @@ -4899,7 +4819,7 @@ static bool is_get_feature_result_set(enum nvme_features_id feature_id) return true; } -static int get_feature_id_changed(struct nvme_dev *dev, struct feat_cfg cfg, +static int get_feature_id_changed(struct nvme_transport_handle *hdl, struct feat_cfg cfg, nvme_print_flags_t flags) { int err; @@ -4912,11 +4832,11 @@ static int get_feature_id_changed(struct nvme_dev *dev, struct feat_cfg cfg, if (cfg.changed) cfg.sel = NVME_GET_FEATURES_SEL_CURRENT; - err = get_feature_id(dev, &cfg, &buf, &result); + err = get_feature_id(hdl, &cfg, &buf, &result); if (!err && cfg.changed) { cfg.sel = NVME_GET_FEATURES_SEL_DEFAULT; - err_def = get_feature_id(dev, &cfg, &buf_def, &result_def); + err_def = get_feature_id(hdl, &cfg, &buf_def, &result_def); } if (!err && !is_get_feature_result_set(cfg.feature_id)) @@ -4929,7 +4849,7 @@ static int get_feature_id_changed(struct nvme_dev *dev, struct feat_cfg cfg, return err; } -static int get_feature_ids(struct nvme_dev *dev, struct feat_cfg cfg, +static int get_feature_ids(struct nvme_transport_handle *hdl, struct feat_cfg cfg, nvme_print_flags_t flags) { int err = 0; @@ -4944,7 +4864,7 @@ static int get_feature_ids(struct nvme_dev *dev, struct feat_cfg cfg, for (i = cfg.feature_id; i < feat_max; i++, feat_num++) { cfg.feature_id = i; - err = get_feature_id_changed(dev, cfg, flags); + err = get_feature_id_changed(hdl, cfg, flags); if (!err) continue; status = filter_out_flags(err); @@ -4962,7 +4882,7 @@ static int get_feature_ids(struct nvme_dev *dev, struct feat_cfg cfg, return err; } -static int get_feature(int argc, char **argv, struct command *cmd, +static int get_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Read operating parameters of the " @@ -4982,7 +4902,8 @@ static int get_feature(int argc, char **argv, struct command *cmd, const char *changed = "show feature changed"; nvme_print_flags_t flags = NORMAL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; struct feat_cfg cfg = { @@ -5007,7 +4928,7 @@ static int get_feature(int argc, char **argv, struct command *cmd, OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable), OPT_FLAG("changed", 'C', &cfg.changed, changed)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -5018,10 +4939,10 @@ static int get_feature(int argc, char **argv, struct command *cmd, } if (!argconfig_parse_seen(opts, "namespace-id")) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { if (errno != ENOTTY) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return err; } cfg.namespace_id = NVME_NSID_ALL; @@ -5043,7 +4964,7 @@ static int get_feature(int argc, char **argv, struct command *cmd, nvme_show_init(); - err = get_feature_ids(dev, cfg, flags); + err = get_feature_ids(hdl, cfg, flags); nvme_show_finish(); @@ -5055,11 +4976,12 @@ static int get_feature(int argc, char **argv, struct command *cmd, * errors. Returns -1 on (fatal) error; signifying that the transfer should * be aborted. */ -static int fw_download_single(struct nvme_dev *dev, void *fw_buf, +static int fw_download_single(struct nvme_transport_handle *hdl, void *fw_buf, unsigned int fw_len, uint32_t offset, uint32_t len, bool progress, bool ignore_ovr) { const unsigned int max_retries = 3; + struct nvme_passthru_cmd cmd; bool retryable, ovr; int err, try; @@ -5068,22 +4990,17 @@ static int fw_download_single(struct nvme_dev *dev, void *fw_buf, offset, fw_len, (int)(100 * offset / fw_len)); } - struct nvme_fw_download_args args = { - .args_size = sizeof(args), - .offset = offset, - .data_len = len, - .data = fw_buf, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; - for (try = 0; try < max_retries; try++) { if (try > 0) { fprintf(stderr, "retrying offset %x (%u/%u)\n", offset, try, max_retries); } - err = nvme_cli_fw_download(dev, &args); + err = nvme_init_fw_download(&cmd, fw_buf, len, offset); + if (err) + return err; + + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) return 0; @@ -5120,7 +5037,7 @@ static int fw_download_single(struct nvme_dev *dev, void *fw_buf, offset, fw_len); if (err < 0) { - fprintf(stderr, "fw-download: %s\n", nvme_strerror(errno)); + fprintf(stderr, "fw-download: %s\n", nvme_strerror(err)); } else { nvme_show_status(err); if (ovr) { @@ -5147,7 +5064,7 @@ static int fw_download_single(struct nvme_dev *dev, void *fw_buf, return -1; } -static int fw_download(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int fw_download(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Copy all or part of a firmware image to " "a controller for future update. Optionally, specify how " @@ -5163,7 +5080,8 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin const char *progress = "display firmware transfer progress"; const char *ignore_ovr = "ignore overwrite errors"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; _cleanup_fd_ int fw_fd = -1; unsigned int fw_size, pos; @@ -5196,7 +5114,7 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin OPT_FLAG("progress", 'p', &cfg.progress, progress), OPT_FLAG("ignore-ovr", 'i', &cfg.ignore_ovr, ignore_ovr)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -5226,9 +5144,9 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin } if (cfg.xfer == 0) { - err = nvme_cli_identify_ctrl(dev, &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err) { - nvme_show_error("identify-ctrl: %s", nvme_strerror(errno)); + nvme_show_error("identify-ctrl: %s", nvme_strerror(err)); return err; } if (ctrl.fwug == 0 || ctrl.fwug == 0xff) @@ -5257,7 +5175,7 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin for (pos = 0; pos < fw_size; pos += cfg.xfer) { cfg.xfer = min(cfg.xfer, fw_size - pos); - err = fw_download_single(dev, fw_buf + pos, fw_size, + err = fw_download_single(hdl, fw_buf + pos, fw_size, cfg.offset + pos, cfg.xfer, cfg.progress, cfg.ignore_ovr); if (err) @@ -5288,7 +5206,7 @@ static char *nvme_fw_status_reset_type(__u16 status) } } -static bool fw_commit_support_mud(struct nvme_dev *dev) +static bool fw_commit_support_mud(struct nvme_transport_handle *hdl) { _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; int err; @@ -5297,19 +5215,19 @@ static bool fw_commit_support_mud(struct nvme_dev *dev) if (!ctrl) return false; - err = nvme_cli_identify_ctrl(dev, ctrl); + err = nvme_identify_ctrl(hdl, ctrl); if (err) - nvme_show_error("identify-ctrl: %s", nvme_strerror(errno)); + nvme_show_error("identify-ctrl: %s", nvme_strerror(err)); else if (ctrl->frmw >> 5 & 0x1) return true; return false; } -static void fw_commit_print_mud(struct nvme_dev *dev, __u32 result) +static void fw_commit_print_mud(struct nvme_transport_handle *hdl, __u32 result) { - if (!fw_commit_support_mud(dev)) + if (!fw_commit_support_mud(hdl)) return; printf("Multiple Update Detected (MUD) Value: %u\n", result); @@ -5323,7 +5241,7 @@ static void fw_commit_print_mud(struct nvme_dev *dev, __u32 result) "sequence due to processing a command from a Management Endpoint\n"); } -static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int fw_commit(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Verify downloaded firmware image and " "commit to specific firmware slot. Device is not automatically " @@ -5334,7 +5252,9 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin * const char *action = "[0-7]: commit action"; const char *bpid = "[0,1]: boot partition identifier, if applicable (default: 0)"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; __u32 result; int err; nvme_print_flags_t flags; @@ -5356,7 +5276,7 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin * OPT_BYTE("action", 'a', &cfg.action, action), OPT_BYTE("bpid", 'b', &cfg.bpid, bpid)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -5379,19 +5299,11 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin * return -EINVAL; } - struct nvme_fw_commit_args args = { - .args_size = sizeof(args), - .slot = cfg.slot, - .action = cfg.action, - .bpid = cfg.bpid, - .timeout = nvme_cfg.timeout, - .result = &result, - }; - err = nvme_cli_fw_commit(dev, &args); - + nvme_init_fw_commit(&cmd, cfg.slot, cfg.action, cfg.bpid); + err = nvme_submit_admin_passthru(hdl, &cmd, &result); if (err < 0) { - nvme_show_error("fw-commit: %s", nvme_strerror(errno)); - } else if (err != 0) { + nvme_show_error("fw-commit: %s", nvme_strerror(err)); + } else if (err > 0) { __u32 val = nvme_status_get_value(err); int type = nvme_status_get_type(err); @@ -5420,70 +5332,73 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin * if (cfg.action == 6 || cfg.action == 7) printf(" bpid:%d", cfg.bpid); printf("\n"); - fw_commit_print_mud(dev, result); + fw_commit_print_mud(hdl, result); } return err; } -static int subsystem_reset(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int subsystem_reset(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Resets the NVMe subsystem"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; NVME_ARGS(opts); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = nvme_subsystem_reset(dev_fd(dev)); + err = nvme_subsystem_reset(hdl); if (err < 0) { if (errno == ENOTTY) nvme_show_error("Subsystem-reset: NVM Subsystem Reset not supported."); else - nvme_show_error("Subsystem-reset: %s", nvme_strerror(errno)); + nvme_show_error("Subsystem-reset: %s", nvme_strerror(err)); } else if (argconfig_parse_seen(opts, "verbose")) - printf("resetting subsystem through %s\n", dev->name); + printf("resetting subsystem through %s\n", nvme_transport_handle_get_name(hdl)); return err; } -static int reset(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int reset(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Resets the NVMe controller\n"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; NVME_ARGS(opts); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = nvme_ctrl_reset(dev_fd(dev)); + err = nvme_ctrl_reset(hdl); if (err < 0) - nvme_show_error("Reset: %s", nvme_strerror(errno)); + nvme_show_error("Reset: %s", nvme_strerror(err)); else if (argconfig_parse_seen(opts, "verbose")) - printf("resetting controller %s\n", dev->name); + printf("resetting controller %s\n", nvme_transport_handle_get_name(hdl)); return err; } -static int ns_rescan(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int ns_rescan(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Rescans the NVMe namespaces\n"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; nvme_print_flags_t flags; NVME_ARGS(opts); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -5493,16 +5408,16 @@ static int ns_rescan(int argc, char **argv, struct command *cmd, struct plugin * return err; } - err = nvme_ns_rescan(dev_fd(dev)); + err = nvme_ns_rescan(hdl); if (err < 0) - nvme_show_error("Namespace Rescan: %s\n", nvme_strerror(errno)); + nvme_show_error("Namespace Rescan: %s\n", nvme_strerror(err)); else if (argconfig_parse_seen(opts, "verbose")) - printf("rescanning namespaces through %s\n", dev->name); + printf("rescanning namespaces through %s\n", nvme_transport_handle_get_name(hdl)); return err; } -static int sanitize_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int sanitize_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send a sanitize command."; const char *emvs_desc = "Enter media verification state."; @@ -5514,9 +5429,11 @@ static int sanitize_cmd(int argc, char **argv, struct command *cmd, struct plugi "3 = Start overwrite, 4 = Start crypto erase, 5 = Exit media verification"; const char *ovrpat_desc = "Overwrite pattern."; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - int err; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; + int err; struct config { bool no_dealloc; @@ -5556,7 +5473,7 @@ static int sanitize_cmd(int argc, char **argv, struct command *cmd, struct plugi OPT_UINT("ovrpat", 'p', &cfg.ovrpat, ovrpat_desc), OPT_FLAG("emvs", 'e', &cfg.emvs, emvs_desc)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -5600,39 +5517,24 @@ static int sanitize_cmd(int argc, char **argv, struct command *cmd, struct plugi } } - struct nvme_sanitize_nvm_args args = { - .args_size = sizeof(args), - .sanact = cfg.sanact, - .ause = cfg.ause, - .owpass = cfg.owpass, - .oipbp = cfg.oipbp, - .nodas = cfg.no_dealloc, - .ovrpat = cfg.ovrpat, - .result = NULL, - .emvs = cfg.emvs, - }; - - err = nvme_cli_sanitize_nvm(dev, &args); + nvme_init_sanitize_nvm(&cmd, cfg.sanact, cfg.ause, cfg.owpass, + cfg.oipbp, cfg.no_dealloc, cfg.emvs, cfg.ovrpat); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) - nvme_show_error("sanitize: %s", nvme_strerror(errno)); + nvme_show_error("sanitize: %s", nvme_strerror(err)); else if (err > 0) nvme_show_status(err); return err; } -static int nvme_get_single_property(int fd, struct get_reg_config *cfg, __u64 *value) +static int nvme_get_single_property(struct nvme_transport_handle *hdl, struct get_reg_config *cfg, __u64 *value) { + struct nvme_passthru_cmd64 cmd; int err; - struct nvme_get_property_args args = { - .args_size = sizeof(args), - .fd = fd, - .offset = cfg->offset, - .value = value, - .timeout = nvme_cfg.timeout, - }; - err = nvme_get_property(&args); + nvme_init_get_property(&cmd, cfg->offset); + err = nvme_submit_admin_passthru64(hdl, &cmd, value); if (!err) return 0; @@ -5650,12 +5552,12 @@ static int nvme_get_single_property(int fd, struct get_reg_config *cfg, __u64 *v if (cfg->fabrics && err > 0) nvme_show_status(err); else - nvme_show_error("get-property: %s", nvme_strerror(errno)); + nvme_show_error("get-property: %s", nvme_strerror(err)); return err; } -static int nvme_get_properties(int fd, void **pbar, struct get_reg_config *cfg) +static int nvme_get_properties(struct nvme_transport_handle *hdl, void **pbar, struct get_reg_config *cfg) { int err, size = getpagesize(); bool is_64bit = false; @@ -5664,10 +5566,8 @@ static int nvme_get_properties(int fd, void **pbar, struct get_reg_config *cfg) int offset; bar = malloc(size); - if (!bar) { - nvme_show_error("malloc: %s", strerror(errno)); - return -errno; - } + if (!bar) + return -ENOMEM; memset(bar, 0xff, size); for (offset = NVME_REG_CAP; offset <= NVME_REG_CMBSZ; @@ -5676,7 +5576,7 @@ static int nvme_get_properties(int fd, void **pbar, struct get_reg_config *cfg) continue; cfg->offset = offset; - err = nvme_get_single_property(fd, cfg, &value); + err = nvme_get_single_property(hdl, cfg, &value); if (err) break; @@ -5695,7 +5595,7 @@ static int nvme_get_properties(int fd, void **pbar, struct get_reg_config *cfg) return err; } -static void *mmap_registers(struct nvme_dev *dev, bool writable) +static void *mmap_registers(struct nvme_transport_handle *hdl, bool writable) { char path[512]; void *membase; @@ -5705,12 +5605,12 @@ static void *mmap_registers(struct nvme_dev *dev, bool writable) if (writable) prot |= PROT_WRITE; - sprintf(path, "/sys/class/nvme/%s/device/resource0", dev->name); + sprintf(path, "/sys/class/nvme/%s/device/resource0", nvme_transport_handle_get_name(hdl)); fd = open(path, writable ? O_RDWR : O_RDONLY); if (fd < 0) { if (log_level >= LOG_INFO) nvme_show_error("%s did not find a pci resource, open failed %s", - dev->name, strerror(errno)); + nvme_transport_handle_get_name(hdl), strerror(errno)); return NULL; } @@ -5730,14 +5630,15 @@ static void *mmap_registers(struct nvme_dev *dev, bool writable) return membase; } -static int show_registers(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int show_registers(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Reads and shows the defined NVMe controller registers\n" "in binary or human-readable format"; const char *human_readable = "show info in readable format in case of output_format == normal"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; void *bar; int err; @@ -5750,11 +5651,11 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu NVME_ARGS(opts, OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - if (is_blkdev(dev)) { + if (nvme_transport_handle_is_blkdev(hdl)) { nvme_show_error("Only character device is allowed"); return -EINVAL; } @@ -5768,10 +5669,10 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; - bar = mmap_registers(dev, false); + bar = mmap_registers(hdl, false); if (!bar) { cfg.fabrics = true; - err = nvme_get_properties(dev_fd(dev), &bar, &cfg); + err = nvme_get_properties(hdl, &bar, &cfg); if (err) return err; } @@ -5856,38 +5757,31 @@ static bool is_reg_selected(struct get_reg_config *cfg, int offset) return false; } -static int get_register_properties(int fd, void **pbar, struct get_reg_config *cfg) +static int get_register_properties(struct nvme_transport_handle *hdl, void **pbar, struct get_reg_config *cfg) { + struct nvme_passthru_cmd64 cmd; int offset = NVME_REG_CRTO; __u64 value; int size; int err; void *bar; - struct nvme_get_property_args args = { - .args_size = sizeof(args), - .fd = fd, - .value = &value, - .timeout = nvme_cfg.timeout, - }; size = offset + get_reg_size(offset); bar = malloc(size); - if (!bar) { - nvme_show_error("malloc: %s", strerror(errno)); - return -1; - } + if (!bar) + return -ENOMEM; for (offset = NVME_REG_CAP; offset <= NVME_REG_CRTO; offset += get_reg_size(offset)) { if ((cfg->offset != offset && !is_reg_selected(cfg, offset)) || !nvme_is_fabrics_reg(offset)) continue; - args.offset = offset; - err = nvme_get_property(&args); + nvme_init_get_property(&cmd, offset); + err = nvme_submit_admin_passthru64(hdl, &cmd, &value); if (nvme_status_equals(err, NVME_STATUS_TYPE_NVME, NVME_SC_INVALID_FIELD)) { value = -1; } else if (err) { - nvme_show_error("get-property: %s", nvme_strerror(errno)); + nvme_show_error("get-property: %s", nvme_strerror(err)); free(bar); return err; } @@ -5962,7 +5856,7 @@ static bool get_register_offset(void *bar, bool fabrics, struct get_reg_config * return offset_matched; } -static int get_register(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_register(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Reads and shows the defined NVMe controller register.\n" "Register offset must be one of:\n" @@ -5988,7 +5882,8 @@ static int get_register(int argc, char **argv, struct command *cmd, struct plugi const char *pmrmscl = "PMRMSCL=0xe14 register offset"; const char *pmrmscu = "PMRMSCU=0xe18 register offset"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; nvme_print_flags_t flags; bool fabrics = false; @@ -6031,11 +5926,11 @@ static int get_register(int argc, char **argv, struct command *cmd, struct plugi OPT_FLAG("pmrmscl", 0, &cfg.pmrmscl, pmrmscl), OPT_FLAG("pmrmscu", 0, &cfg.pmrmscu, pmrmscu)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - if (is_blkdev(dev)) { + if (nvme_transport_handle_is_blkdev(hdl)) { nvme_show_error("Only character device is allowed"); return -EINVAL; } @@ -6049,9 +5944,9 @@ static int get_register(int argc, char **argv, struct command *cmd, struct plugi if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; - bar = mmap_registers(dev, false); + bar = mmap_registers(hdl, false); if (!bar) { - err = get_register_properties(dev_fd(dev), &bar, &cfg); + err = get_register_properties(hdl, &bar, &cfg); if (err) return err; fabrics = true; @@ -6074,20 +5969,15 @@ static int get_register(int argc, char **argv, struct command *cmd, struct plugi return err; } -static int nvme_set_single_property(int fd, int offset, uint64_t value) +static int nvme_set_single_property(struct nvme_transport_handle *hdl, int offset, uint64_t value) { - struct nvme_set_property_args args = { - .args_size = sizeof(args), - .fd = fd, - .offset = offset, - .value = value, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; - int err = nvme_set_property(&args); + struct nvme_passthru_cmd cmd; + int err; + nvme_init_set_property(&cmd, offset, value); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) - nvme_show_error("set-property: %s", nvme_strerror(errno)); + nvme_show_error("set-property: %s", nvme_strerror(err)); else if (!err) printf("set-property: %#02x (%s), value: %#"PRIx64"\n", offset, nvme_register_to_string(offset), value); @@ -6097,7 +5987,7 @@ static int nvme_set_single_property(int fd, int offset, uint64_t value) return err; } -static int set_register_property(int fd, int offset, uint64_t value) +static int set_register_property(struct nvme_transport_handle *hdl, int offset, uint64_t value) { if (!nvme_is_fabrics_reg(offset)) { printf("register: %#04x (%s) not fabrics\n", offset, @@ -6105,13 +5995,13 @@ static int set_register_property(int fd, int offset, uint64_t value) return -EINVAL; } - return nvme_set_single_property(fd, offset, value); + return nvme_set_single_property(hdl, offset, value); } -static int nvme_set_register(int fd, void *bar, int offset, uint64_t value, bool mmio32) +static int nvme_set_register(struct nvme_transport_handle *hdl, void *bar, int offset, uint64_t value, bool mmio32) { if (!bar) - return set_register_property(fd, offset, value); + return set_register_property(hdl, offset, value); if (nvme_is_64bit_reg(offset)) mmio_write64(bar + offset, value, mmio32); @@ -6190,7 +6080,7 @@ static inline int set_register_names_check(struct argconfig_commandline_options return 0; } -static int set_register_offset(int fd, void *bar, struct argconfig_commandline_options *opts, +static int set_register_offset(struct nvme_transport_handle *hdl, void *bar, struct argconfig_commandline_options *opts, struct set_reg_config *cfg) { int err; @@ -6206,98 +6096,98 @@ static int set_register_offset(int fd, void *bar, struct argconfig_commandline_o return err; } - err = nvme_set_register(fd, bar, cfg->offset, cfg->value, cfg->mmio32); + err = nvme_set_register(hdl, bar, cfg->offset, cfg->value, cfg->mmio32); if (err) return err; return 0; } -static int set_register_names(int fd, void *bar, struct argconfig_commandline_options *opts, +static int set_register_names(struct nvme_transport_handle *hdl, void *bar, struct argconfig_commandline_options *opts, struct set_reg_config *cfg) { int err; if (argconfig_parse_seen(opts, "intms")) { - err = nvme_set_register(fd, bar, NVME_REG_INTMS, cfg->intms, cfg->mmio32); + err = nvme_set_register(hdl, bar, NVME_REG_INTMS, cfg->intms, cfg->mmio32); if (err) return err; } if (argconfig_parse_seen(opts, "intmc")) { - err = nvme_set_register(fd, bar, NVME_REG_INTMC, cfg->intmc, cfg->mmio32); + err = nvme_set_register(hdl, bar, NVME_REG_INTMC, cfg->intmc, cfg->mmio32); if (err) return err; } if (argconfig_parse_seen(opts, "cc")) { - err = nvme_set_register(fd, bar, NVME_REG_CC, cfg->cc, cfg->mmio32); + err = nvme_set_register(hdl, bar, NVME_REG_CC, cfg->cc, cfg->mmio32); if (err) return err; } if (argconfig_parse_seen(opts, "csts")) { - err = nvme_set_register(fd, bar, NVME_REG_CSTS, cfg->csts, cfg->mmio32); + err = nvme_set_register(hdl, bar, NVME_REG_CSTS, cfg->csts, cfg->mmio32); if (err) return err; } if (argconfig_parse_seen(opts, "nssr")) { - err = nvme_set_register(fd, bar, NVME_REG_NSSR, cfg->nssr, cfg->mmio32); + err = nvme_set_register(hdl, bar, NVME_REG_NSSR, cfg->nssr, cfg->mmio32); if (err) return err; } if (argconfig_parse_seen(opts, "aqa")) { - err = nvme_set_register(fd, bar, NVME_REG_AQA, cfg->aqa, cfg->mmio32); + err = nvme_set_register(hdl, bar, NVME_REG_AQA, cfg->aqa, cfg->mmio32); if (err) return err; } if (argconfig_parse_seen(opts, "asq")) { - err = nvme_set_register(fd, bar, NVME_REG_ASQ, cfg->asq, cfg->mmio32); + err = nvme_set_register(hdl, bar, NVME_REG_ASQ, cfg->asq, cfg->mmio32); if (err) return err; } if (argconfig_parse_seen(opts, "acq")) { - err = nvme_set_register(fd, bar, NVME_REG_ACQ, cfg->acq, cfg->mmio32); + err = nvme_set_register(hdl, bar, NVME_REG_ACQ, cfg->acq, cfg->mmio32); if (err) return err; } if (argconfig_parse_seen(opts, "bprsel")) { - err = nvme_set_register(fd, bar, NVME_REG_BPRSEL, cfg->bprsel, cfg->mmio32); + err = nvme_set_register(hdl, bar, NVME_REG_BPRSEL, cfg->bprsel, cfg->mmio32); if (err) return err; } if (argconfig_parse_seen(opts, "cmbmsc")) { - err = nvme_set_register(fd, bar, NVME_REG_CMBMSC, cfg->cmbmsc, cfg->mmio32); + err = nvme_set_register(hdl, bar, NVME_REG_CMBMSC, cfg->cmbmsc, cfg->mmio32); if (err) return err; } if (argconfig_parse_seen(opts, "nssd")) { - err = nvme_set_register(fd, bar, NVME_REG_NSSD, cfg->nssd, cfg->mmio32); + err = nvme_set_register(hdl, bar, NVME_REG_NSSD, cfg->nssd, cfg->mmio32); if (err) return err; } if (argconfig_parse_seen(opts, "pmrctl")) { - err = nvme_set_register(fd, bar, NVME_REG_PMRCTL, cfg->pmrctl, cfg->mmio32); + err = nvme_set_register(hdl, bar, NVME_REG_PMRCTL, cfg->pmrctl, cfg->mmio32); if (err) return err; } if (argconfig_parse_seen(opts, "pmrmscl")) { - err = nvme_set_register(fd, bar, NVME_REG_PMRMSCL, cfg->pmrmscl, cfg->mmio32); + err = nvme_set_register(hdl, bar, NVME_REG_PMRMSCL, cfg->pmrmscl, cfg->mmio32); if (err) return err; } if (argconfig_parse_seen(opts, "pmrmscu")) { - err = nvme_set_register(fd, bar, NVME_REG_PMRMSCU, cfg->pmrmscu, cfg->mmio32); + err = nvme_set_register(hdl, bar, NVME_REG_PMRMSCU, cfg->pmrmscu, cfg->mmio32); if (err) return err; } @@ -6305,15 +6195,15 @@ static int set_register_names(int fd, void *bar, struct argconfig_commandline_op return 0; } -static int set_register(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int set_register(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Writes and shows the defined NVMe controller register"; const char *value = "the value of the register to be set"; const char *mmio32 = "Access 64-bit registers as 2 32-bit"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; - void *bar; struct set_reg_config cfg = { @@ -6340,22 +6230,22 @@ static int set_register(int argc, char **argv, struct command *cmd, struct plugi OPT_UINT("pmrmscl", 0, &cfg.pmrmscl, pmrmscl), OPT_UINT("pmrmscu", 0, &cfg.pmrmscu, pmrmscu)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - if (is_blkdev(dev)) { + if (nvme_transport_handle_is_blkdev(hdl)) { nvme_show_error("Only character device is allowed"); return -EINVAL; } - bar = mmap_registers(dev, true); + bar = mmap_registers(hdl, true); if (argconfig_parse_seen(opts, "offset")) - err = set_register_offset(dev_fd(dev), bar, opts, &cfg); + err = set_register_offset(hdl, bar, opts, &cfg); if (!err) - err = set_register_names(dev_fd(dev), bar, opts, &cfg); + err = set_register_names(hdl, bar, opts, &cfg); if (bar) munmap(bar, getpagesize()); @@ -6363,7 +6253,7 @@ static int set_register(int argc, char **argv, struct command *cmd, struct plugi return err; } -static int get_property(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_property(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Reads and shows the defined NVMe controller property\n" "for NVMe over Fabric. Property offset must be one of:\n" @@ -6371,7 +6261,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"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u64 value; int err; nvme_print_flags_t flags = NORMAL; @@ -6386,7 +6277,7 @@ static int get_property(int argc, char **argv, struct command *cmd, struct plugi OPT_UINT("offset", 'O', &cfg.offset, offset), OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -6404,21 +6295,22 @@ static int get_property(int argc, char **argv, struct command *cmd, struct plugi if (cfg.human_readable || argconfig_parse_seen(opts, "verbose")) flags |= VERBOSE; - err = nvme_get_single_property(dev_fd(dev), &cfg, &value); + err = nvme_get_single_property(hdl, &cfg, &value); if (!err) nvme_show_single_property(cfg.offset, value, flags); return err; } -static int set_property(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int set_property(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Writes and shows the defined NVMe controller property for NVMe over Fabric"; const char *offset = "the offset of the property"; const char *value = "the value of the property to be set"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; nvme_print_flags_t flags; @@ -6431,7 +6323,7 @@ static int set_property(int argc, char **argv, struct command *cmd, struct plugi OPT_UINT("offset", 'O', &cfg.offset, offset), OPT_UINT("value", 'V', &cfg.value, value)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -6450,30 +6342,30 @@ static int set_property(int argc, char **argv, struct command *cmd, struct plugi return -EINVAL; } - return nvme_set_single_property(dev_fd(dev), cfg.offset, cfg.value); + return nvme_set_single_property(hdl, cfg.offset, cfg.value); } static void show_relatives(const char *name, nvme_print_flags_t flags) { - int err = 0; - - _cleanup_nvme_root_ nvme_root_t r = nvme_create_root(stderr, log_level); + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx; + int err; - if (!r) { - nvme_show_error("Failed to create topology root: %s", nvme_strerror(errno)); + ctx = nvme_create_global_ctx(stderr, log_level); + if (!ctx) { + nvme_show_error("Failed to create global context"); return; } - err = nvme_scan_topology(r, NULL, NULL); + err = nvme_scan_topology(ctx, NULL, NULL); if (err < 0) { - nvme_show_error("Failed to scan topology: %s", nvme_strerror(errno)); + nvme_show_error("Failed to scan topology: %s", nvme_strerror(-err)); return; } - nvme_show_relatives(r, name, flags); + nvme_show_relatives(ctx, name, flags); } -static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int format_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Re-format a specified namespace on the\n" "given device. Can erase all data in namespace (user\n" @@ -6483,19 +6375,21 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin const char *ses = "[0-2]: secure erase"; const char *pil = "[0-1]: protection info location last/first bytes of metadata"; const char *pi = "[0-3]: protection info off/Type 1/Type 2/Type 3"; - const char *ms = "[0-1]: extended format off/on"; + const char *mset = "[0-1]: extended format off/on"; const char *reset = "Automatically reset the controller after successful format"; const char *bs = "target block size"; const char *force = "The \"I know what I'm doing\" flag, skip confirmation before sending command"; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; _cleanup_free_ struct nvme_id_ns *ns = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + nvme_print_flags_t flags = NORMAL; + struct nvme_passthru_cmd cmd; __u32 timeout_ms = 600000; __u8 prev_lbaf = 0; int block_size; int err, i; - nvme_print_flags_t flags = NORMAL; struct config { __u32 namespace_id; @@ -6503,7 +6397,7 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin __u8 ses; __u8 pi; __u8 pil; - __u8 ms; + __u8 mset; bool reset; bool force; __u64 bs; @@ -6515,7 +6409,7 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin .ses = 0, .pi = 0, .pil = 0, - .ms = 0, + .mset = 0, .reset = false, .force = false, .bs = 0, @@ -6530,7 +6424,7 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin OPT_BYTE("ses", 's', &cfg.ses, ses), OPT_BYTE("pi", 'i', &cfg.pi, pi), OPT_BYTE("pil", 'p', &cfg.pil, pil), - OPT_BYTE("ms", 'm', &cfg.ms, ms), + OPT_BYTE("ms", 'm', &cfg.mset, mset), OPT_FLAG("reset", 'r', &cfg.reset, reset), OPT_FLAG("force", 0, &cfg.force, force), OPT_SUFFIX("block-size", 'b', &cfg.bs, bs)); @@ -6539,9 +6433,9 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin if (err) return err; - err = open_exclusive(&dev, argc, argv, cfg.force); + err = open_exclusive(&ctx, &hdl, argc, argv, cfg.force); if (err) { - if (errno == EBUSY) { + if (-err == EBUSY) { fprintf(stderr, "Failed to open %s.\n", basename(argv[optind])); fprintf(stderr, "Namespace is currently busy.\n"); if (!cfg.force) @@ -6576,9 +6470,9 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin if (!ctrl) return -ENOMEM; - err = nvme_cli_identify_ctrl(dev, ctrl); + err = nvme_identify_ctrl(hdl, ctrl); if (err) { - nvme_show_error("identify-ctrl: %s", nvme_strerror(errno)); + nvme_show_error("identify-ctrl: %s", nvme_strerror(err)); return -errno; } @@ -6590,9 +6484,9 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin */ cfg.namespace_id = NVME_NSID_ALL; } else if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return -errno; } } @@ -6609,10 +6503,10 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin if (!ns) return -ENOMEM; - err = nvme_cli_identify_ns(dev, cfg.namespace_id, ns); + err = nvme_identify_ns(hdl, cfg.namespace_id, ns); if (err) { if (err < 0) { - nvme_show_error("identify-namespace: %s", nvme_strerror(errno)); + nvme_show_error("identify-namespace: %s", nvme_strerror(err)); } else { fprintf(stderr, "identify failed\n"); nvme_show_status(err); @@ -6661,16 +6555,16 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin nvme_show_error("invalid pil:%d", cfg.pil); return -EINVAL; } - if (cfg.ms > 1) { - nvme_show_error("invalid ms:%d", cfg.ms); + if (cfg.mset > 1) { + nvme_show_error("invalid mset:%d", cfg.mset); return -EINVAL; } if (!cfg.force) { fprintf(stderr, "You are about to format %s, namespace %#x%s.\n", - dev->name, cfg.namespace_id, + nvme_transport_handle_get_name(hdl), cfg.namespace_id, cfg.namespace_id == NVME_NSID_ALL ? "(ALL namespaces)" : ""); - show_relatives(dev->name, flags); + show_relatives(nvme_transport_handle_get_name(hdl), flags); fprintf(stderr, "WARNING: Format may irrevocably delete this device's data.\n" "You have 10 seconds to press Ctrl-C to cancel this operation.\n\n" @@ -6679,28 +6573,19 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin fprintf(stderr, "Sending format operation ...\n"); } - struct nvme_format_nvm_args args = { - .args_size = sizeof(args), - .nsid = cfg.namespace_id, - .lbafu = (cfg.lbaf >> 4) & 0x3, - .lbaf = cfg.lbaf & 0xf, - .mset = cfg.ms, - .pi = cfg.pi, - .pil = cfg.pil, - .ses = cfg.ses, - .timeout = timeout_ms, - .result = NULL, - }; - err = nvme_cli_format_nvm(dev, &args); + nvme_init_format_nvm(&cmd, cfg.namespace_id, cfg.lbaf, cfg.mset, + cfg.pi, cfg.pil, cfg.ses); + cmd.timeout_ms = timeout_ms; + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) { - nvme_show_error("format: %s", nvme_strerror(errno)); + nvme_show_error("format: %s", nvme_strerror(err)); } else if (err != 0) { nvme_show_status(err); } else { printf("Success formatting namespace:%x\n", cfg.namespace_id); - if (dev->type == NVME_DEV_DIRECT && cfg.lbaf != prev_lbaf) { - if (is_chardev(dev)) { - if (ioctl(dev_fd(dev), NVME_IOCTL_RESCAN) < 0) { + if (nvme_transport_handle_is_direct(hdl) && cfg.lbaf != prev_lbaf) { + if (nvme_transport_handle_is_chardev(hdl)) { + if (ioctl(nvme_transport_handle_get_fd(hdl), NVME_IOCTL_RESCAN) < 0) { nvme_show_error("failed to rescan namespaces"); return -errno; } @@ -6714,20 +6599,21 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin * to the given one because blkdev will not * update by itself without re-opening fd. */ - if (ioctl(dev_fd(dev), BLKBSZSET, &block_size) < 0) { + if (ioctl(nvme_transport_handle_get_fd(hdl), BLKBSZSET, &block_size) < 0) { nvme_show_error("failed to set block size to %d", block_size); return -errno; } - if (ioctl(dev_fd(dev), BLKRRPART) < 0) { + if (ioctl(nvme_transport_handle_get_fd(hdl), BLKRRPART) < 0) { nvme_show_error("failed to re-read partition table"); return -errno; } } } - if (dev->type == NVME_DEV_DIRECT && cfg.reset && is_chardev(dev)) - nvme_ctrl_reset(dev_fd(dev)); + if (nvme_transport_handle_is_direct(hdl) && cfg.reset && + nvme_transport_handle_is_chardev(hdl)) + nvme_ctrl_reset(hdl); } return err; @@ -6736,7 +6622,7 @@ static int format_cmd(int argc, char **argv, struct command *cmd, struct plugin #define STRTOUL_AUTO_BASE (0) #define NVME_FEAT_TIMESTAMP_DATA_SIZE (6) -static int set_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int set_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Modify the saveable or changeable " "current operating parameters of the controller. " @@ -6747,13 +6633,14 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin "for each Feature are vendor-specific and may not be modified." "Use get-feature to determine which Features are supported by" "the controller and are saveable/changeable."; - const char *feature_id = "feature identifier (required)"; + const char *fid = "feature identifier (required)"; const char *data = "optional file for feature data (default stdin)"; const char *value = "new value of feature (required)"; const char *cdw12 = "feature cdw12, if used"; - const char *save = "specifies that the controller shall save the attribute"; + const char *sv = "specifies that the controller shall save the attribute"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ void *buf = NULL; _cleanup_fd_ int ffd = STDIN_FILENO; int err; @@ -6761,37 +6648,37 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin nvme_print_flags_t flags; struct config { - __u32 namespace_id; - __u8 feature_id; + __u32 nsid; + __u8 fid; __u64 value; __u32 cdw12; - __u8 uuid_index; + __u8 uidx; __u32 data_len; char *file; - bool save; + bool sv; }; struct config cfg = { - .namespace_id = 0, - .feature_id = 0, + .nsid = 0, + .fid = 0, .value = 0, - .uuid_index = 0, + .uidx = 0, .data_len = 0, .file = "", - .save = false, + .sv = false, }; NVME_ARGS(opts, - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_desired), - OPT_BYTE("feature-id", 'f', &cfg.feature_id, feature_id, feature_name), - OPT_SUFFIX("value", 'V', &cfg.value, value), - OPT_UINT("cdw12", 'c', &cfg.cdw12, cdw12), - OPT_BYTE("uuid-index", 'U', &cfg.uuid_index, uuid_index_specify), - OPT_UINT("data-len", 'l', &cfg.data_len, buf_len), - OPT_FILE("data", 'd', &cfg.file, data), - OPT_FLAG("save", 's', &cfg.save, save)); - - err = parse_and_open(&dev, argc, argv, desc, opts); + OPT_UINT("namespace-id", 'n', &cfg.nsid, namespace_desired), + OPT_BYTE("feature-id", 'f', &cfg.fid, fid, feature_name), + OPT_SUFFIX("value", 'V', &cfg.value, value), + OPT_UINT("cdw12", 'c', &cfg.cdw12, cdw12), + OPT_BYTE("uuid-index", 'U', &cfg.uidx, uuid_index_specify), + OPT_UINT("data-len", 'l', &cfg.data_len, buf_len), + OPT_FILE("data", 'd', &cfg.file, data), + OPT_FLAG("save", 's', &cfg.sv, sv)); + + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -6802,30 +6689,30 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin } if (!argconfig_parse_seen(opts, "namespace-id")) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.nsid); if (err < 0) { if (errno != ENOTTY) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return -errno; } - cfg.namespace_id = NVME_NSID_ALL; + cfg.nsid = NVME_NSID_ALL; } } - if (!cfg.feature_id) { + if (!cfg.fid) { nvme_show_error("feature-id required param"); return -EINVAL; } - if (cfg.uuid_index > 127) { - nvme_show_error("invalid uuid index param: %u", cfg.uuid_index); + if (cfg.uidx > 127) { + nvme_show_error("invalid uuid index param: %u", cfg.uidx); return -1; } if (!cfg.data_len) - nvme_cli_get_feature_length2(cfg.feature_id, cfg.value, - NVME_DATA_TFR_HOST_TO_CTRL, - &cfg.data_len); + nvme_get_feature_length(cfg.fid, cfg.value, + NVME_DATA_TFR_HOST_TO_CTRL, + &cfg.data_len); if (cfg.data_len) { buf = nvme_alloc(cfg.data_len); @@ -6840,7 +6727,7 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin * should use the buffer method if the value exceeds this * length. */ - if (cfg.feature_id == NVME_FEAT_FID_TIMESTAMP && + if (cfg.fid == NVME_FEAT_FID_TIMESTAMP && argconfig_parse_seen(opts, "value")) { memcpy(buf, &cfg.value, NVME_FEAT_TIMESTAMP_DATA_SIZE); } else { @@ -6862,34 +6749,20 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin } } - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = cfg.feature_id, - .nsid = cfg.namespace_id, - .cdw11 = cfg.value, - .cdw12 = cfg.cdw12, - .save = cfg.save, - .uuidx = cfg.uuid_index, - .cdw15 = 0, - .data_len = cfg.data_len, - .data = buf, - .timeout = nvme_cfg.timeout, - .result = &result, - }; - err = nvme_set_features(&args); + err = nvme_set_features(hdl, cfg.nsid, cfg.fid, cfg.sv, cfg.value, cfg.cdw12, + 0, cfg.uidx, 0, buf, cfg.data_len, &result); if (err < 0) { - nvme_show_error("set-feature: %s", nvme_strerror(errno)); + nvme_show_error("set-feature: %s", nvme_strerror(err)); } 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.fid ? 4 : 2, cfg.fid, + nvme_feature_to_string(cfg.fid), cfg.value ? 10 : 8, (uint64_t)cfg.value, - cfg.cdw12 ? 10 : 8, cfg.cdw12, cfg.save); - if (cfg.feature_id == NVME_FEAT_FID_LBA_STS_INTERVAL) + cfg.cdw12 ? 10 : 8, cfg.cdw12, cfg.sv); + if (cfg.fid == NVME_FEAT_FID_LBA_STS_INTERVAL) nvme_show_lba_status_info(result); if (buf) { - if (cfg.feature_id == NVME_FEAT_FID_LBA_RANGE) + if (cfg.fid == NVME_FEAT_FID_LBA_RANGE) nvme_show_lba_range((struct nvme_lba_range_type *)buf, result, 0); else d(buf, cfg.data_len, 16, 1); @@ -6901,7 +6774,7 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin return err; } -static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int sec_send(int argc, char **argv, struct command *acmd, struct plugin *plugin) { struct stat sb; const char *desc = "Transfer security protocol data to\n" @@ -6911,7 +6784,9 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p const char *file = "transfer payload"; const char *tl = "transfer length (cf. SPC-4)"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; _cleanup_free_ void *sec_buf = NULL; _cleanup_fd_ int sec_fd = -1; unsigned int sec_size; @@ -6944,7 +6819,7 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p OPT_SHRT("spsp", 's', &cfg.spsp, spsp), OPT_UINT("tl", 't', &cfg.tl, tl)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -6992,25 +6867,12 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p return -errno; } - struct nvme_security_send_args args = { - .args_size = sizeof(args), - .nsid = cfg.namespace_id, - .nssf = cfg.nssf, - .spsp0 = cfg.spsp & 0xff, - .spsp1 = cfg.spsp >> 8, - .secp = cfg.secp, - .tl = cfg.tl, - .data_len = cfg.tl, - .data = sec_buf, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; - - err = nvme_cli_security_send(dev, &args); - + nvme_init_security_send(&cmd, cfg.namespace_id, cfg.nssf, cfg.spsp, + cfg.secp, cfg.tl, sec_buf, cfg.tl); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) - nvme_show_error("security-send: %s", nvme_strerror(errno)); - else if (err != 0) + nvme_show_error("security-send: %s", nvme_strerror(err)); + else if (err > 0) nvme_show_status(err); else printf("NVME Security Send Command Success\n"); @@ -7018,15 +6880,17 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p return err; } -static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int dir_send(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Set directive parameters of the specified directive type."; const char *endir = "directive enable"; const char *ttype = "target directive type to be enabled/disabled"; const char *input = "write/send file (default stdin)"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ void *buf = NULL; + struct nvme_passthru_cmd cmd; __u32 result; __u32 dw12 = 0; _cleanup_fd_ int ffd = STDIN_FILENO; @@ -7070,7 +6934,7 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_directive), OPT_FILE("input-file", 'i', &cfg.file, input)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -7127,22 +6991,12 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p } } - struct nvme_directive_send_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .dspec = cfg.dspec, - .doper = cfg.doper, - .dtype = cfg.dtype, - .cdw12 = dw12, - .data_len = cfg.data_len, - .data = buf, - .timeout = nvme_cfg.timeout, - .result = &result, - }; - err = nvme_directive_send(&args); + nvme_init_directive_send(&cmd, cfg.namespace_id, cfg.doper, cfg.dtype, + cfg.dspec, buf, cfg.data_len); + cmd.cdw12 = dw12; + err = nvme_submit_admin_passthru(hdl, &cmd, &result); if (err < 0) { - nvme_show_error("dir-send: %s", nvme_strerror(errno)); + nvme_show_error("dir-send: %s", nvme_strerror(err)); return err; } if (!err) { @@ -7161,12 +7015,14 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p return err; } -static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int write_uncor(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "The Write Uncorrectable command is used to set a range of logical blocks to invalid."; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; int err; struct config { @@ -7192,14 +7048,14 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin OPT_BYTE("dir-type", 'T', &cfg.dtype, dtype), OPT_SHRT("dir-spec", 'S', &cfg.dspec, dspec_w_dtype)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return err; } } @@ -7209,20 +7065,11 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin return -EINVAL; } - struct nvme_io_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .slba = cfg.start_block, - .nlb = cfg.block_count, - .control = cfg.dtype << 4, - .dspec = cfg.dspec, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; - err = nvme_write_uncorrectable(&args); + nvme_init_write_uncorrectable(&cmd, cfg.namespace_id, cfg.start_block, + cfg.block_count, cfg.dtype << 4, cfg.dspec); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) - nvme_show_error("write uncorrectable: %s", nvme_strerror(errno)); + nvme_show_error("write uncorrectable: %s", nvme_strerror(err)); else if (err != 0) nvme_show_status(err); else @@ -7278,11 +7125,13 @@ static void get_pif_sts(struct nvme_id_ns *ns, struct nvme_nvm_id_ns *nvm_ns, __ *pif = (elbaf & NVME_NVM_ELBAF_QPIF_MASK) >> 9; } -static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int write_zeroes(int argc, char **argv, struct command *acmd, struct plugin *plugin) { _cleanup_free_ struct nvme_nvm_id_ns *nvm_ns = NULL; _cleanup_free_ struct nvme_id_ns *ns = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; __u8 sts = 0, pif = 0; __u16 control = 0; __u32 result = 0; @@ -7350,7 +7199,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi OPT_SHRT("dir-spec", 'D', &cfg.dspec, dspec_w_dtype), OPT_FLAG("namespace-zeroes", 'Z', &cfg.nsz, nsz)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -7375,9 +7224,9 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi control |= NVME_IO_NSZ; control |= (cfg.dtype << 4); if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return err; } } @@ -7386,9 +7235,9 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi if (!ns) return -ENOMEM; - err = nvme_cli_identify_ns(dev, cfg.namespace_id, ns); + err = nvme_identify_ns(hdl, cfg.namespace_id, ns); if (err < 0) { - nvme_show_error("identify namespace: %s", nvme_strerror(errno)); + nvme_show_error("identify namespace: %s", nvme_strerror(err)); return err; } else if (err) { nvme_show_status(err); @@ -7399,7 +7248,8 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi if (!nvm_ns) return -ENOMEM; - err = nvme_identify_ns_csi(dev_fd(dev), cfg.namespace_id, 0, NVME_CSI_NVM, nvm_ns); + err = nvme_identify_csi_ns(hdl, cfg.namespace_id, NVME_CSI_NVM, 0, + nvm_ns); if (!err) { get_pif_sts(ns, nvm_ns, &pif, &sts); } @@ -7407,27 +7257,15 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi if (invalid_tags(cfg.storage_tag, cfg.ref_tag, sts, pif)) return -EINVAL; - struct nvme_io_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .slba = cfg.start_block, - .nlb = cfg.block_count, - .control = control, - .reftag = (__u32)cfg.ref_tag, - .reftag_u64 = cfg.ref_tag, - .apptag = cfg.app_tag, - .appmask = cfg.app_tag_mask, - .sts = sts, - .pif = pif, - .storage_tag = cfg.storage_tag, - .dspec = cfg.dspec, - .timeout = nvme_cfg.timeout, - .result = &result, - }; - err = nvme_write_zeros(&args); + nvme_init_write_zeros(&cmd, cfg.namespace_id, cfg.start_block, + cfg.block_count, control, cfg.dspec, 0, 0); + nvme_init_var_size_tags((struct nvme_passthru_cmd64 *)&cmd, pif, sts, + cfg.ref_tag, cfg.storage_tag); + nvme_init_app_tag((struct nvme_passthru_cmd64 *)&cmd, cfg.app_tag, + cfg.app_tag_mask); + err = nvme_submit_admin_passthru(hdl, &cmd, &result); if (err < 0) - nvme_show_error("write-zeroes: %s", nvme_strerror(errno)); + nvme_show_error("write-zeroes: %s", nvme_strerror(err)); else if (err != 0) nvme_show_status(err); else { @@ -7443,7 +7281,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi return err; } -static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int dsm(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "The Dataset Management command is used by the host to\n" "indicate attributes for ranges of logical blocks. This includes attributes\n" @@ -7457,8 +7295,10 @@ 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"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ struct nvme_dsm_range *dsm = NULL; + struct nvme_passthru_cmd cmd; uint16_t nr, nc, nb, ns; __u32 ctx_attrs[256] = {0,}; __u32 nlbs[256] = {0,}; @@ -7498,7 +7338,7 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin OPT_FLAG("idr", 'r', &cfg.idr, idr), OPT_UINT("cdw11", 'c', &cfg.cdw11, cdw11)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -7518,9 +7358,9 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin } if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return err; } } @@ -7531,20 +7371,11 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin if (!dsm) return -ENOMEM; - nvme_init_dsm_range(dsm, ctx_attrs, nlbs, slbas, nr); - struct nvme_dsm_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .attrs = cfg.cdw11, - .nr_ranges = nr, - .dsm = dsm, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; - err = nvme_dsm(&args); + nvme_init_dsm(&cmd, cfg.namespace_id, nr, cfg.idr, cfg.idw, cfg.ad, dsm, + sizeof(*dsm) * 256); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) - nvme_show_error("data-set management: %s", nvme_strerror(errno)); + nvme_show_error("data-set management: %s", nvme_strerror(err)); else if (err != 0) nvme_show_status(err); else @@ -7553,7 +7384,7 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin return err; } -static int copy_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int copy_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "The Copy command is used by the host to copy data\n" "from one or more source logical block ranges to a\n" @@ -7577,8 +7408,10 @@ static int copy_cmd(int argc, char **argv, struct command *cmd, struct plugin *p const char *d_dspec = "directive specific (write part)"; const char *d_format = "source range entry format"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u16 nr, nb, ns, nrts, natms, nats, nids; + struct nvme_passthru_cmd cmd; __u16 nlbs[256] = { 0 }; __u64 slbas[256] = { 0 }; __u32 snsids[256] = { 0 }; @@ -7665,28 +7498,39 @@ static int copy_cmd(int argc, char **argv, struct command *cmd, struct plugin *p OPT_SHRT("dir-spec", 'S', &cfg.dspec, d_dspec), OPT_BYTE("format", 'F', &cfg.format, d_format)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - nb = argconfig_parse_comma_sep_array_u16(cfg.nlbs, nlbs, ARRAY_SIZE(nlbs)); - ns = argconfig_parse_comma_sep_array_u64(cfg.slbas, slbas, ARRAY_SIZE(slbas)); - nids = argconfig_parse_comma_sep_array_u32(cfg.snsids, snsids, ARRAY_SIZE(snsids)); - argconfig_parse_comma_sep_array_u16(cfg.sopts, sopts, ARRAY_SIZE(sopts)); - - if (cfg.format == 0 || cfg.format == 2) { - nrts = argconfig_parse_comma_sep_array_u32(cfg.eilbrts, eilbrts.short_pi, - ARRAY_SIZE(eilbrts.short_pi)); - } else if (cfg.format == 1 || cfg.format == 3) { - nrts = argconfig_parse_comma_sep_array_u64(cfg.eilbrts, eilbrts.long_pi, - ARRAY_SIZE(eilbrts.long_pi)); - } else { + nb = argconfig_parse_comma_sep_array_u16(cfg.nlbs, nlbs, + ARRAY_SIZE(nlbs)); + ns = argconfig_parse_comma_sep_array_u64(cfg.slbas, slbas, + ARRAY_SIZE(slbas)); + nids = argconfig_parse_comma_sep_array_u32(cfg.snsids, snsids, + ARRAY_SIZE(snsids)); + argconfig_parse_comma_sep_array_u16(cfg.sopts, sopts, + ARRAY_SIZE(sopts)); + + switch (cfg.format) { + case 0: + case 2: + nrts = argconfig_parse_comma_sep_array_u32(cfg.eilbrts, + eilbrts.short_pi, ARRAY_SIZE(eilbrts.short_pi)); + break; + case 1: + case 3: + nrts = argconfig_parse_comma_sep_array_u64(cfg.eilbrts, + eilbrts.long_pi, ARRAY_SIZE(eilbrts.long_pi)); + break; + default: nvme_show_error("invalid format"); return -EINVAL; } - natms = argconfig_parse_comma_sep_array_u32(cfg.elbatms, elbatms, ARRAY_SIZE(elbatms)); - nats = argconfig_parse_comma_sep_array_u32(cfg.elbats, elbats, ARRAY_SIZE(elbats)); + natms = argconfig_parse_comma_sep_array_u32(cfg.elbatms, elbatms, + ARRAY_SIZE(elbatms)); + nats = argconfig_parse_comma_sep_array_u32(cfg.elbats, elbats, + ARRAY_SIZE(elbats)); nr = max(nb, max(ns, max(nrts, max(natms, nats)))); if (cfg.format == 2 || cfg.format == 3) { @@ -7704,9 +7548,9 @@ static int copy_cmd(int argc, char **argv, struct command *cmd, struct plugin *p } if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return err; } } @@ -7715,40 +7559,35 @@ static int copy_cmd(int argc, char **argv, struct command *cmd, struct plugin *p if (!copy) return -ENOMEM; - if (cfg.format == 0) - nvme_init_copy_range(copy->f0, nlbs, slbas, eilbrts.short_pi, elbatms, elbats, nr); - else if (cfg.format == 1) - nvme_init_copy_range_f1(copy->f1, nlbs, slbas, eilbrts.long_pi, elbatms, elbats, nr); - else if (cfg.format == 2) - nvme_init_copy_range_f2(copy->f2, snsids, nlbs, slbas, sopts, eilbrts.short_pi, elbatms, - elbats, nr); - else if (cfg.format == 3) - nvme_init_copy_range_f3(copy->f3, snsids, nlbs, slbas, sopts, eilbrts.long_pi, elbatms, - elbats, nr); - - struct nvme_copy_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .copy = copy->f0, - .sdlba = cfg.sdlba, - .nr = nr, - .prinfor = cfg.prinfor, - .prinfow = cfg.prinfow, - .dtype = cfg.dtype, - .dspec = cfg.dspec, - .format = cfg.format, - .lr = cfg.lr, - .fua = cfg.fua, - .ilbrt_u64 = cfg.ilbrt, - .lbatm = cfg.lbatm, - .lbat = cfg.lbat, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; - err = nvme_copy(&args); + switch (cfg.format) { + case 1: + nvme_init_copy_range_f1(copy->f1, nlbs, slbas, eilbrts.long_pi, + elbatms, elbats, nr); + break; + case 2: + nvme_init_copy_range_f2(copy->f2, snsids, nlbs, slbas, sopts, + eilbrts.short_pi, elbatms, elbats, nr); + break; + case 3: + nvme_init_copy_range_f3(copy->f3, snsids, nlbs, slbas, sopts, + eilbrts.long_pi, elbatms, elbats, nr); + break; + default: + nvme_init_copy_range(copy->f0, nlbs, slbas, eilbrts.short_pi, + elbatms, elbats, nr); + break; + } + + nvme_init_copy(&cmd, cfg.namespace_id, cfg.sdlba, nr, cfg.format, + cfg.prinfor, cfg.prinfow, 0, cfg.dtype, false, false, + cfg.fua, cfg.lr, 0, cfg.dspec, copy->f0); + nvme_init_var_size_tags((struct nvme_passthru_cmd64 *)&cmd, + NVME_NVM_PIF_32B_GUARD, 0, cfg.ilbrt, 0); + nvme_init_app_tag((struct nvme_passthru_cmd64 *)&cmd, cfg.lbat, + cfg.lbatm); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) - nvme_show_error("NVMe Copy: %s", nvme_strerror(errno)); + nvme_show_error("NVMe Copy: %s", nvme_strerror(err)); else if (err != 0) nvme_show_status(err); else @@ -7757,7 +7596,7 @@ static int copy_cmd(int argc, char **argv, struct command *cmd, struct plugin *p return err; } -static int flush_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int flush_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Commit data and metadata associated with\n" "given namespaces to nonvolatile media. Applies to all commands\n" @@ -7765,7 +7604,8 @@ static int flush_cmd(int argc, char **argv, struct command *cmd, struct plugin * "flushed by the controller, from any namespace, depending on controller and\n" "associated namespace status."; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; struct config { @@ -7779,21 +7619,21 @@ static int flush_cmd(int argc, char **argv, struct command *cmd, struct plugin * NVME_ARGS(opts, OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return err; } } - err = nvme_flush(dev_fd(dev), cfg.namespace_id); + err = nvme_flush(hdl, cfg.namespace_id); if (err < 0) - nvme_show_error("flush: %s", nvme_strerror(errno)); + nvme_show_error("flush: %s", nvme_strerror(err)); else if (err != 0) nvme_show_status(err); else @@ -7802,7 +7642,7 @@ static int flush_cmd(int argc, char **argv, struct command *cmd, struct plugin * return err; } -static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int resv_acquire(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Obtain a reservation on a given\n" "namespace. Only one reservation is allowed at a time on a\n" @@ -7812,9 +7652,12 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi const char *prkey = "pre-empt reservation key"; const char *racqa = "reservation acquire action"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - int err; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; + __le64 payload[2]; + int err; struct config { __u32 namespace_id; @@ -7842,7 +7685,7 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi OPT_BYTE("racqa", 'a', &cfg.racqa, racqa), OPT_FLAG("iekey", 'i', &cfg.iekey, iekey)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -7853,9 +7696,9 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi } if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return err; } } @@ -7864,22 +7707,12 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi return -EINVAL; } - struct nvme_resv_acquire_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .rtype = cfg.rtype, - .racqa = cfg.racqa, - .iekey = !!cfg.iekey, - .crkey = cfg.crkey, - .nrkey = cfg.prkey, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; - err = nvme_resv_acquire(&args); + nvme_init_resv_acquire(&cmd, cfg.namespace_id, cfg.racqa, cfg.iekey, + false, cfg.rtype, cfg.crkey, cfg.prkey, payload); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) - nvme_show_error("reservation acquire: %s", nvme_strerror(errno)); - else if (err != 0) + nvme_show_error("reservation acquire: %s", nvme_strerror(err)); + else if (err > 0) nvme_show_status(err); else printf("NVME Reservation Acquire success\n"); @@ -7887,7 +7720,7 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi return err; } -static int resv_register(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int resv_register(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Register, de-register, or\n" "replace a controller's reservation on a given namespace.\n" @@ -7896,9 +7729,12 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug const char *rrega = "reservation registration action"; const char *cptpl = "change persistence through power loss setting"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - int err; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; + __le64 payload[2]; + int err; struct config { __u32 namespace_id; @@ -7925,7 +7761,7 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug OPT_BYTE("cptpl", 'p', &cfg.cptpl, cptpl), OPT_FLAG("iekey", 'i', &cfg.iekey, iekey)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -7936,9 +7772,9 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug } if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return err; } } @@ -7952,22 +7788,13 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug return -EINVAL; } - struct nvme_resv_register_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .rrega = cfg.rrega, - .cptpl = cfg.cptpl, - .iekey = !!cfg.iekey, - .crkey = cfg.crkey, - .nrkey = cfg.nrkey, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; - err = nvme_resv_register(&args); + nvme_init_resv_register(&cmd, cfg.namespace_id, cfg.rrega, cfg.iekey, + false, cfg.cptpl, cfg.crkey, cfg.nrkey, + payload); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) - nvme_show_error("reservation register: %s", nvme_strerror(errno)); - else if (err != 0) + nvme_show_error("reservation register: %s", nvme_strerror(err)); + else if (err > 0) nvme_show_status(err); else printf("NVME Reservation success\n"); @@ -7975,7 +7802,7 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug return err; } -static int resv_release(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int resv_release(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Releases reservation held on a\n" "namespace by the given controller. If rtype != current reservation\n" @@ -7987,12 +7814,15 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi "the issuing controller are notified."; const char *rrela = "reservation release action"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - int err; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; + __le64 payload[1]; + int err; struct config { - __u32 namespace_id; + __u32 nsid; __u64 crkey; __u8 rtype; __u8 rrela; @@ -8000,7 +7830,7 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi }; struct config cfg = { - .namespace_id = 0, + .nsid = 0, .crkey = 0, .rtype = 0, .rrela = 0, @@ -8008,13 +7838,13 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi }; NVME_ARGS(opts, - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_desired), - OPT_SUFFIX("crkey", 'c', &cfg.crkey, crkey), - OPT_BYTE("rtype", 't', &cfg.rtype, rtype), - OPT_BYTE("rrela", 'a', &cfg.rrela, rrela), - OPT_FLAG("iekey", 'i', &cfg.iekey, iekey)); + OPT_UINT("namespace-id", 'n', &cfg.nsid, namespace_desired), + OPT_SUFFIX("crkey", 'c', &cfg.crkey, crkey), + OPT_BYTE("rtype", 't', &cfg.rtype, rtype), + OPT_BYTE("rrela", 'a', &cfg.rrela, rrela), + OPT_FLAG("iekey", 'i', &cfg.iekey, iekey)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -8024,10 +7854,10 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi return err; } - if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + if (!cfg.nsid) { + err = nvme_get_nsid(hdl, &cfg.nsid); if (err < 0) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return err; } } @@ -8036,20 +7866,11 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi return -EINVAL; } - struct nvme_resv_release_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .rtype = cfg.rtype, - .rrela = cfg.rrela, - .iekey = !!cfg.iekey, - .crkey = cfg.crkey, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; - err = nvme_resv_release(&args); + nvme_init_resv_release(&cmd, cfg.nsid, cfg.rrela, cfg.iekey, false, + cfg.rtype, cfg.crkey, payload); + err = nvme_submit_io_passthru(hdl, &cmd, NULL); if (err < 0) - nvme_show_error("reservation release: %s", nvme_strerror(errno)); + nvme_show_error("reservation release: %s", nvme_strerror(err)); else if (err != 0) nvme_show_status(err); else @@ -8058,7 +7879,7 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi return err; } -static int resv_report(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int resv_report(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Returns Reservation Status data\n" "structure describing any existing reservations on and the\n" @@ -8067,33 +7888,35 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin const char *numd = "number of dwords to transfer"; const char *eds = "request extended data structure"; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; _cleanup_free_ struct nvme_resv_status *status = NULL; _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; int err, size; struct config { - __u32 namespace_id; + __u32 nsid; __u32 numd; __u8 eds; bool raw_binary; }; struct config cfg = { - .namespace_id = 0, + .nsid = 0, .numd = 0, .eds = false, .raw_binary = false, }; NVME_ARGS(opts, - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), - OPT_UINT("numd", 'd', &cfg.numd, numd), - OPT_FLAG("eds", 'e', &cfg.eds, eds), - OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_dump)); + OPT_UINT("namespace-id", 'n', &cfg.nsid, namespace_id_desired), + OPT_UINT("numd", 'd', &cfg.numd, numd), + OPT_FLAG("eds", 'e', &cfg.eds, eds), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_dump)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -8106,10 +7929,10 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin if (cfg.raw_binary) flags = BINARY; - if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + if (!cfg.nsid) { + err = nvme_get_nsid(hdl, &cfg.nsid); if (err < 0) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return err; } } @@ -8125,9 +7948,9 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin if (!ctrl) return -ENOMEM; - err = nvme_cli_identify_ctrl(dev, ctrl); + err = nvme_identify_ctrl(hdl, ctrl); if (err) { - nvme_show_error("identify-ctrl: %s", nvme_strerror(errno)); + nvme_show_error("identify-ctrl: %s", nvme_strerror(err)); return -errno; } @@ -8138,23 +7961,14 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin if (!status) return -ENOMEM; - struct nvme_resv_report_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .eds = cfg.eds, - .len = size, - .report = status, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; - err = nvme_resv_report(&args); + nvme_init_resv_report(&cmd, cfg.nsid, cfg.eds, false, status, size); + err = nvme_submit_io_passthru(hdl, &cmd, NULL); if (!err) nvme_show_resv_report(status, size, cfg.eds, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("reservation report: %s", nvme_strerror(errno)); + nvme_show_error("reservation report: %s", nvme_strerror(err)); return err; } @@ -8169,22 +7983,24 @@ unsigned long long elapsed_utime(struct timeval start_time, static int submit_io(int opcode, char *command, const char *desc, int argc, char **argv) { + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + unsigned long long buffer_size = 0, mbuffer_size = 0; + _cleanup_free_ struct nvme_nvm_id_ns *nvm_ns = NULL; + _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; + _cleanup_free_ struct nvme_id_ns *ns = NULL; + unsigned int logical_block_size = 0; struct timeval start_time, end_time; - void *buffer; _cleanup_free_ void *mbuffer = NULL; - int err = 0; _cleanup_fd_ int dfd = -1, mfd = -1; - int flags, pi_size; - int mode = 0644; + __u8 lba_index, sts = 0, pif = 0; __u16 control = 0, nblocks = 0; + struct nvme_passthru_cmd cmd; + int flags, pi_size; __u32 dsmgmt = 0; - unsigned int logical_block_size = 0; - unsigned long long buffer_size = 0, mbuffer_size = 0; - _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - _cleanup_free_ struct nvme_nvm_id_ns *nvm_ns = NULL; - _cleanup_free_ struct nvme_id_ns *ns = NULL; - __u8 lba_index, sts = 0, pif = 0; + int mode = 0644; + void *buffer; + int err = 0; __u16 ms; const char *start_block_addr = "64-bit addr of first block to access"; @@ -8279,16 +8095,16 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char OPT_FLAG("force", 0, &cfg.force, force)); if (opcode != nvme_cmd_write) { - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; } else { err = parse_args(argc, argv, desc, opts); if (err) return err; - err = open_exclusive(&dev, argc, argv, cfg.force); + err = open_exclusive(&ctx, &hdl, argc, argv, cfg.force); if (err) { - if (errno == EBUSY) { + if (err == -EBUSY) { fprintf(stderr, "Failed to open %s.\n", basename(argv[optind])); fprintf(stderr, "Namespace is currently busy.\n"); if (!cfg.force) @@ -8302,9 +8118,9 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char } if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return err; } } @@ -8366,12 +8182,12 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char if (!ns) return -ENOMEM; - err = nvme_cli_identify_ns(dev, cfg.namespace_id, ns); + err = nvme_identify_ns(hdl, cfg.namespace_id, ns); if (err > 0) { nvme_show_status(err); return err; } else if (err < 0) { - nvme_show_error("identify namespace: %s", nvme_strerror(errno)); + nvme_show_error("identify namespace: %s", nvme_strerror(err)); return err; } @@ -8383,7 +8199,8 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char if (!nvm_ns) return -ENOMEM; - err = nvme_identify_ns_csi(dev_fd(dev), cfg.namespace_id, 0, NVME_CSI_NVM, nvm_ns); + err = nvme_identify_csi_ns(hdl, cfg.namespace_id, NVME_CSI_NVM, 0, + nvm_ns); if (!err) get_pif_sts(ns, nvm_ns, &pif, &sts); @@ -8478,36 +8295,31 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char if (nvme_cfg.dry_run) return 0; - struct nvme_io_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .slba = cfg.start_block, - .nlb = nblocks, - .control = control, - .dsm = cfg.dsmgmt, - .sts = sts, - .pif = pif, - .dspec = cfg.dspec, - .reftag = (__u32)cfg.ref_tag, - .reftag_u64 = cfg.ref_tag, - .apptag = cfg.app_tag, - .appmask = cfg.app_tag_mask, - .storage_tag = cfg.storage_tag, - .data_len = buffer_size, - .data = buffer, - .metadata_len = mbuffer_size, - .metadata = mbuffer, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; + nvme_init_io(&cmd, opcode, cfg.namespace_id, cfg.start_block, buffer, + buffer_size, mbuffer, mbuffer_size); + cmd.cdw12 = NVME_FIELD_ENCODE(nblocks, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT, + NVME_IOCS_COMMON_CDW12_NLB_MASK) | + NVME_FIELD_ENCODE(control, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK); + cmd.cdw13 = NVME_FIELD_ENCODE(cfg.dspec, + NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, + NVME_IOCS_COMMON_CDW13_DSPEC_MASK) | + NVME_FIELD_ENCODE(cfg.dsmgmt, + NVME_IOCS_COMMON_CDW13_DSM_SHIFT, + NVME_IOCS_COMMON_CDW13_DSM_MASK); + nvme_init_var_size_tags((struct nvme_passthru_cmd64 *)&cmd, pif, sts, + cfg.ref_tag, cfg.storage_tag); + nvme_init_app_tag((struct nvme_passthru_cmd64 *)&cmd, cfg.app_tag, + cfg.app_tag_mask); gettimeofday(&start_time, NULL); - err = nvme_io(&args, opcode); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); gettimeofday(&end_time, NULL); if (cfg.latency) printf(" latency: %s: %llu us\n", command, elapsed_utime(start_time, end_time)); if (err < 0) { - nvme_show_error("submit-io: %s", nvme_strerror(errno)); + nvme_show_error("submit-io: %s", nvme_strerror(err)); } else if (err) { nvme_show_status(err); } else { @@ -8529,7 +8341,7 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char return err; } -static int compare(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int compare(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Compare specified logical blocks on\n" "device with specified data buffer; return failure if buffer\n" @@ -8538,7 +8350,7 @@ static int compare(int argc, char **argv, struct command *cmd, struct plugin *pl return submit_io(nvme_cmd_compare, "compare", desc, argc, argv); } -static int read_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int read_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Copy specified logical blocks on the given\n" "device to specified data buffer (default buffer is stdout)."; @@ -8546,7 +8358,7 @@ static int read_cmd(int argc, char **argv, struct command *cmd, struct plugin *p return submit_io(nvme_cmd_read, "read", desc, argc, argv); } -static int write_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int write_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Copy from provided data buffer (default\n" "buffer is stdin) to specified logical blocks on the given device."; @@ -8554,11 +8366,13 @@ static int write_cmd(int argc, char **argv, struct command *cmd, struct plugin * return submit_io(nvme_cmd_write, "write", desc, argc, argv); } -static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int verify_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { _cleanup_free_ struct nvme_nvm_id_ns *nvm_ns = NULL; _cleanup_free_ struct nvme_id_ns *ns = NULL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; __u8 sts = 0, pif = 0; __u16 control = 0; int err; @@ -8610,7 +8424,8 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin OPT_SUFFIX("storage-tag", 'S', &cfg.storage_tag, storage_tag), OPT_FLAG("storage-tag-check", 'C', &cfg.storage_tag_check, storage_tag_check)); - err = parse_and_open(&dev, argc, argv, desc, opts); + + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -8626,9 +8441,9 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin control |= NVME_IO_STC; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { - nvme_show_error("get-namespace-id: %s", nvme_strerror(errno)); + nvme_show_error("get-namespace-id: %s", nvme_strerror(err)); return err; } } @@ -8637,9 +8452,9 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin if (!ns) return -ENOMEM; - err = nvme_cli_identify_ns(dev, cfg.namespace_id, ns); + err = nvme_identify_ns(hdl, cfg.namespace_id, ns); if (err < 0) { - nvme_show_error("identify namespace: %s", nvme_strerror(errno)); + nvme_show_error("identify namespace: %s", nvme_strerror(err)); return err; } else if (err) { nvme_show_status(err); @@ -8650,8 +8465,8 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin if (!nvm_ns) return -ENOMEM; - err = nvme_identify_ns_csi(dev_fd(dev), cfg.namespace_id, 0, - NVME_CSI_NVM, nvm_ns); + err = nvme_identify_csi_ns(hdl, cfg.namespace_id, NVME_CSI_NVM, 0, + nvm_ns); if (!err) { get_pif_sts(ns, nvm_ns, &pif, &sts); } @@ -8659,26 +8474,15 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin if (invalid_tags(cfg.storage_tag, cfg.ref_tag, sts, pif)) return -EINVAL; - struct nvme_io_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .slba = cfg.start_block, - .nlb = cfg.block_count, - .control = control, - .reftag = cfg.ref_tag, - .reftag_u64 = cfg.ref_tag, - .apptag = cfg.app_tag, - .appmask = cfg.app_tag_mask, - .sts = sts, - .pif = pif, - .storage_tag = cfg.storage_tag, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; - err = nvme_verify(&args); + nvme_init_verify(&cmd, cfg.namespace_id, cfg.start_block, + cfg.block_count, control, 0, NULL, 0, NULL, 0); + nvme_init_var_size_tags((struct nvme_passthru_cmd64 *)&cmd, pif, sts, + cfg.ref_tag, cfg.storage_tag); + nvme_init_app_tag((struct nvme_passthru_cmd64 *)&cmd, cfg.app_tag, + cfg.app_tag_mask); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) - nvme_show_error("verify: %s", nvme_strerror(errno)); + nvme_show_error("verify: %s", nvme_strerror(err)); else if (err != 0) nvme_show_status(err); else @@ -8687,7 +8491,7 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin return err; } -static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int sec_recv(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Obtain results of one or more\n" "previously submitted security-sends. Results, and association\n" @@ -8698,10 +8502,12 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p const char *size = "size of buffer (prints to stdout on success)"; const char *al = "allocation length (cf. SPC-4)"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; _cleanup_free_ void *sec_buf = NULL; - int err; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; + int err; struct config { __u32 namespace_id; @@ -8732,7 +8538,7 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p OPT_UINT("al", 't', &cfg.al, al), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_dump)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -8748,24 +8554,12 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p return -ENOMEM; } - struct nvme_security_receive_args args = { - .args_size = sizeof(args), - .nsid = cfg.namespace_id, - .nssf = cfg.nssf, - .spsp0 = cfg.spsp & 0xff, - .spsp1 = cfg.spsp >> 8, - .secp = cfg.secp, - .al = cfg.al, - .data_len = cfg.size, - .data = sec_buf, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; - - err = nvme_cli_security_receive(dev, &args); + nvme_init_security_receive(&cmd, cfg.namespace_id, cfg.nssf, cfg.spsp, + cfg.secp, cfg.al, sec_buf, cfg.size); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) { - nvme_show_error("security receive: %s", nvme_strerror(errno)); - } else if (err != 0) { + nvme_show_error("security receive: %s", nvme_strerror(err)); + } else if (err > 0) { nvme_show_status(err); } else { printf("NVME Security Receive Command Success\n"); @@ -8778,7 +8572,7 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p return err; } -static int get_lba_status(int argc, char **argv, struct command *cmd, +static int get_lba_status(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Information about potentially unrecoverable LBAs."; @@ -8791,7 +8585,9 @@ static int get_lba_status(int argc, char **argv, struct command *cmd, const char *rl = "Range Length(RL) specifies the length of the range of contiguous LBAs beginning at SLBA"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; _cleanup_free_ void *buf = NULL; nvme_print_flags_t flags; unsigned long buf_len; @@ -8820,7 +8616,7 @@ static int get_lba_status(int argc, char **argv, struct command *cmd, OPT_BYTE("action", 'a', &cfg.atype, atype), OPT_SHRT("range-len", 'l', &cfg.rl, rl)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -8840,30 +8636,20 @@ static int get_lba_status(int argc, char **argv, struct command *cmd, if (!buf) return -ENOMEM; - struct nvme_get_lba_status_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .slba = cfg.slba, - .mndw = cfg.mndw, - .rl = cfg.rl, - .atype = cfg.atype, - .lbas = buf, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; - err = nvme_get_lba_status(&args); + nvme_init_get_lba_status(&cmd, cfg.namespace_id, cfg.slba, cfg.mndw, + cfg.atype, cfg.rl, buf); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) nvme_show_lba_status(buf, buf_len, flags); else if (err > 0) nvme_show_status(err); else - nvme_show_error("get lba status: %s", nvme_strerror(errno)); + nvme_show_error("get lba status: %s", nvme_strerror(err)); return err; } -static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int capacity_mgmt(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Host software uses the Capacity Management command to\n" "configure Endurance Groups and NVM Sets in an NVM subsystem by either\n" @@ -8876,7 +8662,9 @@ static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plug const char *cap_upper = "Most significant 32 bits of the capacity in bytes of the Endurance Group or NVM Set to be created"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; int err = -1; __u32 result; nvme_print_flags_t flags; @@ -8901,7 +8689,8 @@ static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plug OPT_UINT("cap-lower", 'l', &cfg.dw11, cap_lower), OPT_UINT("cap-upper", 'u', &cfg.dw12, cap_upper)); - err = parse_and_open(&dev, argc, argv, desc, opts); + + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -8916,17 +8705,9 @@ static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plug return -1; } - struct nvme_capacity_mgmt_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .op = cfg.operation, - .element_id = cfg.element_id, - .cdw11 = cfg.dw11, - .cdw12 = cfg.dw12, - .timeout = nvme_cfg.timeout, - .result = &result, - }; - err = nvme_capacity_mgmt(&args); + nvme_init_capacity_mgmt(&cmd, cfg.operation, cfg.element_id, + (__u64)cfg.dw12 << 32 | cfg.dw11); + err = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!err) { printf("Capacity Management Command is Success\n"); if (cfg.operation == 1) @@ -8936,20 +8717,22 @@ static int capacity_mgmt(int argc, char **argv, struct command *cmd, struct plug } else if (err > 0) { nvme_show_status(err); } else if (err < 0) { - nvme_show_error("capacity management: %s", nvme_strerror(errno)); + nvme_show_error("capacity management: %s", nvme_strerror(err)); } return err; } -static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int dir_receive(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Read directive parameters of the specified directive type."; const char *nsr = "namespace stream requested"; nvme_print_flags_t flags = NORMAL; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ void *buf = NULL; + struct nvme_passthru_cmd cmd; __u32 result; __u32 dw12 = 0; int err; @@ -8986,7 +8769,7 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin OPT_SHRT("req-resource", 'r', &cfg.nsr, nsr), OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable_directive)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -9036,39 +8819,29 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin return -ENOMEM; } - struct nvme_directive_recv_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .dspec = cfg.dspec, - .doper = cfg.doper, - .dtype = cfg.dtype, - .cdw12 = dw12, - .data_len = cfg.data_len, - .data = buf, - .timeout = nvme_cfg.timeout, - .result = &result, - }; - err = nvme_directive_recv(&args); + nvme_init_directive_recv(&cmd, cfg.namespace_id, cfg.doper, cfg.dtype, + cfg.dspec, buf, cfg.data_len); + cmd.cdw12 = dw12; + err = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!err) nvme_directive_show(cfg.dtype, cfg.doper, cfg.dspec, cfg.namespace_id, result, buf, cfg.data_len, flags); else if (err > 0) nvme_show_status(err); else if (err < 0) - nvme_show_error("dir-receive: %s", nvme_strerror(errno)); + nvme_show_error("dir-receive: %s", nvme_strerror(err)); return err; } /* rpmb_cmd_option is defined in nvme-rpmb.c */ extern int rpmb_cmd_option(int, char **, struct command *, struct plugin *); -static int rpmb_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int rpmb_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return rpmb_cmd_option(argc, argv, cmd, plugin); + return rpmb_cmd_option(argc, argv, acmd, plugin); } -static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int lockdown_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "The Lockdown command is used to control the\n" "Command and Feature Lockdown capability which configures the\n" @@ -9089,7 +8862,9 @@ static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugi "List that is used by the command.If this field is cleared to 0h,\n" "then no UUID index is specified"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; int err = -1; struct config { @@ -9115,7 +8890,7 @@ static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugi OPT_BYTE("scp", 's', &cfg.scp, scp_desc), OPT_BYTE("uuid", 'U', &cfg.uuid, uuid_desc)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -9137,20 +8912,11 @@ static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugi return -1; } - struct nvme_lockdown_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .scp = cfg.scp, - .prhbt = cfg.prhbt, - .ifc = cfg.ifc, - .ofi = cfg.ofi, - .uuidx = cfg.uuid, - .timeout = nvme_cfg.timeout, - .result = NULL, - }; - err = nvme_lockdown(&args); + nvme_init_lockdown(&cmd, cfg.scp, cfg.prhbt, cfg.ifc, cfg.ofi, + cfg.uuid); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) - nvme_show_error("lockdown: %s", nvme_strerror(errno)); + nvme_show_error("lockdown: %s", nvme_strerror(err)); else if (err > 0) nvme_show_status(err); else @@ -9185,7 +8951,7 @@ static void passthru_print_read_output(struct passthru_config cfg, void *data, i } static int passthru(int argc, char **argv, bool admin, - const char *desc, struct command *cmd) + const char *desc, struct command *acmd) { const char *opcode = "opcode (required)"; const char *cflags = "command flags"; @@ -9208,7 +8974,8 @@ static int passthru(int argc, char **argv, bool admin, const char *prefill = "prefill buffers with known byte-value, default 0"; _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_fd_ int dfd = -1, mfd = -1; int flags; int mode = 0644; @@ -9270,7 +9037,7 @@ static int passthru(int argc, char **argv, bool admin, OPT_FLAG("write", 'w', &cfg.write, wr), OPT_FLAG("latency", 'T', &cfg.latency, latency)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -9281,7 +9048,7 @@ static int passthru(int argc, char **argv, bool admin, } if (!argconfig_parse_seen(opts, "opcode")) { - nvme_show_error("%s: opcode parameter required", cmd->name); + nvme_show_error("%s: opcode parameter required", acmd->name); return -EINVAL; } @@ -9374,17 +9141,17 @@ static int passthru(int argc, char **argv, bool admin, gettimeofday(&start_time, NULL); if (admin) - err = nvme_cli_admin_passthru(dev, cfg.opcode, cfg.flags, - cfg.rsvd, - cfg.namespace_id, cfg.cdw2, - cfg.cdw3, cfg.cdw10, - cfg.cdw11, cfg.cdw12, cfg.cdw13, - cfg.cdw14, - cfg.cdw15, cfg.data_len, data, - cfg.metadata_len, - mdata, nvme_cfg.timeout, &result); + err = nvme_admin_passthru(hdl, cfg.opcode, cfg.flags, + cfg.rsvd, + cfg.namespace_id, cfg.cdw2, + cfg.cdw3, cfg.cdw10, + cfg.cdw11, cfg.cdw12, cfg.cdw13, + cfg.cdw14, + cfg.cdw15, cfg.data_len, data, + cfg.metadata_len, + mdata, nvme_cfg.timeout, &result); else - err = nvme_io_passthru(dev_fd(dev), cfg.opcode, cfg.flags, + err = nvme_io_passthru(hdl, cfg.opcode, cfg.flags, cfg.rsvd, cfg.namespace_id, cfg.cdw2, cfg.cdw3, cfg.cdw10, @@ -9402,7 +9169,7 @@ static int passthru(int argc, char **argv, bool admin, elapsed_utime(start_time, end_time)); if (err < 0) { - nvme_show_error("%s: %s", __func__, nvme_strerror(errno)); + nvme_show_error("%s: %s", __func__, nvme_strerror(err)); } else if (err) { nvme_show_status(err); } else { @@ -9415,30 +9182,30 @@ static int passthru(int argc, char **argv, bool admin, return err; } -static int io_passthru(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int io_passthru(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send a user-defined IO command to the specified device via IOCTL passthrough, return results."; - return passthru(argc, argv, false, desc, cmd); + return passthru(argc, argv, false, desc, acmd); } -static int admin_passthru(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int admin_passthru(int argc, char **argv, struct command *acmd, 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, true, desc, cmd); + return passthru(argc, argv, true, desc, acmd); } -static int gen_hostnqn_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) +static int gen_hostnqn_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { char *hostnqn; hostnqn = nvmf_hostnqn_generate(); if (!hostnqn) { nvme_show_error("\"%s\" not supported. Install lib uuid and rebuild.", - command->name); + acmd->name); return -ENOTSUP; } printf("%s\n", hostnqn); @@ -9446,7 +9213,7 @@ static int gen_hostnqn_cmd(int argc, char **argv, struct command *command, struc return 0; } -static int show_hostnqn_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) +static int show_hostnqn_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { char *hostnqn; @@ -9466,7 +9233,7 @@ static int show_hostnqn_cmd(int argc, char **argv, struct command *command, stru } -static int gen_dhchap_key(int argc, char **argv, struct command *command, struct plugin *plugin) +static int gen_dhchap_key(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Generate a DH-HMAC-CHAP host key usable for NVMe In-Band Authentication."; @@ -9580,8 +9347,9 @@ static int gen_dhchap_key(int argc, char **argv, struct command *command, struct } } - if (nvme_gen_dhchap_key(cfg.nqn, cfg.hmac, cfg.key_len, raw_secret, key) < 0) - return -errno; + err = nvme_gen_dhchap_key(cfg.nqn, cfg.hmac, cfg.key_len, raw_secret, key); + if (err) + return err; crc = crc32(crc, key, cfg.key_len); key[cfg.key_len++] = crc & 0xff; @@ -9596,7 +9364,7 @@ static int gen_dhchap_key(int argc, char **argv, struct command *command, struct return 0; } -static int check_dhchap_key(int argc, char **argv, struct command *command, struct plugin *plugin) +static int check_dhchap_key(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Check a DH-HMAC-CHAP host key for usability for NVMe In-Band Authentication."; @@ -9696,18 +9464,17 @@ static int append_keyfile(const char *keyring, long id, const char *keyfile) long kr_id; char type; - kr_id = nvme_lookup_keyring(keyring); - if (kr_id <= 0) { + err = nvme_lookup_keyring(keyring, &kr_id); + if (err) { nvme_show_error("Failed to lookup keyring '%s', %s", - keyring, strerror(errno)); - return -errno; + keyring, strerror(-err)); + return err; } identity = nvme_describe_key_serial(id); if (!identity) { - nvme_show_error("Failed to get identity info, %s", - strerror(errno)); - return -errno; + nvme_show_error("Failed to get identity info"); + return -EINVAL; } if (sscanf(identity, "NVMe%01d%c%02d %*s", &ver, &type, &hmac) != 3) { @@ -9715,19 +9482,19 @@ static int append_keyfile(const char *keyring, long id, const char *keyfile) return -EINVAL; } - key_data = nvme_read_key(kr_id, id, &key_len); - if (!key_data) { + err = nvme_read_key(kr_id, id, &key_len, &key_data); + if (err) { nvme_show_error("Failed to read back derive TLS PSK, %s", - strerror(errno)); - return -errno; + strerror(-err)); + return err; } - exported_key = nvme_export_tls_key_versioned(ver, hmac, - key_data, key_len); - if (!exported_key) { + err = nvme_export_tls_key_versioned(ver, hmac, key_data, + key_len, &exported_key); + if (err) { nvme_show_error("Failed to export key, %s", - strerror(errno)); - return -errno; + strerror(-err)); + return err; } old_umask = umask(0); @@ -9756,7 +9523,7 @@ static int append_keyfile(const char *keyring, long id, const char *keyfile) return err; } -static int gen_tls_key(int argc, char **argv, struct command *command, struct plugin *plugin) +static int gen_tls_key(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Generate a TLS key in NVMe PSK Interchange format."; const char *secret = @@ -9871,23 +9638,27 @@ static int gen_tls_key(int argc, char **argv, struct command *command, struct pl } } - encoded_key = nvme_export_tls_key(raw_secret, key_len); + err = nvme_export_tls_key(raw_secret, key_len, &encoded_key); + if (err) { + nvme_show_error("Failed to export key, %s", strerror(-err)); + return err; + } printf("%s\n", encoded_key); if (cfg.insert) { if (cfg.compat) - tls_key = nvme_insert_tls_key_compat(cfg.keyring, + err = nvme_insert_tls_key_compat(cfg.keyring, cfg.keytype, cfg.hostnqn, cfg.subsysnqn, cfg.version, - cfg.hmac, raw_secret, key_len); + cfg.hmac, raw_secret, key_len, &tls_key); else - tls_key = nvme_insert_tls_key_versioned(cfg.keyring, + err = nvme_insert_tls_key_versioned(cfg.keyring, cfg.keytype, cfg.hostnqn, cfg.subsysnqn, cfg.version, - cfg.hmac, raw_secret, key_len); - if (tls_key <= 0) { - nvme_show_error("Failed to insert key, error %d", errno); - return -errno; + cfg.hmac, raw_secret, key_len, &tls_key); + if (err) { + nvme_show_error("Failed to insert key, error %d", err); + return err; } printf("Inserted TLS key %08x\n", (unsigned int)tls_key); @@ -9902,7 +9673,7 @@ static int gen_tls_key(int argc, char **argv, struct command *command, struct pl return 0; } -static int check_tls_key(int argc, char **argv, struct command *command, struct plugin *plugin) +static int check_tls_key(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Check a TLS key for NVMe PSK Interchange format.\n"; const char *keydata = "TLS key (in PSK Interchange format) to be validated."; @@ -9969,10 +9740,10 @@ static int check_tls_key(int argc, char **argv, struct command *command, struct return -EINVAL; } - decoded_key = nvme_import_tls_key(cfg.keydata, &decoded_len, &hmac); - if (!decoded_key) { - nvme_show_error("Key decoding failed, error %d\n", errno); - return -errno; + err = nvme_import_tls_key(cfg.keydata, &decoded_len, &hmac, &decoded_key); + if (err) { + nvme_show_error("Key decoding failed, error %d\n", err); + return err; } if (cfg.subsysnqn) { @@ -9990,18 +9761,20 @@ static int check_tls_key(int argc, char **argv, struct command *command, struct if (cfg.insert) { if (cfg.compat) - tls_key = nvme_insert_tls_key_compat(cfg.keyring, + err = nvme_insert_tls_key_compat(cfg.keyring, cfg.keytype, cfg.hostnqn, cfg.subsysnqn, cfg.identity, - hmac, decoded_key, decoded_len); + hmac, decoded_key, decoded_len, + &tls_key); else - tls_key = nvme_insert_tls_key_versioned(cfg.keyring, + err = nvme_insert_tls_key_versioned(cfg.keyring, cfg.keytype, cfg.hostnqn, cfg.subsysnqn, cfg.identity, - hmac, decoded_key, decoded_len); - if (tls_key <= 0) { - nvme_show_error("Failed to insert key, error %d", errno); - return -errno; + hmac, decoded_key, decoded_len, + &tls_key); + if (err) { + nvme_show_error("Failed to insert key, error %d", err); + return err; } printf("Inserted TLS key %08x\n", (unsigned int)tls_key); @@ -10014,17 +9787,19 @@ static int check_tls_key(int argc, char **argv, struct command *command, struct _cleanup_free_ char *tls_id = NULL; if (cfg.compat) - tls_id = nvme_generate_tls_key_identity_compat(cfg.hostnqn, + err = nvme_generate_tls_key_identity_compat(cfg.hostnqn, cfg.subsysnqn, cfg.identity, - hmac, decoded_key, decoded_len); + hmac, decoded_key, decoded_len, + &tls_id); else - tls_id = nvme_generate_tls_key_identity(cfg.hostnqn, + err = nvme_generate_tls_key_identity(cfg.hostnqn, cfg.subsysnqn, cfg.identity, - hmac, decoded_key, decoded_len); - if (!tls_id) { + hmac, decoded_key, decoded_len, + &tls_id); + if (err) { nvme_show_error("Failed to generate identity, error %d", - errno); - return -errno; + err); + return err; } printf("%s\n", tls_id); } @@ -10035,39 +9810,41 @@ static void __scan_tls_key(long keyring_id, long key_id, char *desc, int desc_len, void *data) { FILE *fd = data; - _cleanup_free_ const unsigned char *key_data = NULL; + _cleanup_free_ unsigned char *key_data = NULL; _cleanup_free_ char *encoded_key = NULL; int key_len; int ver, hmac; char type; + int err; - key_data = nvme_read_key(keyring_id, key_id, &key_len); - if (!key_data) + err = nvme_read_key(keyring_id, key_id, &key_len, &key_data); + if (err) return; if (sscanf(desc, "NVMe%01d%c%02d %*s", &ver, &type, &hmac) != 3) return; - encoded_key = nvme_export_tls_key_versioned(ver, hmac, - key_data, key_len); - if (!encoded_key) + err = nvme_export_tls_key_versioned(ver, hmac, key_data, key_len, + &encoded_key); + if (err) return; fprintf(fd, "%s %s\n", desc, encoded_key); } static int import_key(const char *keyring, FILE *fd) { - long keyring_id; + long keyring_id, key; char tls_str[512]; char *tls_key; unsigned char *psk; unsigned int hmac; int linenum = -1, key_len; + int err; - keyring_id = nvme_lookup_keyring(keyring); - if (!keyring_id) { + err = nvme_lookup_keyring(keyring, &keyring_id); + if (err) { nvme_show_error("Invalid keyring '%s'", keyring); - return -ENOKEY; + return err; } while (fgets(tls_str, 512, fd)) { @@ -10081,14 +9858,16 @@ static int import_key(const char *keyring, FILE *fd) *tls_key = '\0'; tls_key++; tls_key[strcspn(tls_key, "\n")] = 0; - psk = nvme_import_tls_key(tls_key, &key_len, &hmac); - if (!psk) { + err = nvme_import_tls_key(tls_key, &key_len, &hmac, &psk); + if (err) { nvme_show_error("Failed to import key in line %d", linenum); continue; } - nvme_update_key(keyring_id, "psk", tls_str, - psk, key_len); + err = nvme_update_key(keyring_id, "psk", tls_str, + psk, key_len, &key); + if (err) + continue; free(psk); } @@ -10096,7 +9875,7 @@ static int import_key(const char *keyring, FILE *fd) } -static int tls_key(int argc, char **argv, struct command *command, struct plugin *plugin) +static int tls_key(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Manipulation of TLS keys.\n"; const char *keyring = "Keyring for the retained key."; @@ -10175,7 +9954,7 @@ static int tls_key(int argc, char **argv, struct command *command, struct plugin err = nvme_scan_tls_keys(cfg.keyring, __scan_tls_key, fd); if (err < 0) { nvme_show_error("Export of TLS keys failed with '%s'", - nvme_strerror(errno)); + nvme_strerror(err)); return err; } @@ -10187,7 +9966,7 @@ static int tls_key(int argc, char **argv, struct command *command, struct plugin err = import_key(cfg.keyring, fd); if (err) { nvme_show_error("Import of TLS keys failed with '%s'", - nvme_strerror(errno)); + nvme_strerror(err)); return err; } @@ -10197,7 +9976,7 @@ static int tls_key(int argc, char **argv, struct command *command, struct plugin err = nvme_revoke_tls_key(cfg.keyring, cfg.keytype, cfg.revoke); if (err) { nvme_show_error("Failed to revoke key '%s'", - nvme_strerror(errno)); + nvme_strerror(err)); return err; } @@ -10213,13 +9992,13 @@ static int tls_key(int argc, char **argv, struct command *command, struct plugin return err; } -static int show_topology_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) +static int show_topology_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Show the topology\n"; const char *output_format = "Output format: normal|json|binary|tabular"; const char *ranking = "Ranking order: namespace|ctrl|multipath"; nvme_print_flags_t flags; - _cleanup_nvme_root_ nvme_root_t r = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; char *devname = NULL; nvme_scan_filter_t filter = NULL; enum nvme_cli_topo_ranking rank; @@ -10260,10 +10039,10 @@ static int show_topology_cmd(int argc, char **argv, struct command *command, str return -EINVAL; } - r = nvme_create_root(stderr, log_level); - if (!r) { - nvme_show_error("Failed to create topology root: %s", nvme_strerror(errno)); - return -errno; + ctx = nvme_create_global_ctx(stderr, log_level); + if (!ctx) { + nvme_show_error("Failed to create global context"); + return -ENOMEM; } if (optind < argc) @@ -10279,49 +10058,49 @@ static int show_topology_cmd(int argc, char **argv, struct command *command, str filter = nvme_match_device_filter; } - err = nvme_scan_topology(r, filter, (void *)devname); + err = nvme_scan_topology(ctx, filter, (void *)devname); if (err < 0) { - nvme_show_error("Failed to scan topology: %s", nvme_strerror(errno)); + nvme_show_error("Failed to scan topology: %s", nvme_strerror(err)); return err; } if (flags & TABULAR) - nvme_show_topology_tabular(r, flags); + nvme_show_topology_tabular(ctx, flags); else - nvme_show_topology(r, rank, flags); + nvme_show_topology(ctx, rank, flags); return err; } -static int discover_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) +static int discover_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send Get Log Page request to Discovery Controller."; return nvmf_discover(desc, argc, argv, false); } -static int connect_all_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) +static int connect_all_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Discover NVMeoF subsystems and connect to them"; return nvmf_discover(desc, argc, argv, true); } -static int connect_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) +static int connect_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Connect to NVMeoF subsystem"; return nvmf_connect(desc, argc, argv); } -static int disconnect_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) +static int disconnect_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Disconnect from NVMeoF subsystem"; return nvmf_disconnect(desc, argc, argv); } -int disconnect_all_cmd(int argc, char **argv, struct command *command, +int disconnect_all_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Disconnect from all connected NVMeoF subsystems"; @@ -10329,14 +10108,14 @@ int disconnect_all_cmd(int argc, char **argv, struct command *command, return nvmf_disconnect_all(desc, argc, argv); } -static int config_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) +static int config_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Configuration of NVMeoF subsystems"; return nvmf_config(desc, argc, argv); } -static int dim_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) +static int dim_cmd(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send Discovery Information Management command to a Discovery Controller (DC)"; @@ -10360,7 +10139,8 @@ static int nvme_mi(int argc, char **argv, __u8 admin_opcode, const char *desc) _cleanup_fd_ int fd = -1; int flags; _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 result; struct config { @@ -10392,7 +10172,7 @@ static int nvme_mi(int argc, char **argv, __u8 admin_opcode, const char *desc) OPT_UINT("nmd1", '1', &cfg.nmd1, nmd1), OPT_FILE("input-file", 'i', &cfg.input_file, input)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -10435,11 +10215,11 @@ static int nvme_mi(int argc, char **argv, __u8 admin_opcode, const char *desc) } } - err = nvme_cli_admin_passthru(dev, admin_opcode, 0, 0, cfg.namespace_id, 0, 0, - cfg.nmimt << 11 | 4, cfg.opcode, cfg.nmd0, cfg.nmd1, 0, 0, - cfg.data_len, data, 0, NULL, 0, &result); + err = nvme_admin_passthru(hdl, admin_opcode, 0, 0, cfg.namespace_id, 0, 0, + cfg.nmimt << 11 | 4, cfg.opcode, cfg.nmd0, cfg.nmd1, 0, 0, + cfg.data_len, data, 0, NULL, 0, &result); if (err < 0) { - nvme_show_error("nmi_recv: %s", nvme_strerror(errno)); + nvme_show_error("nmi_recv: %s", nvme_strerror(err)); } else if (err) { nvme_show_status(err); } else { @@ -10459,7 +10239,7 @@ static int nvme_mi(int argc, char **argv, __u8 admin_opcode, const char *desc) return err; } -static int nmi_recv(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int nmi_recv(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send a NVMe-MI Receive command to the specified device, return results."; @@ -10467,26 +10247,26 @@ static int nmi_recv(int argc, char **argv, struct command *cmd, struct plugin *p return nvme_mi(argc, argv, nvme_admin_nvme_mi_recv, desc); } -static int nmi_send(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int nmi_send(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send a NVMe-MI Send command to the specified device, return results."; return nvme_mi(argc, argv, nvme_admin_nvme_mi_send, desc); } -static int get_mgmt_addr_list_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_mgmt_addr_list_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Management Address List Log, show it"; nvme_print_flags_t flags; int err = -1; _cleanup_free_ struct nvme_mgmt_addr_list_log *ma_log = NULL; - - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; NVME_ARGS(opts); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -10500,7 +10280,7 @@ static int get_mgmt_addr_list_log(int argc, char **argv, struct command *cmd, st if (!ma_log) return -ENOMEM; - err = nvme_cli_get_log_mgmt_addr_list(dev, sizeof(*ma_log), ma_log); + err = nvme_get_log_mgmt_addr_list(hdl, ma_log, sizeof(*ma_log)); if (!err) nvme_show_mgmt_addr_list_log(ma_log, flags); else if (err > 0) @@ -10511,7 +10291,7 @@ static int get_mgmt_addr_list_log(int argc, char **argv, struct command *cmd, st return err; } -static int get_rotational_media_info_log(int argc, char **argv, struct command *cmd, +static int get_rotational_media_info_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Rotational Media Information Log, show it"; @@ -10519,8 +10299,8 @@ static int get_rotational_media_info_log(int argc, char **argv, struct command * int err = -1; _cleanup_free_ struct nvme_rotational_media_info_log *info = NULL; - - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct config { __u16 endgid; @@ -10533,7 +10313,7 @@ static int get_rotational_media_info_log(int argc, char **argv, struct command * NVME_ARGS(opts, OPT_UINT("endg-id", 'e', &cfg.endgid, endgid)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -10547,7 +10327,7 @@ static int get_rotational_media_info_log(int argc, char **argv, struct command * if (!info) return -ENOMEM; - err = nvme_cli_get_log_rotational_media_info(dev, cfg.endgid, sizeof(*info), info); + err = nvme_get_log_rotational_media_info(hdl, cfg.endgid, info, sizeof(*info)); if (!err) nvme_show_rotational_media_info_log(info, flags); else if (err > 0) @@ -10558,26 +10338,19 @@ static int get_rotational_media_info_log(int argc, char **argv, struct command * return err; } -static int get_dispersed_ns_psub(struct nvme_dev *dev, __u32 nsid, +static int get_dispersed_ns_psub(struct nvme_transport_handle *hdl, __u32 nsid, struct nvme_dispersed_ns_participating_nss_log **logp) { int err; __u64 header_len = sizeof(**logp); __u64 psub_list_len; - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = nvme_cfg.timeout, - .lid = NVME_LOG_LID_DISPERSED_NS_PARTICIPATING_NSS, - .nsid = nsid, - .lpo = header_len, - }; struct nvme_dispersed_ns_participating_nss_log *log = nvme_alloc(header_len); + struct nvme_passthru_cmd cmd; if (!log) return -ENOMEM; - err = nvme_cli_get_log_dispersed_ns_participating_nss(dev, nsid, header_len, log); + err = nvme_get_log_dispersed_ns_participating_nss(hdl, nsid, log, header_len); if (err) goto err_free; @@ -10589,10 +10362,11 @@ static int get_dispersed_ns_psub(struct nvme_dev *dev, __u32 nsid, goto err_free; } - args.log = log->participating_nss, - args.len = psub_list_len; - - err = nvme_cli_get_log_page(dev, NVME_LOG_PAGE_PDU_SIZE, &args); + nvme_init_get_log_dispersed_ns_participating_nss(&cmd, nsid, + (void *)log->participating_nss, psub_list_len); + cmd.cdw12 = header_len & 0xffffffff; + cmd.cdw13 = header_len >> 32; + err = nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); if (err) goto err_free; @@ -10604,15 +10378,15 @@ static int get_dispersed_ns_psub(struct nvme_dev *dev, __u32 nsid, return err; } -static int get_dispersed_ns_participating_nss_log(int argc, char **argv, struct command *cmd, +static int get_dispersed_ns_participating_nss_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Dispersed Namespace Participating NVM Subsystems Log, show it"; nvme_print_flags_t flags; int err; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ struct nvme_dispersed_ns_participating_nss_log *log = NULL; struct config { @@ -10625,7 +10399,7 @@ static int get_dispersed_ns_participating_nss_log(int argc, char **argv, struct NVME_ARGS(opts, OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -10635,7 +10409,7 @@ static int get_dispersed_ns_participating_nss_log(int argc, char **argv, struct return err; } - err = get_dispersed_ns_psub(dev, cfg.namespace_id, &log); + err = get_dispersed_ns_psub(hdl, cfg.namespace_id, &log); if (!err) nvme_show_dispersed_ns_psub_log(log, flags); else if (err > 0) @@ -10646,20 +10420,43 @@ static int get_dispersed_ns_participating_nss_log(int argc, char **argv, struct return err; } -static int get_log_offset(struct nvme_dev *dev, struct nvme_get_log_args *args, __u64 *offset, +static int get_log_offset(struct nvme_transport_handle *hdl, + struct nvme_get_log_args *args, __u64 *offset, __u32 len, void **log) { + struct nvme_passthru_cmd cmd; + args->lpo = *offset, args->log = *log + *offset, args->len = len; *offset += args->len; + *log = nvme_realloc(*log, *offset); if (!*log) return -ENOMEM; - return nvme_cli_get_log_page(dev, NVME_LOG_PAGE_PDU_SIZE, args); -} -static int get_reachability_group_desc(struct nvme_dev *dev, struct nvme_get_log_args *args, + nvme_init_get_log(&cmd, args->nsid, args->lid, + args->csi, args->log, args->len); + cmd.cdw10 |= NVME_FIELD_ENCODE(args->lsp, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + cmd.cdw11 |= NVME_FIELD_ENCODE(args->lsi, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); + cmd.cdw12 = args->lpo & 0xffffffff; + cmd.cdw13 = args->lpo >> 32; + cmd.cdw14 |= NVME_FIELD_ENCODE(args->uidx, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK) | + NVME_FIELD_ENCODE(args->ot, + NVME_LOG_CDW14_OT_SHIFT, + NVME_LOG_CDW14_OT_MASK); + + return nvme_get_log(hdl, &cmd, args->rae, + NVME_LOG_PAGE_PDU_SIZE, args->result); +} + +static int get_reachability_group_desc(struct nvme_transport_handle *hdl, struct nvme_get_log_args *args, __u64 *offset, struct nvme_reachability_groups_log **logp) { int err; @@ -10669,11 +10466,11 @@ static int get_reachability_group_desc(struct nvme_dev *dev, struct nvme_get_log for (i = 0; i < le16_to_cpu(log->nrgd); i++) { len = sizeof(*log->rgd); - err = get_log_offset(dev, args, offset, len, (void **)&log); + err = get_log_offset(hdl, args, offset, len, (void **)&log); if (err) goto err_free; len = le32_to_cpu(log->rgd[i].nnid) * sizeof(*log->rgd[i].nsid); - err = get_log_offset(dev, args, offset, len, (void **)&log); + err = get_log_offset(hdl, args, offset, len, (void **)&log); if (err) goto err_free; } @@ -10687,7 +10484,7 @@ static int get_reachability_group_desc(struct nvme_dev *dev, struct nvme_get_log return err; } -static int get_reachability_groups(struct nvme_dev *dev, bool rgo, bool rae, +static int get_reachability_groups(struct nvme_transport_handle *hdl, bool rgo, bool rae, struct nvme_reachability_groups_log **logp, __u64 *lenp) { @@ -10695,9 +10492,6 @@ static int get_reachability_groups(struct nvme_dev *dev, bool rgo, bool rae, struct nvme_reachability_groups_log *log; __u64 log_len = sizeof(*log); struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = nvme_cfg.timeout, .lid = NVME_LOG_LID_REACHABILITY_GROUPS, .nsid = NVME_NSID_ALL, .lsp = rgo, @@ -10708,11 +10502,11 @@ static int get_reachability_groups(struct nvme_dev *dev, bool rgo, bool rae, if (!log) return -ENOMEM; - err = nvme_cli_get_log_reachability_groups(dev, rgo, rae, log_len, log); + err = nvme_get_log_reachability_groups(hdl, rgo, rae, log, log_len); if (err) goto err_free; - err = get_reachability_group_desc(dev, &args, &log_len, &log); + err = get_reachability_group_desc(hdl, &args, &log_len, &log); if (err) goto err_free; @@ -10725,7 +10519,7 @@ static int get_reachability_groups(struct nvme_dev *dev, bool rgo, bool rae, return err; } -static int get_reachability_groups_log(int argc, char **argv, struct command *cmd, +static int get_reachability_groups_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Reachability Groups Log, show it"; @@ -10733,10 +10527,9 @@ static int get_reachability_groups_log(int argc, char **argv, struct command *cm nvme_print_flags_t flags; int err; __u64 len = 0; - _cleanup_free_ struct nvme_reachability_groups_log *log = NULL; - - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct config { bool rgo; @@ -10752,7 +10545,7 @@ static int get_reachability_groups_log(int argc, char **argv, struct command *cm OPT_FLAG("groups-only", 'g', &cfg.rgo, rgo), OPT_FLAG("rae", 'r', &cfg.rae, rae)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -10762,7 +10555,7 @@ static int get_reachability_groups_log(int argc, char **argv, struct command *cm return err; } - err = get_reachability_groups(dev, cfg.rgo, cfg.rae, &log, &len); + err = get_reachability_groups(hdl, cfg.rgo, cfg.rae, &log, &len); if (!err) nvme_show_reachability_groups_log(log, len, flags); else if (err > 0) @@ -10773,7 +10566,7 @@ static int get_reachability_groups_log(int argc, char **argv, struct command *cm return err; } -static int get_reachability_association_desc(struct nvme_dev *dev, struct nvme_get_log_args *args, +static int get_reachability_association_desc(struct nvme_transport_handle *hdl, struct nvme_get_log_args *args, __u64 *offset, struct nvme_reachability_associations_log **logp) { @@ -10784,11 +10577,11 @@ static int get_reachability_association_desc(struct nvme_dev *dev, struct nvme_g for (i = 0; i < le16_to_cpu(log->nrad); i++) { len = sizeof(*log->rad); - err = get_log_offset(dev, args, offset, len, (void **)&log); + err = get_log_offset(hdl, args, offset, len, (void **)&log); if (err) goto err_free; len = le32_to_cpu(log->rad[i].nrid) * sizeof(*log->rad[i].rgid); - err = get_log_offset(dev, args, offset, len, (void **)&log); + err = get_log_offset(hdl, args, offset, len, (void **)&log); if (err) goto err_free; } @@ -10802,7 +10595,7 @@ static int get_reachability_association_desc(struct nvme_dev *dev, struct nvme_g return err; } -static int get_reachability_associations(struct nvme_dev *dev, bool rao, bool rae, +static int get_reachability_associations(struct nvme_transport_handle *hdl, bool rao, bool rae, struct nvme_reachability_associations_log **logp, __u64 *lenp) { @@ -10810,9 +10603,6 @@ static int get_reachability_associations(struct nvme_dev *dev, bool rao, bool ra struct nvme_reachability_associations_log *log; __u64 log_len = sizeof(*log); struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = nvme_cfg.timeout, .lid = NVME_LOG_LID_REACHABILITY_ASSOCIATIONS, .nsid = NVME_NSID_ALL, .lsp = rao, @@ -10823,11 +10613,11 @@ static int get_reachability_associations(struct nvme_dev *dev, bool rao, bool ra if (!log) return -ENOMEM; - err = nvme_cli_get_log_reachability_associations(dev, rao, rae, log_len, log); + err = nvme_get_log_reachability_associations(hdl, rao, rae, log, log_len); if (err) goto err_free; - err = get_reachability_association_desc(dev, &args, &log_len, &log); + err = get_reachability_association_desc(hdl, &args, &log_len, &log); if (err) goto err_free; @@ -10840,7 +10630,7 @@ static int get_reachability_associations(struct nvme_dev *dev, bool rao, bool ra return err; } -static int get_reachability_associations_log(int argc, char **argv, struct command *cmd, +static int get_reachability_associations_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Reachability Associations Log, show it"; @@ -10848,10 +10638,9 @@ static int get_reachability_associations_log(int argc, char **argv, struct comma nvme_print_flags_t flags; int err; __u64 len = 0; - _cleanup_free_ struct nvme_reachability_associations_log *log = NULL; - - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct config { bool rao; @@ -10867,7 +10656,7 @@ static int get_reachability_associations_log(int argc, char **argv, struct comma OPT_FLAG("associations-only", 'a', &cfg.rao, rao), OPT_FLAG("rae", 'r', &cfg.rae, rae)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -10877,7 +10666,7 @@ static int get_reachability_associations_log(int argc, char **argv, struct comma return err; } - err = get_reachability_associations(dev, cfg.rao, cfg.rae, &log, &len); + err = get_reachability_associations(hdl, cfg.rao, cfg.rae, &log, &len); if (!err) nvme_show_reachability_associations_log(log, len, flags); else if (err > 0) @@ -10888,17 +10677,14 @@ static int get_reachability_associations_log(int argc, char **argv, struct comma return err; } -static int get_host_discovery(struct nvme_dev *dev, bool allhoste, bool rae, +static int get_host_discovery(struct nvme_transport_handle *hdl, bool allhoste, bool rae, struct nvme_host_discover_log **logp) { int err; struct nvme_host_discover_log *log; __u64 log_len = sizeof(*log); struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = nvme_cfg.timeout, - .lid = NVME_LOG_LID_HOST_DISCOVER, + .lid = NVME_LOG_LID_HOST_DISCOVERY, .nsid = NVME_NSID_ALL, .lsp = allhoste, .rae = rae, @@ -10908,12 +10694,12 @@ static int get_host_discovery(struct nvme_dev *dev, bool allhoste, bool rae, if (!log) return -ENOMEM; - err = nvme_cli_get_log_host_discovery(dev, allhoste, rae, log_len, log); + err = nvme_get_log_host_discovery(hdl, allhoste, rae, log, log_len); if (err) goto err_free; log_len = le32_to_cpu(log->thdlpl); - err = get_log_offset(dev, &args, &log_len, le32_to_cpu(log->thdlpl) - log_len, + err = get_log_offset(hdl, &args, &log_len, le32_to_cpu(log->thdlpl) - log_len, (void **)&log); if (err) goto err_free; @@ -10926,16 +10712,15 @@ static int get_host_discovery(struct nvme_dev *dev, bool allhoste, bool rae, return err; } -static int get_host_discovery_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_host_discovery_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Host Discovery Log, show it"; const char *allhoste = "All Host Entries"; nvme_print_flags_t flags; int err; - _cleanup_free_ struct nvme_host_discover_log *log = NULL; - - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct config { bool allhoste; @@ -10951,7 +10736,8 @@ static int get_host_discovery_log(int argc, char **argv, struct command *cmd, st OPT_FLAG("all-host-entries", 'a', &cfg.allhoste, allhoste), OPT_FLAG("rae", 'r', &cfg.rae, rae)); - err = parse_and_open(&dev, argc, argv, desc, opts); + + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -10961,7 +10747,7 @@ static int get_host_discovery_log(int argc, char **argv, struct command *cmd, st return err; } - err = get_host_discovery(dev, cfg.allhoste, cfg.rae, &log); + err = get_host_discovery(hdl, cfg.allhoste, cfg.rae, &log); if (!err) nvme_show_host_discovery_log(log, flags); else if (err > 0) @@ -10972,16 +10758,13 @@ static int get_host_discovery_log(int argc, char **argv, struct command *cmd, st return err; } -static int get_ave_discovery(struct nvme_dev *dev, bool rae, struct nvme_ave_discover_log **logp) +static int get_ave_discovery(struct nvme_transport_handle *hdl, bool rae, struct nvme_ave_discover_log **logp) { int err; struct nvme_ave_discover_log *log; __u64 log_len = sizeof(*log); struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = nvme_cfg.timeout, - .lid = NVME_LOG_LID_AVE_DISCOVER, + .lid = NVME_LOG_LID_AVE_DISCOVERY, .nsid = NVME_NSID_ALL, .rae = rae, }; @@ -10990,12 +10773,12 @@ static int get_ave_discovery(struct nvme_dev *dev, bool rae, struct nvme_ave_dis if (!log) return -ENOMEM; - err = nvme_cli_get_log_ave_discovery(dev, rae, log_len, log); + err = nvme_get_log_ave_discovery(hdl, rae, log, log_len); if (err) goto err_free; log_len = le32_to_cpu(log->tadlpl); - err = get_log_offset(dev, &args, &log_len, le32_to_cpu(log->tadlpl) - log_len, + err = get_log_offset(hdl, &args, &log_len, le32_to_cpu(log->tadlpl) - log_len, (void **)&log); if (err) goto err_free; @@ -11008,15 +10791,15 @@ static int get_ave_discovery(struct nvme_dev *dev, bool rae, struct nvme_ave_dis return err; } -static int get_ave_discovery_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_ave_discovery_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve AVE Discovery Log, show it"; nvme_print_flags_t flags; int err; _cleanup_free_ struct nvme_ave_discover_log *log = NULL; - - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct config { bool rae; @@ -11028,7 +10811,7 @@ static int get_ave_discovery_log(int argc, char **argv, struct command *cmd, str NVME_ARGS(opts, OPT_FLAG("rae", 'r', &cfg.rae, rae)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -11038,7 +10821,7 @@ static int get_ave_discovery_log(int argc, char **argv, struct command *cmd, str return err; } - err = get_ave_discovery(dev, cfg.rae, &log); + err = get_ave_discovery(hdl, cfg.rae, &log); if (!err) nvme_show_ave_discovery_log(log, flags); else if (err > 0) @@ -11049,16 +10832,13 @@ static int get_ave_discovery_log(int argc, char **argv, struct command *cmd, str return err; } -static int get_pull_model_ddc_req(struct nvme_dev *dev, +static int get_pull_model_ddc_req(struct nvme_transport_handle *hdl, bool rae, struct nvme_pull_model_ddc_req_log **logp) { int err; struct nvme_pull_model_ddc_req_log *log; __u64 log_len = sizeof(*log); struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = nvme_cfg.timeout, .lid = NVME_LOG_LID_PULL_MODEL_DDC_REQ, .nsid = NVME_NSID_ALL, .rae = rae, @@ -11068,12 +10848,12 @@ static int get_pull_model_ddc_req(struct nvme_dev *dev, if (!log) return -ENOMEM; - err = nvme_cli_get_log_pull_model_ddc_req(dev, rae, log_len, log); + err = nvme_get_log_pull_model_ddc_req(hdl, rae, log, log_len); if (err) goto err_free; log_len = le32_to_cpu(log->tpdrpl); - err = get_log_offset(dev, &args, &log_len, le32_to_cpu(log->tpdrpl) - log_len, + err = get_log_offset(hdl, &args, &log_len, le32_to_cpu(log->tpdrpl) - log_len, (void **)&log); if (err) goto err_free; @@ -11086,7 +10866,7 @@ static int get_pull_model_ddc_req(struct nvme_dev *dev, return err; } -static int get_pull_model_ddc_req_log(int argc, char **argv, struct command *cmd, +static int get_pull_model_ddc_req_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Pull Model DDC Request Log, show it"; @@ -11094,8 +10874,8 @@ static int get_pull_model_ddc_req_log(int argc, char **argv, struct command *cmd int err; _cleanup_free_ struct nvme_pull_model_ddc_req_log *log = NULL; - - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct config { bool rae; @@ -11107,7 +10887,7 @@ static int get_pull_model_ddc_req_log(int argc, char **argv, struct command *cmd NVME_ARGS(opts, OPT_FLAG("rae", 'r', &cfg.rae, rae)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -11117,7 +10897,7 @@ static int get_pull_model_ddc_req_log(int argc, char **argv, struct command *cmd return err; } - err = get_pull_model_ddc_req(dev, cfg.rae, &log); + err = get_pull_model_ddc_req(hdl, cfg.rae, &log); if (!err) nvme_show_pull_model_ddc_req_log(log, flags); else if (err > 0) diff --git a/nvme.h b/nvme.h index c4f0f0cf14..84792f7b57 100644 --- a/nvme.h +++ b/nvme.h @@ -52,30 +52,6 @@ enum nvme_cli_topo_ranking { #define SYS_NVME "/sys/class/nvme" -enum nvme_dev_type { - NVME_DEV_DIRECT, - NVME_DEV_MI, -}; - -struct nvme_dev { - enum nvme_dev_type type; - union { - struct { - int fd; - struct stat stat; - } direct; - struct { - nvme_root_t root; - nvme_mi_ep_t ep; - nvme_mi_ctrl_t ctrl; - } mi; - }; - - const char *name; -}; - -#define dev_fd(d) __dev_fd(d, __func__, __LINE__) - struct nvme_config { char *output_format; int verbose; @@ -103,27 +79,6 @@ struct nvme_config { OPT_END() \ } -static inline int __dev_fd(struct nvme_dev *dev, const char *func, int line) -{ - if (dev->type != NVME_DEV_DIRECT) { - fprintf(stderr, - "warning: %s:%d not a direct transport!\n", - func, line); - return -1; - } - return dev->direct.fd; -} - -static inline nvme_mi_ep_t dev_mi_ep(struct nvme_dev *dev) -{ - if (dev->type != NVME_DEV_MI) { - fprintf(stderr, - "warning: not a MI transport!\n"); - return NULL; - } - return dev->mi.ep; -} - static inline bool nvme_is_multipath(nvme_subsystem_t s) { nvme_ns_t n; @@ -139,16 +94,16 @@ static inline bool nvme_is_multipath(nvme_subsystem_t s) void register_extension(struct plugin *plugin); /* - * parse_and_open - parses arguments and opens the NVMe device, populating @dev + * parse_and_open - parses arguments and opens the NVMe device, populating @ctx, @hdl */ -int parse_and_open(struct nvme_dev **dev, int argc, char **argv, const char *desc, - struct argconfig_commandline_options *clo); - -void dev_close(struct nvme_dev *dev); +int parse_and_open(struct nvme_global_ctx **ctx, + struct nvme_transport_handle **hdl, int argc, char **argv, + const char *desc, struct argconfig_commandline_options *clo); +// TODO: unsure if we need a double ptr here static inline DEFINE_CLEANUP_FUNC( - cleanup_nvme_dev, struct nvme_dev *, dev_close) -#define _cleanup_nvme_dev_ __cleanup__(cleanup_nvme_dev) + cleanup_nvme_transport_handle, struct nvme_transport_handle *, nvme_close) +#define _cleanup_nvme_transport_handle_ __cleanup__(cleanup_nvme_transport_handle) extern const char *output_format; extern const char *timeout; @@ -158,7 +113,7 @@ extern struct nvme_config nvme_cfg; int validate_output_format(const char *format, nvme_print_flags_t *flags); bool nvme_is_output_format_json(void); -int __id_ctrl(int argc, char **argv, struct command *cmd, +int __id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin, void (*vs)(uint8_t *vs, struct json_object *root)); const char *nvme_strerror(int errnum); @@ -174,4 +129,16 @@ void d_raw(unsigned char *buf, unsigned len); int get_reg_size(int offset); bool nvme_is_ctrl_reg(int offset); + +static inline int nvme_get_nsid_log(struct nvme_transport_handle *hdl, + __u32 nsid, bool rae, + enum nvme_cmd_get_log_lid lid, + void *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log(&cmd, nsid, lid, NVME_CSI_NVM, log, len); + + return nvme_get_log(hdl, &cmd, rae, NVME_LOG_PAGE_PDU_SIZE, NULL); +} #endif /* _NVME_H */ diff --git a/plugin.c b/plugin.c index 678129ecfe..0406bd0246 100644 --- a/plugin.c +++ b/plugin.c @@ -39,16 +39,18 @@ static int help(int argc, char **argv, struct plugin *plugin) } for (i = 0; plugin->commands[i]; i++) { - struct command *cmd = plugin->commands[i]; + struct command *command = plugin->commands[i]; - if (strcmp(str, cmd->name)) - if (!cmd->alias || (cmd->alias && strcmp(str, cmd->alias))) + if (strcmp(str, command->name)) + if (!command->alias || + (command->alias && strcmp(str, command->alias))) continue; if (plugin->name) - sprintf(man, "%s-%s-%s", prog->name, plugin->name, cmd->name); + sprintf(man, "%s-%s-%s", prog->name, + plugin->name, command->name); else - sprintf(man, "%s-%s", prog->name, cmd->name); + sprintf(man, "%s-%s", prog->name, command->name); if (execlp("man", "man", man, (char *)NULL)) perror(argv[1]); } diff --git a/plugin.h b/plugin.h index 0262efe1a8..4d1face5bd 100644 --- a/plugin.h +++ b/plugin.h @@ -27,7 +27,7 @@ struct plugin { struct command { char *name; char *help; - int (*fn)(int argc, char **argv, struct command *command, struct plugin *plugin); + int (*fn)(int argc, char **argv, struct command *acmd, struct plugin *plugin); char *alias; }; diff --git a/plugins/amzn/amzn-nvme.c b/plugins/amzn/amzn-nvme.c index 243f652f87..61c44d1550 100644 --- a/plugins/amzn/amzn-nvme.c +++ b/plugins/amzn/amzn-nvme.c @@ -128,9 +128,9 @@ static void amzn_id_ctrl(__u8 *vs, struct json_object *root) printf("bdev : %s\n", bdev); } -static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return __id_ctrl(argc, argv, cmd, plugin, amzn_id_ctrl); + return __id_ctrl(argc, argv, acmd, plugin, amzn_id_ctrl); } /* this function converts the size (in uint32_t) into human readable string @@ -462,16 +462,20 @@ static void amzn_print_json_stats(struct amzn_latency_log_page *log, bool detail #define amzn_print_json_stats(log, detail) #endif /* CONFIG_JSONC */ -static int get_stats(int argc, char **argv, struct command *cmd, +static int get_stats(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "display command latency statistics"; - struct nvme_dev *dev; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; struct amzn_latency_log_page log = { 0 }; - int rc; nvme_print_flags_t flags = 0; // Initialize flags to 0 + struct nvme_passthru_cmd cmd; struct nvme_id_ctrl ctrl; bool detail = false; + size_t len; + __u32 nsid = 1; + int rc; struct config { char *output_format; @@ -487,51 +491,36 @@ static int get_stats(int argc, char **argv, struct command *cmd, OPT_FLAG("details", 'd', &detail, "Detail IO histogram of each block size ranges"), OPT_END()}; - rc = parse_and_open(&dev, argc, argv, desc, opts); + rc = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (rc) return rc; - if (nvme_identify_ctrl(dev_fd(dev), &ctrl)) { + if (nvme_identify_ctrl(hdl, &ctrl)) { fprintf(stderr, "Failed to get identify controller\n"); rc = -errno; goto done; } - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .lid = AMZN_NVME_STATS_LOGPAGE_ID, - .nsid = 1, - .lpo = 0, - .lsp = NVME_LOG_LSP_NONE, - .lsi = 0, - .rae = false, - .uuidx = 0, - .csi = NVME_CSI_NVM, - .ot = false, - .log = (void *) &log, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - if (!strncmp((char *)ctrl.mn, AMZN_NVME_LOCAL_STORAGE_PREFIX, strlen(AMZN_NVME_LOCAL_STORAGE_PREFIX))) { - if (nvme_get_nsid(dev_fd(dev), &args.nsid) < 0) { + if (nvme_get_nsid(hdl, &nsid) < 0) { struct nvme_id_ctrl test_ctrl; - if (nvme_identify_ctrl(dev_fd(dev), &test_ctrl) == 0) { - args.nsid = NVME_NSID_ALL; + if (nvme_identify_ctrl(hdl, &test_ctrl) == 0) { + nsid = NVME_NSID_ALL; } else { rc = -errno; goto done; } } - args.len = sizeof(log); + len = sizeof(log); } else { - args.len = sizeof(log.base); + len = sizeof(log.base); } - rc = nvme_get_log(&args); + nvme_init_get_log(&cmd, nsid, AMZN_NVME_STATS_LOGPAGE_ID, NVME_CSI_NVM, + &log, len); + rc = nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); if (rc != 0) { fprintf(stderr, "[ERROR] %s: Failed to get log page, rc = %d\n", __func__, rc); @@ -557,6 +546,5 @@ static int get_stats(int argc, char **argv, struct command *cmd, amzn_print_normal_stats(&log, detail); done: - dev_close(dev); return rc; } diff --git a/plugins/dapustor/dapustor-nvme.c b/plugins/dapustor/dapustor-nvme.c index b98b1a0458..268f45c101 100644 --- a/plugins/dapustor/dapustor-nvme.c +++ b/plugins/dapustor/dapustor-nvme.c @@ -482,24 +482,24 @@ static void show_dapustor_smart_log(struct nvme_additional_smart_log *smart, } static int dapustor_additional_smart_log_data( - int dev_fd, + struct nvme_transport_handle *hdl, struct nvme_additional_smart_log *smart_log, struct nvme_extended_additional_smart_log *ext_smart_log, bool *has_ext) { int err; - err = nvme_get_log_simple(dev_fd, 0xca, sizeof(*smart_log), smart_log); + err = nvme_get_log_simple(hdl, 0xca, smart_log, sizeof(*smart_log)); if (err) { nvme_show_status(err); return err; } - err = nvme_get_log_simple(dev_fd, 0xcb, sizeof(*ext_smart_log), ext_smart_log); + err = nvme_get_log_simple(hdl, 0xcb, ext_smart_log, sizeof(*ext_smart_log)); *has_ext = !err; return 0; } -static int dapustor_additional_smart_log(int argc, char **argv, struct command *cmd, +static int dapustor_additional_smart_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get DapuStor vendor specific additional smart log, and show it."; @@ -509,11 +509,12 @@ static int dapustor_additional_smart_log(int argc, char **argv, struct command * const char *json = "Dump output in json format"; #endif /* CONFIG_JSONC */ - struct nvme_additional_smart_log smart_log; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct nvme_extended_additional_smart_log ext_smart_log; - struct nvme_dev *dev; - int err; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_additional_smart_log smart_log; bool has_ext = false; + int err; struct config { uint32_t namespace_id; @@ -532,24 +533,28 @@ static int dapustor_additional_smart_log(int argc, char **argv, struct command * OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = dapustor_additional_smart_log_data(dev_fd(dev), &smart_log, &ext_smart_log, &has_ext); + err = dapustor_additional_smart_log_data(hdl, &smart_log, + &ext_smart_log, &has_ext); if (!err) { if (cfg.json) show_dapustor_smart_log_jsn(&smart_log, &ext_smart_log, - cfg.namespace_id, dev->name, has_ext); + cfg.namespace_id, + nvme_transport_handle_get_name(hdl), + has_ext); else if (!cfg.raw_binary) show_dapustor_smart_log(&smart_log, &ext_smart_log, - cfg.namespace_id, dev->name, has_ext); + cfg.namespace_id, + nvme_transport_handle_get_name(hdl), has_ext); else { d_raw((unsigned char *)&smart_log, sizeof(smart_log)); if (has_ext) - d_raw((unsigned char *)&ext_smart_log, sizeof(ext_smart_log)); + d_raw((unsigned char *)&ext_smart_log, + sizeof(ext_smart_log)); } } - dev_close(dev); return err; } diff --git a/plugins/dell/dell-nvme.c b/plugins/dell/dell-nvme.c index 8ed10e7fb5..d77138eb2c 100644 --- a/plugins/dell/dell-nvme.c +++ b/plugins/dell/dell-nvme.c @@ -47,8 +47,8 @@ static void dell_id_ctrl(__u8 *vs, struct json_object *root) printf("array_ver : %s\n", array_ver); } -static int id_ctrl(int argc, char **argv, struct command *cmd, +static int id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return __id_ctrl(argc, argv, cmd, plugin, dell_id_ctrl); + return __id_ctrl(argc, argv, acmd, plugin, dell_id_ctrl); } diff --git a/plugins/dera/dera-nvme.c b/plugins/dera/dera-nvme.c index 8a267826f9..f7f20cae47 100644 --- a/plugins/dera/dera-nvme.c +++ b/plugins/dera/dera-nvme.c @@ -95,7 +95,7 @@ enum dera_device_status DEVICE_STAUTS__OVER_TEMPRATURE = 0x09, }; -static int nvme_dera_get_device_status(int fd, enum dera_device_status *result) +static int nvme_dera_get_device_status(struct nvme_transport_handle *hdl, enum dera_device_status *result) { int err = 0; @@ -107,30 +107,31 @@ static int nvme_dera_get_device_status(int fd, enum dera_device_status *result) .cdw12 = 0x104, }; - err = nvme_submit_admin_passthru(fd, &cmd, NULL); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err && result) *result = cmd.result; return err; } -static int get_status(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_status(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - struct nvme_dera_smart_info_log log; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; enum dera_device_status state = DEVICE_STATUS_FATAL_ERROR; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; char *desc = "Get the Dera device status"; - struct nvme_dev *dev; + struct nvme_dera_smart_info_log log; int err; OPT_ARGS(opts) = { OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = nvme_get_log_simple(dev_fd(dev), 0xc0, sizeof(log), &log); + err = nvme_get_log_simple(hdl, 0xc0, &log, sizeof(log)); if (err) goto exit; @@ -152,7 +153,7 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin "Runtime Low", }; - err = nvme_dera_get_device_status(dev_fd(dev), &state); + err = nvme_dera_get_device_status(hdl, &state); if (!err) { if (state > 0 && state < 4) printf("device_status : %s %d%% completed\n", dev_status[state], log.rebuild_percent); @@ -189,7 +190,6 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin if (err > 0) nvme_show_status(err); - dev_close(dev); return err; } diff --git a/plugins/fdp/fdp.c b/plugins/fdp/fdp.c index 1aec7579d6..00ba0335d6 100644 --- a/plugins/fdp/fdp.c +++ b/plugins/fdp/fdp.c @@ -17,18 +17,19 @@ #define CREATE_CMD #include "fdp.h" -static int fdp_configs(int argc, char **argv, struct command *cmd, - struct plugin *plugin) +static int fdp_configs(int argc, char **argv, struct command *acmd, + struct plugin *plugin) { const char *desc = "Get Flexible Data Placement Configurations"; const char *egid = "Endurance group identifier"; const char *human_readable = "show log in readable format"; const char *raw = "use binary output"; - nvme_print_flags_t flags; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_free_ void *log = NULL; struct nvme_fdp_config_log hdr; - void *log = NULL; + nvme_print_flags_t flags; int err; struct config { @@ -52,13 +53,13 @@ static int fdp_configs(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; err = validate_output_format(cfg.output_format, &flags); if (err < 0) - goto out; + return err; if (cfg.raw_binary) flags = BINARY; @@ -68,50 +69,43 @@ static int fdp_configs(int argc, char **argv, struct command *cmd, if (!cfg.egid) { fprintf(stderr, "endurance group identifier required\n"); - err = -EINVAL; - goto out; + return -EINVAL; } - err = nvme_get_log_fdp_configurations(dev->direct.fd, cfg.egid, 0, - sizeof(hdr), &hdr); + err = nvme_get_log_fdp_configurations(hdl, cfg.egid, 0, + &hdr, sizeof(hdr)); if (err) { nvme_show_status(errno); - goto out; + return err; } log = malloc(hdr.size); - if (!log) { - err = -ENOMEM; - goto out; - } + if (!log) + return -ENOMEM; - err = nvme_get_log_fdp_configurations(dev->direct.fd, cfg.egid, 0, - hdr.size, log); + err = nvme_get_log_fdp_configurations(hdl, cfg.egid, 0, log, hdr.size); if (err) { nvme_show_status(errno); - goto out; + return err; } nvme_show_fdp_configs(log, hdr.size, flags); -out: - dev_close(dev); - free(log); - - return err; + return 0; } -static int fdp_usage(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int fdp_usage(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get Flexible Data Placement Reclaim Unit Handle Usage"; const char *egid = "Endurance group identifier"; const char *raw = "use binary output"; - nvme_print_flags_t flags; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_free_ void *log = NULL; struct nvme_fdp_ruhu_log hdr; + nvme_print_flags_t flags; size_t len; - void *log = NULL; int err; struct config { @@ -133,56 +127,51 @@ static int fdp_usage(int argc, char **argv, struct command *cmd, struct plugin * OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; err = validate_output_format(cfg.output_format, &flags); if (err < 0) - goto out; + return err; if (cfg.raw_binary) flags = BINARY; - err = nvme_get_log_reclaim_unit_handle_usage(dev->direct.fd, cfg.egid, - 0, sizeof(hdr), &hdr); + err = nvme_get_log_reclaim_unit_handle_usage(hdl, cfg.egid, + 0, &hdr, sizeof(hdr)); if (err) { nvme_show_status(err); - goto out; + return err; } len = sizeof(hdr) + le16_to_cpu(hdr.nruh) * sizeof(struct nvme_fdp_ruhu_desc); log = malloc(len); - if (!log) { - err = -ENOMEM; - goto out; - } + if (!log) + return -ENOMEM; - err = nvme_get_log_reclaim_unit_handle_usage(dev->direct.fd, cfg.egid, - 0, len, log); + err = nvme_get_log_reclaim_unit_handle_usage(hdl, cfg.egid, + 0, log, len); if (err) { nvme_show_status(err); - goto out; + return err; } nvme_show_fdp_usage(log, len, flags); -out: - dev_close(dev); - free(log); - - return err; + return 0; } -static int fdp_stats(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int fdp_stats(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get Flexible Data Placement Statistics"; const char *egid = "Endurance group identifier"; const char *raw = "use binary output"; - nvme_print_flags_t flags; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct nvme_fdp_stats_log stats; + nvme_print_flags_t flags; int err; struct config { @@ -204,49 +193,46 @@ static int fdp_stats(int argc, char **argv, struct command *cmd, struct plugin * OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; err = validate_output_format(cfg.output_format, &flags); if (err < 0) - goto out; + return err; if (cfg.raw_binary) flags = BINARY; if (!cfg.egid) { fprintf(stderr, "endurance group identifier required\n"); - err = -EINVAL; - goto out; + return -EINVAL; } memset(&stats, 0x0, sizeof(stats)); - err = nvme_get_log_fdp_stats(dev->direct.fd, cfg.egid, 0, sizeof(stats), &stats); + err = nvme_get_log_fdp_stats(hdl, cfg.egid, 0, &stats, sizeof(stats)); if (err) { nvme_show_status(err); - goto out; + return err; } nvme_show_fdp_stats(&stats, flags); -out: - dev_close(dev); - - return err; + return 0; } -static int fdp_events(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int fdp_events(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get Flexible Data Placement Events"; const char *egid = "Endurance group identifier"; const char *host_events = "Get host events"; const char *raw = "use binary output"; - nvme_print_flags_t flags; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct nvme_fdp_events_log events; + nvme_print_flags_t flags; int err; struct config { @@ -271,55 +257,53 @@ static int fdp_events(int argc, char **argv, struct command *cmd, struct plugin OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; err = validate_output_format(cfg.output_format, &flags); if (err < 0) - goto out; + return err; if (cfg.raw_binary) flags = BINARY; if (!cfg.egid) { fprintf(stderr, "endurance group identifier required\n"); - err = -EINVAL; - goto out; + return -EINVAL; } memset(&events, 0x0, sizeof(events)); - err = nvme_get_log_fdp_events(dev->direct.fd, cfg.egid, - cfg.host_events, 0, sizeof(events), &events); + err = nvme_get_log_fdp_events(hdl, cfg.egid, + cfg.host_events, 0, &events, sizeof(events)); if (err) { nvme_show_status(err); - goto out; + return err; } nvme_show_fdp_events(&events, flags); -out: - dev_close(dev); - - return err; + return 0; } -static int fdp_status(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int fdp_status(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Reclaim Unit Handle Status"; const char *namespace_id = "Namespace identifier"; const char *raw = "use binary output"; - nvme_print_flags_t flags; - struct nvme_dev *dev; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_free_ void *buf = NULL; struct nvme_fdp_ruh_status hdr; - size_t len; - void *buf = NULL; + struct nvme_passthru_cmd cmd; + nvme_print_flags_t flags; int err = -1; + size_t len; struct config { - __u32 namespace_id; + __u32 nsid; char *output_format; bool raw_binary; }; @@ -330,76 +314,73 @@ static int fdp_status(int argc, char **argv, struct command *cmd, struct plugin }; OPT_ARGS(opts) = { - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), - OPT_FMT("output-format", 'o', &cfg.output_format, output_format), - OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_UINT("namespace-id", 'n', &cfg.nsid, namespace_id), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; err = validate_output_format(cfg.output_format, &flags); if (err < 0) - goto out; + return err; if (cfg.raw_binary) flags = BINARY; - if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + if (!cfg.nsid) { + err = nvme_get_nsid(hdl, &cfg.nsid); if (err < 0) { perror("get-namespace-id"); - goto out; + return err; } } - err = nvme_fdp_reclaim_unit_handle_status(dev_fd(dev), - cfg.namespace_id, sizeof(hdr), &hdr); + nvme_init_fdp_reclaim_unit_handle_status(&cmd, cfg.nsid, &hdr, + sizeof(hdr)); + err = nvme_submit_io_passthru(hdl, &cmd, NULL); if (err) { nvme_show_status(err); - goto out; + return err; } len = sizeof(struct nvme_fdp_ruh_status) + le16_to_cpu(hdr.nruhsd) * sizeof(struct nvme_fdp_ruh_status_desc); buf = malloc(len); - if (!buf) { - err = -ENOMEM; - goto out; - } + if (!buf) + return -ENOMEM; - err = nvme_fdp_reclaim_unit_handle_status(dev_fd(dev), - cfg.namespace_id, len, buf); + nvme_init_fdp_reclaim_unit_handle_status(&cmd, cfg.nsid, buf, len); + err = nvme_submit_io_passthru(hdl, &cmd, NULL); if (err) { nvme_show_status(err); - goto out; + return err; } nvme_show_fdp_ruh_status(buf, len, flags); -out: - free(buf); - dev_close(dev); - - return err; + return 0; } -static int fdp_update(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int fdp_update(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Reclaim Unit Handle Update"; const char *namespace_id = "Namespace identifier"; const char *_pids = "Comma-separated list of placement identifiers to update"; - struct nvme_dev *dev; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_passthru_cmd cmd; unsigned short pids[256]; __u16 buf[256]; - int npids; int err = -1; + int npids; struct config { - __u32 namespace_id; + __u32 nsid; char *pids; }; @@ -408,171 +389,141 @@ static int fdp_update(int argc, char **argv, struct command *cmd, struct plugin }; OPT_ARGS(opts) = { - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), - OPT_LIST("pids", 'p', &cfg.pids, _pids), + OPT_UINT("namespace-id", 'n', &cfg.nsid, namespace_id), + OPT_LIST("pids", 'p', &cfg.pids, _pids), OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; npids = argconfig_parse_comma_sep_array_short(cfg.pids, pids, ARRAY_SIZE(pids)); if (npids < 0) { perror("could not parse pids"); - err = -EINVAL; - goto out; + return -EINVAL; } else if (npids == 0) { fprintf(stderr, "no placement identifiers set\n"); - err = -EINVAL; - goto out; + return -EINVAL; } - if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + if (!cfg.nsid) { + err = nvme_get_nsid(hdl, &cfg.nsid); if (err < 0) { perror("get-namespace-id"); - goto out; + return err; } } for (unsigned int i = 0; i < npids; i++) buf[i] = cpu_to_le16(pids[i]); - err = nvme_fdp_reclaim_unit_handle_update(dev_fd(dev), cfg.namespace_id, npids, buf); + nvme_init_fdp_reclaim_unit_handle_status(&cmd, cfg.nsid, buf, npids); + err = nvme_submit_io_passthru(hdl, &cmd, NULL); if (err) { nvme_show_status(err); - goto out; + return err; } printf("update: Success\n"); -out: - dev_close(dev); - - return err; + return 0; } -static int fdp_set_events(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int fdp_set_events(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Enable or disable FDP events"; - const char *namespace_id = "Namespace identifier"; + const char *nsid = "Namespace identifier"; const char *enable = "Enable/disable event"; const char *event_types = "Comma-separated list of event types"; const char *ph = "Placement Handle"; - const char *save = "specifies that the controller shall save the attribute"; + const char *sv = "specifies that the controller shall save the attribute"; - struct nvme_dev *dev; - int err = -1; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; unsigned short evts[255]; - int nev; __u8 buf[255]; + int err = -1; + int nev; struct config { - __u32 namespace_id; + __u32 nsid; __u16 ph; char *event_types; bool enable; - bool save; + bool sv; }; struct config cfg = { .enable = false, - .save = false, + .sv = false, }; OPT_ARGS(opts) = { - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), + OPT_UINT("namespace-id", 'n', &cfg.nsid, nsid), OPT_SHRT("placement-handle", 'p', &cfg.ph, ph), OPT_FLAG("enable", 'e', &cfg.enable, enable), - OPT_FLAG("save", 's', &cfg.save, save), + OPT_FLAG("save", 's', &cfg.sv, sv), OPT_LIST("event-types", 't', &cfg.event_types, event_types), OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; nev = argconfig_parse_comma_sep_array_short(cfg.event_types, evts, ARRAY_SIZE(evts)); if (nev < 0) { perror("could not parse event types"); - err = -EINVAL; - goto out; + return -EINVAL; } else if (nev == 0) { fprintf(stderr, "no event types set\n"); - err = -EINVAL; - goto out; + return -EINVAL; } else if (nev > 255) { fprintf(stderr, "too many event types (max 255)\n"); - err = -EINVAL; - goto out; + return -EINVAL; } - if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + if (!cfg.nsid) { + err = nvme_get_nsid(hdl, &cfg.nsid); if (err < 0) { if (errno != ENOTTY) { fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); - goto out; + return err; } - cfg.namespace_id = NVME_NSID_ALL; + cfg.nsid = NVME_NSID_ALL; } } for (unsigned int i = 0; i < nev; i++) buf[i] = (__u8)evts[i]; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = NVME_FEAT_FID_FDP_EVENTS, - .save = cfg.save, - .nsid = cfg.namespace_id, - .cdw11 = (nev << 16) | cfg.ph, - .cdw12 = cfg.enable ? 0x1 : 0x0, - .data_len = sizeof(buf), - .data = buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - - err = nvme_set_features(&args); + err = nvme_set_features(hdl, cfg.nsid, NVME_FEAT_FID_FDP_EVENTS, cfg.sv, + (nev << 16) | cfg.ph, cfg.enable ? 0x1 : 0x0, + 0, 0, 0, buf, sizeof(buf), NULL); if (err) { nvme_show_status(err); - goto out; + return err;; } printf("set-events: Success\n"); -out: - dev_close(dev); - - return err; + return 0; } -static int fdp_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int fdp_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Show, enable or disable FDP configuration"; const char *enable_conf_idx = "FDP configuration index to enable"; const char *endurance_group = "Endurance group ID"; const char *disable = "Disable current FDP configuration"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - int err = -1; - __u32 result; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; bool enabling_conf_idx = false; - struct nvme_set_features_args setf_args = { - .args_size = sizeof(setf_args), - .fd = -1, - .fid = NVME_FEAT_FID_FDP, - .save = 1, - .nsid = NVME_NSID_ALL, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - }; + __u32 result; + int err = -1; struct config { bool disable; @@ -594,7 +545,7 @@ static int fdp_feature(int argc, char **argv, struct command *cmd, struct plugin OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -605,23 +556,11 @@ static int fdp_feature(int argc, char **argv, struct command *cmd, struct plugin } if (!enabling_conf_idx && !cfg.disable) { - struct nvme_get_features_args getf_args = { - .args_size = sizeof(getf_args), - .fd = dev_fd(dev), - .fid = NVME_FEAT_FID_FDP, - .nsid = NVME_NSID_ALL, - .sel = NVME_GET_FEATURES_SEL_CURRENT, - .cdw11 = cfg.endgid, - .uuidx = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - nvme_show_result("Endurance Group : %d", cfg.endgid); - err = nvme_get_features(&getf_args); + err = nvme_get_features(hdl, NVME_NSID_ALL, NVME_FEAT_FID_FDP, + NVME_GET_FEATURES_SEL_CURRENT, cfg.endgid, 0, + NULL, 0, &result); if (err) { nvme_show_status(err); return err; @@ -634,11 +573,9 @@ static int fdp_feature(int argc, char **argv, struct command *cmd, struct plugin return err; } - setf_args.fd = dev_fd(dev); - setf_args.cdw11 = cfg.endgid; - setf_args.cdw12 = cfg.fdpcidx << 8 | (!cfg.disable); - - err = nvme_set_features(&setf_args); + err = nvme_set_features(hdl, NVME_NSID_ALL, NVME_FEAT_FID_FDP, 1, cfg.endgid, + cfg.fdpcidx << 8 | (!cfg.disable), + 0, 0, 0, NULL, 0, NULL); if (err) { nvme_show_status(err); return err; diff --git a/plugins/feat/feat-nvme.c b/plugins/feat/feat-nvme.c index b2de2926e2..e7b7607279 100644 --- a/plugins/feat/feat-nvme.c +++ b/plugins/feat/feat-nvme.c @@ -49,7 +49,8 @@ static const char *temp_thresh_feat = "temperature threshold feature"; static const char *arbitration_feat = "arbitration feature"; static const char *volatile_wc_feat = "volatile write cache feature"; -static int feat_get(struct nvme_dev *dev, const __u8 fid, __u32 cdw11, __u8 sel, const char *feat) +static int feat_get(struct nvme_transport_handle *hdl, const __u8 fid, + __u32 cdw11, __u8 sel, const char *feat) { __u32 result; int err; @@ -58,7 +59,7 @@ static int feat_get(struct nvme_dev *dev, const __u8 fid, __u32 cdw11, __u8 sel, _cleanup_free_ void *buf = NULL; if (!NVME_CHECK(sel, GET_FEATURES_SEL, SUPPORTED)) - nvme_get_feature_length(fid, cdw11, &len); + nvme_get_feature_length(fid, cdw11, NVME_DATA_TFR_CTRL_TO_HOST, &len); if (len) { buf = nvme_alloc(len - 1); @@ -66,19 +67,7 @@ static int feat_get(struct nvme_dev *dev, const __u8 fid, __u32 cdw11, __u8 sel, return -ENOMEM; } - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .sel = sel, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - .cdw11 = cdw11, - .data = buf, - .data_len = len, - }; - - err = nvme_get_features(&args); + err = nvme_get_features(hdl, 0, fid, sel, cdw11, 0, buf, len, &result); nvme_show_init(); @@ -99,22 +88,15 @@ static int feat_get(struct nvme_dev *dev, const __u8 fid, __u32 cdw11, __u8 sel, return err; } -static int power_mgmt_set(struct nvme_dev *dev, const __u8 fid, __u8 ps, __u8 wh, bool save) +static int power_mgmt_set(struct nvme_transport_handle *hdl, const __u8 fid, + __u8 ps, __u8 wh, bool sv) { + __u32 cdw11 = NVME_SET(ps, FEAT_PWRMGMT_PS) | NVME_SET(wh, FEAT_PWRMGMT_WH); __u32 result; int err; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .cdw11 = NVME_SET(ps, FEAT_PWRMGMT_PS) | NVME_SET(wh, FEAT_PWRMGMT_WH), - .save = save, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 0, fid, sv, cdw11, 0, 0, 0, 0, NULL, 0, + &result); nvme_show_init(); @@ -123,9 +105,9 @@ static int power_mgmt_set(struct nvme_dev *dev, const __u8 fid, __u8 ps, __u8 wh } else if (err < 0) { nvme_show_perror("Set %s", power_mgmt_feat); } else { - nvme_show_result("Set %s: 0x%04x (%s)", power_mgmt_feat, args.cdw11, - save ? "Save" : "Not save"); - nvme_feature_show_fields(fid, args.cdw11, NULL); + nvme_show_result("Set %s: 0x%04x (%s)", power_mgmt_feat, cdw11, + sv ? "Save" : "Not save"); + nvme_feature_show_fields(fid, cdw11, NULL); } nvme_show_finish(); @@ -133,13 +115,14 @@ static int power_mgmt_set(struct nvme_dev *dev, const __u8 fid, __u8 ps, __u8 wh return err; } -static int feat_power_mgmt(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int feat_power_mgmt(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *ps = "power state"; const char *wh = "workload hint"; const __u8 fid = NVME_FEAT_FID_POWER_MGMT; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; struct config { @@ -154,20 +137,20 @@ static int feat_power_mgmt(int argc, char **argv, struct command *cmd, struct pl OPT_BYTE("ps", 'p', &cfg.ps, ps), OPT_BYTE("wh", 'w', &cfg.wh, wh)); - err = parse_and_open(&dev, argc, argv, POWER_MGMT_DESC, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, POWER_MGMT_DESC, opts); if (err) return err; if (argconfig_parse_seen(opts, "ps")) - err = power_mgmt_set(dev, fid, cfg.ps, cfg.wh, argconfig_parse_seen(opts, "save")); + err = power_mgmt_set(hdl, fid, cfg.ps, cfg.wh, argconfig_parse_seen(opts, "save")); else - err = feat_get(dev, fid, 0, cfg.sel, power_mgmt_feat); + err = feat_get(hdl, fid, 0, cfg.sel, power_mgmt_feat); return err; } -static int perfc_set(struct nvme_dev *dev, __u8 fid, __u32 cdw11, struct perfc_config *cfg, - bool save) +static int perfc_set(struct nvme_transport_handle *hdl, __u8 fid, __u32 cdw11, + struct perfc_config *cfg, bool sv) { __u32 result; int err; @@ -178,18 +161,6 @@ static int perfc_set(struct nvme_dev *dev, __u8 fid, __u32 cdw11, struct perfc_c .attr_buf = { 0 }, }; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .cdw11 = cdw11, - .save = save, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - .data = &data, - .data_len = sizeof(data), - }; - switch (cfg->attri) { case NVME_FEAT_PERFC_ATTRI_STD: data.std_perf->r4karl = cfg->r4karl; @@ -216,7 +187,8 @@ static int perfc_set(struct nvme_dev *dev, __u8 fid, __u32 cdw11, struct perfc_c break; } - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 0, fid, sv, cdw11, 0, 0, 0, 0, &data, + sizeof(data), &result); nvme_show_init(); @@ -225,9 +197,9 @@ static int perfc_set(struct nvme_dev *dev, __u8 fid, __u32 cdw11, struct perfc_c } else if (err < 0) { nvme_show_perror("Set %s", perfc_feat); } else { - nvme_show_result("Set %s: 0x%04x (%s)", perfc_feat, args.cdw11, - save ? "Save" : "Not save"); - nvme_feature_show_fields(args.fid, args.cdw11, NULL); + nvme_show_result("Set %s: 0x%04x (%s)", perfc_feat, cdw11, + sv ? "Save" : "Not save"); + nvme_feature_show_fields(fid, cdw11, NULL); } nvme_show_finish(); @@ -235,7 +207,7 @@ static int perfc_set(struct nvme_dev *dev, __u8 fid, __u32 cdw11, struct perfc_c return err; } -static int feat_perfc(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int feat_perfc(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *namespace_id_optional = "optional namespace attached to controller"; const char *attri = "attribute index"; @@ -245,7 +217,8 @@ static int feat_perfc(int argc, char **argv, struct command *cmd, struct plugin const char *attrl = "attribute length"; const char *vs_data = "vendor specific data"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; __u8 fid = NVME_FEAT_FID_PERF_CHARACTERISTICS; __u32 cdw11; @@ -261,7 +234,7 @@ static int feat_perfc(int argc, char **argv, struct command *cmd, struct plugin OPT_SHRT("attrl", 'A', &cfg.attrl, attrl), OPT_FILE("vs-data", 'V', &cfg.vs_data, vs_data)); - err = parse_and_open(&dev, argc, argv, PERFC_DESC, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, PERFC_DESC, opts); if (err) return err; @@ -269,29 +242,23 @@ static int feat_perfc(int argc, char **argv, struct command *cmd, struct plugin if (argconfig_parse_seen(opts, "rvspa") || argconfig_parse_seen(opts, "r4karl") || argconfig_parse_seen(opts, "paid")) - err = perfc_set(dev, fid, cdw11, &cfg, argconfig_parse_seen(opts, "save")); + err = perfc_set(hdl, fid, cdw11, &cfg, argconfig_parse_seen(opts, "save")); else - err = feat_get(dev, fid, cdw11, cfg.sel, perfc_feat); + err = feat_get(hdl, fid, cdw11, cfg.sel, perfc_feat); return err; } -static int hctm_set(struct nvme_dev *dev, const __u8 fid, __u16 tmt1, __u16 tmt2, bool save) +static int hctm_set(struct nvme_transport_handle *hdl, const __u8 fid, + __u16 tmt1, __u16 tmt2, bool sv) { + __u32 cdw11 = NVME_SET(tmt1, FEAT_HCTM_TMT1) + | NVME_SET(tmt2, FEAT_HCTM_TMT2); __u32 result; int err; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .cdw11 = NVME_SET(tmt1, FEAT_HCTM_TMT1) | NVME_SET(tmt2, FEAT_HCTM_TMT2), - .save = save, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 0, fid, sv, cdw11, 0, 0, 0, 0, NULL, 0, + &result); nvme_show_init(); @@ -300,9 +267,9 @@ static int hctm_set(struct nvme_dev *dev, const __u8 fid, __u16 tmt1, __u16 tmt2 } else if (err < 0) { nvme_show_perror("Set %s", hctm_feat); } else { - nvme_show_result("Set %s: 0x%04x (%s)", hctm_feat, args.cdw11, - save ? "Save" : "Not save"); - nvme_feature_show_fields(fid, args.cdw11, NULL); + nvme_show_result("Set %s: 0x%04x (%s)", hctm_feat, cdw11, + sv ? "Save" : "Not save"); + nvme_feature_show_fields(fid, cdw11, NULL); } nvme_show_finish(); @@ -310,11 +277,12 @@ static int hctm_set(struct nvme_dev *dev, const __u8 fid, __u16 tmt1, __u16 tmt2 return err; } -static int feat_hctm(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int feat_hctm(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const __u8 fid = NVME_FEAT_FID_HCTM; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; struct config { @@ -329,39 +297,30 @@ static int feat_hctm(int argc, char **argv, struct command *cmd, struct plugin * OPT_SHRT("tmt1", 't', &cfg.tmt1, TMT(1)), OPT_SHRT("tmt2", 'T', &cfg.tmt2, TMT(2))); - err = parse_and_open(&dev, argc, argv, HCTM_DESC, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, HCTM_DESC, opts); if (err) return err; if (argconfig_parse_seen(opts, "tmt1") || argconfig_parse_seen(opts, "tmt2")) - err = hctm_set(dev, fid, cfg.tmt1, cfg.tmt2, argconfig_parse_seen(opts, "save")); + err = hctm_set(hdl, fid, cfg.tmt1, cfg.tmt2, argconfig_parse_seen(opts, "save")); else - err = feat_get(dev, fid, 0, cfg.sel, hctm_feat); + err = feat_get(hdl, fid, 0, cfg.sel, hctm_feat); return err; } -static int timestamp_set(struct nvme_dev *dev, const __u8 fid, __u64 tstmp, bool save) +static int timestamp_set(struct nvme_transport_handle *hdl, const __u8 fid, + __u64 tstmp, bool sv) { __u32 result; int err; struct nvme_timestamp ts; __le64 timestamp = cpu_to_le64(tstmp); - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .save = save, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - .data = &ts, - .data_len = sizeof(ts), - }; - memcpy(ts.timestamp, ×tamp, sizeof(ts.timestamp)); - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 0, fid, sv, 0, 0, 0, 0, 0, &ts, sizeof(ts), + &result); nvme_show_init(); @@ -370,8 +329,8 @@ static int timestamp_set(struct nvme_dev *dev, const __u8 fid, __u64 tstmp, bool } else if (err < 0) { nvme_show_perror("Set %s", timestamp_feat); } else { - nvme_show_result("Set %s: (%s)", timestamp_feat, save ? "Save" : "Not save"); - nvme_feature_show_fields(fid, args.cdw11, args.data); + nvme_show_result("Set %s: (%s)", timestamp_feat, sv ? "Save" : "Not save"); + nvme_feature_show_fields(fid, 0, (unsigned char *)&ts); } nvme_show_finish(); @@ -379,12 +338,13 @@ static int timestamp_set(struct nvme_dev *dev, const __u8 fid, __u64 tstmp, bool return err; } -static int feat_timestamp(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int feat_timestamp(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const __u8 fid = NVME_FEAT_FID_TIMESTAMP; const char *tstmp = "timestamp"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; struct config { @@ -396,34 +356,37 @@ static int feat_timestamp(int argc, char **argv, struct command *cmd, struct plu FEAT_ARGS(opts, OPT_LONG("tstmp", 't', &cfg.tstmp, tstmp)); - err = parse_and_open(&dev, argc, argv, TIMESTAMP_DESC, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, TIMESTAMP_DESC, opts); if (err) return err; if (argconfig_parse_seen(opts, "tstmp")) - err = timestamp_set(dev, fid, cfg.tstmp, argconfig_parse_seen(opts, "save")); + err = timestamp_set(hdl, fid, cfg.tstmp, argconfig_parse_seen(opts, "save")); else - err = feat_get(dev, fid, 0, cfg.sel, timestamp_feat); + err = feat_get(hdl, fid, 0, cfg.sel, timestamp_feat); return err; } -static int temp_thresh_set(int fd, const __u8 fid, struct argconfig_commandline_options *opts, +static int temp_thresh_set(struct nvme_transport_handle *hdl, const __u8 fid, + struct argconfig_commandline_options *opts, struct temp_thresh_config *cfg) { __u32 result; int err; enum nvme_get_features_sel sel = NVME_GET_FEATURES_SEL_CURRENT; + struct nvme_passthru_cmd cmd; __u16 tmpth; __u8 tmpsel; __u8 thsel; __u8 tmpthh; - bool save = argconfig_parse_seen(opts, "save"); + bool sv = argconfig_parse_seen(opts, "save"); - if (save) + if (sv) sel = NVME_GET_FEATURES_SEL_SAVED; - err = nvme_get_features_temp_thresh2(fd, sel, cfg->tmpsel, cfg->thsel, &result); + nvme_init_get_features_temp_thresh(&cmd, sel, cfg->tmpsel, cfg->thsel); + err = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!err) { nvme_feature_decode_temp_threshold(result, &tmpth, &tmpsel, &thsel, &tmpthh); if (!argconfig_parse_seen(opts, "tmpth")) @@ -432,8 +395,9 @@ static int temp_thresh_set(int fd, const __u8 fid, struct argconfig_commandline_ cfg->tmpthh = tmpthh; } - err = nvme_set_features_temp_thresh2(fd, cfg->tmpth, cfg->tmpsel, cfg->thsel, cfg->tmpthh, - save, &result); + nvme_init_set_features_temp_thresh(&cmd, sv, cfg->tmpth, cfg->tmpsel, + cfg->thsel, cfg->tmpthh); + err = nvme_submit_admin_passthru(hdl, &cmd, &result); nvme_show_init(); @@ -442,7 +406,7 @@ static int temp_thresh_set(int fd, const __u8 fid, struct argconfig_commandline_ } else if (err < 0) { nvme_show_perror("Set %s", temp_thresh_feat); } else { - nvme_show_result("Set %s: (%s)", temp_thresh_feat, save ? "Save" : "Not save"); + nvme_show_result("Set %s: (%s)", temp_thresh_feat, sv ? "Save" : "Not save"); nvme_feature_show_fields(fid, NVME_SET(cfg->tmpth, FEAT_TT_TMPTH) | NVME_SET(cfg->tmpsel, FEAT_TT_TMPSEL) | NVME_SET(cfg->thsel, FEAT_TT_THSEL) | @@ -454,7 +418,7 @@ static int temp_thresh_set(int fd, const __u8 fid, struct argconfig_commandline_ return err; } -static int feat_temp_thresh(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int feat_temp_thresh(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const __u8 fid = NVME_FEAT_FID_TEMP_THRESH; const char *tmpth = "temperature threshold"; @@ -462,7 +426,8 @@ static int feat_temp_thresh(int argc, char **argv, struct command *cmd, struct p const char *thsel = "threshold type select"; const char *tmpthh = "temperature threshold hysteresis"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; struct temp_thresh_config cfg = { 0 }; @@ -473,32 +438,35 @@ static int feat_temp_thresh(int argc, char **argv, struct command *cmd, struct p OPT_BYTE("thsel", 'H', &cfg.thsel, thsel), OPT_BYTE("tmpthh", 'M', &cfg.tmpthh, tmpthh)); - err = parse_and_open(&dev, argc, argv, TEMP_THRESH_DESC, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, TEMP_THRESH_DESC, opts); if (err) return err; if (argconfig_parse_seen(opts, "tmpth") || argconfig_parse_seen(opts, "tmpthh")) - err = temp_thresh_set(dev_fd(dev), fid, opts, &cfg); + err = temp_thresh_set(hdl, fid, opts, &cfg); else - err = feat_get(dev, fid, NVME_SET(cfg.tmpsel, FEAT_TT_TMPSEL) | + err = feat_get(hdl, fid, NVME_SET(cfg.tmpsel, FEAT_TT_TMPSEL) | NVME_SET(cfg.thsel, FEAT_TT_THSEL), cfg.sel, temp_thresh_feat); return err; } -static int arbitration_set(int fd, const __u8 fid, struct argconfig_commandline_options *opts, +static int arbitration_set(struct nvme_transport_handle *hdl, const __u8 fid, + struct argconfig_commandline_options *opts, struct arbitration_config *cfg) { enum nvme_get_features_sel sel = NVME_GET_FEATURES_SEL_CURRENT; - bool save = argconfig_parse_seen(opts, "save"); + bool sv = argconfig_parse_seen(opts, "save"); + struct nvme_passthru_cmd cmd; __u8 ab, lpw, mpw, hpw; __u32 result; int err; - if (save) + if (sv) sel = NVME_GET_FEATURES_SEL_SAVED; - err = nvme_get_features_arbitration(fd, sel, &result); + nvme_init_get_features_arbitration(&cmd, sel); + err = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!err) { nvme_feature_decode_arbitration(result, &ab, &lpw, &mpw, &hpw); if (!argconfig_parse_seen(opts, "ab")) @@ -511,8 +479,9 @@ static int arbitration_set(int fd, const __u8 fid, struct argconfig_commandline_ cfg->hpw = hpw; } - err = nvme_set_features_arbitration(fd, cfg->ab, cfg->lpw, cfg->mpw, cfg->hpw, - save, &result); + nvme_init_set_features_arbitration(&cmd, sv, cfg->ab, cfg->lpw, + cfg->mpw, cfg->hpw); + err = nvme_submit_admin_passthru(hdl, &cmd, &result); nvme_show_init(); @@ -521,7 +490,7 @@ static int arbitration_set(int fd, const __u8 fid, struct argconfig_commandline_ } else if (err < 0) { nvme_show_perror("Set %s", temp_thresh_feat); } else { - nvme_show_result("Set %s: (%s)", arbitration_feat, save ? "Save" : "Not save"); + nvme_show_result("Set %s: (%s)", arbitration_feat, sv ? "Save" : "Not save"); nvme_feature_show_fields(fid, NVME_SET(cfg->ab, FEAT_ARBITRATION_BURST) | NVME_SET(cfg->lpw, FEAT_ARBITRATION_LPW) | NVME_SET(cfg->mpw, FEAT_ARBITRATION_MPW) | @@ -533,16 +502,17 @@ static int arbitration_set(int fd, const __u8 fid, struct argconfig_commandline_ return err; } -static int feat_arbitration(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int feat_arbitration(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const __u8 fid = NVME_FEAT_FID_ARBITRATION; const char *ab = "arbitration burst"; const char *lpw = "low priority weight"; const char *mpw = "medium priority weight"; const char *hpw = "high priority weight"; - int err; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + int err; struct arbitration_config cfg = { 0 }; @@ -552,32 +522,25 @@ static int feat_arbitration(int argc, char **argv, struct command *cmd, struct p OPT_BYTE("mpw", 'm', &cfg.mpw, mpw), OPT_BYTE("hpw", 'H', &cfg.hpw, hpw)); - err = parse_and_open(&dev, argc, argv, TEMP_THRESH_DESC, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, TEMP_THRESH_DESC, opts); if (err) return err; if (argc == 2 || argconfig_parse_seen(opts, "sel")) - return feat_get(dev, fid, 0, cfg.sel, "arbitration feature"); + return feat_get(hdl, fid, 0, cfg.sel, "arbitration feature"); - return arbitration_set(dev_fd(dev), fid, opts, &cfg); + return arbitration_set(hdl, fid, opts, &cfg); } -static int volatile_wc_set(struct nvme_dev *dev, const __u8 fid, bool wce, bool save) +static int volatile_wc_set(struct nvme_transport_handle *hdl, const __u8 fid, + bool wce, bool sv) { + __u32 cdw11 = NVME_SET(wce, FEAT_VWC_WCE); __u32 result; int err; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .cdw11 = NVME_SET(wce, FEAT_VWC_WCE), - .save = save, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 0, fid, sv, cdw11, 0, 0, 0, 0, NULL, 0, + &result); nvme_show_init(); @@ -586,9 +549,9 @@ static int volatile_wc_set(struct nvme_dev *dev, const __u8 fid, bool wce, bool } else if (err < 0) { nvme_show_perror("Set %s", volatile_wc_feat); } else { - nvme_show_result("Set %s: 0x%04x (%s)", volatile_wc_feat, args.cdw11, - save ? "Save" : "Not save"); - nvme_feature_show_fields(fid, args.cdw11, NULL); + nvme_show_result("Set %s: 0x%04x (%s)", volatile_wc_feat, cdw11, + sv ? "Save" : "Not save"); + nvme_feature_show_fields(fid, cdw11, NULL); } nvme_show_finish(); @@ -596,12 +559,13 @@ static int volatile_wc_set(struct nvme_dev *dev, const __u8 fid, bool wce, bool return err; } -static int feat_volatile_wc(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int feat_volatile_wc(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const __u8 fid = NVME_FEAT_FID_VOLATILE_WC; const char *wce = "volatile write cache enable"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; struct config { @@ -613,14 +577,14 @@ static int feat_volatile_wc(int argc, char **argv, struct command *cmd, struct p FEAT_ARGS(opts, OPT_FLAG("wce", 'w', &cfg.wce, wce)); - err = parse_and_open(&dev, argc, argv, VOLATILE_WC_DESC, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, VOLATILE_WC_DESC, opts); if (err) return err; if (argconfig_parse_seen(opts, "wce")) - err = volatile_wc_set(dev, fid, cfg.wce, argconfig_parse_seen(opts, "save")); + err = volatile_wc_set(hdl, fid, cfg.wce, argconfig_parse_seen(opts, "save")); else - err = feat_get(dev, fid, 0, cfg.sel, volatile_wc_feat); + err = feat_get(hdl, fid, 0, cfg.sel, volatile_wc_feat); return err; } diff --git a/plugins/huawei/huawei-nvme.c b/plugins/huawei/huawei-nvme.c index 5de0d3bd9b..8ae01c49c1 100644 --- a/plugins/huawei/huawei-nvme.c +++ b/plugins/huawei/huawei-nvme.c @@ -64,15 +64,16 @@ struct huawei_list_element_len { unsigned int array_name; }; -static int huawei_get_nvme_info(int fd, struct huawei_list_item *item, const char *node) +static int huawei_get_nvme_info(struct nvme_transport_handle *hdl, + struct huawei_list_item *item, const char *node) { + struct stat nvme_stat_info; int err; int len; - struct stat nvme_stat_info; memset(item, 0, sizeof(*item)); - err = nvme_identify_ctrl(fd, &item->ctrl); + err = nvme_identify_ctrl(hdl, &item->ctrl); if (err) return err; @@ -84,12 +85,12 @@ static int huawei_get_nvme_info(int fd, struct huawei_list_item *item, const cha } item->huawei_device = true; - err = nvme_get_nsid(fd, &item->nsid); - err = nvme_identify_ns(fd, item->nsid, &item->ns); + err = nvme_get_nsid(hdl, &item->nsid); + err = nvme_identify_ns(hdl, item->nsid, &item->ns); if (err) return err; - err = fstat(fd, &nvme_stat_info); + err = fstat(nvme_transport_handle_get_fd(hdl), &nvme_stat_info); if (err < 0) return err; @@ -290,9 +291,11 @@ static void huawei_print_list_items(struct huawei_list_item *list_items, unsigne huawei_print_list_item(&list_items[i], element_len); } -static int huawei_list(int argc, char **argv, struct command *command, - struct plugin *plugin) +static int huawei_list(int argc, char **argv, struct command *acmd, + struct plugin *plugin) { + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = + nvme_create_global_ctx(stdout, DEFAULT_LOGLEVEL); char path[264]; struct dirent **devices; struct huawei_list_item *list_items; @@ -313,6 +316,9 @@ static int huawei_list(int argc, char **argv, struct command *command, OPT_END() }; + if (!ctx) + return -ENOMEM; + ret = argconfig_parse(argc, argv, desc, opts); if (ret) return ret; @@ -333,23 +339,21 @@ static int huawei_list(int argc, char **argv, struct command *command, } for (i = 0; i < n; i++) { - int fd; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; snprintf(path, sizeof(path), "/dev/%s", devices[i]->d_name); - fd = open(path, O_RDONLY); - if (fd < 0) { + ret = nvme_open(ctx, path, &hdl); + if (ret) { fprintf(stderr, "Cannot open device %s: %s\n", - path, strerror(errno)); + path, strerror(-ret)); continue; } - ret = huawei_get_nvme_info(fd, &list_items[huawei_num], path); - if (ret) { - close(fd); + ret = huawei_get_nvme_info(hdl, &list_items[huawei_num], path); + if (ret) goto out_free_list_items; - } + if (list_items[huawei_num].huawei_device == true) huawei_num++; - close(fd); } if (huawei_num > 0) { @@ -381,7 +385,7 @@ static void huawei_do_id_ctrl(__u8 *vs, struct json_object *root) printf("array name : %s\n", strlen(array_name) > 1 ? array_name : "NULL"); } -static int huawei_id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int huawei_id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return __id_ctrl(argc, argv, cmd, plugin, huawei_do_id_ctrl); + return __id_ctrl(argc, argv, acmd, plugin, huawei_do_id_ctrl); } diff --git a/plugins/ibm/ibm-nvme.c b/plugins/ibm/ibm-nvme.c index 990dc70de8..d0c2107ce9 100644 --- a/plugins/ibm/ibm-nvme.c +++ b/plugins/ibm/ibm-nvme.c @@ -223,8 +223,9 @@ static int get_ibm_addi_smart_log(int argc, char **argv, struct command *cmd, st const char *desc = "Get IBM specific additional smart log and show it."; const char *raw = "Dump output in binary format"; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct nvme_ibm_additional_smart_log smart_log; - struct nvme_dev *dev; int err; struct config { @@ -240,15 +241,16 @@ static int get_ibm_addi_smart_log(int argc, char **argv, struct command *cmd, st OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = nvme_get_log_simple(dev_fd(dev), 0xf0, sizeof(smart_log), &smart_log); + err = nvme_get_log_simple(hdl, 0xf0, &smart_log, sizeof(smart_log)); if (!err) { if (!cfg.raw_binary) - show_ibm_smart_log(&smart_log, dev->name); + show_ibm_smart_log(&smart_log, + nvme_transport_handle_get_name(hdl)); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); } else if (err > 0) @@ -256,7 +258,6 @@ static int get_ibm_addi_smart_log(int argc, char **argv, struct command *cmd, st else nvme_show_error("ibm additional smart log: %s\n", nvme_strerror(errno)); - dev_close(dev); return err; } @@ -351,9 +352,10 @@ static void show_ibm_vpd_log(struct nvme_ibm_vpd_log *vpd, const char *devname) static int get_ibm_vpd_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct nvme_ibm_vpd_log vpd_log; int err; - struct nvme_dev *dev; const char *desc = "Get IBM vendor specific VPD log"; const char *raw = "dump output in binary format"; @@ -371,16 +373,17 @@ static int get_ibm_vpd_log(int argc, char **argv, struct command *cmd, struct pl OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err < 0) return err; bzero(&vpd_log, sizeof(vpd_log)); - err = nvme_get_log_simple(dev_fd(dev), 0xf1, sizeof(vpd_log), &vpd_log); + err = nvme_get_log_simple(hdl, 0xf1, &vpd_log, sizeof(vpd_log)); if (!err) { if (!cfg.raw_binary) - show_ibm_vpd_log(&vpd_log, dev->name); + show_ibm_vpd_log(&vpd_log, + nvme_transport_handle_get_name(hdl)); else d_raw((unsigned char *)&vpd_log, sizeof(vpd_log)); } else if (err > 0) @@ -388,7 +391,6 @@ static int get_ibm_vpd_log(int argc, char **argv, struct command *cmd, struct pl else nvme_show_error("ibm vpd log: %s\n", nvme_strerror(errno)); - dev_close(dev); return err; } @@ -525,10 +527,11 @@ static int get_ibm_persistent_event_log(int argc, char **argv, const char *action = "action the controller shall take during " "processing this persistent log page command."; const char *log_len = "number of bytes to retrieve"; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct nvme_persistent_event_log pevent_log; void *pevent_log_info = NULL; enum nvme_print_flags flags; - struct nvme_dev *dev; __u32 log_length = 0; int err = 0; @@ -554,28 +557,28 @@ static int get_ibm_persistent_event_log(int argc, char **argv, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) - goto ret; + return err; err = flags = validate_output_format(cfg.output_format, &flags); if (flags < 0) - goto close_dev; + return err; if (cfg.raw_binary) flags = BINARY; /* get persistent event log */ - err = nvme_get_log_persistent_event(dev_fd(dev), NVME_PEVENT_LOG_RELEASE_CTX, - sizeof(pevent_log), &pevent_log); + err = nvme_get_log_persistent_event(hdl, NVME_PEVENT_LOG_RELEASE_CTX, + &pevent_log, sizeof(pevent_log)); if (err) return err; memset(&pevent_log, 0, sizeof(pevent_log)); - err = nvme_get_log_persistent_event(dev_fd(dev), NVME_PEVENT_LOG_EST_CTX_AND_READ, - sizeof(pevent_log), &pevent_log); + err = nvme_get_log_persistent_event(hdl, NVME_PEVENT_LOG_EST_CTX_AND_READ, + &pevent_log, sizeof(pevent_log)); if (err) { fprintf(stderr, "Setting persistent event log read ctx failed (ignored)!\n"); return err; @@ -588,15 +591,13 @@ static int get_ibm_persistent_event_log(int argc, char **argv, return err; } - err = nvme_get_log_persistent_event(dev_fd(dev), NVME_PEVENT_LOG_READ, - log_length, pevent_log_info); + err = nvme_get_log_persistent_event(hdl, NVME_PEVENT_LOG_READ, + pevent_log_info, log_length); if (!err) { nvme_show_ibm_persistent_event_log(pevent_log_info, cfg.action, - log_length, dev->name, flags); + log_length, nvme_transport_handle_get_name(hdl), + flags); } -close_dev: - dev_close(dev); -ret: return err; } diff --git a/plugins/innogrit/innogrit-nvme.c b/plugins/innogrit/innogrit-nvme.c index 9e7be483e2..1182c27987 100644 --- a/plugins/innogrit/innogrit-nvme.c +++ b/plugins/innogrit/innogrit-nvme.c @@ -12,13 +12,15 @@ #include "libnvme.h" #include "nvme-print.h" #include "typedef.h" +#include "util/cleanup.h" #define CREATE_CMD #include "innogrit-nvme.h" -static int nvme_vucmd(int fd, unsigned char opcode, unsigned int cdw12, - unsigned int cdw13, unsigned int cdw14, - unsigned int cdw15, char *data, int data_len) +static int nvme_vucmd(struct nvme_transport_handle *hdl, unsigned char opcode, + unsigned int cdw12, unsigned int cdw13, + unsigned int cdw14, unsigned int cdw15, char *data, + int data_len) { struct nvme_passthru_cmd cmd; @@ -33,33 +35,25 @@ static int nvme_vucmd(int fd, unsigned char opcode, unsigned int cdw12, cmd.nsid = 0xffffffff; cmd.addr = (__u64)(__u64)(uintptr_t)data; cmd.data_len = data_len; - return nvme_submit_admin_passthru(fd, &cmd, NULL); + return nvme_submit_admin_passthru(hdl, &cmd, NULL); } -int getlogpage(struct nvme_dev *dev, unsigned char ilogid, unsigned char ilsp, - char *data, int data_len, unsigned int *result) +static int getlogpage(struct nvme_transport_handle *hdl, unsigned char ilogid, + unsigned char ilsp, char *data, int data_len, + unsigned int *result) { - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .lid = ilogid, - .nsid = 0xffffffff, - .lpo = 0, - .lsp = ilsp, - .lsi = 0, - .rae = true, - .uuidx = 0, - .csi = NVME_CSI_NVM, - .ot = false, - .len = data_len, - .log = (void *)data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - return nvme_get_log(&args); + struct nvme_passthru_cmd cmd; + + nvme_init_get_log(&cmd, NVME_NSID_ALL, ilogid, NVME_CSI_NVM, + data, data_len); + cmd.cdw10 |= NVME_FIELD_ENCODE(ilsp, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + + return nvme_get_log(hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, result); } -int getvsctype(struct nvme_dev *dev) +static int getvsctype(struct nvme_transport_handle *hdl) { unsigned char ilogid; char data[4096]; @@ -68,28 +62,29 @@ int getvsctype(struct nvme_dev *dev) memset(data, 0, 4096); // pdrvinfo by getlogpage for (ilogid = 0xe1; ilogid < 0xe2; ilogid++) { - getlogpage(dev, ilogid, 0, data, 4096, NULL); + getlogpage(hdl, ilogid, 0, data, 4096, NULL); if (pdrvinfo->signature == 0x5A) return 1; } //pdrvinfo by vucmd - nvme_vucmd(dev_fd(dev), 0xfe, 0x82, 0X03, 0x00, 0, (char *)data, 4096); + nvme_vucmd(hdl, 0xfe, 0x82, 0X03, 0x00, 0, (char *)data, 4096); if (pdrvinfo->signature == 0x5A) return 1; return 0; } -int getvsc_eventlog(struct nvme_dev *dev, FILE *fp) +static int getvsc_eventlog(struct nvme_transport_handle *hdl, FILE *fp) { - char data[4096]; unsigned int errcnt, rxlen, start_flag; + int ivsctype = getvsctype(hdl); + struct evlg_flush_hdr *pevlog; unsigned long long end_flag; - struct evlg_flush_hdr *pevlog = (struct evlg_flush_hdr *)data; + char data[4096]; int ret = -1; - int ivsctype = getvsctype(dev); + pevlog = (struct evlg_flush_hdr *)data; start_flag = 0; rxlen = 0; errcnt = 0; @@ -97,12 +92,12 @@ int getvsc_eventlog(struct nvme_dev *dev, FILE *fp) while (1) { memset(data, 0, 4096); if (ivsctype == 0) { - ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET_EVENT_LOG, 0, 0, + ret = nvme_vucmd(hdl, NVME_VSC_GET_EVENT_LOG, 0, 0, (SRB_SIGNATURE >> 32), (SRB_SIGNATURE & 0xFFFFFFFF), (char *)data, 4096); } else { - ret = nvme_vucmd(dev_fd(dev), NVME_VSC_TYPE1_GET, 0x60, 0, + ret = nvme_vucmd(hdl, NVME_VSC_TYPE1_GET, 0x60, 0, 0, 0, (char *)data, 4096); } @@ -140,18 +135,18 @@ int getvsc_eventlog(struct nvme_dev *dev, FILE *fp) return IG_SUCCESS; } -int getlogpage_eventlog(struct nvme_dev *dev, FILE *fp) +int getlogpage_eventlog(struct nvme_transport_handle *hdl, FILE *fp) { unsigned int i, result, total_size; char data[4096]; int ret = 0; result = 0; - ret = getlogpage(dev, 0xcb, 0x01, data, 4096, NULL); + ret = getlogpage(hdl, 0xcb, 0x01, data, 4096, NULL); if (ret) return IG_UNSUPPORT; - ret = getlogpage(dev, 0xcb, 0x02, data, 4096, &result); + ret = getlogpage(hdl, 0xcb, 0x02, data, 4096, &result); if ((ret) || (result == 0)) return IG_UNSUPPORT; @@ -159,7 +154,7 @@ int getlogpage_eventlog(struct nvme_dev *dev, FILE *fp) printf("total eventlog : %d.%d MB\n", total_size / SIZE_MB, (total_size % SIZE_MB) * 100 / SIZE_MB); for (i = 0; i <= total_size; i += 4096) { - ret = getlogpage(dev, 0xcb, 0x00, data, 4096, NULL); + ret = getlogpage(hdl, 0xcb, 0x00, data, 4096, NULL); printf("\rget eventlog : %d.%d MB ", i / SIZE_MB, (i % SIZE_MB) * 100 / SIZE_MB); if (ret) { @@ -173,22 +168,23 @@ int getlogpage_eventlog(struct nvme_dev *dev, FILE *fp) } static int innogrit_geteventlog(int argc, char **argv, - struct command *command, - struct plugin *plugin) + struct command *command, + struct plugin *plugin) { - time_t timep; - struct tm *logtime; - char currentdir[128], filename[512]; const char *desc = "Recrieve event log for the given device "; - struct nvme_dev *dev; - FILE *fp = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_file_ FILE *fp = NULL; + char currentdir[128], filename[512]; + struct tm *logtime; + time_t timep; int ret = -1; OPT_ARGS(opts) = { OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; @@ -198,49 +194,48 @@ static int innogrit_geteventlog(int argc, char **argv, time(&timep); logtime = localtime(&timep); sprintf(filename, "%s/eventlog_%02d%02d-%02d%02d%02d.eraw", currentdir, - logtime->tm_mon+1, logtime->tm_mday, logtime->tm_hour, logtime->tm_min, - logtime->tm_sec); + logtime->tm_mon + 1, logtime->tm_mday, logtime->tm_hour, + logtime->tm_min, logtime->tm_sec); printf("output eventlog file : %s\n", filename); fp = fopen(filename, "a+"); - getvsctype(dev); - ret = getlogpage_eventlog(dev, fp); + getvsctype(hdl); + ret = getlogpage_eventlog(hdl, fp); if (ret == IG_UNSUPPORT) - ret = getvsc_eventlog(dev, fp); + ret = getvsc_eventlog(hdl, fp); - fclose(fp); - dev_close(dev); chmod(filename, 0666); return ret; } -static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command, - struct plugin *plugin) +static int innogrit_vsc_getcdump(int argc, char **argv, struct command *acmd, + struct plugin *plugin) { - time_t timep; - struct tm *logtime; + const char *desc = "Recrieve cdump data for the given device "; char currentdir[128], filename[512], fname[128]; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; unsigned int itotal, icur, ivsctype; - char data[4096]; - struct cdumpinfo cdumpinfo; - unsigned char busevsc = false; unsigned int ipackcount, ipackindex; - char fwvera[32]; - const char *desc = "Recrieve cdump data for the given device "; - struct nvme_dev *dev; + unsigned char busevsc = false; + struct cdumpinfo cdumpinfo; + struct tm *logtime; FILE *fp = NULL; + char data[4096]; + char fwvera[32]; + time_t timep; int ret = -1; OPT_ARGS(opts) = { OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - ivsctype = getvsctype(dev); + ivsctype = getvsctype(hdl); if (getcwd(currentdir, 128) == NULL) return -1; @@ -252,11 +247,11 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command, memset(data, 0, 4096); if (ivsctype == 0) { - ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00, + ret = nvme_vucmd(hdl, NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00, (SRB_SIGNATURE >> 32), (SRB_SIGNATURE & 0xFFFFFFFF), (char *)data, 4096); } else { - ret = nvme_vucmd(dev_fd(dev), NVME_VSC_TYPE1_GET, 0x82, 0x00, + ret = nvme_vucmd(hdl, NVME_VSC_TYPE1_GET, 0x82, 0x00, 0, 0, (char *)data, 4096); } @@ -284,9 +279,8 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command, if (busevsc == false) { memset(data, 0, 4096); - ret = nvme_get_nsid_log(dev_fd(dev), true, 0x07, - NVME_NSID_ALL, - 4096, data); + ret = nvme_get_nsid_log(hdl, NVME_NSID_ALL,true, 0x07, + data, 4096); if (ret != 0) return ret; @@ -313,25 +307,25 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command, memset(data, 0, 4096); if (busevsc) { if (ivsctype == 0) { - ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET, + ret = nvme_vucmd(hdl, NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00, (SRB_SIGNATURE >> 32), (SRB_SIGNATURE & 0xFFFFFFFF), (char *)data, 4096); } else { - ret = nvme_vucmd(dev_fd(dev), NVME_VSC_TYPE1_GET, + ret = nvme_vucmd(hdl, NVME_VSC_TYPE1_GET, 0x82, 0x00, 0, 0, (char *)data, 4096); } } else { - ret = nvme_get_nsid_log(dev_fd(dev), true, - 0x07, - NVME_NSID_ALL, 4096, data); + ret = nvme_get_nsid_log(hdl, NVME_NSID_ALL, true, + 0x07, data, 4096); } if (ret != 0) return ret; fwrite(data, 1, 4096, fp); - printf("\rWait for dump data %d%%" XCLEAN_LINE, ((icur+4096) * 100/itotal)); + printf("\rWait for dump data %d%%" XCLEAN_LINE, + ((icur + 4096) * 100 / itotal)); } memset(data, 0, 4096); strcpy((char *)data, "cdumpend"); @@ -342,20 +336,18 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command, memset(data, 0, 4096); if (busevsc) { if (ivsctype == 0) { - ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET, + ret = nvme_vucmd(hdl, NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00, (SRB_SIGNATURE >> 32), (SRB_SIGNATURE & 0xFFFFFFFF), (char *)data, 4096); } else { - ret = nvme_vucmd(dev_fd(dev), NVME_VSC_TYPE1_GET, + ret = nvme_vucmd(hdl, NVME_VSC_TYPE1_GET, 0x82, 0x00, 0, 0, (char *)data, 4096); } } else { - ret = nvme_get_nsid_log(dev_fd(dev), true, - 0x07, - NVME_NSID_ALL, 4096, - data); + ret = nvme_get_nsid_log(hdl, NVME_NSID_ALL, true, + 0x07, data, 4096); } if (ret != 0) return ret; @@ -374,7 +366,6 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command, } printf("\n"); - dev_close(dev); if (fp != NULL) fclose(fp); return ret; diff --git a/plugins/inspur/inspur-nvme.c b/plugins/inspur/inspur-nvme.c index cda3507533..041a0dede8 100644 --- a/plugins/inspur/inspur-nvme.c +++ b/plugins/inspur/inspur-nvme.c @@ -204,23 +204,23 @@ void show_r1_media_err_log(r1_cli_vendor_log_t *vendorlog) } } -static int nvme_get_vendor_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int nvme_get_vendor_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - __u8 local_mem[BYTE_OF_4K]; char *desc = "Get the Inspur vendor log"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + __u8 local_mem[BYTE_OF_4K]; int err; OPT_ARGS(opts) = { OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; memset(local_mem, 0, BYTE_OF_4K); - err = nvme_get_log_simple(dev_fd(dev), - (enum nvme_cmd_get_log_lid)VENDOR_SMART_LOG_PAGE, - sizeof(r1_cli_vendor_log_t), local_mem); + err = nvme_get_log_simple(hdl, (enum nvme_cmd_get_log_lid)VENDOR_SMART_LOG_PAGE, + local_mem, sizeof(r1_cli_vendor_log_t)); if (!err) { show_r1_vendor_log((r1_cli_vendor_log_t *)local_mem); show_r1_media_err_log((r1_cli_vendor_log_t *)local_mem); @@ -228,6 +228,5 @@ static int nvme_get_vendor_log(int argc, char **argv, struct command *cmd, struc nvme_show_status(err); } - dev_close(dev); return err; } diff --git a/plugins/intel/intel-nvme.c b/plugins/intel/intel-nvme.c index faf1a1534c..ef22ef58ea 100644 --- a/plugins/intel/intel-nvme.c +++ b/plugins/intel/intel-nvme.c @@ -129,12 +129,13 @@ static void intel_id_ctrl(__u8 *vs, struct json_object *root) printf("mic_fw : %s\n", mic_fw); } -static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return __id_ctrl(argc, argv, cmd, plugin, intel_id_ctrl); + return __id_ctrl(argc, argv, acmd, plugin, intel_id_ctrl); } -static void show_intel_smart_log_jsn(struct nvme_additional_smart_log *smart, +static void +show_intel_smart_log_jsn(struct nvme_additional_smart_log *smart, unsigned int nsid, const char *devname) { struct json_object *root, *entry_stats, *dev_stats, *multi; @@ -330,7 +331,7 @@ static void show_intel_smart_log(struct nvme_additional_smart_log *smart, print_intel_smart_log_items(iter); } -static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_additional_smart_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get Intel vendor specific additional smart log (optionally, for the specified namespace), and show it."; @@ -341,7 +342,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, #endif /* CONFIG_JSONC */ struct nvme_additional_smart_log smart_log; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; struct config { @@ -361,33 +363,32 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = nvme_get_log_simple(dev_fd(dev), 0xca, sizeof(smart_log), - &smart_log); + err = nvme_get_log_simple(hdl, 0xca, &smart_log, sizeof(smart_log)); if (!err) { if (cfg.json) show_intel_smart_log_jsn(&smart_log, cfg.namespace_id, - dev->name); + nvme_transport_handle_get_name(hdl)); else if (!cfg.raw_binary) show_intel_smart_log(&smart_log, cfg.namespace_id, - dev->name); + nvme_transport_handle_get_name(hdl)); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); } else if (err > 0) { nvme_show_status(err); } - dev_close(dev); return err; } -static int get_market_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_market_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get Intel Marketing Name log and show it."; const char *raw = "dump output in binary format"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; char log[512]; int err; @@ -403,11 +404,11 @@ static int get_market_log(int argc, char **argv, struct command *cmd, struct plu OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = nvme_get_log_simple(dev_fd(dev), 0xdd, sizeof(log), log); + err = nvme_get_log_simple(hdl, 0xdd, log, sizeof(log)); if (!err) { if (!cfg.raw_binary) printf("Intel Marketing Name Log:\n%s\n", log); @@ -415,7 +416,6 @@ static int get_market_log(int argc, char **argv, struct command *cmd, struct plu d_raw((unsigned char *)&log, sizeof(log)); } else if (err > 0) nvme_show_status(err); - dev_close(dev); return err; } @@ -445,10 +445,11 @@ static void show_temp_stats(struct intel_temp_stats *stats) printf("Estimated offset : %"PRIu64"\n", le64_to_cpu(stats->est_offset)); } -static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_temp_stats_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { struct intel_temp_stats stats; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; const char *desc = "Get Temperature Statistics log and show it."; @@ -465,11 +466,11 @@ static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = nvme_get_log_simple(dev_fd(dev), 0xc5, sizeof(stats), &stats); + err = nvme_get_log_simple(hdl, 0xc5, &stats, sizeof(stats)); if (!err) { if (!cfg.raw_binary) show_temp_stats(&stats); @@ -477,7 +478,6 @@ static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct d_raw((unsigned char *)&stats, sizeof(stats)); } else if (err > 0) nvme_show_status(err); - dev_close(dev); return err; } @@ -770,8 +770,7 @@ static void json_lat_stats_linear(struct intel_lat_stats *stats, } } -static void json_lat_stats_3_0(struct intel_lat_stats *stats, - int write) +static void json_lat_stats_3_0(struct intel_lat_stats *stats, int write) { struct json_object *root = json_create_object(); struct json_object *bucket_list = json_object_new_array(); @@ -789,8 +788,7 @@ static void json_lat_stats_3_0(struct intel_lat_stats *stats, json_free_object(root); } -static void json_lat_stats_4_0(struct intel_lat_stats *stats, - int write) +static void json_lat_stats_4_0(struct intel_lat_stats *stats, int write) { struct json_object *root = json_create_object(); struct json_object *bucket_list = json_object_new_array(); @@ -968,7 +966,8 @@ static void json_lat_stats(int write) printf("\n"); } -static void print_dash_separator(int count) +static void +print_dash_separator(int count) { for (int i = 0; i < count; i++) putchar('-'); @@ -1026,10 +1025,11 @@ static void show_lat_stats(int write) } } -static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_lat_stats_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { __u8 data[NAND_LAT_STATS_LEN]; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; const char *desc = "Get Intel Latency Statistics log and show it."; @@ -1055,44 +1055,34 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; /* For optate, latency stats are deleted every time their LID is pulled. * Therefore, we query the longest lat_stats log page first. */ - err = nvme_get_log_simple(dev_fd(dev), cfg.write ? 0xc2 : 0xc1, - sizeof(data), &data); + err = nvme_get_log_simple(hdl, cfg.write ? 0xc2 : 0xc1, + &data, sizeof(data)); media_version[0] = (data[1] << 8) | data[0]; media_version[1] = (data[3] << 8) | data[2]; if (err) - goto close_dev; + return err; if (media_version[0] == 1000) { __u32 thresholds[OPTANE_V1000_BUCKET_LEN] = {0}; __u32 result; - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = 0xf7, - .nsid = 0, - .sel = 0, - .cdw11 = cfg.write ? 0x1 : 0x0, - .uuidx = 0, - .data_len = sizeof(thresholds), - .data = thresholds, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_get_features(&args); + err = nvme_get_features(hdl, 0, 0xf7, + 0, cfg.write ? 0x1 : 0x0, + 0, thresholds, sizeof(thresholds), + &result); if (err) { fprintf(stderr, "Querying thresholds failed. "); nvme_show_status(err); - goto close_dev; + return err; } /* Update bucket thresholds to be printed */ @@ -1128,9 +1118,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct sizeof(stats)); } -close_dev: - dev_close(dev); - return err; + return 0; } struct intel_assert_dump { @@ -1231,15 +1219,15 @@ static void print_intel_nlog(struct intel_vu_nlog *intel_nlog) } static int read_entire_cmd(struct nvme_passthru_cmd *cmd, int total_size, - const size_t max_tfer, int out_fd, int ioctl_fd, - __u8 *buf) + const size_t max_tfer, int out_fd, + struct nvme_transport_handle *hdl, __u8 *buf) { int err = 0; size_t dword_tfer = 0; dword_tfer = min(max_tfer, total_size); while (total_size > 0) { - err = nvme_submit_admin_passthru(ioctl_fd, cmd, NULL); + err = nvme_submit_admin_passthru(hdl, 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", @@ -1273,8 +1261,8 @@ static int write_header(__u8 *buf, int fd, size_t amnt) return 0; } -static int read_header(struct nvme_passthru_cmd *cmd, __u8 *buf, int ioctl_fd, - __u32 dw12, int nsid) +static int read_header(struct nvme_passthru_cmd *cmd, __u8 *buf, + struct nvme_transport_handle *hdl, __u32 dw12, int nsid) { memset(cmd, 0, sizeof(*cmd)); memset(buf, 0, 4096); @@ -1284,15 +1272,15 @@ static int read_header(struct nvme_passthru_cmd *cmd, __u8 *buf, int ioctl_fd, cmd->cdw12 = dw12; cmd->data_len = 0x1000; cmd->addr = (unsigned long)(void *)buf; - return read_entire_cmd(cmd, 0x400, 0x400, -1, ioctl_fd, buf); + return read_entire_cmd(cmd, 0x400, 0x400, -1, hdl, buf); } -static int setup_file(char *f, char *file, int fd, int type) +static int setup_file(char *f, char *file, struct nvme_transport_handle *hdl, int type) { struct nvme_id_ctrl ctrl; int err = 0, i = sizeof(ctrl.sn) - 1; - err = nvme_identify_ctrl(fd, &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err) return err; @@ -1308,7 +1296,8 @@ static int setup_file(char *f, char *file, int fd, int type) return err; } -static int get_internal_log_old(__u8 *buf, int output, int fd, +static int get_internal_log_old(__u8 *buf, int output, + struct nvme_transport_handle *hdl, struct nvme_passthru_cmd *cmd) { struct intel_vu_log *intel; @@ -1330,7 +1319,7 @@ static int get_internal_log_old(__u8 *buf, int output, int fd, cmd->opcode = 0xd2; cmd->cdw10 = min(dwmax, intel->size); cmd->data_len = min(dmamax, intel->size); - err = read_entire_cmd(cmd, intel->size, dwmax, output, fd, buf); + err = read_entire_cmd(cmd, intel->size, dwmax, output, hdl, buf); if (err) goto out; @@ -1339,8 +1328,8 @@ static int get_internal_log_old(__u8 *buf, int output, int fd, return err; } -static int get_internal_log(int argc, char **argv, struct command *command, - struct plugin *plugin) +static int get_internal_log(int argc, char **argv, struct command *acmd, + struct plugin *plugin) { __u8 buf[0x2000]; char f[0x100]; @@ -1351,7 +1340,8 @@ static int get_internal_log(int argc, char **argv, struct command *command, struct intel_vu_nlog *intel_nlog = (struct intel_vu_nlog *)buf; struct intel_assert_dump *ad = (struct intel_assert_dump *) intel->reserved; struct intel_event_header *ehdr = (struct intel_event_header *)intel->reserved; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; const char *desc = "Get Intel Firmware Log and save it."; const char *log = "Log type: 0, 1, or 2 for nlog, event log, and assert log, respectively."; @@ -1387,7 +1377,7 @@ static int get_internal_log(int argc, char **argv, struct command *command, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { free(intel); return err; @@ -1399,7 +1389,7 @@ static int get_internal_log(int argc, char **argv, struct command *command, } if (!cfg.file) { - err = setup_file(f, cfg.file, dev_fd(dev), cfg.log); + err = setup_file(f, cfg.file, hdl, cfg.log); if (err) goto out_free; cfg.file = f; @@ -1417,7 +1407,7 @@ static int get_internal_log(int argc, char **argv, struct command *command, goto out_free; } - err = read_header(&cmd, buf, dev_fd(dev), cdlog.u.entireDword, + err = read_header(&cmd, buf, hdl, cdlog.u.entireDword, cfg.namespace_id); if (err) goto out; @@ -1427,7 +1417,7 @@ static int get_internal_log(int argc, char **argv, struct command *command, if ((intel->ver.major < 1 && intel->ver.minor < 1) || (intel->ver.major <= 1 && intel->ver.minor <= 1 && cfg.log == 0)) { cmd.addr = (unsigned long)(void *)buf; - err = get_internal_log_old(buf, output, dev_fd(dev), &cmd); + err = get_internal_log_old(buf, output, hdl, &cmd); goto out; } @@ -1472,7 +1462,7 @@ static int get_internal_log(int argc, char **argv, struct command *command, cmd.data_len = min(0x400, ad[i].assertsize) * 4; err = read_entire_cmd(&cmd, ad[i].assertsize, 0x400, output, - dev_fd(dev), + hdl, buf); if (err) goto out; @@ -1482,7 +1472,7 @@ static int get_internal_log(int argc, char **argv, struct command *command, if (count > 1) cdlog.u.fields.selectNlog = i; - err = read_header(&cmd, buf, dev_fd(dev), + err = read_header(&cmd, buf, hdl, cdlog.u.entireDword, cfg.namespace_id); if (err) @@ -1497,7 +1487,7 @@ static int get_internal_log(int argc, char **argv, struct command *command, cmd.data_len = min(0x1000, intel_nlog->nlogbytesize); err = read_entire_cmd(&cmd, intel_nlog->nlogbytesize / 4, 0x400, output, - dev_fd(dev), + hdl, buf); if (err) goto out; @@ -1507,7 +1497,7 @@ static int get_internal_log(int argc, char **argv, struct command *command, cmd.data_len = 0x400; err = read_entire_cmd(&cmd, ehdr->edumps[j].coresize, 0x400, output, - dev_fd(dev), + hdl, buf); if (err) goto out; @@ -1526,7 +1516,6 @@ static int get_internal_log(int argc, char **argv, struct command *command, close(output); out_free: free(intel); - dev_close(dev); return err; } @@ -1544,8 +1533,9 @@ static int enable_lat_stats_tracking(int argc, char **argv, const __u32 cdw11 = 0x0; const __u32 cdw12 = 0x0; const __u32 data_len = 32; - const __u32 save = 0; - struct nvme_dev *dev; + const __u32 sv = 0; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; void *buf = NULL; __u32 result; int err; @@ -1559,13 +1549,13 @@ static int enable_lat_stats_tracking(int argc, char **argv, .disable = false, }; - struct argconfig_commandline_options command_line_options[] = { + struct argconfig_commandline_options opts[] = { {"enable", 'e', "", CFG_FLAG, &cfg.enable, no_argument, enable_desc}, {"disable", 'd', "", CFG_FLAG, &cfg.disable, no_argument, disable_desc}, {NULL} }; - err = parse_and_open(&dev, argc, argv, desc, command_line_options); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); enum Option { None = -1, @@ -1583,52 +1573,23 @@ static int enable_lat_stats_tracking(int argc, char **argv, if (err) return err; - struct nvme_get_features_args args_get = { - .args_size = sizeof(args_get), - .fd = dev_fd(dev), - .fid = fid, - .nsid = nsid, - .sel = sel, - .cdw11 = cdw11, - .uuidx = 0, - .data_len = data_len, - .data = buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - struct nvme_set_features_args args_set = { - .args_size = sizeof(args_set), - .fd = dev_fd(dev), - .fid = fid, - .nsid = nsid, - .cdw11 = option, - .cdw12 = cdw12, - .save = save, - .uuidx = 0, - .cdw15 = 0, - .data_len = data_len, - .data = buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - switch (option) { case None: - err = nvme_get_features(&args_get); + err = nvme_get_features(hdl, nsid, fid, sel, cdw11, 0, buf, + data_len, &result); if (!err) { printf( "Latency Statistics Tracking (FID 0x%X) is currently (%i).\n", fid, result); } else { printf("Could not read feature id 0xE2.\n"); - dev_close(dev); return err; } break; case True: case False: - err = nvme_set_features(&args_set); + err = nvme_set_features(hdl, nsid, fid, sv, option, cdw12, 0, 0, 0, buf, + data_len, &result); if (err > 0) { nvme_show_status(err); } else if (err < 0) { @@ -1643,7 +1604,6 @@ static int enable_lat_stats_tracking(int argc, char **argv, printf("%d not supported.\n", option); return -EINVAL; } - dev_close(dev); return err; } @@ -1657,8 +1617,9 @@ static int set_lat_stats_thresholds(int argc, char **argv, const __u32 nsid = 0; const __u8 fid = 0xf7; const __u32 cdw12 = 0x0; - const __u32 save = 0; - struct nvme_dev *dev; + const __u32 sv = 0; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 result; int err, num; @@ -1679,7 +1640,7 @@ static int set_lat_stats_thresholds(int argc, char **argv, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -1688,8 +1649,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_simple(dev_fd(dev), 0xc2, - sizeof(media_version), media_version); + err = nvme_get_log_simple(hdl, 0xc2, + media_version, sizeof(media_version)); if (err) { fprintf(stderr, "Querying media version failed. "); nvme_show_status(err); @@ -1708,22 +1669,8 @@ static int set_lat_stats_thresholds(int argc, char **argv, } - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = nsid, - .cdw11 = cfg.write ? 0x1 : 0x0, - .cdw12 = cdw12, - .save = save, - .uuidx = 0, - .cdw15 = 0, - .data_len = sizeof(thresholds), - .data = thresholds, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); + err = nvme_set_features(hdl, nsid, fid, sv, cfg.write ? 0x1 : 0x0, cdw12, + 0, 0, 0, thresholds, sizeof(thresholds), &result); if (err > 0) { nvme_show_status(err); @@ -1736,7 +1683,6 @@ static int set_lat_stats_thresholds(int argc, char **argv, } close_dev: - dev_close(dev); return err; } diff --git a/plugins/lm/lm-nvme.c b/plugins/lm/lm-nvme.c index 4f4159fbe9..fdf6f42f82 100644 --- a/plugins/lm/lm-nvme.c +++ b/plugins/lm/lm-nvme.c @@ -29,7 +29,6 @@ #include "libnvme.h" #include "plugin.h" #include "linux/types.h" -#include "nvme-wrap.h" #include "util/cleanup.h" #define CREATE_CMD @@ -37,7 +36,7 @@ #include "lm-print.h" -static inline const char *arg_str(const char * const *strings, size_t array_size, size_t idx) +static inline const char * arg_str(const char * const *strings, size_t array_size, size_t idx) { if (idx < array_size && strings[idx]) return strings[idx]; @@ -47,7 +46,7 @@ static inline const char *arg_str(const char * const *strings, size_t array_size #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #define ARGSTR(s, i) arg_str(s, ARRAY_SIZE(s), i) -static int lm_create_cdq(int argc, char **argv, struct command *command, struct plugin *plugin) +static int lm_create_cdq(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Create Controller Data Queue for controller of specific type and size"; const char *sz = "CDQ Size (in dwords)"; @@ -58,9 +57,12 @@ static int lm_create_cdq(int argc, char **argv, struct command *command, struct "will write to invalid memory, inevitably leading to MMU faults or " "worse."; - _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; struct lba_migration_queue_entry_type_0 *queue = NULL; + _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; + struct nvme_passthru_cmd cmd; + __u32 result; int err = -1; struct config { @@ -87,7 +89,7 @@ static int lm_create_cdq(int argc, char **argv, struct command *command, struct OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -105,33 +107,28 @@ static int lm_create_cdq(int argc, char **argv, struct command *command, struct return -ENOMEM; } - struct nvme_lm_cdq_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .sel = NVME_LM_SEL_CREATE_CDQ, - .mos = NVME_SET(cfg.qt, LM_QT), - .cntlid = cfg.cntlid, - .sz = cfg.sz, - .data = queue - }; - - err = nvme_lm_cdq(&args); + nvme_init_lm_cdq_create(&cmd, NVME_SET(cfg.qt, LM_QT), + cfg.cntlid, cfg.sz, queue); + err = nvme_submit_admin_passthru(hdl, &cmd, &result); if (err < 0) nvme_show_error("ERROR: nvme_lm_cdq() failed: %s", nvme_strerror(errno)); else if (err) nvme_show_status(err); else - printf("Create CDQ Successful: CDQID=0x%04x\n", args.cdqid); + printf("Create CDQ Successful: CDQID=0x%04x\n", + NVME_GET(result, LM_CREATE_CDQ_CDQID)); return err; } -static int lm_delete_cdq(int argc, char **argv, struct command *command, struct plugin *plugin) +static int lm_delete_cdq(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Delete Controller Data Queue"; const char *cdqid = "Controller Data Queue ID"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_passthru_cmd cmd; int err = -1; struct config { @@ -147,18 +144,12 @@ static int lm_delete_cdq(int argc, char **argv, struct command *command, struct OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - struct nvme_lm_cdq_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .sel = NVME_LM_SEL_DELETE_CDQ, - .cdqid = cfg.cdqid, - }; - - err = nvme_lm_cdq(&args); + nvme_init_lm_cdq_delete(&cmd, 0, cfg.cdqid); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) nvme_show_error("ERROR: nvme_lm_cdq() failed: %s", nvme_strerror(errno)); else if (err > 0) @@ -174,7 +165,7 @@ static const char * const lm_track_send_select_argstr[] = { [NVME_LM_SEL_TRACK_MEMORY_CHANGES] = "Track Memory Changes" }; -static int lm_track_send(int argc, char **argv, struct command *command, struct plugin *plugin) +static int lm_track_send(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Track Send command used to manage the tracking of information by a " "controller"; @@ -187,7 +178,9 @@ static int lm_track_send(int argc, char **argv, struct command *command, struct const char *stop = "Equivalent to stop tracking with defaults"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_passthru_cmd cmd; int err = -1; struct config { @@ -215,7 +208,7 @@ static int lm_track_send(int argc, char **argv, struct command *command, struct OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -240,15 +233,8 @@ static int lm_track_send(int argc, char **argv, struct command *command, struct cfg.mos = NVME_SET(NVME_LM_LACT_STOP_LOGGING, LM_LACT); } - struct nvme_lm_track_send_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .cdqid = cfg.cdqid, - .sel = cfg.sel, - .mos = cfg.mos, - }; - - err = nvme_lm_track_send(&args); + nvme_init_lm_track_send(&cmd, cfg.sel, cfg.mos, cfg.cdqid); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) nvme_show_error("ERROR: nvme_lm_track_send() failed %s", strerror(errno)); else if (err) @@ -266,7 +252,7 @@ static const char * const lm_migration_send_select_argstr[] = { [NVME_LM_SEL_SET_CONTROLLER_STATE] = "Set Controller State" }; -static int lm_migration_send(int argc, char **argv, struct command *command, struct plugin *plugin) +static int lm_migration_send(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Migration Send command is used to manage the migration of a controller"; const char *sel = "Select (SEL) the type of management operation to perform " @@ -292,9 +278,11 @@ static int lm_migration_send(int argc, char **argv, struct command *command, str const char *numd = "Number of Dwords (NUMD)"; const char *input = "Controller State Data input file"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - _cleanup_file_ FILE *file = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; + _cleanup_file_ FILE *file = NULL; + struct nvme_passthru_cmd cmd; void *data = NULL; int err = -1; @@ -341,7 +329,7 @@ static int lm_migration_send(int argc, char **argv, struct command *command, str OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -390,22 +378,12 @@ static int lm_migration_send(int argc, char **argv, struct command *command, str } } - struct nvme_lm_migration_send_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .sel = cfg.sel, - .mos = NVME_SET(cfg.seqind, LM_SEQIND), - .cntlid = cfg.cntlid, - .csuuidi = cfg.csuuidi, - .uidx = cfg.uidx, - .stype = cfg.stype, - .offset = cfg.offset, - .dudmq = cfg.dudmq, - .numd = cfg.numd, - .data = data, - }; - - err = nvme_lm_migration_send(&args); + nvme_init_lm_migration_send(&cmd, cfg.sel, + NVME_SET(cfg.seqind, LM_SEQIND), cfg.cntlid, + cfg.stype, cfg.dudmq, cfg.csvi, cfg.csuuidi, + cfg.offset, cfg.uidx, data, + (cfg.numd << 2)); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) nvme_show_error("ERROR: nvme_lm_migration_send() failed %s", strerror(errno)); else if (err > 0) @@ -418,7 +396,7 @@ static int lm_migration_send(int argc, char **argv, struct command *command, str return err; } -static int lm_migration_recv(int argc, char **argv, struct command *command, struct plugin *plugin) +static int lm_migration_recv(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Migration Receive command is used to obtain information used to manage " " a migratable controller"; @@ -434,12 +412,16 @@ static int lm_migration_recv(int argc, char **argv, struct command *command, str const char *output = "Controller State Data output file"; const char *human_readable_info = "show info in readable format"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - _cleanup_file_ FILE *fd = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; + _cleanup_file_ FILE *fd = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; void *data = NULL; + __u32 result = 0; int err = -1; + __u16 mos; struct config { __u8 sel; @@ -481,7 +463,7 @@ static int lm_migration_recv(int argc, char **argv, struct command *command, str OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -511,22 +493,11 @@ static int lm_migration_recv(int argc, char **argv, struct command *command, str if (!data) return -ENOMEM; - __u32 result = 0; - struct nvme_lm_migration_recv_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .sel = cfg.sel, - .mos = NVME_SET(cfg.csvi, LM_GET_CONTROLLER_STATE_CSVI), - .uidx = cfg.uidx, - .csuuidi = cfg.csuuidi, - .offset = cfg.offset, - .cntlid = cfg.cntlid, - .numd = cfg.numd, - .data = data, - .result = &result, - }; - - err = nvme_lm_migration_recv(&args); + mos = NVME_SET(cfg.csvi, LM_GET_CONTROLLER_STATE_CSVI); + nvme_init_lm_migration_recv(&cmd, cfg.offset, mos, cfg.cntlid, + cfg.csuuidi, cfg.sel, cfg.uidx, 0, data, + (cfg.numd + 1) << 2); + err = nvme_submit_admin_passthru(hdl, &cmd, &result); if (err < 0) nvme_show_error("ERROR: nvme_lm_migration_recv() failed %s", strerror(errno)); else if (err) @@ -555,7 +526,7 @@ enum lm_controller_data_queue_feature_id { lm_cdq_feature_id = 0x21 }; -static int lm_set_cdq(int argc, char **argv, struct command *command, struct plugin *plugin) +static int lm_set_cdq(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "This Feature allows a host to update the status of the head pointer " "of a CDQ and specify the configuration of a CDQ Tail event."; @@ -564,7 +535,8 @@ static int lm_set_cdq(int argc, char **argv, struct command *command, struct plu const char *tpt = "If specified, the slot that causes the controller " " to issue a CDQ Tail Pointer event"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err = -1; struct config { @@ -586,21 +558,13 @@ static int lm_set_cdq(int argc, char **argv, struct command *command, struct plu OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = lm_cdq_feature_id, - .cdw11 = cfg.cdqid | - ((cfg.tpt >= 0) ? NVME_SET(1, LM_CTRL_DATA_QUEUE_ETPT) : 0), - .cdw12 = cfg.hp, - .cdw13 = cfg.tpt - }; - - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 0, lm_cdq_feature_id, 0, cfg.cdqid | + ((cfg.tpt >= 0) ? NVME_SET(1, LM_CTRL_DATA_QUEUE_ETPT) : 0), + cfg.hp, cfg.tpt, 0, 0, NULL, 0, NULL); if (err < 0) nvme_show_error("ERROR: nvme_set_features() failed %s", nvme_strerror(errno)); else if (err) @@ -611,13 +575,14 @@ static int lm_set_cdq(int argc, char **argv, struct command *command, struct plu return err; } -static int lm_get_cdq(int argc, char **argv, struct command *command, struct plugin *plugin) +static int lm_get_cdq(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "This Feature allows a host to retrieve the status of the head pointer " "of a CDQ and specify the configuration of a CDQ Tail event."; const char *cdqid = "Controller Data Queue ID"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; int err = -1; @@ -637,7 +602,7 @@ static int lm_get_cdq(int argc, char **argv, struct command *command, struct plu OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -649,16 +614,8 @@ static int lm_get_cdq(int argc, char **argv, struct command *command, struct plu struct nvme_lm_ctrl_data_queue_fid_data data; - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = lm_cdq_feature_id, - .cdw11 = cfg.cdqid, - .data = &data, - .data_len = sizeof(data) - }; - - err = nvme_get_features(&args); + err = nvme_get_features(hdl, 0, lm_cdq_feature_id, 0, cfg.cdqid, 0, + &data, sizeof(data), NULL); if (err < 0) nvme_show_error("ERROR: nvme_get_features() failed %s", nvme_strerror(errno)); else if (err) diff --git a/plugins/mangoboost/mangoboost-nvme.c b/plugins/mangoboost/mangoboost-nvme.c index 2f810c921f..8d64386208 100644 --- a/plugins/mangoboost/mangoboost-nvme.c +++ b/plugins/mangoboost/mangoboost-nvme.c @@ -52,8 +52,8 @@ static void mangoboost_id_ctrl(__u8 *vs, struct json_object *root) printf("json_rpc_2_0_ver : %s\n", json_rpc_2_0_ver); } -static int id_ctrl(int argc, char **argv, struct command *cmd, +static int id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return __id_ctrl(argc, argv, cmd, plugin, mangoboost_id_ctrl); + return __id_ctrl(argc, argv, acmd, plugin, mangoboost_id_ctrl); } diff --git a/plugins/memblaze/memblaze-nvme.c b/plugins/memblaze/memblaze-nvme.c index 85f4254ada..70de8bbf53 100644 --- a/plugins/memblaze/memblaze-nvme.c +++ b/plugins/memblaze/memblaze-nvme.c @@ -107,8 +107,8 @@ static __u64 raw_2_u64(const __u8 *buf, size_t len) return le64_to_cpu(val); } -static void get_memblaze_new_smart_info(struct nvme_p4_smart_log *smart, int index, __u8 *nm_val, - __u8 *raw_val) +static void get_memblaze_new_smart_info(struct nvme_p4_smart_log *smart, + int index, __u8 *nm_val, __u8 *raw_val) { memcpy(nm_val, smart->itemArr[index].nmVal, NM_SIZE); memcpy(raw_val, smart->itemArr[index].rawVal, RAW_SIZE); @@ -352,14 +352,14 @@ static void show_memblaze_smart_log_old(struct nvme_memblaze_smart_log *smart, } } -static int show_memblaze_smart_log(int fd, __u32 nsid, const char *devname, - struct nvme_memblaze_smart_log *smart) +static int show_memblaze_smart_log(struct nvme_transport_handle *hdl, __u32 nsid, + const char *devname, struct nvme_memblaze_smart_log *smart) { struct nvme_id_ctrl ctrl; char fw_ver[10]; int err = 0; - err = nvme_identify_ctrl(fd, &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err) return err; @@ -412,7 +412,7 @@ int parse_params(char *str, int number, ...) return 0; } -static int mb_get_additional_smart_log(int argc, char **argv, struct command *cmd, +static int mb_get_additional_smart_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { struct nvme_memblaze_smart_log smart_log; @@ -420,7 +420,8 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm "Get Memblaze vendor specific additional smart log, and show it."; const char *namespace = "(optional) desired namespace"; const char *raw = "dump output in binary format"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct config { __u32 namespace_id; bool raw_binary; @@ -437,15 +438,16 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = nvme_get_nsid_log(dev_fd(dev), false, 0xca, cfg.namespace_id, - sizeof(smart_log), &smart_log); + err = nvme_get_nsid_log(hdl, cfg.namespace_id, false, 0xca, + &smart_log, sizeof(smart_log)); if (!err) { if (!cfg.raw_binary) - err = show_memblaze_smart_log(dev_fd(dev), cfg.namespace_id, dev->name, + err = show_memblaze_smart_log(hdl, cfg.namespace_id, + nvme_transport_handle_get_name(hdl), &smart_log); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); @@ -470,37 +472,25 @@ static char *mb_feature_to_string(int feature) } } -static int mb_get_powermanager_status(int argc, char **argv, struct command *cmd, +static int mb_get_powermanager_status(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get Memblaze power management ststus\n (value 0 - 25w, 1 - 20w, 2 - 15w)"; __u32 result; __u32 feature_id = MB_FEAT_POWER_MGMT; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; OPT_ARGS(opts) = { OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = feature_id, - .nsid = 0, - .sel = 0, - .cdw11 = 0, - .uuidx = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_get_features(&args); + err = nvme_get_features(hdl, 0, feature_id, 0, 0, 0, NULL, 0, &result); if (err < 0) perror("get-feature"); if (!err) @@ -511,13 +501,14 @@ static int mb_get_powermanager_status(int argc, char **argv, struct command *cmd return err; } -static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd, +static int mb_set_powermanager_status(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Set Memblaze power management status\n (value 0 - 25w, 1 - 20w, 2 - 15w)"; const char *value = "new value of feature (required)"; const char *save = "specifies that the controller shall save the attribute"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 result; int err; @@ -539,26 +530,12 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = cfg.feature_id, - .nsid = 0, - .cdw11 = cfg.value, - .cdw12 = 0, - .save = cfg.save, - .uuidx = 0, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 0, cfg.feature_id, cfg.save, cfg.value, 0, 0, 0, + 0, NULL, 0, &result); if (err < 0) perror("set-feature"); if (!err) @@ -573,7 +550,7 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd #define P2MIN (1) #define P2MAX (5000) #define MB_FEAT_HIGH_LATENCY_VALUE_SHIFT (15) -static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, +static int mb_set_high_latency_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Set Memblaze high latency log\n" @@ -582,7 +559,9 @@ static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, " p2 value: 1 .. 5000 ms"; const char *param = "input parameters"; int param1 = 0, param2 = 0; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + __u32 result; int err; @@ -603,7 +582,7 @@ static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -617,22 +596,8 @@ static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, } cfg.value = (param1 << MB_FEAT_HIGH_LATENCY_VALUE_SHIFT) | param2; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = cfg.feature_id, - .nsid = 0, - .cdw11 = cfg.value, - .cdw12 = 0, - .save = false, - .uuidx = 0, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 0, cfg.feature_id, false, cfg.value, 0, 0, 0, + 0, NULL, 0, &result); if (err < 0) perror("set-feature"); if (!err) @@ -731,12 +696,14 @@ static int glp_high_latency(FILE *fdi, char *buf, int buflen, int print) return 1; } -static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd, +static int mb_high_latency_log_print(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get Memblaze high latency log"; char buf[LOG_PAGE_SIZE]; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + FILE *fdi = NULL; int err; @@ -744,20 +711,20 @@ static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; fdi = fopen(FID_C3_LOG_FILENAME, "w+"); glp_high_latency_show_bar(fdi, DO_PRINT_FLAG); - err = nvme_get_log_simple(dev_fd(dev), GLP_ID_VU_GET_HIGH_LATENCY_LOG, sizeof(buf), &buf); + err = nvme_get_log_simple(hdl, GLP_ID_VU_GET_HIGH_LATENCY_LOG, &buf, sizeof(buf)); while (1) { if (!glp_high_latency(fdi, buf, LOG_PAGE_SIZE, DO_PRINT_FLAG)) break; - err = nvme_get_log_simple(dev_fd(dev), GLP_ID_VU_GET_HIGH_LATENCY_LOG, sizeof(buf), - &buf); + err = nvme_get_log_simple(hdl, GLP_ID_VU_GET_HIGH_LATENCY_LOG, + &buf, sizeof(buf)); if (err) { nvme_show_status(err); break; @@ -769,7 +736,7 @@ static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd, return err; } -static int memblaze_fw_commit(int fd, int select) +static int memblaze_fw_commit(struct nvme_transport_handle *hdl, int select) { struct nvme_passthru_cmd cmd = { .opcode = nvme_admin_fw_commit, @@ -777,10 +744,10 @@ static int memblaze_fw_commit(int fd, int select) .cdw12 = select, }; - return nvme_submit_admin_passthru(fd, &cmd, NULL); + return nvme_submit_admin_passthru(hdl, &cmd, NULL); } -static int mb_selective_download(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int mb_selective_download(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "This performs a selective firmware download, which allows the user to\n" @@ -791,11 +758,15 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str "ALL - This updates the eeprom, OOB, and main firmware"; const char *fw = "firmware file (required)"; const char *select = "FW Select (e.g., --select=OOB, EEP, ALL)"; - int xfer = 4096; - void *fw_buf; + + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + int selectNo, fw_fd, fw_size, err, offset = 0; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + struct nvme_passthru_cmd cmd; + int xfer = 4096; struct stat sb; + void *fw_buf; int i; struct config { @@ -814,7 +785,7 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -874,16 +845,12 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str while (fw_size > 0) { xfer = min(xfer, fw_size); - struct nvme_fw_download_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .offset = offset, - .data_len = xfer, - .data = fw_buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - err = nvme_fw_download(&args); + err = nvme_init_fw_download(&cmd, fw_buf, xfer, offset); + if (err) { + perror("fw-download"); + goto out_free; + } + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) { perror("fw-download"); goto out_free; @@ -896,7 +863,7 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str offset += xfer; } - err = memblaze_fw_commit(dev_fd(dev), selectNo); + err = memblaze_fw_commit(hdl, selectNo); if (err == 0x10B || err == 0x20B) { err = 0; @@ -996,12 +963,14 @@ int io_latency_histogram(char *file, char *buf, int print, int logid) return 1; } -static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int mb_lat_stats_log_print(int argc, char **argv, struct command *acmd, struct plugin *plugin) { char stats[LOG_PAGE_SIZE]; char f1[] = FID_C1_LOG_FILENAME; char f2[] = FID_C2_LOG_FILENAME; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + int err; const char *desc = "Get Latency Statistics log and show it."; @@ -1019,11 +988,11 @@ static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, st OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = nvme_get_log_simple(dev_fd(dev), cfg.write ? 0xc2 : 0xc1, sizeof(stats), &stats); + err = nvme_get_log_simple(hdl, cfg.write ? 0xc2 : 0xc1, &stats, sizeof(stats)); if (!err) io_latency_histogram(cfg.write ? f2 : f1, stats, DO_PRINT_FLAG, cfg.write ? GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM : @@ -1034,11 +1003,13 @@ static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, st return err; } -static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd, +static int memblaze_clear_error_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { char *desc = "Clear Memblaze devices error log."; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + int err; __u32 result; @@ -1059,26 +1030,12 @@ static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = cfg.feature_id, - .nsid = 0, - .cdw11 = cfg.value, - .cdw12 = 0, - .save = cfg.save, - .uuidx = 0, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 0, cfg.feature_id, cfg.save, cfg.value, 0, 0, 0, + 0, NULL, 0, &result); if (err < 0) perror("set-feature"); if (!err) @@ -1090,7 +1047,7 @@ static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd, return err; } -static int mb_set_lat_stats(int argc, char **argv, struct command *command, struct plugin *plugin) +static int mb_set_lat_stats(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = ( "Enable/Disable Latency Statistics Tracking.\n" @@ -1104,7 +1061,9 @@ static int mb_set_lat_stats(int argc, char **argv, struct command *command, stru const __u32 cdw12 = 0x0; const __u32 data_len = 32; const __u32 save = 0; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + void *buf = NULL; __u32 result; int err; @@ -1118,13 +1077,13 @@ static int mb_set_lat_stats(int argc, char **argv, struct command *command, stru .disable = false, }; - struct argconfig_commandline_options command_line_options[] = { + struct argconfig_commandline_options opts[] = { {"enable", 'e', "", CFG_FLAG, &cfg.enable, no_argument, enable_desc}, {"disable", 'd', "", CFG_FLAG, &cfg.disable, no_argument, disable_desc}, {NULL} }; - err = parse_and_open(&dev, argc, argv, desc, command_line_options); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); enum Option { None = -1, @@ -1138,41 +1097,12 @@ static int mb_set_lat_stats(int argc, char **argv, struct command *command, stru else if (cfg.enable || cfg.disable) option = cfg.enable; - struct nvme_get_features_args args_get = { - .args_size = sizeof(args_get), - .fd = dev_fd(dev), - .fid = fid, - .nsid = nsid, - .sel = sel, - .cdw11 = cdw11, - .uuidx = 0, - .data_len = data_len, - .data = buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - struct nvme_set_features_args args_set = { - .args_size = sizeof(args_set), - .fd = dev_fd(dev), - .fid = fid, - .nsid = nsid, - .cdw11 = option, - .cdw12 = cdw12, - .save = save, - .uuidx = 0, - .cdw15 = 0, - .data_len = data_len, - .data = buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - if (err) return err; switch (option) { case None: - err = nvme_get_features(&args_get); + err = nvme_get_features(hdl, nsid, fid, sel, cdw11, 0, buf, data_len, + &result); if (!err) { printf("Latency Statistics Tracking (FID 0x%X) is currently (%i).\n", fid, result); @@ -1183,7 +1113,8 @@ static int mb_set_lat_stats(int argc, char **argv, struct command *command, stru break; case True: case False: - err = nvme_set_features(&args_set); + err = nvme_set_features(hdl, nsid, fid, save, option, cdw12, 0, 0, + 0, buf, data_len, &result); if (err > 0) { nvme_show_status(err); } else if (err < 0) { @@ -1619,7 +1550,7 @@ static void smart_log_add_print(struct smart_log_add *log, const char *devname) } } -static int mb_get_smart_log_add(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int mb_get_smart_log_add(int argc, char **argv, struct command *acmd, struct plugin *plugin) { int err = 0; @@ -1635,9 +1566,11 @@ static int mb_get_smart_log_add(int argc, char **argv, struct command *cmd, stru OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, "dump the whole log buffer in binary format"), OPT_END()}; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; - err = parse_and_open(&dev, argc, argv, cmd->help, opts); + + err = parse_and_open(&ctx, &hdl, argc, argv, acmd->help, opts); if (err) return err; @@ -1645,17 +1578,16 @@ static int mb_get_smart_log_add(int argc, char **argv, struct command *cmd, stru struct smart_log_add log = {0}; - err = nvme_get_log_simple(dev_fd(dev), LID_SMART_LOG_ADD, sizeof(struct smart_log_add), - &log); + err = nvme_get_log_simple(hdl, LID_SMART_LOG_ADD, &log, sizeof(struct smart_log_add)); if (!err) { if (!cfg.raw_binary) - smart_log_add_print(&log, dev->name); + smart_log_add_print(&log, nvme_transport_handle_get_name(hdl)); else d_raw((unsigned char *)&log, sizeof(struct smart_log_add)); } else if (err > 0) { nvme_show_status(err); } else { - nvme_show_error("%s: %s", cmd->name, nvme_strerror(errno)); + nvme_show_error("%s: %s", acmd->name, nvme_strerror(errno)); } return err; @@ -1761,7 +1693,7 @@ struct __packed performance_stats { }; }; -static int mb_set_latency_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int mb_set_latency_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { int err = 0; @@ -1796,9 +1728,11 @@ static int mb_set_latency_feature(int argc, char **argv, struct command *cmd, st "set trim high latency log threshold, it's a 0-based value and unit is 10ms"), OPT_END()}; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + - err = parse_and_open(&dev, argc, argv, cmd->help, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, acmd->help, opts); if (err) return err; @@ -1807,38 +1741,23 @@ static int mb_set_latency_feature(int argc, char **argv, struct command *cmd, st uint32_t result = 0; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = FID_LATENCY_FEATURE, - .nsid = 0, - .cdw11 = 0 | cfg.perf_monitor, - .cdw12 = 0 | cfg.cmd_mask, - .cdw13 = 0 | - (cfg.read_threshold & 0xff) | - ((cfg.write_threshold & 0xff) << 8) | - ((cfg.de_allocate_trim_threshold & 0xff) << 16), - .cdw15 = 0, - .save = 0, - .uuidx = 0, - .data = NULL, - .data_len = 0, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 0, FID_LATENCY_FEATURE, 0, 0 | cfg.perf_monitor, + 0 | cfg.cmd_mask, + 0 | (cfg.read_threshold & 0xff) | + ((cfg.write_threshold & 0xff) << 8) | + ((cfg.de_allocate_trim_threshold & 0xff) << 16), + 0, 0, NULL, 0, &result); if (!err) - printf("%s have done successfully. result = %#" PRIx32 ".\n", cmd->name, result); + printf("%s have done successfully. result = %#" PRIx32 ".\n", acmd->name, result); else if (err > 0) nvme_show_status(err); else - nvme_show_error("%s: %s", cmd->name, nvme_strerror(errno)); + nvme_show_error("%s: %s", acmd->name, nvme_strerror(errno)); return err; } -static int mb_get_latency_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int mb_get_latency_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { int err = 0; @@ -1847,9 +1766,10 @@ static int mb_get_latency_feature(int argc, char **argv, struct command *cmd, st OPT_ARGS(opts) = { OPT_END()}; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; - err = parse_and_open(&dev, argc, argv, cmd->help, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, acmd->help, opts); if (err) return err; @@ -1857,9 +1777,10 @@ static int mb_get_latency_feature(int argc, char **argv, struct command *cmd, st uint32_t result = 0; - err = nvme_get_features_simple(dev_fd(dev), FID_LATENCY_FEATURE, 0, &result); + err = nvme_get_features_simple(hdl, FID_LATENCY_FEATURE, + NVME_GET_FEATURES_SEL_CURRENT, &result); if (!err) { - printf("%s have done successfully. result = %#" PRIx32 ".\n", cmd->name, result); + printf("%s have done successfully. result = %#" PRIx32 ".\n", acmd->name, result); printf("latency statistics enable status = %d\n", (result & (0x01 << 0)) >> 0); printf("high latency enable status = %d\n", (result & (0x01 << 1)) >> 1); @@ -1875,7 +1796,7 @@ static int mb_get_latency_feature(int argc, char **argv, struct command *cmd, st } else if (err > 0) { nvme_show_status(err); } else { - nvme_show_error("%s: %s", cmd->name, nvme_strerror(errno)); + nvme_show_error("%s: %s", acmd->name, nvme_strerror(errno)); } return err; @@ -1981,7 +1902,7 @@ static void latency_stats_print(struct latency_stats *log, const char *devname) } } -static int mb_get_latency_stats(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int mb_get_latency_stats(int argc, char **argv, struct command *acmd, struct plugin *plugin) { // Get the configuration @@ -1998,9 +1919,10 @@ static int mb_get_latency_stats(int argc, char **argv, struct command *cmd, stru "dump the whole log buffer in binary format"), OPT_END()}; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; - int err = parse_and_open(&dev, argc, argv, cmd->help, opts); + int err = parse_and_open(&ctx, &hdl, argc, argv, acmd->help, opts); if (err) return err; @@ -2009,17 +1931,16 @@ static int mb_get_latency_stats(int argc, char **argv, struct command *cmd, stru struct latency_stats log = {0}; - err = nvme_get_log_simple(dev_fd(dev), LID_LATENCY_STATISTICS, sizeof(struct latency_stats), - &log); + err = nvme_get_log_simple(hdl, LID_LATENCY_STATISTICS, &log, sizeof(struct latency_stats)); if (!err) { if (!cfg.raw_binary) - latency_stats_print(&log, dev->name); + latency_stats_print(&log, nvme_transport_handle_get_name(hdl)); else d_raw((unsigned char *)&log, sizeof(struct latency_stats)); } else if (err > 0) { nvme_show_status(err); } else { - nvme_show_error("%s: %s", cmd->name, nvme_strerror(errno)); + nvme_show_error("%s: %s", acmd->name, nvme_strerror(errno)); } return err; @@ -2086,7 +2007,7 @@ static void high_latency_log_print(struct high_latency_log *log, const char *dev } } -static int mb_get_high_latency_log(int argc, char **argv, struct command *cmd, +static int mb_get_high_latency_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { // Get the configuration @@ -2104,10 +2025,10 @@ static int mb_get_high_latency_log(int argc, char **argv, struct command *cmd, "dump the whole log buffer in binary format"), OPT_END()}; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - - int err = parse_and_open(&dev, argc, argv, cmd->help, opts); + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + int err = parse_and_open(&ctx, &hdl, argc, argv, acmd->help, opts); if (err) return err; @@ -2115,17 +2036,17 @@ static int mb_get_high_latency_log(int argc, char **argv, struct command *cmd, struct high_latency_log log = {0}; - err = nvme_get_log_simple(dev_fd(dev), LID_HIGH_LATENCY_LOG, - sizeof(struct high_latency_log), &log); + err = nvme_get_log_simple(hdl, LID_HIGH_LATENCY_LOG, + &log, sizeof(struct high_latency_log)); if (!err) { if (!cfg.raw_binary) - high_latency_log_print(&log, dev->name); + high_latency_log_print(&log, nvme_transport_handle_get_name(hdl)); else d_raw((unsigned char *)&log, sizeof(struct high_latency_log)); } else if (err > 0) { nvme_show_status(err); } else { - nvme_show_error("%s: %s", cmd->name, nvme_strerror(errno)); + nvme_show_error("%s: %s", acmd->name, nvme_strerror(errno)); } return err; @@ -2328,7 +2249,7 @@ static void performance_stats_print(struct performance_stats *log, const char *d } } -static int mb_get_performance_stats(int argc, char **argv, struct command *cmd, +static int mb_get_performance_stats(int argc, char **argv, struct command *acmd, struct plugin *plugin) { // Get the configuration @@ -2351,9 +2272,10 @@ static int mb_get_performance_stats(int argc, char **argv, struct command *cmd, "dump the whole log buffer in binary format"), OPT_END()}; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; - int err = parse_and_open(&dev, argc, argv, cmd->help, opts); + int err = parse_and_open(&ctx, &hdl, argc, argv, acmd->help, opts); if (err) return err; @@ -2373,16 +2295,16 @@ static int mb_get_performance_stats(int argc, char **argv, struct command *cmd, int xfer_size = (cfg.duration % 2) > 0 ? (4 + (cfg.duration + 1) * sizeof(struct performance_stats_timestamp)) : log_size; - err = nvme_get_log_simple(dev_fd(dev), LID_PERFORMANCE_STATISTICS, xfer_size, &log); + err = nvme_get_log_simple(hdl, LID_PERFORMANCE_STATISTICS, &log, xfer_size); if (!err) { if (!cfg.raw_binary) - performance_stats_print(&log, dev->name, cfg.duration); + performance_stats_print(&log, nvme_transport_handle_get_name(hdl), cfg.duration); else d_raw((unsigned char *)&log, log_size); } else if (err > 0) { nvme_show_status(err); } else { - nvme_show_error("%s: %s", cmd->name, nvme_strerror(errno)); + nvme_show_error("%s: %s", acmd->name, nvme_strerror(errno)); } return err; diff --git a/plugins/micron/micron-nvme.c b/plugins/micron/micron-nvme.c index 13df5ac93a..1bb100dd7f 100644 --- a/plugins/micron/micron-nvme.c +++ b/plugins/micron/micron-nvme.c @@ -389,14 +389,14 @@ static int SetupDebugDataDirectories(char *strSN, char *strFilePath, return err; } -static int GetLogPageSize(int nFD, unsigned char ucLogID, int *nLogSize) +static int GetLogPageSize(struct nvme_transport_handle *hdl, unsigned char ucLogID, int *nLogSize) { int err = 0; unsigned char pTmpBuf[CommonChunkSize] = { 0 }; struct LogPageHeader_t *pLogHeader = NULL; if (ucLogID == 0xC1 || ucLogID == 0xC2 || ucLogID == 0xC4) { - err = nvme_get_log_simple(nFD, ucLogID, CommonChunkSize, pTmpBuf); + err = nvme_get_log_simple(hdl, ucLogID, pTmpBuf, CommonChunkSize); if (!err) { pLogHeader = (struct LogPageHeader_t *) pTmpBuf; struct LogPageHeader_t *pLogHeader1 = (struct LogPageHeader_t *) pLogHeader; @@ -416,8 +416,8 @@ static int GetLogPageSize(int nFD, unsigned char ucLogID, int *nLogSize) return err; } -static int NVMEGetLogPage(int nFD, unsigned char ucLogID, unsigned char *pBuffer, int nBuffSize, - int offset) +static int NVMEGetLogPage(struct nvme_transport_handle *hdl, unsigned char ucLogID, unsigned char *pBuffer, int nBuffSize, + int offset) { int err = 0; struct nvme_passthru_cmd cmd = { 0 }; @@ -468,7 +468,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_admin_passthru(nFD, &cmd, NULL); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); ullBytesRead += uiXferDwords * 4; if (ucLogID == 0x07 || ucLogID == 0x08 || ucLogID == 0xE9) pTempPtr = pBuffer + (ullBytesRead - offset); @@ -479,8 +479,8 @@ static int NVMEGetLogPage(int nFD, unsigned char ucLogID, unsigned char *pBuffer return err; } -static int NVMEResetLog(int nFD, unsigned char ucLogID, int nBufferSize, - long long llMaxSize) +static int NVMEResetLog(struct nvme_transport_handle *hdl, unsigned char ucLogID, int nBufferSize, + long long llMaxSize) { unsigned int *pBuffer = NULL; int err = 0; @@ -490,7 +490,7 @@ static int NVMEResetLog(int nFD, unsigned char ucLogID, int nBufferSize, return err; while (!err && llMaxSize > 0) { - err = NVMEGetLogPage(nFD, ucLogID, (unsigned char *)pBuffer, nBufferSize, 0); + err = NVMEGetLogPage(hdl, ucLogID, (unsigned char *)pBuffer, nBufferSize, 0); if (err) { free(pBuffer); return err; @@ -506,8 +506,8 @@ static int NVMEResetLog(int nFD, unsigned char ucLogID, int nBufferSize, return err; } -static int GetCommonLogPage(int nFD, unsigned char ucLogID, - unsigned char **pBuffer, int nBuffSize) +static int GetCommonLogPage(struct nvme_transport_handle *hdl, unsigned char ucLogID, + unsigned char **pBuffer, int nBuffSize) { unsigned char *pTempPtr = NULL; int err = 0; @@ -516,7 +516,7 @@ static int GetCommonLogPage(int nFD, unsigned char ucLogID, if (!pTempPtr) goto exit_status; memset(pTempPtr, 0, nBuffSize); - err = nvme_get_log_simple(nFD, ucLogID, nBuffSize, pTempPtr); + err = nvme_get_log_simple(hdl, ucLogID, pTempPtr, nBuffSize); *pBuffer = pTempPtr; exit_status: @@ -526,13 +526,14 @@ static int GetCommonLogPage(int nFD, unsigned char ucLogID, /* * Plugin Commands */ -static int micron_parse_options(struct nvme_dev **dev, int argc, char **argv, - const char *desc, +static int micron_parse_options(struct nvme_global_ctx **ctx, + struct nvme_transport_handle **hdl, int argc, + char **argv, const char *desc, struct argconfig_commandline_options *opts, enum eDriveModel *modelp) { int idx; - int err = parse_and_open(dev, argc, argv, desc, opts); + int err = parse_and_open(ctx, hdl, argc, argv, desc, opts); if (err) { perror("open"); @@ -548,18 +549,18 @@ static int micron_parse_options(struct nvme_dev **dev, int argc, char **argv, return 0; } -static int micron_fw_commit(int fd, int select) +static int micron_fw_commit(struct nvme_transport_handle *hdl, int select) { struct nvme_passthru_cmd cmd = { .opcode = nvme_admin_fw_commit, .cdw10 = 8, .cdw12 = select, }; - return ioctl(fd, NVME_IOCTL_ADMIN_CMD, &cmd); + return ioctl(nvme_transport_handle_get_fd(hdl), NVME_IOCTL_ADMIN_CMD, &cmd); } static int micron_selective_download(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { const char *desc = "This performs a selective firmware download, which allows the user to\n" @@ -570,11 +571,15 @@ static int micron_selective_download(int argc, char **argv, "ALL - This updates the eeprom, OOB, and main firmware"; const char *fw = "firmware file (required)"; const char *select = "FW Select (e.g., --select=ALL)"; - int xfer = 4096; - void *fw_buf; + + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + int selectNo, fw_fd, fw_size, err, offset = 0; - struct nvme_dev *dev; + struct nvme_passthru_cmd cmd; + int xfer = 4096; struct stat sb; + void *fw_buf; struct config { char *fw; @@ -592,13 +597,12 @@ static int micron_selective_download(int argc, char **argv, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; if (strlen(cfg.select) != 3) { fprintf(stderr, "Invalid select flag\n"); - dev_close(dev); return -EINVAL; } @@ -613,14 +617,12 @@ static int micron_selective_download(int argc, char **argv, selectNo = 26; } else { fprintf(stderr, "Invalid select flag\n"); - dev_close(dev); return -EINVAL; } fw_fd = open(cfg.fw, O_RDONLY); if (fw_fd < 0) { fprintf(stderr, "no firmware file provided\n"); - dev_close(dev); return -EINVAL; } @@ -652,17 +654,12 @@ static int micron_selective_download(int argc, char **argv, while (fw_size > 0) { xfer = min(xfer, fw_size); - struct nvme_fw_download_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .offset = offset, - .data_len = xfer, - .data = fw_buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - - err = nvme_fw_download(&args); + err = nvme_init_fw_download(&cmd, fw_buf, xfer, offset); + if (err) { + perror("fw-download"); + goto out_free; + } + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err < 0) { perror("fw-download"); goto out_free; @@ -675,7 +672,7 @@ static int micron_selective_download(int argc, char **argv, offset += xfer; } - err = micron_fw_commit(dev_fd(dev), selectNo); + err = micron_fw_commit(hdl, selectNo); if (err == 0x10B || err == 0x20B) { err = 0; @@ -687,25 +684,24 @@ static int micron_selective_download(int argc, char **argv, free(fw_buf); out: close(fw_fd); - dev_close(dev); return err; } static int micron_smbus_option(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { __u32 result = 0; __u32 cdw11 = 0; const char *desc = "Enable/Disable/Get status of SMBUS option on controller"; const char *option = "enable or disable or status"; const char *value = - "1 - hottest component temperature, 0 - composite temperature (default) for enable option, 0 (current), 1 (default), 2 (saved) for status options" - ; + "1 - hottest component temperature, 0 - composite temperature (default) for enable option, 0 (current), 1 (default), 2 (saved) for status options"; const char *save = "1 - persistent, 0 - non-persistent (default)"; int fid = MICRON_FEATURE_SMBUS_OPTION; enum eDriveModel model = UNKNOWN_MODEL; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err = 0; struct { @@ -727,40 +723,25 @@ static int micron_smbus_option(int argc, char **argv, OPT_END() }; - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + err = micron_parse_options(&ctx, &hdl, argc, argv, desc, opts, &model); if (err < 0) return err; if (model != M5407 && model != M5411 && model != M6003 && model != M6004) { printf("This option is not supported for specified drive\n"); - dev_close(dev); return err; } if (!strcmp(opt.option, "enable")) { cdw11 = opt.value << 1 | 1; - err = nvme_set_features_simple(dev_fd(dev), fid, 1, cdw11, opt.save, - &result); + err = nvme_set_features_simple(hdl, 1, fid, opt.save, cdw11, + &result); if (!err) printf("successfully enabled SMBus on drive\n"); else printf("Failed to enabled SMBus on drive\n"); } else if (!strcmp(opt.option, "status")) { - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = 1, - .sel = opt.value, - .cdw11 = 0, - .uuidx = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_get_features(&args); + err = nvme_get_features(hdl, 1, fid, opt.value, 0, 0, NULL, 0, &result); if (!err) printf("SMBus status on the drive: %s (returns %s temperature)\n", (result & 1) ? "enabled" : "disabled", @@ -769,8 +750,8 @@ static int micron_smbus_option(int argc, char **argv, printf("Failed to retrieve SMBus status on the drive\n"); } else if (!strcmp(opt.option, "disable")) { cdw11 = opt.value << 1 | 0; - err = nvme_set_features_simple(dev_fd(dev), fid, 1, cdw11, opt.save, - &result); + err = nvme_set_features_simple(hdl, 1, fid, opt.save, cdw11, + &result); if (!err) printf("Successfully disabled SMBus on drive\n"); else @@ -778,15 +759,13 @@ static int micron_smbus_option(int argc, char **argv, } else { printf("Invalid option %s, valid values are enable, disable or status\n", opt.option); - dev_close(dev); return -1; } - close(dev_fd(dev)); return err; } -static int micron_temp_stats(int argc, char **argv, struct command *cmd, +static int micron_temp_stats(int argc, char **argv, struct command *acmd, struct plugin *plugin) { @@ -804,14 +783,14 @@ static int micron_temp_stats(int argc, char **argv, struct command *cmd, bool is_json = false; struct json_object *root; struct json_object *logPages; - struct nvme_dev *dev; - + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; OPT_ARGS(opts) = { OPT_FMT("format", 'f', &cfg.fmt, fmt), OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { printf("\nDevice not found\n"); return -1; @@ -820,7 +799,7 @@ static int micron_temp_stats(int argc, char **argv, struct command *cmd, if (!strcmp(cfg.fmt, "json")) is_json = true; - err = nvme_get_log_smart(dev_fd(dev), 0xffffffff, false, &smart_log); + err = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log); if (!err) { temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]); temperature = temperature ? temperature - 273 : 0; @@ -856,7 +835,6 @@ static int micron_temp_stats(int argc, char **argv, struct command *cmd, printf("%-10s%d : %u C\n", "Temperature Sensor #", i + 1, tempSensors[i]); } } - dev_close(dev); return err; } @@ -922,11 +900,12 @@ struct pcie_error_counters { static int micron_pcie_stats(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { int i, err = 0, bus = 0, domain = 0, device = 0, function = 0, ctrlIdx; - char strTempFile[1024], strTempFile2[1024], command[1024]; - struct nvme_dev *dev; + char strTempFile[1024], strTempFile2[1024], cmdbuf[1024]; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; char *businfo = NULL; char *devicename = NULL; char tdevice[NAME_MAX] = { 0 }; @@ -956,7 +935,7 @@ static int micron_pcie_stats(int argc, char **argv, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { printf("\nDevice not found\n"); return -1; @@ -979,7 +958,7 @@ static int micron_pcie_stats(int argc, char **argv, admin_cmd.addr = (__u64)(uintptr_t)&pcie_error_counters; admin_cmd.data_len = sizeof(pcie_error_counters); admin_cmd.cdw10 = 1; - err = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); + err = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (!err) { counters = true; correctable_errors = 10; @@ -1019,9 +998,9 @@ static int micron_pcie_stats(int argc, char **argv, businfo = strrchr(strTempFile2, '/'); if (sscanf(businfo, "/%x:%x:%x.%x", &domain, &bus, &device, &function) != 4) domain = bus = device = function = 0; - sprintf(command, "setpci -s %x:%x.%x ECAP_AER+10.L", bus, device, + sprintf(cmdbuf, "setpci -s %x:%x.%x ECAP_AER+10.L", bus, device, function); - fp = popen(command, "r"); + fp = popen(cmdbuf, "r"); if (!fp) { printf("Failed to retrieve error count\n"); goto out; @@ -1034,9 +1013,9 @@ static int micron_pcie_stats(int argc, char **argv, } pclose(fp); - sprintf(command, "setpci -s %x:%x.%x ECAP_AER+0x4.L", bus, device, + sprintf(cmdbuf, "setpci -s %x:%x.%x ECAP_AER+0x4.L", bus, device, function); - fp = popen(command, "r"); + fp = popen(cmdbuf, "r"); if (!fp) { printf("Failed to retrieve error count\n"); goto out; @@ -1100,17 +1079,17 @@ static int micron_pcie_stats(int argc, char **argv, } out: - dev_close(dev); return err; } static int micron_clear_pcie_correctable_errors(int argc, char **argv, - struct command *cmd, + struct command *command, struct plugin *plugin) { int err = -EINVAL, bus, domain, device, function; - char strTempFile[1024], strTempFile2[1024], command[1024]; - struct nvme_dev *dev; + char strTempFile[1024], strTempFile2[1024], cmdbuf[1024]; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; char *businfo = NULL; char *devicename = NULL; char tdevice[PATH_MAX] = { 0 }; @@ -1128,7 +1107,7 @@ static int micron_clear_pcie_correctable_errors(int argc, char **argv, OPT_END() }; - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + err = micron_parse_options(&ctx, &hdl, argc, argv, desc, opts, &model); if (err < 0) return err; @@ -1137,8 +1116,8 @@ static int micron_clear_pcie_correctable_errors(int argc, char **argv, * If these fail, proceed with sysfs interface to set/clear bits */ if (model == M51CX || model == M51BY || model == M51CY) { - err = nvme_set_features_simple(dev_fd(dev), fid, 0, (1 << 31), false, - &result); + err = nvme_set_features_simple(hdl, 0, fid, false, (1 << 31), + &result); if (!err) err = (int)result; if (!err) { @@ -1149,7 +1128,7 @@ static int micron_clear_pcie_correctable_errors(int argc, char **argv, admin_cmd.opcode = 0xD6; admin_cmd.addr = 0; admin_cmd.cdw10 = 0; - err = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); + err = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (!err) { printf("Device correctable error counters are cleared!\n"); goto out; @@ -1196,19 +1175,19 @@ static int micron_clear_pcie_correctable_errors(int argc, char **argv, businfo = strrchr(strTempFile2, '/'); if (sscanf(businfo, "/%x:%x:%x.%x", &domain, &bus, &device, &function) != 4) domain = bus = device = function = 0; - sprintf(command, "setpci -s %x:%x.%x ECAP_AER+0x10.L=0xffffffff", bus, + sprintf(cmdbuf, "setpci -s %x:%x.%x ECAP_AER+0x10.L=0xffffffff", bus, device, function); err = -1; - fp = popen(command, "r"); + fp = popen(cmdbuf, "r"); if (!fp) { printf("Failed to clear error count\n"); goto out; } pclose(fp); - sprintf(command, "setpci -s %x:%x.%x ECAP_AER+0x10.L", bus, device, + sprintf(cmdbuf, "setpci -s %x:%x.%x ECAP_AER+0x10.L", bus, device, function); - fp = popen(command, "r"); + fp = popen(cmdbuf, "r"); if (!fp) { printf("Failed to retrieve error count\n"); goto out; @@ -1224,7 +1203,6 @@ static int micron_clear_pcie_correctable_errors(int argc, char **argv, printf("Device correctable errors detected: %s\n", correctable); err = 0; out: - dev_close(dev); return err; } @@ -1815,7 +1793,7 @@ static void print_hyperscale_nand_stats(__u8 *buf, bool is_json) static bool nsze_from_oacs;/* read nsze for now from idd[4059] */ static int micron_nand_stats(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { const char *desc = "Retrieve Micron NAND stats for the given device "; unsigned int extSmartLog[D0_log_size/sizeof(int)] = { 0 }; @@ -1823,7 +1801,8 @@ static int micron_nand_stats(int argc, char **argv, unsigned char logC0[C0_log_size] = { 0 }; enum eDriveModel eModel = UNKNOWN_MODEL; struct nvme_id_ctrl ctrl; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err, ctrlIdx; __u8 nsze; bool has_d0_log = true; @@ -1843,7 +1822,7 @@ static int micron_nand_stats(int argc, char **argv, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { printf("\nDevice not found\n"); return -1; @@ -1852,7 +1831,7 @@ static int micron_nand_stats(int argc, char **argv, if (!strcmp(cfg.fmt, "normal")) is_json = false; - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err) { printf("Error %d retrieving controller identification data\n", err); goto out; @@ -1868,14 +1847,14 @@ static int micron_nand_stats(int argc, char **argv, goto out; } - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err) { fprintf(stderr, "ERROR : identify_ctrl() failed with 0x%x\n", err); return -1; } if ((ctrl.vs[536] == MICRON_CUST_ID_GG) && (eModel == M51CX)) { - err = nvme_get_log_simple(dev_fd(dev), 0xC0, C0_log_size, logC0); + err = nvme_get_log_simple(hdl, 0xC0, logC0, C0_log_size); if (err == 0) { print_hyperscale_nand_stats((__u8 *)logC0, is_json); goto out; @@ -1885,12 +1864,12 @@ static int micron_nand_stats(int argc, char **argv, } } - err = nvme_get_log_simple(dev_fd(dev), 0xD0, D0_log_size, extSmartLog); + err = nvme_get_log_simple(hdl, 0xD0, extSmartLog, D0_log_size); has_d0_log = (err == 0); /* should check for firmware version if this log is supported or not */ if (eModel != M5407 && eModel != M5410) { - err = nvme_get_log_simple(dev_fd(dev), 0xFB, FB_log_size, logFB); + err = nvme_get_log_simple(hdl, 0xFB, logFB, FB_log_size); has_fb_log = !err; } @@ -1910,7 +1889,6 @@ static int micron_nand_stats(int argc, char **argv, err = -ENOTTY; } out: - dev_close(dev); if (err > 0) nvme_show_status(err); @@ -1967,14 +1945,15 @@ static void print_log(__u8 *buf, bool is_json, unsigned char ucLogID) } static int micron_smart_ext_log(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { const char *desc = "Retrieve extended SMART logs for the given device "; unsigned int extSmartLog[E1_log_size/sizeof(int)] = { 0 }; enum eDriveModel eModel = UNKNOWN_MODEL; int err = 0, ctrlIdx = 0; __u8 log_id; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; bool is_json = true; struct format { char *fmt; @@ -1988,7 +1967,7 @@ static int micron_smart_ext_log(int argc, char **argv, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { printf("\nDevice not found\n"); return -1; @@ -2009,23 +1988,24 @@ static int micron_smart_ext_log(int argc, char **argv, err = -1; goto out; } - err = nvme_get_log_simple(dev_fd(dev), log_id, E1_log_size, extSmartLog); + err = nvme_get_log_simple(hdl, log_id, extSmartLog, E1_log_size); if (!err) print_log((__u8 *)extSmartLog, is_json, log_id); out: - dev_close(dev); if (err > 0) nvme_show_status(err); return err; } -static int micron_work_load_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int micron_work_load_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Micron Workload logs for the given device "; unsigned int micronWorkLoadLog[C5_MicronWorkLoad_log_size/sizeof(int)] = { 0 }; enum eDriveModel eModel = UNKNOWN_MODEL; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + int err = 0, ctrlIdx = 0; bool is_json = true; struct format { @@ -2040,7 +2020,7 @@ static int micron_work_load_log(int argc, char **argv, struct command *cmd, stru OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { printf("\nDevice not found\n"); return -1; @@ -2053,8 +2033,8 @@ static int micron_work_load_log(int argc, char **argv, struct command *cmd, stru ctrlIdx = 0; eModel = GetDriveModel(ctrlIdx); if (eModel == M6001 || eModel == M6004 || eModel == M6003) { - err = nvme_get_log_simple(dev_fd(dev), 0xC5, - C5_MicronWorkLoad_log_size, micronWorkLoadLog); + err = nvme_get_log_simple(hdl, 0xC5, + micronWorkLoadLog, C5_MicronWorkLoad_log_size); if (!err) print_log((__u8 *)micronWorkLoadLog, is_json, 0xC5); } else { @@ -2064,21 +2044,22 @@ static int micron_work_load_log(int argc, char **argv, struct command *cmd, stru } out: - dev_close(dev); if (err > 0) nvme_show_status(err); return err; } static int micron_vendor_telemetry_log(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { const char *desc = "Retrieve Vendor Telemetry logs for the given device "; unsigned int vendorTelemetryLog[C6_log_size/sizeof(int)] = { 0 }; enum eDriveModel eModel = UNKNOWN_MODEL; int err = 0, ctrlIdx = 0; bool is_json = true; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct format { char *fmt; }; @@ -2091,7 +2072,7 @@ static int micron_vendor_telemetry_log(int argc, char **argv, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { printf("\nDevice not found\n"); return -1; @@ -2105,7 +2086,7 @@ static int micron_vendor_telemetry_log(int argc, char **argv, eModel = GetDriveModel(ctrlIdx); if (eModel == M6001 || eModel == M6004 || eModel == M6003) { - err = nvme_get_log_simple(dev_fd(dev), 0xC6, C6_log_size, vendorTelemetryLog); + err = nvme_get_log_simple(hdl, 0xC6, vendorTelemetryLog, C6_log_size); if (!err) print_log((__u8 *)vendorTelemetryLog, is_json, 0xC6); } else { @@ -2115,7 +2096,6 @@ static int micron_vendor_telemetry_log(int argc, char **argv, } out: - dev_close(dev); if (err > 0) nvme_show_status(err); return err; @@ -2201,16 +2181,16 @@ static void GetCtrlIDDInfo(const char *dir, struct nvme_id_ctrl *ctrlp) "nvme_controller_identify_data.bin", "id-ctrl"); } -static void GetSmartlogData(int fd, const char *dir) +static void GetSmartlogData(struct nvme_transport_handle *hdl, const char *dir) { struct nvme_smart_log smart_log; - if (!nvme_get_log_smart(fd, -1, false, &smart_log)) + if (!nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log)) WriteData((__u8 *)&smart_log, sizeof(smart_log), dir, "smart_data.bin", "smart log"); } -static void GetErrorlogData(int fd, int entries, const char *dir) +static void GetErrorlogData(struct nvme_transport_handle *hdl, int entries, const char *dir) { int logSize = entries * sizeof(struct nvme_error_log_page); struct nvme_error_log_page *error_log = @@ -2219,14 +2199,14 @@ static void GetErrorlogData(int fd, int entries, const char *dir) if (!error_log) return; - if (!nvme_get_log_error(fd, entries, false, error_log)) + if (!nvme_get_log_error(hdl, NVME_NSID_ALL, entries, error_log)) WriteData((__u8 *)error_log, logSize, dir, "error_information_log.bin", "error log"); free(error_log); } -static void GetGenericLogs(int fd, const char *dir) +static void GetGenericLogs(struct nvme_transport_handle *hdl, const char *dir) { struct nvme_self_test_log self_test_log; struct nvme_firmware_slot fw_log; @@ -2238,26 +2218,26 @@ static void GetGenericLogs(int fd, const char *dir) int err = 0; /* get self test log */ - if (!nvme_get_log_device_self_test(fd, &self_test_log)) + if (!nvme_get_log_device_self_test(hdl, &self_test_log)) WriteData((__u8 *)&self_test_log, sizeof(self_test_log), dir, "drive_self_test.bin", "self test log"); /* get fw slot info log */ - if (!nvme_get_log_fw_slot(fd, false, &fw_log)) + if (!nvme_get_log_fw_slot(hdl, false, &fw_log)) WriteData((__u8 *)&fw_log, sizeof(fw_log), dir, "firmware_slot_info_log.bin", "firmware log"); /* get effects log */ - if (!nvme_get_log_cmd_effects(fd, NVME_CSI_NVM, &effects)) + if (!nvme_get_log_cmd_effects(hdl, NVME_CSI_NVM, &effects)) WriteData((__u8 *)&effects, sizeof(effects), dir, "command_effects_log.bin", "effects log"); /* get persistent event log */ - (void)nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_RELEASE_CTX, - sizeof(pevent_log), &pevent_log); + (void)nvme_get_log_persistent_event(hdl, NVME_PEVENT_LOG_RELEASE_CTX, + &pevent_log, sizeof(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); + err = nvme_get_log_persistent_event(hdl, NVME_PEVENT_LOG_EST_CTX_AND_READ, + &pevent_log, sizeof(pevent_log)); if (err) { fprintf(stderr, "Setting persistent event log read ctx failed (ignored)!\n"); return; @@ -2270,19 +2250,19 @@ static void GetGenericLogs(int fd, const char *dir) return; } - err = nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_READ, - log_len, pevent_log_info); + err = nvme_get_log_persistent_event(hdl, NVME_PEVENT_LOG_READ, + pevent_log_info, log_len); if (!err) WriteData((__u8 *)pevent_log_info, log_len, dir, "persistent_event_log.bin", "persistent event log"); } -static void GetNSIDDInfo(int fd, const char *dir, int nsid) +static void GetNSIDDInfo(struct nvme_transport_handle *hdl, const char *dir, int nsid) { char file[PATH_MAX] = { 0 }; struct nvme_id_ns ns; - if (!nvme_identify_ns(fd, nsid, &ns)) { + if (!nvme_identify_ns(hdl, nsid, &ns)) { sprintf(file, "identify_namespace_%d_data.bin", nsid); WriteData((__u8 *)&ns, sizeof(ns), dir, file, "id-ns"); } @@ -2328,7 +2308,7 @@ static void GetOSConfig(const char *strOSDirName) } } -static int micron_telemetry_log(int fd, __u8 type, __u8 **data, +static int micron_telemetry_log(struct nvme_transport_handle *hdl, __u8 type, __u8 **data, int *logSize, int da) { int err, bs = 512, offset = bs; @@ -2340,9 +2320,9 @@ static int micron_telemetry_log(int fd, __u8 type, __u8 **data, if (!buffer) return -1; if (ctrl_init) - err = nvme_get_log_telemetry_ctrl(fd, true, 0, bs, buffer); + err = nvme_get_log_telemetry_ctrl(hdl, true, 0, buffer, bs); else - err = nvme_get_log_telemetry_host(fd, 0, bs, buffer); + err = nvme_get_log_telemetry_host(hdl, 0, buffer, bs); if (err) { fprintf(stderr, "Failed to get telemetry log header for 0x%X\n", type); free(buffer); @@ -2370,9 +2350,9 @@ static int micron_telemetry_log(int fd, __u8 type, __u8 **data, if (buffer) { while (!err && offset != *logSize) { if (ctrl_init) - err = nvme_get_log_telemetry_ctrl(fd, true, 0, *logSize, buffer + offset); + err = nvme_get_log_telemetry_ctrl(hdl, true, 0, buffer + offset, *logSize); else - err = nvme_get_log_telemetry_host(fd, 0, *logSize, buffer + offset); + err = nvme_get_log_telemetry_host(hdl, 0, buffer + offset, *logSize); offset += bs; } } @@ -2387,7 +2367,7 @@ static int micron_telemetry_log(int fd, __u8 type, __u8 **data, return err; } -static int GetTelemetryData(int fd, const char *dir) +static int GetTelemetryData(struct nvme_transport_handle *hdl, const char *dir) { unsigned char *buffer = NULL; int i, err, logSize = 0; @@ -2401,7 +2381,7 @@ static int GetTelemetryData(int fd, const char *dir) }; for (i = 0; i < (int)(ARRAY_SIZE(tmap)); i++) { - err = micron_telemetry_log(fd, tmap[i].log, &buffer, &logSize, 0); + err = micron_telemetry_log(hdl, tmap[i].log, &buffer, &logSize, 0); if (!err && logSize > 0 && buffer) { sprintf(msg, "telemetry log: 0x%X", tmap[i].log); WriteData(buffer, logSize, dir, tmap[i].file, msg); @@ -2413,7 +2393,7 @@ static int GetTelemetryData(int fd, const char *dir) return err; } -static int GetFeatureSettings(int fd, const char *dir) +static int GetFeatureSettings(struct nvme_transport_handle *hdl, const char *dir) { unsigned char *bufp, buf[4096] = { 0 }; int i, err, len, errcnt = 0; @@ -2446,21 +2426,8 @@ static int GetFeatureSettings(int fd, const char *dir) len = 0; bufp = NULL; } - - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = fmap[i].id, - .nsid = 1, - .sel = 0, - .cdw11 = 0x0, - .uuidx = 0, - .data_len = len, - .data = bufp, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &attrVal, - }; - err = nvme_get_features(&args); + err = nvme_get_features(hdl, 1, fmap[i].id, 0, 0x0, 0, bufp, len, + &attrVal); if (!err) { sprintf(msg, "feature: 0x%X", fmap[i].id); WriteData((__u8 *)&attrVal, sizeof(attrVal), dir, fmap[i].file, msg); @@ -2475,7 +2442,7 @@ static int GetFeatureSettings(int fd, const char *dir) return (int)(errcnt == ARRAY_SIZE(fmap)); } -static int micron_drive_info(int argc, char **argv, struct command *cmd, +static int micron_drive_info(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get drive HW information"; @@ -2495,7 +2462,8 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd, bool is_json = false; struct json_object *root; struct json_object *driveInfo; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct format { char *fmt; }; @@ -2511,19 +2479,17 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd, OPT_END() }; - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + err = micron_parse_options(&ctx, &hdl, argc, argv, desc, opts, &model); if (err < 0) return err; if (model == UNKNOWN_MODEL) { fprintf(stderr, "ERROR : Unsupported drive for vs-drive-info cmd"); - dev_close(dev); return -1; } if (strcmp(cfg.fmt, "normal") || strcmp(cfg.fmt, "json")) { fprintf(stderr, "Invalid output format\n"); - dev_close(dev); return -1; } @@ -2535,17 +2501,15 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd, admin_cmd.addr = (__u64) (uintptr_t) &dinfo; admin_cmd.data_len = (__u32)sizeof(dinfo); admin_cmd.cdw12 = 3; - err = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); + err = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (err) { fprintf(stderr, "ERROR : drive-info opcode failed with 0x%x\n", err); - dev_close(dev); return -1; } } else { - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err) { fprintf(stderr, "ERROR : identify_ctrl() failed with 0x%x\n", err); - dev_close(dev); return -1; } dinfo.hw_ver_major = ctrl.vs[820]; @@ -2555,7 +2519,7 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd, } if ((custId == MICRON_CUST_ID_GG) && (model == M51CX)) { - err = nvme_get_log_simple(dev_fd(dev), 0xC0, C0_log_size, logC0); + err = nvme_get_log_simple(hdl, 0xC0, logC0, C0_log_size); if (err == 0) { dinfo.bs_ver_major = *((__u16 *)(logC0+300)); dinfo.bs_ver_minor = *((__u16 *)(logC0+302)); @@ -2653,19 +2617,18 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd, } - dev_close(dev); return 0; } static int micron_cloud_ssd_plugin_version(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { printf("nvme-cli Micron cloud SSD plugin version: %s.%s\n", __version_major, __version_minor); return 0; } -static int micron_plugin_version(int argc, char **argv, struct command *cmd, +static int micron_plugin_version(int argc, char **argv, struct command *acmd, struct plugin *plugin) { printf("nvme-cli Micron plugin version: %s.%s.%s\n", @@ -2807,7 +2770,7 @@ static void micron_fw_activation_history_header_print(void) printf("__________|___________|_________|__________|___________|________|________|________\n"); } -static int micron_fw_activation_history(int argc, char **argv, struct command *cmd, +static int micron_fw_activation_history(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Firmware Activation history of the given drive"; @@ -2815,7 +2778,8 @@ static int micron_fw_activation_history(int argc, char **argv, struct command *c int count = 0; unsigned int logC2[C2_log_size/sizeof(int)] = { 0 }; enum eDriveModel eModel = UNKNOWN_MODEL; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; bool is_json = false; struct json_object *root, *fw_act, *element; @@ -2834,7 +2798,7 @@ static int micron_fw_activation_history(int argc, char **argv, struct command *c OPT_END() }; - err = micron_parse_options(&dev, argc, argv, desc, opts, &eModel); + err = micron_parse_options(&ctx, &hdl, argc, argv, desc, opts, &eModel); if (err < 0) return -1; @@ -2850,7 +2814,7 @@ static int micron_fw_activation_history(int argc, char **argv, struct command *c goto out; } - err = nvme_get_log_simple(dev_fd(dev), 0xC2, C2_log_size, logC2); + err = nvme_get_log_simple(hdl, 0xC2, logC2, C2_log_size); if (err) { fprintf(stderr, "Failed to retrieve fw activation history log, error: %x\n", err); goto out; @@ -2900,21 +2864,20 @@ static int micron_fw_activation_history(int argc, char **argv, struct command *c } } out: - dev_close(dev); return err; } #define MICRON_FID_LATENCY_MONITOR 0xD0 #define MICRON_LOG_LATENCY_MONITOR 0xD1 -static int micron_latency_stats_track(int argc, char **argv, struct command *cmd, +static int micron_latency_stats_track(int argc, char **argv, struct command *acmd, struct plugin *plugin) { int err = 0; __u32 result = 0; const char *desc = "Enable, Disable or Get cmd latency monitoring stats"; const char *option = "enable or disable or status, default is status"; - const char *command = + const char *cmdstr = "commands to monitor for - all|read|write|trim, default is all i.e, enabled for all commands" ; const char *thrtime = @@ -2926,7 +2889,8 @@ static int micron_latency_stats_track(int argc, char **argv, struct command *cmd uint32_t command_mask = 0x7; /* 1:read 2:write 4:trim 7:all */ uint32_t timing_mask = 0x08080800; /* R[31-24]:W[23:16]:T[15:8]:0 */ uint32_t enable = 2; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct { char *option; char *command; @@ -2939,13 +2903,13 @@ static int micron_latency_stats_track(int argc, char **argv, struct command *cmd OPT_ARGS(opts) = { OPT_STRING("option", 'o', "option", &opt.option, option), - OPT_STRING("command", 'c', "command", &opt.command, command), + OPT_STRING("command", 'c', "command", &opt.command, cmdstr), OPT_UINT("threshold", 't', &opt.threshold, thrtime), OPT_END() }; - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + err = micron_parse_options(&ctx, &hdl, argc, argv, desc, opts, &model); if (err < 0) return -1; @@ -2955,28 +2919,12 @@ static int micron_latency_stats_track(int argc, char **argv, struct command *cmd enable = 0; } else if (strcmp(opt.option, "status")) { printf("Invalid control option %s specified\n", opt.option); - dev_close(dev); return -1; } - struct nvme_get_features_args g_args = { - .args_size = sizeof(g_args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = 0, - .sel = 0, - .cdw11 = 0, - .uuidx = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_get_features(&g_args); + err = nvme_get_features(hdl, 0, fid, 0, 0, 0, NULL, 0, &result); if (err) { printf("Failed to retrieve latency monitoring feature status\n"); - dev_close(dev); return err; } @@ -2998,7 +2946,6 @@ static int micron_latency_stats_track(int argc, char **argv, struct command *cmd } else if (!result) { printf("\n"); } - dev_close(dev); return err; } @@ -3006,12 +2953,10 @@ static int micron_latency_stats_track(int argc, char **argv, struct command *cmd if (enable == 1) { if (opt.threshold > 2550) { printf("The maximum threshold value cannot be more than 2550 ms\n"); - dev_close(dev); return -1; } else if (opt.threshold % 10) { /* timing mask is in terms of 10ms units, so min allowed is 10ms */ printf("The threshold value should be multiple of 10 ms\n"); - dev_close(dev); return -1; } opt.threshold /= 10; @@ -3030,27 +2975,11 @@ static int micron_latency_stats_track(int argc, char **argv, struct command *cmd } else if (strcmp(opt.command, "all")) { printf("Invalid command %s specified for option %s\n", opt.command, opt.option); - dev_close(dev); return -1; } - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = MICRON_FID_LATENCY_MONITOR, - .nsid = 0, - .cdw11 = enable, - .cdw12 = command_mask, - .save = 1, - .uuidx = 0, - .cdw13 = timing_mask, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 0, MICRON_FID_LATENCY_MONITOR, 1, enable, + command_mask, timing_mask, 0, 0, NULL, 0, &result); if (!err) { printf("Successfully %sd latency monitoring for %s commands with %dms threshold\n", opt.option, opt.command, !opt.threshold ? 800 : opt.threshold * 10); @@ -3059,12 +2988,11 @@ static int micron_latency_stats_track(int argc, char **argv, struct command *cmd opt.option, opt.command, !opt.threshold ? 800 : opt.threshold * 10); } - dev_close(dev); return err; } -static int micron_latency_stats_logs(int argc, char **argv, struct command *cmd, +static int micron_latency_stats_logs(int argc, char **argv, struct command *acmd, struct plugin *plugin) { #define LATENCY_LOG_ENTRIES 16 @@ -3100,7 +3028,8 @@ static int micron_latency_stats_logs(int argc, char **argv, struct command *cmd, uint32_t rfu[6]; } log[LATENCY_LOG_ENTRIES]; enum eDriveModel model = UNKNOWN_MODEL; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err = -1; const char *desc = "Display Latency tracking log information"; @@ -3108,15 +3037,14 @@ static int micron_latency_stats_logs(int argc, char **argv, struct command *cmd, OPT_END() }; - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + err = micron_parse_options(&ctx, &hdl, argc, argv, desc, opts, &model); if (err) return err; memset(&log, 0, sizeof(log)); - err = nvme_get_log_simple(dev_fd(dev), 0xD1, sizeof(log), &log); + err = nvme_get_log_simple(hdl, 0xD1, &log, sizeof(log)); if (err) { if (err < 0) printf("Unable to retrieve latency stats log the drive\n"); - dev_close(dev); return err; } /* print header and each log entry */ @@ -3129,17 +3057,17 @@ static int micron_latency_stats_logs(int argc, char **argv, struct command *cmd, log[i].slba_low, log[i].slba_high, log[i].nlb, log[i].deac, log[i].prinfo, log[i].fua, log[i].lr); printf("\n"); - dev_close(dev); return err; } -static int micron_latency_stats_info(int argc, char **argv, struct command *cmd, +static int micron_latency_stats_info(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "display command latency statistics"; - const char *command = "command to display stats - all|read|write|trim, default is all"; + const char *cmdstr = "command to display stats - all|read|write|trim, default is all"; int err = 0; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; enum eDriveModel model = UNKNOWN_MODEL; #define LATENCY_BUCKET_COUNT 32 #define LATENCY_BUCKET_RSVD 32 @@ -3178,11 +3106,11 @@ static int micron_latency_stats_info(int argc, char **argv, struct command *cmd, char *cmd_str = "All"; OPT_ARGS(opts) = { - OPT_STRING("command", 'c', "command", &opt.command, command), + OPT_STRING("command", 'c', "command", &opt.command, cmdstr), OPT_END() }; - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + err = micron_parse_options(&ctx, &hdl, argc, argv, desc, opts, &model); if (err < 0) return err; if (!strcmp(opt.command, "read")) { @@ -3196,16 +3124,14 @@ static int micron_latency_stats_info(int argc, char **argv, struct command *cmd, cmd_str = "Trim"; } else if (strcmp(opt.command, "all")) { printf("Invalid command option %s to display latency stats\n", opt.command); - dev_close(dev); - return -1; + return -1; } memset(&log, 0, sizeof(log)); - err = nvme_get_log_simple(dev_fd(dev), 0xD0, sizeof(log), &log); + err = nvme_get_log_simple(hdl, 0xD0, &log, sizeof(log)); if (err) { if (err < 0) printf("Unable to retrieve latency stats log the drive\n"); - dev_close(dev); return err; } printf("Micron IO %s Command Latency Statistics\n" @@ -3227,11 +3153,10 @@ static int micron_latency_stats_info(int argc, char **argv, struct command *cmd, sprintf(end, "%u%s", thresholds[b].end, thresholds[b].unit); printf("%2d %8s %8s %8"PRIu64"\n", bucket, start, end, cmd_stats[b]); } - dev_close(dev); return err; } -static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *cmd, +static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Smart or Extended Smart Health log for the given device "; @@ -3239,7 +3164,8 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c unsigned int logFB[FB_log_size/sizeof(int)] = { 0 }; struct nvme_id_ctrl ctrl; enum eDriveModel eModel = UNKNOWN_MODEL; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; bool is_json = true; nsze_from_oacs = false; struct format { @@ -3256,7 +3182,7 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c OPT_END() }; - err = micron_parse_options(&dev, argc, argv, desc, opts, &eModel); + err = micron_parse_options(&ctx, &hdl, argc, argv, desc, opts, &eModel); if (err < 0) return -1; @@ -3268,9 +3194,9 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c __u8 spec = (eModel == M5410) ? 0 : 1; __u8 nsze; - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (!err) - err = nvme_get_log_simple(dev_fd(dev), 0xFB, FB_log_size, logFB); + err = nvme_get_log_simple(hdl, 0xFB, logFB, FB_log_size); if (err) { if (err < 0) printf("Unable to retrieve smart log 0xFB for the drive\n"); @@ -3292,55 +3218,53 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c goto out; } - err = nvme_get_log_simple(dev_fd(dev), 0xC0, C0_log_size, logC0); + err = nvme_get_log_simple(hdl, 0xC0, logC0, C0_log_size); if (!err) print_smart_cloud_health_log((__u8 *)logC0, is_json, eModel); else if (err < 0) printf("Unable to retrieve extended smart log 0xC0 for the drive\n"); out: - dev_close(dev); if (err > 0) nvme_show_status(err); return err; } static int micron_clr_fw_activation_history(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { const char *desc = "Clear FW activation history"; __u32 result = 0; __u8 fid = MICRON_FEATURE_CLEAR_FW_ACTIVATION_HISTORY; enum eDriveModel model = UNKNOWN_MODEL; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; OPT_ARGS(opts) = { OPT_END() }; int err = 0; - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + err = micron_parse_options(&ctx, &hdl, argc, argv, desc, opts, &model); if (err < 0) return err; if ((model != M51CX) && (model != M51BY) && (model != M51CY) && (model != M6003) && (model != M6004)) { printf("This option is not supported for specified drive\n"); - dev_close(dev); return err; } - err = nvme_set_features_simple(dev_fd(dev), fid, 1 << 31, 0, 0, &result); + err = nvme_set_features_simple(hdl, 1 << 31, fid, 0, 0, &result); if (!err) err = (int)result; else printf("Failed to clear fw activation history, error = 0x%x\n", err); - dev_close(dev); return err; } static int micron_telemetry_cntrl_option(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { int err = 0; __u32 result = 0; @@ -3353,7 +3277,8 @@ static int micron_telemetry_cntrl_option(int argc, char **argv, int fid = MICRON_FEATURE_TELEMETRY_CONTROL_OPTION; enum eDriveModel model = UNKNOWN_MODEL; struct nvme_id_ctrl ctrl = { 0 }; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct { char *option; @@ -3369,75 +3294,33 @@ static int micron_telemetry_cntrl_option(int argc, char **argv, OPT_END() }; - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + err = micron_parse_options(&ctx, &hdl, argc, argv, desc, opts, &model); if (err < 0) return -1; - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if ((ctrl.lpa & 0x8) != 0x8) { printf("drive doesn't support host/controller generated telemetry logs\n"); - dev_close(dev); return err; } if (!strcmp(opt.option, "enable")) { - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = 1, - .cdw11 = 1, - .cdw12 = 0, - .save = (opt.select & 0x1), - .uuidx = 0, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 1, fid, (opt.select & 0x1), 1, 0, 0, 0, 0, + NULL, 0, &result); if (!err) printf("successfully set controller telemetry option\n"); else printf("Failed to set controller telemetry option\n"); } else if (!strcmp(opt.option, "disable")) { - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = 1, - .cdw11 = 0, - .cdw12 = 0, - .save = (opt.select & 0x1), - .uuidx = 0, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 1, fid, (opt.select & 0x1), 0, 0, 0, 0, 0, + NULL, 0, &result); if (!err) printf("successfully disabled controller telemetry option\n"); else printf("Failed to disable controller telemetry option\n"); } else if (!strcmp(opt.option, "status")) { - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = 1, - .sel = opt.select & 0x3, - .cdw11 = 0, - .uuidx = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_get_features(&args); + err = nvme_get_features(hdl, 1, fid, opt.select & 0x3, 0, 0, NULL, 0, + &result); if (!err) printf("Controller telemetry option : %s\n", (result) ? "enabled" : "disabled"); @@ -3446,11 +3329,9 @@ static int micron_telemetry_cntrl_option(int argc, char **argv, } else { printf("invalid option %s, valid values are enable,disable or status\n", opt.option); - dev_close(dev); return -1; } - dev_close(dev); return err; } @@ -3469,28 +3350,12 @@ struct micron_common_log_header { }; /* helper function to retrieve logs with specific offset and max chunk size */ -int nvme_get_log_lpo(int fd, __u8 log_id, __u32 lpo, __u32 chunk, - __u32 data_len, void *data) +int nvme_get_log_lpo(struct nvme_transport_handle *hdl, __u8 log_id, __u32 lpo, __u32 chunk, + __u32 data_len, void *data) { __u32 offset = lpo, xfer_len = data_len; + struct nvme_passthru_cmd cmd; void *ptr = data; - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = ptr, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = log_id, - .len = xfer_len, - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; int ret = 0; /* divide data into multiple chunks */ @@ -3499,10 +3364,10 @@ int nvme_get_log_lpo(int fd, __u8 log_id, __u32 lpo, __u32 chunk, if (xfer_len > chunk) xfer_len = chunk; - args.lpo = offset; - args.log = ptr; - args.len = xfer_len; - ret = nvme_get_log(&args); + nvme_init_get_log(&cmd, NVME_NSID_ALL, log_id, NVME_CSI_NVM, + ptr, xfer_len); + nvme_init_get_log_lpo(&cmd, lpo); + ret = nvme_get_log(hdl, &cmd, false, xfer_len, NULL); if (ret) return ret; offset += xfer_len; @@ -3512,7 +3377,7 @@ int nvme_get_log_lpo(int fd, __u8 log_id, __u32 lpo, __u32 chunk, } /* retrieves logs with common log format */ -static int get_common_log(int fd, uint8_t id, uint8_t **buf, int *size) +static int get_common_log(struct nvme_transport_handle *hdl, uint8_t id, uint8_t **buf, int *size) { struct micron_common_log_header hdr = { 0 }; int log_size = sizeof(hdr), first = 0, second = 0; @@ -3520,7 +3385,7 @@ static int get_common_log(int fd, uint8_t id, uint8_t **buf, int *size) int ret = -1; int chunk = 0x4000; /* max chunk size to be used for these logs */ - ret = nvme_get_log_simple(fd, id, sizeof(hdr), &hdr); + ret = nvme_get_log_simple(hdl, id, &hdr, sizeof(hdr)); if (ret) { fprintf(stderr, "pull hdr failed for %u with error: 0x%x\n", id, ret); return ret; @@ -3555,7 +3420,7 @@ static int get_common_log(int fd, uint8_t id, uint8_t **buf, int *size) return -ENOMEM; } memcpy(buffer, &hdr, sizeof(hdr)); - ret = nvme_get_log_lpo(fd, id, sizeof(hdr), chunk, hdr.log_size, + ret = nvme_get_log_lpo(hdl, id, sizeof(hdr), chunk, hdr.log_size, buffer + sizeof(hdr)); if (!ret) log_size += hdr.log_size; @@ -3578,7 +3443,7 @@ static int get_common_log(int fd, uint8_t id, uint8_t **buf, int *size) second = hdr.write_pointer - sizeof(hdr); if (first) { - ret = nvme_get_log_lpo(fd, id, hdr.write_pointer, chunk, first, + ret = nvme_get_log_lpo(hdl, id, hdr.write_pointer, chunk, first, buffer + sizeof(hdr)); if (ret) { free(buffer); @@ -3588,7 +3453,7 @@ static int get_common_log(int fd, uint8_t id, uint8_t **buf, int *size) log_size += first; } if (second) { - ret = nvme_get_log_lpo(fd, id, sizeof(hdr), chunk, second, + ret = nvme_get_log_lpo(hdl, id, sizeof(hdr), chunk, second, buffer + sizeof(hdr) + first); if (ret) { fprintf(stderr, "failed to get log: 0x%X\n", id); @@ -3603,7 +3468,7 @@ static int get_common_log(int fd, uint8_t id, uint8_t **buf, int *size) return ret; } -static int GetOcpEnhancedTelemetryLog(int fd, const char *dir, int nLogID) +static int GetOcpEnhancedTelemetryLog(struct nvme_transport_handle *hdl, const char *dir, int nLogID) { int err = 0; unsigned char *pTelemetryDataHeader = 0; @@ -3619,22 +3484,9 @@ static int GetOcpEnhancedTelemetryLog(int fd, const char *dir, int nLogID) pBuffer[1] = 1; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = fd, - .fid = MICRON_FEATURE_OCP_ENHANCED_TELEMETRY, - .nsid = NVME_NSID_ALL, - .cdw11 = 0, - .cdw12 = 0, - .save = 1, - .uuidx = 0, - .cdw15 = 0, - .data_len = uiBufferSize, - .data = pBuffer, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); + err = nvme_set_features(hdl, NVME_NSID_ALL, + MICRON_FEATURE_OCP_ENHANCED_TELEMETRY, 1, 0, 0, 0, + 0, 0, pBuffer, uiBufferSize, &result); if (err != 0) printf("Failed to set ETDAS, Data Area 4 won't be avialable >>> "); @@ -3646,7 +3498,7 @@ static int GetOcpEnhancedTelemetryLog(int fd, const char *dir, int nLogID) printf("Unable to allocate buffer of size 0x%X bytes for telemetry header", 512); return -1; } - err = NVMEGetLogPage(fd, nLogID, pTelemetryDataHeader, 512, 0); + err = NVMEGetLogPage(hdl, nLogID, pTelemetryDataHeader, 512, 0); if (err != 0) return err; @@ -3687,7 +3539,7 @@ static int GetOcpEnhancedTelemetryLog(int fd, const char *dir, int nLogID) continue; } /* Fetch the Data */ - err = NVMEGetLogPage(fd, nLogID, pTelemetryBuffer, nallocSize, nOffset); + err = NVMEGetLogPage(hdl, nLogID, pTelemetryBuffer, nallocSize, nOffset); if (err != 0) { printf( @@ -3737,7 +3589,7 @@ static int GetOcpEnhancedTelemetryLog(int fd, const char *dir, int nLogID) } -static int micron_internal_logs(int argc, char **argv, struct command *cmd, +static int micron_internal_logs(int argc, char **argv, struct command *acmd, struct plugin *plugin) { int err = -EINVAL; @@ -3751,7 +3603,8 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, char sn[20] = { 0 }; char msg[256] = { 0 }; int c_logs_index = 8; /* should be current size of aVendorLogs */ - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct { unsigned char ucLogPage; const char *strFileName; @@ -3836,7 +3689,7 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -3880,7 +3733,7 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, goto out; } - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err) goto out; @@ -3892,7 +3745,7 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, } int logSize = 0; __u8 *buffer = NULL; const char *dir = "."; - err = micron_telemetry_log(dev_fd(dev), cfg.log, &buffer, &logSize, + err = micron_telemetry_log(hdl, cfg.log, &buffer, &logSize, cfg.data_area); if (!err && logSize > 0 && buffer) { sprintf(msg, "telemetry log: 0x%X", cfg.log); @@ -3924,28 +3777,28 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, GetDriveInfo(strOSDirName, ctrlIdx, &ctrl); for (int i = 1; i <= ctrl.nn; i++) - GetNSIDDInfo(dev_fd(dev), strCtrlDirName, i); + GetNSIDDInfo(hdl, strCtrlDirName, i); - GetSmartlogData(dev_fd(dev), strCtrlDirName); - GetErrorlogData(dev_fd(dev), ctrl.elpe, strCtrlDirName); - GetGenericLogs(dev_fd(dev), strCtrlDirName); + GetSmartlogData(hdl, strCtrlDirName); + GetErrorlogData(hdl, ctrl.elpe, strCtrlDirName); + GetGenericLogs(hdl, strCtrlDirName); /* pull if telemetry log data is supported */ if ((ctrl.lpa & 0x8) == 0x8) { if (eModel == M51BY) { - err = GetOcpEnhancedTelemetryLog(dev_fd(dev), strCtrlDirName, + err = GetOcpEnhancedTelemetryLog(hdl, strCtrlDirName, NVME_LOG_LID_TELEMETRY_HOST); if (err != 0) printf("Failed to fetch the host telemetry log"); - err = GetOcpEnhancedTelemetryLog(dev_fd(dev), strCtrlDirName, + err = GetOcpEnhancedTelemetryLog(hdl, strCtrlDirName, NVME_LOG_LID_TELEMETRY_CTRL); if (err != 0) printf("Failed to fetch the controller telemetry log"); } else { - GetTelemetryData(dev_fd(dev), strCtrlDirName); + GetTelemetryData(hdl, strCtrlDirName); } } - GetFeatureSettings(dev_fd(dev), strCtrlDirName); + GetFeatureSettings(hdl, strCtrlDirName); if (eModel != M5410 && eModel != M5407) { memcpy(&aVendorLogs[c_logs_index], aM51XXLogs, sizeof(aM51XXLogs)); @@ -3967,7 +3820,7 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, break; case 0xE9: if (eModel == M51CX || eModel == M51BY) { - err = NVMEGetLogPage(dev_fd(dev), aVendorLogs[i].ucLogPage, + err = NVMEGetLogPage(hdl, aVendorLogs[i].ucLogPage, (unsigned char *)&stWllHdr, sizeof(struct MICRON_WORKLOAD_LOG_HDR), 0); if (err == 0) { @@ -3983,7 +3836,7 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, } memcpy(dataBuffer, &stWllHdr, sizeof(struct MICRON_WORKLOAD_LOG_HDR)); - err = NVMEGetLogPage(dev_fd(dev), + err = NVMEGetLogPage(hdl, aVendorLogs[i].ucLogPage, (dataBuffer + sizeof(struct MICRON_WORKLOAD_LOG_HDR)), @@ -4002,14 +3855,14 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, if (eModel == M51CX || eModel == M51BY || eModel == M51CY) continue; - err = get_common_log(dev_fd(dev), aVendorLogs[i].ucLogPage, + err = get_common_log(hdl, aVendorLogs[i].ucLogPage, &dataBuffer, &bSize); break; case 0xE3: case 0xE4: case 0xE8: case 0xEA: - err = get_common_log(dev_fd(dev), aVendorLogs[i].ucLogPage, + err = get_common_log(hdl, aVendorLogs[i].ucLogPage, &dataBuffer, &bSize); break; case 0xC1: @@ -4017,9 +3870,9 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, if (eModel == M51CX || eModel == M51BY || eModel == M51CY) continue; - err = GetLogPageSize(dev_fd(dev), aVendorLogs[i].ucLogPage, &bSize); + err = GetLogPageSize(hdl, aVendorLogs[i].ucLogPage, &bSize); if (err == 0 && bSize > 0) - err = GetCommonLogPage(dev_fd(dev), + err = GetCommonLogPage(hdl, aVendorLogs[i].ucLogPage, &dataBuffer, bSize); break; @@ -4027,10 +3880,10 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, if (eModel == M51BY || eModel == M51CY) continue; - err = GetLogPageSize(dev_fd(dev), aVendorLogs[i].ucLogPage, + err = GetLogPageSize(hdl, aVendorLogs[i].ucLogPage, &bSize); if (!err && bSize > 0) - err = GetCommonLogPage(dev_fd(dev), aVendorLogs[i].ucLogPage, + err = GetCommonLogPage(hdl, aVendorLogs[i].ucLogPage, &dataBuffer, bSize); break; case 0xE6: @@ -4049,13 +3902,13 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, if (bSize && dataBuffer) { memset(dataBuffer, 0, bSize); if (eModel == M5410 || eModel == M5407) - err = NVMEGetLogPage(dev_fd(dev), + err = NVMEGetLogPage(hdl, aVendorLogs[i].ucLogPage, dataBuffer, bSize, 0); else - err = nvme_get_log_simple(dev_fd(dev), + err = nvme_get_log_simple(hdl, aVendorLogs[i].ucLogPage, - bSize, dataBuffer); + dataBuffer, bSize); } break; case 0xF7: @@ -4063,7 +3916,7 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, case 0xFC: case 0xFD: if (eModel == M51BX) - (void)NVMEResetLog(dev_fd(dev), aVendorLogs[i].ucLogPage, + (void)NVMEResetLog(hdl, aVendorLogs[i].ucLogPage, aVendorLogs[i].nLogSize, aVendorLogs[i].nMaxSize); default: @@ -4072,15 +3925,15 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, if (!dataBuffer) break; memset(dataBuffer, 0, bSize); - err = nvme_get_log_simple(dev_fd(dev), aVendorLogs[i].ucLogPage, - bSize, dataBuffer); + err = nvme_get_log_simple(hdl, aVendorLogs[i].ucLogPage, + dataBuffer, bSize); maxSize = aVendorLogs[i].nMaxSize - bSize; while (!err && 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_simple(dev_fd(dev), + err = nvme_get_log_simple(hdl, aVendorLogs[i].ucLogPage, - bSize, dataBuffer); + dataBuffer, bSize); if (err || (((unsigned int *)dataBuffer)[0] == 0xdeadbeef)) break; maxSize -= bSize; @@ -4099,26 +3952,26 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, err = ZipAndRemoveDir(strMainDirName, cfg.package); out: - dev_close(dev); return err; } #define MIN_LOG_SIZE 512 -static int micron_logpage_dir(int argc, char **argv, struct command *cmd, +static int micron_logpage_dir(int argc, char **argv, struct command *acmd, struct plugin *plugin) { int err = -1; const char *desc = "List the supported log pages"; enum eDriveModel model = UNKNOWN_MODEL; char logbuf[MIN_LOG_SIZE]; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int i; OPT_ARGS(opts) = { OPT_END() }; - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + err = micron_parse_options(&ctx, &hdl, argc, argv, desc, opts, &model); if (err < 0) return err; @@ -4160,8 +4013,8 @@ static int micron_logpage_dir(int argc, char **argv, struct command *cmd, printf("Supported log page list\nLog ID : Description\n"); for (i = 0; i < ARRAY_SIZE(log_list); i++) { - err = nvme_get_log_simple(dev_fd(dev), log_list[i].log_id, - MIN_LOG_SIZE, &logbuf[0]); + err = nvme_get_log_simple(hdl, log_list[i].log_id, + &logbuf[0], MIN_LOG_SIZE); if (err) continue; printf("%02Xh : %s\n", log_list[i].log_id, log_list[i].desc); @@ -4171,14 +4024,15 @@ static int micron_logpage_dir(int argc, char **argv, struct command *cmd, } static int micron_cloud_boot_SSD_version(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { const char *desc = "Prints HyperScale Boot Version"; unsigned char logC0[C0_log_size] = { 0 }; struct nvme_id_ctrl ctrl; enum eDriveModel eModel = UNKNOWN_MODEL; int err = 0; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct format { char *fmt; }; @@ -4192,11 +4046,11 @@ static int micron_cloud_boot_SSD_version(int argc, char **argv, OPT_END() }; - err = micron_parse_options(&dev, argc, argv, desc, opts, &eModel); + err = micron_parse_options(&ctx, &hdl, argc, argv, desc, opts, &eModel); if (err < 0) return -1; - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err == 0) { if (ctrl.vs[536] != MICRON_CUST_ID_GG) { printf( @@ -4209,7 +4063,7 @@ static int micron_cloud_boot_SSD_version(int argc, char **argv, goto out; } - err = nvme_get_log_simple(dev_fd(dev), 0xC0, C0_log_size, logC0); + err = nvme_get_log_simple(hdl, 0xC0, logC0, C0_log_size); if (err == 0) { __u16 major, minor; @@ -4223,11 +4077,10 @@ static int micron_cloud_boot_SSD_version(int argc, char **argv, goto out; } out: - dev_close(dev); return err; } -static int micron_device_waf(int argc, char **argv, struct command *cmd, +static int micron_device_waf(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Prints device Write Amplification Factor(WAF)"; @@ -4236,7 +4089,8 @@ static int micron_device_waf(int argc, char **argv, struct command *cmd, struct nvme_smart_log smart_log; enum eDriveModel eModel = UNKNOWN_MODEL; int err = 0; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; long double tlc_units_written, slc_units_written; long double data_units_written, write_amplification_factor; @@ -4256,11 +4110,11 @@ static int micron_device_waf(int argc, char **argv, struct command *cmd, OPT_END() }; - err = micron_parse_options(&dev, argc, argv, desc, opts, &eModel); + err = micron_parse_options(&ctx, &hdl, argc, argv, desc, opts, &eModel); if (err < 0) return -1; - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err == 0) { if (ctrl.vs[536] != MICRON_CUST_ID_GG) { printf("vs-device-waf option is not supported for specified drive\n"); @@ -4271,13 +4125,13 @@ static int micron_device_waf(int argc, char **argv, struct command *cmd, goto out; } - err = nvme_get_log_smart(dev_fd(dev), 0xffffffff, false, &smart_log); + err = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log); if (err != 0) { fprintf(stderr, "nvme_smart_log() failed, err = %d\n", err); goto out; } - err = nvme_get_log_simple(dev_fd(dev), 0xC0, C0_log_size, logC0); + err = nvme_get_log_simple(hdl, 0xC0, logC0, C0_log_size); if (err != 0) { fprintf(stderr, "Failed to get extended smart log, err = %d\n", err); goto out; @@ -4290,11 +4144,10 @@ static int micron_device_waf(int argc, char **argv, struct command *cmd, printf("Write Amplification Factor %.0Lf\n", write_amplification_factor); out: - dev_close(dev); return err; } -static int micron_cloud_log(int argc, char **argv, struct command *cmd, +static int micron_cloud_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Smart or Extended Smart Health log for the given device "; @@ -4302,7 +4155,8 @@ static int micron_cloud_log(int argc, char **argv, struct command *cmd, struct nvme_id_ctrl ctrl; enum eDriveModel eModel = UNKNOWN_MODEL; int err = 0; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; bool is_json = true; struct format { char *fmt; @@ -4317,7 +4171,7 @@ static int micron_cloud_log(int argc, char **argv, struct command *cmd, OPT_END() }; - err = micron_parse_options(&dev, argc, argv, desc, opts, &eModel); + err = micron_parse_options(&ctx, &hdl, argc, argv, desc, opts, &eModel); if (err < 0) return -1; @@ -4331,7 +4185,7 @@ static int micron_cloud_log(int argc, char **argv, struct command *cmd, goto out; } - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err == 0) { if (ctrl.vs[536] != MICRON_CUST_ID_GG) { printf("vs-cloud-log option is not supported for specified drive\n"); @@ -4342,14 +4196,13 @@ static int micron_cloud_log(int argc, char **argv, struct command *cmd, goto out; } - err = nvme_get_log_simple(dev_fd(dev), 0xC0, C0_log_size, logC0); + err = nvme_get_log_simple(hdl, 0xC0, logC0, C0_log_size); if (err == 0) print_hyperscale_cloud_health_log((__u8 *)logC0, is_json); else if (err < 0) printf("Unable to retrieve extended smart log 0xC0 for the drive\n"); out: - dev_close(dev); if (err > 0) nvme_show_status(err); return err; diff --git a/plugins/nbft/nbft-plugin.c b/plugins/nbft/nbft-plugin.c index 292b516385..f6952348a5 100644 --- a/plugins/nbft/nbft-plugin.c +++ b/plugins/nbft/nbft-plugin.c @@ -529,7 +529,7 @@ static void normal_show_nbfts(struct list_head *nbft_list, bool show_subsys, } } -int show_nbft(int argc, char **argv, struct command *cmd, struct plugin *plugin) +int show_nbft(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Display contents of the ACPI NBFT files."; struct list_head nbft_list; diff --git a/plugins/netapp/netapp-nvme.c b/plugins/netapp/netapp-nvme.c index b82ef5eb62..8d64c9668c 100644 --- a/plugins/netapp/netapp-nvme.c +++ b/plugins/netapp/netapp-nvme.c @@ -724,7 +724,7 @@ static void netapp_ontapdevices_print_json(struct ontapdevice_info *devices, json_free_object(root); } -static int nvme_get_ontap_c2_log(int fd, __u32 nsid, void *buf, __u32 buflen) +static int nvme_get_ontap_c2_log(struct nvme_transport_handle *hdl, __u32 nsid, void *buf, __u32 buflen) { struct nvme_passthru_cmd get_log; int err; @@ -745,7 +745,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, NULL); + err = nvme_submit_admin_passthru(hdl, &get_log, NULL); if (err) { fprintf(stderr, "ioctl error %0x\n", err); return 1; @@ -754,12 +754,13 @@ static int nvme_get_ontap_c2_log(int fd, __u32 nsid, void *buf, __u32 buflen) return 0; } -static int netapp_smdevices_get_info(int fd, struct smdevice_info *item, +static int netapp_smdevices_get_info(struct nvme_transport_handle *hdl, + struct smdevice_info *item, const char *dev) { int err; - err = nvme_identify_ctrl(fd, &item->ctrl); + err = nvme_identify_ctrl(hdl, &item->ctrl); if (err) { fprintf(stderr, "Identify Controller failed to %s (%s)\n", dev, @@ -771,8 +772,11 @@ 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 */ - err = nvme_get_nsid(fd, &item->nsid); - err = nvme_identify_ns(fd, item->nsid, &item->ns); + err = nvme_get_nsid(hdl, &item->nsid); + if (err) + return err; + + err = nvme_identify_ns(hdl, item->nsid, &item->ns); if (err) { fprintf(stderr, "Unable to identify namespace for %s (%s)\n", @@ -785,13 +789,14 @@ static int netapp_smdevices_get_info(int fd, struct smdevice_info *item, return 1; } -static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item, - const char *dev) +static int netapp_ontapdevices_get_info(struct nvme_transport_handle *hdl, + struct ontapdevice_info *item, + const char *dev) { - int err; void *nsdescs; + int err; - err = nvme_identify_ctrl(fd, &item->ctrl); + err = nvme_identify_ctrl(hdl, &item->ctrl); if (err) { fprintf(stderr, "Identify Controller failed to %s (%s)\n", dev, err < 0 ? strerror(-err) : @@ -803,9 +808,9 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item, /* not the right controller model */ return 0; - err = nvme_get_nsid(fd, &item->nsid); + err = nvme_get_nsid(hdl, &item->nsid); - err = nvme_identify_ns(fd, item->nsid, &item->ns); + err = nvme_identify_ns(hdl, item->nsid, &item->ns); if (err) { fprintf(stderr, "Unable to identify namespace for %s (%s)\n", dev, err < 0 ? strerror(-err) : @@ -820,7 +825,7 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item, memset(nsdescs, 0, 0x1000); - err = nvme_identify_ns_descs(fd, item->nsid, nsdescs); + err = nvme_identify_ns_descs_list(hdl, item->nsid, nsdescs); if (err) { fprintf(stderr, "Unable to identify namespace descriptor for %s (%s)\n", dev, err < 0 ? strerror(-err) : @@ -832,7 +837,7 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item, memcpy(item->uuid, nsdescs + sizeof(struct nvme_ns_id_desc), sizeof(item->uuid)); free(nsdescs); - err = nvme_get_ontap_c2_log(fd, item->nsid, item->log_data, ONTAP_C2_LOG_SIZE); + err = nvme_get_ontap_c2_log(hdl, item->nsid, item->log_data, ONTAP_C2_LOG_SIZE); if (err) { fprintf(stderr, "Unable to get log page data for %s (%s)\n", dev, err < 0 ? strerror(-err) : @@ -883,17 +888,18 @@ static int netapp_output_format(char *format) } /* handler for 'nvme netapp smdevices' */ -static int netapp_smdevices(int argc, char **argv, struct command *command, - struct plugin *plugin) +static int netapp_smdevices(int argc, char **argv, struct command *acmd, + struct plugin *plugin) { const char *desc = "Display information about E-Series volumes."; - + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = nvme_create_global_ctx(stdout, DEFAULT_LOGLEVEL); struct dirent **devices; - int num, i, fd, ret, fmt; + int num, i, ret, fmt; struct smdevice_info *smdevices; char path[264]; char *devname = NULL; int num_smdevices = 0; + struct nvme_transport_handle *hdl; struct config { bool verbose; @@ -910,6 +916,9 @@ static int netapp_smdevices(int argc, char **argv, struct command *command, OPT_END() }; + if (!ctx) + return -ENOMEM; + ret = argconfig_parse(argc, argv, desc, opts); if (ret < 0) return ret; @@ -955,16 +964,16 @@ static int netapp_smdevices(int argc, char **argv, struct command *command, for (i = 0; i < num; i++) { snprintf(path, sizeof(path), "%s%s", dev_path, devices[i]->d_name); - fd = open(path, O_RDONLY); - if (fd < 0) { + ret = nvme_open(ctx, path, &hdl); + if (ret) { fprintf(stderr, "Unable to open %s: %s\n", path, - strerror(errno)); + strerror(-ret)); continue; } - num_smdevices += netapp_smdevices_get_info(fd, + num_smdevices += netapp_smdevices_get_info(hdl, &smdevices[num_smdevices], path); - close(fd); + nvme_close(hdl); } if (num_smdevices) { @@ -990,16 +999,18 @@ static int netapp_smdevices(int argc, char **argv, struct command *command, } /* handler for 'nvme netapp ontapdevices' */ -static int netapp_ontapdevices(int argc, char **argv, struct command *command, +static int netapp_ontapdevices(int argc, char **argv, struct command *acmd, struct plugin *plugin) { + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = nvme_create_global_ctx(stdout, DEFAULT_LOGLEVEL); const char *desc = "Display information about ONTAP devices."; struct dirent **devices; - int num, i, fd, ret, fmt; + int num, i, ret, fmt; struct ontapdevice_info *ontapdevices; char path[264]; char *devname = NULL; int num_ontapdevices = 0; + struct nvme_transport_handle *hdl; struct config { bool verbose; @@ -1016,6 +1027,9 @@ static int netapp_ontapdevices(int argc, char **argv, struct command *command, OPT_END() }; + if (!ctx) + return -ENOMEM; + ret = argconfig_parse(argc, argv, desc, opts); if (ret < 0) return ret; @@ -1061,17 +1075,17 @@ static int netapp_ontapdevices(int argc, char **argv, struct command *command, for (i = 0; i < num; i++) { snprintf(path, sizeof(path), "%s%s", dev_path, devices[i]->d_name); - fd = open(path, O_RDONLY); - if (fd < 0) { + ret = nvme_open(ctx, path, &hdl); + if (ret) { fprintf(stderr, "Unable to open %s: %s\n", path, - strerror(errno)); + strerror(-ret)); continue; } - num_ontapdevices += netapp_ontapdevices_get_info(fd, + num_ontapdevices += netapp_ontapdevices_get_info(hdl, &ontapdevices[num_ontapdevices], path); - close(fd); + nvme_close(hdl); } if (num_ontapdevices) { diff --git a/plugins/nvidia/nvidia-nvme.c b/plugins/nvidia/nvidia-nvme.c index 71e0bc3305..e4e3d9b6fb 100644 --- a/plugins/nvidia/nvidia-nvme.c +++ b/plugins/nvidia/nvidia-nvme.c @@ -46,8 +46,8 @@ static void nvidia_id_ctrl(__u8 *vs, struct json_object *root) printf("json_rpc_2_0_ver : %s\n", json_rpc_2_0_ver); } -static int id_ctrl(int argc, char **argv, struct command *cmd, +static int id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return __id_ctrl(argc, argv, cmd, plugin, nvidia_id_ctrl); + return __id_ctrl(argc, argv, acmd, plugin, nvidia_id_ctrl); } diff --git a/plugins/ocp/ocp-clear-features.c b/plugins/ocp/ocp-clear-features.c index ddb95cb7f3..bccbc8809d 100644 --- a/plugins/ocp/ocp-clear-features.c +++ b/plugins/ocp/ocp-clear-features.c @@ -14,9 +14,10 @@ static int ocp_clear_feature(int argc, char **argv, const char *desc, const __u8 fid) { + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 result = 0; __u32 clear = 1 << 31; - struct nvme_dev *dev; __u8 uuid_index = 0; bool uuid = true; int err; @@ -27,7 +28,7 @@ static int ocp_clear_feature(int argc, char **argv, const char *desc, const __u8 OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -36,31 +37,15 @@ static int ocp_clear_feature(int argc, char **argv, const char *desc, const __u8 if (uuid) { /* OCP 2.0 requires UUID index support */ - err = ocp_get_uuid_index(dev, &uuid_index); + err = ocp_get_uuid_index(hdl, &uuid_index); if (err || !uuid_index) { fprintf(stderr, "ERROR: No OCP UUID index found\n"); - goto close_dev; + return err; } } - struct nvme_set_features_args args = { - .result = &result, - .data = NULL, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .nsid = 0, - .cdw11 = clear, - .cdw12 = 0, - .cdw13 = 0, - .cdw15 = 0, - .data_len = 0, - .save = 0, - .uuidx = uuid_index, - .fid = fid, - }; - - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 0, fid, 0, clear, 0, 0, uuid_index, 0, NULL, 0, + &result); if (err == 0) printf("Success : %s\n", desc); @@ -68,14 +53,11 @@ static int ocp_clear_feature(int argc, char **argv, const char *desc, const __u8 nvme_show_status(err); else printf("Fail : %s\n", desc); -close_dev: - /* Redundant close() to make static code analysis happy */ - close(dev->direct.fd); - dev_close(dev); + return err; } -int get_ocp_error_counters(int argc, char **argv, struct command *cmd, +int get_ocp_error_counters(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Define Issue Get Feature cmd (FID: 0xC3) Clear PCIe Corr Err Counters"; @@ -83,8 +65,8 @@ int get_ocp_error_counters(int argc, char **argv, struct command *cmd, const char *nsid = "Byte[04-07]: Namespace Identifier Valid/Invalid/Inactive"; const char *no_uuid = "Do not try to automatically detect UUID index"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 result; int err; bool uuid; @@ -107,7 +89,7 @@ int get_ocp_error_counters(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -115,28 +97,15 @@ int get_ocp_error_counters(int argc, char **argv, struct command *cmd, if (uuid) { /* OCP 2.0 requires UUID index support */ - err = ocp_get_uuid_index(dev, &uuid_index); + err = ocp_get_uuid_index(hdl, &uuid_index); if (err || !uuid_index) { nvme_show_error("ERROR: No OCP UUID index found"); return err; } } - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = OCP_FID_CPCIE, - .nsid = cfg.nsid, - .sel = cfg.sel, - .cdw11 = 0, - .uuidx = uuid_index, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_get_features(&args); + err = nvme_get_features(hdl, cfg.nsid, OCP_FID_CPCIE, cfg.sel, 0, + uuid_index, NULL, 0, &result); if (!err) { printf("get-feature:0xC3 %s value: %#08x\n", nvme_select_to_string(cfg.sel), result); @@ -150,14 +119,16 @@ int get_ocp_error_counters(int argc, char **argv, struct command *cmd, return err; } -int ocp_clear_fw_update_history(int argc, char **argv, struct command *cmd, struct plugin *plugin) +int ocp_clear_fw_update_history(int argc, char **argv, struct command *acmd, + struct plugin *plugin) { const char *desc = "OCP Clear Firmware Update History"; return ocp_clear_feature(argc, argv, desc, OCP_FID_CFUH); } -int ocp_clear_pcie_correctable_errors(int argc, char **argv, struct command *cmd, +int ocp_clear_pcie_correctable_errors(int argc, char **argv, + struct command *command, struct plugin *plugin) { const char *desc = "OCP Clear PCIe Correctable Error Counters"; diff --git a/plugins/ocp/ocp-clear-features.h b/plugins/ocp/ocp-clear-features.h index 9727b88c01..05696e754b 100644 --- a/plugins/ocp/ocp-clear-features.h +++ b/plugins/ocp/ocp-clear-features.h @@ -6,10 +6,10 @@ * leonardo.da.cunha@solidigm.com */ -int ocp_clear_fw_update_history(int argc, char **argv, struct command *cmd, struct plugin *plugin); +int ocp_clear_fw_update_history(int argc, char **argv, struct command *acmd, struct plugin *plugin); -int ocp_clear_pcie_correctable_errors(int argc, char **argv, struct command *cmd, +int ocp_clear_pcie_correctable_errors(int argc, char **argv, struct command *acmd, struct plugin *plugin); -int get_ocp_error_counters(int argc, char **argv, struct command *cmd, +int get_ocp_error_counters(int argc, char **argv, struct command *acmd, struct plugin *plugin); diff --git a/plugins/ocp/ocp-fw-activation-history.c b/plugins/ocp/ocp-fw-activation-history.c index d3eb60c262..02c45bc539 100644 --- a/plugins/ocp/ocp-fw-activation-history.c +++ b/plugins/ocp/ocp-fw-activation-history.c @@ -24,59 +24,45 @@ static const unsigned char ocp_fw_activation_history_guid[GUID_LEN] = { 0xac, 0xf3, 0x1c, 0xd1 }; -int ocp_fw_activation_history_log(int argc, char **argv, struct command *cmd, +int ocp_fw_activation_history_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - const char *description = "Retrieves the OCP firmware activation history log."; + const char *desc = "Retrieves the OCP firmware activation history log."; char *format = "normal"; - OPT_ARGS(options) = { + OPT_ARGS(opts) = { OPT_FMT("output-format", 'o', &format, "output format : normal | json"), OPT_END() }; - struct nvme_dev *dev = NULL; - int err = parse_and_open(&dev, argc, argv, description, options); + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct fw_activation_history fw_history = { 0 }; + struct nvme_passthru_cmd cmd; + __u8 uuid_index = 0; + int err; + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - __u8 uuid_index = 0; - /* * Best effort attempt at uuid. Otherwise, assume no index (i.e. 0) * Log GUID check will ensure correctness of returned data */ - ocp_get_uuid_index(dev, &uuid_index); - - struct fw_activation_history fw_history = { 0 }; - - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = &fw_history, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = (enum nvme_cmd_get_log_lid)OCP_LID_FAHL_OBSOLETE, - .len = sizeof(fw_history), - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = 0, - .uuidx = uuid_index, - .rae = false, - .ot = false, - }; - - err = nvme_get_log(&args); - + ocp_get_uuid_index(hdl, &uuid_index); + nvme_init_get_log(&cmd, NVME_NSID_ALL, + (enum nvme_cmd_get_log_lid)OCP_LID_FAHL_OBSOLETE, + NVME_CSI_NVM, &fw_history, sizeof(fw_history)); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + err = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (err) nvme_show_status(err); - dev_close(dev); - int guid_cmp_res = memcmp(fw_history.log_page_guid, ocp_fw_activation_history_guid, sizeof(ocp_fw_activation_history_guid)); diff --git a/plugins/ocp/ocp-fw-activation-history.h b/plugins/ocp/ocp-fw-activation-history.h index fa37e4bd60..89a86f65da 100644 --- a/plugins/ocp/ocp-fw-activation-history.h +++ b/plugins/ocp/ocp-fw-activation-history.h @@ -40,7 +40,7 @@ struct __packed fw_activation_history { __le64 log_page_guid[2]; }; -int ocp_fw_activation_history_log(int argc, char **argv, struct command *cmd, +int ocp_fw_activation_history_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); #endif diff --git a/plugins/ocp/ocp-hardware-component-log.c b/plugins/ocp/ocp-hardware-component-log.c index 81473e2140..6a50839b63 100644 --- a/plugins/ocp/ocp-hardware-component-log.c +++ b/plugins/ocp/ocp-hardware-component-log.c @@ -167,29 +167,29 @@ const char *hwcomp_id_to_string(__u32 id) return "Reserved"; } -static int get_hwcomp_log_data(struct nvme_dev *dev, struct hwcomp_log *log) +static int get_hwcomp_log_data(struct nvme_transport_handle *hdl, struct hwcomp_log *log) { - int ret = 0; size_t desc_offset = offsetof(struct hwcomp_log, desc); - long double log_bytes; + struct nvme_passthru_cmd cmd; nvme_uint128_t log_size; + long double log_bytes; + __u32 len; + __u8 uidx; + int ret = 0; - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = (enum nvme_cmd_get_log_lid)OCP_LID_HWCOMP, - .nsid = NVME_NSID_ALL, - .log = log, - .len = desc_offset, - }; - - ocp_get_uuid_index(dev, &args.uuidx); + ocp_get_uuid_index(hdl, &uidx); #ifdef HWCOMP_DUMMY memcpy(log, hwcomp_dummy, desc_offset); #else /* HWCOMP_DUMMY */ - ret = nvme_get_log_page(dev_fd(dev), NVME_LOG_PAGE_PDU_SIZE, &args); + nvme_init_get_log(&cmd, NVME_NSID_ALL, + (enum nvme_cmd_get_log_lid)OCP_LID_HWCOMP, + NVME_CSI_NVM, log, desc_offset); + cmd.cdw14 |= NVME_FIELD_ENCODE(uidx, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + ret = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (ret) { print_info_error("error: ocp: failed to get hwcomp log size (ret: %d)\n", ret); return ret; @@ -212,23 +212,25 @@ static int get_hwcomp_log_data(struct nvme_dev *dev, struct hwcomp_log *log) return -EINVAL; } - args.len = log_bytes - desc_offset; + len = log_bytes - desc_offset; - print_info("args.len: %u\n", args.len); + print_info("args.len: %u\n", len); - log->desc = calloc(1, args.len); + log->desc = calloc(1, len); if (!log->desc) { fprintf(stderr, "error: ocp: calloc: %s\n", strerror(errno)); return -errno; } - args.log = log->desc, - args.lpo = desc_offset, - #ifdef HWCOMP_DUMMY - memcpy(log->desc, &hwcomp_dummy[desc_offset], args.len); + memcpy(log->desc, &hwcomp_dummy[desc_offset], len); #else /* HWCOMP_DUMMY */ - ret = nvme_get_log_page(dev_fd(dev), NVME_LOG_PAGE_PDU_SIZE, &args); + nvme_init_get_log(&cmd, NVME_NSID_ALL, + (enum nvme_cmd_get_log_lid)OCP_LID_HWCOMP, + NVME_CSI_NVM, log->desc, len); + nvme_init_get_log_lpo(&cmd, desc_offset); + ret = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (ret) { print_info_error("error: ocp: failed to get log page (hwcomp: %02X, ret: %d)\n", OCP_LID_HWCOMP, ret); @@ -240,7 +242,7 @@ static int get_hwcomp_log_data(struct nvme_dev *dev, struct hwcomp_log *log) return ret; } -static int get_hwcomp_log(struct nvme_dev *dev, __u32 id, bool list) +static int get_hwcomp_log(struct nvme_transport_handle *hdl, __u32 id, bool list) { int ret; nvme_print_flags_t fmt; @@ -254,7 +256,7 @@ static int get_hwcomp_log(struct nvme_dev *dev, __u32 id, bool list) return ret; } - ret = get_hwcomp_log_data(dev, &log); + ret = get_hwcomp_log_data(hdl, &log); if (ret) { print_info_error("error: ocp: failed get hwcomp log: %02X data, ret: %d\n", OCP_LID_HWCOMP, ret); @@ -268,9 +270,10 @@ static int get_hwcomp_log(struct nvme_dev *dev, __u32 id, bool list) return 0; } -int ocp_hwcomp_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +int ocp_hwcomp_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = 0; const char *desc = "retrieve hardware component log"; struct config { @@ -300,11 +303,11 @@ int ocp_hwcomp_log(int argc, char **argv, struct command *cmd, struct plugin *pl NVME_ARGS(opts, OPT_LONG("comp-id", 'i', &cfg.id, id_desc, id), OPT_FLAG("list", 'l', &cfg.list, list_desc)); - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - ret = get_hwcomp_log(dev, cfg.id, cfg.list); + ret = get_hwcomp_log(hdl, cfg.id, cfg.list); if (ret) fprintf(stderr, "error: ocp: failed to get hwcomp log: %02X, ret: %d\n", OCP_LID_HWCOMP, ret); diff --git a/plugins/ocp/ocp-hardware-component-log.h b/plugins/ocp/ocp-hardware-component-log.h index 1755388fc6..9137d87df6 100644 --- a/plugins/ocp/ocp-hardware-component-log.h +++ b/plugins/ocp/ocp-hardware-component-log.h @@ -58,7 +58,7 @@ enum hwcomp_id { HWCOMP_ID_MAX = 0xffff, }; -int ocp_hwcomp_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); +int ocp_hwcomp_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); const char *hwcomp_id_to_string(__u32 id); #endif /* OCP_HARDWARE_COMPONENT_LOG_H */ diff --git a/plugins/ocp/ocp-nvme.c b/plugins/ocp/ocp-nvme.c index c3f4149d4b..c4e61749c7 100644 --- a/plugins/ocp/ocp-nvme.c +++ b/plugins/ocp/ocp-nvme.c @@ -24,7 +24,6 @@ #include "util/types.h" #include "logging.h" #include "nvme-print.h" -#include "nvme-wrap.h" #include "ocp-smart-extended-log.h" #include "ocp-clear-features.h" @@ -197,7 +196,7 @@ static const char *nrtdp = "Number of reads to trigger device panic"; static const char *save = "Specifies that the controller shall save the attribute"; static const char *enable_ieee1667_silo = "enable IEEE1667 silo"; -static int get_c3_log_page(struct nvme_dev *dev, char *format) +static int get_c3_log_page(struct nvme_transport_handle *hdl, char *format) { struct ssd_latency_monitor_log *log_data; nvme_print_flags_t fmt; @@ -218,7 +217,7 @@ static int get_c3_log_page(struct nvme_dev *dev, char *format) } memset(data, 0, sizeof(__u8) * C3_LATENCY_MON_LOG_BUF_LEN); - ret = ocp_get_log_simple(dev, OCP_LID_LMLOG, C3_LATENCY_MON_LOG_BUF_LEN, data); + ret = ocp_get_log_simple(hdl, OCP_LID_LMLOG, C3_LATENCY_MON_LOG_BUF_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); @@ -248,7 +247,7 @@ static int get_c3_log_page(struct nvme_dev *dev, char *format) goto out; } } - ocp_c3_log(dev, log_data, fmt); + ocp_c3_log(hdl, log_data, fmt); } else { fprintf(stderr, "ERROR : OCP : Unable to read C3 data from buffer\n"); } @@ -263,7 +262,8 @@ static int ocp_latency_monitor_log(int argc, char **argv, struct plugin *plugin) { const char *desc = "Retrieve latency monitor log data."; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = 0; struct config { @@ -280,24 +280,24 @@ static int ocp_latency_monitor_log(int argc, char **argv, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - ret = get_c3_log_page(dev, cfg.output_format); + ret = get_c3_log_page(hdl, cfg.output_format); if (ret) fprintf(stderr, "ERROR : OCP : Failure reading the C3 Log Page, ret = %d\n", ret); - dev_close(dev); return ret; } -int ocp_set_latency_monitor_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) +int ocp_set_latency_monitor_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { int err = -1; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 result; struct feature_latency_monitor buf = { 0 }; __u32 nsid = NVME_NSID_ALL; @@ -356,23 +356,23 @@ int ocp_set_latency_monitor_feature(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = fstat(dev_fd(dev), &nvme_stat); + err = fstat(nvme_transport_handle_get_fd(hdl), &nvme_stat); if (err < 0) return err; if (S_ISBLK(nvme_stat.st_mode)) { - err = nvme_get_nsid(dev_fd(dev), &nsid); + err = nvme_get_nsid(hdl, &nsid); if (err < 0) { perror("invalid-namespace-id"); return err; } } - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err) return err; @@ -387,20 +387,8 @@ int ocp_set_latency_monitor_feature(int argc, char **argv, struct command *cmd, buf.discard_debug_log = cfg.discard_debug_log; buf.latency_monitor_feature_enable = cfg.latency_monitor_feature_enable; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = OCP_FID_LM, - .nsid = 0, - .cdw12 = 0, - .save = 1, - .data_len = sizeof(struct feature_latency_monitor), - .data = (void *)&buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 0, OCP_FID_LM, 1, 0, 0, 0, 0, 0, (void *)&buf, + sizeof(struct feature_latency_monitor), &result); if (err < 0) { perror("set-feature"); } else if (!err) { @@ -424,14 +412,15 @@ int ocp_set_latency_monitor_feature(int argc, char **argv, struct command *cmd, return err; } -static int ocp_get_latency_monitor_feature(int argc, char **argv, struct command *cmd, +static int ocp_get_latency_monitor_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Define Issue Get Feature command (FID: 0xC5) Latency Monitor"; const char *sel = "[0-3]: current/default/saved/supported/"; const char *nsid = "Byte[04-07]: Namespace Identifier Valid/Invalid/Inactive"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 result; int err; @@ -455,7 +444,7 @@ static int ocp_get_latency_monitor_feature(int argc, char **argv, struct command OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -463,28 +452,15 @@ static int ocp_get_latency_monitor_feature(int argc, char **argv, struct command if (uuid) { /* OCP 2.0 requires UUID index support */ - err = ocp_get_uuid_index(dev, &uuid_index); + err = ocp_get_uuid_index(hdl, &uuid_index); if (err || !uuid_index) { nvme_show_error("ERROR: No OCP UUID index found"); return err; } } - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = OCP_FID_LM, - .nsid = cfg.nsid, - .sel = cfg.sel, - .cdw11 = 0, - .uuidx = uuid_index, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_get_features(&args); + err = nvme_get_features(hdl, cfg.nsid, OCP_FID_LM, cfg.sel, 0, + uuid_index, NULL, 0, &result); if (!err) { printf("get-feature:0xC5 %s value: %#08x\n", nvme_select_to_string(cfg.sel), result); @@ -520,36 +496,23 @@ static const char *eol_plp_failure_mode_to_string(__u8 mode) return "Reserved"; } -static int eol_plp_failure_mode_get(struct nvme_dev *dev, const __u32 nsid, const __u8 fid, +static int eol_plp_failure_mode_get(struct nvme_transport_handle *hdl, const __u32 nsid, const __u8 fid, __u8 sel, bool uuid) { + __u8 uidx = 0; __u32 result; int err; - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = nsid, - .sel = sel, - .cdw11 = 0, - .uuidx = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - if (uuid) { /* OCP 2.0 requires UUID index support */ - err = ocp_get_uuid_index(dev, &args.uuidx); - if (err || !args.uuidx) { + err = ocp_get_uuid_index(hdl, &uidx); + if (err || !uidx) { nvme_show_error("ERROR: No OCP UUID index found"); return err; } } - err = nvme_get_features(&args); + err = nvme_get_features(hdl, nsid, fid, sel, 0, uidx, NULL, 0, &result); if (!err) { nvme_show_result("End of Life Behavior (feature: %#0*x): %#0*x (%s: %s)", fid ? 4 : 2, fid, result ? 10 : 8, result, @@ -564,40 +527,25 @@ static int eol_plp_failure_mode_get(struct nvme_dev *dev, const __u32 nsid, cons return err; } -static int eol_plp_failure_mode_set(struct nvme_dev *dev, const __u32 nsid, - const __u8 fid, __u8 mode, bool save, +static int eol_plp_failure_mode_set(struct nvme_transport_handle *hdl, const __u32 nsid, + const __u8 fid, __u8 mode, bool sv, bool uuid) { __u32 result; int err; - __u8 uuid_index = 0; + __u8 uidx = 0; if (uuid) { /* OCP 2.0 requires UUID index support */ - err = ocp_get_uuid_index(dev, &uuid_index); - if (err || !uuid_index) { + err = ocp_get_uuid_index(hdl, &uidx); + if (err || !uidx) { nvme_show_error("ERROR: No OCP UUID index found"); return err; } } - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = nsid, - .cdw11 = mode << 30, - .cdw12 = 0, - .save = save, - .uuidx = uuid_index, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_set_features(&args); + err = nvme_set_features(hdl, nsid, fid, sv, mode << 30, 0, 0, uidx, 0, NULL, + 0, &result); if (err > 0) { nvme_show_status(err); } else if (err < 0) { @@ -606,14 +554,14 @@ static int eol_plp_failure_mode_set(struct nvme_dev *dev, const __u32 nsid, } else { nvme_show_result("Successfully set mode (feature: %#0*x): %#0*x (%s: %s).", fid ? 4 : 2, fid, mode ? 10 : 8, mode, - save ? "Save" : "Not save", + sv ? "Save" : "Not save", eol_plp_failure_mode_to_string(mode)); } return err; } -static int eol_plp_failure_mode(int argc, char **argv, struct command *cmd, +static int eol_plp_failure_mode(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Define EOL or PLP circuitry failure mode.\n" @@ -621,7 +569,8 @@ static int eol_plp_failure_mode(int argc, char **argv, struct command *cmd, const char *mode = "[0-3]: default/rom/wtm/normal"; const __u32 nsid = 0; const __u8 fid = OCP_FID_ROWTM; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; struct config { @@ -642,20 +591,18 @@ static int eol_plp_failure_mode(int argc, char **argv, struct command *cmd, OPT_BYTE("sel", 'S', &cfg.sel, sel), OPT_FLAG("no-uuid", 'n', NULL, no_uuid)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; if (argconfig_parse_seen(opts, "mode")) - err = eol_plp_failure_mode_set(dev, nsid, fid, cfg.mode, + err = eol_plp_failure_mode_set(hdl, nsid, fid, cfg.mode, cfg.save, !argconfig_parse_seen(opts, "no-uuid")); else - err = eol_plp_failure_mode_get(dev, nsid, fid, cfg.sel, + err = eol_plp_failure_mode_get(hdl, nsid, fid, cfg.sel, !argconfig_parse_seen(opts, "no-uuid")); - dev_close(dev); - return err; } @@ -723,7 +670,7 @@ static void print_telemetry_header(struct telemetry_initiated_log *logheader, in } } -static int get_telemetry_data(struct nvme_dev *dev, __u32 ns, __u8 tele_type, +static int get_telemetry_data(struct nvme_transport_handle *hdl, __u32 ns, __u8 tele_type, __u32 data_len, void *data, __u8 nLSP, __u8 nRAE, __u64 offset) { @@ -742,7 +689,7 @@ static int get_telemetry_data(struct nvme_dev *dev, __u32 ns, __u8 tele_type, cmd.cdw12 = (__u32)(0x00000000FFFFFFFF & offset); cmd.cdw13 = (__u32)((0xFFFFFFFF00000000 & offset) >> 8); cmd.cdw14 = 0; - return nvme_submit_admin_passthru(dev_fd(dev), &cmd, NULL); + return nvme_submit_admin_passthru(hdl, &cmd, NULL); } static void print_telemetry_data_area_1(struct telemetry_data_area_1 *da1, @@ -862,7 +809,7 @@ static void print_telemetry_da_fifo(struct telemetry_event_desc *da_fifo, printf("===============================================\n\n"); } } -static int extract_dump_get_log(struct nvme_dev *dev, char *featurename, char *filename, char *sn, +static int extract_dump_get_log(struct nvme_transport_handle *hdl, char *featurename, char *filename, char *sn, int dumpsize, int transfersize, __u32 nsid, __u8 log_id, __u8 lsp, __u64 offset, bool rae) { @@ -873,6 +820,7 @@ static int extract_dump_get_log(struct nvme_dev *dev, char *featurename, char *f int output = 0; int total_loop_cnt = dumpsize / transfersize; int last_xfer_size = dumpsize % transfersize; + struct nvme_passthru_cmd cmd; if (last_xfer_size) total_loop_cnt++; @@ -887,24 +835,10 @@ static int extract_dump_get_log(struct nvme_dev *dev, char *featurename, char *f for (i = 0; i < total_loop_cnt; i++) { memset(data, 0, transfersize); - struct nvme_get_log_args args = { - .lpo = offset, - .result = NULL, - .log = (void *)data, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .lid = log_id, - .len = transfersize, - .nsid = nsid, - .lsp = lsp, - .uuidx = 0, - .rae = rae, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .csi = NVME_CSI_NVM, - .ot = false, - }; - - err = nvme_get_log(&args); + nvme_init_get_log(&cmd, nsid, log_id, NVME_CSI_NVM, + data, transfersize); + nvme_init_get_log_lpo(&cmd, offset); + err = nvme_get_log(hdl, &cmd, rae, NVME_LOG_PAGE_PDU_SIZE, NULL); if (err) { if (i > 0) goto close_output; @@ -943,7 +877,7 @@ static int extract_dump_get_log(struct nvme_dev *dev, char *featurename, char *f return err; } -static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, +static int get_telemetry_dump(struct nvme_transport_handle *hdl, char *filename, char *sn, enum TELEMETRY_TYPE tele_type, int data_area, bool header_print) { __u32 err = 0, nsid = 0; @@ -976,7 +910,7 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, } /* Get the telemetry header */ - err = get_telemetry_data(dev, nsid, tele_type, TELEMETRY_HEADER_SIZE, (void *)data, lsp, + err = get_telemetry_data(hdl, nsid, tele_type, TELEMETRY_HEADER_SIZE, (void *)data, lsp, rae, 0); if (err) { printf("get_telemetry_header failed, err: %d.\n", err); @@ -987,7 +921,7 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, print_telemetry_header(logheader, tele_type); /* Get the telemetry data */ - err = get_telemetry_data(dev, nsid, tele_type, TELEMETRY_DATA_SIZE, (void *)data1, lsp, + err = get_telemetry_data(hdl, nsid, tele_type, TELEMETRY_DATA_SIZE, (void *)data1, lsp, rae, 512); if (err) { printf("get_telemetry_data failed for type: 0x%x, err: %d.\n", tele_type, err); @@ -1033,7 +967,7 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, char *da1_stat = calloc(da1_sz, sizeof(char)); - err = get_telemetry_data(dev, nsid, tele_type, da1_sz, (void *)da1_stat, lsp, rae, + err = get_telemetry_data(hdl, nsid, tele_type, da1_sz, (void *)da1_stat, lsp, rae, da1_off); if (err) { printf("get_telemetry_data da1 stats failed, err: %d.\n", err); @@ -1084,7 +1018,7 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, printf("Get DA 1 FIFO addr: %p, offset 0x%"PRIx64"\n", da1_fifo, (uint64_t)da1_off); - err = get_telemetry_data(dev, nsid, tele_type, + err = get_telemetry_data(hdl, nsid, tele_type, le64_to_cpu(da1->event_fifos[i].size) * 4, (void *)da1_fifo, lsp, rae, da1_off); if (err) { @@ -1141,7 +1075,7 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, char *da2_stat = calloc(da1_sz, sizeof(char)); - err = get_telemetry_data(dev, nsid, tele_type, da1_sz, (void *)da2_stat, lsp, rae, + err = get_telemetry_data(hdl, nsid, tele_type, da1_sz, (void *)da2_stat, lsp, rae, da1_off); if (err) { printf("get_telemetry_data da2 stats failed, err: %d.\n", err); @@ -1190,7 +1124,7 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, char *da1_fifo = calloc(da1_sz, sizeof(char)); - err = get_telemetry_data(dev, nsid, tele_type, + err = get_telemetry_data(hdl, nsid, tele_type, le64_to_cpu(da1->event_fifos[i].size) * 4, (void *)da1_fifo, lsp, rae, da1_off); if (err) { @@ -1238,13 +1172,13 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, } snprintf(dumpname, FILE_NAME_SIZE, "Telemetry_%s_Area_%d", featurename, data_area); - err = extract_dump_get_log(dev, dumpname, filename, sn, size * TELEMETRY_BYTE_PER_BLOCK, + err = extract_dump_get_log(hdl, dumpname, filename, sn, size * TELEMETRY_BYTE_PER_BLOCK, TELEMETRY_TRANSFER_SIZE, nsid, tele_type, 0, offset, rae); return err; } -static int get_telemetry_log_page_data(struct nvme_dev *dev, +static int get_telemetry_log_page_data(struct nvme_transport_handle *hdl, int tele_type, int tele_area, const char *output_file) @@ -1252,6 +1186,7 @@ static int get_telemetry_log_page_data(struct nvme_dev *dev, void *telemetry_log; const size_t bs = 512; struct nvme_telemetry_log *hdr; + struct nvme_passthru_cmd cmd; size_t full_size = 0, offset = bs; int err, fd; @@ -1279,25 +1214,11 @@ static int get_telemetry_log_page_data(struct nvme_dev *dev, goto exit_status; } - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = hdr, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = log_id, - .len = bs, - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_TELEM_HOST_LSP_CREATE, - .uuidx = NVME_UUID_NONE, - .rae = true, - .ot = false, - }; - - err = nvme_get_log(&args); + nvme_init_get_log(&cmd, NVME_NSID_ALL, log_id, NVME_CSI_NVM, hdr, bs); + cmd.cdw10 |= NVME_FIELD_ENCODE(NVME_LOG_TELEM_HOST_LSP_CREATE, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + err = nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); if (err < 0) nvme_show_error("Failed to fetch the log from drive.\n"); else if (err > 0) { @@ -1331,10 +1252,10 @@ static int get_telemetry_log_page_data(struct nvme_dev *dev, } while (offset < full_size) { - args.log = telemetry_log; - args.lpo = offset; - args.lsp = NVME_LOG_LSP_NONE; - err = nvme_get_log(&args); + nvme_init_get_log(&cmd, NVME_NSID_ALL, log_id, NVME_CSI_NVM, + telemetry_log, bs); + nvme_init_get_log_lpo(&cmd, offset); + err = nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); if (err < 0) { nvme_show_error("Failed to fetch the log from drive.\n"); break; @@ -1362,7 +1283,7 @@ static int get_telemetry_log_page_data(struct nvme_dev *dev, return err; } -static int get_c9_log_page_data(struct nvme_dev *dev, +static int get_c9_log_page_data(struct nvme_transport_handle *hdl, int print_data, int save_bin, const char *output_file) @@ -1382,7 +1303,7 @@ static int get_c9_log_page_data(struct nvme_dev *dev, } memset(header_data, 0, sizeof(__u8) * C9_TELEMETRY_STR_LOG_LEN); - ret = ocp_get_log_simple(dev, OCP_LID_TELSLG, C9_TELEMETRY_STR_LOG_LEN, header_data); + ret = ocp_get_log_simple(hdl, OCP_LID_TELSLG, C9_TELEMETRY_STR_LOG_LEN, header_data); if (!ret) { log_data = (struct telemetry_str_log_format *)header_data; @@ -1424,7 +1345,7 @@ static int get_c9_log_page_data(struct nvme_dev *dev, } memset(pC9_string_buffer, 0, sizeof(__u8) * total_log_page_sz); - ret = ocp_get_log_simple(dev, OCP_LID_TELSLG, total_log_page_sz, pC9_string_buffer); + ret = ocp_get_log_simple(hdl, OCP_LID_TELSLG, total_log_page_sz, pC9_string_buffer); } else { fprintf(stderr, "ERROR : OCP : Unable to read C9 data.\n"); } @@ -1501,7 +1422,7 @@ int parse_ocp_telemetry_log(struct ocp_telemetry_parse_options *options) return 0; } -static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int ocp_telemetry_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve and parse OCP Telemetry log."; const char *telemetry_log = "Telemetry log binary;\n 'host.bin' or 'controller.bin'"; @@ -1518,7 +1439,8 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct const char *telemetry_type = "Telemetry Type; 'host', 'host0', 'host1' or 'controller'"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err = 0; __u32 nsid = NVME_NSID_ALL; struct stat nvme_stat; @@ -1543,24 +1465,24 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; if (opt.telemetry_type == 0) opt.telemetry_type = "host"; - err = fstat(dev_fd(dev), &nvme_stat); + err = fstat(nvme_transport_handle_get_fd(hdl), &nvme_stat); if (err < 0) return err; if (S_ISBLK(nvme_stat.st_mode)) { - err = nvme_get_nsid(dev_fd(dev), &nsid); + err = nvme_get_nsid(hdl, &nsid); if (err < 0) return err; } - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err) return err; @@ -1611,7 +1533,7 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct goto out; } - err = nvme_set_etdas(dev_fd(dev), &host_behavior_changed); + err = nvme_set_etdas(hdl, &host_behavior_changed); if (err) { fprintf(stderr, "%s: Failed to set ETDAS bit\n", __func__); return err; @@ -1620,7 +1542,7 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct /* Pull the Telemetry log */ sprintf(file_path_telemetry, "%s-%s", opt.output_file, tele_log_suffix); - err = get_telemetry_log_page_data(dev, + err = get_telemetry_log_page_data(hdl, tele_type, tele_area, (const char *)file_path_telemetry); @@ -1633,7 +1555,7 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct if (host_behavior_changed) { host_behavior_changed = false; - err = nvme_clear_etdas(dev_fd(dev), &host_behavior_changed); + err = nvme_clear_etdas(hdl, &host_behavior_changed); if (err) { /* Continue on if this fails, it's not a fatal condition */ nvme_show_error("Failed to clear ETDAS bit.\n"); @@ -1646,7 +1568,7 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct /* Pull String log */ sprintf(file_path_string, "%s-%s", opt.output_file, string_suffix); - err = get_c9_log_page_data(dev, 0, 1, (const char *)file_path_string); + err = get_c9_log_page_data(hdl, 0, 1, (const char *)file_path_string); if (err) { nvme_show_error("Failed to fetch string-log from the drive.\n"); goto out; @@ -1682,7 +1604,7 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct printf("Extracting Telemetry Host(%d) Dump (Data Area %d)...\n", (tele_type == TELEMETRY_TYPE_HOST_0) ? 0 : 1, tele_area); - err = get_telemetry_dump(dev, opt.output_file, sn, tele_type, tele_area, true); + err = get_telemetry_dump(hdl, opt.output_file, sn, tele_type, tele_area, true); if (err) fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), err); @@ -1691,7 +1613,6 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct printf("ocp internal-log command completed.\n"); out: - dev_close(dev); return err; } @@ -1712,10 +1633,10 @@ static __u8 unsupported_req_guid[GUID_LEN] = { }; /* Function declaration for unsupported requirement log page (LID:C5h) */ -static int ocp_unsupported_requirements_log(int argc, char **argv, struct command *cmd, +static int ocp_unsupported_requirements_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); -static int get_c5_log_page(struct nvme_dev *dev, char *format) +static int get_c5_log_page(struct nvme_transport_handle *hdl, char *format) { nvme_print_flags_t fmt; int ret; @@ -1737,7 +1658,7 @@ static int get_c5_log_page(struct nvme_dev *dev, char *format) } memset(data, 0, sizeof(__u8) * C5_UNSUPPORTED_REQS_LEN); - ret = ocp_get_log_simple(dev, OCP_LID_URLP, C5_UNSUPPORTED_REQS_LEN, data); + ret = ocp_get_log_simple(hdl, OCP_LID_URLP, C5_UNSUPPORTED_REQS_LEN, data); if (!ret) { log_data = (struct unsupported_requirement_log *)data; @@ -1760,7 +1681,7 @@ static int get_c5_log_page(struct nvme_dev *dev, char *format) goto out; } } - ocp_c5_log(dev, log_data, fmt); + ocp_c5_log(hdl, log_data, fmt); } else { fprintf(stderr, "ERROR : OCP : Unable to read C3 data from buffer\n"); } @@ -1770,11 +1691,12 @@ static int get_c5_log_page(struct nvme_dev *dev, char *format) return ret; } -static int ocp_unsupported_requirements_log(int argc, char **argv, struct command *cmd, +static int ocp_unsupported_requirements_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve unsupported requirements log data."; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = 0; struct config { @@ -1790,15 +1712,14 @@ static int ocp_unsupported_requirements_log(int argc, char **argv, struct comman OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - ret = get_c5_log_page(dev, cfg.output_format); + ret = get_c5_log_page(hdl, cfg.output_format); if (ret) fprintf(stderr, "ERROR : OCP : Failure reading the C5 Log Page, ret = %d\n", ret); - dev_close(dev); return ret; } @@ -1817,10 +1738,10 @@ static __u8 error_recovery_guid[GUID_LEN] = { 0xba, 0x83, 0x19, 0x5a }; -static int get_c1_log_page(struct nvme_dev *dev, char *format); -static int ocp_error_recovery_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); +static int get_c1_log_page(struct nvme_transport_handle *hdl, char *format); +static int ocp_error_recovery_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); -static int get_c1_log_page(struct nvme_dev *dev, char *format) +static int get_c1_log_page(struct nvme_transport_handle *hdl, char *format) { struct ocp_error_recovery_log_page *log_data; nvme_print_flags_t fmt; @@ -1841,7 +1762,7 @@ static int get_c1_log_page(struct nvme_dev *dev, char *format) } memset(data, 0, sizeof(__u8) * C1_ERROR_RECOVERY_LOG_BUF_LEN); - ret = ocp_get_log_simple(dev, OCP_LID_EREC, C1_ERROR_RECOVERY_LOG_BUF_LEN, data); + ret = ocp_get_log_simple(hdl, OCP_LID_EREC, C1_ERROR_RECOVERY_LOG_BUF_LEN, data); if (!ret) { log_data = (struct ocp_error_recovery_log_page *)data; @@ -1875,10 +1796,11 @@ static int get_c1_log_page(struct nvme_dev *dev, char *format) return ret; } -static int ocp_error_recovery_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int ocp_error_recovery_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve C1h Error Recovery Log data."; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = 0; struct config { @@ -1894,14 +1816,14 @@ static int ocp_error_recovery_log(int argc, char **argv, struct command *cmd, st OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - ret = get_c1_log_page(dev, cfg.output_format); + ret = get_c1_log_page(hdl, cfg.output_format); if (ret) fprintf(stderr, "ERROR : OCP : Failure reading the C1h Log Page, ret = %d\n", ret); - dev_close(dev); + return ret; } @@ -1919,10 +1841,10 @@ static __u8 dev_cap_req_guid[GUID_LEN] = { 0x91, 0x3c, 0x05, 0xb7 }; -static int get_c4_log_page(struct nvme_dev *dev, char *format); -static int ocp_device_capabilities_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); +static int get_c4_log_page(struct nvme_transport_handle *hdl, char *format); +static int ocp_device_capabilities_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); -static int get_c4_log_page(struct nvme_dev *dev, char *format) +static int get_c4_log_page(struct nvme_transport_handle *hdl, char *format) { struct ocp_device_capabilities_log_page *log_data; nvme_print_flags_t fmt; @@ -1943,7 +1865,7 @@ static int get_c4_log_page(struct nvme_dev *dev, char *format) } memset(data, 0, sizeof(__u8) * C4_DEV_CAP_REQ_LEN); - ret = ocp_get_log_simple(dev, OCP_LID_DCLP, C4_DEV_CAP_REQ_LEN, data); + ret = ocp_get_log_simple(hdl, OCP_LID_DCLP, C4_DEV_CAP_REQ_LEN, data); if (!ret) { log_data = (struct ocp_device_capabilities_log_page *)data; @@ -1977,10 +1899,11 @@ static int get_c4_log_page(struct nvme_dev *dev, char *format) return ret; } -static int ocp_device_capabilities_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int ocp_device_capabilities_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve C4h Device Capabilities Log data."; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = 0; struct config { @@ -1996,14 +1919,14 @@ static int ocp_device_capabilities_log(int argc, char **argv, struct command *cm OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - ret = get_c4_log_page(dev, cfg.output_format); + ret = get_c4_log_page(hdl, cfg.output_format); if (ret) fprintf(stderr, "ERROR : OCP : Failure reading the C4h Log Page, ret = %d\n", ret); - dev_close(dev); + return ret; } @@ -2013,36 +1936,21 @@ static int ocp_device_capabilities_log(int argc, char **argv, struct command *cm /////////////////////////////////////////////////////////////////////////////// /// Set Telemetry Profile (Feature Identifier C8h) Set Feature -static int ocp_set_telemetry_profile(struct nvme_dev *dev, __u8 tps) +static int ocp_set_telemetry_profile(struct nvme_transport_handle *hdl, __u8 tps) { __u32 result; int err; - __u8 uuid_index = 0; + __u8 uidx = 0; /* OCP 2.0 requires UUID index support */ - err = ocp_get_uuid_index(dev, &uuid_index); - if (err || !uuid_index) { + err = ocp_get_uuid_index(hdl, &uidx); + if (err || !uidx) { nvme_show_error("ERROR: No OCP UUID index found"); return err; } - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = OCP_FID_TEL_CFG, - .nsid = 0xFFFFFFFF, - .cdw11 = tps, - .cdw12 = 0, - .save = true, - .uuidx = uuid_index, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 0xFFFFFFFF, OCP_FID_TEL_CFG, true, tps, 0, 0, + uidx, 0, NULL, 0, &result); if (err > 0) { nvme_show_status(err); } else if (err < 0) { @@ -2056,12 +1964,13 @@ static int ocp_set_telemetry_profile(struct nvme_dev *dev, __u8 tps) return err; } -static int ocp_set_telemetry_profile_feature(int argc, char **argv, struct command *cmd, +static int ocp_set_telemetry_profile_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Set Telemetry Profile (Feature Identifier C8h) Set Feature."; const char *tps = "Telemetry Profile Select for device debug data collection"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; struct config { @@ -2077,17 +1986,15 @@ static int ocp_set_telemetry_profile_feature(int argc, char **argv, struct comma OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; if (argconfig_parse_seen(opts, "telemetry-profile-select")) - err = ocp_set_telemetry_profile(dev, cfg.tps); + err = ocp_set_telemetry_profile(hdl, cfg.tps); else nvme_show_error("Telemetry Profile Select is a required argument"); - dev_close(dev); - return err; } @@ -2096,14 +2003,15 @@ static int ocp_set_telemetry_profile_feature(int argc, char **argv, struct comma /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /// DSSD Power State (Feature Identifier C8h) Get Feature -static int ocp_get_telemetry_profile_feature(int argc, char **argv, struct command *cmd, +static int ocp_get_telemetry_profile_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Define Issue Get Feature command (FID: 0xC8) Latency Monitor"; const char *sel = "[0-3]: current/default/saved/supported/"; const char *nsid = "Byte[04-07]: Namespace Identifier Valid/Invalid/Inactive"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 result; int err; @@ -2127,7 +2035,7 @@ static int ocp_get_telemetry_profile_feature(int argc, char **argv, struct comma OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -2135,28 +2043,15 @@ static int ocp_get_telemetry_profile_feature(int argc, char **argv, struct comma if (uuid) { /* OCP 2.0 requires UUID index support */ - err = ocp_get_uuid_index(dev, &uuid_index); + err = ocp_get_uuid_index(hdl, &uuid_index); if (err || !uuid_index) { nvme_show_error("ERROR: No OCP UUID index found"); return err; } } - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = OCP_FID_TEL_CFG, - .nsid = cfg.nsid, - .sel = cfg.sel, - .cdw11 = 0, - .uuidx = uuid_index, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_get_features(&args); + err = nvme_get_features(hdl, cfg.nsid, OCP_FID_TEL_CFG, cfg.sel, 0, + uuid_index, NULL, 0, &result); if (!err) { printf("get-feature:0xC8 %s value: %#08x\n", nvme_select_to_string(cfg.sel), result); @@ -2176,40 +2071,27 @@ static int ocp_get_telemetry_profile_feature(int argc, char **argv, struct comma /////////////////////////////////////////////////////////////////////////////// /// DSSD Power State (Feature Identifier C7h) Set Feature -static int set_dssd_power_state(struct nvme_dev *dev, const __u32 nsid, - const __u8 fid, __u8 power_state, bool save, +static int +set_dssd_power_state(struct nvme_transport_handle *hdl, + const __u32 nsid, + const __u8 fid, __u8 power_state, bool sv, bool uuid) { __u32 result; int err; - __u8 uuid_index = 0; + __u8 uidx = 0; if (uuid) { /* OCP 2.0 requires UUID index support */ - err = ocp_get_uuid_index(dev, &uuid_index); - if (err || !uuid_index) { + err = ocp_get_uuid_index(hdl, &uidx); + if (err || !uidx) { nvme_show_error("ERROR: No OCP UUID index found"); return err; } } - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = nsid, - .cdw11 = power_state, - .cdw12 = 0, - .save = save, - .uuidx = uuid_index, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_set_features(&args); + err = nvme_set_features(hdl, nsid, fid, sv, power_state, 0, 0, + uidx, 0, NULL, 0, &result); if (err > 0) { nvme_show_status(err); } else if (err < 0) { @@ -2218,20 +2100,21 @@ static int set_dssd_power_state(struct nvme_dev *dev, const __u32 nsid, } else { printf("Successfully set DSSD Power State (feature: 0xC7) to below values\n"); printf("DSSD Power State: 0x%x\n", power_state); - printf("Save bit Value: 0x%x\n", save); + printf("Save bit Value: 0x%x\n", sv); } return err; } -static int set_dssd_power_state_feature(int argc, char **argv, struct command *cmd, +static int set_dssd_power_state_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Define DSSD Power State (Feature Identifier C7h) Set Feature."; const char *power_state = "DSSD Power State to set in watts"; const char *save = "Specifies that the controller shall save the attribute"; const __u32 nsid = 0; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; struct config { @@ -2251,16 +2134,14 @@ static int set_dssd_power_state_feature(int argc, char **argv, struct command *c OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; if (argconfig_parse_seen(opts, "power-state")) - err = set_dssd_power_state(dev, nsid, OCP_FID_DSSDPS, cfg.power_state, cfg.save, + err = set_dssd_power_state(hdl, nsid, OCP_FID_DSSDPS, cfg.power_state, cfg.save, !argconfig_parse_seen(opts, "no-uuid")); - dev_close(dev); - return err; } @@ -2270,7 +2151,7 @@ static int set_dssd_power_state_feature(int argc, char **argv, struct command *c /////////////////////////////////////////////////////////////////////////////// /// DSSD Power State (Feature Identifier C7h) Get Feature -static int get_dssd_power_state(struct nvme_dev *dev, const __u32 nsid, +static int get_dssd_power_state(struct nvme_transport_handle *hdl, const __u32 nsid, const __u8 fid, __u8 sel, bool uuid) { __u32 result; @@ -2279,28 +2160,14 @@ static int get_dssd_power_state(struct nvme_dev *dev, const __u32 nsid, if (uuid) { /* OCP 2.0 requires UUID index support */ - err = ocp_get_uuid_index(dev, &uuid_index); + err = ocp_get_uuid_index(hdl, &uuid_index); if (err || !uuid_index) { nvme_show_error("ERROR: No OCP UUID index found"); return err; } } - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = nsid, - .sel = sel, - .cdw11 = 0, - .uuidx = uuid_index, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_get_features(&args); + err = nvme_get_features(hdl, nsid, fid, sel, 0, uuid_index, NULL, 0, &result); if (!err) { printf("get-feature:0xC7 %s value: %#08x\n", nvme_select_to_string(sel), result); @@ -2313,7 +2180,7 @@ static int get_dssd_power_state(struct nvme_dev *dev, const __u32 nsid, return err; } -static int get_dssd_power_state_feature(int argc, char **argv, struct command *cmd, +static int get_dssd_power_state_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Define DSSD Power State (Feature Identifier C7h) Get Feature."; @@ -2321,7 +2188,8 @@ static int get_dssd_power_state_feature(int argc, char **argv, struct command *c const char *sel = "[0-3]: current/default/saved/supported/"; const __u32 nsid = 0; const __u8 fid = OCP_FID_DSSDPS; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int i, err; struct config { @@ -2341,25 +2209,23 @@ static int get_dssd_power_state_feature(int argc, char **argv, struct command *c OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; if (argconfig_parse_seen(opts, "all")) { for (i = 0; i < 3; i++) { - err = get_dssd_power_state(dev, nsid, fid, i, + err = get_dssd_power_state(hdl, nsid, fid, i, !argconfig_parse_seen(opts, "no-uuid")); if (err) break; } } else if (argconfig_parse_seen(opts, "sel")) - err = get_dssd_power_state(dev, nsid, fid, cfg.sel, + err = get_dssd_power_state(hdl, nsid, fid, cfg.sel, !argconfig_parse_seen(opts, "no-uuid")); else nvme_show_error("Required to have --sel as an argument, or pass the --all flag."); - dev_close(dev); - return err; } @@ -2369,68 +2235,54 @@ static int get_dssd_power_state_feature(int argc, char **argv, struct command *c /////////////////////////////////////////////////////////////////////////////// /// plp_health_check_interval -static int set_plp_health_check_interval(int argc, char **argv, struct command *cmd, +static int set_plp_health_check_interval(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Define Issue Set Feature command (FID : 0xC6) PLP Health Check Interval"; const char *plp_health_interval = "[31:16]:PLP Health Check Interval"; - const char *save = "Specifies that the controller shall save the attribute"; + const char *sv = "Specifies that the controller shall save the attribute"; const __u32 nsid = 0; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; __u32 result; - __u8 uuid_index = 0; + __u8 uidx = 0; struct config { __le16 plp_health_interval; - bool save; + bool sv; }; struct config cfg = { .plp_health_interval = 0, - .save = false, + .sv = false, }; OPT_ARGS(opts) = { OPT_BYTE("plp_health_interval", 'p', &cfg.plp_health_interval, plp_health_interval), - OPT_FLAG("save", 's', &cfg.save, save), + OPT_FLAG("save", 's', &cfg.sv, sv), OPT_FLAG("no-uuid", 'n', NULL, no_uuid), OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; if (!argconfig_parse_seen(opts, "no-uuid")) { /* OCP 2.0 requires UUID index support */ - err = ocp_get_uuid_index(dev, &uuid_index); - if (err || !uuid_index) { + err = ocp_get_uuid_index(hdl, &uidx); + if (err || !uidx) { printf("ERROR: No OCP UUID index found"); return err; } } - - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = OCP_FID_PLPI, - .nsid = nsid, - .cdw11 = cfg.plp_health_interval << 16, - .cdw12 = 0, - .save = cfg.save, - .uuidx = uuid_index, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_set_features(&args); + err = nvme_set_features(hdl, nsid, OCP_FID_PLPI, cfg.sv, + cfg.plp_health_interval << 16, 0, 0, uidx, 0, NULL, 0, + &result); if (err > 0) { nvme_show_status(err); } else if (err < 0) { @@ -2439,19 +2291,20 @@ static int set_plp_health_check_interval(int argc, char **argv, struct command * } else { printf("Successfully set the PLP Health Check Interval"); printf("PLP Health Check Interval: 0x%x\n", cfg.plp_health_interval); - printf("Save bit Value: 0x%x\n", cfg.save); + printf("Save bit Value: 0x%x\n", cfg.sv); } return err; } -static int get_plp_health_check_interval(int argc, char **argv, struct command *cmd, +static int get_plp_health_check_interval(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Define Issue Get Feature command (FID : 0xC6) PLP Health Check Interval"; const __u32 nsid = 0; const __u8 fid = 0xc6; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 result; int err; @@ -2468,26 +2321,12 @@ static int get_plp_health_check_interval(int argc, char **argv, struct command * OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = OCP_FID_PLPI, - .nsid = nsid, - .sel = cfg.sel, - .cdw11 = 0, - .uuidx = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_get_features(&args); + err = nvme_get_features(hdl, nsid, OCP_FID_PLPI, cfg.sel, 0, 0, + NULL, 0, &result); if (!err) { printf("get-feature:0xC6 %s value: %#08x\n", nvme_select_to_string(cfg.sel), result); @@ -2506,63 +2345,49 @@ static int get_plp_health_check_interval(int argc, char **argv, struct command * /////////////////////////////////////////////////////////////////////////////// /// dssd_async_event_config -static int set_dssd_async_event_config(int argc, char **argv, struct command *cmd, +static int set_dssd_async_event_config(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Issue Set Feature command (FID : 0xC9) DSSD Async Event Config"; const char *epn = "[0]:Enable Panic Notices"; - const char *save = "Specifies that the controller shall save the attribute"; + const char *sv = "Specifies that the controller shall save the attribute"; const __u32 nsid = 0; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; __u32 result; - __u8 uuid_index = 0; + __u8 uidx = 0; struct config { bool epn; - bool save; + bool sv; }; struct config cfg = { .epn = false, - .save = false, + .sv = false, }; OPT_ARGS(opts) = { OPT_FLAG("enable-panic-notices", 'e', &cfg.epn, epn), - OPT_FLAG("save", 's', &cfg.save, save), + OPT_FLAG("save", 's', &cfg.sv, sv), OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; /* OCP 2.0 requires UUID index support */ - err = ocp_get_uuid_index(dev, &uuid_index); - if (err || !uuid_index) { + err = ocp_get_uuid_index(hdl, &uidx); + if (err || !uidx) { printf("ERROR: No OCP UUID index found\n"); return err; } - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = OCP_FID_DAEC, - .nsid = nsid, - .cdw11 = cfg.epn ? 1 : 0, - .cdw12 = 0, - .save = cfg.save, - .uuidx = uuid_index, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_set_features(&args); + err = nvme_set_features(hdl, nsid, OCP_FID_DAEC, cfg.sv, cfg.epn ? 1 : 0, + 0, 0, uidx, 0, NULL, 0, &result); if (err > 0) { nvme_show_status(err); } else if (err < 0) { @@ -2571,12 +2396,12 @@ static int set_dssd_async_event_config(int argc, char **argv, struct command *cm } else { printf("Successfully set the DSSD Asynchronous Event Configuration\n"); printf("Enable Panic Notices bit Value: 0x%x\n", cfg.epn); - printf("Save bit Value: 0x%x\n", cfg.save); + printf("Save bit Value: 0x%x\n", cfg.sv); } return err; } -static int get_dssd_async_event_config(int argc, char **argv, struct command *cmd, +static int get_dssd_async_event_config(int argc, char **argv, struct command *acmd, struct plugin *plugin) { @@ -2584,7 +2409,8 @@ static int get_dssd_async_event_config(int argc, char **argv, struct command *cm const char *sel = "[0-3]: current/default/saved/supported"; const __u32 nsid = 0; const __u8 fid = OCP_FID_DAEC; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 result; int err; @@ -2601,26 +2427,11 @@ static int get_dssd_async_event_config(int argc, char **argv, struct command *cm OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = nsid, - .sel = cfg.sel, - .cdw11 = 0, - .uuidx = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_get_features(&args); + err = nvme_get_features(hdl, nsid, fid, cfg.sel, 0, 0, NULL, 0, &result); if (!err) { printf("get-feature:0xC9 %s value: %#08x\n", nvme_select_to_string(cfg.sel), result); @@ -2640,10 +2451,10 @@ static int get_dssd_async_event_config(int argc, char **argv, struct command *cm /// Telemetry String Log Format Log Page (LID : C9h) /* Function declaration for Telemetry String Log Format (LID:C9h) */ -static int ocp_telemetry_str_log_format(int argc, char **argv, struct command *cmd, +static int ocp_telemetry_str_log_format(int argc, char **argv, struct command *acmd, struct plugin *plugin); -static int get_c9_log_page(struct nvme_dev *dev, +static int get_c9_log_page(struct nvme_transport_handle *hdl, char *format, const char *output_file) { @@ -2656,7 +2467,7 @@ static int get_c9_log_page(struct nvme_dev *dev, return ret; } - ret = get_c9_log_page_data(dev, 0, 1, output_file); + ret = get_c9_log_page_data(hdl, 0, 1, output_file); if ((!ret) && (fmt != BINARY)) ocp_c9_log(log_data, pC9_string_buffer, total_log_page_sz, fmt); @@ -2667,10 +2478,11 @@ static int get_c9_log_page(struct nvme_dev *dev, return ret; } -static int ocp_telemetry_str_log_format(int argc, char **argv, struct command *cmd, +static int ocp_telemetry_str_log_format(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = 0; char file_path[PATH_MAX]; const char *string_suffix = ".bin"; @@ -2696,7 +2508,7 @@ static int ocp_telemetry_str_log_format(int argc, char **argv, struct command *c OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; @@ -2705,12 +2517,10 @@ static int ocp_telemetry_str_log_format(int argc, char **argv, struct command *c else sprintf(file_path, "%s", DEFAULT_STRING_BIN); - ret = get_c9_log_page(dev, cfg.output_format, file_path); + ret = get_c9_log_page(hdl, cfg.output_format, file_path); if (ret) fprintf(stderr, "ERROR : OCP : Failure reading the C9 Log Page, ret = %d\n", ret); - dev_close(dev); - return ret; } @@ -2731,10 +2541,10 @@ static __u8 tcg_configuration_guid[GUID_LEN] = { }; /* Function declaration for TCG Configuration log page (LID:C7h) */ -static int ocp_tcg_configuration_log(int argc, char **argv, struct command *cmd, +static int ocp_tcg_configuration_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); -static int get_c7_log_page(struct nvme_dev *dev, char *format) +static int get_c7_log_page(struct nvme_transport_handle *hdl, char *format) { nvme_print_flags_t fmt; int ret; @@ -2756,7 +2566,7 @@ static int get_c7_log_page(struct nvme_dev *dev, char *format) } memset(data, 0, sizeof(__u8) * C7_TCG_CONFIGURATION_LEN); - ret = ocp_get_log_simple(dev, OCP_LID_TCGL, C7_TCG_CONFIGURATION_LEN, data); + ret = ocp_get_log_simple(hdl, OCP_LID_TCGL, C7_TCG_CONFIGURATION_LEN, data); if (!ret) { log_data = (struct tcg_configuration_log *)data; @@ -2779,7 +2589,7 @@ static int get_c7_log_page(struct nvme_dev *dev, char *format) goto out; } } - ocp_c7_log(dev, log_data, fmt); + ocp_c7_log(hdl, log_data, fmt); } else { fprintf(stderr, "ERROR : OCP : Unable to read C7 data from buffer\n"); } @@ -2789,11 +2599,12 @@ static int get_c7_log_page(struct nvme_dev *dev, char *format) return ret; } -static int ocp_tcg_configuration_log(int argc, char **argv, struct command *cmd, +static int ocp_tcg_configuration_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve TCG Configuration Log Page Data"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = 0; struct config { @@ -2809,15 +2620,14 @@ static int ocp_tcg_configuration_log(int argc, char **argv, struct command *cmd, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - ret = get_c7_log_page(dev, cfg.output_format); + ret = get_c7_log_page(hdl, cfg.output_format); if (ret) fprintf(stderr, "ERROR : OCP : Failure reading the C7 Log Page, ret = %d\n", ret); - dev_close(dev); return ret; } @@ -2828,78 +2638,71 @@ static int ocp_tcg_configuration_log(int argc, char **argv, struct command *cmd, /// Misc static int clear_fw_update_history(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *command, struct plugin *plugin) { - return ocp_clear_fw_update_history(argc, argv, cmd, plugin); + return ocp_clear_fw_update_history(argc, argv, command, plugin); } -static int smart_add_log(int argc, char **argv, struct command *cmd, +static int smart_add_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return ocp_smart_add_log(argc, argv, cmd, plugin); + return ocp_smart_add_log(argc, argv, acmd, plugin); } -static int clear_pcie_correctable_error_counters(int argc, char **argv, struct command *cmd, +static int clear_pcie_correctable_error_counters(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return ocp_clear_pcie_correctable_errors(argc, argv, cmd, plugin); + return ocp_clear_pcie_correctable_errors(argc, argv, acmd, plugin); } -static int get_clear_pcie_correctable_error_counters(int argc, char **argv, struct command *cmd, +static int get_clear_pcie_correctable_error_counters(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return get_ocp_error_counters(argc, argv, cmd, plugin); + return get_ocp_error_counters(argc, argv, acmd, plugin); } -static int fw_activation_history_log(int argc, char **argv, struct command *cmd, +static int fw_activation_history_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return ocp_fw_activation_history_log(argc, argv, cmd, plugin); + return ocp_fw_activation_history_log(argc, argv, acmd, plugin); } -static int error_injection_get(struct nvme_dev *dev, const __u8 sel, bool uuid, __u32 nsid) +static int error_injection_get(struct nvme_transport_handle *hdl, const __u8 sel, bool uuid, __u32 nsid) { + _cleanup_free_ struct erri_entry *entry = NULL; struct erri_get_cq_entry cq_entry; + const __u8 fid = OCP_FID_ERRI; + __u32 *result = (__u32 *)&cq_entry; + __u32 data_len = 0; + __u8 uidx = 0; int err; int i; - const __u8 fid = OCP_FID_ERRI; - _cleanup_free_ struct erri_entry *entry = NULL; - - struct nvme_get_features_args args = { - .result = (__u32 *)&cq_entry, - .nsid = nsid, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .sel = sel, - .data_len = sizeof(*entry) * ERRI_ENTRIES_MAX, - .fid = fid, - }; + data_len = sizeof(*entry) * ERRI_ENTRIES_MAX; if (uuid) { /* OCP 2.0 requires UUID index support */ - err = ocp_get_uuid_index(dev, &args.uuidx); - if (err || !args.uuidx) { + err = ocp_get_uuid_index(hdl, &uidx); + if (err || !uidx) { nvme_show_error("ERROR: No OCP UUID index found"); return err; } } - entry = nvme_alloc(args.data_len); + entry = nvme_alloc(data_len); if (!entry) { nvme_show_error("malloc: %s", strerror(errno)); - return -errno; + return -ENOMEM; } - args.data = entry; - err = nvme_cli_get_features(dev, &args); + err = nvme_get_features(hdl, 0, fid, sel, 0, uidx, entry, + data_len, result); if (!err) { nvme_show_result("Number of Error Injections (feature: %#0*x): %#0*x (%s: %d)", fid ? 4 : 2, fid, cq_entry.nume ? 10 : 8, cq_entry.nume, nvme_select_to_string(sel), cq_entry.nume); if (sel == NVME_GET_FEATURES_SEL_SUPPORTED) - nvme_show_select_result(fid, *args.result); + nvme_show_select_result(fid, *result); for (i = 0; i < cq_entry.nume; i++) { printf("Entry: %d, Flags: %x (%s%s), Type: %x (%s), NRTDP: %d\n", i, entry[i].flags, entry[i].enable ? "Enabled" : "Disabled", @@ -2913,9 +2716,11 @@ static int error_injection_get(struct nvme_dev *dev, const __u8 sel, bool uuid, return err; } -static int get_error_injection(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_error_injection(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Return set of error injection"; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; struct config { __u8 sel; @@ -2923,7 +2728,6 @@ static int get_error_injection(int argc, char **argv, struct command *cmd, struc __u32 nsid; struct config cfg = { 0 }; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; OPT_ARGS(opts) = { OPT_BYTE("sel", 's', &cfg.sel, sel), @@ -2932,7 +2736,7 @@ static int get_error_injection(int argc, char **argv, struct command *cmd, struc OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -2944,41 +2748,31 @@ static int get_error_injection(int argc, char **argv, struct command *cmd, struc */ nsid = argconfig_parse_seen(opts, "all-ns") ? NVME_NSID_ALL : 0; - return error_injection_get(dev, cfg.sel, !argconfig_parse_seen(opts, "no-uuid"), nsid); + return error_injection_get(hdl, cfg.sel, !argconfig_parse_seen(opts, "no-uuid"), nsid); } -static int error_injection_set(struct nvme_dev *dev, struct erri_config *cfg, bool uuid, __u32 nsid) +static int error_injection_set(struct nvme_transport_handle *hdl, struct erri_config *cfg, bool uuid, __u32 nsid) { - int err; - __u32 result; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .nsid = nsid, - .fd = dev_fd(dev), - .fid = OCP_FID_ERRI, - .cdw11 = cfg->number, - .data_len = cfg->number * sizeof(struct erri_entry), - .timeout = nvme_cfg.timeout, - .result = &result, - }; - - _cleanup_fd_ int ffd = -1; - _cleanup_free_ struct erri_entry *entry = NULL; + _cleanup_fd_ int ffd = -1; + __u32 data_len; + __u8 uidx = 0; + int err; if (uuid) { /* OCP 2.0 requires UUID index support */ - err = ocp_get_uuid_index(dev, &args.uuidx); - if (err || !args.uuidx) { + err = ocp_get_uuid_index(hdl, &uidx); + if (err || !uidx) { nvme_show_error("ERROR: No OCP UUID index found"); return err; } } - entry = nvme_alloc(args.data_len); + data_len = cfg->number * sizeof(struct erri_entry); + entry = nvme_alloc(data_len); if (!entry) { nvme_show_error("malloc: %s", strerror(errno)); - return -errno; + return -ENOMEM; } if (cfg->file && strlen(cfg->file)) { @@ -2987,7 +2781,7 @@ static int error_injection_set(struct nvme_dev *dev, struct erri_config *cfg, bo nvme_show_error("Failed to open file %s: %s", cfg->file, strerror(errno)); return -EINVAL; } - err = read(ffd, entry, args.data_len); + err = read(ffd, entry, data_len); if (err < 0) { nvme_show_error("failed to read data buffer from input file: %s", strerror(errno)); @@ -3000,9 +2794,8 @@ static int error_injection_set(struct nvme_dev *dev, struct erri_config *cfg, bo entry->nrtdp = cfg->nrtdp; } - args.data = entry; - - err = nvme_set_features(&args); + err = nvme_set_features(hdl, nsid, OCP_FID_ERRI, false, cfg->number, + 0, 0, 0, 0, entry, data_len, NULL); if (err) { if (err < 0) nvme_show_error("set-error-injection: %s", nvme_strerror(errno)); @@ -3012,24 +2805,25 @@ static int error_injection_set(struct nvme_dev *dev, struct erri_config *cfg, bo } printf("set-error-injection, data: %s, number: %d, uuid: %d, type: %d, nrtdp: %d\n", - cfg->file, cfg->number, args.uuidx, cfg->type, cfg->nrtdp); - if (args.data) - d(args.data, args.data_len, 16, 1); + cfg->file, cfg->number, uidx, cfg->type, cfg->nrtdp); + if (entry) + d((unsigned char *)entry, data_len, 16, 1); return 0; } -static int set_error_injection(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int set_error_injection(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Inject error conditions"; - int err; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 nsid; + int err; + struct erri_config cfg = { .number = 1, }; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - NVME_ARGS(opts, OPT_FILE("data", 'd', &cfg.file, data), OPT_BYTE("number", 'n', &cfg.number, number), @@ -3038,7 +2832,7 @@ static int set_error_injection(int argc, char **argv, struct command *cmd, struc OPT_SHRT("type", 't', &cfg.type, type), OPT_SHRT("nrtdp", 'r', &cfg.nrtdp, nrtdp)); - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -3049,37 +2843,31 @@ static int set_error_injection(int argc, char **argv, struct command *cmd, struc * OCP v2.5 - NSID: The host should either clear this to zero or set this to FFFFFFFFh */ nsid = argconfig_parse_seen(opts, "all-ns") ? NVME_NSID_ALL : 0; - return error_injection_set(dev, &cfg, !argconfig_parse_seen(opts, "no-uuid"), nsid); + return error_injection_set(hdl, &cfg, !argconfig_parse_seen(opts, "no-uuid"), nsid); } -static int enable_ieee1667_silo_get(struct nvme_dev *dev, const __u8 sel, bool uuid) +static int enable_ieee1667_silo_get(struct nvme_transport_handle *hdl, const __u8 sel, bool uuid) { - struct ieee1667_get_cq_entry cq_entry; - int err; + struct ieee1667_get_cq_entry cq_entry = { 0 }; const __u8 fid = OCP_FID_1667; - - struct nvme_get_features_args args = { - .result = (__u32 *)&cq_entry, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .sel = sel, - .fid = fid, - }; + __u32 result; + __u8 uidx = 0; + int err; if (uuid) { /* OCP 2.0 requires UUID index support */ - err = ocp_get_uuid_index(dev, &args.uuidx); - if (err || !args.uuidx) { + err = ocp_get_uuid_index(hdl, &uidx); + if (err || !uidx) { nvme_show_error("ERROR: No OCP UUID index found"); return err; } } - err = nvme_cli_get_features(dev, &args); + err = nvme_get_features(hdl, NVME_NSID_NONE, fid, sel, 0, uidx, + NULL, 0, &result); if (!err) { if (sel == NVME_GET_FEATURES_SEL_SUPPORTED) - nvme_show_select_result(fid, *args.result); + nvme_show_select_result(fid, result); else nvme_show_result("IEEE1667 Sifo Enabled (feature: 0x%02x): 0x%0x (%s: %s)", fid, cq_entry.enabled, nvme_select_to_string(sel), @@ -3091,7 +2879,7 @@ static int enable_ieee1667_silo_get(struct nvme_dev *dev, const __u8 sel, bool u return err; } -static int get_enable_ieee1667_silo(int argc, char **argv, struct command *cmd, +static int get_enable_ieee1667_silo(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "return set of enable IEEE1667 silo"; @@ -3101,7 +2889,8 @@ static int get_enable_ieee1667_silo(int argc, char **argv, struct command *cmd, }; struct config cfg = { 0 }; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; OPT_ARGS(opts) = { OPT_BYTE("sel", 's', &cfg.sel, sel), @@ -3109,62 +2898,57 @@ static int get_enable_ieee1667_silo(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - return enable_ieee1667_silo_get(dev, cfg.sel, !argconfig_parse_seen(opts, "no-uuid")); + return enable_ieee1667_silo_get(hdl, cfg.sel, !argconfig_parse_seen(opts, "no-uuid")); } -static int enable_ieee1667_silo_set(struct nvme_dev *dev, +static int enable_ieee1667_silo_set(struct nvme_transport_handle *hdl, struct argconfig_commandline_options *opts) { + bool enable = argconfig_parse_seen(opts, "enable"); + bool save = argconfig_parse_seen(opts, "save"); struct ieee1667_get_cq_entry cq_entry; - int err; const __u8 fid = OCP_FID_1667; - bool enable = argconfig_parse_seen(opts, "enable"); - - struct nvme_set_features_args args = { - .result = (__u32 *)&cq_entry, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .cdw11 = OCP_SET(enable, ENABLE_IEEE1667_SILO), - .save = argconfig_parse_seen(opts, "save"), - .fid = fid, - }; + __u32 cdw11; + __u8 uidx = 0; + int err; if (!argconfig_parse_seen(opts, "no-uuid")) { /* OCP 2.0 requires UUID index support */ - err = ocp_get_uuid_index(dev, &args.uuidx); - if (err || !args.uuidx) { + err = ocp_get_uuid_index(hdl, &uidx); + if (err || !uidx) { nvme_show_error("ERROR: No OCP UUID index found"); return err; } } - err = nvme_cli_set_features(dev, &args); + cdw11 = OCP_SET(enable, ENABLE_IEEE1667_SILO); + err = nvme_set_features(hdl, NVME_NSID_NONE, fid, save, + cdw11, 0, 0, uidx, 0, NULL, 0, (__u32 *)&cq_entry); if (err > 0) { nvme_show_status(err); } else if (err < 0) { nvme_show_perror(enable_ieee1667_silo); fprintf(stderr, "Command failed while parsing.\n"); } else { - enable = OCP_GET(args.cdw11, ENABLE_IEEE1667_SILO); nvme_show_result("Successfully set enable (feature: 0x%02x): %d (%s: %s).", fid, - enable, args.save ? "Save" : "Not save", + enable, save ? "Save" : "Not save", enable ? "Enabled" : "Disabled"); } return err; } -static int set_enable_ieee1667_silo(int argc, char **argv, struct command *cmd, +static int set_enable_ieee1667_silo(int argc, char **argv, struct command *acmd, struct plugin *plugin) { int err; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; OPT_ARGS(opts) = { OPT_FLAG("enable", 'e', NULL, no_uuid), @@ -3173,14 +2957,14 @@ static int set_enable_ieee1667_silo(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, enable_ieee1667_silo, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, enable_ieee1667_silo, opts); if (err) return err; - return enable_ieee1667_silo_set(dev, opts); + return enable_ieee1667_silo_set(hdl, opts); } -static int hwcomp_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int hwcomp_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return ocp_hwcomp_log(argc, argv, cmd, plugin); + return ocp_hwcomp_log(argc, argv, acmd, plugin); } diff --git a/plugins/ocp/ocp-print-binary.c b/plugins/ocp/ocp-print-binary.c index c966b4737f..50604296bc 100644 --- a/plugins/ocp/ocp-print-binary.c +++ b/plugins/ocp/ocp-print-binary.c @@ -15,7 +15,7 @@ static void binary_hwcomp_log(struct hwcomp_log *log, __u32 id, bool list) d_raw((unsigned char *)log, log_bytes); } -static void binary_c5_log(struct nvme_dev *dev, struct unsupported_requirement_log *log_data) +static void binary_c5_log(struct nvme_transport_handle *hdl, struct unsupported_requirement_log *log_data) { d_raw((unsigned char *)log_data, sizeof(*log_data)); } @@ -36,7 +36,7 @@ static void binary_c9_log(struct telemetry_str_log_format *log_data, __u8 *log_d d_raw((unsigned char *)log_data_buf, total_log_page_size); } -static void binary_c7_log(struct nvme_dev *dev, struct tcg_configuration_log *log_data) +static void binary_c7_log(struct nvme_transport_handle *hdl, struct tcg_configuration_log *log_data) { d_raw((unsigned char *)log_data, sizeof(*log_data)); } diff --git a/plugins/ocp/ocp-print-json.c b/plugins/ocp/ocp-print-json.c index a76ecc2797..d4b7e77bb6 100644 --- a/plugins/ocp/ocp-print-json.c +++ b/plugins/ocp/ocp-print-json.c @@ -478,7 +478,7 @@ static void json_telemetry_log(struct ocp_telemetry_parse_options *options) print_ocp_telemetry_json(options); } -static void json_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data) +static void json_c3_log(struct nvme_transport_handle *hdl, struct ssd_latency_monitor_log *log_data) { struct json_object *root; char ts_buf[128]; @@ -649,7 +649,7 @@ static void json_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log *lo json_free_object(root); } -static void json_c5_log(struct nvme_dev *dev, struct unsupported_requirement_log *log_data) +static void json_c5_log(struct nvme_transport_handle *hdl, struct unsupported_requirement_log *log_data) { int j; struct json_object *root; @@ -1031,7 +1031,7 @@ static void json_c9_log(struct telemetry_str_log_format *log_data, __u8 *log_dat json_free_object(root); } -static void json_c7_log(struct nvme_dev *dev, struct tcg_configuration_log *log_data) +static void json_c7_log(struct nvme_transport_handle *hdl, struct tcg_configuration_log *log_data) { int j; struct json_object *root; diff --git a/plugins/ocp/ocp-print-stdout.c b/plugins/ocp/ocp-print-stdout.c index d63a318715..f99fbda6c3 100644 --- a/plugins/ocp/ocp-print-stdout.c +++ b/plugins/ocp/ocp-print-stdout.c @@ -246,14 +246,15 @@ static void stdout_telemetry_log(struct ocp_telemetry_parse_options *options) #endif /* CONFIG_JSONC */ } -static void stdout_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data) +static void stdout_c3_log(struct nvme_transport_handle *hdl, struct ssd_latency_monitor_log *log_data) { char ts_buf[128]; int i, j; __u16 log_page_version = le16_to_cpu(log_data->log_page_version); printf("-Latency Monitor/C3 Log Page Data-\n"); - printf(" Controller : %s\n", dev->name); + printf(" Controller : %s\n", + nvme_transport_handle_get_name(hdl)); printf(" Feature Status 0x%x\n", log_data->feature_status); printf(" Active Bucket Timer %d min\n", @@ -384,7 +385,7 @@ static void stdout_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log * } } -static void stdout_c5_log(struct nvme_dev *dev, struct unsupported_requirement_log *log_data) +static void stdout_c5_log(struct nvme_transport_handle *hdl, struct unsupported_requirement_log *log_data) { int j; @@ -685,7 +686,7 @@ static void stdout_c9_log(struct telemetry_str_log_format *log_data, __u8 *log_d } } -static void stdout_c7_log(struct nvme_dev *dev, struct tcg_configuration_log *log_data) +static void stdout_c7_log(struct nvme_transport_handle *hdl, struct tcg_configuration_log *log_data) { int j; __u16 log_page_version = le16_to_cpu(log_data->log_page_version); diff --git a/plugins/ocp/ocp-print.c b/plugins/ocp/ocp-print.c index 31037db946..43acf729c2 100644 --- a/plugins/ocp/ocp-print.c +++ b/plugins/ocp/ocp-print.c @@ -47,16 +47,18 @@ void ocp_show_telemetry_log(struct ocp_telemetry_parse_options *options, nvme_pr ocp_print(telemetry_log, flags, options); } -void ocp_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data, +void ocp_c3_log(struct nvme_transport_handle *hdl, + struct ssd_latency_monitor_log *log_data, nvme_print_flags_t flags) { - ocp_print(c3_log, flags, dev, log_data); + ocp_print(c3_log, flags, hdl, log_data); } -void ocp_c5_log(struct nvme_dev *dev, struct unsupported_requirement_log *log_data, +void ocp_c5_log(struct nvme_transport_handle *hdl, + struct unsupported_requirement_log *log_data, nvme_print_flags_t flags) { - ocp_print(c5_log, flags, dev, log_data); + ocp_print(c5_log, flags, hdl, log_data); } void ocp_c1_log(struct ocp_error_recovery_log_page *log_data, nvme_print_flags_t flags) @@ -75,8 +77,9 @@ void ocp_c9_log(struct telemetry_str_log_format *log_data, __u8 *log_data_buf, ocp_print(c9_log, flags, log_data, log_data_buf, total_log_page_size); } -void ocp_c7_log(struct nvme_dev *dev, struct tcg_configuration_log *log_data, +void ocp_c7_log(struct nvme_transport_handle *hdl, + struct tcg_configuration_log *log_data, nvme_print_flags_t flags) { - ocp_print(c7_log, flags, dev, log_data); + ocp_print(c7_log, flags, hdl, log_data); } diff --git a/plugins/ocp/ocp-print.h b/plugins/ocp/ocp-print.h index e9ede1c09e..35b9e10c1a 100644 --- a/plugins/ocp/ocp-print.h +++ b/plugins/ocp/ocp-print.h @@ -13,13 +13,13 @@ struct ocp_print_ops { void (*fw_act_history)(const struct fw_activation_history *fw_history); void (*smart_extended_log)(struct ocp_smart_extended_log *log, unsigned int version); void (*telemetry_log)(struct ocp_telemetry_parse_options *options); - void (*c3_log)(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data); - void (*c5_log)(struct nvme_dev *dev, struct unsupported_requirement_log *log_data); + void (*c3_log)(struct nvme_transport_handle *hdl, struct ssd_latency_monitor_log *log_data); + void (*c5_log)(struct nvme_transport_handle *hdl, struct unsupported_requirement_log *log_data); void (*c1_log)(struct ocp_error_recovery_log_page *log_data); void (*c4_log)(struct ocp_device_capabilities_log_page *log_data); void (*c9_log)(struct telemetry_str_log_format *log_data, __u8 *log_data_buf, int total_log_page_size); - void (*c7_log)(struct nvme_dev *dev, struct tcg_configuration_log *log_data); + void (*c7_log)(struct nvme_transport_handle *hdl, struct tcg_configuration_log *log_data); nvme_print_flags_t flags; }; @@ -40,14 +40,14 @@ void ocp_fw_act_history(const struct fw_activation_history *fw_history, nvme_pri void ocp_smart_extended_log(struct ocp_smart_extended_log *log, unsigned int version, nvme_print_flags_t flags); void ocp_show_telemetry_log(struct ocp_telemetry_parse_options *options, nvme_print_flags_t flags); -void ocp_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data, +void ocp_c3_log(struct nvme_transport_handle *hdl, struct ssd_latency_monitor_log *log_data, nvme_print_flags_t flags); -void ocp_c5_log(struct nvme_dev *dev, struct unsupported_requirement_log *log_data, +void ocp_c5_log(struct nvme_transport_handle *hdl, struct unsupported_requirement_log *log_data, nvme_print_flags_t flags); void ocp_c1_log(struct ocp_error_recovery_log_page *log_data, nvme_print_flags_t flags); void ocp_c4_log(struct ocp_device_capabilities_log_page *log_data, nvme_print_flags_t flags); void ocp_c9_log(struct telemetry_str_log_format *log_data, __u8 *log_data_buf, int total_log_page_size, nvme_print_flags_t flags); -void ocp_c7_log(struct nvme_dev *dev, struct tcg_configuration_log *log_data, +void ocp_c7_log(struct nvme_transport_handle *hdl, struct tcg_configuration_log *log_data, nvme_print_flags_t flags); #endif /* OCP_PRINT_H */ diff --git a/plugins/ocp/ocp-smart-extended-log.c b/plugins/ocp/ocp-smart-extended-log.c index 5e081c969f..d2341356f4 100644 --- a/plugins/ocp/ocp-smart-extended-log.c +++ b/plugins/ocp/ocp-smart-extended-log.c @@ -26,21 +26,15 @@ static __u8 scao_guid[GUID_LEN] = { 0xC9, 0x14, 0xD5, 0xAF }; -static int get_c0_log_page(struct nvme_dev *dev, char *format, +static int get_c0_log_page(struct nvme_transport_handle *hdl, char *format, unsigned int format_version) { - nvme_print_flags_t fmt; struct ocp_smart_extended_log *data; - int i; + struct nvme_passthru_cmd cmd; + nvme_print_flags_t fmt; + __u8 uidx; int ret; - int fd = dev_fd(dev); - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = (enum nvme_cmd_get_log_lid)OCP_LID_SMART, - .nsid = NVME_NSID_ALL, - .len = C0_SMART_CLOUD_ATTR_LEN, - }; + int i; ret = validate_output_format(format, &fmt); if (ret < 0) { @@ -55,9 +49,15 @@ static int get_c0_log_page(struct nvme_dev *dev, char *format, } memset(data, 0, sizeof(__u8) * C0_SMART_CLOUD_ATTR_LEN); - args.log = data; - ocp_get_uuid_index(dev, &args.uuidx); - ret = nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); + ocp_get_uuid_index(hdl, &uidx); + nvme_init_get_log(&cmd, NVME_NSID_ALL, + (enum nvme_cmd_get_log_lid)OCP_LID_SMART, + NVME_CSI_NVM, data, C0_SMART_CLOUD_ATTR_LEN); + cmd.cdw14 |= NVME_FIELD_ENCODE(uidx, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + ret = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", @@ -96,11 +96,12 @@ static int get_c0_log_page(struct nvme_dev *dev, char *format, return ret; } -int ocp_smart_add_log(int argc, char **argv, struct command *cmd, - struct plugin *plugin) +int ocp_smart_add_log(int argc, char **argv, struct command *acmd, + struct plugin *plugin) { const char *desc = "Retrieve the extended SMART health data."; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = 0; struct config { @@ -119,15 +120,14 @@ int ocp_smart_add_log(int argc, char **argv, struct command *cmd, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - ret = get_c0_log_page(dev, cfg.output_format, + ret = get_c0_log_page(hdl, cfg.output_format, cfg.output_format_version); if (ret) fprintf(stderr, "ERROR : OCP : Failure reading the C0 Log Page, ret = %d\n", ret); - dev_close(dev); return ret; } diff --git a/plugins/ocp/ocp-smart-extended-log.h b/plugins/ocp/ocp-smart-extended-log.h index df338099bf..9ac52e508f 100644 --- a/plugins/ocp/ocp-smart-extended-log.h +++ b/plugins/ocp/ocp-smart-extended-log.h @@ -151,7 +151,7 @@ struct ocp_smart_extended_log { __u8 log_page_guid[16]; /* [511:496] */ }; -int ocp_smart_add_log(int argc, char **argv, struct command *cmd, +int ocp_smart_add_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); #endif diff --git a/plugins/ocp/ocp-utils.c b/plugins/ocp/ocp-utils.c index e3c0747fa9..665c0c2163 100644 --- a/plugins/ocp/ocp-utils.c +++ b/plugins/ocp/ocp-utils.c @@ -10,6 +10,7 @@ #include "util/types.h" #include "ocp-nvme.h" #include "ocp-utils.h" +#include "types.h" const unsigned char ocp_uuid[NVME_UUID_LEN] = { 0xc1, 0x94, 0xd5, 0x5b, 0xe0, 0x94, 0x47, 0x94, 0xa2, 0x1d, @@ -28,34 +29,32 @@ int ocp_find_uuid_index(struct nvme_id_uuid_list *uuid_list, __u8 *index) return 0; } -int ocp_get_uuid_index(struct nvme_dev *dev, __u8 *index) +int ocp_get_uuid_index(struct nvme_transport_handle *hdl, __u8 *index) { struct nvme_id_uuid_list uuid_list; - int err = nvme_identify_uuid(dev_fd(dev), &uuid_list); + int err; *index = 0; + + err = nvme_identify_uuid_list(hdl, &uuid_list); if (err) return err; return ocp_find_uuid_index(&uuid_list, index); } -int ocp_get_log_simple(struct nvme_dev *dev, enum ocp_dssd_log_id lid, __u32 len, void *log) +int ocp_get_log_simple(struct nvme_transport_handle *hdl, + enum ocp_dssd_log_id lid, __u32 len, void *log) { - int fd = dev_fd(dev); - struct nvme_get_log_args args = { - .log = log, - .args_size = sizeof(args), - .fd = fd, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = (enum nvme_cmd_get_log_lid)lid, - .len = len, - .nsid = NVME_NSID_ALL, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - }; - - ocp_get_uuid_index(dev, &args.uuidx); - - return nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &args); + struct nvme_passthru_cmd cmd; + __u8 uidx; + + ocp_get_uuid_index(hdl, &uidx); + nvme_init_get_log(&cmd, NVME_NSID_ALL, (enum nvme_cmd_get_log_lid) lid, + NVME_CSI_NVM, log, len); + cmd.cdw14 |= NVME_FIELD_ENCODE(uidx, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + + return nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); } diff --git a/plugins/ocp/ocp-utils.h b/plugins/ocp/ocp-utils.h index 9832474eac..58eef7b031 100644 --- a/plugins/ocp/ocp-utils.h +++ b/plugins/ocp/ocp-utils.h @@ -19,7 +19,7 @@ extern const unsigned char ocp_uuid[NVME_UUID_LEN]; * Return: Zero if nvme device has UUID list identify page, or positive result of get uuid list * or negative POSIX error code otherwise. */ -int ocp_get_uuid_index(struct nvme_dev *dev, __u8 *index); +int ocp_get_uuid_index(struct nvme_transport_handle *hdl, __u8 *index); /** * ocp_find_uuid_index() - Find OCP UUID index in UUID list @@ -30,4 +30,4 @@ int ocp_get_uuid_index(struct nvme_dev *dev, __u8 *index); */ int ocp_find_uuid_index(struct nvme_id_uuid_list *uuid_list, __u8 *index); -int ocp_get_log_simple(struct nvme_dev *dev, enum ocp_dssd_log_id lid, __u32 len, void *log); +int ocp_get_log_simple(struct nvme_transport_handle *hdl, enum ocp_dssd_log_id lid, __u32 len, void *log); diff --git a/plugins/sandisk/sandisk-nvme.c b/plugins/sandisk/sandisk-nvme.c index d888788a94..c2615c8913 100644 --- a/plugins/sandisk/sandisk-nvme.c +++ b/plugins/sandisk/sandisk-nvme.c @@ -33,8 +33,10 @@ static __u8 ocp_C2_guid[SNDK_GUID_LENGTH] = { 0xE2, 0x4D, 0xB2, 0x8A, 0xAC, 0xF3, 0x1C, 0xD1 }; -static int sndk_do_cap_telemetry_log(struct nvme_dev *dev, const char *file, - __u32 bs, int type, int data_area) +static int sndk_do_cap_telemetry_log(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl, + const char *file, __u32 bs, int type, + int data_area) { struct nvme_telemetry_log *log; size_t full_size = 0; @@ -45,11 +47,10 @@ static int sndk_do_cap_telemetry_log(struct nvme_dev *dev, const char *file, int data_written = 0, data_remaining = 0; struct nvme_id_ctrl ctrl; __u64 capabilities = 0; - nvme_root_t r; bool host_behavior_changed = false; memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err) { fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", err); return err; @@ -60,8 +61,10 @@ static int sndk_do_cap_telemetry_log(struct nvme_dev *dev, const char *file, return -EINVAL; } - r = nvme_scan(NULL); - capabilities = sndk_get_drive_capabilities(r, dev); + err = nvme_scan_topology(ctx, NULL, NULL); + if (err) + return err; + capabilities = sndk_get_drive_capabilities(ctx, hdl); if (data_area == 4) { if (!(ctrl.lpa & 0x40)) { @@ -70,7 +73,7 @@ static int sndk_do_cap_telemetry_log(struct nvme_dev *dev, const char *file, return -EINVAL; } - err = nvme_set_etdas(dev_fd(dev), &host_behavior_changed); + err = nvme_set_etdas(hdl, &host_behavior_changed); if (err) { fprintf(stderr, "%s: Failed to set ETDAS bit\n", __func__); return err; @@ -82,7 +85,7 @@ static int sndk_do_cap_telemetry_log(struct nvme_dev *dev, const char *file, ctrl_init = 0; } else if (type == SNDK_TELEMETRY_TYPE_CONTROLLER) { if (capabilities & SNDK_DRIVE_CAP_INTERNAL_LOG) { - err = sndk_check_ctrl_telemetry_option_disabled(dev); + err = sndk_check_ctrl_telemetry_option_disabled(hdl); if (err) return err; } @@ -106,13 +109,13 @@ static int sndk_do_cap_telemetry_log(struct nvme_dev *dev, const char *file, } if (ctrl_init) - err = nvme_get_ctrl_telemetry(dev_fd(dev), true, &log, + err = nvme_get_ctrl_telemetry(hdl, true, &log, data_area, &full_size); else if (host_gen) - err = nvme_get_new_host_telemetry(dev_fd(dev), &log, + err = nvme_get_new_host_telemetry(hdl, &log, data_area, &full_size); else - err = nvme_get_host_telemetry(dev_fd(dev), &log, data_area, + err = nvme_get_host_telemetry(hdl, &log, data_area, &full_size); if (err < 0) { @@ -157,7 +160,7 @@ static int sndk_do_cap_telemetry_log(struct nvme_dev *dev, const char *file, if (host_behavior_changed) { host_behavior_changed = false; - err = nvme_clear_etdas(dev_fd(dev), &host_behavior_changed); + err = nvme_clear_etdas(hdl, &host_behavior_changed); if (err) { fprintf(stderr, "%s: Failed to clear ETDAS bit\n", __func__); return err; @@ -170,8 +173,8 @@ static int sndk_do_cap_telemetry_log(struct nvme_dev *dev, const char *file, return err; } -static __u32 sndk_dump_udui_data(int fd, __u32 dataLen, __u32 offset, - __u8 *dump_data) +static __u32 sndk_dump_udui_data(struct nvme_transport_handle *hdl, + __u32 dataLen, __u32 offset, __u8 *dump_data) { int ret; struct nvme_passthru_cmd admin_cmd; @@ -183,7 +186,7 @@ static __u32 sndk_dump_udui_data(int fd, __u32 dataLen, __u32 offset, admin_cmd.data_len = dataLen; admin_cmd.cdw10 = ((dataLen >> 2) - 1); admin_cmd.cdw12 = offset; - ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (ret) { fprintf(stderr, "ERROR: SNDK: reading DUI data failed\n"); nvme_show_status(ret); @@ -192,8 +195,9 @@ static __u32 sndk_dump_udui_data(int fd, __u32 dataLen, __u32 offset, return ret; } -static int sndk_do_cap_udui(int fd, char *file, __u32 xfer_size, int verbose, - __u64 file_size, __u64 offset) +static int sndk_do_cap_udui(struct nvme_transport_handle *hdl, char *file, + __u32 xfer_size, int verbose, __u64 file_size, + __u64 offset) { int ret = 0; int output; @@ -213,7 +217,7 @@ static int sndk_do_cap_udui(int fd, char *file, __u32 xfer_size, int verbose, memset(log, 0, udui_log_hdr_size); /* get the udui telemetry and log headers */ - ret = sndk_dump_udui_data(fd, udui_log_hdr_size, 0, (__u8 *)log); + ret = sndk_dump_udui_data(hdl, udui_log_hdr_size, 0, (__u8 *)log); if (ret) { fprintf(stderr, "%s: ERROR: SNDK: Get UDUI header failed\n", __func__); nvme_show_status(ret); @@ -242,7 +246,7 @@ static int sndk_do_cap_udui(int fd, char *file, __u32 xfer_size, int verbose, while (offset < total_size) { if (chunk_size > total_size - offset) chunk_size = total_size - offset; - ret = sndk_dump_udui_data(fd, chunk_size, offset, + ret = sndk_dump_udui_data(hdl, chunk_size, offset, ((__u8 *)log)); if (ret) { fprintf(stderr, @@ -294,8 +298,6 @@ static int sndk_vs_internal_fw_log(int argc, char **argv, const char *verbose = "Display more debug messages."; char f[PATH_MAX] = {0}; char fileSuffix[PATH_MAX] = {0}; - struct nvme_dev *dev; - nvme_root_t r; __u32 xfer_size = 0; int telemetry_type = 0, telemetry_data_area = 0; struct SNDK_UtilsTimeInfo timeInfo; @@ -303,6 +305,8 @@ static int sndk_vs_internal_fw_log(int argc, char **argv, __u64 capabilities = 0; __u32 device_id, read_vendor_id; int ret = -1; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct config { char *file; @@ -335,12 +339,12 @@ static int sndk_vs_internal_fw_log(int argc, char **argv, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); - if (!sndk_check_device(r, dev)) + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || !sndk_check_device(ctx, hdl)) goto out; if (cfg.xfer_size) { @@ -350,7 +354,7 @@ static int sndk_vs_internal_fw_log(int argc, char **argv, goto out; } - ret = sndk_get_pci_ids(r, dev, &device_id, &read_vendor_id); + ret = sndk_get_pci_ids(ctx, hdl, &device_id, &read_vendor_id); if (cfg.file) { int verify_file; @@ -373,7 +377,7 @@ static int sndk_vs_internal_fw_log(int argc, char **argv, timeInfo.second); snprintf(fileSuffix, PATH_MAX, "_internal_fw_log_%s", (char *)timeStamp); - ret = sndk_get_serial_name(dev, f, PATH_MAX, fileSuffix); + ret = sndk_get_serial_name(hdl, f, PATH_MAX, fileSuffix); if (ret) { fprintf(stderr, "ERROR: SNDK: failed to generate file name\n"); goto out; @@ -414,7 +418,7 @@ static int sndk_vs_internal_fw_log(int argc, char **argv, goto out; } - capabilities = sndk_get_drive_capabilities(r, dev); + capabilities = sndk_get_drive_capabilities(ctx, hdl); /* Supported through WDC plugin for non-telemetry */ if ((capabilities & SNDK_DRIVE_CAP_INTERNAL_LOG) && @@ -423,7 +427,7 @@ static int sndk_vs_internal_fw_log(int argc, char **argv, if (!telemetry_data_area) telemetry_data_area = 3; - ret = sndk_do_cap_telemetry_log(dev, f, xfer_size, + ret = sndk_do_cap_telemetry_log(ctx, hdl, f, xfer_size, telemetry_type, telemetry_data_area); goto out; } @@ -435,11 +439,11 @@ static int sndk_vs_internal_fw_log(int argc, char **argv, if (!telemetry_data_area) telemetry_data_area = 3; - ret = sndk_do_cap_telemetry_log(dev, f, xfer_size, + ret = sndk_do_cap_telemetry_log(ctx, hdl, f, xfer_size, telemetry_type, telemetry_data_area); goto out; } else { - ret = sndk_do_cap_udui(dev_fd(dev), f, xfer_size, + ret = sndk_do_cap_udui(hdl, f, xfer_size, cfg.verbose, cfg.file_size, cfg.offset); goto out; @@ -447,13 +451,9 @@ static int sndk_vs_internal_fw_log(int argc, char **argv, } /* Fallback to WDC plugin if otherwise not supported */ - nvme_free_tree(r); - dev_close(dev); return run_wdc_vs_internal_fw_log(argc, argv, command, plugin); out: - nvme_free_tree(r); - dev_close(dev); return ret; } @@ -495,7 +495,7 @@ static int sndk_clear_assert_dump(int argc, char **argv, #define SNDK_NVME_SN861_DRIVE_RESIZE_OPCODE 0xD1 #define SNDK_NVME_SN861_DRIVE_RESIZE_BUFFER_SIZE 0x1000 -static int sndk_do_sn861_drive_resize(struct nvme_dev *dev, +static int sndk_do_sn861_drive_resize(struct nvme_transport_handle *hdl, uint64_t new_size, __u32 *result) { @@ -513,7 +513,7 @@ static int sndk_do_sn861_drive_resize(struct nvme_dev *dev, admin_cmd.addr = (__u64)(uintptr_t)buffer; admin_cmd.data_len = SNDK_NVME_SN861_DRIVE_RESIZE_BUFFER_SIZE; - ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, result); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, result); return ret; } @@ -523,9 +523,9 @@ static int sndk_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."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; uint64_t capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; int ret; uint32_t device_id = -1, vendor_id = -1; __u32 result; @@ -543,17 +543,19 @@ static int sndk_drive_resize(int argc, char **argv, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); - sndk_check_device(r, dev); - capabilities = sndk_get_drive_capabilities(r, dev); - ret = sndk_get_pci_ids(r, dev, &device_id, &vendor_id); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret) + return ret; + sndk_check_device(ctx, hdl); + capabilities = sndk_get_drive_capabilities(ctx, hdl); + ret = sndk_get_pci_ids(ctx, hdl, &device_id, &vendor_id); if ((capabilities & SNDK_DRIVE_CAP_RESIZE_SN861) == SNDK_DRIVE_CAP_RESIZE_SN861) { - ret = sndk_do_sn861_drive_resize(dev, cfg.size, &result); + ret = sndk_do_sn861_drive_resize(hdl, cfg.size, &result); if (!ret) { fprintf(stderr, "The drive-resize command was successful. A system "); @@ -563,14 +565,10 @@ static int sndk_drive_resize(int argc, char **argv, __func__, ret, result); } else { /* Fallback to WDC plugin command if otherwise not supported */ - nvme_free_tree(r); - dev_close(dev); return run_wdc_drive_resize(argc, argv, command, plugin); } nvme_show_status(ret); - nvme_free_tree(r); - dev_close(dev); return ret; } @@ -804,7 +802,7 @@ static int sndk_print_fw_act_history_log(__u8 *data, int num_entries, int fmt) return 0; } -static int sndk_get_fw_act_history_C2(nvme_root_t r, struct nvme_dev *dev, +static int sndk_get_fw_act_history_C2(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, char *format) { struct sndk_fw_act_history_log_format_c2 *fw_act_history_log; @@ -814,7 +812,7 @@ static int sndk_get_fw_act_history_C2(nvme_root_t r, struct nvme_dev *dev, int ret; bool c2GuidMatch = false; - if (!sndk_check_device(r, dev)) + if (!sndk_check_device(ctx, hdl)) return -1; ret = validate_output_format(format, &fmt); @@ -831,9 +829,9 @@ static int sndk_get_fw_act_history_C2(nvme_root_t r, struct nvme_dev *dev, memset(data, 0, sizeof(__u8) * SNDK_FW_ACT_HISTORY_C2_LOG_BUF_LEN); - ret = nvme_get_log_simple(dev_fd(dev), + ret = nvme_get_log_simple(hdl, SNDK_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID, - SNDK_FW_ACT_HISTORY_C2_LOG_BUF_LEN, data); + data, SNDK_FW_ACT_HISTORY_C2_LOG_BUF_LEN); if (strcmp(format, "json")) nvme_show_status(ret); @@ -878,10 +876,10 @@ static int sndk_vs_fw_activate_history(int argc, char **argv, struct plugin *plugin) { const char *desc = "Retrieve FW activate history table."; - __u64 capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; - int ret = -1; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + uint64_t capabilities = 0; + int ret; struct config { char *output_format; @@ -896,15 +894,17 @@ static int sndk_vs_fw_activate_history(int argc, char **argv, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); - capabilities = sndk_get_drive_capabilities(r, dev); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret) + return ret; + capabilities = sndk_get_drive_capabilities(ctx, hdl); if (capabilities & SNDK_DRIVE_CAP_FW_ACTIVATE_HISTORY_C2) { - ret = sndk_get_fw_act_history_C2(r, dev, cfg.output_format); + ret = sndk_get_fw_act_history_C2(ctx, hdl, cfg.output_format); if (ret) { fprintf(stderr, "ERROR: SNDK: Failure reading the FW "); @@ -914,18 +914,16 @@ static int sndk_vs_fw_activate_history(int argc, char **argv, /* Fall back to the wdc plugin command */ ret = run_wdc_vs_fw_activate_history(argc, argv, command, plugin); - nvme_free_tree(r); - dev_close(dev); return ret; } -static int sndk_do_clear_fw_activate_history_fid(int fd) +static int sndk_do_clear_fw_activate_history_fid(struct nvme_transport_handle *hdl) { int ret = -1; __u32 result; __u32 value = 1 << 31; /* Bit 31 - Clear Firmware Update History Log */ - ret = nvme_set_features_simple(fd, SNDK_NVME_CLEAR_FW_ACT_HIST_VU_FID, 0, value, + ret = nvme_set_features_simple(hdl, SNDK_NVME_CLEAR_FW_ACT_HIST_VU_FID, 0, value, false, &result); nvme_show_status(ret); @@ -937,24 +935,26 @@ static int sndk_clear_fw_activate_history(int argc, char **argv, struct plugin *plugin) { const char *desc = "Clear FW activate history table."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u64 capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; int ret; OPT_ARGS(opts) = { OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); - capabilities = sndk_get_drive_capabilities(r, dev); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret) + return ret; + capabilities = sndk_get_drive_capabilities(ctx, hdl); if (capabilities & SNDK_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY) { - ret = sndk_do_clear_fw_activate_history_fid(dev_fd(dev)); + ret = sndk_do_clear_fw_activate_history_fid(hdl); if (ret) { fprintf(stderr, "ERROR: SNDK: Failure clearing the FW "); @@ -964,8 +964,6 @@ static int sndk_clear_fw_activate_history(int argc, char **argv, /* Fall back to the wdc plugin command */ ret = run_wdc_clear_fw_activate_history(argc, argv, command, plugin); - nvme_free_tree(r); - dev_close(dev); return ret; } @@ -1009,26 +1007,28 @@ static int sndk_capabilities(int argc, char **argv, struct plugin *plugin) { const char *desc = "Send a capabilities command."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; uint64_t capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; int ret; OPT_ARGS(opts) = { OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; /* get capabilities */ - r = nvme_scan(NULL); - sndk_check_device(r, dev); - capabilities = sndk_get_drive_capabilities(r, dev); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || sndk_check_device(ctx, hdl)) + return -1; + + capabilities = sndk_get_drive_capabilities(ctx, hdl); /* print command and supported status */ - printf("Sandisk Plugin Capabilities for NVME device:%s\n", dev->name); + printf("Sandisk Plugin Capabilities for NVME device:%s\n", nvme_transport_handle_get_name(hdl)); printf("vs-internal-log : %s\n", capabilities & SNDK_DRIVE_CAP_INTERNAL_LOG_MASK ? "Supported" : "Not Supported"); printf("vs-nand-stats : %s\n", @@ -1095,8 +1095,6 @@ static int sndk_capabilities(int argc, char **argv, printf("set-latency-monitor-feature : %s\n", capabilities & SNDK_DRIVE_CAP_SET_LATENCY_MONITOR ? "Supported" : "Not Supported"); printf("capabilities : Supported\n"); - nvme_free_tree(r); - dev_close(dev); return 0; } diff --git a/plugins/sandisk/sandisk-utils.c b/plugins/sandisk/sandisk-utils.c index 523609dec4..835c82e7ac 100644 --- a/plugins/sandisk/sandisk-utils.c +++ b/plugins/sandisk/sandisk-utils.c @@ -30,26 +30,28 @@ static const __u8 SNDK_UUID[NVME_UUID_LEN] = { 0xad, 0xd8, 0x3c, 0x29, 0xd1, 0x23, 0x7c, 0x70 }; -int sndk_get_pci_ids(nvme_root_t r, struct nvme_dev *dev, +int sndk_get_pci_ids(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, uint32_t *device_id, uint32_t *vendor_id) { char vid[256], did[256], id[32]; nvme_ctrl_t c = NULL; nvme_ns_t n = NULL; + const char *name; int fd, ret; - c = nvme_scan_ctrl(r, dev->name); - if (c) { + name = nvme_transport_handle_get_name(hdl); + ret = nvme_scan_ctrl(ctx, name, &c); + if (!ret) { 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(dev->name); - if (!n) { - fprintf(stderr, "Unable to find %s\n", dev->name); - return -1; + ret = nvme_scan_namespace(name, &n); + if (!ret) { + fprintf(stderr, "Unable to find %s\n", name); + return ret; } snprintf(vid, sizeof(vid), "%s/device/device/vendor", @@ -100,13 +102,13 @@ int sndk_get_pci_ids(nvme_root_t r, struct nvme_dev *dev, return 0; } -int sndk_get_vendor_id(struct nvme_dev *dev, uint32_t *vendor_id) +int sndk_get_vendor_id(struct nvme_transport_handle *hdl, uint32_t *vendor_id) { - int ret; struct nvme_id_ctrl ctrl; + int ret; memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); + ret = nvme_identify_ctrl(hdl, &ctrl); if (ret) { fprintf(stderr, "ERROR: SNDK: nvme_identify_ctrl() failed 0x%x\n", ret); return -1; @@ -117,16 +119,17 @@ int sndk_get_vendor_id(struct nvme_dev *dev, uint32_t *vendor_id) return ret; } -bool sndk_check_device(nvme_root_t r, struct nvme_dev *dev) +bool sndk_check_device(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl) { - int ret; - bool supported; uint32_t read_device_id = -1, read_vendor_id = -1; + bool supported; + int ret; - ret = sndk_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); + ret = sndk_get_pci_ids(ctx, hdl, &read_device_id, &read_vendor_id); if (ret < 0) { /* Use the identify nvme command to get vendor id due to NVMeOF device. */ - if (sndk_get_vendor_id(dev, &read_vendor_id) < 0) + if (sndk_get_vendor_id(hdl, &read_vendor_id) < 0) return false; } @@ -303,7 +306,7 @@ bool sndk_nvme_parse_dev_status_log_str(void *log_data, } -bool sndk_get_dev_mgment_data(nvme_root_t r, struct nvme_dev *dev, +bool sndk_get_dev_mgment_data(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, void **data) { bool found = false; @@ -319,10 +322,10 @@ bool sndk_get_dev_mgment_data(nvme_root_t r, struct nvme_dev *dev, * initialized to 0 so the code can continue on without issue for * both cases: sndk_get_pci_ids successful or failed. */ - sndk_get_pci_ids(r, dev, &device_id, &vendor_id); + sndk_get_pci_ids(ctx, hdl, &device_id, &vendor_id); memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list)); - if (!nvme_get_uuid_list(dev_fd(dev), &uuid_list)) { + if (!nvme_get_uuid_list(hdl, &uuid_list)) { /* check for the Sandisk UUID first */ uuid_index = nvme_uuid_find(&uuid_list, SNDK_UUID); @@ -334,7 +337,7 @@ bool sndk_get_dev_mgment_data(nvme_root_t r, struct nvme_dev *dev, } if (uuid_index >= 0) - found = sndk_get_dev_mgmt_log_page_data(dev, data, uuid_index); + found = sndk_get_dev_mgmt_log_page_data(hdl, data, uuid_index); else { fprintf(stderr, "%s: UUID lists are supported but a matching ", __func__); @@ -345,7 +348,7 @@ bool sndk_get_dev_mgment_data(nvme_root_t r, struct nvme_dev *dev, fprintf(stderr, "INFO: SNDK: %s: UUID Lists not supported\n", __func__); uuid_index = 0; - found = sndk_get_dev_mgmt_log_page_data(dev, data, uuid_index); + found = sndk_get_dev_mgmt_log_page_data(hdl, data, uuid_index); } return found; @@ -423,15 +426,16 @@ bool sndk_validate_dev_mng_log(void *data) return valid_log; } -bool sndk_get_dev_mgmt_log_page_data(struct nvme_dev *dev, +bool sndk_get_dev_mgmt_log_page_data(struct nvme_transport_handle *hdl, void **log_data, __u8 uuid_ix) { - void *data; struct sndk_c2_log_page_header *hdr_ptr; + struct nvme_passthru_cmd cmd; + bool valid = false; __u32 length = 0; + void *data; int ret = 0; - bool valid = false; data = (__u8 *)malloc(sizeof(__u8) * SNDK_DEV_MGMNT_LOG_PAGE_LEN); if (!data) { @@ -442,24 +446,13 @@ bool sndk_get_dev_mgmt_log_page_data(struct nvme_dev *dev, memset(data, 0, sizeof(__u8) * SNDK_DEV_MGMNT_LOG_PAGE_LEN); /* get the log page length */ - struct nvme_get_log_args args_len = { - .args_size = sizeof(args_len), - .fd = dev_fd(dev), - .lid = SNDK_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, - .nsid = 0xFFFFFFFF, - .lpo = 0, - .lsp = NVME_LOG_LSP_NONE, - .lsi = 0, - .rae = false, - .uuidx = uuid_ix, - .csi = NVME_CSI_NVM, - .ot = false, - .len = SNDK_DEV_MGMNT_LOG_PAGE_LEN, - .log = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - ret = nvme_get_log(&args_len); + nvme_init_get_log(&cmd, NVME_NSID_ALL, + SNDK_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, NVME_CSI_NVM, data, + SNDK_DEV_MGMNT_LOG_PAGE_LEN); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + ret = nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); if (ret) { fprintf(stderr, "ERROR: SNDK: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n", @@ -480,25 +473,13 @@ bool sndk_get_dev_mgmt_log_page_data(struct nvme_dev *dev, } /* get the log page data with the increased length */ - struct nvme_get_log_args args_data = { - .args_size = sizeof(args_data), - .fd = dev_fd(dev), - .lid = SNDK_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, - .nsid = 0xFFFFFFFF, - .lpo = 0, - .lsp = NVME_LOG_LSP_NONE, - .lsi = 0, - .rae = false, - .uuidx = uuid_ix, - .csi = NVME_CSI_NVM, - .ot = false, - .len = length, - .log = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - ret = nvme_get_log(&args_data); - + nvme_init_get_log(&cmd, NVME_NSID_ALL, + SNDK_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, NVME_CSI_NVM, data, + length); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + ret = nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); if (ret) { fprintf(stderr, "ERROR: SNDK: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n", @@ -527,16 +508,16 @@ bool sndk_get_dev_mgmt_log_page_data(struct nvme_dev *dev, return valid; } -__u64 sndk_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) +__u64 sndk_get_drive_capabilities(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl) { + uint32_t read_device_id = -1, read_vendor_id = -1; __u64 capabilities = 0; - int ret; - uint32_t read_device_id = -1, read_vendor_id = -1; - ret = sndk_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); + ret = sndk_get_pci_ids(ctx, hdl, &read_device_id, &read_vendor_id); if (ret < 0) { - if (sndk_get_vendor_id(dev, &read_vendor_id) < 0) + if (sndk_get_vendor_id(hdl, &read_vendor_id) < 0) return capabilities; } @@ -546,7 +527,7 @@ __u64 sndk_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) * so we can only use the vendor_id */ if (read_device_id == -1 && read_vendor_id != -1) { - capabilities = sndk_get_enc_drive_capabilities(r, dev); + capabilities = sndk_get_enc_drive_capabilities(ctx, hdl); return capabilities; } @@ -653,13 +634,13 @@ __u64 sndk_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) /* Check for fallback WDC plugin support */ if (!capabilities) - capabilities = run_wdc_get_drive_capabilities(r, dev); + capabilities = run_wdc_get_drive_capabilities(ctx, hdl); return capabilities; } -__u64 sndk_get_enc_drive_capabilities(nvme_root_t r, - struct nvme_dev *dev) +__u64 sndk_get_enc_drive_capabilities(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl) { int ret; uint32_t read_vendor_id; @@ -673,7 +654,7 @@ __u64 sndk_get_enc_drive_capabilities(nvme_root_t r, memset(marketing_name, 0, 64); - ret = sndk_get_vendor_id(dev, &read_vendor_id); + ret = sndk_get_vendor_id(hdl, &read_vendor_id); if (ret < 0) return capabilities; @@ -686,7 +667,7 @@ __u64 sndk_get_enc_drive_capabilities(nvme_root_t r, /* Check for the Sandisk or WDC UUID index */ memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list)); - if (!nvme_get_uuid_list(dev_fd(dev), &uuid_list)) { + if (!nvme_get_uuid_list(hdl, &uuid_list)) { /* check for the Sandisk UUID first */ uuid_index = nvme_uuid_find(&uuid_list, SNDK_UUID); @@ -703,7 +684,7 @@ __u64 sndk_get_enc_drive_capabilities(nvme_root_t r, } /* verify the 0xC2 Device Manageability log page is supported */ - if (run_wdc_nvme_check_supported_log_page(r, dev, + if (run_wdc_nvme_check_supported_log_page(ctx, hdl, SNDK_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, uuid_index) == false) { fprintf(stderr, "ERROR: SNDK: 0xC2 Log Page not supported, "); @@ -712,7 +693,7 @@ __u64 sndk_get_enc_drive_capabilities(nvme_root_t r, goto out; } - if (!sndk_get_dev_mgment_data(r, dev, &dev_mng_log)) { + if (!sndk_get_dev_mgment_data(ctx, hdl, &dev_mng_log)) { fprintf(stderr, "ERROR: SNDK: 0xC2 Log Page not found\n"); ret = -1; goto out; @@ -739,22 +720,22 @@ __u64 sndk_get_enc_drive_capabilities(nvme_root_t r, /* verify the 0xC3 log page is supported */ - if (run_wdc_nvme_check_supported_log_page(r, dev, + if (run_wdc_nvme_check_supported_log_page(ctx, hdl, SNDK_LATENCY_MON_LOG_ID, 0)) capabilities |= SNDK_DRIVE_CAP_C3_LOG_PAGE; /* verify the 0xCB log page is supported */ - if (run_wdc_nvme_check_supported_log_page(r, dev, + if (run_wdc_nvme_check_supported_log_page(ctx, hdl, SNDK_NVME_GET_FW_ACT_HISTORY_LOG_ID, 0)) capabilities |= SNDK_DRIVE_CAP_FW_ACTIVATE_HISTORY; /* verify the 0xCA log page is supported */ - if (run_wdc_nvme_check_supported_log_page(r, dev, + if (run_wdc_nvme_check_supported_log_page(ctx, hdl, SNDK_NVME_GET_DEVICE_INFO_LOG_ID, 0)) capabilities |= SNDK_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (run_wdc_nvme_check_supported_log_page(r, dev, + if (run_wdc_nvme_check_supported_log_page(ctx, hdl, SNDK_NVME_GET_VU_SMART_LOG_ID, 0)) capabilities |= SNDK_DRIVE_CAP_D0_LOG_PAGE; @@ -783,7 +764,7 @@ __u64 sndk_get_enc_drive_capabilities(nvme_root_t r, SNDK_DRIVE_CAP_CLEAR_PCIE); /* if the 0xCB log page is supported */ - if (run_wdc_nvme_check_supported_log_page(r, dev, + if (run_wdc_nvme_check_supported_log_page(ctx, hdl, SNDK_NVME_GET_FW_ACT_HISTORY_LOG_ID, 0)) capabilities |= SNDK_DRIVE_CAP_FW_ACTIVATE_HISTORY; } @@ -796,8 +777,8 @@ __u64 sndk_get_enc_drive_capabilities(nvme_root_t r, return capabilities; } -int sndk_get_serial_name(struct nvme_dev *dev, char *file, size_t len, - const char *suffix) +int sndk_get_serial_name(struct nvme_transport_handle *hdl, char *file, + size_t len, const char *suffix) { int i; int ret; @@ -810,7 +791,7 @@ int sndk_get_serial_name(struct nvme_dev *dev, char *file, size_t len, strncpy(orig, file, PATH_MAX - 1); memset(file, 0, len); memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); + ret = nvme_identify_ctrl(hdl, &ctrl); if (ret) { fprintf(stderr, "ERROR: SNDK: nvme_identify_ctrl() failed 0x%x\n", ret); return -1; @@ -858,7 +839,8 @@ void sndk_UtilsGetTime(struct SNDK_UtilsTimeInfo *timeInfo) #endif /* HAVE_TM_GMTOFF */ } -int sndk_UtilsSnprintf(char *buffer, unsigned int sizeOfBuffer, const char *format, ...) +int sndk_UtilsSnprintf(char *buffer, unsigned int sizeOfBuffer, + const char *format, ...) { int res = 0; va_list vArgs; @@ -871,14 +853,15 @@ int sndk_UtilsSnprintf(char *buffer, unsigned int sizeOfBuffer, const char *form } /* Verify the Controller Initiated Option is enabled */ -int sndk_check_ctrl_telemetry_option_disabled(struct nvme_dev *dev) +int sndk_check_ctrl_telemetry_option_disabled(struct nvme_transport_handle *hdl) { int err; __u32 result; - err = nvme_get_features_data(dev_fd(dev), - SNDK_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, - 0, 4, NULL, &result); + err = nvme_get_features(hdl, 0, + SNDK_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, + NVME_GET_FEATURES_SEL_CURRENT, 0, 0, + NULL, 4, &result); if (!err) { if (result) { fprintf(stderr, diff --git a/plugins/sandisk/sandisk-utils.h b/plugins/sandisk/sandisk-utils.h index 24f10941a8..ca70d45955 100644 --- a/plugins/sandisk/sandisk-utils.h +++ b/plugins/sandisk/sandisk-utils.h @@ -296,16 +296,16 @@ struct __packed sndk_fw_act_history_log_format_c2 { __u8 log_page_guid[SNDK_GUID_LENGTH]; }; -int sndk_get_pci_ids(nvme_root_t r, - struct nvme_dev *dev, +int sndk_get_pci_ids(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl, uint32_t *device_id, uint32_t *vendor_id); -int sndk_get_vendor_id(struct nvme_dev *dev, +int sndk_get_vendor_id(struct nvme_transport_handle *hdl, uint32_t *vendor_id); -bool sndk_check_device(nvme_root_t r, - struct nvme_dev *dev); +bool sndk_check_device(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl); void sndk_get_commit_action_bin(__u8 commit_action_type, char *action_bin); @@ -323,23 +323,23 @@ bool sndk_nvme_parse_dev_status_log_str(void *log_data, char *ret_data, __u32 *ret_data_len); -bool sndk_get_dev_mgment_data(nvme_root_t r, - struct nvme_dev *dev, +bool sndk_get_dev_mgment_data(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl, void **data); bool sndk_validate_dev_mng_log(void *data); -bool sndk_get_dev_mgmt_log_page_data(struct nvme_dev *dev, +bool sndk_get_dev_mgmt_log_page_data(struct nvme_transport_handle *hdl, void **log_data, __u8 uuid_ix); -__u64 sndk_get_drive_capabilities(nvme_root_t r, - struct nvme_dev *dev); +__u64 sndk_get_drive_capabilities(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl); -__u64 sndk_get_enc_drive_capabilities(nvme_root_t r, - struct nvme_dev *dev); +__u64 sndk_get_enc_drive_capabilities(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl); -int sndk_get_serial_name(struct nvme_dev *dev, char *file, size_t len, +int sndk_get_serial_name(struct nvme_transport_handle *hdl, char *file, size_t len, const char *suffix); void sndk_UtilsGetTime(struct SNDK_UtilsTimeInfo *timeInfo); @@ -347,4 +347,4 @@ void sndk_UtilsGetTime(struct SNDK_UtilsTimeInfo *timeInfo); int sndk_UtilsSnprintf(char *buffer, unsigned int sizeOfBuffer, const char *format, ...); -int sndk_check_ctrl_telemetry_option_disabled(struct nvme_dev *dev); +int sndk_check_ctrl_telemetry_option_disabled(struct nvme_transport_handle *hdl); diff --git a/plugins/scaleflux/sfx-nvme.c b/plugins/scaleflux/sfx-nvme.c index 63e0e2e4d8..1d2f768b91 100644 --- a/plugins/scaleflux/sfx-nvme.c +++ b/plugins/scaleflux/sfx-nvme.c @@ -19,7 +19,6 @@ #include "libnvme.h" #include "plugin.h" #include "linux/types.h" -#include "nvme-wrap.h" #include "nvme-print.h" #include "util/cleanup.h" #include "util/types.h" @@ -47,7 +46,7 @@ -int nvme_query_cap(int fd, __u32 nsid, __u32 data_len, void *data) +int nvme_query_cap(struct nvme_transport_handle *hdl, __u32 nsid, __u32 data_len, void *data) { int rc = 0; struct nvme_passthru_cmd cmd = { @@ -57,11 +56,11 @@ int nvme_query_cap(int fd, __u32 nsid, __u32 data_len, void *data) .data_len = data_len, }; - rc = ioctl(fd, SFX_GET_FREESPACE, data); - return rc ? nvme_submit_admin_passthru(fd, &cmd, NULL) : 0; + rc = ioctl(nvme_transport_handle_get_fd(hdl), SFX_GET_FREESPACE, data); + return rc ? nvme_submit_admin_passthru(hdl, &cmd, NULL) : 0; } -int nvme_change_cap(int fd, __u32 nsid, __u64 capacity) +int nvme_change_cap(struct nvme_transport_handle *hdl, __u32 nsid, __u64 capacity) { struct nvme_passthru_cmd cmd = { .opcode = nvme_admin_change_cap, @@ -70,10 +69,10 @@ int nvme_change_cap(int fd, __u32 nsid, __u64 capacity) .cdw11 = (capacity >> 32), }; - return nvme_submit_admin_passthru(fd, &cmd, NULL); + return nvme_submit_admin_passthru(hdl, &cmd, NULL); } -int nvme_sfx_set_features(int fd, __u32 nsid, __u32 fid, __u32 value) +int nvme_sfx_set_features(struct nvme_transport_handle *hdl, __u32 nsid, __u32 fid, __u32 value) { struct nvme_passthru_cmd cmd = { .opcode = nvme_admin_sfx_set_features, @@ -82,10 +81,10 @@ int nvme_sfx_set_features(int fd, __u32 nsid, __u32 fid, __u32 value) .cdw11 = value, }; - return nvme_submit_admin_passthru(fd, &cmd, NULL); + return nvme_submit_admin_passthru(hdl, &cmd, NULL); } -int nvme_sfx_get_features(int fd, __u32 nsid, __u32 fid, __u32 *result) +int nvme_sfx_get_features(struct nvme_transport_handle *hdl, __u32 nsid, __u32 fid, __u32 *result) { int err = 0; struct nvme_passthru_cmd cmd = { @@ -94,7 +93,7 @@ int nvme_sfx_get_features(int fd, __u32 nsid, __u32 fid, __u32 *result) .cdw10 = fid, }; - err = nvme_submit_admin_passthru(fd, &cmd, NULL); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err && result) *result = cmd.result; @@ -325,7 +324,7 @@ static void show_sfx_smart_log(struct nvme_additional_smart_log *smart, } -static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_additional_smart_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { struct nvme_additional_smart_log smart_log; char *desc = @@ -335,7 +334,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, #ifdef CONFIG_JSONC const char *json = "Dump output in json format"; #endif /* CONFIG_JSONC */ - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct config { __u32 namespace_id; bool raw_binary; @@ -354,25 +354,24 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = nvme_get_nsid_log(dev_fd(dev), false, 0xca, cfg.namespace_id, - sizeof(smart_log), (void *)&smart_log); + err = nvme_get_nsid_log(hdl, cfg.namespace_id, false, 0xca, + (void *)&smart_log, sizeof(smart_log)); if (!err) { if (cfg.json) show_sfx_smart_log_jsn(&smart_log, cfg.namespace_id, - dev->name); + nvme_transport_handle_get_name(hdl)); else if (!cfg.raw_binary) show_sfx_smart_log(&smart_log, cfg.namespace_id, - dev->name); + nvme_transport_handle_get_name(hdl)); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); } else if (err > 0) { nvme_show_status(err); } - dev_close(dev); return err; } @@ -497,13 +496,14 @@ static void show_lat_stats_myrtle(struct sfx_lat_stats_myrtle *stats, int write) } -static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_lat_stats_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { struct sfx_lat_stats stats; char *desc = "Get ScaleFlux Latency Statistics log and show it."; const char *raw = "dump output in binary format"; const char *write = "Get write statistics (read default)"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct config { bool raw_binary; bool write; @@ -519,12 +519,12 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = nvme_get_log_simple(dev_fd(dev), cfg.write ? 0xc3 : 0xc1, - sizeof(stats), (void *)&stats); + err = nvme_get_log_simple(hdl, cfg.write ? 0xc3 : 0xc1, + (void *)&stats, sizeof(stats)); if (!err) { if ((stats.ver.maj == VANDA_MAJOR_IDX) && (stats.ver.min == VANDA_MINOR_IDX)) { if (!cfg.raw_binary) @@ -543,11 +543,10 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct } else if (err > 0) { nvme_show_status(err); } - dev_close(dev); return err; } -int sfx_nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data) +int sfx_nvme_get_log(struct nvme_transport_handle *hdl, __u32 nsid, __u8 log_id, __u32 data_len, void *data) { struct nvme_passthru_cmd cmd = { .opcode = nvme_admin_get_log_page, @@ -561,7 +560,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, NULL); + return nvme_submit_admin_passthru(hdl, &cmd, NULL); } /** @@ -573,14 +572,14 @@ int sfx_nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data * * @return -1 fail ; 0 success */ -static int get_bb_table(int fd, __u32 nsid, unsigned char *buf, __u64 size) +static int get_bb_table(struct nvme_transport_handle *hdl, __u32 nsid, unsigned char *buf, __u64 size) { - if (fd < 0 || !buf || size != 256*4096*sizeof(unsigned char)) { + if (nvme_transport_handle_get_fd(hdl) < 0 || !buf || size != 256*4096*sizeof(unsigned char)) { fprintf(stderr, "Invalid Param \r\n"); return -EINVAL; } - return sfx_nvme_get_log(fd, nsid, SFX_LOG_BBT, size, (void *)buf); + return sfx_nvme_get_log(hdl, nsid, SFX_LOG_BBT, size, (void *)buf); } /** @@ -645,11 +644,12 @@ static void bd_table_show(unsigned char *bd_table, __u64 table_size) * * @return */ -static int sfx_get_bad_block(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int sfx_get_bad_block(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const __u64 buf_size = 256*4096*sizeof(unsigned char); unsigned char *data_buf; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err = 0; char *desc = "Get bad block table of sfx block device."; @@ -658,18 +658,17 @@ static int sfx_get_bad_block(int argc, char **argv, struct command *cmd, struct OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; data_buf = malloc(buf_size); if (!data_buf) { fprintf(stderr, "malloc fail, errno %d\r\n", errno); - dev_close(dev); return -1; } - err = get_bb_table(dev_fd(dev), NVME_NSID_ALL, data_buf, buf_size); + err = get_bb_table(hdl, NVME_NSID_ALL, data_buf, buf_size); if (err < 0) { perror("get-bad-block"); } else if (err) { @@ -680,7 +679,6 @@ static int sfx_get_bad_block(int argc, char **argv, struct command *cmd, struct } free(data_buf); - dev_close(dev); return 0; } @@ -699,12 +697,13 @@ static void show_cap_info(struct sfx_freespace_ctx *ctx) printf("map_unit :0x%"PRIx64"K\n", (uint64_t)(ctx->map_unit * 4)); } -static int query_cap_info(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int query_cap_info(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - struct sfx_freespace_ctx ctx = { 0 }; + struct sfx_freespace_ctx sfctx = { 0 }; char *desc = "query current capacity info"; const char *raw = "dump output in binary format"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct config { bool raw_binary; }; @@ -716,26 +715,25 @@ static int query_cap_info(int argc, char **argv, struct command *cmd, struct plu OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - if (nvme_query_cap(dev_fd(dev), NVME_NSID_ALL, sizeof(ctx), &ctx)) { + if (nvme_query_cap(hdl, NVME_NSID_ALL, sizeof(sfctx), &sfctx)) { perror("sfx-query-cap"); err = -1; } if (!err) { if (!cfg.raw_binary) - show_cap_info(&ctx); + show_cap_info(&sfctx); else - d_raw((unsigned char *)&ctx, sizeof(ctx)); + d_raw((unsigned char *)&sfctx, sizeof(sfctx)); } - dev_close(dev); return err; } -static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink) +static int change_sanity_check(struct nvme_transport_handle *hdl, __u64 trg_in_4k, int *shrink) { struct sfx_freespace_ctx freespace_ctx = { 0 }; struct sysinfo s_info; @@ -744,7 +742,7 @@ static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink) __u64 provisioned_cap_4k = 0; int extend = 0; - if (nvme_query_cap(fd, NVME_NSID_ALL, sizeof(freespace_ctx), &freespace_ctx)) + if (nvme_query_cap(hdl, NVME_NSID_ALL, sizeof(freespace_ctx), &freespace_ctx)) return -1; /* @@ -817,13 +815,14 @@ static int sfx_confirm_change(const char *str) return 1; } -static int change_cap(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int change_cap(int argc, char **argv, struct command *acmd, struct plugin *plugin) { char *desc = "dynamic change capacity"; const char *cap_gb = "cap size in GB"; const char *cap_byte = "cap size in byte"; const char *force = "The \"I know what I'm doing\" flag, skip confirmation before sending command"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u64 cap_in_4k = 0; __u64 cap_in_sec = 0; int shrink = 0; @@ -848,7 +847,7 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -859,34 +858,31 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin printf("%dG %"PRIu64"B %"PRIu64" 4K\n", cfg.capacity_in_gb, (uint64_t)cfg.cap_in_byte, (uint64_t)cap_in_4k); - if (change_sanity_check(dev_fd(dev), cap_in_4k, &shrink)) { + if (change_sanity_check(hdl, cap_in_4k, &shrink)) { printf("ScaleFlux change-capacity: fail\n"); - dev_close(dev); return err; } if (!cfg.force && shrink && !sfx_confirm_change("Changing Cap may irrevocably delete this device's data")) { - dev_close(dev); return 0; } - err = nvme_change_cap(dev_fd(dev), NVME_NSID_ALL, cap_in_4k); + err = nvme_change_cap(hdl, NVME_NSID_ALL, cap_in_4k); if (err < 0) { perror("sfx-change-cap"); } else if (err) { nvme_show_status(err); } else { printf("ScaleFlux change-capacity: success\n"); - ioctl(dev_fd(dev), BLKRRPART); + ioctl(nvme_transport_handle_get_fd(hdl), BLKRRPART); } - dev_close(dev); return err; } -static int sfx_verify_chr(int fd) +static int sfx_verify_chr(struct nvme_transport_handle *hdl) { static struct stat nvme_stat; - int err = fstat(fd, &nvme_stat); + int err = fstat(nvme_transport_handle_get_fd(hdl), &nvme_stat); if (err < 0) { perror("fstat"); @@ -900,14 +896,14 @@ static int sfx_verify_chr(int fd) return 0; } -static int sfx_clean_card(int fd) +static int sfx_clean_card(struct nvme_transport_handle *hdl) { int ret; - ret = sfx_verify_chr(fd); + ret = sfx_verify_chr(hdl); if (ret) return ret; - ret = ioctl(fd, NVME_IOCTL_CLR_CARD); + ret = ioctl(nvme_transport_handle_get_fd(hdl), NVME_IOCTL_CLR_CARD); if (ret) perror("Ioctl Fail."); else @@ -928,7 +924,7 @@ char *sfx_feature_to_string(int feature) } } -static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int sfx_set_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { char *desc = "ScaleFlux internal set features\n" "feature id 1: ATOMIC\n" @@ -938,7 +934,8 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl const char *feature_id = "hex feature name (required)"; const char *namespace_id = "desired namespace"; const char *force = "The \"I know what I'm doing\" flag, skip confirmation before sending command"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct nvme_id_ns ns; int err = 0; @@ -963,70 +960,62 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); - dev_close(dev); - return -EINVAL; + return -EINVAL; } if (cfg.feature_id == SFX_FEAT_CLR_CARD) { /*Warning for clean card*/ if (!cfg.force && !sfx_confirm_change("Going to clean device's data, confirm umount fs and try again")) { - dev_close(dev); - return 0; + return 0; } else { - return sfx_clean_card(dev_fd(dev)); + return sfx_clean_card(hdl); } } if (cfg.feature_id == SFX_FEAT_ATOMIC && cfg.value) { if (cfg.namespace_id != NVME_NSID_ALL) { - err = nvme_identify_ns(dev_fd(dev), cfg.namespace_id, - &ns); + err = nvme_identify_ns(hdl, cfg.namespace_id, &ns); if (err) { if (err < 0) perror("identify-namespace"); else nvme_show_status(err); - dev_close(dev); - return err; + return err; } /* * atomic only support with sector-size = 4k now */ if ((ns.flbas & 0xf) != 1) { printf("Please change-sector size to 4K, then retry\n"); - dev_close(dev); - return -EFAULT; + return -EFAULT; } } } else if (cfg.feature_id == SFX_FEAT_UP_P_CAP) { if (cfg.value <= 0) { fprintf(stderr, "Invalid Param\n"); - dev_close(dev); - return -EINVAL; + return -EINVAL; } /*Warning for change pacp by GB*/ if (!cfg.force && !sfx_confirm_change("Changing physical capacity may irrevocably delete this device's data")) { - dev_close(dev); - return 0; + return 0; } } - err = nvme_sfx_set_features(dev_fd(dev), cfg.namespace_id, + err = nvme_sfx_set_features(hdl, cfg.namespace_id, cfg.feature_id, cfg.value); if (err < 0) { perror("ScaleFlux-set-feature"); - dev_close(dev); - return errno; + return errno; } else if (!err) { printf("ScaleFlux set-feature:%#02x (%s), value:%d\n", cfg.feature_id, sfx_feature_to_string(cfg.feature_id), cfg.value); @@ -1034,17 +1023,17 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl nvme_show_status(err); } - dev_close(dev); return err; } -static int sfx_get_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int sfx_get_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { char *desc = "ScaleFlux internal set features\n" "feature id 1: ATOMIC"; const char *feature_id = "hex feature name (required)"; const char *namespace_id = "desired namespace"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 result = 0; int err = 0; @@ -1063,22 +1052,20 @@ static int sfx_get_feature(int argc, char **argv, struct command *cmd, struct pl OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); - dev_close(dev); - return -EINVAL; + return -EINVAL; } - err = nvme_sfx_get_features(dev_fd(dev), cfg.namespace_id, + err = nvme_sfx_get_features(hdl, cfg.namespace_id, cfg.feature_id, &result); if (err < 0) { perror("ScaleFlux-get-feature"); - dev_close(dev); - return errno; + return errno; } else if (!err) { printf("ScaleFlux get-feature:%02x (%s), value:%d\n", cfg.feature_id, sfx_feature_to_string(cfg.feature_id), result); @@ -1086,7 +1073,6 @@ static int sfx_get_feature(int argc, char **argv, struct command *cmd, struct pl nvme_show_status(err); } - dev_close(dev); return err; } @@ -1218,36 +1204,23 @@ static int nvme_parse_evtlog(void *pevent_log_info, __u32 log_len, char *output) return err; } -static int nvme_dump_evtlog(struct nvme_dev *dev, __u32 namespace_id, __u32 storage_medium, +static int nvme_dump_evtlog(struct nvme_transport_handle *hdl, __u32 namespace_id, __u32 storage_medium, char *file, bool parse, char *output) { + _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; struct nvme_persistent_event_log *pevent; void *pevent_log_info; - _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; - __u8 lsp_base; + __u8 lsp_base, lsp; __u32 offset = 0; __u32 length = 0; - __u32 log_len; __u32 single_len; + __u32 log_len; + __u32 len; + __u64 lpo; + void *log; int err = 0; FILE *fd = NULL; - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .lid = NVME_LOG_LID_PERSISTENT_EVENT, - .nsid = namespace_id, - .lpo = NVME_LOG_LPO_NONE, - .lsp = NVME_LOG_LSP_NONE, - .lsi = NVME_LOG_LSI_NONE, - .rae = false, - .uuidx = NVME_UUID_NONE, - .csi = NVME_CSI_NVM, - .ot = false, - .len = 0, - .log = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; + struct nvme_passthru_cmd cmd; if (!storage_medium) { lsp_base = 0; @@ -1263,20 +1236,31 @@ static int nvme_dump_evtlog(struct nvme_dev *dev, __u32 namespace_id, __u32 stor goto ret; } - args.lsp = lsp_base + NVME_PEVENT_LOG_RELEASE_CTX; - args.log = pevent; - args.len = sizeof(*pevent); - - err = nvme_get_log(&args); + lsp = lsp_base + NVME_PEVENT_LOG_RELEASE_CTX; + log = pevent; + len = sizeof(*pevent); + nvme_init_get_log(&cmd, NVME_NSID_NONE, NVME_LOG_LID_PERSISTENT_EVENT, + NVME_CSI_NVM, log, len); + cmd.cdw10 |= NVME_FIELD_ENCODE(lsp, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + err = nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); if (err) { - fprintf(stderr, "Unable to get evtlog lsp=0x%x, ret = 0x%x\n", args.lsp, err); + fprintf(stderr, "Unable to get evtlog lsp=0x%x, ret = 0x%x\n", + lsp, err); goto free_pevent; } - args.lsp = lsp_base + NVME_PEVENT_LOG_EST_CTX_AND_READ; - err = nvme_get_log(&args); + lsp = lsp_base + NVME_PEVENT_LOG_EST_CTX_AND_READ; + nvme_init_get_log(&cmd, NVME_NSID_NONE, NVME_LOG_LID_PERSISTENT_EVENT, + NVME_CSI_NVM, log, len); + cmd.cdw10 |= NVME_FIELD_ENCODE(lsp, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + err = nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); if (err) { - fprintf(stderr, "Unable to get evtlog lsp=0x%x, ret = 0x%x\n", args.lsp, err); + fprintf(stderr, "Unable to get evtlog lsp=0x%x, ret = 0x%x\n", + lsp, err); goto free_pevent; } @@ -1297,30 +1281,40 @@ static int nvme_dump_evtlog(struct nvme_dev *dev, __u32 namespace_id, __u32 stor goto free_pevent; } - args.lsp = lsp_base + NVME_PEVENT_LOG_READ; - args.log = pevent_log_info; + lsp = lsp_base + NVME_PEVENT_LOG_READ; + log = pevent_log_info; length = log_len; while (length > 0) { - args.lpo = offset; + lpo = offset; if (length > single_len) { - args.len = single_len; + len = single_len; } else { - memset(args.log, 0, args.len); - args.len = length; + memset(log, 0, len); + len = length; } - err = nvme_get_log(&args); + nvme_init_get_log(&cmd, NVME_NSID_NONE, + NVME_LOG_LID_PERSISTENT_EVENT, + NVME_CSI_NVM, log, len); + cmd.cdw10 |= NVME_FIELD_ENCODE(lsp, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + nvme_init_get_log_lpo(&cmd, lpo); + err = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (err) { - fprintf(stderr, "Unable to get evtlog offset=0x%x len 0x%x ret = 0x%x\n", offset, args.len, err); + fprintf(stderr, + "Unable to get evtlog offset=0x%x len 0x%x ret = 0x%x\n", + offset, len, err); goto close_fd; } - if (fwrite(args.log, 1, args.len, fd) != args.len) { + if (fwrite(log, 1, len, fd) != len) { fprintf(stderr, "Failed to write evtlog to file\n"); goto close_fd; } - offset += args.len; - length -= args.len; + offset += len; + length -= len; util_spinner("Parse", (float) (offset) / (float) (log_len)); } @@ -1358,7 +1352,7 @@ static int nvme_dump_evtlog(struct nvme_dev *dev, __u32 namespace_id, __u32 stor return err; } -static int sfx_dump_evtlog(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int sfx_dump_evtlog(int argc, char **argv, struct command *acmd, struct plugin *plugin) { char *desc = "dump evtlog into file and parse"; const char *file = "evtlog file(required)"; @@ -1367,7 +1361,8 @@ static int sfx_dump_evtlog(int argc, char **argv, struct command *cmd, struct pl "0: nand(default) 1: nor"; const char *parse = "parse error & warning evtlog from evtlog file"; const char *output = "parse result output file"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err = 0; struct config { @@ -1394,31 +1389,26 @@ static int sfx_dump_evtlog(int argc, char **argv, struct command *cmd, struct pl OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) - goto ret; + return err; if (!cfg.file) { fprintf(stderr, "file required param\n"); - err = EINVAL; - goto close_dev; + return -EINVAL; } if (cfg.parse && !cfg.output) { fprintf(stderr, "output file required if evtlog need be parsed\n"); - err = EINVAL; - goto close_dev; + return -EINVAL; } - err = nvme_dump_evtlog(dev, cfg.namespace_id, cfg.storage_medium, cfg.file, cfg.parse, cfg.output); + err = nvme_dump_evtlog(hdl, cfg.namespace_id, cfg.storage_medium, cfg.file, cfg.parse, cfg.output); -close_dev: - dev_close(dev); -ret: - return err; + return 0; } -static int nvme_expand_cap(struct nvme_dev *dev, __u32 namespace_id, __u64 namespace_size, +static int nvme_expand_cap(struct nvme_transport_handle *hdl, __u32 namespace_id, __u64 namespace_size, __u64 namespace_cap, __u32 lbaf, __u32 units) { struct dirent **devices; @@ -1435,10 +1425,10 @@ static int nvme_expand_cap(struct nvme_dev *dev, __u32 namespace_id, __u64 names __u8 reserve1[5]; } __packed; - if (S_ISCHR(dev->direct.stat.st_mode)) - snprintf(dev_name, 32, "%sn%u", dev->name, namespace_id); + if (nvme_transport_handle_is_chardev(hdl)) + snprintf(dev_name, 32, "%sn%u", nvme_transport_handle_get_name(hdl), namespace_id); else - strcpy(dev_name, dev->name); + strcpy(dev_name, nvme_transport_handle_get_name(hdl)); num = scandir("/dev", &devices, nvme_namespace_filter, alphasort); if (num <= 0) { @@ -1471,7 +1461,7 @@ static int nvme_expand_cap(struct nvme_dev *dev, __u32 namespace_id, __u64 names .cdw10 = 0x0e, }; - err = nvme_submit_admin_passthru(dev_fd(dev), &cmd, NULL); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (err) { fprintf(stderr, "Create ns failed\n"); nvme_show_status(err); @@ -1486,7 +1476,7 @@ static int nvme_expand_cap(struct nvme_dev *dev, __u32 namespace_id, __u64 names return err; } -static int sfx_expand_cap(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int sfx_expand_cap(int argc, char **argv, struct command *acmd, struct plugin *plugin) { char *desc = "expand capacity"; const char *namespace_id = "desired namespace"; @@ -1496,7 +1486,8 @@ static int sfx_expand_cap(int argc, char **argv, struct command *cmd, struct plu "0: 512(default) 1: 4096"; const char *units = "namespace size/capacity units\n" "0: GB(default) 1: LBA"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err = 0; struct config { @@ -1521,55 +1512,49 @@ static int sfx_expand_cap(int argc, char **argv, struct command *cmd, struct plu OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) - goto ret; + return err; if (cfg.namespace_id == NVME_NSID_ALL) { - if (S_ISCHR(dev->direct.stat.st_mode)) { + if (nvme_transport_handle_is_chardev(hdl)) { fprintf(stderr, "namespace_id or blk device required\n"); - err = EINVAL; - goto ret; + return -EINVAL; } else { - cfg.namespace_id = atoi(&dev->name[strlen(dev->name) - 1]); + cfg.namespace_id = atoi(&nvme_transport_handle_get_name(hdl)[strlen(nvme_transport_handle_get_name(hdl)) - 1]); } } if (!cfg.namespace_size) { fprintf(stderr, "namespace_size required param\n"); - err = EINVAL; - goto close_dev; + return -EINVAL; } if (!cfg.namespace_cap) { fprintf(stderr, "namespace_cap required param\n"); - err = EINVAL; - goto close_dev; + return -EINVAL; } - err = nvme_expand_cap(dev, cfg.namespace_id, cfg.namespace_size, cfg.namespace_cap, cfg.lbaf, cfg.units); + err = nvme_expand_cap(hdl, cfg.namespace_id, cfg.namespace_size, cfg.namespace_cap, cfg.lbaf, cfg.units); if (err) - goto close_dev; + return err; - printf("%s: Success, create nsid:%d\n", cmd->name, cfg.namespace_id); + printf("%s: Success, create nsid:%d\n", acmd->name, cfg.namespace_id); -close_dev: - dev_close(dev); -ret: - return err; + return 0; } -static int sfx_status(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int sfx_status(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get ScaleFlux specific status information and print it"; const char *json_desc = "Print output in JSON format, otherwise human readable"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct nvme_id_ctrl id_ctrl = { 0 }; struct extended_health_info_myrtle sfx_smart = { 0 }; struct nvme_smart_log smart_log = { 0 }; struct nvme_additional_smart_log additional_smart_log = { 0 }; struct sfx_freespace_ctx sfx_freespace = { 0 }; - struct nvme_get_features_args get_feat_args = { 0 }; unsigned int get_feat_result, pcie_correctable, pcie_fatal, pcie_nonfatal; unsigned long long capacity; bool capacity_valid = false; @@ -1592,14 +1577,13 @@ static int sfx_status(int argc, char **argv, struct command *cmd, struct plugin OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); - + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) - goto ret; + return err; //Calculate formatted capacity, not concerned with errors, we may have a char device memset(&path, 0, 512); - snprintf(path, 512, "/dev/%s", dev->name); + snprintf(path, 512, "/dev/%s", nvme_transport_handle_get_name(hdl)); fd = open(path, O_RDONLY | O_NONBLOCK); if (fd >= 0) { err = ioctl(fd, BLKSSZGET, §or_size); @@ -1616,7 +1600,7 @@ static int sfx_status(int argc, char **argv, struct command *cmd, struct plugin capacity = capacity / (1000 * 1000 * 1000); //B --> GB memset(&chr_dev, 0, 8); - strcpy(chr_dev, dev->name); + strcpy(chr_dev, nvme_transport_handle_get_name(hdl)); for (len = 2; len < 8; len++) { if (chr_dev[len] == 'n') chr_dev[len] = '\0'; @@ -1627,16 +1611,14 @@ static int sfx_status(int argc, char **argv, struct command *cmd, struct plugin fd = open(path, O_RDONLY); if (fd < 0) { perror("Could not open PCIe VID in /sys/"); - err = errno; - goto close_dev; + return -errno; } memset(&pci_vid, 0, 7); len = read(fd, pci_vid, 6); if (len < 1) { perror("Could not read PCIe VID in /sys/"); close(fd); - err = errno; - goto close_dev; + return -errno; } close(fd); @@ -1644,16 +1626,14 @@ static int sfx_status(int argc, char **argv, struct command *cmd, struct plugin fd = open(path, O_RDONLY); if (fd < 0) { perror("Could not open PCIe DID in /sys/"); - err = errno; - goto close_dev; + return -errno; } memset(&pci_did, 0, 7); len = read(fd, pci_did, 6); if (len < 1) { perror("Could not read PCIe DID in /sys/"); close(fd); - err = errno; - goto close_dev; + return -errno; } close(fd); @@ -1663,24 +1643,21 @@ static int sfx_status(int argc, char **argv, struct command *cmd, struct plugin strncpy(vendor, "DIGISTOR", 10); else { fprintf(stderr, "Please use on a ScaleFlux device\n"); - err = -1; - goto close_dev; + return -1; } snprintf(path, 512, "/sys/class/nvme/%s/device/subsystem_vendor", chr_dev); fd = open(path, O_RDONLY); if (fd < 0) { perror("Could not open PCIe Subsystem Vendor ID in /sys/"); - err = errno; - goto close_dev; + return -errno; } memset(&pci_ssvid, 0, 7); len = read(fd, pci_ssvid, 6); if (len < 1) { perror("could not read PCIe Subsystem Vendor ID in /sys/"); close(fd); - err = errno; - goto close_dev; + return -errno; } close(fd); @@ -1688,16 +1665,14 @@ static int sfx_status(int argc, char **argv, struct command *cmd, struct plugin fd = open(path, O_RDONLY); if (fd < 0) { perror("Could not open link speed in /sys/"); - err = errno; - goto close_dev; + return -errno; } memset(&link_speed, 0, 20); len = read(fd, link_speed, 20); if (len < 1) { perror("Could not read link speed in /sys/"); close(fd); - err = errno; - goto close_dev; + return -errno; } close(fd); // Ending string before "PCIe" and newline @@ -1710,16 +1685,14 @@ static int sfx_status(int argc, char **argv, struct command *cmd, struct plugin fd = open(path, O_RDONLY); if (fd < 0) { perror("Could not open link width in /sys/"); - err = errno; - goto close_dev; + return -errno; } memset(&link_width, 0, 5); len = read(fd, link_width, 5); if (len < 1) { perror("Could not read link width in /sys/"); close(fd); - err = errno; - goto close_dev; + return -errno; } close(fd); // Ending string before newline @@ -1734,16 +1707,14 @@ static int sfx_status(int argc, char **argv, struct command *cmd, struct plugin fd = open(path, O_RDONLY); if (fd < 0) { perror("Could not open NUMA node in /sys/"); - err = errno; - goto close_dev; + return -errno; } memset(&numa_node, 0, 5); len = read(fd, numa_node, 5); if (len < 1) { perror("Could not read NUMA node in /sys/"); close(fd); - err = errno; - goto close_dev; + return -errno; } close(fd); @@ -1757,78 +1728,69 @@ static int sfx_status(int argc, char **argv, struct command *cmd, struct plugin fd = open(path, O_RDONLY); if (fd < 0) { perror("Could not open PCIe AER Correctable errors in /sys/"); - err = errno; - goto close_dev; + return -errno; } len = read(fd, path, 512); if (len < 1) { perror("Could not read PCIe AER Correctable errors in /sys/"); close(fd); - err = errno; - goto close_dev; + return -errno; } close(fd); len = sscanf(path, "%*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d TOTAL_ERR_COR %d", &pcie_correctable); len = 1; if (len < 1 || len == EOF) { perror("Could not parse PCIe AER Correctable errors in /sys/"); - err = -1; - goto close_dev; + return -1; } snprintf(path, 512, "/sys/class/nvme/%s/device/aer_dev_nonfatal", chr_dev); fd = open(path, O_RDONLY); if (fd < 0) { perror("Could not open PCIe AER Non-Fatal errors in /sys/"); - err = errno; - goto close_dev; + return -errno; } len = read(fd, path, 512); if (len < 1) { perror("Could not read PCIe AER Non-Fatal errors in /sys/"); - err = errno; - goto close_dev; + return -errno; } close(fd); len = sscanf(path, "%*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d TOTAL_ERR_NONFATAL %d", &pcie_nonfatal); if (len < 1) { perror("Could not parse PCIe AER Non-Fatal errors in /sys/"); - err = -1; - goto close_dev; + return -1; } snprintf(path, 512, "/sys/class/nvme/%s/device/aer_dev_fatal", chr_dev); fd = open(path, O_RDONLY); if (fd < 0) { perror("Could not open PCIe AER Fatal errors in /sys/"); - err = errno; - goto close_dev; + return -errno; } len = read(fd, path, 512); if (len < 1) { perror("Could not read PCIe AER Fatal errors in /sys/"); close(fd); - err = errno; - goto close_dev; + return -errno; } close(fd); len = sscanf(path, "%*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d TOTAL_ERR_FATAL %d", &pcie_fatal); if (len < 1) { perror("Could not parse PCIe AER Fatal errors in /sys/"); close(fd); - err = -1; - goto close_dev; + return -1; } snprintf(pcie_status, 9, "%s", (pcie_fatal != 0 || pcie_nonfatal != 0 || pcie_correctable != 0) ? "Warning":"Good"); //Populate id-ctrl - err = nvme_identify_ctrl(dev_fd(dev), &id_ctrl); + err = nvme_identify_ctrl(hdl, &id_ctrl); if (err) { fprintf(stderr, "Unable to read nvme_identify_ctrl() error code:%x\n", err); - goto close_dev; + return err; } //Re-format specific fields so they can be safely treated as strings later serial_number[20] = '\0'; @@ -1839,30 +1801,30 @@ static int sfx_status(int argc, char **argv, struct command *cmd, struct plugin memcpy(firmware_revision, id_ctrl.fr, 8); //Populate SMART log (0x02) - err = nvme_cli_get_log_smart(dev, NVME_NSID_ALL, false, &smart_log); + err = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log); if (err < 0) { perror("Could not read SMART log (0x02)"); - err = errno; - goto close_dev; + return -errno; } else if (err > 0) { nvme_show_status(err); - goto close_dev; + return err; } snprintf(temperature, 10, "%li", kelvin_to_celsius(smart_log.temperature[1]<<8 | smart_log.temperature[0])); //Populate SFX Extended Health log (0xC2) or if PCIe DID ==0x20 (Quince) use 0xD2 if (strncmp("0x0020", pci_did, 6) == 0) - err = nvme_get_log_simple(dev_fd(dev), SFX_LOG_EXTENDED_HEALTH_ALT, sizeof(sfx_smart), (void *)&sfx_smart); + err = nvme_get_log_simple(hdl, SFX_LOG_EXTENDED_HEALTH_ALT, (void *)&sfx_smart, + sizeof(sfx_smart)); else - err = nvme_get_log_simple(dev_fd(dev), SFX_LOG_EXTENDED_HEALTH, sizeof(sfx_smart), (void *)&sfx_smart); + err = nvme_get_log_simple(hdl, SFX_LOG_EXTENDED_HEALTH, (void *)&sfx_smart, + sizeof(sfx_smart)); if (err < 0) { perror("Could not read ScaleFlux SMART log"); - err = errno; - goto close_dev; + return -errno; } else if (err > 0) { nvme_show_status(err); - goto close_dev; + return err; } //Make sure the OPN can be printed safely @@ -1883,28 +1845,27 @@ static int sfx_status(int argc, char **argv, struct command *cmd, struct plugin } //Populate Additional SMART log (0xCA) - err = nvme_get_nsid_log(dev_fd(dev), false, 0xca, NVME_NSID_ALL, sizeof(struct nvme_additional_smart_log), (void *)&additional_smart_log); + err = nvme_get_nsid_log(hdl, NVME_NSID_ALL, false, 0xca, (void *)&additional_smart_log, + sizeof(struct nvme_additional_smart_log)); if (err < 0) { perror("Could not read ScaleFlux SMART log"); - err = errno; - goto close_dev; + return -errno; } else if (err > 0) { nvme_show_status(err); - goto close_dev; + return err; } //OK with the '-nan' if host_bytes_written is zero write_amp = int48_to_long(additional_smart_log.nand_bytes_written.raw)/(1.0 * int48_to_long(additional_smart_log.host_bytes_written.raw)); //Get SFX freespace information - err = nvme_query_cap(dev_fd(dev), NVME_NSID_ALL, sizeof(sfx_freespace), &sfx_freespace); + err = nvme_query_cap(hdl, NVME_NSID_ALL, sizeof(sfx_freespace), &sfx_freespace); if (err < 0) { perror("Could not query freespace information (0xD6)"); - err = errno; - goto close_dev; + return -errno; } else if (err > 0) { nvme_show_status(err); - goto close_dev; + return err; } //Parse IO Speed information @@ -1935,23 +1896,18 @@ static int sfx_status(int argc, char **argv, struct command *cmd, struct plugin sfx_smart.comp_ratio = 800; //Get status of atomic write feature - get_feat_args.args_size = sizeof(get_feat_args); - get_feat_args.fid = 0x0A; - get_feat_args.timeout = NVME_DEFAULT_IOCTL_TIMEOUT; - get_feat_args.result = &get_feat_result; - err = nvme_cli_get_features(dev, &get_feat_args); + err = nvme_get_features(hdl, 0, 0x0A, 0, 0, 0, NULL, 0, &get_feat_result); if (err < 0) { perror("Could not get feature (0x0A)"); - err = errno; - goto close_dev; + return -errno; } else if (err > 0) { nvme_show_status(err); - goto close_dev; + return err; } if (cfg.json) { root = json_create_object(); - json_object_add_value_string(root, "ScaleFlux Status", dev->name); + json_object_add_value_string(root, "ScaleFlux Status", nvme_transport_handle_get_name(hdl)); dev_stats = json_create_object(); link_stats = json_create_object(); @@ -2031,7 +1987,7 @@ static int sfx_status(int argc, char **argv, struct command *cmd, struct plugin if (len < 11) strcpy(path, "None"); - printf("%-35s%s%s\n", "ScaleFlux Drive:", "/dev/", dev->name); + printf("%-35s%s%s\n", "ScaleFlux Drive:", "/dev/", nvme_transport_handle_get_name(hdl)); printf("%-35s%s\n", "PCIe Vendor ID:", pci_vid); printf("%-35s%s\n", "PCIe Subsystem Vendor ID:", pci_ssvid); printf("%-35s%s\n", "Manufacturer:", vendor); @@ -2078,8 +2034,5 @@ static int sfx_status(int argc, char **argv, struct command *cmd, struct plugin printf("%-35s%s\n", "Critical Warning(s):", path); } -close_dev: - dev_close(dev); -ret: - return err; + return 0; } diff --git a/plugins/seagate/seagate-nvme.c b/plugins/seagate/seagate-nvme.c index 96bbbb6349..d1d48cbea1 100644 --- a/plugins/seagate/seagate-nvme.c +++ b/plugins/seagate/seagate-nvme.c @@ -143,15 +143,16 @@ static void json_log_pages_supp(log_page_map *logPageMap) json_free_object(root); } -static int log_pages_supp(int argc, char **argv, struct command *cmd, - struct plugin *plugin) +static int log_pages_supp(int argc, char **argv, struct command *acmd, + struct plugin *plugin) { int err = 0; __u32 i = 0; log_page_map logPageMap; const char *desc = "Retrieve Seagate Supported Log-Page information for the given device "; const char *output_format = "output in binary format"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int fmt; struct config { @@ -167,11 +168,10 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = nvme_get_log_simple(dev_fd(dev), 0xc5, - sizeof(logPageMap), &logPageMap); + err = nvme_get_log_simple(hdl, 0xc5, &logPageMap, sizeof(logPageMap)); if (!err) { if (strcmp(cfg.output_format, "json")) { printf("Seagate Supported Log-pages count :%d\n", @@ -196,7 +196,7 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd, if (err > 0) nvme_show_status(err); - dev_close(dev); + return err; } @@ -885,7 +885,7 @@ static void json_print_stx_smart_log_C0(struct json_object *root, STX_EXT_SMART_ json_array_add_value_object(logPages, lbaf); } -static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int vs_smart_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { struct nvme_id_ctrl ctrl; char modelNo[40]; @@ -898,7 +898,8 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi const char *desc = "Retrieve the Firmware Activation History for Seagate NVMe drives"; const char *output_format = "output in binary format"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err, index = 0; struct config { char *output_format; @@ -913,7 +914,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { printf("\nDevice not found\n"); return -1; @@ -929,7 +930,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi * to determine drive family. */ - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (!err) { memcpy(modelNo, ctrl.mn, sizeof(modelNo)); } else { @@ -938,7 +939,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi } if (!stx_is_jag_pan(modelNo)) { - err = nvme_get_log_simple(dev_fd(dev), 0xC4, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); + err = nvme_get_log_simple(hdl, 0xC4, &ExtdSMARTInfo, sizeof(ExtdSMARTInfo)); if (!err) { if (strcmp(cfg.output_format, "json")) { printf("%-39s %-15s %-19s\n", "Description", "Ext-Smart-Id", "Ext-Smart-Value"); @@ -960,7 +961,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi * Next get Log Page 0xCF */ - err = nvme_get_log_simple(dev_fd(dev), 0xCF, sizeof(logPageCF), &logPageCF); + err = nvme_get_log_simple(hdl, 0xCF, &logPageCF, sizeof(logPageCF)); if (!err) { if (strcmp(cfg.output_format, "json")) { print_smart_log_CF(&logPageCF); @@ -978,7 +979,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi nvme_show_status(err); } } else { - err = nvme_get_log_simple(dev_fd(dev), 0xC0, sizeof(ehExtSmart), &ehExtSmart); + err = nvme_get_log_simple(hdl, 0xC0, &ehExtSmart, sizeof(ehExtSmart)); if (!err) { if (strcmp(cfg.output_format, "json")) { @@ -999,8 +1000,8 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi nvme_show_status(err); } - err = nvme_get_log_simple(dev_fd(dev), 0xC4, - sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); + err = nvme_get_log_simple(hdl, 0xC4, + &ExtdSMARTInfo, sizeof(ExtdSMARTInfo)); if (!err) { if (strcmp(cfg.output_format, "json")) { printf("%-39s %-15s %-19s\n", "Description", "Ext-Smart-Id", "Ext-Smart-Value"); @@ -1022,8 +1023,8 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi * Next get Log Page 0xCF */ - err = nvme_get_log_simple(dev_fd(dev), 0xCF, - sizeof(logPageCF), &logPageCF); + err = nvme_get_log_simple(hdl, 0xCF, + &logPageCF, sizeof(logPageCF)); if (!err) { if (strcmp(cfg.output_format, "json")) { print_smart_log_CF(&logPageCF); @@ -1040,8 +1041,6 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi nvme_show_status(err); } - dev_close(dev); - return err; } @@ -1050,8 +1049,9 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi /*************************************** * Temperature-Stats information ***************************************/ -static void json_temp_stats(__u32 temperature, __u32 PcbTemp, __u32 SocTemp, __u32 maxTemperature, - __u32 MaxSocTemp, __u32 cf_err, __u32 scCurrentTemp, __u32 scMaxTem) +static void json_temp_stats(__u32 temperature, __u32 PcbTemp, __u32 SocTemp, + __u32 maxTemperature, __u32 MaxSocTemp, + __u32 cf_err, __u32 scCurrentTemp, __u32 scMaxTem) { struct json_object *root = json_create_object(); @@ -1068,7 +1068,7 @@ static void json_temp_stats(__u32 temperature, __u32 PcbTemp, __u32 SocTemp, __u json_print_object(root, NULL); } -static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int temp_stats(int argc, char **argv, struct command *acmd, struct plugin *plugin) { struct nvme_smart_log smart_log; EXTENDED_SMART_INFO_T ExtdSMARTInfo; @@ -1081,7 +1081,8 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin nvme_print_flags_t flags; unsigned int temperature = 0, PcbTemp = 0, SocTemp = 0, scCurrentTemp = 0, scMaxTemp = 0; unsigned long long maxTemperature = 0, MaxSocTemp = 0; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct config { char *output_format; }; @@ -1095,7 +1096,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { printf("\nDevice not found\n"); return -1; @@ -1110,7 +1111,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin if (flags & NORMAL) printf("Seagate Temperature Stats Information :\n"); /*STEP-1 : Get Current Temperature from SMART */ - err = nvme_get_log_smart(dev_fd(dev), 0xffffffff, false, &smart_log); + err = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log); if (!err) { temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]); temperature = temperature ? temperature - 273 : 0; @@ -1126,8 +1127,8 @@ 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_simple(dev_fd(dev), 0xC4, - sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); + err = nvme_get_log_simple(hdl, 0xC4, + &ExtdSMARTInfo, sizeof(ExtdSMARTInfo)); if (!err) { for (index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) { if (ExtdSMARTInfo.vendorData[index].AttributeNumber == VS_ATTR_ID_MAX_LIFE_TEMPERATURE) { @@ -1149,8 +1150,8 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin nvme_show_status(err); } - cf_err = nvme_get_log_simple(dev_fd(dev), 0xCF, - sizeof(ExtdSMARTInfo), &logPageCF); + cf_err = nvme_get_log_simple(hdl, 0xCF, + &logPageCF, sizeof(ExtdSMARTInfo)); if (!cf_err) { scCurrentTemp = logPageCF.AttrCF.SuperCapCurrentTemperature; @@ -1165,7 +1166,6 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin if (flags & JSON) json_temp_stats(temperature, PcbTemp, SocTemp, maxTemperature, MaxSocTemp, cf_err, scCurrentTemp, scMaxTemp); - dev_close(dev); return err; } /* EOF Temperature Stats information */ @@ -1173,7 +1173,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin /*************************************** * PCIe error-log information ***************************************/ -static void print_vs_pcie_error_log(pcie_error_log_page pcieErrorLog) +static void print_vs_pcie_error_log(pcie_error_log_page pcieErrorLog) { __u32 correctPcieEc = pcieErrorLog.BadDllpErrCnt + pcieErrorLog.BadTlpErrCnt + pcieErrorLog.RcvrErrCnt + pcieErrorLog.ReplayTOErrCnt + @@ -1247,10 +1247,11 @@ static void json_vs_pcie_error_log(pcie_error_log_page pcieErrorLog) json_print_object(root, NULL); } -static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int vs_pcie_error_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { pcie_error_log_page pcieErrorLog; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; const char *desc = "Retrieve Seagate PCIe error counters for the given device "; const char *output_format = "output in binary format"; @@ -1269,7 +1270,7 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { printf("\nDevice not found\n"); return -1; @@ -1284,8 +1285,8 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct if (flags & NORMAL) printf("Seagate PCIe error counters Information :\n"); - err = nvme_get_log_simple(dev_fd(dev), 0xCB, - sizeof(pcieErrorLog), &pcieErrorLog); + err = nvme_get_log_simple(hdl, 0xCB, + &pcieErrorLog, sizeof(pcieErrorLog)); if (!err) { if (flags & NORMAL) print_vs_pcie_error_log(pcieErrorLog); @@ -1296,7 +1297,7 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct nvme_show_status(err); } - dev_close(dev); + return err; } /* EOF PCIE error-log information */ @@ -1392,10 +1393,11 @@ static void json_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwActi json_free_object(root); } -static int stx_vs_fw_activate_history(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int stx_vs_fw_activate_history(int argc, char **argv, struct command *acmd, struct plugin *plugin) { stx_fw_activ_history_log_page fwActivHis; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; const char *desc = "Retrieve FW Activate History for Seagate device "; const char *output_format = "output in binary format"; @@ -1414,7 +1416,7 @@ static int stx_vs_fw_activate_history(int argc, char **argv, struct command *cmd OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err < 0) { printf("\nDevice not found\n"); return -1; @@ -1429,7 +1431,7 @@ static int stx_vs_fw_activate_history(int argc, char **argv, struct command *cmd if (flags & NORMAL) printf("Seagate FW Activation History Information :\n"); - err = nvme_get_log_simple(dev_fd(dev), 0xC2, sizeof(fwActivHis), &fwActivHis); + err = nvme_get_log_simple(hdl, 0xC2, &fwActivHis, sizeof(fwActivHis)); if (!err) { if (flags & NORMAL) print_stx_vs_fw_activate_history(fwActivHis); @@ -1439,18 +1441,18 @@ static int stx_vs_fw_activate_history(int argc, char **argv, struct command *cmd nvme_show_status(err); } - dev_close(dev); return err; } /* EOF FW Activation History log information */ -static int clear_fw_activate_history(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int clear_fw_activate_history(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Clear FW Activation History for the given Seagate device "; const char *save = "specifies that the controller shall save the attribute"; int err; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct nvme_id_ctrl ctrl; char modelNo[40]; __u32 result; @@ -1468,13 +1470,13 @@ static int clear_fw_activate_history(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err < 0) { printf("\nDevice not found\n"); return -1; } - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (!err) { memcpy(modelNo, ctrl.mn, sizeof(modelNo)); } else { @@ -1485,25 +1487,11 @@ static int clear_fw_activate_history(int argc, char **argv, struct command *cmd, if (!stx_is_jag_pan(modelNo)) { printf("\nDevice does not support Clear FW Activation History\n"); } else { - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = 0xC1, - .nsid = 0, - .cdw11 = 0x80000000, - .cdw12 = 0, - .save = 0, - .uuidx = 0, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); - if (err) - fprintf(stderr, "%s: couldn't clear PCIe correctable errors\n", - __func__); + err = nvme_set_features(hdl, 0, 0xC1, 0, 0x80000000, 0, 0, 0, 0, NULL, + 0, &result); + if (err) + fprintf(stderr, "%s: couldn't clear PCIe correctable errors\n", + __func__); } if (err < 0) { @@ -1511,12 +1499,11 @@ static int clear_fw_activate_history(int argc, char **argv, struct command *cmd, return errno; } - dev_close(dev); return err; } -static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Clear Seagate PCIe Correctable counters for the given device "; const char *save = "specifies that the controller shall save the attribute"; @@ -1524,7 +1511,8 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c struct nvme_id_ctrl ctrl; char modelNo[40]; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 result; int err; @@ -1542,14 +1530,14 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { printf("\nDevice not found\n"); return -1; } - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (!err) { memcpy(modelNo, ctrl.mn, sizeof(modelNo)); } else { @@ -1558,40 +1546,25 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c } if (!stx_is_jag_pan(modelNo)) { - err = nvme_set_features_simple(dev_fd(dev), 0xE1, 0, 0xCB, cfg.save, &result); + err = nvme_set_features_simple(hdl, 0, 0xE1, cfg.save, 0xCB, &result); } else { - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = 0xC3, - .nsid = 0, - .cdw11 = 0x80000000, - .cdw12 = 0, - .save = 0, - .uuidx = 0, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); + err = nvme_set_features(hdl, 0, 0xC3, 0, 0x80000000, 0, 0, 0, 0, NULL, + 0, &result); if (err) fprintf(stderr, "%s: couldn't clear PCIe correctable errors\n", __func__); } - err = nvme_set_features_simple(dev_fd(dev), 0xE1, 0, 0xCB, cfg.save, &result); + err = nvme_set_features_simple(hdl, 0, 0xE1, cfg.save, 0xCB, &result); if (err < 0) { perror("set-feature"); return errno; } - dev_close(dev); return err; } -static int get_host_tele(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_host_tele(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Capture the Telemetry Host-Initiated Data in either hex-dump (default) or binary format"; @@ -1602,7 +1575,9 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug const char *raw = "output in raw format"; struct nvme_temetry_log_hdr tele_log; int blkCnt, maxBlk = 0, blksToGet; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; unsigned char *log; __le64 offset = 0; int err, dump_fd; @@ -1625,22 +1600,21 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; dump_fd = STDOUT_FILENO; cfg.log_id = (cfg.log_id << 8) | 0x07; - err = nvme_get_nsid_log(dev_fd(dev), false, cfg.log_id, - cfg.namespace_id, - sizeof(tele_log), (void *)(&tele_log)); + err = nvme_get_nsid_log(hdl, cfg.namespace_id, false, cfg.log_id, + (void *)(&tele_log), sizeof(tele_log)); if (!err) { maxBlk = tele_log.tele_data_area3; offset += 512; if (!cfg.raw_binary) { printf("Device:%s log-id:%d namespace-id:%#x\n", - dev->name, cfg.log_id, + nvme_transport_handle_get_name(hdl), cfg.log_id, cfg.namespace_id); printf("Data Block 1 Last Block:%d Data Block 2 Last Block:%d Data Block 3 Last Block:%d\n", tele_log.tele_data_area1, tele_log.tele_data_area2, tele_log.tele_data_area3); @@ -1662,7 +1636,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt); if (!blksToGet) { - dev_close(dev); + return err; } @@ -1671,30 +1645,17 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug if (!log) { fprintf(stderr, "could not alloc buffer for log\n"); - dev_close(dev); + return -EINVAL; } memset(log, 0, bytesToGet); - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .lid = cfg.log_id, - .nsid = cfg.namespace_id, - .lpo = offset, - .lsp = 0, - .lsi = 0, - .rae = true, - .uuidx = 0, - .csi = NVME_CSI_NVM, - .ot = false, - .len = bytesToGet, - .log = (void *)log, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - err = nvme_get_log(&args); + nvme_init_get_log(&cmd, cfg.namespace_id, cfg.log_id, + NVME_CSI_NVM, log, bytesToGet); + nvme_init_get_log_lpo(&cmd, offset); + err = nvme_get_log(hdl, &cmd, true, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (!err) { offset += (__le64)bytesToGet; @@ -1715,17 +1676,18 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug free(log); } - dev_close(dev); return err; } -static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_ctrl_tele(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Capture the Telemetry Controller-Initiated Data in either hex-dump (default) or binary format"; const char *namespace_id = "desired namespace"; const char *raw = "output in raw format"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; int err, dump_fd; struct nvme_temetry_log_hdr tele_log; __le64 offset = 0; @@ -1748,22 +1710,22 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; dump_fd = STDOUT_FILENO; log_id = 0x08; - err = nvme_get_nsid_log(dev_fd(dev), false, log_id, cfg.namespace_id, - sizeof(tele_log), (void *)(&tele_log)); + err = nvme_get_nsid_log(hdl, cfg.namespace_id, false, log_id, + (void *)(&tele_log), sizeof(tele_log)); if (!err) { maxBlk = tele_log.tele_data_area3; offset += 512; if (!cfg.raw_binary) { printf("Device:%s namespace-id:%#x\n", - dev->name, cfg.namespace_id); + nvme_transport_handle_get_name(hdl), cfg.namespace_id); printf("Data Block 1 Last Block:%d Data Block 2 Last Block:%d Data Block 3 Last Block:%d\n", tele_log.tele_data_area1, tele_log.tele_data_area2, tele_log.tele_data_area3); @@ -1796,24 +1758,11 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug memset(log, 0, bytesToGet); - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .lid = log_id, - .nsid = cfg.namespace_id, - .lpo = offset, - .lsp = 0, - .lsi = 0, - .rae = true, - .uuidx = 0, - .csi = NVME_CSI_NVM, - .ot = false, - .len = bytesToGet, - .log = (void *)log, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - err = nvme_get_log(&args); + nvme_init_get_log(&cmd, cfg.namespace_id, log_id, + NVME_CSI_NVM, log, bytesToGet); + nvme_init_get_log_lpo(&cmd, offset); + err = nvme_get_log(hdl, &cmd, true, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (!err) { offset += (__le64)bytesToGet; @@ -1834,24 +1783,27 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug free(log); } - dev_close(dev); + return err; } -void seaget_d_raw(unsigned char *buf, int len, int fd) +void +seaget_d_raw(unsigned char *buf, int len, int fd) { if (write(fd, (void *)buf, len) <= 0) printf("%s: Write Failed\n", __func__); } -static int vs_internal_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int vs_internal_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Capture the Telemetry Controller-Initiated Data in binary format"; const char *namespace_id = "desired namespace"; const char *file = "dump file"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; int err, dump_fd; int flags = O_WRONLY | O_CREAT; int mode = 0664; @@ -1877,7 +1829,7 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -1886,14 +1838,13 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl dump_fd = open(cfg.file, flags, mode); if (dump_fd < 0) { perror(cfg.file); - dev_close(dev); return -EINVAL; } } log_id = 0x08; - err = nvme_get_nsid_log(dev_fd(dev), false, log_id, cfg.namespace_id, - sizeof(tele_log), (void *)(&tele_log)); + err = nvme_get_nsid_log(hdl, cfg.namespace_id, false, log_id, + (void *)(&tele_log), sizeof(tele_log)); if (!err) { maxBlk = tele_log.tele_data_area3; offset += 512; @@ -1926,24 +1877,12 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl memset(log, 0, bytesToGet); - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .lid = log_id, - .nsid = cfg.namespace_id, - .lpo = offset, - .lsp = 0, - .lsi = 0, - .rae = true, - .uuidx = 0, - .csi = NVME_CSI_NVM, - .ot = false, - .len = bytesToGet, - .log = (void *)log, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - err = nvme_get_log(&args); + nvme_init_get_log_lpo(&cmd, offset); + nvme_init_get_log(&cmd, cfg.namespace_id, log_id, + NVME_CSI_NVM, log, bytesToGet); + nvme_init_get_log_lpo(&cmd, offset); + err = nvme_get_log(hdl, &cmd, true, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (!err) { offset += (__le64)bytesToGet; @@ -1963,12 +1902,11 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl if (strlen(cfg.file)) close(dump_fd); - dev_close(dev); return err; } /*SEAGATE-PLUGIN Version */ -static int seagate_plugin_version(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int seagate_plugin_version(int argc, char **argv, struct command *acmd, struct plugin *plugin) { printf("Seagate-Plugin version : %d.%d\n", SEAGATE_PLUGIN_VERSION_MAJOR, @@ -1978,7 +1916,7 @@ static int seagate_plugin_version(int argc, char **argv, struct command *cmd, st /*EOF SEAGATE-PLUGIN Version */ /*OCP SEAGATE-PLUGIN Version */ -static int stx_ocp_plugin_version(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int stx_ocp_plugin_version(int argc, char **argv, struct command *acmd, struct plugin *plugin) { printf("Seagate-OCP-Plugin version : %d.%d\n", SEAGATE_OCP_PLUGIN_VERSION_MAJOR, diff --git a/plugins/sed/sed.c b/plugins/sed/sed.c index 3d6052a927..9cfbebd764 100644 --- a/plugins/sed/sed.c +++ b/plugins/sed/sed.c @@ -62,138 +62,137 @@ OPT_ARGS(discovery_opts) = { * Open the NVMe device specified on the command line. It must be the * NVMe block device (e.g. /dev/nvme0n1). */ -static int sed_opal_open_device(struct nvme_dev **dev, int argc, char **argv, +static int sed_opal_open_device(struct nvme_global_ctx **ctx, struct nvme_transport_handle **hdl, int argc, char **argv, const char *desc, struct argconfig_commandline_options *opts) { int err; - err = parse_and_open(dev, argc, argv, desc, opts); + err = parse_and_open(ctx, hdl, argc, argv, desc, opts); if (err) return err; - if (!S_ISBLK((*dev)->direct.stat.st_mode)) { + if (!nvme_transport_handle_is_blkdev(*hdl)) { fprintf(stderr, "ERROR : The NVMe block device must be specified\n"); err = -EINVAL; - dev_close(*dev); } return err; } -static int sed_opal_discover(int argc, char **argv, struct command *cmd, +static int sed_opal_discover(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - int err; const char *desc = "Query SED device and display locking features"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + int err; - err = sed_opal_open_device(&dev, argc, argv, desc, discovery_opts); + err = sed_opal_open_device(&ctx, &hdl, argc, argv, desc, discovery_opts); if (err) return err; - err = sedopal_cmd_discover(dev->direct.fd); + err = sedopal_cmd_discover(nvme_transport_handle_get_fd(hdl)); - dev_close(dev); return err; } -static int sed_opal_initialize(int argc, char **argv, struct command *cmd, +static int sed_opal_initialize(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - int err; const char *desc = "Initialize a SED device for locking"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + int err; - err = sed_opal_open_device(&dev, argc, argv, desc, init_opts); + err = sed_opal_open_device(&ctx, &hdl, argc, argv, desc, init_opts); if (err) return err; - err = sedopal_cmd_initialize(dev->direct.fd); + err = sedopal_cmd_initialize(nvme_transport_handle_get_fd(hdl)); if ((err != 0) && (err != -EOPNOTSUPP)) fprintf(stderr, "initialize: SED error - %s\n", sedopal_error_to_text(err)); - dev_close(dev); return err; } -static int sed_opal_revert(int argc, char **argv, struct command *cmd, +static int sed_opal_revert(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - int err; const char *desc = "Revert a SED device from locking state"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + int err; - err = sed_opal_open_device(&dev, argc, argv, desc, revert_opts); + err = sed_opal_open_device(&ctx, &hdl, argc, argv, desc, revert_opts); if (err) return err; - err = sedopal_cmd_revert(dev->direct.fd); + err = sedopal_cmd_revert(nvme_transport_handle_get_fd(hdl)); if ((err != 0) && (err != -EOPNOTSUPP) && (err != EPERM)) fprintf(stderr, "revert: SED error - %s\n", sedopal_error_to_text(err)); - dev_close(dev); return err; } -static int sed_opal_lock(int argc, char **argv, struct command *cmd, +static int sed_opal_lock(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - int err; const char *desc = "Lock a SED device"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + int err; - err = sed_opal_open_device(&dev, argc, argv, desc, lock_opts); + err = sed_opal_open_device(&ctx, &hdl, argc, argv, desc, lock_opts); if (err) return err; - err = sedopal_cmd_lock(dev->direct.fd); + err = sedopal_cmd_lock(nvme_transport_handle_get_fd(hdl)); if ((err != 0) && (err != -EOPNOTSUPP)) fprintf(stderr, "lock: SED error - %s\n", sedopal_error_to_text(err)); - dev_close(dev); return err; } -static int sed_opal_unlock(int argc, char **argv, struct command *cmd, +static int sed_opal_unlock(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - int err; const char *desc = "Unlock a SED device"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + int err; - err = sed_opal_open_device(&dev, argc, argv, desc, lock_opts); + err = sed_opal_open_device(&ctx, &hdl, argc, argv, desc, lock_opts); if (err) return err; - err = sedopal_cmd_unlock(dev->direct.fd); + err = sedopal_cmd_unlock(nvme_transport_handle_get_fd(hdl)); if ((err != 0) && (err != -EOPNOTSUPP)) fprintf(stderr, "unlock: SED error - %s\n", sedopal_error_to_text(err)); - dev_close(dev); return err; } -static int sed_opal_password(int argc, char **argv, struct command *cmd, +static int sed_opal_password(int argc, char **argv, struct command *acmd, struct plugin *plugin) { int err; const char *desc = "Change the locking password of a SED device"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; - err = sed_opal_open_device(&dev, argc, argv, desc, no_opts); + err = sed_opal_open_device(&ctx, &hdl, argc, argv, desc, no_opts); if (err) return err; - err = sedopal_cmd_password(dev->direct.fd); + err = sedopal_cmd_password(nvme_transport_handle_get_fd(hdl)); if ((err != 0) && (err != EPERM)) fprintf(stderr, "password: SED error - %s\n", sedopal_error_to_text(err)); - dev_close(dev); return err; } diff --git a/plugins/sed/sedopal_cmd.c b/plugins/sed/sedopal_cmd.c index bbcf16b4cf..40d7a7ffcd 100644 --- a/plugins/sed/sedopal_cmd.c +++ b/plugins/sed/sedopal_cmd.c @@ -11,6 +11,9 @@ #include #include #include + +#include + #include "sedopal_spec.h" #include "sedopal_cmd.h" diff --git a/plugins/shannon/shannon-nvme.c b/plugins/shannon/shannon-nvme.c index b4c02fb79d..1a44f32743 100644 --- a/plugins/shannon/shannon-nvme.c +++ b/plugins/shannon/shannon-nvme.c @@ -60,8 +60,8 @@ struct nvme_shannon_smart_log { __u8 vend_spec_resv; }; -static void show_shannon_smart_log(struct nvme_shannon_smart_log *smart, unsigned int nsid, - const char *devname) +static void show_shannon_smart_log(struct nvme_shannon_smart_log *smart, + unsigned int nsid, const char *devname) { printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", devname, nsid); @@ -113,14 +113,15 @@ static void show_shannon_smart_log(struct nvme_shannon_smart_log *smart, unsigne int48_to_long(smart->items[SRAM_ERROR_CNT].item_val)); } -static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_additional_smart_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { struct nvme_shannon_smart_log smart_log; char *desc = "Get Shannon vendor specific additional smart log (optionally, for the specified namespace), and show it."; const char *namespace = "(optional) desired namespace"; const char *raw = "dump output in binary format"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct config { __u32 namespace_id; bool raw_binary; @@ -137,24 +138,26 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = nvme_get_nsid_log(dev_fd(dev), false, 0xca, cfg.namespace_id, - sizeof(smart_log), &smart_log); + err = nvme_get_nsid_log(hdl, cfg.namespace_id, false, 0xca, + &smart_log, sizeof(smart_log)); if (!err) { if (!cfg.raw_binary) - show_shannon_smart_log(&smart_log, cfg.namespace_id, dev->name); + show_shannon_smart_log( + &smart_log, cfg.namespace_id, + nvme_transport_handle_get_name(hdl)); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); } else if (err > 0) { nvme_show_status(err); } - dev_close(dev); + return err; } -static int get_additional_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_additional_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Read operating parameters of the\n" "specified controller. Operating parameters are grouped\n" @@ -174,7 +177,8 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st const char *data_len = "buffer len (if) data is returned"; const char *cdw11 = "dword 11 for interrupt vector config"; const char *human_readable = "show infos in readable format"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; void *buf = NULL; __u32 result; int err; @@ -208,49 +212,33 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; if (cfg.sel > 7) { fprintf(stderr, "invalid 'select' param:%d\n", cfg.sel); - dev_close(dev); return -EINVAL; } if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); - dev_close(dev); return -EINVAL; } if (cfg.data_len) { - if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { - dev_close(dev); - exit(ENOMEM); - } + if (posix_memalign(&buf, getpagesize(), cfg.data_len)) + return -ENOMEM; memset(buf, 0, cfg.data_len); } - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = cfg.feature_id, - .nsid = cfg.namespace_id, - .sel = cfg.sel, - .cdw11 = cfg.cdw11, - .uuidx = 0, - .data_len = cfg.data_len, - .data = buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_get_features(&args); + err = nvme_get_features(hdl, cfg.namespace_id, cfg.feature_id, cfg.sel, + cfg.cdw11, 0, buf, cfg.data_len, &result); if (err > 0) nvme_show_status(err); free(buf); return err; } -static int set_additional_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int set_additional_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Modify the saveable or changeable\n" "current operating parameters of the controller. Operating\n" @@ -269,9 +257,10 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st const char *data = "optional file for feature data (default stdin)"; const char *value = "new value of feature (required)"; const char *save = "specifies that the controller shall save the attribute"; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_free_ void *buf = NULL; int ffd = STDIN_FILENO; - struct nvme_dev *dev; - void *buf = NULL; __u32 result; int err; @@ -303,20 +292,18 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); - dev_close(dev); return -EINVAL; } if (cfg.data_len) { if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { fprintf(stderr, "can not allocate feature payload\n"); - dev_close(dev); return -ENOMEM; } memset(buf, 0, cfg.data_len); @@ -327,37 +314,21 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st ffd = open(cfg.file, O_RDONLY); if (ffd <= 0) { fprintf(stderr, "no firmware file provided\n"); - err = EINVAL; - goto free; + return -EINVAL; } } err = read(ffd, (void *)buf, cfg.data_len); if (err < 0) { fprintf(stderr, "failed to read data buffer from input file\n"); - err = EINVAL; - goto free; + return -EINVAL; } } - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = cfg.feature_id, - .nsid = cfg.namespace_id, - .cdw11 = cfg.value, - .cdw12 = 0, - .save = cfg.save, - .uuidx = 0, - .cdw15 = 0, - .data_len = cfg.data_len, - .data = buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); + err = nvme_set_features(hdl, cfg.namespace_id, cfg.feature_id, cfg.save, + cfg.value, 0, 0, 0, 0, buf, cfg.data_len, &result); if (err < 0) { perror("set-feature"); - goto free; + return -errno; } if (!err) { if (buf) @@ -365,15 +336,11 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st } else if (err > 0) nvme_show_status(err); -free: - free(buf); return err; } -static int shannon_id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int shannon_id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return __id_ctrl(argc, argv, cmd, plugin, NULL); + return __id_ctrl(argc, argv, acmd, plugin, NULL); } - - diff --git a/plugins/solidigm/solidigm-garbage-collection.c b/plugins/solidigm/solidigm-garbage-collection.c index 3c046b0ed4..3e91205162 100644 --- a/plugins/solidigm/solidigm-garbage-collection.c +++ b/plugins/solidigm/solidigm-garbage-collection.c @@ -65,11 +65,13 @@ static void vu_gc_log_show(struct garbage_control_collection_log *payload, const } } -int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get and parse Solidigm vendor specific garbage collection event log."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; - struct nvme_dev *dev; int err; __u8 uuid_index; @@ -86,53 +88,38 @@ int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *c OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; err = validate_output_format(cfg.output_format, &flags); if (err) { fprintf(stderr, "Invalid output format '%s'\n", cfg.output_format); - dev_close(dev); return -EINVAL; } - sldgm_get_uuid_index(dev, &uuid_index); + sldgm_get_uuid_index(hdl, &uuid_index); struct garbage_control_collection_log gc_log; const int solidigm_vu_gc_log_id = 0xfd; - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = &gc_log, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = solidigm_vu_gc_log_id, - .len = sizeof(gc_log), - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = uuid_index, - .rae = false, - .ot = false, - }; - - err = nvme_get_log(&args); + nvme_init_get_log(&cmd, NVME_NSID_ALL, + solidigm_vu_gc_log_id, NVME_CSI_NVM, + &gc_log, sizeof(gc_log)); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + err = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (!err) { if (flags & BINARY) d_raw((unsigned char *)&gc_log, sizeof(gc_log)); else if (flags & JSON) - vu_gc_log_show_json(&gc_log, dev->name); + vu_gc_log_show_json(&gc_log, nvme_transport_handle_get_name(hdl)); else - vu_gc_log_show(&gc_log, dev->name, uuid_index); + vu_gc_log_show(&gc_log, nvme_transport_handle_get_name(hdl), uuid_index); } else if (err > 0) { nvme_show_status(err); } - /* Redundant close() to make static code analysis happy */ - close(dev->direct.fd); - dev_close(dev); return err; } diff --git a/plugins/solidigm/solidigm-garbage-collection.h b/plugins/solidigm/solidigm-garbage-collection.h index a3e34b2b8b..7dd8041804 100644 --- a/plugins/solidigm/solidigm-garbage-collection.h +++ b/plugins/solidigm/solidigm-garbage-collection.h @@ -5,4 +5,4 @@ * Author: leonardo.da.cunha@solidigm.com */ -int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); +int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); diff --git a/plugins/solidigm/solidigm-get-drive-info.c b/plugins/solidigm/solidigm-get-drive-info.c index c783fa8abd..f92abfb41d 100644 --- a/plugins/solidigm/solidigm-get-drive-info.c +++ b/plugins/solidigm/solidigm-get-drive-info.c @@ -7,17 +7,16 @@ #include #include "nvme-print.h" -#include "nvme-wrap.h" #include "common.h" -int sldgm_get_drive_info(int argc, char **argv, struct command *cmd, struct plugin *plugin) +int sldgm_get_drive_info(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; const char *desc = "Get drive HW information"; const char *FTL_unit_size_str = "FTL_unit_size"; char *output_format = "normal"; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; - nvme_root_t r; nvme_ctrl_t c; nvme_ns_t n; struct nvme_id_ns ns = { 0 }; @@ -31,7 +30,7 @@ int sldgm_get_drive_info(int argc, char **argv, struct command *cmd, struct plug OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -41,12 +40,19 @@ int sldgm_get_drive_info(int argc, char **argv, struct command *cmd, struct plug return err; } - r = nvme_scan(NULL); - c = nvme_scan_ctrl(r, dev->name); - n = c ? nvme_ctrl_first_ns(c) : nvme_scan_namespace(dev->name); - if (!n) { - nvme_show_error("solidigm-vs-drive-info: drive missing namespace"); - return -EINVAL; + err = nvme_scan_topology(ctx, NULL, NULL); + if (err) + return err; + + err = nvme_scan_ctrl(ctx, nvme_transport_handle_get_name(hdl), &c); + if (!err) + n = nvme_ctrl_first_ns(c); + else { + err = nvme_scan_namespace(nvme_transport_handle_get_name(hdl), &n); + if (err) { + nvme_show_error("solidigm-vs-drive-info: drive missing namespace"); + return err; + } } err = nvme_ns_identify(n, &ns); diff --git a/plugins/solidigm/solidigm-get-drive-info.h b/plugins/solidigm/solidigm-get-drive-info.h index ffc1bd2468..859fbeaad4 100644 --- a/plugins/solidigm/solidigm-get-drive-info.h +++ b/plugins/solidigm/solidigm-get-drive-info.h @@ -5,4 +5,4 @@ * Author: leonardo.da.cunha@solidigm.com */ -int sldgm_get_drive_info(int argc, char **argv, struct command *cmd, struct plugin *plugin); +int sldgm_get_drive_info(int argc, char **argv, struct command *acmd, struct plugin *plugin); diff --git a/plugins/solidigm/solidigm-internal-logs.c b/plugins/solidigm/solidigm-internal-logs.c index 1481fee9fd..105f1b9e5c 100644 --- a/plugins/solidigm/solidigm-internal-logs.c +++ b/plugins/solidigm/solidigm-internal-logs.c @@ -134,7 +134,6 @@ struct config { }; struct ilog { - struct nvme_dev *dev; struct config *cfg; int count; struct nvme_id_ctrl id_ctrl; @@ -174,7 +173,7 @@ static void print_nlog_header(__u8 *buffer) #define INTERNAL_LOG_MAX_DWORD_TRANSFER (INTERNAL_LOG_MAX_BYTE_TRANSFER / 4) static int cmd_dump_repeat(struct nvme_passthru_cmd *cmd, __u32 total_dw_size, - int out_fd, int ioctl_fd, bool force_max_transfer) + int out_fd, struct nvme_transport_handle *hdl, bool force_max_transfer) { int err = 0; @@ -183,7 +182,7 @@ static int cmd_dump_repeat(struct nvme_passthru_cmd *cmd, __u32 total_dw_size, cmd->cdw10 = force_max_transfer ? INTERNAL_LOG_MAX_DWORD_TRANSFER : dword_tfer; cmd->data_len = dword_tfer * 4; - err = nvme_submit_admin_passthru(ioctl_fd, cmd, NULL); + err = nvme_submit_admin_passthru(hdl, cmd, NULL); if (err) return err; @@ -208,18 +207,18 @@ static int write_header(__u8 *buf, int fd, size_t amnt) return 0; } -static int read_header(struct nvme_passthru_cmd *cmd, int ioctl_fd) +static int read_header(struct nvme_passthru_cmd *cmd, struct nvme_transport_handle *hdl) { memset((void *)(uintptr_t)cmd->addr, 0, INTERNAL_LOG_MAX_BYTE_TRANSFER); - return cmd_dump_repeat(cmd, INTERNAL_LOG_MAX_DWORD_TRANSFER, -1, ioctl_fd, false); + return cmd_dump_repeat(cmd, INTERNAL_LOG_MAX_DWORD_TRANSFER, -1, hdl, false); } -static int get_serial_number(char *str, int fd) +static int get_serial_number(char *str, struct nvme_transport_handle *hdl) { struct nvme_id_ctrl ctrl = {0}; int err; - err = nvme_identify_ctrl(fd, &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err) return err; @@ -230,7 +229,7 @@ static int get_serial_number(char *str, int fd) return err; } -static int ilog_dump_assert_logs(struct ilog *ilog) +static int ilog_dump_assert_logs(struct nvme_transport_handle *hdl, struct ilog *ilog) { __u8 buf[INTERNAL_LOG_MAX_BYTE_TRANSFER]; __u8 head_buf[INTERNAL_LOG_MAX_BYTE_TRANSFER]; @@ -246,7 +245,7 @@ static int ilog_dump_assert_logs(struct ilog *ilog) }; int output, err; - err = read_header(&cmd, dev_fd(ilog->dev)); + err = read_header(&cmd, hdl); if (err) return err; @@ -277,7 +276,7 @@ static int ilog_dump_assert_logs(struct ilog *ilog) continue; cmd.cdw13 = ad->core[i].coreoffset; err = cmd_dump_repeat(&cmd, ad->core[i].assertsize, output, - dev_fd(ilog->dev), false); + hdl, false); if (err) { close(output); return err; @@ -288,7 +287,7 @@ static int ilog_dump_assert_logs(struct ilog *ilog) return err; } -static int ilog_dump_event_logs(struct ilog *ilog) +static int ilog_dump_event_logs(struct nvme_transport_handle *hdl, struct ilog *ilog) { __u8 buf[INTERNAL_LOG_MAX_BYTE_TRANSFER]; __u8 head_buf[INTERNAL_LOG_MAX_BYTE_TRANSFER]; @@ -304,7 +303,7 @@ static int ilog_dump_event_logs(struct ilog *ilog) int output; int core_num, err; - err = read_header(&cmd, dev_fd(ilog->dev)); + err = read_header(&cmd, hdl); if (err) return err; if (asprintf(&file_path, "%s/EventLog.bin", ilog->cfg->out_dir)) @@ -335,7 +334,7 @@ static int ilog_dump_event_logs(struct ilog *ilog) } cmd.cdw13 = ehdr->edumps[j].coreoffset; err = cmd_dump_repeat(&cmd, ehdr->edumps[j].coresize, - output, dev_fd(ilog->dev), false); + output, hdl, false); if (err) { close(output); return err; @@ -362,7 +361,7 @@ static size_t get_nlog_header_size(struct nlog_dump_header_common *nlog_header) } /* dumps nlogs from specified core or all cores when core = -1 */ -static int ilog_dump_nlogs(struct ilog *ilog, int core) +static int ilog_dump_nlogs(struct nvme_transport_handle *hdl, struct ilog *ilog, int core) { int err = 0; __u32 count, core_num; @@ -395,7 +394,7 @@ static int ilog_dump_nlogs(struct ilog *ilog, int core) do { cmd.cdw13 = 0; cmd.cdw12 = log_select.raw; - err = read_header(&cmd, dev_fd(ilog->dev)); + err = read_header(&cmd, hdl); if (err) { if (is_open) close(output); @@ -421,7 +420,7 @@ static int ilog_dump_nlogs(struct ilog *ilog, int core) print_nlog_header(buf); cmd.cdw13 = 0x400; err = cmd_dump_repeat(&cmd, nlog_header->nlogbytesize / 4, - output, dev_fd(ilog->dev), true); + output, hdl, true); if (err) break; } while (++log_select.selectNlog < count); @@ -491,23 +490,28 @@ static int log_save(struct log *log, const char *parent_dir_name, const char *su return 0; } -static int ilog_dump_identify_page(struct ilog *ilog, struct log *cns, __u32 nsid) +static int ilog_dump_identify_page(struct nvme_transport_handle *hdl, + struct ilog *ilog, struct log *cns, __u32 nsid) { __u8 data[NVME_IDENTIFY_DATA_SIZE]; __u8 *buff = cns->buffer ? cns->buffer : data; _cleanup_free_ char *filename = NULL; - int err = nvme_identify_cns_nsid(dev_fd(ilog->dev), cns->id, nsid, buff); + int err; + err = nvme_identify(hdl, nsid, NVME_CSI_NVM, cns->id, buff, 0); if (err) return err; - if (asprintf(&filename, "cntid_0_cns_%d_nsid_%d_nvmsetid_0_csi_0.bin", cns->id, nsid) < 0) + if (asprintf(&filename, "cntid_0_cns_%d_nsid_%d_nvmsetid_0_csi_0.bin", + cns->id, nsid) < 0) return -errno; - return log_save(cns, ilog->cfg->out_dir, "identify", filename, buff, sizeof(data)); + return log_save(cns, ilog->cfg->out_dir, "identify", filename, buff, + sizeof(data)); } -static int ilog_ensure_dump_id_ctrl(struct ilog *ilog) +static int ilog_ensure_dump_id_ctrl(struct nvme_transport_handle *hdl, + struct ilog *ilog) { static bool first = true; static int err; @@ -518,7 +522,7 @@ static int ilog_ensure_dump_id_ctrl(struct ilog *ilog) return err; first = false; - err = ilog_dump_identify_page(ilog, &idctrl, 0); + err = ilog_dump_identify_page(hdl, ilog, &idctrl, 0); if (!err) ilog->count++; @@ -526,19 +530,20 @@ static int ilog_ensure_dump_id_ctrl(struct ilog *ilog) return err; } -static bool is_atmos(struct ilog *ilog) +static bool is_atmos(struct nvme_transport_handle *hdl, struct ilog *ilog) { - ilog_ensure_dump_id_ctrl(ilog); + ilog_ensure_dump_id_ctrl(hdl, ilog); return !strncmp(ilog->id_ctrl.mn, ATMOS_MODEL_PREFIX, sizeof(ATMOS_MODEL_PREFIX) - 1); } -static enum nvme_telemetry_da get_max_da(struct ilog *ilog, enum log_type ttype) +static enum nvme_telemetry_da get_max_da(struct nvme_transport_handle *hdl, + struct ilog *ilog, enum log_type ttype) { enum nvme_telemetry_da max_da = NVME_TELEMETRY_DA_1; - ilog_ensure_dump_id_ctrl(ilog); + ilog_ensure_dump_id_ctrl(hdl, ilog); - if (is_atmos(ilog) && ttype != EXTENDED) + if (is_atmos(hdl, ilog) && ttype != EXTENDED) return NVME_TELEMETRY_DA_3; if (ilog->id_ctrl.lpa & 0x8) @@ -548,7 +553,7 @@ static enum nvme_telemetry_da get_max_da(struct ilog *ilog, enum log_type ttype) return max_da; } -static int ilog_dump_telemetry(struct ilog *ilog, enum log_type ttype) +static int ilog_dump_telemetry(struct nvme_transport_handle *hdl, struct ilog *ilog, enum log_type ttype) { int err = 0; enum nvme_telemetry_da da; @@ -556,24 +561,27 @@ static int ilog_dump_telemetry(struct ilog *ilog, enum log_type ttype) const char *file_name; struct nvme_feat_host_behavior prev = {0}; bool host_behavior_changed = false; + struct nvme_passthru_cmd cmd; struct log log = {0}; - err = ilog_ensure_dump_id_ctrl(ilog); + err = ilog_ensure_dump_id_ctrl(hdl, ilog); if (err) return err; - da = get_max_da(ilog, ttype); + da = get_max_da(hdl, ilog, ttype); mdts = ilog->id_ctrl.mdts; if (da == 4) { __u32 result; - int err = nvme_get_features_host_behavior(dev_fd(ilog->dev), 0, &prev, &result); + nvme_init_get_features_host_behavior(&cmd, 0, &prev); + int err = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!err && !prev.etdas) { struct nvme_feat_host_behavior da4_enable = prev; da4_enable.etdas = 1; - nvme_set_features_host_behavior(dev_fd(ilog->dev), 0, &da4_enable); + nvme_init_set_features_host_behavior(&cmd, 0, &da4_enable); + nvme_submit_admin_passthru(hdl, &cmd, NULL); host_behavior_changed = true; } } @@ -584,14 +592,14 @@ static int ilog_dump_telemetry(struct ilog *ilog, enum log_type ttype) case EXTENDED: file_name = "lid_0x07_lsp_0x01_lsi_0x0000.bin"; log.desc = "Host Initiated Telemetry"; - err = sldgm_dynamic_telemetry(dev_fd(ilog->dev), true, false, false, mdts, + err = sldgm_dynamic_telemetry(hdl, true, false, false, mdts, da, (struct nvme_telemetry_log **) &log.buffer, &log.buffer_size); break; case CIT: file_name = "lid_0x08_lsp_0x00_lsi_0x0000.bin"; log.desc = "Controller Initiated Telemetry"; - err = sldgm_dynamic_telemetry(dev_fd(ilog->dev), false, true, true, mdts, + err = sldgm_dynamic_telemetry(hdl, false, true, true, mdts, da, (struct nvme_telemetry_log **) &log.buffer, &log.buffer_size); break; @@ -599,8 +607,10 @@ static int ilog_dump_telemetry(struct ilog *ilog, enum log_type ttype) return -EINVAL; } - if (host_behavior_changed) - nvme_set_features_host_behavior(dev_fd(ilog->dev), 0, &prev); + if (host_behavior_changed) { + nvme_init_set_features_host_behavior(&cmd, 0, &prev); + nvme_submit_admin_passthru(hdl, &cmd, NULL); + } if (err) return err; @@ -610,7 +620,7 @@ static int ilog_dump_telemetry(struct ilog *ilog, enum log_type ttype) return err; } -static int ilog_dump_identify_pages(struct ilog *ilog) +static int ilog_dump_identify_pages(struct nvme_transport_handle *hdl, struct ilog *ilog) { struct nvme_ns_list ns_attached_list; struct nvme_ns_list ns_allocated_list; @@ -637,10 +647,10 @@ static int ilog_dump_identify_pages(struct ilog *ilog) struct log allocated = {NVME_IDENTIFY_CNS_ALLOCATED_NS, "Allocated Namespace Data", NVME_IDENTIFY_DATA_SIZE, NULL}; - ilog_ensure_dump_id_ctrl(ilog); + ilog_ensure_dump_id_ctrl(hdl, ilog); for (int i = 0; i < ARRAY_SIZE(identify_base_list); i++) { - int err = ilog_dump_identify_page(ilog, &identify_base_list[i], 0); + int err = ilog_dump_identify_page(hdl, ilog, &identify_base_list[i], 0); if (err == 0) ilog->count++; @@ -648,7 +658,7 @@ static int ilog_dump_identify_pages(struct ilog *ilog) while (ns_attached_list.ns[j]) { for (int i = 0; i < ARRAY_SIZE(identify_ns_required_list); i++) { - int err = ilog_dump_identify_page(ilog, &identify_ns_required_list[i], + int err = ilog_dump_identify_page(hdl, ilog, &identify_ns_required_list[i], ns_attached_list.ns[j]); if (err == 0) @@ -659,7 +669,7 @@ static int ilog_dump_identify_pages(struct ilog *ilog) j = 0; while (ns_allocated_list.ns[j]) { - int err = ilog_dump_identify_page(ilog, &allocated, ns_allocated_list.ns[j]); + int err = ilog_dump_identify_page(hdl, ilog, &allocated, ns_allocated_list.ns[j]); if (err == 0) ilog->count++; @@ -669,7 +679,7 @@ static int ilog_dump_identify_pages(struct ilog *ilog) return 0; } -static int ilog_dump_log_page(struct ilog *ilog, struct log *lp, __u32 nsid) +static int ilog_dump_log_page(struct nvme_transport_handle *hdl, struct ilog *ilog, struct log *lp, __u32 nsid) { __u8 *buff = lp->buffer; _cleanup_free_ char *filename = NULL; @@ -682,7 +692,7 @@ static int ilog_dump_log_page(struct ilog *ilog, struct log *lp, __u32 nsid) if (!buff) return -ENOMEM; } - err = nvme_get_nsid_log(dev_fd(ilog->dev), 0, lp->id, 0, lp->buffer_size, buff); + err = nvme_get_nsid_log(hdl, 0, 0, lp->id, buff, lp->buffer_size); if (err) return err; @@ -692,7 +702,7 @@ static int ilog_dump_log_page(struct ilog *ilog, struct log *lp, __u32 nsid) return log_save(lp, ilog->cfg->out_dir, "log_pages", filename, buff, lp->buffer_size); } -static int ilog_dump_no_lsp_log_pages(struct ilog *ilog) +static int ilog_dump_no_lsp_log_pages(struct nvme_transport_handle *hdl, struct ilog *ilog) { struct lba_status_info { __u32 lslplen; @@ -740,7 +750,7 @@ static int ilog_dump_no_lsp_log_pages(struct ilog *ilog) log_page_base_list[i].desc = log_page_base_list[i].desc ? log_page_base_list[i].desc : nvme_log_to_string(log_page_base_list[i].id); - if (!ilog_dump_log_page(ilog, &log_page_base_list[i], 0)) + if (!ilog_dump_log_page(hdl, ilog, &log_page_base_list[i], 0)) ilog->count++; } @@ -755,29 +765,26 @@ static int ilog_dump_no_lsp_log_pages(struct ilog *ilog) log_page_dependent_list[i].desc = log_page_dependent_list[i].desc ? log_page_dependent_list[i].desc : nvme_log_to_string(log_page_dependent_list[i].id); - ilog_dump_log_page(ilog, &log_page_dependent_list[i], 0); + ilog_dump_log_page(hdl, ilog, &log_page_dependent_list[i], 0); } return 0; } -static int ilog_dump_pel(struct ilog *ilog) +static int ilog_dump_pel(struct nvme_transport_handle *hdl, struct ilog *ilog) { + _cleanup_free_ struct nvme_persistent_event_log *pevent = NULL; + _cleanup_huge_ struct nvme_mem_huge mh = {0}; + void *pevent_log_full; + size_t max_data_tx; struct log lp = { NVME_LOG_LID_PERSISTENT_EVENT, nvme_log_to_string(NVME_LOG_LID_PERSISTENT_EVENT) }; - void *pevent_log_full; int err; - struct nvme_get_log_args args; - size_t max_data_tx; - _cleanup_free_ struct nvme_persistent_event_log *pevent = NULL; - - _cleanup_huge_ struct nvme_mem_huge mh = {0}; - - err = nvme_get_log_persistent_event(dev_fd(ilog->dev), NVME_PEVENT_LOG_RELEASE_CTX, - sizeof(*pevent), pevent); + err = nvme_get_log_persistent_event(hdl, NVME_PEVENT_LOG_RELEASE_CTX, + pevent, sizeof(*pevent)); if (err) return err; @@ -786,8 +793,8 @@ static int ilog_dump_pel(struct ilog *ilog) if (!pevent) return -ENOMEM; - err = nvme_get_log_persistent_event(dev_fd(ilog->dev), NVME_PEVENT_LOG_EST_CTX_AND_READ, - sizeof(*pevent), pevent); + err = nvme_get_log_persistent_event(hdl, NVME_PEVENT_LOG_EST_CTX_AND_READ, + pevent, sizeof(*pevent)); if (err) return err; @@ -797,29 +804,12 @@ static int ilog_dump_pel(struct ilog *ilog) if (!pevent_log_full) return -ENOMEM; - err = nvme_get_log_persistent_event(dev_fd(ilog->dev), NVME_PEVENT_LOG_READ, - lp.buffer_size, pevent_log_full); - args = (struct nvme_get_log_args) { - .lpo = 0, - .result = NULL, - .log = pevent_log_full, - .args_size = sizeof(args), - .fd = dev_fd(ilog->dev), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_PERSISTENT_EVENT, - .len = lp.buffer_size, - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_PEVENT_LOG_READ, - .uuidx = NVME_UUID_NONE, - .rae = false, - .ot = false, - }; - + err = nvme_get_log_persistent_event(hdl, NVME_PEVENT_LOG_READ, + pevent_log_full, lp.buffer_size); max_data_tx = (1 << ilog->id_ctrl.mdts) * NVME_LOG_PAGE_PDU_SIZE; do { - err = nvme_get_log_page(dev_fd(ilog->dev), max_data_tx, &args); + err = nvme_get_log_persistent_event(hdl, NVME_PEVENT_LOG_READ, + pevent_log_full, lp.buffer_size); max_data_tx /= 2; } while (err == -EPERM && max_data_tx >= NVME_LOG_PAGE_PDU_SIZE); @@ -829,13 +819,13 @@ static int ilog_dump_pel(struct ilog *ilog) err = log_save(&lp, ilog->cfg->out_dir, "log_pages", "lid_0x0d_lsp_0x00_lsi_0x0000.bin", pevent_log_full, lp.buffer_size); - nvme_get_log_persistent_event(dev_fd(ilog->dev), NVME_PEVENT_LOG_RELEASE_CTX, - sizeof(*pevent), pevent); + nvme_get_log_persistent_event(hdl, NVME_PEVENT_LOG_RELEASE_CTX, + pevent, sizeof(*pevent)); return err; } -int solidigm_get_internal_log(int argc, char **argv, struct command *command, +int solidigm_get_internal_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { char sn_prefix[sizeof(((struct nvme_id_ctrl *)0)->sn)+1]; @@ -843,12 +833,12 @@ int solidigm_get_internal_log(int argc, char **argv, struct command *command, _cleanup_free_ char *full_folder = NULL; _cleanup_free_ char *unique_folder = NULL; _cleanup_free_ char *zip_name = NULL; - + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; char *initial_folder; char *output_path; struct ilog ilog = {0}; int err; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; enum log_type log_type = ALL; char type_ALL[] = "ALL"; time_t current_time; @@ -871,10 +861,9 @@ int solidigm_get_internal_log(int argc, char **argv, struct command *command, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - ilog.dev = dev; ilog.cfg = &cfg; for (char *p = cfg.type; *p; ++p) @@ -909,7 +898,7 @@ int solidigm_get_internal_log(int argc, char **argv, struct command *command, initial_folder = cfg.out_dir; - err = get_serial_number(sn_prefix, dev_fd(dev)); + err = get_serial_number(sn_prefix, hdl); if (err) return err; @@ -930,50 +919,50 @@ int solidigm_get_internal_log(int argc, char **argv, struct command *command, /* Retrieve first logs that records actions to retrieve other logs */ if (log_type == ALL || log_type == HIT || log_type == EXTENDED) { - err = ilog_dump_telemetry(&ilog, log_type); + err = ilog_dump_telemetry(hdl, &ilog, log_type); if (err == 0) ilog.count++; else if (err < 0) perror("Error retrieving Host Initiated Telemetry"); } if (log_type == ALL || log_type == NLOG || log_type == EXTENDED) { - err = ilog_dump_nlogs(&ilog, -1); + err = ilog_dump_nlogs(hdl, &ilog, -1); if (err == 0) ilog.count++; else if (err < 0) perror("Error retrieving Nlog"); } if (log_type == ALL || log_type == CIT || log_type == EXTENDED) { - err = ilog_dump_telemetry(&ilog, CIT); + err = ilog_dump_telemetry(hdl, &ilog, CIT); if (err == 0) ilog.count++; else if (err < 0) perror("Error retrieving Controller Initiated Telemetry"); } if (log_type == ALL || log_type == ASSERTLOG || log_type == EXTENDED) { - err = ilog_dump_assert_logs(&ilog); + err = ilog_dump_assert_logs(hdl, &ilog); if (err == 0) ilog.count++; else if (err < 0) perror("Error retrieving Assert log"); } if (log_type == ALL || log_type == EVENTLOG || log_type == EXTENDED) { - err = ilog_dump_event_logs(&ilog); + err = ilog_dump_event_logs(hdl, &ilog); if (err == 0) ilog.count++; else if (err < 0) perror("Error retrieving Event log"); } if (log_type == ALL || log_type == EXTENDED) { - err = ilog_dump_identify_pages(&ilog); + err = ilog_dump_identify_pages(hdl, &ilog); if (err < 0) perror("Error retrieving Identify pages"); - err = ilog_dump_pel(&ilog); + err = ilog_dump_pel(hdl, &ilog); if (err < 0) perror("Error retrieving Persistent Event Log page"); - err = ilog_dump_no_lsp_log_pages(&ilog); + err = ilog_dump_no_lsp_log_pages(hdl, &ilog); if (err < 0) perror("Error retrieving no LSP Log pages"); } diff --git a/plugins/solidigm/solidigm-internal-logs.h b/plugins/solidigm/solidigm-internal-logs.h index 801af246c7..ed851763dc 100644 --- a/plugins/solidigm/solidigm-internal-logs.h +++ b/plugins/solidigm/solidigm-internal-logs.h @@ -5,4 +5,4 @@ * Author: leonardo.da.cunha@solidigm.com */ -int solidigm_get_internal_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); +int solidigm_get_internal_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); diff --git a/plugins/solidigm/solidigm-latency-tracking.c b/plugins/solidigm/solidigm-latency-tracking.c index 899075d7ac..e51db52f66 100644 --- a/plugins/solidigm/solidigm-latency-tracking.c +++ b/plugins/solidigm/solidigm-latency-tracking.c @@ -42,7 +42,7 @@ struct config { }; struct latency_tracker { - int fd; + struct nvme_transport_handle *hdl; __u8 uuid_index; struct config cfg; nvme_print_flags_t print_flags; @@ -271,20 +271,9 @@ static void latency_tracker_parse(struct latency_tracker *lt) static int latency_tracking_is_enable(struct latency_tracker *lt, __u32 *enabled) { - struct nvme_get_features_args args_get = { - .args_size = sizeof(args_get), - .fd = lt->fd, - .uuidx = lt->uuid_index, - .fid = LATENCY_TRACKING_FID, - .nsid = 0, - .sel = 0, - .cdw11 = 0, - .data_len = LATENCY_TRACKING_FID_DATA_LEN, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = enabled, - }; - return nvme_get_features(&args_get); + return nvme_get_features(lt->hdl, 0, LATENCY_TRACKING_FID, 0, 0, + lt->uuid_index, NULL, + LATENCY_TRACKING_FID_DATA_LEN, enabled); } static int latency_tracking_enable(struct latency_tracker *lt) @@ -300,23 +289,9 @@ static int latency_tracking_enable(struct latency_tracker *lt) return -EINVAL; } - struct nvme_set_features_args args_set = { - .args_size = sizeof(args_set), - .fd = lt->fd, - .uuidx = lt->uuid_index, - .fid = LATENCY_TRACKING_FID, - .nsid = 0, - .cdw11 = lt->cfg.enable, - .cdw12 = 0, - .save = 0, - .cdw15 = 0, - .data_len = LATENCY_TRACKING_FID_DATA_LEN, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - err = nvme_set_features(&args_set); + err = nvme_set_features(lt->hdl, 0, LATENCY_TRACKING_FID, 0, + lt->cfg.enable, 0, 0, lt->uuid_index, 0, NULL, + LATENCY_TRACKING_FID_DATA_LEN, &result); if (err > 0) { nvme_show_status(err); } else if (err < 0) { @@ -336,6 +311,7 @@ static int latency_tracking_enable(struct latency_tracker *lt) static int latency_tracker_get_log(struct latency_tracker *lt) { + struct nvme_passthru_cmd cmd; int err; if (lt->cfg.read && lt->cfg.write) { @@ -346,25 +322,17 @@ static int latency_tracker_get_log(struct latency_tracker *lt) if (!(lt->cfg.read || lt->cfg.write)) return 0; - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = <->stats, - .args_size = sizeof(args), - .fd = lt->fd, - .uuidx = lt->uuid_index, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = lt->cfg.write ? WRITE_LOG_ID : READ_LOG_ID, - .len = sizeof(lt->stats), - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = lt->cfg.type, - .rae = false, - .ot = false, - }; - - err = nvme_get_log(&args); + nvme_init_get_log(&cmd, NVME_NSID_ALL, + lt->cfg.write ? WRITE_LOG_ID : READ_LOG_ID, + NVME_CSI_NVM, <->stats, sizeof(lt->stats)); + cmd.cdw10 |= NVME_FIELD_ENCODE(lt->cfg.type, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + cmd.cdw14 |= NVME_FIELD_ENCODE(lt->uuid_index, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + err = nvme_get_log(lt->hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (err) return err; @@ -377,11 +345,12 @@ static int latency_tracker_get_log(struct latency_tracker *lt) return err; } -int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd, +int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get and Parse Solidigm Latency Tracking Statistics log."; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 enabled; int err; @@ -405,49 +374,40 @@ int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - lt.fd = dev_fd(dev); + lt.hdl = hdl; err = validate_output_format(lt.cfg.output_format, <.print_flags); if (err < 0) { fprintf(stderr, "Invalid output format '%s'\n", lt.cfg.output_format); - dev_close(dev); return -EINVAL; } if (lt.cfg.type > 0xf) { fprintf(stderr, "Invalid Log type value '%d'\n", lt.cfg.type); - dev_close(dev); return -EINVAL; } if (lt.cfg.type && !(lt.cfg.read || lt.cfg.write)) { fprintf(stderr, "Log type option valid only when retrieving statistics\n"); - dev_close(dev); return -EINVAL; } - sldgm_get_uuid_index(dev, <.uuid_index); + sldgm_get_uuid_index(hdl, <.uuid_index); err = latency_tracking_enable(<); - if (err) { - dev_close(dev); + if (err) return err; - } err = latency_tracker_get_log(<); - if (err) { - dev_close(dev); + if (err) return err; - } - if ((lt.cfg.read || lt.cfg.write || lt.cfg.enable || lt.cfg.disable)) { - dev_close(dev); + if ((lt.cfg.read || lt.cfg.write || lt.cfg.enable || lt.cfg.disable)) return 0; - } err = latency_tracking_is_enable(<, &enabled); if (!err) { @@ -467,8 +427,5 @@ int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd } else { fprintf(stderr, "Could not read feature id 0xE2.\n"); } - /* Redundant close() to make static code analysis happy */ - close(dev->direct.fd); - dev_close(dev); return err; } diff --git a/plugins/solidigm/solidigm-latency-tracking.h b/plugins/solidigm/solidigm-latency-tracking.h index 9a763a9067..e5329c6af0 100644 --- a/plugins/solidigm/solidigm-latency-tracking.h +++ b/plugins/solidigm/solidigm-latency-tracking.h @@ -5,5 +5,5 @@ * Author: leonardo.da.cunha@solidigm.com */ -int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd, +int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); diff --git a/plugins/solidigm/solidigm-log-page-dir.c b/plugins/solidigm/solidigm-log-page-dir.c index c3f08bb4c8..7590956300 100644 --- a/plugins/solidigm/solidigm-log-page-dir.c +++ b/plugins/solidigm/solidigm-log-page-dir.c @@ -40,29 +40,20 @@ static void init_lid_dir(struct lid_dir *lid_dir) } } -static int get_supported_log_pages_log(struct nvme_dev *dev, int uuid_index, +static int get_supported_log_pages_log(struct nvme_transport_handle *hdl, int uuid_index, struct nvme_supported_log_pages *supported) { - memset(supported, 0, sizeof(*supported)); - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = supported, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_SUPPORTED_LOG_PAGES, - .len = sizeof(*supported), - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = 0, - .uuidx = uuid_index, - .rae = false, - .ot = false, - }; + struct nvme_passthru_cmd cmd; - return nvme_get_log(&args); + memset(supported, 0, sizeof(*supported)); + nvme_init_get_log(&cmd, NVME_NSID_ALL, + NVME_LOG_LID_SUPPORTED_LOG_PAGES, NVME_CSI_NVM, + supported, sizeof(*supported)); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + return nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); } static struct lid_dir *get_standard_lids(struct nvme_supported_log_pages *supported) @@ -188,7 +179,7 @@ static void supported_log_pages_json(struct lid_dir *lid_dir[SOLIDIGM_MAX_UUID + printf("\n"); } -int solidigm_get_log_page_directory_log(int argc, char **argv, struct command *cmd, +int solidigm_get_log_page_directory_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const int NO_UUID_INDEX = 0; @@ -201,9 +192,10 @@ int solidigm_get_log_page_directory_log(int argc, char **argv, struct command *c OPT_END() }; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - int err = parse_and_open(&dev, argc, argv, description, options); + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + int err = parse_and_open(&ctx, &hdl, argc, argv, description, options); if (err) return err; @@ -211,13 +203,13 @@ int solidigm_get_log_page_directory_log(int argc, char **argv, struct command *c struct nvme_id_uuid_list uuid_list = { 0 }; struct nvme_supported_log_pages supported = { 0 }; - err = get_supported_log_pages_log(dev, NO_UUID_INDEX, &supported); + err = get_supported_log_pages_log(hdl, NO_UUID_INDEX, &supported); if (!err) { lid_dirs[NO_UUID_INDEX] = get_standard_lids(&supported); // Assume VU logs are the Solidigm log pages if UUID not supported. - if (nvme_identify_uuid(dev_fd(dev), &uuid_list)) { + if (!nvme_identify_uuid_list(hdl, &uuid_list)) { struct lid_dir *solidigm_lid_dir = get_solidigm_lids(&supported); // Transfer supported Solidigm lids to lid directory at UUID index 0 @@ -233,12 +225,12 @@ int solidigm_get_log_page_directory_log(int argc, char **argv, struct command *c ocp_find_uuid_index(&uuid_list, &ocp_idx); if (sldgm_idx && (sldgm_idx <= SOLIDIGM_MAX_UUID)) { - err = get_supported_log_pages_log(dev, sldgm_idx, &supported); + err = get_supported_log_pages_log(hdl, sldgm_idx, &supported); if (!err) lid_dirs[sldgm_idx] = get_solidigm_lids(&supported); } if (ocp_idx && (ocp_idx <= SOLIDIGM_MAX_UUID)) { - err = get_supported_log_pages_log(dev, ocp_idx, &supported); + err = get_supported_log_pages_log(hdl, ocp_idx, &supported); if (!err) lid_dirs[ocp_idx] = get_ocp_lids(&supported); } diff --git a/plugins/solidigm/solidigm-log-page-dir.h b/plugins/solidigm/solidigm-log-page-dir.h index 48777df7d8..d87eeeaca2 100644 --- a/plugins/solidigm/solidigm-log-page-dir.h +++ b/plugins/solidigm/solidigm-log-page-dir.h @@ -11,7 +11,7 @@ struct command; struct plugin; -int solidigm_get_log_page_directory_log(int argc, char **argv, struct command *cmd, +int solidigm_get_log_page_directory_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); #endif diff --git a/plugins/solidigm/solidigm-market-log.c b/plugins/solidigm/solidigm-market-log.c index e0934df5e5..38e29acdc2 100644 --- a/plugins/solidigm/solidigm-market-log.c +++ b/plugins/solidigm/solidigm-market-log.c @@ -23,12 +23,14 @@ #define MARKET_LOG_LID 0xDD #define MARKET_LOG_MAX_SIZE 512 -int sldgm_get_market_log(int argc, char **argv, struct command *command, +int sldgm_get_market_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get Solidigm Marketing Name log and show it."; const char *raw = "dump output in binary format"; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; char log[MARKET_LOG_MAX_SIZE]; int err; __u8 uuid_idx; @@ -40,31 +42,20 @@ int sldgm_get_market_log(int argc, char **argv, struct command *command, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - sldgm_get_uuid_index(dev, &uuid_idx); + sldgm_get_uuid_index(hdl, &uuid_idx); - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .uuidx = uuid_idx, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = MARKET_LOG_LID, - .len = sizeof(log), - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .rae = false, - .ot = false, - }; - - err = nvme_get_log(&args); + nvme_init_get_log(&cmd, NVME_NSID_ALL, + MARKET_LOG_LID, NVME_CSI_NVM, + log, sizeof(log)); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_idx, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + err = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (err) { nvme_show_status(err); return err; diff --git a/plugins/solidigm/solidigm-market-log.h b/plugins/solidigm/solidigm-market-log.h index 6f808c4ed3..3361e49ae1 100644 --- a/plugins/solidigm/solidigm-market-log.h +++ b/plugins/solidigm/solidigm-market-log.h @@ -5,4 +5,4 @@ * Author: hardeep.dhillon@solidigm.com */ -int sldgm_get_market_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); +int sldgm_get_market_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); diff --git a/plugins/solidigm/solidigm-nvme.c b/plugins/solidigm/solidigm-nvme.c index 8a7db07843..b8165db760 100644 --- a/plugins/solidigm/solidigm-nvme.c +++ b/plugins/solidigm/solidigm-nvme.c @@ -27,90 +27,90 @@ #include "plugins/ocp/ocp-smart-extended-log.h" #include "plugins/ocp/ocp-fw-activation-history.h" -static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return __id_ctrl(argc, argv, cmd, plugin, sldgm_id_ctrl); + return __id_ctrl(argc, argv, acmd, plugin, sldgm_id_ctrl); } -static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_additional_smart_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return solidigm_get_additional_smart_log(argc, argv, cmd, plugin); + return solidigm_get_additional_smart_log(argc, argv, acmd, plugin); } -static int get_internal_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_internal_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return solidigm_get_internal_log(argc, argv, cmd, plugin); + return solidigm_get_internal_log(argc, argv, acmd, plugin); } -static int get_garbage_collection_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_garbage_collection_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return solidigm_get_garbage_collection_log(argc, argv, cmd, plugin); + return solidigm_get_garbage_collection_log(argc, argv, acmd, plugin); } -static int get_latency_tracking_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_latency_tracking_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return solidigm_get_latency_tracking_log(argc, argv, cmd, plugin); + return solidigm_get_latency_tracking_log(argc, argv, acmd, plugin); } -static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_telemetry_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return solidigm_get_telemetry_log(argc, argv, cmd, plugin); + return solidigm_get_telemetry_log(argc, argv, acmd, plugin); } -static int clear_fw_update_history(int argc, char **argv, struct command *cmd, +static int clear_fw_update_history(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return ocp_clear_fw_update_history(argc, argv, cmd, plugin); + return ocp_clear_fw_update_history(argc, argv, acmd, plugin); } -static int clear_pcie_correctable_error_counters(int argc, char **argv, struct command *cmd, +static int clear_pcie_correctable_error_counters(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return ocp_clear_pcie_correctable_errors(argc, argv, cmd, plugin); + return ocp_clear_pcie_correctable_errors(argc, argv, acmd, plugin); } -static int smart_cloud(int argc, char **argv, struct command *cmd, +static int smart_cloud(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return ocp_smart_add_log(argc, argv, cmd, plugin); + return ocp_smart_add_log(argc, argv, acmd, plugin); } -static int fw_activation_history(int argc, char **argv, struct command *cmd, +static int fw_activation_history(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return ocp_fw_activation_history_log(argc, argv, cmd, plugin); + return ocp_fw_activation_history_log(argc, argv, acmd, plugin); } -static int get_log_page_directory_log(int argc, char **argv, struct command *cmd, +static int get_log_page_directory_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return solidigm_get_log_page_directory_log(argc, argv, cmd, plugin); + return solidigm_get_log_page_directory_log(argc, argv, acmd, plugin); } -static int get_market_log(int argc, char **argv, struct command *cmd, +static int get_market_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return sldgm_get_market_log(argc, argv, cmd, plugin); + return sldgm_get_market_log(argc, argv, acmd, plugin); } -static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_temp_stats_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return sldgm_get_temp_stats_log(argc, argv, cmd, plugin); + return sldgm_get_temp_stats_log(argc, argv, acmd, plugin); } -static int get_drive_info(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_drive_info(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return sldgm_get_drive_info(argc, argv, cmd, plugin); + return sldgm_get_drive_info(argc, argv, acmd, plugin); } -static int get_cloud_SSDplugin_version(int argc, char **argv, struct command *cmd, +static int get_cloud_SSDplugin_version(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return sldgm_ocp_version(argc, argv, cmd, plugin); + return sldgm_ocp_version(argc, argv, acmd, plugin); } -static int get_workload_tracker(int argc, char **argv, struct command *cmd, +static int get_workload_tracker(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return sldgm_get_workload_tracker(argc, argv, cmd, plugin); + return sldgm_get_workload_tracker(argc, argv, acmd, plugin); } diff --git a/plugins/solidigm/solidigm-ocp-version.c b/plugins/solidigm/solidigm-ocp-version.c index 4048cc1bd3..5904f87c6b 100644 --- a/plugins/solidigm/solidigm-ocp-version.c +++ b/plugins/solidigm/solidigm-ocp-version.c @@ -8,7 +8,7 @@ #include #include "nvme.h" -int sldgm_ocp_version(int argc, char **argv, struct command *cmd, struct plugin *plugin) +int sldgm_ocp_version(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Prints OCP extensions version of Solidigm plugin"; diff --git a/plugins/solidigm/solidigm-ocp-version.h b/plugins/solidigm/solidigm-ocp-version.h index d79452cbcc..8fbb333b44 100644 --- a/plugins/solidigm/solidigm-ocp-version.h +++ b/plugins/solidigm/solidigm-ocp-version.h @@ -5,4 +5,4 @@ * Author: leonardo.da.cunha@solidigm.com */ -int sldgm_ocp_version(int argc, char **argv, struct command *cmd, struct plugin *plugin); +int sldgm_ocp_version(int argc, char **argv, struct command *acmd, struct plugin *plugin); diff --git a/plugins/solidigm/solidigm-smart.c b/plugins/solidigm/solidigm-smart.c index 70869ce927..3edcbbaa27 100644 --- a/plugins/solidigm/solidigm-smart.c +++ b/plugins/solidigm/solidigm-smart.c @@ -222,14 +222,16 @@ static void vu_smart_log_show(struct vu_smart_log *payload, unsigned int nsid, c smart_log_item_print(&item[i]); } -int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +int solidigm_get_additional_smart_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get Solidigm vendor specific smart log (optionally, for the specified namespace), and show it."; const int solidigm_vu_smart_log_id = 0xCA; struct vu_smart_log smart_log_payload; nvme_print_flags_t flags; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; int err; __u8 uuid_index; @@ -250,47 +252,35 @@ int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; err = validate_output_format(cfg.output_format, &flags); if (err < 0) { fprintf(stderr, "Invalid output format '%s'\n", cfg.output_format); - dev_close(dev); return err; } - sldgm_get_uuid_index(dev, &uuid_index); - - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = &smart_log_payload, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = solidigm_vu_smart_log_id, - .len = sizeof(smart_log_payload), - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .uuidx = uuid_index, - .rae = false, - .ot = false, - }; + sldgm_get_uuid_index(hdl, &uuid_index); - err = nvme_get_log(&args); + nvme_init_get_log(&cmd, NVME_NSID_ALL, + solidigm_vu_smart_log_id, NVME_CSI_NVM, + &smart_log_payload, sizeof(smart_log_payload)); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + err = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (!err) { if (flags & JSON) vu_smart_log_show_json(&smart_log_payload, - cfg.namespace_id, dev->name); + cfg.namespace_id, nvme_transport_handle_get_name(hdl)); else if (flags & BINARY) d_raw((unsigned char *)&smart_log_payload, sizeof(smart_log_payload)); else vu_smart_log_show(&smart_log_payload, cfg.namespace_id, - dev->name, uuid_index); + nvme_transport_handle_get_name(hdl), uuid_index); } else if (err > 0) { nvme_show_status(err); } diff --git a/plugins/solidigm/solidigm-smart.h b/plugins/solidigm/solidigm-smart.h index e19ebe5170..0000240cae 100644 --- a/plugins/solidigm/solidigm-smart.h +++ b/plugins/solidigm/solidigm-smart.h @@ -5,4 +5,4 @@ * Author: leonardo.da.cunha@solidigm.com */ -int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); +int solidigm_get_additional_smart_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); diff --git a/plugins/solidigm/solidigm-telemetry.c b/plugins/solidigm/solidigm-telemetry.c index 24926e46d4..7f189c0cbf 100644 --- a/plugins/solidigm/solidigm-telemetry.c +++ b/plugins/solidigm/solidigm-telemetry.c @@ -60,7 +60,7 @@ static void cleanup_json_object(struct json_object **jobj_ptr) *jobj_ptr = NULL; } -int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +int solidigm_get_telemetry_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Parse Solidigm Telemetry log"; const char *hgen = "Controls when to generate new host initiated report. Default value '1' generates new host initiated report, value '0' causes retrieval of existing log."; @@ -69,9 +69,8 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc const char *cfile = "JSON configuration file"; const char *sfile = "binary file containing log dump"; bool has_binary_file = false; - - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ struct nvme_telemetry_log *tlog = NULL; __attribute__((cleanup(cleanup_json_object))) struct json_object *configuration = NULL; @@ -122,7 +121,7 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc } err = read_file2buffer(cfg.binary_file, (char **)&tlog, &tl.log_size); } else { - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); } if (err) { nvme_show_status(err); @@ -166,7 +165,7 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc size_t power2; __u8 mdts = 0; - err = nvme_get_telemetry_max(dev_fd(dev), NULL, &max_data_tx); + err = nvme_get_telemetry_max(hdl, NULL, &max_data_tx); if (err < 0) { SOLIDIGM_LOG_WARNING("identify_ctrl: %s", nvme_strerror(errno)); @@ -182,7 +181,7 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc mdts++; } - err = sldgm_dynamic_telemetry(dev_fd(dev), cfg.host_gen, cfg.ctrl_init, true, + err = sldgm_dynamic_telemetry(hdl, cfg.host_gen, cfg.ctrl_init, true, mdts, cfg.data_area, &tlog, &tl.log_size); if (err < 0) { SOLIDIGM_LOG_WARNING("get-telemetry-log: %s", diff --git a/plugins/solidigm/solidigm-telemetry.h b/plugins/solidigm/solidigm-telemetry.h index 971ee2acb0..3f62fae97c 100644 --- a/plugins/solidigm/solidigm-telemetry.h +++ b/plugins/solidigm/solidigm-telemetry.h @@ -5,4 +5,4 @@ * Author: leonardo.da.cunha@solidigm.com */ -int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); +int solidigm_get_telemetry_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); diff --git a/plugins/solidigm/solidigm-temp-stats.c b/plugins/solidigm/solidigm-temp-stats.c index 7f385db96b..d9d4df1d27 100644 --- a/plugins/solidigm/solidigm-temp-stats.c +++ b/plugins/solidigm/solidigm-temp-stats.c @@ -38,10 +38,12 @@ static void show_temp_stats(struct temp_stats *stats) printf("Estimated offset : %"PRIu64"\n", le64_to_cpu(stats->est_offset)); } -int sldgm_get_temp_stats_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +int sldgm_get_temp_stats_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; unsigned char buffer[4096] = {0}; - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + struct nvme_passthru_cmd cmd; __u8 uuid_idx; int err; @@ -60,34 +62,29 @@ int sldgm_get_temp_stats_log(int argc, char **argv, struct command *cmd, struct OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - sldgm_get_uuid_index(dev, &uuid_idx); + sldgm_get_uuid_index(hdl, &uuid_idx); - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = buffer, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .uuidx = uuid_idx, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = SLDGM_TEMP_STATS_LID, - .len = sizeof(buffer), - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_LSP_NONE, - .rae = false, - .ot = false, - }; - - err = nvme_get_log(&args); + nvme_init_get_log(&cmd, NVME_NSID_ALL, + SLDGM_TEMP_STATS_LID, NVME_CSI_NVM, + buffer, sizeof(buffer)); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_idx, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + err = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (err > 0) { - args.lid = SLDGM_LEGACY_TEMP_STATS_LID; - err = nvme_get_log(&args); + nvme_init_get_log(&cmd, NVME_NSID_ALL, + SLDGM_LEGACY_TEMP_STATS_LID, NVME_CSI_NVM, + buffer, sizeof(buffer)); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_idx, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + err = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (!err) { uint64_t *guid = (uint64_t *)&buffer[4080]; diff --git a/plugins/solidigm/solidigm-temp-stats.h b/plugins/solidigm/solidigm-temp-stats.h index 58d5a86801..bca59ff134 100644 --- a/plugins/solidigm/solidigm-temp-stats.h +++ b/plugins/solidigm/solidigm-temp-stats.h @@ -5,4 +5,4 @@ * Author: leonardo.da.cunha@solidigm.com */ -int sldgm_get_temp_stats_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); +int sldgm_get_temp_stats_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); diff --git a/plugins/solidigm/solidigm-util.c b/plugins/solidigm/solidigm-util.c index 8206ef8cf0..11b3ba1647 100644 --- a/plugins/solidigm/solidigm-util.c +++ b/plugins/solidigm/solidigm-util.c @@ -26,27 +26,31 @@ int sldgm_find_uuid_index(struct nvme_id_uuid_list *uuid_list, __u8 *index) return 0; } -int sldgm_get_uuid_index(struct nvme_dev *dev, __u8 *index) +int sldgm_get_uuid_index(struct nvme_transport_handle *hdl, __u8 *index) { struct nvme_id_uuid_list uuid_list; - int err = nvme_identify_uuid(dev_fd(dev), &uuid_list); + int err; *index = 0; + + err = nvme_identify_uuid_list(hdl, &uuid_list); if (err) return err; return sldgm_find_uuid_index(&uuid_list, index); } -int sldgm_dynamic_telemetry(int dev_fd, bool create, bool ctrl, bool log_page, __u8 mtds, - enum nvme_telemetry_da da, struct nvme_telemetry_log **log_buffer, +int sldgm_dynamic_telemetry(struct nvme_transport_handle *hdl, bool create, + bool ctrl, bool log_page, __u8 mtds, + enum nvme_telemetry_da da, + struct nvme_telemetry_log **log_buffer, size_t *log_buffer_size) { - int err; size_t max_data_tx = (1 << mtds) * NVME_LOG_PAGE_PDU_SIZE; + int err; do { - err = nvme_get_telemetry_log(dev_fd, create, ctrl, log_page, max_data_tx, da, + err = nvme_get_telemetry_log(hdl, create, ctrl, log_page, max_data_tx, da, log_buffer, log_buffer_size); max_data_tx /= 2; create = false; diff --git a/plugins/solidigm/solidigm-util.h b/plugins/solidigm/solidigm-util.h index 85adbf9a20..7ab27ac3da 100644 --- a/plugins/solidigm/solidigm-util.h +++ b/plugins/solidigm/solidigm-util.h @@ -8,7 +8,7 @@ #include "nvme.h" int sldgm_find_uuid_index(struct nvme_id_uuid_list *uuid_list, __u8 *index); -int sldgm_get_uuid_index(struct nvme_dev *dev, __u8 *index); -int sldgm_dynamic_telemetry(int dev_fd, bool create, bool ctrl, bool log_page, __u8 mtds, +int sldgm_get_uuid_index(struct nvme_transport_handle *hdl, __u8 *index); +int sldgm_dynamic_telemetry(struct nvme_transport_handle *hdl, bool create, bool ctrl, bool log_page, __u8 mtds, enum nvme_telemetry_da da, struct nvme_telemetry_log **log_buffer, size_t *log_buffer_size); diff --git a/plugins/solidigm/solidigm-workload-tracker.c b/plugins/solidigm/solidigm-workload-tracker.c index f2e3913a6b..3d07f1ec9f 100644 --- a/plugins/solidigm/solidigm-workload-tracker.c +++ b/plugins/solidigm/solidigm-workload-tracker.c @@ -196,7 +196,7 @@ struct workloadLog { // Full WL Log Structure #pragma pack(pop) struct wltracker { - int fd; + struct nvme_transport_handle *hdl; __u8 uuid_index; struct workloadLog workload_log; size_t poll_count; @@ -273,40 +273,28 @@ __u64 micros(void) int wltracker_config(struct wltracker *wlt, union WorkloadLogEnable *we) { - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = wlt->fd, - .fid = FID, - .cdw11 = we->dword, - .uuidx = wlt->uuid_index, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - }; - return nvme_set_features(&args); + return nvme_set_features(wlt->hdl, 0, FID, 0, we->dword, 0, 0, 0, + wlt->uuid_index, NULL, 0, NULL); } static int wltracker_show_newer_entries(struct wltracker *wlt) { struct workloadLog *log = &wlt->workload_log; - __u8 cnt; - __u8 content_group; + union WorkloadLogEnable workloadEnable; static __u64 last_timestamp_us; + struct nvme_passthru_cmd cmd; __u64 timestamp_us = 0; __u64 timestamp = 0; - union WorkloadLogEnable workloadEnable; - - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = log, - .args_size = sizeof(args), - .fd = wlt->fd, - .uuidx = wlt->uuid_index, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = LID, - .len = sizeof(*log), - }; - int err = nvme_get_log(&args); + __u8 content_group; + __u8 cnt; + int err; + nvme_init_get_log(&cmd, NVME_NSID_NONE, LID, NVME_CSI_NVM, + log, sizeof(*log)); + cmd.cdw14 |= NVME_FIELD_ENCODE(wlt->uuid_index, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + err = nvme_get_log(wlt->hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); if (err > 0) { nvme_show_status(err); return err; @@ -358,7 +346,7 @@ static int wltracker_show_newer_entries(struct wltracker *wlt) if (!err) { struct workloadLog tl; - err = nvme_get_log_simple(wlt->fd, LID, sizeof(tl), &tl); + err = nvme_get_log_simple(wlt->hdl, LID, &tl, sizeof(tl)); tle = tl.timestamp_lastEntry; } if (err) { @@ -496,17 +484,17 @@ static void join_fields(char *dest, struct field *fields) } } -int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struct plugin *plugin) +int sldgm_get_workload_tracker(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - struct wltracker wlt = {0}; - union WorkloadLogEnable we = {0}; - - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; const char *desc = "Real Time capture Workload Tracker samples"; const char *sample_interval = "Sample interval"; const char *run_time = "Limit runtime capture time in seconds"; const char *flush_frequency = "Samples (1 to 126) to wait for extracting data. Default 100 samples"; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct wltracker wlt = {0}; + union WorkloadLogEnable we = {0}; char type_options[80] = {0}; char sample_options[80] = {0}; __u64 stop_time_us; @@ -558,7 +546,7 @@ int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struc OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; @@ -567,7 +555,7 @@ int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struc return -1; } - wlt.fd = dev_fd(dev); + wlt.hdl = hdl; if ((cfg.flush_frequency < 1) || (cfg.flush_frequency > MAX_WORKLOAD_LOG_ENTRIES)) { nvme_show_error("Invalid number of samples: %s. Valid values: 1-%d", @@ -615,15 +603,8 @@ int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struc we.triggerEnable = true; we.triggerDelta = cfg.trigger_on_delta; we.triggerSynchronous = !cfg.trigger_on_latency; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = wlt.fd, - .fid = 0xf5, - .cdw11 = cfg.trigger_treshold, - .uuidx = wlt.uuid_index, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - }; - err = nvme_set_features(&args); + err = nvme_set_features(wlt.hdl, 0, 0xf5, 0, cfg.trigger_treshold, 0, + 0, wlt.uuid_index, 0, NULL, 0, NULL); if (err < 0) { nvme_show_error("Trigger Threshold set-feature: %s", nvme_strerror(errno)); return err; diff --git a/plugins/solidigm/solidigm-workload-tracker.h b/plugins/solidigm/solidigm-workload-tracker.h index d3ecc1623e..f48c7b5268 100644 --- a/plugins/solidigm/solidigm-workload-tracker.h +++ b/plugins/solidigm/solidigm-workload-tracker.h @@ -5,4 +5,4 @@ * Author: leonardo.da.cunha@solidigm.com */ -int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struct plugin *plugin); +int sldgm_get_workload_tracker(int argc, char **argv, struct command *acmd, struct plugin *plugin); diff --git a/plugins/ssstc/ssstc-nvme.c b/plugins/ssstc/ssstc-nvme.c index f90ad6054d..90571f7b1f 100644 --- a/plugins/ssstc/ssstc-nvme.c +++ b/plugins/ssstc/ssstc-nvme.c @@ -375,7 +375,7 @@ void show_ssstc_add_smart_log(struct nvme_additional_smart_log *smart, } static -int ssstc_get_add_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +int ssstc_get_add_smart_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = @@ -388,7 +388,8 @@ int ssstc_get_add_smart_log(int argc, char **argv, struct command *cmd, struct p #endif /* CONFIG_JSONC */ struct nvme_additional_smart_log smart_log_add; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; struct config { @@ -408,25 +409,25 @@ int ssstc_get_add_smart_log(int argc, char **argv, struct command *cmd, struct p OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = nvme_get_log_simple(dev_fd(dev), 0xca, sizeof(smart_log_add), - &smart_log_add); + err = nvme_get_log_simple(hdl, 0xca, &smart_log_add, sizeof(smart_log_add)); if (!err) { if (cfg.json) - show_ssstc_add_smart_log_jsn(&smart_log_add, cfg.namespace_id, - dev->name); + show_ssstc_add_smart_log_jsn( + &smart_log_add, cfg.namespace_id, + nvme_transport_handle_get_name(hdl)); else if (!cfg.raw_binary) - show_ssstc_add_smart_log(&smart_log_add, cfg.namespace_id, - dev->name); + show_ssstc_add_smart_log( + &smart_log_add, cfg.namespace_id, + nvme_transport_handle_get_name(hdl)); else d_raw((unsigned char *)&smart_log_add, sizeof(smart_log_add)); } else if (err > 0) { nvme_show_status(err); } - dev_close(dev); return err; } diff --git a/plugins/toshiba/toshiba-nvme.c b/plugins/toshiba/toshiba-nvme.c index 3ae1bc4096..6f427333d8 100644 --- a/plugins/toshiba/toshiba-nvme.c +++ b/plugins/toshiba/toshiba-nvme.c @@ -48,8 +48,8 @@ enum { CODE_1 = 0x10 }; - -static int nvme_sct_op(int fd, __u32 opcode, __u32 cdw10, __u32 cdw11, void *data, __u32 data_len) +static int nvme_sct_op(struct nvme_transport_handle *hdl, __u32 opcode, + __u32 cdw10, __u32 cdw11, void *data, __u32 data_len) { void *metadata = NULL; const __u32 cdw2 = 0; @@ -65,12 +65,12 @@ static int nvme_sct_op(int fd, __u32 opcode, __u32 cdw10, __u32 cdw11, void *dat const __u32 rsvd = 0; __u32 result; - return nvme_admin_passthru(fd, opcode, flags, rsvd, namespace_id, cdw2, cdw3, cdw10, cdw11, + return nvme_admin_passthru(hdl, opcode, flags, rsvd, namespace_id, cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, cdw14, cdw15, data_len, data, metadata_len, metadata, timeout, &result); } -static int nvme_get_sct_status(int fd, __u32 device_mask) +static int nvme_get_sct_status(struct nvme_transport_handle *hdl, __u32 device_mask) { int err; void *data = NULL; @@ -82,7 +82,7 @@ static int nvme_get_sct_status(int fd, __u32 device_mask) return -ENOMEM; memset(data, 0, data_len); - err = nvme_sct_op(fd, OP_SCT_STATUS, DW10_SCT_STATUS_COMMAND, DW11_SCT_STATUS_COMMAND, data, data_len); + err = nvme_sct_op(hdl, OP_SCT_STATUS, DW10_SCT_STATUS_COMMAND, DW11_SCT_STATUS_COMMAND, data, data_len); if (err) { fprintf(stderr, "%s: SCT status failed :%d\n", __func__, err); goto end; @@ -122,7 +122,7 @@ static int nvme_get_sct_status(int fd, __u32 device_mask) return err; } -static int nvme_sct_command_transfer_log(int fd, bool current) +static int nvme_sct_command_transfer_log(struct nvme_transport_handle *hdl, bool current) { int err; void *data = NULL; @@ -141,12 +141,13 @@ static int nvme_sct_command_transfer_log(int fd, bool current) memcpy(data, &action_code, sizeof(action_code)); memcpy(data + 2, &function_code, sizeof(function_code)); - err = nvme_sct_op(fd, OP_SCT_COMMAND_TRANSFER, DW10_SCT_COMMAND_TRANSFER, DW11_SCT_COMMAND_TRANSFER, data, data_len); + err = nvme_sct_op(hdl, OP_SCT_COMMAND_TRANSFER, DW10_SCT_COMMAND_TRANSFER, DW11_SCT_COMMAND_TRANSFER, data, data_len); free(data); return err; } -static int nvme_sct_data_transfer(int fd, void *data, size_t data_len, size_t offset) +static int nvme_sct_data_transfer(struct nvme_transport_handle *hdl, void *data, + size_t data_len, size_t offset) { __u32 dw10, dw11, lba_count = (data_len) / 512; @@ -160,7 +161,7 @@ static int nvme_sct_data_transfer(int fd, void *data, size_t data_len, size_t of dw10 = (offset << 16) | lba_count; dw11 = (offset >> 16); - return nvme_sct_op(fd, OP_SCT_DATA_TRANSFER, dw10, dw11, data, data_len); + return nvme_sct_op(hdl, OP_SCT_DATA_TRANSFER, dw10, dw11, data, data_len); } static int d_raw_to_fd(const unsigned char *buf, unsigned int len, int fd) @@ -204,7 +205,8 @@ static void progress_runner(float progress) fflush(stdout); } -static int nvme_get_internal_log(int fd, const char *const filename, bool current) +static int nvme_get_internal_log(struct nvme_transport_handle *hdl, + const char *const filename, bool current) { int err; int o_fd = -1; @@ -226,7 +228,7 @@ static int nvme_get_internal_log(int fd, const char *const filename, bool curren unsigned int j; float progress = 0.0; - err = nvme_sct_command_transfer_log(fd, current); + err = nvme_sct_command_transfer_log(hdl, current); if (err) { fprintf(stderr, "%s: SCT command transfer failed\n", __func__); goto end; @@ -239,7 +241,7 @@ static int nvme_get_internal_log(int fd, const char *const filename, bool curren memset(page_data, 0, max_pages * page_data_len); /* Read the header to get the last log page - offsets 8->11, 12->15, 16->19 */ - err = nvme_sct_data_transfer(fd, page_data, page_data_len, 0); + err = nvme_sct_data_transfer(hdl, page_data, page_data_len, 0); if (err) { fprintf(stderr, "%s: SCT data transfer failed, page 0\n", __func__); goto end; @@ -283,7 +285,7 @@ static int nvme_get_internal_log(int fd, const char *const filename, bool curren if (pages_chunk + i >= pages) pages_chunk = pages - i; - err = nvme_sct_data_transfer(fd, page_data, + err = nvme_sct_data_transfer(hdl, page_data, pages_chunk * page_data_len, i * page_sector_len); if (err) { @@ -312,7 +314,7 @@ static int nvme_get_internal_log(int fd, const char *const filename, bool curren progress = 1.0f; progress_runner(progress); fprintf(stdout, "\n"); - err = nvme_get_sct_status(fd, MASK_IGNORE); + err = nvme_get_sct_status(hdl, MASK_IGNORE); if (err) { fprintf(stderr, "%s: bad SCT status\n", __func__); goto end; @@ -324,14 +326,15 @@ static int nvme_get_internal_log(int fd, const char *const filename, bool curren return err; } -static int nvme_get_internal_log_file(int fd, const char *const filename, bool current) +static int nvme_get_internal_log_file(struct nvme_transport_handle *hdl, + const char *const filename, bool current) { int err; /* Check device supported */ - err = nvme_get_sct_status(fd, MASK_0 | MASK_1); + err = nvme_get_sct_status(hdl, MASK_0 | MASK_1); if (!err) - err = nvme_get_internal_log(fd, filename, current); + err = nvme_get_internal_log(hdl, filename, current); return err; } @@ -351,11 +354,12 @@ struct nvme_xdn_smart_log_c0 { __u8 resv[512 - NR_SMART_ITEMS_C0]; }; -static void default_show_vendor_log_c0(struct nvme_dev *dev, __u32 nsid, - struct nvme_xdn_smart_log_c0 *smart) +static void default_show_vendor_log_c0(struct nvme_transport_handle *hdl, + __u32 nsid, + struct nvme_xdn_smart_log_c0 *smart) { printf("Vendor Log Page Directory 0xC0 for NVME device:%s namespace-id:%x\n", - dev->name, nsid); + nvme_transport_handle_get_name(hdl), nsid); printf("Error Log : %u\n", smart->items[ERROR_LOG_C0]); printf("SMART Health Log : %u\n", smart->items[SMART_HEALTH_LOG_C0]); printf("Firmware Slot Info : %u\n", smart->items[FIRMWARE_SLOT_INFO_C0]); @@ -365,8 +369,9 @@ static void default_show_vendor_log_c0(struct nvme_dev *dev, __u32 nsid, printf("SMART Attributes : %u\n", smart->items[SMART_ATTRIBUTES_C0]); } -static int nvme_get_vendor_log(struct nvme_dev *dev, __u32 namespace_id, - int log_page, const char *const filename) +static int nvme_get_vendor_log(struct nvme_transport_handle *hdl, + __u32 namespace_id, int log_page, + const char *const filename) { int err; void *log = NULL; @@ -378,11 +383,11 @@ static int nvme_get_vendor_log(struct nvme_dev *dev, __u32 namespace_id, } /* Check device supported */ - err = nvme_get_sct_status(dev_fd(dev), MASK_0 | MASK_1); + err = nvme_get_sct_status(hdl, MASK_0 | MASK_1); if (err) goto end; - err = nvme_get_nsid_log(dev_fd(dev), false, log_page, namespace_id, - log_len, log); + err = nvme_get_nsid_log(hdl, namespace_id, false, log_page, + log, log_len); if (err) { fprintf(stderr, "%s: couldn't get log 0x%x\n", __func__, log_page); @@ -409,7 +414,7 @@ static int nvme_get_vendor_log(struct nvme_dev *dev, __u32 namespace_id, } } else { if (log_page == 0xc0) - default_show_vendor_log_c0(dev, namespace_id, log); + default_show_vendor_log_c0(hdl, namespace_id, log); else d(log, log_len, 16, 1); } @@ -418,13 +423,14 @@ static int nvme_get_vendor_log(struct nvme_dev *dev, __u32 namespace_id, return err; } -static int vendor_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int vendor_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { char *desc = "Get extended SMART information and show it."; const char *namespace = "(optional) desired namespace"; const char *output_file = "(optional) binary output filename"; const char *log = "(optional) log ID (0xC0, or 0xCA), default 0xCA"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; struct config { @@ -446,7 +452,7 @@ static int vendor_log(int argc, char **argv, struct command *cmd, struct plugin OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { fprintf(stderr, "%s: failed to parse arguments\n", __func__); return -EINVAL; @@ -458,23 +464,24 @@ static int vendor_log(int argc, char **argv, struct command *cmd, struct plugin goto end; } - err = nvme_get_vendor_log(dev, cfg.namespace_id, cfg.log, + err = nvme_get_vendor_log(hdl, cfg.namespace_id, cfg.log, cfg.output_file); if (err) fprintf(stderr, "%s: couldn't get vendor log 0x%x\n", __func__, cfg.log); end: if (err > 0) nvme_show_status(err); - dev_close(dev); + return err; } -static int internal_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int internal_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { char *desc = "Get internal status log and show it."; const char *output_file = "(optional) binary output filename"; const char *prev_log = "(optional) use previous log. Otherwise uses current log."; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int err; struct config { @@ -493,7 +500,7 @@ static int internal_log(int argc, char **argv, struct command *cmd, struct plugi OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { fprintf(stderr, "%s: failed to parse arguments\n", __func__); return -EINVAL; @@ -504,27 +511,27 @@ static int internal_log(int argc, char **argv, struct command *cmd, struct plugi else printf("Getting current log\n"); - err = nvme_get_internal_log_file(dev_fd(dev), cfg.output_file, + err = nvme_get_internal_log_file(hdl, cfg.output_file, !cfg.prev_log); if (err < 0) fprintf(stderr, "%s: couldn't get fw log\n", __func__); if (err > 0) nvme_show_status(err); - dev_close(dev); return err; } -static int clear_correctable_errors(int argc, char **argv, struct command *cmd, - struct plugin *plugin) +static int clear_correctable_errors(int argc, char **argv, struct command *acmd, + struct plugin *plugin) { char *desc = "Clear PCIe correctable error count."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; const __u32 namespace_id = 0xFFFFFFFF; const __u32 feature_id = 0xCA; const __u32 value = 1; /* Bit0 - reset clear PCIe correctable count */ const __u32 cdw12 = 0; const bool save = false; - struct nvme_dev *dev; __u32 result; int err; @@ -532,39 +539,25 @@ static int clear_correctable_errors(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { fprintf(stderr, "%s: failed to parse arguments\n", __func__); return -EINVAL; } /* Check device supported */ - err = nvme_get_sct_status(dev_fd(dev), MASK_0 | MASK_1); + err = nvme_get_sct_status(hdl, MASK_0 | MASK_1); if (err) goto end; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = feature_id, - .nsid = namespace_id, - .cdw11 = value, - .cdw12 = cdw12, - .save = save, - .uuidx = 0, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); + err = nvme_set_features(hdl, namespace_id, feature_id, save, value, cdw12, + 0, 0, 0, NULL, 0, &result); if (err) fprintf(stderr, "%s: couldn't clear PCIe correctable errors\n", __func__); end: if (err > 0) nvme_show_status(err); - dev_close(dev); + return err; } diff --git a/plugins/transcend/transcend-nvme.c b/plugins/transcend/transcend-nvme.c index 547fbf4ea9..f80be2b659 100644 --- a/plugins/transcend/transcend-nvme.c +++ b/plugins/transcend/transcend-nvme.c @@ -17,24 +17,25 @@ static const __u32 OP_BAD_BLOCK = 0xc2; static const __u32 DW10_BAD_BLOCK = 0x400; static const __u32 DW12_BAD_BLOCK = 0x5a; -static int getHealthValue(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int getHealthValue(int argc, char **argv, struct command *acmd, struct plugin *plugin) { struct nvme_smart_log smart_log; char *desc = "Get nvme health percentage."; int percent_used = 0, healthvalue = 0; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int result; OPT_ARGS(opts) = { OPT_END() }; - result = parse_and_open(&dev, argc, argv, desc, opts); + result = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (result) { printf("\nDevice not found\n"); return -1; } - result = nvme_get_log_smart(dev_fd(dev), 0xffffffff, false, &smart_log); + result = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log); if (!result) { printf("Transcend NVME heath value: "); percent_used = smart_log.percent_used; @@ -46,28 +47,29 @@ static int getHealthValue(int argc, char **argv, struct command *cmd, struct plu printf("%d%%\n", healthvalue); } } - dev_close(dev); + return result; } -static int getBadblock(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int getBadblock(int argc, char **argv, struct command *acmd, struct plugin *plugin) { char *desc = "Get nvme bad block number."; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd nvmecmd; + unsigned char data[1] = {0}; int result; OPT_ARGS(opts) = { OPT_END() }; - result = parse_and_open(&dev, argc, argv, desc, opts); + result = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (result) { printf("\nDevice not found\n"); return -1; } - unsigned char data[1] = {0}; - struct nvme_passthru_cmd nvmecmd; memset(&nvmecmd, 0, sizeof(nvmecmd)); nvmecmd.opcode = OP_BAD_BLOCK; @@ -75,12 +77,13 @@ 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(dev_fd(dev), &nvmecmd, NULL); + + result = nvme_submit_admin_passthru(hdl, &nvmecmd, NULL); if (!result) { int badblock = data[0]; printf("Transcend NVME badblock count: %d\n", badblock); } - dev_close(dev); + return result; } diff --git a/plugins/virtium/virtium-nvme.c b/plugins/virtium/virtium-nvme.c index 50b2a5433b..88ec40db2c 100644 --- a/plugins/virtium/virtium-nvme.c +++ b/plugins/virtium/virtium-nvme.c @@ -262,7 +262,9 @@ static void vt_process_string(char *str, const size_t size) } } -static int vt_add_entry_to_log(const int fd, const char *path, const struct vtview_save_log_settings *cfg) +static int vt_add_entry_to_log(struct nvme_transport_handle *hdl, + const char *path, + const struct vtview_save_log_settings *cfg) { struct vtview_smart_log_entry smart; const char *filename; @@ -277,26 +279,26 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi filename = cfg->output_file; smart.time_stamp = time(NULL); - ret = nvme_get_nsid(fd, &nsid); + ret = nvme_get_nsid(hdl, &nsid); if (ret < 0) { printf("Cannot read namespace-id\n"); return -1; } - ret = nvme_identify_ns(fd, nsid, &smart.raw_ns); + ret = nvme_identify_ns(hdl, nsid, &smart.raw_ns); if (ret) { printf("Cannot read namespace identify\n"); return -1; } - ret = nvme_identify_ctrl(fd, &smart.raw_ctrl); + ret = nvme_identify_ctrl(hdl, &smart.raw_ctrl); if (ret) { printf("Cannot read device identify controller\n"); return -1; } - ret = nvme_get_log_smart(fd, NVME_NSID_ALL, false, &smart.raw_smart); + ret = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart.raw_smart); if (ret) { printf("Cannot read device SMART log\n"); return -1; @@ -309,7 +311,9 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi return ret; } -static int vt_update_vtview_log_header(const int fd, const char *path, const struct vtview_save_log_settings *cfg) +static int +vt_update_vtview_log_header(struct nvme_transport_handle *hdl, const char *path, + const struct vtview_save_log_settings *cfg) { struct vtview_log_header header; const char *filename; @@ -342,13 +346,13 @@ static int vt_update_vtview_log_header(const int fd, const char *path, const str printf("Log file: %s\n", filename); header.time_stamp = time(NULL); - ret = nvme_identify_ctrl(fd, &header.raw_ctrl); + ret = nvme_identify_ctrl(hdl, &header.raw_ctrl); if (ret) { printf("Cannot read identify device\n"); return -1; } - ret = nvme_get_log_fw_slot(fd, false, &header.raw_fw); + ret = nvme_get_log_fw_slot(hdl, false, &header.raw_fw); if (ret) { printf("Cannot read device firmware log\n"); return -1; @@ -918,7 +922,9 @@ static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl) printf("\"}\n"); } -static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int vt_save_smart_to_vtview_log(int argc, char **argv, + struct command *command, + struct plugin *plugin) { int ret, err = 0; long total_time = 0; @@ -941,7 +947,8 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm const char *freq = "(optional) How often you want to log SMART data (0.25 = 15' , 0.5 = 30' , 1 = 1 hour, 2 = 2 hours, etc.). Default = 10 hours."; const char *output_file = "(optional) Name of the log file (give it a name that easy for you to remember what the test is). You can leave it blank too, we will take care it for you."; const char *test_name = "(optional) Name of the test you are doing. We use this as part of the name of the log file."; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct vtview_save_log_settings cfg = { .run_time_hrs = 20, @@ -968,7 +975,7 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm strcpy(path, argv[1]); } - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { printf("Error parse and open (err = %d)\n", err); return err; @@ -979,12 +986,9 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm printf("Running for %lf hour(s)\n", cfg.run_time_hrs); printf("Logging SMART data for every %lf hour(s)\n", cfg.log_record_frequency_hrs); - ret = vt_update_vtview_log_header(dev_fd(dev), path, &cfg); - if (ret) { - err = EINVAL; - dev_close(dev); - return err; - } + ret = vt_update_vtview_log_header(hdl, path, &cfg); + if (ret) + return ret; total_time = cfg.run_time_hrs * (float)HOUR_IN_SECONDS; freq_time = cfg.log_record_frequency_hrs * (float)HOUR_IN_SECONDS; @@ -1002,7 +1006,7 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm if (cur_time >= end_time) break; - ret = vt_add_entry_to_log(dev_fd(dev), path, &cfg); + ret = vt_add_entry_to_log(hdl, path, &cfg); if (ret) { printf("Cannot update driver log\n"); break; @@ -1014,33 +1018,32 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm fflush(stdout); } - dev_close(dev); return err; } -static int vt_show_identify(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int vt_show_identify(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - int ret, err = 0; - struct nvme_id_ctrl ctrl; - struct nvme_dev *dev; char *desc = "Parse identify data to json format\n\n" "Typical usages:\n\n" "virtium show-identify /dev/yourDevice\n"; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_id_ctrl ctrl; + int ret, err = 0; OPT_ARGS(opts) = { OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) { printf("Error parse and open (err = %d)\n", err); return err; } - ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); + ret = nvme_identify_ctrl(hdl, &ctrl); if (ret) { printf("Cannot read identify device\n"); - dev_close(dev); return -1; } @@ -1048,6 +1051,5 @@ static int vt_show_identify(int argc, char **argv, struct command *cmd, struct p vt_process_string(ctrl.mn, sizeof(ctrl.mn)); vt_parse_detail_identify(&ctrl); - dev_close(dev); return err; } diff --git a/plugins/wdc/wdc-nvme-cmds.h b/plugins/wdc/wdc-nvme-cmds.h index dc37a2da34..ac8dace8e9 100644 --- a/plugins/wdc/wdc-nvme-cmds.h +++ b/plugins/wdc/wdc-nvme-cmds.h @@ -106,7 +106,7 @@ int run_wdc_vs_device_waf(int argc, char **argv, struct plugin *plugin); int run_wdc_set_latency_monitor_feature(int argc, char **argv, - struct command *cmd, + struct command *command, struct plugin *plugin); int run_wdc_vs_temperature_stats(int argc, char **argv, @@ -117,12 +117,13 @@ int run_wdc_cu_smart_log(int argc, char **argv, struct command *command, struct plugin *plugin); -bool run_wdc_nvme_check_supported_log_page(nvme_root_t r, - struct nvme_dev *dev, +bool run_wdc_nvme_check_supported_log_page(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl, __u8 log_id, __u8 uuid_index); -__u32 run_wdc_get_fw_cust_id(nvme_root_t r, - struct nvme_dev *dev); +__u32 run_wdc_get_fw_cust_id(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl); -__u64 run_wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev); +__u64 run_wdc_get_drive_capabilities(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl); diff --git a/plugins/wdc/wdc-nvme.c b/plugins/wdc/wdc-nvme.c index 43bf793bdb..fd7bf11520 100644 --- a/plugins/wdc/wdc-nvme.c +++ b/plugins/wdc/wdc-nvme.c @@ -932,66 +932,66 @@ struct __packed feature_latency_monitor { __u8 reserved[4083]; }; -static int wdc_get_serial_name(struct nvme_dev *dev, char *file, size_t len, const char *suffix); +static int wdc_get_serial_name(struct nvme_transport_handle *hdl, char *file, size_t len, const char *suffix); static int wdc_create_log_file(const char *file, const __u8 *drive_log_data, __u32 drive_log_length); -static int wdc_do_clear_dump(struct nvme_dev *dev, __u8 opcode, __u32 cdw12); -static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode, __u32 data_len, __u32 cdw12, +static int wdc_do_clear_dump(struct nvme_transport_handle *hdl, __u8 opcode, __u32 cdw12); +static int wdc_do_dump(struct nvme_transport_handle *hdl, __u32 opcode, __u32 data_len, __u32 cdw12, const char *file, __u32 xfer_size); -static int wdc_do_crash_dump(struct nvme_dev *dev, char *file, int type); -static int wdc_crash_dump(struct nvme_dev *dev, const char *file, int type); -static int wdc_get_crash_dump(int argc, char **argv, struct command *command, +static int wdc_do_crash_dump(struct nvme_transport_handle *hdl, char *file, int type); +static int wdc_crash_dump(struct nvme_transport_handle *hdl, const char *file, int type); +static int wdc_get_crash_dump(int argc, char **argv, struct command *acmd, struct plugin *plugin); -static int wdc_do_drive_log(struct nvme_dev *dev, const char *file); -static int wdc_drive_log(int argc, char **argv, struct command *command, struct plugin *plugin); +static int wdc_do_drive_log(struct nvme_transport_handle *hdl, const char *file); +static int wdc_drive_log(int argc, char **argv, struct command *acmd, struct plugin *plugin); static const char *wdc_purge_mon_status_to_string(__u32 status); -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(nvme_root_t r, - struct nvme_dev *dev, +static int wdc_purge(int argc, char **argv, struct command *acmd, struct plugin *plugin); +static int wdc_purge_monitor(int argc, char **argv, struct command *acmd, struct plugin *plugin); +static bool wdc_nvme_check_supported_log_page(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl, __u8 log_id, __u8 uuid_index); -static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *command, +static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *acmd, struct plugin *plugin); -static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, char *dir, char *key); -static int wdc_drive_essentials(int argc, char **argv, struct command *command, +static int wdc_do_drive_essentials(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, char *dir, char *key); +static int wdc_drive_essentials(int argc, char **argv, struct command *acmd, struct plugin *plugin); -static int wdc_drive_status(int argc, char **argv, struct command *command, struct plugin *plugin); -static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, +static int wdc_drive_status(int argc, char **argv, struct command *acmd, struct plugin *plugin); +static int wdc_clear_assert_dump(int argc, char **argv, struct command *acmd, struct plugin *plugin); -static int wdc_drive_resize(int argc, char **argv, struct command *command, struct plugin *plugin); -static int wdc_do_drive_resize(struct nvme_dev *dev, uint64_t new_size); -static int wdc_namespace_resize(int argc, char **argv, struct command *command, +static int wdc_drive_resize(int argc, char **argv, struct command *acmd, struct plugin *plugin); +static int wdc_do_drive_resize(struct nvme_transport_handle *hdl, uint64_t new_size); +static int wdc_namespace_resize(int argc, char **argv, struct command *acmd, struct plugin *plugin); -static int wdc_do_namespace_resize(struct nvme_dev *dev, __u32 nsid, __u32 op_option); -static int wdc_reason_identifier(int argc, char **argv, struct command *command, +static int wdc_do_namespace_resize(struct nvme_transport_handle *hdl, __u32 nsid, __u32 op_option); +static int wdc_reason_identifier(int argc, char **argv, struct command *acmd, struct plugin *plugin); -static int wdc_do_get_reason_id(struct nvme_dev *dev, const char *file, int log_id); -static int wdc_save_reason_id(struct nvme_dev *dev, __u8 *rsn_ident, int size); -static int wdc_clear_reason_id(struct nvme_dev *dev); -static int wdc_log_page_directory(int argc, char **argv, struct command *command, +static int wdc_do_get_reason_id(struct nvme_transport_handle *hdl, const char *file, int log_id); +static int wdc_save_reason_id(struct nvme_transport_handle *hdl, __u8 *rsn_ident, int size); +static int wdc_clear_reason_id(struct nvme_transport_handle *hdl); +static int wdc_log_page_directory(int argc, char **argv, struct command *acmd, struct plugin *plugin); -static int wdc_do_drive_info(struct nvme_dev *dev, __u32 *result); -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, +static int wdc_do_drive_info(struct nvme_transport_handle *hdl, __u32 *result); +static int wdc_vs_drive_info(int argc, char **argv, struct command *acmd, struct plugin *plugin); +static int wdc_vs_temperature_stats(int argc, char **argv, struct command *acmd, struct plugin *plugin); -static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, struct nvme_dev *dev); -static int wdc_enc_get_nic_log(struct nvme_dev *dev, __u8 log_id, __u32 xfer_size, __u32 data_len, +static __u64 wdc_get_enc_drive_capabilities(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl); +static int wdc_enc_get_nic_log(struct nvme_transport_handle *hdl, __u8 log_id, __u32 xfer_size, __u32 data_len, FILE *out); -static int wdc_enc_submit_move_data(struct nvme_dev *dev, char *cmd, int len, int xfer_size, +static int wdc_enc_submit_move_data(struct nvme_transport_handle *hdl, char *cmd, int len, int xfer_size, FILE *out, int data_id, int cdw14, int cdw15); -static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev, __u8 log_id, +static bool get_dev_mgment_cbs_data(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, __u8 log_id, void **cbs_data); -static __u32 wdc_get_fw_cust_id(nvme_root_t r, struct nvme_dev *dev); +static __u32 wdc_get_fw_cust_id(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl); static int wdc_print_c0_cloud_attr_log(void *data, int fmt, - struct nvme_dev *dev); + struct nvme_transport_handle *hdl); static int wdc_print_c0_eol_log(void *data, int fmt); static void wdc_show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log, - struct nvme_dev *dev); + struct nvme_transport_handle *hdl); static void wdc_show_cloud_smart_log_json(struct ocp_cloud_smart_log *log); -static bool get_dev_mgment_data(nvme_root_t r, - struct nvme_dev *dev, +static bool get_dev_mgment_data(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl, void **data); static bool wdc_nvme_parse_dev_status_log_entry(void *log_data, __u32 *ret_data, @@ -1465,26 +1465,27 @@ static double calc_percent(uint64_t numerator, uint64_t denominator) (uint64_t)(((double)numerator / (double)denominator) * 100) : 0; } -static int wdc_get_pci_ids(nvme_root_t r, struct nvme_dev *dev, +static int wdc_get_pci_ids(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, uint32_t *device_id, uint32_t *vendor_id) { + const char *name = nvme_transport_handle_get_name(hdl); char vid[256], did[256], id[32]; nvme_ctrl_t c = NULL; nvme_ns_t n = NULL; int fd, ret; - c = nvme_scan_ctrl(r, dev->name); - if (c) { + ret = nvme_scan_ctrl(ctx, name, &c); + if (!ret) { 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(dev->name); - if (!n) { - fprintf(stderr, "Unable to find %s\n", dev->name); - return -1; + ret = nvme_scan_namespace(name, &n); + if (ret) { + fprintf(stderr, "Unable to find %s\n", name); + return ret; } snprintf(vid, sizeof(vid), "%s/device/device/vendor", @@ -1535,13 +1536,13 @@ static int wdc_get_pci_ids(nvme_root_t r, struct nvme_dev *dev, return 0; } -static int wdc_get_vendor_id(struct nvme_dev *dev, uint32_t *vendor_id) +static int wdc_get_vendor_id(struct nvme_transport_handle *hdl, uint32_t *vendor_id) { - int ret; struct nvme_id_ctrl ctrl; + int ret; memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); + ret = nvme_identify_ctrl(hdl, &ctrl); if (ret) { fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret); return -1; @@ -1625,13 +1626,13 @@ static bool wdc_check_power_of_2(int num) return num && (!(num & (num-1))); } -static int wdc_get_model_number(struct nvme_dev *dev, char *model) +static int wdc_get_model_number(struct nvme_transport_handle *hdl, char *model) { - int ret, i; struct nvme_id_ctrl ctrl; + int ret, i; memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); + ret = nvme_identify_ctrl(hdl, &ctrl); if (ret) { fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret); return -1; @@ -1647,16 +1648,16 @@ static int wdc_get_model_number(struct nvme_dev *dev, char *model) return ret; } -static bool wdc_check_device(nvme_root_t r, struct nvme_dev *dev) +static bool wdc_check_device(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl) { int ret; bool supported; uint32_t read_device_id = -1, read_vendor_id = -1; - ret = wdc_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(ctx, hdl, &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(dev, &read_vendor_id) < 0) + if (wdc_get_vendor_id(hdl, &read_vendor_id) < 0) return false; } @@ -1674,13 +1675,13 @@ static bool wdc_check_device(nvme_root_t r, struct nvme_dev *dev) return supported; } -static bool wdc_enc_check_model(struct nvme_dev *dev) +static bool wdc_enc_check_model(struct nvme_transport_handle *hdl) { int ret; bool supported; char model[NVME_ID_CTRL_MODEL_NUMBER_SIZE+1]; - ret = wdc_get_model_number(dev, model); + ret = wdc_get_model_number(hdl, model); if (ret < 0) return false; @@ -1694,22 +1695,22 @@ static bool wdc_enc_check_model(struct nvme_dev *dev) return supported; } -static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) +static __u64 wdc_get_drive_capabilities(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl) { int ret; uint32_t read_device_id = -1, read_vendor_id = -1; __u64 capabilities = 0; __u32 cust_id; - ret = wdc_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(ctx, hdl, &read_device_id, &read_vendor_id); if (ret < 0) { - if (wdc_get_vendor_id(dev, &read_vendor_id) < 0) + if (wdc_get_vendor_id(hdl, &read_vendor_id) < 0) return capabilities; } /* 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(r, dev); + capabilities = wdc_get_enc_drive_capabilities(ctx, hdl); return capabilities; } @@ -1728,12 +1729,12 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) WDC_DRIVE_CAP_PURGE); /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, 0)) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xC1 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_ADD_LOG_OPCODE, 0)) capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE; break; @@ -1751,12 +1752,12 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) 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(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, 0)) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_VU_SMART_LOG_OPCODE, 0)) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; break; @@ -1770,7 +1771,7 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) case WDC_NVME_SN560_DEV_ID_3: case WDC_NVME_SN660_DEV_ID: /* verify the 0xC0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, 0) == true) { capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE; @@ -1783,36 +1784,36 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) WDC_DRIVE_CAP_LOG_PAGE_DIR); /* verify the 0xC1 (OCP Error Recovery) log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_ERROR_REC_LOG_ID, 0)) capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE; /* verify the 0xC3 (OCP Latency Monitor) log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_LATENCY_MON_LOG_ID, 0)) capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE; /* verify the 0xC4 (OCP Device Capabilities) log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_DEV_CAP_LOG_ID, 0)) capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE; /* verify the 0xC5 (OCP Unsupported Requirements) log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_UNSUPPORTED_REQS_LOG_ID, 0)) capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE; /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, 0)) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_VU_SMART_LOG_OPCODE, 0)) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; - cust_id = wdc_get_fw_cust_id(r, dev); + cust_id = wdc_get_fw_cust_id(ctx, hdl); /* Can still determine some capabilities in this case, but log an error */ if (cust_id == WDC_INVALID_CUSTOMER_ID) fprintf(stderr, @@ -1832,7 +1833,7 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) case WDC_NVME_SN840_DEV_ID_1: case WDC_NVME_SN860_DEV_ID: /* verify the 0xC0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, 0)) capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE; fallthrough; @@ -1846,12 +1847,12 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) WDC_DRIVE_CAP_LOG_PAGE_DIR); /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, 0)) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_VU_SMART_LOG_OPCODE, 0)) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; break; @@ -1865,27 +1866,27 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) case WDC_NVME_SN655_DEV_ID_1: case WDC_NVME_SN550_DEV_ID: /* verify the 0xC0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, 0)) capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE; /* verify the 0xC1 (OCP Error Recovery) log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_ERROR_REC_LOG_ID, 0)) capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE; /* verify the 0xC3 (OCP Latency Monitor) log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_LATENCY_MON_LOG_ID, 0)) capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE; /* verify the 0xC4 (OCP Device Capabilities) log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_DEV_CAP_LOG_ID, 0)) capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE; /* verify the 0xC5 (OCP Unsupported Requirements) log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_UNSUPPORTED_REQS_LOG_ID, 0)) capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE; @@ -1895,7 +1896,7 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG | WDC_DRIVE_CAP_REASON_ID | WDC_DRIVE_CAP_LOG_PAGE_DIR); - cust_id = wdc_get_fw_cust_id(r, dev); + cust_id = wdc_get_fw_cust_id(ctx, hdl); /* Can still determine some capabilities in this case, but log an error */ if (cust_id == WDC_INVALID_CUSTOMER_ID) fprintf(stderr, @@ -2066,8 +2067,8 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) return capabilities; } -static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, - struct nvme_dev *dev) +static __u64 wdc_get_enc_drive_capabilities(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl) { int ret; uint32_t read_vendor_id; @@ -2080,7 +2081,7 @@ static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, memset(marketing_name, 0, 64); - ret = wdc_get_vendor_id(dev, &read_vendor_id); + ret = wdc_get_vendor_id(hdl, &read_vendor_id); if (ret < 0) return capabilities; @@ -2090,12 +2091,12 @@ static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, 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(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, 0) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xC1 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_ADD_LOG_OPCODE, 0) == true) capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE; break; @@ -2106,7 +2107,7 @@ static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, /* Find the WDC UUID index */ memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list)); - if (wdc_CheckUuidListSupport(dev, &uuid_list)) { + if (wdc_CheckUuidListSupport(hdl, &uuid_list)) { /* check for the Sandisk UUID first */ uuid_index = nvme_uuid_find(&uuid_list, SNDK_UUID); @@ -2122,7 +2123,7 @@ static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, uuid_index = 0; /* verify the 0xC2 Device Manageability log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, uuid_index) == false) { fprintf(stderr, "ERROR: SNDK: 0xC2 Log Page not supported, index: %d\n", @@ -2131,7 +2132,7 @@ static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, goto out; } - if (!get_dev_mgment_data(r, dev, &dev_mng_log)) { + if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) { fprintf(stderr, "ERROR: SNDK: 0xC2 Log Page not found\n"); ret = -1; goto out; @@ -2150,17 +2151,17 @@ static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, fprintf(stderr, "ERROR: SNDK: Get Marketing Name Failed\n"); /* verify the 0xC3 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_LATENCY_MON_LOG_ID, 0) == true) capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE; /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, 0) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_VU_SMART_LOG_OPCODE, 0) == true) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; @@ -2179,7 +2180,7 @@ static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, WDC_DRIVE_CAP_CLEAR_PCIE); /* if the 0xCB log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID, 0) == true) capabilities |= WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY; } @@ -2196,7 +2197,7 @@ static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, return capabilities; } -static int wdc_get_serial_name(struct nvme_dev *dev, char *file, size_t len, +static int wdc_get_serial_name(struct nvme_transport_handle *hdl, char *file, size_t len, const char *suffix) { int i; @@ -2210,7 +2211,7 @@ static int wdc_get_serial_name(struct nvme_dev *dev, char *file, size_t len, strncpy(orig, file, PATH_MAX - 1); memset(file, 0, len); memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); + ret = nvme_identify_ctrl(hdl, &ctrl); if (ret) { fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret); return -1; @@ -2533,14 +2534,15 @@ bool wdc_get_dev_mng_log_entry(__u32 log_length, __u32 entry_id, return valid_log; } -static bool get_dev_mgmt_log_page_data(struct nvme_dev *dev, void **log_data, +static bool get_dev_mgmt_log_page_data(struct nvme_transport_handle *hdl, void **log_data, __u8 uuid_ix) { - void *data; struct wdc_c2_log_page_header *hdr_ptr; + struct nvme_passthru_cmd cmd; + bool valid = false; __u32 length = 0; + void *data; int ret = 0; - bool valid = false; data = (__u8 *)malloc(sizeof(__u8) * WDC_C2_LOG_BUF_LEN); if (!data) { @@ -2551,24 +2553,13 @@ static bool get_dev_mgmt_log_page_data(struct nvme_dev *dev, void **log_data, memset(data, 0, sizeof(__u8) * WDC_C2_LOG_BUF_LEN); /* get the log page length */ - struct nvme_get_log_args args_len = { - .args_size = sizeof(args_len), - .fd = dev_fd(dev), - .lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, - .nsid = 0xFFFFFFFF, - .lpo = 0, - .lsp = NVME_LOG_LSP_NONE, - .lsi = 0, - .rae = false, - .uuidx = uuid_ix, - .csi = NVME_CSI_NVM, - .ot = false, - .len = WDC_C2_LOG_BUF_LEN, - .log = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - ret = nvme_get_log(&args_len); + nvme_init_get_log(&cmd, NVME_NSID_ALL, + WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, NVME_CSI_NVM, data, + WDC_C2_LOG_BUF_LEN); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + ret = nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); if (ret) { fprintf(stderr, "ERROR: WDC: Unable to get 0x%x Log Page with uuid %d, ret = 0x%x\n", @@ -2589,25 +2580,14 @@ static bool get_dev_mgmt_log_page_data(struct nvme_dev *dev, void **log_data, } /* get the log page data with the increased length */ - struct nvme_get_log_args args_data = { - .args_size = sizeof(args_data), - .fd = dev_fd(dev), - .lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, - .nsid = 0xFFFFFFFF, - .lpo = 0, - .lsp = NVME_LOG_LSP_NONE, - .lsi = 0, - .rae = false, - .uuidx = uuid_ix, - .csi = NVME_CSI_NVM, - .ot = false, - .len = length, - .log = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - ret = nvme_get_log(&args_data); - + nvme_init_get_log(&cmd, NVME_NSID_ALL, + WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, NVME_CSI_NVM, data, + length); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + ret = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (ret) { fprintf(stderr, "ERROR: WDC: Unable to read 0x%x Log with uuid %d, ret = 0x%x\n", @@ -2636,7 +2616,7 @@ static bool get_dev_mgmt_log_page_data(struct nvme_dev *dev, void **log_data, return valid; } -static bool get_dev_mgmt_log_page_lid_data(struct nvme_dev *dev, +static bool get_dev_mgmt_log_page_lid_data(struct nvme_transport_handle *hdl, void **cbs_data, __u8 lid, __u8 log_id, @@ -2645,6 +2625,7 @@ static bool get_dev_mgmt_log_page_lid_data(struct nvme_dev *dev, void *data; struct wdc_c2_log_page_header *hdr_ptr; struct wdc_c2_log_subpage_header *sph; + struct nvme_passthru_cmd cmd; __u32 length = 0; int ret = 0; bool found = false; @@ -2658,24 +2639,12 @@ static bool get_dev_mgmt_log_page_lid_data(struct nvme_dev *dev, memset(data, 0, sizeof(__u8) * WDC_C2_LOG_BUF_LEN); /* get the log page length */ - struct nvme_get_log_args args_len = { - .args_size = sizeof(args_len), - .fd = dev_fd(dev), - .lid = lid, - .nsid = 0xFFFFFFFF, - .lpo = 0, - .lsp = NVME_LOG_LSP_NONE, - .lsi = 0, - .rae = false, - .uuidx = uuid_ix, - .csi = NVME_CSI_NVM, - .ot = false, - .len = WDC_C2_LOG_BUF_LEN, - .log = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - ret = nvme_get_log(&args_len); + nvme_init_get_log(&cmd, NVME_NSID_ALL, lid, NVME_CSI_NVM, data, + WDC_C2_LOG_BUF_LEN); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + ret = nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); if (ret) { fprintf(stderr, "ERROR: WDC: Unable to get 0x%x Log Page length with uuid %d, ret = 0x%x\n", @@ -2696,25 +2665,13 @@ static bool get_dev_mgmt_log_page_lid_data(struct nvme_dev *dev, } /* get the log page data with the increased length */ - struct nvme_get_log_args args_data = { - .args_size = sizeof(args_data), - .fd = dev_fd(dev), - .lid = lid, - .nsid = 0xFFFFFFFF, - .lpo = 0, - .lsp = NVME_LOG_LSP_NONE, - .lsi = 0, - .rae = false, - .uuidx = uuid_ix, - .csi = NVME_CSI_NVM, - .ot = false, - .len = length, - .log = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - ret = nvme_get_log(&args_data); - + nvme_init_get_log(&cmd, NVME_NSID_ALL, lid, NVME_CSI_NVM, data, + length); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_ix, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + ret = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (ret) { fprintf(stderr, "ERROR: WDC: Unable to read 0x%x Log Page data with uuid %d, ret = 0x%x\n", @@ -2746,7 +2703,7 @@ static bool get_dev_mgmt_log_page_lid_data(struct nvme_dev *dev, return found; } -static bool get_dev_mgment_data(nvme_root_t r, struct nvme_dev *dev, +static bool get_dev_mgment_data(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, void **data) { bool found = false; @@ -2762,10 +2719,10 @@ static bool get_dev_mgment_data(nvme_root_t r, struct nvme_dev *dev, * initialized to 0 so the code can continue on without issue for * both cases: wdc_get_pci_ids successful or failed. */ - wdc_get_pci_ids(r, dev, &device_id, &vendor_id); + wdc_get_pci_ids(ctx, hdl, &device_id, &vendor_id); memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list)); - if (wdc_CheckUuidListSupport(dev, &uuid_list)) { + if (wdc_CheckUuidListSupport(hdl, &uuid_list)) { /* check for the Sandisk UUID first */ uuid_index = nvme_uuid_find(&uuid_list, SNDK_UUID); @@ -2780,7 +2737,7 @@ static bool get_dev_mgment_data(nvme_root_t r, struct nvme_dev *dev, } if (uuid_index >= 0) - found = get_dev_mgmt_log_page_data(dev, data, uuid_index); + found = get_dev_mgmt_log_page_data(hdl, data, uuid_index); else { fprintf(stderr, "%s: UUID lists are supported but a matching ", __func__); @@ -2794,7 +2751,7 @@ static bool get_dev_mgment_data(nvme_root_t r, struct nvme_dev *dev, */ uuid_index = 1; - found = get_dev_mgmt_log_page_data(dev, data, uuid_index); + found = get_dev_mgmt_log_page_data(hdl, data, uuid_index); if (!found) { /* not found with uuid = 1 try with uuid = 0 */ @@ -2802,18 +2759,18 @@ static bool get_dev_mgment_data(nvme_root_t r, struct nvme_dev *dev, fprintf(stderr, "Not found, requesting log page with uuid_index %d\n", uuid_index); - found = get_dev_mgmt_log_page_data(dev, data, uuid_index); + found = get_dev_mgmt_log_page_data(hdl, data, uuid_index); } } else { /* Default to uuid-index 0 for cases where UUID lists are not supported */ uuid_index = 0; - found = get_dev_mgmt_log_page_data(dev, data, uuid_index); + found = get_dev_mgmt_log_page_data(hdl, data, uuid_index); } return found; } -static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev, +static bool get_dev_mgment_cbs_data(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, __u8 log_id, void **cbs_data) { bool found = false; @@ -2830,12 +2787,12 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev, * initialized to 0 so the code can continue on without issue for * both cases: wdc_get_pci_ids successful or failed. */ - wdc_get_pci_ids(r, dev, &device_id, &vendor_id); + wdc_get_pci_ids(ctx, hdl, &device_id, &vendor_id); lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID; memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list)); - if (wdc_CheckUuidListSupport(dev, &uuid_list)) { + if (wdc_CheckUuidListSupport(hdl, &uuid_list)) { /* check for the Sandisk UUID first */ uuid_index = nvme_uuid_find(&uuid_list, SNDK_UUID); @@ -2850,7 +2807,7 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev, } if (uuid_index >= 0) - found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, + found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id, uuid_index); else { fprintf(stderr, "%s: UUID lists are supported but a matching ", @@ -2864,53 +2821,42 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev, * to determine which is returning the correct log page data. */ uuid_index = 1; - found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, log_id, uuid_index); + found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id, uuid_index); if (!found) { /* not found with uuid = 1 try with uuid = 0 */ uuid_index = 0; fprintf(stderr, "Not found, requesting log page with uuid_index %d\n", uuid_index); - found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, log_id, + found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id, uuid_index); } } else { /* Default to uuid-index 0 for cases where UUID lists are not supported */ uuid_index = 0; - found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, log_id, uuid_index); + found = get_dev_mgmt_log_page_lid_data(hdl, cbs_data, lid, log_id, uuid_index); } return found; } -static int wdc_get_supported_log_pages(struct nvme_dev *dev, +static int wdc_get_supported_log_pages(struct nvme_transport_handle *hdl, struct nvme_supported_log_pages *supported, int uuid_index) { - memset(supported, 0, sizeof(*supported)); - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = supported, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_SUPPORTED_LOG_PAGES, - .len = sizeof(*supported), - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = 0, - .uuidx = uuid_index, - .rae = false, - .ot = false, - }; + struct nvme_passthru_cmd cmd; - return nvme_get_log(&args); + memset(supported, 0, sizeof(*supported)); + nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_SUPPORTED_LOG_PAGES, + NVME_CSI_NVM, supported, sizeof(*supported)); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + return nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE, NULL); } -static bool wdc_nvme_check_supported_log_page(nvme_root_t r, - struct nvme_dev *dev, +static bool wdc_nvme_check_supported_log_page(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl, __u8 log_id, __u8 uuid_index) { @@ -2926,7 +2872,7 @@ static bool wdc_nvme_check_supported_log_page(nvme_root_t r, if (!supports) return -ENOMEM; - err = wdc_get_supported_log_pages(dev, + err = wdc_get_supported_log_pages(hdl, supports, uuid_index); @@ -2941,8 +2887,7 @@ static bool wdc_nvme_check_supported_log_page(nvme_root_t r, * check the WDC C2 log page */ if (!found) { - if (get_dev_mgment_cbs_data(r, - dev, + if (get_dev_mgment_cbs_data(ctx, hdl, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { if (cbs_data) { @@ -3016,12 +2961,12 @@ static bool wdc_nvme_parse_dev_status_log_str(void *log_data, return false; } -static bool wdc_nvme_get_dev_status_log_data(nvme_root_t r, struct nvme_dev *dev, __le32 *ret_data, +static bool wdc_nvme_get_dev_status_log_data(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, __le32 *ret_data, __u8 log_id) { __u32 *cbs_data = NULL; - if (get_dev_mgment_cbs_data(r, dev, log_id, (void *)&cbs_data)) { + if (get_dev_mgment_cbs_data(ctx, hdl, log_id, (void *)&cbs_data)) { if (cbs_data) { memcpy((void *)ret_data, (void *)cbs_data, 4); free(cbs_data); @@ -3034,7 +2979,7 @@ static bool wdc_nvme_get_dev_status_log_data(nvme_root_t r, struct nvme_dev *dev return false; } -static int wdc_do_clear_dump(struct nvme_dev *dev, __u8 opcode, __u32 cdw12) +static int wdc_do_clear_dump(struct nvme_transport_handle *hdl, __u8 opcode, __u32 cdw12) { int ret; struct nvme_passthru_cmd admin_cmd; @@ -3042,14 +2987,14 @@ static int wdc_do_clear_dump(struct nvme_dev *dev, __u8 opcode, __u32 cdw12) memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); admin_cmd.opcode = opcode; admin_cmd.cdw12 = cdw12; - ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (ret) fprintf(stdout, "ERROR: WDC: Crash dump erase failed\n"); nvme_show_status(ret); return ret; } -static __u32 wdc_dump_length(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, __u32 *dump_length) +static __u32 wdc_dump_length(struct nvme_transport_handle *link, __u32 opcode, __u32 cdw10, __u32 cdw12, __u32 *dump_length) { int ret; __u8 buf[WDC_NVME_LOG_SIZE_DATA_LEN] = {0}; @@ -3064,7 +3009,7 @@ static __u32 wdc_dump_length(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, __u admin_cmd.cdw10 = cdw10; admin_cmd.cdw12 = cdw12; - ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(link, &admin_cmd, NULL); if (ret) { l->log_size = 0; ret = -1; @@ -3080,7 +3025,7 @@ static __u32 wdc_dump_length(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, __u return ret; } -static __u32 wdc_dump_length_e6(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, struct wdc_e6_log_hdr *dump_hdr) +static __u32 wdc_dump_length_e6(struct nvme_transport_handle *hdl, __u32 opcode, __u32 cdw10, __u32 cdw12, struct wdc_e6_log_hdr *dump_hdr) { int ret; struct nvme_passthru_cmd admin_cmd; @@ -3092,7 +3037,7 @@ static __u32 wdc_dump_length_e6(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, admin_cmd.cdw10 = cdw10; admin_cmd.cdw12 = cdw12; - ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (ret) { fprintf(stderr, "ERROR: WDC: reading dump length failed\n"); nvme_show_status(ret); @@ -3101,7 +3046,7 @@ static __u32 wdc_dump_length_e6(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, return ret; } -static __u32 wdc_dump_dui_data(int fd, __u32 dataLen, __u32 offset, __u8 *dump_data, bool last_xfer) +static __u32 wdc_dump_dui_data(struct nvme_transport_handle *hdl, __u32 dataLen, __u32 offset, __u8 *dump_data, bool last_xfer) { int ret; struct nvme_passthru_cmd admin_cmd; @@ -3119,7 +3064,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, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (ret) { fprintf(stderr, "ERROR: WDC: reading DUI data failed\n"); nvme_show_status(ret); @@ -3128,7 +3073,7 @@ static __u32 wdc_dump_dui_data(int fd, __u32 dataLen, __u32 offset, __u8 *dump_d return ret; } -static __u32 wdc_dump_dui_data_v2(int fd, __u32 dataLen, __u64 offset, __u8 *dump_data, bool last_xfer) +static __u32 wdc_dump_dui_data_v2(struct nvme_transport_handle *hdl, __u32 dataLen, __u64 offset, __u8 *dump_data, bool last_xfer) { int ret; struct nvme_passthru_cmd admin_cmd; @@ -3150,7 +3095,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, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (ret) { fprintf(stderr, "ERROR: WDC: reading DUI data V2 failed\n"); nvme_show_status(ret); @@ -3159,7 +3104,7 @@ static __u32 wdc_dump_dui_data_v2(int fd, __u32 dataLen, __u64 offset, __u8 *dum return ret; } -static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode, __u32 data_len, +static int wdc_do_dump(struct nvme_transport_handle *hdl, __u32 opcode, __u32 data_len, __u32 cdw12, const char *file, __u32 xfer_size) { int ret = 0; @@ -3188,7 +3133,7 @@ static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode, __u32 data_len, admin_cmd.cdw13 = curr_data_offset; while (curr_data_offset < data_len) { - ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (ret) { nvme_show_status(ret); @@ -3218,7 +3163,7 @@ static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode, __u32 data_len, return ret; } -static int wdc_do_dump_e6(int fd, __u32 opcode, __u32 data_len, +static int wdc_do_dump_e6(struct nvme_transport_handle *hdl, __u32 opcode, __u32 data_len, __u32 cdw12, char *file, __u32 xfer_size, __u8 *log_hdr) { int ret = 0; @@ -3264,7 +3209,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, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (ret) { nvme_show_status(ret); fprintf(stderr, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n", @@ -3293,8 +3238,9 @@ static int wdc_do_dump_e6(int fd, __u32 opcode, __u32 data_len, return ret; } -static int wdc_do_cap_telemetry_log(struct nvme_dev *dev, const char *file, - __u32 bs, int type, int data_area) +static int wdc_do_cap_telemetry_log(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl, const char *file, + __u32 bs, int type, int data_area) { struct nvme_telemetry_log *log; size_t full_size = 0; @@ -3307,10 +3253,9 @@ static int wdc_do_cap_telemetry_log(struct nvme_dev *dev, const char *file, int data_written = 0, data_remaining = 0; struct nvme_id_ctrl ctrl; __u64 capabilities = 0; - nvme_root_t r; memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err) { fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", err); return err; @@ -3321,8 +3266,13 @@ static int wdc_do_cap_telemetry_log(struct nvme_dev *dev, const char *file, return -EINVAL; } - r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, dev); + err = nvme_scan_topology(ctx, NULL, NULL); + if (err) { + fprintf(stderr, "Failed to scan nvme subsystems\n"); + return err; + } + + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (type == WDC_TELEMETRY_TYPE_HOST) { host_gen = 1; @@ -3330,9 +3280,10 @@ static int wdc_do_cap_telemetry_log(struct nvme_dev *dev, const char *file, } else if (type == WDC_TELEMETRY_TYPE_CONTROLLER) { if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG) == WDC_DRIVE_CAP_INTERNAL_LOG) { /* Verify the Controller Initiated Option is enabled */ - err = nvme_get_features_data(dev_fd(dev), - WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, - 0, 4, buf, &result); + err = nvme_get_features(hdl, 0, + WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, + NVME_GET_FEATURES_SEL_CURRENT, 0, 0, + buf, 4, &result); if (!err) { if (!result) { /* enabled */ @@ -3369,13 +3320,13 @@ static int wdc_do_cap_telemetry_log(struct nvme_dev *dev, const char *file, } if (ctrl_init) - err = nvme_get_ctrl_telemetry(dev_fd(dev), true, &log, + err = nvme_get_ctrl_telemetry(hdl, true, &log, data_area, &full_size); else if (host_gen) - err = nvme_get_new_host_telemetry(dev_fd(dev), &log, + err = nvme_get_new_host_telemetry(hdl, &log, data_area, &full_size); else - err = nvme_get_host_telemetry(dev_fd(dev), &log, data_area, + err = nvme_get_host_telemetry(hdl, &log, data_area, &full_size); if (err < 0) { @@ -3423,7 +3374,7 @@ static int wdc_do_cap_telemetry_log(struct nvme_dev *dev, const char *file, return err; } -static int wdc_do_cap_diag(nvme_root_t r, struct nvme_dev *dev, char *file, +static int wdc_do_cap_diag(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, char *file, __u32 xfer_size, int type, int data_area) { int ret = -1; @@ -3440,7 +3391,7 @@ static int wdc_do_cap_diag(nvme_root_t r, struct nvme_dev *dev, char *file, memset(log_hdr, 0, e6_log_hdr_size); if (type == WDC_TELEMETRY_TYPE_NONE) { - ret = wdc_dump_length_e6(dev_fd(dev), + ret = wdc_dump_length_e6(hdl, WDC_NVME_CAP_DIAG_OPCODE, WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE>>2, 0x00, @@ -3456,7 +3407,7 @@ static int wdc_do_cap_diag(nvme_root_t r, struct nvme_dev *dev, char *file, if (!cap_diag_length) { fprintf(stderr, "INFO: WDC: Capture Diagnostics log is empty\n"); } else { - ret = wdc_do_dump_e6(dev_fd(dev), + ret = wdc_do_dump_e6(hdl, WDC_NVME_CAP_DIAG_OPCODE, cap_diag_length, (WDC_NVME_CAP_DIAG_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CAP_DIAG_CMD, @@ -3467,7 +3418,8 @@ static int wdc_do_cap_diag(nvme_root_t r, struct nvme_dev *dev, char *file, } else if ((type == WDC_TELEMETRY_TYPE_HOST) || (type == WDC_TELEMETRY_TYPE_CONTROLLER)) { /* Get the desired telemetry log page */ - ret = wdc_do_cap_telemetry_log(dev, file, xfer_size, type, data_area); + ret = wdc_do_cap_telemetry_log(ctx, hdl, file, xfer_size, + type, data_area); } else { fprintf(stderr, "%s: ERROR: Invalid type : %d\n", __func__, type); } @@ -3477,7 +3429,7 @@ static int wdc_do_cap_diag(nvme_root_t r, struct nvme_dev *dev, char *file, return ret; } -static int wdc_do_cap_dui_v1(int fd, char *file, __u32 xfer_size, int data_area, int verbose, +static int wdc_do_cap_dui_v1(struct nvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose, struct wdc_dui_log_hdr *log_hdr, __s64 *total_size) { __s32 log_size = 0; @@ -3557,7 +3509,7 @@ static int wdc_do_cap_dui_v1(int fd, char *file, __u32 xfer_size, int data_area, if (log_size <= xfer_size) last_xfer = true; - ret = wdc_dump_dui_data(fd, xfer_size, curr_data_offset, buffer_addr, last_xfer); + ret = wdc_dump_dui_data(hdl, xfer_size, curr_data_offset, buffer_addr, last_xfer); if (ret) { fprintf(stderr, "%s: ERROR: WDC: Get chunk %d, size = 0x%"PRIx64", offset = 0x%x, addr = %p\n", @@ -3587,7 +3539,7 @@ static int wdc_do_cap_dui_v1(int fd, char *file, __u32 xfer_size, int data_area, return ret; } -static int wdc_do_cap_dui_v2_v3(int fd, char *file, __u32 xfer_size, int data_area, int verbose, +static int wdc_do_cap_dui_v2_v3(struct nvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose, struct wdc_dui_log_hdr *log_hdr, __s64 *total_size, __u64 file_size, __u64 offset) { @@ -3700,7 +3652,7 @@ static int wdc_do_cap_dui_v2_v3(int fd, char *file, __u32 xfer_size, int data_ar if (log_size <= xfer_size_long) last_xfer = true; - ret = wdc_dump_dui_data_v2(fd, (__u32)xfer_size_long, curr_data_offset, buffer_addr, + ret = wdc_dump_dui_data_v2(hdl, (__u32)xfer_size_long, curr_data_offset, buffer_addr, last_xfer); if (ret) { fprintf(stderr, @@ -3732,7 +3684,7 @@ static int wdc_do_cap_dui_v2_v3(int fd, char *file, __u32 xfer_size, int data_ar return ret; } -static int wdc_do_cap_dui_v4(int fd, char *file, __u32 xfer_size, int data_area, int verbose, +static int wdc_do_cap_dui_v4(struct nvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose, struct wdc_dui_log_hdr *log_hdr, __s64 *total_size, __u64 file_size, __u64 offset) { @@ -3841,7 +3793,7 @@ static int wdc_do_cap_dui_v4(int fd, char *file, __u32 xfer_size, int data_area, if (log_size <= xfer_size_long) last_xfer = true; - ret = wdc_dump_dui_data_v2(fd, (__u32)xfer_size_long, curr_data_offset, buffer_addr, last_xfer); + ret = wdc_dump_dui_data_v2(hdl, (__u32)xfer_size_long, curr_data_offset, buffer_addr, last_xfer); if (ret) { fprintf(stderr, "%s: ERROR: WDC: Get chunk %d, size = 0x%"PRIx64", offset = 0x%"PRIx64", addr = %p\n", @@ -3872,7 +3824,7 @@ static int wdc_do_cap_dui_v4(int fd, char *file, __u32 xfer_size, int data_area, return ret; } -static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, int verbose, +static int wdc_do_cap_dui(struct nvme_transport_handle *hdl, char *file, __u32 xfer_size, int data_area, int verbose, __u64 file_size, __u64 offset) { int ret = 0; @@ -3890,7 +3842,7 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in memset(log_hdr, 0, dui_log_hdr_size); /* get the dui telemetry and log headers */ - ret = wdc_dump_dui_data(fd, WDC_NVME_CAP_DUI_HEADER_SIZE, 0x00, (__u8 *)log_hdr, last_xfer); + ret = wdc_dump_dui_data(hdl, WDC_NVME_CAP_DUI_HEADER_SIZE, 0x00, (__u8 *)log_hdr, last_xfer); if (ret) { fprintf(stderr, "%s: ERROR: WDC: Get DUI headers failed\n", __func__); fprintf(stderr, "%s: ERROR: WDC: ", __func__); @@ -3900,19 +3852,19 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in /* Check the Log Header version */ if ((log_hdr->hdr_version & 0xFF) == 0x00 || (log_hdr->hdr_version & 0xFF) == 0x01) { - ret = wdc_do_cap_dui_v1(fd, file, xfer_size, data_area, verbose, log_hdr, + ret = wdc_do_cap_dui_v1(hdl, file, xfer_size, data_area, verbose, log_hdr, &total_size); if (ret) goto out; } else if ((log_hdr->hdr_version & 0xFF) == 0x02 || (log_hdr->hdr_version & 0xFF) == 0x03) { /* Process Version 2 or 3 header */ - ret = wdc_do_cap_dui_v2_v3(fd, file, xfer_size, data_area, verbose, log_hdr, + ret = wdc_do_cap_dui_v2_v3(hdl, file, xfer_size, data_area, verbose, log_hdr, &total_size, file_size, offset); if (ret) goto out; } else if ((log_hdr->hdr_version & 0xFF) == 0x04) { - ret = wdc_do_cap_dui_v4(fd, file, xfer_size, data_area, verbose, log_hdr, + ret = wdc_do_cap_dui_v4(hdl, file, xfer_size, data_area, verbose, log_hdr, &total_size, file_size, offset); if (ret) goto out; @@ -3932,16 +3884,16 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in return ret; } -static int wdc_cap_diag(int argc, char **argv, struct command *command, +static int wdc_cap_diag(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; const char *desc = "Capture Diagnostics Log."; const char *file = "Output file pathname."; const char *size = "Data retrieval transfer size."; __u64 capabilities = 0; char f[PATH_MAX] = {0}; - struct nvme_dev *dev; __u32 xfer_size = 0; int ret = 0; @@ -3961,42 +3913,40 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret) + return ret; if (cfg.file) strncpy(f, cfg.file, PATH_MAX - 1); if (cfg.xfer_size) xfer_size = cfg.xfer_size; - ret = wdc_get_serial_name(dev, f, PATH_MAX, "cap_diag"); + ret = wdc_get_serial_name(hdl, f, PATH_MAX, "cap_diag"); if (ret) { fprintf(stderr, "ERROR: WDC: failed to generate file name\n"); - goto out; + return ret; } if (!cfg.file) { if (strlen(f) > PATH_MAX - 5) { fprintf(stderr, "ERROR: WDC: file name overflow\n"); - ret = -1; - goto out; + return -1; } strcat(f, ".bin"); } - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if ((capabilities & WDC_DRIVE_CAP_CAP_DIAG) == WDC_DRIVE_CAP_CAP_DIAG) - ret = wdc_do_cap_diag(r, dev, f, xfer_size, 0, 0); + ret = wdc_do_cap_diag(ctx, hdl, f, xfer_size, 0, 0); else fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); -out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_do_get_sn730_log_len(int fd, uint32_t *len_buf, uint32_t subopcode) +static int wdc_do_get_sn730_log_len(struct nvme_transport_handle *hdl, uint32_t *len_buf, uint32_t subopcode) { int ret; uint32_t *output = NULL; @@ -4016,14 +3966,14 @@ 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, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (!ret) *len_buf = *output; free(output); return ret; } -static int wdc_do_get_sn730_log(int fd, void *log_buf, uint32_t offset, uint32_t subopcode) +static int wdc_do_get_sn730_log(struct nvme_transport_handle *hdl, void *log_buf, uint32_t offset, uint32_t subopcode) { int ret; uint8_t *output = NULL; @@ -4042,13 +3992,13 @@ static int wdc_do_get_sn730_log(int fd, void *log_buf, uint32_t offset, uint32_t admin_cmd.cdw13 = offset; admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE / 4; - ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (!ret) memcpy(log_buf, output, SN730_LOG_CHUNK_SIZE); return ret; } -static int get_sn730_log_chunks(int fd, uint8_t *log_buf, uint32_t log_len, uint32_t subopcode) +static int get_sn730_log_chunks(struct nvme_transport_handle *hdl, uint8_t *log_buf, uint32_t log_len, uint32_t subopcode) { int ret = 0; uint8_t *chunk_buf = NULL; @@ -4064,7 +4014,7 @@ static int get_sn730_log_chunks(int fd, uint8_t *log_buf, uint32_t log_len, uint while (remaining > 0) { memset(chunk_buf, 0, SN730_LOG_CHUNK_SIZE); - ret = wdc_do_get_sn730_log(fd, chunk_buf, curr_offset, subopcode); + ret = wdc_do_get_sn730_log(hdl, chunk_buf, curr_offset, subopcode); if (!ret) { if (remaining >= SN730_LOG_CHUNK_SIZE) { memcpy(log_buf + (curr_offset * SN730_LOG_CHUNK_SIZE), @@ -4084,7 +4034,7 @@ static int get_sn730_log_chunks(int fd, uint8_t *log_buf, uint32_t log_len, uint return ret; } -static int wdc_do_sn730_get_and_tar(int fd, char *outputName) +static int wdc_do_sn730_get_and_tar(struct nvme_transport_handle *hdl, char *outputName) { int ret = 0; void *retPtr; @@ -4133,22 +4083,22 @@ static int wdc_do_sn730_get_and_tar(int fd, char *outputName) fprintf(stderr, "Stored log files in directory: %s\n", tarInfo->bufferFolderPath); } - ret = wdc_do_get_sn730_log_len(fd, &full_log_len, SN730_GET_FULL_LOG_LENGTH); + ret = wdc_do_get_sn730_log_len(hdl, &full_log_len, SN730_GET_FULL_LOG_LENGTH); if (ret) { nvme_show_status(ret); goto free_buf; } - ret = wdc_do_get_sn730_log_len(fd, &key_log_len, SN730_GET_KEY_LOG_LENGTH); + ret = wdc_do_get_sn730_log_len(hdl, &key_log_len, SN730_GET_KEY_LOG_LENGTH); if (ret) { nvme_show_status(ret); goto free_buf; } - ret = wdc_do_get_sn730_log_len(fd, &core_dump_log_len, SN730_GET_COREDUMP_LOG_LENGTH); + ret = wdc_do_get_sn730_log_len(hdl, &core_dump_log_len, SN730_GET_COREDUMP_LOG_LENGTH); if (ret) { nvme_show_status(ret); goto free_buf; } - ret = wdc_do_get_sn730_log_len(fd, &extended_log_len, SN730_GET_EXTENDED_LOG_LENGTH); + ret = wdc_do_get_sn730_log_len(hdl, &extended_log_len, SN730_GET_EXTENDED_LOG_LENGTH); if (ret) { nvme_show_status(ret); goto free_buf; @@ -4166,28 +4116,28 @@ static int wdc_do_sn730_get_and_tar(int fd, char *outputName) } /* Get the full log */ - ret = get_sn730_log_chunks(fd, full_log_buf, full_log_len, SN730_GET_FULL_LOG_SUBOPCODE); + ret = get_sn730_log_chunks(hdl, full_log_buf, full_log_len, SN730_GET_FULL_LOG_SUBOPCODE); if (ret) { nvme_show_status(ret); goto free_buf; } /* Get the key log */ - ret = get_sn730_log_chunks(fd, key_log_buf, key_log_len, SN730_GET_KEY_LOG_SUBOPCODE); + ret = get_sn730_log_chunks(hdl, key_log_buf, key_log_len, SN730_GET_KEY_LOG_SUBOPCODE); if (ret) { nvme_show_status(ret); goto free_buf; } /* Get the core dump log */ - ret = get_sn730_log_chunks(fd, core_dump_log_buf, core_dump_log_len, SN730_GET_CORE_LOG_SUBOPCODE); + ret = get_sn730_log_chunks(hdl, core_dump_log_buf, core_dump_log_len, SN730_GET_CORE_LOG_SUBOPCODE); if (ret) { nvme_show_status(ret); goto free_buf; } /* Get the extended log */ - ret = get_sn730_log_chunks(fd, extended_log_buf, extended_log_len, SN730_GET_EXTEND_LOG_SUBOPCODE); + ret = get_sn730_log_chunks(hdl, extended_log_buf, extended_log_len, SN730_GET_EXTEND_LOG_SUBOPCODE); if (ret) { nvme_show_status(ret); goto free_buf; @@ -4229,12 +4179,13 @@ static int wdc_do_sn730_get_and_tar(int fd, char *outputName) return ret; } -static int dump_internal_logs(struct nvme_dev *dev, const char *dir_name, int verbose) +static int dump_internal_logs(struct nvme_transport_handle *hdl, const char *dir_name, int verbose) { char file_path[PATH_MAX]; void *telemetry_log; const size_t bs = 512; struct nvme_telemetry_log *hdr; + struct nvme_passthru_cmd cmd; size_t full_size, offset = bs; int err, output; @@ -4258,25 +4209,12 @@ static int dump_internal_logs(struct nvme_dev *dev, const char *dir_name, int ve goto free_mem; } - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = hdr, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = NVME_LOG_LID_TELEMETRY_HOST, - .len = bs, - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = NVME_LOG_TELEM_HOST_LSP_CREATE, - .uuidx = NVME_UUID_NONE, - .rae = true, - .ot = false, - }; - - err = nvme_get_log(&args); + nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_TELEMETRY_HOST, + NVME_CSI_NVM, hdr, bs); + cmd.cdw10 |= NVME_FIELD_ENCODE(NVME_LOG_TELEM_HOST_LSP_CREATE, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + err = nvme_get_log(hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, NULL); if (err < 0) perror("get-telemetry-log"); else if (err > 0) { @@ -4294,10 +4232,10 @@ static int dump_internal_logs(struct nvme_dev *dev, const char *dir_name, int ve full_size = (le16_to_cpu(hdr->dalb3) * bs) + offset; while (offset != full_size) { - args.log = telemetry_log; - args.lpo = offset; - args.lsp = NVME_LOG_LSP_NONE; - err = nvme_get_log(&args); + nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_TELEMETRY_HOST, + NVME_CSI_NVM, telemetry_log, bs); + nvme_init_get_log_lpo(&cmd, offset); + err = nvme_get_log(hdl, &cmd, true, NVME_LOG_PAGE_PDU_SIZE, NULL); if (err < 0) { perror("get-telemetry-log"); break; @@ -4325,7 +4263,7 @@ static int dump_internal_logs(struct nvme_dev *dev, const char *dir_name, int ve return err; } -static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command, +static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Internal Firmware Log."; @@ -4342,8 +4280,8 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command char f[PATH_MAX] = {0}; char fb[PATH_MAX/2] = {0}; char fileSuffix[PATH_MAX] = {0}; - struct nvme_dev *dev; - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 xfer_size = 0; int telemetry_type = 0, telemetry_data_area = 0; UtilsTimeInfo timeInfo; @@ -4385,12 +4323,12 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); - if (!wdc_check_device(r, dev)) + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || !wdc_check_device(ctx, hdl)) goto out; if (cfg.xfer_size) { @@ -4400,7 +4338,7 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command goto out; } - ret = wdc_get_pci_ids(r, dev, &device_id, &read_vendor_id); + ret = wdc_get_pci_ids(ctx, hdl, &device_id, &read_vendor_id); if (!wdc_is_sn861(device_id)) { if (cfg.file) { @@ -4424,7 +4362,7 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command timeInfo.second); snprintf(fileSuffix, PATH_MAX, "_internal_fw_log_%s", (char *)timeStamp); - ret = wdc_get_serial_name(dev, f, PATH_MAX, fileSuffix); + ret = wdc_get_serial_name(hdl, f, PATH_MAX, fileSuffix); if (ret) { fprintf(stderr, "ERROR: WDC: failed to generate file name\n"); goto out; @@ -4477,7 +4415,7 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command timeInfo.second); snprintf(fileSuffix, PATH_MAX, "_internal_fw_log_%s", (char *)timeStamp); - ret = wdc_get_serial_name(dev, fb, PATH_MAX/2 - 7, fileSuffix); + ret = wdc_get_serial_name(hdl, fb, PATH_MAX/2 - 7, fileSuffix); if (ret) { fprintf(stderr, "ERROR: WDC: failed to generate file name\n"); goto out; @@ -4505,14 +4443,14 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command } } - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG) == WDC_DRIVE_CAP_INTERNAL_LOG) { if (!wdc_is_sn861(device_id)) { /* Set the default DA to 3 if not specified */ if (!telemetry_data_area) telemetry_data_area = 3; - ret = wdc_do_cap_diag(r, dev, f, xfer_size, + ret = wdc_do_cap_diag(ctx, hdl, f, xfer_size, telemetry_type, telemetry_data_area); } else { if (cfg.verbose) @@ -4524,7 +4462,7 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command goto out; } - ret = dump_internal_logs(dev, fb, cfg.verbose); + ret = dump_internal_logs(hdl, fb, cfg.verbose); if (ret < 0) perror("vs-internal-log"); @@ -4551,7 +4489,7 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command if (!telemetry_data_area) telemetry_data_area = 3; /* Set the default DA to 3 if not specified */ /* Get the desired telemetry log page */ - ret = wdc_do_cap_telemetry_log(dev, f, xfer_size, + ret = wdc_do_cap_telemetry_log(ctx, hdl, f, xfer_size, telemetry_type, telemetry_data_area); goto out; } else { @@ -4561,7 +4499,7 @@ 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; - ret = wdc_do_cap_dui(dev_fd(dev), f, xfer_size, + ret = wdc_do_cap_dui(hdl, f, xfer_size, cfg.data_area, cfg.verbose, cfg.file_size, cfg.offset); @@ -4574,29 +4512,27 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command if (!telemetry_data_area) telemetry_data_area = 3; /* Set the default DA to 3 if not specified */ /* Get the desired telemetry log page */ - ret = wdc_do_cap_telemetry_log(dev, f, xfer_size, + ret = wdc_do_cap_telemetry_log(ctx, hdl, f, xfer_size, telemetry_type, telemetry_data_area); goto out; } else { - ret = wdc_do_cap_dui(dev_fd(dev), f, xfer_size, + ret = wdc_do_cap_dui(hdl, f, xfer_size, WDC_NVME_DUI_MAX_DATA_AREA, cfg.verbose, 0, 0); goto out; } } if ((capabilities & WDC_SN730B_CAP_VUC_LOG) == WDC_SN730B_CAP_VUC_LOG) { - ret = wdc_do_sn730_get_and_tar(dev_fd(dev), f); + ret = wdc_do_sn730_get_and_tar(hdl, f); } else { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; } out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_do_crash_dump(struct nvme_dev *dev, char *file, int type) +static int wdc_do_crash_dump(struct nvme_transport_handle *hdl, char *file, int type) { int ret; __u32 crash_dump_length; @@ -4633,7 +4569,7 @@ static int wdc_do_crash_dump(struct nvme_dev *dev, char *file, int type) WDC_NVME_CLEAR_CRASH_DUMP_CMD); } - ret = wdc_dump_length(dev_fd(dev), + ret = wdc_dump_length(hdl, opcode, cdw10_size, cdw12_size, @@ -4654,7 +4590,7 @@ static int wdc_do_crash_dump(struct nvme_dev *dev, char *file, int type) else fprintf(stderr, "INFO: WDC: Crash dump is empty\n"); } else { - ret = wdc_do_dump(dev, + ret = wdc_do_dump(hdl, opcode, crash_dump_length, cdw12, @@ -4662,13 +4598,13 @@ static int wdc_do_crash_dump(struct nvme_dev *dev, char *file, int type) crash_dump_length); if (!ret) - ret = wdc_do_clear_dump(dev, WDC_NVME_CLEAR_DUMP_OPCODE, + ret = wdc_do_clear_dump(hdl, WDC_NVME_CLEAR_DUMP_OPCODE, cdw12_clear); } return ret; } -static int wdc_crash_dump(struct nvme_dev *dev, const char *file, int type) +static int wdc_crash_dump(struct nvme_transport_handle *hdl, const char *file, int type) { char f[PATH_MAX] = {0}; const char *dump_type; @@ -4682,22 +4618,22 @@ static int wdc_crash_dump(struct nvme_dev *dev, const char *file, int type) else dump_type = "_crash_dump"; - ret = wdc_get_serial_name(dev, f, PATH_MAX, dump_type); + ret = wdc_get_serial_name(hdl, f, PATH_MAX, dump_type); if (ret) fprintf(stderr, "ERROR: WDC: failed to generate file name\n"); else - ret = wdc_do_crash_dump(dev, f, type); + ret = wdc_do_crash_dump(hdl, f, type); return ret; } -static int wdc_do_drive_log(struct nvme_dev *dev, const char *file) +static int wdc_do_drive_log(struct nvme_transport_handle *hdl, const char *file) { int ret; __u8 *drive_log_data; __u32 drive_log_length; struct nvme_passthru_cmd admin_cmd; - ret = wdc_dump_length(dev_fd(dev), WDC_NVME_DRIVE_LOG_SIZE_OPCODE, + ret = wdc_dump_length(hdl, WDC_NVME_DRIVE_LOG_SIZE_OPCODE, WDC_NVME_DRIVE_LOG_SIZE_NDT, (WDC_NVME_DRIVE_LOG_SIZE_SUBCMD << WDC_NVME_SUBCMD_SHIFT | WDC_NVME_DRIVE_LOG_SIZE_CMD), @@ -4720,7 +4656,7 @@ static int wdc_do_drive_log(struct nvme_dev *dev, const 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(dev_fd(dev), &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); nvme_show_status(ret); if (!ret) ret = wdc_create_log_file(file, drive_log_data, drive_log_length); @@ -4728,15 +4664,15 @@ static int wdc_do_drive_log(struct nvme_dev *dev, const char *file) return ret; } -static int wdc_drive_log(int argc, char **argv, struct command *command, +static int wdc_drive_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Capture Drive Log."; const char *file = "Output file pathname."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; char f[PATH_MAX] = {0}; - struct nvme_dev *dev; int ret; - nvme_root_t r; __u64 capabilities = 0; struct config { char *file; @@ -4751,18 +4687,15 @@ static int wdc_drive_log(int argc, char **argv, struct command *command, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || !wdc_check_device(ctx, hdl)) + return ret; - if (!wdc_check_device(r, dev)) { - nvme_free_tree(r); - dev_close(dev); - return -1; - } - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_DRIVE_LOG)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); @@ -4770,25 +4703,23 @@ static int wdc_drive_log(int argc, char **argv, struct command *command, } else { if (cfg.file) strncpy(f, cfg.file, PATH_MAX - 1); - ret = wdc_get_serial_name(dev, f, PATH_MAX, "drive_log"); + ret = wdc_get_serial_name(hdl, f, PATH_MAX, "drive_log"); if (ret) fprintf(stderr, "ERROR: WDC: failed to generate file name\n"); else - ret = wdc_do_drive_log(dev, f); + ret = wdc_do_drive_log(hdl, f); } - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_get_crash_dump(int argc, char **argv, struct command *command, +static int wdc_get_crash_dump(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get Crash Dump."; const char *file = "Output file pathname."; __u64 capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret; struct config { @@ -4804,45 +4735,38 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); - - if (!wdc_check_device(r, dev)) { - nvme_free_tree(r); - dev_close(dev); - return -1; - - } + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || !wdc_check_device(ctx, hdl)) + return ret; - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_CRASH_DUMP)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; } else { - ret = wdc_crash_dump(dev, cfg.file, WDC_NVME_CRASH_DUMP_TYPE); + ret = wdc_crash_dump(hdl, cfg.file, WDC_NVME_CRASH_DUMP_TYPE); if (ret) fprintf(stderr, "ERROR: WDC: failed to read crash dump\n"); } - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_get_pfail_dump(int argc, char **argv, struct command *command, +static int wdc_get_pfail_dump(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get Pfail Crash Dump."; const char *file = "Output file pathname."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u64 capabilities = 0; - struct nvme_dev *dev; struct config { char *file; }; - nvme_root_t r; int ret; struct config cfg = { @@ -4854,29 +4778,23 @@ static int wdc_get_pfail_dump(int argc, char **argv, struct command *command, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); - - if (!wdc_check_device(r, dev)) { - nvme_free_tree(r); - dev_close(dev); - return -1; - } + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || !wdc_check_device(ctx, hdl)) + return ret; - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_PFAIL_DUMP)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; } else { - ret = wdc_crash_dump(dev, cfg.file, WDC_NVME_PFAIL_DUMP_TYPE); + ret = wdc_crash_dump(hdl, cfg.file, WDC_NVME_PFAIL_DUMP_TYPE); if (ret) fprintf(stderr, "ERROR: WDC: failed to read pfail crash dump\n"); } - nvme_free_tree(r); - dev_close(dev); return ret; } @@ -4893,9 +4811,9 @@ static void wdc_do_id_ctrl(__u8 *vs, struct json_object *root) printf("wdc vsn: %s\n", strlen(vsn) > 1 ? vsn : "NULL"); } -static int wdc_id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int wdc_id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - return __id_ctrl(argc, argv, cmd, plugin, wdc_do_id_ctrl); + return __id_ctrl(argc, argv, acmd, plugin, wdc_do_id_ctrl); } static const char *wdc_purge_mon_status_to_string(__u32 status) @@ -4930,30 +4848,26 @@ static int wdc_purge(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Send a Purge command."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct nvme_passthru_cmd admin_cmd; __u64 capabilities = 0; - struct nvme_dev *dev; char *err_str; - nvme_root_t r; int ret; OPT_ARGS(opts) = { OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); - - if (!wdc_check_device(r, dev)) { - nvme_free_tree(r); - dev_close(dev); - return -1; - } + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || !wdc_check_device(ctx, hdl)) + return ret; - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_PURGE)) { ret = -1; fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); @@ -4962,7 +4876,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(dev_fd(dev), &admin_cmd, + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (ret > 0) { switch (ret) { @@ -4980,8 +4894,6 @@ static int wdc_purge(int argc, char **argv, fprintf(stderr, "%s", err_str); nvme_show_status(ret); } - nvme_free_tree(r); - dev_close(dev); return ret; } @@ -4990,30 +4902,27 @@ static int wdc_purge_monitor(int argc, char **argv, { const char *desc = "Send a Purge Monitor command."; __u8 output[WDC_NVME_PURGE_MONITOR_DATA_LEN]; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; double progress_percent; struct nvme_passthru_cmd admin_cmd; struct wdc_nvme_purge_monitor_data *mon; - struct nvme_dev *dev; __u64 capabilities; - nvme_root_t r; int ret; OPT_ARGS(opts) = { OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); - if (!wdc_check_device(r, dev)) { - nvme_free_tree(r); - dev_close(dev); - return -1; - } + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || !wdc_check_device(ctx, hdl)) + return ret; - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_PURGE)) { ret = -1; fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); @@ -5026,7 +4935,7 @@ static int wdc_purge_monitor(int argc, char **argv, admin_cmd.cdw10 = WDC_NVME_PURGE_MONITOR_CMD_CDW10; admin_cmd.timeout_ms = WDC_NVME_PURGE_MONITOR_TIMEOUT; - ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (!ret) { mon = (struct wdc_nvme_purge_monitor_data *) output; @@ -5042,8 +4951,6 @@ static int wdc_purge_monitor(int argc, char **argv, nvme_show_status(ret); } - nvme_free_tree(r); - dev_close(dev); return ret; } @@ -5176,16 +5083,16 @@ static int wdc_print_log(struct wdc_ssd_perf_stats *perf, int fmt) return 0; } -static int wdc_print_latency_monitor_log_normal(struct nvme_dev *dev, +static int wdc_print_latency_monitor_log_normal(struct nvme_transport_handle *hdl, struct wdc_ssd_latency_monitor_log *log_data) { printf("Latency Monitor/C3 Log Page Data\n"); - printf(" Controller : %s\n", dev->name); + printf(" Controller : %s\n", nvme_transport_handle_get_name(hdl)); int err = -1, i, j; struct nvme_id_ctrl ctrl; char ts_buf[128]; - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (!err) { printf(" Serial Number: %-.*s\n", (int)sizeof(ctrl.sn), ctrl.sn); } else { @@ -5661,7 +5568,7 @@ static void wdc_print_fb_ca_log_json(struct wdc_ssd_ca_perf_stats *perf) json_free_object(root); } -static void wdc_print_bd_ca_log_normal(struct nvme_dev *dev, void *data) +static void wdc_print_bd_ca_log_normal(struct nvme_transport_handle *hdl, void *data) { struct wdc_bd_ca_log_format *bd_data = (struct wdc_bd_ca_log_format *)data; __u64 *raw; @@ -5680,7 +5587,7 @@ static void wdc_print_bd_ca_log_normal(struct nvme_dev *dev, void *data) switch (bd_data->field_id) { case 0x0: printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", - dev->name, WDC_DE_GLOBAL_NSID); + nvme_transport_handle_get_name(hdl), WDC_DE_GLOBAL_NSID); printf("key normalized raw\n"); printf("program_fail_count : %3"PRIu8"%% %"PRIu64"\n", bd_data->normalized_value, (uint64_t)rawSwapped); @@ -6374,15 +6281,15 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, json_free_object(root); } -static int nvme_get_print_ocp_cloud_smart_log(struct nvme_dev *dev, +static int nvme_get_print_ocp_cloud_smart_log(struct nvme_transport_handle *hdl, int uuid_index, __u32 namespace_id, int fmt) { + __u32 length = WDC_NVME_SMART_CLOUD_ATTR_LEN; struct ocp_cloud_smart_log *log_ptr = NULL; + struct nvme_passthru_cmd cmd; int ret, i; - __u32 length = WDC_NVME_SMART_CLOUD_ATTR_LEN; - int fd = dev_fd(dev); log_ptr = (struct ocp_cloud_smart_log *)malloc(sizeof(__u8) * length); if (!log_ptr) { @@ -6391,31 +6298,20 @@ static int nvme_get_print_ocp_cloud_smart_log(struct nvme_dev *dev, } if (namespace_id == NVME_NSID_ALL) { - ret = nvme_get_nsid(fd, &namespace_id); + ret = nvme_get_nsid(hdl, &namespace_id); if (ret < 0) namespace_id = NVME_NSID_ALL; } /* Get the 0xC0 log data */ - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = fd, - .lid = WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, - .nsid = namespace_id, - .lpo = 0, - .lsp = NVME_LOG_LSP_NONE, - .lsi = 0, - .rae = false, - .uuidx = uuid_index, - .csi = NVME_CSI_NVM, - .ot = false, - .len = length, - .log = log_ptr, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - ret = nvme_get_log(&args); - + nvme_init_get_log(&cmd, namespace_id, + WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, NVME_CSI_NVM, + log_ptr, length); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + ret = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (fmt == JSON) nvme_show_status(ret); @@ -6441,7 +6337,7 @@ static int nvme_get_print_ocp_cloud_smart_log(struct nvme_dev *dev, if (!ret) /* parse the data */ - wdc_print_c0_cloud_attr_log(log_ptr, fmt, dev); + wdc_print_c0_cloud_attr_log(log_ptr, fmt, hdl); } else { fprintf(stderr, "ERROR: WDC: Unable to read C0 Log Page data\n"); ret = -1; @@ -6451,15 +6347,15 @@ static int nvme_get_print_ocp_cloud_smart_log(struct nvme_dev *dev, return ret; } -static int nvme_get_print_c0_eol_log(struct nvme_dev *dev, +static int nvme_get_print_c0_eol_log(struct nvme_transport_handle *hdl, int uuid_index, __u32 namespace_id, int fmt) { + __u32 length = WDC_NVME_EOL_STATUS_LOG_LEN; + struct nvme_passthru_cmd cmd; void *log_ptr = NULL; int ret; - __u32 length = WDC_NVME_EOL_STATUS_LOG_LEN; - int fd = dev_fd(dev); log_ptr = (void *)malloc(sizeof(__u8) * length); if (!log_ptr) { @@ -6468,31 +6364,20 @@ static int nvme_get_print_c0_eol_log(struct nvme_dev *dev, } if (namespace_id == NVME_NSID_ALL) { - ret = nvme_get_nsid(fd, &namespace_id); + ret = nvme_get_nsid(hdl, &namespace_id); if (ret < 0) namespace_id = NVME_NSID_ALL; } /* Get the 0xC0 log data */ - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = fd, - .lid = WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, - .nsid = namespace_id, - .lpo = 0, - .lsp = NVME_LOG_LSP_NONE, - .lsi = 0, - .rae = false, - .uuidx = uuid_index, - .csi = NVME_CSI_NVM, - .ot = false, - .len = length, - .log = log_ptr, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - ret = nvme_get_log(&args); - + nvme_init_get_log(&cmd, namespace_id, + WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, NVME_CSI_NVM, + log_ptr, length); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + ret = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (fmt == JSON) nvme_show_status(ret); @@ -6509,10 +6394,11 @@ static int nvme_get_print_c0_eol_log(struct nvme_dev *dev, return ret; } -static int nvme_get_ext_smart_cloud_log(int fd, __u8 **data, int uuid_index, __u32 namespace_id) +static int nvme_get_ext_smart_cloud_log(struct nvme_transport_handle *hdl, __u8 **data, int uuid_index, __u32 namespace_id) { - int ret, i; + struct nvme_passthru_cmd cmd; __u8 *log_ptr = NULL; + int ret, i; log_ptr = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN); if (!log_ptr) { @@ -6521,25 +6407,14 @@ static int nvme_get_ext_smart_cloud_log(int fd, __u8 **data, int uuid_index, __u } /* Get the 0xC0 log data */ - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = fd, - .lid = WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, - .nsid = namespace_id, - .lpo = 0, - .lsp = NVME_LOG_LSP_NONE, - .lsi = 0, - .rae = false, - .uuidx = uuid_index, - .csi = NVME_CSI_NVM, - .ot = false, - .len = WDC_NVME_SMART_CLOUD_ATTR_LEN, - .log = log_ptr, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - ret = nvme_get_log(&args); - + nvme_init_get_log(&cmd, namespace_id, + WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, NVME_CSI_NVM, + log_ptr, WDC_NVME_SMART_CLOUD_ATTR_LEN); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + ret = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (!ret) { /* Verify GUID matches */ for (i = 0; i < WDC_C0_GUID_LENGTH; i++) { @@ -6567,10 +6442,11 @@ static int nvme_get_ext_smart_cloud_log(int fd, __u8 **data, int uuid_index, __u } -static int nvme_get_hw_rev_log(int fd, __u8 **data, int uuid_index, __u32 namespace_id) +static int nvme_get_hw_rev_log(struct nvme_transport_handle *hdl, __u8 **data, int uuid_index, __u32 namespace_id) { - int ret, i; struct wdc_nvme_hw_rev_log *log_ptr = NULL; + struct nvme_passthru_cmd cmd; + int ret, i; log_ptr = (struct wdc_nvme_hw_rev_log *)malloc(sizeof(__u8) * WDC_NVME_HW_REV_LOG_PAGE_LEN); if (!log_ptr) { @@ -6579,25 +6455,14 @@ static int nvme_get_hw_rev_log(int fd, __u8 **data, int uuid_index, __u32 namesp } /* Get the 0xC0 log data */ - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = fd, - .lid = WDC_NVME_GET_HW_REV_LOG_OPCODE, - .nsid = namespace_id, - .lpo = 0, - .lsp = NVME_LOG_LSP_NONE, - .lsi = 0, - .rae = false, - .uuidx = uuid_index, - .csi = NVME_CSI_NVM, - .ot = false, - .len = WDC_NVME_HW_REV_LOG_PAGE_LEN, - .log = log_ptr, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - ret = nvme_get_log(&args); - + nvme_init_get_log(&cmd, namespace_id, + WDC_NVME_GET_HW_REV_LOG_OPCODE, NVME_CSI_NVM, + log_ptr, WDC_NVME_HW_REV_LOG_PAGE_LEN); + cmd.cdw14 |= NVME_FIELD_ENCODE(uuid_index, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + ret = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (!ret) { /* Verify GUID matches */ for (i = 0; i < WDC_NVME_C6_GUID_LENGTH; i++) { @@ -7259,7 +7124,7 @@ static int wdc_print_ext_smart_cloud_log(void *data, int fmt) static int wdc_print_c0_cloud_attr_log(void *data, int fmt, - struct nvme_dev *dev) + struct nvme_transport_handle *hdl) { struct ocp_cloud_smart_log *log = (struct ocp_cloud_smart_log *)data; @@ -7273,7 +7138,7 @@ static int wdc_print_c0_cloud_attr_log(void *data, d_raw((unsigned char *)log, sizeof(struct ocp_cloud_smart_log)); break; case NORMAL: - wdc_show_cloud_smart_log_normal(log, dev); + wdc_show_cloud_smart_log_normal(log, hdl); break; case JSON: wdc_show_cloud_smart_log_json(log); @@ -7302,18 +7167,18 @@ static int wdc_print_c0_eol_log(void *data, int fmt) return 0; } -static int wdc_get_c0_log_page_sn_customer_id_0x100X(struct nvme_dev *dev, int uuid_index, +static int wdc_get_c0_log_page_sn_customer_id_0x100X(struct nvme_transport_handle *hdl, int uuid_index, char *format, __u32 namespace_id, int fmt) { int ret; if (!uuid_index) { - ret = nvme_get_print_ocp_cloud_smart_log(dev, + ret = nvme_get_print_ocp_cloud_smart_log(hdl, uuid_index, namespace_id, fmt); } else if (uuid_index == 1) { - ret = nvme_get_print_c0_eol_log(dev, + ret = nvme_get_print_c0_eol_log(hdl, uuid_index, namespace_id, fmt); @@ -7325,13 +7190,13 @@ static int wdc_get_c0_log_page_sn_customer_id_0x100X(struct nvme_dev *dev, int u return ret; } -static int wdc_get_c0_log_page_sn(nvme_root_t r, struct nvme_dev *dev, int uuid_index, char *format, +static int wdc_get_c0_log_page_sn(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, int uuid_index, char *format, __u32 namespace_id, int fmt) { int ret = 0; __u32 cust_id; - cust_id = wdc_get_fw_cust_id(r, dev); + cust_id = wdc_get_fw_cust_id(ctx, hdl); if (cust_id == WDC_INVALID_CUSTOMER_ID) { fprintf(stderr, "%s: ERROR: WDC: invalid customer id\n", __func__); return -1; @@ -7339,10 +7204,10 @@ static int wdc_get_c0_log_page_sn(nvme_root_t r, struct nvme_dev *dev, int uuid_ if ((cust_id == WDC_CUSTOMER_ID_0x1004) || (cust_id == WDC_CUSTOMER_ID_0x1008) || (cust_id == WDC_CUSTOMER_ID_0x1005)) { - ret = wdc_get_c0_log_page_sn_customer_id_0x100X(dev, uuid_index, format, + ret = wdc_get_c0_log_page_sn_customer_id_0x100X(hdl, uuid_index, format, namespace_id, fmt); } else { - ret = nvme_get_print_c0_eol_log(dev, + ret = nvme_get_print_c0_eol_log(hdl, 0, namespace_id, fmt); @@ -7351,7 +7216,7 @@ static int wdc_get_c0_log_page_sn(nvme_root_t r, struct nvme_dev *dev, int uuid_ return ret; } -static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format, int uuid_index, +static int wdc_get_c0_log_page(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, char *format, int uuid_index, __u32 namespace_id) { uint32_t device_id, read_vendor_id; @@ -7359,7 +7224,7 @@ static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format int ret; __u8 *data; - if (!wdc_check_device(r, dev)) + if (!wdc_check_device(ctx, hdl)) return -1; ret = validate_output_format(format, &fmt); if (ret < 0) { @@ -7367,7 +7232,7 @@ static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format return ret; } - ret = wdc_get_pci_ids(r, dev, &device_id, &read_vendor_id); + ret = wdc_get_pci_ids(ctx, hdl, &device_id, &read_vendor_id); switch (device_id) { case WDC_NVME_SN640_DEV_ID: @@ -7381,7 +7246,7 @@ static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format case WDC_NVME_SN560_DEV_ID_2: case WDC_NVME_SN560_DEV_ID_3: case WDC_NVME_SN550_DEV_ID: - ret = wdc_get_c0_log_page_sn(r, dev, uuid_index, format, namespace_id, fmt); + ret = wdc_get_c0_log_page_sn(ctx, hdl, uuid_index, format, namespace_id, fmt); break; case WDC_NVME_SN650_DEV_ID: case WDC_NVME_SN650_DEV_ID_1: @@ -7393,12 +7258,12 @@ static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format case WDC_NVME_SNTMP_DEV_ID: case WDC_NVME_SNTMP_DEV_ID_1: if (uuid_index == 0) { - ret = nvme_get_print_ocp_cloud_smart_log(dev, + ret = nvme_get_print_ocp_cloud_smart_log(hdl, uuid_index, namespace_id, fmt); } else { - ret = nvme_get_print_c0_eol_log(dev, + ret = nvme_get_print_c0_eol_log(hdl, uuid_index, namespace_id, fmt); @@ -7406,7 +7271,7 @@ static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format break; case WDC_NVME_ZN350_DEV_ID: case WDC_NVME_ZN350_DEV_ID_1: - ret = nvme_get_print_ocp_cloud_smart_log(dev, + ret = nvme_get_print_ocp_cloud_smart_log(hdl, 0, NVME_NSID_ALL, fmt); @@ -7414,7 +7279,7 @@ static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format case WDC_NVME_SN820CL_DEV_ID: /* Get the 0xC0 Extended Smart Cloud Attribute log data */ data = NULL; - ret = nvme_get_ext_smart_cloud_log(dev_fd(dev), &data, + ret = nvme_get_ext_smart_cloud_log(hdl, &data, uuid_index, namespace_id); if (strcmp(format, "json")) @@ -7440,7 +7305,7 @@ static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format return ret; } -static int wdc_print_latency_monitor_log(struct nvme_dev *dev, +static int wdc_print_latency_monitor_log(struct nvme_transport_handle *hdl, struct wdc_ssd_latency_monitor_log *log_data, int fmt) { @@ -7450,7 +7315,7 @@ static int wdc_print_latency_monitor_log(struct nvme_dev *dev, } switch (fmt) { case NORMAL: - wdc_print_latency_monitor_log_normal(dev, log_data); + wdc_print_latency_monitor_log_normal(hdl, log_data); break; case JSON: wdc_print_latency_monitor_log_json(log_data); @@ -7527,7 +7392,7 @@ static int wdc_print_fb_ca_log(struct wdc_ssd_ca_perf_stats *perf, int fmt) return 0; } -static int wdc_print_bd_ca_log(struct nvme_dev *dev, void *bd_data, int fmt) +static int wdc_print_bd_ca_log(struct nvme_transport_handle *hdl, void *bd_data, int fmt) { if (!bd_data) { fprintf(stderr, "ERROR: WDC: Invalid buffer to read data\n"); @@ -7535,7 +7400,7 @@ static int wdc_print_bd_ca_log(struct nvme_dev *dev, void *bd_data, int fmt) } switch (fmt) { case NORMAL: - wdc_print_bd_ca_log_normal(dev, bd_data); + wdc_print_bd_ca_log_normal(hdl, bd_data); break; case JSON: wdc_print_bd_ca_log_json(bd_data); @@ -7586,7 +7451,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(nvme_root_t r, struct nvme_dev *dev, char *format) +static int wdc_get_ca_log_page(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, char *format) { uint32_t read_device_id, read_vendor_id; struct wdc_ssd_ca_perf_stats *perf; @@ -7595,7 +7460,7 @@ static int wdc_get_ca_log_page(nvme_root_t r, struct nvme_dev *dev, char *format __u8 *data; int ret; - if (!wdc_check_device(r, dev)) + if (!wdc_check_device(ctx, hdl)) return -1; ret = validate_output_format(format, &fmt); if (ret < 0) { @@ -7604,20 +7469,20 @@ static int wdc_get_ca_log_page(nvme_root_t r, struct nvme_dev *dev, char *format } /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, 0) == false) { fprintf(stderr, "ERROR: WDC: 0xCA Log Page not supported\n"); return -1; } /* get the FW customer id */ - cust_id = wdc_get_fw_cust_id(r, dev); + cust_id = wdc_get_fw_cust_id(ctx, hdl); if (cust_id == WDC_INVALID_CUSTOMER_ID) { fprintf(stderr, "%s: ERROR: WDC: invalid customer id\n", __func__); return -1; } - ret = wdc_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(ctx, hdl, &read_device_id, &read_vendor_id); switch (read_device_id) { case WDC_NVME_SN200_DEV_ID: @@ -7630,9 +7495,9 @@ static int wdc_get_ca_log_page(nvme_root_t r, struct nvme_dev *dev, char *format memset(data, 0, sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN); - ret = nvme_get_log_simple(dev_fd(dev), + ret = nvme_get_log_simple(hdl, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, - WDC_FB_CA_LOG_BUF_LEN, data); + data, WDC_FB_CA_LOG_BUF_LEN); if (strcmp(format, "json")) nvme_show_status(ret); @@ -7666,9 +7531,9 @@ static int wdc_get_ca_log_page(nvme_root_t r, struct nvme_dev *dev, char *format memset(data, 0, sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN); - ret = nvme_get_log_simple(dev_fd(dev), + ret = nvme_get_log_simple(hdl, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, - WDC_FB_CA_LOG_BUF_LEN, data); + data, WDC_FB_CA_LOG_BUF_LEN); if (strcmp(format, "json")) nvme_show_status(ret); @@ -7689,15 +7554,15 @@ static int wdc_get_ca_log_page(nvme_root_t r, struct nvme_dev *dev, char *format } memset(data, 0, sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN); - ret = nvme_get_log_simple(dev_fd(dev), + ret = nvme_get_log_simple(hdl, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, - WDC_BD_CA_LOG_BUF_LEN, data); + data, WDC_BD_CA_LOG_BUF_LEN); if (strcmp(format, "json")) nvme_show_status(ret); if (!ret) { /* parse the data */ - ret = wdc_print_bd_ca_log(dev, data, fmt); + ret = wdc_print_bd_ca_log(hdl, data, fmt); } else { fprintf(stderr, "ERROR: WDC: Unable to read CA Log Page data\n"); ret = -1; @@ -7716,8 +7581,9 @@ static int wdc_get_ca_log_page(nvme_root_t r, struct nvme_dev *dev, char *format return ret; } -static int wdc_get_c1_log_page(nvme_root_t r, struct nvme_dev *dev, - char *format, uint8_t interval) +static int wdc_get_c1_log_page(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl, char *format, + uint8_t interval) { struct wdc_log_page_subpage_header *sph; struct wdc_ssd_perf_stats *perf; @@ -7730,7 +7596,7 @@ static int wdc_get_c1_log_page(nvme_root_t r, struct nvme_dev *dev, int i; int ret; - if (!wdc_check_device(r, dev)) + if (!wdc_check_device(ctx, hdl)) return -1; ret = validate_output_format(format, &fmt); @@ -7751,8 +7617,8 @@ static int wdc_get_c1_log_page(nvme_root_t r, struct nvme_dev *dev, } memset(data, 0, sizeof(__u8) * WDC_ADD_LOG_BUF_LEN); - ret = nvme_get_log_simple(dev_fd(dev), WDC_NVME_ADD_LOG_OPCODE, - WDC_ADD_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(hdl, WDC_NVME_ADD_LOG_OPCODE, + data, WDC_ADD_LOG_BUF_LEN); if (strcmp(format, "json")) nvme_show_status(ret); if (!ret) { @@ -7776,7 +7642,7 @@ static int wdc_get_c1_log_page(nvme_root_t r, struct nvme_dev *dev, return ret; } -static int wdc_get_c3_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) +static int wdc_get_c3_log_page(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, char *format) { struct wdc_ssd_latency_monitor_log *log_data; nvme_print_flags_t fmt; @@ -7784,7 +7650,7 @@ static int wdc_get_c3_log_page(nvme_root_t r, struct nvme_dev *dev, char *format int ret; int i; - if (!wdc_check_device(r, dev)) + if (!wdc_check_device(ctx, hdl)) return -1; ret = validate_output_format(format, &fmt); @@ -7800,8 +7666,8 @@ static int wdc_get_c3_log_page(nvme_root_t r, struct nvme_dev *dev, char *format } memset(data, 0, sizeof(__u8) * WDC_LATENCY_MON_LOG_BUF_LEN); - ret = nvme_get_log_simple(dev_fd(dev), WDC_LATENCY_MON_LOG_ID, - WDC_LATENCY_MON_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(hdl, WDC_LATENCY_MON_LOG_ID, + data, WDC_LATENCY_MON_LOG_BUF_LEN); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); @@ -7837,7 +7703,7 @@ static int wdc_get_c3_log_page(nvme_root_t r, struct nvme_dev *dev, char *format } /* parse the data */ - wdc_print_latency_monitor_log(dev, log_data, fmt); + wdc_print_latency_monitor_log(hdl, log_data, fmt); } else { fprintf(stderr, "ERROR: WDC: Unable to read C3 data from buffer\n"); } @@ -7848,7 +7714,7 @@ static int wdc_get_c3_log_page(nvme_root_t r, struct nvme_dev *dev, char *format } -static int wdc_get_ocp_c1_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) +static int wdc_get_ocp_c1_log_page(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, char *format) { struct wdc_ocp_c1_error_recovery_log *log_data; nvme_print_flags_t fmt; @@ -7856,7 +7722,7 @@ static int wdc_get_ocp_c1_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo int ret; int i; - if (!wdc_check_device(r, dev)) + if (!wdc_check_device(ctx, hdl)) return -1; ret = validate_output_format(format, &fmt); @@ -7872,8 +7738,8 @@ static int wdc_get_ocp_c1_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo } memset(data, 0, sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN); - ret = nvme_get_log_simple(dev_fd(dev), WDC_ERROR_REC_LOG_ID, - WDC_ERROR_REC_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(hdl, WDC_ERROR_REC_LOG_ID, + data, WDC_ERROR_REC_LOG_BUF_LEN); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); @@ -7920,7 +7786,7 @@ static int wdc_get_ocp_c1_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo return ret; } -static int wdc_get_ocp_c4_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) +static int wdc_get_ocp_c4_log_page(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, char *format) { struct wdc_ocp_C4_dev_cap_log *log_data; nvme_print_flags_t fmt; @@ -7928,7 +7794,7 @@ static int wdc_get_ocp_c4_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo int ret; int i; - if (!wdc_check_device(r, dev)) + if (!wdc_check_device(ctx, hdl)) return -1; ret = validate_output_format(format, &fmt); @@ -7944,8 +7810,8 @@ static int wdc_get_ocp_c4_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo } memset(data, 0, sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN); - ret = nvme_get_log_simple(dev_fd(dev), WDC_DEV_CAP_LOG_ID, - WDC_DEV_CAP_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(hdl, WDC_DEV_CAP_LOG_ID, + data, WDC_DEV_CAP_LOG_BUF_LEN); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); @@ -7990,7 +7856,7 @@ static int wdc_get_ocp_c4_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo return ret; } -static int wdc_get_ocp_c5_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) +static int wdc_get_ocp_c5_log_page(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, char *format) { struct wdc_ocp_C5_unsupported_reqs *log_data; nvme_print_flags_t fmt; @@ -7998,7 +7864,7 @@ static int wdc_get_ocp_c5_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo __u8 *data; int i; - if (!wdc_check_device(r, dev)) + if (!wdc_check_device(ctx, hdl)) return -1; ret = validate_output_format(format, &fmt); @@ -8014,8 +7880,8 @@ static int wdc_get_ocp_c5_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo } memset(data, 0, sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN); - ret = nvme_get_log_simple(dev_fd(dev), WDC_UNSUPPORTED_REQS_LOG_ID, - WDC_UNSUPPORTED_REQS_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(hdl, WDC_UNSUPPORTED_REQS_LOG_ID, + data, WDC_UNSUPPORTED_REQS_LOG_BUF_LEN); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); @@ -8062,14 +7928,14 @@ static int wdc_get_ocp_c5_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo return ret; } -static int wdc_get_d0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) +static int wdc_get_d0_log_page(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, char *format) { struct wdc_ssd_d0_smart_log *perf; nvme_print_flags_t fmt; int ret = 0; __u8 *data; - if (!wdc_check_device(r, dev)) + if (!wdc_check_device(ctx, hdl)) return -1; ret = validate_output_format(format, &fmt); @@ -8079,7 +7945,7 @@ static int wdc_get_d0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format } /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_VU_SMART_LOG_OPCODE, 0) == false) { fprintf(stderr, "ERROR: WDC: 0xD0 Log Page not supported\n"); return -1; @@ -8092,9 +7958,9 @@ static int wdc_get_d0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format } memset(data, 0, sizeof(__u8) * WDC_NVME_VU_SMART_LOG_LEN); - ret = nvme_get_log_simple(dev_fd(dev), + ret = nvme_get_log_simple(hdl, WDC_NVME_GET_VU_SMART_LOG_OPCODE, - WDC_NVME_VU_SMART_LOG_LEN, data); + data, WDC_NVME_VU_SMART_LOG_LEN); if (strcmp(format, "json")) nvme_show_status(ret); @@ -8286,12 +8152,13 @@ static void wdc_show_cloud_smart_log_json(struct ocp_cloud_smart_log *log) } static void wdc_show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log, - struct nvme_dev *dev) + struct nvme_transport_handle *hdl) { char buf[2 * sizeof(log->log_page_guid) + 3]; uint16_t smart_log_ver = (uint16_t)le16_to_cpu(log->log_page_version); - printf("SMART Cloud Attributes for NVMe device : %s\n", dev->name); + printf("SMART Cloud Attributes for NVMe device : %s\n", + nvme_transport_handle_get_name(hdl)); printf("Physical Media Units Written : %'.0Lf\n", le_to_float(log->physical_media_units_written, 16)); printf("Physical Media Units Read : %'.0Lf\n", @@ -8386,7 +8253,7 @@ static void wdc_show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log, printf("\n\n"); } -static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, +static int wdc_vs_smart_add_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve additional performance statistics."; @@ -8395,8 +8262,8 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, const char *log_page_mask = "Log Page Mask, comma separated list: 0xC0, 0xC1, 0xCA, 0xD0"; const char *namespace_id = "desired namespace id"; nvme_print_flags_t fmt; - struct nvme_dev *dev; - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = 0; int uuid_index = 0; int page_mask = 0, num, i; @@ -8429,11 +8296,14 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); + if (ret) + return ret; + + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret) return ret; - r = nvme_scan(NULL); if (!cfg.log_page_version) { uuid_index = 0; } else if (cfg.log_page_version == 1) { @@ -8470,9 +8340,9 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, if (!page_mask) fprintf(stderr, "ERROR: WDC: Unknown log page mask - %s\n", cfg.log_page_mask); - ret = wdc_get_pci_ids(r, dev, &device_id, &read_vendor_id); + ret = wdc_get_pci_ids(ctx, hdl, &device_id, &read_vendor_id); - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; @@ -8483,7 +8353,7 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, (page_mask & WDC_C0_PAGE_MASK)) { /* Get 0xC0 log page if possible. */ if (!wdc_is_sn861(device_id)) { - ret = wdc_get_c0_log_page(r, dev, cfg.output_format, + ret = wdc_get_c0_log_page(ctx, hdl, cfg.output_format, uuid_index, cfg.namespace_id); if (ret) fprintf(stderr, @@ -8496,7 +8366,7 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, goto out; } - ret = nvme_get_print_ocp_cloud_smart_log(dev, + ret = nvme_get_print_ocp_cloud_smart_log(hdl, 0, NVME_NSID_ALL, fmt); @@ -8506,14 +8376,14 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, (page_mask & WDC_CA_PAGE_MASK) && (!wdc_is_sn861(device_id))) { /* Get the CA Log Page */ - ret = wdc_get_ca_log_page(r, dev, cfg.output_format); + ret = wdc_get_ca_log_page(ctx, hdl, 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(r, dev, cfg.output_format, + ret = wdc_get_c1_log_page(ctx, hdl, cfg.output_format, cfg.interval); if (ret) fprintf(stderr, "ERROR: WDC: Failure reading the C1 Log Page, ret = %d\n", ret); @@ -8521,24 +8391,23 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, 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(r, dev, cfg.output_format); + ret = wdc_get_d0_log_page(ctx, hdl, cfg.output_format); if (ret) fprintf(stderr, "ERROR: WDC: Failure reading the D0 Log Page, ret = %d\n", ret); } out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_cu_smart_log(int argc, char **argv, struct command *command, +static int wdc_cu_smart_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve customer unique smart log statistics."; const char *uuid_index = "The uuid index to select the correct log page implementation."; - struct nvme_dev *dev; - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; int ret = 0; __u64 capabilities = 0; uint32_t read_device_id, read_vendor_id; @@ -8561,13 +8430,15 @@ static int wdc_cu_smart_log(int argc, char **argv, struct command *command, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret) + return ret; - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; @@ -8575,7 +8446,7 @@ static int wdc_cu_smart_log(int argc, char **argv, struct command *command, } if ((capabilities & WDC_DRIVE_CAP_CA_LOG_PAGE) == WDC_DRIVE_CAP_CA_LOG_PAGE) { - if (!wdc_check_device(r, dev)) + if (!wdc_check_device(ctx, hdl)) return -1; ret = validate_output_format(cfg.output_format, &fmt); @@ -8586,13 +8457,13 @@ static int wdc_cu_smart_log(int argc, char **argv, struct command *command, } /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, 0) == false) { fprintf(stderr, "ERROR: WDC: 0xCA Log Page not supported\n"); return -1; } - ret = wdc_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(ctx, hdl, &read_device_id, &read_vendor_id); switch (read_device_id) { case WDC_NVME_SN861_DEV_ID: @@ -8605,33 +8476,23 @@ static int wdc_cu_smart_log(int argc, char **argv, struct command *command, } memset(data, 0, sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN); - struct nvme_get_log_args args = { - .lpo = 0, - .result = NULL, - .log = data, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, - .len = WDC_BD_CA_LOG_BUF_LEN, - .nsid = NVME_NSID_ALL, - .csi = NVME_CSI_NVM, - .lsi = NVME_LOG_LSI_NONE, - .lsp = 0, - .uuidx = cfg.uuid_index, - .rae = false, - .ot = false, - }; /* Get the CA Log Page */ - ret = nvme_get_log(&args); + nvme_init_get_log(&cmd, NVME_NSID_ALL, + WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, + NVME_CSI_NVM, data, WDC_BD_CA_LOG_BUF_LEN); + cmd.cdw14 |= NVME_FIELD_ENCODE(cfg.uuid_index, + NVME_LOG_CDW14_UUID_SHIFT, + NVME_LOG_CDW14_UUID_MASK); + ret = nvme_get_log(hdl, &cmd, false, + NVME_LOG_PAGE_PDU_SIZE, NULL); if (strcmp(cfg.output_format, "json")) nvme_show_status(ret); if (!ret) { /* parse the data */ - ret = wdc_print_bd_ca_log(dev, data, fmt); + ret = wdc_print_bd_ca_log(hdl, data, fmt); } else { fprintf(stderr, "ERROR: WDC: Unable to read CA Log Page data\n"); ret = -1; @@ -8649,20 +8510,18 @@ static int wdc_cu_smart_log(int argc, char **argv, struct command *command, } out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_vs_cloud_log(int argc, char **argv, struct command *command, +static int wdc_vs_cloud_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Cloud Log Smart/Health Information"; const char *namespace_id = "desired namespace id"; nvme_print_flags_t fmt; __u64 capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret; __u8 *data; @@ -8682,13 +8541,15 @@ static int wdc_vs_cloud_log(int argc, char **argv, struct command *command, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret) + return ret; - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); @@ -8697,7 +8558,7 @@ static int wdc_vs_cloud_log(int argc, char **argv, struct command *command, } data = NULL; - ret = nvme_get_ext_smart_cloud_log(dev_fd(dev), &data, 0, + ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0, cfg.namespace_id); if (strcmp(cfg.output_format, "json")) @@ -8719,22 +8580,20 @@ static int wdc_vs_cloud_log(int argc, char **argv, struct command *command, free(data); out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *command, +static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Hardware Revision Log Information"; const char *namespace_id = "desired namespace id"; nvme_print_flags_t fmt; __u64 capabilities = 0; - struct nvme_dev *dev; + struct nvme_transport_handle *hdl; int ret; __u8 *data = NULL; - nvme_root_t r; + struct nvme_global_ctx *ctx; struct config { char *output_format; @@ -8752,13 +8611,15 @@ static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *command, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret) + return ret; - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); @@ -8766,7 +8627,7 @@ static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *command, goto out; } - ret = nvme_get_hw_rev_log(dev_fd(dev), &data, 0, cfg.namespace_id); + ret = nvme_get_hw_rev_log(hdl, &data, 0, cfg.namespace_id); if (strcmp(cfg.output_format, "json")) nvme_show_status(ret); @@ -8802,21 +8663,19 @@ static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *command, free(data); out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_vs_device_waf(int argc, char **argv, struct command *command, +static int wdc_vs_device_waf(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Device Write Amplication Factor"; const char *namespace_id = "desired namespace id"; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct nvme_smart_log smart_log; nvme_print_flags_t fmt; - struct nvme_dev *dev; __u8 *data; - nvme_root_t r; int ret = 0; __u64 capabilities = 0; struct __packed wdc_nvme_ext_smart_log * ext_smart_log_ptr; @@ -8843,13 +8702,15 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret) + return ret; - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_DEVICE_WAF)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); @@ -8858,8 +8719,7 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, } /* get data units written from the smart log page */ - ret = nvme_get_log_smart(dev_fd(dev), cfg.namespace_id, false, - &smart_log); + ret = nvme_get_log_smart(hdl, cfg.namespace_id, &smart_log); if (!ret) { data_units_written = int128_to_double(smart_log.data_units_written); } else if (ret > 0) { @@ -8874,7 +8734,7 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, /* get Physical Media Units Written from extended smart/C0 log page */ data = NULL; - ret = nvme_get_ext_smart_cloud_log(dev_fd(dev), &data, 0, + ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0, cfg.namespace_id); if (!ret) { @@ -8924,18 +8784,16 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, } out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *command, +static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve latency monitor log data."; __u64 capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = 0; struct config { @@ -8951,12 +8809,14 @@ static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *co OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, dev); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret) + return ret; + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); @@ -8964,23 +8824,21 @@ static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *co goto out; } - ret = wdc_get_c3_log_page(r, dev, cfg.output_format); + ret = wdc_get_c3_log_page(ctx, hdl, cfg.output_format); if (ret) fprintf(stderr, "ERROR: WDC: Failure reading the Latency Monitor (C3) Log Page, ret = %d\n", ret); out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_get_error_recovery_log(int argc, char **argv, struct command *command, +static int wdc_get_error_recovery_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve error recovery log data."; __u64 capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = 0; struct config { @@ -8996,12 +8854,15 @@ static int wdc_get_error_recovery_log(int argc, char **argv, struct command *com OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, dev); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret) + return ret; + + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); @@ -9009,23 +8870,21 @@ static int wdc_get_error_recovery_log(int argc, char **argv, struct command *com goto out; } - ret = wdc_get_ocp_c1_log_page(r, dev, cfg.output_format); + ret = wdc_get_ocp_c1_log_page(ctx, hdl, cfg.output_format); if (ret) fprintf(stderr, "ERROR: WDC: Failure reading the Error Recovery (C1) Log Page, ret = 0x%x\n", ret); out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *command, +static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve device capabilities log data."; __u64 capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = 0; struct config { @@ -9041,12 +8900,15 @@ static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *c OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); + if (ret) + return ret; + + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret) return ret; - r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); @@ -9054,23 +8916,21 @@ static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *c goto out; } - ret = wdc_get_ocp_c4_log_page(r, dev, cfg.output_format); + ret = wdc_get_ocp_c4_log_page(ctx, hdl, cfg.output_format); if (ret) fprintf(stderr, "ERROR: WDC: Failure reading the Device Capabilities (C4) Log Page, ret = 0x%x\n", ret); out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *command, +static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve unsupported requirements log data."; __u64 capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = 0; struct config { @@ -9086,12 +8946,15 @@ static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *c OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); + if (ret) + return ret; + + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret) return ret; - r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); @@ -9099,17 +8962,15 @@ static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *c goto out; } - ret = wdc_get_ocp_c5_log_page(r, dev, cfg.output_format); + ret = wdc_get_ocp_c5_log_page(ctx, hdl, cfg.output_format); if (ret) fprintf(stderr, "ERROR: WDC: Failure reading the Unsupported Requirements (C5) Log Page, ret = 0x%x\n", ret); out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_do_clear_pcie_correctable_errors(int fd) +static int wdc_do_clear_pcie_correctable_errors(struct nvme_transport_handle *hdl) { int ret; struct nvme_passthru_cmd admin_cmd; @@ -9119,12 +8980,12 @@ 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, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); nvme_show_status(ret); return ret; } -static int wdc_do_clear_pcie_correctable_errors_vuc(int fd) +static int wdc_do_clear_pcie_correctable_errors_vuc(struct nvme_transport_handle *hdl) { int ret; struct nvme_passthru_cmd admin_cmd; @@ -9132,48 +8993,46 @@ 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, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); nvme_show_status(ret); return ret; } -static int wdc_do_clear_pcie_correctable_errors_fid(int fd) +static int wdc_do_clear_pcie_correctable_errors_fid(struct nvme_transport_handle *hdl) { int ret; __u32 result; __u32 value = 1 << 31; /* Bit 31 - clear PCIe correctable count */ - ret = nvme_set_features_simple(fd, WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID, 0, value, - false, &result); + ret = nvme_set_features_simple(hdl, 0, WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID, false, + value, &result); nvme_show_status(ret); return ret; } -static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *command, +static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Clear PCIE Correctable Errors."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u64 capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; int ret; OPT_ARGS(opts) = { OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); - if (!wdc_check_device(r, dev)) { - ret = -1; - goto out; - } + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || !wdc_check_device(ctx, hdl)) + return -1; - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; @@ -9181,26 +9040,24 @@ static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct comma } if (capabilities & WDC_DRIVE_CAP_CLEAR_PCIE) - ret = wdc_do_clear_pcie_correctable_errors(dev_fd(dev)); + ret = wdc_do_clear_pcie_correctable_errors(hdl); else if (capabilities & WDC_DRIVE_CAP_VUC_CLEAR_PCIE) - ret = wdc_do_clear_pcie_correctable_errors_vuc(dev_fd(dev)); + ret = wdc_do_clear_pcie_correctable_errors_vuc(hdl); else - ret = wdc_do_clear_pcie_correctable_errors_fid(dev_fd(dev)); + ret = wdc_do_clear_pcie_correctable_errors_fid(hdl); out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_drive_status(int argc, char **argv, struct command *command, +static int wdc_drive_status(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get Drive Status."; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = 0; int uuid_index; - nvme_root_t r; void *dev_mng_log = NULL; __u32 system_eol_state; __u32 user_eol_state; @@ -9215,12 +9072,16 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); + if (ret) + return ret; + + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret) return ret; - r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); + if ((capabilities & WDC_DRIVE_CAP_DRIVE_STATUS) != WDC_DRIVE_CAP_DRIVE_STATUS) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; @@ -9231,7 +9092,7 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, /* Find the WDC UUID index */ memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list)); - if (wdc_CheckUuidListSupport(dev, &uuid_list)) { + if (wdc_CheckUuidListSupport(hdl, &uuid_list)) { /* check for the Sandisk UUID first */ uuid_index = nvme_uuid_find(&uuid_list, SNDK_UUID); @@ -9247,7 +9108,7 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, uuid_index = 0; /* verify the 0xC2 Device Manageability log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, + if (wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID, uuid_index) == false) { fprintf(stderr, "ERROR: WDC: 0xC2 Log Page not supported, uuid_index: %d\n", @@ -9256,7 +9117,7 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, goto out; } - if (!get_dev_mgment_data(r, dev, &dev_mng_log)) { + if (!get_dev_mgment_data(ctx, hdl, &dev_mng_log)) { fprintf(stderr, "ERROR: WDC: 0xC2 Log Page not found\n"); ret = -1; goto out; @@ -9339,18 +9200,16 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, free(dev_mng_log); out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, +static int wdc_clear_assert_dump(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Clear Assert Dump Present Status."; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = -1; - nvme_root_t r; __le32 assert_status = cpu_to_le32(0xFFFFFFFF); __u64 capabilities = 0; struct nvme_passthru_cmd admin_cmd; @@ -9359,18 +9218,22 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, dev); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret) + return ret; + + capabilities = wdc_get_drive_capabilities(ctx, hdl); + 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(r, dev, &assert_status, + if (!wdc_nvme_get_dev_status_log_data(ctx, hdl, &assert_status, WDC_C2_ASSERT_DUMP_PRESENT_ID)) { fprintf(stderr, "ERROR: WDC: Get Assert Status Failed\n"); ret = -1; @@ -9384,19 +9247,17 @@ 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(dev_fd(dev), &admin_cmd, + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); nvme_show_status(ret); } else fprintf(stderr, "INFO: WDC: No Assert Dump Present\n"); out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_get_fw_act_history(nvme_root_t r, struct nvme_dev *dev, +static int wdc_get_fw_act_history(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, char *format) { struct wdc_fw_act_history_log_hdr *fw_act_history_hdr; @@ -9404,7 +9265,7 @@ static int wdc_get_fw_act_history(nvme_root_t r, struct nvme_dev *dev, int ret; __u8 *data; - if (!wdc_check_device(r, dev)) + if (!wdc_check_device(ctx, hdl)) return -1; ret = validate_output_format(format, &fmt); @@ -9414,7 +9275,7 @@ static int wdc_get_fw_act_history(nvme_root_t r, struct nvme_dev *dev, } /* verify the FW Activate History log page is supported */ - if (!wdc_nvme_check_supported_log_page(r, dev, + if (!wdc_nvme_check_supported_log_page(ctx, hdl, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID, 0)) { fprintf(stderr, "ERROR: WDC: %d Log Page not supported\n", WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID); @@ -9429,9 +9290,9 @@ static int wdc_get_fw_act_history(nvme_root_t r, struct nvme_dev *dev, memset(data, 0, sizeof(__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN); - ret = nvme_get_log_simple(dev_fd(dev), + ret = nvme_get_log_simple(hdl, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID, - WDC_FW_ACT_HISTORY_LOG_BUF_LEN, data); + data, WDC_FW_ACT_HISTORY_LOG_BUF_LEN); if (strcmp(format, "json")) nvme_show_status(ret); @@ -9462,13 +9323,13 @@ static int wdc_get_fw_act_history(nvme_root_t r, struct nvme_dev *dev, return ret; } -static __u32 wdc_get_fw_cust_id(nvme_root_t r, struct nvme_dev *dev) +static __u32 wdc_get_fw_cust_id(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl) { __u32 cust_id = WDC_INVALID_CUSTOMER_ID; __u32 *cust_id_ptr = NULL; - if (!get_dev_mgment_cbs_data(r, dev, WDC_C2_CUSTOMER_ID_ID, (void *)&cust_id_ptr)) + if (!get_dev_mgment_cbs_data(ctx, hdl, WDC_C2_CUSTOMER_ID_ID, (void *)&cust_id_ptr)) fprintf(stderr, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); else @@ -9478,7 +9339,7 @@ static __u32 wdc_get_fw_cust_id(nvme_root_t r, struct nvme_dev *dev) return cust_id; } -static int wdc_get_fw_act_history_C2(nvme_root_t r, struct nvme_dev *dev, +static int wdc_get_fw_act_history_C2(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, char *format) { struct wdc_fw_act_history_log_format_c2 *fw_act_history_log; @@ -9490,7 +9351,7 @@ static int wdc_get_fw_act_history_C2(nvme_root_t r, struct nvme_dev *dev, int ret; bool c2GuidMatch = false; - if (!wdc_check_device(r, dev)) + if (!wdc_check_device(ctx, hdl)) return -1; ret = validate_output_format(format, &fmt); @@ -9499,7 +9360,7 @@ static int wdc_get_fw_act_history_C2(nvme_root_t r, struct nvme_dev *dev, return ret; } - ret = wdc_get_pci_ids(r, dev, &device_id, &vendor_id); + ret = wdc_get_pci_ids(ctx, hdl, &device_id, &vendor_id); data = (__u8 *)malloc(sizeof(__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN); if (!data) { @@ -9509,9 +9370,9 @@ static int wdc_get_fw_act_history_C2(nvme_root_t r, struct nvme_dev *dev, memset(data, 0, sizeof(__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN); - ret = nvme_get_log_simple(dev_fd(dev), + ret = nvme_get_log_simple(hdl, WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID, - WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN, data); + data, WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN); if (strcmp(format, "json")) nvme_show_status(ret); @@ -9531,7 +9392,7 @@ static int wdc_get_fw_act_history_C2(nvme_root_t r, struct nvme_dev *dev, if (tot_entries > 0) { /* get the FW customer id */ if (!wdc_is_sn861(device_id)) { - cust_id = wdc_get_fw_cust_id(r, dev); + cust_id = wdc_get_fw_cust_id(ctx, hdl); if (cust_id == WDC_INVALID_CUSTOMER_ID) { fprintf(stderr, "%s: ERROR: WDC: invalid customer id\n", @@ -9562,13 +9423,13 @@ static int wdc_get_fw_act_history_C2(nvme_root_t r, struct nvme_dev *dev, return ret; } -static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *command, +static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve FW activate history table."; __u64 capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret = -1; struct config { @@ -9584,12 +9445,16 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); + if (ret) + return ret; + + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret) return ret; - r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); + if (!(capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; @@ -9599,7 +9464,7 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com if (capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY) { __u32 cust_fw_id = 0; /* get the FW customer id */ - cust_fw_id = wdc_get_fw_cust_id(r, dev); + cust_fw_id = wdc_get_fw_cust_id(ctx, hdl); if (cust_fw_id == WDC_INVALID_CUSTOMER_ID) { fprintf(stderr, "%s: ERROR: WDC: invalid customer id\n", __func__); ret = -1; @@ -9610,22 +9475,20 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com (cust_fw_id == WDC_CUSTOMER_ID_0x1008) || (cust_fw_id == WDC_CUSTOMER_ID_0x1005) || (cust_fw_id == WDC_CUSTOMER_ID_0x1304)) - ret = wdc_get_fw_act_history_C2(r, dev, cfg.output_format); + ret = wdc_get_fw_act_history_C2(ctx, hdl, cfg.output_format); else - ret = wdc_get_fw_act_history(r, dev, cfg.output_format); + ret = wdc_get_fw_act_history(ctx, hdl, cfg.output_format); } else if (capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C2) { - ret = wdc_get_fw_act_history_C2(r, dev, cfg.output_format); + ret = wdc_get_fw_act_history_C2(ctx, hdl, cfg.output_format); } if (ret) fprintf(stderr, "ERROR: WDC: Failure reading the FW Activate History, ret = %d\n", ret); out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_do_clear_fw_activate_history_vuc(int fd) +static int wdc_do_clear_fw_activate_history_vuc(struct nvme_transport_handle *hdl) { int ret = -1; struct nvme_passthru_cmd admin_cmd; @@ -9635,44 +9498,48 @@ 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, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); nvme_show_status(ret); return ret; } -static int wdc_do_clear_fw_activate_history_fid(int fd) +static int wdc_do_clear_fw_activate_history_fid(struct nvme_transport_handle *hdl) { int ret = -1; __u32 result; __u32 value = 1 << 31; /* Bit 31 - Clear Firmware Update History Log */ - ret = nvme_set_features_simple(fd, WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID, 0, value, - false, &result); + ret = nvme_set_features_simple(hdl, 0, WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID, false, + value, &result); nvme_show_status(ret); return ret; } -static int wdc_clear_fw_activate_history(int argc, char **argv, struct command *command, +static int wdc_clear_fw_activate_history(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Clear FW activate history table."; __u64 capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret; OPT_ARGS(opts) = { OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); + if (ret) + return ret; + + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret) return ret; - r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); + if (!(capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; @@ -9680,17 +9547,15 @@ static int wdc_clear_fw_activate_history(int argc, char **argv, struct command * } if (capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY) - ret = wdc_do_clear_fw_activate_history_vuc(dev_fd(dev)); + ret = wdc_do_clear_fw_activate_history_vuc(hdl); else - ret = wdc_do_clear_fw_activate_history_fid(dev_fd(dev)); + ret = wdc_do_clear_fw_activate_history_fid(hdl); out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct command *command, +static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Disable/Enable Controller Option of the Telemetry Log Page."; @@ -9698,8 +9563,8 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm const char *enable = "Enable controller option of the telemetry log page."; const char *status = "Displays the current state of the controller initiated log page."; __u64 capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u32 result; int ret = -1; @@ -9723,12 +9588,16 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, dev); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret) + return ret; + + capabilities = wdc_get_drive_capabilities(ctx, hdl); + 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; @@ -9744,20 +9613,21 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm } if (cfg.disable) { - ret = nvme_set_features_simple(dev_fd(dev), - WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, - 0, 1, false, &result); + ret = nvme_set_features_simple(hdl, 0, + WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, + false, 1, &result); - wdc_clear_reason_id(dev); + wdc_clear_reason_id(hdl); } else { if (cfg.enable) { - ret = nvme_set_features_simple(dev_fd(dev), - WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, - 0, 0, false, &result); + ret = nvme_set_features_simple(hdl, 0, + WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, + false, 0, &result); } else if (cfg.status) { - ret = nvme_get_features_simple(dev_fd(dev), - WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, - 0, &result); + ret = nvme_get_features_simple(hdl, + WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, + NVME_GET_FEATURES_SEL_CURRENT, + &result); if (!ret) { if (result) fprintf(stderr, "Controller Option Telemetry Log Page State: Disabled\n"); @@ -9775,23 +9645,21 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm } out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_get_serial_and_fw_rev(struct nvme_dev *dev, char *sn, char *fw_rev) +static int wdc_get_serial_and_fw_rev(struct nvme_transport_handle *hdl, char *sn, char *fw_rev) { - int i; - int ret; struct nvme_id_ctrl ctrl; + int ret; + int i; i = sizeof(ctrl.sn) - 1; memset(sn, 0, WDC_SERIAL_NO_LEN); memset(fw_rev, 0, WDC_NVME_FIRMWARE_REV_LEN); memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); + ret = nvme_identify_ctrl(hdl, &ctrl); if (ret) { fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret); return -1; @@ -9807,15 +9675,15 @@ static int wdc_get_serial_and_fw_rev(struct nvme_dev *dev, char *sn, char *fw_re return 0; } -static int wdc_get_max_transfer_len(struct nvme_dev *dev, __u32 *maxTransferLen) +static int wdc_get_max_transfer_len(struct nvme_transport_handle *hdl, __u32 *maxTransferLen) { - int ret = 0; struct nvme_id_ctrl ctrl; + int ret = 0; __u32 maxTransferLenDevice = 0; memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); + ret = nvme_identify_ctrl(hdl, &ctrl); if (ret) { fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret); return -1; @@ -9827,12 +9695,12 @@ static int wdc_get_max_transfer_len(struct nvme_dev *dev, __u32 *maxTransferLen) return ret; } -static int wdc_de_VU_read_size(struct nvme_dev *dev, __u32 fileId, __u16 spiDestn, __u32 *logSize) +static int wdc_de_VU_read_size(struct nvme_transport_handle *hdl, __u32 fileId, __u16 spiDestn, __u32 *logSize) { int ret = WDC_STATUS_FAILURE; struct nvme_passthru_cmd cmd; - if (!dev || !logSize) { + if (!logSize) { ret = WDC_STATUS_INVALID_PARAMETER; goto end; } @@ -9843,7 +9711,7 @@ static int wdc_de_VU_read_size(struct nvme_dev *dev, __u32 fileId, __u16 spiDest cmd.cdw13 = fileId << 16; cmd.cdw14 = spiDestn; - ret = nvme_submit_admin_passthru(dev_fd(dev), &cmd, NULL); + ret = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!ret && logSize) *logSize = cmd.result; @@ -9856,14 +9724,14 @@ static int wdc_de_VU_read_size(struct nvme_dev *dev, __u32 fileId, __u16 spiDest return ret; } -static int wdc_de_VU_read_buffer(struct nvme_dev *dev, __u32 fileId, __u16 spiDestn, +static int wdc_de_VU_read_buffer(struct nvme_transport_handle *hdl, __u32 fileId, __u16 spiDestn, __u32 offsetInDwords, __u8 *dataBuffer, __u32 *bufferSize) { int ret = WDC_STATUS_FAILURE; struct nvme_passthru_cmd cmd; __u32 noOfDwordExpected = 0; - if (!dev || !dataBuffer || !bufferSize) { + if (!dataBuffer || !bufferSize) { ret = WDC_STATUS_INVALID_PARAMETER; goto end; } @@ -9880,7 +9748,7 @@ static int wdc_de_VU_read_buffer(struct nvme_dev *dev, __u32 fileId, __u16 spiDe cmd.addr = (__u64)(__u64)(uintptr_t)dataBuffer; cmd.data_len = *bufferSize; - ret = nvme_submit_admin_passthru(dev_fd(dev), &cmd, NULL); + ret = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (ret != WDC_STATUS_SUCCESS) { fprintf(stderr, "ERROR: WDC: VUReadBuffer() failed, "); @@ -9891,7 +9759,7 @@ static int wdc_de_VU_read_buffer(struct nvme_dev *dev, __u32 fileId, __u16 spiDe return ret; } -static int wdc_get_log_dir_max_entries(struct nvme_dev *dev, __u32 *maxNumOfEntries) +static int wdc_get_log_dir_max_entries(struct nvme_transport_handle *hdl, __u32 *maxNumOfEntries) { int ret = WDC_STATUS_FAILURE; __u32 headerPayloadSize = 0; @@ -9901,12 +9769,12 @@ static int wdc_get_log_dir_max_entries(struct nvme_dev *dev, __u32 *maxNumOfEntr __u16 fileOffset = 0; - if (!dev || !maxNumOfEntries) { + if (!maxNumOfEntries) { ret = WDC_STATUS_INVALID_PARAMETER; return ret; } /* 1.Get log directory first four bytes */ - ret = wdc_de_VU_read_size(dev, 0, 5, (__u32 *)&headerPayloadSize); + ret = wdc_de_VU_read_size(hdl, 0, 5, (__u32 *)&headerPayloadSize); if (ret != WDC_STATUS_SUCCESS) { fprintf(stderr, "ERROR: WDC: %s: Failed to get headerPayloadSize from file directory 0x%x\n", @@ -9919,7 +9787,7 @@ static int wdc_get_log_dir_max_entries(struct nvme_dev *dev, __u32 *maxNumOfEntr fileIdOffsetsBuffer = (__u8 *)calloc(1, fileIdOffsetsBufferSize); /* 2.Read to get file offsets */ - ret = wdc_de_VU_read_buffer(dev, 0, 5, 0, fileIdOffsetsBuffer, &fileIdOffsetsBufferSize); + ret = wdc_de_VU_read_buffer(hdl, 0, 5, 0, fileIdOffsetsBuffer, &fileIdOffsetsBufferSize); if (ret != WDC_STATUS_SUCCESS) { fprintf(stderr, "ERROR: WDC: %s: Failed to get fileIdOffsets from file directory 0x%x\n", @@ -9958,7 +9826,7 @@ static enum WDC_DRIVE_ESSENTIAL_TYPE wdc_get_essential_type(__u8 fileName[]) return essentialType; } -static int wdc_fetch_log_directory(struct nvme_dev *dev, struct WDC_DE_VU_LOG_DIRECTORY *directory) +static int wdc_fetch_log_directory(struct nvme_transport_handle *hdl, struct WDC_DE_VU_LOG_DIRECTORY *directory) { int ret = WDC_STATUS_FAILURE; __u8 *fileOffset = NULL; @@ -9969,12 +9837,12 @@ static int wdc_fetch_log_directory(struct nvme_dev *dev, struct WDC_DE_VU_LOG_DI __u32 entryId = 0; __u32 fileDirectorySize = 0; - if (!dev || !directory) { + if (!directory) { ret = WDC_STATUS_INVALID_PARAMETER; goto end; } - ret = wdc_de_VU_read_size(dev, 0, 5, &fileDirectorySize); + ret = wdc_de_VU_read_size(hdl, 0, 5, &fileDirectorySize); if (ret != WDC_STATUS_SUCCESS) { fprintf(stderr, "ERROR: WDC: %s: Failed to get filesystem directory size, ret = %d\n", @@ -9983,7 +9851,7 @@ static int wdc_fetch_log_directory(struct nvme_dev *dev, struct WDC_DE_VU_LOG_DI } fileDirectory = (__u8 *)calloc(1, fileDirectorySize); - ret = wdc_de_VU_read_buffer(dev, 0, 5, 0, fileDirectory, &fileDirectorySize); + ret = wdc_de_VU_read_buffer(hdl, 0, 5, 0, fileDirectory, &fileDirectorySize); if (ret != WDC_STATUS_SUCCESS) { fprintf(stderr, "ERROR: WDC: %s: Failed to get filesystem directory, ret = %d\n", __func__, ret); @@ -10031,7 +9899,7 @@ static int wdc_fetch_log_directory(struct nvme_dev *dev, struct WDC_DE_VU_LOG_DI return ret; } -static int wdc_fetch_log_file_from_device(struct nvme_dev *dev, __u32 fileId, +static int wdc_fetch_log_file_from_device(struct nvme_transport_handle *hdl, __u32 fileId, __u16 spiDestn, __u64 fileSize, __u8 *dataBuffer) { int ret = WDC_STATUS_FAILURE; @@ -10040,12 +9908,12 @@ static int wdc_fetch_log_file_from_device(struct nvme_dev *dev, __u32 fileId, __u32 buffSize = 0; __u64 offsetIdx = 0; - if (!dev || !dataBuffer || !fileSize) { + if (!dataBuffer || !fileSize) { ret = WDC_STATUS_INVALID_PARAMETER; goto end; } - if (wdc_get_max_transfer_len(dev, &maximumTransferLength) < 0) { + if (wdc_get_max_transfer_len(hdl, &maximumTransferLength) < 0) { ret = WDC_STATUS_FAILURE; goto end; } @@ -10061,7 +9929,7 @@ static int wdc_fetch_log_file_from_device(struct nvme_dev *dev, __u32 fileId, if (((offsetIdx * chunckSize) + buffSize) > fileSize) buffSize = (__u32)(fileSize - (offsetIdx * chunckSize)); /* Limitation in VU read buffer - offsetIdx and bufferSize are not greater than u32 */ - ret = wdc_de_VU_read_buffer(dev, fileId, spiDestn, + ret = wdc_de_VU_read_buffer(hdl, fileId, spiDestn, (__u32)((offsetIdx * chunckSize) / sizeof(__u32)), dataBuffer + (offsetIdx * chunckSize), &buffSize); if (ret != WDC_STATUS_SUCCESS) { fprintf(stderr, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx\n", @@ -10071,7 +9939,7 @@ static int wdc_fetch_log_file_from_device(struct nvme_dev *dev, __u32 fileId, } } else { buffSize = (__u32)fileSize; - ret = wdc_de_VU_read_buffer(dev, fileId, spiDestn, + ret = wdc_de_VU_read_buffer(hdl, fileId, spiDestn, (__u32)((offsetIdx * chunckSize) / sizeof(__u32)), dataBuffer, &buffSize); if (ret != WDC_STATUS_SUCCESS) { @@ -10084,7 +9952,7 @@ static int wdc_fetch_log_file_from_device(struct nvme_dev *dev, __u32 fileId, return ret; } -static int wdc_de_get_dump_trace(struct nvme_dev *dev, const char *filePath, __u16 binFileNameLen, +static int wdc_de_get_dump_trace(struct nvme_transport_handle *hdl, const char *filePath, __u16 binFileNameLen, const char *binFileName) { int ret = WDC_STATUS_FAILURE; @@ -10099,17 +9967,17 @@ static int wdc_de_get_dump_trace(struct nvme_dev *dev, const char *filePath, __u __u32 i; __u32 maximumTransferLength = 0; - if (!dev || !binFileName || !filePath) { + if (!binFileName || !filePath) { ret = WDC_STATUS_INVALID_PARAMETER; return ret; } - if (wdc_get_max_transfer_len(dev, &maximumTransferLength) < 0) + if (wdc_get_max_transfer_len(hdl, &maximumTransferLength) < 0) return WDC_STATUS_FAILURE; do { /* Get dumptrace size */ - ret = wdc_de_VU_read_size(dev, 0, WDC_DE_DUMPTRACE_DESTINATION, &dumptraceSize); + ret = wdc_de_VU_read_size(hdl, 0, WDC_DE_DUMPTRACE_DESTINATION, &dumptraceSize); if (ret != WDC_STATUS_SUCCESS) { fprintf(stderr, "ERROR: WDC: %s: wdc_de_VU_read_size failed with ret = %d\n", __func__, ret); @@ -10152,7 +10020,7 @@ static int wdc_de_get_dump_trace(struct nvme_dev *dev, const char *filePath, __u if (i == (chunks - 1)) readBufferLen = lastPktReadBufferLen; - ret = wdc_de_VU_read_buffer(dev, 0, WDC_DE_DUMPTRACE_DESTINATION, 0, + ret = wdc_de_VU_read_buffer(hdl, 0, WDC_DE_DUMPTRACE_DESTINATION, 0, readBuffer + offset, &readBufferLen); if (ret != WDC_STATUS_SUCCESS) { fprintf(stderr, @@ -10178,11 +10046,11 @@ static int wdc_de_get_dump_trace(struct nvme_dev *dev, const char *filePath, __u return ret; } -int wdc_fetch_vu_file_directory(struct nvme_dev *dev, +int wdc_fetch_vu_file_directory(struct nvme_transport_handle *hdl, struct WDC_DE_VU_LOG_DIRECTORY deEssentialsList, __s8 *bufferFolderPath, __u8 *serialNo, __u8 *timeString) { - int ret = wdc_fetch_log_directory(dev, &deEssentialsList); + int ret = wdc_fetch_log_directory(hdl, &deEssentialsList); __u32 listIdx; char *dataBuffer; char fileName[MAX_PATH_LEN]; @@ -10201,7 +10069,7 @@ int wdc_fetch_vu_file_directory(struct nvme_dev *dev, } else { /* Fetch Log File Data */ dataBuffer = (char *)calloc(1, (size_t)deEssentialsList.logEntry[listIdx].metaData.fileSize); - ret = wdc_fetch_log_file_from_device(dev, + ret = wdc_fetch_log_file_from_device(hdl, deEssentialsList.logEntry[listIdx].metaData.fileID, WDC_DE_DESTN_SPI, deEssentialsList.logEntry[listIdx].metaData.fileSize, @@ -10229,11 +10097,11 @@ int wdc_fetch_vu_file_directory(struct nvme_dev *dev, return ret; } -int wdc_read_debug_directory(struct nvme_dev *dev, __s8 *bufferFolderPath, __u8 *serialNo, +int wdc_read_debug_directory(struct nvme_transport_handle *hdl, __s8 *bufferFolderPath, __u8 *serialNo, __u8 *timeString) { __u32 maxNumOfVUFiles = 0; - int ret = wdc_get_log_dir_max_entries(dev, &maxNumOfVUFiles); + int ret = wdc_get_log_dir_max_entries(hdl, &maxNumOfVUFiles); struct WDC_DE_VU_LOG_DIRECTORY deEssentialsList; if (ret != WDC_STATUS_SUCCESS) { @@ -10246,7 +10114,7 @@ int wdc_read_debug_directory(struct nvme_dev *dev, __s8 *bufferFolderPath, __u8 (struct WDC_DRIVE_ESSENTIALS *)calloc(1, sizeof(struct WDC_DRIVE_ESSENTIALS) * maxNumOfVUFiles); deEssentialsList.maxNumLogEntries = maxNumOfVUFiles; - ret = wdc_fetch_vu_file_directory(dev, deEssentialsList, bufferFolderPath, serialNo, + ret = wdc_fetch_vu_file_directory(hdl, deEssentialsList, bufferFolderPath, serialNo, timeString); free(deEssentialsList.logEntry); @@ -10255,7 +10123,7 @@ int wdc_read_debug_directory(struct nvme_dev *dev, __s8 *bufferFolderPath, __u8 return ret; } -static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, +static int wdc_do_drive_essentials(struct nvme_global_ctx *ctx, struct nvme_transport_handle *hdl, char *dir, char *key) { int ret = 0; @@ -10294,7 +10162,7 @@ static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, memset(tarCmd, 0, sizeof(tarCmd)); memset(&timeInfo, 0, sizeof(timeInfo)); - if (wdc_get_serial_and_fw_rev(dev, (char *)idSerialNo, (char *)idFwRev)) { + if (wdc_get_serial_and_fw_rev(hdl, (char *)idSerialNo, (char *)idFwRev)) { fprintf(stderr, "ERROR: WDC: get serial # and fw revision failed\n"); return -1; } @@ -10345,7 +10213,7 @@ static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, /* Get Identify Controller Data */ memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); + ret = nvme_identify_ctrl(hdl, &ctrl); if (ret) { fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed, ret = %d\n", ret); return -1; @@ -10357,7 +10225,7 @@ static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, wdc_WriteToFile(fileName, (char *)&ctrl, sizeof(struct nvme_id_ctrl)); memset(&ns, 0, sizeof(struct nvme_id_ns)); - ret = nvme_identify_ns(dev_fd(dev), 1, &ns); + ret = nvme_identify_ns(hdl, 1, &ns); if (ret) { fprintf(stderr, "ERROR: WDC: nvme_identify_ns() failed, ret = %d\n", ret); } else { @@ -10372,8 +10240,7 @@ static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, dataBuffer = calloc(1, elogBufferSize); elogBuffer = (struct nvme_error_log_page *)dataBuffer; - ret = nvme_get_log_error(dev_fd(dev), elogNumEntries, false, - elogBuffer); + ret = nvme_get_log_error(hdl, NVME_NSID_ALL, elogNumEntries, elogBuffer); if (ret) { fprintf(stderr, "ERROR: WDC: nvme_error_log() failed, ret = %d\n", ret); } else { @@ -10387,8 +10254,7 @@ static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, /* Get Smart log page */ memset(&smart_log, 0, sizeof(struct nvme_smart_log)); - ret = nvme_get_log_smart(dev_fd(dev), NVME_NSID_ALL, false, - &smart_log); + ret = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log); if (ret) { fprintf(stderr, "ERROR: WDC: nvme_smart_log() failed, ret = %d\n", ret); } else { @@ -10399,7 +10265,7 @@ static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, /* Get FW Slot log page */ memset(&fw_log, 0, sizeof(struct nvme_firmware_slot)); - ret = nvme_get_log_fw_slot(dev_fd(dev), false, &fw_log); + ret = nvme_get_log_fw_slot(hdl, false, &fw_log); if (ret) { fprintf(stderr, "ERROR: WDC: nvme_fw_log() failed, ret = %d\n", ret); } else { @@ -10418,9 +10284,9 @@ static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, dataBuffer = calloc(1, dataBufferSize); memset(dataBuffer, 0, dataBufferSize); - ret = nvme_get_log_simple(dev_fd(dev), + ret = nvme_get_log_simple(hdl, deVULogPagesList[vuLogIdx].logPageId, - dataBufferSize, dataBuffer); + dataBuffer, dataBufferSize); if (ret) { fprintf(stderr, "ERROR: WDC: nvme_get_log() for log page 0x%x failed, ret = %d\n", deVULogPagesList[vuLogIdx].logPageId, ret); @@ -10443,12 +10309,10 @@ static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, /* skipping LbaRangeType as it is an optional nvme command and not supported */ if (deFeatureIdList[listIdx].featureId == FID_LBA_RANGE_TYPE) continue; - ret = nvme_get_features_data(dev_fd(dev), - (enum nvme_features_id)deFeatureIdList[listIdx].featureId, - WDC_DE_GLOBAL_NSID, - sizeof(featureIdBuff), - &featureIdBuff, &result); - + ret = nvme_get_features(hdl, WDC_DE_GLOBAL_NSID, + (enum nvme_features_id)deFeatureIdList[listIdx].featureId, + NVME_GET_FEATURES_SEL_CURRENT, 0, 0, &featureIdBuff, + sizeof(featureIdBuff), &result); if (ret) { fprintf(stderr, "ERROR: WDC: nvme_get_feature id 0x%x failed, ret = %d\n", deFeatureIdList[listIdx].featureId, ret); @@ -10460,11 +10324,11 @@ static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, } } - ret = wdc_read_debug_directory(dev, bufferFolderPath, serialNo, timeString); + ret = wdc_read_debug_directory(hdl, bufferFolderPath, serialNo, timeString); /* Get Dump Trace Data */ wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR, "dumptrace", serialNo, timeString); - ret = wdc_de_get_dump_trace(dev, (char *)bufferFolderPath, 0, fileName); + ret = wdc_de_get_dump_trace(hdl, (char *)bufferFolderPath, 0, fileName); if (ret != WDC_STATUS_SUCCESS) fprintf(stderr, "ERROR: WDC: wdc_de_get_dump_trace failed, ret = %d\n", ret); @@ -10486,20 +10350,19 @@ static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, ret); fprintf(stderr, "Get of Drive Essentials data successful\n"); - nvme_free_tree(r); return 0; } -static int wdc_drive_essentials(int argc, char **argv, struct command *command, +static int wdc_drive_essentials(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Capture Drive Essentials."; const char *dirName = "Output directory pathname."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; char d[PATH_MAX] = {0}; char k[PATH_MAX] = {0}; __u64 capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; char *d_ptr; int ret; @@ -10517,12 +10380,16 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command, }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); + if (ret) + return ret; + + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret) return ret; - r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); + if ((capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS) != WDC_DRIVE_CAP_DRIVE_ESSENTIALS) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; @@ -10536,14 +10403,12 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command, d_ptr = NULL; } - ret = wdc_do_drive_essentials(r, dev, d_ptr, k); + ret = wdc_do_drive_essentials(ctx, hdl, d_ptr, k); out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_do_drive_resize(struct nvme_dev *dev, uint64_t new_size) +static int wdc_do_drive_resize(struct nvme_transport_handle *hdl, uint64_t new_size) { int ret; struct nvme_passthru_cmd admin_cmd; @@ -10554,11 +10419,11 @@ static int wdc_do_drive_resize(struct nvme_dev *dev, uint64_t new_size) WDC_NVME_DRIVE_RESIZE_CMD); admin_cmd.cdw13 = new_size; - ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); return ret; } -static int wdc_do_namespace_resize(struct nvme_dev *dev, __u32 nsid, __u32 op_option) +static int wdc_do_namespace_resize(struct nvme_transport_handle *hdl, __u32 nsid, __u32 op_option) { int ret; struct nvme_passthru_cmd admin_cmd; @@ -10568,11 +10433,11 @@ static int wdc_do_namespace_resize(struct nvme_dev *dev, __u32 nsid, __u32 op_op admin_cmd.nsid = nsid; admin_cmd.cdw10 = op_option; - ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); return ret; } -static int wdc_do_drive_info(struct nvme_dev *dev, __u32 *result) +static int wdc_do_drive_info(struct nvme_transport_handle *hdl, __u32 *result) { int ret; struct nvme_passthru_cmd admin_cmd; @@ -10582,7 +10447,7 @@ static int wdc_do_drive_info(struct nvme_dev *dev, __u32 *result) admin_cmd.cdw12 = ((WDC_NVME_DRIVE_INFO_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_DRIVE_INFO_CMD); - ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (!ret && result) *result = admin_cmd.result; @@ -10595,9 +10460,9 @@ 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."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; uint64_t capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; int ret; struct config { @@ -10613,15 +10478,18 @@ static int wdc_drive_resize(int argc, char **argv, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); - wdc_check_device(r, dev); - capabilities = wdc_get_drive_capabilities(r, dev); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || !wdc_check_device(ctx, hdl)) + return -1; + + capabilities = wdc_get_drive_capabilities(ctx, hdl); + if ((capabilities & WDC_DRIVE_CAP_RESIZE) == WDC_DRIVE_CAP_RESIZE) { - ret = wdc_do_drive_resize(dev, cfg.size); + ret = wdc_do_drive_resize(hdl, cfg.size); } else { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; @@ -10631,8 +10499,6 @@ static int wdc_drive_resize(int argc, char **argv, printf("New size: %" PRIu64 " GB\n", cfg.size); nvme_show_status(ret); - nvme_free_tree(r); - dev_close(dev); return ret; } @@ -10642,9 +10508,9 @@ 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."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; uint64_t capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; int ret; struct config { @@ -10663,22 +10529,24 @@ static int wdc_namespace_resize(int argc, char **argv, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; if ((cfg.op_option != 0x1) && (cfg.op_option != 0x2) && (cfg.op_option != 0x3) && (cfg.op_option != 0xF)) { fprintf(stderr, "ERROR: WDC: unsupported OP option parameter\n"); - dev_close(dev); return -1; } - r = nvme_scan(NULL); - wdc_check_device(r, dev); - capabilities = wdc_get_drive_capabilities(r, dev); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || !wdc_check_device(ctx, hdl)) + return -1; + + capabilities = wdc_get_drive_capabilities(ctx, hdl); + if ((capabilities & WDC_DRIVE_CAP_NS_RESIZE) == WDC_DRIVE_CAP_NS_RESIZE) { - ret = wdc_do_namespace_resize(dev, cfg.namespace_id, + ret = wdc_do_namespace_resize(hdl, cfg.namespace_id, cfg.op_option); if (ret) @@ -10689,8 +10557,6 @@ static int wdc_namespace_resize(int argc, char **argv, } nvme_show_status(ret); - nvme_free_tree(r); - dev_close(dev); return ret; } @@ -10700,8 +10566,8 @@ 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"; - struct nvme_dev *dev; - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; int ret; uint64_t capabilities = 0; char f[PATH_MAX] = {0}; @@ -10725,18 +10591,19 @@ static int wdc_reason_identifier(int argc, char **argv, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; - r = nvme_scan(NULL); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret) + return ret; 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_dev; + return -1; } if (cfg.file) { @@ -10746,8 +10613,7 @@ static int wdc_reason_identifier(int argc, char **argv, verify_file = open(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (verify_file < 0) { fprintf(stderr, "ERROR: WDC: open: %s\n", strerror(errno)); - ret = -1; - goto close_dev; + return -1; } close(verify_file); strncpy(f, cfg.file, PATH_MAX - 1); @@ -10762,24 +10628,22 @@ static int wdc_reason_identifier(int argc, char **argv, else snprintf(fileSuffix, PATH_MAX, "_error_reason_identifier_host_%s", (char *)timeStamp); - if (wdc_get_serial_name(dev, f, PATH_MAX, fileSuffix) == -1) { + if (wdc_get_serial_name(hdl, f, PATH_MAX, fileSuffix) == -1) { fprintf(stderr, "ERROR: WDC: failed to generate file name\n"); - ret = -1; - goto close_dev; + return -1; } if (strlen(f) > PATH_MAX - 5) { fprintf(stderr, "ERROR: WDC: file name overflow\n"); - ret = -1; - goto close_dev; + return -1; } strcat(f, ".bin"); } fprintf(stderr, "%s: filename = %s\n", __func__, f); - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if ((capabilities & WDC_DRIVE_CAP_REASON_ID) == WDC_DRIVE_CAP_REASON_ID) { - ret = wdc_do_get_reason_id(dev, f, cfg.log_id); + ret = wdc_do_get_reason_id(hdl, f, cfg.log_id); } else { fprintf(stderr, "ERROR: WDC:unsupported device for this command\n"); ret = -1; @@ -10787,9 +10651,6 @@ static int wdc_reason_identifier(int argc, char **argv, nvme_show_status(ret); -close_dev: - dev_close(dev); - nvme_free_tree(r); return ret; } @@ -10818,7 +10679,7 @@ static const char *nvme_log_id_to_string(__u8 log_id) return "ANA Log ID"; case NVME_LOG_LID_PERSISTENT_EVENT: return "Persistent Event Log ID"; - case NVME_LOG_LID_DISCOVER: + case NVME_LOG_LID_DISCOVERY: return "Discovery Log ID"; case NVME_LOG_LID_RESERVATION: return "Reservation Notification Log ID"; @@ -10962,14 +10823,14 @@ static void __show_log_page_directory(struct log_page_directory *directory) } } -static int wdc_log_page_directory(int argc, char **argv, struct command *command, +static int wdc_log_page_directory(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Log Page Directory."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t fmt; - struct nvme_dev *dev; int ret = 0; - nvme_root_t r; __u64 capabilities = 0; struct wdc_c2_cbs_data *cbs_data = NULL; int i, uuid_index = 0; @@ -10991,26 +10852,28 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; ret = validate_output_format(cfg.output_format, &fmt); if (ret < 0) { fprintf(stderr, "%s: ERROR: WDC: invalid output format\n", __func__); - dev_close(dev); return ret; } - r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, dev); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret) + return ret; + + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; } else { memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list)); - if (wdc_CheckUuidListSupport(dev, &uuid_list)) + if (wdc_CheckUuidListSupport(hdl, &uuid_list)) uuid_supported = true; if (uuid_supported) @@ -11019,7 +10882,7 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command fprintf(stderr, "WDC: UUID lists NOT supported\n"); - ret = wdc_get_pci_ids(r, dev, &device_id, &read_vendor_id); + ret = wdc_get_pci_ids(ctx, hdl, &device_id, &read_vendor_id); log_id = wdc_is_zn350(device_id) ? WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C8 : WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID; @@ -11041,14 +10904,14 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command uuid_index = 0; /* verify the 0xC2 Device Manageability log page is supported */ - if (!wdc_nvme_check_supported_log_page(r, dev, log_id, uuid_index)) { + if (!wdc_nvme_check_supported_log_page(ctx, hdl, log_id, uuid_index)) { fprintf(stderr, "%s: ERROR: WDC: 0x%x Log Page not supported\n", __func__, log_id); ret = -1; goto out; } - if (!get_dev_mgment_cbs_data(r, dev, + if (!get_dev_mgment_cbs_data(ctx, hdl, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { fprintf(stderr, @@ -11103,7 +10966,7 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command } dir = (struct log_page_directory *)data; - ret = nvme_admin_passthru(dev_fd(dev), WDC_NVME_ADMIN_VUC_OPCODE_D2, 0, 0, + ret = nvme_admin_passthru(hdl, WDC_NVME_ADMIN_VUC_OPCODE_D2, 0, 0, 0, 0, 0, 8, 0, WDC_VUC_SUBOPCODE_LOG_PAGE_DIR_D2, 0, 0, 0, 32, data, 0, NULL, @@ -11128,24 +10991,22 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command } out: - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_get_drive_reason_id(struct nvme_dev *dev, char *drive_reason_id, size_t len) +static int wdc_get_drive_reason_id(struct nvme_transport_handle *hdl, char *drive_reason_id, size_t len) { + const char *reason_id_str = "reason_id"; + struct nvme_id_ctrl ctrl; + int res_len = 0; int i, j; int ret; - int res_len = 0; - struct nvme_id_ctrl ctrl; - const char *reason_id_str = "reason_id"; i = sizeof(ctrl.sn) - 1; j = sizeof(ctrl.mn) - 1; memset(drive_reason_id, 0, len); memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); + ret = nvme_identify_ctrl(hdl, &ctrl); if (ret) { fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret); return -1; @@ -11171,7 +11032,7 @@ static int wdc_get_drive_reason_id(struct nvme_dev *dev, char *drive_reason_id, return 0; } -static int wdc_save_reason_id(struct nvme_dev *dev, __u8 *rsn_ident, int size) +static int wdc_save_reason_id(struct nvme_transport_handle *hdl, __u8 *rsn_ident, int size) { int ret = 0; char *reason_id_file; @@ -11179,7 +11040,7 @@ static int wdc_save_reason_id(struct nvme_dev *dev, __u8 *rsn_ident, int size) char reason_id_path[PATH_MAX] = WDC_REASON_ID_PATH_NAME; struct stat st = {0}; - if (wdc_get_drive_reason_id(dev, drive_reason_id, PATH_MAX) == -1) { + if (wdc_get_drive_reason_id(hdl, drive_reason_id, PATH_MAX) == -1) { fprintf(stderr, "%s: ERROR: failed to get drive reason id\n", __func__); return -1; } @@ -11206,14 +11067,14 @@ static int wdc_save_reason_id(struct nvme_dev *dev, __u8 *rsn_ident, int size) return ret; } -static int wdc_clear_reason_id(struct nvme_dev *dev) +static int wdc_clear_reason_id(struct nvme_transport_handle *hdl) { int ret = -1; int verify_file; char *reason_id_file; char drive_reason_id[PATH_MAX] = {0}; - if (wdc_get_drive_reason_id(dev, drive_reason_id, PATH_MAX) == -1) { + if (wdc_get_drive_reason_id(hdl, drive_reason_id, PATH_MAX) == -1) { fprintf(stderr, "%s: ERROR: failed to get drive reason id\n", __func__); return -1; } @@ -11239,15 +11100,14 @@ static int wdc_clear_reason_id(struct nvme_dev *dev) return ret; } -static int wdc_dump_telemetry_hdr(struct nvme_dev *dev, int log_id, struct nvme_telemetry_log *log_hdr) +static int wdc_dump_telemetry_hdr(struct nvme_transport_handle *hdl, 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(dev_fd(dev), log_hdr); + ret = nvme_get_log_create_telemetry_host(hdl, log_hdr); else - ret = nvme_get_log_telemetry_ctrl(dev_fd(dev), false, 0, 512, - (void *)log_hdr); + ret = nvme_get_log_telemetry_ctrl(hdl, false, 0, (void *)log_hdr, 512); if (ret < 0) { perror("get-telemetry-log"); @@ -11259,7 +11119,7 @@ static int wdc_dump_telemetry_hdr(struct nvme_dev *dev, int log_id, struct nvme_ return ret; } -static int wdc_do_get_reason_id(struct nvme_dev *dev, const char *file, int log_id) +static int wdc_do_get_reason_id(struct nvme_transport_handle *hdl, const char *file, int log_id) { int ret; struct nvme_telemetry_log *log_hdr; @@ -11274,7 +11134,7 @@ static int wdc_do_get_reason_id(struct nvme_dev *dev, const char *file, int log_ } memset(log_hdr, 0, log_hdr_size); - ret = wdc_dump_telemetry_hdr(dev, log_id, log_hdr); + ret = wdc_dump_telemetry_hdr(hdl, log_id, log_hdr); if (ret) { fprintf(stderr, "%s: ERROR: get telemetry header failed, ret : %d\n", __func__, ret); ret = -1; @@ -11284,7 +11144,7 @@ static int wdc_do_get_reason_id(struct nvme_dev *dev, const char *file, int log_ reason_id_size = sizeof(log_hdr->rsnident); if (log_id == NVME_LOG_LID_TELEMETRY_CTRL) - wdc_save_reason_id(dev, log_hdr->rsnident, reason_id_size); + wdc_save_reason_id(hdl, log_hdr->rsnident, reason_id_size); ret = wdc_create_log_file(file, (__u8 *)log_hdr->rsnident, reason_id_size); @@ -11636,14 +11496,14 @@ static void wdc_print_pcie_stats_json(struct wdc_vs_pcie_stats *pcie_stats) json_free_object(root); } -static int wdc_do_vs_nand_stats_sn810_2(struct nvme_dev *dev, char *format) +static int wdc_do_vs_nand_stats_sn810_2(struct nvme_transport_handle *hdl, char *format) { nvme_print_flags_t fmt; uint8_t *data = NULL; int ret; data = NULL; - ret = nvme_get_ext_smart_cloud_log(dev_fd(dev), &data, 0, + ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0, NVME_NSID_ALL); if (ret) { @@ -11674,7 +11534,7 @@ static int wdc_do_vs_nand_stats_sn810_2(struct nvme_dev *dev, char *format) return ret; } -static int wdc_do_vs_nand_stats(struct nvme_dev *dev, char *format) +static int wdc_do_vs_nand_stats(struct nvme_transport_handle *hdl, char *format) { nvme_print_flags_t fmt; uint8_t *output = NULL; @@ -11688,8 +11548,8 @@ static int wdc_do_vs_nand_stats(struct nvme_dev *dev, char *format) goto out; } - ret = nvme_get_log_simple(dev_fd(dev), WDC_NVME_NAND_STATS_LOG_ID, - WDC_NVME_NAND_STATS_SIZE, (void *)output); + ret = nvme_get_log_simple(hdl, WDC_NVME_NAND_STATS_LOG_ID, + (void *)output, WDC_NVME_NAND_STATS_SIZE); if (ret) { fprintf(stderr, "ERROR: WDC: %s : Failed to retrieve NAND stats\n", __func__); goto out; @@ -11720,12 +11580,12 @@ static int wdc_do_vs_nand_stats(struct nvme_dev *dev, char *format) return ret; } -static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, +static int wdc_vs_nand_stats(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve NAND statistics."; - struct nvme_dev *dev; - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; __u64 capabilities = 0; uint32_t read_device_id = 0, read_vendor_id = 0; int ret; @@ -11743,18 +11603,21 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); + if (ret) + return ret; + + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret) return ret; - r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_NAND_STATS)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; } else { - ret = wdc_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(ctx, hdl, &read_device_id, &read_vendor_id); if (ret < 0) { fprintf(stderr, "ERROR: WDC: %s: failure to get pci ids, ret = %d\n", __func__, ret); return -1; @@ -11762,11 +11625,11 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, switch (read_device_id) { case WDC_NVME_SN820CL_DEV_ID: - ret = wdc_do_vs_nand_stats_sn810_2(dev, + ret = wdc_do_vs_nand_stats_sn810_2(hdl, cfg.output_format); break; default: - ret = wdc_do_vs_nand_stats(dev, cfg.output_format); + ret = wdc_do_vs_nand_stats(hdl, cfg.output_format); break; } } @@ -11774,12 +11637,10 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, if (ret) fprintf(stderr, "ERROR: WDC: Failure reading NAND statistics, ret = %d\n", ret); - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_do_vs_pcie_stats(struct nvme_dev *dev, +static int wdc_do_vs_pcie_stats(struct nvme_transport_handle *hdl, struct wdc_vs_pcie_stats *pcieStatsPtr) { int ret; @@ -11791,18 +11652,18 @@ static int wdc_do_vs_pcie_stats(struct nvme_dev *dev, admin_cmd.addr = (__u64)(uintptr_t)pcieStatsPtr; admin_cmd.data_len = pcie_stats_size; - ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); return ret; } -static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, +static int wdc_vs_pcie_stats(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve PCIE statistics."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t fmt; - struct nvme_dev *dev; - nvme_root_t r; int ret; __u64 capabilities = 0; _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; @@ -11822,11 +11683,14 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); + if (ret) + return ret; + + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret) return ret; - r = nvme_scan(NULL); ret = validate_output_format(cfg.output_format, &fmt); if (ret < 0) { fprintf(stderr, "ERROR: WDC: invalid output format\n"); @@ -11842,13 +11706,13 @@ 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(r, dev); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_PCIE_STATS)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; } else { - ret = wdc_do_vs_pcie_stats(dev, pcieStatsPtr); + ret = wdc_do_vs_pcie_stats(hdl, pcieStatsPtr); if (ret) { fprintf(stderr, "ERROR: WDC: Failure reading PCIE statistics, ret = 0x%x\n", ret); } else { @@ -11866,8 +11730,6 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, } } out: - nvme_free_tree(r); - dev_close(dev); return ret; } @@ -11875,10 +11737,10 @@ 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."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t fmt; - nvme_root_t r; uint64_t capabilities = 0; - struct nvme_dev *dev; int ret; __le32 result; __u16 size; @@ -11911,31 +11773,31 @@ static int wdc_vs_drive_info(int argc, char **argv, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; ret = validate_output_format(cfg.output_format, &fmt); if (ret < 0) { fprintf(stderr, "ERROR: WDC %s invalid output format\n", __func__); - dev_close(dev); return ret; } /* get the id ctrl data used to fill in drive info below */ - ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); - + ret = nvme_identify_ctrl(hdl, &ctrl); if (ret) { fprintf(stderr, "ERROR: WDC %s: Identify Controller failed\n", __func__); - dev_close(dev); return ret; } - r = nvme_scan(NULL); - wdc_check_device(r, dev); - capabilities = wdc_get_drive_capabilities(r, dev); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || !wdc_check_device(ctx, hdl)) + return -1; + + capabilities = wdc_get_drive_capabilities(ctx, hdl); + if ((capabilities & WDC_DRIVE_CAP_INFO) == WDC_DRIVE_CAP_INFO) { - ret = wdc_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(ctx, hdl, &read_device_id, &read_vendor_id); if (ret < 0) { fprintf(stderr, "ERROR: WDC: %s: failure to get pci ids, ret = %d\n", __func__, ret); goto out; @@ -11959,7 +11821,7 @@ static int wdc_vs_drive_info(int argc, char **argv, case WDC_NVME_SN550_DEV_ID: case WDC_NVME_ZN350_DEV_ID: case WDC_NVME_ZN350_DEV_ID_1: - ret = wdc_do_drive_info(dev, &result); + ret = wdc_do_drive_info(hdl, &result); if (!ret) { size = (__u16)((cpu_to_le32(result) & 0xffff0000) >> 16); @@ -12009,7 +11871,7 @@ static int wdc_vs_drive_info(int argc, char **argv, break; case WDC_NVME_SN820CL_DEV_ID: /* Get the Drive HW Rev from the C6 Log page */ - ret = nvme_get_hw_rev_log(dev_fd(dev), &data, 0, + ret = nvme_get_hw_rev_log(hdl, &data, 0, NVME_NSID_ALL); if (!ret) { struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data; @@ -12031,7 +11893,7 @@ static int wdc_vs_drive_info(int argc, char **argv, goto out; } - ret = nvme_get_ext_smart_cloud_log(dev_fd(dev), &data, + ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0, NVME_NSID_ALL); if (!ret) { @@ -12083,7 +11945,7 @@ static int wdc_vs_drive_info(int argc, char **argv, if (data_len % 4 != 0) num_dwords += 1; - ret = nvme_admin_passthru(dev_fd(dev), + ret = nvme_admin_passthru(hdl, WDC_NVME_ADMIN_VUC_OPCODE_D2, 0, 0, 0, 0, 0, num_dwords, 0, WDC_VUC_SUBOPCODE_VS_DRIVE_INFO_D2, @@ -12133,8 +11995,6 @@ static int wdc_vs_drive_info(int argc, char **argv, out: nvme_show_status(ret); - nvme_free_tree(r); - dev_close(dev); return ret; } @@ -12142,11 +12002,11 @@ static int wdc_vs_temperature_stats(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Send a vs-temperature-stats command."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct nvme_smart_log smart_log; struct nvme_id_ctrl id_ctrl; nvme_print_flags_t fmt; - struct nvme_dev *dev; - nvme_root_t r; uint64_t capabilities = 0; __u32 hctm_tmt; int temperature, temp_tmt1, temp_tmt2; @@ -12165,11 +12025,14 @@ static int wdc_vs_temperature_stats(int argc, char **argv, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); + if (ret) + return ret; + + ret = nvme_scan_topology(ctx, NULL, NULL); if (ret) return ret; - r = nvme_scan(NULL); ret = validate_output_format(cfg.output_format, &fmt); if (ret < 0) { fprintf(stderr, "ERROR: WDC: invalid output format\n"); @@ -12177,8 +12040,8 @@ static int wdc_vs_temperature_stats(int argc, char **argv, } /* check if command is supported */ - wdc_check_device(r, dev); - capabilities = wdc_get_drive_capabilities(r, dev); + wdc_check_device(ctx, hdl); + capabilities = wdc_get_drive_capabilities(ctx, hdl); if ((capabilities & WDC_DRIVE_CAP_TEMP_STATS) != WDC_DRIVE_CAP_TEMP_STATS) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; @@ -12186,11 +12049,10 @@ static int wdc_vs_temperature_stats(int argc, char **argv, } /* get the temperature stats or report errors */ - ret = nvme_identify_ctrl(dev_fd(dev), &id_ctrl); + ret = nvme_identify_ctrl(hdl, &id_ctrl); if (ret) goto out; - ret = nvme_get_log_smart(dev_fd(dev), NVME_NSID_ALL, false, - &smart_log); + ret = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log); if (ret) goto out; @@ -12198,14 +12060,15 @@ 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_features_simple(dev_fd(dev), 0x10, 0, &hctm_tmt); + nvme_get_features_simple(hdl, 0x10, + NVME_GET_FEATURES_SEL_CURRENT, &hctm_tmt); temp_tmt1 = ((hctm_tmt >> 16) & 0xffff) ? ((hctm_tmt >> 16) & 0xffff) - 273 : 0; temp_tmt2 = (hctm_tmt & 0xffff) ? (hctm_tmt & 0xffff) - 273 : 0; if (fmt == NORMAL) { /* print the temperature stats */ printf("Temperature Stats for NVME device:%s namespace-id:%x\n", - dev->name, WDC_DE_GLOBAL_NSID); + nvme_transport_handle_get_name(hdl), WDC_DE_GLOBAL_NSID); printf("Current Composite Temperature : %d °C\n", temperature); printf("WCTEMP : %"PRIu16" °C\n", id_ctrl.wctemp - 273); @@ -12251,34 +12114,34 @@ static int wdc_vs_temperature_stats(int argc, char **argv, out: nvme_show_status(ret); - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_capabilities(int argc, char **argv, struct command *command, struct plugin *plugin) +static int wdc_capabilities(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send a capabilities command."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; uint64_t capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; int ret; OPT_ARGS(opts) = { OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; /* get capabilities */ - r = nvme_scan(NULL); - wdc_check_device(r, dev); - capabilities = wdc_get_drive_capabilities(r, dev); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || !wdc_check_device(ctx, hdl)) + return -1; + + capabilities = wdc_get_drive_capabilities(ctx, hdl); /* print command and supported status */ - printf("WDC Plugin Capabilities for NVME device:%s\n", dev->name); + printf("WDC Plugin Capabilities for NVME device:%s\n", nvme_transport_handle_get_name(hdl)); printf("cap-diag : %s\n", capabilities & WDC_DRIVE_CAP_CAP_DIAG ? "Supported" : "Not Supported"); printf("drive-log : %s\n", @@ -12357,32 +12220,32 @@ static int wdc_capabilities(int argc, char **argv, struct command *command, stru printf("set-latency-monitor-feature : %s\n", capabilities & WDC_DRIVE_CAP_SET_LATENCY_MONITOR ? "Supported" : "Not Supported"); printf("capabilities : Supported\n"); - nvme_free_tree(r); - dev_close(dev); return 0; } -static int wdc_cloud_ssd_plugin_version(int argc, char **argv, struct command *command, +static int wdc_cloud_ssd_plugin_version(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get Cloud SSD Plugin Version command."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; uint64_t capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; int ret; OPT_ARGS(opts) = { OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; /* get capabilities */ - r = nvme_scan(NULL); - wdc_check_device(r, dev); - capabilities = wdc_get_drive_capabilities(r, dev); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || !wdc_check_device(ctx, hdl)) + return -1; + + capabilities = wdc_get_drive_capabilities(ctx, hdl); if ((capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION) == WDC_DRIVE_CAP_CLOUD_SSD_VERSION) { /* print command and supported status */ @@ -12391,19 +12254,17 @@ static int wdc_cloud_ssd_plugin_version(int argc, char **argv, struct command *c fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); } - nvme_free_tree(r); - dev_close(dev); return 0; } -static int wdc_cloud_boot_SSD_version(int argc, char **argv, struct command *command, +static int wdc_cloud_boot_SSD_version(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get Cloud Boot SSD Version command."; const char *namespace_id = "desired namespace id"; - nvme_root_t r; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; uint64_t capabilities = 0; - struct nvme_dev *dev; int ret; int major = 0, minor = 0; __u8 *data = NULL; @@ -12422,18 +12283,20 @@ static int wdc_cloud_boot_SSD_version(int argc, char **argv, struct command *com OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret) return ret; /* get capabilities */ - r = nvme_scan(NULL); - wdc_check_device(r, dev); - capabilities = wdc_get_drive_capabilities(r, dev); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || !wdc_check_device(ctx, hdl)) + return -1; + + capabilities = wdc_get_drive_capabilities(ctx, hdl); if ((capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION) == WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION) { /* Get the 0xC0 Smart Cloud Attribute V1 log data */ - ret = nvme_get_ext_smart_cloud_log(dev_fd(dev), &data, 0, + ret = nvme_get_ext_smart_cloud_log(hdl, &data, 0, cfg.namespace_id); ext_smart_log_ptr = (struct __packed wdc_nvme_ext_smart_log *)data; @@ -12453,18 +12316,17 @@ static int wdc_cloud_boot_SSD_version(int argc, char **argv, struct command *com fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); } - nvme_free_tree(r); - dev_close(dev); return ret; } -static int wdc_enc_get_log(int argc, char **argv, struct command *command, struct plugin *plugin) +static int wdc_enc_get_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Get Enclosure Log."; const char *file = "Output file pathname."; const char *size = "Data retrieval transfer size."; const char *log = "Enclosure Log Page ID."; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; FILE *output_fd; int xfer_size = 0; int len; @@ -12489,20 +12351,18 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command, struc OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) - goto ret; + return err; - if (!wdc_enc_check_model(dev)) { - err = -EINVAL; - goto closed_fd; - } + if (!wdc_enc_check_model(hdl)) + return -EINVAL; if (cfg.log_id > 0xff) { fprintf(stderr, "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n", cfg.log_id); - goto closed_fd; + return -EINVAL; } if (cfg.xfer_size) { @@ -12510,8 +12370,7 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command, struc if (!wdc_check_power_of_2(cfg.xfer_size)) { fprintf(stderr, "%s: ERROR: xfer-size (%d) must be a power of 2\n", __func__, cfg.xfer_size); - err = -EINVAL; - goto closed_fd; + return -EINVAL; } } @@ -12524,8 +12383,7 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command, struc if (!output_fd) { fprintf(stderr, "%s: ERROR: opening:%s: %s\n", __func__, cfg.file, strerror(errno)); - err = -EINVAL; - goto closed_fd; + return -EINVAL; } } else { output_fd = stdout; @@ -12536,12 +12394,12 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command, struc cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_4) { fprintf(stderr, "args - sz:%x logid:%x of:%s\n", xfer_size, cfg.log_id, cfg.file); - err = wdc_enc_get_nic_log(dev, cfg.log_id, xfer_size, + err = wdc_enc_get_nic_log(hdl, cfg.log_id, xfer_size, WDC_NVME_ENC_NIC_LOG_SIZE, output_fd); } else { fprintf(stderr, "args - sz:%x logid:%x of:%s\n", xfer_size, cfg.log_id, cfg.file); - err = wdc_enc_submit_move_data(dev, NULL, 0, xfer_size, output_fd, + err = wdc_enc_submit_move_data(hdl, NULL, 0, xfer_size, output_fd, cfg.log_id, 0, 0); } @@ -12553,13 +12411,10 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command, struc cfg.log_id); } } -closed_fd: - dev_close(dev); -ret: return err; } -static int wdc_enc_submit_move_data(struct nvme_dev *dev, char *cmd, int len, +static int wdc_enc_submit_move_data(struct nvme_transport_handle *hdl, char *cmd, int len, int xfer_size, FILE *out, int log_id, int cdw14, int cdw15) { @@ -12611,7 +12466,7 @@ static int wdc_enc_submit_move_data(struct nvme_dev *dev, char *cmd, int len, nvme_cmd.timeout_ms, nvme_cmd.result, md, d); #endif nvme_cmd.result = 0; - err = nvme_submit_admin_passthru(dev_fd(dev), &nvme_cmd, NULL); + err = nvme_submit_admin_passthru(hdl, &nvme_cmd, NULL); if (nvme_status_equals(err, NVME_STATUS_TYPE_NVME, NVME_SC_INTERNAL)) { fprintf(stderr, "%s: WARNING : WDC: No log ID:x%x available\n", __func__, log_id); } else if (err) { @@ -12636,7 +12491,7 @@ static int wdc_enc_submit_move_data(struct nvme_dev *dev, char *cmd, int len, nvme_cmd.cdw14 = cdw14; nvme_cmd.cdw15 = cdw15; nvme_cmd.result = 0; /* returned result !=0 indicates more data available */ - err = nvme_submit_admin_passthru(dev_fd(dev), + err = nvme_submit_admin_passthru(hdl, &nvme_cmd, NULL); if (err) { more = 0; @@ -12659,7 +12514,7 @@ static int wdc_enc_submit_move_data(struct nvme_dev *dev, char *cmd, int len, return err; } -static int wdc_enc_get_nic_log(struct nvme_dev *dev, __u8 log_id, __u32 xfer_size, __u32 data_len, FILE *out) +static int wdc_enc_get_nic_log(struct nvme_transport_handle *hdl, __u8 log_id, __u32 xfer_size, __u32 data_len, FILE *out) { __u8 *dump_data; __u32 curr_data_offset, curr_data_len; @@ -12697,7 +12552,7 @@ static int wdc_enc_get_nic_log(struct nvme_dev *dev, __u8 log_id, __u32 xfer_siz 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(dev_fd(dev), &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(hdl, &admin_cmd, NULL); if (ret) { nvme_show_status(ret); fprintf(stderr, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n", @@ -12729,17 +12584,17 @@ static int wdc_enc_get_nic_log(struct nvme_dev *dev, __u8 log_id, __u32 xfer_siz //------------------------------------------------------------------------------------ // Description: set latency monitor feature // -int wdc_set_latency_monitor_feature(int argc, char **argv, struct command *cmd, +int wdc_set_latency_monitor_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Set Latency Monitor feature."; + struct feature_latency_monitor buf = {0,}; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; uint64_t capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; - int ret; __u32 result; - struct feature_latency_monitor buf = {0,}; + int ret; const char *active_bucket_timer_threshold = "This is the value that loads the Active Bucket Timer Threshold."; @@ -12813,15 +12668,17 @@ int wdc_set_latency_monitor_feature(int argc, char **argv, struct command *cmd, OPT_END() }; - ret = parse_and_open(&dev, argc, argv, desc, opts); + ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (ret < 0) return ret; /* get capabilities */ - r = nvme_scan(NULL); - wdc_check_device(r, dev); - capabilities = wdc_get_drive_capabilities(r, dev); + ret = nvme_scan_topology(ctx, NULL, NULL); + if (ret || !wdc_check_device(ctx, hdl)) + return -1; + + capabilities = wdc_get_drive_capabilities(ctx, hdl); if (!(capabilities & WDC_DRIVE_CAP_SET_LATENCY_MONITOR)) { fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); @@ -12841,20 +12698,8 @@ int wdc_set_latency_monitor_feature(int argc, char **argv, struct command *cmd, buf.discard_debug_log = cfg.discard_debug_log; buf.latency_monitor_feature_enable = cfg.latency_monitor_feature_enable; - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = NVME_FEAT_OCP_LATENCY_MONITOR, - .nsid = 0, - .cdw12 = 0, - .save = 1, - .data_len = sizeof(struct feature_latency_monitor), - .data = (void *)&buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - - ret = nvme_set_features(&args); + ret = nvme_set_features(hdl, 0, NVME_FEAT_OCP_LATENCY_MONITOR, 1, 0, 0, 0, + 0, 0, (void *)&buf, sizeof(struct feature_latency_monitor), &result); if (ret < 0) { perror("set-feature"); @@ -13075,23 +12920,25 @@ int run_wdc_cu_smart_log(int argc, char **argv, } -__u32 run_wdc_get_fw_cust_id(nvme_root_t r, struct nvme_dev *dev) +__u32 run_wdc_get_fw_cust_id(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl) { - return wdc_get_fw_cust_id(r, dev); + return wdc_get_fw_cust_id(ctx, hdl); } -bool run_wdc_nvme_check_supported_log_page(nvme_root_t r, - struct nvme_dev *dev, +bool run_wdc_nvme_check_supported_log_page(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl, __u8 log_id, __u8 uuid_index) { - return wdc_nvme_check_supported_log_page(r, - dev, + return wdc_nvme_check_supported_log_page(ctx, + hdl, log_id, uuid_index); } -__u64 run_wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) +__u64 run_wdc_get_drive_capabilities(struct nvme_global_ctx *ctx, + struct nvme_transport_handle *hdl) { - return wdc_get_drive_capabilities(r, dev); + return wdc_get_drive_capabilities(ctx, hdl); } diff --git a/plugins/wdc/wdc-utils.c b/plugins/wdc/wdc-utils.c index 9988ff1d12..9fb708e0d7 100644 --- a/plugins/wdc/wdc-utils.c +++ b/plugins/wdc/wdc-utils.c @@ -165,20 +165,21 @@ void wdc_StrFormat(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz) } } -bool wdc_CheckUuidListSupport(struct nvme_dev *dev, struct nvme_id_uuid_list *uuid_list) +bool wdc_CheckUuidListSupport(struct nvme_transport_handle *hdl, + struct nvme_id_uuid_list *uuid_list) { - int err; struct nvme_id_ctrl ctrl; + int err; memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err) { fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", err); return false; } if ((ctrl.ctratt & NVME_CTRL_CTRATT_UUID_LIST) == NVME_CTRL_CTRATT_UUID_LIST) { - err = nvme_identify_uuid(dev_fd(dev), uuid_list); + err = nvme_identify_uuid_list(hdl, uuid_list); if (!err) return true; else if (err > 0) diff --git a/plugins/wdc/wdc-utils.h b/plugins/wdc/wdc-utils.h index 545f0675f8..1ea1ec49cc 100644 --- a/plugins/wdc/wdc-utils.h +++ b/plugins/wdc/wdc-utils.h @@ -77,4 +77,4 @@ int wdc_UtilsStrCompare(const char *pcSrc, const char *pcDst); int wdc_UtilsCreateDir(const char *path); int wdc_WriteToFile(const char *fileName, const char *buffer, unsigned int bufferLen); void wdc_StrFormat(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz); -bool wdc_CheckUuidListSupport(struct nvme_dev *dev, struct nvme_id_uuid_list *uuid_list); +bool wdc_CheckUuidListSupport(struct nvme_transport_handle *hdl, struct nvme_id_uuid_list *uuid_list); diff --git a/plugins/ymtc/ymtc-nvme.c b/plugins/ymtc/ymtc-nvme.c index 40013fe534..945b2315bf 100644 --- a/plugins/ymtc/ymtc-nvme.c +++ b/plugins/ymtc/ymtc-nvme.c @@ -21,7 +21,7 @@ static void get_ymtc_smart_info(struct nvme_ymtc_smart_log *smart, int index, u8 memcpy(raw_val, smart->itemArr[index].rawVal, RAW_SIZE); } -static int show_ymtc_smart_log(struct nvme_dev *dev, __u32 nsid, +static int show_ymtc_smart_log(struct nvme_transport_handle *hdl, __u32 nsid, struct nvme_ymtc_smart_log *smart) { struct nvme_id_ctrl ctrl; @@ -39,7 +39,7 @@ static int show_ymtc_smart_log(struct nvme_dev *dev, __u32 nsid, free(nm); return -1; } - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + err = nvme_identify_ctrl(hdl, &ctrl); if (err) { free(nm); free(raw); @@ -52,7 +52,7 @@ static int show_ymtc_smart_log(struct nvme_dev *dev, __u32 nsid, /* Table Title */ printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", - dev->name, nsid); + nvme_transport_handle_get_name(hdl), nsid); /* Column Name*/ printf("key normalized raw\n"); /* 00 SI_VD_PROGRAM_FAIL */ @@ -116,14 +116,15 @@ static int show_ymtc_smart_log(struct nvme_dev *dev, __u32 nsid, return err; } -static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_additional_smart_log(int argc, char **argv, struct command *acmd, struct plugin *plugin) { struct nvme_ymtc_smart_log smart_log; char *desc = "Get Ymtc vendor specific additional smart log (optionally, for the specified namespace), and show it."; const char *namespace = "(optional) desired namespace"; const char *raw = "dump output in binary format"; - struct nvme_dev *dev; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct config { __u32 namespace_id; bool raw_binary; @@ -140,21 +141,20 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return err; - err = nvme_get_nsid_log(dev_fd(dev), false, 0xca, cfg.namespace_id, - sizeof(smart_log), &smart_log); + err = nvme_get_nsid_log(hdl, cfg.namespace_id, false, 0xca, + &smart_log, sizeof(smart_log)); if (!err) { if (!cfg.raw_binary) - err = show_ymtc_smart_log(dev, cfg.namespace_id, &smart_log); + err = show_ymtc_smart_log(hdl, cfg.namespace_id, &smart_log); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); } if (err > 0) nvme_show_status(err); - dev_close(dev); return err; } diff --git a/plugins/zns/zns.c b/plugins/zns/zns.c index 6cf54bba4d..47656e556f 100644 --- a/plugins/zns/zns.c +++ b/plugins/zns/zns.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later +#include #include #include #include @@ -55,7 +56,7 @@ static int print_zns_list_ns(nvme_ns_t ns, struct table *t) return err; } -static int print_zns_list(nvme_root_t nvme_root, struct table *t) +static int print_zns_list(struct nvme_global_ctx *ctx, struct table *t) { int err = 0; nvme_host_t h; @@ -63,7 +64,7 @@ static int print_zns_list(nvme_root_t nvme_root, struct table *t) nvme_ctrl_t c; nvme_ns_t n; - nvme_for_each_host(nvme_root, h) { + nvme_for_each_host(ctx, h) { nvme_for_each_subsystem(h, s) { nvme_subsystem_for_each_ns(s, n) { err = print_zns_list_ns(n, t); @@ -84,11 +85,11 @@ static int print_zns_list(nvme_root_t nvme_root, struct table *t) return err; } -static int list(int argc, char **argv, struct command *cmd, +static int list(int argc, char **argv, struct command *acmd, struct plugin *plugin) { - int err = 0; - nvme_root_t nvme_root; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + int err; struct table_column columns[] = { { "Node", LEFT, 21 }, { "Generic", LEFT, 21 }, @@ -101,14 +102,19 @@ static int list(int argc, char **argv, struct command *cmd, }; struct table *t = table_init_with_columns(columns, ARRAY_SIZE(columns)); - nvme_root = nvme_scan(NULL); - if (!nvme_root) { + ctx = nvme_create_global_ctx(stdout, DEFAULT_LOGLEVEL); + if (ctx) { + fprintf(stderr, "Failed to create root object\n"); + return -ENOMEM; + } + + err = nvme_scan_topology(ctx, NULL, NULL); + if (err) { fprintf(stderr, "Failed to scan nvme subsystems\n"); - return -errno; + return err; } - err = print_zns_list(nvme_root, t); - nvme_free_tree(nvme_root); + err = print_zns_list(ctx, t); table_print(t); @@ -117,15 +123,17 @@ static int list(int argc, char **argv, struct command *cmd, return err; } -static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send a ZNS specific Identify Controller command to\n" "the given device and report information about the specified\n" "controller in various formats."; - nvme_print_flags_t flags; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; struct nvme_zns_id_ctrl ctrl; - struct nvme_dev *dev; + nvme_print_flags_t flags; int err = -1; struct config { @@ -141,27 +149,27 @@ static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *pl OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return errno; err = validate_output_format(cfg.output_format, &flags); if (err < 0) - goto close_dev; + return err; - err = nvme_zns_identify_ctrl(dev_fd(dev), &ctrl); + nvme_init_zns_identify_ctrl(&cmd, &ctrl); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) nvme_show_zns_id_ctrl(&ctrl, flags); else if (err > 0) nvme_show_status(err); else perror("zns identify controller"); -close_dev: - dev_close(dev); + return err; } -static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int id_ns(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Send a ZNS specific Identify Namespace command to\n" "the given device and report information about the specified\n" @@ -169,10 +177,11 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug const char *vendor_specific = "dump binary vendor fields"; const char *human_readable = "show identify in readable format"; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; struct nvme_zns_id_ns ns; struct nvme_id_ns id_ns; - struct nvme_dev *dev; int err = -1; struct config { @@ -194,53 +203,54 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return errno; err = validate_output_format(cfg.output_format, &flags); if (err < 0) - goto close_dev; + return err; if (cfg.vendor_specific) flags |= VS; if (cfg.human_readable) flags |= VERBOSE; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_dev; + return err; } } - err = nvme_identify_ns(dev_fd(dev), cfg.namespace_id, &id_ns); + err = nvme_identify_ns(hdl, cfg.namespace_id, &id_ns); if (err) { nvme_show_status(err); - goto close_dev; + return err; } - err = nvme_zns_identify_ns(dev_fd(dev), cfg.namespace_id, &ns); + err = nvme_zns_identify_ns(hdl, cfg.namespace_id, &ns); if (!err) nvme_show_zns_id_ns(&ns, &id_ns, flags); else if (err > 0) nvme_show_status(err); else perror("zns identify namespace"); -close_dev: - dev_close(dev); + return err; } -static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plugin *plugin, +static int zns_mgmt_send(int argc, char **argv, struct command *acmd, struct plugin *plugin, const char *desc, enum nvme_zns_send_action zsa) { const char *zslba = "starting LBA of the zone for this command"; const char *select_all = "send command to all zones"; const char *timeout = "timeout value, in milliseconds"; - struct nvme_dev *dev; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_passthru_cmd cmd; int err, zcapc = 0; - char *command; + char *cmdstr; __u32 result; struct config { @@ -260,42 +270,31 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) - goto ret; + return err; - err = asprintf(&command, "%s-%s", plugin->name, cmd->name); + err = asprintf(&cmdstr, "%s-%s", plugin->name, acmd->name); if (err < 0) - goto close_dev; + return err; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); goto free; } } - struct nvme_zns_mgmt_send_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .slba = cfg.zslba, - .zsa = zsa, - .select_all = cfg.select_all, - .zsaso = 0, - .data_len = 0, - .data = NULL, - .timeout = cfg.timeout, - .result = &result, - }; - err = nvme_zns_mgmt_send(&args); + nvme_init_zns_mgmt_send(&cmd, cfg.namespace_id, cfg.zslba, zsa, + cfg.select_all, 0, 0, NULL, 0); + err = nvme_submit_admin_passthru(hdl, &cmd, &result); if (!err) { if (zsa == NVME_ZNS_ZSA_RESET) zcapc = result & 0x1; printf("%s: Success, action:%d zone:%"PRIx64" all:%d zcapc:%u nsid:%d\n", - command, zsa, (uint64_t)cfg.zslba, (int)cfg.select_all, + cmdstr, zsa, (uint64_t)cfg.zslba, (int)cfg.select_all, zcapc, cfg.namespace_id); } else if (err > 0) { nvme_show_status(err); @@ -303,21 +302,18 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug perror(desc); } free: - free(command); -close_dev: - dev_close(dev); -ret: + free(cmdstr); return err; } -static int get_zdes_bytes(int fd, __u32 nsid) +static int get_zdes_bytes(struct nvme_transport_handle *hdl, __u32 nsid) { struct nvme_zns_id_ns ns; struct nvme_id_ns id_ns; __u8 lbaf; int err; - err = nvme_identify_ns(fd, nsid, &id_ns); + err = nvme_identify_ns(hdl, nsid, &id_ns); if (err > 0) { nvme_show_status(err); return -1; @@ -326,7 +322,7 @@ static int get_zdes_bytes(int fd, __u32 nsid) return -1; } - err = nvme_zns_identify_ns(fd, nsid, &ns); + err = nvme_zns_identify_ns(hdl, nsid, &ns); if (err > 0) { nvme_show_status(err); return -1; @@ -339,7 +335,7 @@ static int get_zdes_bytes(int fd, __u32 nsid) return ns.lbafe[lbaf].zdes << 6; } -static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int zone_mgmt_send(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Zone Management Send"; const char *zslba = @@ -351,8 +347,10 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu const char *data = "optional file for data (default stdin)"; const char *timeout = "timeout value, in milliseconds"; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; int ffd = STDIN_FILENO, err = -1; - struct nvme_dev *dev; + struct nvme_passthru_cmd cmd; void *buf = NULL; struct config { @@ -380,41 +378,39 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return errno; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_dev; + return err; } } if (!cfg.zsa) { fprintf(stderr, "zone send action must be specified\n"); - err = -EINVAL; - goto close_dev; + return -EINVAL; } if (cfg.zsa == NVME_ZNS_ZSA_SET_DESC_EXT) { if (!cfg.data_len) { - int data_len = get_zdes_bytes(dev_fd(dev), + int data_len = get_zdes_bytes(hdl, cfg.namespace_id); if (data_len == 0) { fprintf(stderr, "Zone Descriptor Extensions are not supported\n"); - goto close_dev; + return -EINVAL; } else if (data_len < 0) { - err = data_len; - goto close_dev; + return data_len; } cfg.data_len = data_len; } if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { fprintf(stderr, "can not allocate feature payload\n"); - goto close_dev; + return -ENOMEM; } memset(buf, 0, cfg.data_len); @@ -434,25 +430,14 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu } else { if (cfg.file || cfg.data_len) { fprintf(stderr, "data, data_len only valid with set extended descriptor\n"); - err = -EINVAL; - goto close_dev; + return -EINVAL; } } - struct nvme_zns_mgmt_send_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .slba = cfg.zslba, - .zsa = cfg.zsa, - .select_all = cfg.select_all, - .zsaso = cfg.zsaso, - .data_len = cfg.data_len, - .data = buf, - .timeout = cfg.timeout, - .result = NULL, - }; - err = nvme_zns_mgmt_send(&args); + nvme_init_zns_mgmt_send(&cmd, cfg.namespace_id, cfg.zslba, cfg.zsa, + cfg.select_all, cfg.zsaso, 0, buf, + cfg.data_len); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) printf("zone-mgmt-send: Success, action:%d zone:%"PRIx64" all:%d nsid:%d\n", cfg.zsa, (uint64_t)cfg.zslba, (int)cfg.select_all, cfg.namespace_id); @@ -466,33 +451,33 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu close(ffd); free: free(buf); -close_dev: - dev_close(dev); return err; } -static int close_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int close_zone(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Close zones\n"; - return zns_mgmt_send(argc, argv, cmd, plugin, desc, NVME_ZNS_ZSA_CLOSE); + return zns_mgmt_send(argc, argv, acmd, plugin, desc, NVME_ZNS_ZSA_CLOSE); } -static int finish_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int finish_zone(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Finish zones\n"; - return zns_mgmt_send(argc, argv, cmd, plugin, desc, NVME_ZNS_ZSA_FINISH); + return zns_mgmt_send(argc, argv, acmd, plugin, desc, NVME_ZNS_ZSA_FINISH); } -static int open_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int open_zone(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Open zones\n"; const char *zslba = "starting LBA of the zone for this command"; const char *zrwaa = "Allocate Zone Random Write Area to zone"; const char *select_all = "send command to all zones"; const char *timeout = "timeout value, in milliseconds"; - struct nvme_dev *dev; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_passthru_cmd cmd; int err; struct config { @@ -515,57 +500,48 @@ static int open_zone(int argc, char **argv, struct command *cmd, struct plugin * OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return errno; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_dev; + return err; } } - struct nvme_zns_mgmt_send_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .slba = cfg.zslba, - .zsa = NVME_ZNS_ZSA_OPEN, - .select_all = cfg.select_all, - .zsaso = cfg.zrwaa, - .data_len = 0, - .data = NULL, - .timeout = cfg.timeout, - .result = NULL, - }; - err = nvme_zns_mgmt_send(&args); + nvme_init_zns_mgmt_send(&cmd, cfg.namespace_id, cfg.zslba, + NVME_ZNS_ZSA_OPEN, cfg.select_all, cfg.zrwaa, 0, + NULL, 0); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) printf("zns-open-zone: Success zone slba:%"PRIx64" nsid:%d\n", (uint64_t)cfg.zslba, cfg.namespace_id); - else + else if (err > 0) nvme_show_status(err); -close_dev: - dev_close(dev); + else + perror("zns open-zone"); + return err; } -static int reset_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int reset_zone(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Reset zones\n"; - return zns_mgmt_send(argc, argv, cmd, plugin, desc, NVME_ZNS_ZSA_RESET); + return zns_mgmt_send(argc, argv, acmd, plugin, desc, NVME_ZNS_ZSA_RESET); } -static int offline_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int offline_zone(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Offline zones\n"; - return zns_mgmt_send(argc, argv, cmd, plugin, desc, NVME_ZNS_ZSA_OFFLINE); + return zns_mgmt_send(argc, argv, acmd, plugin, desc, NVME_ZNS_ZSA_OFFLINE); } -static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int set_zone_desc(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Set Zone Descriptor Extension\n"; const char *zslba = "starting LBA of the zone for this command"; @@ -573,8 +549,10 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug const char *data = "optional file for zone extension data (default stdin)"; const char *timeout = "timeout value, in milliseconds"; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_passthru_cmd cmd; int ffd = STDIN_FILENO, err; - struct nvme_dev *dev; void *buf = NULL; int data_len; @@ -597,33 +575,30 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return errno; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_dev; + return err; } } - data_len = get_zdes_bytes(dev_fd(dev), cfg.namespace_id); + data_len = get_zdes_bytes(hdl, cfg.namespace_id); if (!data_len || data_len < 0) { fprintf(stderr, "zone format does not provide descriptor extension\n"); - errno = EINVAL; - err = -1; - goto close_dev; + return -EINVAL; } buf = calloc(1, data_len); if (!buf) { perror("could not alloc memory for zone desc"); - err = -ENOMEM; - goto close_dev; + return -ENOMEM; } if (cfg.file) { @@ -641,20 +616,10 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug goto close_ffd; } - struct nvme_zns_mgmt_send_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .slba = cfg.zslba, - .zsa = NVME_ZNS_ZSA_SET_DESC_EXT, - .select_all = 0, - .zsaso = cfg.zrwaa, - .data_len = data_len, - .data = buf, - .timeout = cfg.timeout, - .result = NULL, - }; - err = nvme_zns_mgmt_send(&args); + nvme_init_zns_mgmt_send(&cmd, cfg.namespace_id, cfg.zslba, + NVME_ZNS_ZSA_SET_DESC_EXT, 0, cfg.zrwaa, 0, buf, + data_len); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) printf("set-zone-desc: Success, zone:%"PRIx64" nsid:%d\n", (uint64_t)cfg.zslba, cfg.namespace_id); @@ -667,18 +632,19 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug close(ffd); free: free(buf); -close_dev: - dev_close(dev); + return err; } -static int zrwa_flush_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int zrwa_flush_zone(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Flush Explicit ZRWA Range"; const char *slba = "LBA to flush up to"; const char *timeout = "timeout value, in milliseconds"; - struct nvme_dev *dev; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_passthru_cmd cmd; int err; struct config { @@ -696,43 +662,33 @@ static int zrwa_flush_zone(int argc, char **argv, struct command *cmd, struct pl OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return errno; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_dev; + return err; } } - struct nvme_zns_mgmt_send_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .slba = cfg.lba, - .zsa = NVME_ZNS_ZSA_ZRWA_FLUSH, - .select_all = 0, - .zsaso = 0, - .data_len = 0, - .data = NULL, - .timeout = cfg.timeout, - .result = NULL, - }; - err = nvme_zns_mgmt_send(&args); + nvme_init_zns_mgmt_send(&cmd, cfg.namespace_id, cfg.lba, + NVME_ZNS_ZSA_ZRWA_FLUSH, 0, 0, 0, NULL, 0); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) printf("zrwa-flush-zone: Success, lba:%"PRIx64" nsid:%d\n", (uint64_t)cfg.lba, cfg.namespace_id); - else + else if (err > 0) nvme_show_status(err); -close_dev: - dev_close(dev); + else + perror("zns zrwa-flush-zone"); + return err; } -static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int zone_mgmt_recv(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Zone Management Receive"; const char *zslba = "starting LBA of the zone"; @@ -741,8 +697,10 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu const char *partial = "Zone Receive Action Specific Features(Partial Report)"; const char *data_len = "length of data in bytes"; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; - struct nvme_dev *dev; void *data = NULL; int err = -1; @@ -771,50 +729,37 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return errno; err = validate_output_format(cfg.output_format, &flags); if (err < 0) - goto close_dev; + return err; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_dev; + return err; } } if (cfg.zra == NVME_ZNS_ZRA_REPORT_ZONES && !cfg.data_len) { fprintf(stderr, "error: data len is needed for NVME_ZRA_ZONE_REPORT\n"); - err = -EINVAL; - goto close_dev; + return -EINVAL; } if (cfg.data_len) { data = calloc(1, cfg.data_len); if (!data) { perror("could not alloc memory for zone mgmt receive data"); - err = -ENOMEM; - goto close_dev; + return -ENOMEM; } } - struct nvme_zns_mgmt_recv_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .slba = cfg.zslba, - .zra = cfg.zra, - .zrasf = cfg.zrasf, - .zras_feat = cfg.partial, - .data_len = cfg.data_len, - .data = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - err = nvme_zns_mgmt_recv(&args); + nvme_init_zns_mgmt_recv(&cmd, cfg.namespace_id, cfg.zslba, cfg.zra, + cfg.zrasf, cfg.partial, data, cfg.data_len); + err = nvme_submit_admin_passthru(hdl, &cmd, NULL); if (!err) printf("zone-mgmt-recv: Success, action:%d zone:%"PRIx64" nsid:%d\n", cfg.zra, (uint64_t)cfg.zslba, cfg.namespace_id); @@ -824,12 +769,11 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu perror("zns zone-mgmt-recv"); free(data); -close_dev: - dev_close(dev); + return err; } -static int report_zones(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int report_zones(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve the Report Zones data structure"; const char *zslba = "starting LBA of the zone"; @@ -839,12 +783,14 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi const char *part = "set to use the partial report"; const char *verbose = "show report zones verbosity"; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; + struct nvme_zone_report *report, *buff; + struct nvme_passthru_cmd cmd; nvme_print_flags_t flags; int zdes = 0, err = -1; - struct nvme_dev *dev; __u32 report_size; - struct nvme_zone_report *report, *buff; - _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; unsigned int nr_zones_chunks = 1024, /* 1024 entries * 64 bytes per entry = 64k byte transfer */ nr_zones_retrieved = 0, @@ -886,59 +832,55 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return errno; err = validate_output_format(cfg.output_format, &flags); if (err < 0) - goto close_dev; + return err; if (cfg.verbose) flags |= VERBOSE; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_dev; + return err; } } if (cfg.extended) { - zdes = get_zdes_bytes(dev_fd(dev), cfg.namespace_id); - if (zdes < 0) { - err = zdes; - goto close_dev; - } + zdes = get_zdes_bytes(hdl, cfg.namespace_id); + if (zdes < 0) + return zdes; } - err = nvme_identify_ns(dev_fd(dev), cfg.namespace_id, &id_ns); + err = nvme_identify_ns(hdl, cfg.namespace_id, &id_ns); if (err) { nvme_show_status(err); - goto close_dev; + return err; } - err = nvme_zns_identify_ns(dev_fd(dev), cfg.namespace_id, &id_zns); + err = nvme_zns_identify_ns(hdl, cfg.namespace_id, &id_zns); if (!err) { /* get zsze field from zns id ns data - needed for offset calculation */ nvme_id_ns_flbas_to_lbaf_inuse(id_ns.flbas, &lbaf); zsze = le64_to_cpu(id_zns.lbafe[lbaf].zsze); } else { nvme_show_status(err); - goto close_dev; + return err; } log_len = sizeof(struct nvme_zone_report); buff = calloc(1, log_len); if (!buff) { - err = -ENOMEM; - goto close_dev; + return -ENOMEM; } - err = nvme_zns_report_zones(dev_fd(dev), cfg.namespace_id, 0, - cfg.state, false, false, - log_len, buff, - NVME_DEFAULT_IOCTL_TIMEOUT, NULL); + nvme_init_zns_report_zones(&cmd, cfg.namespace_id, 0, cfg.state, false, + false, buff, log_len); + err = nvme_submit_io_passthru(hdl, &cmd, NULL); if (err > 0) { nvme_show_status(err); goto free_buff; @@ -962,8 +904,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi report = nvme_alloc_huge(report_size, &mh); if (!report) { perror("alloc"); - err = -ENOMEM; - goto close_dev; + return -ENOMEM; } offset = cfg.zslba; @@ -979,15 +920,15 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi log_len = sizeof(struct nvme_zone_report) + ((sizeof(struct nvme_zns_desc) * nr_zones_chunks) + (nr_zones_chunks * zdes)); } - err = nvme_zns_report_zones(dev_fd(dev), cfg.namespace_id, - offset, - cfg.state, cfg.extended, - cfg.partial, log_len, report, - NVME_DEFAULT_IOCTL_TIMEOUT, NULL); + nvme_init_zns_report_zones(&cmd, cfg.namespace_id, offset, + cfg.state, cfg.extended, cfg.partial, + report, log_len); + err = nvme_submit_io_passthru(hdl, &cmd, NULL); if (err > 0) { nvme_show_status(err); break; } + // QUESTION: should we also check for < 0 here? if (!err) nvme_show_zns_report_zones(report, nr_zones_chunks, @@ -1001,12 +942,11 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi free_buff: free(buff); -close_dev: - dev_close(dev); + return err; } -static int zone_append(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int zone_append(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "The zone append command is used to write to a zone\n" "using the slba of the zone, and the write will be appended from the\n" @@ -1018,21 +958,21 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin const char *fua = "force unit access"; const char *prinfo = "protection information action and checks field"; const char *piremap = "protection information remap (for type 1 PI)"; - const char *ref_tag = "reference tag for end-to-end PI"; - const char *lbat = "logical block application tag for end-to-end PI"; - const char *lbatm = "logical block application tag mask for end-to-end PI"; const char *metadata_size = "size of metadata in bytes"; const char *data_size = "size of data in bytes"; const char *latency = "output latency statistics"; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; int err = -1, dfd = STDIN_FILENO, mfd = STDIN_FILENO; + struct timeval start_time, end_time; unsigned int lba_size, meta_size; void *buf = NULL, *mbuf = NULL; + struct nvme_passthru_cmd64 cmd; __u16 nblocks, control = 0; - struct nvme_dev *dev; - __u64 result; + __u16 cev = 0, dspec = 0; __u8 lba_index; - struct timeval start_time, end_time; + __u64 result; struct nvme_id_ns ns; @@ -1045,9 +985,6 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin bool limited_retry; bool fua; __u32 namespace_id; - __u64 ref_tag; - __u16 lbat; - __u16 lbatm; __u8 prinfo; bool piremap; bool latency; @@ -1064,37 +1001,33 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin OPT_FILE("metadata", 'M', &cfg.metadata, metadata), OPT_FLAG("limited-retry", 'l', &cfg.limited_retry, limited_retry), OPT_FLAG("force-unit-access", 'f', &cfg.fua, fua), - OPT_SUFFIX("ref-tag", 'r', &cfg.ref_tag, ref_tag), - OPT_SHRT("app-tag-mask", 'm', &cfg.lbatm, lbatm), - OPT_SHRT("app-tag", 'a', &cfg.lbat, lbat), OPT_BYTE("prinfo", 'p', &cfg.prinfo, prinfo), OPT_FLAG("piremap", 'P', &cfg.piremap, piremap), OPT_FLAG("latency", 't', &cfg.latency, latency), OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return errno; if (!cfg.data_size) { fprintf(stderr, "Append size not provided\n"); - errno = EINVAL; - goto close_dev; + return -EINVAL; } if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_dev; + return err;; } } - err = nvme_identify_ns(dev_fd(dev), cfg.namespace_id, &ns); + err = nvme_identify_ns(hdl, cfg.namespace_id, &ns); if (err) { nvme_show_status(err); - goto close_dev; + return err; } nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &lba_index); @@ -1103,8 +1036,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin fprintf(stderr, "Data size:%#"PRIx64" not aligned to lba size:%#x\n", (uint64_t)cfg.data_size, lba_size); - errno = EINVAL; - goto close_dev; + return -EINVAL; } meta_size = ns.lbaf[lba_index].ms; @@ -1113,21 +1045,19 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin fprintf(stderr, "Metadata size:%#"PRIx64" not aligned to metadata size:%#x\n", (uint64_t)cfg.metadata_size, meta_size); - errno = EINVAL; - goto close_dev; + return -EINVAL; } if (cfg.prinfo > 0xf) { fprintf(stderr, "Invalid value for prinfo:%#x\n", cfg.prinfo); - errno = EINVAL; - goto close_dev; + return -EINVAL; } if (cfg.data) { dfd = open(cfg.data, O_RDONLY); if (dfd < 0) { perror(cfg.data); - goto close_dev; + return -errno; } } @@ -1178,26 +1108,11 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin if (cfg.piremap) control |= NVME_IO_ZNS_APPEND_PIREMAP; - struct nvme_zns_append_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .nsid = cfg.namespace_id, - .zslba = cfg.zslba, - .nlb = nblocks, - .control = control, - .ilbrt_u64 = cfg.ref_tag, - .lbat = cfg.lbat, - .lbatm = cfg.lbatm, - .data_len = cfg.data_size, - .data = buf, - .metadata_len = cfg.metadata_size, - .metadata = mbuf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - gettimeofday(&start_time, NULL); - err = nvme_zns_append(&args); + nvme_init_zns_append(&cmd, cfg.namespace_id, cfg.zslba, nblocks, + control, cev, dspec, buf, cfg.data_size, mbuf, + cfg.metadata_size); + err = nvme_submit_admin_passthru64(hdl, &cmd, &result); gettimeofday(&end_time, NULL); if (cfg.latency) printf(" latency: zone append: %llu us\n", @@ -1220,19 +1135,19 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin close_dfd: if (cfg.data) close(dfd); -close_dev: - dev_close(dev); + return err; } -static int changed_zone_list(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int changed_zone_list(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Retrieve Changed Zone log for the given device"; const char *rae = "retain an asynchronous event"; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; + _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; struct nvme_zns_changed_zone_log log; nvme_print_flags_t flags; - struct nvme_dev *dev; int err = -1; struct config { @@ -1252,23 +1167,23 @@ static int changed_zone_list(int argc, char **argv, struct command *cmd, struct OPT_END() }; - err = parse_and_open(&dev, argc, argv, desc, opts); + err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) return errno; err = validate_output_format(cfg.output_format, &flags); if (err < 0) - goto close_dev; + return err; if (!cfg.namespace_id) { - err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + err = nvme_get_nsid(hdl, &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_dev; + return err; } } - err = nvme_get_log_zns_changed_zones(dev_fd(dev), cfg.namespace_id, + err = nvme_get_log_zns_changed_zones(hdl, cfg.namespace_id, cfg.rae, &log); if (!err) nvme_show_zns_changed(&log, flags); @@ -1277,7 +1192,5 @@ static int changed_zone_list(int argc, char **argv, struct command *cmd, struct else perror("zns changed-zone-list"); -close_dev: - dev_close(dev); return err; } diff --git a/scripts/build.sh b/scripts/build.sh index 4c2d21126a..9d8ac782df 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -260,6 +260,7 @@ config_meson_distro() { --prefix="${BUILDDIR}/usr" \ --werror \ --buildtype="${BUILDTYPE}" \ + --force-fallback-for= \ "${BUILDDIR}" } diff --git a/types.h b/types.h new file mode 100644 index 0000000000..2b976d046f --- /dev/null +++ b/types.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef TYPES_H +#define TYPES_H + +#include "nvme/types.h" + +/** + * struct nvme_get_log_args - Arguments for the NVMe Admin Get Log command + * @nsid: Namespace identifier, if applicable + * @rae: Retain asynchronous events + * @lsp: Log specific field + * @lid: Log page identifier, see &enum nvme_cmd_get_log_lid for known + * values + * @lsi: Log Specific Identifier + * @csi: Command set identifier, see &enum nvme_csi for known values + * @ot: Offset Type; if set @lpo specifies the index into the list + * of data structures, otherwise @lpo specifies the byte offset + * into the log page. + * @uidx: UUID selection, if supported + * @lpo: Log page offset for partial log transfers + * @log: User space destination address to transfer the data + * @len: Length of provided user buffer to hold the log data in bytes + * @result: The command completion result from CQE dword0 + */ +struct nvme_get_log_args { + __u32 nsid; + bool rae; + __u8 lsp; + enum nvme_cmd_get_log_lid lid; + __u16 lsi; + enum nvme_csi csi; + bool ot; + __u8 uidx; + __u64 lpo; + void *log; + __u32 len; + __u32 *result; +}; + +#endif diff --git a/util/cleanup.h b/util/cleanup.h index ff26cda3e9..bb11d32842 100644 --- a/util/cleanup.h +++ b/util/cleanup.h @@ -36,11 +36,11 @@ static inline void cleanup_fd(int *fd) } #define _cleanup_fd_ __cleanup__(cleanup_fd) -static inline void cleanup_nvme_root(nvme_root_t *r) +static inline void cleanup_nvme_global_ctx(struct nvme_global_ctx **ctx) { - nvme_free_tree(*r); + nvme_free_global_ctx(*ctx); } -#define _cleanup_nvme_root_ __cleanup__(cleanup_nvme_root) +#define _cleanup_nvme_global_ctx_ __cleanup__(cleanup_nvme_global_ctx) static inline DEFINE_CLEANUP_FUNC(cleanup_nvme_ctrl, nvme_ctrl_t, nvme_free_ctrl) #define _cleanup_nvme_ctrl_ __cleanup__(cleanup_nvme_ctrl)