Add exitall_on_error option
[fio.git] / init.c
diff --git a/init.c b/init.c
index cdb98c57231066b5e71c7c7ce2636c7870215d15..63ba32481b9ba87943d320e0b6daa7f2ae31965b 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"
 
@@ -47,8 +47,8 @@ static char **job_sections;
 static int nr_job_sections;
 
 int exitall_on_terminate = 0;
+int exitall_on_terminate_error = 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;
@@ -465,7 +465,7 @@ static int __setup_rate(struct thread_data *td, enum fio_ddir ddir)
        if (td->o.rate[ddir])
                td->rate_bps[ddir] = td->o.rate[ddir];
        else
-               td->rate_bps[ddir] = td->o.rate_iops[ddir] * bs;
+               td->rate_bps[ddir] = (uint64_t) td->o.rate_iops[ddir] * bs;
 
        if (!td->rate_bps[ddir]) {
                log_err("rate lower than supported\n");
@@ -474,6 +474,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;
 }
 
@@ -630,6 +631,13 @@ static int fixup_options(struct thread_data *td)
        if (o->iodepth_batch > o->iodepth || !o->iodepth_batch)
                o->iodepth_batch = o->iodepth;
 
+       /*
+        * If max batch complete number isn't set or set incorrectly,
+        * default to the same as iodepth_batch_complete_min
+        */
+       if (o->iodepth_batch_complete_min > o->iodepth_batch_complete_max)
+               o->iodepth_batch_complete_max = o->iodepth_batch_complete_min;
+
        if (o->nr_files > td->files_index)
                o->nr_files = td->files_index;
 
@@ -730,11 +738,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;
        }
 
        /*
@@ -851,6 +864,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;
@@ -1225,6 +1239,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;
@@ -1310,7 +1328,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
        if (!o->name)
                o->name = strdup(jobname);
 
-       if (output_format == FIO_OUTPUT_NORMAL) {
+       if (output_format & FIO_OUTPUT_NORMAL) {
                if (!job_add_num) {
                        if (is_backend && !recursed)
                                fio_server_send_add_job(td);
@@ -1760,7 +1778,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");
@@ -1882,6 +1900,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++) {
@@ -2002,6 +2023,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;
@@ -2063,17 +2115,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;
@@ -2525,7 +2575,7 @@ int parse_options(int argc, char *argv[])
                return 0;
        }
 
-       if (output_format == FIO_OUTPUT_NORMAL)
+       if (output_format & FIO_OUTPUT_NORMAL)
                log_info("%s\n", fio_version_string);
 
        return 0;