Merge branch 'fio_pr_alternate_epoch' of https://github.com/PCPartPicker/fio
authorJens Axboe <axboe@kernel.dk>
Thu, 3 Feb 2022 22:34:40 +0000 (15:34 -0700)
committerJens Axboe <axboe@kernel.dk>
Thu, 3 Feb 2022 22:34:40 +0000 (15:34 -0700)
* 'fio_pr_alternate_epoch' of https://github.com/PCPartPicker/fio:
  Support for alternate epochs in fio log files

13 files changed:
HOWTO
backend.c
cconv.c
fio.1
fio.h
fio_time.h
libfio.c
options.c
os/windows/posix.c
rate-submit.c
stat.c
thread_options.h
time.c

diff --git a/HOWTO b/HOWTO
index 216ea185b16d4120fe55a0059bfdc2a71649087b..74ba7216e132c358309ffd0961c2cb73ea7494be 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -3681,6 +3681,19 @@ Measurements and reporting
        write_type_log for each log type, instead of the default zero-based
        timestamps.
 
+.. option:: log_alternate_epoch=bool
+
+       If set, fio will log timestamps based on the epoch used by the clock specified
+       in the log_alternate_epoch_clock_id option, to the log files produced by
+       enabling write_type_log for each log type, instead of the default zero-based
+       timestamps.
+
+.. option:: log_alternate_epoch_clock_id=int
+
+       Specifies the clock_id to be used by clock_gettime to obtain the alternate epoch
+       if either log_unix_epoch or log_alternate_epoch are true. Otherwise has no
+       effect. Default value is 0, or CLOCK_REALTIME.
+
 .. option:: block_error_percentiles=bool
 
        If set, record errors in trim block-sized units from writes and trims and
index 933d84144f5caec32d7c0d5f8c7168dbc140f714..061e3b329d2cd113d1f566a6e2da31c8019d37c7 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -1830,7 +1830,7 @@ static void *thread_main(void *data)
        if (rate_submit_init(td, sk_out))
                goto err;
 
-       set_epoch_time(td, o->log_unix_epoch);
+       set_epoch_time(td, o->log_unix_epoch | o->log_alternate_epoch, o->log_alternate_epoch_clock_id);
        fio_getrusage(&td->ru_start);
        memcpy(&td->bw_sample_time, &td->epoch, sizeof(td->epoch));
        memcpy(&td->iops_sample_time, &td->epoch, sizeof(td->epoch));
diff --git a/cconv.c b/cconv.c
index 4f8d27eb2dcec47244dfab3b902205b32a21da5e..62d02e366e06473da2b74b55a090d0e46499af16 100644 (file)
--- a/cconv.c
+++ b/cconv.c
@@ -197,6 +197,8 @@ void convert_thread_options_to_cpu(struct thread_options *o,
        o->log_gz = le32_to_cpu(top->log_gz);
        o->log_gz_store = le32_to_cpu(top->log_gz_store);
        o->log_unix_epoch = le32_to_cpu(top->log_unix_epoch);
+       o->log_alternate_epoch = le32_to_cpu(top->log_alternate_epoch);
+       o->log_alternate_epoch_clock_id = le32_to_cpu(top->log_alternate_epoch_clock_id);
        o->norandommap = le32_to_cpu(top->norandommap);
        o->softrandommap = le32_to_cpu(top->softrandommap);
        o->bs_unaligned = le32_to_cpu(top->bs_unaligned);
@@ -425,6 +427,8 @@ void convert_thread_options_to_net(struct thread_options_pack *top,
        top->log_gz = cpu_to_le32(o->log_gz);
        top->log_gz_store = cpu_to_le32(o->log_gz_store);
        top->log_unix_epoch = cpu_to_le32(o->log_unix_epoch);
+       top->log_alternate_epoch = cpu_to_le32(o->log_alternate_epoch);
+       top->log_alternate_epoch_clock_id = cpu_to_le32(o->log_alternate_epoch_clock_id);
        top->norandommap = cpu_to_le32(o->norandommap);
        top->softrandommap = cpu_to_le32(o->softrandommap);
        top->bs_unaligned = cpu_to_le32(o->bs_unaligned);
diff --git a/fio.1 b/fio.1
index 0b25fad244121d1014fb3f2c2d9dccd469e589c1..f32d791594e24ed46d818c407bcd79e1b6e57c18 100644 (file)
--- a/fio.1
+++ b/fio.1
@@ -3384,6 +3384,17 @@ If set, fio will log Unix timestamps to the log files produced by enabling
 write_type_log for each log type, instead of the default zero-based
 timestamps.
 .TP
+.BI log_alternate_epoch \fR=\fPbool
+If set, fio will log timestamps based on the epoch used by the clock specified
+in the \fBlog_alternate_epoch_clock_id\fR option, to the log files produced by
+enabling write_type_log for each log type, instead of the default zero-based
+timestamps.
+.TP
+.BI log_alternate_epoch_clock_id \fR=\fPint
+Specifies the clock_id to be used by clock_gettime to obtain the alternate epoch
+if either \fBBlog_unix_epoch\fR or \fBlog_alternate_epoch\fR are true. Otherwise has no
+effect. Default value is 0, or CLOCK_REALTIME.
+.TP
 .BI block_error_percentiles \fR=\fPbool
 If set, record errors in trim block-sized units from writes and trims and
 output a histogram of how many trims it took to get to errors, and what kind
diff --git a/fio.h b/fio.h
index 1ea3d064c913510ff1ada2be0c4206ba99ee5474..7b0ca8435978f7eb1216d287584c780941fe4049 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -380,7 +380,7 @@ struct thread_data {
 
        struct timespec start;  /* start of this loop */
        struct timespec epoch;  /* time job was started */
-       unsigned long long unix_epoch; /* Time job was started, unix epoch based. */
+       unsigned long long alternate_epoch; /* Time job was started, clock_gettime's clock_id epoch based. */
        struct timespec last_issue;
        long time_offset;
        struct timespec ts_cache;
index b3bbd4c011c2518aea5cbf5523f514136f8601b3..59f25d82a54d0917472da4a6f900d825ce6daa12 100644 (file)
@@ -30,6 +30,6 @@ extern bool ramp_time_over(struct thread_data *);
 extern bool in_ramp_time(struct thread_data *);
 extern void fio_time_init(void);
 extern void timespec_add_msec(struct timespec *, unsigned int);
-extern void set_epoch_time(struct thread_data *, int);
+extern void set_epoch_time(struct thread_data *, int, int);
 
 #endif
index 198eaf2eb723f744cbc279cd3dff51a1be64bd00..01fa74529fa9fedd1833e33082b73b1198bf19e1 100644 (file)
--- a/libfio.c
+++ b/libfio.c
@@ -142,7 +142,7 @@ void reset_all_stats(struct thread_data *td)
                td->ts.runtime[i] = 0;
        }
 
-       set_epoch_time(td, td->o.log_unix_epoch);
+       set_epoch_time(td, td->o.log_unix_epoch | td->o.log_alternate_epoch, td->o.log_alternate_epoch_clock_id);
        memcpy(&td->start, &td->epoch, sizeof(td->epoch));
        memcpy(&td->iops_sample_time, &td->epoch, sizeof(td->epoch));
        memcpy(&td->bw_sample_time, &td->epoch, sizeof(td->epoch));
index dcf5e09fc2f5cdd733c3a5093482c38400ec6b15..6cdbd2686cf5e715b8dd76baae0d23d1fca5088a 100644 (file)
--- a/options.c
+++ b/options.c
@@ -4514,6 +4514,24 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_LOG,
                .group = FIO_OPT_G_INVALID,
        },
+       {
+               .name = "log_alternate_epoch",
+               .lname = "Log epoch alternate",
+               .type = FIO_OPT_BOOL,
+               .off1 = offsetof(struct thread_options, log_alternate_epoch),
+               .help = "Use alternate epoch time in log files. Uses the same epoch as that is used by clock_gettime with specified log_alternate_epoch_clock_id.",
+               .category = FIO_OPT_C_LOG,
+               .group = FIO_OPT_G_INVALID,
+       },
+       {
+               .name = "log_alternate_epoch_clock_id",
+               .lname = "Log alternate epoch clock_id",
+               .type = FIO_OPT_INT,
+               .off1 = offsetof(struct thread_options, log_alternate_epoch_clock_id),
+               .help = "If log_alternate_epoch or log_unix_epoch is true, this option specifies the clock_id from clock_gettime whose epoch should be used. If neither of those is true, this option has no effect. Default value is 0, or CLOCK_REALTIME",
+               .category = FIO_OPT_C_LOG,
+               .group = FIO_OPT_G_INVALID,
+       },
        {
                .name   = "block_error_percentiles",
                .lname  = "Block error percentiles",
index 0978bcf6f4638cecfe019c36b24ae15f0f1579f0..0d415e1e0dd0272f7ea797b4e8735812f83522f2 100644 (file)
@@ -537,16 +537,21 @@ int fcntl(int fildes, int cmd, ...)
 return 0;
 }
 
+#ifndef CLOCK_MONOTONIC_RAW
+#define CLOCK_MONOTONIC_RAW 4
+#endif
+
 /*
  * Get the value of a local clock source.
- * This implementation supports 2 clocks: CLOCK_MONOTONIC provides high-accuracy
- * relative time, while CLOCK_REALTIME provides a low-accuracy wall time.
+ * This implementation supports 3 clocks: CLOCK_MONOTONIC/CLOCK_MONOTONIC_RAW
+ * provide high-accuracy relative time, while CLOCK_REALTIME provides a
+ * low-accuracy wall time.
  */
 int clock_gettime(clockid_t clock_id, struct timespec *tp)
 {
        int rc = 0;
 
-       if (clock_id == CLOCK_MONOTONIC) {
+       if (clock_id == CLOCK_MONOTONIC || clock_id == CLOCK_MONOTONIC_RAW) {
                static LARGE_INTEGER freq = {{0,0}};
                LARGE_INTEGER counts;
                uint64_t t;
index e3a71168013f6526190b75323b6cd06160488a57..268356d17a1f1b35a6eaa0ad82219db86177a4de 100644 (file)
@@ -173,7 +173,7 @@ static int io_workqueue_init_worker_fn(struct submit_worker *sw)
        if (td->io_ops->post_init && td->io_ops->post_init(td))
                goto err_io_init;
 
-       set_epoch_time(td, td->o.log_unix_epoch);
+       set_epoch_time(td, td->o.log_unix_epoch | td->o.log_alternate_epoch, td->o.log_alternate_epoch_clock_id);
        fio_getrusage(&td->ru_start);
        clear_io_state(td, 1);
 
diff --git a/stat.c b/stat.c
index 24fc679fa1c39d7f79db798c9175b58f559139a8..0876222a1b6be28d0f5fd7ce6b278e6f90c099ff 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -3017,7 +3017,7 @@ static void __add_log_sample(struct io_log *iolog, union io_sample_data data,
                s = get_sample(iolog, cur_log, cur_log->nr_samples);
 
                s->data = data;
-               s->time = t + (iolog->td ? iolog->td->unix_epoch : 0);
+               s->time = t + (iolog->td ? iolog->td->alternate_epoch : 0);
                io_sample_set_ddir(iolog, s, ddir);
                s->bs = bs;
                s->priority = priority;
index ace658b7144d2b69ca7d059c2b246987f5544162..4162c42faf731db6ec1d434656032d31e8350777 100644 (file)
@@ -172,6 +172,8 @@ struct thread_options {
        unsigned int log_gz;
        unsigned int log_gz_store;
        unsigned int log_unix_epoch;
+       unsigned int log_alternate_epoch;
+       unsigned int log_alternate_epoch_clock_id;
        unsigned int norandommap;
        unsigned int softrandommap;
        unsigned int bs_unaligned;
@@ -488,6 +490,8 @@ struct thread_options_pack {
        uint32_t log_gz;
        uint32_t log_gz_store;
        uint32_t log_unix_epoch;
+       uint32_t log_alternate_epoch;
+       uint32_t log_alternate_epoch_clock_id;
        uint32_t norandommap;
        uint32_t softrandommap;
        uint32_t bs_unaligned;
diff --git a/time.c b/time.c
index cd0e2a89144b59a565d88fab6192dda951a8ff2b..5c4d6de0399c5cc681e9ca362c019870baf9db98 100644 (file)
--- a/time.c
+++ b/time.c
@@ -172,14 +172,14 @@ void set_genesis_time(void)
        fio_gettime(&genesis, NULL);
 }
 
-void set_epoch_time(struct thread_data *td, int log_unix_epoch)
+void set_epoch_time(struct thread_data *td, int log_alternate_epoch, clockid_t clock_id)
 {
        fio_gettime(&td->epoch, NULL);
-       if (log_unix_epoch) {
-               struct timeval tv;
-               gettimeofday(&tv, NULL);
-               td->unix_epoch = (unsigned long long)(tv.tv_sec) * 1000 +
-                                (unsigned long long)(tv.tv_usec) / 1000;
+       if (log_alternate_epoch) {
+               struct timespec ts;
+               clock_gettime(clock_id, &ts);
+               td->alternate_epoch = (unsigned long long)(ts.tv_sec) * 1000 +
+                                (unsigned long long)(ts.tv_nsec) / 1000000;
        }
 }