Some more bits of blktrace support
[fio.git] / io_u.c
diff --git a/io_u.c b/io_u.c
index 31d3b14be50d0e124a8de277245cc043f4d1c624..7fe5242f51287b4bd72102400686eb6f1fcd31f7 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -6,7 +6,6 @@
 #include <assert.h>
 
 #include "fio.h"
-#include "os.h"
 
 /*
  * Change this define to play with the timeout handling
@@ -142,8 +141,12 @@ static int get_next_offset(struct thread_data *td, struct io_u *io_u)
 
                if (get_next_rand_offset(td, f, ddir, &b))
                        return 1;
-       } else
+       } else {
+               if (f->last_pos >= f->real_file_size)
+                       return 1;
+
                b = f->last_pos / td->o.min_bs[ddir];
+       }
 
        io_u->offset = (b * td->o.min_bs[ddir]) + f->file_offset;
        if (io_u->offset >= f->real_file_size)
@@ -154,7 +157,6 @@ static int get_next_offset(struct thread_data *td, struct io_u *io_u)
 
 static unsigned int get_next_buflen(struct thread_data *td, struct io_u *io_u)
 {
-       struct fio_file *f = io_u->file;
        const int ddir = io_u->ddir;
        unsigned int buflen;
        long r;
@@ -168,19 +170,6 @@ static unsigned int get_next_buflen(struct thread_data *td, struct io_u *io_u)
                        buflen = (buflen + td->o.min_bs[ddir] - 1) & ~(td->o.min_bs[ddir] - 1);
        }
 
-       while (buflen + io_u->offset > f->real_file_size) {
-               if (buflen == td->o.min_bs[ddir]) {
-                       if (!td->o.odirect) {
-                               assert(io_u->offset <= f->real_file_size);
-                               buflen = f->real_file_size - io_u->offset;
-                               return buflen;
-                       }
-                       return 0;
-               }
-
-               buflen = td->o.min_bs[ddir];
-       }
-
        return buflen;
 }
 
@@ -276,6 +265,9 @@ void put_io_u(struct thread_data *td, struct io_u *io_u)
        assert((io_u->flags & IO_U_F_FREE) == 0);
        io_u->flags |= IO_U_F_FREE;
 
+       if (io_u->file)
+               put_file(td, io_u->file);
+
        io_u->file = NULL;
        list_del(&io_u->list);
        list_add(&io_u->list, &td->io_u_freelist);
@@ -300,7 +292,7 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u)
        /*
         * If using an iolog, grab next piece if any available.
         */
-       if (td->o.read_iolog)
+       if (td->o.read_iolog_file)
                return read_iolog_get(td, io_u);
 
        /*
@@ -418,6 +410,8 @@ static struct fio_file *get_next_file_rand(struct thread_data *td, int goodf,
 
                fno = (unsigned int) ((double) td->o.nr_files * (r / (RAND_MAX + 1.0)));
                f = &td->files[fno];
+               if (f->flags & FIO_FILE_DONE)
+                       continue;
 
                if ((!goodf || (f->flags & goodf)) && !(f->flags & badf))
                        return f;
@@ -440,6 +434,11 @@ static struct fio_file *get_next_file_rr(struct thread_data *td, int goodf,
                if (td->next_file >= td->o.nr_files)
                        td->next_file = 0;
 
+               if (f->flags & FIO_FILE_DONE) {
+                       f = NULL;
+                       continue;
+               }
+
                if ((!goodf || (f->flags & goodf)) && !(f->flags & badf))
                        break;
 
@@ -455,7 +454,7 @@ static struct fio_file *get_next_file(struct thread_data *td)
 
        assert(td->o.nr_files <= td->files_index);
 
-       if (!td->nr_open_files)
+       if (!td->nr_open_files || td->nr_done_files >= td->o.nr_files)
                return NULL;
 
        f = td->file_service_file;
@@ -476,6 +475,9 @@ static struct fio_file *find_next_new_file(struct thread_data *td)
 {
        struct fio_file *f;
 
+       if (!td->nr_open_files || td->nr_done_files >= td->o.nr_files)
+               return NULL;
+
        if (td->o.file_service_type == FIO_FSERVICE_RR)
                f = get_next_file_rr(td, 0, FIO_FILE_OPEN);
        else
@@ -541,15 +543,19 @@ struct io_u *get_io_u(struct thread_data *td)
 
 set_file:
                io_u->file = f;
+               get_file(f);
 
                if (!fill_io_u(td, io_u))
                        break;
 
                /*
-                * No more to do for this file, close it
+                * td_io_close() does a put_file() as well, so no need to
+                * do that here.
                 */
                io_u->file = NULL;
                td_io_close_file(td, f);
+               f->flags |= FIO_FILE_DONE;
+               td->nr_done_files++;
 
                /*
                 * probably not the right place to do this, but see
@@ -572,15 +578,6 @@ set_file:
                f->last_pos += td->o.zone_skip;
        }
 
-       if (io_u->buflen + io_u->offset > f->real_file_size) {
-               if (td->io_ops->flags & FIO_RAWIO) {
-                       put_io_u(td, io_u);
-                       return NULL;
-               }
-
-               io_u->buflen = f->real_file_size - io_u->offset;
-       }
-
        if (io_u->ddir != DDIR_SYNC) {
                if (!io_u->buflen) {
                        put_io_u(td, io_u);
@@ -596,6 +593,7 @@ set_file:
        /*
         * Set io data pointers.
         */
+       io_u->endpos = io_u->offset + io_u->buflen;
 out:
        io_u->xfer_buf = io_u->buf;
        io_u->xfer_buflen = io_u->buflen;
@@ -634,8 +632,6 @@ static void io_completed(struct thread_data *td, struct io_u *io_u,
        assert(io_u->flags & IO_U_F_FLIGHT);
        io_u->flags &= ~IO_U_F_FLIGHT;
 
-       put_file(td, io_u->file);
-
        if (io_u->ddir == DDIR_SYNC) {
                td->last_was_sync = 1;
                return;
@@ -653,7 +649,7 @@ static void io_completed(struct thread_data *td, struct io_u *io_u,
                td->zone_bytes += bytes;
                td->this_io_bytes[idx] += bytes;
 
-               io_u->file->last_completed_pos = io_u->offset + io_u->buflen;
+               io_u->file->last_completed_pos = io_u->endpos;
 
                msec = mtime_since(&io_u->issue_time, &icd->time);
 
@@ -661,7 +657,7 @@ static void io_completed(struct thread_data *td, struct io_u *io_u,
                add_bw_sample(td, idx, &icd->time);
                io_u_mark_latency(td, msec);
 
-               if ((td_rw(td) || td_write(td)) && idx == DDIR_WRITE &&
+               if (td_write(td) && idx == DDIR_WRITE &&
                    td->o.verify != VERIFY_NONE)
                        log_io_piece(td, io_u);