Reduntant write bit checks
[fio.git] / io_u.c
diff --git a/io_u.c b/io_u.c
index a171ee4be8998cfd07612ea79bc6d854dbfcc3f3..d5dd84b96ddf9b00fa89134551fc323bce923eb3 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
@@ -97,6 +96,35 @@ static int get_next_free_block(struct thread_data *td, struct fio_file *f,
        return 1;
 }
 
+static int get_next_rand_offset(struct thread_data *td, struct fio_file *f,
+                               int ddir, unsigned long long *b)
+{
+       unsigned long long max_blocks = f->io_size / td->o.min_bs[ddir];
+       unsigned long long r, rb;
+       int loops = 5;
+
+       do {
+               r = os_random_long(&td->random_state);
+               if (!max_blocks)
+                       *b = 0;
+               else
+                       *b = ((max_blocks - 1) * r / (unsigned long long) (RAND_MAX+1.0));
+               if (td->o.norandommap)
+                       break;
+               rb = *b + (f->file_offset / td->o.min_bs[ddir]);
+               loops--;
+       } while (!random_map_free(td, f, rb) && loops);
+
+       /*
+        * if we failed to retrieve a truly random offset within
+        * the loops assigned, see if there are free ones left at all
+        */
+       if (!loops && get_next_free_block(td, f, b))
+               return 1;
+
+       return 0;
+}
+
 /*
  * For random io, generate a random new block and see if it's used. Repeat
  * until we find a free one. For sequential io, just return the end of
@@ -106,44 +134,20 @@ static int get_next_offset(struct thread_data *td, struct io_u *io_u)
 {
        struct fio_file *f = io_u->file;
        const int ddir = io_u->ddir;
-       unsigned long long b, rb;
-       long r;
-
-       if (td_random(td)) {
-               unsigned long long max_blocks = f->file_size / td->o.min_bs[ddir];
-               int loops = 5;
-
-               if (td->o.ddir_nr) {
-                       if (!--td->ddir_nr)
-                               td->ddir_nr = td->o.ddir_nr;
-                       else {
-                               b = f->last_pos / td->o.min_bs[ddir];
-                               goto out;
-                       }
-               }
+       unsigned long long b;
 
-               do {
-                       r = os_random_long(&td->random_state);
-                       if (!max_blocks)
-                               b = 0;
-                       else
-                               b = ((max_blocks - 1) * r / (unsigned long long) (RAND_MAX+1.0));
-                       if (td->o.norandommap)
-                               break;
-                       rb = b + (f->file_offset / td->o.min_bs[ddir]);
-                       loops--;
-               } while (!random_map_free(td, f, rb) && loops);
+       if (td_random(td) && (td->o.ddir_nr && !--td->ddir_nr)) {
+               td->ddir_nr = td->o.ddir_nr;
 
-               /*
-                * if we failed to retrieve a truly random offset within
-                * the loops assigned, see if there are free ones left at all
-                */
-               if (!loops && get_next_free_block(td, f, &b))
+               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];
+       }
 
-out:
        io_u->offset = (b * td->o.min_bs[ddir]) + f->file_offset;
        if (io_u->offset >= f->real_file_size)
                return 1;
@@ -153,7 +157,6 @@ out:
 
 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;
@@ -167,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;
 }
 
@@ -249,7 +239,7 @@ static enum fio_ddir get_rw_ddir(struct thread_data *td)
                         */
                        ddir = get_rand_ddir(td);
                        max_bytes = td->this_io_bytes[ddir];
-                       if (max_bytes >= (td->io_size * td->o.rwmix[ddir] / 100)) {
+                       if (max_bytes >= (td->o.size * td->o.rwmix[ddir] / 100)) {
                                if (!td->rw_end_set[ddir]) {
                                        td->rw_end_set[ddir] = 1;
                                        memcpy(&td->rw_end[ddir], &now, sizeof(now));
@@ -309,7 +299,7 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u)
           !(td->io_issues[DDIR_WRITE] % td->o.fsync_blocks) &&
             td->io_issues[DDIR_WRITE] && should_fsync(td)) {
                io_u->ddir = DDIR_SYNC;
-               return 0;
+               goto out;
        }
 
        io_u->ddir = get_rw_ddir(td);
@@ -328,12 +318,13 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u)
        /*
         * mark entry before potentially trimming io_u
         */
-       if (!td->o.read_iolog && td_random(td) && !td->o.norandommap)
+       if (td_random(td) && !td->o.norandommap)
                mark_random_map(td, io_u);
 
        /*
         * If using a write iolog, store this entry.
         */
+out:
        if (td->o.write_iolog_file)
                write_iolog_put(td, io_u);
 
@@ -416,6 +407,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;
@@ -438,6 +431,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;
 
@@ -453,7 +451,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;
@@ -474,6 +472,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
@@ -548,6 +549,8 @@ set_file:
                 */
                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
@@ -570,15 +573,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);
@@ -594,6 +588,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;
@@ -651,7 +646,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);
 
@@ -659,13 +654,14 @@ 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);
 
                icd->bytes_done[idx] += bytes;
 
                if (io_u->end_io) {
-                       ret = io_u->end_io(io_u);
+                       ret = io_u->end_io(td, io_u);
                        if (ret && !icd->error)
                                icd->error = ret;
                }