engines/nvme: pass offset and len instead of io_u
[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_range *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
389         /* only supports nvme_uring_cmd */
390         if (o->cmd_type != FIO_URING_CMD_NVME)
391                 return -EINVAL;
392
393         if (io_u->ddir == DDIR_TRIM && td->io_ops->flags & FIO_ASYNCIO_SYNC_TRIM)
394                 return 0;
395
396         sqe = &ld->sqes[(io_u->index) << 1];
397
398         if (o->registerfiles) {
399                 sqe->fd = f->engine_pos;
400                 sqe->flags = IOSQE_FIXED_FILE;
401         } else {
402                 sqe->fd = f->fd;
403         }
404         sqe->rw_flags = 0;
405         if (!td->o.odirect && o->uncached)
406                 sqe->rw_flags |= RWF_UNCACHED;
407         if (o->nowait)
408                 sqe->rw_flags |= RWF_NOWAIT;
409
410         sqe->opcode = IORING_OP_URING_CMD;
411         sqe->user_data = (unsigned long) io_u;
412         if (o->nonvectored)
413                 sqe->cmd_op = NVME_URING_CMD_IO;
414         else
415                 sqe->cmd_op = NVME_URING_CMD_IO_VEC;
416         if (o->force_async && ++ld->prepped == o->force_async) {
417                 ld->prepped = 0;
418                 sqe->flags |= IOSQE_ASYNC;
419         }
420         if (o->fixedbufs) {
421                 sqe->uring_cmd_flags = IORING_URING_CMD_FIXED;
422                 sqe->buf_index = io_u->index;
423         }
424
425         cmd = (struct nvme_uring_cmd *)sqe->cmd;
426         return fio_nvme_uring_cmd_prep(cmd, io_u,
427                         o->nonvectored ? NULL : &ld->iovecs[io_u->index],
428                         &ld->dsm[io_u->index]);
429 }
430
431 static struct io_u *fio_ioring_event(struct thread_data *td, int event)
432 {
433         struct ioring_data *ld = td->io_ops_data;
434         struct io_uring_cqe *cqe;
435         struct io_u *io_u;
436         unsigned index;
437
438         index = (event + ld->cq_ring_off) & ld->cq_ring_mask;
439
440         cqe = &ld->cq_ring.cqes[index];
441         io_u = (struct io_u *) (uintptr_t) cqe->user_data;
442
443         if (cqe->res != io_u->xfer_buflen) {
444                 if (cqe->res > io_u->xfer_buflen)
445                         io_u->error = -cqe->res;
446                 else
447                         io_u->resid = io_u->xfer_buflen - cqe->res;
448         } else
449                 io_u->error = 0;
450
451         return io_u;
452 }
453
454 static struct io_u *fio_ioring_cmd_event(struct thread_data *td, int event)
455 {
456         struct ioring_data *ld = td->io_ops_data;
457         struct ioring_options *o = td->eo;
458         struct io_uring_cqe *cqe;
459         struct io_u *io_u;
460         struct nvme_data *data;
461         unsigned index;
462         int ret;
463
464         index = (event + ld->cq_ring_off) & ld->cq_ring_mask;
465         if (o->cmd_type == FIO_URING_CMD_NVME)
466                 index <<= 1;
467
468         cqe = &ld->cq_ring.cqes[index];
469         io_u = (struct io_u *) (uintptr_t) cqe->user_data;
470
471         if (cqe->res != 0) {
472                 io_u->error = -cqe->res;
473                 return io_u;
474         } else {
475                 io_u->error = 0;
476         }
477
478         if (o->cmd_type == FIO_URING_CMD_NVME) {
479                 data = FILE_ENG_DATA(io_u->file);
480                 if (data->pi_type && (io_u->ddir == DDIR_READ) && !o->pi_act) {
481                         ret = fio_nvme_pi_verify(data, io_u);
482                         if (ret)
483                                 io_u->error = ret;
484                 }
485         }
486
487         return io_u;
488 }
489
490 static int fio_ioring_cqring_reap(struct thread_data *td, unsigned int events,
491                                    unsigned int max)
492 {
493         struct ioring_data *ld = td->io_ops_data;
494         struct io_cq_ring *ring = &ld->cq_ring;
495         unsigned head, reaped = 0;
496
497         head = *ring->head;
498         do {
499                 if (head == atomic_load_acquire(ring->tail))
500                         break;
501                 reaped++;
502                 head++;
503         } while (reaped + events < max);
504
505         if (reaped)
506                 atomic_store_release(ring->head, head);
507
508         return reaped;
509 }
510
511 static int fio_ioring_getevents(struct thread_data *td, unsigned int min,
512                                 unsigned int max, const struct timespec *t)
513 {
514         struct ioring_data *ld = td->io_ops_data;
515         unsigned actual_min = td->o.iodepth_batch_complete_min == 0 ? 0 : min;
516         struct ioring_options *o = td->eo;
517         struct io_cq_ring *ring = &ld->cq_ring;
518         unsigned events = 0;
519         int r;
520
521         ld->cq_ring_off = *ring->head;
522         do {
523                 r = fio_ioring_cqring_reap(td, events, max);
524                 if (r) {
525                         events += r;
526                         max -= r;
527                         if (actual_min != 0)
528                                 actual_min -= r;
529                         continue;
530                 }
531
532                 if (!o->sqpoll_thread) {
533                         r = io_uring_enter(ld, 0, actual_min,
534                                                 IORING_ENTER_GETEVENTS);
535                         if (r < 0) {
536                                 if (errno == EAGAIN || errno == EINTR)
537                                         continue;
538                                 r = -errno;
539                                 td_verror(td, errno, "io_uring_enter");
540                                 break;
541                         }
542                 }
543         } while (events < min);
544
545         return r < 0 ? r : events;
546 }
547
548 static inline void fio_ioring_cmd_nvme_pi(struct thread_data *td,
549                                           struct io_u *io_u)
550 {
551         struct ioring_data *ld = td->io_ops_data;
552         struct ioring_options *o = td->eo;
553         struct nvme_uring_cmd *cmd;
554         struct io_uring_sqe *sqe;
555         struct nvme_cmd_ext_io_opts ext_opts = {0};
556         struct nvme_data *data = FILE_ENG_DATA(io_u->file);
557
558         if (io_u->ddir == DDIR_TRIM)
559                 return;
560
561         sqe = &ld->sqes[(io_u->index) << 1];
562         cmd = (struct nvme_uring_cmd *)sqe->cmd;
563
564         if (data->pi_type) {
565                 if (o->pi_act)
566                         ext_opts.io_flags |= NVME_IO_PRINFO_PRACT;
567                 ext_opts.io_flags |= o->prchk;
568                 ext_opts.apptag = o->apptag;
569                 ext_opts.apptag_mask = o->apptag_mask;
570         }
571
572         fio_nvme_pi_fill(cmd, io_u, &ext_opts);
573 }
574
575 static inline void fio_ioring_cmdprio_prep(struct thread_data *td,
576                                            struct io_u *io_u)
577 {
578         struct ioring_data *ld = td->io_ops_data;
579         struct cmdprio *cmdprio = &ld->cmdprio;
580
581         if (fio_cmdprio_set_ioprio(td, cmdprio, io_u))
582                 ld->sqes[io_u->index].ioprio = io_u->ioprio;
583 }
584
585 static enum fio_q_status fio_ioring_queue(struct thread_data *td,
586                                           struct io_u *io_u)
587 {
588         struct ioring_data *ld = td->io_ops_data;
589         struct ioring_options *o = td->eo;
590         struct io_sq_ring *ring = &ld->sq_ring;
591         unsigned tail, next_tail;
592
593         fio_ro_check(td, io_u);
594
595         if (ld->queued == ld->iodepth)
596                 return FIO_Q_BUSY;
597
598         if (io_u->ddir == DDIR_TRIM && td->io_ops->flags & FIO_ASYNCIO_SYNC_TRIM) {
599                 if (ld->queued)
600                         return FIO_Q_BUSY;
601
602                 do_io_u_trim(td, io_u);
603
604                 io_u_mark_submit(td, 1);
605                 io_u_mark_complete(td, 1);
606                 return FIO_Q_COMPLETED;
607         }
608
609         tail = *ring->tail;
610         next_tail = tail + 1;
611         if (next_tail == atomic_load_relaxed(ring->head))
612                 return FIO_Q_BUSY;
613
614         if (ld->cmdprio.mode != CMDPRIO_MODE_NONE)
615                 fio_ioring_cmdprio_prep(td, io_u);
616
617         if (!strcmp(td->io_ops->name, "io_uring_cmd") &&
618                 o->cmd_type == FIO_URING_CMD_NVME)
619                 fio_ioring_cmd_nvme_pi(td, io_u);
620
621         ring->array[tail & ld->sq_ring_mask] = io_u->index;
622         atomic_store_release(ring->tail, next_tail);
623
624         ld->queued++;
625         return FIO_Q_QUEUED;
626 }
627
628 static void fio_ioring_queued(struct thread_data *td, int start, int nr)
629 {
630         struct ioring_data *ld = td->io_ops_data;
631         struct timespec now;
632
633         if (!fio_fill_issue_time(td))
634                 return;
635
636         fio_gettime(&now, NULL);
637
638         while (nr--) {
639                 struct io_sq_ring *ring = &ld->sq_ring;
640                 int index = ring->array[start & ld->sq_ring_mask];
641                 struct io_u *io_u = ld->io_u_index[index];
642
643                 memcpy(&io_u->issue_time, &now, sizeof(now));
644                 io_u_queued(td, io_u);
645
646                 start++;
647         }
648
649         /*
650          * only used for iolog
651          */
652         if (td->o.read_iolog_file)
653                 memcpy(&td->last_issue, &now, sizeof(now));
654 }
655
656 static int fio_ioring_commit(struct thread_data *td)
657 {
658         struct ioring_data *ld = td->io_ops_data;
659         struct ioring_options *o = td->eo;
660         int ret;
661
662         if (!ld->queued)
663                 return 0;
664
665         /*
666          * Kernel side does submission. just need to check if the ring is
667          * flagged as needing a kick, if so, call io_uring_enter(). This
668          * only happens if we've been idle too long.
669          */
670         if (o->sqpoll_thread) {
671                 struct io_sq_ring *ring = &ld->sq_ring;
672                 unsigned start = *ld->sq_ring.tail - ld->queued;
673                 unsigned flags;
674
675                 flags = atomic_load_relaxed(ring->flags);
676                 if (flags & IORING_SQ_NEED_WAKEUP)
677                         io_uring_enter(ld, ld->queued, 0,
678                                         IORING_ENTER_SQ_WAKEUP);
679                 fio_ioring_queued(td, start, ld->queued);
680                 io_u_mark_submit(td, ld->queued);
681
682                 ld->queued = 0;
683                 return 0;
684         }
685
686         do {
687                 unsigned start = *ld->sq_ring.head;
688                 long nr = ld->queued;
689
690                 ret = io_uring_enter(ld, nr, 0, IORING_ENTER_GETEVENTS);
691                 if (ret > 0) {
692                         fio_ioring_queued(td, start, ret);
693                         io_u_mark_submit(td, ret);
694
695                         ld->queued -= ret;
696                         ret = 0;
697                 } else if (!ret) {
698                         io_u_mark_submit(td, ret);
699                         continue;
700                 } else {
701                         if (errno == EAGAIN || errno == EINTR) {
702                                 ret = fio_ioring_cqring_reap(td, 0, ld->queued);
703                                 if (ret)
704                                         continue;
705                                 /* Shouldn't happen */
706                                 usleep(1);
707                                 continue;
708                         }
709                         ret = -errno;
710                         td_verror(td, errno, "io_uring_enter submit");
711                         break;
712                 }
713         } while (ld->queued);
714
715         return ret;
716 }
717
718 static void fio_ioring_unmap(struct ioring_data *ld)
719 {
720         int i;
721
722         for (i = 0; i < FIO_ARRAY_SIZE(ld->mmap); i++)
723                 munmap(ld->mmap[i].ptr, ld->mmap[i].len);
724         close(ld->ring_fd);
725 }
726
727 static void fio_ioring_cleanup(struct thread_data *td)
728 {
729         struct ioring_data *ld = td->io_ops_data;
730
731         if (ld) {
732                 if (!(td->flags & TD_F_CHILD))
733                         fio_ioring_unmap(ld);
734
735                 fio_cmdprio_cleanup(&ld->cmdprio);
736                 free(ld->io_u_index);
737                 free(ld->md_buf);
738                 free(ld->iovecs);
739                 free(ld->fds);
740                 free(ld->dsm);
741                 free(ld);
742         }
743 }
744
745 static int fio_ioring_mmap(struct ioring_data *ld, struct io_uring_params *p)
746 {
747         struct io_sq_ring *sring = &ld->sq_ring;
748         struct io_cq_ring *cring = &ld->cq_ring;
749         void *ptr;
750
751         ld->mmap[0].len = p->sq_off.array + p->sq_entries * sizeof(__u32);
752         ptr = mmap(0, ld->mmap[0].len, PROT_READ | PROT_WRITE,
753                         MAP_SHARED | MAP_POPULATE, ld->ring_fd,
754                         IORING_OFF_SQ_RING);
755         ld->mmap[0].ptr = ptr;
756         sring->head = ptr + p->sq_off.head;
757         sring->tail = ptr + p->sq_off.tail;
758         sring->ring_mask = ptr + p->sq_off.ring_mask;
759         sring->ring_entries = ptr + p->sq_off.ring_entries;
760         sring->flags = ptr + p->sq_off.flags;
761         sring->array = ptr + p->sq_off.array;
762         ld->sq_ring_mask = *sring->ring_mask;
763
764         if (p->flags & IORING_SETUP_SQE128)
765                 ld->mmap[1].len = 2 * p->sq_entries * sizeof(struct io_uring_sqe);
766         else
767                 ld->mmap[1].len = p->sq_entries * sizeof(struct io_uring_sqe);
768         ld->sqes = mmap(0, ld->mmap[1].len, PROT_READ | PROT_WRITE,
769                                 MAP_SHARED | MAP_POPULATE, ld->ring_fd,
770                                 IORING_OFF_SQES);
771         ld->mmap[1].ptr = ld->sqes;
772
773         if (p->flags & IORING_SETUP_CQE32) {
774                 ld->mmap[2].len = p->cq_off.cqes +
775                                         2 * p->cq_entries * sizeof(struct io_uring_cqe);
776         } else {
777                 ld->mmap[2].len = p->cq_off.cqes +
778                                         p->cq_entries * sizeof(struct io_uring_cqe);
779         }
780         ptr = mmap(0, ld->mmap[2].len, PROT_READ | PROT_WRITE,
781                         MAP_SHARED | MAP_POPULATE, ld->ring_fd,
782                         IORING_OFF_CQ_RING);
783         ld->mmap[2].ptr = ptr;
784         cring->head = ptr + p->cq_off.head;
785         cring->tail = ptr + p->cq_off.tail;
786         cring->ring_mask = ptr + p->cq_off.ring_mask;
787         cring->ring_entries = ptr + p->cq_off.ring_entries;
788         cring->cqes = ptr + p->cq_off.cqes;
789         ld->cq_ring_mask = *cring->ring_mask;
790         return 0;
791 }
792
793 static void fio_ioring_probe(struct thread_data *td)
794 {
795         struct ioring_data *ld = td->io_ops_data;
796         struct ioring_options *o = td->eo;
797         struct io_uring_probe *p;
798         int ret;
799
800         /* already set by user, don't touch */
801         if (o->nonvectored != -1)
802                 return;
803
804         /* default to off, as that's always safe */
805         o->nonvectored = 0;
806
807         p = calloc(1, sizeof(*p) + 256 * sizeof(struct io_uring_probe_op));
808         if (!p)
809                 return;
810
811         ret = syscall(__NR_io_uring_register, ld->ring_fd,
812                         IORING_REGISTER_PROBE, p, 256);
813         if (ret < 0)
814                 goto out;
815
816         if (IORING_OP_WRITE > p->ops_len)
817                 goto out;
818
819         if ((p->ops[IORING_OP_READ].flags & IO_URING_OP_SUPPORTED) &&
820             (p->ops[IORING_OP_WRITE].flags & IO_URING_OP_SUPPORTED))
821                 o->nonvectored = 1;
822 out:
823         free(p);
824 }
825
826 static int fio_ioring_queue_init(struct thread_data *td)
827 {
828         struct ioring_data *ld = td->io_ops_data;
829         struct ioring_options *o = td->eo;
830         int depth = td->o.iodepth;
831         struct io_uring_params p;
832         int ret;
833
834         memset(&p, 0, sizeof(p));
835
836         if (o->hipri)
837                 p.flags |= IORING_SETUP_IOPOLL;
838         if (o->sqpoll_thread) {
839                 p.flags |= IORING_SETUP_SQPOLL;
840                 if (o->sqpoll_set) {
841                         p.flags |= IORING_SETUP_SQ_AFF;
842                         p.sq_thread_cpu = o->sqpoll_cpu;
843                 }
844
845                 /*
846                  * Submission latency for sqpoll_thread is just the time it
847                  * takes to fill in the SQ ring entries, and any syscall if
848                  * IORING_SQ_NEED_WAKEUP is set, we don't need to log that time
849                  * separately.
850                  */
851                 td->o.disable_slat = 1;
852         }
853
854         /*
855          * Clamp CQ ring size at our SQ ring size, we don't need more entries
856          * than that.
857          */
858         p.flags |= IORING_SETUP_CQSIZE;
859         p.cq_entries = depth;
860
861         /*
862          * Setup COOP_TASKRUN as we don't need to get IPI interrupted for
863          * completing IO operations.
864          */
865         p.flags |= IORING_SETUP_COOP_TASKRUN;
866
867         /*
868          * io_uring is always a single issuer, and we can defer task_work
869          * runs until we reap events.
870          */
871         p.flags |= IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN;
872
873 retry:
874         ret = syscall(__NR_io_uring_setup, depth, &p);
875         if (ret < 0) {
876                 if (errno == EINVAL && p.flags & IORING_SETUP_DEFER_TASKRUN) {
877                         p.flags &= ~IORING_SETUP_DEFER_TASKRUN;
878                         p.flags &= ~IORING_SETUP_SINGLE_ISSUER;
879                         goto retry;
880                 }
881                 if (errno == EINVAL && p.flags & IORING_SETUP_COOP_TASKRUN) {
882                         p.flags &= ~IORING_SETUP_COOP_TASKRUN;
883                         goto retry;
884                 }
885                 if (errno == EINVAL && p.flags & IORING_SETUP_CQSIZE) {
886                         p.flags &= ~IORING_SETUP_CQSIZE;
887                         goto retry;
888                 }
889                 return ret;
890         }
891
892         ld->ring_fd = ret;
893
894         fio_ioring_probe(td);
895
896         if (o->fixedbufs) {
897                 ret = syscall(__NR_io_uring_register, ld->ring_fd,
898                                 IORING_REGISTER_BUFFERS, ld->iovecs, depth);
899                 if (ret < 0)
900                         return ret;
901         }
902
903         return fio_ioring_mmap(ld, &p);
904 }
905
906 static int fio_ioring_cmd_queue_init(struct thread_data *td)
907 {
908         struct ioring_data *ld = td->io_ops_data;
909         struct ioring_options *o = td->eo;
910         int depth = td->o.iodepth;
911         struct io_uring_params p;
912         int ret;
913
914         memset(&p, 0, sizeof(p));
915
916         if (o->hipri)
917                 p.flags |= IORING_SETUP_IOPOLL;
918         if (o->sqpoll_thread) {
919                 p.flags |= IORING_SETUP_SQPOLL;
920                 if (o->sqpoll_set) {
921                         p.flags |= IORING_SETUP_SQ_AFF;
922                         p.sq_thread_cpu = o->sqpoll_cpu;
923                 }
924
925                 /*
926                  * Submission latency for sqpoll_thread is just the time it
927                  * takes to fill in the SQ ring entries, and any syscall if
928                  * IORING_SQ_NEED_WAKEUP is set, we don't need to log that time
929                  * separately.
930                  */
931                 td->o.disable_slat = 1;
932         }
933         if (o->cmd_type == FIO_URING_CMD_NVME) {
934                 p.flags |= IORING_SETUP_SQE128;
935                 p.flags |= IORING_SETUP_CQE32;
936         }
937
938         /*
939          * Clamp CQ ring size at our SQ ring size, we don't need more entries
940          * than that.
941          */
942         p.flags |= IORING_SETUP_CQSIZE;
943         p.cq_entries = depth;
944
945         /*
946          * Setup COOP_TASKRUN as we don't need to get IPI interrupted for
947          * completing IO operations.
948          */
949         p.flags |= IORING_SETUP_COOP_TASKRUN;
950
951         /*
952          * io_uring is always a single issuer, and we can defer task_work
953          * runs until we reap events.
954          */
955         p.flags |= IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN;
956
957 retry:
958         ret = syscall(__NR_io_uring_setup, depth, &p);
959         if (ret < 0) {
960                 if (errno == EINVAL && p.flags & IORING_SETUP_DEFER_TASKRUN) {
961                         p.flags &= ~IORING_SETUP_DEFER_TASKRUN;
962                         p.flags &= ~IORING_SETUP_SINGLE_ISSUER;
963                         goto retry;
964                 }
965                 if (errno == EINVAL && p.flags & IORING_SETUP_COOP_TASKRUN) {
966                         p.flags &= ~IORING_SETUP_COOP_TASKRUN;
967                         goto retry;
968                 }
969                 if (errno == EINVAL && p.flags & IORING_SETUP_CQSIZE) {
970                         p.flags &= ~IORING_SETUP_CQSIZE;
971                         goto retry;
972                 }
973                 return ret;
974         }
975
976         ld->ring_fd = ret;
977
978         fio_ioring_probe(td);
979
980         if (o->fixedbufs) {
981                 ret = syscall(__NR_io_uring_register, ld->ring_fd,
982                                 IORING_REGISTER_BUFFERS, ld->iovecs, depth);
983                 if (ret < 0)
984                         return ret;
985         }
986
987         return fio_ioring_mmap(ld, &p);
988 }
989
990 static int fio_ioring_register_files(struct thread_data *td)
991 {
992         struct ioring_data *ld = td->io_ops_data;
993         struct fio_file *f;
994         unsigned int i;
995         int ret;
996
997         ld->fds = calloc(td->o.nr_files, sizeof(int));
998
999         for_each_file(td, f, i) {
1000                 ret = generic_open_file(td, f);
1001                 if (ret)
1002                         goto err;
1003                 ld->fds[i] = f->fd;
1004                 f->engine_pos = i;
1005         }
1006
1007         ret = syscall(__NR_io_uring_register, ld->ring_fd,
1008                         IORING_REGISTER_FILES, ld->fds, td->o.nr_files);
1009         if (ret) {
1010 err:
1011                 free(ld->fds);
1012                 ld->fds = NULL;
1013         }
1014
1015         /*
1016          * Pretend the file is closed again, and really close it if we hit
1017          * an error.
1018          */
1019         for_each_file(td, f, i) {
1020                 if (ret) {
1021                         int fio_unused ret2;
1022                         ret2 = generic_close_file(td, f);
1023                 } else
1024                         f->fd = -1;
1025         }
1026
1027         return ret;
1028 }
1029
1030 static int fio_ioring_post_init(struct thread_data *td)
1031 {
1032         struct ioring_data *ld = td->io_ops_data;
1033         struct ioring_options *o = td->eo;
1034         struct io_u *io_u;
1035         int err, i;
1036
1037         for (i = 0; i < td->o.iodepth; i++) {
1038                 struct iovec *iov = &ld->iovecs[i];
1039
1040                 io_u = ld->io_u_index[i];
1041                 iov->iov_base = io_u->buf;
1042                 iov->iov_len = td_max_bs(td);
1043         }
1044
1045         err = fio_ioring_queue_init(td);
1046         if (err) {
1047                 int init_err = errno;
1048
1049                 if (init_err == ENOSYS)
1050                         log_err("fio: your kernel doesn't support io_uring\n");
1051                 td_verror(td, init_err, "io_queue_init");
1052                 return 1;
1053         }
1054
1055         for (i = 0; i < td->o.iodepth; i++) {
1056                 struct io_uring_sqe *sqe;
1057
1058                 sqe = &ld->sqes[i];
1059                 memset(sqe, 0, sizeof(*sqe));
1060         }
1061
1062         if (o->registerfiles) {
1063                 err = fio_ioring_register_files(td);
1064                 if (err) {
1065                         td_verror(td, errno, "ioring_register_files");
1066                         return 1;
1067                 }
1068         }
1069
1070         return 0;
1071 }
1072
1073 static int fio_ioring_cmd_post_init(struct thread_data *td)
1074 {
1075         struct ioring_data *ld = td->io_ops_data;
1076         struct ioring_options *o = td->eo;
1077         struct io_u *io_u;
1078         int err, i;
1079
1080         for (i = 0; i < td->o.iodepth; i++) {
1081                 struct iovec *iov = &ld->iovecs[i];
1082
1083                 io_u = ld->io_u_index[i];
1084                 iov->iov_base = io_u->buf;
1085                 iov->iov_len = td_max_bs(td);
1086         }
1087
1088         err = fio_ioring_cmd_queue_init(td);
1089         if (err) {
1090                 int init_err = errno;
1091
1092                 td_verror(td, init_err, "io_queue_init");
1093                 return 1;
1094         }
1095
1096         for (i = 0; i < td->o.iodepth; i++) {
1097                 struct io_uring_sqe *sqe;
1098
1099                 if (o->cmd_type == FIO_URING_CMD_NVME) {
1100                         sqe = &ld->sqes[i << 1];
1101                         memset(sqe, 0, 2 * sizeof(*sqe));
1102                 } else {
1103                         sqe = &ld->sqes[i];
1104                         memset(sqe, 0, sizeof(*sqe));
1105                 }
1106         }
1107
1108         if (o->registerfiles) {
1109                 err = fio_ioring_register_files(td);
1110                 if (err) {
1111                         td_verror(td, errno, "ioring_register_files");
1112                         return 1;
1113                 }
1114         }
1115
1116         return 0;
1117 }
1118
1119 static void parse_prchk_flags(struct ioring_options *o)
1120 {
1121         if (!o->pi_chk)
1122                 return;
1123
1124         if (strstr(o->pi_chk, "GUARD") != NULL)
1125                 o->prchk = NVME_IO_PRINFO_PRCHK_GUARD;
1126         if (strstr(o->pi_chk, "REFTAG") != NULL)
1127                 o->prchk |= NVME_IO_PRINFO_PRCHK_REF;
1128         if (strstr(o->pi_chk, "APPTAG") != NULL)
1129                 o->prchk |= NVME_IO_PRINFO_PRCHK_APP;
1130 }
1131
1132 static int fio_ioring_init(struct thread_data *td)
1133 {
1134         struct ioring_options *o = td->eo;
1135         struct ioring_data *ld;
1136         unsigned long long md_size;
1137         int ret;
1138
1139         /* sqthread submission requires registered files */
1140         if (o->sqpoll_thread)
1141                 o->registerfiles = 1;
1142
1143         if (o->registerfiles && td->o.nr_files != td->o.open_files) {
1144                 log_err("fio: io_uring registered files require nr_files to "
1145                         "be identical to open_files\n");
1146                 return 1;
1147         }
1148
1149         ld = calloc(1, sizeof(*ld));
1150
1151         /* ring depth must be a power-of-2 */
1152         ld->iodepth = td->o.iodepth;
1153         td->o.iodepth = roundup_pow2(td->o.iodepth);
1154
1155         /* io_u index */
1156         ld->io_u_index = calloc(td->o.iodepth, sizeof(struct io_u *));
1157
1158         /*
1159          * metadata buffer for nvme command.
1160          * We are only supporting iomem=malloc / mem=malloc as of now.
1161          */
1162         if (!strcmp(td->io_ops->name, "io_uring_cmd") &&
1163             (o->cmd_type == FIO_URING_CMD_NVME) && o->md_per_io_size) {
1164                 md_size = (unsigned long long) o->md_per_io_size
1165                                 * (unsigned long long) td->o.iodepth;
1166                 md_size += page_mask + td->o.mem_align;
1167                 if (td->o.mem_align && td->o.mem_align > page_size)
1168                         md_size += td->o.mem_align - page_size;
1169                 if (td->o.mem_type == MEM_MALLOC) {
1170                         ld->md_buf = malloc(md_size);
1171                         if (!ld->md_buf) {
1172                                 free(ld);
1173                                 return 1;
1174                         }
1175                 } else {
1176                         log_err("fio: Only iomem=malloc or mem=malloc is supported\n");
1177                         free(ld);
1178                         return 1;
1179                 }
1180         }
1181         parse_prchk_flags(o);
1182
1183         ld->iovecs = calloc(td->o.iodepth, sizeof(struct iovec));
1184
1185         td->io_ops_data = ld;
1186
1187         ret = fio_cmdprio_init(td, &ld->cmdprio, &o->cmdprio_options);
1188         if (ret) {
1189                 td_verror(td, EINVAL, "fio_ioring_init");
1190                 return 1;
1191         }
1192
1193         /*
1194          * For io_uring_cmd, trims are async operations unless we are operating
1195          * in zbd mode where trim means zone reset.
1196          */
1197         if (!strcmp(td->io_ops->name, "io_uring_cmd") && td_trim(td) &&
1198             td->o.zone_mode == ZONE_MODE_ZBD)
1199                 td->io_ops->flags |= FIO_ASYNCIO_SYNC_TRIM;
1200         else
1201                 ld->dsm = calloc(td->o.iodepth, sizeof(*ld->dsm));
1202
1203         return 0;
1204 }
1205
1206 static int fio_ioring_io_u_init(struct thread_data *td, struct io_u *io_u)
1207 {
1208         struct ioring_data *ld = td->io_ops_data;
1209         struct ioring_options *o = td->eo;
1210         struct nvme_pi_data *pi_data;
1211         char *p;
1212
1213         ld->io_u_index[io_u->index] = io_u;
1214
1215         if (!strcmp(td->io_ops->name, "io_uring_cmd")) {
1216                 p = PTR_ALIGN(ld->md_buf, page_mask) + td->o.mem_align;
1217                 p += o->md_per_io_size * io_u->index;
1218                 io_u->mmap_data = p;
1219
1220                 if (!o->pi_act) {
1221                         pi_data = calloc(1, sizeof(*pi_data));
1222                         pi_data->io_flags |= o->prchk;
1223                         pi_data->apptag_mask = o->apptag_mask;
1224                         pi_data->apptag = o->apptag;
1225                         io_u->engine_data = pi_data;
1226                 }
1227         }
1228
1229         return 0;
1230 }
1231
1232 static void fio_ioring_io_u_free(struct thread_data *td, struct io_u *io_u)
1233 {
1234         struct ioring_options *o = td->eo;
1235         struct nvme_pi *pi;
1236
1237         if (!strcmp(td->io_ops->name, "io_uring_cmd") &&
1238             (o->cmd_type == FIO_URING_CMD_NVME)) {
1239                 pi = io_u->engine_data;
1240                 free(pi);
1241                 io_u->engine_data = NULL;
1242         }
1243 }
1244
1245 static int fio_ioring_open_file(struct thread_data *td, struct fio_file *f)
1246 {
1247         struct ioring_data *ld = td->io_ops_data;
1248         struct ioring_options *o = td->eo;
1249
1250         if (!ld || !o->registerfiles)
1251                 return generic_open_file(td, f);
1252
1253         f->fd = ld->fds[f->engine_pos];
1254         return 0;
1255 }
1256
1257 static int fio_ioring_cmd_open_file(struct thread_data *td, struct fio_file *f)
1258 {
1259         struct ioring_data *ld = td->io_ops_data;
1260         struct ioring_options *o = td->eo;
1261
1262         if (o->cmd_type == FIO_URING_CMD_NVME) {
1263                 struct nvme_data *data = NULL;
1264                 unsigned int lba_size = 0;
1265                 __u64 nlba = 0;
1266                 int ret;
1267
1268                 /* Store the namespace-id and lba size. */
1269                 data = FILE_ENG_DATA(f);
1270                 if (data == NULL) {
1271                         data = calloc(1, sizeof(struct nvme_data));
1272                         ret = fio_nvme_get_info(f, &nlba, o->pi_act, data);
1273                         if (ret) {
1274                                 free(data);
1275                                 return ret;
1276                         }
1277
1278                         FILE_SET_ENG_DATA(f, data);
1279                 }
1280
1281                 lba_size = data->lba_ext ? data->lba_ext : data->lba_size;
1282
1283                 for_each_rw_ddir(ddir) {
1284                         if (td->o.min_bs[ddir] % lba_size || td->o.max_bs[ddir] % lba_size) {
1285                                 if (data->lba_ext) {
1286                                         log_err("%s: block size must be a multiple of %u "
1287                                                 "(LBA data size + Metadata size)\n", f->file_name, lba_size);
1288                                         if (td->o.min_bs[ddir] == td->o.max_bs[ddir] &&
1289                                             !(td->o.min_bs[ddir] % data->lba_size)) {
1290                                                 /* fixed block size is actually a multiple of LBA data size */
1291                                                 unsigned long long suggestion = lba_size *
1292                                                         (td->o.min_bs[ddir] / data->lba_size);
1293                                                 log_err("Did you mean to use a block size of %llu?\n", suggestion);
1294                                         }
1295                                 } else {
1296                                         log_err("%s: block size must be a multiple of LBA data size\n",
1297                                                 f->file_name);
1298                                 }
1299                                 td_verror(td, EINVAL, "fio_ioring_cmd_open_file");
1300                                 return 1;
1301                         }
1302                         if (data->ms && !data->lba_ext && ddir != DDIR_TRIM &&
1303                             (o->md_per_io_size < ((td->o.max_bs[ddir] / data->lba_size) *
1304                                                   data->ms))) {
1305                                 log_err("%s: md_per_io_size should be at least %llu bytes\n",
1306                                         f->file_name,
1307                                         ((td->o.max_bs[ddir] / data->lba_size) * data->ms));
1308                                 td_verror(td, EINVAL, "fio_ioring_cmd_open_file");
1309                                 return 1;
1310                         }
1311                 }
1312
1313                 /*
1314                  * For extended logical block sizes we cannot use verify when
1315                  * end to end data protection checks are enabled, as the PI
1316                  * section of data buffer conflicts with verify.
1317                  */
1318                 if (data->ms && data->pi_type && data->lba_ext &&
1319                     td->o.verify != VERIFY_NONE) {
1320                         log_err("%s: for extended LBA, verify cannot be used when E2E data protection is enabled\n",
1321                                 f->file_name);
1322                         td_verror(td, EINVAL, "fio_ioring_cmd_open_file");
1323                         return 1;
1324                 }
1325         }
1326         if (!ld || !o->registerfiles)
1327                 return generic_open_file(td, f);
1328
1329         f->fd = ld->fds[f->engine_pos];
1330         return 0;
1331 }
1332
1333 static int fio_ioring_close_file(struct thread_data *td, struct fio_file *f)
1334 {
1335         struct ioring_data *ld = td->io_ops_data;
1336         struct ioring_options *o = td->eo;
1337
1338         if (!ld || !o->registerfiles)
1339                 return generic_close_file(td, f);
1340
1341         f->fd = -1;
1342         return 0;
1343 }
1344
1345 static int fio_ioring_cmd_close_file(struct thread_data *td,
1346                                      struct fio_file *f)
1347 {
1348         struct ioring_data *ld = td->io_ops_data;
1349         struct ioring_options *o = td->eo;
1350
1351         if (o->cmd_type == FIO_URING_CMD_NVME) {
1352                 struct nvme_data *data = FILE_ENG_DATA(f);
1353
1354                 FILE_SET_ENG_DATA(f, NULL);
1355                 free(data);
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_get_file_size(struct thread_data *td,
1365                                         struct fio_file *f)
1366 {
1367         struct ioring_options *o = td->eo;
1368
1369         if (fio_file_size_known(f))
1370                 return 0;
1371
1372         if (o->cmd_type == FIO_URING_CMD_NVME) {
1373                 struct nvme_data *data = NULL;
1374                 __u64 nlba = 0;
1375                 int ret;
1376
1377                 data = calloc(1, sizeof(struct nvme_data));
1378                 ret = fio_nvme_get_info(f, &nlba, o->pi_act, data);
1379                 if (ret) {
1380                         free(data);
1381                         return ret;
1382                 }
1383
1384                 f->real_file_size = data->lba_size * nlba;
1385                 fio_file_set_size_known(f);
1386
1387                 FILE_SET_ENG_DATA(f, data);
1388                 return 0;
1389         }
1390         return generic_get_file_size(td, f);
1391 }
1392
1393 static int fio_ioring_cmd_get_zoned_model(struct thread_data *td,
1394                                           struct fio_file *f,
1395                                           enum zbd_zoned_model *model)
1396 {
1397         return fio_nvme_get_zoned_model(td, f, model);
1398 }
1399
1400 static int fio_ioring_cmd_report_zones(struct thread_data *td,
1401                                        struct fio_file *f, uint64_t offset,
1402                                        struct zbd_zone *zbdz,
1403                                        unsigned int nr_zones)
1404 {
1405         return fio_nvme_report_zones(td, f, offset, zbdz, nr_zones);
1406 }
1407
1408 static int fio_ioring_cmd_reset_wp(struct thread_data *td, struct fio_file *f,
1409                                    uint64_t offset, uint64_t length)
1410 {
1411         return fio_nvme_reset_wp(td, f, offset, length);
1412 }
1413
1414 static int fio_ioring_cmd_get_max_open_zones(struct thread_data *td,
1415                                              struct fio_file *f,
1416                                              unsigned int *max_open_zones)
1417 {
1418         return fio_nvme_get_max_open_zones(td, f, max_open_zones);
1419 }
1420
1421 static int fio_ioring_cmd_fetch_ruhs(struct thread_data *td, struct fio_file *f,
1422                                      struct fio_ruhs_info *fruhs_info)
1423 {
1424         struct nvme_fdp_ruh_status *ruhs;
1425         int bytes, ret, i;
1426
1427         bytes = sizeof(*ruhs) + FDP_MAX_RUHS * sizeof(struct nvme_fdp_ruh_status_desc);
1428         ruhs = scalloc(1, bytes);
1429         if (!ruhs)
1430                 return -ENOMEM;
1431
1432         ret = fio_nvme_iomgmt_ruhs(td, f, ruhs, bytes);
1433         if (ret)
1434                 goto free;
1435
1436         fruhs_info->nr_ruhs = le16_to_cpu(ruhs->nruhsd);
1437         for (i = 0; i < fruhs_info->nr_ruhs; i++)
1438                 fruhs_info->plis[i] = le16_to_cpu(ruhs->ruhss[i].pid);
1439 free:
1440         sfree(ruhs);
1441         return ret;
1442 }
1443
1444 static struct ioengine_ops ioengine_uring = {
1445         .name                   = "io_uring",
1446         .version                = FIO_IOOPS_VERSION,
1447         .flags                  = FIO_ASYNCIO_SYNC_TRIM | FIO_NO_OFFLOAD |
1448                                         FIO_ASYNCIO_SETS_ISSUE_TIME,
1449         .init                   = fio_ioring_init,
1450         .post_init              = fio_ioring_post_init,
1451         .io_u_init              = fio_ioring_io_u_init,
1452         .prep                   = fio_ioring_prep,
1453         .queue                  = fio_ioring_queue,
1454         .commit                 = fio_ioring_commit,
1455         .getevents              = fio_ioring_getevents,
1456         .event                  = fio_ioring_event,
1457         .cleanup                = fio_ioring_cleanup,
1458         .open_file              = fio_ioring_open_file,
1459         .close_file             = fio_ioring_close_file,
1460         .get_file_size          = generic_get_file_size,
1461         .options                = options,
1462         .option_struct_size     = sizeof(struct ioring_options),
1463 };
1464
1465 static struct ioengine_ops ioengine_uring_cmd = {
1466         .name                   = "io_uring_cmd",
1467         .version                = FIO_IOOPS_VERSION,
1468         .flags                  = FIO_NO_OFFLOAD | FIO_MEMALIGN | FIO_RAWIO |
1469                                         FIO_ASYNCIO_SETS_ISSUE_TIME,
1470         .init                   = fio_ioring_init,
1471         .post_init              = fio_ioring_cmd_post_init,
1472         .io_u_init              = fio_ioring_io_u_init,
1473         .io_u_free              = fio_ioring_io_u_free,
1474         .prep                   = fio_ioring_cmd_prep,
1475         .queue                  = fio_ioring_queue,
1476         .commit                 = fio_ioring_commit,
1477         .getevents              = fio_ioring_getevents,
1478         .event                  = fio_ioring_cmd_event,
1479         .cleanup                = fio_ioring_cleanup,
1480         .open_file              = fio_ioring_cmd_open_file,
1481         .close_file             = fio_ioring_cmd_close_file,
1482         .get_file_size          = fio_ioring_cmd_get_file_size,
1483         .get_zoned_model        = fio_ioring_cmd_get_zoned_model,
1484         .report_zones           = fio_ioring_cmd_report_zones,
1485         .reset_wp               = fio_ioring_cmd_reset_wp,
1486         .get_max_open_zones     = fio_ioring_cmd_get_max_open_zones,
1487         .options                = options,
1488         .option_struct_size     = sizeof(struct ioring_options),
1489         .fdp_fetch_ruhs         = fio_ioring_cmd_fetch_ruhs,
1490 };
1491
1492 static void fio_init fio_ioring_register(void)
1493 {
1494         register_ioengine(&ioengine_uring);
1495         register_ioengine(&ioengine_uring_cmd);
1496 }
1497
1498 static void fio_exit fio_ioring_unregister(void)
1499 {
1500         unregister_ioengine(&ioengine_uring);
1501         unregister_ioengine(&ioengine_uring_cmd);
1502 }
1503 #endif