From: Ankit Kumar Date: Tue, 31 May 2022 13:31:50 +0000 (+0530) Subject: nvme: add nvme opcodes, structures and helper functions X-Git-Tag: test-tag-2022-08-09~43 X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=b3d5e3fd80e3834097578e92d1b788065b8346e1;hp=f43aab595c1b8832d5f2641606f5bd5a7cdd22ea;p=fio.git nvme: add nvme opcodes, structures and helper functions Add NVMe specification opcodes, data structures and helper functions to get identify namespace and form nvme uring command. This will help the follow up patches to get nvme-ns generic character device size, lba size. Signed-off-by: Ankit Kumar Co-authored-by: Anuj Gupta Link: https://lore.kernel.org/r/20220531133155.17493-5-ankit.kumar@samsung.com Signed-off-by: Jens Axboe --- diff --git a/Makefile b/Makefile index ed66305a..188a74d7 100644 --- a/Makefile +++ b/Makefile @@ -231,7 +231,7 @@ ifdef CONFIG_LIBXNVME endif ifeq ($(CONFIG_TARGET_OS), Linux) SOURCE += diskutil.c fifo.c blktrace.c cgroup.c trim.c engines/sg.c \ - oslib/linux-dev-lookup.c engines/io_uring.c + oslib/linux-dev-lookup.c engines/io_uring.c engines/nvme.c cmdprio_SRCS = engines/cmdprio.c ifdef CONFIG_HAS_BLKZONED SOURCE += oslib/linux-blkzoned.c @@ -241,7 +241,7 @@ endif endif ifeq ($(CONFIG_TARGET_OS), Android) SOURCE += diskutil.c fifo.c blktrace.c cgroup.c trim.c profiles/tiobench.c \ - oslib/linux-dev-lookup.c engines/io_uring.c + oslib/linux-dev-lookup.c engines/io_uring.c engines/nvme.c cmdprio_SRCS = engines/cmdprio.c ifdef CONFIG_HAS_BLKZONED SOURCE += oslib/linux-blkzoned.c diff --git a/engines/nvme.c b/engines/nvme.c new file mode 100644 index 00000000..6fecf0ba --- /dev/null +++ b/engines/nvme.c @@ -0,0 +1,103 @@ +/* + * nvme structure declarations and helper functions for the + * io_uring_cmd engine. + */ + +#include "nvme.h" + +int fio_nvme_uring_cmd_prep(struct nvme_uring_cmd *cmd, struct io_u *io_u, + struct iovec *iov) +{ + struct nvme_data *data = FILE_ENG_DATA(io_u->file); + __u64 slba; + __u32 nlb; + + memset(cmd, 0, sizeof(struct nvme_uring_cmd)); + + if (io_u->ddir == DDIR_READ) + cmd->opcode = nvme_cmd_read; + else if (io_u->ddir == DDIR_WRITE) + cmd->opcode = nvme_cmd_write; + else + return -ENOTSUP; + + slba = io_u->offset >> data->lba_shift; + nlb = (io_u->xfer_buflen >> data->lba_shift) - 1; + + /* cdw10 and cdw11 represent starting lba */ + cmd->cdw10 = slba & 0xffffffff; + cmd->cdw11 = slba >> 32; + /* cdw12 represent number of lba's for read/write */ + cmd->cdw12 = nlb; + if (iov) { + iov->iov_base = io_u->xfer_buf; + iov->iov_len = io_u->xfer_buflen; + cmd->addr = (__u64)(uintptr_t)iov; + cmd->data_len = 1; + } else { + cmd->addr = (__u64)(uintptr_t)io_u->xfer_buf; + cmd->data_len = io_u->xfer_buflen; + } + cmd->nsid = data->nsid; + return 0; +} + +static int nvme_identify(int fd, __u32 nsid, enum nvme_identify_cns cns, + enum nvme_csi csi, void *data) +{ + struct nvme_passthru_cmd cmd = { + .opcode = nvme_admin_identify, + .nsid = nsid, + .addr = (__u64)(uintptr_t)data, + .data_len = NVME_IDENTIFY_DATA_SIZE, + .cdw10 = cns, + .cdw11 = csi << NVME_IDENTIFY_CSI_SHIFT, + .timeout_ms = NVME_DEFAULT_IOCTL_TIMEOUT, + }; + + return ioctl(fd, NVME_IOCTL_ADMIN_CMD, &cmd); +} + +int fio_nvme_get_info(struct fio_file *f, __u32 *nsid, __u32 *lba_sz, + __u64 *nlba) +{ + struct nvme_id_ns ns; + unsigned int namespace_id; + int fd, err; + + if (f->filetype != FIO_TYPE_CHAR) { + log_err("ioengine io_uring_cmd only works with nvme ns " + "generic char devices (/dev/ngXnY)\n"); + return 1; + } + + fd = open(f->file_name, O_RDONLY); + if (fd < 0) + return -errno; + + namespace_id = ioctl(fd, NVME_IOCTL_ID); + if (namespace_id < 0) { + log_err("failed to fetch namespace-id"); + close(fd); + return -errno; + } + + /* + * Identify namespace to get namespace-id, namespace size in LBA's + * and LBA data size. + */ + err = nvme_identify(fd, namespace_id, NVME_IDENTIFY_CNS_NS, + NVME_CSI_NVM, &ns); + if (err) { + log_err("failed to fetch identify namespace\n"); + close(fd); + return err; + } + + *nsid = namespace_id; + *lba_sz = 1 << ns.lbaf[(ns.flbas & 0x0f)].ds; + *nlba = ns.nsze; + + close(fd); + return 0; +} diff --git a/engines/nvme.h b/engines/nvme.h new file mode 100644 index 00000000..8e626bb2 --- /dev/null +++ b/engines/nvme.h @@ -0,0 +1,136 @@ +/* + * nvme structure declarations and helper functions for the + * io_uring_cmd engine. + */ + +#ifndef FIO_NVME_H +#define FIO_NVME_H + +#include +#include "../fio.h" + +/* + * If the uapi headers installed on the system lacks nvme uring command + * support, use the local version to prevent compilation issues. + */ +#ifndef CONFIG_NVME_URING_CMD +struct nvme_uring_cmd { + __u8 opcode; + __u8 flags; + __u16 rsvd1; + __u32 nsid; + __u32 cdw2; + __u32 cdw3; + __u64 metadata; + __u64 addr; + __u32 metadata_len; + __u32 data_len; + __u32 cdw10; + __u32 cdw11; + __u32 cdw12; + __u32 cdw13; + __u32 cdw14; + __u32 cdw15; + __u32 timeout_ms; + __u32 rsvd2; +}; + +#define NVME_URING_CMD_IO _IOWR('N', 0x80, struct nvme_uring_cmd) +#define NVME_URING_CMD_IO_VEC _IOWR('N', 0x81, struct nvme_uring_cmd) +#endif /* CONFIG_NVME_URING_CMD */ + +#define NVME_DEFAULT_IOCTL_TIMEOUT 0 +#define NVME_IDENTIFY_DATA_SIZE 4096 +#define NVME_IDENTIFY_CSI_SHIFT 24 + +enum nvme_identify_cns { + NVME_IDENTIFY_CNS_NS = 0x00, +}; + +enum nvme_csi { + NVME_CSI_NVM = 0, + NVME_CSI_KV = 1, + NVME_CSI_ZNS = 2, +}; + +enum nvme_admin_opcode { + nvme_admin_identify = 0x06, +}; + +enum nvme_io_opcode { + nvme_cmd_write = 0x01, + nvme_cmd_read = 0x02, +}; + +struct nvme_data { + __u32 nsid; + __u32 lba_shift; +}; + +struct nvme_lbaf { + __le16 ms; + __u8 ds; + __u8 rp; +}; + +struct nvme_id_ns { + __le64 nsze; + __le64 ncap; + __le64 nuse; + __u8 nsfeat; + __u8 nlbaf; + __u8 flbas; + __u8 mc; + __u8 dpc; + __u8 dps; + __u8 nmic; + __u8 rescap; + __u8 fpi; + __u8 dlfeat; + __le16 nawun; + __le16 nawupf; + __le16 nacwu; + __le16 nabsn; + __le16 nabo; + __le16 nabspf; + __le16 noiob; + __u8 nvmcap[16]; + __le16 npwg; + __le16 npwa; + __le16 npdg; + __le16 npda; + __le16 nows; + __le16 mssrl; + __le32 mcl; + __u8 msrc; + __u8 rsvd81[11]; + __le32 anagrpid; + __u8 rsvd96[3]; + __u8 nsattr; + __le16 nvmsetid; + __le16 endgid; + __u8 nguid[16]; + __u8 eui64[8]; + struct nvme_lbaf lbaf[16]; + __u8 rsvd192[192]; + __u8 vs[3712]; +}; + +static inline int ilog2(uint32_t i) +{ + int log = -1; + + while (i) { + i >>= 1; + log++; + } + return log; +} + +int fio_nvme_get_info(struct fio_file *f, __u32 *nsid, __u32 *lba_sz, + __u64 *nlba); + +int fio_nvme_uring_cmd_prep(struct nvme_uring_cmd *cmd, struct io_u *io_u, + struct iovec *iov); + +#endif