X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=io_u.c;h=d00e6e3fe44a593033670cd5f226fa07395a5698;hp=16065128c324e76e3cf9326ff1824fec42baad5b;hb=95603b7470fac1917cb11bc686e60b4339f8a2fc;hpb=56d9fa4b8d4fa5166e3ec5dcdd37b5789b2cb01d diff --git a/io_u.c b/io_u.c index 16065128..d00e6e3f 100644 --- a/io_u.c +++ b/io_u.c @@ -326,7 +326,7 @@ static int get_next_block(struct thread_data *td, struct io_u *io_u, *is_random = 1; } else { *is_random = 0; - io_u->flags |= IO_U_F_BUSY_OK; + io_u_set(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); @@ -336,7 +336,7 @@ static int get_next_block(struct thread_data *td, struct io_u *io_u, ret = get_next_seq_offset(td, f, ddir, &offset); } } else { - io_u->flags |= IO_U_F_BUSY_OK; + io_u_set(io_u, IO_U_F_BUSY_OK); *is_random = 0; if (td->o.rw_seq == RW_SEQ_SEQ) { @@ -485,7 +485,7 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u, ~(td->o.verify_interval - 1); if (!td->o.bs_unaligned && is_power_of_2(minbs)) - buflen = (buflen + minbs - 1) & ~(minbs - 1); + buflen &= ~(minbs - 1); } while (!io_u_fits(td, io_u, buflen)); @@ -552,7 +552,7 @@ void io_u_quiesce(struct thread_data *td) while (td->io_u_in_flight) { int fio_unused ret; - ret = io_u_queued_complete(td, 1, NULL); + ret = io_u_queued_complete(td, 1); } } @@ -591,7 +591,8 @@ static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir) } else usec = td->rate_pending_usleep[ddir]; - io_u_quiesce(td); + if (td->o.io_submit_mode == IO_MODE_INLINE) + io_u_quiesce(td); usec = usec_sleep(td, usec); @@ -668,13 +669,23 @@ static enum fio_ddir get_rw_ddir(struct thread_data *td) static void set_rw_ddir(struct thread_data *td, struct io_u *io_u) { - io_u->ddir = io_u->acct_ddir = get_rw_ddir(td); + enum fio_ddir ddir = get_rw_ddir(td); + + if (td_trimwrite(td)) { + struct fio_file *f = io_u->file; + if (f->last_pos[DDIR_WRITE] == f->last_pos[DDIR_TRIM]) + ddir = DDIR_TRIM; + else + ddir = DDIR_WRITE; + } + + io_u->ddir = io_u->acct_ddir = ddir; if (io_u->ddir == DDIR_WRITE && (td->io_ops->flags & FIO_BARRIER) && td->o.barrier_blocks && !(td->io_issues[DDIR_WRITE] % td->o.barrier_blocks) && td->io_issues[DDIR_WRITE]) - io_u->flags |= IO_U_F_BARRIER; + io_u_set(io_u, IO_U_F_BARRIER); } void put_file_log(struct thread_data *td, struct fio_file *f) @@ -687,16 +698,21 @@ void put_file_log(struct thread_data *td, struct fio_file *f) void put_io_u(struct thread_data *td, struct io_u *io_u) { + if (td->parent) + td = td->parent; + td_io_u_lock(td); if (io_u->file && !(io_u->flags & IO_U_F_NO_FILE_PUT)) put_file_log(td, io_u->file); io_u->file = NULL; - io_u->flags |= IO_U_F_FREE; + io_u_set(io_u, IO_U_F_FREE); - if (io_u->flags & IO_U_F_IN_CUR_DEPTH) + if (io_u->flags & IO_U_F_IN_CUR_DEPTH) { td->cur_depth--; + 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); @@ -704,7 +720,7 @@ void put_io_u(struct thread_data *td, struct io_u *io_u) void clear_io_u(struct thread_data *td, struct io_u *io_u) { - io_u->flags &= ~IO_U_F_FLIGHT; + io_u_clear(io_u, IO_U_F_FLIGHT); put_io_u(td, io_u); } @@ -715,18 +731,24 @@ void requeue_io_u(struct thread_data *td, struct io_u **io_u) dprint(FD_IO, "requeue %p\n", __io_u); + if (td->parent) + td = td->parent; + td_io_u_lock(td); - __io_u->flags |= IO_U_F_FREE; + io_u_set(__io_u, IO_U_F_FREE); if ((__io_u->flags & IO_U_F_FLIGHT) && ddir_rw(ddir)) td->io_issues[ddir]--; - __io_u->flags &= ~IO_U_F_FLIGHT; - if (__io_u->flags & IO_U_F_IN_CUR_DEPTH) + io_u_clear(__io_u, IO_U_F_FLIGHT); + if (__io_u->flags & IO_U_F_IN_CUR_DEPTH) { td->cur_depth--; + assert(!(td->flags & TD_F_CHILD)); + } io_u_rpush(&td->io_u_requeues, __io_u); td_io_u_unlock(td); + td_io_u_free_notify(td); *io_u = NULL; } @@ -1319,21 +1341,23 @@ again: if (io_u) { assert(io_u->flags & IO_U_F_FREE); - io_u->flags &= ~(IO_U_F_FREE | IO_U_F_NO_FILE_PUT | + io_u_clear(io_u, IO_U_F_FREE | IO_U_F_NO_FILE_PUT | IO_U_F_TRIMMED | IO_U_F_BARRIER | IO_U_F_VER_LIST); io_u->error = 0; io_u->acct_ddir = -1; td->cur_depth++; - io_u->flags |= IO_U_F_IN_CUR_DEPTH; + assert(!(td->flags & TD_F_CHILD)); + io_u_set(io_u, IO_U_F_IN_CUR_DEPTH); io_u->ipo = NULL; - } else if (td->o.verify_async) { + } else if (td_async_processing(td)) { /* * We ran out, wait for async verify threads to finish and * return one */ - pthread_cond_wait(&td->free_cond, &td->io_u_lock); + assert(!(td->flags & TD_F_CHILD)); + assert(!pthread_cond_wait(&td->free_cond, &td->io_u_lock)); goto again; } @@ -1532,7 +1556,7 @@ err_put: return ERR_PTR(ret); } -void io_u_log_error(struct thread_data *td, struct io_u *io_u) +static void __io_u_log_error(struct thread_data *td, struct io_u *io_u) { enum error_type_bit eb = td_error_type(io_u->ddir, io_u->error); @@ -1550,6 +1574,13 @@ void io_u_log_error(struct thread_data *td, struct io_u *io_u) td_verror(td, io_u->error, "io_u error"); } +void io_u_log_error(struct thread_data *td, struct io_u *io_u) +{ + __io_u_log_error(td, io_u); + if (td->parent) + __io_u_log_error(td, io_u); +} + static inline int gtod_reduce(struct thread_data *td) { return td->o.disable_clat && td->o.disable_lat && td->o.disable_slat @@ -1560,9 +1591,10 @@ static void account_io_completion(struct thread_data *td, struct io_u *io_u, struct io_completion_data *icd, const enum fio_ddir idx, unsigned int bytes) { + const int no_reduce = !gtod_reduce(td); unsigned long lusec = 0; - if (!gtod_reduce(td)) + if (no_reduce) lusec = utime_since(&io_u->issue_time, &icd->time); if (!td->o.disable_lat) { @@ -1591,17 +1623,34 @@ static void account_io_completion(struct thread_data *td, struct io_u *io_u, io_u_mark_latency(td, lusec); } + if (td->parent) + td = td->parent; + if (!td->o.disable_bw) add_bw_sample(td, idx, bytes, &icd->time); - if (!gtod_reduce(td)) + if (no_reduce) add_iops_sample(td, idx, bytes, &icd->time); + + if (td->ts.nr_block_infos && io_u->ddir == DDIR_TRIM) { + uint32_t *info = io_u_block_info(td, io_u); + if (BLOCK_INFO_STATE(*info) < BLOCK_STATE_TRIM_FAILURE) { + if (io_u->ddir == DDIR_TRIM) { + *info = BLOCK_INFO(BLOCK_STATE_TRIMMED, + BLOCK_INFO_TRIMS(*info) + 1); + } else if (io_u->ddir == DDIR_WRITE) { + *info = BLOCK_INFO_SET_STATE(BLOCK_STATE_WRITTEN, + *info); + } + } + } } static long long usec_for_io(struct thread_data *td, enum fio_ddir ddir) { uint64_t secs, remainder, bps, bytes; + assert(!(td->flags & TD_F_CHILD)); bytes = td->this_io_bytes[ddir]; bps = td->rate_bps[ddir]; secs = bytes / bps; @@ -1618,9 +1667,8 @@ static void io_completed(struct thread_data *td, struct io_u **io_u_ptr, dprint_io_u(io_u, "io complete"); - td_io_u_lock(td); assert(io_u->flags & IO_U_F_FLIGHT); - io_u->flags &= ~(IO_U_F_FLIGHT | IO_U_F_BUSY_OK); + io_u_clear(io_u, IO_U_F_FLIGHT | IO_U_F_BUSY_OK); /* * Mark IO ok to verify @@ -1637,8 +1685,6 @@ static void io_completed(struct thread_data *td, struct io_u **io_u_ptr, } } - td_io_u_unlock(td); - if (ddir_sync(ddir)) { td->last_was_sync = 1; if (f) { @@ -1683,18 +1729,23 @@ static void io_completed(struct thread_data *td, struct io_u **io_u_ptr, if (ramp_time_over(td) && (td->runstate == TD_RUNNING || td->runstate == TD_VERIFYING)) { + struct thread_data *__td = td; + account_io_completion(td, io_u, icd, ddir, bytes); - if (__should_check_rate(td, ddir)) { - td->rate_pending_usleep[ddir] = - (usec_for_io(td, ddir) - - utime_since_now(&td->start)); + if (td->parent) + __td = td->parent; + + if (__should_check_rate(__td, ddir)) { + __td->rate_pending_usleep[ddir] = + (usec_for_io(__td, ddir) - + utime_since_now(&__td->start)); } if (ddir != DDIR_TRIM && - __should_check_rate(td, oddir)) { - td->rate_pending_usleep[oddir] = - (usec_for_io(td, oddir) - - utime_since_now(&td->start)); + __should_check_rate(__td, oddir)) { + __td->rate_pending_usleep[oddir] = + (usec_for_io(__td, oddir) - + utime_since_now(&__td->start)); } } @@ -1762,10 +1813,10 @@ static void ios_completed(struct thread_data *td, /* * Complete a single io_u for the sync engines. */ -int io_u_sync_complete(struct thread_data *td, struct io_u *io_u, - uint64_t *bytes) +int io_u_sync_complete(struct thread_data *td, struct io_u *io_u) { struct io_completion_data icd; + int ddir; init_icd(td, &icd, 1); io_completed(td, &io_u, &icd); @@ -1778,12 +1829,8 @@ int io_u_sync_complete(struct thread_data *td, struct io_u *io_u, return -1; } - if (bytes) { - int ddir; - - for (ddir = DDIR_READ; ddir < DDIR_RWDIR_CNT; ddir++) - bytes[ddir] += icd.bytes_done[ddir]; - } + for (ddir = DDIR_READ; ddir < DDIR_RWDIR_CNT; ddir++) + td->bytes_done[ddir] += icd.bytes_done[ddir]; return 0; } @@ -1791,12 +1838,11 @@ int io_u_sync_complete(struct thread_data *td, struct io_u *io_u, /* * Called to complete min_events number of io for the async engines. */ -int io_u_queued_complete(struct thread_data *td, int min_evts, - uint64_t *bytes) +int io_u_queued_complete(struct thread_data *td, int min_evts) { struct io_completion_data icd; struct timespec *tvp = NULL; - int ret; + int ret, ddir; struct timespec ts = { .tv_sec = 0, .tv_nsec = 0, }; dprint(FD_IO, "io_u_queued_completed: min=%d\n", min_evts); @@ -1820,12 +1866,8 @@ int io_u_queued_complete(struct thread_data *td, int min_evts, return -1; } - if (bytes) { - int ddir; - - for (ddir = DDIR_READ; ddir < DDIR_RWDIR_CNT; ddir++) - bytes[ddir] += icd.bytes_done[ddir]; - } + for (ddir = DDIR_READ; ddir < DDIR_RWDIR_CNT; ddir++) + td->bytes_done[ddir] += icd.bytes_done[ddir]; return 0; } @@ -1854,8 +1896,10 @@ static struct frand_state *get_buf_state(struct thread_data *td) if (!td->o.dedupe_percentage) return &td->buf_state; - else if (td->o.dedupe_percentage == 100) - return &td->buf_state_prev; + else if (td->o.dedupe_percentage == 100) { + frand_copy(&td->buf_state_prev, &td->buf_state); + return &td->buf_state; + } r = __rand(&td->dedupe_state); v = 1 + (int) (100.0 * (r / (FRAND_MAX + 1.0))); @@ -1868,7 +1912,9 @@ static struct frand_state *get_buf_state(struct thread_data *td) static void save_buf_state(struct thread_data *td, struct frand_state *rs) { - if (rs == &td->buf_state) + if (td->o.dedupe_percentage == 100) + frand_copy(rs, &td->buf_state_prev); + else if (rs == &td->buf_state) frand_copy(&td->buf_state_prev, rs); }