core: Don't leak memory if error is unknown
[fio.git] / options.c
index fcf427037f77f0ab456efc055b725a485fbe2512..1c44f426dcbde350f6bff5479e31aeee37b7702f 100644 (file)
--- a/options.c
+++ b/options.c
@@ -271,6 +271,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++;
@@ -376,6 +377,23 @@ static int str_rwmix_write_cb(void *data, unsigned long long *val)
        return 0;
 }
 
+static int str_perc_rand_cb(void *data, unsigned long long *val)
+{
+       struct thread_data *td = data;
+
+       td->o.perc_rand = *val;
+       return 0;
+}
+
+static int str_perc_seq_cb(void *data, unsigned long long *val)
+{
+       struct thread_data *td = data;
+
+       td->o.perc_rand = 100 - *val;
+       return 0;
+}
+
+
 static int str_exitall_cb(void)
 {
        exitall_on_terminate = 1;
@@ -533,7 +551,7 @@ 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 = strchr(input, ':');
@@ -805,7 +823,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");
@@ -844,10 +862,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
@@ -868,20 +899,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;
@@ -950,19 +967,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
  */
@@ -1161,11 +1165,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",
@@ -1290,6 +1303,11 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                          { .ival = "vsync",
                            .help = "Use readv/writev",
                          },
+#ifdef CONFIG_PWRITEV
+                         { .ival = "pvsync",
+                           .help = "Use preadv/pwritev",
+                         },
+#endif
 #ifdef CONFIG_LIBAIO
                          { .ival = "libaio",
                            .help = "Linux native asynchronous IO",
@@ -1647,6 +1665,32 @@ 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,
+               .cb     = str_perc_rand_cb,
+               .maxval = 100,
+               .help   = "Percentage of seq/random mix that should be random",
+               .def    = "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_INT,
+               .cb     = str_perc_seq_cb,
+               .maxval = 100,
+               .help   = "Percentage of seq/random mix that should be sequential",
+               .def    = "0",
+               .interval = 5,
+               .inverse = "percentage_random",
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_RANDOM,
+       },
        {
                .name   = "nrfiles",
                .lname  = "Number of files",
@@ -2358,7 +2402,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,
@@ -2635,12 +2679,16 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .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
        {
@@ -2731,7 +2779,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,
@@ -2777,10 +2825,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,
        },
@@ -3077,13 +3124,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",