#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/ipc.h>
+#ifndef FIO_NO_HAVE_SHM_H
#include <sys/shm.h>
+#endif
#include <sys/mman.h>
#include "fio.h"
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;
+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;
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)) {
+ if (td_non_fatal_error(td, eb, err)) {
/*
* Continue with the I/Os in case of
* a non fatal error.
int ret2, full;
enum fio_ddir ddir;
- if (td->terminate)
+ if (td->terminate || td->done)
break;
update_tv_cache(td);
if (ret < 0)
break;
- if (!(bytes_done[DDIR_READ] + bytes_done[DDIR_WRITE]
- + bytes_done[DDIR_TRIM]))
+ 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[DDIR_READ] + td->io_blocks[DDIR_WRITE] +
- td->io_blocks[DDIR_TRIM];
+ b = ddir_rw_sum(td->io_blocks);
if (!(b % td->o.thinktime_blocks)) {
int left;
/*
* stop job if we failed doing any IO
*/
- if ((td->this_io_bytes[DDIR_READ] + td->this_io_bytes[DDIR_WRITE] +
- td->this_io_bytes[DDIR_TRIM]) == 0)
+ if (!ddir_rw_sum(td->this_io_bytes))
td->done = 1;
}
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;
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_bytes[DDIR_TRIM] + td->io_skip_bytes;
- if (io_done < td->o.size)
+ if (ddir_rw_sum(td->io_bytes) < td->o.size)
return 1;
return 0;
} else
td->pid = gettid();
+ fio_local_clock_init(td->o.use_thread);
+
dprint(FD_PROCESS, "jobs pid=%d started\n", (int) td->pid);
INIT_FLIST_HEAD(&td->io_u_freelist);
goto err;
}
+#ifdef FIO_HAVE_LIBNUMA
+ /* numa node setup */
+ if (td->o.numa_cpumask_set || td->o.numa_memmask_set) {
+ int ret;
+
+ if (numa_available() < 0) {
+ td_verror(td, errno, "Does not support NUMA API\n");
+ goto err;
+ }
+
+ if (td->o.numa_cpumask_set) {
+ ret = numa_run_on_node_mask(td->o.numa_cpunodesmask);
+ if (ret == -1) {
+ td_verror(td, errno, \
+ "numa_run_on_node_mask failed\n");
+ goto err;
+ }
+ }
+
+ if (td->o.numa_memmask_set) {
+
+ switch (td->o.numa_mem_mode) {
+ case MPOL_INTERLEAVE:
+ numa_set_interleave_mask(td->o.numa_memnodesmask);
+ break;
+ case MPOL_BIND:
+ numa_set_membind(td->o.numa_memnodesmask);
+ break;
+ case MPOL_LOCAL:
+ numa_set_localalloc();
+ break;
+ case MPOL_PREFERRED:
+ numa_set_preferred(td->o.numa_mem_prefer_node);
+ break;
+ case MPOL_DEFAULT:
+ default:
+ break;
+ }
+
+ }
+ }
+#endif
+
/*
* May alter parameters that init_io_u() will use, so we need to
* do this first.
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 (td->o.cpumask_set) {
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[DDIR_READ] + td->o.ratemin[DDIR_WRITE] +
- td->o.ratemin[DDIR_TRIM]);
- (*t_rate) -= (td->o.rate[DDIR_READ] + td->o.rate[DDIR_WRITE] +
- td->o.rate[DDIR_TRIM]);
+ (*m_rate) -= ddir_rw_sum(td->o.ratemin);
+ (*t_rate) -= ddir_rw_sum(td->o.rate);
if (!td->pid)
pending--;
set_sig_handlers();
- if (!terse_output) {
+ if (output_format == FIO_OUTPUT_NORMAL) {
log_info("Starting ");
if (nr_thread)
log_info("%d thread%s", nr_thread,
td_set_runstate(td, TD_RUNNING);
nr_running++;
nr_started--;
- m_rate += td->o.ratemin[DDIR_READ] +
- td->o.ratemin[DDIR_WRITE] + td->o.ratemin[DDIR_TRIM];
- t_rate += td->o.rate[DDIR_READ] +
- td->o.rate[DDIR_WRITE] + td->o.rate[DDIR_TRIM];
+ m_rate += ddir_rw_sum(td->o.ratemin);
+ t_rate += ddir_rw_sum(td->o.rate);
todo--;
fio_mutex_up(td->mutex);
}
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;