Signal td->free_cond with the associated mutex held
[fio.git] / io_u.c
diff --git a/io_u.c b/io_u.c
index 1d6872edb2876794e9c4c07d5ea5e05a726f34dd..f3b593227043626d6978005c35ebec5c5a6472dc 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -163,7 +163,6 @@ static int __get_next_rand_offset_zoned_abs(struct thread_data *td,
 {
        struct zone_split_index *zsi;
        uint64_t lastb, send, stotal;
-       static int warned;
        unsigned int v;
 
        lastb = last_block(td, f, ddir);
@@ -192,10 +191,8 @@ bail:
         * Should never happen
         */
        if (send == -1U) {
-               if (!warned) {
+               if (!fio_did_warn(FIO_WARN_ZONED_BUG))
                        log_err("fio: bug in zoned generation\n");
-                       warned = 1;
-               }
                goto bail;
        } else if (send > lastb) {
                /*
@@ -223,7 +220,6 @@ static int __get_next_rand_offset_zoned(struct thread_data *td,
 {
        unsigned int v, send, stotal;
        uint64_t offset, lastb;
-       static int warned;
        struct zone_split_index *zsi;
 
        lastb = last_block(td, f, ddir);
@@ -248,10 +244,8 @@ bail:
         * Should never happen
         */
        if (send == -1U) {
-               if (!warned) {
+               if (!fio_did_warn(FIO_WARN_ZONED_BUG))
                        log_err("fio: bug in zoned generation\n");
-                       warned = 1;
-               }
                goto bail;
        }
 
@@ -436,7 +430,11 @@ static int get_next_seq_offset(struct thread_data *td, struct fio_file *f,
        if (f->last_pos[ddir] < f->real_file_size) {
                uint64_t pos;
 
-               if (f->last_pos[ddir] == f->file_offset && o->ddir_seq_add < 0) {
+               /*
+                * Only rewind if we already hit the end
+                */
+               if (f->last_pos[ddir] == f->file_offset &&
+                   f->file_offset && o->ddir_seq_add < 0) {
                        if (f->real_file_size > f->io_size)
                                f->last_pos[ddir] = f->io_size;
                        else
@@ -476,7 +474,7 @@ static int get_next_seq_offset(struct thread_data *td, struct fio_file *f,
 
 static int get_next_block(struct thread_data *td, struct io_u *io_u,
                          enum fio_ddir ddir, int rw_seq,
-                         unsigned int *is_random)
+                         bool *is_random)
 {
        struct fio_file *f = io_u->file;
        uint64_t b, offset;
@@ -490,27 +488,27 @@ static int get_next_block(struct thread_data *td, struct io_u *io_u,
                if (td_random(td)) {
                        if (should_do_random(td, ddir)) {
                                ret = get_next_rand_block(td, f, ddir, &b);
-                               *is_random = 1;
+                               *is_random = true;
                        } else {
-                               *is_random = 0;
+                               *is_random = false;
                                io_u_set(td, io_u, IO_U_F_BUSY_OK);
                                ret = get_next_seq_offset(td, f, ddir, &offset);
                                if (ret)
                                        ret = get_next_rand_block(td, f, ddir, &b);
                        }
                } else {
-                       *is_random = 0;
+                       *is_random = false;
                        ret = get_next_seq_offset(td, f, ddir, &offset);
                }
        } else {
                io_u_set(td, io_u, IO_U_F_BUSY_OK);
-               *is_random = 0;
+               *is_random = false;
 
                if (td->o.rw_seq == RW_SEQ_SEQ) {
                        ret = get_next_seq_offset(td, f, ddir, &offset);
                        if (ret) {
                                ret = get_next_rand_block(td, f, ddir, &b);
-                               *is_random = 0;
+                               *is_random = false;
                        }
                } else if (td->o.rw_seq == RW_SEQ_IDENT) {
                        if (f->last_start[ddir] != -1ULL)
@@ -543,8 +541,8 @@ static int get_next_block(struct thread_data *td, struct io_u *io_u,
  * until we find a free one. For sequential io, just return the end of
  * the last io issued.
  */
-static int __get_next_offset(struct thread_data *td, struct io_u *io_u,
-                            unsigned int *is_random)
+static int get_next_offset(struct thread_data *td, struct io_u *io_u,
+                          bool *is_random)
 {
        struct fio_file *f = io_u->file;
        enum fio_ddir ddir = io_u->ddir;
@@ -578,19 +576,6 @@ static int __get_next_offset(struct thread_data *td, struct io_u *io_u,
        return 0;
 }
 
-static int get_next_offset(struct thread_data *td, struct io_u *io_u,
-                          unsigned int *is_random)
-{
-       if (td->flags & TD_F_PROFILE_OPS) {
-               struct prof_io_ops *ops = &td->prof_io_ops;
-
-               if (ops->fill_io_u_off)
-                       return ops->fill_io_u_off(td, io_u, is_random);
-       }
-
-       return __get_next_offset(td, io_u, is_random);
-}
-
 static inline bool io_u_fits(struct thread_data *td, struct io_u *io_u,
                             unsigned int buflen)
 {
@@ -599,8 +584,8 @@ static inline bool io_u_fits(struct thread_data *td, struct io_u *io_u,
        return io_u->offset + buflen <= f->io_size + get_start_offset(td, f);
 }
 
-static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u,
-                                     unsigned int is_random)
+static unsigned int get_next_buflen(struct thread_data *td, struct io_u *io_u,
+                                   bool is_random)
 {
        int ddir = io_u->ddir;
        unsigned int buflen = 0;
@@ -611,7 +596,7 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u,
        assert(ddir_rw(ddir));
 
        if (td->o.bs_is_seq_rand)
-               ddir = is_random ? DDIR_WRITE: DDIR_READ;
+               ddir = is_random ? DDIR_WRITE : DDIR_READ;
 
        minbs = td->o.min_bs[ddir];
        maxbs = td->o.max_bs[ddir];
@@ -661,19 +646,6 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u,
        return buflen;
 }
 
-static unsigned int get_next_buflen(struct thread_data *td, struct io_u *io_u,
-                                   unsigned int is_random)
-{
-       if (td->flags & TD_F_PROFILE_OPS) {
-               struct prof_io_ops *ops = &td->prof_io_ops;
-
-               if (ops->fill_io_u_size)
-                       return ops->fill_io_u_size(td, io_u, is_random);
-       }
-
-       return __get_next_buflen(td, io_u, is_random);
-}
-
 static void set_rwmix_bytes(struct thread_data *td)
 {
        unsigned int diff;
@@ -884,8 +856,8 @@ void put_io_u(struct thread_data *td, struct io_u *io_u)
                assert(!(td->flags & TD_F_CHILD));
        }
        io_u_qpush(&td->io_u_freelist, io_u);
-       td_io_u_unlock(td);
        td_io_u_free_notify(td);
+       td_io_u_unlock(td);
 }
 
 void clear_io_u(struct thread_data *td, struct io_u *io_u)
@@ -917,8 +889,8 @@ void requeue_io_u(struct thread_data *td, struct io_u **io_u)
        }
 
        io_u_rpush(&td->io_u_requeues, __io_u);
-       td_io_u_unlock(td);
        td_io_u_free_notify(td);
+       td_io_u_unlock(td);
        *io_u = NULL;
 }
 
@@ -963,7 +935,7 @@ static void __fill_io_u_zone(struct thread_data *td, struct io_u *io_u)
 
 static int fill_io_u(struct thread_data *td, struct io_u *io_u)
 {
-       unsigned int is_random;
+       bool is_random;
 
        if (td_ioengine_flagged(td, FIO_NOIO))
                goto out;
@@ -1018,7 +990,7 @@ out:
        return 0;
 }
 
-static void __io_u_mark_map(unsigned int *map, unsigned int nr)
+static void __io_u_mark_map(uint64_t *map, unsigned int nr)
 {
        int idx = 0;
 
@@ -1393,13 +1365,6 @@ out:
 
 static struct fio_file *get_next_file(struct thread_data *td)
 {
-       if (td->flags & TD_F_PROFILE_OPS) {
-               struct prof_io_ops *ops = &td->prof_io_ops;
-
-               if (ops->get_next_file)
-                       return ops->get_next_file(td);
-       }
-
        return __get_next_file(td);
 }
 
@@ -1593,6 +1558,7 @@ bool queue_full(const struct thread_data *td)
 struct io_u *__get_io_u(struct thread_data *td)
 {
        struct io_u *io_u = NULL;
+       int ret;
 
        if (td->stop_io)
                return NULL;
@@ -1629,7 +1595,8 @@ again:
                 * return one
                 */
                assert(!(td->flags & TD_F_CHILD));
-               assert(!pthread_cond_wait(&td->free_cond, &td->io_u_lock));
+               ret = pthread_cond_wait(&td->free_cond, &td->io_u_lock);
+               assert(ret == 0);
                goto again;
        }
 
@@ -1921,7 +1888,8 @@ static void account_io_completion(struct thread_data *td, struct io_u *io_u,
 
                if (no_reduce && per_unit_log(td->iops_log))
                        add_iops_sample(td, io_u, bytes);
-       }
+       } else if (ddir_sync(idx) && !td->o.disable_clat)
+               add_sync_clat_sample(&td->ts, llnsec);
 
        if (td->ts.nr_block_infos && io_u->ddir == DDIR_TRIM) {
                uint32_t *info = io_u_block_info(td, io_u);
@@ -1959,6 +1927,12 @@ static void file_log_write_comp(const struct thread_data *td, struct fio_file *f
                f->last_write_idx = 0;
 }
 
+static bool should_account(struct thread_data *td)
+{
+       return ramp_time_over(td) && (td->runstate == TD_RUNNING ||
+                                          td->runstate == TD_VERIFYING);
+}
+
 static void io_completed(struct thread_data *td, struct io_u **io_u_ptr,
                         struct io_completion_data *icd)
 {
@@ -1987,15 +1961,17 @@ static void io_completed(struct thread_data *td, struct io_u **io_u_ptr,
        }
 
        if (ddir_sync(ddir)) {
-               td->last_was_sync = 1;
+               td->last_was_sync = true;
                if (f) {
                        f->first_write = -1ULL;
                        f->last_write = -1ULL;
                }
+               if (should_account(td))
+                       account_io_completion(td, io_u, icd, ddir, io_u->buflen);
                return;
        }
 
-       td->last_was_sync = 0;
+       td->last_was_sync = false;
        td->last_ddir = ddir;
 
        if (!io_u->error && ddir_rw(ddir)) {
@@ -2013,8 +1989,7 @@ static void io_completed(struct thread_data *td, struct io_u **io_u_ptr,
                if (ddir == DDIR_WRITE)
                        file_log_write_comp(td, f, io_u->offset, bytes);
 
-               if (ramp_time_over(td) && (td->runstate == TD_RUNNING ||
-                                          td->runstate == TD_VERIFYING))
+               if (should_account(td))
                        account_io_completion(td, io_u, icd, ddir, bytes);
 
                icd->bytes_done[ddir] += bytes;