libaio: Add vectored io support
authorRitesh Harjani (IBM) <ritesh.list@gmail.com>
Sat, 15 Feb 2025 08:41:30 +0000 (14:11 +0530)
committerJens Axboe <axboe@kernel.dk>
Mon, 17 Feb 2025 16:37:23 +0000 (09:37 -0700)
This adds support for doing vectored I/O to libaio.
Instead of using pread/pwrite calls, this allows libaio to use
preadv/pwritev calls which uses iovecs.
option: libaio_vectored=1

Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
Link: https://lore.kernel.org/r/f0d66512e3df3d2142910e996c42389c21232d12.1739608655.git.ritesh.list@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
HOWTO.rst
engines/libaio.c

index 504a64b8082adebdb23b6923509e6042f156cb36..3f2bde18dc39eb17741f8bb8ab881ee76a5cf12b 100644 (file)
--- a/HOWTO.rst
+++ b/HOWTO.rst
@@ -2515,6 +2515,10 @@ with the caveat that when used on the command line, they must come after the
        not support torn-write protection. To learn a file's torn-write limits, issue
        statx with STATX_WRITE_ATOMIC.
 
+.. option:: libaio_vectored=bool : [libaio]
+
+    Submit vectored read and write requests.
+
 .. option:: fdp=bool : [io_uring_cmd] [xnvme]
 
        Enable Flexible Data Placement mode for write commands.
index c2d437938e2284d50737dbae4a9f7c43ffe9a194..aff4025e0c5fec5df01b1d0862a04b402d0d9124 100644 (file)
@@ -37,6 +37,7 @@ struct libaio_data {
        struct io_u **io_us;
 
        struct io_u **io_u_index;
+       struct iovec *iovecs;           /* for vectored requests */
 
        /*
         * Basic ring buffer. 'head' is incremented in _queue(), and
@@ -60,6 +61,7 @@ struct libaio_options {
        unsigned int userspace_reap;
        struct cmdprio_options cmdprio_options;
        unsigned int nowait;
+       unsigned int vectored;
 };
 
 static struct fio_option options[] = {
@@ -81,6 +83,16 @@ static struct fio_option options[] = {
                .category = FIO_OPT_C_ENGINE,
                .group  = FIO_OPT_G_LIBAIO,
        },
+       {
+               .name   = "libaio_vectored",
+               .lname  = "Use libaio preadv,pwritev",
+               .type   = FIO_OPT_BOOL,
+               .off1   = offsetof(struct libaio_options, vectored),
+               .help   = "Use libaio {preadv,pwritev} instead of libaio {pread,pwrite}",
+               .category = FIO_OPT_C_ENGINE,
+               .group  = FIO_OPT_G_LIBAIO,
+       },
+
        CMDPRIO_OPTIONS(struct libaio_options, FIO_OPT_G_LIBAIO),
        {
                .name   = NULL,
@@ -101,13 +113,32 @@ static int fio_libaio_prep(struct thread_data *td, struct io_u *io_u)
        struct libaio_options *o = td->eo;
        struct fio_file *f = io_u->file;
        struct iocb *iocb = &io_u->iocb;
+       struct libaio_data *ld = td->io_ops_data;
 
        if (io_u->ddir == DDIR_READ) {
-               io_prep_pread(iocb, f->fd, io_u->xfer_buf, io_u->xfer_buflen, io_u->offset);
+               if (o->vectored) {
+                       struct iovec *iov = &ld->iovecs[io_u->index];
+
+                       iov->iov_base = io_u->xfer_buf;
+                       iov->iov_len = (size_t)io_u->xfer_buflen;
+                       io_prep_preadv(iocb, f->fd, iov, 1, io_u->offset);
+               } else {
+                       io_prep_pread(iocb, f->fd, io_u->xfer_buf, io_u->xfer_buflen,
+                                                 io_u->offset);
+               }
                if (o->nowait)
                        iocb->aio_rw_flags |= RWF_NOWAIT;
        } else if (io_u->ddir == DDIR_WRITE) {
-               io_prep_pwrite(iocb, f->fd, io_u->xfer_buf, io_u->xfer_buflen, io_u->offset);
+               if (o->vectored) {
+                       struct iovec *iov = &ld->iovecs[io_u->index];
+
+                       iov->iov_base = io_u->xfer_buf;
+                       iov->iov_len = (size_t)io_u->xfer_buflen;
+                       io_prep_pwritev(iocb, f->fd, iov, 1, io_u->offset);
+               } else {
+                       io_prep_pwrite(iocb, f->fd, io_u->xfer_buf, io_u->xfer_buflen,
+                                                  io_u->offset);
+               }
                if (o->nowait)
                        iocb->aio_rw_flags |= RWF_NOWAIT;
 #ifdef FIO_HAVE_RWF_ATOMIC
@@ -394,6 +425,7 @@ static void fio_libaio_cleanup(struct thread_data *td)
                        io_destroy(ld->aio_ctx);
 
                fio_cmdprio_cleanup(&ld->cmdprio);
+               free(ld->iovecs);
                free(ld->aio_events);
                free(ld->iocbs);
                free(ld->io_us);
@@ -428,6 +460,7 @@ static int fio_libaio_init(struct thread_data *td)
        ld->aio_events = calloc(ld->entries, sizeof(struct io_event));
        ld->iocbs = calloc(ld->entries, sizeof(struct iocb *));
        ld->io_us = calloc(ld->entries, sizeof(struct io_u *));
+       ld->iovecs = calloc(ld->entries, sizeof(ld->iovecs[0]));
 
        td->io_ops_data = ld;