Fixup iolog replay and add 'wait' command
authorGlen Ogilvie <gogilvie@oss.co.nz>
Tue, 3 Nov 2009 20:52:36 +0000 (21:52 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Tue, 3 Nov 2009 20:52:36 +0000 (21:52 +0100)
I have been working with Mike O'Sullivan, a senior lecturer at the University
of Auckland, New Zealand. He has been adapting fio 1.34.1 to work with iolog
files and also to be able to read a "wait" command to allow the iolog file to
specify a wait (in millisecs) before the next io. Mike's not completely
confident that his changes are correct in the overall fio picture, but they are
working with the iolog files we are using. What we did:

1) We incorporated wait into iolog file reading;
2) We made some modifications so that read_iolog worked.

We have attached a patch for fio-1.34.1.tar.bz2 along with some demonstration
fio config files and iolog files.

We are doing this so we can use an open source SPC-1 emulator to
generate SPC-1 like workloads and then run them in fio.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
fio.c
io_ddir.h
log.c

diff --git a/fio.c b/fio.c
index 3a9a3badff0fddefbe9d4f0dca22768c52137c25..8f8bb56113d2de45fe28191094742b247c227a79 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -581,7 +581,8 @@ static void do_io(struct thread_data *td)
        else
                td_set_runstate(td, TD_RUNNING);
 
-       while ((td->this_io_bytes[0] + td->this_io_bytes[1]) < td->o.size) {
+       while ( (td->o.read_iolog_file && !flist_empty(&td->io_log_list)) ||
+               ((td->this_io_bytes[0] + td->this_io_bytes[1]) < td->o.size) ) {
                struct timeval comp_time;
                unsigned long bytes_done[2] = { 0, 0 };
                int min_evts = 0;
index 620a9ee32d51ec8f18d94c565da7b962f015adfe..03eefdb87c0db8931a82b8e7cd628fec4f957742 100644 (file)
--- a/io_ddir.h
+++ b/io_ddir.h
@@ -6,6 +6,7 @@ enum fio_ddir {
        DDIR_WRITE,
        DDIR_SYNC,
        DDIR_DATASYNC,
+       DDIR_WAIT,
        DDIR_INVAL = -1,
 };
 
diff --git a/log.c b/log.c
index c44d8221ee936c4c0d235c87efa0f7607eca8dc7..ba52f0768744df5ea19cec1c2758a399e0cc8db9 100644 (file)
--- a/log.c
+++ b/log.c
@@ -86,10 +86,8 @@ static int ipo_special(struct thread_data *td, struct io_piece *ipo)
        switch (ipo->file_action) {
        case FIO_LOG_OPEN_FILE:
                ret = td_io_open_file(td, f);
-               if (!ret) {
-                       free(ipo);
+               if (!ret)
                        break;
-               }
                td_verror(td, ret, "iolog open file");
                return -1;
        case FIO_LOG_CLOSE_FILE:
@@ -109,7 +107,8 @@ static int ipo_special(struct thread_data *td, struct io_piece *ipo)
 int read_iolog_get(struct thread_data *td, struct io_u *io_u)
 {
        struct io_piece *ipo;
-
+       unsigned long elapsed;
+       
        while (!flist_empty(&td->io_log_list)) {
                int ret;
 
@@ -125,20 +124,27 @@ int read_iolog_get(struct thread_data *td, struct io_u *io_u)
                        continue;
                }
 
-               io_u->offset = ipo->offset;
-               io_u->buflen = ipo->len;
                io_u->ddir = ipo->ddir;
-               io_u->file = td->files[ipo->fileno];
-               get_file(io_u->file);
-
-               dprint(FD_IO, "iolog: get %llu/%lu/%s\n", io_u->offset,
-                                       io_u->buflen, io_u->file->file_name);
-
-               if (ipo->delay)
-                       iolog_delay(td, ipo->delay);
+               if (ipo->ddir != DDIR_WAIT) {
+                       io_u->offset = ipo->offset;
+                       io_u->buflen = ipo->len;
+                       io_u->file = td->files[ipo->fileno];
+                       get_file(io_u->file);
+
+                       dprint(FD_IO, "iolog: get %llu/%lu/%s\n", io_u->offset,
+                                               io_u->buflen, io_u->file->file_name);
+                       if (ipo->delay) iolog_delay(td, ipo->delay);
+               } else {
+                       elapsed = mtime_since_genesis();
+                       if (ipo->delay > elapsed)
+                               usec_sleep(td, (ipo->delay - elapsed) * 1000);
+                               
+               }
 
                free(ipo);
-               return 0;
+               
+               if (ipo->ddir != DDIR_WAIT)
+                       return 0;
        }
 
        td->done = 1;
@@ -241,7 +247,7 @@ static int read_iolog2(struct thread_data *td, FILE *f)
 {
        unsigned long long offset;
        unsigned int bytes;
-       int reads, writes, fileno = 0, file_action = 0; /* stupid gcc */
+       int reads, writes, waits, fileno = 0, file_action = 0; /* stupid gcc */
        char *fname, *act;
        char *str, *p;
        enum fio_ddir rw;
@@ -256,7 +262,7 @@ static int read_iolog2(struct thread_data *td, FILE *f)
        fname = malloc(256+16);
        act = malloc(256+16);
 
-       reads = writes = 0;
+       reads = writes = waits = 0;
        while ((p = fgets(str, 4096, f)) != NULL) {
                struct io_piece *ipo;
                int r;
@@ -267,7 +273,9 @@ static int read_iolog2(struct thread_data *td, FILE *f)
                        /*
                         * Check action first
                         */
-                       if (!strcmp(act, "read"))
+                       if (!strcmp(act, "wait"))
+                               rw = DDIR_WAIT;
+                       else if (!strcmp(act, "read"))
                                rw = DDIR_READ;
                        else if (!strcmp(act, "write"))
                                rw = DDIR_WRITE;
@@ -312,6 +320,9 @@ static int read_iolog2(struct thread_data *td, FILE *f)
                        if (read_only)
                                continue;
                        writes++;
+               } else if (rw == DDIR_WAIT) {
+                       waits++;
+               } else if (rw == DDIR_INVAL) {
                } else if (!ddir_sync(rw)) {
                        log_err("bad ddir: %d\n", rw);
                        continue;
@@ -323,15 +334,18 @@ static int read_iolog2(struct thread_data *td, FILE *f)
                ipo = malloc(sizeof(*ipo));
                memset(ipo, 0, sizeof(*ipo));
                INIT_FLIST_HEAD(&ipo->list);
-               ipo->offset = offset;
-               ipo->len = bytes;
                ipo->ddir = rw;
-               if (bytes > td->o.max_bs[rw])
-                       td->o.max_bs[rw] = bytes;
-               if (rw == DDIR_INVAL) {
+               if (rw == DDIR_WAIT) {
+                       ipo->delay = offset;
+               } else {
+                       ipo->offset = offset;
+                       ipo->len = bytes;
+                       if (bytes > td->o.max_bs[rw])
+                               td->o.max_bs[rw] = bytes;
                        ipo->fileno = fileno;
                        ipo->file_action = file_action;
                }
+                       
                queue_io_piece(td, ipo);
        }
 
@@ -345,7 +359,7 @@ static int read_iolog2(struct thread_data *td, FILE *f)
                writes = 0;
        }
 
-       if (!reads && !writes)
+       if (!reads && !writes && !waits)
                return 1;
        else if (reads && !writes)
                td->o.td_ddir = TD_DDIR_READ;