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