filesetup.c revision afad68f778a764cbe57d4a5d54cbea32444aaa45
1#include <unistd.h> 2#include <fcntl.h> 3#include <string.h> 4#include <assert.h> 5#include <dirent.h> 6#include <sys/stat.h> 7#include <sys/mman.h> 8#include <sys/types.h> 9 10#include "fio.h" 11#include "smalloc.h" 12#include "filehash.h" 13 14static int root_warn; 15 16/* 17 * Leaves f->fd open on success, caller must close 18 */ 19static int extend_file(struct thread_data *td, struct fio_file *f) 20{ 21 int r, new_layout = 0, unlink_file = 0, flags; 22 unsigned long long left; 23 unsigned int bs; 24 char *b; 25 26 if (read_only) { 27 log_err("fio: refusing extend of file due to read-only\n"); 28 return 0; 29 } 30 31 /* 32 * check if we need to lay the file out complete again. fio 33 * does that for operations involving reads, or for writes 34 * where overwrite is set 35 */ 36 if (td_read(td) || (td_write(td) && td->o.overwrite) || 37 (td_write(td) && td->io_ops->flags & FIO_NOEXTEND)) 38 new_layout = 1; 39 if (td_write(td) && !td->o.overwrite) 40 unlink_file = 1; 41 42 if (unlink_file || new_layout) { 43 dprint(FD_FILE, "layout unlink %s\n", f->file_name); 44 if ((unlink(f->file_name) < 0) && (errno != ENOENT)) { 45 td_verror(td, errno, "unlink"); 46 return 1; 47 } 48 } 49 50 flags = O_WRONLY | O_CREAT; 51 if (new_layout) 52 flags |= O_TRUNC; 53 54 dprint(FD_FILE, "open file %s, flags %x\n", f->file_name, flags); 55 f->fd = open(f->file_name, flags, 0644); 56 if (f->fd < 0) { 57 td_verror(td, errno, "open"); 58 return 1; 59 } 60 61 if (!new_layout) 62 goto done; 63 64 dprint(FD_FILE, "truncate file %s, size %llu\n", f->file_name, 65 f->real_file_size); 66 if (ftruncate(f->fd, f->real_file_size) == -1) { 67 td_verror(td, errno, "ftruncate"); 68 goto err; 69 } 70 71#ifdef FIO_HAVE_FALLOCATE 72 dprint(FD_FILE, "fallocate file %s, size %llu\n", f->file_name, 73 f->real_file_size); 74 r = posix_fallocate(f->fd, 0, f->real_file_size); 75 if (r < 0) 76 log_err("fio: posix_fallocate fails: %s\n", strerror(-r)); 77#endif 78 79 b = malloc(td->o.max_bs[DDIR_WRITE]); 80 memset(b, 0, td->o.max_bs[DDIR_WRITE]); 81 82 left = f->real_file_size; 83 while (left && !td->terminate) { 84 bs = td->o.max_bs[DDIR_WRITE]; 85 if (bs > left) 86 bs = left; 87 88 r = write(f->fd, b, bs); 89 90 if (r == (int) bs) { 91 left -= bs; 92 continue; 93 } else { 94 if (r < 0) 95 td_verror(td, errno, "write"); 96 else 97 td_verror(td, EIO, "write"); 98 99 break; 100 } 101 } 102 103 if (td->terminate) { 104 dprint(FD_FILE, "terminate unlink %s\n", f->file_name); 105 unlink(f->file_name); 106 } else if (td->o.create_fsync) { 107 if (fsync(f->fd) < 0) { 108 td_verror(td, errno, "fsync"); 109 goto err; 110 } 111 } 112 113 free(b); 114done: 115 return 0; 116err: 117 close(f->fd); 118 f->fd = -1; 119 return 1; 120} 121 122static int pre_read_file(struct thread_data *td, struct fio_file *f) 123{ 124 int r; 125 unsigned long long left; 126 unsigned int bs; 127 char *b; 128 129 bs = td->o.max_bs[DDIR_READ]; 130 b = malloc(bs); 131 memset(b, 0, bs); 132 133 lseek(f->fd, f->file_offset, SEEK_SET); 134 left = f->io_size; 135 136 while (left && !td->terminate) { 137 if (bs > left) 138 bs = left; 139 140 r = read(f->fd, b, bs); 141 142 if (r == (int) bs) { 143 left -= bs; 144 continue; 145 } else { 146 td_verror(td, EIO, "pre_read"); 147 break; 148 } 149 } 150 151 free(b); 152 return 0; 153} 154 155static unsigned long long get_rand_file_size(struct thread_data *td) 156{ 157 unsigned long long ret, sized; 158 long r; 159 160 r = os_random_long(&td->file_size_state); 161 sized = td->o.file_size_high - td->o.file_size_low; 162 ret = (unsigned long long) ((double) sized * (r / (OS_RAND_MAX + 1.0))); 163 ret += td->o.file_size_low; 164 ret -= (ret % td->o.rw_min_bs); 165 return ret; 166} 167 168static int file_size(struct thread_data *td, struct fio_file *f) 169{ 170 struct stat st; 171 172 if (stat(f->file_name, &st) == -1) { 173 td_verror(td, errno, "fstat"); 174 return 1; 175 } 176 177 f->real_file_size = st.st_size; 178 return 0; 179} 180 181static int bdev_size(struct thread_data *td, struct fio_file *f) 182{ 183 unsigned long long bytes; 184 int r; 185 186 if (td->io_ops->open_file(td, f)) { 187 log_err("fio: failed opening blockdev %s for size check\n", 188 f->file_name); 189 return 1; 190 } 191 192 r = blockdev_size(f->fd, &bytes); 193 if (r) { 194 td_verror(td, r, "blockdev_size"); 195 goto err; 196 } 197 198 if (!bytes) { 199 log_err("%s: zero sized block device?\n", f->file_name); 200 goto err; 201 } 202 203 f->real_file_size = bytes; 204 return 0; 205err: 206 td->io_ops->close_file(td, f); 207 return 1; 208} 209 210static int get_file_size(struct thread_data *td, struct fio_file *f) 211{ 212 int ret = 0; 213 214 if (f->flags & FIO_SIZE_KNOWN) 215 return 0; 216 217 if (f->filetype == FIO_TYPE_FILE) 218 ret = file_size(td, f); 219 else if (f->filetype == FIO_TYPE_BD) 220 ret = bdev_size(td, f); 221 else 222 f->real_file_size = -1; 223 224 if (ret) 225 return ret; 226 227 if (f->file_offset > f->real_file_size) { 228 log_err("%s: offset extends end (%Lu > %Lu)\n", td->o.name, 229 f->file_offset, f->real_file_size); 230 return 1; 231 } 232 233 f->flags |= FIO_SIZE_KNOWN; 234 return 0; 235} 236 237static int __file_invalidate_cache(struct thread_data *td, struct fio_file *f, 238 unsigned long long off, 239 unsigned long long len) 240{ 241 int ret = 0; 242 243 if (len == -1ULL) 244 len = f->io_size; 245 if (off == -1ULL) 246 off = f->file_offset; 247 248 dprint(FD_IO, "invalidate cache %s: %llu/%llu\n", f->file_name, off, 249 len); 250 251 /* 252 * FIXME: add blockdev flushing too 253 */ 254 if (f->mmap) 255 ret = madvise(f->mmap, len, MADV_DONTNEED); 256 else if (f->filetype == FIO_TYPE_FILE) { 257 ret = fadvise(f->fd, off, len, POSIX_FADV_DONTNEED); 258 } else if (f->filetype == FIO_TYPE_BD) { 259 ret = blockdev_invalidate_cache(f->fd); 260 if (ret < 0 && errno == EACCES && geteuid()) { 261 if (!root_warn) { 262 log_err("fio: only root may flush block " 263 "devices. Cache flush bypassed!\n"); 264 root_warn = 1; 265 } 266 ret = 0; 267 } 268 } else if (f->filetype == FIO_TYPE_CHAR || f->filetype == FIO_TYPE_PIPE) 269 ret = 0; 270 271 if (ret < 0) { 272 td_verror(td, errno, "invalidate_cache"); 273 return 1; 274 } else if (ret > 0) { 275 td_verror(td, ret, "invalidate_cache"); 276 return 1; 277 } 278 279 return ret; 280 281} 282 283int file_invalidate_cache(struct thread_data *td, struct fio_file *f) 284{ 285 if (!(f->flags & FIO_FILE_OPEN)) 286 return 0; 287 288 return __file_invalidate_cache(td, f, -1, -1); 289} 290 291int generic_close_file(struct thread_data fio_unused *td, struct fio_file *f) 292{ 293 int ret = 0; 294 295 dprint(FD_FILE, "fd close %s\n", f->file_name); 296 297 remove_file_hash(f); 298 299 if (close(f->fd) < 0) 300 ret = errno; 301 302 f->fd = -1; 303 return ret; 304} 305 306static int file_lookup_open(struct fio_file *f, int flags) 307{ 308 struct fio_file *__f; 309 int from_hash; 310 311 __f = lookup_file_hash(f->file_name); 312 if (__f) { 313 dprint(FD_FILE, "found file in hash %s\n", f->file_name); 314 /* 315 * racy, need the __f->lock locked 316 */ 317 f->lock = __f->lock; 318 f->lock_owner = __f->lock_owner; 319 f->lock_batch = __f->lock_batch; 320 f->lock_ddir = __f->lock_ddir; 321 from_hash = 1; 322 } else { 323 dprint(FD_FILE, "file not found in hash %s\n", f->file_name); 324 from_hash = 0; 325 } 326 327 f->fd = open(f->file_name, flags, 0600); 328 return from_hash; 329} 330 331int generic_open_file(struct thread_data *td, struct fio_file *f) 332{ 333 int is_std = 0; 334 int flags = 0; 335 int from_hash = 0; 336 337 dprint(FD_FILE, "fd open %s\n", f->file_name); 338 339 if (!strcmp(f->file_name, "-")) { 340 if (td_rw(td)) { 341 log_err("fio: can't read/write to stdin/out\n"); 342 return 1; 343 } 344 is_std = 1; 345 346 /* 347 * move output logging to stderr, if we are writing to stdout 348 */ 349 if (td_write(td)) 350 f_out = stderr; 351 } 352 353 if (td->o.odirect) 354 flags |= OS_O_DIRECT; 355 if (td->o.sync_io) 356 flags |= O_SYNC; 357 if (f->filetype != FIO_TYPE_FILE) 358 flags |= FIO_O_NOATIME; 359 if (td->o.create_on_open) 360 flags |= O_CREAT; 361 362open_again: 363 if (td_write(td)) { 364 if (!read_only) 365 flags |= O_RDWR; 366 367 if (f->filetype == FIO_TYPE_FILE) 368 flags |= O_CREAT; 369 370 if (is_std) 371 f->fd = dup(STDOUT_FILENO); 372 else 373 from_hash = file_lookup_open(f, flags); 374 } else { 375 if (f->filetype == FIO_TYPE_CHAR && !read_only) 376 flags |= O_RDWR; 377 else 378 flags |= O_RDONLY; 379 380 if (is_std) 381 f->fd = dup(STDIN_FILENO); 382 else 383 from_hash = file_lookup_open(f, flags); 384 } 385 386 if (f->fd == -1) { 387 char buf[FIO_VERROR_SIZE]; 388 int __e = errno; 389 390 if (errno == EPERM && (flags & FIO_O_NOATIME)) { 391 flags &= ~FIO_O_NOATIME; 392 goto open_again; 393 } 394 395 snprintf(buf, sizeof(buf) - 1, "open(%s)", f->file_name); 396 397 td_verror(td, __e, buf); 398 } 399 400 if (!from_hash && f->fd != -1) { 401 if (add_file_hash(f)) { 402 int ret; 403 404 /* 405 * OK to ignore, we haven't done anything with it 406 */ 407 ret = generic_close_file(td, f); 408 goto open_again; 409 } 410 } 411 412 return 0; 413} 414 415int generic_get_file_size(struct thread_data *td, struct fio_file *f) 416{ 417 return get_file_size(td, f); 418} 419 420/* 421 * open/close all files, so that ->real_file_size gets set 422 */ 423static int get_file_sizes(struct thread_data *td) 424{ 425 struct fio_file *f; 426 unsigned int i; 427 int err = 0; 428 429 for_each_file(td, f, i) { 430 dprint(FD_FILE, "get file size for %p/%d/%p\n", f, i, 431 f->file_name); 432 433 if (td_io_get_file_size(td, f)) { 434 if (td->error != ENOENT) { 435 log_err("%s\n", td->verror); 436 err = 1; 437 } 438 clear_error(td); 439 } 440 441 if (f->real_file_size == -1ULL && td->o.size) 442 f->real_file_size = td->o.size / td->o.nr_files; 443 } 444 445 return err; 446} 447 448/* 449 * Open the files and setup files sizes, creating files if necessary. 450 */ 451int setup_files(struct thread_data *td) 452{ 453 unsigned long long total_size, extend_size; 454 struct fio_file *f; 455 unsigned int i; 456 int err = 0, need_extend; 457 458 dprint(FD_FILE, "setup files\n"); 459 460 if (td->o.read_iolog_file) 461 return 0; 462 463 /* 464 * if ioengine defines a setup() method, it's responsible for 465 * opening the files and setting f->real_file_size to indicate 466 * the valid range for that file. 467 */ 468 if (td->io_ops->setup) 469 err = td->io_ops->setup(td); 470 else 471 err = get_file_sizes(td); 472 473 if (err) 474 return err; 475 476 /* 477 * check sizes. if the files/devices do not exist and the size 478 * isn't passed to fio, abort. 479 */ 480 total_size = 0; 481 for_each_file(td, f, i) { 482 if (f->real_file_size == -1ULL) 483 total_size = -1ULL; 484 else 485 total_size += f->real_file_size; 486 } 487 488 /* 489 * device/file sizes are zero and no size given, punt 490 */ 491 if ((!total_size || total_size == -1ULL) && !td->o.size && 492 !(td->io_ops->flags & FIO_NOIO) && !td->o.fill_device) { 493 log_err("%s: you need to specify size=\n", td->o.name); 494 td_verror(td, EINVAL, "total_file_size"); 495 return 1; 496 } 497 498 /* 499 * now file sizes are known, so we can set ->io_size. if size= is 500 * not given, ->io_size is just equal to ->real_file_size. if size 501 * is given, ->io_size is size / nr_files. 502 */ 503 extend_size = total_size = 0; 504 need_extend = 0; 505 for_each_file(td, f, i) { 506 f->file_offset = td->o.start_offset; 507 508 if (!td->o.file_size_low) { 509 /* 510 * no file size range given, file size is equal to 511 * total size divided by number of files. if that is 512 * zero, set it to the real file size. 513 */ 514 f->io_size = td->o.size / td->o.nr_files; 515 if (!f->io_size) 516 f->io_size = f->real_file_size - f->file_offset; 517 } else if (f->real_file_size < td->o.file_size_low || 518 f->real_file_size > td->o.file_size_high) { 519 if (f->file_offset > td->o.file_size_low) 520 goto err_offset; 521 /* 522 * file size given. if it's fixed, use that. if it's a 523 * range, generate a random size in-between. 524 */ 525 if (td->o.file_size_low == td->o.file_size_high) { 526 f->io_size = td->o.file_size_low 527 - f->file_offset; 528 } else { 529 f->io_size = get_rand_file_size(td) 530 - f->file_offset; 531 } 532 } else 533 f->io_size = f->real_file_size - f->file_offset; 534 535 if (f->io_size == -1ULL) 536 total_size = -1ULL; 537 else 538 total_size += f->io_size; 539 540 if (f->filetype == FIO_TYPE_FILE && 541 (f->io_size + f->file_offset) > f->real_file_size && 542 !(td->io_ops->flags & FIO_DISKLESSIO)) { 543 if (!td->o.create_on_open) { 544 need_extend++; 545 extend_size += (f->io_size + f->file_offset); 546 } else 547 f->real_file_size = f->io_size + f->file_offset; 548 f->flags |= FIO_FILE_EXTEND; 549 } 550 } 551 552 if (!td->o.size || td->o.size > total_size) 553 td->o.size = total_size; 554 555 /* 556 * See if we need to extend some files 557 */ 558 if (need_extend) { 559 temp_stall_ts = 1; 560 if (!terse_output) 561 log_info("%s: Laying out IO file(s) (%u file(s) /" 562 " %LuMiB)\n", td->o.name, need_extend, 563 extend_size >> 20); 564 565 for_each_file(td, f, i) { 566 unsigned long long old_len, extend_len; 567 568 if (!(f->flags & FIO_FILE_EXTEND)) 569 continue; 570 571 assert(f->filetype == FIO_TYPE_FILE); 572 f->flags &= ~FIO_FILE_EXTEND; 573 old_len = f->real_file_size; 574 extend_len = f->io_size + f->file_offset - old_len; 575 f->real_file_size = (f->io_size + f->file_offset); 576 err = extend_file(td, f); 577 if (err) 578 break; 579 580 err = __file_invalidate_cache(td, f, old_len, 581 extend_len); 582 close(f->fd); 583 f->fd = -1; 584 if (err) 585 break; 586 } 587 temp_stall_ts = 0; 588 } 589 590 if (err) 591 return err; 592 593 if (!td->o.zone_size) 594 td->o.zone_size = td->o.size; 595 596 /* 597 * iolog already set the total io size, if we read back 598 * stored entries. 599 */ 600 if (!td->o.read_iolog_file) 601 td->total_io_size = td->o.size * td->o.loops; 602 return 0; 603err_offset: 604 log_err("%s: you need to specify valid offset=\n", td->o.name); 605 return 1; 606} 607 608int pre_read_files(struct thread_data *td) 609{ 610 struct fio_file *f; 611 unsigned int i; 612 613 dprint(FD_FILE, "pre_read files\n"); 614 615 for_each_file(td, f, i) { 616 pre_read_file(td, f); 617 } 618 619 return 1; 620} 621 622int init_random_map(struct thread_data *td) 623{ 624 unsigned long long blocks, num_maps; 625 struct fio_file *f; 626 unsigned int i; 627 628 if (td->o.norandommap || !td_random(td)) 629 return 0; 630 631 for_each_file(td, f, i) { 632 blocks = (f->real_file_size + td->o.rw_min_bs - 1) / 633 (unsigned long long) td->o.rw_min_bs; 634 num_maps = (blocks + BLOCKS_PER_MAP - 1) / 635 (unsigned long long) BLOCKS_PER_MAP; 636 f->file_map = smalloc(num_maps * sizeof(int)); 637 if (f->file_map) { 638 f->num_maps = num_maps; 639 continue; 640 } 641 if (!td->o.softrandommap) { 642 log_err("fio: failed allocating random map. If running" 643 " a large number of jobs, try the 'norandommap'" 644 " option or set 'softrandommap'. Or give" 645 " a larger --alloc-size to fio.\n"); 646 return 1; 647 } 648 649 log_info("fio: file %s failed allocating random map. Running " 650 "job without.\n", f->file_name); 651 f->num_maps = 0; 652 } 653 654 return 0; 655} 656 657void close_files(struct thread_data *td) 658{ 659 struct fio_file *f; 660 unsigned int i; 661 662 for_each_file(td, f, i) 663 td_io_close_file(td, f); 664} 665 666void close_and_free_files(struct thread_data *td) 667{ 668 struct fio_file *f; 669 unsigned int i; 670 671 dprint(FD_FILE, "close files\n"); 672 673 for_each_file(td, f, i) { 674 if (td->o.unlink && f->filetype == FIO_TYPE_FILE) { 675 dprint(FD_FILE, "free unlink %s\n", f->file_name); 676 unlink(f->file_name); 677 } 678 679 td_io_close_file(td, f); 680 remove_file_hash(f); 681 682 sfree(f->file_name); 683 f->file_name = NULL; 684 685 if (f->file_map) { 686 sfree(f->file_map); 687 f->file_map = NULL; 688 } 689 sfree(f); 690 } 691 692 td->o.filename = NULL; 693 free(td->files); 694 td->files_index = 0; 695 td->files = NULL; 696 td->o.nr_files = 0; 697} 698 699static void get_file_type(struct fio_file *f) 700{ 701 struct stat sb; 702 703 if (!strcmp(f->file_name, "-")) 704 f->filetype = FIO_TYPE_PIPE; 705 else 706 f->filetype = FIO_TYPE_FILE; 707 708 if (!lstat(f->file_name, &sb)) { 709 if (S_ISBLK(sb.st_mode)) 710 f->filetype = FIO_TYPE_BD; 711 else if (S_ISCHR(sb.st_mode)) 712 f->filetype = FIO_TYPE_CHAR; 713 else if (S_ISFIFO(sb.st_mode)) 714 f->filetype = FIO_TYPE_PIPE; 715 } 716} 717 718int add_file(struct thread_data *td, const char *fname) 719{ 720 int cur_files = td->files_index; 721 char file_name[PATH_MAX]; 722 struct fio_file *f; 723 int len = 0; 724 725 dprint(FD_FILE, "add file %s\n", fname); 726 727 f = smalloc(sizeof(*f)); 728 if (!f) { 729 log_err("fio: smalloc OOM\n"); 730 assert(0); 731 } 732 733 f->fd = -1; 734 735 if (td->files_size <= td->files_index) { 736 int new_size = td->o.nr_files + 1; 737 738 dprint(FD_FILE, "resize file array to %d files\n", new_size); 739 740 td->files = realloc(td->files, new_size * sizeof(f)); 741 td->files_size = new_size; 742 } 743 td->files[cur_files] = f; 744 745 /* 746 * init function, io engine may not be loaded yet 747 */ 748 if (td->io_ops && (td->io_ops->flags & FIO_DISKLESSIO)) 749 f->real_file_size = -1ULL; 750 751 if (td->o.directory) 752 len = sprintf(file_name, "%s/", td->o.directory); 753 754 sprintf(file_name + len, "%s", fname); 755 f->file_name = smalloc_strdup(file_name); 756 if (!f->file_name) { 757 log_err("fio: smalloc OOM\n"); 758 assert(0); 759 } 760 761 get_file_type(f); 762 763 switch (td->o.file_lock_mode) { 764 case FILE_LOCK_NONE: 765 break; 766 case FILE_LOCK_READWRITE: 767 f->lock = fio_mutex_rw_init(); 768 break; 769 case FILE_LOCK_EXCLUSIVE: 770 f->lock = fio_mutex_init(1); 771 break; 772 default: 773 log_err("fio: unknown lock mode: %d\n", td->o.file_lock_mode); 774 assert(0); 775 } 776 777 td->files_index++; 778 if (f->filetype == FIO_TYPE_FILE) 779 td->nr_normal_files++; 780 781 dprint(FD_FILE, "file %p \"%s\" added at %d\n", f, f->file_name, 782 cur_files); 783 784 return cur_files; 785} 786 787void get_file(struct fio_file *f) 788{ 789 dprint(FD_FILE, "get file %s, ref=%d\n", f->file_name, f->references); 790 assert(f->flags & FIO_FILE_OPEN); 791 f->references++; 792} 793 794int put_file(struct thread_data *td, struct fio_file *f) 795{ 796 int f_ret = 0, ret = 0; 797 798 dprint(FD_FILE, "put file %s, ref=%d\n", f->file_name, f->references); 799 800 if (!(f->flags & FIO_FILE_OPEN)) 801 return 0; 802 803 assert(f->references); 804 if (--f->references) 805 return 0; 806 807 if (should_fsync(td) && td->o.fsync_on_close) 808 f_ret = fsync(f->fd); 809 810 if (td->io_ops->close_file) 811 ret = td->io_ops->close_file(td, f); 812 813 if (!ret) 814 ret = f_ret; 815 816 td->nr_open_files--; 817 f->flags &= ~FIO_FILE_OPEN; 818 return ret; 819} 820 821void lock_file(struct thread_data *td, struct fio_file *f, enum fio_ddir ddir) 822{ 823 if (!f->lock || td->o.file_lock_mode == FILE_LOCK_NONE) 824 return; 825 826 if (f->lock_owner == td && f->lock_batch--) 827 return; 828 829 if (td->o.file_lock_mode == FILE_LOCK_READWRITE) { 830 if (ddir == DDIR_READ) 831 fio_mutex_down_read(f->lock); 832 else 833 fio_mutex_down_write(f->lock); 834 } else if (td->o.file_lock_mode == FILE_LOCK_EXCLUSIVE) 835 fio_mutex_down(f->lock); 836 837 f->lock_owner = td; 838 f->lock_batch = td->o.lockfile_batch; 839 f->lock_ddir = ddir; 840} 841 842void unlock_file(struct thread_data *td, struct fio_file *f) 843{ 844 if (!f->lock || td->o.file_lock_mode == FILE_LOCK_NONE) 845 return; 846 if (f->lock_batch) 847 return; 848 849 if (td->o.file_lock_mode == FILE_LOCK_READWRITE) { 850 const int is_read = f->lock_ddir == DDIR_READ; 851 int val = fio_mutex_getval(f->lock); 852 853 if ((is_read && val == 1) || (!is_read && val == -1)) 854 f->lock_owner = NULL; 855 856 if (is_read) 857 fio_mutex_up_read(f->lock); 858 else 859 fio_mutex_up_write(f->lock); 860 } else if (td->o.file_lock_mode == FILE_LOCK_EXCLUSIVE) { 861 int val = fio_mutex_getval(f->lock); 862 863 if (val == 0) 864 f->lock_owner = NULL; 865 866 fio_mutex_up(f->lock); 867 } 868} 869 870void unlock_file_all(struct thread_data *td, struct fio_file *f) 871{ 872 if (f->lock_owner != td) 873 return; 874 875 f->lock_batch = 0; 876 unlock_file(td, f); 877} 878 879static int recurse_dir(struct thread_data *td, const char *dirname) 880{ 881 struct dirent *dir; 882 int ret = 0; 883 DIR *D; 884 885 D = opendir(dirname); 886 if (!D) { 887 char buf[FIO_VERROR_SIZE]; 888 889 snprintf(buf, FIO_VERROR_SIZE - 1, "opendir(%s)", dirname); 890 td_verror(td, errno, buf); 891 return 1; 892 } 893 894 while ((dir = readdir(D)) != NULL) { 895 char full_path[PATH_MAX]; 896 struct stat sb; 897 898 if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..")) 899 continue; 900 901 sprintf(full_path, "%s/%s", dirname, dir->d_name); 902 903 if (lstat(full_path, &sb) == -1) { 904 if (errno != ENOENT) { 905 td_verror(td, errno, "stat"); 906 return 1; 907 } 908 } 909 910 if (S_ISREG(sb.st_mode)) { 911 add_file(td, full_path); 912 td->o.nr_files++; 913 continue; 914 } 915 if (!S_ISDIR(sb.st_mode)) 916 continue; 917 918 ret = recurse_dir(td, full_path); 919 if (ret) 920 break; 921 } 922 923 closedir(D); 924 return ret; 925} 926 927int add_dir_files(struct thread_data *td, const char *path) 928{ 929 int ret = recurse_dir(td, path); 930 931 if (!ret) 932 log_info("fio: opendir added %d files\n", td->o.nr_files); 933 934 return ret; 935} 936 937void dup_files(struct thread_data *td, struct thread_data *org) 938{ 939 struct fio_file *f; 940 unsigned int i; 941 942 dprint(FD_FILE, "dup files: %d\n", org->files_index); 943 944 if (!org->files) 945 return; 946 947 td->files = malloc(org->files_index * sizeof(f)); 948 949 for_each_file(org, f, i) { 950 struct fio_file *__f; 951 952 __f = smalloc(sizeof(*__f)); 953 if (!__f) { 954 log_err("fio: smalloc OOM\n"); 955 assert(0); 956 } 957 958 if (f->file_name) { 959 __f->file_name = smalloc_strdup(f->file_name); 960 if (!__f->file_name) { 961 log_err("fio: smalloc OOM\n"); 962 assert(0); 963 } 964 965 __f->filetype = f->filetype; 966 } 967 968 td->files[i] = __f; 969 } 970} 971 972/* 973 * Returns the index that matches the filename, or -1 if not there 974 */ 975int get_fileno(struct thread_data *td, const char *fname) 976{ 977 struct fio_file *f; 978 unsigned int i; 979 980 for_each_file(td, f, i) 981 if (!strcmp(f->file_name, fname)) 982 return i; 983 984 return -1; 985} 986 987/* 988 * For log usage, where we add/open/close files automatically 989 */ 990void free_release_files(struct thread_data *td) 991{ 992 close_files(td); 993 td->files_index = 0; 994 td->nr_normal_files = 0; 995} 996