#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/ipc.h>
-#include <sys/shm.h>
#include <sys/mman.h>
#include "fio.h"
+#ifndef FIO_NO_HAVE_SHM_H
+#include <sys/shm.h>
+#endif
#include "hash.h"
#include "smalloc.h"
#include "verify.h"
#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;
static struct fio_mutex *startup_mutex;
static struct fio_mutex *writeout_mutex;
static struct flist_head *cgroup_list;
static unsigned int nr_process = 0;
static unsigned int nr_thread = 0;
-struct io_log *agg_io_log[2];
+struct io_log *agg_io_log[DDIR_RWDIR_CNT];
int groupid = 0;
unsigned int thread_number = 0;
+unsigned int stat_number = 0;
int shm_id = 0;
int temp_stall_ts;
unsigned long done_secs = 0;
+volatile int disk_util_exit = 0;
#define PAGE_ALIGN(buf) \
(char *) (((uintptr_t) (buf) + page_mask) & ~page_mask)
act.sa_flags = SA_RESTART;
sigaction(SIGTERM, &act, NULL);
+/* Windows uses SIGBREAK as a quit signal from other applications */
+#ifdef WIN32
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = sig_int;
+ act.sa_flags = SA_RESTART;
+ sigaction(SIGBREAK, &act, NULL);
+#endif
+
memset(&act, 0, sizeof(act));
act.sa_handler = sig_show_status;
act.sa_flags = SA_RESTART;
}
static int check_min_rate(struct thread_data *td, struct timeval *now,
- unsigned long *bytes_done)
+ uint64_t *bytes_done)
{
int ret = 0;
- if (bytes_done[0])
- ret |= __check_min_rate(td, now, 0);
- if (bytes_done[1])
- ret |= __check_min_rate(td, now, 1);
+ if (bytes_done[DDIR_READ])
+ ret |= __check_min_rate(td, now, DDIR_READ);
+ if (bytes_done[DDIR_WRITE])
+ ret |= __check_min_rate(td, now, DDIR_WRITE);
+ if (bytes_done[DDIR_TRIM])
+ ret |= __check_min_rate(td, now, DDIR_TRIM);
return ret;
}
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);
int ret = *retptr;
if (ret < 0 || td->error) {
- int err;
+ int err = td->error;
+ enum error_type_bit eb;
if (ret < 0)
err = -ret;
- else
- err = td->error;
- if (!(td->o.continue_on_error & td_error_type(ddir, err)))
+ eb = td_error_type(ddir, err);
+ if (!(td->o.continue_on_error & (1 << eb)))
return 1;
- if (td_non_fatal_error(err)) {
- /*
- * Continue with the I/Os in case of
+ if (td_non_fatal_error(td, eb, err)) {
+ /*
+ * Continue with the I/Os in case of
* a non fatal error.
*/
update_error_count(td, err);
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.
*/
-static void do_verify(struct thread_data *td)
+static void do_verify(struct thread_data *td, uint64_t verify_bytes)
{
+ uint64_t bytes_done[DDIR_RWDIR_CNT] = { 0, 0, 0 };
struct fio_file *f;
struct io_u *io_u;
int ret, min_events;
break;
}
+ check_update_rusage(td);
+
if (td->error)
return;
io_u = NULL;
while (!td->terminate) {
+ enum fio_ddir ddir;
int ret2, full;
update_tv_cache(td);
+ check_update_rusage(td);
if (runtime_exceeded(td, &td->tv_cache)) {
__update_tv_cache(td);
if (flow_threshold_exceeded(td))
continue;
- io_u = __get_io_u(td);
- if (!io_u)
- break;
+ if (!td->o.experimental_verify) {
+ io_u = __get_io_u(td);
+ if (!io_u)
+ break;
- if (get_next_verify(td, io_u)) {
- put_io_u(td, io_u);
- break;
- }
+ if (get_next_verify(td, io_u)) {
+ put_io_u(td, io_u);
+ break;
+ }
- if (td_io_prep(td, io_u)) {
- put_io_u(td, io_u);
- break;
+ if (td_io_prep(td, io_u)) {
+ put_io_u(td, io_u);
+ break;
+ }
+ } else {
+ if (ddir_rw_sum(bytes_done) + td->o.rw_min_bs > verify_bytes)
+ break;
+
+ while ((io_u = get_io_u(td)) != NULL) {
+ /*
+ * We are only interested in the places where
+ * we wrote or trimmed IOs. Turn those into
+ * reads for verification purposes.
+ */
+ if (io_u->ddir == DDIR_READ) {
+ /*
+ * Pretend we issued it for rwmix
+ * accounting
+ */
+ td->io_issues[DDIR_READ]++;
+ put_io_u(td, io_u);
+ continue;
+ } else if (io_u->ddir == DDIR_TRIM) {
+ io_u->ddir = DDIR_READ;
+ io_u->flags |= IO_U_F_TRIMMED;
+ break;
+ } else if (io_u->ddir == DDIR_WRITE) {
+ io_u->ddir = DDIR_READ;
+ break;
+ } else {
+ put_io_u(td, io_u);
+ continue;
+ }
+ }
+
+ if (!io_u)
+ break;
}
if (td->o.verify_async)
else
io_u->end_io = verify_io_u;
+ ddir = io_u->ddir;
+
ret = td_io_queue(td, io_u);
switch (ret) {
case FIO_Q_COMPLETED:
requeue_io_u(td, &io_u);
} else {
sync_done:
- ret = io_u_sync_complete(td, io_u, NULL);
+ ret = io_u_sync_complete(td, io_u, bytes_done);
if (ret < 0)
break;
}
break;
}
- if (break_on_this_error(td, io_u->ddir, &ret))
+ if (break_on_this_error(td, ddir, &ret))
break;
/*
* and do the verification on them through
* the callback handler
*/
- if (io_u_queued_complete(td, min_events, NULL) < 0) {
+ if (io_u_queued_complete(td, min_events, bytes_done) < 0) {
ret = -1;
break;
}
break;
}
+ check_update_rusage(td);
+
if (!td->error) {
min_events = td->cur_depth;
unsigned long long bytes;
if (td_rw(td))
- bytes = td->this_io_bytes[0] + td->this_io_bytes[1];
+ bytes = td->this_io_bytes[DDIR_READ] + td->this_io_bytes[DDIR_WRITE];
else if (td_write(td))
- bytes = td->this_io_bytes[1];
+ bytes = td->this_io_bytes[DDIR_WRITE];
+ else if (td_read(td))
+ bytes = td->this_io_bytes[DDIR_READ];
else
- bytes = td->this_io_bytes[0];
+ bytes = td->this_io_bytes[DDIR_TRIM];
return bytes >= td->o.size;
}
/*
* Main IO worker function. It retrieves io_u's to process and queues
* and reaps them, checking for rate and errors along the way.
+ *
+ * Returns number of bytes written and trimmed.
*/
-static void do_io(struct thread_data *td)
+static uint64_t do_io(struct thread_data *td)
{
+ uint64_t bytes_done[DDIR_RWDIR_CNT] = { 0, 0, 0 };
unsigned int i;
int ret = 0;
(!flist_empty(&td->trim_list)) || !io_bytes_exceeded(td) ||
td->o.time_based) {
struct timeval comp_time;
- unsigned long bytes_done[2] = { 0, 0 };
int min_evts = 0;
struct io_u *io_u;
int ret2, full;
enum fio_ddir ddir;
- if (td->terminate)
+ check_update_rusage(td);
+
+ if (td->terminate || td->done)
break;
update_tv_cache(td);
requeue_io_u(td, &io_u);
} else {
sync_done:
- if (__should_check_rate(td, 0) ||
- __should_check_rate(td, 1))
+ if (__should_check_rate(td, DDIR_READ) ||
+ __should_check_rate(td, DDIR_WRITE) ||
+ __should_check_rate(td, DDIR_TRIM))
fio_gettime(&comp_time, NULL);
ret = io_u_sync_complete(td, io_u, bytes_done);
if (full && !min_evts)
min_evts = 1;
- if (__should_check_rate(td, 0) ||
- __should_check_rate(td, 1))
+ if (__should_check_rate(td, DDIR_READ) ||
+ __should_check_rate(td, DDIR_WRITE) ||
+ __should_check_rate(td, DDIR_TRIM))
fio_gettime(&comp_time, NULL);
do {
if (ret < 0)
break;
- if (!(bytes_done[0] + bytes_done[1]))
+ if (!ddir_rw_sum(bytes_done) && !(td->io_ops->flags & FIO_NOIO))
continue;
if (!in_ramp_time(td) && should_check_rate(td, bytes_done)) {
if (td->o.thinktime) {
unsigned long long b;
- b = td->io_blocks[0] + td->io_blocks[1];
+ b = ddir_rw_sum(td->io_blocks);
if (!(b % td->o.thinktime_blocks)) {
int left;
}
}
+ check_update_rusage(td);
+
if (td->trim_entries)
- log_err("fio: %d trim entries leaked?\n", td->trim_entries);
+ log_err("fio: %lu trim entries leaked?\n", td->trim_entries);
if (td->o.fill_device && td->error == ENOSPC) {
td->error = 0;
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;
}
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
/*
* stop job if we failed doing any IO
*/
- if ((td->this_io_bytes[0] + td->this_io_bytes[1]) == 0)
+ if (!ddir_rw_sum(td->this_io_bytes))
td->done = 1;
+
+ return bytes_done[DDIR_WRITE] + bytes_done[DDIR_TRIM];
}
static void cleanup_io_u(struct thread_data *td)
io_u = flist_entry(entry, struct io_u, list);
flist_del(&io_u->list);
+
+ if (td->io_ops->io_u_free)
+ td->io_ops->io_u_free(td, io_u);
+
fio_memfree(io_u, sizeof(*io_u));
}
struct io_u *io_u;
unsigned int max_bs, min_write;
int cl_align, i, max_units;
+ int data_xfer = 1;
char *p;
max_units = td->o.iodepth;
- max_bs = max(td->o.max_bs[DDIR_READ], td->o.max_bs[DDIR_WRITE]);
+ 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;
+ if ((td->io_ops->flags & FIO_NOIO) || !(td_read(td) || td_write(td)))
+ data_xfer = 0;
+
if (td->o.mem_type == MEM_SHMHUGE || td->o.mem_type == MEM_MMAPHUGE) {
unsigned long bs;
return 1;
}
- if (allocate_io_mem(td))
+ if (data_xfer && allocate_io_mem(td))
return 1;
if (td->o.odirect || td->o.mem_align ||
INIT_FLIST_HEAD(&io_u->list);
dprint(FD_MEM, "io_u alloc %p, index %u\n", io_u, i);
- if (!(td->io_ops->flags & FIO_NOIO)) {
+ if (data_xfer) {
io_u->buf = p;
dprint(FD_MEM, "io_u %p, mem %p\n", io_u, io_u->buf);
io_u->index = i;
io_u->flags = IO_U_F_FREE;
flist_add(&io_u->list, &td->io_u_freelist);
+
+ if (td->io_ops->io_u_init) {
+ int ret = td->io_ops->io_u_init(td, io_u);
+
+ if (ret) {
+ log_err("fio: failed to init engine data: %d\n", ret);
+ return 1;
+ }
+ }
+
p += max_bs;
}
static int keep_running(struct thread_data *td)
{
- unsigned long long io_done;
-
if (td->done)
return 0;
if (td->o.time_based)
return 1;
}
- io_done = td->io_bytes[DDIR_READ] + td->io_bytes[DDIR_WRITE]
- + td->io_skip_bytes;
- if (io_done < 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;
}
} else
td->pid = gettid();
+ fio_local_clock_init(o->use_thread);
+
dprint(FD_PROCESS, "jobs pid=%d started\n", (int) td->pid);
if (is_backend)
INIT_FLIST_HEAD(&td->io_hist_list);
INIT_FLIST_HEAD(&td->verify_list);
INIT_FLIST_HEAD(&td->trim_list);
+ INIT_FLIST_HEAD(&td->next_rand_list);
pthread_mutex_init(&td->io_u_lock, NULL);
td->io_hist_tree = RB_ROOT;
}
}
+#ifdef CONFIG_LIBNUMA
+ /* numa node setup */
+ if (o->numa_cpumask_set || o->numa_memmask_set) {
+ int ret;
+
+ if (numa_available() < 0) {
+ td_verror(td, errno, "Does not support NUMA API\n");
+ goto err;
+ }
+
+ 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");
+ goto err;
+ }
+ }
+
+ if (o->numa_memmask_set) {
+
+ switch (o->numa_mem_mode) {
+ case MPOL_INTERLEAVE:
+ numa_set_interleave_mask(o->numa_memnodesmask);
+ break;
+ case MPOL_BIND:
+ numa_set_membind(o->numa_memnodesmask);
+ break;
+ case MPOL_LOCAL:
+ numa_set_localalloc();
+ break;
+ case MPOL_PREFERRED:
+ numa_set_preferred(o->numa_mem_prefer_node);
+ break;
+ case MPOL_DEFAULT:
+ default:
+ break;
+ }
+
+ }
+ }
+#endif
+
if (fio_pin_memory(td))
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;
fio_verify_init(td);
fio_gettime(&td->epoch, NULL);
- getrusage(RUSAGE_SELF, &td->ru_start);
-
+ fio_getrusage(&td->ru_start);
clear_state = 0;
while (keep_running(td)) {
+ uint64_t verify_bytes;
+
fio_gettime(&td->start, NULL);
memcpy(&td->bw_sample_time, &td->start, sizeof(td->start));
memcpy(&td->iops_sample_time, &td->start, sizeof(td->start));
memcpy(&td->tv_cache, &td->start, sizeof(td->start));
- if (td->o.ratemin[0] || td->o.ratemin[1]) {
- memcpy(&td->lastrate[0], &td->bw_sample_time,
+ 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[1], &td->bw_sample_time,
+ memcpy(&td->lastrate[DDIR_WRITE], &td->bw_sample_time,
+ sizeof(td->bw_sample_time));
+ memcpy(&td->lastrate[DDIR_TRIM], &td->bw_sample_time,
sizeof(td->bw_sample_time));
}
prune_io_piece_log(td);
- do_io(td);
+ verify_bytes = do_io(td);
clear_state = 1;
elapsed = utime_since_now(&td->start);
td->ts.runtime[DDIR_WRITE] += elapsed;
}
+ if (td_trim(td) && td->io_bytes[DDIR_TRIM]) {
+ elapsed = utime_since_now(&td->start);
+ td->ts.runtime[DDIR_TRIM] += elapsed;
+ }
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;
fio_gettime(&td->start, NULL);
- do_verify(td);
+ do_verify(td, verify_bytes);
td->ts.runtime[DDIR_READ] += utime_since_now(&td->start);
}
update_rusage_stat(td);
- td->ts.runtime[0] = (td->ts.runtime[0] + 999) / 1000;
- td->ts.runtime[1] = (td->ts.runtime[1] + 999) / 1000;
+ td->ts.runtime[DDIR_READ] = (td->ts.runtime[DDIR_READ] + 999) / 1000;
+ td->ts.runtime[DDIR_WRITE] = (td->ts.runtime[DDIR_WRITE] + 999) / 1000;
+ td->ts.runtime[DDIR_TRIM] = (td->ts.runtime[DDIR_TRIM] + 999) / 1000;
td->ts.total_run_time = mtime_since_now(&td->epoch);
- td->ts.io_bytes[0] = td->io_bytes[0];
- td->ts.io_bytes[1] = td->io_bytes[1];
+ td->ts.io_bytes[DDIR_READ] = td->io_bytes[DDIR_READ];
+ 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);
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);
- close_ioengine(td);
cleanup_io_u(td);
+ close_ioengine(td);
cgroup_shutdown(td, &cgroup_mnt);
if (o->cpumask_set) {
/*
* 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;
}
if (WIFSIGNALED(status)) {
int sig = WTERMSIG(status);
- if (sig != SIGTERM)
+ if (sig != SIGTERM && sig != SIGUSR2)
log_err("fio: pid=%d, got signal=%d\n",
(int) td->pid, sig);
td->sig = sig;
continue;
reaped:
(*nr_running)--;
- (*m_rate) -= (td->o.ratemin[0] + td->o.ratemin[1]);
- (*t_rate) -= (td->o.rate[0] + td->o.rate[1]);
+ (*m_rate) -= ddir_rw_sum(td->o.ratemin);
+ (*t_rate) -= ddir_rw_sum(td->o.rate);
if (!td->pid)
pending--;
if (fio_gtod_offload && fio_start_gtod_thread())
return;
+
+ fio_idle_prof_init();
set_sig_handlers();
nr_process++;
}
- if (!terse_output) {
+ if (output_format == FIO_OUTPUT_NORMAL) {
log_info("Starting ");
if (nr_thread)
log_info("%d thread%s", nr_thread,
}
}
+ /* start idle threads before io threads start to run */
+ fio_idle_prof_start();
+
set_genesis_time();
while (todo) {
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.
td_set_runstate(td, TD_RUNNING);
nr_running++;
nr_started--;
- m_rate += td->o.ratemin[0] + td->o.ratemin[1];
- t_rate += td->o.rate[0] + td->o.rate[1];
+ m_rate += ddir_rw_sum(td->o.ratemin);
+ t_rate += ddir_rw_sum(td->o.rate);
todo--;
fio_mutex_up(td->mutex);
}
usleep(10000);
}
+ fio_idle_prof_stop();
+
update_io_ticks();
}
+void wait_for_disk_thread_exit(void)
+{
+ fio_mutex_down(disk_thread_mutex);
+}
+
+static void free_disk_util(void)
+{
+ disk_util_start_exit();
+ wait_for_disk_thread_exit();
+ disk_util_prune_entries();
+}
+
static void *disk_thread_main(void *data)
{
+ int ret = 0;
+
fio_mutex_up(startup_mutex);
- while (threads) {
+ while (threads && !ret) {
usleep(DISK_UTIL_MSEC * 1000);
if (!threads)
break;
- update_io_ticks();
+ ret = update_io_ticks();
if (!is_backend)
print_thread_status();
}
+ fio_mutex_up(disk_thread_mutex);
return NULL;
}
{
int ret;
+ setup_disk_util();
+
+ disk_thread_mutex = fio_mutex_init(FIO_MUTEX_LOCKED);
+
ret = pthread_create(&disk_util_thread, NULL, disk_thread_main, NULL);
if (ret) {
+ fio_mutex_remove(disk_thread_mutex);
log_err("Can't create disk util thread: %s\n", strerror(ret));
return 1;
}
ret = pthread_detach(disk_util_thread);
if (ret) {
+ fio_mutex_remove(disk_thread_mutex);
log_err("Can't detatch disk util thread: %s\n", strerror(ret));
return 1;
}
if (write_bw_log) {
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(0);
+ startup_mutex = fio_mutex_init(FIO_MUTEX_LOCKED);
if (startup_mutex == NULL)
return 1;
- writeout_mutex = fio_mutex_init(1);
+ writeout_mutex = fio_mutex_init(FIO_MUTEX_UNLOCKED);
if (writeout_mutex == NULL)
return 1;
__finish_log(agg_io_log[DDIR_READ], "agg-read_bw.log");
__finish_log(agg_io_log[DDIR_WRITE],
"agg-write_bw.log");
+ __finish_log(agg_io_log[DDIR_TRIM],
+ "agg-write_bw.log");
}
}
fio_mutex_remove(startup_mutex);
fio_mutex_remove(writeout_mutex);
+ fio_mutex_remove(disk_thread_mutex);
return exit_value;
}