Prepare for splitting the verify_header from the checksum header
[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 "md5.h"
12 #include "crc64.h"
13 #include "crc32.h"
14 #include "crc16.h"
15 #include "crc7.h"
16 #include "sha256.h"
17 #include "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 fio_unused verify_type)
107 {
108         return sizeof(struct verify_header);
109
110 }
111
112 static inline unsigned int hdr_size(struct verify_header *hdr)
113 {
114         return sizeof(*hdr);
115 }
116
117 /*
118  * Return data area 'header_num'
119  */
120 static inline void *io_u_verify_off(struct verify_header *hdr,
121                                     struct io_u *io_u,
122                                     unsigned char header_num)
123 {
124         return io_u->buf + header_num * hdr->len + hdr_size(hdr);
125 }
126
127 static int verify_io_u_sha512(struct verify_header *hdr, struct io_u *io_u,
128                               unsigned int header_num)
129 {
130         void *p = io_u_verify_off(hdr, io_u, header_num);
131         uint8_t sha512[128];
132         struct sha512_ctx sha512_ctx = {
133                 .buf = sha512,
134         };
135
136         sha512_init(&sha512_ctx);
137         sha512_update(&sha512_ctx, p, hdr->len - hdr_size(hdr));
138
139         if (memcmp(hdr->sha512, sha512_ctx.buf, sizeof(sha512))) {
140                 log_err("sha512: verify failed at %llu/%u\n",
141                               io_u->offset + header_num * hdr->len,
142                               hdr->len);
143                 hexdump(hdr->sha512, sizeof(hdr->sha512));
144                 hexdump(sha512_ctx.buf, sizeof(sha512));
145                 return 1;
146         }
147
148         return 0;
149 }
150
151 static int verify_io_u_sha256(struct verify_header *hdr, struct io_u *io_u,
152                               unsigned int header_num)
153 {
154         void *p = io_u_verify_off(hdr, io_u, header_num);
155         uint8_t sha256[128];
156         struct sha256_ctx sha256_ctx = {
157                 .buf = sha256,
158         };
159
160         sha256_init(&sha256_ctx);
161         sha256_update(&sha256_ctx, p, hdr->len - hdr_size(hdr));
162
163         if (memcmp(hdr->sha256, sha256_ctx.buf, sizeof(sha256))) {
164                 log_err("sha256: verify failed at %llu/%u\n",
165                               io_u->offset + header_num * hdr->len,
166                               hdr->len);
167                 hexdump(hdr->sha256, sizeof(hdr->sha256));
168                 hexdump(sha256_ctx.buf, sizeof(sha256));
169                 return 1;
170         }
171
172         return 0;
173 }
174
175 static int verify_io_u_crc7(struct verify_header *hdr, struct io_u *io_u,
176                             unsigned char header_num)
177 {
178         void *p = io_u_verify_off(hdr, io_u, header_num);
179         unsigned char c;
180
181         c = crc7(p, hdr->len - hdr_size(hdr));
182
183         if (c != hdr->crc7) {
184                 log_err("crc7: verify failed at %llu/%u\n",
185                                 io_u->offset + header_num * hdr->len,
186                                 hdr->len);
187                 log_err("crc7: wanted %x, got %x\n", hdr->crc7, c);
188                 return 1;
189         }
190
191         return 0;
192 }
193
194 static int verify_io_u_crc16(struct verify_header *hdr, struct io_u *io_u,
195                              unsigned int header_num)
196 {
197         void *p = io_u_verify_off(hdr, io_u, header_num);
198         unsigned short c;
199
200         c = crc16(p, hdr->len - hdr_size(hdr));
201
202         if (c != hdr->crc16) {
203                 log_err("crc16: verify failed at %llu/%u\n",
204                                 io_u->offset + header_num * hdr->len,
205                                 hdr->len);
206                 log_err("crc16: wanted %x, got %x\n", hdr->crc16, c);
207                 return 1;
208         }
209
210         return 0;
211 }
212
213 static int verify_io_u_crc64(struct verify_header *hdr, struct io_u *io_u,
214                              unsigned int header_num)
215 {
216         void *p = io_u_verify_off(hdr, io_u, header_num);
217         unsigned long long c;
218
219         c = crc64(p, hdr->len - hdr_size(hdr));
220
221         if (c != hdr->crc64) {
222                 log_err("crc64: verify failed at %llu/%u\n",
223                                 io_u->offset + header_num * hdr->len,
224                                 hdr->len);
225                 log_err("crc64: wanted %llx, got %llx\n", hdr->crc64, c);
226                 return 1;
227         }
228
229         return 0;
230 }
231
232 static int verify_io_u_crc32(struct verify_header *hdr, struct io_u *io_u,
233                              unsigned int header_num)
234 {
235         void *p = io_u_verify_off(hdr, io_u, header_num);
236         unsigned long c;
237
238         c = crc32(p, hdr->len - hdr_size(hdr));
239
240         if (c != hdr->crc32) {
241                 log_err("crc32: verify failed at %llu/%u\n",
242                                 io_u->offset + header_num * hdr->len,
243                                 hdr->len);
244                 log_err("crc32: wanted %lx, got %lx\n", hdr->crc32, c);
245                 return 1;
246         }
247
248         return 0;
249 }
250
251 static int verify_io_u_md5(struct verify_header *hdr, struct io_u *io_u,
252                            unsigned int header_num)
253 {
254         void *p = io_u_verify_off(hdr, io_u, header_num);
255         uint32_t hash[MD5_HASH_WORDS];
256         struct md5_ctx md5_ctx = {
257                 .hash = hash,
258         };
259
260         md5_init(&md5_ctx);
261         md5_update(&md5_ctx, p, hdr->len - hdr_size(hdr));
262
263         if (memcmp(hdr->md5_digest, md5_ctx.hash, sizeof(hash))) {
264                 log_err("md5: verify failed at %llu/%u\n",
265                               io_u->offset + header_num * hdr->len,
266                               hdr->len);
267                 hexdump(hdr->md5_digest, sizeof(hdr->md5_digest));
268                 hexdump(md5_ctx.hash, sizeof(hash));
269                 return 1;
270         }
271
272         return 0;
273 }
274
275 int verify_io_u(struct thread_data *td, struct io_u *io_u)
276 {
277         struct verify_header *hdr;
278         unsigned int hdr_inc, hdr_num = 0;
279         void *p;
280         int ret;
281
282         if (td->o.verify == VERIFY_NULL || io_u->ddir != DDIR_READ)
283                 return 0;
284
285         hdr_inc = io_u->buflen;
286         if (td->o.verify_interval)
287                 hdr_inc = td->o.verify_interval;
288
289         for (p = io_u->buf; p < io_u->buf + io_u->buflen; p += hdr_inc) {
290                 if (td->o.verify_offset)
291                         memswp(p, p + td->o.verify_offset, __hdr_size(hdr->verify_type));
292
293                 hdr = p;
294
295                 if (hdr->fio_magic != FIO_HDR_MAGIC) {
296                         log_err("Bad verify header %x\n", hdr->fio_magic);
297                         return EIO;
298                 }
299
300                 switch (hdr->verify_type) {
301                 case VERIFY_MD5:
302                         ret = verify_io_u_md5(hdr, io_u, hdr_num);
303                         break;
304                 case VERIFY_CRC64:
305                         ret = verify_io_u_crc64(hdr, io_u, hdr_num);
306                         break;
307                 case VERIFY_CRC32:
308                         ret = verify_io_u_crc32(hdr, io_u, hdr_num);
309                         break;
310                 case VERIFY_CRC16:
311                         ret = verify_io_u_crc16(hdr, io_u, hdr_num);
312                         break;
313                 case VERIFY_CRC7:
314                         ret = verify_io_u_crc7(hdr, io_u, hdr_num);
315                         break;
316                 case VERIFY_SHA256:
317                         ret = verify_io_u_sha256(hdr, io_u, hdr_num);
318                         break;
319                 case VERIFY_SHA512:
320                         ret = verify_io_u_sha512(hdr, io_u, hdr_num);
321                         break;
322                 default:
323                         log_err("Bad verify type %u\n", hdr->verify_type);
324                         ret = 1;
325                 }
326                 hdr_num++;
327         }
328
329         return 0;
330 }
331
332 static void fill_sha512(struct verify_header *hdr, void *p, unsigned int len)
333 {
334         struct sha512_ctx sha512_ctx = {
335                 .buf = hdr->sha512,
336         };
337
338         sha512_init(&sha512_ctx);
339         sha512_update(&sha512_ctx, p, len);
340 }
341
342 static void fill_sha256(struct verify_header *hdr, void *p, unsigned int len)
343 {
344         struct sha256_ctx sha256_ctx = {
345                 .buf = hdr->sha256,
346         };
347
348         sha256_init(&sha256_ctx);
349         sha256_update(&sha256_ctx, p, len);
350 }
351
352 static void fill_crc7(struct verify_header *hdr, void *p, unsigned int len)
353 {
354         hdr->crc7 = crc7(p, len);
355 }
356
357 static void fill_crc16(struct verify_header *hdr, void *p, unsigned int len)
358 {
359         hdr->crc16 = crc16(p, len);
360 }
361
362 static void fill_crc32(struct verify_header *hdr, void *p, unsigned int len)
363 {
364         hdr->crc32 = crc32(p, len);
365 }
366
367 static void fill_crc64(struct verify_header *hdr, void *p, unsigned int len)
368 {
369         hdr->crc64 = crc64(p, len);
370 }
371
372 static void fill_md5(struct verify_header *hdr, void *p, unsigned int len)
373 {
374         struct md5_ctx md5_ctx = {
375                 .hash = (uint32_t *) hdr->md5_digest,
376         };
377
378         md5_init(&md5_ctx);
379         md5_update(&md5_ctx, p, len);
380 }
381
382 /*
383  * fill body of io_u->buf with random data and add a header with the
384  * crc32 or md5 sum of that data.
385  */
386 void populate_verify_io_u(struct thread_data *td, struct io_u *io_u)
387 {
388         struct verify_header *hdr;
389         void *p = io_u->buf, *data;
390         unsigned int hdr_inc, data_len;
391
392         if (td->o.verify == VERIFY_NULL)
393                 return;
394
395         fill_pattern(td, p, io_u->buflen);
396
397         hdr_inc = io_u->buflen;
398         if (td->o.verify_interval)
399                 hdr_inc = td->o.verify_interval;
400
401         for (;p < io_u->buf + io_u->buflen; p += hdr_inc) {
402                 hdr = p;
403
404                 hdr->fio_magic = FIO_HDR_MAGIC;
405                 hdr->verify_type = td->o.verify;
406                 hdr->len = hdr_inc;
407                 data_len = hdr_inc - hdr_size(hdr);
408
409                 data = p + hdr_size(hdr);
410                 switch (td->o.verify) {
411                 case VERIFY_MD5:
412                         fill_md5(hdr, data, data_len);
413                         break;
414                 case VERIFY_CRC64:
415                         fill_crc64(hdr, data, data_len);
416                         break;
417                 case VERIFY_CRC32:
418                         fill_crc32(hdr, data, data_len);
419                         break;
420                 case VERIFY_CRC16:
421                         fill_crc16(hdr, data, data_len);
422                         break;
423                 case VERIFY_CRC7:
424                         fill_crc7(hdr, data, data_len);
425                         break;
426                 case VERIFY_SHA256:
427                         fill_sha256(hdr, data, data_len);
428                         break;
429                 case VERIFY_SHA512:
430                         fill_sha512(hdr, data, data_len);
431                         break;
432                 default:
433                         log_err("fio: bad verify type: %d\n", td->o.verify);
434                         assert(0);
435                 }
436                 if (td->o.verify_offset)
437                         memswp(p, p + td->o.verify_offset, hdr_size(hdr));
438         }
439 }
440
441 int get_next_verify(struct thread_data *td, struct io_u *io_u)
442 {
443         struct io_piece *ipo = NULL;
444
445         /*
446          * this io_u is from a requeue, we already filled the offsets
447          */
448         if (io_u->file)
449                 return 0;
450
451         if (!RB_EMPTY_ROOT(&td->io_hist_tree)) {
452                 struct rb_node *n = rb_first(&td->io_hist_tree);
453
454                 ipo = rb_entry(n, struct io_piece, rb_node);
455                 rb_erase(n, &td->io_hist_tree);
456         } else if (!list_empty(&td->io_hist_list)) {
457                 ipo = list_entry(td->io_hist_list.next, struct io_piece, list);
458                 list_del(&ipo->list);
459         }
460
461         if (ipo) {
462                 io_u->offset = ipo->offset;
463                 io_u->buflen = ipo->len;
464                 io_u->file = ipo->file;
465
466                 if ((io_u->file->flags & FIO_FILE_OPEN) == 0) {
467                         int r = td_io_open_file(td, io_u->file);
468
469                         if (r)
470                                 return 1;
471                 }
472
473                 get_file(ipo->file);
474                 assert(io_u->file->flags & FIO_FILE_OPEN);
475                 io_u->ddir = DDIR_READ;
476                 io_u->xfer_buf = io_u->buf;
477                 io_u->xfer_buflen = io_u->buflen;
478                 free(ipo);
479                 return 0;
480         }
481
482         return 1;
483 }