X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=backend.c;h=119c4f982fb32e39e2f141fa792dab3e9f6cd290;hb=941bda94;hp=e025dbffe01b4f6a667f2b7d561603d1664eef06;hpb=100f49f105126a26de6f1069679c20fd75194188;p=fio.git diff --git a/backend.c b/backend.c index e025dbff..119c4f98 100644 --- a/backend.c +++ b/backend.c @@ -34,12 +34,12 @@ #include #include #include -#ifndef FIO_NO_HAVE_SHM_H -#include -#endif #include #include "fio.h" +#ifndef FIO_NO_HAVE_SHM_H +#include +#endif #include "hash.h" #include "smalloc.h" #include "verify.h" @@ -50,6 +50,8 @@ #include "lib/rand.h" #include "memalign.h" #include "server.h" +#include "lib/getrusage.h" +#include "idletime.h" static pthread_t disk_util_thread; static struct fio_mutex *disk_thread_mutex; @@ -59,14 +61,14 @@ static struct flist_head *cgroup_list; static char *cgroup_mnt; static int exit_value; static volatile int fio_abort; +static unsigned int nr_process = 0; +static unsigned int nr_thread = 0; struct io_log *agg_io_log[DDIR_RWDIR_CNT]; int groupid = 0; unsigned int thread_number = 0; unsigned int stat_number = 0; -unsigned int nr_process = 0; -unsigned int nr_thread = 0; int shm_id = 0; int temp_stall_ts; unsigned long done_secs = 0; @@ -320,6 +322,21 @@ requeue: return 0; } +static int fio_file_fsync(struct thread_data *td, struct fio_file *f) +{ + int ret; + + if (fio_file_open(f)) + return fio_io_sync(td, f); + + if (td_io_open_file(td, f)) + return 1; + + ret = fio_io_sync(td, f); + td_io_close_file(td, f); + return ret; +} + static inline void __update_tv_cache(struct thread_data *td) { fio_gettime(&td->tv_cache, NULL); @@ -389,6 +406,15 @@ static int break_on_this_error(struct thread_data *td, enum fio_ddir ddir, return 0; } +static void check_update_rusage(struct thread_data *td) +{ + if (td->update_rusage) { + td->update_rusage = 0; + update_rusage_stat(td); + fio_mutex_up(td->rusage_sem); + } +} + /* * The main verify engine. Runs over the writes we previously submitted, * reads the blocks back in, and checks the crc/md5 of the data. @@ -416,6 +442,8 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes) break; } + check_update_rusage(td); + if (td->error) return; @@ -427,6 +455,7 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes) int ret2, full; update_tv_cache(td); + check_update_rusage(td); if (runtime_exceeded(td, &td->tv_cache)) { __update_tv_cache(td); @@ -580,6 +609,8 @@ sync_done: break; } + check_update_rusage(td); + if (!td->error) { min_events = td->cur_depth; @@ -635,6 +666,8 @@ static uint64_t do_io(struct thread_data *td) int ret2, full; enum fio_ddir ddir; + check_update_rusage(td); + if (td->terminate || td->done) break; @@ -799,6 +832,8 @@ sync_done: } } + check_update_rusage(td); + if (td->trim_entries) log_err("fio: %d trim entries leaked?\n", td->trim_entries); @@ -811,7 +846,7 @@ sync_done: i = td->cur_depth; if (i) { - ret = io_u_queued_complete(td, i, NULL); + ret = io_u_queued_complete(td, i, bytes_done); if (td->o.fill_device && td->error == ENOSPC) td->error = 0; } @@ -820,9 +855,11 @@ sync_done: td_set_runstate(td, TD_FSYNCING); for_each_file(td, f, i) { - if (!fio_file_open(f)) + if (!fio_file_fsync(td, f)) continue; - fio_io_sync(td, f); + + log_err("fio: end_fsync failed for file %s\n", + f->file_name); } } } else @@ -865,8 +902,7 @@ static int init_io_u(struct thread_data *td) char *p; max_units = td->o.iodepth; - max_bs = max(td->o.max_bs[DDIR_READ], td->o.max_bs[DDIR_WRITE]); - max_bs = max(td->o.max_bs[DDIR_TRIM], max_bs); + max_bs = td_max_bs(td); min_write = td->o.min_bs[DDIR_WRITE]; td->orig_buffer_size = (unsigned long long) max_bs * (unsigned long long) max_units; @@ -1015,8 +1051,19 @@ static int keep_running(struct thread_data *td) return 1; } - if (ddir_rw_sum(td->io_bytes) < td->o.size) + if (td->o.size != -1ULL && ddir_rw_sum(td->io_bytes) < td->o.size) { + uint64_t diff; + + /* + * If the difference is less than the minimum IO size, we + * are done. + */ + diff = td->o.size - ddir_rw_sum(td->io_bytes); + if (diff < td_max_bs(td)) + return 0; + return 1; + } return 0; } @@ -1045,19 +1092,24 @@ static void *thread_main(void *data) { unsigned long long elapsed; struct thread_data *td = data; + struct thread_options *o = &td->o; pthread_condattr_t attr; int clear_state; + int ret; - if (!td->o.use_thread) { + if (!o->use_thread) { setsid(); td->pid = getpid(); } else td->pid = gettid(); - fio_local_clock_init(td->o.use_thread); + fio_local_clock_init(o->use_thread); dprint(FD_PROCESS, "jobs pid=%d started\n", (int) td->pid); + if (is_backend) + fio_server_send_start(td); + INIT_FLIST_HEAD(&td->io_u_freelist); INIT_FLIST_HEAD(&td->io_u_busylist); INIT_FLIST_HEAD(&td->io_u_requeues); @@ -1085,16 +1137,17 @@ static void *thread_main(void *data) * eating a file descriptor */ fio_mutex_remove(td->mutex); + td->mutex = NULL; /* * A new gid requires privilege, so we need to do this before setting * the uid. */ - if (td->o.gid != -1U && setgid(td->o.gid)) { + if (o->gid != -1U && setgid(o->gid)) { td_verror(td, errno, "setgid"); goto err; } - if (td->o.uid != -1U && setuid(td->o.uid)) { + if (o->uid != -1U && setuid(o->uid)) { td_verror(td, errno, "setuid"); goto err; } @@ -1103,21 +1156,24 @@ static void *thread_main(void *data) * If we have a gettimeofday() thread, make sure we exclude that * thread from this job */ - if (td->o.gtod_cpu) - fio_cpu_clear(&td->o.cpumask, td->o.gtod_cpu); + if (o->gtod_cpu) + fio_cpu_clear(&o->cpumask, o->gtod_cpu); /* * Set affinity first, in case it has an impact on the memory * allocations. */ - if (td->o.cpumask_set && fio_setaffinity(td->pid, td->o.cpumask) == -1) { - td_verror(td, errno, "cpu_set_affinity"); - goto err; + if (o->cpumask_set) { + ret = fio_setaffinity(td->pid, o->cpumask); + if (ret == -1) { + td_verror(td, errno, "cpu_set_affinity"); + goto err; + } } #ifdef CONFIG_LIBNUMA /* numa node setup */ - if (td->o.numa_cpumask_set || td->o.numa_memmask_set) { + if (o->numa_cpumask_set || o->numa_memmask_set) { int ret; if (numa_available() < 0) { @@ -1125,8 +1181,8 @@ static void *thread_main(void *data) goto err; } - if (td->o.numa_cpumask_set) { - ret = numa_run_on_node_mask(td->o.numa_cpunodesmask); + if (o->numa_cpumask_set) { + ret = numa_run_on_node_mask(o->numa_cpunodesmask); if (ret == -1) { td_verror(td, errno, \ "numa_run_on_node_mask failed\n"); @@ -1134,20 +1190,20 @@ static void *thread_main(void *data) } } - if (td->o.numa_memmask_set) { + if (o->numa_memmask_set) { - switch (td->o.numa_mem_mode) { + switch (o->numa_mem_mode) { case MPOL_INTERLEAVE: - numa_set_interleave_mask(td->o.numa_memnodesmask); + numa_set_interleave_mask(o->numa_memnodesmask); break; case MPOL_BIND: - numa_set_membind(td->o.numa_memnodesmask); + numa_set_membind(o->numa_memnodesmask); break; case MPOL_LOCAL: numa_set_localalloc(); break; case MPOL_PREFERRED: - numa_set_preferred(td->o.numa_mem_prefer_node); + numa_set_preferred(o->numa_mem_prefer_node); break; case MPOL_DEFAULT: default: @@ -1158,6 +1214,9 @@ static void *thread_main(void *data) } #endif + if (fio_pin_memory(td)) + goto err; + /* * May alter parameters that init_io_u() will use, so we need to * do this first. @@ -1168,29 +1227,30 @@ static void *thread_main(void *data) if (init_io_u(td)) goto err; - if (td->o.verify_async && verify_async_init(td)) + if (o->verify_async && verify_async_init(td)) goto err; - if (td->ioprio_set) { - if (ioprio_set(IOPRIO_WHO_PROCESS, 0, td->ioprio) == -1) { + if (o->ioprio) { + ret = ioprio_set(IOPRIO_WHO_PROCESS, 0, o->ioprio_class, o->ioprio); + if (ret == -1) { td_verror(td, errno, "ioprio_set"); goto err; } } - if (td->o.cgroup && cgroup_setup(td, cgroup_list, &cgroup_mnt)) + if (o->cgroup && cgroup_setup(td, cgroup_list, &cgroup_mnt)) goto err; errno = 0; - if (nice(td->o.nice) == -1 && errno != 0) { + if (nice(o->nice) == -1 && errno != 0) { td_verror(td, errno, "nice"); goto err; } - if (td->o.ioscheduler && switch_ioscheduler(td)) + if (o->ioscheduler && switch_ioscheduler(td)) goto err; - if (!td->o.create_serialize && setup_files(td)) + if (!o->create_serialize && setup_files(td)) goto err; if (td_io_init(td)) @@ -1199,19 +1259,18 @@ static void *thread_main(void *data) if (init_random_map(td)) goto err; - if (td->o.exec_prerun) { - if (exec_string(td->o.exec_prerun)) - goto err; - } + if (o->exec_prerun && exec_string(o->exec_prerun)) + goto err; - if (td->o.pre_read) { + if (o->pre_read) { if (pre_read_files(td) < 0) goto err; } - fio_gettime(&td->epoch, NULL); - getrusage(RUSAGE_SELF, &td->ru_start); + fio_verify_init(td); + fio_gettime(&td->epoch, NULL); + fio_getrusage(&td->ru_start); clear_state = 0; while (keep_running(td)) { uint64_t verify_bytes; @@ -1221,8 +1280,8 @@ static void *thread_main(void *data) memcpy(&td->iops_sample_time, &td->start, sizeof(td->start)); memcpy(&td->tv_cache, &td->start, sizeof(td->start)); - if (td->o.ratemin[DDIR_READ] || td->o.ratemin[DDIR_WRITE] || - td->o.ratemin[DDIR_TRIM]) { + if (o->ratemin[DDIR_READ] || o->ratemin[DDIR_WRITE] || + o->ratemin[DDIR_TRIM]) { memcpy(&td->lastrate[DDIR_READ], &td->bw_sample_time, sizeof(td->bw_sample_time)); memcpy(&td->lastrate[DDIR_WRITE], &td->bw_sample_time, @@ -1256,8 +1315,8 @@ static void *thread_main(void *data) if (td->error || td->terminate) break; - if (!td->o.do_verify || - td->o.verify == VERIFY_NONE || + if (!o->do_verify || + o->verify == VERIFY_NONE || (td->io_ops->flags & FIO_UNIDIR)) continue; @@ -1282,46 +1341,48 @@ static void *thread_main(void *data) td->ts.io_bytes[DDIR_WRITE] = td->io_bytes[DDIR_WRITE]; td->ts.io_bytes[DDIR_TRIM] = td->io_bytes[DDIR_TRIM]; + fio_unpin_memory(td); + fio_mutex_down(writeout_mutex); if (td->bw_log) { - if (td->o.bw_log_file) { + if (o->bw_log_file) { finish_log_named(td, td->bw_log, - td->o.bw_log_file, "bw"); + o->bw_log_file, "bw"); } else finish_log(td, td->bw_log, "bw"); } if (td->lat_log) { - if (td->o.lat_log_file) { + if (o->lat_log_file) { finish_log_named(td, td->lat_log, - td->o.lat_log_file, "lat"); + o->lat_log_file, "lat"); } else finish_log(td, td->lat_log, "lat"); } if (td->slat_log) { - if (td->o.lat_log_file) { + if (o->lat_log_file) { finish_log_named(td, td->slat_log, - td->o.lat_log_file, "slat"); + o->lat_log_file, "slat"); } else finish_log(td, td->slat_log, "slat"); } if (td->clat_log) { - if (td->o.lat_log_file) { + if (o->lat_log_file) { finish_log_named(td, td->clat_log, - td->o.lat_log_file, "clat"); + o->lat_log_file, "clat"); } else finish_log(td, td->clat_log, "clat"); } if (td->iops_log) { - if (td->o.iops_log_file) { + if (o->iops_log_file) { finish_log_named(td, td->iops_log, - td->o.iops_log_file, "iops"); + o->iops_log_file, "iops"); } else finish_log(td, td->iops_log, "iops"); } fio_mutex_up(writeout_mutex); - if (td->o.exec_postrun) - exec_string(td->o.exec_postrun); + if (o->exec_postrun) + exec_string(o->exec_postrun); if (exitall_on_terminate) fio_terminate_threads(td->groupid); @@ -1331,7 +1392,7 @@ err: log_info("fio: pid=%d, err=%d/%s\n", (int) td->pid, td->error, td->verror); - if (td->o.verify_async) + if (o->verify_async) verify_async_exit(td); close_and_free_files(td); @@ -1339,8 +1400,8 @@ err: close_ioengine(td); cgroup_shutdown(td, &cgroup_mnt); - if (td->o.cpumask_set) { - int ret = fio_cpuset_exit(&td->o.cpumask); + if (o->cpumask_set) { + int ret = fio_cpuset_exit(&o->cpumask); td_verror(td, ret, "fio_cpuset_exit"); } @@ -1348,9 +1409,12 @@ err: /* * do this very late, it will log file closing as well */ - if (td->o.write_iolog_file) + if (o->write_iolog_file) write_iolog_close(td); + fio_mutex_remove(td->rusage_sem); + td->rusage_sem = NULL; + td_set_runstate(td, TD_EXITED); return (void *) (uintptr_t) td->error; } @@ -1494,14 +1558,21 @@ static void run_threads(void) unsigned long spent; unsigned int i, todo, nr_running, m_rate, t_rate, nr_started; - if (fio_pin_memory()) - return; - if (fio_gtod_offload && fio_start_gtod_thread()) return; + + fio_idle_prof_init(); set_sig_handlers(); + nr_thread = nr_process = 0; + for_each_td(td, i) { + if (td->o.use_thread) + nr_thread++; + else + nr_process++; + } + if (output_format == FIO_OUTPUT_NORMAL) { log_info("Starting "); if (nr_thread) @@ -1556,6 +1627,9 @@ static void run_threads(void) } } + /* start idle threads before io threads start to run */ + fio_idle_prof_start(); + set_genesis_time(); while (todo) { @@ -1594,6 +1668,9 @@ static void run_threads(void) init_disk_util(td); + td->rusage_sem = fio_mutex_init(FIO_MUTEX_LOCKED); + td->update_rusage = 0; + /* * Set state to created. Thread will transition * to TD_INITIALIZED when it's done setting up. @@ -1701,25 +1778,18 @@ static void run_threads(void) reap_threads(&nr_running, &t_rate, &m_rate); - if (todo) { - if (is_backend) - fio_server_idle_loop(); - else - usleep(100000); - } + if (todo) + usleep(100000); } while (nr_running) { reap_threads(&nr_running, &t_rate, &m_rate); - - if (is_backend) - fio_server_idle_loop(); - else - usleep(10000); + usleep(10000); } + fio_idle_prof_stop(); + update_io_ticks(); - fio_unpin_memory(); } void wait_for_disk_thread_exit(void) @@ -1797,9 +1867,9 @@ int fio_backend(void) return 0; if (write_bw_log) { - setup_log(&agg_io_log[DDIR_READ], 0); - setup_log(&agg_io_log[DDIR_WRITE], 0); - setup_log(&agg_io_log[DDIR_TRIM], 0); + setup_log(&agg_io_log[DDIR_READ], 0, IO_LOG_TYPE_BW); + setup_log(&agg_io_log[DDIR_WRITE], 0, IO_LOG_TYPE_BW); + setup_log(&agg_io_log[DDIR_TRIM], 0, IO_LOG_TYPE_BW); } startup_mutex = fio_mutex_init(FIO_MUTEX_LOCKED);