Use char* for pid_file path
[fio.git] / init.c
diff --git a/init.c b/init.c
index 77cf9f2ac8b32e7000f72abe0ff681183fba17fa..0a6766e39f1a082dc78a815b307d36d289684ae7 100644 (file)
--- a/init.c
+++ b/init.c
@@ -493,7 +493,7 @@ static struct thread_data *get_new_job(int global, struct thread_data *parent,
        if (jobname)
                td->o.name = strdup(jobname);
 
-       if (!parent->o.group_reporting)
+       if (!parent->o.group_reporting || parent == &def_thread)
                stat_number++;
 
        set_cmd_options(td);
@@ -860,7 +860,7 @@ static int fixup_options(struct thread_data *td)
                td->loops = 1;
 
        if (td->o.block_error_hist && td->o.nr_files != 1) {
-               log_err("fio: block error histogram only available with "
+               log_err("fio: block error histogram only available "
                        "with a single file per job, but %d files "
                        "provided\n", td->o.nr_files);
                ret = 1;
@@ -904,34 +904,75 @@ static const char *get_engine_name(const char *str)
        return p;
 }
 
-static int exists_and_not_file(const char *filename)
+static int exists_and_not_regfile(const char *filename)
 {
        struct stat sb;
 
        if (lstat(filename, &sb) == -1)
                return 0;
 
+#ifndef WIN32 /* NOT Windows */
+       if (S_ISREG(sb.st_mode))
+               return 0;
+#else
        /* \\.\ is the device namespace in Windows, where every file
         * is a device node */
        if (S_ISREG(sb.st_mode) && strncmp(filename, "\\\\.\\", 4) != 0)
                return 0;
+#endif
 
        return 1;
 }
 
-static void td_fill_rand_seeds_internal(struct thread_data *td, int use64)
+static void init_rand_file_service(struct thread_data *td)
+{
+       unsigned long nranges = td->o.nr_files << FIO_FSERVICE_SHIFT;
+       const unsigned int seed = td->rand_seeds[FIO_RAND_FILE_OFF];
+
+       if (td->o.file_service_type == FIO_FSERVICE_ZIPF) {
+               zipf_init(&td->next_file_zipf, nranges, td->zipf_theta, seed);
+               zipf_disable_hash(&td->next_file_zipf);
+       } else if (td->o.file_service_type == FIO_FSERVICE_PARETO) {
+               pareto_init(&td->next_file_zipf, nranges, td->pareto_h, seed);
+               zipf_disable_hash(&td->next_file_zipf);
+       } else if (td->o.file_service_type == FIO_FSERVICE_GAUSS) {
+               gauss_init(&td->next_file_gauss, nranges, td->gauss_dev, seed);
+               gauss_disable_hash(&td->next_file_gauss);
+       }
+}
+
+void td_fill_verify_state_seed(struct thread_data *td)
+{
+       bool use64;
+
+       if (td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE64)
+               use64 = 1;
+       else
+               use64 = 0;
+
+       init_rand_seed(&td->verify_state, td->rand_seeds[FIO_RAND_VER_OFF],
+               use64);
+}
+
+static void td_fill_rand_seeds_internal(struct thread_data *td, bool use64)
 {
+       int i;
+
        init_rand_seed(&td->bsrange_state, td->rand_seeds[FIO_RAND_BS_OFF], use64);
-       init_rand_seed(&td->verify_state, td->rand_seeds[FIO_RAND_VER_OFF], use64);
-       init_rand_seed(&td->rwmix_state, td->rand_seeds[FIO_RAND_MIX_OFF], use64);
+       td_fill_verify_state_seed(td);
+       init_rand_seed(&td->rwmix_state, td->rand_seeds[FIO_RAND_MIX_OFF], false);
 
        if (td->o.file_service_type == FIO_FSERVICE_RANDOM)
                init_rand_seed(&td->next_file_state, td->rand_seeds[FIO_RAND_FILE_OFF], use64);
+       else if (td->o.file_service_type & __FIO_FSERVICE_NONUNIFORM)
+               init_rand_file_service(td);
 
        init_rand_seed(&td->file_size_state, td->rand_seeds[FIO_RAND_FILE_SIZE_OFF], use64);
        init_rand_seed(&td->trim_state, td->rand_seeds[FIO_RAND_TRIM_OFF], use64);
        init_rand_seed(&td->delay_state, td->rand_seeds[FIO_RAND_START_DELAY], use64);
        init_rand_seed(&td->poisson_state, td->rand_seeds[FIO_RAND_POISSON_OFF], 0);
+       init_rand_seed(&td->dedupe_state, td->rand_seeds[FIO_DEDUPE_OFF], false);
+       init_rand_seed(&td->zone_state, td->rand_seeds[FIO_RAND_ZONE_OFF], false);
 
        if (!td_random(td))
                return;
@@ -940,14 +981,17 @@ static void td_fill_rand_seeds_internal(struct thread_data *td, int use64)
                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], use64);
-       init_rand_seed(&td->seq_rand_state[DDIR_READ], td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF], use64);
-       init_rand_seed(&td->seq_rand_state[DDIR_WRITE], td->rand_seeds[FIO_RAND_SEQ_RAND_WRITE_OFF], use64);
-       init_rand_seed(&td->seq_rand_state[DDIR_TRIM], td->rand_seeds[FIO_RAND_SEQ_RAND_TRIM_OFF], use64);
+
+       for (i = 0; i < DDIR_RWDIR_CNT; i++) {
+               struct frand_state *s = &td->seq_rand_state[i];
+
+               init_rand_seed(s, td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF], false);
+       }
 }
 
 void td_fill_rand_seeds(struct thread_data *td)
 {
-       int use64;
+       bool use64;
 
        if (td->o.allrand_repeatable) {
                unsigned int i;
@@ -966,8 +1010,6 @@ void td_fill_rand_seeds(struct thread_data *td)
 
        init_rand_seed(&td->buf_state, td->rand_seeds[FIO_RAND_BUF_OFF], use64);
        frand_copy(&td->buf_state_prev, &td->buf_state);
-
-       init_rand_seed(&td->dedupe_state, td->rand_seeds[FIO_DEDUPE_OFF], use64);
 }
 
 /*
@@ -1074,7 +1116,7 @@ static int setup_random_seeds(struct thread_data *td)
                seed *= 0x9e370001UL;
 
        for (i = 0; i < FIO_RAND_NR_OFFS; i++) {
-               td->rand_seeds[i] = seed;
+               td->rand_seeds[i] = seed * td->thread_number + i;
                seed *= 0x9e370001UL;
        }
 
@@ -1305,7 +1347,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
        if (!o->filename && !td->files_index && !o->read_iolog_file) {
                file_alloced = 1;
 
-               if (o->nr_files == 1 && exists_and_not_file(jobname))
+               if (o->nr_files == 1 && exists_and_not_regfile(jobname))
                        add_file(td, jobname, job_add_num, 0);
                else {
                        for (i = 0; i < o->nr_files; i++)
@@ -1376,6 +1418,8 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                struct log_params p = {
                        .td = td,
                        .avg_msec = o->log_avg_msec,
+                       .hist_msec = o->log_hist_msec,
+                       .hist_coarseness = o->log_hist_coarseness,
                        .log_type = IO_LOG_TYPE_LAT,
                        .log_offset = o->log_offset,
                        .log_gz = o->log_gz,
@@ -1400,10 +1444,36 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                                td->thread_number, suf, o->per_job_logs);
                setup_log(&td->clat_log, &p, logname);
        }
+
+       if (o->hist_log_file) {
+               struct log_params p = {
+                       .td = td,
+                       .avg_msec = o->log_avg_msec,
+                       .hist_msec = o->log_hist_msec,
+                       .hist_coarseness = o->log_hist_coarseness,
+                       .log_type = IO_LOG_TYPE_HIST,
+                       .log_offset = o->log_offset,
+                       .log_gz = o->log_gz,
+                       .log_gz_store = o->log_gz_store,
+               };
+               const char *suf;
+
+               if (p.log_gz_store)
+                       suf = "log.fz";
+               else
+                       suf = "log";
+
+               gen_log_name(logname, sizeof(logname), "clat_hist", o->hist_log_file,
+                               td->thread_number, suf, o->per_job_logs);
+               setup_log(&td->clat_hist_log, &p, logname);
+       }
+
        if (o->bw_log_file) {
                struct log_params p = {
                        .td = td,
                        .avg_msec = o->log_avg_msec,
+                       .hist_msec = o->log_hist_msec,
+                       .hist_coarseness = o->log_hist_coarseness,
                        .log_type = IO_LOG_TYPE_BW,
                        .log_offset = o->log_offset,
                        .log_gz = o->log_gz,
@@ -1411,6 +1481,14 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                };
                const char *suf;
 
+               if (fio_option_is_set(o, bw_avg_time))
+                       p.avg_msec = min(o->log_avg_msec, o->bw_avg_time);
+               else
+                       o->bw_avg_time = p.avg_msec;
+       
+               p.hist_msec = o->log_hist_msec;
+               p.hist_coarseness = o->log_hist_coarseness;
+
                if (p.log_gz_store)
                        suf = "log.fz";
                else
@@ -1424,6 +1502,8 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                struct log_params p = {
                        .td = td,
                        .avg_msec = o->log_avg_msec,
+                       .hist_msec = o->log_hist_msec,
+                       .hist_coarseness = o->log_hist_coarseness,
                        .log_type = IO_LOG_TYPE_IOPS,
                        .log_offset = o->log_offset,
                        .log_gz = o->log_gz,
@@ -1431,6 +1511,14 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                };
                const char *suf;
 
+               if (fio_option_is_set(o, iops_avg_time))
+                       p.avg_msec = min(o->log_avg_msec, o->iops_avg_time);
+               else
+                       o->iops_avg_time = p.avg_msec;
+       
+               p.hist_msec = o->log_hist_msec;
+               p.hist_coarseness = o->log_hist_coarseness;
+
                if (p.log_gz_store)
                        suf = "log.fz";
                else
@@ -1773,15 +1861,48 @@ int __parse_jobs_ini(struct thread_data *td,
                        strip_blank_end(p);
 
                        if (!strncmp(p, "include", strlen("include"))) {
-                               char *filename = p + strlen("include") + 1;
+                               char *filename = p + strlen("include") + 1,
+                                       *ts, *full_fn = NULL;
 
-                               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",
+                               /*
+                                * Allow for the include filename
+                                * specification to be relative.
+                                */
+                               if (access(filename, F_OK) &&
+                                   (ts = strrchr(file, '/'))) {
+                                       int len = ts - file +
+                                               strlen(filename) + 2;
+
+                                       if (!(full_fn = calloc(1, len))) {
+                                               ret = ENOMEM;
+                                               break;
+                                       }
+
+                                       strncpy(full_fn,
+                                               file, (ts - file) + 1);
+                                       strncpy(full_fn + (ts - file) + 1,
+                                               filename, strlen(filename));
+                                       full_fn[len - 1] = 0;
+                                       filename = full_fn;
+                               }
+
+                               ret = __parse_jobs_ini(td, filename, is_buf,
+                                                      stonewall_flag, type, 1,
+                                                      name, &opts,
+                                                      &alloc_opts, &num_opts);
+
+                               if (ret) {
+                                       log_err("Error %d while parsing "
+                                               "include file %s\n",
                                                ret, filename);
-                                       break;
                                }
+
+                               if (full_fn)
+                                       free(full_fn);
+
+                               if (ret)
+                                       break;
+
                                continue;
                        }
 
@@ -1860,6 +1981,7 @@ static int fill_def_thread(void)
 
 static void show_debug_categories(void)
 {
+#ifdef FIO_INC_DEBUG
        struct debug_level *dl = &debug_levels[0];
        int curlen, first = 1;
 
@@ -1885,6 +2007,7 @@ static void show_debug_categories(void)
                first = 0;
        }
        printf("\n");
+#endif
 }
 
 static void usage(const char *name)
@@ -2179,7 +2302,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
        struct thread_data *td = NULL;
        int c, ini_idx = 0, lidx, ret = 0, do_exit = 0, exit_val = 0;
        char *ostr = cmd_optstr;
-       void *pid_file = NULL;
+       char *pid_file = NULL;
        void *cur_client = NULL;
        int backend = 0;
 
@@ -2512,14 +2635,14 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
                                    !strncmp(argv[optind], "-", 1))
                                        break;
 
-                               if (fio_client_add_ini_file(cur_client, argv[optind], 0))
+                               if (fio_client_add_ini_file(cur_client, argv[optind], false))
                                        break;
                                optind++;
                        }
                        break;
                case 'R':
                        did_arg = 1;
-                       if (fio_client_add_ini_file(cur_client, optarg, 1)) {
+                       if (fio_client_add_ini_file(cur_client, optarg, true)) {
                                do_exit++;
                                exit_val = 1;
                        }