Basic support for dedupe
[fio.git] / options.c
index 9096a322bbc089db652662f8a1b04defd3f228b3..593f717149050fac1d5b206b53a27b7139e44af3 100644 (file)
--- a/options.c
+++ b/options.c
@@ -133,7 +133,7 @@ static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
                        perc += bsp->perc;
        }
 
-       if (perc > 100) {
+       if (perc > 100 && perc_missing > 1) {
                log_err("fio: bssplit percentages add to more than 100%%\n");
                free(bssplit);
                return 1;
@@ -143,6 +143,8 @@ static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
         * them.
         */
        if (perc_missing) {
+               if (perc_missing == 1)
+                       perc = 100;
                for (i = 0; i < o->bssplit_nr[ddir]; i++) {
                        struct bssplit *bsp = &bssplit[i];
 
@@ -269,7 +271,7 @@ static int ignore_error_type(struct thread_data *td, int etype, char *str)
                } else {
                        error[i] = atoi(fname);
                        if (error[i] < 0)
-                               error[i] = error[i];
+                               error[i] = -error[i];
                }
                if (!error[i]) {
                        log_err("Unknown error %s, please use number value \n",
@@ -554,6 +556,7 @@ static int str_verify_cpus_allowed_cb(void *data, const char *input)
 static int str_numa_cpunodes_cb(void *data, char *input)
 {
        struct thread_data *td = data;
+       struct bitmask *verify_bitmask;
 
        if (parse_dryrun())
                return 0;
@@ -563,13 +566,15 @@ static int str_numa_cpunodes_cb(void *data, char *input)
         * numa_allocate_nodemask(), so it should be freed by
         * numa_free_nodemask().
         */
-       td->o.numa_cpunodesmask = numa_parse_nodestring(input);
-       if (td->o.numa_cpunodesmask == NULL) {
+       verify_bitmask = numa_parse_nodestring(input);
+       if (verify_bitmask == NULL) {
                log_err("fio: numa_parse_nodestring failed\n");
                td_verror(td, 1, "str_numa_cpunodes_cb");
                return 1;
        }
+       numa_free_nodemask(verify_bitmask);
 
+       td->o.numa_cpunodes = strdup(input);
        td->o.numa_cpumask_set = 1;
        return 0;
 }
@@ -581,6 +586,7 @@ static int str_numa_mpol_cb(void *data, char *input)
                { "default", "prefer", "bind", "interleave", "local", NULL };
        int i;
        char *nodelist;
+       struct bitmask *verify_bitmask;
 
        if (parse_dryrun())
                return 0;
@@ -660,12 +666,15 @@ static int str_numa_mpol_cb(void *data, char *input)
                break;
        case MPOL_INTERLEAVE:
        case MPOL_BIND:
-               td->o.numa_memnodesmask = numa_parse_nodestring(nodelist);
-               if (td->o.numa_memnodesmask == NULL) {
+               verify_bitmask = numa_parse_nodestring(nodelist);
+               if (verify_bitmask == NULL) {
                        log_err("fio: numa_parse_nodestring failed\n");
                        td_verror(td, 1, "str_numa_memnodes_cb");
                        return 1;
                }
+               td->o.numa_memnodes = strdup(nodelist);
+               numa_free_nodemask(verify_bitmask);
+
                break;
        case MPOL_LOCAL:
        case MPOL_DEFAULT:
@@ -923,6 +932,29 @@ static int pattern_cb(char *pattern, unsigned int max_size,
        uint32_t pattern_length;
        char *loc1, *loc2;
 
+       /*
+        * Check if it's a string input
+        */
+       loc1 = strchr(input, '\"');
+       if (loc1) {
+               do {
+                       loc1++;
+                       if (*loc1 == '\0' || *loc1 == '\"')
+                               break;
+
+                       pattern[i] = *loc1;
+                       i++;
+               } while (i < max_size);
+
+               if (!i)
+                       return 1;
+
+               goto fill;
+       }
+
+       /*
+        * No string, find out if it's decimal or hexidecimal
+        */
        loc1 = strstr(input, "0x");
        loc2 = strstr(input, "0X");
        if (loc1 || loc2)
@@ -959,6 +991,7 @@ static int pattern_cb(char *pattern, unsigned int max_size,
         * 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.
         */
+fill:
        pattern_length = i;
        while (i > 1 && i * 2 <= max_size) {
                memcpy(&pattern[i], &pattern[0], i);
@@ -978,8 +1011,8 @@ static int pattern_cb(char *pattern, unsigned int max_size,
 
        if (i == 1) {
                /*
-                * The code in verify_io_u_pattern assumes a single byte pattern
-                * fills the whole verify pattern buffer.
+                * The code in verify_io_u_pattern assumes a single byte
+                * pattern fills the whole verify pattern buffer.
                 */
                memset(pattern, pattern[0], max_size);
        }
@@ -996,10 +1029,13 @@ static int str_buffer_pattern_cb(void *data, const char *input)
        ret = pattern_cb(td->o.buffer_pattern, MAX_PATTERN_SIZE, input,
                                &td->o.buffer_pattern_bytes);
 
-       if (!ret) {
+       if (!ret && td->o.buffer_pattern_bytes) {
                td->o.refill_buffers = 0;
                td->o.scramble_buffers = 0;
                td->o.zero_buffers = 0;
+       } else {
+               log_err("fio: failed parsing pattern `%s`\n", input);
+               ret = 1;
        }
 
        return ret;
@@ -1014,6 +1050,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;
@@ -1525,6 +1571,19 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                          { .ival = "falloc",
                            .help = "fallocate() file based engine",
                          },
+#endif
+#ifdef CONFIG_GFAPI
+                         { .ival = "gfapi",
+                           .help = "Glusterfs libgfapi(sync) based engine"
+                         },
+                         { .ival = "gfapi_async",
+                           .help = "Glusterfs libgfapi(async) based engine"
+                         },
+#endif
+#ifdef CONFIG_LIBHDFS
+                         { .ival = "libhdfs",
+                           .help = "Hadoop Distributed Filesystem (HDFS) engine"
+                         },
 #endif
                          { .ival = "external",
                            .help = "Load external engine (append name)",
@@ -1594,6 +1653,15 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_INVALID,
        },
+       {
+               .name   = "io_limit",
+               .lname  = "IO Limit",
+               .type   = FIO_OPT_STR_VAL,
+               .off1   = td_var_offset(io_limit),
+               .interval = 1024 * 1024,
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_INVALID,
+       },
        {
                .name   = "fill_device",
                .lname  = "Fill device",
@@ -2201,6 +2269,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                            .oval = MEM_MALLOC,
                            .help = "Use malloc(3) for IO buffers",
                          },
+#ifndef CONFIG_NO_SHM
                          { .ival = "shm",
                            .oval = MEM_SHM,
                            .help = "Use shared memory segments for IO buffers",
@@ -2210,6 +2279,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                            .oval = MEM_SHMHUGE,
                            .help = "Like shm, but use huge pages",
                          },
+#endif
 #endif
                          { .ival = "mmap",
                            .oval = MEM_MMAP,
@@ -3023,6 +3093,10 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .type   = FIO_OPT_STR_SET,
                .off1   = td_var_offset(use_thread),
                .help   = "Use threads instead of processes",
+#ifdef CONFIG_NO_SHM
+               .def    = "1",
+               .no_warn_def = 1,
+#endif
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_PROCESS,
        },
@@ -3063,6 +3137,38 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_LOG,
                .group  = FIO_OPT_G_INVALID,
        },
+       {
+               .name   = "log_offset",
+               .lname  = "Log offset of IO",
+               .type   = FIO_OPT_BOOL,
+               .off1   = td_var_offset(log_offset),
+               .help   = "Include offset of IO for each log entry",
+               .def    = "0",
+               .category = FIO_OPT_C_LOG,
+               .group  = FIO_OPT_G_INVALID,
+       },
+#ifdef CONFIG_ZLIB
+       {
+               .name   = "log_compression",
+               .lname  = "Log compression",
+               .type   = FIO_OPT_INT,
+               .off1   = td_var_offset(log_gz),
+               .help   = "Log in compressed chunks of this size",
+               .minval = 32 * 1024 * 1024ULL,
+               .maxval = 512 * 1024 * 1024ULL,
+               .category = FIO_OPT_C_LOG,
+               .group  = FIO_OPT_G_INVALID,
+       },
+       {
+               .name   = "log_store_compressed",
+               .lname  = "Log store compressed",
+               .type   = FIO_OPT_BOOL,
+               .off1   = td_var_offset(log_gz_store),
+               .help   = "Store logs in a compressed format",
+               .category = FIO_OPT_C_LOG,
+               .group  = FIO_OPT_G_INVALID,
+       },
+#endif
        {
                .name   = "bwavgtime",
                .lname  = "Bandwidth average time",
@@ -3160,6 +3266,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",