The following changes since commit 10aa136bddbaa7c845ab4eacb4a9a4a88d6657a3:

  Cleanup symbols that should be static (2014-04-01 21:10:36 -0600)

are available in the git repository at:

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

for you to fetch changes up to 2e80228232afc9cf90ad06b360a33a05637978f3:

  Use setvbuf() for log writing (2014-04-02 21:47:27 -0600)

----------------------------------------------------------------
Erwan Velu (3):
      iolog: Keep full path for logs files
      stat: fixing bw_agg reporting
      io_u: Using initialized local variable

Jens Axboe (12):
      Merge branch 'erwan/nobasename' of https://github.com/enovance/fio
      Merge branch 'erwan/clang' of https://github.com/enovance/fio
      Fix propagation of error value on failure to connect to fio server
      Add missing crc/test.h file
      Don't crash when using filehash lock before init
      mutex: add open init function and down_trylock() variant
      Add 'f' (Finishing) flag to status output
      iolog: don't serialize the writing of all logs
      Cleanup the parallellized log writing
      crc: add test.h header to test.c
      iolog: invert log_mask bits
      Use setvbuf() for log writing

 HOWTO      |    1 +
 Makefile   |    2 +-
 backend.c  |   44 +--------------
 configure  |   20 +++++++
 crc/test.c |    2 +
 crc/test.h |    6 ++
 eta.c      |    6 +-
 filehash.c |    6 +-
 filelock.c |  157 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 filelock.h |   11 ++++
 fio.h      |    1 +
 init.c     |    9 ++-
 io_u.c     |    4 +-
 iolog.c    |  179 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 iolog.h    |    3 +-
 libfio.c   |    6 ++
 mutex.c    |   55 +++++++++++++------
 mutex.h    |    2 +
 stat.c     |    2 +-
 19 files changed, 432 insertions(+), 84 deletions(-)
 create mode 100644 crc/test.h
 create mode 100644 filelock.c
 create mode 100644 filelock.h

---

Diff of recent changes:

diff --git a/HOWTO b/HOWTO
index 47eff96..7db7b89 100644
--- a/HOWTO
+++ b/HOWTO
@@ -1590,6 +1590,7 @@ I         Thread initialized, waiting or generating 
necessary data.
        M       Running, doing mixed sequential reads/writes.
        m       Running, doing mixed random reads/writes.
        F       Running, currently waiting for fsync()
+       f       Running, finishing up (writing IO logs, etc)
        V       Running, doing verification of written data.
 E              Thread exited, not reaped by main thread yet.
 _              Thread reaped, or
diff --git a/Makefile b/Makefile
index 1113c2f..231b4ab 100644
--- a/Makefile
+++ b/Makefile
@@ -35,7 +35,7 @@ SOURCE := gettime.c ioengines.c init.c stat.c log.c time.c 
filesetup.c \
                cconv.c lib/prio_tree.c json.c lib/zipf.c lib/axmap.c \
                lib/lfsr.c gettime-thread.c helpers.c lib/flist_sort.c \
                lib/hweight.c lib/getrusage.c idletime.c td_error.c \
-               profiles/tiobench.c profiles/act.c io_u_queue.c
+               profiles/tiobench.c profiles/act.c io_u_queue.c filelock.c
 
 ifdef CONFIG_64BIT_LLP64
   CFLAGS += -DBITS_PER_LONG=32
diff --git a/backend.c b/backend.c
index 1ff8b3f..5ac3659 100644
--- a/backend.c
+++ b/backend.c
@@ -57,7 +57,6 @@
 static pthread_t disk_util_thread;
 static struct fio_mutex *disk_thread_mutex;
 static struct fio_mutex *startup_mutex;
-static struct fio_mutex *writeout_mutex;
 static struct flist_head *cgroup_list;
 static char *cgroup_mnt;
 static int exit_value;
@@ -1490,45 +1489,8 @@ static void *thread_main(void *data)
 
        fio_unpin_memory(td);
 
-       fio_mutex_down(writeout_mutex);
-       finalize_logs(td);
-       if (td->bw_log) {
-               if (o->bw_log_file) {
-                       finish_log_named(td, td->bw_log,
-                                               o->bw_log_file, "bw");
-               } else
-                       finish_log(td, td->bw_log, "bw");
-       }
-       if (td->lat_log) {
-               if (o->lat_log_file) {
-                       finish_log_named(td, td->lat_log,
-                                               o->lat_log_file, "lat");
-               } else
-                       finish_log(td, td->lat_log, "lat");
-       }
-       if (td->slat_log) {
-               if (o->lat_log_file) {
-                       finish_log_named(td, td->slat_log,
-                                               o->lat_log_file, "slat");
-               } else
-                       finish_log(td, td->slat_log, "slat");
-       }
-       if (td->clat_log) {
-               if (o->lat_log_file) {
-                       finish_log_named(td, td->clat_log,
-                                               o->lat_log_file, "clat");
-               } else
-                       finish_log(td, td->clat_log, "clat");
-       }
-       if (td->iops_log) {
-               if (o->iops_log_file) {
-                       finish_log_named(td, td->iops_log,
-                                               o->iops_log_file, "iops");
-               } else
-                       finish_log(td, td->iops_log, "iops");
-       }
+       fio_writeout_logs(td);
 
-       fio_mutex_up(writeout_mutex);
        if (o->exec_postrun)
                exec_string(o, o->exec_postrun, (const char *)"postrun");
 
@@ -2033,9 +1995,6 @@ int fio_backend(void)
        startup_mutex = fio_mutex_init(FIO_MUTEX_LOCKED);
        if (startup_mutex == NULL)
                return 1;
-       writeout_mutex = fio_mutex_init(FIO_MUTEX_UNLOCKED);
-       if (writeout_mutex == NULL)
-               return 1;
 
        set_genesis_time();
        stat_init();
@@ -2066,7 +2025,6 @@ int fio_backend(void)
        sfree(cgroup_mnt);
 
        fio_mutex_remove(startup_mutex);
-       fio_mutex_remove(writeout_mutex);
        fio_mutex_remove(disk_thread_mutex);
        stat_exit();
        return exit_value;
diff --git a/configure b/configure
index 63aa02d..05f985b 100755
--- a/configure
+++ b/configure
@@ -1163,6 +1163,23 @@ if compile_prog "" "-lrbd -lrados" "rbd"; then
 fi
 echo "Rados Block Device engine     $rbd"
 
+##########################################
+# Check whether we have setvbuf
+setvbuf="no"
+cat > $TMPC << EOF
+#include <stdio.h>
+int main(int argc, char **argv)
+{
+  FILE *f = NULL;
+  char buf[80];
+  setvbuf(f, buf, _IOFBF, sizeof(buf));
+  return 0;
+}
+EOF
+if compile_prog "" "" "setvbuf"; then
+  setvbuf="yes"
+fi
+echo "setvbuf                       $setvbuf"
 
 #############################################################################
 
@@ -1291,6 +1308,9 @@ fi
 if test "$cpu_count" = "yes" ; then
   output_sym "CONFIG_CPU_COUNT"
 fi
+if test "$setvbuf" = "yes" ; then
+  output_sym "CONFIG_SETVBUF"
+fi
 
 echo "LIBS+=$LIBS" >> $config_host_mak
 echo "CFLAGS+=$CFLAGS" >> $config_host_mak
diff --git a/crc/test.c b/crc/test.c
index 174bea3..2cc7c0f 100644
--- a/crc/test.c
+++ b/crc/test.c
@@ -18,6 +18,8 @@
 #include "../crc/sha512.h"
 #include "../crc/xxhash.h"
 
+#include "test.h"
+
 #define CHUNK          131072U
 #define NR_CHUNKS        2048U
 
diff --git a/crc/test.h b/crc/test.h
new file mode 100644
index 0000000..2b52d6a
--- /dev/null
+++ b/crc/test.h
@@ -0,0 +1,6 @@
+#ifndef FIO_CRC_TEST_H
+#define FIO_CRC_TEST_H
+
+int fio_crctest(const char *type);
+
+#endif
diff --git a/eta.c b/eta.c
index b050102..42066e0 100644
--- a/eta.c
+++ b/eta.c
@@ -74,6 +74,9 @@ static void check_str_update(struct thread_data *td)
        case TD_FSYNCING:
                c = 'F';
                break;
+       case TD_FINISHING:
+               c = 'f';
+               break;
        case TD_CREATED:
                c = 'C';
                break;
@@ -331,7 +334,8 @@ int calc_thread_status(struct jobs_eta *je, int force)
                        bw_avg_time = td->o.bw_avg_time;
                if (td->runstate == TD_RUNNING || td->runstate == TD_VERIFYING
                    || td->runstate == TD_FSYNCING
-                   || td->runstate == TD_PRE_READING) {
+                   || td->runstate == TD_PRE_READING
+                   || td->runstate == TD_FINISHING) {
                        je->nr_running++;
                        if (td_read(td)) {
                                je->t_rate[0] += td->o.rate[DDIR_READ];
diff --git a/filehash.c b/filehash.c
index c6ebe76..0d61f54 100644
--- a/filehash.c
+++ b/filehash.c
@@ -21,12 +21,14 @@ static unsigned short hash(const char *name)
 
 void fio_file_hash_lock(void)
 {
-       fio_mutex_down(hash_lock);
+       if (hash_lock)
+               fio_mutex_down(hash_lock);
 }
 
 void fio_file_hash_unlock(void)
 {
-       fio_mutex_up(hash_lock);
+       if (hash_lock)
+               fio_mutex_up(hash_lock);
 }
 
 void remove_file_hash(struct fio_file *f)
diff --git a/filelock.c b/filelock.c
new file mode 100644
index 0000000..b252a97
--- /dev/null
+++ b/filelock.c
@@ -0,0 +1,157 @@
+/*
+ * Really simple exclusive file locking based on filename.
+ * No hash indexing, just a list, so only works well for < 100 files or
+ * so. But that's more than what fio needs, so should be fine.
+ */
+#include <inttypes.h>
+#include <string.h>
+#include <assert.h>
+
+#include "flist.h"
+#include "filelock.h"
+#include "smalloc.h"
+#include "mutex.h"
+#include "hash.h"
+#include "log.h"
+
+struct fio_filelock {
+       uint32_t hash;
+       struct fio_mutex lock;
+       struct flist_head list;
+       unsigned int references;
+};
+       
+static struct flist_head *filelock_list;
+static struct fio_mutex *filelock_lock;
+
+int fio_filelock_init(void)
+{
+       filelock_list = smalloc(sizeof(*filelock_list));
+       if (!filelock_list)
+               return 1;
+
+       INIT_FLIST_HEAD(filelock_list);
+       filelock_lock = fio_mutex_init(FIO_MUTEX_UNLOCKED);
+       if (!filelock_lock) {
+               sfree(filelock_list);
+               return 1;
+       }
+
+       return 0;
+}
+
+void fio_filelock_exit(void)
+{
+       if (!filelock_list)
+               return;
+
+       assert(flist_empty(filelock_list));
+       sfree(filelock_list);
+       filelock_list = NULL;
+       fio_mutex_remove(filelock_lock);
+       filelock_lock = NULL;
+}
+
+static struct fio_filelock *fio_hash_find(uint32_t hash)
+{
+       struct flist_head *entry;
+       struct fio_filelock *ff;
+
+       flist_for_each(entry, filelock_list) {
+               ff = flist_entry(entry, struct fio_filelock, list);
+               if (ff->hash == hash)
+                       return ff;
+       }
+
+       return NULL;
+}
+
+static struct fio_filelock *fio_hash_get(uint32_t hash)
+{
+       struct fio_filelock *ff;
+
+       ff = fio_hash_find(hash);
+       if (!ff) {
+               ff = smalloc(sizeof(*ff));
+               ff->hash = hash;
+               __fio_mutex_init(&ff->lock, FIO_MUTEX_UNLOCKED);
+               ff->references = 0;
+               flist_add(&ff->list, filelock_list);
+       }
+
+       return ff;
+}
+
+int fio_trylock_file(const char *fname)
+{
+       struct fio_filelock *ff;
+       uint32_t hash;
+
+       hash = jhash(fname, strlen(fname), 0);
+
+       fio_mutex_down(filelock_lock);
+       ff = fio_hash_get(hash);
+       ff->references++;
+       fio_mutex_up(filelock_lock);
+
+       if (!fio_mutex_down_trylock(&ff->lock))
+               return 0;
+
+       fio_mutex_down(filelock_lock);
+
+       /*
+        * If we raced and the only reference to the lock is us, we can
+        * grab it
+        */
+       if (ff->references != 1) {
+               ff->references--;
+               ff = NULL;
+       }
+
+       fio_mutex_up(filelock_lock);
+
+       if (ff) {
+               fio_mutex_down(&ff->lock);
+               return 0;
+       }
+
+       return 1;
+}
+
+void fio_lock_file(const char *fname)
+{
+       struct fio_filelock *ff;
+       uint32_t hash;
+
+       hash = jhash(fname, strlen(fname), 0);
+
+       fio_mutex_down(filelock_lock);
+       ff = fio_hash_get(hash);
+       ff->references++;
+       fio_mutex_up(filelock_lock);
+
+       fio_mutex_down(&ff->lock);
+}
+
+void fio_unlock_file(const char *fname)
+{
+       struct fio_filelock *ff;
+       uint32_t hash;
+
+       hash = jhash(fname, strlen(fname), 0);
+
+       fio_mutex_down(filelock_lock);
+
+       ff = fio_hash_find(hash);
+       if (ff) {
+               ff->references--;
+               fio_mutex_up(&ff->lock);
+               if (!ff->references) {
+                       flist_del(&ff->list);
+                       sfree(ff);
+               }
+       } else
+               log_err("fio: file not found for unlocking\n");
+
+       fio_mutex_up(filelock_lock);
+}
diff --git a/filelock.h b/filelock.h
new file mode 100644
index 0000000..97d13b7
--- /dev/null
+++ b/filelock.h
@@ -0,0 +1,11 @@
+#ifndef FIO_LOCK_FILE_H
+#define FIO_LOCK_FILE_H
+
+extern void fio_lock_file(const char *);
+extern int fio_trylock_file(const char *);
+extern void fio_unlock_file(const char *);
+
+extern int fio_filelock_init(void);
+extern void fio_filelock_exit(void);
+
+#endif
diff --git a/fio.h b/fio.h
index befdce3..a539f21 100644
--- a/fio.h
+++ b/fio.h
@@ -471,6 +471,7 @@ enum {
        TD_PRE_READING,
        TD_VERIFYING,
        TD_FSYNCING,
+       TD_FINISHING,
        TD_EXITED,
        TD_REAPED,
 };
diff --git a/init.c b/init.c
index c3996a7..910f2ba 100644
--- a/init.c
+++ b/init.c
@@ -24,6 +24,7 @@
 #include "profile.h"
 #include "server.h"
 #include "idletime.h"
+#include "filelock.h"
 
 #include "lib/getopt.h"
 #include "lib/strcasestr.h"
@@ -259,6 +260,7 @@ static void free_shm(void)
        }
 
        options_free(fio_options, &def_thread);
+       fio_filelock_exit();
        scleanup();
 }
 
@@ -1963,11 +1965,8 @@ int parse_cmd_line(int argc, char *argv[], int 
client_type)
        if (do_exit && !(is_backend || nr_clients))
                exit(exit_val);
 
-       if (nr_clients && fio_clients_connect()) {
-               do_exit++;
-               exit_val = 1;
-               return -1;
-       }
+       if (nr_clients && fio_clients_connect())
+               exit(1);
 
        if (is_backend && backend)
                return fio_start_server(pid_file);
diff --git a/io_u.c b/io_u.c
index 2f6aecf..411da32 100644
--- a/io_u.c
+++ b/io_u.c
@@ -426,12 +426,10 @@ static unsigned int __get_next_buflen(struct thread_data 
*td, struct io_u *io_u,
        unsigned int minbs, maxbs;
        unsigned long r, rand_max;
 
-       assert(ddir_rw(io_u->ddir));
+       assert(ddir_rw(ddir));
 
        if (td->o.bs_is_seq_rand)
                ddir = is_random ? DDIR_WRITE: DDIR_READ;
-       else
-               ddir = io_u->ddir;
 
        minbs = td->o.min_bs[ddir];
        maxbs = td->o.max_bs[ddir];
diff --git a/iolog.c b/iolog.c
index b8ee067..e805eae 100644
--- a/iolog.c
+++ b/iolog.c
@@ -10,6 +10,7 @@
 #include "fio.h"
 #include "verify.h"
 #include "trim.h"
+#include "filelock.h"
 
 static const char iolog_ver2[] = "fio version 2 iolog";
 
@@ -515,9 +516,36 @@ void setup_log(struct io_log **log, unsigned long 
avg_msec, int log_type)
        *log = l;
 }
 
+#ifdef CONFIG_SETVBUF
+static void *set_file_buffer(FILE *f)
+{
+       size_t size = 1048576;
+       void *buf;
+
+       buf = malloc(size);
+       setvbuf(f, buf, _IOFBF, size);
+       return buf;
+}
+
+static void clear_file_buffer(void *buf)
+{
+       free(buf);
+}
+#else
+static void *set_file_buffer(FILE *f)
+{
+       return NULL;
+}
+
+static void clear_file_buffer(void *buf)
+{
+}
+#endif
+
 void __finish_log(struct io_log *log, const char *name)
 {
        unsigned int i;
+       void *buf;
        FILE *f;
 
        f = fopen(name, "a");
@@ -526,6 +554,8 @@ void __finish_log(struct io_log *log, const char *name)
                return;
        }
 
+       buf = set_file_buffer(f);
+
        for (i = 0; i < log->nr_samples; i++) {
                fprintf(f, "%lu, %lu, %u, %u\n",
                                (unsigned long) log->log[i].time,
@@ -534,27 +564,160 @@ void __finish_log(struct io_log *log, const char *name)
        }
 
        fclose(f);
+       clear_file_buffer(buf);
        free(log->log);
        free(log);
 }
 
-void finish_log_named(struct thread_data *td, struct io_log *log,
-                      const char *prefix, const char *postfix)
+static int finish_log_named(struct thread_data *td, struct io_log *log,
+                           const char *prefix, const char *postfix,
+                           int trylock)
 {
-       char file_name[256], *p;
+       char file_name[256];
 
        snprintf(file_name, sizeof(file_name), "%s_%s.log", prefix, postfix);
-       p = basename(file_name);
+
+       if (trylock) {
+               if (fio_trylock_file(file_name))
+                       return 1;
+       } else
+               fio_lock_file(file_name);
 
        if (td->client_type == FIO_CLIENT_TYPE_GUI) {
-               fio_send_iolog(td, log, p);
+               fio_send_iolog(td, log, file_name);
                free(log->log);
                free(log);
        } else
-               __finish_log(log, p);
+               __finish_log(log, file_name);
+
+       fio_unlock_file(file_name);
+       return 0;
+}
+
+static int finish_log(struct thread_data *td, struct io_log *log,
+                     const char *name, int trylock)
+{
+       return finish_log_named(td, log, td->o.name, name, trylock);
+}
+
+static int write_this_log(struct thread_data *td, struct io_log *log,
+                         const char *log_file, const char *name, int try)
+{
+       int ret;
+
+       if (!log)
+               return 0;
+
+       if (log_file)
+               ret = finish_log_named(td, log, log_file, name, try);
+       else
+               ret = finish_log(td, log, name, try);
+
+       return ret;
 }
 
-void finish_log(struct thread_data *td, struct io_log *log, const char *name)
+static int write_iops_log(struct thread_data *td, int try)
 {
-       finish_log_named(td, log, td->o.name, name);
+       struct thread_options *o = &td->o;
+
+       return write_this_log(td, td->iops_log, o->iops_log_file, "iops", try);
+}
+
+static int write_slat_log(struct thread_data *td, int try)
+{
+       struct thread_options *o = &td->o;
+
+       return write_this_log(td, td->slat_log, o->lat_log_file, "slat", try);
+}
+
+static int write_clat_log(struct thread_data *td, int try)
+{
+       struct thread_options *o = &td->o;
+
+       return write_this_log(td, td->clat_log, o->lat_log_file, "clat" , try);
+}
+
+static int write_lat_log(struct thread_data *td, int try)
+{
+       struct thread_options *o = &td->o;
+
+       return write_this_log(td, td->lat_log, o->lat_log_file, "lat", try);
+}
+
+static int write_bandw_log(struct thread_data *td, int try)
+{
+       struct thread_options *o = &td->o;
+
+       return write_this_log(td, td->bw_log, o->bw_log_file, "bw", try);
+}
+
+enum {
+       BW_LOG_MASK     = 1,
+       LAT_LOG_MASK    = 2,
+       SLAT_LOG_MASK   = 4,
+       CLAT_LOG_MASK   = 8,
+       IOPS_LOG_MASK   = 16,
+
+       ALL_LOG_NR      = 5,
+};
+
+struct log_type {
+       unsigned int mask;
+       int (*fn)(struct thread_data *, int);
+};
+
+static struct log_type log_types[] = {
+       {
+               .mask   = BW_LOG_MASK,
+               .fn     = write_bandw_log,
+       },
+       {
+               .mask   = LAT_LOG_MASK,
+               .fn     = write_lat_log,
+       },
+       {
+               .mask   = SLAT_LOG_MASK,
+               .fn     = write_slat_log,
+       },
+       {
+               .mask   = CLAT_LOG_MASK,
+               .fn     = write_clat_log,
+       },
+       {
+               .mask   = IOPS_LOG_MASK,
+               .fn     = write_iops_log,
+       },
+};
+
+void fio_writeout_logs(struct thread_data *td)
+{
+       unsigned int log_mask = 0;
+       unsigned int log_left = ALL_LOG_NR;
+       int old_state, i;
+
+       old_state = td_bump_runstate(td, TD_FINISHING);
+
+       finalize_logs(td);
+
+       while (log_left) {
+               int prev_log_left = log_left;
+
+               for (i = 0; i < ALL_LOG_NR && log_left; i++) {
+                       struct log_type *lt = &log_types[i];
+                       int ret;
+
+                       if (!(log_mask & lt->mask)) {
+                               ret = lt->fn(td, log_left != 1);
+                               if (!ret) {
+                                       log_left--;
+                                       log_mask |= lt->mask;
+                               }
+                       }
+               }
+
+               if (prev_log_left == log_left)
+                       usleep(5000);
+       }
+
+       td_restore_runstate(td, old_state);
 }
diff --git a/iolog.h b/iolog.h
index 0716391..50d09e2 100644
--- a/iolog.h
+++ b/iolog.h
@@ -131,12 +131,11 @@ 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 **, unsigned long, int);
-extern void finish_log(struct thread_data *, struct io_log *, const char *);
-extern void finish_log_named(struct thread_data *, struct io_log *, const char 
*, const char *);
 extern void __finish_log(struct io_log *, const char *);
 extern struct io_log *agg_io_log[DDIR_RWDIR_CNT];
 extern int write_bw_log;
 extern void add_agg_sample(unsigned long, enum fio_ddir, unsigned int);
+extern void fio_writeout_logs(struct thread_data *);
 
 static inline void init_ipo(struct io_piece *ipo)
 {
diff --git a/libfio.c b/libfio.c
index 8eddab8..1fd77e4 100644
--- a/libfio.c
+++ b/libfio.c
@@ -31,6 +31,7 @@
 #include "fio.h"
 #include "smalloc.h"
 #include "os/os.h"
+#include "filelock.h"
 
 /*
  * Just expose an empty list, if the OS does not support disk util stats
@@ -265,6 +266,11 @@ int initialize_fio(char *envp[])
 
        sinit();
 
+       if (fio_filelock_init()) {
+               log_err("fio: failed initializing filelock subsys\n");
+               return 1;
+       }
+
        /*
         * We need locale for number printing, if it isn't set then just
         * go with the US format.
diff --git a/mutex.c b/mutex.c
index e1fbb60..466e20e 100644
--- a/mutex.c
+++ b/mutex.c
@@ -25,29 +25,19 @@ void fio_mutex_remove(struct fio_mutex *mutex)
        munmap((void *) mutex, sizeof(*mutex));
 }
 
-struct fio_mutex *fio_mutex_init(int value)
+int __fio_mutex_init(struct fio_mutex *mutex, int value)
 {
-       struct fio_mutex *mutex = NULL;
        pthread_mutexattr_t attr;
        pthread_condattr_t cond;
        int ret;
 
-       mutex = (void *) mmap(NULL, sizeof(struct fio_mutex),
-                               PROT_READ | PROT_WRITE,
-                               OS_MAP_ANON | MAP_SHARED, -1, 0);
-       if (mutex == MAP_FAILED) {
-               perror("mmap mutex");
-               mutex = NULL;
-               goto err;
-       }
-
        mutex->value = value;
        mutex->magic = FIO_MUTEX_MAGIC;
 
        ret = pthread_mutexattr_init(&attr);
        if (ret) {
                log_err("pthread_mutexattr_init: %s\n", strerror(ret));
-               goto err;
+               return ret;
        }
 
        /*
@@ -57,7 +47,7 @@ struct fio_mutex *fio_mutex_init(int value)
        ret = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
        if (ret) {
                log_err("pthread_mutexattr_setpshared: %s\n", strerror(ret));
-               goto err;
+               return ret;
        }
 #endif
 
@@ -70,17 +60,30 @@ struct fio_mutex *fio_mutex_init(int value)
        ret = pthread_mutex_init(&mutex->lock, &attr);
        if (ret) {
                log_err("pthread_mutex_init: %s\n", strerror(ret));
-               goto err;
+               return ret;
        }
 
        pthread_condattr_destroy(&cond);
        pthread_mutexattr_destroy(&attr);
+       return 0;
+}
 
-       return mutex;
-err:
-       if (mutex)
-               fio_mutex_remove(mutex);
+struct fio_mutex *fio_mutex_init(int value)
+{
+       struct fio_mutex *mutex = NULL;
+
+       mutex = (void *) mmap(NULL, sizeof(struct fio_mutex),
+                               PROT_READ | PROT_WRITE,
+                               OS_MAP_ANON | MAP_SHARED, -1, 0);
+       if (mutex == MAP_FAILED) {
+               perror("mmap mutex");
+               return NULL;
+       }
+
+       if (!__fio_mutex_init(mutex, value))
+               return mutex;
 
+       fio_mutex_remove(mutex);
        return NULL;
 }
 
@@ -125,6 +128,22 @@ int fio_mutex_down_timeout(struct fio_mutex *mutex, 
unsigned int seconds)
        return ret;
 }
 
+int fio_mutex_down_trylock(struct fio_mutex *mutex)
+{
+       int ret = 1;
+
+       assert(mutex->magic == FIO_MUTEX_MAGIC);
+
+       pthread_mutex_lock(&mutex->lock);
+       if (mutex->value) {
+               mutex->value--;
+               ret = 0;
+       }
+       pthread_mutex_unlock(&mutex->lock);
+
+       return ret;
+}
+
 void fio_mutex_down(struct fio_mutex *mutex)
 {
        assert(mutex->magic == FIO_MUTEX_MAGIC);
diff --git a/mutex.h b/mutex.h
index 4f3486d..246afee 100644
--- a/mutex.h
+++ b/mutex.h
@@ -24,10 +24,12 @@ enum {
        FIO_MUTEX_UNLOCKED      = 1,
 };
 
+extern int __fio_mutex_init(struct fio_mutex *, int);
 extern struct fio_mutex *fio_mutex_init(int);
 extern void fio_mutex_remove(struct fio_mutex *);
 extern void fio_mutex_up(struct fio_mutex *);
 extern void fio_mutex_down(struct fio_mutex *);
+extern int fio_mutex_down_trylock(struct fio_mutex *);
 extern int fio_mutex_down_timeout(struct fio_mutex *, unsigned int);
 
 extern void fio_rwlock_read(struct fio_rwlock *);
diff --git a/stat.c b/stat.c
index 4529f69..509c6f0 100644
--- a/stat.c
+++ b/stat.c
@@ -770,7 +770,7 @@ static void add_ddir_status_json(struct thread_stat *ts,
        }
        json_object_add_value_int(dir_object, "bw_min", min);
        json_object_add_value_int(dir_object, "bw_max", max);
-       json_object_add_value_float(dir_object, "bw_agg", mean);
+       json_object_add_value_float(dir_object, "bw_agg", p_of_agg);
        json_object_add_value_float(dir_object, "bw_mean", mean);
        json_object_add_value_float(dir_object, "bw_dev", dev);
 }
--
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