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