X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=backend.c;h=1723b8f423190b6bb2bd8d812692d55f8017d1ca;hp=c9875f480c726ec814ed916d02491a4dce442faf;hb=2078c1369f993b4d760d3fe1f90cb6ffa4389fe5;hpb=2466096336bd0fbc1a94811aa338926af6baf42f diff --git a/backend.c b/backend.c index c9875f48..1723b8f4 100644 --- a/backend.c +++ b/backend.c @@ -309,6 +309,8 @@ requeue: put_io_u(td, io_u); return true; } else if (ret == FIO_Q_QUEUED) { + if (td_io_commit(td)) + return true; if (io_u_queued_complete(td, 1) < 0) return true; } else if (ret == FIO_Q_COMPLETED) { @@ -520,6 +522,14 @@ sync_done: if (*ret < 0) break; } + + /* + * when doing I/O (not when verifying), + * check for any errors that are to be ignored + */ + if (!from_verify) + break; + return 0; case FIO_Q_QUEUED: /* @@ -808,12 +818,15 @@ static long long usec_for_io(struct thread_data *td, enum fio_ddir ddir) * * Returns number of bytes written and trimmed. */ -static uint64_t do_io(struct thread_data *td) +static void do_io(struct thread_data *td, uint64_t *bytes_done) { unsigned int i; int ret = 0; uint64_t total_bytes, bytes_issued = 0; + for (i = 0; i < DDIR_RWDIR_CNT; i++) + bytes_done[i] = td->bytes_done[i]; + if (in_ramp_time(td)) td_set_runstate(td, TD_RAMP); else @@ -868,7 +881,14 @@ static uint64_t do_io(struct thread_data *td) if (flow_threshold_exceeded(td)) continue; - if (!td->o.time_based && bytes_issued >= total_bytes) + /* + * Break if we exceeded the bytes. The exception is time + * based runs, but we still need to break out of the loop + * for those to run verification, if enabled. + */ + if (bytes_issued >= total_bytes && + (!td->o.time_based || + (td->o.time_based && td->o.verify != VERIFY_NONE))) break; io_u = get_io_u(td); @@ -1046,7 +1066,43 @@ reap: if (!ddir_rw_sum(td->this_io_bytes)) td->done = 1; - return td->bytes_done[DDIR_WRITE] + td->bytes_done[DDIR_TRIM]; + for (i = 0; i < DDIR_RWDIR_CNT; i++) + bytes_done[i] = td->bytes_done[i] - bytes_done[i]; +} + +static void free_file_completion_logging(struct thread_data *td) +{ + struct fio_file *f; + unsigned int i; + + for_each_file(td, f, i) { + if (!f->last_write_comp) + break; + sfree(f->last_write_comp); + } +} + +static int init_file_completion_logging(struct thread_data *td, + unsigned int depth) +{ + struct fio_file *f; + unsigned int i; + + if (td->o.verify == VERIFY_NONE || !td->o.verify_state_save) + return 0; + + for_each_file(td, f, i) { + f->last_write_comp = scalloc(depth, sizeof(uint64_t)); + if (!f->last_write_comp) + goto cleanup; + } + + return 0; + +cleanup: + free_file_completion_logging(td); + log_err("fio: failed to alloc write comp data\n"); + return 1; } static void cleanup_io_u(struct thread_data *td) @@ -1067,8 +1123,7 @@ static void cleanup_io_u(struct thread_data *td) io_u_qexit(&td->io_u_freelist); io_u_qexit(&td->io_u_all); - if (td->last_write_comp) - sfree(td->last_write_comp); + free_file_completion_logging(td); } static int init_io_u(struct thread_data *td) @@ -1185,13 +1240,8 @@ static int init_io_u(struct thread_data *td) p += max_bs; } - if (td->o.verify != VERIFY_NONE) { - td->last_write_comp = scalloc(max_units, sizeof(uint64_t)); - if (!td->last_write_comp) { - log_err("fio: failed to alloc write comp data\n"); - return 1; - } - } + if (init_file_completion_logging(td, max_units)) + return 1; return 0; } @@ -1289,7 +1339,7 @@ static bool keep_running(struct thread_data *td) if (diff < td_max_bs(td)) return false; - if (fio_files_done(td)) + if (fio_files_done(td) && !td->o.io_limit) return false; return true; @@ -1598,9 +1648,17 @@ static void *thread_main(void *data) if (td->o.verify_only && (td_write(td) || td_rw(td))) verify_bytes = do_dry_run(td); else { - verify_bytes = do_io(td); - if (!verify_bytes) + uint64_t bytes_done[DDIR_RWDIR_CNT]; + + do_io(td, bytes_done); + + if (!ddir_rw_sum(bytes_done)) { fio_mark_td_terminate(td); + verify_bytes = 0; + } else { + verify_bytes = bytes_done[DDIR_WRITE] + + bytes_done[DDIR_TRIM]; + } } clear_state = 1; @@ -1689,6 +1747,15 @@ err: cgroup_shutdown(td, &cgroup_mnt); verify_free_state(td); + if (td->zone_state_index) { + int i; + + for (i = 0; i < DDIR_RWDIR_CNT; i++) + free(td->zone_state_index[i]); + free(td->zone_state_index); + td->zone_state_index = NULL; + } + if (fio_option_is_set(o, cpumask)) { ret = fio_cpuset_exit(&o->cpumask); if (ret) @@ -1926,12 +1993,11 @@ static int fio_verify_load_state(struct thread_data *td) if (is_backend) { void *data; - int ver; ret = fio_server_get_verify_state(td->o.name, - td->thread_number - 1, &data, &ver); + td->thread_number - 1, &data); if (!ret) - verify_convert_assign_state(td, data, ver); + verify_assign_state(td, data); } else ret = verify_load_state(td, "local"); @@ -1966,6 +2032,32 @@ mounted: return true; } +static bool waitee_running(struct thread_data *me) +{ + const char *waitee = me->o.wait_for; + const char *self = me->o.name; + struct thread_data *td; + int i; + + if (!waitee) + return false; + + for_each_td(td, i) { + if (!strcmp(td->o.name, self) || strcmp(td->o.name, waitee)) + continue; + + if (td->runstate < TD_EXITED) { + dprint(FD_PROCESS, "%s fenced by %s(%s)\n", + self, td->o.name, + runstate_to_name(td->runstate)); + return true; + } + } + + dprint(FD_PROCESS, "%s: %s completed, can run\n", self, waitee); + return false; +} + /* * Main function for kicking off and reaping jobs, as needed. */ @@ -2089,6 +2181,12 @@ reap: break; } + if (waitee_running(td)) { + dprint(FD_PROCESS, "%s: waiting for %s\n", + td->o.name, td->o.wait_for); + continue; + } + init_disk_util(td); td->rusage_sem = fio_mutex_init(FIO_MUTEX_LOCKED);