Add new writetrim rw= mode for trims preceding writes
[fio.git] / options.c
index 2c703fdb85e622c79f8537d80bd2681d87f85d05..d7ce94bb75c7129cf5e4ff2bc663143ef537d63b 100644 (file)
--- a/options.c
+++ b/options.c
@@ -453,7 +453,6 @@ static int str_cpumask_cb(void *data, unsigned long long *val)
                }
        }
 
-       td->o.cpumask_set = 1;
        return 0;
 }
 
@@ -520,36 +519,24 @@ static int set_cpus_allowed(struct thread_data *td, os_cpu_mask_t *mask,
        }
 
        free(p);
-       if (!ret)
-               td->o.cpumask_set = 1;
        return ret;
 }
 
 static int str_cpus_allowed_cb(void *data, const char *input)
 {
        struct thread_data *td = data;
-       int ret;
 
        if (parse_dryrun())
                return 0;
 
-       ret = set_cpus_allowed(td, &td->o.cpumask, input);
-       if (!ret)
-               td->o.cpumask_set = 1;
-
-       return ret;
+       return set_cpus_allowed(td, &td->o.cpumask, input);
 }
 
 static int str_verify_cpus_allowed_cb(void *data, const char *input)
 {
        struct thread_data *td = data;
-       int ret;
-
-       ret = set_cpus_allowed(td, &td->o.verify_cpumask, input);
-       if (!ret)
-               td->o.verify_cpumask_set = 1;
 
-       return ret;
+       return set_cpus_allowed(td, &td->o.verify_cpumask, input);
 }
 #endif
 
@@ -576,7 +563,6 @@ static int str_numa_cpunodes_cb(void *data, char *input)
        numa_free_nodemask(verify_bitmask);
 
        td->o.numa_cpunodes = strdup(input);
-       td->o.numa_cpumask_set = 1;
        return 0;
 }
 
@@ -683,9 +669,7 @@ static int str_numa_mpol_cb(void *data, char *input)
                break;
        }
 
-       td->o.numa_memmask_set = 1;
        return 0;
-
 out:
        return 1;
 }
@@ -731,9 +715,11 @@ static int str_random_distribution_cb(void *data, const char *str)
                return 0;
 
        if (td->o.random_distribution == FIO_RAND_DIST_ZIPF)
-               val = 1.1;
+               val = FIO_DEF_ZIPF;
        else if (td->o.random_distribution == FIO_RAND_DIST_PARETO)
-               val = 0.2;
+               val = FIO_DEF_PARETO;
+       else if (td->o.random_distribution == FIO_RAND_DIST_GAUSS)
+               val = 0.0;
        else
                return 0;
 
@@ -752,12 +738,18 @@ static int str_random_distribution_cb(void *data, const char *str)
                        return 1;
                }
                td->o.zipf_theta.u.f = val;
-       } else {
+       } else if (td->o.random_distribution == FIO_RAND_DIST_PARETO) {
                if (val <= 0.00 || val >= 1.00) {
                        log_err("fio: pareto input out of range (0 < input < 1.0)\n");
                        return 1;
                }
                td->o.pareto_h.u.f = val;
+       } else {
+               if (val <= 0.00 || val >= 100.0) {
+                       log_err("fio: normal deviation out of range (0 < input < 100.0)\n");
+                       return 1;
+               }
+               td->o.gauss_dev.u.f = val;
        }
 
        return 0;
@@ -900,18 +892,6 @@ out:
        return ret;
 }
 
-static int str_lockfile_cb(void *data, const char fio_unused *str)
-{
-       struct thread_data *td = data;
-
-       if (td->files_index) {
-               log_err("fio: lockfile= option must precede filename=\n");
-               return 1;
-       }
-
-       return 0;
-}
-
 static int str_opendir_cb(void *data, const char fio_unused *str)
 {
        struct thread_data *td = data;
@@ -1095,16 +1075,6 @@ static int str_gtod_reduce_cb(void *data, int *il)
        return 0;
 }
 
-static int str_gtod_cpu_cb(void *data, long long *il)
-{
-       struct thread_data *td = data;
-       int val = *il;
-
-       td->o.gtod_cpu = val;
-       td->o.gtod_offload = 1;
-       return 0;
-}
-
 static int str_size_cb(void *data, unsigned long long *__val)
 {
        struct thread_data *td = data;
@@ -1369,7 +1339,6 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .parent = "filename",
                .hide   = 0,
                .def    = "none",
-               .cb     = str_lockfile_cb,
                .category = FIO_OPT_C_FILE,
                .group  = FIO_OPT_G_FILENAME,
                .posval = {
@@ -1447,6 +1416,10 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                            .oval = TD_DDIR_RANDRW,
                            .help = "Random read and write mix"
                          },
+                         { .ival = "writetrim",
+                           .oval = TD_DDIR_WRITETRIM,
+                           .help = "Write and trim mix, trims preceding writes"
+                         },
                },
        },
        {
@@ -1650,14 +1623,16 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "Size",
                .type   = FIO_OPT_STR_VAL,
                .cb     = str_size_cb,
+               .off1   = td_var_offset(size),
                .help   = "Total size of device or files",
                .interval = 1024 * 1024,
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_INVALID,
        },
        {
-               .name   = "io_limit",
-               .lname  = "IO Limit",
+               .name   = "io_size",
+               .alias  = "io_limit",
+               .lname  = "IO Size",
                .type   = FIO_OPT_STR_VAL,
                .off1   = td_var_offset(io_limit),
                .interval = 1024 * 1024,
@@ -1789,6 +1764,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "Block size split",
                .type   = FIO_OPT_STR,
                .cb     = str_bssplit_cb,
+               .off1   = td_var_offset(bssplit),
                .help   = "Set a specific mix of block sizes",
                .parent = "rw",
                .hide   = 1,
@@ -1911,6 +1887,10 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                            .oval = FIO_RAND_DIST_PARETO,
                            .help = "Pareto distribution",
                          },
+                         { .ival = "normal",
+                           .oval = FIO_RAND_DIST_GAUSS,
+                           .help = "Normal (gaussian) distribution",
+                         },
                },
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_RANDOM,
@@ -2041,6 +2021,17 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_FILE,
                .group  = FIO_OPT_G_INVALID,
        },
+#ifdef FIO_HAVE_STREAMID
+       {
+               .name   = "fadvise_stream",
+               .lname  = "Fadvise stream",
+               .type   = FIO_OPT_INT,
+               .off1   = td_var_offset(fadvise_stream),
+               .help   = "Use fadvise() to set stream ID",
+               .category = FIO_OPT_C_FILE,
+               .group  = FIO_OPT_G_INVALID,
+       },
+#endif
        {
                .name   = "fsync",
                .lname  = "Fsync",
@@ -2443,6 +2434,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "Verify pattern",
                .type   = FIO_OPT_STR,
                .cb     = str_verify_pattern_cb,
+               .off1   = td_var_offset(verify_pattern),
                .help   = "Fill pattern for IO buffers",
                .parent = "verify",
                .hide   = 1,
@@ -2513,6 +2505,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "Async verify CPUs",
                .type   = FIO_OPT_STR,
                .cb     = str_verify_cpus_allowed_cb,
+               .off1   = td_var_offset(verify_cpumask),
                .help   = "Set CPUs allowed for async verify threads",
                .parent = "verify_async",
                .hide   = 1,
@@ -2722,6 +2715,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "Read/write mix read",
                .type   = FIO_OPT_INT,
                .cb     = str_rwmix_read_cb,
+               .off1   = td_var_offset(rwmix[DDIR_READ]),
                .maxval = 100,
                .help   = "Percentage of mixed workload that is reads",
                .def    = "50",
@@ -2735,6 +2729,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "Read/write mix write",
                .type   = FIO_OPT_INT,
                .cb     = str_rwmix_write_cb,
+               .off1   = td_var_offset(rwmix[DDIR_WRITE]),
                .maxval = 100,
                .help   = "Percentage of mixed workload that is writes",
                .def    = "50",
@@ -3004,6 +2999,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "CPU mask",
                .type   = FIO_OPT_INT,
                .cb     = str_cpumask_cb,
+               .off1   = td_var_offset(cpumask),
                .help   = "CPU affinity mask",
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_CRED,
@@ -3013,6 +3009,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "CPUs allowed",
                .type   = FIO_OPT_STR,
                .cb     = str_cpus_allowed_cb,
+               .off1   = td_var_offset(cpumask),
                .help   = "Set CPUs allowed",
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_CRED,
@@ -3044,6 +3041,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .name   = "numa_cpu_nodes",
                .type   = FIO_OPT_STR,
                .cb     = str_numa_cpunodes_cb,
+               .off1   = td_var_offset(numa_cpunodes),
                .help   = "NUMA CPU nodes bind",
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_INVALID,
@@ -3052,6 +3050,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .name   = "numa_mem_policy",
                .type   = FIO_OPT_STR,
                .cb     = str_numa_mpol_cb,
+               .off1   = td_var_offset(numa_memnodes),
                .help   = "NUMA memory policy setup",
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_INVALID,
@@ -3266,6 +3265,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "Buffer pattern",
                .type   = FIO_OPT_STR,
                .cb     = str_buffer_pattern_cb,
+               .off1   = td_var_offset(buffer_pattern),
                .help   = "Fill pattern for IO buffers",
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_IO_BUF,
@@ -3275,6 +3275,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "Buffer compression percentage",
                .type   = FIO_OPT_INT,
                .cb     = str_buffer_compress_cb,
+               .off1   = td_var_offset(compress_percentage),
                .maxval = 100,
                .minval = 0,
                .help   = "How compressible the buffer is (approximately)",
@@ -3299,6 +3300,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "Dedupe percentage",
                .type   = FIO_OPT_INT,
                .cb     = str_dedupe_cb,
+               .off1   = td_var_offset(dedupe_percentage),
                .maxval = 100,
                .minval = 0,
                .help   = "Percentage of buffers that are dedupable",
@@ -3406,7 +3408,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .name   = "gtod_cpu",
                .lname  = "Dedicated gettimeofday() CPU",
                .type   = FIO_OPT_INT,
-               .cb     = str_gtod_cpu_cb,
+               .off1   = td_var_offset(gtod_cpu),
                .help   = "Set up dedicated gettimeofday() thread on this CPU",
                .verify = gtod_cpu_verify,
                .category = FIO_OPT_C_GENERAL,
@@ -3469,6 +3471,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .name   = "ignore_error",
                .type   = FIO_OPT_STR,
                .cb     = str_ignore_error_cb,
+               .off1   = td_var_offset(ignore_error_nr),
                .help   = "Set a specific list of errors to ignore",
                .parent = "rw",
                .category = FIO_OPT_C_GENERAL,
@@ -3980,6 +3983,9 @@ int fio_options_parse(struct thread_data *td, char **opts, int num_opts,
                int newret = parse_option(opts_copy[i], opts[i], fio_options,
                                                &o, td, dump_cmdline);
 
+               if (!newret && o)
+                       fio_option_mark_set(&td->o, o);
+
                if (opts_copy[i]) {
                        if (newret && !o) {
                                unknown++;
@@ -4026,7 +4032,18 @@ int fio_options_parse(struct thread_data *td, char **opts, int num_opts,
 
 int fio_cmd_option_parse(struct thread_data *td, const char *opt, char *val)
 {
-       return parse_cmd_option(opt, val, fio_options, td);
+       int ret;
+
+       ret = parse_cmd_option(opt, val, fio_options, td);
+       if (!ret) {
+               struct fio_option *o;
+
+               o = find_option(fio_options, opt);
+               if (o)
+                       fio_option_mark_set(&td->o, o);
+       }
+
+       return ret;
 }
 
 int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt,
@@ -4188,3 +4205,60 @@ struct fio_option *fio_option_find(const char *name)
        return find_option(fio_options, name);
 }
 
+static struct fio_option *find_next_opt(struct thread_options *o,
+                                       struct fio_option *from,
+                                       unsigned int off1)
+{
+       struct fio_option *opt;
+
+       if (!from)
+               from = &fio_options[0];
+       else
+               from++;
+
+       opt = NULL;
+       do {
+               if (off1 == from->off1) {
+                       opt = from;
+                       break;
+               }
+               from++;
+       } while (from->name);
+
+       return opt;
+}
+
+static int opt_is_set(struct thread_options *o, struct fio_option *opt)
+{
+       unsigned int opt_off, index, offset;
+
+       opt_off = opt - &fio_options[0];
+       index = opt_off / (8 * sizeof(uint64_t));
+       offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
+       return (o->set_options[index] & (1UL << offset)) != 0;
+}
+
+int __fio_option_is_set(struct thread_options *o, unsigned int off1)
+{
+       struct fio_option *opt, *next;
+
+       next = NULL;
+       while ((opt = find_next_opt(o, next, off1)) != NULL) {
+               if (opt_is_set(o, opt))
+                       return 1;
+
+               next = opt;
+       }
+
+       return 0;
+}
+
+void fio_option_mark_set(struct thread_options *o, struct fio_option *opt)
+{
+       unsigned int opt_off, index, offset;
+
+       opt_off = opt - &fio_options[0];
+       index = opt_off / (8 * sizeof(uint64_t));
+       offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
+       o->set_options[index] |= 1UL << offset;
+}