zbd: Check for direct flag only if its block device
[fio.git] / engines / nvme.c
CommitLineData
b3d5e3fd
AK
1/*
2 * nvme structure declarations and helper functions for the
3 * io_uring_cmd engine.
4 */
5
6#include "nvme.h"
7
8int fio_nvme_uring_cmd_prep(struct nvme_uring_cmd *cmd, struct io_u *io_u,
9 struct iovec *iov)
10{
11 struct nvme_data *data = FILE_ENG_DATA(io_u->file);
12 __u64 slba;
13 __u32 nlb;
14
15 memset(cmd, 0, sizeof(struct nvme_uring_cmd));
16
17 if (io_u->ddir == DDIR_READ)
18 cmd->opcode = nvme_cmd_read;
19 else if (io_u->ddir == DDIR_WRITE)
20 cmd->opcode = nvme_cmd_write;
21 else
22 return -ENOTSUP;
23
24 slba = io_u->offset >> data->lba_shift;
25 nlb = (io_u->xfer_buflen >> data->lba_shift) - 1;
26
27 /* cdw10 and cdw11 represent starting lba */
28 cmd->cdw10 = slba & 0xffffffff;
29 cmd->cdw11 = slba >> 32;
30 /* cdw12 represent number of lba's for read/write */
31 cmd->cdw12 = nlb;
32 if (iov) {
33 iov->iov_base = io_u->xfer_buf;
34 iov->iov_len = io_u->xfer_buflen;
35 cmd->addr = (__u64)(uintptr_t)iov;
36 cmd->data_len = 1;
37 } else {
38 cmd->addr = (__u64)(uintptr_t)io_u->xfer_buf;
39 cmd->data_len = io_u->xfer_buflen;
40 }
41 cmd->nsid = data->nsid;
42 return 0;
43}
44
45static int nvme_identify(int fd, __u32 nsid, enum nvme_identify_cns cns,
46 enum nvme_csi csi, void *data)
47{
48 struct nvme_passthru_cmd cmd = {
49 .opcode = nvme_admin_identify,
50 .nsid = nsid,
51 .addr = (__u64)(uintptr_t)data,
52 .data_len = NVME_IDENTIFY_DATA_SIZE,
53 .cdw10 = cns,
54 .cdw11 = csi << NVME_IDENTIFY_CSI_SHIFT,
55 .timeout_ms = NVME_DEFAULT_IOCTL_TIMEOUT,
56 };
57
58 return ioctl(fd, NVME_IOCTL_ADMIN_CMD, &cmd);
59}
60
61int fio_nvme_get_info(struct fio_file *f, __u32 *nsid, __u32 *lba_sz,
62 __u64 *nlba)
63{
64 struct nvme_id_ns ns;
65 unsigned int namespace_id;
66 int fd, err;
67
68 if (f->filetype != FIO_TYPE_CHAR) {
69 log_err("ioengine io_uring_cmd only works with nvme ns "
70 "generic char devices (/dev/ngXnY)\n");
71 return 1;
72 }
73
74 fd = open(f->file_name, O_RDONLY);
75 if (fd < 0)
76 return -errno;
77
78 namespace_id = ioctl(fd, NVME_IOCTL_ID);
79 if (namespace_id < 0) {
80 log_err("failed to fetch namespace-id");
81 close(fd);
82 return -errno;
83 }
84
85 /*
86 * Identify namespace to get namespace-id, namespace size in LBA's
87 * and LBA data size.
88 */
89 err = nvme_identify(fd, namespace_id, NVME_IDENTIFY_CNS_NS,
90 NVME_CSI_NVM, &ns);
91 if (err) {
92 log_err("failed to fetch identify namespace\n");
93 close(fd);
94 return err;
95 }
96
97 *nsid = namespace_id;
98 *lba_sz = 1 << ns.lbaf[(ns.flbas & 0x0f)].ds;
99 *nlba = ns.nsze;
100
101 close(fd);
102 return 0;
103}