X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=backend.c;h=7de6f654d153b2f2798450ed4298a6d2c6763a2d;hp=edc0644a113b259cf2d65cf91f96175a5f50201b;hb=ae24a6153993ebd2341f3459cfd975b917847a3e;hpb=9cc8cb91d355d7e47d5b930b352087ec71f85f85 diff --git a/backend.c b/backend.c index edc0644a..7de6f654 100644 --- a/backend.c +++ b/backend.c @@ -57,11 +57,7 @@ #include "workqueue.h" #include "lib/mountcheck.h" #include "rate-submit.h" - -static pthread_t helper_thread; -static pthread_mutex_t helper_lock; -pthread_cond_t helper_cond; -int helper_do_stat = 0; +#include "helper_thread.h" static struct fio_mutex *startup_mutex; static struct flist_head *cgroup_list; @@ -79,7 +75,6 @@ unsigned int stat_number = 0; int shm_id = 0; int temp_stall_ts; unsigned long done_secs = 0; -volatile int helper_exit = 0; #define PAGE_ALIGN(buf) \ (char *) (((uintptr_t) (buf) + page_mask) & ~page_mask) @@ -309,6 +304,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 +517,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: /* @@ -871,7 +876,14 @@ static void do_io(struct thread_data *td, uint64_t *bytes_done) 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); @@ -1053,6 +1065,41 @@ reap: 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) { struct io_u *io_u; @@ -1071,8 +1118,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) @@ -1189,13 +1235,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; } @@ -1293,7 +1334,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; @@ -1676,7 +1717,7 @@ static void *thread_main(void *data) fio_unpin_memory(td); - fio_writeout_logs(td); + td_writeout_logs(td, true); iolog_compress_exit(td); rate_submit_exit(td); @@ -1701,6 +1742,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) @@ -1938,12 +1988,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"); @@ -2130,7 +2179,7 @@ reap: if (waitee_running(td)) { dprint(FD_PROCESS, "%s: waiting for %s\n", td->o.name, td->o.wait_for); - break; + continue; } init_disk_util(td); @@ -2265,82 +2314,10 @@ reap: update_io_ticks(); } -static void wait_for_helper_thread_exit(void) -{ - void *ret; - - helper_exit = 1; - pthread_cond_signal(&helper_cond); - pthread_join(helper_thread, &ret); -} - static void free_disk_util(void) { disk_util_prune_entries(); - - pthread_cond_destroy(&helper_cond); -} - -static void *helper_thread_main(void *data) -{ - struct sk_out *sk_out = data; - int ret = 0; - - sk_out_assign(sk_out); - - fio_mutex_up(startup_mutex); - - while (!ret) { - uint64_t sec = DISK_UTIL_MSEC / 1000; - uint64_t nsec = (DISK_UTIL_MSEC % 1000) * 1000000; - struct timespec ts; - struct timeval tv; - - gettimeofday(&tv, NULL); - ts.tv_sec = tv.tv_sec + sec; - ts.tv_nsec = (tv.tv_usec * 1000) + nsec; - - if (ts.tv_nsec >= 1000000000ULL) { - ts.tv_nsec -= 1000000000ULL; - ts.tv_sec++; - } - - pthread_cond_timedwait(&helper_cond, &helper_lock, &ts); - - ret = update_io_ticks(); - - if (helper_do_stat) { - helper_do_stat = 0; - __show_running_run_stats(); - } - - if (!is_backend) - print_thread_status(); - } - - sk_out_drop(); - return NULL; -} - -static int create_helper_thread(struct sk_out *sk_out) -{ - int ret; - - setup_disk_util(); - - pthread_cond_init(&helper_cond, NULL); - pthread_mutex_init(&helper_lock, NULL); - - ret = pthread_create(&helper_thread, NULL, helper_thread_main, sk_out); - if (ret) { - log_err("Can't create helper thread: %s\n", strerror(ret)); - return 1; - } - - dprint(FD_MUTEX, "wait on startup_mutex\n"); - fio_mutex_down(startup_mutex); - dprint(FD_MUTEX, "done waiting on startup_mutex\n"); - return 0; + helper_thread_destroy(); } int fio_backend(struct sk_out *sk_out) @@ -2373,14 +2350,14 @@ int fio_backend(struct sk_out *sk_out) set_genesis_time(); stat_init(); - create_helper_thread(sk_out); + helper_thread_create(startup_mutex, sk_out); cgroup_list = smalloc(sizeof(*cgroup_list)); INIT_FLIST_HEAD(cgroup_list); run_threads(sk_out); - wait_for_helper_thread_exit(); + helper_thread_exit(); if (!fio_abort) { __show_run_stats();