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