verify.c revision e40823b10920f679d84f3f2222e319c168b1e7da
1/* 2 * IO verification helpers 3 */ 4#include <unistd.h> 5#include <fcntl.h> 6#include <string.h> 7#include <assert.h> 8#include <pthread.h> 9 10#include "fio.h" 11#include "verify.h" 12#include "smalloc.h" 13 14#include "crc/md5.h" 15#include "crc/crc64.h" 16#include "crc/crc32.h" 17#include "crc/crc32c.h" 18#include "crc/crc16.h" 19#include "crc/crc7.h" 20#include "crc/sha256.h" 21#include "crc/sha512.h" 22 23static void fill_random_bytes(struct thread_data *td, void *p, unsigned int len) 24{ 25 unsigned int todo; 26 int r; 27 28 while (len) { 29 r = os_random_long(&td->verify_state); 30 31 /* 32 * lrand48_r seems to be broken and only fill the bottom 33 * 32-bits, even on 64-bit archs with 64-bit longs 34 */ 35 todo = sizeof(r); 36 if (todo > len) 37 todo = len; 38 39 memcpy(p, &r, todo); 40 41 len -= todo; 42 p += todo; 43 } 44} 45 46static void fill_pattern(struct thread_data *td, void *p, unsigned int len) 47{ 48 switch (td->o.verify_pattern_bytes) { 49 case 0: 50 dprint(FD_VERIFY, "fill random bytes len=%u\n", len); 51 fill_random_bytes(td, p, len); 52 break; 53 case 1: 54 dprint(FD_VERIFY, "fill verify pattern b=0 len=%u\n", len); 55 memset(p, td->o.verify_pattern, len); 56 break; 57 case 2: 58 case 3: 59 case 4: { 60 unsigned int pattern = td->o.verify_pattern; 61 unsigned int i = 0; 62 unsigned char c1, c2, c3, c4; 63 unsigned char *b = p; 64 65 dprint(FD_VERIFY, "fill verify pattern b=%d len=%u\n", 66 td->o.verify_pattern_bytes, len); 67 68 c1 = pattern & 0xff; 69 pattern >>= 8; 70 c2 = pattern & 0xff; 71 pattern >>= 8; 72 c3 = pattern & 0xff; 73 pattern >>= 8; 74 c4 = pattern & 0xff; 75 76 while (i < len) { 77 b[i++] = c1; 78 if (i == len) 79 break; 80 b[i++] = c2; 81 if (td->o.verify_pattern_bytes == 2 || i == len) 82 continue; 83 b[i++] = c3; 84 if (td->o.verify_pattern_bytes == 3 || i == len) 85 continue; 86 b[i++] = c4; 87 } 88 break; 89 } 90 } 91} 92 93static void memswp(void *buf1, void *buf2, unsigned int len) 94{ 95 char swap[200]; 96 97 assert(len <= sizeof(swap)); 98 99 memcpy(&swap, buf1, len); 100 memcpy(buf1, buf2, len); 101 memcpy(buf2, &swap, len); 102} 103 104static void hexdump(void *buffer, int len) 105{ 106 unsigned char *p = buffer; 107 int i; 108 109 for (i = 0; i < len; i++) 110 log_info("%02x", p[i]); 111 log_info("\n"); 112} 113 114/* 115 * Prepare for seperation of verify_header and checksum header 116 */ 117static inline unsigned int __hdr_size(int verify_type) 118{ 119 unsigned int len = len; 120 121 switch (verify_type) { 122 case VERIFY_NONE: 123 case VERIFY_NULL: 124 len = 0; 125 break; 126 case VERIFY_MD5: 127 len = sizeof(struct vhdr_md5); 128 break; 129 case VERIFY_CRC64: 130 len = sizeof(struct vhdr_crc64); 131 break; 132 case VERIFY_CRC32C: 133 case VERIFY_CRC32: 134 case VERIFY_CRC32C_INTEL: 135 len = sizeof(struct vhdr_crc32); 136 break; 137 case VERIFY_CRC16: 138 len = sizeof(struct vhdr_crc16); 139 break; 140 case VERIFY_CRC7: 141 len = sizeof(struct vhdr_crc7); 142 break; 143 case VERIFY_SHA256: 144 len = sizeof(struct vhdr_sha256); 145 break; 146 case VERIFY_SHA512: 147 len = sizeof(struct vhdr_sha512); 148 break; 149 case VERIFY_META: 150 len = sizeof(struct vhdr_meta); 151 break; 152 default: 153 log_err("fio: unknown verify header!\n"); 154 assert(0); 155 } 156 157 return len + sizeof(struct verify_header); 158} 159 160static inline unsigned int hdr_size(struct verify_header *hdr) 161{ 162 return __hdr_size(hdr->verify_type); 163} 164 165static void *hdr_priv(struct verify_header *hdr) 166{ 167 void *priv = hdr; 168 169 return priv + sizeof(struct verify_header); 170} 171 172/* 173 * Return data area 'header_num' 174 */ 175static inline void *io_u_verify_off(struct verify_header *hdr, 176 struct io_u *io_u, unsigned char header_num) 177{ 178 return io_u->buf + header_num * hdr->len + hdr_size(hdr); 179} 180 181static int verify_io_u_meta(struct verify_header *hdr, struct thread_data *td, 182 struct io_u *io_u, unsigned int header_num) 183{ 184 struct vhdr_meta *vh = hdr_priv(hdr); 185 186 dprint(FD_VERIFY, "meta verify io_u %p, len %u\n", io_u, hdr->len); 187 188 if (vh->offset != io_u->offset + header_num * td->o.verify_interval) { 189 log_err("meta: verify failed at %llu/%u\n", 190 io_u->offset + header_num * hdr->len, hdr->len); 191 return EILSEQ; 192 } 193 194 return 0; 195} 196 197static int verify_io_u_sha512(struct verify_header *hdr, struct io_u *io_u, 198 unsigned int header_num) 199{ 200 void *p = io_u_verify_off(hdr, io_u, header_num); 201 struct vhdr_sha512 *vh = hdr_priv(hdr); 202 uint8_t sha512[128]; 203 struct sha512_ctx sha512_ctx = { 204 .buf = sha512, 205 }; 206 207 dprint(FD_VERIFY, "sha512 verify io_u %p, len %u\n", io_u, hdr->len); 208 209 sha512_init(&sha512_ctx); 210 sha512_update(&sha512_ctx, p, hdr->len - hdr_size(hdr)); 211 212 if (memcmp(vh->sha512, sha512_ctx.buf, sizeof(sha512))) { 213 log_err("sha512: verify failed at %llu/%u\n", 214 io_u->offset + header_num * hdr->len, hdr->len); 215 hexdump(vh->sha512, sizeof(vh->sha512)); 216 hexdump(sha512_ctx.buf, sizeof(sha512)); 217 return EILSEQ; 218 } 219 220 return 0; 221} 222 223static int verify_io_u_sha256(struct verify_header *hdr, struct io_u *io_u, 224 unsigned int header_num) 225{ 226 void *p = io_u_verify_off(hdr, io_u, header_num); 227 struct vhdr_sha256 *vh = hdr_priv(hdr); 228 uint8_t sha256[128]; 229 struct sha256_ctx sha256_ctx = { 230 .buf = sha256, 231 }; 232 233 dprint(FD_VERIFY, "sha256 verify io_u %p, len %u\n", io_u, hdr->len); 234 235 sha256_init(&sha256_ctx); 236 sha256_update(&sha256_ctx, p, hdr->len - hdr_size(hdr)); 237 238 if (memcmp(vh->sha256, sha256_ctx.buf, sizeof(sha256))) { 239 log_err("sha256: verify failed at %llu/%u\n", 240 io_u->offset + header_num * hdr->len, hdr->len); 241 hexdump(vh->sha256, sizeof(vh->sha256)); 242 hexdump(sha256_ctx.buf, sizeof(sha256)); 243 return EILSEQ; 244 } 245 246 return 0; 247} 248 249static int verify_io_u_crc7(struct verify_header *hdr, struct io_u *io_u, 250 unsigned char header_num) 251{ 252 void *p = io_u_verify_off(hdr, io_u, header_num); 253 struct vhdr_crc7 *vh = hdr_priv(hdr); 254 unsigned char c; 255 256 dprint(FD_VERIFY, "crc7 verify io_u %p, len %u\n", io_u, hdr->len); 257 258 c = crc7(p, hdr->len - hdr_size(hdr)); 259 260 if (c != vh->crc7) { 261 log_err("crc7: verify failed at %llu/%u\n", 262 io_u->offset + header_num * hdr->len, hdr->len); 263 log_err("crc7: wanted %x, got %x\n", vh->crc7, c); 264 return EILSEQ; 265 } 266 267 return 0; 268} 269 270static int verify_io_u_crc16(struct verify_header *hdr, struct io_u *io_u, 271 unsigned int header_num) 272{ 273 void *p = io_u_verify_off(hdr, io_u, header_num); 274 struct vhdr_crc16 *vh = hdr_priv(hdr); 275 unsigned short c; 276 277 dprint(FD_VERIFY, "crc16 verify io_u %p, len %u\n", io_u, hdr->len); 278 279 c = crc16(p, hdr->len - hdr_size(hdr)); 280 281 if (c != vh->crc16) { 282 log_err("crc16: verify failed at %llu/%u\n", 283 io_u->offset + header_num * hdr->len, hdr->len); 284 log_err("crc16: wanted %x, got %x\n", vh->crc16, c); 285 return EILSEQ; 286 } 287 288 return 0; 289} 290 291static int verify_io_u_crc64(struct verify_header *hdr, struct io_u *io_u, 292 unsigned int header_num) 293{ 294 void *p = io_u_verify_off(hdr, io_u, header_num); 295 struct vhdr_crc64 *vh = hdr_priv(hdr); 296 unsigned long long c; 297 298 dprint(FD_VERIFY, "crc64 verify io_u %p, len %u\n", io_u, hdr->len); 299 300 c = crc64(p, hdr->len - hdr_size(hdr)); 301 302 if (c != vh->crc64) { 303 log_err("crc64: verify failed at %llu/%u\n", 304 io_u->offset + header_num * hdr->len, 305 hdr->len); 306 log_err("crc64: wanted %llx, got %llx\n", 307 (unsigned long long) vh->crc64, c); 308 return EILSEQ; 309 } 310 311 return 0; 312} 313 314static int verify_io_u_crc32(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_crc32 *vh = hdr_priv(hdr); 319 uint32_t c; 320 321 dprint(FD_VERIFY, "crc32 verify io_u %p, len %u\n", io_u, hdr->len); 322 323 c = crc32(p, hdr->len - hdr_size(hdr)); 324 325 if (c != vh->crc32) { 326 log_err("crc32: verify failed at %llu/%u\n", 327 io_u->offset + header_num * hdr->len, hdr->len); 328 log_err("crc32: wanted %x, got %x\n", vh->crc32, c); 329 return EILSEQ; 330 } 331 332 return 0; 333} 334 335static int verify_io_u_crc32c(struct verify_header *hdr, struct io_u *io_u, 336 unsigned int header_num) 337{ 338 void *p = io_u_verify_off(hdr, io_u, header_num); 339 struct vhdr_crc32 *vh = hdr_priv(hdr); 340 uint32_t c; 341 342 dprint(FD_VERIFY, "crc32c verify io_u %p, len %u\n", io_u, hdr->len); 343 344 if (hdr->verify_type == VERIFY_CRC32C_INTEL) 345 c = crc32c_intel(p, hdr->len - hdr_size(hdr)); 346 else 347 c = crc32c(p, hdr->len - hdr_size(hdr)); 348 349 if (c != vh->crc32) { 350 log_err("crc32c: verify failed at %llu/%u\n", 351 io_u->offset + header_num * hdr->len, hdr->len); 352 log_err("crc32c: wanted %x, got %x\n", vh->crc32, c); 353 return EILSEQ; 354 } 355 356 return 0; 357} 358 359static int verify_io_u_md5(struct verify_header *hdr, struct io_u *io_u, 360 unsigned int header_num) 361{ 362 void *p = io_u_verify_off(hdr, io_u, header_num); 363 struct vhdr_md5 *vh = hdr_priv(hdr); 364 uint32_t hash[MD5_HASH_WORDS]; 365 struct md5_ctx md5_ctx = { 366 .hash = hash, 367 }; 368 369 dprint(FD_VERIFY, "md5 verify io_u %p, len %u\n", io_u, hdr->len); 370 371 md5_init(&md5_ctx); 372 md5_update(&md5_ctx, p, hdr->len - hdr_size(hdr)); 373 374 if (memcmp(vh->md5_digest, md5_ctx.hash, sizeof(hash))) { 375 log_err("md5: verify failed at %llu/%u\n", 376 io_u->offset + header_num * hdr->len, hdr->len); 377 hexdump(vh->md5_digest, sizeof(vh->md5_digest)); 378 hexdump(md5_ctx.hash, sizeof(hash)); 379 return EILSEQ; 380 } 381 382 return 0; 383} 384 385static unsigned int hweight8(unsigned int w) 386{ 387 unsigned int res = w - ((w >> 1) & 0x55); 388 389 res = (res & 0x33) + ((res >> 2) & 0x33); 390 return (res + (res >> 4)) & 0x0F; 391} 392 393int verify_io_u_pattern(unsigned long pattern, unsigned long pattern_size, 394 char *buf, unsigned int len, unsigned int mod) 395{ 396 unsigned int i; 397 char split_pattern[4]; 398 399 for (i = 0; i < 4; i++) { 400 split_pattern[i] = pattern & 0xff; 401 pattern >>= 8; 402 } 403 404 for (i = 0; i < len; i++) { 405 if (buf[i] != split_pattern[mod]) { 406 unsigned int bits; 407 408 bits = hweight8(buf[i] ^ split_pattern[mod]); 409 log_err("fio: got pattern %x, wanted %x. Bad bits %d\n", 410 buf[i], split_pattern[mod], bits); 411 log_err("fio: bad pattern block offset %u\n", i); 412 return EILSEQ; 413 } 414 mod++; 415 if (mod == pattern_size) 416 mod = 0; 417 } 418 419 return 0; 420} 421 422/* 423 * Push IO verification to a separate thread 424 */ 425int verify_io_u_async(struct thread_data *td, struct io_u *io_u) 426{ 427 if (io_u->file) 428 put_file_log(td, io_u->file); 429 430 io_u->file = NULL; 431 432 pthread_mutex_lock(&td->io_u_lock); 433 flist_del(&io_u->list); 434 flist_add_tail(&io_u->list, &td->verify_list); 435 pthread_mutex_unlock(&td->io_u_lock); 436 437 pthread_cond_signal(&td->verify_cond); 438 io_u->flags |= IO_U_F_FREE_DEF; 439 return 0; 440} 441 442int verify_io_u(struct thread_data *td, struct io_u *io_u) 443{ 444 struct verify_header *hdr; 445 unsigned int hdr_size, hdr_inc, hdr_num = 0; 446 void *p; 447 int ret; 448 449 if (td->o.verify == VERIFY_NULL || io_u->ddir != DDIR_READ) 450 return 0; 451 452 hdr_inc = io_u->buflen; 453 if (td->o.verify_interval) 454 hdr_inc = td->o.verify_interval; 455 456 ret = 0; 457 for (p = io_u->buf; p < io_u->buf + io_u->buflen; 458 p += hdr_inc, hdr_num++) { 459 if (ret && td->o.verify_fatal) { 460 td->terminate = 1; 461 break; 462 } 463 hdr_size = __hdr_size(td->o.verify); 464 if (td->o.verify_offset) 465 memswp(p, p + td->o.verify_offset, hdr_size); 466 hdr = p; 467 468 if (hdr->fio_magic != FIO_HDR_MAGIC) { 469 log_err("Bad verify header %x\n", hdr->fio_magic); 470 return EILSEQ; 471 } 472 473 if (td->o.verify_pattern_bytes) { 474 dprint(FD_VERIFY, "pattern verify io_u %p, len %u\n", 475 io_u, hdr->len); 476 ret = verify_io_u_pattern(td->o.verify_pattern, 477 td->o.verify_pattern_bytes, 478 p + hdr_size, 479 hdr_inc - hdr_size, 480 hdr_size % 4); 481 if (ret) 482 log_err("fio: verify failed at %llu/%u\n", 483 io_u->offset + hdr_num * hdr->len, 484 hdr->len); 485 continue; 486 } 487 488 switch (hdr->verify_type) { 489 case VERIFY_MD5: 490 ret = verify_io_u_md5(hdr, io_u, hdr_num); 491 break; 492 case VERIFY_CRC64: 493 ret = verify_io_u_crc64(hdr, io_u, hdr_num); 494 break; 495 case VERIFY_CRC32C: 496 case VERIFY_CRC32C_INTEL: 497 ret = verify_io_u_crc32c(hdr, io_u, hdr_num); 498 break; 499 case VERIFY_CRC32: 500 ret = verify_io_u_crc32(hdr, io_u, hdr_num); 501 break; 502 case VERIFY_CRC16: 503 ret = verify_io_u_crc16(hdr, io_u, hdr_num); 504 break; 505 case VERIFY_CRC7: 506 ret = verify_io_u_crc7(hdr, io_u, hdr_num); 507 break; 508 case VERIFY_SHA256: 509 ret = verify_io_u_sha256(hdr, io_u, hdr_num); 510 break; 511 case VERIFY_SHA512: 512 ret = verify_io_u_sha512(hdr, io_u, hdr_num); 513 break; 514 case VERIFY_META: 515 ret = verify_io_u_meta(hdr, td, io_u, hdr_num); 516 break; 517 default: 518 log_err("Bad verify type %u\n", hdr->verify_type); 519 ret = EINVAL; 520 } 521 } 522 523 return ret; 524} 525 526static void fill_meta(struct verify_header *hdr, struct thread_data *td, 527 struct io_u *io_u, unsigned int header_num) 528{ 529 struct vhdr_meta *vh = hdr_priv(hdr); 530 531 vh->thread = td->thread_number; 532 533 vh->time_sec = io_u->start_time.tv_sec; 534 vh->time_usec = io_u->start_time.tv_usec; 535 536 vh->numberio = td->io_issues[DDIR_WRITE]; 537 538 vh->offset = io_u->offset + header_num * td->o.verify_interval; 539} 540 541static void fill_sha512(struct verify_header *hdr, void *p, unsigned int len) 542{ 543 struct vhdr_sha512 *vh = hdr_priv(hdr); 544 struct sha512_ctx sha512_ctx = { 545 .buf = vh->sha512, 546 }; 547 548 sha512_init(&sha512_ctx); 549 sha512_update(&sha512_ctx, p, len); 550} 551 552static void fill_sha256(struct verify_header *hdr, void *p, unsigned int len) 553{ 554 struct vhdr_sha256 *vh = hdr_priv(hdr); 555 struct sha256_ctx sha256_ctx = { 556 .buf = vh->sha256, 557 }; 558 559 sha256_init(&sha256_ctx); 560 sha256_update(&sha256_ctx, p, len); 561} 562 563static void fill_crc7(struct verify_header *hdr, void *p, unsigned int len) 564{ 565 struct vhdr_crc7 *vh = hdr_priv(hdr); 566 567 vh->crc7 = crc7(p, len); 568} 569 570static void fill_crc16(struct verify_header *hdr, void *p, unsigned int len) 571{ 572 struct vhdr_crc16 *vh = hdr_priv(hdr); 573 574 vh->crc16 = crc16(p, len); 575} 576 577static void fill_crc32(struct verify_header *hdr, void *p, unsigned int len) 578{ 579 struct vhdr_crc32 *vh = hdr_priv(hdr); 580 581 vh->crc32 = crc32(p, len); 582} 583 584static void fill_crc32c(struct verify_header *hdr, void *p, unsigned int len) 585{ 586 struct vhdr_crc32 *vh = hdr_priv(hdr); 587 588 if (hdr->verify_type == VERIFY_CRC32C_INTEL) 589 vh->crc32 = crc32c_intel(p, len); 590 else 591 vh->crc32 = crc32c(p, len); 592} 593 594static void fill_crc64(struct verify_header *hdr, void *p, unsigned int len) 595{ 596 struct vhdr_crc64 *vh = hdr_priv(hdr); 597 598 vh->crc64 = crc64(p, len); 599} 600 601static void fill_md5(struct verify_header *hdr, void *p, unsigned int len) 602{ 603 struct vhdr_md5 *vh = hdr_priv(hdr); 604 struct md5_ctx md5_ctx = { 605 .hash = (uint32_t *) vh->md5_digest, 606 }; 607 608 md5_init(&md5_ctx); 609 md5_update(&md5_ctx, p, len); 610} 611 612/* 613 * fill body of io_u->buf with random data and add a header with the 614 * crc32 or md5 sum of that data. 615 */ 616void populate_verify_io_u(struct thread_data *td, struct io_u *io_u) 617{ 618 struct verify_header *hdr; 619 void *p = io_u->buf, *data; 620 unsigned int hdr_inc, data_len, header_num = 0; 621 622 if (td->o.verify == VERIFY_NULL) 623 return; 624 625 fill_pattern(td, p, io_u->buflen); 626 627 hdr_inc = io_u->buflen; 628 if (td->o.verify_interval) 629 hdr_inc = td->o.verify_interval; 630 631 for (; p < io_u->buf + io_u->buflen; p += hdr_inc) { 632 hdr = p; 633 634 hdr->fio_magic = FIO_HDR_MAGIC; 635 hdr->verify_type = td->o.verify; 636 hdr->len = hdr_inc; 637 data_len = hdr_inc - hdr_size(hdr); 638 639 data = p + hdr_size(hdr); 640 switch (td->o.verify) { 641 case VERIFY_MD5: 642 dprint(FD_VERIFY, "fill md5 io_u %p, len %u\n", 643 io_u, hdr->len); 644 fill_md5(hdr, data, data_len); 645 break; 646 case VERIFY_CRC64: 647 dprint(FD_VERIFY, "fill crc64 io_u %p, len %u\n", 648 io_u, hdr->len); 649 fill_crc64(hdr, data, data_len); 650 break; 651 case VERIFY_CRC32C: 652 case VERIFY_CRC32C_INTEL: 653 dprint(FD_VERIFY, "fill crc32c io_u %p, len %u\n", 654 io_u, hdr->len); 655 fill_crc32c(hdr, data, data_len); 656 break; 657 case VERIFY_CRC32: 658 dprint(FD_VERIFY, "fill crc32 io_u %p, len %u\n", 659 io_u, hdr->len); 660 fill_crc32(hdr, data, data_len); 661 break; 662 case VERIFY_CRC16: 663 dprint(FD_VERIFY, "fill crc16 io_u %p, len %u\n", 664 io_u, hdr->len); 665 fill_crc16(hdr, data, data_len); 666 break; 667 case VERIFY_CRC7: 668 dprint(FD_VERIFY, "fill crc7 io_u %p, len %u\n", 669 io_u, hdr->len); 670 fill_crc7(hdr, data, data_len); 671 break; 672 case VERIFY_SHA256: 673 dprint(FD_VERIFY, "fill sha256 io_u %p, len %u\n", 674 io_u, hdr->len); 675 fill_sha256(hdr, data, data_len); 676 break; 677 case VERIFY_SHA512: 678 dprint(FD_VERIFY, "fill sha512 io_u %p, len %u\n", 679 io_u, hdr->len); 680 fill_sha512(hdr, data, data_len); 681 break; 682 case VERIFY_META: 683 dprint(FD_VERIFY, "fill meta io_u %p, len %u\n", 684 io_u, hdr->len); 685 fill_meta(hdr, td, io_u, header_num); 686 break; 687 default: 688 log_err("fio: bad verify type: %d\n", td->o.verify); 689 assert(0); 690 } 691 if (td->o.verify_offset) 692 memswp(p, p + td->o.verify_offset, hdr_size(hdr)); 693 header_num++; 694 } 695} 696 697int get_next_verify(struct thread_data *td, struct io_u *io_u) 698{ 699 struct io_piece *ipo = NULL; 700 701 /* 702 * this io_u is from a requeue, we already filled the offsets 703 */ 704 if (io_u->file) 705 return 0; 706 707 if (!RB_EMPTY_ROOT(&td->io_hist_tree)) { 708 struct rb_node *n = rb_first(&td->io_hist_tree); 709 710 ipo = rb_entry(n, struct io_piece, rb_node); 711 rb_erase(n, &td->io_hist_tree); 712 } else if (!flist_empty(&td->io_hist_list)) { 713 ipo = flist_entry(td->io_hist_list.next, struct io_piece, list); 714 flist_del(&ipo->list); 715 } 716 717 if (ipo) { 718 io_u->offset = ipo->offset; 719 io_u->buflen = ipo->len; 720 io_u->file = ipo->file; 721 722 if (!fio_file_open(io_u->file)) { 723 int r = td_io_open_file(td, io_u->file); 724 725 if (r) { 726 dprint(FD_VERIFY, "failed file %s open\n", 727 io_u->file->file_name); 728 return 1; 729 } 730 } 731 732 get_file(ipo->file); 733 assert(fio_file_open(io_u->file)); 734 io_u->ddir = DDIR_READ; 735 io_u->xfer_buf = io_u->buf; 736 io_u->xfer_buflen = io_u->buflen; 737 free(ipo); 738 dprint(FD_VERIFY, "get_next_verify: ret io_u %p\n", io_u); 739 return 0; 740 } 741 742 dprint(FD_VERIFY, "get_next_verify: empty\n"); 743 return 1; 744} 745 746static void *verify_async_thread(void *data) 747{ 748 struct thread_data *td = data; 749 struct io_u *io_u; 750 int ret = 0; 751 752 if (td->o.verify_cpumask_set && 753 fio_setaffinity(td->pid, td->o.verify_cpumask)) { 754 log_err("fio: failed setting verify thread affinity\n"); 755 goto done; 756 } 757 758 do { 759 FLIST_HEAD(list); 760 761 read_barrier(); 762 if (td->verify_thread_exit) 763 break; 764 765 pthread_mutex_lock(&td->io_u_lock); 766 767 while (flist_empty(&td->verify_list) && 768 !td->verify_thread_exit) { 769 ret = pthread_cond_wait(&td->verify_cond, 770 &td->io_u_lock); 771 if (ret) { 772 pthread_mutex_unlock(&td->io_u_lock); 773 break; 774 } 775 } 776 777 flist_splice_init(&td->verify_list, &list); 778 pthread_mutex_unlock(&td->io_u_lock); 779 780 if (flist_empty(&list)) 781 continue; 782 783 while (!flist_empty(&list)) { 784 io_u = flist_entry(list.next, struct io_u, list); 785 flist_del_init(&io_u->list); 786 787 ret = verify_io_u(td, io_u); 788 put_io_u(td, io_u); 789 if (!ret) 790 continue; 791 if (td->o.continue_on_error && 792 td_non_fatal_error(ret)) { 793 update_error_count(td, ret); 794 td_clear_error(td); 795 ret = 0; 796 } 797 } 798 } while (!ret); 799 800 if (ret) { 801 td_verror(td, ret, "async_verify"); 802 td->terminate = 1; 803 } 804 805done: 806 pthread_mutex_lock(&td->io_u_lock); 807 td->nr_verify_threads--; 808 pthread_mutex_unlock(&td->io_u_lock); 809 810 pthread_cond_signal(&td->free_cond); 811 return NULL; 812} 813 814int verify_async_init(struct thread_data *td) 815{ 816 int i, ret; 817 818 td->verify_thread_exit = 0; 819 820 td->verify_threads = malloc(sizeof(pthread_t) * td->o.verify_async); 821 for (i = 0; i < td->o.verify_async; i++) { 822 ret = pthread_create(&td->verify_threads[i], NULL, 823 verify_async_thread, td); 824 if (ret) { 825 log_err("fio: async verify creation failed: %s\n", 826 strerror(ret)); 827 break; 828 } 829 ret = pthread_detach(td->verify_threads[i]); 830 if (ret) { 831 log_err("fio: async verify thread detach failed: %s\n", 832 strerror(ret)); 833 break; 834 } 835 td->nr_verify_threads++; 836 } 837 838 if (i != td->o.verify_async) { 839 log_err("fio: only %d verify threads started, exiting\n", i); 840 td->verify_thread_exit = 1; 841 write_barrier(); 842 pthread_cond_broadcast(&td->verify_cond); 843 return 1; 844 } 845 846 return 0; 847} 848 849void verify_async_exit(struct thread_data *td) 850{ 851 td->verify_thread_exit = 1; 852 write_barrier(); 853 pthread_cond_broadcast(&td->verify_cond); 854 855 pthread_mutex_lock(&td->io_u_lock); 856 857 while (td->nr_verify_threads) 858 pthread_cond_wait(&td->free_cond, &td->io_u_lock); 859 860 pthread_mutex_unlock(&td->io_u_lock); 861 free(td->verify_threads); 862 td->verify_threads = NULL; 863} 864