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