-/*
- * Return the data direction for the next io_u. If the job is a
- * mixed read/write workload, check the rwmix cycle and switch if
- * necessary.
- */
-static int get_rw_ddir(struct thread_data *td)
-{
- if (td_rw(td)) {
- struct timeval now;
- unsigned long elapsed;
-
- gettimeofday(&now, NULL);
- elapsed = mtime_since_now(&td->rwmix_switch);
-
- /*
- * Check if it's time to seed a new data direction.
- */
- if (elapsed >= td->rwmixcycle) {
- unsigned int v;
- long r;
-
- r = os_random_long(&td->rwmix_state);
- v = 1 + (int) (100.0 * (r / (RAND_MAX + 1.0)));
- if (v < td->rwmixread)
- td->rwmix_ddir = DDIR_READ;
- else
- td->rwmix_ddir = DDIR_WRITE;
- memcpy(&td->rwmix_switch, &now, sizeof(now));
- }
- return td->rwmix_ddir;
- } else if (td_read(td))
- return DDIR_READ;
- else
- return DDIR_WRITE;
-}
-
-static int td_io_prep(struct thread_data *td, struct io_u *io_u)
-{
- if (td->io_ops->prep && td->io_ops->prep(td, io_u))
- return 1;
-
- return 0;
-}
-
-void put_io_u(struct thread_data *td, struct io_u *io_u)
-{
- io_u->file = NULL;
- list_del(&io_u->list);
- list_add(&io_u->list, &td->io_u_freelist);
- td->cur_depth--;
-}
-
-static int fill_io_u(struct thread_data *td, struct fio_file *f,
- struct io_u *io_u)
-{
- /*
- * If using an iolog, grab next piece if any available.
- */
- if (td->read_iolog)
- return read_iolog_get(td, io_u);
-
- /*
- * No log, let the seq/rand engine retrieve the next position.
- */
- if (!get_next_offset(td, f, &io_u->offset)) {
- io_u->buflen = get_next_buflen(td);
-
- if (io_u->buflen) {
- io_u->ddir = get_rw_ddir(td);
-
- /*
- * If using a write iolog, store this entry.
- */
- if (td->write_iolog)
- write_iolog_put(td, io_u);
-
- io_u->file = f;
- return 0;
- }
- }
-
- return 1;
-}
-
-#define queue_full(td) list_empty(&(td)->io_u_freelist)
-
-struct io_u *__get_io_u(struct thread_data *td)
-{
- struct io_u *io_u = NULL;
-
- if (!queue_full(td)) {
- io_u = list_entry(td->io_u_freelist.next, struct io_u, list);
-
- io_u->error = 0;
- io_u->resid = 0;
- list_del(&io_u->list);
- list_add(&io_u->list, &td->io_u_busylist);
- td->cur_depth++;
- }
-
- return io_u;
-}
-
-/*
- * Return an io_u to be processed. Gets a buflen and offset, sets direction,
- * etc. The returned io_u is fully ready to be prepped and submitted.
- */
-static struct io_u *get_io_u(struct thread_data *td, struct fio_file *f)
-{
- struct io_u *io_u;
-
- io_u = __get_io_u(td);
- if (!io_u)
- return NULL;
-
- if (td->zone_bytes >= td->zone_size) {
- td->zone_bytes = 0;
- f->last_pos += td->zone_skip;
- }
-
- if (fill_io_u(td, f, io_u)) {
- put_io_u(td, io_u);
- return NULL;
- }
-
- if (io_u->buflen + io_u->offset > f->file_size) {
- if (td->io_ops->flags & FIO_RAWIO) {
- put_io_u(td, io_u);
- return NULL;
- }
-
- io_u->buflen = f->file_size - io_u->offset;
- }
-
- if (!io_u->buflen) {
- put_io_u(td, io_u);
- return NULL;
- }
-
- if (!td->read_iolog && !td->sequential)
- mark_random_map(td, f, io_u);
-
- f->last_pos += io_u->buflen;
-
- if (td->verify != VERIFY_NONE)
- populate_verify_io_u(td, io_u);
-
- if (td_io_prep(td, io_u)) {
- put_io_u(td, io_u);
- return NULL;
- }
-
- gettimeofday(&io_u->start_time, NULL);
- return io_u;
-}
-