backend: terminate loop if we didn't do IO
[fio.git] / init.c
diff --git a/init.c b/init.c
index e7faca10ca1dd448e48867a1602c2d5e61710465..0100da213a2420db2487b24979895b4c68468455 100644 (file)
--- a/init.c
+++ b/init.c
@@ -27,7 +27,7 @@
 #include "filelock.h"
 
 #include "lib/getopt.h"
-#include "lib/strcasestr.h"
+#include "oslib/strcasestr.h"
 
 #include "crc/test.h"
 
@@ -48,7 +48,6 @@ static int nr_job_sections;
 
 int exitall_on_terminate = 0;
 int output_format = FIO_OUTPUT_NORMAL;
-int append_terse_output = 0;
 int eta_print = FIO_ETA_AUTO;
 int eta_new_line = 0;
 FILE *f_out = NULL;
@@ -474,6 +473,7 @@ static int __setup_rate(struct thread_data *td, enum fio_ddir ddir)
 
        td->rate_next_io_time[ddir] = 0;
        td->rate_io_issue_bytes[ddir] = 0;
+       td->last_usec = 0;
        return 0;
 }
 
@@ -737,11 +737,16 @@ static int fixup_options(struct thread_data *td)
 
        /*
         * For fully compressible data, just zero them at init time.
-        * It's faster than repeatedly filling it.
+        * It's faster than repeatedly filling it. For non-zero
+        * compression, we should have refill_buffers set. Set it, unless
+        * the job file already changed it.
         */
-       if (td->o.compress_percentage == 100) {
-               td->o.zero_buffers = 1;
-               td->o.compress_percentage = 0;
+       if (o->compress_percentage) {
+               if (o->compress_percentage == 100) {
+                       o->zero_buffers = 1;
+                       o->compress_percentage = 0;
+               } else if (!fio_option_is_set(o, refill_buffers))
+                       o->refill_buffers = 1;
        }
 
        /*
@@ -858,6 +863,7 @@ static void td_fill_rand_seeds_internal(struct thread_data *td, int use64)
        init_rand_seed(&td->file_size_state, td->rand_seeds[FIO_RAND_FILE_SIZE_OFF], use64);
        init_rand_seed(&td->trim_state, td->rand_seeds[FIO_RAND_TRIM_OFF], use64);
        init_rand_seed(&td->delay_state, td->rand_seeds[FIO_RAND_START_DELAY], use64);
+       init_rand_seed(&td->poisson_state, td->rand_seeds[FIO_RAND_POISSON_OFF], 0);
 
        if (!td_random(td))
                return;
@@ -1232,6 +1238,10 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
        if ((o->stonewall || o->new_group) && prev_group_jobs) {
                prev_group_jobs = 0;
                groupid++;
+               if (groupid == INT_MAX) {
+                       log_err("fio: too many groups defined\n");
+                       goto err;
+               }
        }
 
        td->groupid = groupid;
@@ -1767,7 +1777,7 @@ static void usage(const char *name)
        printf("  --runtime\t\tRuntime in seconds\n");
        printf("  --bandwidth-log\tGenerate per-job bandwidth logs\n");
        printf("  --minimal\t\tMinimal (terse) output\n");
-       printf("  --output-format=x\tOutput format (terse,json,normal)\n");
+       printf("  --output-format=x\tOutput format (terse,json,json+,normal)\n");
        printf("  --terse-version=x\tSet terse version output format to 'x'\n");
        printf("  --version\t\tPrint version info and exit\n");
        printf("  --help\t\tPrint this page\n");
@@ -1889,6 +1899,9 @@ static int set_debug(const char *string)
        char *opt;
        int i;
 
+       if (!string)
+               return 0;
+
        if (!strcmp(string, "?") || !strcmp(string, "help")) {
                log_info("fio: dumping debug options:");
                for (i = 0; debug_levels[i].name; i++) {
@@ -2009,6 +2022,37 @@ static void show_closest_option(const char *name)
                log_err("Did you mean %s?\n", l_opts[best_option].name);
 }
 
+static int parse_output_format(const char *optarg)
+{
+       char *p, *orig, *opt;
+       int ret = 0;
+
+       p = orig = strdup(optarg);
+
+       output_format = 0;
+
+       while ((opt = strsep(&p, ",")) != NULL) {
+               if (!strcmp(opt, "minimal") ||
+                   !strcmp(opt, "terse") ||
+                   !strcmp(opt, "csv"))
+                       output_format |= FIO_OUTPUT_TERSE;
+               else if (!strcmp(opt, "json"))
+                       output_format |= FIO_OUTPUT_JSON;
+               else if (!strcmp(opt, "json+"))
+                       output_format |= (FIO_OUTPUT_JSON | FIO_OUTPUT_JSON_PLUS);
+               else if (!strcmp(opt, "normal"))
+                       output_format |= FIO_OUTPUT_NORMAL;
+               else {
+                       log_err("fio: invalid output format %s\n", opt);
+                       ret = 1;
+                       break;
+               }
+       }
+
+       free(orig);
+       return ret;
+}
+
 int parse_cmd_line(int argc, char *argv[], int client_type)
 {
        struct thread_data *td = NULL;
@@ -2070,17 +2114,15 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
                                do_exit++;
                                break;
                        }
-                       if (!strcmp(optarg, "minimal") ||
-                           !strcmp(optarg, "terse") ||
-                           !strcmp(optarg, "csv"))
-                               output_format = FIO_OUTPUT_TERSE;
-                       else if (!strcmp(optarg, "json"))
-                               output_format = FIO_OUTPUT_JSON;
-                       else
-                               output_format = FIO_OUTPUT_NORMAL;
+                       if (parse_output_format(optarg)) {
+                               log_err("fio: failed parsing output-format\n");
+                               exit_val = 1;
+                               do_exit++;
+                               break;
+                       }
                        break;
                case 'f':
-                       append_terse_output = 1;
+                       output_format |= FIO_OUTPUT_TERSE;
                        break;
                case 'h':
                        did_arg = 1;