Streamline thread_data data direction setting and checking
[fio.git] / init.c
diff --git a/init.c b/init.c
index 9e41d55af957a66d6a0900462d5d4ca5a8c7f038..9ed99d797feace5c46cba7e2141450633174bbe0 100644 (file)
--- a/init.c
+++ b/init.c
@@ -33,6 +33,7 @@ static int str_prioclass_cb(void *, unsigned int *);
 #endif
 static int str_exitall_cb(void);
 static int str_cpumask_cb(void *, unsigned int *);
+static int str_file_service_cb(void *, const char *);
 
 #define __stringify_1(x)       #x
 #define __stringify(x)         __stringify_1(x)
@@ -90,6 +91,12 @@ static struct fio_option options[] = {
                .help   = "Amount of IO buffers to keep in flight",
                .def    = "1",
        },
+       {
+               .name   = "iodepth_low",
+               .type   = FIO_OPT_INT,
+               .off1   = td_var_offset(iodepth_low),
+               .help   = "Low water mark for queuing depth",
+       },
        {
                .name   = "size",
                .type   = FIO_OPT_STR_VAL,
@@ -146,6 +153,14 @@ static struct fio_option options[] = {
                .help   = "Split job workload between this number of files",
                .def    = "1",
        },
+       {
+               .name   = "file_service_type",
+               .type   = FIO_OPT_STR,
+               .cb     = str_file_service_cb,
+               .help   = "How to select which file to service next",
+               .def    = "roundrobin",
+               .posval = { "random", "roundrobin" },
+       },
        {
                .name   = "fsync",
                .type   = FIO_OPT_INT,
@@ -330,6 +345,13 @@ static struct fio_option options[] = {
                .help   = "Idle time between IO buffers (usec)",
                .def    = "0",
        },
+       {
+               .name   = "thinktime_spin",
+               .type   = FIO_OPT_INT,
+               .off1   = td_var_offset(thinktime_spin),
+               .help   = "Start thinktime by spinning this amount (usec)",
+               .def    = "0",
+       },
        {
                .name   = "thinktime_blocks",
                .type   = FIO_OPT_INT,
@@ -596,7 +618,7 @@ static void fixup_options(struct thread_data *td)
        /*
         * only really works for sequential io for now, and with 1 file
         */
-       if (td->zone_size && !td->sequential && td->nr_files == 1)
+       if (td->zone_size && td_random(td) && td->nr_files == 1)
                td->zone_size = 0;
 
        /*
@@ -631,6 +653,18 @@ static void fixup_options(struct thread_data *td)
         */
        if (td->filetype == FIO_TYPE_CHAR && td->odirect)
                td->odirect = 0;
+
+       /*
+        * thinktime_spin must be less than thinktime
+        */
+       if (td->thinktime_spin > td->thinktime)
+               td->thinktime_spin = td->thinktime;
+
+       /*
+        * The low water mark cannot be bigger than the iodepth
+        */
+       if (td->iodepth_low > td->iodepth || !td->iodepth_low)
+               td->iodepth_low = td->iodepth;
 }
 
 /*
@@ -661,10 +695,10 @@ static char *to_kmg(unsigned int val)
  */
 static int add_job(struct thread_data *td, const char *jobname, int job_add_num)
 {
-       const char *ddir_str[] = { "read", "write", "randread", "randwrite",
-                                  "rw", NULL, "randrw" };
+       const char *ddir_str[] = { NULL, "read", "write", "rw", NULL,
+                                  "randread", "randwrite", "randrw" };
        struct stat sb;
-       int numjobs, ddir, i;
+       int numjobs, i;
        struct fio_file *f;
 
        /*
@@ -700,7 +734,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num)
                if (td->directory && td->directory[0] != '\0') {
                        if (lstat(td->directory, &sb) < 0) {
                                log_err("fio: %s is not a directory\n", td->directory);
-                               td_verror(td, errno);
+                               td_verror(td, errno, "lstat");
                                return 1;
                        }
                        if (!S_ISDIR(sb.st_mode)) {
@@ -739,9 +773,9 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num)
                
        fio_sem_init(&td->mutex, 0);
 
-       td->clat_stat[0].min_val = td->clat_stat[1].min_val = ULONG_MAX;
-       td->slat_stat[0].min_val = td->slat_stat[1].min_val = ULONG_MAX;
-       td->bw_stat[0].min_val = td->bw_stat[1].min_val = ULONG_MAX;
+       td->ts.clat_stat[0].min_val = td->ts.clat_stat[1].min_val = ULONG_MAX;
+       td->ts.slat_stat[0].min_val = td->ts.slat_stat[1].min_val = ULONG_MAX;
+       td->ts.bw_stat[0].min_val = td->ts.bw_stat[1].min_val = ULONG_MAX;
 
        if (td->stonewall && td->thread_number > 1)
                groupid++;
@@ -752,17 +786,15 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num)
                goto err;
 
        if (td->write_lat_log) {
-               setup_log(&td->slat_log);
-               setup_log(&td->clat_log);
+               setup_log(&td->ts.slat_log);
+               setup_log(&td->ts.clat_log);
        }
        if (td->write_bw_log)
-               setup_log(&td->bw_log);
+               setup_log(&td->ts.bw_log);
 
        if (!td->name)
                td->name = strdup(jobname);
 
-       ddir = td->ddir + (!td->sequential << 1) + (td->iomix << 2);
-
        if (!terse_output) {
                if (!job_add_num) {
                        if (td->io_ops->flags & FIO_CPUIO)
@@ -775,7 +807,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num)
                                c3 = to_kmg(td->min_bs[DDIR_WRITE]);
                                c4 = to_kmg(td->max_bs[DDIR_WRITE]);
 
-                               fprintf(f_out, "%s: (g=%d): rw=%s, bs=%s-%s/%s-%s, ioengine=%s, iodepth=%u\n", td->name, td->groupid, ddir_str[ddir], c1, c2, c3, c4, td->io_ops->name, td->iodepth);
+                               fprintf(f_out, "%s: (g=%d): rw=%s, bs=%s-%s/%s-%s, ioengine=%s, iodepth=%u\n", td->name, td->groupid, ddir_str[td->td_ddir], c1, c2, c3, c4, td->io_ops->name, td->iodepth);
 
                                free(c1);
                                free(c2);
@@ -816,7 +848,7 @@ err:
  */
 int init_random_state(struct thread_data *td)
 {
-       unsigned long seeds[4];
+       unsigned long seeds[5];
        int fd, num_maps, blocks, i;
        struct fio_file *f;
 
@@ -825,12 +857,12 @@ int init_random_state(struct thread_data *td)
 
        fd = open("/dev/urandom", O_RDONLY);
        if (fd == -1) {
-               td_verror(td, errno);
+               td_verror(td, errno, "open");
                return 1;
        }
 
        if (read(fd, seeds, sizeof(seeds)) < (int) sizeof(seeds)) {
-               td_verror(td, EIO);
+               td_verror(td, EIO, "read");
                close(fd);
                return 1;
        }
@@ -841,11 +873,14 @@ int init_random_state(struct thread_data *td)
        os_random_seed(seeds[1], &td->verify_state);
        os_random_seed(seeds[2], &td->rwmix_state);
 
-       if (td->sequential)
+       if (td->file_service_type == FIO_FSERVICE_RANDOM)
+               os_random_seed(seeds[3], &td->next_file_state);
+
+       if (!td_random(td))
                return 0;
 
        if (td->rand_repeatable)
-               seeds[3] = FIO_RANDSEED;
+               seeds[4] = FIO_RANDSEED * td->thread_number;
 
        if (!td->norandommap) {
                for_each_file(td, f, i) {
@@ -857,7 +892,7 @@ int init_random_state(struct thread_data *td)
                }
        }
 
-       os_random_seed(seeds[3], &td->random_state);
+       os_random_seed(seeds[4], &td->random_state);
        return 0;
 }
 
@@ -882,6 +917,8 @@ static int is_empty_or_comment(char *line)
        for (i = 0; i < strlen(line); i++) {
                if (line[i] == ';')
                        return 1;
+               if (line[i] == '#')
+                       return 1;
                if (!isspace(line[i]) && !iscntrl(line[i]))
                        return 0;
        }
@@ -894,30 +931,22 @@ static int str_rw_cb(void *data, const char *mem)
        struct thread_data *td = data;
 
        if (!strncmp(mem, "read", 4) || !strncmp(mem, "0", 1)) {
-               td->ddir = DDIR_READ;
-               td->sequential = 1;
+               td->td_ddir = TD_DDIR_READ;
                return 0;
        } else if (!strncmp(mem, "randread", 8)) {
-               td->ddir = DDIR_READ;
-               td->sequential = 0;
+               td->td_ddir = TD_DDIR_READ | TD_DDIR_RAND;
                return 0;
        } else if (!strncmp(mem, "write", 5) || !strncmp(mem, "1", 1)) {
-               td->ddir = DDIR_WRITE;
-               td->sequential = 1;
+               td->td_ddir = TD_DDIR_WRITE;
                return 0;
        } else if (!strncmp(mem, "randwrite", 9)) {
-               td->ddir = DDIR_WRITE;
-               td->sequential = 0;
+               td->td_ddir = TD_DDIR_WRITE | TD_DDIR_RAND;
                return 0;
        } else if (!strncmp(mem, "rw", 2)) {
-               td->ddir = DDIR_READ;
-               td->iomix = 1;
-               td->sequential = 1;
+               td->td_ddir = TD_DDIR_RW;
                return 0;
        } else if (!strncmp(mem, "randrw", 6)) {
-               td->ddir = DDIR_READ;
-               td->iomix = 1;
-               td->sequential = 0;
+               td->td_ddir = TD_DDIR_RW | TD_DDIR_RAND;
                return 0;
        }
 
@@ -1017,7 +1046,7 @@ static int str_ioengine_cb(void *data, const char *str)
        if (td->io_ops)
                return 0;
 
-       log_err("fio: ioengine= libaio, posixaio, sync, mmap, sgio, splice, cpu, null\n");
+       log_err("fio: ioengine= libaio, posixaio, sync, syslet-rw, mmap, sgio, splice, cpu, null\n");
        log_err("fio: or specify path to dynamic ioengine module\n");
        return 1;
 }
@@ -1060,6 +1089,22 @@ static int str_cpumask_cb(void *data, unsigned int *val)
        return 0;
 }
 
+static int str_file_service_cb(void *data, const char *str)
+{
+       struct thread_data *td = data;
+
+       if (!strncmp(str, "random", 6)) {
+               td->file_service_type = FIO_FSERVICE_RANDOM;
+               return 0;
+       } else if (!strncmp(str, "roundrobin", 10)) {
+               td->file_service_type = FIO_FSERVICE_RR;
+               return 0;
+       }
+
+       log_err("fio: file_service= random, roundrobin\n");
+       return 1;
+}
+
 /*
  * This is our [ini] type file parser.
  */