X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=io_u.c;h=96683954a0378f5ad5eb6163ea6e424e401d73ca;hp=e218a30f6f24da6a2cfc6134717c3d04ad6305c1;hb=c5d3d7901f7b8225d31486894ff7778b0ac3d582;hpb=581e71417760e0aa86eac0acd704253ff0eeea4f diff --git a/io_u.c b/io_u.c index e218a30f..96683954 100644 --- a/io_u.c +++ b/io_u.c @@ -231,11 +231,6 @@ static int get_next_offset(struct thread_data *td, struct io_u *io_u) return 0; } -static inline int is_power_of_2(unsigned int val) -{ - return (val != 0 && ((val & (val - 1)) == 0)); -} - static unsigned int get_next_buflen(struct thread_data *td, struct io_u *io_u) { const int ddir = io_u->ddir; @@ -363,6 +358,22 @@ static enum fio_ddir get_rw_ddir(struct thread_data *td) { enum fio_ddir ddir; + /* + * see if it's time to fsync + */ + if (td->o.fsync_blocks && + !(td->io_issues[DDIR_WRITE] % td->o.fsync_blocks) && + td->io_issues[DDIR_WRITE] && should_fsync(td)) + return DDIR_SYNC; + + /* + * see if it's time to fdatasync + */ + if (td->o.fdatasync_blocks && + !(td->io_issues[DDIR_WRITE] % td->o.fdatasync_blocks) && + td->io_issues[DDIR_WRITE] && should_fsync(td)) + return DDIR_DATASYNC; + if (td_rw(td)) { /* * Check if it's time to seed a new data direction. @@ -390,7 +401,7 @@ static enum fio_ddir get_rw_ddir(struct thread_data *td) return td->rwmix_ddir; } -static void put_file_log(struct thread_data *td, struct fio_file *f) +void put_file_log(struct thread_data *td, struct fio_file *f) { int ret = put_file(td, f); @@ -400,16 +411,27 @@ static 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) { + td_io_u_lock(td); + assert((io_u->flags & IO_U_F_FREE) == 0); io_u->flags |= IO_U_F_FREE; + io_u->flags &= ~IO_U_F_FREE_DEF; if (io_u->file) put_file_log(td, io_u->file); io_u->file = NULL; - flist_del(&io_u->list); + flist_del_init(&io_u->list); flist_add(&io_u->list, &td->io_u_freelist); td->cur_depth--; + td_io_u_unlock(td); + td_io_u_free_notify(td); +} + +void clear_io_u(struct thread_data *td, struct io_u *io_u) +{ + io_u->flags &= ~IO_U_F_FLIGHT; + put_io_u(td, io_u); } void requeue_io_u(struct thread_data *td, struct io_u **io_u) @@ -418,8 +440,10 @@ void requeue_io_u(struct thread_data *td, struct io_u **io_u) dprint(FD_IO, "requeue %p\n", __io_u); + td_io_u_lock(td); + __io_u->flags |= IO_U_F_FREE; - if ((__io_u->flags & IO_U_F_FLIGHT) && (__io_u->ddir != DDIR_SYNC)) + if ((__io_u->flags & IO_U_F_FLIGHT) && !ddir_sync(__io_u->ddir)) td->io_issues[__io_u->ddir]--; __io_u->flags &= ~IO_U_F_FLIGHT; @@ -427,6 +451,7 @@ void requeue_io_u(struct thread_data *td, struct io_u **io_u) flist_del(&__io_u->list); flist_add_tail(&__io_u->list, &td->io_u_requeues); td->cur_depth--; + td_io_u_unlock(td); *io_u = NULL; } @@ -435,17 +460,13 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u) if (td->io_ops->flags & FIO_NOIO) goto out; + io_u->ddir = get_rw_ddir(td); + /* - * see if it's time to sync + * fsync() or fdatasync(), we are done */ - if (td->o.fsync_blocks && - !(td->io_issues[DDIR_WRITE] % td->o.fsync_blocks) && - td->io_issues[DDIR_WRITE] && should_fsync(td)) { - io_u->ddir = DDIR_SYNC; + if (ddir_sync(io_u->ddir)) goto out; - } - - io_u->ddir = get_rw_ddir(td); /* * See if it's time to switch to a new zone @@ -661,7 +682,8 @@ static void io_u_mark_latency(struct thread_data *td, unsigned long usec) /* * Get next file to service by choosing one at random */ -static struct fio_file *get_next_file_rand(struct thread_data *td, enum fio_file_flags goodf, +static struct fio_file *get_next_file_rand(struct thread_data *td, + enum fio_file_flags goodf, enum fio_file_flags badf) { struct fio_file *f; @@ -812,6 +834,9 @@ struct io_u *__get_io_u(struct thread_data *td) { struct io_u *io_u = NULL; + td_io_u_lock(td); + +again: if (!flist_empty(&td->io_u_requeues)) io_u = flist_entry(td->io_u_requeues.next, struct io_u, list); else if (!queue_full(td)) { @@ -823,9 +848,18 @@ struct io_u *__get_io_u(struct thread_data *td) io_u->end_io = NULL; } + /* + * We ran out, wait for async verify threads to finish and return one + */ + if (!io_u && td->o.verify_async) { + pthread_cond_wait(&td->free_cond, &td->io_u_lock); + goto again; + } + if (io_u) { assert(io_u->flags & IO_U_F_FREE); io_u->flags &= ~IO_U_F_FREE; + io_u->flags &= ~IO_U_F_FREE_DEF; io_u->error = 0; flist_del(&io_u->list); @@ -833,6 +867,7 @@ struct io_u *__get_io_u(struct thread_data *td) td->cur_depth++; } + td_io_u_unlock(td); return io_u; } @@ -871,7 +906,7 @@ struct io_u *get_io_u(struct thread_data *td) f = io_u->file; assert(fio_file_open(f)); - if (io_u->ddir != DDIR_SYNC) { + if (!ddir_sync(io_u->ddir)) { if (!io_u->buflen && !(td->io_ops->flags & FIO_NOIO)) { dprint(FD_IO, "get_io_u: zero buflen on %p\n", io_u); goto err_put; @@ -935,7 +970,7 @@ static void io_completed(struct thread_data *td, struct io_u *io_u, assert(io_u->flags & IO_U_F_FLIGHT); io_u->flags &= ~IO_U_F_FLIGHT; - if (io_u->ddir == DDIR_SYNC) { + if (ddir_sync(io_u->ddir)) { td->last_was_sync = 1; return; } @@ -952,21 +987,29 @@ static void io_completed(struct thread_data *td, struct io_u *io_u, td->this_io_bytes[idx] += bytes; if (ramp_time_over(td)) { - if (!td->o.disable_clat || !td->o.disable_bw || - __should_check_rate(td, idx)) - usec = utime_since(&io_u->issue_time, + unsigned long uninitialized_var(lusec); + unsigned long uninitialized_var(rusec); + + if (!td->o.disable_clat || !td->o.disable_bw) + lusec = utime_since(&io_u->issue_time, + &icd->time); + if (__should_check_rate(td, idx) || + __should_check_rate(td, idx ^ 1)) + rusec = utime_since(&io_u->start_time, &icd->time); if (!td->o.disable_clat) { - add_clat_sample(td, idx, usec, bytes); - io_u_mark_latency(td, usec); + add_clat_sample(td, idx, lusec, bytes); + io_u_mark_latency(td, lusec); } if (!td->o.disable_bw) add_bw_sample(td, idx, bytes, &icd->time); - if (__should_check_rate(td, idx)) - td->rate_pending_usleep[idx] += (long) td->rate_usec_cycle[idx] - usec; + if (__should_check_rate(td, idx)) { + td->rate_pending_usleep[idx] += + (long) td->rate_usec_cycle[idx] - rusec; + } if (__should_check_rate(td, idx ^ 1)) - td->rate_pending_usleep[idx ^ 1] -= usec; + td->rate_pending_usleep[idx ^ 1] -= rusec; } if (td_write(td) && idx == DDIR_WRITE && @@ -985,6 +1028,17 @@ 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 there is a non_fatal error, then add to the error count + * and clear all the errors. + */ + update_error_count(td, icd->error); + td_clear_error(td); + icd->error = 0; + io_u->error = 0; + } } static void init_icd(struct thread_data *td, struct io_completion_data *icd, @@ -1009,7 +1063,9 @@ static void ios_completed(struct thread_data *td, io_u = td->io_ops->event(td, i); io_completed(td, io_u, icd); - put_io_u(td, io_u); + + if (!(io_u->flags & IO_U_F_FREE_DEF)) + put_io_u(td, io_u); } } @@ -1023,7 +1079,9 @@ int io_u_sync_complete(struct thread_data *td, struct io_u *io_u, init_icd(td, &icd, 1); io_completed(td, io_u, &icd); - put_io_u(td, io_u); + + if (!(io_u->flags & IO_U_F_FREE_DEF)) + put_io_u(td, io_u); if (icd.error) { td_verror(td, icd.error, "io_u_sync_complete"); @@ -1085,7 +1143,7 @@ void io_u_queued(struct thread_data *td, struct io_u *io_u) unsigned long slat_time; slat_time = utime_since(&io_u->start_time, &io_u->issue_time); - add_slat_sample(td, io_u->ddir, io_u->xfer_buflen, slat_time); + add_slat_sample(td, io_u->ddir, slat_time, io_u->xfer_buflen); } }