[PATCH] fio: fixup ->io_prep to not require 'read' and implement timeout
authorJens Axboe <axboe@suse.de>
Wed, 7 Dec 2005 07:56:28 +0000 (08:56 +0100)
committerJens Axboe <axboe@suse.de>
Wed, 7 Dec 2005 07:56:28 +0000 (08:56 +0100)
fio-io.c
fio.c
fio.h

index 3792a9bd50e712cd03481355e29ac49ef0ae0839..fc8dc83e5e8bb575bf42a27c1d7fbcdd0023b9aa 100644 (file)
--- a/fio-io.c
+++ b/fio-io.c
@@ -14,6 +14,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <assert.h>
+#include <time.h>
 #include <sys/mman.h>
 #include "fio.h"
 #include "os.h"
@@ -27,15 +28,45 @@ static int fio_io_sync(struct thread_data *td)
        return fsync(td->fd);
 }
 
+static int fill_timespec(struct timespec *ts)
+{
+#ifdef _POSIX_TIMERS
+       if (!clock_gettime(CLOCK_MONOTONIC, ts))
+               return 0;
+
+       perror("clock_gettime");
+#endif
+       return 1;
+}
+
+static unsigned long long ts_utime_since_now(struct timespec *t)
+{
+       long long sec, nsec;
+       struct timespec now;
+
+       if (fill_timespec(&now))
+               return 0;
+       
+       sec = now.tv_sec - t->tv_sec;
+       nsec = now.tv_nsec - t->tv_nsec;
+       if (sec > 0 && nsec < 0) {
+               sec--;
+               nsec += 1000000000;
+       }
+
+       sec *= 1000000;
+       nsec /= 1000;
+       return sec + nsec;
+}
+
 struct libaio_data {
        io_context_t aio_ctx;
        struct io_event *aio_events;
 };
 
-static int fio_libaio_io_prep(struct thread_data *td, struct io_u *io_u,
-                              int read)
+static int fio_libaio_io_prep(struct thread_data *td, struct io_u *io_u)
 {
-       if (read)
+       if (io_u->ddir == DDIR_READ)
                io_prep_pread(&io_u->iocb, td->fd, io_u->buf, io_u->buflen, io_u->offset);
        else
                io_prep_pwrite(&io_u->iocb, td->fd, io_u->buf, io_u->buflen, io_u->offset);
@@ -161,8 +192,7 @@ static int fio_posixaio_cancel(struct thread_data *td, struct io_u *io_u)
        return 1;
 }
 
-static int fio_posixaio_prep(struct thread_data *td, struct io_u *io_u,
-                             int read)
+static int fio_posixaio_prep(struct thread_data *td, struct io_u *io_u)
 {
        struct aiocb *aiocb = &io_u->aiocb;
 
@@ -180,7 +210,11 @@ static int fio_posixaio_getevents(struct thread_data *td, int min, int max,
 {
        struct posixaio_data *pd = td->io_data;
        struct list_head *entry;
-       int r;
+       struct timespec start;
+       int r, have_timeout = 0;
+
+       if (t && !fill_timespec(&start))
+               have_timeout = 1;
 
        r = 0;
 restart:
@@ -211,6 +245,14 @@ restart:
        if (r >= min)
                return r;
 
+       if (have_timeout) {
+               unsigned long long usec;
+
+               usec = (t->tv_sec * 1000000) + (t->tv_nsec / 1000);
+               if (ts_utime_since_now(&start) > usec)
+                       return r;
+       }
+
        /*
         * hrmpf, we need to wait for more. we should use aio_suspend, for
         * now just sleep a little and recheck status of busy-and-not-seen
@@ -308,8 +350,7 @@ static struct io_u *fio_syncio_event(struct thread_data *td, int event)
        return sd->last_io_u;
 }
 
-static int fio_syncio_prep(struct thread_data *td, struct io_u *io_u,
-                          int read)
+static int fio_syncio_prep(struct thread_data *td, struct io_u *io_u)
 {
        if (td->cur_off != io_u->offset) {
                if (lseek(td->fd, io_u->offset, SEEK_SET) == -1) {
@@ -331,7 +372,7 @@ static int fio_syncio_queue(struct thread_data *td, struct io_u *io_u)
        else
                ret = write(td->fd, io_u->buf, io_u->buflen);
 
-       if (ret != io_u->buflen) {
+       if ((unsigned int) ret != io_u->buflen) {
                if (ret > 0) {
                        io_u->resid = io_u->buflen - ret;
                        io_u->error = ENODATA;
diff --git a/fio.c b/fio.c
index cc5a9da315bf5f902d309056b0a2a5fcf5fd5210..7d186b0c8bcfecf7a3f1bccdc820c0f66b6537be 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -580,14 +580,14 @@ static struct io_u *__get_io_u(struct thread_data *td)
 
 static int td_io_prep(struct thread_data *td, struct io_u *io_u, int read)
 {
-       if (td->io_prep && td->io_prep(td, io_u, read))
-               return 1;
-
        if (read)
                io_u->ddir = DDIR_READ;
        else
                io_u->ddir = DDIR_WRITE;
 
+       if (td->io_prep && td->io_prep(td, io_u))
+               return 1;
+
        return 0;
 }
 
diff --git a/fio.h b/fio.h
index ff8e78ee14c452b1d95ebd4443c193f6fef8b966..6fad44966be16dec860503f8f5cda8a9d44c4211 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -148,7 +148,7 @@ struct thread_data {
 
        void *io_data;
        char io_engine_name[16];
-       int (*io_prep)(struct thread_data *, struct io_u *, int);
+       int (*io_prep)(struct thread_data *, struct io_u *);
        int (*io_queue)(struct thread_data *, struct io_u *);
        int (*io_getevents)(struct thread_data *, int, int, struct timespec *);
        struct io_u *(*io_event)(struct thread_data *, int);