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.
                        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
                
 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 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;
        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 "fio.h"
 #include "parse.h"
+#include "fls.h"
 
 #define td_var_offset(var)     ((size_t) &((struct thread_options *)0)->var)
 
 
 #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;
 }
 
        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)
 
 #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, 
        },
                .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,
        {
                .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"
 
 
 #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;
 {
        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;
 {
        struct verify_header swap;
+
        memcpy(&swap, buf1, len);
        memcpy(buf1, buf2, len);
        memcpy(buf2, &swap, len);
        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;
 
        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)
 
        hdr_inc = io_u->buflen;
        if (td->o.verify_interval)