Parent options didn't recurse properly
[fio.git] / verify.c
1 /*
2  * IO verification helpers
3  */
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <string.h>
7 #include <assert.h>
8
9 #include "fio.h"
10
11 #include "crc/md5.h"
12 #include "crc/crc64.h"
13 #include "crc/crc32.h"
14 #include "crc/crc16.h"
15 #include "crc/crc7.h"
16 #include "crc/sha256.h"
17 #include "crc/sha512.h"
18
19 static void fill_random_bytes(struct thread_data *td, void *p, unsigned int len)
20 {
21         unsigned int todo;
22         int r;
23
24         while (len) {
25                 r = os_random_long(&td->verify_state);
26
27                 /*
28                  * lrand48_r seems to be broken and only fill the bottom
29                  * 32-bits, even on 64-bit archs with 64-bit longs
30                  */
31                 todo = sizeof(r);
32                 if (todo > len)
33                         todo = len;
34
35                 memcpy(p, &r, todo);
36
37                 len -= todo;
38                 p += todo;
39         }
40 }
41
42 static void fill_pattern(struct thread_data *td, void *p, unsigned int len)
43 {
44         switch (td->o.verify_pattern_bytes) {
45         case 0:
46                 fill_random_bytes(td, p, len);
47                 break;
48         case 1:
49                 memset(p, td->o.verify_pattern, len);
50                 break;
51         case 2:
52         case 3:
53         case 4: {
54                 unsigned int pattern = td->o.verify_pattern;
55                 unsigned int i = 0;
56                 unsigned char c1, c2, c3, c4;
57                 unsigned char *b = p;
58
59                 c1 = pattern & 0xff;
60                 pattern >>= 8;
61                 c2 = pattern & 0xff;
62                 pattern >>= 8;
63                 c3 = pattern & 0xff;
64                 pattern >>= 8;
65                 c4 = pattern & 0xff;
66
67                 while (i < len) {
68                         b[i++] = c1;
69                         if (i == len)
70                                 break;
71                         b[i++] = c2;
72                         if (td->o.verify_pattern_bytes == 2 || i == len)
73                                 continue;
74                         b[i++] = c3;
75                         if (td->o.verify_pattern_bytes == 3 || i == len)
76                                 continue;
77                         b[i++] = c4;
78                 }
79                 break;
80                 }
81         }
82 }
83
84 static void memswp(void* buf1, void* buf2, unsigned int len)
85 {
86         struct verify_header swap;
87
88         memcpy(&swap, buf1, len);
89         memcpy(buf1, buf2, len);
90         memcpy(buf2, &swap, len);
91 }
92
93 static void hexdump(void *buffer, int len)
94 {
95         unsigned char *p = buffer;
96         int i;
97
98         for (i = 0; i < len; i++)
99                 log_info("%02x", p[i]);
100         log_info("\n");
101 }
102
103 /*
104  * Prepare for seperation of verify_header and checksum header
105  */
106 static inline unsigned int __hdr_size(int verify_type)
107 {
108         unsigned int len;
109
110         switch (verify_type) {
111         case VERIFY_NONE:
112         case VERIFY_NULL:
113                 len = 0;
114                 break;
115         case VERIFY_MD5:
116                 len = sizeof(struct vhdr_md5);
117                 break;
118         case VERIFY_CRC64:
119                 len = sizeof(struct vhdr_crc64);
120                 break;
121         case VERIFY_CRC32:
122                 len = sizeof(struct vhdr_crc32);
123                 break;
124         case VERIFY_CRC16:
125                 len = sizeof(struct vhdr_crc16);
126                 break;
127         case VERIFY_CRC7:
128                 len = sizeof(struct vhdr_crc7);
129                 break;
130         case VERIFY_SHA256:
131                 len = sizeof(struct vhdr_sha256);
132                 break;
133         case VERIFY_SHA512:
134                 len = sizeof(struct vhdr_sha512);
135                 break;
136         default:
137                 log_err("fio: unknown verify header!\n");
138                 assert(0);
139         }
140
141         return len + sizeof(struct verify_header);
142 }
143
144 static inline unsigned int hdr_size(struct verify_header *hdr)
145 {
146         return __hdr_size(hdr->verify_type);
147 }
148
149 static void *hdr_priv(struct verify_header *hdr)
150 {
151         void *priv = hdr;
152
153         return priv + sizeof(struct verify_header);
154 }
155
156 /*
157  * Return data area 'header_num'
158  */
159 static inline void *io_u_verify_off(struct verify_header *hdr,
160                                     struct io_u *io_u,
161                                     unsigned char header_num)
162 {
163         return io_u->buf + header_num * hdr->len + hdr_size(hdr);
164 }
165
166 static int verify_io_u_sha512(struct verify_header *hdr, struct io_u *io_u,
167                               unsigned int header_num)
168 {
169         void *p = io_u_verify_off(hdr, io_u, header_num);
170         struct vhdr_sha512 *vh = hdr_priv(hdr);
171         uint8_t sha512[128];
172         struct sha512_ctx sha512_ctx = {
173                 .buf = sha512,
174         };
175
176         sha512_init(&sha512_ctx);
177         sha512_update(&sha512_ctx, p, hdr->len - hdr_size(hdr));
178
179         if (memcmp(vh->sha512, sha512_ctx.buf, sizeof(sha512))) {
180                 log_err("sha512: verify failed at %llu/%u\n",
181                               io_u->offset + header_num * hdr->len,
182                               hdr->len);
183                 hexdump(vh->sha512, sizeof(vh->sha512));
184                 hexdump(sha512_ctx.buf, sizeof(sha512));
185                 return 1;
186         }
187
188         return 0;
189 }
190
191 static int verify_io_u_sha256(struct verify_header *hdr, struct io_u *io_u,
192                               unsigned int header_num)
193 {
194         void *p = io_u_verify_off(hdr, io_u, header_num);
195         struct vhdr_sha256 *vh = hdr_priv(hdr);
196         uint8_t sha256[128];
197         struct sha256_ctx sha256_ctx = {
198                 .buf = sha256,
199         };
200
201         sha256_init(&sha256_ctx);
202         sha256_update(&sha256_ctx, p, hdr->len - hdr_size(hdr));
203
204         if (memcmp(vh->sha256, sha256_ctx.buf, sizeof(sha256))) {
205                 log_err("sha256: verify failed at %llu/%u\n",
206                               io_u->offset + header_num * hdr->len,
207                               hdr->len);
208                 hexdump(vh->sha256, sizeof(vh->sha256));
209                 hexdump(sha256_ctx.buf, sizeof(sha256));
210                 return 1;
211         }
212
213         return 0;
214 }
215
216 static int verify_io_u_crc7(struct verify_header *hdr, struct io_u *io_u,
217                             unsigned char header_num)
218 {
219         void *p = io_u_verify_off(hdr, io_u, header_num);
220         struct vhdr_crc7 *vh = hdr_priv(hdr);
221         unsigned char c;
222
223         c = crc7(p, hdr->len - hdr_size(hdr));
224
225         if (c != vh->crc7) {
226                 log_err("crc7: verify failed at %llu/%u\n",
227                                 io_u->offset + header_num * hdr->len,
228                                 hdr->len);
229                 log_err("crc7: wanted %x, got %x\n", vh->crc7, c);
230                 return 1;
231         }
232
233         return 0;
234 }
235
236 static int verify_io_u_crc16(struct verify_header *hdr, struct io_u *io_u,
237                              unsigned int header_num)
238 {
239         void *p = io_u_verify_off(hdr, io_u, header_num);
240         struct vhdr_crc16 *vh = hdr_priv(hdr);
241         unsigned short c;
242
243         c = crc16(p, hdr->len - hdr_size(hdr));
244
245         if (c != vh->crc16) {
246                 log_err("crc16: verify failed at %llu/%u\n",
247                                 io_u->offset + header_num * hdr->len,
248                                 hdr->len);
249                 log_err("crc16: wanted %x, got %x\n", vh->crc16, c);
250                 return 1;
251         }
252
253         return 0;
254 }
255
256 static int verify_io_u_crc64(struct verify_header *hdr, struct io_u *io_u,
257                              unsigned int header_num)
258 {
259         void *p = io_u_verify_off(hdr, io_u, header_num);
260         struct vhdr_crc64 *vh = hdr_priv(hdr);
261         unsigned long long c;
262
263         c = crc64(p, hdr->len - hdr_size(hdr));
264
265         if (c != vh->crc64) {
266                 log_err("crc64: verify failed at %llu/%u\n",
267                                 io_u->offset + header_num * hdr->len,
268                                 hdr->len);
269                 log_err("crc64: wanted %llx, got %llx\n", (unsigned long long) vh->crc64, c);
270                 return 1;
271         }
272
273         return 0;
274 }
275
276 static int verify_io_u_crc32(struct verify_header *hdr, struct io_u *io_u,
277                              unsigned int header_num)
278 {
279         void *p = io_u_verify_off(hdr, io_u, header_num);
280         struct vhdr_crc32 *vh = hdr_priv(hdr);
281         uint32_t c;
282
283         c = crc32(p, hdr->len - hdr_size(hdr));
284
285         if (c != vh->crc32) {
286                 log_err("crc32: verify failed at %llu/%u\n",
287                                 io_u->offset + header_num * hdr->len,
288                                 hdr->len);
289                 log_err("crc32: wanted %x, got %x\n", vh->crc32, c);
290                 return 1;
291         }
292
293         return 0;
294 }
295
296 static int verify_io_u_md5(struct verify_header *hdr, struct io_u *io_u,
297                            unsigned int header_num)
298 {
299         void *p = io_u_verify_off(hdr, io_u, header_num);
300         struct vhdr_md5 *vh = hdr_priv(hdr);
301         uint32_t hash[MD5_HASH_WORDS];
302         struct md5_ctx md5_ctx = {
303                 .hash = hash,
304         };
305
306         md5_init(&md5_ctx);
307         md5_update(&md5_ctx, p, hdr->len - hdr_size(hdr));
308
309         if (memcmp(vh->md5_digest, md5_ctx.hash, sizeof(hash))) {
310                 log_err("md5: verify failed at %llu/%u\n",
311                               io_u->offset + header_num * hdr->len,
312                               hdr->len);
313                 hexdump(vh->md5_digest, sizeof(vh->md5_digest));
314                 hexdump(md5_ctx.hash, sizeof(hash));
315                 return 1;
316         }
317
318         return 0;
319 }
320
321 int verify_io_u(struct thread_data *td, struct io_u *io_u)
322 {
323         struct verify_header *hdr;
324         unsigned int hdr_inc, hdr_num = 0;
325         void *p;
326         int ret;
327
328         if (td->o.verify == VERIFY_NULL || io_u->ddir != DDIR_READ)
329                 return 0;
330
331         hdr_inc = io_u->buflen;
332         if (td->o.verify_interval)
333                 hdr_inc = td->o.verify_interval;
334
335         for (p = io_u->buf; p < io_u->buf + io_u->buflen; p += hdr_inc) {
336                 if (td->o.verify_offset)
337                         memswp(p, p + td->o.verify_offset, __hdr_size(td->o.verify));
338
339                 hdr = p;
340
341                 if (hdr->fio_magic != FIO_HDR_MAGIC) {
342                         log_err("Bad verify header %x\n", hdr->fio_magic);
343                         return EIO;
344                 }
345
346                 switch (hdr->verify_type) {
347                 case VERIFY_MD5:
348                         ret = verify_io_u_md5(hdr, io_u, hdr_num);
349                         break;
350                 case VERIFY_CRC64:
351                         ret = verify_io_u_crc64(hdr, io_u, hdr_num);
352                         break;
353                 case VERIFY_CRC32:
354                         ret = verify_io_u_crc32(hdr, io_u, hdr_num);
355                         break;
356                 case VERIFY_CRC16:
357                         ret = verify_io_u_crc16(hdr, io_u, hdr_num);
358                         break;
359                 case VERIFY_CRC7:
360                         ret = verify_io_u_crc7(hdr, io_u, hdr_num);
361                         break;
362                 case VERIFY_SHA256:
363                         ret = verify_io_u_sha256(hdr, io_u, hdr_num);
364                         break;
365                 case VERIFY_SHA512:
366                         ret = verify_io_u_sha512(hdr, io_u, hdr_num);
367                         break;
368                 default:
369                         log_err("Bad verify type %u\n", hdr->verify_type);
370                         ret = 1;
371                 }
372                 hdr_num++;
373         }
374
375         return 0;
376 }
377
378 static void fill_sha512(struct verify_header *hdr, void *p, unsigned int len)
379 {
380         struct vhdr_sha512 *vh = hdr_priv(hdr);
381         struct sha512_ctx sha512_ctx = {
382                 .buf = vh->sha512,
383         };
384
385         sha512_init(&sha512_ctx);
386         sha512_update(&sha512_ctx, p, len);
387 }
388
389 static void fill_sha256(struct verify_header *hdr, void *p, unsigned int len)
390 {
391         struct vhdr_sha256 *vh = hdr_priv(hdr);
392         struct sha256_ctx sha256_ctx = {
393                 .buf = vh->sha256,
394         };
395
396         sha256_init(&sha256_ctx);
397         sha256_update(&sha256_ctx, p, len);
398 }
399
400 static void fill_crc7(struct verify_header *hdr, void *p, unsigned int len)
401 {
402         struct vhdr_crc7 *vh = hdr_priv(hdr);
403
404         vh->crc7 = crc7(p, len);
405 }
406
407 static void fill_crc16(struct verify_header *hdr, void *p, unsigned int len)
408 {
409         struct vhdr_crc16 *vh = hdr_priv(hdr);
410
411         vh->crc16 = crc16(p, len);
412 }
413
414 static void fill_crc32(struct verify_header *hdr, void *p, unsigned int len)
415 {
416         struct vhdr_crc32 *vh = hdr_priv(hdr);
417
418         vh->crc32 = crc32(p, len);
419 }
420
421 static void fill_crc64(struct verify_header *hdr, void *p, unsigned int len)
422 {
423         struct vhdr_crc64 *vh = hdr_priv(hdr);
424
425         vh->crc64 = crc64(p, len);
426 }
427
428 static void fill_md5(struct verify_header *hdr, void *p, unsigned int len)
429 {
430         struct vhdr_md5 *vh = hdr_priv(hdr);
431         struct md5_ctx md5_ctx = {
432                 .hash = (uint32_t *) vh->md5_digest,
433         };
434
435         md5_init(&md5_ctx);
436         md5_update(&md5_ctx, p, len);
437 }
438
439 /*
440  * fill body of io_u->buf with random data and add a header with the
441  * crc32 or md5 sum of that data.
442  */
443 void populate_verify_io_u(struct thread_data *td, struct io_u *io_u)
444 {
445         struct verify_header *hdr;
446         void *p = io_u->buf, *data;
447         unsigned int hdr_inc, data_len;
448
449         if (td->o.verify == VERIFY_NULL)
450                 return;
451
452         fill_pattern(td, p, io_u->buflen);
453
454         hdr_inc = io_u->buflen;
455         if (td->o.verify_interval)
456                 hdr_inc = td->o.verify_interval;
457
458         for (;p < io_u->buf + io_u->buflen; p += hdr_inc) {
459                 hdr = p;
460
461                 hdr->fio_magic = FIO_HDR_MAGIC;
462                 hdr->verify_type = td->o.verify;
463                 hdr->len = hdr_inc;
464                 data_len = hdr_inc - hdr_size(hdr);
465
466                 data = p + hdr_size(hdr);
467                 switch (td->o.verify) {
468                 case VERIFY_MD5:
469                         fill_md5(hdr, data, data_len);
470                         break;
471                 case VERIFY_CRC64:
472                         fill_crc64(hdr, data, data_len);
473                         break;
474                 case VERIFY_CRC32:
475                         fill_crc32(hdr, data, data_len);
476                         break;
477                 case VERIFY_CRC16:
478                         fill_crc16(hdr, data, data_len);
479                         break;
480                 case VERIFY_CRC7:
481                         fill_crc7(hdr, data, data_len);
482                         break;
483                 case VERIFY_SHA256:
484                         fill_sha256(hdr, data, data_len);
485                         break;
486                 case VERIFY_SHA512:
487                         fill_sha512(hdr, data, data_len);
488                         break;
489                 default:
490                         log_err("fio: bad verify type: %d\n", td->o.verify);
491                         assert(0);
492                 }
493                 if (td->o.verify_offset)
494                         memswp(p, p + td->o.verify_offset, hdr_size(hdr));
495         }
496 }
497
498 int get_next_verify(struct thread_data *td, struct io_u *io_u)
499 {
500         struct io_piece *ipo = NULL;
501
502         /*
503          * this io_u is from a requeue, we already filled the offsets
504          */
505         if (io_u->file)
506                 return 0;
507
508         if (!RB_EMPTY_ROOT(&td->io_hist_tree)) {
509                 struct rb_node *n = rb_first(&td->io_hist_tree);
510
511                 ipo = rb_entry(n, struct io_piece, rb_node);
512                 rb_erase(n, &td->io_hist_tree);
513         } else if (!list_empty(&td->io_hist_list)) {
514                 ipo = list_entry(td->io_hist_list.next, struct io_piece, list);
515                 list_del(&ipo->list);
516         }
517
518         if (ipo) {
519                 io_u->offset = ipo->offset;
520                 io_u->buflen = ipo->len;
521                 io_u->file = ipo->file;
522
523                 if ((io_u->file->flags & FIO_FILE_OPEN) == 0) {
524                         int r = td_io_open_file(td, io_u->file);
525
526                         if (r)
527                                 return 1;
528                 }
529
530                 get_file(ipo->file);
531                 assert(io_u->file->flags & FIO_FILE_OPEN);
532                 io_u->ddir = DDIR_READ;
533                 io_u->xfer_buf = io_u->buf;
534                 io_u->xfer_buflen = io_u->buflen;
535                 free(ipo);
536                 return 0;
537         }
538
539         return 1;
540 }