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