Add verify_pattern option
authorJens Axboe <jens.axboe@oracle.com>
Mon, 30 Jul 2007 07:33:12 +0000 (09:33 +0200)
committerJens Axboe <jens.axboe@oracle.com>
Mon, 30 Jul 2007 07:33:12 +0000 (09:33 +0200)
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
HOWTO
fio.h
fls.h [new file with mode: 0644]
options.c
verify.c

diff --git a/HOWTO b/HOWTO
index a07cf8848923245891b9c76bc3778e5c460a6856..58e12819e7f5868f5adb12eac6e5949784266227 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -612,6 +612,14 @@ verify_interval=siint      Write the verification header at a finer granularity
                        than the blocksize. It will be written for chunks the
                        size of header_interval. blocksize should divide this
                        evenly.
+
+verify_pattern=int     If set, fio will fill the io buffers with this
+               pattern. Fio defaults to filling with totally random
+               bytes, but sometimes it's interesting to fill with a known
+               pattern for io verification purposes. Depending on the
+               width of the pattern, fio will fill 1/2/3/4 bytes of the
+               buffer at the time. The verify_pattern cannot be larger than
+               a 32-bit quantity.
                
 stonewall      Wait for preceeding jobs in the job file to exit, before
                starting this one. Can be used to insert serialization
diff --git a/fio.h b/fio.h
index eb36d1cfd01a2e06a2305c96d76b460ee18c2d40..2ca800bf1a618e7144b84b474f8564437e5f6ceb 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -397,6 +397,8 @@ struct thread_options {
        unsigned int verifysort;
        unsigned int verify_interval;
        unsigned int verify_offset;
+       unsigned int verify_pattern;
+       unsigned int verify_pattern_bytes;
        unsigned int use_thread;
        unsigned int unlink;
        unsigned int do_disk_util;
diff --git a/fls.h b/fls.h
new file mode 100644 (file)
index 0000000..850859b
--- /dev/null
+++ b/fls.h
@@ -0,0 +1,41 @@
+#ifndef _ASM_GENERIC_BITOPS_FLS_H_
+#define _ASM_GENERIC_BITOPS_FLS_H_
+
+/**
+ * fls - find last (most-significant) bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as ffs.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
+ */
+
+static inline int fls(int x)
+{
+       int r = 32;
+
+       if (!x)
+               return 0;
+       if (!(x & 0xffff0000u)) {
+               x <<= 16;
+               r -= 16;
+       }
+       if (!(x & 0xff000000u)) {
+               x <<= 8;
+               r -= 8;
+       }
+       if (!(x & 0xf0000000u)) {
+               x <<= 4;
+               r -= 4;
+       }
+       if (!(x & 0xc0000000u)) {
+               x <<= 2;
+               r -= 2;
+       }
+       if (!(x & 0x80000000u)) {
+               x <<= 1;
+               r -= 1;
+       }
+       return r;
+}
+
+#endif /* _ASM_GENERIC_BITOPS_FLS_H_ */
index 5a63f638ee74d4659aae9cd3558cd5196801d7e6..3112d65e5297f5fb66902c2c237abf7adf832ed6 100644 (file)
--- a/options.c
+++ b/options.c
@@ -8,6 +8,7 @@
 
 #include "fio.h"
 #include "parse.h"
+#include "fls.h"
 
 #define td_var_offset(var)     ((size_t) &((struct thread_options *)0)->var)
 
@@ -216,6 +217,24 @@ static int str_verify_offset_cb(void *data, unsigned int *off)
        return 0;
 }
 
+static int str_verify_pattern_cb(void *data, unsigned int *off)
+{
+       struct thread_data *td = data;
+       unsigned int msb;
+
+       msb = fls(*off);
+       if (msb <= 8)
+               td->o.verify_pattern_bytes = 1;
+       else if (msb <= 16)
+               td->o.verify_pattern_bytes = 2;
+       else if (msb <= 24)
+               td->o.verify_pattern_bytes = 3;
+       else
+               td->o.verify_pattern_bytes = 4;
+
+       td->o.verify_pattern = *off;
+       return 0;
+}
 
 #define __stringify_1(x)       #x
 #define __stringify(x)         __stringify_1(x)
@@ -630,6 +649,13 @@ static struct fio_option options[] = {
                .def    = "0",
                .cb     = str_verify_offset_cb, 
        },
+       {
+               .name   = "verify_pattern",
+               .type   = FIO_OPT_INT,
+               .cb     = str_verify_pattern_cb,
+               .maxval = UINT_MAX,
+               .help   = "Fill pattern for IO buffers",
+       },
        {
                .name   = "write_iolog",
                .type   = FIO_OPT_STR_STORE,
index d98dfcf4c52b8bd5a43411bb2cf8397c6fd0952d..5770b46112270252696a25575a21e14caaf07b44 100644 (file)
--- a/verify.c
+++ b/verify.c
@@ -8,8 +8,7 @@
 
 #include "fio.h"
 
-static void fill_random_bytes(struct thread_data *td,
-                             void *p, unsigned int len)
+static void fill_random_bytes(struct thread_data *td, void *p, unsigned int len)
 {
        unsigned int todo;
        int r;
@@ -32,9 +31,52 @@ static void fill_random_bytes(struct thread_data *td,
        }
 }
 
-void memswp(void* buf1, void* buf2, unsigned int len)
+static void fill_pattern(struct thread_data *td, void *p, unsigned int len)
+{
+       switch (td->o.verify_pattern_bytes) {
+       case 0:
+               fill_random_bytes(td, p, len);
+               break;
+       case 1:
+               memset(p, td->o.verify_pattern, len);
+               break;
+       case 2:
+       case 3:
+       case 4: {
+               unsigned int pattern = td->o.verify_pattern;
+               unsigned int i = 0;
+               unsigned char c1, c2, c3, c4;
+               unsigned char *b = p;
+
+               c1 = pattern & 0xff;
+               pattern >>= 8;
+               c2 = pattern & 0xff;
+               pattern >>= 8;
+               c3 = pattern & 0xff;
+               pattern >>= 8;
+               c4 = pattern & 0xff;
+
+               while (i < len) {
+                       b[i++] = c1;
+                       if (i == len)
+                               break;
+                       b[i++] = c2;
+                       if (td->o.verify_pattern_bytes == 2 || i == len)
+                               continue;
+                       b[i++] = c3;
+                       if (td->o.verify_pattern_bytes == 3 || i == len)
+                               continue;
+                       b[i++] = c4;
+               }
+               break;
+               }
+       }
+}
+
+static void memswp(void* buf1, void* buf2, unsigned int len)
 {
        struct verify_header swap;
+
        memcpy(&swap, buf1, len);
        memcpy(buf1, buf2, len);
        memcpy(buf2, &swap, len);
@@ -254,7 +296,7 @@ void populate_verify_io_u(struct thread_data *td, struct io_u *io_u)
        if (td->o.verify == VERIFY_NULL)
                return;
 
-       fill_random_bytes(td, p, io_u->buflen);
+       fill_pattern(td, p, io_u->buflen);
 
        hdr_inc = io_u->buflen;
        if (td->o.verify_interval)