Add verify trim support
[fio.git] / fio.c
diff --git a/fio.c b/fio.c
index 4bbab5af9a12e9c0d00fa559bdddb94107b42f77..c8de2ee7a7e3a3f94a0f1af8dc01080c01e22be1 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -40,6 +40,8 @@
 #include "verify.h"
 #include "diskutil.h"
 #include "cgroup.h"
+#include "profile.h"
+#include "lib/rand.h"
 
 unsigned long page_mask;
 unsigned long page_size;
@@ -61,6 +63,8 @@ static volatile int fio_abort;
 static int exit_value;
 static struct itimerval itimer;
 static pthread_t gtod_thread;
+static struct flist_head *cgroup_list;
+static char *cgroup_mnt;
 
 struct io_log *agg_io_log[2];
 
@@ -132,23 +136,12 @@ static void sig_quit(int sig)
 static void sig_int(int sig)
 {
        if (threads) {
-               printf("\nfio: terminating on signal %d\n", sig);
+               log_info("\nfio: terminating on signal %d\n", sig);
                fflush(stdout);
                terminate_threads(TERMINATE_ALL);
        }
 }
 
-static void sig_ill(int fio_unused sig)
-{
-       if (!threads)
-               return;
-
-       log_err("fio: illegal instruction. your cpu does not support "
-               "the sse4.2 instruction for crc32c\n");
-       terminate_threads(TERMINATE_ALL);
-       exit(4);
-}
-
 static void set_sig_handlers(void)
 {
        struct sigaction act;
@@ -163,11 +156,6 @@ static void set_sig_handlers(void)
        act.sa_flags = SA_RESTART;
        sigaction(SIGINT, &act, NULL);
 
-       memset(&act, 0, sizeof(act));
-       act.sa_handler = sig_ill;
-       act.sa_flags = SA_RESTART;
-       sigaction(SIGILL, &act, NULL);
-
        memset(&act, 0, sizeof(act));
        act.sa_handler = sig_quit;
        act.sa_flags = SA_RESTART;
@@ -188,6 +176,8 @@ static int __check_min_rate(struct thread_data *td, struct timeval *now,
        unsigned int rate_iops = 0;
        unsigned int rate_iops_min = 0;
 
+       assert(ddir_rw(ddir));
+
        if (!td->o.ratemin[ddir] && !td->o.rate_iops_min[ddir])
                return 0;
 
@@ -430,6 +420,8 @@ static void do_verify(struct thread_data *td)
        int ret, min_events;
        unsigned int i;
 
+       dprint(FD_VERIFY, "starting loop\n");
+
        /*
         * sync io first and invalidate cache, to make sure we really
         * read from disk.
@@ -501,7 +493,8 @@ static void do_verify(struct thread_data *td)
                                io_u->xfer_buf += bytes;
                                io_u->offset += bytes;
 
-                               td->ts.short_io_u[io_u->ddir]++;
+                               if (ddir_rw(io_u->ddir))
+                                       td->ts.short_io_u[io_u->ddir]++;
 
                                if (io_u->offset == f->real_file_size)
                                        goto sync_done;
@@ -567,6 +560,8 @@ sync_done:
                cleanup_pending_aio(td);
 
        td_set_runstate(td, TD_RUNNING);
+
+       dprint(FD_VERIFY, "exiting loop\n");
 }
 
 /*
@@ -644,7 +639,8 @@ static void do_io(struct thread_data *td)
                                io_u->xfer_buf += bytes;
                                io_u->offset += bytes;
 
-                               td->ts.short_io_u[io_u->ddir]++;
+                               if (ddir_rw(io_u->ddir))
+                                       td->ts.short_io_u[io_u->ddir]++;
 
                                if (io_u->offset == f->real_file_size)
                                        goto sync_done;
@@ -839,6 +835,13 @@ static int init_io_u(struct thread_data *td)
 
                        if (td_write(td) && !td->o.refill_buffers)
                                io_u_fill_buffer(td, io_u, max_bs);
+                       else if (td_write(td) && td->o.verify_pattern_bytes) {
+                               /*
+                                * Fill the buffer with the pattern if we are
+                                * going to be doing writes.
+                                */
+                               fill_pattern(td, io_u->buf, max_bs, io_u);
+                       }
                }
 
                io_u->index = i;
@@ -1019,6 +1022,7 @@ static void *thread_main(void *data)
        INIT_FLIST_HEAD(&td->io_log_list);
        INIT_FLIST_HEAD(&td->io_hist_list);
        INIT_FLIST_HEAD(&td->verify_list);
+       INIT_FLIST_HEAD(&td->trim_list);
        pthread_mutex_init(&td->io_u_lock, NULL);
        td->io_hist_tree = RB_ROOT;
 
@@ -1039,6 +1043,15 @@ 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;
+       }
+       if (td->o.gid != -1U && setgid(td->o.gid)) {
+               td_verror(td, errno, "setgid");
+               goto err;
+       }
+
        /*
         * May alter parameters that init_io_u() will use, so we need to
         * do this first.
@@ -1076,7 +1089,7 @@ static void *thread_main(void *data)
                }
        }
 
-       if (td->o.cgroup_weight && cgroup_setup(td))
+       if (td->o.cgroup_weight && cgroup_setup(td, cgroup_list, &cgroup_mnt))
                goto err;
 
        if (nice(td->o.nice) == -1) {
@@ -1176,6 +1189,13 @@ static void *thread_main(void *data)
                } else
                        finish_log(td, td->ts.bw_log, "bw");
        }
+       if (td->ts.lat_log) {
+               if (td->o.lat_log_file) {
+                       finish_log_named(td, td->ts.lat_log,
+                                               td->o.lat_log_file, "lat");
+               } else
+                       finish_log(td, td->ts.lat_log, "lat");
+       }
        if (td->ts.slat_log) {
                if (td->o.lat_log_file) {
                        finish_log_named(td, td->ts.slat_log,
@@ -1199,7 +1219,7 @@ static void *thread_main(void *data)
 
 err:
        if (td->error)
-               printf("fio: pid=%d, err=%d/%s\n", (int) td->pid, td->error,
+               log_info("fio: pid=%d, err=%d/%s\n", (int) td->pid, td->error,
                                                        td->verror);
 
        if (td->o.verify_async)
@@ -1208,7 +1228,7 @@ err:
        close_and_free_files(td);
        close_ioengine(td);
        cleanup_io_u(td);
-       cgroup_shutdown(td);
+       cgroup_shutdown(td, &cgroup_mnt);
 
        if (td->o.cpumask_set) {
                int ret = fio_cpuset_exit(&td->o.cpumask);
@@ -1365,9 +1385,13 @@ static void *gtod_thread_main(void *data)
 
 static int fio_start_gtod_thread(void)
 {
+       pthread_attr_t attr;
        int ret;
 
-       ret = pthread_create(&gtod_thread, NULL, gtod_thread_main, NULL);
+       pthread_attr_init(&attr);
+       pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
+       ret = pthread_create(&gtod_thread, &attr, gtod_thread_main, NULL);
+       pthread_attr_destroy(&attr);
        if (ret) {
                log_err("Can't create gtod thread: %s\n", strerror(ret));
                return 1;
@@ -1401,17 +1425,17 @@ static void run_threads(void)
                return;
 
        if (!terse_output) {
-               printf("Starting ");
+               log_info("Starting ");
                if (nr_thread)
-                       printf("%d thread%s", nr_thread,
+                       log_info("%d thread%s", nr_thread,
                                                nr_thread > 1 ? "s" : "");
                if (nr_process) {
                        if (nr_thread)
                                printf(" and ");
-                       printf("%d process%s", nr_process,
+                       log_info("%d process%s", nr_process,
                                                nr_process > 1 ? "es" : "");
                }
-               printf("\n");
+               log_info("\n");
                fflush(stdout);
        }
 
@@ -1620,6 +1644,7 @@ int main(int argc, char *argv[])
        long ps;
 
        sinit();
+       init_rand(&__fio_rand_state);
 
        /*
         * We need locale for number printing, if it isn't set then just
@@ -1642,6 +1667,9 @@ int main(int argc, char *argv[])
        if (parse_options(argc, argv))
                return 1;
 
+       if (exec_profile && load_profile(exec_profile))
+               return 1;
+
        if (!thread_number)
                return 0;
 
@@ -1657,6 +1685,9 @@ int main(int argc, char *argv[])
 
        status_timer_arm();
 
+       cgroup_list = smalloc(sizeof(*cgroup_list));
+       INIT_FLIST_HEAD(cgroup_list);
+
        run_threads();
 
        if (!fio_abort) {
@@ -1668,6 +1699,10 @@ int main(int argc, char *argv[])
                }
        }
 
+       cgroup_kill(cgroup_list);
+       sfree(cgroup_list);
+       sfree(cgroup_mnt);
+
        fio_mutex_remove(startup_mutex);
        fio_mutex_remove(writeout_mutex);
        return exit_value;