time_based: Avoid restarting main I/O loop
authorDaniel Ehrenberg <dehrenberg@google.com>
Fri, 16 Mar 2012 17:54:15 +0000 (18:54 +0100)
committerJens Axboe <axboe@kernel.dk>
Fri, 16 Mar 2012 17:54:15 +0000 (18:54 +0100)
Previously, when fio had written a volume of I/O equal to the size
argument, it restarted the main do_io loop.

This patch allows time_based tests to be run for longer than one
cycle in the do_io main loop. This has a couple of advantages:
 * The random number generator is not reset on each iteration
   of the loop, so running longer will reach different locations.
 * There is not a throughput-reducing point where all operations
   must be reaped before new operations are submitted.

The implementation consists of two minor changes:
 * In the do_io loop, a time_based test will not exit the loop for
   reading or writing too much data.
 * When reading or writing sequentially, the operations wrap around
   to the beginning after reading the end within the
   get_next_seq_block function.

Modified by Jens to properly restart when using a randommap
as well.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
backend.c
io_u.c

index a9885c6042f75e93a40bb073f2c215999c0d5eb6..23734d595d0d60325e0d2df7aa12fa13750fcc54 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -558,7 +558,8 @@ static void do_io(struct thread_data *td)
                td_set_runstate(td, TD_RUNNING);
 
        while ((td->o.read_iolog_file && !flist_empty(&td->io_log_list)) ||
-               (!flist_empty(&td->trim_list)) || !io_bytes_exceeded(td)) {
+               (!flist_empty(&td->trim_list)) || !io_bytes_exceeded(td) ||
+               td->o.time_based) {
                struct timeval comp_time;
                unsigned long bytes_done[2] = { 0, 0 };
                int min_evts = 0;
diff --git a/io_u.c b/io_u.c
index ba6757993a403ee34b11a222317460c4818a9dd7..65a144d3ad517c86a5e45386bc818a2293f38d2a 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -237,13 +237,18 @@ ret:
 static int get_next_rand_block(struct thread_data *td, struct fio_file *f,
                               enum fio_ddir ddir, unsigned long long *b)
 {
-       if (get_next_rand_offset(td, f, ddir, b)) {
-               dprint(FD_IO, "%s: rand offset failed, last=%llu, size=%llu\n",
-                               f->file_name, f->last_pos, f->real_file_size);
-               return 1;
+       if (!get_next_rand_offset(td, f, ddir, b))
+               return 0;
+
+       if (td->o.time_based) {
+               fio_file_reset(f);
+               if (!get_next_rand_offset(td, f, ddir, b))
+                       return 0;
        }
 
-       return 0;
+       dprint(FD_IO, "%s: rand offset failed, last=%llu, size=%llu\n",
+                       f->file_name, f->last_pos, f->real_file_size);
+       return 1;
 }
 
 static int get_next_seq_block(struct thread_data *td, struct fio_file *f,
@@ -251,6 +256,9 @@ static int get_next_seq_block(struct thread_data *td, struct fio_file *f,
 {
        assert(ddir_rw(ddir));
 
+       if (f->last_pos >= f->io_size && td->o.time_based)
+               f->last_pos = f->last_pos - f->io_size;
+
        if (f->last_pos < f->real_file_size) {
                unsigned long long pos;