[PATCH] Make the libaio fsync fallback really work
[fio.git] / engines / libaio.c
index da43f18ce1571b7c729ceb35fce02ec1aae00e12..47c1d4b8d8603571779b59be064173327ae24c0c 100644 (file)
@@ -18,6 +18,7 @@
 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)
@@ -25,9 +26,9 @@ 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
@@ -40,6 +41,13 @@ static struct io_u *fio_libaio_event(struct thread_data *td, int event)
 {
        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);
 }
 
@@ -49,6 +57,9 @@ static int fio_libaio_getevents(struct thread_data *td, int min, int max,
        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)
@@ -77,17 +88,32 @@ static int fio_libaio_queue(struct thread_data *td, struct io_u *io_u)
        do {
                ret = io_submit(ld->aio_ctx, 1, &iocb);
                if (ret == 1)
-                       return 0;
+                       break;
                else if (ret == -EAGAIN || !ret)
                        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.
+                        */
+                       if (fsync(io_u->file->fd) < 0)
+                               ret = errno;
+                       else {
+                               ret = 1;
+                               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;
        }