blob: 566c53c1f995c42d51f41f681df880005c6cc078 [file] [log] [blame]
Jens Axboee29d1b72006-10-18 15:43:15 +02001/*
2 * IO verification helpers
3 */
4#include <unistd.h>
5#include <fcntl.h>
6#include <string.h>
Jens Axboe97af62c2007-05-22 11:12:13 +02007#include <assert.h>
Jens Axboee29d1b72006-10-18 15:43:15 +02008
9#include "fio.h"
Jens Axboee29d1b72006-10-18 15:43:15 +020010
Jens Axboe90059d62007-07-30 09:33:12 +020011static void fill_random_bytes(struct thread_data *td, void *p, unsigned int len)
Jens Axboee29d1b72006-10-18 15:43:15 +020012{
13 unsigned int todo;
Jens Axboe4c5946c2007-07-26 11:55:10 +020014 int r;
Jens Axboee29d1b72006-10-18 15:43:15 +020015
16 while (len) {
Jens Axboe4c5946c2007-07-26 11:55:10 +020017 r = os_random_long(&td->verify_state);
Jens Axboee29d1b72006-10-18 15:43:15 +020018
19 /*
20 * lrand48_r seems to be broken and only fill the bottom
21 * 32-bits, even on 64-bit archs with 64-bit longs
22 */
23 todo = sizeof(r);
24 if (todo > len)
25 todo = len;
26
27 memcpy(p, &r, todo);
28
29 len -= todo;
30 p += todo;
31 }
32}
33
Jens Axboe90059d62007-07-30 09:33:12 +020034static void fill_pattern(struct thread_data *td, void *p, unsigned int len)
35{
36 switch (td->o.verify_pattern_bytes) {
37 case 0:
38 fill_random_bytes(td, p, len);
39 break;
40 case 1:
41 memset(p, td->o.verify_pattern, len);
42 break;
43 case 2:
44 case 3:
45 case 4: {
46 unsigned int pattern = td->o.verify_pattern;
47 unsigned int i = 0;
48 unsigned char c1, c2, c3, c4;
49 unsigned char *b = p;
50
51 c1 = pattern & 0xff;
52 pattern >>= 8;
53 c2 = pattern & 0xff;
54 pattern >>= 8;
55 c3 = pattern & 0xff;
56 pattern >>= 8;
57 c4 = pattern & 0xff;
58
59 while (i < len) {
60 b[i++] = c1;
61 if (i == len)
62 break;
63 b[i++] = c2;
64 if (td->o.verify_pattern_bytes == 2 || i == len)
65 continue;
66 b[i++] = c3;
67 if (td->o.verify_pattern_bytes == 3 || i == len)
68 continue;
69 b[i++] = c4;
70 }
71 break;
72 }
73 }
74}
75
76static void memswp(void* buf1, void* buf2, unsigned int len)
Shawn Lewis546a9142007-07-28 21:11:37 +020077{
78 struct verify_header swap;
Jens Axboe90059d62007-07-30 09:33:12 +020079
Shawn Lewis546a9142007-07-28 21:11:37 +020080 memcpy(&swap, buf1, len);
81 memcpy(buf1, buf2, len);
82 memcpy(buf2, &swap, len);
83}
84
Jens Axboee29d1b72006-10-18 15:43:15 +020085static void hexdump(void *buffer, int len)
86{
87 unsigned char *p = buffer;
88 int i;
89
90 for (i = 0; i < len; i++)
Jens Axboe6d861442007-03-15 09:22:23 +010091 log_info("%02x", p[i]);
92 log_info("\n");
Jens Axboee29d1b72006-10-18 15:43:15 +020093}
94
Jens Axboed9f2caf2007-07-28 21:22:03 +020095/*
96 * Return data area 'header_num'
97 */
98static inline void *io_u_verify_off(struct verify_header *hdr,
99 struct io_u *io_u,
100 unsigned char header_num)
101{
102 return io_u->buf + sizeof(*hdr) + header_num * hdr->len;
103}
104
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200105static int verify_io_u_crc7(struct verify_header *hdr, struct io_u *io_u,
106 unsigned char header_num)
Jens Axboe1e154bd2007-07-27 09:52:40 +0200107{
Jens Axboed9f2caf2007-07-28 21:22:03 +0200108 void *p = io_u_verify_off(hdr, io_u, header_num);
Jens Axboe1e154bd2007-07-27 09:52:40 +0200109 unsigned char c;
110
Jens Axboe1e154bd2007-07-27 09:52:40 +0200111 c = crc7(p, hdr->len - sizeof(*hdr));
112
113 if (c != hdr->crc7) {
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200114 log_err("crc7: verify failed at %llu/%u\n",
115 io_u->offset + header_num * hdr->len,
116 hdr->len);
Jens Axboe1e154bd2007-07-27 09:52:40 +0200117 log_err("crc7: wanted %x, got %x\n", hdr->crc7, c);
118 return 1;
119 }
120
121 return 0;
122}
123
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200124static int verify_io_u_crc16(struct verify_header *hdr, struct io_u *io_u,
125 unsigned int header_num)
Jens Axboe969f7ed2007-07-27 09:07:17 +0200126{
Jens Axboed9f2caf2007-07-28 21:22:03 +0200127 void *p = io_u_verify_off(hdr, io_u, header_num);
Jens Axboe969f7ed2007-07-27 09:07:17 +0200128 unsigned short c;
129
Jens Axboe969f7ed2007-07-27 09:07:17 +0200130 c = crc16(p, hdr->len - sizeof(*hdr));
131
132 if (c != hdr->crc16) {
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200133 log_err("crc16: verify failed at %llu/%u\n",
134 io_u->offset + header_num * hdr->len,
135 hdr->len);
Jens Axboe1f24ea42007-07-27 09:53:14 +0200136 log_err("crc16: wanted %x, got %x\n", hdr->crc16, c);
Jens Axboe969f7ed2007-07-27 09:07:17 +0200137 return 1;
138 }
139
140 return 0;
141}
142
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200143static int verify_io_u_crc64(struct verify_header *hdr, struct io_u *io_u,
144 unsigned int header_num)
Jens Axboed77a7af2007-07-27 15:35:06 +0200145{
Jens Axboed9f2caf2007-07-28 21:22:03 +0200146 void *p = io_u_verify_off(hdr, io_u, header_num);
Jens Axboed77a7af2007-07-27 15:35:06 +0200147 unsigned long long c;
148
149 c = crc64(p, hdr->len - sizeof(*hdr));
150
151 if (c != hdr->crc64) {
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200152 log_err("crc64: verify failed at %llu/%u\n",
153 io_u->offset + header_num * hdr->len,
154 hdr->len);
Jens Axboed77a7af2007-07-27 15:35:06 +0200155 log_err("crc64: wanted %llx, got %llx\n", hdr->crc64, c);
156 return 1;
157 }
158
159 return 0;
160}
161
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200162static int verify_io_u_crc32(struct verify_header *hdr, struct io_u *io_u,
163 unsigned int header_num)
Jens Axboee29d1b72006-10-18 15:43:15 +0200164{
Jens Axboed9f2caf2007-07-28 21:22:03 +0200165 void *p = io_u_verify_off(hdr, io_u, header_num);
Jens Axboee29d1b72006-10-18 15:43:15 +0200166 unsigned long c;
167
Jens Axboee29d1b72006-10-18 15:43:15 +0200168 c = crc32(p, hdr->len - sizeof(*hdr));
169
170 if (c != hdr->crc32) {
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200171 log_err("crc32: verify failed at %llu/%u\n",
172 io_u->offset + header_num * hdr->len,
173 hdr->len);
Jens Axboee29d1b72006-10-18 15:43:15 +0200174 log_err("crc32: wanted %lx, got %lx\n", hdr->crc32, c);
175 return 1;
176 }
177
178 return 0;
179}
180
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200181static int verify_io_u_md5(struct verify_header *hdr, struct io_u *io_u,
182 unsigned int header_num)
Jens Axboee29d1b72006-10-18 15:43:15 +0200183{
Jens Axboed9f2caf2007-07-28 21:22:03 +0200184 void *p = io_u_verify_off(hdr, io_u, header_num);
Jens Axboe8c432322007-07-27 13:16:24 +0200185 uint32_t hash[MD5_HASH_WORDS];
186 struct md5_ctx md5_ctx = {
187 .hash = hash,
188 };
Jens Axboee29d1b72006-10-18 15:43:15 +0200189
Jens Axboe61f821f2007-07-30 10:18:06 +0200190 md5_init(&md5_ctx);
Jens Axboee29d1b72006-10-18 15:43:15 +0200191 md5_update(&md5_ctx, p, hdr->len - sizeof(*hdr));
192
Jens Axboec9b3fdf2007-07-29 08:49:16 +0200193 if (memcmp(hdr->md5_digest, md5_ctx.hash, sizeof(hash))) {
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200194 log_err("md5: verify failed at %llu/%u\n",
195 io_u->offset + header_num * hdr->len,
196 hdr->len);
Jens Axboee29d1b72006-10-18 15:43:15 +0200197 hexdump(hdr->md5_digest, sizeof(hdr->md5_digest));
Jens Axboe8c432322007-07-27 13:16:24 +0200198 hexdump(md5_ctx.hash, sizeof(hash));
Jens Axboee29d1b72006-10-18 15:43:15 +0200199 return 1;
200 }
201
202 return 0;
203}
204
Jens Axboe36690c92007-03-26 10:23:34 +0200205int verify_io_u(struct thread_data *td, struct io_u *io_u)
Jens Axboee29d1b72006-10-18 15:43:15 +0200206{
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200207 struct verify_header *hdr;
208 unsigned int hdr_inc, hdr_num = 0;
Jens Axboe95646102007-07-28 21:17:50 +0200209 void *p;
Jens Axboee29d1b72006-10-18 15:43:15 +0200210 int ret;
211
Shawn Lewis1dcc0492007-07-27 08:02:45 +0200212 if (td->o.verify == VERIFY_NULL || io_u->ddir != DDIR_READ)
Jens Axboe36690c92007-03-26 10:23:34 +0200213 return 0;
214
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200215 hdr_inc = io_u->buflen;
Jens Axboea59e1702007-07-30 08:53:27 +0200216 if (td->o.verify_interval)
217 hdr_inc = td->o.verify_interval;
Jens Axboee29d1b72006-10-18 15:43:15 +0200218
Jens Axboe95646102007-07-28 21:17:50 +0200219 for (p = io_u->buf; p < io_u->buf + io_u->buflen; p += hdr_inc) {
Jens Axboea59e1702007-07-30 08:53:27 +0200220 if (td->o.verify_offset)
221 memswp(p, p + td->o.verify_offset, sizeof(*hdr));
Shawn Lewis546a9142007-07-28 21:11:37 +0200222
Jens Axboe95646102007-07-28 21:17:50 +0200223 hdr = p;
Jens Axboee29d1b72006-10-18 15:43:15 +0200224
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200225 if (hdr->fio_magic != FIO_HDR_MAGIC) {
226 log_err("Bad verify header %x\n", hdr->fio_magic);
227 return EIO;
228 }
229
230 switch (hdr->verify_type) {
231 case VERIFY_MD5:
232 ret = verify_io_u_md5(hdr, io_u, hdr_num);
233 break;
234 case VERIFY_CRC64:
235 ret = verify_io_u_crc64(hdr, io_u, hdr_num);
236 break;
237 case VERIFY_CRC32:
238 ret = verify_io_u_crc32(hdr, io_u, hdr_num);
239 break;
240 case VERIFY_CRC16:
241 ret = verify_io_u_crc16(hdr, io_u, hdr_num);
242 break;
243 case VERIFY_CRC7:
244 ret = verify_io_u_crc7(hdr, io_u, hdr_num);
245 break;
246 default:
247 log_err("Bad verify type %u\n", hdr->verify_type);
248 ret = 1;
249 }
250 hdr_num++;
251 }
Jens Axboea7dfe862007-03-12 10:05:08 +0100252
253 return 0;
Jens Axboee29d1b72006-10-18 15:43:15 +0200254}
255
Jens Axboe1e154bd2007-07-27 09:52:40 +0200256static void fill_crc7(struct verify_header *hdr, void *p, unsigned int len)
257{
258 hdr->crc7 = crc7(p, len);
259}
260
Jens Axboe969f7ed2007-07-27 09:07:17 +0200261static void fill_crc16(struct verify_header *hdr, void *p, unsigned int len)
262{
263 hdr->crc16 = crc16(p, len);
264}
265
Jens Axboee29d1b72006-10-18 15:43:15 +0200266static void fill_crc32(struct verify_header *hdr, void *p, unsigned int len)
267{
268 hdr->crc32 = crc32(p, len);
269}
270
Jens Axboed77a7af2007-07-27 15:35:06 +0200271static void fill_crc64(struct verify_header *hdr, void *p, unsigned int len)
272{
273 hdr->crc64 = crc64(p, len);
274}
275
Jens Axboee29d1b72006-10-18 15:43:15 +0200276static void fill_md5(struct verify_header *hdr, void *p, unsigned int len)
277{
Jens Axboe8c432322007-07-27 13:16:24 +0200278 struct md5_ctx md5_ctx = {
279 .hash = (uint32_t *) hdr->md5_digest,
280 };
Jens Axboee29d1b72006-10-18 15:43:15 +0200281
Jens Axboe61f821f2007-07-30 10:18:06 +0200282 md5_init(&md5_ctx);
Jens Axboee29d1b72006-10-18 15:43:15 +0200283 md5_update(&md5_ctx, p, len);
Jens Axboee29d1b72006-10-18 15:43:15 +0200284}
285
286/*
287 * fill body of io_u->buf with random data and add a header with the
288 * crc32 or md5 sum of that data.
289 */
290void populate_verify_io_u(struct thread_data *td, struct io_u *io_u)
291{
Jens Axboebaefa9b2007-07-27 12:57:25 +0200292 struct verify_header *hdr;
Jens Axboe95646102007-07-28 21:17:50 +0200293 void *p = io_u->buf, *data;
Shawn Lewis546a9142007-07-28 21:11:37 +0200294 unsigned int hdr_inc, data_len;
Jens Axboee29d1b72006-10-18 15:43:15 +0200295
Jens Axboe9cc3d152007-03-26 10:32:30 +0200296 if (td->o.verify == VERIFY_NULL)
297 return;
298
Jens Axboe90059d62007-07-30 09:33:12 +0200299 fill_pattern(td, p, io_u->buflen);
Jens Axboebaefa9b2007-07-27 12:57:25 +0200300
Shawn Lewis546a9142007-07-28 21:11:37 +0200301 hdr_inc = io_u->buflen;
Jens Axboea59e1702007-07-30 08:53:27 +0200302 if (td->o.verify_interval)
303 hdr_inc = td->o.verify_interval;
Shawn Lewis546a9142007-07-28 21:11:37 +0200304 data_len = hdr_inc - sizeof(*hdr);
305
Jens Axboe95646102007-07-28 21:17:50 +0200306 for (;p < io_u->buf + io_u->buflen; p += hdr_inc) {
307 hdr = p;
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200308
309 hdr->fio_magic = FIO_HDR_MAGIC;
310 hdr->verify_type = td->o.verify;
Shawn Lewis546a9142007-07-28 21:11:37 +0200311 hdr->len = hdr_inc;
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200312
313 data = p + sizeof(*hdr);
Shawn Lewis3f9f4e22007-07-28 21:10:37 +0200314 switch (td->o.verify) {
315 case VERIFY_MD5:
316 fill_md5(hdr, data, data_len);
317 break;
318 case VERIFY_CRC64:
319 fill_crc64(hdr, data, data_len);
320 break;
321 case VERIFY_CRC32:
322 fill_crc32(hdr, data, data_len);
323 break;
324 case VERIFY_CRC16:
325 fill_crc16(hdr, data, data_len);
326 break;
327 case VERIFY_CRC7:
328 fill_crc7(hdr, data, data_len);
329 break;
330 default:
331 log_err("fio: bad verify type: %d\n", td->o.verify);
332 assert(0);
333 }
Jens Axboea59e1702007-07-30 08:53:27 +0200334 if (td->o.verify_offset)
335 memswp(p, p + td->o.verify_offset, sizeof(*hdr));
Jens Axboee29d1b72006-10-18 15:43:15 +0200336 }
Jens Axboee29d1b72006-10-18 15:43:15 +0200337}
338
339int get_next_verify(struct thread_data *td, struct io_u *io_u)
340{
Jens Axboe8de8f042007-03-27 10:36:12 +0200341 struct io_piece *ipo = NULL;
Jens Axboee29d1b72006-10-18 15:43:15 +0200342
Jens Axboed2d7fa52007-02-19 13:21:35 +0100343 /*
344 * this io_u is from a requeue, we already filled the offsets
345 */
346 if (io_u->file)
347 return 0;
348
Jens Axboe8de8f042007-03-27 10:36:12 +0200349 if (!RB_EMPTY_ROOT(&td->io_hist_tree)) {
350 struct rb_node *n = rb_first(&td->io_hist_tree);
351
Jens Axboe4b878982007-03-26 09:32:22 +0200352 ipo = rb_entry(n, struct io_piece, rb_node);
Jens Axboe4b878982007-03-26 09:32:22 +0200353 rb_erase(n, &td->io_hist_tree);
Jens Axboe8de8f042007-03-27 10:36:12 +0200354 } else if (!list_empty(&td->io_hist_list)) {
355 ipo = list_entry(td->io_hist_list.next, struct io_piece, list);
356 list_del(&ipo->list);
357 }
Jens Axboee29d1b72006-10-18 15:43:15 +0200358
Jens Axboe8de8f042007-03-27 10:36:12 +0200359 if (ipo) {
Jens Axboee29d1b72006-10-18 15:43:15 +0200360 io_u->offset = ipo->offset;
361 io_u->buflen = ipo->len;
Jens Axboe36167d82007-02-18 05:41:31 +0100362 io_u->file = ipo->file;
Jens Axboe97af62c2007-05-22 11:12:13 +0200363
364 if ((io_u->file->flags & FIO_FILE_OPEN) == 0) {
365 int r = td_io_open_file(td, io_u->file);
366
367 if (r)
368 return 1;
369 }
370
371 get_file(ipo->file);
372 assert(io_u->file->flags & FIO_FILE_OPEN);
Jens Axboee29d1b72006-10-18 15:43:15 +0200373 io_u->ddir = DDIR_READ;
Jens Axboe36167d82007-02-18 05:41:31 +0100374 io_u->xfer_buf = io_u->buf;
375 io_u->xfer_buflen = io_u->buflen;
Jens Axboee29d1b72006-10-18 15:43:15 +0200376 free(ipo);
377 return 0;
378 }
379
380 return 1;
381}