setgid first, setuid second
[fio.git] / fio.c
diff --git a/fio.c b/fio.c
index 7b03250bd22ddce7b01c6a3e8e306ca108ef447e..8cc8fcf3361be69e39bd4003a8d93e8ec81466a2 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -28,6 +28,7 @@
 #include <time.h>
 #include <locale.h>
 #include <assert.h>
+#include <time.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <sys/ipc.h>
@@ -62,7 +63,7 @@ static struct fio_mutex *startup_mutex;
 static struct fio_mutex *writeout_mutex;
 static volatile int fio_abort;
 static int exit_value;
-static struct itimerval itimer;
+static timer_t ival_timer;
 static pthread_t gtod_thread;
 static struct flist_head *cgroup_list;
 static char *cgroup_mnt;
@@ -113,17 +114,21 @@ static void terminate_threads(int group_id)
 
 static void status_timer_arm(void)
 {
-       itimer.it_value.tv_sec = 0;
-       itimer.it_value.tv_usec = DISK_UTIL_MSEC * 1000;
-       setitimer(ITIMER_REAL, &itimer, NULL);
+       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 sig_alrm(int fio_unused sig)
+static void ival_fn(union sigval sig)
 {
        if (threads) {
                update_io_ticks();
                print_thread_status();
-               status_timer_arm();
        }
 }
 
@@ -143,15 +148,27 @@ static void sig_int(int sig)
        }
 }
 
+static void posix_timer_teardown(void)
+{
+       timer_delete(ival_timer);
+}
+
+static void posix_timer_setup(void)
+{
+       struct sigevent evt;
+
+       memset(&evt, 0, sizeof(evt));
+       evt.sigev_notify = SIGEV_THREAD;
+       evt.sigev_notify_function = ival_fn;
+
+       if (timer_create(CLOCK_MONOTONIC, &evt, &ival_timer) < 0)
+               perror("timer_create");
+}
+
 static void set_sig_handlers(void)
 {
        struct sigaction act;
 
-       memset(&act, 0, sizeof(act));
-       act.sa_handler = sig_alrm;
-       act.sa_flags = SA_RESTART;
-       sigaction(SIGALRM, &act, NULL);
-
        memset(&act, 0, sizeof(act));
        act.sa_handler = sig_int;
        act.sa_flags = SA_RESTART;
@@ -811,7 +828,8 @@ static int init_io_u(struct thread_data *td)
        if (allocate_io_mem(td))
                return 1;
 
-       if (td->o.odirect || td->o.mem_align)
+       if (td->o.odirect || td->o.mem_align ||
+           (td->io_ops->flags & FIO_RAWIO))
                p = PAGE_ALIGN(td->orig_buffer) + td->o.mem_align;
        else
                p = td->orig_buffer;
@@ -971,6 +989,8 @@ void reset_all_stats(struct thread_data *td)
        }
        
        fio_gettime(&tv, NULL);
+       td->ts.runtime[0] = 0;
+       td->ts.runtime[1] = 0;
        memcpy(&td->epoch, &tv, sizeof(tv));
        memcpy(&td->start, &tv, sizeof(tv));
 }
@@ -1009,7 +1029,7 @@ static int exec_string(const char *string)
  */
 static void *thread_main(void *data)
 {
-       unsigned long long runtime[2], elapsed;
+       unsigned long long elapsed;
        struct thread_data *td = data;
        pthread_condattr_t attr;
        int clear_state;
@@ -1048,14 +1068,18 @@ static void *thread_main(void *data)
         */
        fio_mutex_remove(td->mutex);
 
-       if (td->o.uid != -1U && setuid(td->o.uid)) {
-               td_verror(td, errno, "setuid");
-               goto err;
-       }
+       /*
+        * 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;
+       }
 
        /*
         * May alter parameters that init_io_u() will use, so we need to
@@ -1127,7 +1151,6 @@ static void *thread_main(void *data)
        fio_gettime(&td->epoch, NULL);
        getrusage(RUSAGE_SELF, &td->ts.ru_start);
 
-       runtime[0] = runtime[1] = 0;
        clear_state = 0;
        while (keep_running(td)) {
                fio_gettime(&td->start, NULL);
@@ -1152,11 +1175,11 @@ static void *thread_main(void *data)
 
                if (td_read(td) && td->io_bytes[DDIR_READ]) {
                        elapsed = utime_since_now(&td->start);
-                       runtime[DDIR_READ] += elapsed;
+                       td->ts.runtime[DDIR_READ] += elapsed;
                }
                if (td_write(td) && td->io_bytes[DDIR_WRITE]) {
                        elapsed = utime_since_now(&td->start);
-                       runtime[DDIR_WRITE] += elapsed;
+                       td->ts.runtime[DDIR_WRITE] += elapsed;
                }
 
                if (td->error || td->terminate)
@@ -1173,15 +1196,15 @@ static void *thread_main(void *data)
 
                do_verify(td);
 
-               runtime[DDIR_READ] += utime_since_now(&td->start);
+               td->ts.runtime[DDIR_READ] += utime_since_now(&td->start);
 
                if (td->error || td->terminate)
                        break;
        }
 
        update_rusage_stat(td);
-       td->ts.runtime[0] = (runtime[0] + 999) / 1000;
-       td->ts.runtime[1] = (runtime[1] + 999) / 1000;
+       td->ts.runtime[0] = (td->ts.runtime[0] + 999) / 1000;
+       td->ts.runtime[1] = (td->ts.runtime[1] + 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];
@@ -1688,6 +1711,7 @@ int main(int argc, char *argv[])
 
        set_genesis_time();
 
+       posix_timer_setup();
        status_timer_arm();
 
        cgroup_list = smalloc(sizeof(*cgroup_list));
@@ -1708,6 +1732,7 @@ int main(int argc, char *argv[])
        sfree(cgroup_list);
        sfree(cgroup_mnt);
 
+       posix_timer_teardown();
        fio_mutex_remove(startup_mutex);
        fio_mutex_remove(writeout_mutex);
        return exit_value;