Get rid of __ prefix for internal frand state
[fio.git] / init.c
diff --git a/init.c b/init.c
index 8268ed59e99668216fdee94a1a921ef0ae319bce..c2c126b55ff2bd2187baebe5e7a04b1977519369 100644 (file)
--- a/init.c
+++ b/init.c
@@ -216,6 +216,11 @@ static struct option l_opts[FIO_NR_OPTIONS] = {
                .has_arg        = required_argument,
                .val            = 'C',
        },
+       {
+               .name           = (char *) "remote-config",
+               .has_arg        = required_argument,
+               .val            = 'R',
+       },
        {
                .name           = (char *) "cpuclock-test",
                .has_arg        = no_argument,
@@ -380,6 +385,7 @@ static struct thread_data *get_new_job(int global, struct thread_data *parent,
        profile_add_hooks(td);
 
        td->thread_number = thread_number;
+       td->subjob_number = 0;
 
        if (jobname)
                td->o.name = strdup(jobname);
@@ -464,13 +470,8 @@ static unsigned long long get_rand_start_delay(struct thread_data *td)
 
        delayrange = td->o.start_delay_high - td->o.start_delay;
 
-       if (td->o.use_os_rand) {
-               r = os_random_long(&td->delay_state);
-               delayrange = (unsigned long long) ((double) delayrange * (r / (OS_RAND_MAX + 1.0)));
-       } else {
-               r = __rand(&td->__delay_state);
-               delayrange = (unsigned long long) ((double) delayrange * (r / (FRAND_MAX + 1.0)));
-       }
+       r = __rand(&td->delay_state);
+       delayrange = (unsigned long long) ((double) delayrange * (r / (FRAND_MAX + 1.0)));
 
        delayrange += td->o.start_delay;
        return delayrange;
@@ -635,6 +636,15 @@ static int fixup_options(struct thread_data *td)
                if (o->max_bs[DDIR_WRITE] != o->min_bs[DDIR_WRITE] &&
                    !o->verify_interval)
                        o->verify_interval = o->min_bs[DDIR_WRITE];
+
+               /*
+                * Verify interval must be smaller or equal to the
+                * write size.
+                */
+               if (o->verify_interval > o->min_bs[DDIR_WRITE])
+                       o->verify_interval = o->min_bs[DDIR_WRITE];
+               else if (td_read(td) && o->verify_interval > o->min_bs[DDIR_READ])
+                       o->verify_interval = o->min_bs[DDIR_READ];
        }
 
        if (o->pre_read) {
@@ -772,44 +782,18 @@ static int exists_and_not_file(const char *filename)
        return 1;
 }
 
-static void td_fill_rand_seeds_os(struct thread_data *td)
-{
-       os_random_seed(td->rand_seeds[FIO_RAND_BS_OFF], &td->bsrange_state);
-       os_random_seed(td->rand_seeds[FIO_RAND_VER_OFF], &td->verify_state);
-       os_random_seed(td->rand_seeds[FIO_RAND_MIX_OFF], &td->rwmix_state);
-
-       if (td->o.file_service_type == FIO_FSERVICE_RANDOM)
-               os_random_seed(td->rand_seeds[FIO_RAND_FILE_OFF], &td->next_file_state);
-
-       os_random_seed(td->rand_seeds[FIO_RAND_FILE_SIZE_OFF], &td->file_size_state);
-       os_random_seed(td->rand_seeds[FIO_RAND_TRIM_OFF], &td->trim_state);
-       os_random_seed(td->rand_seeds[FIO_RAND_START_DELAY], &td->delay_state);
-
-       if (!td_random(td))
-               return;
-
-       if (td->o.rand_repeatable)
-               td->rand_seeds[FIO_RAND_BLOCK_OFF] = FIO_RANDSEED * td->thread_number;
-
-       os_random_seed(td->rand_seeds[FIO_RAND_BLOCK_OFF], &td->random_state);
-
-       os_random_seed(td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF], &td->seq_rand_state[DDIR_READ]);
-       os_random_seed(td->rand_seeds[FIO_RAND_SEQ_RAND_WRITE_OFF], &td->seq_rand_state[DDIR_WRITE]);
-       os_random_seed(td->rand_seeds[FIO_RAND_SEQ_RAND_TRIM_OFF], &td->seq_rand_state[DDIR_TRIM]);
-}
-
 static void td_fill_rand_seeds_internal(struct thread_data *td)
 {
-       init_rand_seed(&td->__bsrange_state, td->rand_seeds[FIO_RAND_BS_OFF]);
-       init_rand_seed(&td->__verify_state, td->rand_seeds[FIO_RAND_VER_OFF]);
-       init_rand_seed(&td->__rwmix_state, td->rand_seeds[FIO_RAND_MIX_OFF]);
+       init_rand_seed(&td->bsrange_state, td->rand_seeds[FIO_RAND_BS_OFF]);
+       init_rand_seed(&td->verify_state, td->rand_seeds[FIO_RAND_VER_OFF]);
+       init_rand_seed(&td->rwmix_state, td->rand_seeds[FIO_RAND_MIX_OFF]);
 
        if (td->o.file_service_type == FIO_FSERVICE_RANDOM)
-               init_rand_seed(&td->__next_file_state, td->rand_seeds[FIO_RAND_FILE_OFF]);
+               init_rand_seed(&td->next_file_state, td->rand_seeds[FIO_RAND_FILE_OFF]);
 
-       init_rand_seed(&td->__file_size_state, td->rand_seeds[FIO_RAND_FILE_SIZE_OFF]);
-       init_rand_seed(&td->__trim_state, td->rand_seeds[FIO_RAND_TRIM_OFF]);
-       init_rand_seed(&td->__delay_state, td->rand_seeds[FIO_RAND_START_DELAY]);
+       init_rand_seed(&td->file_size_state, td->rand_seeds[FIO_RAND_FILE_SIZE_OFF]);
+       init_rand_seed(&td->trim_state, td->rand_seeds[FIO_RAND_TRIM_OFF]);
+       init_rand_seed(&td->delay_state, td->rand_seeds[FIO_RAND_START_DELAY]);
 
        if (!td_random(td))
                return;
@@ -817,26 +801,28 @@ static void td_fill_rand_seeds_internal(struct thread_data *td)
        if (td->o.rand_repeatable)
                td->rand_seeds[FIO_RAND_BLOCK_OFF] = FIO_RANDSEED * td->thread_number;
 
-       init_rand_seed(&td->__random_state, td->rand_seeds[FIO_RAND_BLOCK_OFF]);
-       init_rand_seed(&td->__seq_rand_state[DDIR_READ], td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF]);
-       init_rand_seed(&td->__seq_rand_state[DDIR_WRITE], td->rand_seeds[FIO_RAND_SEQ_RAND_WRITE_OFF]);
-       init_rand_seed(&td->__seq_rand_state[DDIR_TRIM], td->rand_seeds[FIO_RAND_SEQ_RAND_TRIM_OFF]);
+       init_rand_seed(&td->random_state, td->rand_seeds[FIO_RAND_BLOCK_OFF]);
+       init_rand_seed(&td->seq_rand_state[DDIR_READ], td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF]);
+       init_rand_seed(&td->seq_rand_state[DDIR_WRITE], td->rand_seeds[FIO_RAND_SEQ_RAND_WRITE_OFF]);
+       init_rand_seed(&td->seq_rand_state[DDIR_TRIM], td->rand_seeds[FIO_RAND_SEQ_RAND_TRIM_OFF]);
 }
 
 void td_fill_rand_seeds(struct thread_data *td)
 {
        if (td->o.allrand_repeatable) {
-               for (int i = 0; i < FIO_RAND_NR_OFFS; i++)
+               unsigned int i;
+
+               for (i = 0; i < FIO_RAND_NR_OFFS; i++)
                        td->rand_seeds[i] = FIO_RANDSEED * td->thread_number
                                + i;
        }
 
-       if (td->o.use_os_rand)
-               td_fill_rand_seeds_os(td);
-       else
-               td_fill_rand_seeds_internal(td);
+       td_fill_rand_seeds_internal(td);
 
        init_rand_seed(&td->buf_state, td->rand_seeds[FIO_RAND_BUF_OFF]);
+       frand_copy(&td->buf_state_prev, &td->buf_state);
+
+       init_rand_seed(&td->dedupe_state, td->rand_seeds[FIO_DEDUPE_OFF]);
 }
 
 /*
@@ -1167,14 +1153,14 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                else
                        suf = "log";
 
-               snprintf(logname, sizeof(logname), "%s_lat.%s",
-                               o->lat_log_file, suf);
+               snprintf(logname, sizeof(logname), "%s_lat.%d.%s",
+                               o->lat_log_file, td->thread_number, suf);
                setup_log(&td->lat_log, &p, logname);
-               snprintf(logname, sizeof(logname), "%s_slat.%s",
-                               o->lat_log_file, suf);
+               snprintf(logname, sizeof(logname), "%s_slat.%d.%s",
+                               o->lat_log_file, td->thread_number, suf);
                setup_log(&td->slat_log, &p, logname);
-               snprintf(logname, sizeof(logname), "%s_clat.%s",
-                               o->lat_log_file, suf);
+               snprintf(logname, sizeof(logname), "%s_clat.%d.%s",
+                               o->lat_log_file, td->thread_number, suf);
                setup_log(&td->clat_log, &p, logname);
        }
        if (o->bw_log_file) {
@@ -1193,8 +1179,8 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                else
                        suf = "log";
 
-               snprintf(logname, sizeof(logname), "%s_bw.%s",
-                               o->bw_log_file, suf);
+               snprintf(logname, sizeof(logname), "%s_bw.%d.%s",
+                               o->bw_log_file, td->thread_number, suf);
                setup_log(&td->bw_log, &p, logname);
        }
        if (o->iops_log_file) {
@@ -1213,8 +1199,8 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                else
                        suf = "log";
 
-               snprintf(logname, sizeof(logname), "%s_iops.%s",
-                               o->iops_log_file, suf);
+               snprintf(logname, sizeof(logname), "%s_iops.%d.%s",
+                               o->iops_log_file, td->thread_number, suf);
                setup_log(&td->iops_log, &p, logname);
        }
 
@@ -1279,6 +1265,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                td_new->o.numjobs = 1;
                td_new->o.stonewall = 0;
                td_new->o.new_group = 0;
+               td_new->subjob_number = numjobs;
 
                if (file_alloced) {
                        if (td_new->files) {
@@ -1381,11 +1368,12 @@ static int is_empty_or_comment(char *line)
 /*
  * This is our [ini] type file parser.
  */
-int parse_jobs_ini(char *file, int is_buf, int stonewall_flag, int type)
+int __parse_jobs_ini(struct thread_data *td,
+               char *file, int is_buf, int stonewall_flag, int type,
+               int nested, char *name, char ***popts, int *aopts, int *nopts)
 {
-       unsigned int global;
-       struct thread_data *td;
-       char *string, *name;
+       unsigned int global = 0;
+       char *string;
        FILE *f;
        char *p;
        int ret = 0, stonewall;
@@ -1395,6 +1383,9 @@ int parse_jobs_ini(char *file, int is_buf, int stonewall_flag, int type)
        char **opts;
        int i, alloc_opts, num_opts;
 
+       dprint(FD_PARSE, "Parsing ini file %s\n", file);
+       assert(td || !nested);
+
        if (is_buf)
                f = NULL;
        else {
@@ -1404,7 +1395,11 @@ int parse_jobs_ini(char *file, int is_buf, int stonewall_flag, int type)
                        f = fopen(file, "r");
 
                if (!f) {
-                       perror("fopen job file");
+                       int __err = errno;
+
+                       log_err("fio: unable to open '%s' job file\n", file);
+                       if (td)
+                               td_verror(td, __err, "job file open");
                        return 1;
                }
        }
@@ -1414,12 +1409,23 @@ int parse_jobs_ini(char *file, int is_buf, int stonewall_flag, int type)
        /*
         * it's really 256 + small bit, 280 should suffice
         */
-       name = malloc(280);
-       memset(name, 0, 280);
+       if (!nested) {
+               name = malloc(280);
+               memset(name, 0, 280);
+       }
+
+       opts = NULL;
+       if (nested && popts) {
+               opts = *popts;
+               alloc_opts = *aopts;
+               num_opts = *nopts;
+       }
 
-       alloc_opts = 8;
-       opts = malloc(sizeof(char *) * alloc_opts);
-       num_opts = 0;
+       if (!opts) {
+               alloc_opts = 8;
+               opts = malloc(sizeof(char *) * alloc_opts);
+               num_opts = 0;
+       }
 
        stonewall = stonewall_flag;
        do {
@@ -1440,58 +1446,73 @@ int parse_jobs_ini(char *file, int is_buf, int stonewall_flag, int type)
                strip_blank_front(&p);
                strip_blank_end(p);
 
+               dprint(FD_PARSE, "%s\n", p);
                if (is_empty_or_comment(p))
                        continue;
-               if (sscanf(p, "[%255[^\n]]", name) != 1) {
-                       if (inside_skip)
+
+               if (!nested) {
+                       if (sscanf(p, "[%255[^\n]]", name) != 1) {
+                               if (inside_skip)
+                                       continue;
+
+                               log_err("fio: option <%s> outside of "
+                                       "[] job section\n", p);
+                               ret = 1;
+                               break;
+                       }
+
+                       name[strlen(name) - 1] = '\0';
+
+                       if (skip_this_section(name)) {
+                               inside_skip = 1;
                                continue;
-                       log_err("fio: option <%s> outside of [] job section\n",
-                                                                       p);
-                       break;
-               }
+                       } else
+                               inside_skip = 0;
 
-               name[strlen(name) - 1] = '\0';
+                       dprint(FD_PARSE, "Parsing section [%s]\n", name);
 
-               if (skip_this_section(name)) {
-                       inside_skip = 1;
-                       continue;
-               } else
-                       inside_skip = 0;
+                       global = !strncmp(name, "global", 6);
 
-               global = !strncmp(name, "global", 6);
+                       if (dump_cmdline) {
+                               if (first_sect)
+                                       log_info("fio ");
+                               if (!global)
+                                       log_info("--name=%s ", name);
+                               first_sect = 0;
+                       }
 
-               if (dump_cmdline) {
-                       if (first_sect)
-                               log_info("fio ");
-                       if (!global)
-                               log_info("--name=%s ", name);
-                       first_sect = 0;
-               }
+                       td = get_new_job(global, &def_thread, 0, name);
+                       if (!td) {
+                               ret = 1;
+                               break;
+                       }
 
-               td = get_new_job(global, &def_thread, 0, name);
-               if (!td) {
-                       ret = 1;
-                       break;
-               }
+                       /*
+                        * Separate multiple job files by a stonewall
+                        */
+                       if (!global && stonewall) {
+                               td->o.stonewall = stonewall;
+                               stonewall = 0;
+                       }
 
-               /*
-                * Separate multiple job files by a stonewall
-                */
-               if (!global && stonewall) {
-                       td->o.stonewall = stonewall;
-                       stonewall = 0;
+                       num_opts = 0;
+                       memset(opts, 0, alloc_opts * sizeof(char *));
                }
-
-               num_opts = 0;
-               memset(opts, 0, alloc_opts * sizeof(char *));
+               else
+                       skip_fgets = 1;
 
                while (1) {
-                       if (is_buf)
-                               p = strsep(&file, "\n");
+                       if (!skip_fgets) {
+                               if (is_buf)
+                                       p = strsep(&file, "\n");
+                               else
+                                       p = fgets(string, 4096, f);
+                               if (!p)
+                                       break;
+                               dprint(FD_PARSE, "%s", p);
+                       }
                        else
-                               p = fgets(string, 4096, f);
-                       if (!p)
-                               break;
+                               skip_fgets = 0;
 
                        if (is_empty_or_comment(p))
                                continue;
@@ -1503,12 +1524,30 @@ int parse_jobs_ini(char *file, int is_buf, int stonewall_flag, int type)
                         * fgets() a new line at the top.
                         */
                        if (p[0] == '[') {
+                               if (nested) {
+                                       log_err("No new sections in included files\n");
+                                       return 1;
+                               }
+
                                skip_fgets = 1;
                                break;
                        }
 
                        strip_blank_end(p);
 
+                       if (!strncmp(p, "include", strlen("include"))) {
+                               char *filename = p + strlen("include") + 1;
+
+                               if ((ret = __parse_jobs_ini(td, filename,
+                                               is_buf, stonewall_flag, type, 1,
+                                               name, &opts, &alloc_opts, &num_opts))) {
+                                       log_err("Error %d while parsing include file %s\n",
+                                               ret, filename);
+                                       break;
+                               }
+                               continue;
+                       }
+
                        if (num_opts == alloc_opts) {
                                alloc_opts <<= 1;
                                opts = realloc(opts,
@@ -1519,6 +1558,13 @@ int parse_jobs_ini(char *file, int is_buf, int stonewall_flag, int type)
                        num_opts++;
                }
 
+               if (nested) {
+                       *popts = opts;
+                       *aopts = alloc_opts;
+                       *nopts = num_opts;
+                       goto out;
+               }
+
                ret = fio_options_parse(td, opts, num_opts, dump_cmdline);
                if (!ret)
                        ret = add_job(td, name, 0, 0, type);
@@ -1541,14 +1587,22 @@ int parse_jobs_ini(char *file, int is_buf, int stonewall_flag, int type)
                i++;
        }
 
-       free(string);
-       free(name);
        free(opts);
+out:
+       free(string);
+       if (!nested)
+               free(name);
        if (!is_buf && f != stdin)
                fclose(f);
        return ret;
 }
 
+int parse_jobs_ini(char *file, int is_buf, int stonewall_flag, int type)
+{
+       return __parse_jobs_ini(NULL, file, is_buf, stonewall_flag, type,
+                       0, NULL, NULL, NULL, NULL);
+}
+
 static int fill_def_thread(void)
 {
        memset(&def_thread, 0, sizeof(def_thread));
@@ -1569,7 +1623,7 @@ static void usage(const char *name)
        printf("%s [options] [job options] <job file(s)>\n", name);
        printf("  --debug=options\tEnable debug logging. May be one/more of:\n"
                "\t\t\tprocess,file,io,mem,blktrace,verify,random,parse,\n"
-               "\t\t\tdiskutil,job,mutex,profile,time,net,rate\n");
+               "\t\t\tdiskutil,job,mutex,profile,time,net,rate,compress\n");
        printf("  --parse-only\t\tParse options only, don't start any IO\n");
        printf("  --output\t\tWrite output to file\n");
        printf("  --runtime\t\tRuntime in seconds\n");
@@ -1604,6 +1658,7 @@ static void usage(const char *name)
        printf("  --server=args\t\tStart a backend fio server\n");
        printf("  --daemonize=pidfile\tBackground fio server, write pid to file\n");
        printf("  --client=hostname\tTalk to remote backend fio server at hostname\n");
+       printf("  --remote-config=file\tTell fio server to load this local job file\n");
        printf("  --idle-prof=option\tReport cpu idleness on a system or percpu basis\n"
                "\t\t\t(option=system,percpu) or run unit work\n"
                "\t\t\tcalibration only (option=calibrate)\n");
@@ -1677,6 +1732,10 @@ struct debug_level debug_levels[] = {
          .help = "Rate logging",
          .shift = FD_RATE,
        },
+       { .name = "compress",
+         .help = "Log compression logging",
+         .shift = FD_COMPRESS,
+       },
        { .name = NULL, },
 };
 
@@ -2091,10 +2150,18 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
                                    !strncmp(argv[optind], "-", 1))
                                        break;
 
-                               fio_client_add_ini_file(cur_client, argv[optind]);
+                               if (fio_client_add_ini_file(cur_client, argv[optind], 0))
+                                       break;
                                optind++;
                        }
                        break;
+               case 'R':
+                       did_arg = 1;
+                       if (fio_client_add_ini_file(cur_client, optarg, 1)) {
+                               do_exit++;
+                               exit_val = 1;
+                       }
+                       break;
                case 'T':
                        did_arg = 1;
                        do_exit++;