Add 'per_job_logs' option
authorJens Axboe <axboe@fb.com>
Mon, 11 May 2015 17:39:36 +0000 (13:39 -0400)
committerJens Axboe <axboe@fb.com>
Mon, 11 May 2015 17:39:36 +0000 (13:39 -0400)
If set, this generates bw/clat/iops log with per file private
filenames. If not set, jobs with identical names will share the
log filename. Default: true.

Signed-off-by: Jens Axboe <axboe@fb.com>
HOWTO
backend.c
cconv.c
fio.1
init.c
iolog.c
iolog.h
options.c
thread_options.h

diff --git a/HOWTO b/HOWTO
index d62d4089fb9d633892e60290f0917530c9411f5b..406cfca0d3ba855e5261878d66ae9fcd7c976723 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -1440,6 +1440,10 @@ replay_align=int Force alignment of IO offsets and lengths in a trace
 replay_scale=int       Scale sector offsets down by this factor when
                replaying traces.
 
 replay_scale=int       Scale sector offsets down by this factor when
                replaying traces.
 
+per_job_logs=bool      If set, this generates bw/clat/iops log with per
+               file private filenames. If not set, jobs with identical names
+               will share the log filename. Default: true.
+
 write_bw_log=str If given, write a bandwidth log of the jobs in this job
                file. Can be used to store data of the bandwidth of the
                jobs in their lifetime. The included fio_generate_plots
 write_bw_log=str If given, write a bandwidth log of the jobs in this job
                file. Can be used to store data of the bandwidth of the
                jobs in their lifetime. The included fio_generate_plots
@@ -1447,7 +1451,8 @@ write_bw_log=str If given, write a bandwidth log of the jobs in this job
                graphs. See write_lat_log for behaviour of given
                filename. For this option, the suffix is _bw.x.log, where
                x is the index of the job (1..N, where N is the number of
                graphs. See write_lat_log for behaviour of given
                filename. For this option, the suffix is _bw.x.log, where
                x is the index of the job (1..N, where N is the number of
-               jobs).
+               jobs). If 'per_job_logs' is false, then the filename will not
+               include the job index.
 
 write_lat_log=str Same as write_bw_log, except that this option stores io
                submission, completion, and total latencies instead. If no
 
 write_lat_log=str Same as write_bw_log, except that this option stores io
                submission, completion, and total latencies instead. If no
@@ -1460,13 +1465,17 @@ write_lat_log=str Same as write_bw_log, except that this option stores io
                The actual log names will be foo_slat.x.log, foo_clat.x.log,
                and foo_lat.x.log, where x is the index of the job (1..N,
                where N is the number of jobs). This helps fio_generate_plot
                The actual log names will be foo_slat.x.log, foo_clat.x.log,
                and foo_lat.x.log, where x is the index of the job (1..N,
                where N is the number of jobs). This helps fio_generate_plot
-               fine the logs automatically.
+               fine the logs automatically. If 'per_job_logs' is false, then
+               the filename will not include the job index.
+
 
 write_iops_log=str Same as write_bw_log, but writes IOPS. If no filename is
                given with this option, the default filename of
                "jobname_type.x.log" is used,where x is the index of the job
                (1..N, where N is the number of jobs). Even if the filename
 
 write_iops_log=str Same as write_bw_log, but writes IOPS. If no filename is
                given with this option, the default filename of
                "jobname_type.x.log" is used,where x is the index of the job
                (1..N, where N is the number of jobs). Even if the filename
-               is given, fio will still append the type of log.
+               is given, fio will still append the type of log. If
+               'per_job_logs' is false, then the filename will not include
+               the job index.
 
 log_avg_msec=int By default, fio will log an entry in the iops, latency,
                or bw log for every IO that completes. When writing to the
 
 log_avg_msec=int By default, fio will log an entry in the iops, latency,
                or bw log for every IO that completes. When writing to the
index 1dcdcf049026db4f1ae33d04284ade793b76d77f..c58294bb7558f3c4ef8c2b5773d753735d954b90 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -2261,7 +2261,7 @@ int fio_backend(void)
                        for (i = 0; i < DDIR_RWDIR_CNT; i++) {
                                struct io_log *log = agg_io_log[i];
 
                        for (i = 0; i < DDIR_RWDIR_CNT; i++) {
                                struct io_log *log = agg_io_log[i];
 
-                               flush_log(log);
+                               flush_log(log, 0);
                                free_log(log);
                        }
                }
                                free_log(log);
                        }
                }
diff --git a/cconv.c b/cconv.c
index 1e095afdc7ccc8960adba0ce311054b0c7f4e407..bc9edb2df2b5b83c4c7e58995117df77a48ed0e9 100644 (file)
--- a/cconv.c
+++ b/cconv.c
@@ -248,6 +248,7 @@ void convert_thread_options_to_cpu(struct thread_options *o,
        o->block_error_hist = le32_to_cpu(top->block_error_hist);
        o->replay_align = le32_to_cpu(top->replay_align);
        o->replay_scale = le32_to_cpu(top->replay_scale);
        o->block_error_hist = le32_to_cpu(top->block_error_hist);
        o->replay_align = le32_to_cpu(top->replay_align);
        o->replay_scale = le32_to_cpu(top->replay_scale);
+       o->per_job_logs = le32_to_cpu(top->per_job_logs);
 
        o->trim_backlog = le64_to_cpu(top->trim_backlog);
 
 
        o->trim_backlog = le64_to_cpu(top->trim_backlog);
 
@@ -415,6 +416,7 @@ void convert_thread_options_to_net(struct thread_options_pack *top,
        top->skip_bad = cpu_to_le32(o->skip_bad);
        top->replay_align = cpu_to_le32(o->replay_align);
        top->replay_scale = cpu_to_le32(o->replay_scale);
        top->skip_bad = cpu_to_le32(o->skip_bad);
        top->replay_align = cpu_to_le32(o->replay_align);
        top->replay_scale = cpu_to_le32(o->replay_scale);
+       top->per_job_logs = cpu_to_le32(o->per_job_logs);
 
        for (i = 0; i < DDIR_RWDIR_CNT; i++) {
                top->bs[i] = cpu_to_le32(o->bs[i]);
 
        for (i = 0; i < DDIR_RWDIR_CNT; i++) {
                top->bs[i] = cpu_to_le32(o->bs[i]);
diff --git a/fio.1 b/fio.1
index e5451b1696f7a6b16754bf576a3531a8f81fd321..6c4e5c8f16ad492be550ff73f4b291b077ec113d 100644 (file)
--- a/fio.1
+++ b/fio.1
@@ -1271,26 +1271,33 @@ Force alignment of IO offsets and lengths in a trace to this power of 2 value.
 .BI replay_scale \fR=\fPint
 Scale sector offsets down by this factor when replaying traces.
 .TP
 .BI replay_scale \fR=\fPint
 Scale sector offsets down by this factor when replaying traces.
 .TP
+.BI per_job_logs \fR=\fPbool
+If set, this generates bw/clat/iops log with per file private filenames. If
+not set, jobs with identical names will share the log filename. Default: true.
+.TP
 .BI write_bw_log \fR=\fPstr
 If given, write a bandwidth log of the jobs in this job file. Can be used to
 store data of the bandwidth of the jobs in their lifetime. The included
 fio_generate_plots script uses gnuplot to turn these text files into nice
 graphs. See \fBwrite_lat_log\fR for behaviour of given filename. For this
 option, the postfix is _bw.x.log, where x is the index of the job (1..N,
 .BI write_bw_log \fR=\fPstr
 If given, write a bandwidth log of the jobs in this job file. Can be used to
 store data of the bandwidth of the jobs in their lifetime. The included
 fio_generate_plots script uses gnuplot to turn these text files into nice
 graphs. See \fBwrite_lat_log\fR for behaviour of given filename. For this
 option, the postfix is _bw.x.log, where x is the index of the job (1..N,
-where N is the number of jobs)
+where N is the number of jobs). If \fBper_job_logs\fR is false, then the
+filename will not include the job index.
 .TP
 .BI write_lat_log \fR=\fPstr
 Same as \fBwrite_bw_log\fR, but writes I/O completion latencies.  If no
 filename is given with this option, the default filename of
 "jobname_type.x.log" is used, where x is the index of the job (1..N, where
 N is the number of jobs). Even if the filename is given, fio will still
 .TP
 .BI write_lat_log \fR=\fPstr
 Same as \fBwrite_bw_log\fR, but writes I/O completion latencies.  If no
 filename is given with this option, the default filename of
 "jobname_type.x.log" is used, where x is the index of the job (1..N, where
 N is the number of jobs). Even if the filename is given, fio will still
-append the type of log.
+append the type of log. If \fBper_job_logs\fR is false, then the filename will
+not include the job index.
 .TP
 .BI write_iops_log \fR=\fPstr
 Same as \fBwrite_bw_log\fR, but writes IOPS. If no filename is given with this
 option, the default filename of "jobname_type.x.log" is used, where x is the
 index of the job (1..N, where N is the number of jobs). Even if the filename
 .TP
 .BI write_iops_log \fR=\fPstr
 Same as \fBwrite_bw_log\fR, but writes IOPS. If no filename is given with this
 option, the default filename of "jobname_type.x.log" is used, where x is the
 index of the job (1..N, where N is the number of jobs). Even if the filename
-is given, fio will still append the type of log.
+is given, fio will still append the type of log. If \fBper_job_logs\fR is false,
+then the filename will not include the job index.
 .TP
 .BI log_avg_msec \fR=\fPint
 By default, fio will log an entry in the iops, latency, or bw log for every
 .TP
 .BI log_avg_msec \fR=\fPint
 By default, fio will log an entry in the iops, latency, or bw log for every
diff --git a/init.c b/init.c
index ba5bf2fbf4bb9b55bc61267e7ff0e3e8889bbd04..f34e8182ce7d775b7ab36d0545135a978801d408 100644 (file)
--- a/init.c
+++ b/init.c
@@ -1107,6 +1107,16 @@ int parse_dryrun(void)
        return dump_cmdline || parse_only;
 }
 
        return dump_cmdline || parse_only;
 }
 
+static void gen_log_name(char *name, size_t size, const char *logtype,
+                        const char *logname, unsigned int num,
+                        const char *suf, int per_job)
+{
+       if (per_job)
+               snprintf(name, size, "%s_%s.%d.%s", logname, logtype, num, suf);
+       else
+               snprintf(name, size, "%s_%s.%s", logname, logtype, suf);
+}
+
 /*
  * Adds a job to the list of things todo. Sanitizes the various options
  * to make sure we don't have conflicts, and initializes various
 /*
  * Adds a job to the list of things todo. Sanitizes the various options
  * to make sure we don't have conflicts, and initializes various
@@ -1225,14 +1235,16 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                else
                        suf = "log";
 
                else
                        suf = "log";
 
-               snprintf(logname, sizeof(logname), "%s_lat.%d.%s",
-                               o->lat_log_file, td->thread_number, suf);
+               gen_log_name(logname, sizeof(logname), "lat", o->lat_log_file,
+                               td->thread_number, suf, o->per_job_logs);
                setup_log(&td->lat_log, &p, logname);
                setup_log(&td->lat_log, &p, logname);
-               snprintf(logname, sizeof(logname), "%s_slat.%d.%s",
-                               o->lat_log_file, td->thread_number, suf);
+
+               gen_log_name(logname, sizeof(logname), "slat", o->lat_log_file,
+                               td->thread_number, suf, o->per_job_logs);
                setup_log(&td->slat_log, &p, logname);
                setup_log(&td->slat_log, &p, logname);
-               snprintf(logname, sizeof(logname), "%s_clat.%d.%s",
-                               o->lat_log_file, td->thread_number, suf);
+
+               gen_log_name(logname, sizeof(logname), "clat", o->lat_log_file,
+                               td->thread_number, suf, o->per_job_logs);
                setup_log(&td->clat_log, &p, logname);
        }
        if (o->bw_log_file) {
                setup_log(&td->clat_log, &p, logname);
        }
        if (o->bw_log_file) {
@@ -1251,8 +1263,8 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                else
                        suf = "log";
 
                else
                        suf = "log";
 
-               snprintf(logname, sizeof(logname), "%s_bw.%d.%s",
-                               o->bw_log_file, td->thread_number, suf);
+               gen_log_name(logname, sizeof(logname), "bw", o->bw_log_file,
+                               td->thread_number, suf, o->per_job_logs);
                setup_log(&td->bw_log, &p, logname);
        }
        if (o->iops_log_file) {
                setup_log(&td->bw_log, &p, logname);
        }
        if (o->iops_log_file) {
@@ -1271,8 +1283,8 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                else
                        suf = "log";
 
                else
                        suf = "log";
 
-               snprintf(logname, sizeof(logname), "%s_iops.%d.%s",
-                               o->iops_log_file, td->thread_number, suf);
+               gen_log_name(logname, sizeof(logname), "iops", o->iops_log_file,
+                               td->thread_number, suf, o->per_job_logs);
                setup_log(&td->iops_log, &p, logname);
        }
 
                setup_log(&td->iops_log, &p, logname);
        }
 
diff --git a/iolog.c b/iolog.c
index b29684a85eb69c30d219b95eff122c33df9ce5f6..82b2b8a3ec40084853655a42d5494a4e9bbf91bf 100644 (file)
--- a/iolog.c
+++ b/iolog.c
@@ -945,12 +945,15 @@ int iolog_file_inflate(const char *file)
 
 #endif
 
 
 #endif
 
-void flush_log(struct io_log *log)
+void flush_log(struct io_log *log, int do_append)
 {
        void *buf;
        FILE *f;
 
 {
        void *buf;
        FILE *f;
 
-       f = fopen(log->filename, "w");
+       if (!do_append)
+               f = fopen(log->filename, "w");
+       else
+               f = fopen(log->filename, "a");
        if (!f) {
                perror("fopen log");
                return;
        if (!f) {
                perror("fopen log");
                return;
@@ -980,7 +983,7 @@ static int finish_log(struct thread_data *td, struct io_log *log, int trylock)
        if (td->client_type == FIO_CLIENT_TYPE_GUI)
                fio_send_iolog(td, log, log->filename);
        else
        if (td->client_type == FIO_CLIENT_TYPE_GUI)
                fio_send_iolog(td, log, log->filename);
        else
-               flush_log(log);
+               flush_log(log, !td->o.per_job_logs);
 
        fio_unlock_file(log->filename);
        free_log(log);
 
        fio_unlock_file(log->filename);
        free_log(log);
diff --git a/iolog.h b/iolog.h
index a1e32ae7335b0b439518f3e1940235c041158ab1..b1c13bf7e16b7230c11a9c9dd3c459236a5bef05 100644 (file)
--- a/iolog.h
+++ b/iolog.h
@@ -215,7 +215,7 @@ extern void add_iops_sample(struct thread_data *, enum fio_ddir, unsigned int,
 extern void init_disk_util(struct thread_data *);
 extern void update_rusage_stat(struct thread_data *);
 extern void setup_log(struct io_log **, struct log_params *, const char *);
 extern void init_disk_util(struct thread_data *);
 extern void update_rusage_stat(struct thread_data *);
 extern void setup_log(struct io_log **, struct log_params *, const char *);
-extern void flush_log(struct io_log *);
+extern void flush_log(struct io_log *, int);
 extern void free_log(struct io_log *);
 extern struct io_log *agg_io_log[DDIR_RWDIR_CNT];
 extern int write_bw_log;
 extern void free_log(struct io_log *);
 extern struct io_log *agg_io_log[DDIR_RWDIR_CNT];
 extern int write_bw_log;
index e306b28b6c08398c139f162b309523ec6f990c63..5c6ec2321bd13819742ed9056318a222a51f88d3 100644 (file)
--- a/options.c
+++ b/options.c
@@ -3183,6 +3183,15 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_PROCESS,
        },
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_PROCESS,
        },
+       {
+               .name   = "per_job_logs",
+               .type   = FIO_OPT_BOOL,
+               .off1   = td_var_offset(per_job_logs),
+               .help   = "Include job number in generated log files or not",
+               .def    = "1",
+               .category = FIO_OPT_C_LOG,
+               .group  = FIO_OPT_G_INVALID,
+       },
        {
                .name   = "write_bw_log",
                .lname  = "Write bandwidth log",
        {
                .name   = "write_bw_log",
                .lname  = "Write bandwidth log",
index 1c48bd83d394577b463ecb9ec5b4572b05123747..f967a8a10aa4fc4da5212b48eabf4c427b3fc999 100644 (file)
@@ -268,6 +268,8 @@ struct thread_options {
 
        unsigned int replay_align;
        unsigned int replay_scale;
 
        unsigned int replay_align;
        unsigned int replay_scale;
+
+       unsigned int per_job_logs;
 };
 
 #define FIO_TOP_STR_MAX                256
 };
 
 #define FIO_TOP_STR_MAX                256
@@ -501,6 +503,8 @@ struct thread_options_pack {
 
        uint32_t replay_align;
        uint32_t replay_scale;
 
        uint32_t replay_align;
        uint32_t replay_scale;
+
+       uint32_t per_job_logs;
 } __attribute__((packed));
 
 extern void convert_thread_options_to_cpu(struct thread_options *o, struct thread_options_pack *top);
 } __attribute__((packed));
 
 extern void convert_thread_options_to_cpu(struct thread_options *o, struct thread_options_pack *top);