Skip to content

Commit 7a7897a

Browse files
committed
Add posixaio_waitcomplete engine.
Provide a variant of the posixaio engine that uses FreeBSD's aio_waitcomplete() function to consume completions, instead of running around polling all IOs with aio_error(). Signed-off-by: Thomas Munro <thomas.munro@gmail.com>
1 parent 15ce99b commit 7a7897a

4 files changed

Lines changed: 110 additions & 0 deletions

File tree

HOWTO

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,6 +1945,11 @@ I/O engine
19451945
POSIX asynchronous I/O using :manpage:`aio_read(3)` and
19461946
:manpage:`aio_write(3)`.
19471947

1948+
**posixaio_waitcomplete**
1949+
POSIX asynchronous I/O, using FreeBSD's
1950+
aio_waitcomplete(2) to get completion events from the
1951+
kernel.
1952+
19481953
**solarisaio**
19491954
Solaris native asynchronous I/O.
19501955

configure

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,26 @@ EOF
737737
fi
738738
print_config "POSIX AIO fsync" "$posix_aio_fsync"
739739

740+
##########################################
741+
# aio_waitcomplete probe
742+
if test "have_aio_waitcomplete" != "yes" ; then
743+
have_aio_waitcomplete="no"
744+
fi
745+
cat > $TMPC <<EOF
746+
#include <aio.h>
747+
#include <stdlib.h>
748+
int main(void)
749+
{
750+
struct aiocb *cb;
751+
aio_waitcomplete(&cb, NULL);
752+
return 0;
753+
}
754+
EOF
755+
if compile_prog "" "" "aio_waitcomplete" ; then
756+
have_aio_waitcomplete="yes"
757+
fi
758+
print_config "aio_waitcomplete()" "$have_aio_waitcomplete"
759+
740760
##########################################
741761
# POSIX pshared attribute probe
742762
if test "$posix_pshared" != "yes" ; then
@@ -2858,6 +2878,9 @@ fi
28582878
if test "$posix_aio_fsync" = "yes" ; then
28592879
output_sym "CONFIG_POSIXAIO_FSYNC"
28602880
fi
2881+
if test "$have_aio_waitcomplete" = "yes" ; then
2882+
output_sym "CONFIG_HAVE_AIO_WAITCOMPLETE"
2883+
fi
28612884
if test "$posix_pshared" = "yes" ; then
28622885
output_sym "CONFIG_PSHARED"
28632886
fi

engines/posixaio.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,59 @@ static int fio_posixaio_prep(struct thread_data fio_unused *td,
5555
return 0;
5656
}
5757

58+
#ifdef CONFIG_HAVE_AIO_WAITCOMPLETE
59+
60+
static int fio_posixaio_waitcomplete_getevents(struct thread_data *td,
61+
unsigned int min,
62+
unsigned int max,
63+
const struct timespec *t)
64+
{
65+
struct posixaio_data *pd = td->io_ops_data;
66+
struct aiocb *aiocb;
67+
struct io_u *io_u;
68+
ssize_t retval;
69+
unsigned int events = 0;
70+
struct timespec zero_timeout = {0};
71+
struct timespec *timeout;
72+
73+
do
74+
{
75+
if (events < min) {
76+
/* Wait until the minimum is satisfied. */
77+
timeout = (struct timespec *)t;
78+
} else {
79+
/* Consume as many more as we can without waiting. */
80+
timeout = &zero_timeout;
81+
}
82+
83+
retval = aio_waitcomplete(&aiocb, timeout);
84+
if (retval < 0) {
85+
if (errno == EINTR)
86+
continue;
87+
if (errno == EAGAIN)
88+
break;
89+
td_verror(td, errno, "aio_waitcomplete");
90+
break;
91+
}
92+
93+
io_u = container_of(aiocb, struct io_u, aiocb);
94+
pd->queued--;
95+
pd->aio_events[events++] = io_u;
96+
97+
if (retval >= 0)
98+
io_u->resid = io_u->xfer_buflen - retval;
99+
else if (errno == ECANCELED)
100+
io_u->resid = io_u->xfer_buflen;
101+
else
102+
io_u->error = errno;
103+
104+
} while (events < max && pd->queued > 0);
105+
106+
return events;
107+
}
108+
109+
#endif
110+
58111
#define SUSPEND_ENTRIES 8
59112

60113
static int fio_posixaio_getevents(struct thread_data *td, unsigned int min,
@@ -223,12 +276,36 @@ static struct ioengine_ops ioengine = {
223276
.get_file_size = generic_get_file_size,
224277
};
225278

279+
#ifdef CONFIG_HAVE_AIO_WAITCOMPLETE
280+
static struct ioengine_ops ioengine_waitcomplete = {
281+
.name = "posixaio_waitcomplete",
282+
.version = FIO_IOOPS_VERSION,
283+
.flags = FIO_ASYNCIO_SYNC_TRIM,
284+
.init = fio_posixaio_init,
285+
.prep = fio_posixaio_prep,
286+
.queue = fio_posixaio_queue,
287+
.cancel = fio_posixaio_cancel,
288+
.getevents = fio_posixaio_waitcomplete_getevents,
289+
.event = fio_posixaio_event,
290+
.cleanup = fio_posixaio_cleanup,
291+
.open_file = generic_open_file,
292+
.close_file = generic_close_file,
293+
.get_file_size = generic_get_file_size,
294+
};
295+
#endif
296+
226297
static void fio_init fio_posixaio_register(void)
227298
{
228299
register_ioengine(&ioengine);
300+
#ifdef CONFIG_HAVE_AIO_WAITCOMPLETE
301+
register_ioengine(&ioengine_waitcomplete);
302+
#endif
229303
}
230304

231305
static void fio_exit fio_posixaio_unregister(void)
232306
{
233307
unregister_ioengine(&ioengine);
308+
#ifdef CONFIG_HAVE_AIO_WAITCOMPLETE
309+
unregister_ioengine(&ioengine_waitcomplete);
310+
#endif
234311
}

fio.1

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,6 +1739,11 @@ This engine defines engine specific options.
17391739
POSIX asynchronous I/O using \fBaio_read\fR\|(3) and
17401740
\fBaio_write\fR\|(3).
17411741
.TP
1742+
.B posixaio_waitcomplete
1743+
POSIX asynchronous I/O using \fBaio_read\fR\|(3) and
1744+
\fBaio_write\fR\|(3), with FreeBSD \fBaio_waitcomplete\fR\|(2)
1745+
to consume completion events.
1746+
.TP
17421747
.B solarisaio
17431748
Solaris native asynchronous I/O.
17441749
.TP

0 commit comments

Comments
 (0)