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