t/nvmept_trim: increase transfer size for some tests
[fio.git] / engines / io_uring.c
1 /*
2  * io_uring engine
3  *
4  * IO engine using the new native Linux aio io_uring interface. See:
5  *
6  * http://git.kernel.dk/cgit/linux-block/log/?h=io_uring
7  *
8  */
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <errno.h>
12 #include <sys/time.h>
13 #include <sys/resource.h>
14
15 #include "../fio.h"
16 #include "../lib/pow2.h"
17 #include "../optgroup.h"
18 #include "../lib/memalign.h"
19 #include "../lib/fls.h"
20 #include "../lib/roundup.h"
21 #include "../verify.h"
22
23 #ifdef ARCH_HAVE_IOURING
24
25 #include "../lib/types.h"
26 #include "../os/linux/io_uring.h"
27 #include "cmdprio.h"
28 #include "zbd.h"
29 #include "nvme.h"
30
31 #include <sys/stat.h>
32
33 enum uring_cmd_type {
34         FIO_URING_CMD_NVME = 1,
35 };
36
37 struct io_sq_ring {
38         unsigned *head;
39         unsigned *tail;
40         unsigned *ring_mask;
41         unsigned *ring_entries;
42         unsigned *flags;
43         unsigned *array;
44 };
45
46 struct io_cq_ring {
47         unsigned *head;
48         unsigned *tail;
49         unsigned *ring_mask;
50         unsigned *ring_entries;
51         struct io_uring_cqe *cqes;
52 };
53
54 struct ioring_mmap {
55         void *ptr;
56         size_t len;
57 };
58
59 struct ioring_data {
60         int ring_fd;
61
62         struct io_u **io_u_index;
63         char *md_buf;
64
65         int *fds;
66
67         struct io_sq_ring sq_ring;
68         struct io_uring_sqe *sqes;
69         struct iovec *iovecs;
70         unsigned sq_ring_mask;
71
72         struct io_cq_ring cq_ring;
73         unsigned cq_ring_mask;
74
75         int queued;
76         int cq_ring_off;
77         unsigned iodepth;
78         int prepped;
79
80         struct ioring_mmap mmap[3];
81
82         struct cmdprio cmdprio;
83
84         struct nvme_dsm *dsm;
85 };
86
87 struct ioring_options {
88         struct thread_data *td;
89         unsigned int hipri;
90         struct cmdprio_options cmdprio_options;
91         unsigned int fixedbufs;
92         unsigned int registerfiles;
93         unsigned int sqpoll_thread;
94         unsigned int sqpoll_set;
95         unsigned int sqpoll_cpu;
96         unsigned int nonvectored;
97         unsigned int uncached;
98         unsigned int nowait;
99         unsigned int force_async;
100         unsigned int md_per_io_size;
101         unsigned int pi_act;
102         unsigned int apptag;
103         unsigned int apptag_mask;
104         unsigned int prchk;
105         char *pi_chk;
106         enum uring_cmd_type cmd_type;
107 };
108
109 static const int ddir_to_op[2][2] = {
110         { IORING_OP_READV, IORING_OP_READ },
111         { IORING_OP_WRITEV, IORING_OP_WRITE }
112 };
113
114 static const int fixed_ddir_to_op[2] = {
115         IORING_OP_READ_FIXED,
116         IORING_OP_WRITE_FIXED
117 };
118
119 static int fio_ioring_sqpoll_cb(void *data, unsigned long long *val)
120 {
121         struct ioring_options *o = data;
122
123         o->sqpoll_cpu = *val;
124         o->sqpoll_set = 1;
125         return 0;
126 }
127
128 static struct fio_option options[] = {
129         {
130                 .name   = "hipri",
131                 .lname  = "High Priority",
132                 .type   = FIO_OPT_STR_SET,
133                 .off1   = offsetof(struct ioring_options, hipri),
134                 .help   = "Use polled IO completions",
135                 .category = FIO_OPT_C_ENGINE,
136                 .group  = FIO_OPT_G_IOURING,
137         },
138         {
139                 .name   = "fixedbufs",
140                 .lname  = "Fixed (pre-mapped) IO buffers",
141                 .type   = FIO_OPT_STR_SET,
142                 .off1   = offsetof(struct ioring_options, fixedbufs),
143                 .help   = "Pre map IO buffers",
144                 .category = FIO_OPT_C_ENGINE,
145                 .group  = FIO_OPT_G_IOURING,
146         },
147         {
148                 .name   = "registerfiles",
149                 .lname  = "Register file set",
150                 .type   = FIO_OPT_STR_SET,
151                 .off1   = offsetof(struct ioring_options, registerfiles),
152                 .help   = "Pre-open/register files",
153                 .category = FIO_OPT_C_ENGINE,
154                 .group  = FIO_OPT_G_IOURING,
155         },
156         {
157                 .name   = "sqthread_poll",
158                 .lname  = "Kernel SQ thread polling",
159                 .type   = FIO_OPT_STR_SET,
160                 .off1   = offsetof(struct ioring_options, sqpoll_thread),
161                 .help   = "Offload submission/completion to kernel thread",
162                 .category = FIO_OPT_C_ENGINE,
163                 .group  = FIO_OPT_G_IOURING,
164         },
165         {
166                 .name   = "sqthread_poll_cpu",
167                 .lname  = "SQ Thread Poll CPU",
168                 .type   = FIO_OPT_INT,
169                 .cb     = fio_ioring_sqpoll_cb,
170                 .help   = "What CPU to run SQ thread polling on",
171                 .category = FIO_OPT_C_ENGINE,
172                 .group  = FIO_OPT_G_IOURING,
173         },
174         {
175                 .name   = "nonvectored",
176                 .lname  = "Non-vectored",
177                 .type   = FIO_OPT_INT,
178                 .off1   = offsetof(struct ioring_options, nonvectored),
179                 .def    = "-1",
180                 .help   = "Use non-vectored read/write commands",
181                 .category = FIO_OPT_C_ENGINE,
182                 .group  = FIO_OPT_G_IOURING,
183         },
184         {
185                 .name   = "uncached",
186                 .lname  = "Uncached",
187                 .type   = FIO_OPT_INT,
188                 .off1   = offsetof(struct ioring_options, uncached),
189                 .help   = "Use RWF_UNCACHED for buffered read/writes",
190                 .category = FIO_OPT_C_ENGINE,
191                 .group  = FIO_OPT_G_IOURING,
192         },
193         {
194                 .name   = "nowait",
195                 .lname  = "RWF_NOWAIT",
196                 .type   = FIO_OPT_BOOL,
197                 .off1   = offsetof(struct ioring_options, nowait),
198                 .help   = "Use RWF_NOWAIT for reads/writes",
199                 .category = FIO_OPT_C_ENGINE,
200                 .group  = FIO_OPT_G_IOURING,
201         },
202         {
203                 .name   = "force_async",
204                 .lname  = "Force async",
205                 .type   = FIO_OPT_INT,
206                 .off1   = offsetof(struct ioring_options, force_async),
207                 .help   = "Set IOSQE_ASYNC every N requests",
208                 .category = FIO_OPT_C_ENGINE,
209                 .group  = FIO_OPT_G_IOURING,
210         },
211         {
212                 .name   = "cmd_type",
213                 .lname  = "Uring cmd type",
214                 .type   = FIO_OPT_STR,
215                 .off1   = offsetof(struct ioring_options, cmd_type),
216                 .help   = "Specify uring-cmd type",
217                 .def    = "nvme",
218                 .posval = {
219                           { .ival = "nvme",
220                             .oval = FIO_URING_CMD_NVME,
221                             .help = "Issue nvme-uring-cmd",
222                           },
223                 },
224                 .category = FIO_OPT_C_ENGINE,
225                 .group  = FIO_OPT_G_IOURING,
226         },
227         CMDPRIO_OPTIONS(struct ioring_options, FIO_OPT_G_IOURING),
228         {
229                 .name   = "md_per_io_size",
230                 .lname  = "Separate Metadata Buffer Size per I/O",
231                 .type   = FIO_OPT_INT,
232                 .off1   = offsetof(struct ioring_options, md_per_io_size),
233                 .def    = "0",
234                 .help   = "Size of separate metadata buffer per I/O (Default: 0)",
235                 .category = FIO_OPT_C_ENGINE,
236                 .group  = FIO_OPT_G_IOURING,
237         },
238         {
239                 .name   = "pi_act",
240                 .lname  = "Protection Information Action",
241                 .type   = FIO_OPT_BOOL,
242                 .off1   = offsetof(struct ioring_options, pi_act),
243                 .def    = "1",
244                 .help   = "Protection Information Action bit (pi_act=1 or pi_act=0)",
245                 .category = FIO_OPT_C_ENGINE,
246                 .group  = FIO_OPT_G_IOURING,
247         },
248         {
249                 .name   = "pi_chk",
250                 .lname  = "Protection Information Check",
251                 .type   = FIO_OPT_STR_STORE,
252                 .off1   = offsetof(struct ioring_options, pi_chk),
253                 .def    = NULL,
254                 .help   = "Control of Protection Information Checking (pi_chk=GUARD,REFTAG,APPTAG)",
255                 .category = FIO_OPT_C_ENGINE,
256                 .group  = FIO_OPT_G_IOURING,
257         },
258         {
259                 .name   = "apptag",
260                 .lname  = "Application Tag used in Protection Information",
261                 .type   = FIO_OPT_INT,
262                 .off1   = offsetof(struct ioring_options, apptag),
263                 .def    = "0x1234",
264                 .help   = "Application Tag used in Protection Information field (Default: 0x1234)",
265                 .category = FIO_OPT_C_ENGINE,
266                 .group  = FIO_OPT_G_IOURING,
267         },
268         {
269                 .name   = "apptag_mask",
270                 .lname  = "Application Tag Mask",
271                 .type   = FIO_OPT_INT,
272                 .off1   = offsetof(struct ioring_options, apptag_mask),
273                 .def    = "0xffff",
274                 .help   = "Application Tag Mask used with Application Tag (Default: 0xffff)",
275                 .category = FIO_OPT_C_ENGINE,
276                 .group  = FIO_OPT_G_IOURING,
277         },
278         {
279                 .name   = NULL,
280         },
281 };
282
283 static int io_uring_enter(struct ioring_data *ld, unsigned int to_submit,
284                          unsigned int min_complete, unsigned int flags)
285 {
286 #ifdef FIO_ARCH_HAS_SYSCALL
287         return __do_syscall6(__NR_io_uring_enter, ld->ring_fd, to_submit,
288                                 min_complete, flags, NULL, 0);
289 #else
290         return syscall(__NR_io_uring_enter, ld->ring_fd, to_submit,
291                         min_complete, flags, NULL, 0);
292 #endif
293 }
294
295 static int fio_ioring_prep(struct thread_data *td, struct io_u *io_u)
296 {
297         struct ioring_data *ld = td->io_ops_data;
298         struct ioring_options *o = td->eo;
299         struct fio_file *f = io_u->file;
300         struct io_uring_sqe *sqe;
301
302         sqe = &ld->sqes[io_u->index];
303
304         if (o->registerfiles) {
305                 sqe->fd = f->engine_pos;
306                 sqe->flags = IOSQE_FIXED_FILE;
307         } else {
308                 sqe->fd = f->fd;
309                 sqe->flags = 0;
310         }
311
312         if (io_u->ddir == DDIR_READ || io_u->ddir == DDIR_WRITE) {
313                 if (o->fixedbufs) {
314                         sqe->opcode = fixed_ddir_to_op[io_u->ddir];
315                         sqe->addr = (unsigned long) io_u->xfer_buf;
316                         sqe->len = io_u->xfer_buflen;
317                         sqe->buf_index = io_u->index;
318                 } else {
319                         struct iovec *iov = &ld->iovecs[io_u->index];
320
321                         /*
322                          * Update based on actual io_u, requeue could have
323                          * adjusted these
324                          */
325                         iov->iov_base = io_u->xfer_buf;
326                         iov->iov_len = io_u->xfer_buflen;
327
328                         sqe->opcode = ddir_to_op[io_u->ddir][!!o->nonvectored];
329                         if (o->nonvectored) {
330                                 sqe->addr = (unsigned long) iov->iov_base;
331                                 sqe->len = iov->iov_len;
332                         } else {
333                                 sqe->addr = (unsigned long) iov;
334                                 sqe->len = 1;
335                         }
336                 }
337                 sqe->rw_flags = 0;
338                 if (!td->o.odirect && o->uncached)
339                         sqe->rw_flags |= RWF_UNCACHED;
340                 if (o->nowait)
341                         sqe->rw_flags |= RWF_NOWAIT;
342
343                 /*
344                  * Since io_uring can have a submission context (sqthread_poll)
345                  * that is different from the process context, we cannot rely on
346                  * the IO priority set by ioprio_set() (options prio, prioclass,
347                  * and priohint) to be inherited.
348                  * td->ioprio will have the value of the "default prio", so set
349                  * this unconditionally. This value might get overridden by
350                  * fio_ioring_cmdprio_prep() if the option cmdprio_percentage or
351                  * cmdprio_bssplit is used.
352                  */
353                 sqe->ioprio = td->ioprio;
354                 sqe->off = io_u->offset;
355         } else if (ddir_sync(io_u->ddir)) {
356                 sqe->ioprio = 0;
357                 if (io_u->ddir == DDIR_SYNC_FILE_RANGE) {
358                         sqe->off = f->first_write;
359                         sqe->len = f->last_write - f->first_write;
360                         sqe->sync_range_flags = td->o.sync_file_range;
361                         sqe->opcode = IORING_OP_SYNC_FILE_RANGE;
362                 } else {
363                         sqe->off = 0;
364                         sqe->addr = 0;
365                         sqe->len = 0;
366                         if (io_u->ddir == DDIR_DATASYNC)
367                                 sqe->fsync_flags |= IORING_FSYNC_DATASYNC;
368                         sqe->opcode = IORING_OP_FSYNC;
369                 }
370         }
371
372         if (o->force_async && ++ld->prepped == o->force_async) {
373                 ld->prepped = 0;
374                 sqe->flags |= IOSQE_ASYNC;
375         }
376
377         sqe->user_data = (unsigned long) io_u;
378         return 0;
379 }
380
381 static int fio_ioring_cmd_prep(struct thread_data *td, struct io_u *io_u)
382 {
383         struct ioring_data *ld = td->io_ops_data;
384         struct ioring_options *o = td->eo;
385         struct fio_file *f = io_u->file;
386         struct nvme_uring_cmd *cmd;
387         struct io_uring_sqe *sqe;
388         struct nvme_dsm *dsm;
389         void *ptr = ld->dsm;
390         unsigned int dsm_size;
391
392         /* only supports nvme_uring_cmd */
393         if (o->cmd_type != FIO_URING_CMD_NVME)
394                 return -EINVAL;
395
396         if (io_u->ddir == DDIR_TRIM && td->io_ops->flags & FIO_ASYNCIO_SYNC_TRIM)
397                 return 0;
398
399         sqe = &ld->sqes[(io_u->index) << 1];
400
401         if (o->registerfiles) {
402                 sqe->fd = f->engine_pos;
403                 sqe->flags = IOSQE_FIXED_FILE;
404         } else {
405                 sqe->fd = f->fd;
406         }
407         sqe->rw_flags = 0;
408         if (!td->o.odirect && o->uncached)
409                 sqe->rw_flags |= RWF_UNCACHED;
410         if (o->nowait)
411                 sqe->rw_flags |= RWF_NOWAIT;
412
413         sqe->opcode = IORING_OP_URING_CMD;
414         sqe->user_data = (unsigned long) io_u;
415         if (o->nonvectored)
416                 sqe->cmd_op = NVME_URING_CMD_IO;
417         else
418                 sqe->cmd_op = NVME_URING_CMD_IO_VEC;
419         if (o->force_async && ++ld->prepped == o->force_async) {
420                 ld->prepped = 0;
421                 sqe->flags |= IOSQE_ASYNC;
422         }
423         if (o->fixedbufs) {
424                 sqe->uring_cmd_flags = IORING_URING_CMD_FIXED;
425                 sqe->buf_index = io_u->index;
426         }
427
428         cmd = (struct nvme_uring_cmd *)sqe->cmd;
429         dsm_size = sizeof(*ld->dsm) + td->o.num_range * sizeof(struct nvme_dsm_range);
430         ptr += io_u->index * dsm_size;
431         dsm = (struct nvme_dsm *)ptr;
432
433         return fio_nvme_uring_cmd_prep(cmd, io_u,
434                         o->nonvectored ? NULL : &ld->iovecs[io_u->index],
435                         dsm);
436 }
437
438 static struct io_u *fio_ioring_event(struct thread_data *td, int event)
439 {
440         struct ioring_data *ld = td->io_ops_data;
441         struct io_uring_cqe *cqe;
442         struct io_u *io_u;
443         unsigned index;
444
445         index = (event + ld->cq_ring_off) & ld->cq_ring_mask;
446
447         cqe = &ld->cq_ring.cqes[index];
448         io_u = (struct io_u *) (uintptr_t) cqe->user_data;
449
450         if (cqe->res != io_u->xfer_buflen) {
451                 if (cqe->res > io_u->xfer_buflen)
452                         io_u->error = -cqe->res;
453                 else
454                         io_u->resid = io_u->xfer_buflen - cqe->res;
455         } else
456                 io_u->error = 0;
457
458         return io_u;
459 }
460
461 static struct io_u *fio_ioring_cmd_event(struct thread_data *td, int event)
462 {
463         struct ioring_data *ld = td->io_ops_data;
464         struct ioring_options *o = td->eo;
465         struct io_uring_cqe *cqe;
466         struct io_u *io_u;
467         struct nvme_data *data;
468         unsigned index;
469         int ret;
470
471         index = (event + ld->cq_ring_off) & ld->cq_ring_mask;
472         if (o->cmd_type == FIO_URING_CMD_NVME)
473                 index <<= 1;
474
475         cqe = &ld->cq_ring.cqes[index];
476         io_u = (struct io_u *) (uintptr_t) cqe->user_data;
477
478         if (cqe->res != 0) {
479                 io_u->error = -cqe->res;
480                 return io_u;
481         } else {
482                 io_u->error = 0;
483         }
484
485         if (o->cmd_type == FIO_URING_CMD_NVME) {
486                 data = FILE_ENG_DATA(io_u->file);
487                 if (data->pi_type && (io_u->ddir == DDIR_READ) && !o->pi_act) {
488                         ret = fio_nvme_pi_verify(data, io_u);
489                         if (ret)
490                                 io_u->error = ret;
491                 }
492         }
493
494         return io_u;
495 }
496
497 static int fio_ioring_cqring_reap(struct thread_data *td, unsigned int events,
498                                    unsigned int max)
499 {
500         struct ioring_data *ld = td->io_ops_data;
501         struct io_cq_ring *ring = &ld->cq_ring;
502         unsigned head, reaped = 0;
503
504         head = *ring->head;
505         do {
506                 if (head == atomic_load_acquire(ring->tail))
507                         break;
508                 reaped++;
509                 head++;
510         } while (reaped + events < max);
511
512         if (reaped)
513                 atomic_store_release(ring->head, head);
514
515         return reaped;
516 }
517
518 static int fio_ioring_getevents(struct thread_data *td, unsigned int min,
519                                 unsigned int max, const struct timespec *t)
520 {
521         struct ioring_data *ld = td->io_ops_data;
522         unsigned actual_min = td->o.iodepth_batch_complete_min == 0 ? 0 : min;
523         struct ioring_options *o = td->eo;
524         struct io_cq_ring *ring = &ld->cq_ring;
525         unsigned events = 0;
526         int r;
527
528         ld->cq_ring_off = *ring->head;
529         do {
530                 r = fio_ioring_cqring_reap(td, events, max);
531                 if (r) {
532                         events += r;
533                         max -= r;
534                         if (actual_min != 0)
535                                 actual_min -= r;
536                         continue;
537                 }
538
539                 if (!o->sqpoll_thread) {
540                         r = io_uring_enter(ld, 0, actual_min,
541                                                 IORING_ENTER_GETEVENTS);
542                         if (r < 0) {
543                                 if (errno == EAGAIN || errno == EINTR)
544                                         continue;
545                                 r = -errno;
546                                 td_verror(td, errno, "io_uring_enter");
547                                 break;
548                         }
549                 }
550         } while (events < min);
551
552         return r < 0 ? r : events;
553 }
554
555 static inline void fio_ioring_cmd_nvme_pi(struct thread_data *td,
556                                           struct io_u *io_u)
557 {
558         struct ioring_data *ld = td->io_ops_data;
559         struct ioring_options *o = td->eo;
560         struct nvme_uring_cmd *cmd;
561         struct io_uring_sqe *sqe;
562         struct nvme_cmd_ext_io_opts ext_opts = {0};
563         struct nvme_data *data = FILE_ENG_DATA(io_u->file);
564
565         if (io_u->ddir == DDIR_TRIM)
566                 return;
567
568         sqe = &ld->sqes[(io_u->index) << 1];
569         cmd = (struct nvme_uring_cmd *)sqe->cmd;
570
571         if (data->pi_type) {
572                 if (o->pi_act)
573                         ext_opts.io_flags |= NVME_IO_PRINFO_PRACT;
574                 ext_opts.io_flags |= o->prchk;
575                 ext_opts.apptag = o->apptag;
576                 ext_opts.apptag_mask = o->apptag_mask;
577         }
578
579         fio_nvme_pi_fill(cmd, io_u, &ext_opts);
580 }
581
582 static inline void fio_ioring_cmdprio_prep(struct thread_data *td,
583                                            struct io_u *io_u)
584 {
585         struct ioring_data *ld = td->io_ops_data;
586         struct cmdprio *cmdprio = &ld->cmdprio;
587
588         if (fio_cmdprio_set_ioprio(td, cmdprio, io_u))
589                 ld->sqes[io_u->index].ioprio = io_u->ioprio;
590 }
591
592 static enum fio_q_status fio_ioring_queue(struct thread_data *td,
593                                           struct io_u *io_u)
594 {
595         struct ioring_data *ld = td->io_ops_data;
596         struct ioring_options *o = td->eo;
597         struct io_sq_ring *ring = &ld->sq_ring;
598         unsigned tail, next_tail;
599
600         fio_ro_check(td, io_u);
601
602         if (ld->queued == ld->iodepth)
603                 return FIO_Q_BUSY;
604
605         if (io_u->ddir == DDIR_TRIM && td->io_ops->flags & FIO_ASYNCIO_SYNC_TRIM) {
606                 if (ld->queued)
607                         return FIO_Q_BUSY;
608
609                 do_io_u_trim(td, io_u);
610
611                 io_u_mark_submit(td, 1);
612                 io_u_mark_complete(td, 1);
613                 return FIO_Q_COMPLETED;
614         }
615
616         tail = *ring->tail;
617         next_tail = tail + 1;
618         if (next_tail == atomic_load_relaxed(ring->head))
619                 return FIO_Q_BUSY;
620
621         if (ld->cmdprio.mode != CMDPRIO_MODE_NONE)
622                 fio_ioring_cmdprio_prep(td, io_u);
623
624         if (!strcmp(td->io_ops->name, "io_uring_cmd") &&
625                 o->cmd_type == FIO_URING_CMD_NVME)
626                 fio_ioring_cmd_nvme_pi(td, io_u);
627
628         ring->array[tail & ld->sq_ring_mask] = io_u->index;
629         atomic_store_release(ring->tail, next_tail);
630
631         ld->queued++;
632         return FIO_Q_QUEUED;
633 }
634
635 static void fio_ioring_queued(struct thread_data *td, int start, int nr)
636 {
637         struct ioring_data *ld = td->io_ops_data;
638         struct timespec now;
639
640         if (!fio_fill_issue_time(td))
641                 return;
642
643         fio_gettime(&now, NULL);
644
645         while (nr--) {
646                 struct io_sq_ring *ring = &ld->sq_ring;
647                 int index = ring->array[start & ld->sq_ring_mask];
648                 struct io_u *io_u = ld->io_u_index[index];
649
650                 memcpy(&io_u->issue_time, &now, sizeof(now));
651                 io_u_queued(td, io_u);
652
653                 start++;
654         }
655
656         /*
657          * only used for iolog
658          */
659         if (td->o.read_iolog_file)
660                 memcpy(&td->last_issue, &now, sizeof(now));
661 }
662
663 static int fio_ioring_commit(struct thread_data *td)
664 {
665         struct ioring_data *ld = td->io_ops_data;
666         struct ioring_options *o = td->eo;
667         int ret;
668
669         if (!ld->queued)
670                 return 0;
671
672         /*
673          * Kernel side does submission. just need to check if the ring is
674          * flagged as needing a kick, if so, call io_uring_enter(). This
675          * only happens if we've been idle too long.
676          */
677         if (o->sqpoll_thread) {
678                 struct io_sq_ring *ring = &ld->sq_ring;
679                 unsigned start = *ld->sq_ring.tail - ld->queued;
680                 unsigned flags;
681
682                 flags = atomic_load_relaxed(ring->flags);
683                 if (flags & IORING_SQ_NEED_WAKEUP)
684                         io_uring_enter(ld, ld->queued, 0,
685                                         IORING_ENTER_SQ_WAKEUP);
686                 fio_ioring_queued(td, start, ld->queued);
687                 io_u_mark_submit(td, ld->queued);
688
689                 ld->queued = 0;
690                 return 0;
691         }
692
693         do {
694                 unsigned start = *ld->sq_ring.head;
695                 long nr = ld->queued;
696
697                 ret = io_uring_enter(ld, nr, 0, IORING_ENTER_GETEVENTS);
698                 if (ret > 0) {
699                         fio_ioring_queued(td, start, ret);
700                         io_u_mark_submit(td, ret);
701
702                         ld->queued -= ret;
703                         ret = 0;
704                 } else if (!ret) {
705                         io_u_mark_submit(td, ret);
706                         continue;
707                 } else {
708                         if (errno == EAGAIN || errno == EINTR) {
709                                 ret = fio_ioring_cqring_reap(td, 0, ld->queued);
710                                 if (ret)
711                                         continue;
712                                 /* Shouldn't happen */
713                                 usleep(1);
714                                 continue;
715                         }
716                         ret = -errno;
717                         td_verror(td, errno, "io_uring_enter submit");
718                         break;
719                 }
720         } while (ld->queued);
721
722         return ret;
723 }
724
725 static void fio_ioring_unmap(struct ioring_data *ld)
726 {
727         int i;
728
729         for (i = 0; i < FIO_ARRAY_SIZE(ld->mmap); i++)
730                 munmap(ld->mmap[i].ptr, ld->mmap[i].len);
731         close(ld->ring_fd);
732 }
733
734 static void fio_ioring_cleanup(struct thread_data *td)
735 {
736         struct ioring_data *ld = td->io_ops_data;
737
738         if (ld) {
739                 if (!(td->flags & TD_F_CHILD))
740                         fio_ioring_unmap(ld);
741
742                 fio_cmdprio_cleanup(&ld->cmdprio);
743                 free(ld->io_u_index);
744                 free(ld->md_buf);
745                 free(ld->iovecs);
746                 free(ld->fds);
747                 free(ld->dsm);
748                 free(ld);
749         }
750 }
751
752 static int fio_ioring_mmap(struct ioring_data *ld, struct io_uring_params *p)
753 {
754         struct io_sq_ring *sring = &ld->sq_ring;
755         struct io_cq_ring *cring = &ld->cq_ring;
756         void *ptr;
757
758         ld->mmap[0].len = p->sq_off.array + p->sq_entries * sizeof(__u32);
759         ptr = mmap(0, ld->mmap[0].len, PROT_READ | PROT_WRITE,
760                         MAP_SHARED | MAP_POPULATE, ld->ring_fd,
761                         IORING_OFF_SQ_RING);
762         ld->mmap[0].ptr = ptr;
763         sring->head = ptr + p->sq_off.head;
764         sring->tail = ptr + p->sq_off.tail;
765         sring->ring_mask = ptr + p->sq_off.ring_mask;
766         sring->ring_entries = ptr + p->sq_off.ring_entries;
767         sring->flags = ptr + p->sq_off.flags;
768         sring->array = ptr + p->sq_off.array;
769         ld->sq_ring_mask = *sring->ring_mask;
770
771         if (p->flags & IORING_SETUP_SQE128)
772                 ld->mmap[1].len = 2 * p->sq_entries * sizeof(struct io_uring_sqe);
773         else
774                 ld->mmap[1].len = p->sq_entries * sizeof(struct io_uring_sqe);
775         ld->sqes = mmap(0, ld->mmap[1].len, PROT_READ | PROT_WRITE,
776                                 MAP_SHARED | MAP_POPULATE, ld->ring_fd,
777                                 IORING_OFF_SQES);
778         ld->mmap[1].ptr = ld->sqes;
779
780         if (p->flags & IORING_SETUP_CQE32) {
781                 ld->mmap[2].len = p->cq_off.cqes +
782                                         2 * p->cq_entries * sizeof(struct io_uring_cqe);
783         } else {
784                 ld->mmap[2].len = p->cq_off.cqes +
785                                         p->cq_entries * sizeof(struct io_uring_cqe);
786         }
787         ptr = mmap(0, ld->mmap[2].len, PROT_READ | PROT_WRITE,
788                         MAP_SHARED | MAP_POPULATE, ld->ring_fd,
789                         IORING_OFF_CQ_RING);
790         ld->mmap[2].ptr = ptr;
791         cring->head = ptr + p->cq_off.head;
792         cring->tail = ptr + p->cq_off.tail;
793         cring->ring_mask = ptr + p->cq_off.ring_mask;
794         cring->ring_entries = ptr + p->cq_off.ring_entries;
795         cring->cqes = ptr + p->cq_off.cqes;
796         ld->cq_ring_mask = *cring->ring_mask;
797         return 0;
798 }
799
800 static void fio_ioring_probe(struct thread_data *td)
801 {
802         struct ioring_data *ld = td->io_ops_data;
803         struct ioring_options *o = td->eo;
804         struct io_uring_probe *p;
805         int ret;
806
807         /* already set by user, don't touch */
808         if (o->nonvectored != -1)
809                 return;
810
811         /* default to off, as that's always safe */
812         o->nonvectored = 0;
813
814         p = calloc(1, sizeof(*p) + 256 * sizeof(struct io_uring_probe_op));
815         if (!p)
816                 return;
817
818         ret = syscall(__NR_io_uring_register, ld->ring_fd,
819                         IORING_REGISTER_PROBE, p, 256);
820         if (ret < 0)
821                 goto out;
822
823         if (IORING_OP_WRITE > p->ops_len)
824                 goto out;
825
826         if ((p->ops[IORING_OP_READ].flags & IO_URING_OP_SUPPORTED) &&
827             (p->ops[IORING_OP_WRITE].flags & IO_URING_OP_SUPPORTED))
828                 o->nonvectored = 1;
829 out:
830         free(p);
831 }
832
833 static int fio_ioring_queue_init(struct thread_data *td)
834 {
835         struct ioring_data *ld = td->io_ops_data;
836         struct ioring_options *o = td->eo;
837         int depth = td->o.iodepth;
838         struct io_uring_params p;
839         int ret;
840
841         memset(&p, 0, sizeof(p));
842
843         if (o->hipri)
844                 p.flags |= IORING_SETUP_IOPOLL;
845         if (o->sqpoll_thread) {
846                 p.flags |= IORING_SETUP_SQPOLL;
847                 if (o->sqpoll_set) {
848                         p.flags |= IORING_SETUP_SQ_AFF;
849                         p.sq_thread_cpu = o->sqpoll_cpu;
850                 }
851
852                 /*
853                  * Submission latency for sqpoll_thread is just the time it
854                  * takes to fill in the SQ ring entries, and any syscall if
855                  * IORING_SQ_NEED_WAKEUP is set, we don't need to log that time
856                  * separately.
857                  */
858                 td->o.disable_slat = 1;
859         }
860
861         /*
862          * Clamp CQ ring size at our SQ ring size, we don't need more entries
863          * than that.
864          */
865         p.flags |= IORING_SETUP_CQSIZE;
866         p.cq_entries = depth;
867
868         /*
869          * Setup COOP_TASKRUN as we don't need to get IPI interrupted for
870          * completing IO operations.
871          */
872         p.flags |= IORING_SETUP_COOP_TASKRUN;
873
874         /*
875          * io_uring is always a single issuer, and we can defer task_work
876          * runs until we reap events.
877          */
878         p.flags |= IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN;
879
880 retry:
881         ret = syscall(__NR_io_uring_setup, depth, &p);
882         if (ret < 0) {
883                 if (errno == EINVAL && p.flags & IORING_SETUP_DEFER_TASKRUN) {
884                         p.flags &= ~IORING_SETUP_DEFER_TASKRUN;
885                         p.flags &= ~IORING_SETUP_SINGLE_ISSUER;
886                         goto retry;
887                 }
888                 if (errno == EINVAL && p.flags & IORING_SETUP_COOP_TASKRUN) {
889                         p.flags &= ~IORING_SETUP_COOP_TASKRUN;
890                         goto retry;
891                 }
892                 if (errno == EINVAL && p.flags & IORING_SETUP_CQSIZE) {
893                         p.flags &= ~IORING_SETUP_CQSIZE;
894                         goto retry;
895                 }
896                 return ret;
897         }
898
899         ld->ring_fd = ret;
900
901         fio_ioring_probe(td);
902
903         if (o->fixedbufs) {
904                 ret = syscall(__NR_io_uring_register, ld->ring_fd,
905                                 IORING_REGISTER_BUFFERS, ld->iovecs, depth);
906                 if (ret < 0)
907                         return ret;
908         }
909
910         return fio_ioring_mmap(ld, &p);
911 }
912
913 static int fio_ioring_cmd_queue_init(struct thread_data *td)
914 {
915         struct ioring_data *ld = td->io_ops_data;
916         struct ioring_options *o = td->eo;
917         int depth = td->o.iodepth;
918         struct io_uring_params p;
919         int ret;
920
921         memset(&p, 0, sizeof(p));
922
923         if (o->hipri)
924                 p.flags |= IORING_SETUP_IOPOLL;
925         if (o->sqpoll_thread) {
926                 p.flags |= IORING_SETUP_SQPOLL;
927                 if (o->sqpoll_set) {
928                         p.flags |= IORING_SETUP_SQ_AFF;
929                         p.sq_thread_cpu = o->sqpoll_cpu;
930                 }
931
932                 /*
933                  * Submission latency for sqpoll_thread is just the time it
934                  * takes to fill in the SQ ring entries, and any syscall if
935                  * IORING_SQ_NEED_WAKEUP is set, we don't need to log that time
936                  * separately.
937                  */
938                 td->o.disable_slat = 1;
939         }
940         if (o->cmd_type == FIO_URING_CMD_NVME) {
941                 p.flags |= IORING_SETUP_SQE128;
942                 p.flags |= IORING_SETUP_CQE32;
943         }
944
945         /*
946          * Clamp CQ ring size at our SQ ring size, we don't need more entries
947          * than that.
948          */
949         p.flags |= IORING_SETUP_CQSIZE;
950         p.cq_entries = depth;
951
952         /*
953          * Setup COOP_TASKRUN as we don't need to get IPI interrupted for
954          * completing IO operations.
955          */
956         p.flags |= IORING_SETUP_COOP_TASKRUN;
957
958         /*
959          * io_uring is always a single issuer, and we can defer task_work
960          * runs until we reap events.
961          */
962         p.flags |= IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN;
963
964 retry:
965         ret = syscall(__NR_io_uring_setup, depth, &p);
966         if (ret < 0) {
967                 if (errno == EINVAL && p.flags & IORING_SETUP_DEFER_TASKRUN) {
968                         p.flags &= ~IORING_SETUP_DEFER_TASKRUN;
969                         p.flags &= ~IORING_SETUP_SINGLE_ISSUER;
970                         goto retry;
971                 }
972                 if (errno == EINVAL && p.flags & IORING_SETUP_COOP_TASKRUN) {
973                         p.flags &= ~IORING_SETUP_COOP_TASKRUN;
974                         goto retry;
975                 }
976                 if (errno == EINVAL && p.flags & IORING_SETUP_CQSIZE) {
977                         p.flags &= ~IORING_SETUP_CQSIZE;
978                         goto retry;
979                 }
980                 return ret;
981         }
982
983         ld->ring_fd = ret;
984
985         fio_ioring_probe(td);
986
987         if (o->fixedbufs) {
988                 ret = syscall(__NR_io_uring_register, ld->ring_fd,
989                                 IORING_REGISTER_BUFFERS, ld->iovecs, depth);
990                 if (ret < 0)
991                         return ret;
992         }
993
994         return fio_ioring_mmap(ld, &p);
995 }
996
997 static int fio_ioring_register_files(struct thread_data *td)
998 {
999         struct ioring_data *ld = td->io_ops_data;
1000         struct fio_file *f;
1001         unsigned int i;
1002         int ret;
1003
1004         ld->fds = calloc(td->o.nr_files, sizeof(int));
1005
1006         for_each_file(td, f, i) {
1007                 ret = generic_open_file(td, f);
1008                 if (ret)
1009                         goto err;
1010                 ld->fds[i] = f->fd;
1011                 f->engine_pos = i;
1012         }
1013
1014         ret = syscall(__NR_io_uring_register, ld->ring_fd,
1015                         IORING_REGISTER_FILES, ld->fds, td->o.nr_files);
1016         if (ret) {
1017 err:
1018                 free(ld->fds);
1019                 ld->fds = NULL;
1020         }
1021
1022         /*
1023          * Pretend the file is closed again, and really close it if we hit
1024          * an error.
1025          */
1026         for_each_file(td, f, i) {
1027                 if (ret) {
1028                         int fio_unused ret2;
1029                         ret2 = generic_close_file(td, f);
1030                 } else
1031                         f->fd = -1;
1032         }
1033
1034         return ret;
1035 }
1036
1037 static int fio_ioring_post_init(struct thread_data *td)
1038 {
1039         struct ioring_data *ld = td->io_ops_data;
1040         struct ioring_options *o = td->eo;
1041         struct io_u *io_u;
1042         int err, i;
1043
1044         for (i = 0; i < td->o.iodepth; i++) {
1045                 struct iovec *iov = &ld->iovecs[i];
1046
1047                 io_u = ld->io_u_index[i];
1048                 iov->iov_base = io_u->buf;
1049                 iov->iov_len = td_max_bs(td);
1050         }
1051
1052         err = fio_ioring_queue_init(td);
1053         if (err) {
1054                 int init_err = errno;
1055
1056                 if (init_err == ENOSYS)
1057                         log_err("fio: your kernel doesn't support io_uring\n");
1058                 td_verror(td, init_err, "io_queue_init");
1059                 return 1;
1060         }
1061
1062         for (i = 0; i < td->o.iodepth; i++) {
1063                 struct io_uring_sqe *sqe;
1064
1065                 sqe = &ld->sqes[i];
1066                 memset(sqe, 0, sizeof(*sqe));
1067         }
1068
1069         if (o->registerfiles) {
1070                 err = fio_ioring_register_files(td);
1071                 if (err) {
1072                         td_verror(td, errno, "ioring_register_files");
1073                         return 1;
1074                 }
1075         }
1076
1077         return 0;
1078 }
1079
1080 static int fio_ioring_cmd_post_init(struct thread_data *td)
1081 {
1082         struct ioring_data *ld = td->io_ops_data;
1083         struct ioring_options *o = td->eo;
1084         struct io_u *io_u;
1085         int err, i;
1086
1087         for (i = 0; i < td->o.iodepth; i++) {
1088                 struct iovec *iov = &ld->iovecs[i];
1089
1090                 io_u = ld->io_u_index[i];
1091                 iov->iov_base = io_u->buf;
1092                 iov->iov_len = td_max_bs(td);
1093         }
1094
1095         err = fio_ioring_cmd_queue_init(td);
1096         if (err) {
1097                 int init_err = errno;
1098
1099                 td_verror(td, init_err, "io_queue_init");
1100                 return 1;
1101         }
1102
1103         for (i = 0; i < td->o.iodepth; i++) {
1104                 struct io_uring_sqe *sqe;
1105
1106                 if (o->cmd_type == FIO_URING_CMD_NVME) {
1107                         sqe = &ld->sqes[i << 1];
1108                         memset(sqe, 0, 2 * sizeof(*sqe));
1109                 } else {
1110                         sqe = &ld->sqes[i];
1111                         memset(sqe, 0, sizeof(*sqe));
1112                 }
1113         }
1114
1115         if (o->registerfiles) {
1116                 err = fio_ioring_register_files(td);
1117                 if (err) {
1118                         td_verror(td, errno, "ioring_register_files");
1119                         return 1;
1120                 }
1121         }
1122
1123         return 0;
1124 }
1125
1126 static void parse_prchk_flags(struct ioring_options *o)
1127 {
1128         if (!o->pi_chk)
1129                 return;
1130
1131         if (strstr(o->pi_chk, "GUARD") != NULL)
1132                 o->prchk = NVME_IO_PRINFO_PRCHK_GUARD;
1133         if (strstr(o->pi_chk, "REFTAG") != NULL)
1134                 o->prchk |= NVME_IO_PRINFO_PRCHK_REF;
1135         if (strstr(o->pi_chk, "APPTAG") != NULL)
1136                 o->prchk |= NVME_IO_PRINFO_PRCHK_APP;
1137 }
1138
1139 static int fio_ioring_init(struct thread_data *td)
1140 {
1141         struct ioring_options *o = td->eo;
1142         struct ioring_data *ld;
1143         struct nvme_dsm *dsm;
1144         void *ptr;
1145         unsigned int dsm_size;
1146         unsigned long long md_size;
1147         int ret, i;
1148
1149         /* sqthread submission requires registered files */
1150         if (o->sqpoll_thread)
1151                 o->registerfiles = 1;
1152
1153         if (o->registerfiles && td->o.nr_files != td->o.open_files) {
1154                 log_err("fio: io_uring registered files require nr_files to "
1155                         "be identical to open_files\n");
1156                 return 1;
1157         }
1158
1159         ld = calloc(1, sizeof(*ld));
1160
1161         /* ring depth must be a power-of-2 */
1162         ld->iodepth = td->o.iodepth;
1163         td->o.iodepth = roundup_pow2(td->o.iodepth);
1164
1165         /* io_u index */
1166         ld->io_u_index = calloc(td->o.iodepth, sizeof(struct io_u *));
1167
1168         /*
1169          * metadata buffer for nvme command.
1170          * We are only supporting iomem=malloc / mem=malloc as of now.
1171          */
1172         if (!strcmp(td->io_ops->name, "io_uring_cmd") &&
1173             (o->cmd_type == FIO_URING_CMD_NVME) && o->md_per_io_size) {
1174                 md_size = (unsigned long long) o->md_per_io_size
1175                                 * (unsigned long long) td->o.iodepth;
1176                 md_size += page_mask + td->o.mem_align;
1177                 if (td->o.mem_align && td->o.mem_align > page_size)
1178                         md_size += td->o.mem_align - page_size;
1179                 if (td->o.mem_type == MEM_MALLOC) {
1180                         ld->md_buf = malloc(md_size);
1181                         if (!ld->md_buf) {
1182                                 free(ld);
1183                                 return 1;
1184                         }
1185                 } else {
1186                         log_err("fio: Only iomem=malloc or mem=malloc is supported\n");
1187                         free(ld);
1188                         return 1;
1189                 }
1190         }
1191         parse_prchk_flags(o);
1192
1193         ld->iovecs = calloc(td->o.iodepth, sizeof(struct iovec));
1194
1195         td->io_ops_data = ld;
1196
1197         ret = fio_cmdprio_init(td, &ld->cmdprio, &o->cmdprio_options);
1198         if (ret) {
1199                 td_verror(td, EINVAL, "fio_ioring_init");
1200                 return 1;
1201         }
1202
1203         /*
1204          * For io_uring_cmd, trims are async operations unless we are operating
1205          * in zbd mode where trim means zone reset.
1206          */
1207         if (!strcmp(td->io_ops->name, "io_uring_cmd") && td_trim(td) &&
1208             td->o.zone_mode == ZONE_MODE_ZBD) {
1209                 td->io_ops->flags |= FIO_ASYNCIO_SYNC_TRIM;
1210         } else {
1211                 dsm_size = sizeof(*ld->dsm) +
1212                         td->o.num_range * sizeof(struct nvme_dsm_range);
1213                 ld->dsm = calloc(td->o.iodepth, dsm_size);
1214                 ptr = ld->dsm;
1215                 for (i = 0; i < td->o.iodepth; i++) {
1216                         dsm = (struct nvme_dsm *)ptr;
1217                         dsm->nr_ranges = td->o.num_range;
1218                         ptr += dsm_size;
1219                 }
1220         }
1221
1222         return 0;
1223 }
1224
1225 static int fio_ioring_io_u_init(struct thread_data *td, struct io_u *io_u)
1226 {
1227         struct ioring_data *ld = td->io_ops_data;
1228         struct ioring_options *o = td->eo;
1229         struct nvme_pi_data *pi_data;
1230         char *p;
1231
1232         ld->io_u_index[io_u->index] = io_u;
1233
1234         if (!strcmp(td->io_ops->name, "io_uring_cmd")) {
1235                 p = PTR_ALIGN(ld->md_buf, page_mask) + td->o.mem_align;
1236                 p += o->md_per_io_size * io_u->index;
1237                 io_u->mmap_data = p;
1238
1239                 if (!o->pi_act) {
1240                         pi_data = calloc(1, sizeof(*pi_data));
1241                         pi_data->io_flags |= o->prchk;
1242                         pi_data->apptag_mask = o->apptag_mask;
1243                         pi_data->apptag = o->apptag;
1244                         io_u->engine_data = pi_data;
1245                 }
1246         }
1247
1248         return 0;
1249 }
1250
1251 static void fio_ioring_io_u_free(struct thread_data *td, struct io_u *io_u)
1252 {
1253         struct ioring_options *o = td->eo;
1254         struct nvme_pi *pi;
1255
1256         if (!strcmp(td->io_ops->name, "io_uring_cmd") &&
1257             (o->cmd_type == FIO_URING_CMD_NVME)) {
1258                 pi = io_u->engine_data;
1259                 free(pi);
1260                 io_u->engine_data = NULL;
1261         }
1262 }
1263
1264 static int fio_ioring_open_file(struct thread_data *td, struct fio_file *f)
1265 {
1266         struct ioring_data *ld = td->io_ops_data;
1267         struct ioring_options *o = td->eo;
1268
1269         if (!ld || !o->registerfiles)
1270                 return generic_open_file(td, f);
1271
1272         f->fd = ld->fds[f->engine_pos];
1273         return 0;
1274 }
1275
1276 static int fio_ioring_cmd_open_file(struct thread_data *td, struct fio_file *f)
1277 {
1278         struct ioring_data *ld = td->io_ops_data;
1279         struct ioring_options *o = td->eo;
1280
1281         if (o->cmd_type == FIO_URING_CMD_NVME) {
1282                 struct nvme_data *data = NULL;
1283                 unsigned int lba_size = 0;
1284                 __u64 nlba = 0;
1285                 int ret;
1286
1287                 /* Store the namespace-id and lba size. */
1288                 data = FILE_ENG_DATA(f);
1289                 if (data == NULL) {
1290                         data = calloc(1, sizeof(struct nvme_data));
1291                         ret = fio_nvme_get_info(f, &nlba, o->pi_act, data);
1292                         if (ret) {
1293                                 free(data);
1294                                 return ret;
1295                         }
1296
1297                         FILE_SET_ENG_DATA(f, data);
1298                 }
1299
1300                 lba_size = data->lba_ext ? data->lba_ext : data->lba_size;
1301
1302                 for_each_rw_ddir(ddir) {
1303                         if (td->o.min_bs[ddir] % lba_size || td->o.max_bs[ddir] % lba_size) {
1304                                 if (data->lba_ext) {
1305                                         log_err("%s: block size must be a multiple of %u "
1306                                                 "(LBA data size + Metadata size)\n", f->file_name, lba_size);
1307                                         if (td->o.min_bs[ddir] == td->o.max_bs[ddir] &&
1308                                             !(td->o.min_bs[ddir] % data->lba_size)) {
1309                                                 /* fixed block size is actually a multiple of LBA data size */
1310                                                 unsigned long long suggestion = lba_size *
1311                                                         (td->o.min_bs[ddir] / data->lba_size);
1312                                                 log_err("Did you mean to use a block size of %llu?\n", suggestion);
1313                                         }
1314                                 } else {
1315                                         log_err("%s: block size must be a multiple of LBA data size\n",
1316                                                 f->file_name);
1317                                 }
1318                                 td_verror(td, EINVAL, "fio_ioring_cmd_open_file");
1319                                 return 1;
1320                         }
1321                         if (data->ms && !data->lba_ext && ddir != DDIR_TRIM &&
1322                             (o->md_per_io_size < ((td->o.max_bs[ddir] / data->lba_size) *
1323                                                   data->ms))) {
1324                                 log_err("%s: md_per_io_size should be at least %llu bytes\n",
1325                                         f->file_name,
1326                                         ((td->o.max_bs[ddir] / data->lba_size) * data->ms));
1327                                 td_verror(td, EINVAL, "fio_ioring_cmd_open_file");
1328                                 return 1;
1329                         }
1330                 }
1331
1332                 /*
1333                  * For extended logical block sizes we cannot use verify when
1334                  * end to end data protection checks are enabled, as the PI
1335                  * section of data buffer conflicts with verify.
1336                  */
1337                 if (data->ms && data->pi_type && data->lba_ext &&
1338                     td->o.verify != VERIFY_NONE) {
1339                         log_err("%s: for extended LBA, verify cannot be used when E2E data protection is enabled\n",
1340                                 f->file_name);
1341                         td_verror(td, EINVAL, "fio_ioring_cmd_open_file");
1342                         return 1;
1343                 }
1344         }
1345         if (!ld || !o->registerfiles)
1346                 return generic_open_file(td, f);
1347
1348         f->fd = ld->fds[f->engine_pos];
1349         return 0;
1350 }
1351
1352 static int fio_ioring_close_file(struct thread_data *td, struct fio_file *f)
1353 {
1354         struct ioring_data *ld = td->io_ops_data;
1355         struct ioring_options *o = td->eo;
1356
1357         if (!ld || !o->registerfiles)
1358                 return generic_close_file(td, f);
1359
1360         f->fd = -1;
1361         return 0;
1362 }
1363
1364 static int fio_ioring_cmd_close_file(struct thread_data *td,
1365                                      struct fio_file *f)
1366 {
1367         struct ioring_data *ld = td->io_ops_data;
1368         struct ioring_options *o = td->eo;
1369
1370         if (o->cmd_type == FIO_URING_CMD_NVME) {
1371                 struct nvme_data *data = FILE_ENG_DATA(f);
1372
1373                 FILE_SET_ENG_DATA(f, NULL);
1374                 free(data);
1375         }
1376         if (!ld || !o->registerfiles)
1377                 return generic_close_file(td, f);
1378
1379         f->fd = -1;
1380         return 0;
1381 }
1382
1383 static int fio_ioring_cmd_get_file_size(struct thread_data *td,
1384                                         struct fio_file *f)
1385 {
1386         struct ioring_options *o = td->eo;
1387
1388         if (fio_file_size_known(f))
1389                 return 0;
1390
1391         if (o->cmd_type == FIO_URING_CMD_NVME) {
1392                 struct nvme_data *data = NULL;
1393                 __u64 nlba = 0;
1394                 int ret;
1395
1396                 data = calloc(1, sizeof(struct nvme_data));
1397                 ret = fio_nvme_get_info(f, &nlba, o->pi_act, data);
1398                 if (ret) {
1399                         free(data);
1400                         return ret;
1401                 }
1402
1403                 f->real_file_size = data->lba_size * nlba;
1404                 fio_file_set_size_known(f);
1405
1406                 FILE_SET_ENG_DATA(f, data);
1407                 return 0;
1408         }
1409         return generic_get_file_size(td, f);
1410 }
1411
1412 static int fio_ioring_cmd_get_zoned_model(struct thread_data *td,
1413                                           struct fio_file *f,
1414                                           enum zbd_zoned_model *model)
1415 {
1416         return fio_nvme_get_zoned_model(td, f, model);
1417 }
1418
1419 static int fio_ioring_cmd_report_zones(struct thread_data *td,
1420                                        struct fio_file *f, uint64_t offset,
1421                                        struct zbd_zone *zbdz,
1422                                        unsigned int nr_zones)
1423 {
1424         return fio_nvme_report_zones(td, f, offset, zbdz, nr_zones);
1425 }
1426
1427 static int fio_ioring_cmd_reset_wp(struct thread_data *td, struct fio_file *f,
1428                                    uint64_t offset, uint64_t length)
1429 {
1430         return fio_nvme_reset_wp(td, f, offset, length);
1431 }
1432
1433 static int fio_ioring_cmd_get_max_open_zones(struct thread_data *td,
1434                                              struct fio_file *f,
1435                                              unsigned int *max_open_zones)
1436 {
1437         return fio_nvme_get_max_open_zones(td, f, max_open_zones);
1438 }
1439
1440 static int fio_ioring_cmd_fetch_ruhs(struct thread_data *td, struct fio_file *f,
1441                                      struct fio_ruhs_info *fruhs_info)
1442 {
1443         struct nvme_fdp_ruh_status *ruhs;
1444         int bytes, ret, i;
1445
1446         bytes = sizeof(*ruhs) + FDP_MAX_RUHS * sizeof(struct nvme_fdp_ruh_status_desc);
1447         ruhs = scalloc(1, bytes);
1448         if (!ruhs)
1449                 return -ENOMEM;
1450
1451         ret = fio_nvme_iomgmt_ruhs(td, f, ruhs, bytes);
1452         if (ret)
1453                 goto free;
1454
1455         fruhs_info->nr_ruhs = le16_to_cpu(ruhs->nruhsd);
1456         for (i = 0; i < fruhs_info->nr_ruhs; i++)
1457                 fruhs_info->plis[i] = le16_to_cpu(ruhs->ruhss[i].pid);
1458 free:
1459         sfree(ruhs);
1460         return ret;
1461 }
1462
1463 static struct ioengine_ops ioengine_uring = {
1464         .name                   = "io_uring",
1465         .version                = FIO_IOOPS_VERSION,
1466         .flags                  = FIO_ASYNCIO_SYNC_TRIM | FIO_NO_OFFLOAD |
1467                                         FIO_ASYNCIO_SETS_ISSUE_TIME,
1468         .init                   = fio_ioring_init,
1469         .post_init              = fio_ioring_post_init,
1470         .io_u_init              = fio_ioring_io_u_init,
1471         .prep                   = fio_ioring_prep,
1472         .queue                  = fio_ioring_queue,
1473         .commit                 = fio_ioring_commit,
1474         .getevents              = fio_ioring_getevents,
1475         .event                  = fio_ioring_event,
1476         .cleanup                = fio_ioring_cleanup,
1477         .open_file              = fio_ioring_open_file,
1478         .close_file             = fio_ioring_close_file,
1479         .get_file_size          = generic_get_file_size,
1480         .options                = options,
1481         .option_struct_size     = sizeof(struct ioring_options),
1482 };
1483
1484 static struct ioengine_ops ioengine_uring_cmd = {
1485         .name                   = "io_uring_cmd",
1486         .version                = FIO_IOOPS_VERSION,
1487         .flags                  = FIO_NO_OFFLOAD | FIO_MEMALIGN | FIO_RAWIO |
1488                                         FIO_ASYNCIO_SETS_ISSUE_TIME |
1489                                         FIO_MULTI_RANGE_TRIM,
1490         .init                   = fio_ioring_init,
1491         .post_init              = fio_ioring_cmd_post_init,
1492         .io_u_init              = fio_ioring_io_u_init,
1493         .io_u_free              = fio_ioring_io_u_free,
1494         .prep                   = fio_ioring_cmd_prep,
1495         .queue                  = fio_ioring_queue,
1496         .commit                 = fio_ioring_commit,
1497         .getevents              = fio_ioring_getevents,
1498         .event                  = fio_ioring_cmd_event,
1499         .cleanup                = fio_ioring_cleanup,
1500         .open_file              = fio_ioring_cmd_open_file,
1501         .close_file             = fio_ioring_cmd_close_file,
1502         .get_file_size          = fio_ioring_cmd_get_file_size,
1503         .get_zoned_model        = fio_ioring_cmd_get_zoned_model,
1504         .report_zones           = fio_ioring_cmd_report_zones,
1505         .reset_wp               = fio_ioring_cmd_reset_wp,
1506         .get_max_open_zones     = fio_ioring_cmd_get_max_open_zones,
1507         .options                = options,
1508         .option_struct_size     = sizeof(struct ioring_options),
1509         .fdp_fetch_ruhs         = fio_ioring_cmd_fetch_ruhs,
1510 };
1511
1512 static void fio_init fio_ioring_register(void)
1513 {
1514         register_ioengine(&ioengine_uring);
1515         register_ioengine(&ioengine_uring_cmd);
1516 }
1517
1518 static void fio_exit fio_ioring_unregister(void)
1519 {
1520         unregister_ioengine(&ioengine_uring);
1521         unregister_ioengine(&ioengine_uring_cmd);
1522 }
1523 #endif