struct libaio_data {
io_context_t aio_ctx;
struct io_event *aio_events;
+ struct io_u *sync_io_u;
};
static int fio_libaio_prep(struct thread_data fio_unused *td, struct io_u *io_u)
struct fio_file *f = io_u->file;
if (io_u->ddir == DDIR_READ)
- io_prep_pread(&io_u->iocb, f->fd, io_u->buf, io_u->buflen, io_u->offset);
+ io_prep_pread(&io_u->iocb, f->fd, io_u->xfer_buf, io_u->xfer_buflen, io_u->offset);
else if (io_u->ddir == DDIR_WRITE)
- io_prep_pwrite(&io_u->iocb, f->fd, io_u->buf, io_u->buflen, io_u->offset);
+ io_prep_pwrite(&io_u->iocb, f->fd, io_u->xfer_buf, io_u->xfer_buflen, io_u->offset);
else if (io_u->ddir == DDIR_SYNC)
io_prep_fsync(&io_u->iocb, f->fd);
else
{
struct libaio_data *ld = td->io_ops->data;
+ if (ld->sync_io_u) {
+ struct io_u *ret = ld->sync_io_u;
+
+ ld->sync_io_u = NULL;
+ return ret;
+ }
+
return ev_to_iou(ld->aio_events + event);
}
struct libaio_data *ld = td->io_ops->data;
long r;
+ if (ld->sync_io_u)
+ return 1;
+
do {
r = io_getevents(ld->aio_ctx, min, max, ld->aio_events, t);
if (r >= min)
usleep(100);
else if (ret == -EINTR)
continue;
- else
+ else if (ret == -EINVAL && io_u->ddir == DDIR_SYNC) {
+ /*
+ * the async fsync doesn't currently seem to be
+ * supported, so just fsync if we fail with EINVAL
+ * for a sync. since buffered io is also sync
+ * with libaio (still), we don't have pending
+ * requests to flush first.
+ */
+ ret = fsync(io_u->file->fd);
+ ld->sync_io_u = io_u;
+ break;
+ } else
break;
} while (1);
if (ret <= 0) {
- io_u->resid = io_u->buflen;
+ io_u->resid = io_u->xfer_buflen;
io_u->error = -ret;
return 1;
}