@@ -37,6 +37,7 @@ struct libaio_data {
3737 struct io_u * * io_us ;
3838
3939 struct io_u * * io_u_index ;
40+ struct iovec * iovecs ; /* for vectored requests */
4041
4142 /*
4243 * Basic ring buffer. 'head' is incremented in _queue(), and
@@ -60,6 +61,7 @@ struct libaio_options {
6061 unsigned int userspace_reap ;
6162 struct cmdprio_options cmdprio_options ;
6263 unsigned int nowait ;
64+ unsigned int vectored ;
6365};
6466
6567static struct fio_option options [] = {
@@ -81,6 +83,16 @@ static struct fio_option options[] = {
8183 .category = FIO_OPT_C_ENGINE ,
8284 .group = FIO_OPT_G_LIBAIO ,
8385 },
86+ {
87+ .name = "libaio_vectored" ,
88+ .lname = "Use libaio preadv,pwritev" ,
89+ .type = FIO_OPT_BOOL ,
90+ .off1 = offsetof(struct libaio_options , vectored ),
91+ .help = "Use libaio {preadv,pwritev} instead of libaio {pread,pwrite}" ,
92+ .category = FIO_OPT_C_ENGINE ,
93+ .group = FIO_OPT_G_LIBAIO ,
94+ },
95+
8496 CMDPRIO_OPTIONS (struct libaio_options , FIO_OPT_G_LIBAIO ),
8597 {
8698 .name = NULL ,
@@ -101,13 +113,32 @@ static int fio_libaio_prep(struct thread_data *td, struct io_u *io_u)
101113 struct libaio_options * o = td -> eo ;
102114 struct fio_file * f = io_u -> file ;
103115 struct iocb * iocb = & io_u -> iocb ;
116+ struct libaio_data * ld = td -> io_ops_data ;
104117
105118 if (io_u -> ddir == DDIR_READ ) {
106- io_prep_pread (iocb , f -> fd , io_u -> xfer_buf , io_u -> xfer_buflen , io_u -> offset );
119+ if (o -> vectored ) {
120+ struct iovec * iov = & ld -> iovecs [io_u -> index ];
121+
122+ iov -> iov_base = io_u -> xfer_buf ;
123+ iov -> iov_len = (size_t )io_u -> xfer_buflen ;
124+ io_prep_preadv (iocb , f -> fd , iov , 1 , io_u -> offset );
125+ } else {
126+ io_prep_pread (iocb , f -> fd , io_u -> xfer_buf , io_u -> xfer_buflen ,
127+ io_u -> offset );
128+ }
107129 if (o -> nowait )
108130 iocb -> aio_rw_flags |= RWF_NOWAIT ;
109131 } else if (io_u -> ddir == DDIR_WRITE ) {
110- io_prep_pwrite (iocb , f -> fd , io_u -> xfer_buf , io_u -> xfer_buflen , io_u -> offset );
132+ if (o -> vectored ) {
133+ struct iovec * iov = & ld -> iovecs [io_u -> index ];
134+
135+ iov -> iov_base = io_u -> xfer_buf ;
136+ iov -> iov_len = (size_t )io_u -> xfer_buflen ;
137+ io_prep_pwritev (iocb , f -> fd , iov , 1 , io_u -> offset );
138+ } else {
139+ io_prep_pwrite (iocb , f -> fd , io_u -> xfer_buf , io_u -> xfer_buflen ,
140+ io_u -> offset );
141+ }
111142 if (o -> nowait )
112143 iocb -> aio_rw_flags |= RWF_NOWAIT ;
113144#ifdef FIO_HAVE_RWF_ATOMIC
@@ -394,6 +425,7 @@ static void fio_libaio_cleanup(struct thread_data *td)
394425 io_destroy (ld -> aio_ctx );
395426
396427 fio_cmdprio_cleanup (& ld -> cmdprio );
428+ free (ld -> iovecs );
397429 free (ld -> aio_events );
398430 free (ld -> iocbs );
399431 free (ld -> io_us );
@@ -428,6 +460,7 @@ static int fio_libaio_init(struct thread_data *td)
428460 ld -> aio_events = calloc (ld -> entries , sizeof (struct io_event ));
429461 ld -> iocbs = calloc (ld -> entries , sizeof (struct iocb * ));
430462 ld -> io_us = calloc (ld -> entries , sizeof (struct io_u * ));
463+ ld -> iovecs = calloc (ld -> entries , sizeof (ld -> iovecs [0 ]));
431464
432465 td -> io_ops_data = ld ;
433466
0 commit comments