X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=backend.c;h=62bca29194ed08a80af9c68afdc1fbda75b164ef;hp=a607134b878d4603fcb0d3e32e6273847fa2dc7a;hb=735ed278a7ba6e3f1d5a0c08fc08149a2f435c37;hpb=ea66e04fe1a803f6a9ddf31cb999641d4396d67c diff --git a/backend.c b/backend.c index a607134b..62bca291 100644 --- a/backend.c +++ b/backend.c @@ -52,11 +52,11 @@ #include "server.h" #include "lib/getrusage.h" #include "idletime.h" +#include "err.h" static pthread_t disk_util_thread; static struct fio_mutex *disk_thread_mutex; static struct fio_mutex *startup_mutex; -static struct fio_mutex *writeout_mutex; static struct flist_head *cgroup_list; static char *cgroup_mnt; static int exit_value; @@ -182,7 +182,11 @@ static int __check_min_rate(struct thread_data *td, struct timeval *now, ratemin); return 1; } else { - rate = ((bytes - td->rate_bytes[ddir]) * 1000) / spent; + if (spent) + rate = ((bytes - td->rate_bytes[ddir]) * 1000) / spent; + else + rate = 0; + if (rate < ratemin || bytes < td->rate_bytes[ddir]) { log_err("%s: min rate %u not met, got" @@ -345,7 +349,7 @@ static inline int runtime_exceeded(struct thread_data *td, struct timeval *t) return 0; if (!td->o.timeout) return 0; - if (mtime_since(&td->epoch, t) >= td->o.timeout * 1000) + if (utime_since(&td->epoch, t) >= td->o.timeout) return 1; return 0; @@ -478,6 +482,12 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes) break; while ((io_u = get_io_u(td)) != NULL) { + if (IS_ERR(io_u)) { + io_u = NULL; + ret = FIO_Q_BUSY; + goto reap; + } + /* * We are only interested in the places where * we wrote or trimmed IOs. Turn those into @@ -574,6 +584,7 @@ sync_done: * completed io_u's first. Note that we can get BUSY even * without IO queued, if the system is resource starved. */ +reap: full = queue_full(td) || (ret == FIO_Q_BUSY && td->cur_depth); if (full || !td->o.iodepth_batch_complete) { min_events = min(td->o.iodepth_batch_complete, @@ -615,6 +626,19 @@ sync_done: dprint(FD_VERIFY, "exiting loop\n"); } +static unsigned int exceeds_number_ios(struct thread_data *td) +{ + unsigned long long number_ios; + + if (!td->o.number_ios) + return 0; + + number_ios = ddir_rw_sum(td->this_io_blocks); + number_ios += td->io_u_queued + td->io_u_in_flight; + + return number_ios >= td->o.number_ios; +} + static int io_bytes_exceeded(struct thread_data *td) { unsigned long long bytes; @@ -628,7 +652,7 @@ static int io_bytes_exceeded(struct thread_data *td) else bytes = td->this_io_bytes[DDIR_TRIM]; - return bytes >= td->o.size; + return bytes >= td->o.size || exceeds_number_ios(td); } /* @@ -692,7 +716,14 @@ static uint64_t do_io(struct thread_data *td) break; io_u = get_io_u(td); - if (!io_u) { + if (IS_ERR_OR_NULL(io_u)) { + int err = PTR_ERR(io_u); + + io_u = NULL; + if (err == -EBUSY) { + ret = FIO_Q_BUSY; + goto reap; + } if (td->o.latency_target) goto reap; break; @@ -1083,12 +1114,14 @@ static int switch_ioscheduler(struct thread_data *td) /* * Read back and check that the selected scheduler is now the default. */ - ret = fread(tmp, 1, sizeof(tmp), f); + ret = fread(tmp, sizeof(tmp), 1, f); if (ferror(f) || ret < 0) { td_verror(td, errno, "fread"); fclose(f); return 1; } + tmp[sizeof(tmp) - 1] = '\0'; + sprintf(tmp2, "[%s]", td->o.ioscheduler); if (!strstr(tmp, tmp2)) { @@ -1112,6 +1145,8 @@ static int keep_running(struct thread_data *td) td->o.loops--; return 1; } + if (exceeds_number_ios(td)) + return 0; if (td->o.size != -1ULL && ddir_rw_sum(td->io_bytes) < td->o.size) { uint64_t diff; @@ -1124,6 +1159,9 @@ static int keep_running(struct thread_data *td) if (diff < td_max_bs(td)) return 0; + if (fio_files_done(td)) + return 0; + return 1; } @@ -1178,6 +1216,12 @@ static uint64_t do_dry_run(struct thread_data *td) td->ts.total_io_u[io_u->ddir]++; } + if (td_write(td) && io_u->ddir == DDIR_WRITE && + td->o.do_verify && + td->o.verify != VERIFY_NONE && + !td->o.experimental_verify) + log_io_piece(td, io_u); + ret = io_u_sync_complete(td, io_u, bytes_done); (void) ret; } @@ -1260,6 +1304,15 @@ static void *thread_main(void *data) * allocations. */ if (o->cpumask_set) { + if (o->cpus_allowed_policy == FIO_CPUS_SPLIT) { + ret = fio_cpus_split(&o->cpumask, td->thread_number - 1); + if (!ret) { + log_err("fio: no CPUs set\n"); + log_err("fio: Try increasing number of available CPUs\n"); + td_verror(td, EINVAL, "cpus_split"); + goto err; + } + } ret = fio_setaffinity(td->pid, o->cpumask); if (ret == -1) { td_verror(td, errno, "cpu_set_affinity"); @@ -1442,44 +1495,8 @@ static void *thread_main(void *data) fio_unpin_memory(td); - fio_mutex_down(writeout_mutex); - if (td->bw_log) { - if (o->bw_log_file) { - finish_log_named(td, td->bw_log, - o->bw_log_file, "bw"); - } else - finish_log(td, td->bw_log, "bw"); - } - if (td->lat_log) { - if (o->lat_log_file) { - finish_log_named(td, td->lat_log, - o->lat_log_file, "lat"); - } else - finish_log(td, td->lat_log, "lat"); - } - if (td->slat_log) { - if (o->lat_log_file) { - finish_log_named(td, td->slat_log, - o->lat_log_file, "slat"); - } else - finish_log(td, td->slat_log, "slat"); - } - if (td->clat_log) { - if (o->lat_log_file) { - finish_log_named(td, td->clat_log, - o->lat_log_file, "clat"); - } else - finish_log(td, td->clat_log, "clat"); - } - if (td->iops_log) { - if (o->iops_log_file) { - finish_log_named(td, td->iops_log, - o->iops_log_file, "iops"); - } else - finish_log(td, td->iops_log, "iops"); - } + fio_writeout_logs(td); - fio_mutex_up(writeout_mutex); if (o->exec_postrun) exec_string(o, o->exec_postrun, (const char *)"postrun"); @@ -1664,8 +1681,8 @@ static void do_usleep(unsigned int usecs) static void run_threads(void) { struct thread_data *td; - unsigned long spent; unsigned int i, todo, nr_running, m_rate, t_rate, nr_started; + uint64_t spent; if (fio_gtod_offload && fio_start_gtod_thread()) return; @@ -1763,9 +1780,9 @@ static void run_threads(void) } if (td->o.start_delay) { - spent = mtime_since_genesis(); + spent = utime_since_genesis(); - if (td->o.start_delay * 1000 > spent) + if (td->o.start_delay > spent) continue; } @@ -1984,9 +2001,6 @@ int fio_backend(void) startup_mutex = fio_mutex_init(FIO_MUTEX_LOCKED); if (startup_mutex == NULL) return 1; - writeout_mutex = fio_mutex_init(FIO_MUTEX_UNLOCKED); - if (writeout_mutex == NULL) - return 1; set_genesis_time(); stat_init(); @@ -2017,7 +2031,6 @@ int fio_backend(void) sfree(cgroup_mnt); fio_mutex_remove(startup_mutex); - fio_mutex_remove(writeout_mutex); fio_mutex_remove(disk_thread_mutex); stat_exit(); return exit_value;