From: Klaus Jensen Date: Wed, 29 Sep 2021 18:20:23 +0000 (+0200) Subject: linux: move linux specific stuff from util.{c,h} X-Git-Tag: v1.0-rc0~73^2~1 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=018e4af269b52f6ea7f8d6321ce19a57c59f0d9e;p=users%2Fsagi%2Flibnvme.git linux: move linux specific stuff from util.{c,h} Add the nvme/linux.h header for Linux specific helpers. This leaves util.{c,h} with only system-agnostic utilities. Signed-off-by: Klaus Jensen --- diff --git a/src/Makefile b/src/Makefile index 2f269e43..23372b0b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -48,8 +48,8 @@ libccan_sobjs := $(patsubst %.c,%.os,$(libccan_srcs)) $(libccan_objs) $(libccan_sobjs): $(libccan_headers) $(CCANDIR)config.h libnvme_priv := nvme/private.h -libnvme_api := libnvme.h nvme/types.h nvme/ioctl.h nvme/filters.h nvme/tree.h nvme/util.h nvme/fabrics.h nvme/log.h -libnvme_srcs := nvme/ioctl.c nvme/filters.c nvme/fabrics.c nvme/util.c nvme/tree.c nvme/log.c nvme/cleanup.c +libnvme_api := libnvme.h nvme/types.h nvme/linux.h nvme/ioctl.h nvme/filters.h nvme/tree.h nvme/util.h nvme/fabrics.h nvme/log.h +libnvme_srcs := nvme/linux.c nvme/ioctl.c nvme/filters.c nvme/fabrics.c nvme/util.c nvme/tree.c nvme/log.c nvme/cleanup.c ifeq ($(CONFIG_JSONC),y) override LDFLAGS += $(shell pkg-config --libs json-c) override CFLAGS += $(shell pkg-config --cflags json-c) diff --git a/src/libnvme.h b/src/libnvme.h index 00b1211e..6be90581 100644 --- a/src/libnvme.h +++ b/src/libnvme.h @@ -15,6 +15,7 @@ extern "C" { #endif #include "nvme/types.h" +#include "nvme/linux.h" #include "nvme/ioctl.h" #include "nvme/fabrics.h" #include "nvme/filters.h" diff --git a/src/meson.build b/src/meson.build index 2b8fa638..10acb15e 100644 --- a/src/meson.build +++ b/src/meson.build @@ -10,6 +10,7 @@ sources = [ 'nvme/fabrics.c', 'nvme/filters.c', 'nvme/ioctl.c', + 'nvme/linux.c', 'nvme/log.c', 'nvme/tree.c', 'nvme/util.c', diff --git a/src/nvme/fabrics.c b/src/nvme/fabrics.c index 21dec686..d96f09e9 100644 --- a/src/nvme/fabrics.c +++ b/src/nvme/fabrics.c @@ -29,6 +29,7 @@ #include #include "fabrics.h" +#include "linux.h" #include "ioctl.h" #include "util.h" #include "log.h" diff --git a/src/nvme/fabrics.h b/src/nvme/fabrics.h index 10ac2e29..9b796be5 100644 --- a/src/nvme/fabrics.h +++ b/src/nvme/fabrics.h @@ -182,4 +182,15 @@ 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); +/** + * nvme_chomp() - Strip trailing white space + * &s: String to strip + * @l: Maximum length of string + */ +static inline void nvme_chomp(char *s, int l) +{ + while (l && (s[l] == '\0' || s[l] == ' ')) + s[l--] = '\0'; +} + #endif /* _LIBNVME_FABRICS_H */ diff --git a/src/nvme/linux.c b/src/nvme/linux.c new file mode 100644 index 00000000..90b9b5ce --- /dev/null +++ b/src/nvme/linux.c @@ -0,0 +1,382 @@ +// 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 + * Chaitanya Kulkarni + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "linux.h" +#include "tree.h" +#include "log.h" + +static int __nvme_open(const char *name) +{ + char *path; + int fd, ret; + + ret = asprintf(&path, "%s/%s", "/dev", name); + if (ret < 0) { + errno = ENOMEM; + return -1; + } + + fd = open(path, O_RDONLY); + free(path); + return fd; +} + +int nvme_open(const char *name) +{ + int ret, fd, id, ns; + struct stat stat; + bool c; + + ret = sscanf(name, "nvme%dn%d", &id, &ns); + if (ret != 1 && ret != 2) { + errno = EINVAL; + return -1; + } + c = ret == 1; + + fd = __nvme_open(name); + if (fd < 0) + return fd; + + ret = fstat(fd, &stat); + if (ret < 0) + goto close_fd; + + 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; + } + + return fd; + +close_fd: + close(fd); + return -1; +} + +int nvme_fw_download_seq(int fd, __u32 size, __u32 xfer, __u32 offset, + void *buf) +{ + int err = 0; + + while (size > 0) { + xfer = MIN(xfer, size); + err = nvme_fw_download(fd, offset, xfer, buf); + if (err) + break; + + buf += xfer; + size -= xfer; + offset += xfer; + } + + return err; +} + +int __nvme_get_log_page(int fd, __u32 nsid, __u8 log_id, bool rae, + __u32 xfer_len, __u32 data_len, void *data) +{ + __u64 offset = 0, xfer; + bool retain = true; + void *ptr = data; + int ret; + + /* + * 4k is the smallest possible transfer unit, so restricting to 4k + * avoids having to check the MDTS value of the controller. + */ + do { + xfer = data_len - offset; + if (xfer > xfer_len) + xfer = xfer_len; + + /* + * Always retain regardless of the RAE parameter until the very + * last portion of this log page so the data remains latched + * during the fetch sequence. + */ + if (offset + xfer == data_len) + retain = rae; + + ret = nvme_get_log(fd, log_id, nsid, offset, NVME_LOG_LSP_NONE, + NVME_LOG_LSI_NONE, retain, NVME_UUID_NONE, + NVME_CSI_NVM, xfer, ptr); + if (ret) + return ret; + + offset += xfer; + ptr += xfer; + } while (offset < data_len); + + return 0; +} + +int nvme_get_log_page(int fd, __u32 nsid, __u8 log_id, bool rae, + __u32 data_len, void *data) +{ + return __nvme_get_log_page(fd, nsid, log_id, rae, 4096, data_len, data); +} + +static int nvme_get_telemetry_log(int fd, bool create, bool ctrl, bool rae, + struct nvme_telemetry_log **buf) +{ + static const __u32 xfer = NVME_LOG_TELEM_BLOCK_SIZE; + + struct nvme_telemetry_log *telem; + enum nvme_cmd_get_log_lid lid; + void *log, *tmp; + __u32 size; + int err; + + log = malloc(xfer); + if (!log) { + errno = ENOMEM; + return -1; + } + + if (ctrl) { + err = nvme_get_log_telemetry_ctrl(fd, true, 0, xfer, log); + lid = NVME_LOG_LID_TELEMETRY_CTRL; + } else { + lid = NVME_LOG_LID_TELEMETRY_HOST; + if (create) + err = nvme_get_log_create_telemetry_host(fd, log); + else + err = nvme_get_log_telemetry_host(fd, 0, xfer, log); + } + + if (err) + goto free; + + telem = log; + if (ctrl && !telem->ctrlavail) { + *buf = log; + return 0; + } + + /* dalb3 >= dalb2 >= dalb1 */ + size = (le16_to_cpu(telem->dalb3) + 1) * xfer; + tmp = realloc(log, size); + if (!tmp) { + errno = ENOMEM; + err = -1; + goto free; + } + log = tmp; + + err = nvme_get_log_page(fd, NVME_NSID_NONE, lid, rae, size, (void *)log); + if (!err) { + *buf = log; + return 0; + } +free: + free(log); + return err; +} + +int nvme_get_ctrl_telemetry(int fd, bool rae, struct nvme_telemetry_log **log) +{ + return nvme_get_telemetry_log(fd, false, true, rae, log); +} + +int nvme_get_host_telemetry(int fd, struct nvme_telemetry_log **log) +{ + return nvme_get_telemetry_log(fd, false, false, false, log); +} + +int nvme_get_new_host_telemetry(int fd, struct nvme_telemetry_log **log) +{ + return nvme_get_telemetry_log(fd, true, false, false, log); +} + +int nvme_get_lba_status_log(int fd, bool rae, struct nvme_lba_status_log **log) +{ + __u32 size = sizeof(struct nvme_lba_status_log); + void *buf, *tmp; + int err; + + buf = malloc(size); + if (!buf) + return -1; + + *log = buf; + err = nvme_get_log_lba_status(fd, true, 0, size, buf); + if (err) + goto free; + + size = le32_to_cpu((*log)->lslplen); + if (!size) + return 0; + + tmp = realloc(buf, size); + if (!tmp) { + err = -1; + goto free; + } + buf = tmp; + *log = buf; + + err = nvme_get_log_page(fd, NVME_NSID_NONE, NVME_LOG_LID_LBA_STATUS, + rae, size, buf); + if (!err) + return 0; + +free: + *log = NULL; + free(buf); + return err; +} + +static int nvme_ns_attachment(int fd, __u32 nsid, __u16 num_ctrls, + __u16 *ctrlist, bool attach) +{ + enum nvme_ns_attach_sel sel = NVME_NS_ATTACH_SEL_CTRL_DEATTACH; + struct nvme_ctrl_list cntlist = { 0 }; + + if (attach) + sel = NVME_NS_ATTACH_SEL_CTRL_ATTACH; + + nvme_init_ctrl_list(&cntlist, num_ctrls, ctrlist); + return nvme_ns_attach(fd, nsid, sel, &cntlist); +} + +int nvme_namespace_attach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, + __u16 *ctrlist) +{ + return nvme_ns_attachment(fd, nsid, num_ctrls, ctrlist, true); +} + +int nvme_namespace_detach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, + __u16 *ctrlist) +{ + return nvme_ns_attachment(fd, nsid, num_ctrls, ctrlist, false); +} + +int nvme_get_ana_log_len(int fd, size_t *analen) +{ + struct nvme_id_ctrl ctrl; + int ret; + + ret = nvme_identify_ctrl(fd, &ctrl); + if (ret) + return ret; + + *analen = sizeof(struct nvme_ana_log) + + le32_to_cpu(ctrl.nanagrpid) * sizeof(struct nvme_ana_group_desc) + + le32_to_cpu(ctrl.mnan) * sizeof(__le32); + return 0; +} + +static int __nvme_set_attr(const char *path, const char *value) +{ + int ret, fd; + + fd = open(path, O_WRONLY); + if (fd < 0) { +#if 0 + nvme_msg(LOG_DEBUG, "Failed to open %s: %s\n", path, + strerror(errno)); +#endif + return -1; + } + ret = write(fd, value, strlen(value)); + close(fd); + return ret; +} + +int nvme_set_attr(const char *dir, const char *attr, const char *value) +{ + char *path; + int ret; + + ret = asprintf(&path, "%s/%s", dir, attr); + if (ret < 0) + return -1; + + ret = __nvme_set_attr(path, value); + free(path); + return ret; +} + +static char *__nvme_get_attr(const char *path) +{ + char value[4096] = { 0 }; + int ret, fd; + + fd = open(path, O_RDONLY); + if (fd < 0) { +#if 0 + nvme_msg(LOG_DEBUG, "Failed to open %s: %s\n", path, + strerror(errno)); +#endif + return NULL; + } + + ret = read(fd, value, sizeof(value) - 1); + close(fd); + if (ret < 0 || !strlen(value)) { + return NULL; + } + + if (value[strlen(value) - 1] == '\n') + value[strlen(value) - 1] = '\0'; + while (strlen(value) > 0 && value[strlen(value) - 1] == ' ') + value[strlen(value) - 1] = '\0'; + + return strlen(value) ? strdup(value) : NULL; +} + +char *nvme_get_attr(const char *dir, const char *attr) +{ + char *path, *value; + int ret; + + ret = asprintf(&path, "%s/%s", dir, attr); + if (ret < 0) + return NULL; + + value = __nvme_get_attr(path); + free(path); + return value; +} + +char *nvme_get_subsys_attr(nvme_subsystem_t s, const char *attr) +{ + return nvme_get_attr(nvme_subsystem_get_sysfs_dir(s), attr); +} + +char *nvme_get_ctrl_attr(nvme_ctrl_t c, const char *attr) +{ + return nvme_get_attr(nvme_ctrl_get_sysfs_dir(c), attr); +} + +char *nvme_get_ns_attr(nvme_ns_t n, const char *attr) +{ + return nvme_get_attr(nvme_ns_get_sysfs_dir(n), attr); +} + +char *nvme_get_path_attr(nvme_path_t p, const char *attr) +{ + return nvme_get_attr(nvme_path_get_sysfs_dir(p), attr); +} diff --git a/src/nvme/linux.h b/src/nvme/linux.h new file mode 100644 index 00000000..2a751a13 --- /dev/null +++ b/src/nvme/linux.h @@ -0,0 +1,156 @@ +// 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 + * Chaitanya Kulkarni + */ +#ifndef _LIBNVME_LINUX_H +#define _LIBNVME_LINUX_H + +#include "types.h" + +/** + * nvme_fw_download_seq() - + * @fd: File descriptor of nvme device + * @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 downlaod + * @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. + */ +int nvme_fw_download_seq(int fd, __u32 size, __u32 xfer, __u32 offset, + void *buf); + +/** + * nvme_get_ctrl_telemetry() - + * @fd: File descriptor of nvme device + * @rae: Retain asynchronous events + * @log: On success, set to the value of the allocated and retreived log. + * + * The total size allocated can be calculated as: + * (&struct nvme_telemetry_log.dalb3 + 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. + */ +int nvme_get_ctrl_telemetry(int fd, bool rae, struct nvme_telemetry_log **log); + +/** + * nvme_get_host_telemetry() - + * @fd: File descriptor of nvme device + * @log: On success, set to the value of the allocated and retreived log. + * + * The total size allocated can be calculated as: + * (&struct nvme_telemetry_log.dalb3 + 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. + */ +int nvme_get_host_telemetry(int fd, struct nvme_telemetry_log **log); + +/** + * nvme_get_new_host_telemetry() - + * @fd: File descriptor of nvme device + * @log: On success, set to the value of the allocated and retreived log. + * + * The total size allocated can be calculated as: + * (&struct nvme_telemetry_log.dalb3 + 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. + */ +int nvme_get_new_host_telemetry(int fd, struct nvme_telemetry_log **log); + +/** + * __nvme_get_log_page() - + * @fd: File descriptor of nvme device + * @nsid: Namespace Identifier, if applicable. + * @log_id: Log Identifier, see &enum nvme_cmd_get_log_lid. + * @rae: Retain asynchronous events + * @xfer_len: Max log transfer size per request to split the total. + * @data_len: Total length of the log to transfer. + * @data: User address of at least &data_len to store the log. + * + * 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 nsid, __u8 log_id, bool rae, + __u32 xfer_len, __u32 data_len, void *data); + +/** + * nvme_get_log_page() - + * @fd: File descriptor of nvme device + * @nsid: Namespace Identifier, if applicable. + * @log_id: Log Identifier, see &enum nvme_cmd_get_log_lid. + * @rae: Retain asynchronous events + * @data_len: Total length of the log to transfer. + * @data: User address of at least &data_len to store the log. + * + * Calls __nvme_get_log_page() with a default 4k transfer length, as that is + * guarnateed by the protocol to be a safe transfer size. + * + * 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 nsid, __u8 log_id, bool rae, + __u32 data_len, void *data); + +/** + * nvme_get_ana_log_len() - Retreive size of the current ANA log + * @fd: File descriptor of nvme device + * @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. + */ +int nvme_get_ana_log_len(int fd, size_t *analen); + +/** + * nvme_get_lba_status_log() - Retreive the LBA Status log page + * @fd: File descriptor of the nvme device + * @rae: Retain asynchronous events + * @log: On success, set to the value of the allocated and retreived log. + */ +int nvme_get_lba_status_log(int fd, bool rae, struct nvme_lba_status_log **log); + +/** + * nvme_namespace_attach_ctrls() - Attach namespace to controller(s) + * @fd: File descriptor of nvme device + * @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. + */ +int nvme_namespace_attach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); + +/** + * nvme_namespace_detach_ctrls() - Detach namespace from controller(s) + * @fd: File descriptor of nvme device + * @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. + */ +int nvme_namespace_detach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); + +/** + * nvme_open() - Open an nvme controller or namespace device + * @name: The basename of the device to open + * + * 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. + */ +int nvme_open(const char *name); + +#endif /* _LIBNVME_LINUX_H */ diff --git a/src/nvme/tree.c b/src/nvme/tree.c index fb724c9d..552496d8 100644 --- a/src/nvme/tree.c +++ b/src/nvme/tree.c @@ -23,6 +23,7 @@ #include #include "ioctl.h" +#include "linux.h" #include "filters.h" #include "tree.h" #include "filters.h" diff --git a/src/nvme/util.c b/src/nvme/util.c index bd82add2..3fd78490 100644 --- a/src/nvme/util.c +++ b/src/nvme/util.c @@ -7,24 +7,12 @@ * Chaitanya Kulkarni */ -#include -#include -#include #include #include -#include -#include -#include -#include #include -#include -#include -#include "filters.h" #include "util.h" -#include "tree.h" -#include "log.h" static inline __u8 nvme_generic_status_to_errno(__u16 status) { @@ -346,233 +334,6 @@ const char *nvme_status_to_string(int status, bool fabrics) return s; } -static int __nvme_open(const char *name) -{ - char *path; - int fd, ret; - - ret = asprintf(&path, "%s/%s", "/dev", name); - if (ret < 0) { - errno = ENOMEM; - return -1; - } - - fd = open(path, O_RDONLY); - free(path); - return fd; -} - -int nvme_open(const char *name) -{ - int ret, fd, id, ns; - struct stat stat; - bool c; - - ret = sscanf(name, "nvme%dn%d", &id, &ns); - if (ret != 1 && ret != 2) { - errno = EINVAL; - return -1; - } - c = ret == 1; - - fd = __nvme_open(name); - if (fd < 0) - return fd; - - ret = fstat(fd, &stat); - if (ret < 0) - goto close_fd; - - 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; - } - - return fd; - -close_fd: - close(fd); - return -1; -} - -int nvme_fw_download_seq(int fd, __u32 size, __u32 xfer, __u32 offset, - void *buf) -{ - int err = 0; - - while (size > 0) { - xfer = MIN(xfer, size); - err = nvme_fw_download(fd, offset, xfer, buf); - if (err) - break; - - buf += xfer; - size -= xfer; - offset += xfer; - } - - return err; -} - -int __nvme_get_log_page(int fd, __u32 nsid, __u8 log_id, bool rae, - __u32 xfer_len, __u32 data_len, void *data) -{ - __u64 offset = 0, xfer; - bool retain = true; - void *ptr = data; - int ret; - - /* - * 4k is the smallest possible transfer unit, so restricting to 4k - * avoids having to check the MDTS value of the controller. - */ - do { - xfer = data_len - offset; - if (xfer > xfer_len) - xfer = xfer_len; - - /* - * Always retain regardless of the RAE parameter until the very - * last portion of this log page so the data remains latched - * during the fetch sequence. - */ - if (offset + xfer == data_len) - retain = rae; - - ret = nvme_get_log(fd, log_id, nsid, offset, NVME_LOG_LSP_NONE, - NVME_LOG_LSI_NONE, retain, NVME_UUID_NONE, - NVME_CSI_NVM, xfer, ptr); - if (ret) - return ret; - - offset += xfer; - ptr += xfer; - } while (offset < data_len); - - return 0; -} - -int nvme_get_log_page(int fd, __u32 nsid, __u8 log_id, bool rae, - __u32 data_len, void *data) -{ - return __nvme_get_log_page(fd, nsid, log_id, rae, 4096, data_len, data); -} - -static int nvme_get_telemetry_log(int fd, bool create, bool ctrl, bool rae, - struct nvme_telemetry_log **buf) -{ - static const __u32 xfer = NVME_LOG_TELEM_BLOCK_SIZE; - - struct nvme_telemetry_log *telem; - enum nvme_cmd_get_log_lid lid; - void *log, *tmp; - __u32 size; - int err; - - log = malloc(xfer); - if (!log) { - errno = ENOMEM; - return -1; - } - - if (ctrl) { - err = nvme_get_log_telemetry_ctrl(fd, true, 0, xfer, log); - lid = NVME_LOG_LID_TELEMETRY_CTRL; - } else { - lid = NVME_LOG_LID_TELEMETRY_HOST; - if (create) - err = nvme_get_log_create_telemetry_host(fd, log); - else - err = nvme_get_log_telemetry_host(fd, 0, xfer, log); - } - - if (err) - goto free; - - telem = log; - if (ctrl && !telem->ctrlavail) { - *buf = log; - return 0; - } - - /* dalb3 >= dalb2 >= dalb1 */ - size = (le16_to_cpu(telem->dalb3) + 1) * xfer; - tmp = realloc(log, size); - if (!tmp) { - errno = ENOMEM; - err = -1; - goto free; - } - log = tmp; - - err = nvme_get_log_page(fd, NVME_NSID_NONE, lid, rae, size, (void *)log); - if (!err) { - *buf = log; - return 0; - } -free: - free(log); - return err; -} - -int nvme_get_ctrl_telemetry(int fd, bool rae, struct nvme_telemetry_log **log) -{ - return nvme_get_telemetry_log(fd, false, true, rae, log); -} - -int nvme_get_host_telemetry(int fd, struct nvme_telemetry_log **log) -{ - return nvme_get_telemetry_log(fd, false, false, false, log); -} - -int nvme_get_new_host_telemetry(int fd, struct nvme_telemetry_log **log) -{ - return nvme_get_telemetry_log(fd, true, false, false, log); -} - -int nvme_get_lba_status_log(int fd, bool rae, struct nvme_lba_status_log **log) -{ - __u32 size = sizeof(struct nvme_lba_status_log); - void *buf, *tmp; - int err; - - buf = malloc(size); - if (!buf) - return -1; - - *log = buf; - err = nvme_get_log_lba_status(fd, true, 0, size, buf); - if (err) - goto free; - - size = le32_to_cpu((*log)->lslplen); - if (!size) - return 0; - - tmp = realloc(buf, size); - if (!tmp) { - err = -1; - goto free; - } - buf = tmp; - *log = buf; - - err = nvme_get_log_page(fd, NVME_NSID_NONE, NVME_LOG_LID_LBA_STATUS, - rae, size, buf); - if (!err) - return 0; - -free: - *log = NULL; - free(buf); - return err; -} - void nvme_init_copy_range(struct nvme_copy_range *copy, __u16 *nlbs, __u64 *slbas, __u32 *eilbrts, __u32 *elbatms, __u32 *elbats, __u16 nr) @@ -623,46 +384,6 @@ void nvme_init_ctrl_list(struct nvme_ctrl_list *cntlist, __u16 num_ctrls, cntlist->identifier[i] = cpu_to_le16(ctrlist[i]); } -static int nvme_ns_attachment(int fd, __u32 nsid, __u16 num_ctrls, - __u16 *ctrlist, bool attach) -{ - enum nvme_ns_attach_sel sel = NVME_NS_ATTACH_SEL_CTRL_DEATTACH; - struct nvme_ctrl_list cntlist = { 0 }; - - if (attach) - sel = NVME_NS_ATTACH_SEL_CTRL_ATTACH; - - nvme_init_ctrl_list(&cntlist, num_ctrls, ctrlist); - return nvme_ns_attach(fd, nsid, sel, &cntlist); -} - -int nvme_namespace_attach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, - __u16 *ctrlist) -{ - return nvme_ns_attachment(fd, nsid, num_ctrls, ctrlist, true); -} - -int nvme_namespace_detach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, - __u16 *ctrlist) -{ - return nvme_ns_attachment(fd, nsid, num_ctrls, ctrlist, false); -} - -int nvme_get_ana_log_len(int fd, size_t *analen) -{ - struct nvme_id_ctrl ctrl; - int ret; - - ret = nvme_identify_ctrl(fd, &ctrl); - if (ret) - return ret; - - *analen = sizeof(struct nvme_ana_log) + - le32_to_cpu(ctrl.nanagrpid) * sizeof(struct nvme_ana_group_desc) + - le32_to_cpu(ctrl.mnan) * sizeof(__le32); - return 0; -} - int nvme_get_feature_length(int fid, __u32 cdw11, __u32 *len) { switch (fid) { @@ -747,96 +468,3 @@ int nvme_get_directive_receive_length(enum nvme_directive_dtype dtype, return -EINVAL; } } - -static int __nvme_set_attr(const char *path, const char *value) -{ - int ret, fd; - - fd = open(path, O_WRONLY); - if (fd < 0) { -#if 0 - nvme_msg(LOG_DEBUG, "Failed to open %s: %s\n", path, - strerror(errno)); -#endif - return -1; - } - ret = write(fd, value, strlen(value)); - close(fd); - return ret; -} - -int nvme_set_attr(const char *dir, const char *attr, const char *value) -{ - char *path; - int ret; - - ret = asprintf(&path, "%s/%s", dir, attr); - if (ret < 0) - return -1; - - ret = __nvme_set_attr(path, value); - free(path); - return ret; -} - -static char *__nvme_get_attr(const char *path) -{ - char value[4096] = { 0 }; - int ret, fd; - - fd = open(path, O_RDONLY); - if (fd < 0) { -#if 0 - nvme_msg(LOG_DEBUG, "Failed to open %s: %s\n", path, - strerror(errno)); -#endif - return NULL; - } - - ret = read(fd, value, sizeof(value) - 1); - close(fd); - if (ret < 0 || !strlen(value)) { - return NULL; - } - - if (value[strlen(value) - 1] == '\n') - value[strlen(value) - 1] = '\0'; - while (strlen(value) > 0 && value[strlen(value) - 1] == ' ') - value[strlen(value) - 1] = '\0'; - - return strlen(value) ? strdup(value) : NULL; -} - -char *nvme_get_attr(const char *dir, const char *attr) -{ - char *path, *value; - int ret; - - ret = asprintf(&path, "%s/%s", dir, attr); - if (ret < 0) - return NULL; - - value = __nvme_get_attr(path); - free(path); - return value; -} - -char *nvme_get_subsys_attr(nvme_subsystem_t s, const char *attr) -{ - return nvme_get_attr(nvme_subsystem_get_sysfs_dir(s), attr); -} - -char *nvme_get_ctrl_attr(nvme_ctrl_t c, const char *attr) -{ - return nvme_get_attr(nvme_ctrl_get_sysfs_dir(c), attr); -} - -char *nvme_get_ns_attr(nvme_ns_t n, const char *attr) -{ - return nvme_get_attr(nvme_ns_get_sysfs_dir(n), attr); -} - -char *nvme_get_path_attr(nvme_path_t p, const char *attr) -{ - return nvme_get_attr(nvme_path_get_sysfs_dir(p), attr); -} diff --git a/src/nvme/util.h b/src/nvme/util.h index b84ccf7a..80118955 100644 --- a/src/nvme/util.h +++ b/src/nvme/util.h @@ -9,7 +9,7 @@ #ifndef _LIBNVME_UTIL_H #define _LIBNVME_UTIL_H -#include "ioctl.h" +#include "types.h" /** * nvme_status_to_errno() - Converts nvme return status to errno @@ -31,60 +31,6 @@ __u8 nvme_status_to_errno(int status, bool fabrics); */ const char *nvme_status_to_string(int status, bool fabrics); -/** - * nvme_fw_download_seq() - - * @fd: File descriptor of nvme device - * @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 downlaod - * @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. - */ -int nvme_fw_download_seq(int fd, __u32 size, __u32 xfer, __u32 offset, - void *buf); - -/** - * nvme_get_ctrl_telemetry() - - * @fd: File descriptor of nvme device - * @rae: Retain asynchronous events - * @log: On success, set to the value of the allocated and retreived log. - * - * The total size allocated can be calculated as: - * (&struct nvme_telemetry_log.dalb3 + 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. - */ -int nvme_get_ctrl_telemetry(int fd, bool rae, struct nvme_telemetry_log **log); - -/** - * nvme_get_host_telemetry() - - * @fd: File descriptor of nvme device - * @log: On success, set to the value of the allocated and retreived log. - * - * The total size allocated can be calculated as: - * (&struct nvme_telemetry_log.dalb3 + 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. - */ -int nvme_get_host_telemetry(int fd, struct nvme_telemetry_log **log); - -/** - * nvme_get_new_host_telemetry() - - * @fd: File descriptor of nvme device - * @log: On success, set to the value of the allocated and retreived log. - * - * The total size allocated can be calculated as: - * (&struct nvme_telemetry_log.dalb3 + 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. - */ -int nvme_get_new_host_telemetry(int fd, struct nvme_telemetry_log **log); - /** * nvme_init_id_ns() - Initialize an Identify Namepsace structure for creation. * @ns: Address of the Identify Namespace structure to initialize @@ -138,82 +84,6 @@ void nvme_init_copy_range(struct nvme_copy_range *copy, __u16 *nlbs, __u64 *slbas, __u32 *eilbrts, __u32 *elbatms, __u32 *elbats, __u16 nr); -/** - * __nvme_get_log_page() - - * @fd: File descriptor of nvme device - * @nsid: Namespace Identifier, if applicable. - * @log_id: Log Identifier, see &enum nvme_cmd_get_log_lid. - * @rae: Retain asynchronous events - * @xfer_len: Max log transfer size per request to split the total. - * @data_len: Total length of the log to transfer. - * @data: User address of at least &data_len to store the log. - * - * 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 nsid, __u8 log_id, bool rae, - __u32 xfer_len, __u32 data_len, void *data); - -/** - * nvme_get_log_page() - - * @fd: File descriptor of nvme device - * @nsid: Namespace Identifier, if applicable. - * @log_id: Log Identifier, see &enum nvme_cmd_get_log_lid. - * @rae: Retain asynchronous events - * @data_len: Total length of the log to transfer. - * @data: User address of at least &data_len to store the log. - * - * Calls __nvme_get_log_page() with a default 4k transfer length, as that is - * guarnateed by the protocol to be a safe transfer size. - * - * 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 nsid, __u8 log_id, bool rae, - __u32 data_len, void *data); - -/** - * nvme_get_ana_log_len() - Retreive size of the current ANA log - * @fd: File descriptor of nvme device - * @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. - */ -int nvme_get_ana_log_len(int fd, size_t *analen); - -/** - * nvme_get_lba_status_log() - Retreive the LBA Status log page - * @fd: File descriptor of the nvme device - * @rae: Retain asynchronous events - * @log: On success, set to the value of the allocated and retreived log. - */ -int nvme_get_lba_status_log(int fd, bool rae, struct nvme_lba_status_log **log); - -/** - * nvme_namespace_attach_ctrls() - Attach namespace to controller(s) - * @fd: File descriptor of nvme device - * @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. - */ -int nvme_namespace_attach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); - -/** - * nvme_namespace_detach_ctrls() - Detach namespace from controller(s) - * @fd: File descriptor of nvme device - * @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. - */ -int nvme_namespace_detach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); - /** * nvme_get_feature_length() - Retreive the command payload length for a * specific feature identifier @@ -239,29 +109,6 @@ int nvme_get_feature_length(int fid, __u32 cdw11, __u32 *len); int nvme_get_directive_receive_length(enum nvme_directive_dtype dtype, enum nvme_directive_receive_doper doper, __u32 *len); -/** - * nvme_open() - Open an nvme controller or namespace device - * @name: The basename of the device to open - * - * 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. - */ -int nvme_open(const char *name); - -/** - * nvme_chomp() - Strip trailing white space - * &s: String to strip - * @l: Maximum length of string - */ -static inline void nvme_chomp(char *s, int l) -{ - while (l && (s[l] == '\0' || s[l] == ' ')) - s[l--] = '\0'; -} - #define NVME_FEAT_ARB_BURST(v) NVME_GET(v, FEAT_ARBITRATION_BURST) #define NVME_FEAT_ARB_LPW(v) NVME_GET(v, FEAT_ARBITRATION_LPW) #define NVME_FEAT_ARB_MPW(v) NVME_GET(v, FEAT_ARBITRATION_MPW)