io_u: cleanup and simplify __get_next_rand_offset_zoned_abs()
[fio.git] / io_u.c
diff --git a/io_u.c b/io_u.c
index 375413f4b6d230e38432484179327736ae2de060..6b950014aa7cb6382d5ce2be00e18b30c745ba7f 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -37,7 +37,7 @@ static bool random_map_free(struct fio_file *f, const uint64_t block)
  */
 static void mark_random_map(struct thread_data *td, struct io_u *io_u)
 {
-       unsigned int min_bs = td->o.rw_min_bs;
+       unsigned int min_bs = td->o.min_bs[io_u->ddir];
        struct fio_file *f = io_u->file;
        unsigned int nr_blocks;
        uint64_t block;
@@ -157,6 +157,66 @@ static int __get_next_rand_offset_gauss(struct thread_data *td,
        return 0;
 }
 
+static int __get_next_rand_offset_zoned_abs(struct thread_data *td,
+                                           struct fio_file *f,
+                                           enum fio_ddir ddir, uint64_t *b)
+{
+       struct zone_split_index *zsi;
+       uint64_t lastb, send, stotal;
+       static int warned;
+       unsigned int v;
+
+       lastb = last_block(td, f, ddir);
+       if (!lastb)
+               return 1;
+
+       if (!td->o.zone_split_nr[ddir]) {
+bail:
+               return __get_next_rand_offset(td, f, ddir, b, lastb);
+       }
+
+       /*
+        * Generate a value, v, between 1 and 100, both inclusive
+        */
+       v = rand32_between(&td->zone_state, 1, 100);
+
+       /*
+        * Find our generated table. 'send' is the end block of this zone,
+        * 'stotal' is our start offset.
+        */
+       zsi = &td->zone_state_index[ddir][v - 1];
+       stotal = zsi->size_prev / td->o.ba[ddir];
+       send = zsi->size / td->o.ba[ddir];
+
+       /*
+        * Should never happen
+        */
+       if (send == -1U) {
+               if (!warned) {
+                       log_err("fio: bug in zoned generation\n");
+                       warned = 1;
+               }
+               goto bail;
+       } else if (send > lastb) {
+               /*
+                * This happens if the user specifies ranges that exceed
+                * the file/device size. We can't handle that gracefully,
+                * so error and exit.
+                */
+               log_err("fio: zoned_abs sizes exceed file size\n");
+               return 1;
+       }
+
+       /*
+        * Generate index from 0..send-stotal
+        */
+       if (__get_next_rand_offset(td, f, ddir, b, send - stotal) == 1)
+               return 1;
+
+       *b += stotal;
+       return 0;
+}
+
 static int __get_next_rand_offset_zoned(struct thread_data *td,
                                        struct fio_file *f, enum fio_ddir ddir,
                                        uint64_t *b)
@@ -249,6 +309,8 @@ static int get_off_from_method(struct thread_data *td, struct fio_file *f,
                return __get_next_rand_offset_gauss(td, f, ddir, b);
        else if (td->o.random_distribution == FIO_RAND_DIST_ZONED)
                return __get_next_rand_offset_zoned(td, f, ddir, b);
+       else if (td->o.random_distribution == FIO_RAND_DIST_ZONED_ABS)
+               return __get_next_rand_offset_zoned_abs(td, f, ddir, b);
 
        log_err("fio: unknown random distribution: %d\n", td->o.random_distribution);
        return 1;
@@ -323,6 +385,17 @@ fetch:
        goto fetch;
 }
 
+static void loop_cache_invalidate(struct thread_data *td, struct fio_file *f)
+{
+       struct thread_options *o = &td->o;
+
+       if (o->invalidate_cache && !o->odirect) {
+               int fio_unused ret;
+
+               ret = file_invalidate_cache(td, f);
+       }
+}
+
 static int get_next_rand_block(struct thread_data *td, struct fio_file *f,
                               enum fio_ddir ddir, uint64_t *b)
 {
@@ -334,6 +407,7 @@ static int get_next_rand_block(struct thread_data *td, struct fio_file *f,
                fio_file_reset(td, f);
                if (!get_next_rand_offset(td, f, ddir, b))
                        return 0;
+               loop_cache_invalidate(td, f);
        }
 
        dprint(FD_IO, "%s: rand offset failed, last=%llu, size=%llu\n",
@@ -349,15 +423,14 @@ static int get_next_seq_offset(struct thread_data *td, struct fio_file *f,
 
        assert(ddir_rw(ddir));
 
+       /*
+        * If we reach the end for a time based run, reset us back to 0
+        * and invalidate the cache, if we need to.
+        */
        if (f->last_pos[ddir] >= f->io_size + get_start_offset(td, f) &&
            o->time_based) {
-               struct thread_options *o = &td->o;
-               uint64_t io_size = f->io_size + (f->io_size % o->min_bs[ddir]);
-
-               if (io_size > f->last_pos[ddir])
-                       f->last_pos[ddir] = 0;
-               else
-                       f->last_pos[ddir] = f->last_pos[ddir] - io_size;
+               f->last_pos[ddir] = f->file_offset;
+               loop_cache_invalidate(td, f);
        }
 
        if (f->last_pos[ddir] < f->real_file_size) {
@@ -552,9 +625,9 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u,
        if (!io_u_fits(td, io_u, minbs))
                return 0;
 
-       frand_max = rand_max(&td->bsrange_state);
+       frand_max = rand_max(&td->bsrange_state[ddir]);
        do {
-               r = __rand(&td->bsrange_state);
+               r = __rand(&td->bsrange_state[ddir]);
 
                if (!td->o.bssplit_nr[ddir]) {
                        buflen = 1 + (unsigned int) ((double) maxbs *
@@ -662,7 +735,7 @@ int io_u_quiesce(struct thread_data *td)
 static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir)
 {
        enum fio_ddir odir = ddir ^ 1;
-       long usec;
+       uint64_t usec;
        uint64_t now;
 
        assert(ddir_rw(ddir));
@@ -1602,7 +1675,7 @@ static void small_content_scramble(struct io_u *io_u)
        unsigned int i, nr_blocks = io_u->buflen / 512;
        uint64_t boffset;
        unsigned int offset;
-       void *p, *end;
+       char *p, *end;
 
        if (!nr_blocks)
                return;
@@ -1779,7 +1852,7 @@ static void account_io_completion(struct thread_data *td, struct io_u *io_u,
        if (td->parent)
                td = td->parent;
 
-       if (!td->o.stats)
+       if (!td->o.stats || td_ioengine_flagged(td, FIO_NOSTATS))
                return;
 
        if (no_reduce)
@@ -2188,7 +2261,7 @@ int do_io_u_trim(const struct thread_data *td, struct io_u *io_u)
        struct fio_file *f = io_u->file;
        int ret;
 
-       ret = os_trim(f->fd, io_u->offset, io_u->xfer_buflen);
+       ret = os_trim(f, io_u->offset, io_u->xfer_buflen);
        if (!ret)
                return io_u->xfer_buflen;