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
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;
--- /dev/null
+#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_ */
#include "fio.h"
#include "parse.h"
+#include "fls.h"
#define td_var_offset(var) ((size_t) &((struct thread_options *)0)->var)
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)
.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,
#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;
}
}
-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);
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)