The following changes since commit c604fb8eea323d8dbf948f238f61f12dadf821af: Fio 1.41 (2010-06-18 14:49:46 +0200) are available in the git repository at: git://git.kernel.dk/fio.git master Jens Axboe (12): Fix a bug with multiple files in the same io_piece rbtree Fio 1.41.1 Do diskutil check earlier Fix disk util for slaves Fio 1.41.2 Add documentation for verify_backlog and verify_backlog_batch Cleanup up SIGILL for crc32c-intel Missing new line Auto-detect missing hw support for crc32c and fallback to software Documentation update Speedup verify random fills by 10-15x Fio 1.41.3 HOWTO | 20 +++++++++++++++++++- crc/crc32c-intel.c | 40 +++++++++++++++++++++++++++++++++++++++- crc/crc32c.h | 5 +++++ diskutil.c | 16 +++++++++++++--- fio.1 | 18 +++++++++++++++++- fio.c | 16 ---------------- init.c | 2 +- io_u.c | 20 ++++---------------- lib/rand.c | 17 +++++++++++++++++ lib/rand.h | 1 + log.c | 6 +++++- options.c | 18 ++++++++++++++++++ verify.c | 26 ++------------------------ 13 files changed, 141 insertions(+), 64 deletions(-) --- Diff of recent changes: diff --git a/HOWTO b/HOWTO index 19304ae..3e1e62a 100644 --- a/HOWTO +++ b/HOWTO @@ -823,7 +823,9 @@ verify=str If writing to a file, fio can verify the file contents it in the header of each block. crc32c-intel Use hardware assisted crc32c calcuation - provided on SSE4.2 enabled processors. + provided on SSE4.2 enabled processors. Falls + back to regular software crc32c, if not + supported by the system. crc32 Use a crc32 sum of the data area and store it in the header of each block. @@ -899,6 +901,22 @@ verify_async=int Fio will normally verify IO inline from the submitting verify_async_cpus=str Tell fio to set the given CPU affinity on the async IO verification threads. See cpus_allowed for the format used. + +verify_backlog=int Fio will normally verify the written contents of a + job that utilizes verify once that job has completed. In + other words, everything is written then everything is read + back and verified. You may want to verify continually + instead for a variety of reasons. Fio stores the meta data + associated with an IO block in memory, so for large + verify workloads, quite a bit of memory would be used up + holding this meta data. If this option is enabled, fio + will verify the previously written blocks before continuing + to write new ones. + +verify_backlog_batch=int Control how many blocks fio will verify + if verify_backlog is set. If not set, will default to + the value of verify_backlog (meaning the entire queue + is read back and verified). stonewall Wait for preceeding jobs in the job file to exit, before starting this one. Can be used to insert serialization diff --git a/crc/crc32c-intel.c b/crc/crc32c-intel.c index cec5ad5..fc106fa 100644 --- a/crc/crc32c-intel.c +++ b/crc/crc32c-intel.c @@ -1,4 +1,10 @@ #include <inttypes.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/wait.h> #include "crc32c.h" /* @@ -68,5 +74,37 @@ uint32_t crc32c_intel(unsigned char const *data, unsigned long length) return crc; } -#endif /* ARCH_HAVE_SSE */ +static void sig_ill(int sig) +{ +} + +static void crc32c_test(void) +{ + unsigned char buf[4] = { 1, 2, 3, 4 }; + struct sigaction act; + + /* + * Check if hw accelerated crc32c is available + */ + memset(&act, 0, sizeof(act)); + act.sa_handler = sig_ill; + act.sa_flags = SA_RESETHAND; + sigaction(SIGILL, &act, NULL); + + (void) crc32c_intel(buf, sizeof(buf)); +} + +int crc32c_intel_works(void) +{ + if (!fork()) { + crc32c_test(); + exit(0); + } else { + int status; + wait(&status); + return !WIFSIGNALED(status); + } +} + +#endif /* ARCH_HAVE_SSE */ diff --git a/crc/crc32c.h b/crc/crc32c.h index 0976261..50f3665 100644 --- a/crc/crc32c.h +++ b/crc/crc32c.h @@ -24,8 +24,13 @@ extern uint32_t crc32c(unsigned char const *, unsigned long); #ifdef ARCH_HAVE_SSE extern uint32_t crc32c_intel(unsigned char const *, unsigned long); +extern int crc32c_intel_works(void); #else #define crc32c_intel crc32c +static inline int crc32c_intel_works(void) +{ + return 0; +} #endif #endif diff --git a/diskutil.c b/diskutil.c index e90096b..4f705c9 100644 --- a/diskutil.c +++ b/diskutil.c @@ -24,6 +24,14 @@ static void disk_util_free(struct disk_util *du) if (du == last_du) last_du = NULL; + while (!flist_empty(&du->slaves)) { + struct disk_util *slave; + + slave = flist_entry(du->slaves.next, struct disk_util, slavelist); + flist_del(&slave->slavelist); + slave->users--; + } + fio_mutex_remove(du->lock); sfree(du->name); sfree(du); @@ -67,10 +75,10 @@ static void update_io_tick_disk(struct disk_util *du) struct disk_util_stat __dus, *dus, *ldus; struct timeval t; - if (get_io_ticks(du, &__dus)) - return; if (!du->users) return; + if (get_io_ticks(du, &__dus)) + return; dus = &du->dus; ldus = &du->last_dus; @@ -236,8 +244,10 @@ static void find_add_disk_slaves(struct thread_data *td, char *path, /* Should probably use an assert here. slavedu should * always be present at this point. */ - if (slavedu) + if (slavedu) { + slavedu->users++; flist_add_tail(&slavedu->slavelist, &masterdu->slaves); + } } closedir(dirhandle); diff --git a/fio.1 b/fio.1 index ac729df..e737906 100644 --- a/fio.1 +++ b/fio.1 @@ -602,7 +602,9 @@ values are: .RS .TP .B md5 crc16 crc32 crc32c crc32c-intel crc64 crc7 sha256 sha512 sha1 -Store appropriate checksum in the header of each block. +Store appropriate checksum in the header of each block. crc32c-intel is +hardware accelerated SSE4.2 driven, falls back to regular crc32c if +not supported by the system. .TP .B meta Write extra information about each I/O (timestamp, block number, etc.). The @@ -653,6 +655,20 @@ allows them to have IO in flight while verifies are running. Tell fio to set the given CPU affinity on the async IO verification threads. See \fBcpus_allowed\fP for the format used. .TP +.BI verify_backlog \fR=\fPint +Fio will normally verify the written contents of a job that utilizes verify +once that job has completed. In other words, everything is written then +everything is read back and verified. You may want to verify continually +instead for a variety of reasons. Fio stores the meta data associated with an +IO block in memory, so for large verify workloads, quite a bit of memory would +be used up holding this meta data. If this option is enabled, fio will verify +the previously written blocks before continuing to write new ones. +.TP +.BI verify_backlog_batch \fR=\fPint +Control how many blocks fio will verify if verify_backlog is set. If not set, +will default to the value of \fBverify_backlog\fR (meaning the entire queue is +read back and verified). +.TP .B stonewall Wait for preceeding jobs in the job file to exit before starting this one. \fBstonewall\fR implies \fBnew_group\fR. diff --git a/fio.c b/fio.c index ae62d23..b2a08bf 100644 --- a/fio.c +++ b/fio.c @@ -142,17 +142,6 @@ static void sig_int(int sig) } } -static void sig_ill(int fio_unused sig) -{ - if (!threads) - return; - - log_err("fio: illegal instruction. your cpu does not support " - "the sse4.2 instruction for crc32c\n"); - terminate_threads(TERMINATE_ALL); - exit(4); -} - static void set_sig_handlers(void) { struct sigaction act; @@ -168,11 +157,6 @@ static void set_sig_handlers(void) sigaction(SIGINT, &act, NULL); memset(&act, 0, sizeof(act)); - act.sa_handler = sig_ill; - act.sa_flags = SA_RESTART; - sigaction(SIGILL, &act, NULL); - - memset(&act, 0, sizeof(act)); act.sa_handler = sig_quit; act.sa_flags = SA_RESTART; sigaction(SIGQUIT, &act, NULL); diff --git a/init.c b/init.c index ae7a4d2..fad487d 100644 --- a/init.c +++ b/init.c @@ -21,7 +21,7 @@ #include "verify.h" #include "profile.h" -static char fio_version_string[] = "fio 1.41"; +static char fio_version_string[] = "fio 1.41.3"; #define FIO_RANDSEED (0xb1899bedUL) diff --git a/io_u.c b/io_u.c index f451d1a..69edd70 100644 --- a/io_u.c +++ b/io_u.c @@ -1240,20 +1240,8 @@ void io_u_queued(struct thread_data *td, struct io_u *io_u) void io_u_fill_buffer(struct thread_data *td, struct io_u *io_u, unsigned int max_bs) { - long *ptr = io_u->buf; - - if (!td->o.zero_buffers) { - unsigned long r = __rand(&__fio_rand_state); - - if (sizeof(int) != sizeof(*ptr)) - r *= (unsigned long) __rand(&__fio_rand_state); - - while ((void *) ptr - io_u->buf < max_bs) { - *ptr = r; - ptr++; - r *= GOLDEN_RATIO_PRIME; - r >>= 3; - } - } else - memset(ptr, 0, max_bs); + if (!td->o.zero_buffers) + fill_random_buf(io_u->buf, max_bs); + else + memset(io_u->buf, 0, max_bs); } diff --git a/lib/rand.c b/lib/rand.c index cecc4c2..839a6a9 100644 --- a/lib/rand.c +++ b/lib/rand.c @@ -34,6 +34,7 @@ */ #include "rand.h" +#include "../hash.h" struct frand_state __fio_rand_state; @@ -57,3 +58,19 @@ void init_rand(struct frand_state *state) __rand(state); __rand(state); } + +void fill_random_buf(void *buf, unsigned int len) +{ + unsigned long r = __rand(&__fio_rand_state); + long *ptr = buf; + + if (sizeof(int) != sizeof(*ptr)) + r *= (unsigned long) __rand(&__fio_rand_state); + + while ((void *) ptr - buf < len) { + *ptr = r; + ptr++; + r *= GOLDEN_RATIO_PRIME; + r >>= 3; + } +} diff --git a/lib/rand.h b/lib/rand.h index 363e7b6..573116c 100644 --- a/lib/rand.h +++ b/lib/rand.h @@ -19,5 +19,6 @@ static inline unsigned int __rand(struct frand_state *state) } extern void init_rand(struct frand_state *); +extern void fill_random_buf(void *buf, unsigned int len); #endif diff --git a/log.c b/log.c index 6a99c66..5fc8f64 100644 --- a/log.c +++ b/log.c @@ -219,7 +219,11 @@ restart: parent = *p; __ipo = rb_entry(parent, struct io_piece, rb_node); - if (ipo->offset < __ipo->offset) + if (ipo->file < __ipo->file) + p = &(*p)->rb_left; + else if (ipo->file > __ipo->file) + p = &(*p)->rb_right; + else if (ipo->offset < __ipo->offset) p = &(*p)->rb_left; else if (ipo->offset > __ipo->offset) p = &(*p)->rb_right; diff --git a/options.c b/options.c index f470b45..fb18748 100644 --- a/options.c +++ b/options.c @@ -16,6 +16,8 @@ #include "lib/fls.h" #include "options.h" +#include "crc/crc32c.h" + /* * Check if mmap/mmaphuge has a :/foo/bar/file at the end. If so, return that. */ @@ -225,6 +227,21 @@ static int str_mem_cb(void *data, const char *mem) return 0; } +static int str_verify_cb(void *data, const char *mem) +{ + struct thread_data *td = data; + + if (td->o.verify != VERIFY_CRC32C_INTEL) + return 0; + + if (!crc32c_intel_works()) { + log_info("fio: System does not support hw accelerated crc32c. Falling back to sw crc32c.\n"); + td->o.verify = VERIFY_CRC32C; + } + + return 0; +} + static int fio_clock_source_cb(void *data, const char *str) { struct thread_data *td = data; @@ -1298,6 +1315,7 @@ static struct fio_option options[FIO_MAX_OPTS] = { .type = FIO_OPT_STR, .off1 = td_var_offset(verify), .help = "Verify data written", + .cb = str_verify_cb, .def = "0", .posval = { { .ival = "0", diff --git a/verify.c b/verify.c index 6b54b70..265bd55 100644 --- a/verify.c +++ b/verify.c @@ -10,6 +10,7 @@ #include "fio.h" #include "verify.h" #include "smalloc.h" +#include "lib/rand.h" #include "crc/md5.h" #include "crc/crc64.h" @@ -21,35 +22,12 @@ #include "crc/sha512.h" #include "crc/sha1.h" -static void fill_random_bytes(struct thread_data *td, void *p, unsigned int len) -{ - unsigned int todo; - int r; - - while (len) { - r = os_random_long(&td->verify_state); - - /* - * lrand48_r seems to be broken and only fill the bottom - * 32-bits, even on 64-bit archs with 64-bit longs - */ - todo = sizeof(r); - if (todo > len) - todo = len; - - memcpy(p, &r, todo); - - len -= todo; - p += todo; - } -} - static void fill_pattern(struct thread_data *td, void *p, unsigned int len) { switch (td->o.verify_pattern_bytes) { case 0: dprint(FD_VERIFY, "fill random bytes len=%u\n", len); - fill_random_bytes(td, p, len); + fill_random_buf(p, len); break; case 1: dprint(FD_VERIFY, "fill verify pattern b=0 len=%u\n", len); -- 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