[PATCH] Add verify_meta verification type
[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         case VERIFY_META:
137                 len = sizeof(struct vhdr_meta);
138                 break;
139         default:
140                 log_err("fio: unknown verify header!\n");
141                 assert(0);
142         }
143
144         return len + sizeof(struct verify_header);
145 }
146
147 static inline unsigned int hdr_size(struct verify_header *hdr)
148 {
149         return __hdr_size(hdr->verify_type);
150 }
151
152 static void *hdr_priv(struct verify_header *hdr)
153 {
154         void *priv = hdr;
155
156         return priv + sizeof(struct verify_header);
157 }
158
159 /*
160  * Return data area 'header_num'
161  */
162 static inline void *io_u_verify_off(struct verify_header *hdr,
163                                     struct io_u *io_u,
164                                     unsigned char header_num)
165 {
166         return io_u->buf + header_num * hdr->len + hdr_size(hdr);
167 }
168
169 static int verify_io_u_meta(struct verify_header *hdr, struct thread_data *td,
170                             struct io_u *io_u, unsigned int header_num)
171 {
172         struct vhdr_meta *vh = hdr_priv(hdr);
173
174         if (vh->offset != io_u->offset + header_num * td->o.verify_interval) {
175                 log_err("meta: verify failed at %llu/%u\n",
176                               io_u->offset + header_num * hdr->len,
177                               hdr->len);
178                 return 1;
179         }
180
181         return 0;
182 }
183
184 static int verify_io_u_sha512(struct verify_header *hdr, struct io_u *io_u,
185                               unsigned int header_num)
186 {
187         void *p = io_u_verify_off(hdr, io_u, header_num);
188         struct vhdr_sha512 *vh = hdr_priv(hdr);
189         uint8_t sha512[128];
190         struct sha512_ctx sha512_ctx = {
191                 .buf = sha512,
192         };
193
194         sha512_init(&sha512_ctx);
195         sha512_update(&sha512_ctx, p, hdr->len - hdr_size(hdr));
196
197         if (memcmp(vh->sha512, sha512_ctx.buf, sizeof(sha512))) {
198                 log_err("sha512: verify failed at %llu/%u\n",
199                               io_u->offset + header_num * hdr->len,
200                               hdr->len);
201                 hexdump(vh->sha512, sizeof(vh->sha512));
202                 hexdump(sha512_ctx.buf, sizeof(sha512));
203                 return 1;
204         }
205
206         return 0;
207 }
208
209 static int verify_io_u_sha256(struct verify_header *hdr, struct io_u *io_u,
210                               unsigned int header_num)
211 {
212         void *p = io_u_verify_off(hdr, io_u, header_num);
213         struct vhdr_sha256 *vh = hdr_priv(hdr);
214         uint8_t sha256[128];
215         struct sha256_ctx sha256_ctx = {
216                 .buf = sha256,
217         };
218
219         sha256_init(&sha256_ctx);
220         sha256_update(&sha256_ctx, p, hdr->len - hdr_size(hdr));
221
222         if (memcmp(vh->sha256, sha256_ctx.buf, sizeof(sha256))) {
223                 log_err("sha256: verify failed at %llu/%u\n",
224                               io_u->offset + header_num * hdr->len,
225                               hdr->len);
226                 hexdump(vh->sha256, sizeof(vh->sha256));
227                 hexdump(sha256_ctx.buf, sizeof(sha256));
228                 return 1;
229         }
230
231         return 0;
232 }
233
234 static int verify_io_u_crc7(struct verify_header *hdr, struct io_u *io_u,
235                             unsigned char header_num)
236 {
237         void *p = io_u_verify_off(hdr, io_u, header_num);
238         struct vhdr_crc7 *vh = hdr_priv(hdr);
239         unsigned char c;
240
241         c = crc7(p, hdr->len - hdr_size(hdr));
242
243         if (c != vh->crc7) {
244                 log_err("crc7: verify failed at %llu/%u\n",
245                                 io_u->offset + header_num * hdr->len,
246                                 hdr->len);
247                 log_err("crc7: wanted %x, got %x\n", vh->crc7, c);
248                 return 1;
249         }
250
251         return 0;
252 }
253
254 static int verify_io_u_crc16(struct verify_header *hdr, struct io_u *io_u,
255                              unsigned int header_num)
256 {
257         void *p = io_u_verify_off(hdr, io_u, header_num);
258         struct vhdr_crc16 *vh = hdr_priv(hdr);
259         unsigned short c;
260
261         c = crc16(p, hdr->len - hdr_size(hdr));
262
263         if (c != vh->crc16) {
264                 log_err("crc16: verify failed at %llu/%u\n",
265                                 io_u->offset + header_num * hdr->len,
266                                 hdr->len);
267                 log_err("crc16: wanted %x, got %x\n", vh->crc16, c);
268                 return 1;
269         }
270
271         return 0;
272 }
273
274 static int verify_io_u_crc64(struct verify_header *hdr, struct io_u *io_u,
275                              unsigned int header_num)
276 {
277         void *p = io_u_verify_off(hdr, io_u, header_num);
278         struct vhdr_crc64 *vh = hdr_priv(hdr);
279         unsigned long long c;
280
281         c = crc64(p, hdr->len - hdr_size(hdr));
282
283         if (c != vh->crc64) {
284                 log_err("crc64: verify failed at %llu/%u\n",
285                                 io_u->offset + header_num * hdr->len,
286                                 hdr->len);
287                 log_err("crc64: wanted %llx, got %llx\n", (unsigned long long) vh->crc64, c);
288                 return 1;
289         }
290
291         return 0;
292 }
293
294 static int verify_io_u_crc32(struct verify_header *hdr, struct io_u *io_u,
295                              unsigned int header_num)
296 {
297         void *p = io_u_verify_off(hdr, io_u, header_num);
298         struct vhdr_crc32 *vh = hdr_priv(hdr);
299         uint32_t c;
300
301         c = crc32(p, hdr->len - hdr_size(hdr));
302
303         if (c != vh->crc32) {
304                 log_err("crc32: verify failed at %llu/%u\n",
305                                 io_u->offset + header_num * hdr->len,
306                                 hdr->len);
307                 log_err("crc32: wanted %x, got %x\n", vh->crc32, c);
308                 return 1;
309         }
310
311         return 0;
312 }
313
314 static int verify_io_u_md5(struct verify_header *hdr, struct io_u *io_u,
315                            unsigned int header_num)
316 {
317         void *p = io_u_verify_off(hdr, io_u, header_num);
318         struct vhdr_md5 *vh = hdr_priv(hdr);
319         uint32_t hash[MD5_HASH_WORDS];
320         struct md5_ctx md5_ctx = {
321                 .hash = hash,
322         };
323
324         md5_init(&md5_ctx);
325         md5_update(&md5_ctx, p, hdr->len - hdr_size(hdr));
326
327         if (memcmp(vh->md5_digest, md5_ctx.hash, sizeof(hash))) {
328                 log_err("md5: verify failed at %llu/%u\n",
329                               io_u->offset + header_num * hdr->len,
330                               hdr->len);
331                 hexdump(vh->md5_digest, sizeof(vh->md5_digest));
332                 hexdump(md5_ctx.hash, sizeof(hash));
333                 return 1;
334         }
335
336         return 0;
337 }
338
339 int verify_io_u(struct thread_data *td, struct io_u *io_u)
340 {
341         struct verify_header *hdr;
342         unsigned int hdr_inc, hdr_num = 0;
343         void *p;
344         int ret;
345
346         if (td->o.verify == VERIFY_NULL || io_u->ddir != DDIR_READ)
347                 return 0;
348
349         hdr_inc = io_u->buflen;
350         if (td->o.verify_interval)
351                 hdr_inc = td->o.verify_interval;
352
353         for (p = io_u->buf; p < io_u->buf + io_u->buflen; p += hdr_inc) {
354                 if (td->o.verify_offset)
355                         memswp(p, p + td->o.verify_offset, __hdr_size(td->o.verify));
356
357                 hdr = p;
358
359                 if (hdr->fio_magic != FIO_HDR_MAGIC) {
360                         log_err("Bad verify header %x\n", hdr->fio_magic);
361                         return EIO;
362                 }
363
364                 switch (hdr->verify_type) {
365                 case VERIFY_MD5:
366                         ret = verify_io_u_md5(hdr, io_u, hdr_num);
367                         break;
368                 case VERIFY_CRC64:
369                         ret = verify_io_u_crc64(hdr, io_u, hdr_num);
370                         break;
371                 case VERIFY_CRC32:
372                         ret = verify_io_u_crc32(hdr, io_u, hdr_num);
373                         break;
374                 case VERIFY_CRC16:
375                         ret = verify_io_u_crc16(hdr, io_u, hdr_num);
376                         break;
377                 case VERIFY_CRC7:
378                         ret = verify_io_u_crc7(hdr, io_u, hdr_num);
379                         break;
380                 case VERIFY_SHA256:
381                         ret = verify_io_u_sha256(hdr, io_u, hdr_num);
382                         break;
383                 case VERIFY_SHA512:
384                         ret = verify_io_u_sha512(hdr, io_u, hdr_num);
385                         break;
386                 case VERIFY_META:
387                         ret = verify_io_u_meta(hdr, td, io_u, hdr_num);
388                         break;
389                 default:
390                         log_err("Bad verify type %u\n", hdr->verify_type);
391                         ret = 1;
392                 }
393                 hdr_num++;
394         }
395
396         return 0;
397 }
398
399 static void fill_meta(struct verify_header *hdr, struct thread_data *td,
400                       struct io_u *io_u, unsigned int header_num)
401 {
402         struct vhdr_meta *vh = hdr_priv(hdr);
403
404         vh->thread = td->thread_number;
405
406         vh->time_sec = io_u->start_time.tv_sec;
407         vh->time_usec = io_u->start_time.tv_usec;
408
409         vh->numberio = td->io_issues[DDIR_WRITE];
410
411         vh->offset = io_u->offset + header_num * td->o.verify_interval;
412 }
413
414 static void fill_sha512(struct verify_header *hdr, void *p, unsigned int len)
415 {
416         struct vhdr_sha512 *vh = hdr_priv(hdr);
417         struct sha512_ctx sha512_ctx = {
418                 .buf = vh->sha512,
419         };
420
421         sha512_init(&sha512_ctx);
422         sha512_update(&sha512_ctx, p, len);
423 }
424
425 static void fill_sha256(struct verify_header *hdr, void *p, unsigned int len)
426 {
427         struct vhdr_sha256 *vh = hdr_priv(hdr);
428         struct sha256_ctx sha256_ctx = {
429                 .buf = vh->sha256,
430         };
431
432         sha256_init(&sha256_ctx);
433         sha256_update(&sha256_ctx, p, len);
434 }
435
436 static void fill_crc7(struct verify_header *hdr, void *p, unsigned int len)
437 {
438         struct vhdr_crc7 *vh = hdr_priv(hdr);
439
440         vh->crc7 = crc7(p, len);
441 }
442
443 static void fill_crc16(struct verify_header *hdr, void *p, unsigned int len)
444 {
445         struct vhdr_crc16 *vh = hdr_priv(hdr);
446
447         vh->crc16 = crc16(p, len);
448 }
449
450 static void fill_crc32(struct verify_header *hdr, void *p, unsigned int len)
451 {
452         struct vhdr_crc32 *vh = hdr_priv(hdr);
453
454         vh->crc32 = crc32(p, len);
455 }
456
457 static void fill_crc64(struct verify_header *hdr, void *p, unsigned int len)
458 {
459         struct vhdr_crc64 *vh = hdr_priv(hdr);
460
461         vh->crc64 = crc64(p, len);
462 }
463
464 static void fill_md5(struct verify_header *hdr, void *p, unsigned int len)
465 {
466         struct vhdr_md5 *vh = hdr_priv(hdr);
467         struct md5_ctx md5_ctx = {
468                 .hash = (uint32_t *) vh->md5_digest,
469         };
470
471         md5_init(&md5_ctx);
472         md5_update(&md5_ctx, p, len);
473 }
474
475 /*
476  * fill body of io_u->buf with random data and add a header with the
477  * crc32 or md5 sum of that data.
478  */
479 void populate_verify_io_u(struct thread_data *td, struct io_u *io_u)
480 {
481         struct verify_header *hdr;
482         void *p = io_u->buf, *data;
483         unsigned int hdr_inc, data_len, header_num = 0;
484
485         if (td->o.verify == VERIFY_NULL)
486                 return;
487
488         fill_pattern(td, p, io_u->buflen);
489
490         hdr_inc = io_u->buflen;
491         if (td->o.verify_interval)
492                 hdr_inc = td->o.verify_interval;
493
494         for (;p < io_u->buf + io_u->buflen; p += hdr_inc) {
495                 hdr = p;
496
497                 hdr->fio_magic = FIO_HDR_MAGIC;
498                 hdr->verify_type = td->o.verify;
499                 hdr->len = hdr_inc;
500                 data_len = hdr_inc - hdr_size(hdr);
501
502                 data = p + hdr_size(hdr);
503                 switch (td->o.verify) {
504                 case VERIFY_MD5:
505                         fill_md5(hdr, data, data_len);
506                         break;
507                 case VERIFY_CRC64:
508                         fill_crc64(hdr, data, data_len);
509                         break;
510                 case VERIFY_CRC32:
511                         fill_crc32(hdr, data, data_len);
512                         break;
513                 case VERIFY_CRC16:
514                         fill_crc16(hdr, data, data_len);
515                         break;
516                 case VERIFY_CRC7:
517                         fill_crc7(hdr, data, data_len);
518                         break;
519                 case VERIFY_SHA256:
520                         fill_sha256(hdr, data, data_len);
521                         break;
522                 case VERIFY_SHA512:
523                         fill_sha512(hdr, data, data_len);
524                         break;
525                 case VERIFY_META:
526                         fill_meta(hdr, td, io_u, header_num);
527                         break;
528                 default:
529                         log_err("fio: bad verify type: %d\n", td->o.verify);
530                         assert(0);
531                 }
532                 if (td->o.verify_offset)
533                         memswp(p, p + td->o.verify_offset, hdr_size(hdr));
534                 header_num++;
535         }
536 }
537
538 int get_next_verify(struct thread_data *td, struct io_u *io_u)
539 {
540         struct io_piece *ipo = NULL;
541
542         /*
543          * this io_u is from a requeue, we already filled the offsets
544          */
545         if (io_u->file)
546                 return 0;
547
548         if (!RB_EMPTY_ROOT(&td->io_hist_tree)) {
549                 struct rb_node *n = rb_first(&td->io_hist_tree);
550
551                 ipo = rb_entry(n, struct io_piece, rb_node);
552                 rb_erase(n, &td->io_hist_tree);
553         } else if (!list_empty(&td->io_hist_list)) {
554                 ipo = list_entry(td->io_hist_list.next, struct io_piece, list);
555                 list_del(&ipo->list);
556         }
557
558         if (ipo) {
559                 io_u->offset = ipo->offset;
560                 io_u->buflen = ipo->len;
561                 io_u->file = ipo->file;
562
563                 if ((io_u->file->flags & FIO_FILE_OPEN) == 0) {
564                         int r = td_io_open_file(td, io_u->file);
565
566                         if (r)
567                                 return 1;
568                 }
569
570                 get_file(ipo->file);
571                 assert(io_u->file->flags & FIO_FILE_OPEN);
572                 io_u->ddir = DDIR_READ;
573                 io_u->xfer_buf = io_u->buf;
574                 io_u->xfer_buflen = io_u->buflen;
575                 free(ipo);
576                 return 0;
577         }
578
579         return 1;
580 }