The following changes since commit f893b76d5745811033f056ae4d4efe4f571452bd:

  backend: use monotonic clock for ETA, if we have it (2014-12-15 19:54:57 
-0700)

are available in the git repository at:

  git://git.kernel.dk/fio.git master

for you to fetch changes up to d5e16441bd7727f3e1b90708f957d42a7e47121d:

  gettime: cleanup for FIO_DEBUG_TIME (2014-12-16 23:03:54 -0700)

----------------------------------------------------------------
Jens Axboe (9):
      engines/mmap: fix segfault on large devices and 32-bit archs
      engines/mmap: clear partial mmap flag on close
      gettime: don't attempt to fixup what looks like a backwards clock
      gettime: limit warning on CPU clock
      gettime: improve gettimeofday() offload support
      gettime-thread: fix missing startup mutex
      gettime-thread: set and allow multiple CPUs
      gettime: fix overflow in cycle to usec conversion
      gettime: cleanup for FIO_DEBUG_TIME

 cconv.c          |    2 --
 engines/mmap.c   |    6 +++++
 gettime-thread.c |   29 ++++++++++++++++++++-----
 gettime.c        |   64 ++++++++++++++++++++----------------------------------
 gettime.h        |   20 +++++++++++++++++
 init.c           |   12 +++++-----
 options.c        |   12 +---------
 server.h         |    2 +-
 thread_options.h |    5 ++---
 9 files changed, 84 insertions(+), 68 deletions(-)

---

Diff of recent changes:

diff --git a/cconv.c b/cconv.c
index 0de2f5c..0fca764 100644
--- a/cconv.c
+++ b/cconv.c
@@ -219,7 +219,6 @@ void convert_thread_options_to_cpu(struct thread_options *o,
        o->unified_rw_rep = le32_to_cpu(top->unified_rw_rep);
        o->gtod_reduce = le32_to_cpu(top->gtod_reduce);
        o->gtod_cpu = le32_to_cpu(top->gtod_cpu);
-       o->gtod_offload = le32_to_cpu(top->gtod_offload);
        o->clocksource = le32_to_cpu(top->clocksource);
        o->no_stall = le32_to_cpu(top->no_stall);
        o->trim_percentage = le32_to_cpu(top->trim_percentage);
@@ -381,7 +380,6 @@ void convert_thread_options_to_net(struct 
thread_options_pack *top,
        top->unified_rw_rep = cpu_to_le32(o->unified_rw_rep);
        top->gtod_reduce = cpu_to_le32(o->gtod_reduce);
        top->gtod_cpu = cpu_to_le32(o->gtod_cpu);
-       top->gtod_offload = cpu_to_le32(o->gtod_offload);
        top->clocksource = cpu_to_le32(o->clocksource);
        top->no_stall = cpu_to_le32(o->no_stall);
        top->trim_percentage = cpu_to_le32(o->trim_percentage);
diff --git a/engines/mmap.c b/engines/mmap.c
index 6464cba..8bcd42c 100644
--- a/engines/mmap.c
+++ b/engines/mmap.c
@@ -103,6 +103,11 @@ static int fio_mmapio_prep_full(struct thread_data *td, 
struct io_u *io_u)
 
        if (fio_file_partial_mmap(f))
                return EINVAL;
+       if (io_u->offset != (size_t) io_u->offset ||
+           f->io_size != (size_t) f->io_size) {
+               fio_file_set_partial_mmap(f);
+               return EINVAL;
+       }
 
        fmd->mmap_sz = f->io_size;
        fmd->mmap_off = 0;
@@ -242,6 +247,7 @@ static int fio_mmapio_close_file(struct thread_data *td, 
struct fio_file *f)
 
        FILE_SET_ENG_DATA(f, NULL);
        free(fmd);
+       fio_file_clear_partial_mmap(f);
 
        return generic_close_file(td, f);
 }
diff --git a/gettime-thread.c b/gettime-thread.c
index 3d49034..73632d0 100644
--- a/gettime-thread.c
+++ b/gettime-thread.c
@@ -8,11 +8,14 @@
 
 struct timeval *fio_tv = NULL;
 int fio_gtod_offload = 0;
-int fio_gtod_cpu = -1;
+static os_cpu_mask_t fio_gtod_cpumask;
 static pthread_t gtod_thread;
 
 void fio_gtod_init(void)
 {
+       if (fio_tv)
+               return;
+
        fio_tv = smalloc(sizeof(struct timeval));
        if (!fio_tv)
                log_err("fio: smalloc pool exhausted\n");
@@ -20,14 +23,27 @@ void fio_gtod_init(void)
 
 static void fio_gtod_update(void)
 {
-       if (fio_tv)
-               gettimeofday(fio_tv, NULL);
+       if (fio_tv) {
+               struct timeval __tv;
+
+               gettimeofday(&__tv, NULL);
+               fio_tv->tv_sec = __tv.tv_sec;
+               write_barrier();
+               fio_tv->tv_usec = __tv.tv_usec;
+               write_barrier();
+       }
 }
 
+struct gtod_cpu_data {
+       struct fio_mutex *mutex;
+       unsigned int cpu;
+};
+
 static void *gtod_thread_main(void *data)
 {
        struct fio_mutex *mutex = data;
 
+       fio_setaffinity(gettid(), fio_gtod_cpumask);
        fio_mutex_up(mutex);
 
        /*
@@ -56,7 +72,7 @@ int fio_start_gtod_thread(void)
 
        pthread_attr_init(&attr);
        pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
-       ret = pthread_create(&gtod_thread, &attr, gtod_thread_main, NULL);
+       ret = pthread_create(&gtod_thread, &attr, gtod_thread_main, mutex);
        pthread_attr_destroy(&attr);
        if (ret) {
                log_err("Can't create gtod thread: %s\n", strerror(ret));
@@ -77,4 +93,7 @@ err:
        return ret;
 }
 
-
+void fio_gtod_set_cpu(unsigned int cpu)
+{
+       fio_cpu_set(&fio_gtod_cpumask, cpu);
+}
diff --git a/gettime.c b/gettime.c
index 6a7e35f..7e3e2e5 100644
--- a/gettime.c
+++ b/gettime.c
@@ -16,13 +16,14 @@
 #if defined(ARCH_HAVE_CPU_CLOCK) && !defined(ARCH_CPU_CLOCK_CYCLES_PER_USEC)
 static unsigned long cycles_per_usec;
 static unsigned long inv_cycles_per_usec;
+static uint64_t max_cycles_for_mult;
 #endif
 int tsc_reliable = 0;
 
 struct tv_valid {
-       struct timeval last_tv;
        uint64_t last_cycles;
        int last_tv_valid;
+       int warned;
 };
 #ifdef CONFIG_TLS_THREAD
 static __thread struct tv_valid static_tv_valid;
@@ -64,7 +65,7 @@ static struct gtod_log *find_hash(void *caller)
        return NULL;
 }
 
-static struct gtod_log *find_log(void *caller)
+static void inc_caller(void *caller)
 {
        struct gtod_log *log = find_hash(caller);
 
@@ -80,16 +81,13 @@ static struct gtod_log *find_log(void *caller)
                flist_add_tail(&log->list, &hash[h]);
        }
 
-       return log;
+       log->calls++;
 }
 
 static void gtod_log_caller(void *caller)
 {
-       if (gtod_inited) {
-               struct gtod_log *log = find_log(caller);
-
-               log->calls++;
-       }
+       if (gtod_inited)
+               inc_caller(caller);
 }
 
 static void fio_exit fio_dump_gtod(void)
@@ -136,7 +134,7 @@ static int fill_clock_gettime(struct timespec *ts)
 }
 #endif
 
-static void *__fio_gettime(struct timeval *tp)
+static void __fio_gettime(struct timeval *tp)
 {
        struct tv_valid *tv;
 
@@ -171,16 +169,21 @@ static void *__fio_gettime(struct timeval *tp)
                uint64_t usecs, t;
 
                t = get_cpu_clock();
-               if (tv && t < tv->last_cycles) {
-                       dprint(FD_TIME, "CPU clock going back in time\n");
-                       t = tv->last_cycles;
-               } else if (tv)
-                       tv->last_cycles = t;
+               if (t < tv->last_cycles && tv->last_tv_valid &&
+                   !tv->warned) {
+                       log_err("fio: CPU clock going back in time\n");
+                       tv->warned = 1;
+               }
 
+               tv->last_cycles = t;
+               tv->last_tv_valid = 1;
 #ifdef ARCH_CPU_CLOCK_CYCLES_PER_USEC
                usecs = t / ARCH_CPU_CLOCK_CYCLES_PER_USEC;
 #else
-               usecs = (t * inv_cycles_per_usec) / 16777216UL;
+               if (t < max_cycles_for_mult)
+                       usecs = (t * inv_cycles_per_usec) / 16777216UL;
+               else
+                       usecs = t / cycles_per_usec;
 #endif
                tp->tv_sec = usecs / 1000000;
                tp->tv_usec = usecs % 1000000;
@@ -191,8 +194,6 @@ static void *__fio_gettime(struct timeval *tp)
                log_err("fio: invalid clock source %d\n", fio_clock_source);
                break;
        }
-
-       return tv;
 }
 
 #ifdef FIO_DEBUG_TIME
@@ -201,36 +202,16 @@ void fio_gettime(struct timeval *tp, void *caller)
 void fio_gettime(struct timeval *tp, void fio_unused *caller)
 #endif
 {
-       struct tv_valid *tv;
-
 #ifdef FIO_DEBUG_TIME
        if (!caller)
                caller = __builtin_return_address(0);
 
        gtod_log_caller(caller);
 #endif
-       if (fio_unlikely(fio_tv)) {
-               memcpy(tp, fio_tv, sizeof(*tp));
+       if (fio_unlikely(fio_gettime_offload(tp)))
                return;
-       }
 
-       tv = __fio_gettime(tp);
-
-       /*
-        * If Linux is using the tsc clock on non-synced processors,
-        * sometimes time can appear to drift backwards. Fix that up.
-        */
-       if (tv) {
-               if (tv->last_tv_valid) {
-                       if (tp->tv_sec < tv->last_tv.tv_sec)
-                               tp->tv_sec = tv->last_tv.tv_sec;
-                       else if (tv->last_tv.tv_sec == tp->tv_sec &&
-                                tp->tv_usec < tv->last_tv.tv_usec)
-                               tp->tv_usec = tv->last_tv.tv_usec;
-               }
-               tv->last_tv_valid = 1;
-               memcpy(&tv->last_tv, tp, sizeof(*tp));
-       }
+       __fio_gettime(tp);
 }
 
 #if defined(ARCH_HAVE_CPU_CLOCK) && !defined(ARCH_CPU_CLOCK_CYCLES_PER_USEC)
@@ -316,6 +297,7 @@ static int calibrate_cpu_clock(void)
 
        cycles_per_usec = avg;
        inv_cycles_per_usec = 16777216UL / cycles_per_usec;
+       max_cycles_for_mult = ~0ULL / inv_cycles_per_usec;
        dprint(FD_TIME, "inv_cycles_per_usec=%lu\n", inv_cycles_per_usec);
        return 0;
 }
@@ -336,8 +318,10 @@ void fio_local_clock_init(int is_thread)
        struct tv_valid *t;
 
        t = calloc(1, sizeof(*t));
-       if (pthread_setspecific(tv_tls_key, t))
+       if (pthread_setspecific(tv_tls_key, t)) {
                log_err("fio: can't set TLS key\n");
+               assert(0);
+       }
 }
 
 static void kill_tv_tls_key(void *data)
diff --git a/gettime.h b/gettime.h
index f0ad20c..b775ef3 100644
--- a/gettime.h
+++ b/gettime.h
@@ -1,6 +1,8 @@
 #ifndef FIO_GETTIME_H
 #define FIO_GETTIME_H
 
+#include "arch/arch.h"
+
 /*
  * Clock sources
  */
@@ -20,4 +22,22 @@ extern void fio_local_clock_init(int);
 
 extern struct timeval *fio_tv;
 
+static inline int fio_gettime_offload(struct timeval *tv)
+{
+       size_t last_sec;
+
+       if (!fio_tv)
+               return 0;
+
+       do {
+               read_barrier();
+               last_sec = tv->tv_sec = fio_tv->tv_sec;
+               tv->tv_usec = fio_tv->tv_usec;
+       } while (fio_tv->tv_sec != last_sec);
+
+       return 1;
+}
+
+extern void fio_gtod_set_cpu(unsigned int cpu);
+
 #endif
diff --git a/init.c b/init.c
index f606087..427768c 100644
--- a/init.c
+++ b/init.c
@@ -758,6 +758,12 @@ static int fixup_options(struct thread_data *td)
                ret = 1;
        }
 
+       if (fio_option_is_set(o, gtod_cpu)) {
+               fio_gtod_init();
+               fio_gtod_set_cpu(o->gtod_cpu);
+               fio_gtod_offload = 1;
+       }
+
        return ret;
 }
 
@@ -2385,12 +2391,6 @@ int parse_options(int argc, char *argv[])
                return 0;
        }
 
-       if (def_thread.o.gtod_offload) {
-               fio_gtod_init();
-               fio_gtod_offload = 1;
-               fio_gtod_cpu = def_thread.o.gtod_cpu;
-       }
-
        if (output_format == FIO_OUTPUT_NORMAL)
                log_info("%s\n", fio_version_string);
 
diff --git a/options.c b/options.c
index a01b2d9..80a7047 100644
--- a/options.c
+++ b/options.c
@@ -1079,16 +1079,6 @@ static int str_gtod_reduce_cb(void *data, int *il)
        return 0;
 }
 
-static int str_gtod_cpu_cb(void *data, long long *il)
-{
-       struct thread_data *td = data;
-       int val = *il;
-
-       td->o.gtod_cpu = val;
-       td->o.gtod_offload = 1;
-       return 0;
-}
-
 static int str_size_cb(void *data, unsigned long long *__val)
 {
        struct thread_data *td = data;
@@ -3404,7 +3394,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .name   = "gtod_cpu",
                .lname  = "Dedicated gettimeofday() CPU",
                .type   = FIO_OPT_INT,
-               .cb     = str_gtod_cpu_cb,
+               .off1   = td_var_offset(gtod_cpu),
                .help   = "Set up dedicated gettimeofday() thread on this CPU",
                .verify = gtod_cpu_verify,
                .category = FIO_OPT_C_GENERAL,
diff --git a/server.h b/server.h
index cd3f999..dc5a69e 100644
--- a/server.h
+++ b/server.h
@@ -38,7 +38,7 @@ struct fio_net_cmd_reply {
 };
 
 enum {
-       FIO_SERVER_VER                  = 41,
+       FIO_SERVER_VER                  = 42,
 
        FIO_SERVER_MAX_FRAGMENT_PDU     = 1024,
        FIO_SERVER_MAX_CMD_MB           = 2048,
diff --git a/thread_options.h b/thread_options.h
index 530dd9a..611f8e7 100644
--- a/thread_options.h
+++ b/thread_options.h
@@ -195,7 +195,6 @@ struct thread_options {
        unsigned int unified_rw_rep;
        unsigned int gtod_reduce;
        unsigned int gtod_cpu;
-       unsigned int gtod_offload;
        enum fio_cs clocksource;
        unsigned int no_stall;
        unsigned int trim_percentage;
@@ -419,7 +418,6 @@ struct thread_options_pack {
        uint32_t unified_rw_rep;
        uint32_t gtod_reduce;
        uint32_t gtod_cpu;
-       uint32_t gtod_offload;
        uint32_t clocksource;
        uint32_t no_stall;
        uint32_t trim_percentage;
@@ -428,6 +426,7 @@ struct thread_options_pack {
        uint64_t trim_backlog;
        uint32_t clat_percentiles;
        uint32_t percentile_precision;
+       uint32_t pad2;
        fio_fp64_t percentile_list[FIO_IO_U_LIST_MAX_LEN];
 
        uint8_t read_iolog_file[FIO_TOP_STR_MAX];
@@ -480,10 +479,10 @@ struct thread_options_pack {
        uint64_t number_ios;
 
        uint32_t sync_file_range;
-       uint32_t pad2;
 
        uint64_t latency_target;
        uint64_t latency_window;
+       uint32_t pad3;
        fio_fp64_t latency_percentile;
 } __attribute__((packed));
 
--
To unsubscribe from this list: send the line "unsubscribe fio" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to