X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=fio.c;h=d8c143332823bf2c488ef0799951c8ce70c71fe3;hb=b680c54e8736ef11387f20ebf3da2fa3141bac99;hp=a416856459c12ccf59cef5792efd126701bd7c0c;hpb=687270767de17dbad53c50e03e5d73d52505405c;p=fio.git diff --git a/fio.c b/fio.c index a4168564..d8c14333 100644 --- a/fio.c +++ b/fio.c @@ -35,7 +35,7 @@ #include #include "fio.h" -#include "os.h" +#include "hash.h" unsigned long page_mask; unsigned long page_size; @@ -311,6 +311,7 @@ static void do_verify(struct thread_data *td) if (runtime_exceeded(td, &io_u->start_time)) { put_io_u(td, io_u); + td->terminate = 1; break; } @@ -333,6 +334,7 @@ static void do_verify(struct thread_data *td) ret = -io_u->error; else if (io_u->resid) { int bytes = io_u->xfer_buflen - io_u->resid; + struct fio_file *f = io_u->file; /* * zero read, fail @@ -342,10 +344,20 @@ static void do_verify(struct thread_data *td) put_io_u(td, io_u); break; } + io_u->xfer_buflen = io_u->resid; io_u->xfer_buf += bytes; + io_u->offset += bytes; + f->last_completed_pos = io_u->offset; + + td->ts.short_io_u[io_u->ddir]++; + + if (io_u->offset == f->real_file_size) + goto sync_done; + requeue_io_u(td, &io_u); } else { +sync_done: ret = io_u_sync_complete(td, io_u); if (ret < 0) break; @@ -412,7 +424,7 @@ static void do_io(struct thread_data *td) td_set_runstate(td, TD_RUNNING); - while ((td->this_io_bytes[0] + td->this_io_bytes[1]) < td->io_size) { + while ((td->this_io_bytes[0] + td->this_io_bytes[1]) < td->o.size) { struct timeval comp_time; long bytes_done = 0; int min_evts = 0; @@ -430,6 +442,7 @@ static void do_io(struct thread_data *td) if (runtime_exceeded(td, &s)) { put_io_u(td, io_u); + td->terminate = 1; break; } @@ -440,6 +453,7 @@ static void do_io(struct thread_data *td) ret = -io_u->error; else if (io_u->resid) { int bytes = io_u->xfer_buflen - io_u->resid; + struct fio_file *f = io_u->file; /* * zero read, fail @@ -452,8 +466,17 @@ static void do_io(struct thread_data *td) io_u->xfer_buflen = io_u->resid; io_u->xfer_buf += bytes; + io_u->offset += bytes; + f->last_completed_pos = io_u->offset; + + td->ts.short_io_u[io_u->ddir]++; + + if (io_u->offset == f->real_file_size) + goto sync_done; + requeue_io_u(td, &io_u); } else { +sync_done: fio_gettime(&comp_time, NULL); bytes_done = io_u_sync_complete(td, io_u); if (bytes_done < 0) @@ -576,18 +599,22 @@ static void cleanup_io_u(struct thread_data *td) /* * "randomly" fill the buffer contents */ -static void fill_rand_buf(struct io_u *io_u, int max_bs) +static void fill_io_buf(struct thread_data *td, struct io_u *io_u, int max_bs) { - int *ptr = io_u->buf; + long *ptr = io_u->buf; - while ((void *) ptr - io_u->buf < max_bs) { - *ptr = rand() * 0x9e370001; - ptr++; - } + if (!td->o.zero_buffers) { + while ((void *) ptr - io_u->buf < max_bs) { + *ptr = rand() * GOLDEN_RATIO_PRIME; + ptr++; + } + } else + memset(ptr, 0, max_bs); } static int init_io_u(struct thread_data *td) { + unsigned long long buf_size; struct io_u *io_u; unsigned int max_bs; int i, max_units; @@ -599,12 +626,19 @@ static int init_io_u(struct thread_data *td) max_units = td->o.iodepth; max_bs = max(td->o.max_bs[DDIR_READ], td->o.max_bs[DDIR_WRITE]); - td->orig_buffer_size = max_bs * max_units; + buf_size = (unsigned long long) max_bs * (unsigned long long) max_units; + buf_size += page_mask; + if (buf_size != (size_t) buf_size) { + log_err("fio: IO memory too large. Reduce max_bs or iodepth\n"); + return 1; + } + + td->orig_buffer_size = buf_size; if (td->o.mem_type == MEM_SHMHUGE || td->o.mem_type == MEM_MMAPHUGE) td->orig_buffer_size = (td->orig_buffer_size + td->o.hugepage_size - 1) & ~(td->o.hugepage_size - 1); - else - td->orig_buffer_size += page_mask; + else if (td->orig_buffer_size & page_mask) + td->orig_buffer_size = (td->orig_buffer_size + page_mask) & ~page_mask; if (allocate_io_mem(td)) return 1; @@ -616,8 +650,9 @@ static int init_io_u(struct thread_data *td) INIT_LIST_HEAD(&io_u->list); io_u->buf = p + max_bs * i; - if (td_write(td) || td_rw(td)) - fill_rand_buf(io_u, max_bs); + + if (td_write(td)) + fill_io_buf(td, io_u, max_bs); io_u->index = i; io_u->flags = IO_U_F_FREE; @@ -642,7 +677,11 @@ static int switch_ioscheduler(struct thread_data *td) f = fopen(tmp, "r+"); if (!f) { - td_verror(td, errno, "fopen"); + if (errno == ENOENT) { + log_err("fio: os or kernel doesn't support IO scheduler switching\n"); + return 0; + } + td_verror(td, errno, "fopen iosched"); return 1; } @@ -691,6 +730,7 @@ static int clear_io_state(struct thread_data *td) td->zone_bytes = 0; td->rate_bytes = 0; td->rate_blocks = 0; + td->rw_end_set[0] = td->rw_end_set[1] = 0; td->last_was_sync = 0; @@ -715,6 +755,7 @@ static void *thread_main(void *data) { unsigned long long runtime[2]; struct thread_data *td = data; + unsigned long elapsed; int clear_state; if (!td->o.use_thread) @@ -725,8 +766,9 @@ static void *thread_main(void *data) INIT_LIST_HEAD(&td->io_u_freelist); INIT_LIST_HEAD(&td->io_u_busylist); INIT_LIST_HEAD(&td->io_u_requeues); - INIT_LIST_HEAD(&td->io_hist_list); INIT_LIST_HEAD(&td->io_log_list); + INIT_LIST_HEAD(&td->io_hist_list); + td->io_hist_tree = RB_ROOT; if (init_io_u(td)) goto err_sem; @@ -787,7 +829,7 @@ static void *thread_main(void *data) runtime[0] = runtime[1] = 0; clear_state = 0; - while (td->o.loops--) { + while (td->o.time_based || td->o.loops--) { fio_gettime(&td->start, NULL); memcpy(&td->ts.stat_sample_time, &td->start, sizeof(td->start)); @@ -803,10 +845,22 @@ static void *thread_main(void *data) clear_state = 1; - if (td_read(td) && td->io_bytes[DDIR_READ]) - runtime[DDIR_READ] += utime_since_now(&td->start); - if (td_write(td) && td->io_bytes[DDIR_WRITE]) - runtime[DDIR_WRITE] += utime_since_now(&td->start); + if (td_read(td) && td->io_bytes[DDIR_READ]) { + if (td->rw_end_set[DDIR_READ]) + elapsed = utime_since(&td->start, &td->rw_end[DDIR_READ]); + else + elapsed = utime_since_now(&td->start); + + runtime[DDIR_READ] += elapsed; + } + if (td_write(td) && td->io_bytes[DDIR_WRITE]) { + if (td->rw_end_set[DDIR_WRITE]) + elapsed = utime_since(&td->start, &td->rw_end[DDIR_WRITE]); + else + elapsed = utime_since_now(&td->start); + + runtime[DDIR_WRITE] += elapsed; + } if (td->error || td->terminate) break; @@ -856,6 +910,7 @@ err: close_files(td); close_ioengine(td); cleanup_io_u(td); + options_mem_free(td); td_set_runstate(td, TD_EXITED); return (void *) (unsigned long) td->error; err_sem: @@ -954,6 +1009,7 @@ static void reap_threads(int *nr_running, int *t_rate, int *m_rate) /* * thread is not dead, continue */ + pending++; continue; reaped: if (td->o.use_thread) { @@ -966,6 +1022,7 @@ reaped: (*nr_running)--; (*m_rate) -= td->o.ratemin; (*t_rate) -= td->o.rate; + pending--; if (td->error) exit_value++; @@ -1173,10 +1230,8 @@ int main(int argc, char *argv[]) if (parse_options(argc, argv)) return 1; - if (!thread_number) { - log_err("Nothing to do\n"); - return 1; - } + if (!thread_number) + return 0; ps = sysconf(_SC_PAGESIZE); if (ps < 0) {