Recent changes (master)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The following changes since commit a240e441dd3ebf9705d9edc9d6f35f48acdb0241:

  Use unsigned long long for the uint64_t type (2013-01-21 12:30:34 -0700)

are available in the git repository at:
  git://git.kernel.dk/fio.git master

Jens Axboe (19):
      eta: improve accuracy for rwmix workloads and verify
      Ensure all random seeds are repeatable for randrepeat=1
      Make experimental_verify=1 handle all cases properly
      axmap: fix bug in axmap_find_first_free()
      verify: stop on actual number of bytes needed to be verified
      axmap: improve axmap_find_first_free()
      axmap: ensure that we never return a value that is larger than the map size
      t/axmap: update to catch recent bugs
      Fix 32-bit compile warning in should_check_rate()
      configure: add --cc= option to script
      configure: remember to output CC for windows
      OSX: Fixup warnings and clock_gettime() bug
      Kill now unneeded clock definitions
      configure: add endian check
      configure: fixup Windows
      configure: add default compiler on Windows
      windows: don't provide strsep(), fio already has one
      Fix compile warnings on Windows
      init: complain on unrecognized option with builtin getopt_long_only()

 Makefile           |    6 ++++
 backend.c          |   62 +++++++++++++++++++++++++++++++++---------------
 configure          |   66 +++++++++++++++++++++++++++++++++++++++++-----------
 engines/net.c      |    8 +++---
 engines/posixaio.c |   20 +++++++++++++--
 eta.c              |   16 ++++++++----
 fio.c              |    4 +-
 fio.h              |    2 +-
 init.c             |   26 +++++++++++++++++++-
 io_u.c             |   50 +++++++++++++++++++++------------------
 ioengine.h         |   20 +++++++++++++--
 ioengines.c        |    9 +++++-
 lib/axmap.c        |   25 ++++++++++++++++---
 lib/bswap.h        |    2 +-
 libfio.c           |    3 ++
 os/os-aix.h        |    6 ----
 os/os-android.h    |    9 -------
 os/os-freebsd.h    |    7 -----
 os/os-hpux.h       |   10 --------
 os/os-linux.h      |    9 -------
 os/os-mac.h        |   23 +++++------------
 os/os-netbsd.h     |    7 -----
 os/os-solaris.h    |    6 ----
 os/os-windows.h    |    6 +---
 os/os.h            |    4 +-
 os/windows/posix.c |   33 --------------------------
 os/windows/posix.h |   10 ++++++++
 server.c           |    4 +-
 t/axmap.c          |   20 +++++++++++----
 29 files changed, 272 insertions(+), 201 deletions(-)
 create mode 100644 os/windows/posix.h

---

Diff of recent changes:

diff --git a/Makefile b/Makefile
index 967996d..22ea022 100644
--- a/Makefile
+++ b/Makefile
@@ -40,6 +40,12 @@ endif
 ifdef CONFIG_32BIT
   CFLAGS += -DBITS_PER_LONG=32
 endif
+ifdef CONFIG_BIG_ENDIAN
+  CFLAGS += -DCONFIG_BIG_ENDIAN
+endif
+ifdef CONFIG_LITTLE_ENDIAN
+  CFLAGS += -DCONFIG_LITTLE_ENDIAN
+endif
 ifdef CONFIG_LIBAIO
   CFLAGS += -DCONFIG_LIBAIO
   SOURCE += engines/libaio.c
diff --git a/backend.c b/backend.c
index 507faa9..e025dbf 100644
--- a/backend.c
+++ b/backend.c
@@ -216,7 +216,7 @@ static int __check_min_rate(struct thread_data *td, struct timeval *now,
 }
 
 static int check_min_rate(struct thread_data *td, struct timeval *now,
-			  unsigned long *bytes_done)
+			  uint64_t *bytes_done)
 {
 	int ret = 0;
 
@@ -395,10 +395,10 @@ static int break_on_this_error(struct thread_data *td, enum fio_ddir ddir,
  */
 static void do_verify(struct thread_data *td, uint64_t verify_bytes)
 {
+	uint64_t bytes_done[DDIR_RWDIR_CNT] = { 0, 0, 0 };
 	struct fio_file *f;
 	struct io_u *io_u;
 	int ret, min_events;
-	uint64_t io_bytes;
 	unsigned int i;
 
 	dprint(FD_VERIFY, "starting loop\n");
@@ -422,7 +422,6 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes)
 	td_set_runstate(td, TD_VERIFYING);
 
 	io_u = NULL;
-	io_bytes = 0;
 	while (!td->terminate) {
 		enum fio_ddir ddir;
 		int ret2, full;
@@ -455,11 +454,37 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes)
 				break;
 			}
 		} else {
-			io_u = get_io_u(td);
-			if (!io_u)
+			if (ddir_rw_sum(bytes_done) + td->o.rw_min_bs > verify_bytes)
 				break;
 
-			if (io_u->buflen + io_bytes > verify_bytes)
+			while ((io_u = get_io_u(td)) != NULL) {
+				/*
+				 * We are only interested in the places where
+				 * we wrote or trimmed IOs. Turn those into
+				 * reads for verification purposes.
+				 */
+				if (io_u->ddir == DDIR_READ) {
+					/*
+					 * Pretend we issued it for rwmix
+					 * accounting
+					 */
+					td->io_issues[DDIR_READ]++;
+					put_io_u(td, io_u);
+					continue;
+				} else if (io_u->ddir == DDIR_TRIM) {
+					io_u->ddir = DDIR_READ;
+					io_u->flags |= IO_U_F_TRIMMED;
+					break;
+				} else if (io_u->ddir == DDIR_WRITE) {
+					io_u->ddir = DDIR_READ;
+					break;
+				} else {
+					put_io_u(td, io_u);
+					continue;
+				}
+			}
+
+			if (!io_u)
 				break;
 		}
 
@@ -491,7 +516,6 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes)
 				io_u->xfer_buflen = io_u->resid;
 				io_u->xfer_buf += bytes;
 				io_u->offset += bytes;
-				io_bytes += bytes;
 
 				if (ddir_rw(io_u->ddir))
 					td->ts.short_io_u[io_u->ddir]++;
@@ -503,11 +527,10 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes)
 				requeue_io_u(td, &io_u);
 			} else {
 sync_done:
-				ret = io_u_sync_complete(td, io_u, NULL);
+				ret = io_u_sync_complete(td, io_u, bytes_done);
 				if (ret < 0)
 					break;
 			}
-			io_bytes += io_u->xfer_buflen;
 			continue;
 		case FIO_Q_QUEUED:
 			break;
@@ -542,18 +565,15 @@ sync_done:
 				min_events = 1;
 
 			do {
-				unsigned long bytes = 0;
-
 				/*
 				 * Reap required number of io units, if any,
 				 * and do the verification on them through
 				 * the callback handler
 				 */
-				if (io_u_queued_complete(td, min_events, &bytes) < 0) {
+				if (io_u_queued_complete(td, min_events, bytes_done) < 0) {
 					ret = -1;
 					break;
 				}
-				io_bytes += bytes;
 			} while (full && (td->cur_depth > td->o.iodepth_low));
 		}
 		if (ret < 0)
@@ -592,9 +612,12 @@ static int io_bytes_exceeded(struct thread_data *td)
 /*
  * Main IO worker function. It retrieves io_u's to process and queues
  * and reaps them, checking for rate and errors along the way.
+ *
+ * Returns number of bytes written and trimmed.
  */
-static void do_io(struct thread_data *td)
+static uint64_t do_io(struct thread_data *td)
 {
+	uint64_t bytes_done[DDIR_RWDIR_CNT] = { 0, 0, 0 };
 	unsigned int i;
 	int ret = 0;
 
@@ -607,7 +630,6 @@ static void do_io(struct thread_data *td)
 		(!flist_empty(&td->trim_list)) || !io_bytes_exceeded(td) ||
 		td->o.time_based) {
 		struct timeval comp_time;
-		unsigned long bytes_done[DDIR_RWDIR_CNT] = { 0, 0, 0 };
 		int min_evts = 0;
 		struct io_u *io_u;
 		int ret2, full;
@@ -811,6 +833,8 @@ sync_done:
 	 */
 	if (!ddir_rw_sum(td->this_io_bytes))
 		td->done = 1;
+
+	return bytes_done[DDIR_WRITE] + bytes_done[DDIR_TRIM];
 }
 
 static void cleanup_io_u(struct thread_data *td)
@@ -1190,7 +1214,7 @@ static void *thread_main(void *data)
 
 	clear_state = 0;
 	while (keep_running(td)) {
-		uint64_t write_bytes;
+		uint64_t verify_bytes;
 
 		fio_gettime(&td->start, NULL);
 		memcpy(&td->bw_sample_time, &td->start, sizeof(td->start));
@@ -1212,9 +1236,7 @@ static void *thread_main(void *data)
 
 		prune_io_piece_log(td);
 
-		write_bytes = td->io_bytes[DDIR_WRITE];
-		do_io(td);
-		write_bytes = td->io_bytes[DDIR_WRITE] - write_bytes;
+		verify_bytes = do_io(td);
 
 		clear_state = 1;
 
@@ -1243,7 +1265,7 @@ static void *thread_main(void *data)
 
 		fio_gettime(&td->start, NULL);
 
-		do_verify(td, write_bytes);
+		do_verify(td, verify_bytes);
 
 		td->ts.runtime[DDIR_READ] += utime_since_now(&td->start);
 
diff --git a/configure b/configure
index 08c8bd2..f730dfd 100755
--- a/configure
+++ b/configure
@@ -102,22 +102,20 @@ cpu=""
 
 cc="${CC-${cross_prefix}gcc}"
 
+# parse options
+for opt do
+  optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
+  case "$opt" in
+  --cc=*) CC="$optarg"
+  ;;
+  *)
+  echo "Bad option $opt"
+  exit 1
+  esac
+done
+
 if check_define __linux__ ; then
   targetos="Linux"
-elif test `uname -o` = Cygwin ; then
-  echo "Forcing known good options on Windows"
-  echo "CC=x86_64-w64-mingw32-gcc" >> $config_host_mak
-  echo "CONFIG_64BIT_LLP64=y"      >> $config_host_mak
-  echo "CONFIG_CLOCK_GETTIME=y"    >> $config_host_mak
-  echo "CONFIG_CLOCK_MONOTONIC=y"  >> $config_host_mak
-  echo "CONFIG_GETTIMEOFDAY=y"     >> $config_host_mak
-  echo "CONFIG_FADVISE=y"          >> $config_host_mak
-  echo "CONFIG_STRSEP=y"           >> $config_host_mak
-  echo "CONFIG_SOCKLEN_T=y"        >> $config_host_mak
-  echo "CONFIG_POSIX_FALLOCATE=y"  >> $config_host_mak
-  echo "CONFIG_FADVISE=y"          >> $config_host_mak
-  echo "CONFIG_SFAA=y"             >> $config_host_mak
-  exit 0
 elif check_define __OpenBSD__ ; then
   targetos='OpenBSD'
 elif check_define __sun__ ; then
@@ -146,6 +144,24 @@ SunOS)
   if test -z "$cpu" && test "$(isainfo -k)" = "amd64"; then
     cpu="x86_64"
   fi
+  ;;
+CYGWIN*)
+  echo "Forcing known good options on Windows"
+  if test -z "$CC" ; then
+    CC="x86_64-w64-mingw32-gcc"
+  fi
+  echo "CC=$CC"                    >  $config_host_mak
+  echo "CONFIG_LITTLE_ENDIAN=y"    >> $config_host_mak
+  echo "CONFIG_64BIT_LLP64=y"      >> $config_host_mak
+  echo "CONFIG_CLOCK_GETTIME=y"    >> $config_host_mak
+  echo "CONFIG_CLOCK_MONOTONIC=y"  >> $config_host_mak
+  echo "CONFIG_GETTIMEOFDAY=y"     >> $config_host_mak
+  echo "CONFIG_FADVISE=y"          >> $config_host_mak
+  echo "CONFIG_SOCKLEN_T=y"        >> $config_host_mak
+  echo "CONFIG_POSIX_FALLOCATE=y"  >> $config_host_mak
+  echo "CONFIG_FADVISE=y"          >> $config_host_mak
+  echo "CONFIG_SFAA=y"             >> $config_host_mak
+  exit 0
 esac
 
 if test ! -z "$cpu" ; then
@@ -226,8 +242,25 @@ fi
 
 cc="${CC-${cross_prefix}gcc}"
 
+##########################################
+# check endianness
+bigendian="no"
+cat > $TMPC <<EOF
+#include <inttypes.h>
+int main(void)
+{
+  volatile uint32_t i=0x01234567;
+  return (*((uint8_t*)(&i))) == 0x67;
+}
+EOF
+if compile_prog "" "" "endian"; then
+  $TMPE && bigendian="yes"
+fi
+
+
 echo "Operating system              $targetos"
 echo "CPU                           $cpu"
+echo "Big endian                    $bigendian"
 echo "Compiler                      $cc"
 echo
 
@@ -771,6 +804,11 @@ else
   echo "Unknown wordsize!"
   exit 1
 fi
+if test "$bigendian" = "yes" ; then
+  echo "CONFIG_BIG_ENDIAN=y" >> $config_host_mak
+else
+  echo "CONFIG_LITTLE_ENDIAN=y" >> $config_host_mak
+fi
 if test "$libaio" = "yes" ; then
   echo "CONFIG_LIBAIO=y" >> $config_host_mak
 fi
diff --git a/engines/net.c b/engines/net.c
index eb05bcc..de7cdb5 100644
--- a/engines/net.c
+++ b/engines/net.c
@@ -541,7 +541,7 @@ static void fio_netio_udp_close(struct thread_data *td, struct fio_file *f)
 	msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
 	msg.cmd = htonl(FIO_LINK_CLOSE);
 
-	ret = sendto(f->fd, &msg, sizeof(msg), MSG_WAITALL, to,
+	ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to,
 			sizeof(nd->addr));
 	if (ret < 0)
 		td_verror(td, errno, "sendto udp link close");
@@ -569,7 +569,7 @@ static int fio_netio_udp_recv_open(struct thread_data *td, struct fio_file *f)
 	socklen_t len = sizeof(nd->addr);
 	int ret;
 
-	ret = recvfrom(f->fd, &msg, sizeof(msg), MSG_WAITALL, to, &len);
+	ret = recvfrom(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to, &len);
 	if (ret < 0) {
 		td_verror(td, errno, "sendto udp link open");
 		return ret;
@@ -595,7 +595,7 @@ static int fio_netio_udp_send_open(struct thread_data *td, struct fio_file *f)
 	msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
 	msg.cmd = htonl(FIO_LINK_OPEN);
 
-	ret = sendto(f->fd, &msg, sizeof(msg), MSG_WAITALL, to,
+	ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to,
 			sizeof(nd->addr));
 	if (ret < 0) {
 		td_verror(td, errno, "sendto udp link open");
@@ -743,7 +743,7 @@ static int fio_netio_setup_listen_inet(struct thread_data *td, short port)
 	}
 
 	opt = 1;
-	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
+	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&opt, sizeof(opt)) < 0) {
 		td_verror(td, errno, "setsockopt");
 		return 1;
 	}
diff --git a/engines/posixaio.c b/engines/posixaio.c
index 0872f9a..a943e5b 100644
--- a/engines/posixaio.c
+++ b/engines/posixaio.c
@@ -19,13 +19,25 @@ struct posixaio_data {
 
 static int fill_timespec(struct timespec *ts)
 {
-#ifdef _POSIX_TIMERS
-	if (!clock_gettime(CLOCK_MONOTONIC, ts))
+#ifdef CONFIG_CLOCK_GETTIME
+#ifdef CONFIG_CLOCK_MONOTONIC
+	clockid_t clk = CLOCK_MONOTONIC;
+#else
+	clockid_t clk = CLOCK_REALTIME;
+#endif
+	if (!clock_gettime(clk, ts))
 		return 0;
 
 	perror("clock_gettime");
-#endif
 	return 1;
+#else
+	struct timeval tv;
+
+	gettimeofday(&tv, NULL);
+	ts->tv_sec = tv.tv_sec;
+	ts->tv_nsec = tv.tv_usec * 1000;
+	return 0;
+#endif
 }
 
 static unsigned long long ts_utime_since_now(struct timespec *t)
@@ -91,6 +103,8 @@ static int fio_posixaio_getevents(struct thread_data *td, unsigned int min,
 
 	if (t && !fill_timespec(&start))
 		have_timeout = 1;
+	else
+		memset(&start, 0, sizeof(start));
 
 	r = 0;
 	memset(suspend_list, 0, sizeof(*suspend_list));
diff --git a/eta.c b/eta.c
index 1f67301..fdf55c5 100644
--- a/eta.c
+++ b/eta.c
@@ -140,13 +140,19 @@ static int thread_eta(struct thread_data *td)
 	}
 
 	/*
-	 * if writing, bytes_total will be twice the size. If mixing,
-	 * assume a 50/50 split and thus bytes_total will be 50% larger.
+	 * if writing and verifying afterwards, bytes_total will be twice the
+	 * size. In a mixed workload, verify phase will be the size of the
+	 * first stage writes.
 	 */
 	if (td->o.do_verify && td->o.verify && td_write(td)) {
-		if (td_rw(td))
-			bytes_total = bytes_total * 3 / 2;
-		else
+		if (td_rw(td)) {
+			unsigned int perc = 50;
+
+			if (td->o.rwmix[DDIR_WRITE])
+				perc = td->o.rwmix[DDIR_WRITE];
+
+			bytes_total += (bytes_total * perc) / 100;
+		} else
 			bytes_total <<= 1;
 	}
 
diff --git a/fio.c b/fio.c
index 24af397..a408727 100644
--- a/fio.c
+++ b/fio.c
@@ -53,10 +53,10 @@ static int endian_check(void)
 	else if (u.c[0] == 0x12)
 		le = 1;
 
-#if defined(FIO_LITTLE_ENDIAN)
+#if defined(CONFIG_LITTLE_ENDIAN)
 	if (be)
 		return 1;
-#elif defined(FIO_BIG_ENDIAN)
+#elif defined(CONFIG_BIG_ENDIAN)
 	if (le)
 		return 1;
 #else
diff --git a/fio.h b/fio.h
index ed793ae..1ff384f 100644
--- a/fio.h
+++ b/fio.h
@@ -792,7 +792,7 @@ static inline int __should_check_rate(struct thread_data *td,
 }
 
 static inline int should_check_rate(struct thread_data *td,
-				    unsigned long *bytes_done)
+				    uint64_t *bytes_done)
 {
 	int ret = 0;
 
diff --git a/init.c b/init.c
index 15b5411..fca74fe 100644
--- a/init.c
+++ b/init.c
@@ -706,7 +706,6 @@ void td_fill_rand_seeds(struct thread_data *td)
 	init_rand_seed(&td->buf_state, td->rand_seeds[FIO_RAND_BUF_OFF]);
 }
 
-
 /*
  * Initializes the ioengine configured for a job, if it has not been done so
  * already.
@@ -781,6 +780,26 @@ static void init_flags(struct thread_data *td)
 		td->flags |= TD_F_VER_NONE;
 }
 
+static int setup_random_seeds(struct thread_data *td)
+{
+	unsigned long seed;
+	unsigned int i;
+
+	if (!td->o.rand_repeatable)
+		return init_random_state(td, td->rand_seeds, sizeof(td->rand_seeds));
+
+	for (seed = 0x89, i = 0; i < 4; i++)
+		seed *= 0x9e370001UL;
+
+	for (i = 0; i < FIO_RAND_NR_OFFS; i++) {
+		td->rand_seeds[i] = seed;
+		seed *= 0x9e370001UL;
+	}
+
+	td_fill_rand_seeds(td);
+	return 0;
+}
+
 /*
  * Adds a job to the list of things todo. Sanitizes the various options
  * to make sure we don't have conflicts, and initializes various
@@ -883,7 +902,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num)
 	td->groupid = groupid;
 	prev_group_jobs++;
 
-	if (init_random_state(td, td->rand_seeds, sizeof(td->rand_seeds))) {
+	if (setup_random_seeds(td)) {
 		td_verror(td, errno, "init_random_state");
 		goto err;
 	}
@@ -1622,6 +1641,9 @@ int parse_cmd_line(int argc, char *argv[])
 			do_exit++;
 			exit_val = fio_monotonic_clocktest();
 			break;
+		case '?':
+			log_err("%s: unrecognized option '%s'\n", argv[0],
+							argv[optind - 1]);
 		default:
 			do_exit++;
 			exit_val = 1;
diff --git a/io_u.c b/io_u.c
index f020cac..6ae3eae 100644
--- a/io_u.c
+++ b/io_u.c
@@ -16,7 +16,7 @@ struct io_completion_data {
 	int nr;				/* input */
 
 	int error;			/* output */
-	unsigned long bytes_done[DDIR_RWDIR_CNT];	/* output */
+	uint64_t bytes_done[DDIR_RWDIR_CNT];	/* output */
 	struct timeval time;		/* output */
 };
 
@@ -172,19 +172,31 @@ static int get_off_from_method(struct thread_data *td, struct fio_file *f,
 	return 1;
 }
 
+/*
+ * Sort the reads for a verify phase in batches of verifysort_nr, if
+ * specified.
+ */
+static inline int should_sort_io(struct thread_data *td)
+{
+	if (!td->o.verifysort_nr || !td->o.do_verify)
+		return 0;
+	if (!td_random(td))
+		return 0;
+	if (td->runstate != TD_VERIFYING)
+		return 0;
+	if (td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE)
+		return 0;
+
+	return 1;
+}
+
 static int get_next_rand_offset(struct thread_data *td, struct fio_file *f,
 				enum fio_ddir ddir, uint64_t *b)
 {
 	struct rand_off *r;
 	int i, ret = 1;
 
-	/*
-	 * If sort not enabled, or not a pure random read workload without
-	 * any stored write metadata, just return a random offset
-	 */
-	if (!td->o.verifysort_nr || !(ddir == DDIR_READ && td->o.do_verify &&
-	    td->o.verify != VERIFY_NONE && td_random(td)) ||
-	    td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE)
+	if (!should_sort_io(td))
 		return get_off_from_method(td, f, ddir, b);
 
 	if (!flist_empty(&td->next_rand_list)) {
@@ -546,12 +558,6 @@ static enum fio_ddir get_rw_ddir(struct thread_data *td)
 	enum fio_ddir ddir;
 
 	/*
-	 * If verify phase started, it's always a READ
-	 */
-	if (td->runstate == TD_VERIFYING)
-		return DDIR_READ;
-
-	/*
 	 * see if it's time to fsync
 	 */
 	if (td->o.fsync_blocks &&
@@ -606,7 +612,7 @@ static enum fio_ddir get_rw_ddir(struct thread_data *td)
 
 static void set_rw_ddir(struct thread_data *td, struct io_u *io_u)
 {
-	io_u->ddir = get_rw_ddir(td);
+	io_u->ddir = io_u->acct_ddir = get_rw_ddir(td);
 
 	if (io_u->ddir == DDIR_WRITE && (td->io_ops->flags & FIO_BARRIER) &&
 	    td->o.barrier_blocks &&
@@ -650,14 +656,15 @@ void clear_io_u(struct thread_data *td, struct io_u *io_u)
 void requeue_io_u(struct thread_data *td, struct io_u **io_u)
 {
 	struct io_u *__io_u = *io_u;
+	enum fio_ddir ddir = acct_ddir(__io_u);
 
 	dprint(FD_IO, "requeue %p\n", __io_u);
 
 	td_io_u_lock(td);
 
 	__io_u->flags |= IO_U_F_FREE;
-	if ((__io_u->flags & IO_U_F_FLIGHT) && ddir_rw(__io_u->ddir))
-		td->io_issues[__io_u->ddir]--;
+	if ((__io_u->flags & IO_U_F_FLIGHT) && ddir_rw(ddir))
+		td->io_issues[ddir]--;
 
 	__io_u->flags &= ~IO_U_F_FLIGHT;
 	if (__io_u->flags & IO_U_F_IN_CUR_DEPTH)
@@ -719,13 +726,9 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u)
 	if (td_random(td) && file_randommap(td, io_u->file))
 		mark_random_map(td, io_u);
 
-	/*
-	 * If using a write iolog, store this entry.
-	 */
 out:
 	dprint_io_u(io_u, "fill_io_u");
 	td->zone_bytes += io_u->buflen;
-	log_io_u(td, io_u);
 	return 0;
 }
 
@@ -1091,6 +1094,7 @@ again:
 		io_u->flags &= ~IO_U_F_VER_LIST;
 
 		io_u->error = 0;
+		io_u->acct_ddir = -1;
 		flist_del(&io_u->list);
 		flist_add_tail(&io_u->list, &td->io_u_busylist);
 		td->cur_depth++;
@@ -1489,7 +1493,7 @@ static void ios_completed(struct thread_data *td,
  * Complete a single io_u for the sync engines.
  */
 int io_u_sync_complete(struct thread_data *td, struct io_u *io_u,
-		       unsigned long *bytes)
+		       uint64_t *bytes)
 {
 	struct io_completion_data icd;
 
@@ -1518,7 +1522,7 @@ int io_u_sync_complete(struct thread_data *td, struct io_u *io_u,
  * Called to complete min_events number of io for the async engines.
  */
 int io_u_queued_complete(struct thread_data *td, int min_evts,
-			 unsigned long *bytes)
+			 uint64_t *bytes)
 {
 	struct io_completion_data icd;
 	struct timespec *tvp = NULL;
diff --git a/ioengine.h b/ioengine.h
index 6809501..7299636 100644
--- a/ioengine.h
+++ b/ioengine.h
@@ -8,7 +8,7 @@
 #include <guasi.h>
 #endif
 
-#define FIO_IOOPS_VERSION	14
+#define FIO_IOOPS_VERSION	15
 
 enum {
 	IO_U_F_FREE		= 1 << 0,
@@ -57,6 +57,12 @@ struct io_u {
 	enum fio_ddir ddir;
 
 	/*
+	 * For replay workloads, we may want to account as a different
+	 * IO type than what is being submitted.
+	 */
+	enum fio_ddir acct_ddir;
+
+	/*
 	 * Allocated/set buffer and length
 	 */
 	unsigned long buflen;
@@ -179,8 +185,8 @@ extern struct io_u *get_io_u(struct thread_data *);
 extern void put_io_u(struct thread_data *, struct io_u *);
 extern void clear_io_u(struct thread_data *, struct io_u *);
 extern void requeue_io_u(struct thread_data *, struct io_u **);
-extern int __must_check io_u_sync_complete(struct thread_data *, struct io_u *, unsigned long *);
-extern int __must_check io_u_queued_complete(struct thread_data *, int, unsigned long *);
+extern int __must_check io_u_sync_complete(struct thread_data *, struct io_u *, uint64_t *);
+extern int __must_check io_u_queued_complete(struct thread_data *, int, uint64_t *);
 extern void io_u_queued(struct thread_data *, struct io_u *);
 extern void io_u_log_error(struct thread_data *, struct io_u *);
 extern void io_u_mark_depth(struct thread_data *, unsigned int);
@@ -210,4 +216,12 @@ static inline void dprint_io_u(struct io_u *io_u, const char *p)
 #define dprint_io_u(io_u, p)
 #endif
 
+static inline enum fio_ddir acct_ddir(struct io_u *io_u)
+{
+	if (io_u->acct_ddir != -1)
+		return io_u->acct_ddir;
+
+	return io_u->ddir;
+}
+
 #endif
diff --git a/ioengines.c b/ioengines.c
index f81c46f..234f8ed 100644
--- a/ioengines.c
+++ b/ioengines.c
@@ -260,6 +260,11 @@ int td_io_queue(struct thread_data *td, struct io_u *io_u)
 
 	assert(fio_file_open(io_u->file));
 
+	/*
+	 * If using a write iolog, store this entry.
+	 */
+	log_io_u(td, io_u);
+
 	io_u->error = 0;
 	io_u->resid = 0;
 
@@ -275,8 +280,8 @@ int td_io_queue(struct thread_data *td, struct io_u *io_u)
 					sizeof(struct timeval));
 	}
 
-	if (ddir_rw(io_u->ddir))
-		td->io_issues[io_u->ddir]++;
+	if (ddir_rw(acct_ddir(io_u)))
+		td->io_issues[acct_ddir(io_u)]++;
 
 	ret = td->io_ops->queue(td, io_u);
 
diff --git a/lib/axmap.c b/lib/axmap.c
index d9ad30b..533a155 100644
--- a/lib/axmap.c
+++ b/lib/axmap.c
@@ -48,6 +48,7 @@ struct axmap {
 	unsigned int nr_levels;
 	struct axmap_level *levels;
 	uint64_t first_free;
+	uint64_t nr_bits;
 };
 
 static unsigned long ulog64(unsigned long val, unsigned int log)
@@ -103,6 +104,7 @@ struct axmap *axmap_new(unsigned long nr_bits)
 
 	axmap->nr_levels = levels;
 	axmap->levels = smalloc(axmap->nr_levels * sizeof(struct axmap_level));
+	axmap->nr_bits = nr_bits;
 
 	for (i = 0; i < axmap->nr_levels; i++) {
 		struct axmap_level *al = &axmap->levels[i];
@@ -261,6 +263,11 @@ static void __axmap_set(struct axmap *axmap, uint64_t bit_nr,
 	    axmap->first_free < bit_nr + data->nr_bits)
 		axmap->first_free = -1ULL;
 
+	if (bit_nr > axmap->nr_bits)
+		return;
+	else if (bit_nr + nr_bits > axmap->nr_bits)
+		nr_bits = axmap->nr_bits - bit_nr;
+
 	set_bits = 0;
 	while (nr_bits) {
 		axmap_handler(axmap, bit_nr, axmap_set_fn, data);
@@ -302,12 +309,16 @@ static int axmap_isset_fn(struct axmap_level *al, unsigned long offset,
 
 int axmap_isset(struct axmap *axmap, uint64_t bit_nr)
 {
-	return axmap_handler_topdown(axmap, bit_nr, axmap_isset_fn, NULL);
+	if (bit_nr <= axmap->nr_bits)
+		return axmap_handler_topdown(axmap, bit_nr, axmap_isset_fn, NULL);
+
+	return 0;
 }
 
 static uint64_t axmap_find_first_free(struct axmap *axmap, unsigned int level,
 				       uint64_t index)
 {
+	uint64_t ret = -1ULL;
 	unsigned long j;
 	int i;
 
@@ -317,8 +328,11 @@ static uint64_t axmap_find_first_free(struct axmap *axmap, unsigned int level,
 	for (i = level; i >= 0; i--) {
 		struct axmap_level *al = &axmap->levels[i];
 
+		/*
+		 * Clear 'ret', this is a bug condition.
+		 */
 		if (index >= al->map_size) {
-			index = -1ULL;
+			ret = -1ULL;
 			break;
 		}
 
@@ -330,12 +344,15 @@ static uint64_t axmap_find_first_free(struct axmap *axmap, unsigned int level,
 			 * First free bit here is our index into the first
 			 * free bit at the next higher level
 			 */
-			index = (j << UNIT_SHIFT) + ffz(al->map[j]);
+			ret = index = (j << UNIT_SHIFT) + ffz(al->map[j]);
 			break;
 		}
 	}
 
-	return index;
+	if (ret < axmap->nr_bits)
+		return ret;
+
+	return (uint64_t) -1ULL;
 }
 
 uint64_t axmap_first_free(struct axmap *axmap)
diff --git a/lib/bswap.h b/lib/bswap.h
index 30fcac5..1fe5194 100644
--- a/lib/bswap.h
+++ b/lib/bswap.h
@@ -3,7 +3,7 @@
 
 #include <inttypes.h>
 
-#if __BYTE_ORDER == __LITTLE_ENDIAN
+#ifdef CONFIG_LITTLE_ENDIAN
 static inline uint32_t __be32_to_cpu(uint32_t val)
 {
 	uint32_t c1, c2, c3, c4;
diff --git a/libfio.c b/libfio.c
index 8255072..ac629dc 100644
--- a/libfio.c
+++ b/libfio.c
@@ -67,6 +67,7 @@ static const char *fio_arch_strings[arch_nr] = {
 static void reset_io_counters(struct thread_data *td)
 {
 	int ddir;
+
 	for (ddir = 0; ddir < DDIR_RWDIR_CNT; ddir++) {
 		td->stat_io_bytes[ddir] = 0;
 		td->this_io_bytes[ddir] = 0;
@@ -74,10 +75,12 @@ static void reset_io_counters(struct thread_data *td)
 		td->this_io_blocks[ddir] = 0;
 		td->rate_bytes[ddir] = 0;
 		td->rate_blocks[ddir] = 0;
+		td->io_issues[ddir] = 0;
 	}
 	td->zone_bytes = 0;
 
 	td->last_was_sync = 0;
+	td->rwmix_issues = 0;
 
 	/*
 	 * reset file done count if we are to start over
diff --git a/os/os-aix.h b/os/os-aix.h
index 01b2bdb..3d67765 100644
--- a/os/os-aix.h
+++ b/os/os-aix.h
@@ -19,12 +19,6 @@
 #define OS_MAP_ANON		MAP_ANON
 #define OS_MSG_DONTWAIT		0
 
-#if BYTE_ORDER == BIG_ENDIAN
-#define FIO_BIG_ENDIAN
-#else
-#define FIO_LITTLE_ENDIAN
-#endif
-
 #define FIO_USE_GENERIC_SWAP
 
 static inline int blockdev_invalidate_cache(struct fio_file *f)
diff --git a/os/os-android.h b/os/os-android.h
index e78a95b..e436f8f 100644
--- a/os/os-android.h
+++ b/os/os-android.h
@@ -13,7 +13,6 @@
 #include <sched.h>
 #include <linux/unistd.h>
 #include <linux/major.h>
-#include <endian.h>
 
 #include "binject.h"
 #include "../file.h"
@@ -134,14 +133,6 @@ static inline long os_random_long(os_random_state_t *rs)
 #define FIO_O_NOATIME	0
 #endif
 
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define FIO_LITTLE_ENDIAN
-#elif __BYTE_ORDER == __BIG_ENDIAN
-#define FIO_BIG_ENDIAN
-#else
-#error "Unknown endianness"
-#endif
-
 #define fio_swap16(x)	__bswap_16(x)
 #define fio_swap32(x)	__bswap_32(x)
 #define fio_swap64(x)	__bswap_64(x)
diff --git a/os/os-freebsd.h b/os/os-freebsd.h
index 5012600..c55a7c3 100644
--- a/os/os-freebsd.h
+++ b/os/os-freebsd.h
@@ -7,7 +7,6 @@
 #include <sys/sysctl.h>
 #include <sys/disk.h>
 #include <sys/thr.h>
-#include <sys/endian.h>
 #include <sys/socket.h>
 
 #include "../file.h"
@@ -20,12 +19,6 @@
 
 #define OS_MAP_ANON		MAP_ANON
 
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define FIO_LITTLE_ENDIAN
-#else
-#define FIO_BIG_ENDIAN
-#endif
-
 #define fio_swap16(x)	bswap16(x)
 #define fio_swap32(x)	bswap32(x)
 #define fio_swap64(x)	bswap64(x)
diff --git a/os/os-hpux.h b/os/os-hpux.h
index b4d677a..82acd11 100644
--- a/os/os-hpux.h
+++ b/os/os-hpux.h
@@ -33,20 +33,10 @@
 #define POSIX_MADV_RANDOM	MADV_RANDOM
 #define posix_madvise(ptr, sz, hint)	madvise((ptr), (sz), (hint))
 
-#ifndef CLOCK_MONOTONIC
-#define CLOCK_MONOTONIC		CLOCK_REALTIME
-#endif
-
 #ifndef MSG_WAITALL
 #define MSG_WAITALL	0x40
 #endif
 
-#ifdef LITTLE_ENDIAN
-#define FIO_LITTLE_ENDIAN
-#else
-#define FIO_BIG_ENDIAN
-#endif
-
 #define FIO_USE_GENERIC_SWAP
 
 #define FIO_OS_HAVE_AIOCB_TYPEDEF
diff --git a/os/os-linux.h b/os/os-linux.h
index d7eec0f..4e837da 100644
--- a/os/os-linux.h
+++ b/os/os-linux.h
@@ -15,7 +15,6 @@
 #include <linux/unistd.h>
 #include <linux/raw.h>
 #include <linux/major.h>
-#include <endian.h>
 
 #include "binject.h"
 #include "../file.h"
@@ -194,14 +193,6 @@ static inline int fio_lookup_raw(dev_t dev, int *majdev, int *mindev)
 #define FIO_MADV_FREE	MADV_REMOVE
 #endif
 
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define FIO_LITTLE_ENDIAN
-#elif __BYTE_ORDER == __BIG_ENDIAN
-#define FIO_BIG_ENDIAN
-#else
-#error "Unknown endianness"
-#endif
-
 #define fio_swap16(x)	__bswap_16(x)
 #define fio_swap32(x)	__bswap_32(x)
 #define fio_swap64(x)	__bswap_64(x)
diff --git a/os/os-mac.h b/os/os-mac.h
index 0f351a7..d202e99 100644
--- a/os/os-mac.h
+++ b/os/os-mac.h
@@ -16,14 +16,6 @@
 
 #include "../file.h"
 
-#ifndef CLOCK_MONOTONIC
-#define CLOCK_MONOTONIC 1
-#endif
-
-#ifndef CLOCK_REALTIME
-#define CLOCK_REALTIME 1
-#endif
-
 #define FIO_USE_GENERIC_RAND
 #define FIO_USE_GENERIC_INIT_RANDOM_STATE
 #define FIO_HAVE_GETTID
@@ -31,14 +23,6 @@
 
 #define OS_MAP_ANON		MAP_ANON
 
-#if defined(__LITTLE_ENDIAN__)
-#define FIO_LITTLE_ENDIAN
-#elif defined(__BIG_ENDIAN__)
-#define FIO_BIG_ENDIAN
-#else
-#error "Undefined byte order"
-#endif
-
 #define fio_swap16(x)	OSSwapInt16(x)
 #define fio_swap32(x)	OSSwapInt32(x)
 #define fio_swap64(x)	OSSwapInt64(x)
@@ -177,4 +161,11 @@ static inline int gettid(void)
 {
 	return mach_thread_self();
 }
+
+/*
+ * For some reason, there's no header definition for fdatasync(), even
+ * if it exists.
+ */
+extern int fdatasync(int fd);
+
 #endif
diff --git a/os/os-netbsd.h b/os/os-netbsd.h
index 1753226..4b0269e 100644
--- a/os/os-netbsd.h
+++ b/os/os-netbsd.h
@@ -6,7 +6,6 @@
 #include <errno.h>
 #include <lwp.h>
 #include <sys/param.h>
-#include <sys/endian.h>
 /* XXX hack to avoid confilcts between rbtree.h and <sys/rb.h> */
 #define	rb_node	_rb_node
 #include <sys/sysctl.h>
@@ -30,12 +29,6 @@
 #define PTHREAD_STACK_MIN 4096
 #endif
 
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define FIO_LITTLE_ENDIAN
-#else
-#define FIO_BIG_ENDIAN
-#endif
-
 #define fio_swap16(x)	bswap16(x)
 #define fio_swap32(x)	bswap32(x)
 #define fio_swap64(x)	bswap64(x)
diff --git a/os/os-solaris.h b/os/os-solaris.h
index 7dd62a7..de59f77 100644
--- a/os/os-solaris.h
+++ b/os/os-solaris.h
@@ -25,12 +25,6 @@
 #define OS_MAP_ANON		MAP_ANON
 #define OS_RAND_MAX		2147483648UL
 
-#if defined(_BIG_ENDIAN)
-#define FIO_BIG_ENDIAN
-#else
-#define FIO_LITTLE_ENDIAN
-#endif
-
 #define fio_swap16(x)	BSWAP_16(x)
 #define fio_swap32(x)	BSWAP_32(x)
 #define fio_swap64(x)	BSWAP_64(x)
diff --git a/os/os-windows.h b/os/os-windows.h
index 6862226..f68f654 100644
--- a/os/os-windows.h
+++ b/os/os-windows.h
@@ -15,6 +15,8 @@
 #include "../file.h"
 #include "../log.h"
 
+#include "windows/posix.h"
+
 #define FIO_HAVE_ODIRECT
 #define FIO_HAVE_CPU_AFFINITY
 #define FIO_HAVE_CHARDEV_SIZE
@@ -32,14 +34,10 @@
 
 #define OS_MAP_ANON		MAP_ANON
 
-#define FIO_LITTLE_ENDIAN
 #define fio_swap16(x)	_byteswap_ushort(x)
 #define fio_swap32(x)	_byteswap_ulong(x)
 #define fio_swap64(x)	_byteswap_uint64(x)
 
-typedef off_t off64_t;
-typedef int clockid_t;
-
 typedef DWORD_PTR os_cpu_mask_t;
 
 #define CLOCK_REALTIME	1
diff --git a/os/os.h b/os/os.h
index a14d7f0..f33a7cd 100644
--- a/os/os.h
+++ b/os/os.h
@@ -137,7 +137,7 @@ typedef unsigned int socklen_t;
 #endif
 
 #ifndef FIO_OS_HAS_CTIME_R
-#define os_ctime_r(x, y, z)     ctime_r((x), (y))
+#define os_ctime_r(x, y, z)     (void) ctime_r((x), (y))
 #endif
 
 #ifdef FIO_USE_GENERIC_SWAP
@@ -165,7 +165,7 @@ static inline uint64_t fio_swap64(uint64_t val)
 #endif
 
 #ifndef FIO_HAVE_BYTEORDER_FUNCS
-#ifdef FIO_LITTLE_ENDIAN
+#ifdef CONFIG_LITTLE_ENDIAN
 #define __le16_to_cpu(x)		(x)
 #define __le32_to_cpu(x)		(x)
 #define __le64_to_cpu(x)		(x)
diff --git a/os/windows/posix.c b/os/windows/posix.c
index f5d5300..67e71c8 100755
--- a/os/windows/posix.c
+++ b/os/windows/posix.c
@@ -628,39 +628,6 @@ long long strtoll(const char *restrict str, char **restrict endptr,
 	return _strtoi64(str, endptr, base);
 }
 
-char *strsep(char **stringp, const char *delim)
-{
-	char *orig = *stringp;
-	BOOL gotMatch = FALSE;
-	int i = 0;
-	int j = 0;
-
-	if (*stringp == NULL)
-		return NULL;
-
-	while ((*stringp)[i] != '\0') {
-		j = 0;
-		while (delim[j] != '\0') {
-			if ((*stringp)[i] == delim[j]) {
-				gotMatch = TRUE;
-				(*stringp)[i] = '\0';
-				*stringp = *stringp + i + 1;
-				break;
-			}
-			j++;
-		}
-		if (gotMatch)
-			break;
-
-		i++;
-	}
-
-	if (!gotMatch)
-		*stringp = NULL;
-
-	return orig;
-}
-
 int poll(struct pollfd fds[], nfds_t nfds, int timeout)
 {
 	struct timeval tv;
diff --git a/os/windows/posix.h b/os/windows/posix.h
new file mode 100644
index 0000000..cb89cf6
--- /dev/null
+++ b/os/windows/posix.h
@@ -0,0 +1,10 @@
+#ifndef FIO_WINDOWS_POSIX_H
+#define FIO_WINDOWS_POSIX_H
+
+typedef off_t off64_t;
+typedef int clockid_t;
+
+extern int clock_gettime(clockid_t clock_id, struct timespec *tp);
+extern int inet_aton(const char *, struct in_addr *);
+
+#endif
diff --git a/server.c b/server.c
index ffa6ed4..3607ee8 100644
--- a/server.c
+++ b/server.c
@@ -403,7 +403,7 @@ static int handle_probe_cmd(struct fio_net_cmd *cmd)
 
 	memset(&probe, 0, sizeof(probe));
 	gethostname((char *) probe.hostname, sizeof(probe.hostname));
-#ifdef FIO_BIG_ENDIAN
+#ifdef CONFIG_BIG_ENDIAN
 	probe.bigendian = 1;
 #endif
 	strncpy((char *) probe.fio_version, fio_version_string, sizeof(probe.fio_version));
@@ -829,7 +829,7 @@ static int fio_init_server_ip(void)
 	}
 
 	opt = 1;
-	if (setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
+	if (setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt)) < 0) {
 		log_err("fio: setsockopt: %s\n", strerror(errno));
 		close(sk);
 		return -1;
diff --git a/t/axmap.c b/t/axmap.c
index 3f6043d..27fdaa7 100644
--- a/t/axmap.c
+++ b/t/axmap.c
@@ -6,10 +6,7 @@
 #include <inttypes.h>
 
 #include "../lib/lfsr.h"
-
-struct axmap;
-void axmap_set(struct axmap *, uint64_t);
-struct axmap *axmap_new(uint64_t size);
+#include "../lib/axmap.h"
 
 void *smalloc(size_t size)
 {
@@ -24,8 +21,9 @@ void sfree(void *ptr)
 int main(int argc, char *argv[])
 {
 	struct fio_lfsr lfsr;
-	size_t size = (1UL << 28) - 200;
+	size_t osize, size = (1UL << 28) - 200;
 	struct axmap *map;
+	uint64_t ff;
 	int seed = 1;
 
 	if (argc > 1) {
@@ -38,13 +36,23 @@ int main(int argc, char *argv[])
 
 	lfsr_init(&lfsr, size, seed);
 	map = axmap_new(size);
+	osize = size;
 
 	while (size--) {
 		uint64_t val;
 
-		lfsr_next(&lfsr, &val);
+		if (lfsr_next(&lfsr, &val, osize)) {
+			printf("lfsr: short loop\n");
+			break;
+		}
 		axmap_set(map, val);
 	}
 
+	ff = axmap_next_free(map, osize);
+	if (ff != (uint64_t) -1ULL) {
+		printf("axmap_next_free broken: got %llu\n", (unsigned long long) ff);
+		return 1;
+	}
+
 	return 0;
 }
--
To unsubscribe from this list: send the line "unsubscribe fio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel]     [Linux SCSI]     [Linux IDE]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux