make ioengine specific command line options work
[fio.git] / options.c
index 917dbf0e3e9e41e8426e0639b910ec2094fd5a81..f26ff77647329a645f0fa4ead9eb9a58adcceba7 100644 (file)
--- a/options.c
+++ b/options.c
@@ -104,7 +104,7 @@ static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
 
                if (str_to_decimal(fname, &val, 1, o)) {
                        log_err("fio: bssplit conversion failed\n");
-                       free(o->bssplit);
+                       free(bssplit);
                        return 1;
                }
 
@@ -168,6 +168,9 @@ static int str_bssplit_cb(void *data, const char *input)
        char *str, *p, *odir, *ddir;
        int ret = 0;
 
+       if (parse_dryrun())
+               return 0;
+
        p = str = strdup(input);
 
        strip_blank_front(&str);
@@ -271,6 +274,7 @@ static int ignore_error_type(struct thread_data *td, int etype, char *str)
                if (!error[i]) {
                        log_err("Unknown error %s, please use number value \n",
                                  fname);
+                       free(error);
                        return 1;
                }
                i++;
@@ -289,6 +293,10 @@ static int str_ignore_error_cb(void *data, const char *input)
        struct thread_data *td = data;
        char *str, *p, *n;
        int type = 0, ret = 1;
+
+       if (parse_dryrun())
+               return 0;
+
        p = str = strdup(input);
 
        strip_blank_front(&str);
@@ -314,6 +322,9 @@ static int str_rw_cb(void *data, const char *str)
        struct thread_options *o = &td->o;
        char *nr = get_opt_postfix(str);
 
+       if (parse_dryrun())
+               return 0;
+
        o->ddir_seq_nr = 1;
        o->ddir_seq_add = 0;
 
@@ -341,15 +352,9 @@ static int str_rw_cb(void *data, const char *str)
 static int str_mem_cb(void *data, const char *mem)
 {
        struct thread_data *td = data;
-       struct thread_options *o = &td->o;
 
-       if (o->mem_type == MEM_MMAPHUGE || o->mem_type == MEM_MMAP) {
-               o->mmapfile = get_opt_postfix(mem);
-               if (o->mem_type == MEM_MMAPHUGE && !o->mmapfile) {
-                       log_err("fio: mmaphuge:/path/to/file\n");
-                       return 1;
-               }
-       }
+       if (td->o.mem_type == MEM_MMAPHUGE || td->o.mem_type == MEM_MMAP)
+               td->o.mmapfile = get_opt_postfix(mem);
 
        return 0;
 }
@@ -360,6 +365,7 @@ static int fio_clock_source_cb(void *data, const char *str)
 
        fio_clock_source = td->o.clocksource;
        fio_clock_source_set = 1;
+       fio_clock_init();
        return 0;
 }
 
@@ -395,6 +401,9 @@ static int str_cpumask_cb(void *data, unsigned long long *val)
        long max_cpu;
        int ret;
 
+       if (parse_dryrun())
+               return 0;
+
        ret = fio_cpuset_init(&td->o.cpumask);
        if (ret < 0) {
                log_err("fio: cpuset_init failed\n");
@@ -493,6 +502,9 @@ 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;
@@ -513,11 +525,14 @@ static int str_verify_cpus_allowed_cb(void *data, const char *input)
 }
 #endif
 
-#ifdef FIO_HAVE_LIBNUMA
+#ifdef CONFIG_LIBNUMA
 static int str_numa_cpunodes_cb(void *data, char *input)
 {
        struct thread_data *td = data;
 
+       if (parse_dryrun())
+               return 0;
+
        /* numa_parse_nodestring() parses a character string list
         * of nodes into a bit mask. The bit mask is allocated by
         * numa_allocate_nodemask(), so it should be freed by
@@ -538,10 +553,14 @@ static int str_numa_mpol_cb(void *data, char *input)
 {
        struct thread_data *td = data;
        const char * const policy_types[] =
-               { "default", "prefer", "bind", "interleave", "local" };
+               { "default", "prefer", "bind", "interleave", "local", NULL };
        int i;
+       char *nodelist;
 
-       char *nodelist = strchr(input, ':');
+       if (parse_dryrun())
+               return 0;
+
+       nodelist = strchr(input, ':');
        if (nodelist) {
                /* NUL-terminate mode */
                *nodelist++ = '\0';
@@ -651,7 +670,7 @@ static int str_fst_cb(void *data, const char *str)
        return 0;
 }
 
-#ifdef FIO_HAVE_SYNC_FILE_RANGE
+#ifdef CONFIG_SYNC_FILE_RANGE
 static int str_sfr_cb(void *data, const char *str)
 {
        struct thread_data *td = data;
@@ -673,6 +692,9 @@ static int str_random_distribution_cb(void *data, const char *str)
        double val;
        char *nr;
 
+       if (parse_dryrun())
+               return 0;
+
        if (td->o.random_distribution == FIO_RAND_DIST_ZIPF)
                val = 1.1;
        else if (td->o.random_distribution == FIO_RAND_DIST_PARETO)
@@ -781,6 +803,9 @@ static int str_directory_cb(void *data, const char fio_unused *str)
        struct thread_data *td = data;
        struct stat sb;
 
+       if (parse_dryrun())
+               return 0;
+
        if (lstat(td->o.directory, &sb) < 0) {
                int ret = errno;
 
@@ -800,6 +825,9 @@ static int str_opendir_cb(void *data, const char fio_unused *str)
 {
        struct thread_data *td = data;
 
+       if (parse_dryrun())
+               return 0;
+
        if (!td->files_index)
                td->o.nr_files = 0;
 
@@ -810,7 +838,7 @@ static int str_verify_pattern_cb(void *data, const char *input)
 {
        struct thread_data *td = data;
        long off;
-       int i = 0, j = 0, len, k, base = 10;
+       int i = 0, j = 0, len, k, base = 10, pattern_length;
        char *loc1, *loc2;
 
        loc1 = strstr(input, "0x");
@@ -849,10 +877,23 @@ static int str_verify_pattern_cb(void *data, const char *input)
         * Fill the pattern all the way to the end. This greatly reduces
         * the number of memcpy's we have to do when verifying the IO.
         */
+       pattern_length = i;
        while (i > 1 && i * 2 <= MAX_PATTERN_SIZE) {
                memcpy(&td->o.verify_pattern[i], &td->o.verify_pattern[0], i);
                i *= 2;
        }
+
+       /*
+        * Fill remainder, if the pattern multiple ends up not being
+        * MAX_PATTERN_SIZE.
+        */
+       while (i > 1 && i < MAX_PATTERN_SIZE) {
+               unsigned int b = min(pattern_length, MAX_PATTERN_SIZE - i);
+
+               memcpy(&td->o.verify_pattern[i], &td->o.verify_pattern[0], b);
+               i += b;
+       }
+
        if (i == 1) {
                /*
                 * The code in verify_io_u_pattern assumes a single byte pattern
@@ -873,20 +914,6 @@ static int str_verify_pattern_cb(void *data, const char *input)
        return 0;
 }
 
-static int str_lockfile_cb(void *data, const char *str)
-{
-       struct thread_data *td = data;
-       char *nr = get_opt_postfix(str);
-
-       td->o.lockfile_batch = 1;
-       if (nr) {
-               td->o.lockfile_batch = atoi(nr);
-               free(nr);
-       }
-
-       return 0;
-}
-
 static int str_gtod_reduce_cb(void *data, int *il)
 {
        struct thread_data *td = data;
@@ -955,19 +982,6 @@ static int gtod_cpu_verify(struct fio_option *o, void *data)
        return 0;
 }
 
-static int kb_base_verify(struct fio_option *o, void *data)
-{
-       struct thread_data *td = data;
-
-       if (td->o.kb_base != 1024 && td->o.kb_base != 1000) {
-               log_err("fio: kb_base set to nonsensical value: %u\n",
-                               td->o.kb_base);
-               return 1;
-       }
-
-       return 0;
-}
-
 /*
  * Option grouping
  */
@@ -1166,11 +1180,20 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_FILE,
                .group  = FIO_OPT_G_FILENAME,
        },
+       {
+               .name   = "filename_format",
+               .type   = FIO_OPT_STR_STORE,
+               .off1   = td_var_offset(filename_format),
+               .prio   = -1, /* must come after "directory" */
+               .help   = "Override default $jobname.$jobnum.$filenum naming",
+               .def    = "$jobname.$jobnum.$filenum",
+               .category = FIO_OPT_C_FILE,
+               .group  = FIO_OPT_G_FILENAME,
+       },
        {
                .name   = "lockfile",
                .lname  = "Lockfile",
                .type   = FIO_OPT_STR,
-               .cb     = str_lockfile_cb,
                .off1   = td_var_offset(file_lock_mode),
                .help   = "Lock file when doing IO to it",
                .parent = "filename",
@@ -1295,22 +1318,27 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                          { .ival = "vsync",
                            .help = "Use readv/writev",
                          },
-#ifdef FIO_HAVE_LIBAIO
+#ifdef CONFIG_PWRITEV
+                         { .ival = "pvsync",
+                           .help = "Use preadv/pwritev",
+                         },
+#endif
+#ifdef CONFIG_LIBAIO
                          { .ival = "libaio",
                            .help = "Linux native asynchronous IO",
                          },
 #endif
-#ifdef FIO_HAVE_POSIXAIO
+#ifdef CONFIG_POSIXAIO
                          { .ival = "posixaio",
                            .help = "POSIX asynchronous IO",
                          },
 #endif
-#ifdef FIO_HAVE_SOLARISAIO
+#ifdef CONFIG_SOLARISAIO
                          { .ival = "solarisaio",
                            .help = "Solaris native asynchronous IO",
                          },
 #endif
-#ifdef FIO_HAVE_WINDOWSAIO
+#ifdef CONFIG_WINDOWSAIO
                          { .ival = "windowsaio",
                            .help = "Windows native asynchronous IO"
                          },
@@ -1318,7 +1346,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                          { .ival = "mmap",
                            .help = "Memory mapped IO"
                          },
-#ifdef FIO_HAVE_SPLICE
+#ifdef CONFIG_LINUX_SPLICE
                          { .ival = "splice",
                            .help = "splice/vmsplice based IO",
                          },
@@ -1337,15 +1365,10 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                          { .ival = "net",
                            .help = "Network IO",
                          },
-#ifdef FIO_HAVE_SYSLET
-                         { .ival = "syslet-rw",
-                           .help = "syslet enabled async pread/pwrite IO",
-                         },
-#endif
                          { .ival = "cpuio",
                            .help = "CPU cycle burner engine",
                          },
-#ifdef FIO_HAVE_GUASI
+#ifdef CONFIG_GUASI
                          { .ival = "guasi",
                            .help = "GUASI IO engine",
                          },
@@ -1355,22 +1378,22 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                            .help = "binject direct inject block engine",
                          },
 #endif
-#ifdef FIO_HAVE_RDMA
+#ifdef CONFIG_RDMA
                          { .ival = "rdma",
                            .help = "RDMA IO engine",
                          },
 #endif
-#ifdef FIO_HAVE_FUSION_AW
+#ifdef CONFIG_FUSION_AW
                          { .ival = "fusion-aw-sync",
                            .help = "Fusion-io atomic write engine",
                          },
 #endif
-#ifdef FIO_HAVE_E4_ENG
+#ifdef CONFIG_LINUX_EXT4_MOVE_EXTENT
                          { .ival = "e4defrag",
                            .help = "ext4 defrag engine",
                          },
 #endif
-#ifdef FIO_HAVE_FALLOC_ENG
+#ifdef CONFIG_LINUX_FALLOCATE
                          { .ival = "falloc",
                            .help = "fallocate() file based engine",
                          },
@@ -1491,6 +1514,16 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_INVALID,
        },
+       {
+               .name   = "number_ios",
+               .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",
+               .def    = "0",
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_INVALID,
+       },
        {
                .name   = "bs",
                .lname  = "Block size",
@@ -1566,6 +1599,17 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_INVALID,
        },
+       {
+               .name   = "bs_is_seq_rand",
+               .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",
+               .def    = "0",
+               .parent = "blocksize",
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_INVALID,
+       },
        {
                .name   = "randrepeat",
                .lname  = "Random repeatable",
@@ -1657,6 +1701,28 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_RANDOM,
        },
+       {
+               .name   = "percentage_random",
+               .lname  = "Percentage Random",
+               .type   = FIO_OPT_INT,
+               .off1   = td_var_offset(perc_rand[DDIR_READ]),
+               .off2   = td_var_offset(perc_rand[DDIR_WRITE]),
+               .off3   = td_var_offset(perc_rand[DDIR_TRIM]),
+               .maxval = 100,
+               .help   = "Percentage of seq/random mix that should be random",
+               .def    = "100,100,100",
+               .interval = 5,
+               .inverse = "percentage_sequential",
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_RANDOM,
+       },
+       {
+               .name   = "percentage_sequential",
+               .lname  = "Percentage Sequential",
+               .type   = FIO_OPT_DEPRECATED,
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_RANDOM,
+       },
        {
                .name   = "nrfiles",
                .lname  = "Number of files",
@@ -1705,7 +1771,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .parent = "nrfiles",
                .hide   = 1,
        },
-#ifdef FIO_HAVE_FALLOCATE
+#ifdef CONFIG_POSIX_FALLOCATE
        {
                .name   = "fallocate",
                .lname  = "Fallocate",
@@ -1724,7 +1790,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                            .oval = FIO_FALLOCATE_POSIX,
                            .help = "Use posix_fallocate()",
                          },
-#ifdef FIO_HAVE_LINUX_FALLOCATE
+#ifdef CONFIG_LINUX_FALLOCATE
                          { .ival = "keep",
                            .oval = FIO_FALLOCATE_KEEP_SIZE,
                            .help = "Use fallocate(..., FALLOC_FL_KEEP_SIZE, ...)",
@@ -1741,7 +1807,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                          },
                },
        },
-#endif /* FIO_HAVE_FALLOCATE */
+#endif /* CONFIG_POSIX_FALLOCATE */
        {
                .name   = "fadvise_hint",
                .lname  = "Fadvise hint",
@@ -1785,7 +1851,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_INVALID,
        },
-#ifdef FIO_HAVE_SYNC_FILE_RANGE
+#ifdef CONFIG_SYNC_FILE_RANGE
        {
                .name   = "sync_file_range",
                .lname  = "Sync file range",
@@ -1919,14 +1985,18 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_CLOCK,
                .posval = {
+#ifdef CONFIG_GETTIMEOFDAY
                          { .ival = "gettimeofday",
                            .oval = CS_GTOD,
                            .help = "Use gettimeofday(2) for timing",
                          },
+#endif
+#ifdef CONFIG_CLOCK_GETTIME
                          { .ival = "clock_gettime",
                            .oval = CS_CGETTIME,
                            .help = "Use clock_gettime(2) for timing",
                          },
+#endif
 #ifdef ARCH_HAVE_CPU_CLOCK
                          { .ival = "cpu",
                            .oval = CS_CPUCLOCK,
@@ -2076,6 +2146,18 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_VERIFY,
        },
+       {
+               .name   = "verifysort_nr",
+               .type   = FIO_OPT_INT,
+               .off1   = td_var_offset(verifysort_nr),
+               .help   = "Pre-load and sort verify blocks for a read workload",
+               .minval = 0,
+               .maxval = 131072,
+               .def    = "1024",
+               .parent = "verify",
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_VERIFY,
+       },
        {
                .name   = "verify_interval",
                .lname  = "Verify interval",
@@ -2183,6 +2265,14 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .group  = FIO_OPT_G_VERIFY,
        },
 #endif
+       {
+               .name   = "experimental_verify",
+               .off1   = td_var_offset(experimental_verify),
+               .type   = FIO_OPT_BOOL,
+               .help   = "Enable experimental verification",
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_VERIFY,
+       },
 #ifdef FIO_HAVE_TRIM
        {
                .name   = "trim_percentage",
@@ -2344,7 +2434,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "Lock memory",
                .type   = FIO_OPT_STR_VAL,
                .off1   = td_var_offset(lockmem),
-               .help   = "Lock down this amount of memory",
+               .help   = "Lock down this amount of memory (per worker)",
                .def    = "0",
                .interval = 1024 * 1024,
                .category = FIO_OPT_C_GENERAL,
@@ -2615,18 +2705,22 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .group  = FIO_OPT_G_CRED,
        },
 #endif
-#ifdef FIO_HAVE_LIBNUMA
+#ifdef CONFIG_LIBNUMA
        {
                .name   = "numa_cpu_nodes",
                .type   = FIO_OPT_STR,
                .cb     = str_numa_cpunodes_cb,
                .help   = "NUMA CPU nodes bind",
+               .category = FIO_OPT_C_GENERAL,
+               .group  = FIO_OPT_G_INVALID,
        },
        {
                .name   = "numa_mem_policy",
                .type   = FIO_OPT_STR,
                .cb     = str_numa_mpol_cb,
                .help   = "NUMA memory policy setup",
+               .category = FIO_OPT_C_GENERAL,
+               .group  = FIO_OPT_G_INVALID,
        },
 #endif
        {
@@ -2717,7 +2811,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
        {
                .name   = "write_iops_log",
                .lname  = "Write IOPS log",
-               .type   = FIO_OPT_STR,
+               .type   = FIO_OPT_STR_STORE,
                .off1   = td_var_offset(iops_log_file),
                .help   = "Write log of IOPS during run",
                .category = FIO_OPT_C_LOG,
@@ -2763,10 +2857,9 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
        {
                .name   = "group_reporting",
                .lname  = "Group reporting",
-               .type   = FIO_OPT_BOOL,
+               .type   = FIO_OPT_STR_SET,
                .off1   = td_var_offset(group_reporting),
                .help   = "Do reporting on a per-group basis",
-               .def    = "1",
                .category = FIO_OPT_C_STAT,
                .group  = FIO_OPT_G_INVALID,
        },
@@ -2837,8 +2930,9 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "Completion latency percentile list",
                .type   = FIO_OPT_FLOAT_LIST,
                .off1   = td_var_offset(percentile_list),
-               .off2   = td_var_offset(overwrite_plist),
+               .off2   = td_var_offset(percentile_precision),
                .help   = "Specify a custom list of percentiles to report",
+               .def    = "1:5:10:20:30:40:50:60:70:80:90:95:99:99.5:99.9:99.95:99.99",
                .maxlen = FIO_IO_U_LIST_MAX_LEN,
                .minfp  = 0.0,
                .maxfp  = 100.0,
@@ -2927,6 +3021,15 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_CLOCK,
        },
+       {
+               .name   = "unified_rw_reporting",
+               .type   = FIO_OPT_BOOL,
+               .off1   = td_var_offset(unified_rw_rep),
+               .help   = "Unify reporting across data direction",
+               .def    = "0",
+               .category = FIO_OPT_C_GENERAL,
+               .group  = FIO_OPT_G_INVALID,
+       },
        {
                .name   = "continue_on_error",
                .lname  = "Continue on error",
@@ -3053,13 +3156,46 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "KB Base",
                .type   = FIO_OPT_INT,
                .off1   = td_var_offset(kb_base),
-               .verify = kb_base_verify,
                .prio   = 1,
                .def    = "1024",
+               .posval = {
+                         { .ival = "1024",
+                           .oval = 1024,
+                           .help = "Use 1024 as the K base",
+                         },
+                         { .ival = "1000",
+                           .oval = 1000,
+                           .help = "Use 1000 as the K base",
+                         },
+               },
                .help   = "How many bytes per KB for reporting (1000 or 1024)",
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_INVALID,
        },
+       {
+               .name   = "unit_base",
+               .lname  = "Base unit for reporting (Bits or Bytes)",
+               .type   = FIO_OPT_INT,
+               .off1   = td_var_offset(unit_base),
+               .prio   = 1,
+               .posval = {
+                         { .ival = "0",
+                           .oval = 0,
+                           .help = "Auto-detect",
+                         },
+                         { .ival = "8",
+                           .oval = 8,
+                           .help = "Normal (byte based)",
+                         },
+                         { .ival = "1",
+                           .oval = 1,
+                           .help = "Bit based",
+                         },
+               },
+               .help   = "Bit multiple of result summary data (8 for byte, 1 for bit)",
+               .category = FIO_OPT_C_GENERAL,
+               .group  = FIO_OPT_G_INVALID,
+       },
        {
                .name   = "hugepage-size",
                .lname  = "Hugepage size",
@@ -3467,7 +3603,7 @@ int fio_cmd_option_parse(struct thread_data *td, const char *opt, char *val)
 int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt,
                                char *val)
 {
-       return parse_cmd_option(opt, val, td->io_ops->options, td);
+       return parse_cmd_option(opt, val, td->io_ops->options, td->eo);
 }
 
 void fio_fill_default_options(struct thread_data *td)