Commit | Line | Data |
---|---|---|
b3d5e3fd AK |
1 | /* |
2 | * nvme structure declarations and helper functions for the | |
3 | * io_uring_cmd engine. | |
4 | */ | |
5 | ||
6 | #include "nvme.h" | |
7 | ||
8 | int 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 | ||
45 | static 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 | ||
61 | int 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 | } |