options: strip off =optval when matching
[fio.git] / options.c
index ce955133eff6ddc3beda8ddcdd8af02725b7b621..2c703fdb85e622c79f8537d80bd2681d87f85d05 100644 (file)
--- a/options.c
+++ b/options.c
@@ -98,11 +98,11 @@ static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
                        if (perc > 100)
                                perc = 100;
                        else if (!perc)
-                               perc = -1;
+                               perc = -1U;
                } else
-                       perc = -1;
+                       perc = -1U;
 
-               if (str_to_decimal(fname, &val, 1, o, 0)) {
+               if (str_to_decimal(fname, &val, 1, o, 0, 0)) {
                        log_err("fio: bssplit conversion failed\n");
                        free(bssplit);
                        return 1;
@@ -127,7 +127,7 @@ static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
        for (i = 0; i < o->bssplit_nr[ddir]; i++) {
                struct bssplit *bsp = &bssplit[i];
 
-               if (bsp->perc == (unsigned char) -1)
+               if (bsp->perc == -1U)
                        perc_missing++;
                else
                        perc += bsp->perc;
@@ -138,17 +138,18 @@ static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
                free(bssplit);
                return 1;
        }
+
        /*
         * If values didn't have a percentage set, divide the remains between
         * them.
         */
        if (perc_missing) {
-               if (perc_missing == 1)
+               if (perc_missing == 1 && o->bssplit_nr[ddir] == 1)
                        perc = 100;
                for (i = 0; i < o->bssplit_nr[ddir]; i++) {
                        struct bssplit *bsp = &bssplit[i];
 
-                       if (bsp->perc == (unsigned char) -1)
+                       if (bsp->perc == -1U)
                                bsp->perc = (100 - perc) / perc_missing;
                }
        }
@@ -341,7 +342,7 @@ static int str_rw_cb(void *data, const char *str)
        else {
                long long val;
 
-               if (str_to_decimal(nr, &val, 1, o, 0)) {
+               if (str_to_decimal(nr, &val, 1, o, 0, 0)) {
                        log_err("fio: rw postfix parsing failed\n");
                        free(nr);
                        return 1;
@@ -737,7 +738,7 @@ static int str_random_distribution_cb(void *data, const char *str)
                return 0;
 
        nr = get_opt_postfix(str);
-       if (nr && !str_to_float(nr, &val)) {
+       if (nr && !str_to_float(nr, &val, 0)) {
                log_err("fio: random postfix parsing failed\n");
                free(nr);
                return 1;
@@ -1030,7 +1031,8 @@ static int str_buffer_pattern_cb(void *data, const char *input)
                                &td->o.buffer_pattern_bytes);
 
        if (!ret && td->o.buffer_pattern_bytes) {
-               td->o.refill_buffers = 0;
+               if (!td->o.compress_percentage)
+                       td->o.refill_buffers = 0;
                td->o.scramble_buffers = 0;
                td->o.zero_buffers = 0;
        } else {
@@ -1050,6 +1052,16 @@ static int str_buffer_compress_cb(void *data, unsigned long long *il)
        return 0;
 }
 
+static int str_dedupe_cb(void *data, unsigned long long *il)
+{
+       struct thread_data *td = data;
+
+       td->flags |= TD_F_COMPRESS;
+       td->o.dedupe_percentage = *il;
+       td->o.refill_buffers = 1;
+       return 0;
+}
+
 static int str_verify_pattern_cb(void *data, const char *input)
 {
        struct thread_data *td = data;
@@ -1715,7 +1727,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "Number of IOs to perform",
                .type   = FIO_OPT_STR_VAL,
                .off1   = td_var_offset(number_ios),
-               .help   = "Force job completion of this number of IOs",
+               .help   = "Force job completion after this number of IOs",
                .def    = "0",
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_INVALID,
@@ -1800,7 +1812,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "Block size division is seq/random (not read/write)",
                .type   = FIO_OPT_BOOL,
                .off1   = td_var_offset(bs_is_seq_rand),
-               .help   = "Consider any blocksize setting to be sequential,ramdom",
+               .help   = "Consider any blocksize setting to be sequential,random",
                .def    = "0",
                .parent = "blocksize",
                .category = FIO_OPT_C_IO,
@@ -1831,12 +1843,8 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
        {
                .name   = "use_os_rand",
                .lname  = "Use OS random",
-               .type   = FIO_OPT_BOOL,
-               .off1   = td_var_offset(use_os_rand),
-               .help   = "Set to use OS random generator",
-               .def    = "0",
-               .parent = "rw",
-               .hide   = 1,
+               .type   = FIO_OPT_DEPRECATED,
+               .off1   = td_var_offset(dep_use_os_rand),
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_RANDOM,
        },
@@ -2170,6 +2178,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .help   = "Only start job when this period has passed",
                .def    = "0",
                .is_seconds = 1,
+               .is_time = 1,
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_RUNTIME,
        },
@@ -2182,6 +2191,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .help   = "Stop workload when this amount of time has passed",
                .def    = "0",
                .is_seconds = 1,
+               .is_time = 1,
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_RUNTIME,
        },
@@ -2210,6 +2220,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .off1   = td_var_offset(ramp_time),
                .help   = "Ramp up time before measuring performance",
                .is_seconds = 1,
+               .is_time = 1,
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_RUNTIME,
        },
@@ -2514,6 +2525,28 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .off1   = td_var_offset(experimental_verify),
                .type   = FIO_OPT_BOOL,
                .help   = "Enable experimental verification",
+               .parent = "verify",
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_VERIFY,
+       },
+       {
+               .name   = "verify_state_load",
+               .lname  = "Load verify state",
+               .off1   = td_var_offset(verify_state),
+               .type   = FIO_OPT_BOOL,
+               .help   = "Load verify termination state",
+               .parent = "verify",
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_VERIFY,
+       },
+       {
+               .name   = "verify_state_save",
+               .lname  = "Save verify state",
+               .off1   = td_var_offset(verify_state_save),
+               .type   = FIO_OPT_BOOL,
+               .def    = "1",
+               .help   = "Save verify state on termination",
+               .parent = "verify",
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_VERIFY,
        },
@@ -2763,6 +2796,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .off1   = td_var_offset(thinktime),
                .help   = "Idle time between IO buffers (usec)",
                .def    = "0",
+               .is_time = 1,
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_THINKTIME,
        },
@@ -2773,6 +2807,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .off1   = td_var_offset(thinktime_spin),
                .help   = "Start think time by spinning this amount (usec)",
                .def    = "0",
+               .is_time = 1,
                .parent = "thinktime",
                .hide   = 1,
                .category = FIO_OPT_C_IO,
@@ -2856,6 +2891,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .type   = FIO_OPT_INT,
                .off1   = td_var_offset(max_latency),
                .help   = "Maximum tolerated IO latency (usec)",
+               .is_time = 1,
                .category = FIO_OPT_C_IO,
                .group = FIO_OPT_G_LATPROF,
        },
@@ -2865,6 +2901,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .type   = FIO_OPT_STR_VAL_TIME,
                .off1   = td_var_offset(latency_target),
                .help   = "Ramp to max queue depth supporting this latency",
+               .is_time = 1,
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_LATPROF,
        },
@@ -2874,6 +2911,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .type   = FIO_OPT_STR_VAL_TIME,
                .off1   = td_var_offset(latency_window),
                .help   = "Time to sustain latency_target",
+               .is_time = 1,
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_LATPROF,
        },
@@ -3256,6 +3294,18 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_IO_BUF,
        },
+       {
+               .name   = "dedupe_percentage",
+               .lname  = "Dedupe percentage",
+               .type   = FIO_OPT_INT,
+               .cb     = str_dedupe_cb,
+               .maxval = 100,
+               .minval = 0,
+               .help   = "Percentage of buffers that are dedupable",
+               .interval = 1,
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_IO_BUF,
+       },
        {
                .name   = "clat_percentiles",
                .lname  = "Completion latency percentiles",
@@ -3883,6 +3933,39 @@ static char **dup_and_sub_options(char **opts, int num_opts)
        return opts_copy;
 }
 
+static void show_closest_option(const char *opt)
+{
+       int best_option, best_distance;
+       int i, distance;
+       char *name;
+
+       if (!strlen(opt))
+               return;
+
+       name = strdup(opt);
+       i = 0;
+       while (name[i] != '\0' && name[i] != '=')
+               i++;
+       name[i] = '\0';
+
+       best_option = -1;
+       best_distance = INT_MAX;
+       i = 0;
+       while (fio_options[i].name) {
+               distance = string_distance(name, fio_options[i].name);
+               if (distance < best_distance) {
+                       best_distance = distance;
+                       best_option = i;
+               }
+               i++;
+       }
+
+       if (best_option != -1)
+               log_err("Did you mean %s?\n", fio_options[best_option].name);
+
+       free(name);
+}
+
 int fio_options_parse(struct thread_data *td, char **opts, int num_opts,
                        int dump_cmdline)
 {
@@ -3918,6 +4001,7 @@ int fio_options_parse(struct thread_data *td, char **opts, int num_opts,
                for (i = 0; i < num_opts; i++) {
                        struct fio_option *o = NULL;
                        int newret = 1;
+
                        if (!opts_copy[i])
                                continue;
 
@@ -3927,9 +4011,10 @@ int fio_options_parse(struct thread_data *td, char **opts, int num_opts,
                                                      td->eo, dump_cmdline);
 
                        ret |= newret;
-                       if (!o)
+                       if (!o) {
                                log_err("Bad option <%s>\n", opts[i]);
-
+                               show_closest_option(opts[i]);
+                       }
                        free(opts_copy[i]);
                        opts_copy[i] = NULL;
                }