implement zoned random I/O testing support
[fio.git] / io_u.c
diff --git a/io_u.c b/io_u.c
index d1f66a949293310f166690089438e2a883f9feec..703d1e85e45ad570715d237bd3dc96fccff6f020 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -114,6 +114,9 @@ static unsigned long long last_block(struct thread_data *td, struct fio_file *f,
        if (max_size > f->real_file_size)
                max_size = f->real_file_size;
 
+       if (td->o.zone_range)
+               max_size = td->o.zone_range;
+
        max_blocks = max_size / (unsigned long long) td->o.ba[ddir];
        if (!max_blocks)
                return 0;
@@ -597,13 +600,12 @@ void put_io_u(struct thread_data *td, struct io_u *io_u)
 {
        td_io_u_lock(td);
 
-       io_u->flags |= IO_U_F_FREE;
-       io_u->flags &= ~IO_U_F_FREE_DEF;
-
-       if (io_u->file)
+       if (io_u->file && !(io_u->flags & IO_U_F_FREE_DEF))
                put_file_log(td, io_u->file);
-
        io_u->file = NULL;
+       io_u->flags &= ~IO_U_F_FREE_DEF;
+       io_u->flags |= IO_U_F_FREE;
+
        if (io_u->flags & IO_U_F_IN_CUR_DEPTH)
                td->cur_depth--;
        flist_del_init(&io_u->list);
@@ -657,7 +659,8 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u)
         */
        if (td->zone_bytes >= td->o.zone_size) {
                td->zone_bytes = 0;
-               io_u->file->last_pos += td->o.zone_skip;
+               io_u->file->file_offset += td->o.zone_range + td->o.zone_skip;
+               io_u->file->last_pos = io_u->file->file_offset;
                td->io_skip_bytes += td->o.zone_skip;
        }
 
@@ -1297,6 +1300,16 @@ static void account_io_completion(struct thread_data *td, struct io_u *io_u,
        add_iops_sample(td, idx, &icd->time);
 }
 
+static long long usec_for_io(struct thread_data *td, enum fio_ddir ddir)
+{
+       unsigned long long secs, remainder, bps, bytes;
+       bytes = td->this_io_bytes[ddir];
+       bps = td->rate_bps[ddir];
+       secs = bytes / bps;
+       remainder = bytes % bps;
+       return remainder * 1000000 / bps + secs * 1000000;
+}
+
 static void io_completed(struct thread_data *td, struct io_u *io_u,
                         struct io_completion_data *icd)
 {
@@ -1355,14 +1368,12 @@ static void io_completed(struct thread_data *td, struct io_u *io_u,
 
                        if (__should_check_rate(td, idx)) {
                                td->rate_pending_usleep[idx] =
-                                       ((td->this_io_bytes[idx] *
-                                         td->rate_nsec_cycle[idx]) / 1000 -
+                                       (usec_for_io(td, idx) -
                                         utime_since_now(&td->start));
                        }
-                       if (__should_check_rate(td, idx ^ 1))
+                       if (__should_check_rate(td, odx))
                                td->rate_pending_usleep[odx] =
-                                       ((td->this_io_bytes[odx] *
-                                         td->rate_nsec_cycle[odx]) / 1000 -
+                                       (usec_for_io(td, odx) -
                                         utime_since_now(&td->start));
                }
 
@@ -1382,8 +1393,8 @@ static void io_completed(struct thread_data *td, struct io_u *io_u,
                icd->error = io_u->error;
                io_u_log_error(td, io_u);
        }
-       if (td->o.continue_on_error && icd->error &&
-           td_non_fatal_error(icd->error)) {
+       if (icd->error && td_non_fatal_error(icd->error) &&
+           (td->o.continue_on_error & td_error_type(io_u->ddir, icd->error))) {
                /*
                 * If there is a non_fatal error, then add to the error count
                 * and clear all the errors.