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