#include <unistd.h>
#include <fcntl.h>
#include <string.h>
+#include <limits.h>
#include <signal.h>
#include <time.h>
#include <locale.h>
#include "cgroup.h"
#include "profile.h"
#include "lib/rand.h"
+#include "memalign.h"
unsigned long page_mask;
unsigned long page_size;
static struct fio_mutex *writeout_mutex;
static volatile int fio_abort;
static int exit_value;
-static timer_t ival_timer;
static pthread_t gtod_thread;
+static pthread_t disk_util_thread;
static struct flist_head *cgroup_list;
static char *cgroup_mnt;
/*
* if the thread is running, just let it exit
*/
- if (td->runstate < TD_RUNNING)
- kill(td->pid, SIGQUIT);
+ if (td->runstate < TD_RAMP)
+ kill(td->pid, SIGTERM);
else {
struct ioengine_ops *ops = td->io_ops;
- if (ops && (ops->flags & FIO_SIGQUIT))
- kill(td->pid, SIGQUIT);
+ if (ops && (ops->flags & FIO_SIGTERM))
+ kill(td->pid, SIGTERM);
}
}
}
}
-static void status_timer_arm(void)
-{
- struct itimerspec value;
-
- value.it_value.tv_sec = 0;
- value.it_value.tv_nsec = DISK_UTIL_MSEC * 1000000;
- value.it_interval.tv_sec = 0;
- value.it_interval.tv_nsec = DISK_UTIL_MSEC * 1000000;
-
- timer_settime(ival_timer, 0, &value, NULL);
-}
-
-static void ival_fn(union sigval sig)
-{
- if (threads) {
- update_io_ticks();
- print_thread_status();
- }
-}
-
-/*
- * Happens on thread runs with ctrl-c, ignore our own SIGQUIT
- */
-static void sig_quit(int sig)
-{
-}
-
static void sig_int(int sig)
{
if (threads) {
log_info("\nfio: terminating on signal %d\n", sig);
fflush(stdout);
+ exit_value = 128;
terminate_threads(TERMINATE_ALL);
}
}
-static void posix_timer_teardown(void)
+static void *disk_thread_main(void *data)
{
- timer_delete(ival_timer);
+ fio_mutex_up(startup_mutex);
+
+ while (threads) {
+ usleep(DISK_UTIL_MSEC * 1000);
+ if (!threads)
+ break;
+ update_io_ticks();
+ print_thread_status();
+ }
+
+ return NULL;
}
-static void posix_timer_setup(void)
+static int create_disk_util_thread(void)
{
- struct sigevent evt;
+ int ret;
- memset(&evt, 0, sizeof(evt));
- evt.sigev_notify = SIGEV_THREAD;
- evt.sigev_notify_function = ival_fn;
+ ret = pthread_create(&disk_util_thread, NULL, disk_thread_main, NULL);
+ if (ret) {
+ log_err("Can't create disk util thread: %s\n", strerror(ret));
+ return 1;
+ }
- if (timer_create(CLOCK_MONOTONIC, &evt, &ival_timer) < 0)
- perror("timer_create");
+ ret = pthread_detach(disk_util_thread);
+ if (ret) {
+ log_err("Can't detatch disk util 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;
}
static void set_sig_handlers(void)
sigaction(SIGINT, &act, NULL);
memset(&act, 0, sizeof(act));
- act.sa_handler = sig_quit;
+ act.sa_handler = sig_int;
act.sa_flags = SA_RESTART;
- sigaction(SIGQUIT, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
}
/*
* Check if we are above the minimum rate given.
*/
static int __check_min_rate(struct thread_data *td, struct timeval *now,
- enum td_ddir ddir)
+ enum fio_ddir ddir)
{
unsigned long long bytes = 0;
unsigned long iops = 0;
return 0;
}
+static inline void __update_tv_cache(struct thread_data *td)
+{
+ fio_gettime(&td->tv_cache, NULL);
+}
+
static inline void update_tv_cache(struct thread_data *td)
{
if ((++td->tv_cache_nr & td->tv_cache_mask) == td->tv_cache_mask)
- fio_gettime(&td->tv_cache, NULL);
+ __update_tv_cache(td);
}
static int break_on_this_error(struct thread_data *td, int *retptr)
update_tv_cache(td);
if (runtime_exceeded(td, &td->tv_cache)) {
- td->terminate = 1;
- break;
+ __update_tv_cache(td);
+ if (runtime_exceeded(td, &td->tv_cache)) {
+ td->terminate = 1;
+ break;
+ }
}
io_u = __get_io_u(td);
clear_io_u(td, io_u);
} else if (io_u->resid) {
int bytes = io_u->xfer_buflen - io_u->resid;
- struct fio_file *f = io_u->file;
/*
* zero read, fail
if (ddir_rw(io_u->ddir))
td->ts.short_io_u[io_u->ddir]++;
+ f = io_u->file;
if (io_u->offset == f->real_file_size)
goto sync_done;
update_tv_cache(td);
if (runtime_exceeded(td, &td->tv_cache)) {
- td->terminate = 1;
- break;
+ __update_tv_cache(td);
+ if (runtime_exceeded(td, &td->tv_cache)) {
+ td->terminate = 1;
+ break;
+ }
}
io_u = get_io_u(td);
struct fio_file *f;
i = td->cur_depth;
- if (i)
+ if (i) {
ret = io_u_queued_complete(td, i, NULL);
+ if (td->o.fill_device && td->error == ENOSPC)
+ td->error = 0;
+ }
if (should_fsync(td) && td->o.end_fsync) {
td_set_runstate(td, TD_FSYNCING);
io_u = flist_entry(entry, struct io_u, list);
flist_del(&io_u->list);
- free(io_u);
+ fio_memfree(io_u, sizeof(*io_u));
}
free_io_mem(td);
if (td->terminate)
return 1;
- if (posix_memalign(&ptr, cl_align, sizeof(*io_u))) {
- log_err("fio: posix_memalign=%s\n", strerror(errno));
+ ptr = fio_memalign(cl_align, sizeof(*io_u));
+ if (!ptr) {
+ log_err("fio: unable to allocate aligned memory\n");
break;
}
* Fill the buffer with the pattern if we are
* going to be doing writes.
*/
- fill_pattern(td, io_u->buf, max_bs, io_u);
+ fill_pattern(td, io_u->buf, max_bs, io_u, 0, 0);
}
}
*/
if (td->o.time_based || td->o.loops)
td->nr_done_files = 0;
-
- /*
- * Set the same seed to get repeatable runs
- */
- td_fill_rand_seeds(td);
}
void reset_all_stats(struct thread_data *td)
td->io_issues[i] = 0;
td->ts.total_io_u[i] = 0;
}
-
+
fio_gettime(&tv, NULL);
td->ts.runtime[0] = 0;
td->ts.runtime[1] = 0;
close_files(td);
for_each_file(td, f, i)
fio_file_clear_done(f);
+
+ /*
+ * Set the same seed to get repeatable runs
+ */
+ td_fill_rand_seeds(td);
}
static int exec_string(const char *string)
pthread_condattr_t attr;
int clear_state;
- if (!td->o.use_thread)
+ if (!td->o.use_thread) {
setsid();
-
- td->pid = getpid();
+ td->pid = getpid();
+ } else
+ td->pid = gettid();
dprint(FD_PROCESS, "jobs pid=%d started\n", (int) td->pid);
*/
fio_mutex_remove(td->mutex);
+ /*
+ * A new gid requires privilege, so we need to do this before setting
+ * the uid.
+ */
+ if (td->o.gid != -1U && setgid(td->o.gid)) {
+ td_verror(td, errno, "setgid");
+ goto err;
+ }
if (td->o.uid != -1U && setuid(td->o.uid)) {
td_verror(td, errno, "setuid");
goto err;
}
- if (td->o.gid != -1U && setgid(td->o.gid)) {
- td_verror(td, errno, "setgid");
+
+ /*
+ * 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);
+
+ /*
+ * 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 (td->o.verify_async && verify_async_init(td))
goto err;
- if (td->o.cpumask_set && fio_setaffinity(td->pid, td->o.cpumask) == -1) {
- td_verror(td, errno, "cpu_set_affinity");
- goto err;
- }
-
- /*
- * 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 (fio_setaffinity(td->pid, td->o.cpumask) == -1) {
- td_verror(td, errno, "cpu_set_affinity");
- goto err;
- }
- }
-
if (td->ioprio_set) {
if (ioprio_set(IOPRIO_WHO_PROCESS, 0, td->ioprio) == -1) {
td_verror(td, errno, "ioprio_set");
struct thread_data *td;
void *data, *ret;
+#ifndef __hpux
data = shmat(shmid, NULL, 0);
if (data == (void *) -1) {
int __err = errno;
perror("shmat");
return __err;
}
+#else
+ /*
+ * HP-UX inherits shm mappings?
+ */
+ data = threads;
+#endif
td = data + offset * sizeof(struct thread_data);
ret = thread_main(td);
if (WIFSIGNALED(status)) {
int sig = WTERMSIG(status);
- if (sig != SIGQUIT)
+ if (sig != SIGTERM)
log_err("fio: pid=%d, got signal=%d\n",
(int) td->pid, sig);
td_set_runstate(td, TD_REAPED);
todo--;
} else {
struct fio_file *f;
- unsigned int i;
+ unsigned int j;
/*
* for sharing to work, each job must always open
* its own files. so close them, if we opened them
* for creation
*/
- for_each_file(td, f, i) {
+ for_each_file(td, f, j) {
if (fio_file_open(f))
td_io_close_file(td, f);
}
set_genesis_time();
while (todo) {
- struct thread_data *map[MAX_JOBS];
+ struct thread_data *map[REAL_MAX_JOBS];
struct timeval this_start;
int this_jobs = 0, left;
}
startup_mutex = fio_mutex_init(0);
+ if (startup_mutex == NULL)
+ return 1;
writeout_mutex = fio_mutex_init(1);
+ if (writeout_mutex == NULL)
+ return 1;
set_genesis_time();
-
- posix_timer_setup();
- status_timer_arm();
+ create_disk_util_thread();
cgroup_list = smalloc(sizeof(*cgroup_list));
INIT_FLIST_HEAD(cgroup_list);
sfree(cgroup_list);
sfree(cgroup_mnt);
- posix_timer_teardown();
fio_mutex_remove(startup_mutex);
fio_mutex_remove(writeout_mutex);
return exit_value;