Merge branch 'master' into gfio
[fio.git] / backend.c
index ae4216db26c69b8fc23d1494a9f648965b882948..022122a2d9914ca78a6406075e41e3c58b58242a 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -61,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;
@@ -406,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.
@@ -433,6 +442,8 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes)
                        break;
        }
 
+       check_update_rusage(td);
+
        if (td->error)
                return;
 
@@ -444,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);
@@ -597,6 +609,8 @@ sync_done:
                        break;
        }
 
+       check_update_rusage(td);
+
        if (!td->error) {
                min_events = td->cur_depth;
 
@@ -652,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;
 
@@ -816,6 +832,8 @@ sync_done:
                }
        }
 
+       check_update_rusage(td);
+
        if (td->trim_entries)
                log_err("fio: %d trim entries leaked?\n", td->trim_entries);
 
@@ -1074,10 +1092,12 @@ 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
@@ -1087,6 +1107,9 @@ static void *thread_main(void *data)
 
        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);
@@ -1114,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;
        }
@@ -1132,16 +1156,19 @@ 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
@@ -1197,11 +1224,12 @@ 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;
                }
@@ -1211,15 +1239,15 @@ static void *thread_main(void *data)
                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))
@@ -1228,16 +1256,16 @@ 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_verify_init(td);
+
        fio_gettime(&td->epoch, NULL);
        fio_getrusage(&td->ru_start);
        clear_state = 0;
@@ -1310,6 +1338,8 @@ 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) {
@@ -1367,8 +1397,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");
        }
@@ -1379,6 +1409,9 @@ err:
        if (td->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;
 }
@@ -1522,9 +1555,6 @@ 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;
        
@@ -1532,6 +1562,14 @@ static void run_threads(void)
 
        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)
@@ -1627,6 +1665,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.
@@ -1734,27 +1775,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)
@@ -1832,9 +1864,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);