filesetup.c revision ee56ad500f6692381e131cc37299d23fa910a24a
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 12static int root_warn; 13 14static int extend_file(struct thread_data *td, struct fio_file *f) 15{ 16 int r, new_layout = 0, unlink_file = 0, flags; 17 unsigned long long left; 18 unsigned int bs; 19 char *b; 20 21 if (read_only) { 22 log_err("fio: refusing extend of file due to read-only\n"); 23 return 0; 24 } 25 26 /* 27 * check if we need to lay the file out complete again. fio 28 * does that for operations involving reads, or for writes 29 * where overwrite is set 30 */ 31 if (td_read(td) || (td_write(td) && td->o.overwrite)) 32 new_layout = 1; 33 if (td_write(td) && !td->o.overwrite) 34 unlink_file = 1; 35 36 if ((unlink_file || new_layout) && (f->flags & FIO_FILE_EXISTS)) { 37 if (unlink(f->file_name) < 0) { 38 td_verror(td, errno, "unlink"); 39 return 1; 40 } 41 } 42 43 flags = O_WRONLY | O_CREAT; 44 if (new_layout) 45 flags |= O_TRUNC; 46 47 dprint(FD_FILE, "open file %s, flags %x\n", f->file_name, flags); 48 f->fd = open(f->file_name, flags, 0644); 49 if (f->fd < 0) { 50 td_verror(td, errno, "open"); 51 return 1; 52 } 53 54 if (!new_layout) 55 goto done; 56 57 dprint(FD_FILE, "truncate file %s, size %llu\n", f->file_name, 58 f->real_file_size); 59 if (ftruncate(f->fd, f->real_file_size) == -1) { 60 td_verror(td, errno, "ftruncate"); 61 goto err; 62 } 63 64 dprint(FD_FILE, "fallocate file %s, size %llu\n", f->file_name, 65 f->real_file_size); 66 if (posix_fallocate(f->fd, 0, f->real_file_size) < 0) { 67 td_verror(td, errno, "posix_fallocate"); 68 goto err; 69 } 70 71 b = malloc(td->o.max_bs[DDIR_WRITE]); 72 memset(b, 0, td->o.max_bs[DDIR_WRITE]); 73 74 left = f->real_file_size; 75 while (left && !td->terminate) { 76 bs = td->o.max_bs[DDIR_WRITE]; 77 if (bs > left) 78 bs = left; 79 80 r = write(f->fd, b, bs); 81 82 if (r == (int) bs) { 83 left -= bs; 84 continue; 85 } else { 86 if (r < 0) 87 td_verror(td, errno, "write"); 88 else 89 td_verror(td, EIO, "write"); 90 91 break; 92 } 93 } 94 95 if (td->terminate) 96 unlink(f->file_name); 97 else if (td->o.create_fsync) 98 fsync(f->fd); 99 100 free(b); 101done: 102 close(f->fd); 103 f->fd = -1; 104 return 0; 105err: 106 close(f->fd); 107 f->fd = -1; 108 return 1; 109} 110 111static unsigned long long get_rand_file_size(struct thread_data *td) 112{ 113 unsigned long long ret; 114 long r; 115 116 r = os_random_long(&td->file_size_state); 117 ret = td->o.file_size_low + (unsigned long long) ((double) (td->o.file_size_high - td->o.file_size_low) * (r / (RAND_MAX + 1.0))); 118 ret -= (ret % td->o.rw_min_bs); 119 return ret; 120} 121 122static int file_size(struct thread_data *td, struct fio_file *f) 123{ 124 struct stat st; 125 126 if (fstat(f->fd, &st) == -1) { 127 td_verror(td, errno, "fstat"); 128 return 1; 129 } 130 131 f->real_file_size = st.st_size; 132 return 0; 133} 134 135static int bdev_size(struct thread_data *td, struct fio_file *f) 136{ 137 unsigned long long bytes; 138 int r; 139 140 r = blockdev_size(f->fd, &bytes); 141 if (r) { 142 td_verror(td, r, "blockdev_size"); 143 return 1; 144 } 145 146 f->real_file_size = bytes; 147 return 0; 148} 149 150static int get_file_size(struct thread_data *td, struct fio_file *f) 151{ 152 int ret = 0; 153 154 if (f->flags & FIO_SIZE_KNOWN) 155 return 0; 156 157 if (f->filetype == FIO_TYPE_FILE) 158 ret = file_size(td, f); 159 else if (f->filetype == FIO_TYPE_BD) 160 ret = bdev_size(td, f); 161 else 162 f->real_file_size = -1; 163 164 if (ret) 165 return ret; 166 167 if (f->file_offset > f->real_file_size) { 168 log_err("%s: offset extends end (%Lu > %Lu)\n", td->o.name, f->file_offset, f->real_file_size); 169 return 1; 170 } 171 172 f->flags |= FIO_SIZE_KNOWN; 173 return 0; 174} 175 176int file_invalidate_cache(struct thread_data *td, struct fio_file *f) 177{ 178 int ret = 0; 179 180 dprint(FD_IO, "invalidate cache (%d)\n", td->o.odirect); 181 182 if (td->o.odirect) 183 return 0; 184 185 /* 186 * FIXME: add blockdev flushing too 187 */ 188 if (f->mmap) 189 ret = madvise(f->mmap, f->io_size, MADV_DONTNEED); 190 else if (f->filetype == FIO_TYPE_FILE) 191 ret = fadvise(f->fd, f->file_offset, f->io_size, POSIX_FADV_DONTNEED); 192 else if (f->filetype == FIO_TYPE_BD) { 193 ret = blockdev_invalidate_cache(f->fd); 194 if (ret < 0 && errno == EACCES && geteuid()) { 195 if (!root_warn) { 196 log_err("fio: only root may flush block devices. Cache flush bypassed!\n"); 197 root_warn = 1; 198 } 199 ret = 0; 200 } 201 } else if (f->filetype == FIO_TYPE_CHAR || f->filetype == FIO_TYPE_PIPE) 202 ret = 0; 203 204 if (ret < 0) { 205 td_verror(td, errno, "invalidate_cache"); 206 return 1; 207 } 208 209 return ret; 210} 211 212void generic_close_file(struct thread_data fio_unused *td, struct fio_file *f) 213{ 214 dprint(FD_FILE, "fd close %s\n", f->file_name); 215 close(f->fd); 216 f->fd = -1; 217} 218 219int generic_open_file(struct thread_data *td, struct fio_file *f) 220{ 221 int is_std = 0; 222 int flags = 0; 223 224 dprint(FD_FILE, "fd open %s\n", f->file_name); 225 226 if (!strcmp(f->file_name, "-")) { 227 if (td_rw(td)) { 228 log_err("fio: can't read/write to stdin/out\n"); 229 return 1; 230 } 231 is_std = 1; 232 233 /* 234 * move output logging to stderr, if we are writing to stdout 235 */ 236 if (td_write(td)) 237 f_out = stderr; 238 } 239 240 if (td->o.odirect) 241 flags |= OS_O_DIRECT; 242 if (td->o.sync_io) 243 flags |= O_SYNC; 244 if (f->filetype != FIO_TYPE_FILE) 245 flags |= O_NOATIME; 246 247open_again: 248 if (td_write(td)) { 249 assert(!read_only); 250 251 flags |= O_RDWR; 252 253 if (f->filetype == FIO_TYPE_FILE) 254 flags |= O_CREAT; 255 256 if (is_std) 257 f->fd = dup(STDOUT_FILENO); 258 else 259 f->fd = open(f->file_name, flags, 0600); 260 } else { 261 if (f->filetype == FIO_TYPE_CHAR && !read_only) 262 flags |= O_RDWR; 263 else 264 flags |= O_RDONLY; 265 266 if (is_std) 267 f->fd = dup(STDIN_FILENO); 268 else 269 f->fd = open(f->file_name, flags); 270 } 271 272 if (f->fd == -1) { 273 char buf[FIO_VERROR_SIZE]; 274 int __e = errno; 275 276 if (errno == EPERM && (flags & O_NOATIME)) { 277 flags &= ~O_NOATIME; 278 goto open_again; 279 } 280 281 snprintf(buf, sizeof(buf) - 1, "open(%s)", f->file_name); 282 283 td_verror(td, __e, buf); 284 } 285 286 if (get_file_size(td, f)) 287 goto err; 288 289 return 0; 290err: 291 close(f->fd); 292 return 1; 293} 294 295int open_files(struct thread_data *td) 296{ 297 struct fio_file *f; 298 unsigned int i; 299 int err = 0; 300 301 dprint(FD_FILE, "open files\n"); 302 303 for_each_file(td, f, i) { 304 err = td_io_open_file(td, f); 305 if (err) { 306 if (td->error == EMFILE) { 307 log_err("fio: limited open files to: %d\n", td->nr_open_files); 308 td->o.open_files = td->nr_open_files; 309 err = 0; 310 clear_error(td); 311 } 312 break; 313 } 314 315 if (td->o.open_files == td->nr_open_files) 316 break; 317 } 318 319 if (!err) 320 return 0; 321 322 for_each_file(td, f, i) 323 td_io_close_file(td, f); 324 325 return err; 326} 327 328/* 329 * open/close all files, so that ->real_file_size gets set 330 */ 331static int get_file_sizes(struct thread_data *td) 332{ 333 struct fio_file *f; 334 unsigned int i; 335 int err = 0; 336 337 for_each_file(td, f, i) { 338 if (td->io_ops->open_file(td, f)) { 339 if (td->error != ENOENT) { 340 log_err("%s\n", td->verror); 341 err = 1; 342 } 343 clear_error(td); 344 } else { 345 if (td->io_ops->close_file) 346 td->io_ops->close_file(td, f); 347 } 348 349 if (f->real_file_size == -1ULL && td->o.size) 350 f->real_file_size = td->o.size / td->o.nr_files; 351 } 352 353 return err; 354} 355 356/* 357 * Open the files and setup files sizes, creating files if necessary. 358 */ 359int setup_files(struct thread_data *td) 360{ 361 unsigned long long total_size, extend_size; 362 struct fio_file *f; 363 unsigned int i; 364 int err = 0, need_extend; 365 366 dprint(FD_FILE, "setup files\n"); 367 368 /* 369 * if ioengine defines a setup() method, it's responsible for 370 * opening the files and setting f->real_file_size to indicate 371 * the valid range for that file. 372 */ 373 if (td->io_ops->setup) 374 err = td->io_ops->setup(td); 375 else 376 err = get_file_sizes(td); 377 378 if (err) 379 return err; 380 381 /* 382 * check sizes. if the files/devices do not exist and the size 383 * isn't passed to fio, abort. 384 */ 385 total_size = 0; 386 for_each_file(td, f, i) { 387 if (f->real_file_size == -1ULL) 388 total_size = -1ULL; 389 else 390 total_size += f->real_file_size; 391 } 392 393 /* 394 * device/file sizes are zero and no size given, punt 395 */ 396 if ((!total_size || total_size == -1ULL) && !td->o.size && 397 !(td->io_ops->flags & FIO_NOIO) && !td->o.fill_device) { 398 log_err("%s: you need to specify size=\n", td->o.name); 399 td_verror(td, EINVAL, "total_file_size"); 400 return 1; 401 } 402 403 /* 404 * now file sizes are known, so we can set ->io_size. if size= is 405 * not given, ->io_size is just equal to ->real_file_size. if size 406 * is given, ->io_size is size / nr_files. 407 */ 408 extend_size = total_size = 0; 409 need_extend = 0; 410 for_each_file(td, f, i) { 411 f->file_offset = td->o.start_offset; 412 413 if (!td->o.file_size_low) { 414 /* 415 * no file size range given, file size is equal to 416 * total size divided by number of files. if that is 417 * zero, set it to the real file size. 418 */ 419 f->io_size = td->o.size / td->o.nr_files; 420 if (!f->io_size) 421 f->io_size = f->real_file_size - f->file_offset; 422 } else if (f->real_file_size < td->o.file_size_low || 423 f->real_file_size > td->o.file_size_high) { 424 if (f->file_offset > td->o.file_size_low) 425 goto err_offset; 426 /* 427 * file size given. if it's fixed, use that. if it's a 428 * range, generate a random size in-between. 429 */ 430 if (td->o.file_size_low == td->o.file_size_high) 431 f->io_size = td->o.file_size_low - f->file_offset; 432 else 433 f->io_size = get_rand_file_size(td) - f->file_offset; 434 } else 435 f->io_size = f->real_file_size - f->file_offset; 436 437 if (f->io_size == -1ULL) 438 total_size = -1ULL; 439 else 440 total_size += f->io_size; 441 442 if (f->filetype == FIO_TYPE_FILE && 443 (f->io_size + f->file_offset) > f->real_file_size && 444 !(td->io_ops->flags & FIO_DISKLESSIO)) { 445 need_extend++; 446 extend_size += (f->io_size + f->file_offset); 447 f->flags |= FIO_FILE_EXTEND; 448 } 449 } 450 451 if (!td->o.size || td->o.size > total_size) 452 td->o.size = total_size; 453 454 /* 455 * See if we need to extend some files 456 */ 457 if (need_extend) { 458 temp_stall_ts = 1; 459 log_info("%s: Laying out IO file(s) (%u file(s) / %LuMiB)\n", 460 td->o.name, need_extend, extend_size >> 20); 461 462 for_each_file(td, f, i) { 463 if (!(f->flags & FIO_FILE_EXTEND)) 464 continue; 465 466 assert(f->filetype == FIO_TYPE_FILE); 467 f->flags &= ~FIO_FILE_EXTEND; 468 f->real_file_size = (f->io_size + f->file_offset); 469 err = extend_file(td, f); 470 if (err) 471 break; 472 } 473 temp_stall_ts = 0; 474 } 475 476 if (err) 477 return err; 478 479 if (!td->o.zone_size) 480 td->o.zone_size = td->o.size; 481 482 /* 483 * iolog already set the total io size, if we read back 484 * stored entries. 485 */ 486 if (!td->o.read_iolog_file) 487 td->total_io_size = td->o.size * td->o.loops; 488 return 0; 489err_offset: 490 log_err("%s: you need to specify valid offset=\n", td->o.name); 491 return 1; 492} 493 494int init_random_map(struct thread_data *td) 495{ 496 unsigned long long blocks, num_maps; 497 struct fio_file *f; 498 unsigned int i; 499 500 if (td->o.norandommap) 501 return 0; 502 503 for_each_file(td, f, i) { 504 blocks = (f->real_file_size + td->o.rw_min_bs - 1) / (unsigned long long) td->o.rw_min_bs; 505 num_maps = (blocks + BLOCKS_PER_MAP-1)/ (unsigned long long) BLOCKS_PER_MAP; 506 f->file_map = malloc(num_maps * sizeof(long)); 507 if (!f->file_map) { 508 log_err("fio: failed allocating random map. If running a large number of jobs, try the 'norandommap' option\n"); 509 return 1; 510 } 511 f->num_maps = num_maps; 512 memset(f->file_map, 0, num_maps * sizeof(long)); 513 } 514 515 return 0; 516} 517 518void close_files(struct thread_data *td) 519{ 520 struct fio_file *f; 521 unsigned int i; 522 523 dprint(FD_FILE, "close files\n"); 524 525 for_each_file(td, f, i) { 526 if (td->o.unlink && f->filetype == FIO_TYPE_FILE) 527 unlink(f->file_name); 528 529 td_io_close_file(td, f); 530 531 free(f->file_name); 532 f->file_name = NULL; 533 534 if (f->file_map) { 535 free(f->file_map); 536 f->file_map = NULL; 537 } 538 } 539 540 td->o.filename = NULL; 541 free(td->files); 542 td->files = NULL; 543 td->o.nr_files = 0; 544} 545 546static void get_file_type(struct fio_file *f) 547{ 548 struct stat sb; 549 550 if (!strcmp(f->file_name, "-")) 551 f->filetype = FIO_TYPE_PIPE; 552 else 553 f->filetype = FIO_TYPE_FILE; 554 555 if (!lstat(f->file_name, &sb)) { 556 if (S_ISBLK(sb.st_mode)) 557 f->filetype = FIO_TYPE_BD; 558 else if (S_ISCHR(sb.st_mode)) 559 f->filetype = FIO_TYPE_CHAR; 560 else if (S_ISFIFO(sb.st_mode)) 561 f->filetype = FIO_TYPE_PIPE; 562 } 563} 564 565int add_file(struct thread_data *td, const char *fname) 566{ 567 int cur_files = td->files_index; 568 char file_name[PATH_MAX]; 569 struct fio_file *f; 570 int len = 0; 571 572 dprint(FD_FILE, "add file %s\n", fname); 573 574 td->files = realloc(td->files, (cur_files + 1) * sizeof(*f)); 575 576 f = &td->files[cur_files]; 577 memset(f, 0, sizeof(*f)); 578 f->fd = -1; 579 580 /* 581 * init function, io engine may not be loaded yet 582 */ 583 if (td->io_ops && (td->io_ops->flags & FIO_DISKLESSIO)) 584 f->real_file_size = -1ULL; 585 586 if (td->o.directory) 587 len = sprintf(file_name, "%s/", td->o.directory); 588 589 sprintf(file_name + len, "%s", fname); 590 f->file_name = strdup(file_name); 591 592 get_file_type(f); 593 594 td->files_index++; 595 if (f->filetype == FIO_TYPE_FILE) 596 td->nr_normal_files++; 597 598 return cur_files; 599} 600 601void get_file(struct fio_file *f) 602{ 603 dprint(FD_FILE, "get file %s/%d\n", f->file_name, f->references); 604 assert(f->flags & FIO_FILE_OPEN); 605 f->references++; 606} 607 608void put_file(struct thread_data *td, struct fio_file *f) 609{ 610 dprint(FD_FILE, "get put %s/%d\n", f->file_name, f->references); 611 612 if (!(f->flags & FIO_FILE_OPEN)) 613 return; 614 615 assert(f->references); 616 if (--f->references) 617 return; 618 619 if (should_fsync(td) && td->o.fsync_on_close) 620 fsync(f->fd); 621 622 if (td->io_ops->close_file) 623 td->io_ops->close_file(td, f); 624 625 td->nr_open_files--; 626 f->flags &= ~FIO_FILE_OPEN; 627} 628 629static int recurse_dir(struct thread_data *td, const char *dirname) 630{ 631 struct dirent *dir; 632 int ret = 0; 633 DIR *D; 634 635 D = opendir(dirname); 636 if (!D) { 637 char buf[FIO_VERROR_SIZE]; 638 639 snprintf(buf, FIO_VERROR_SIZE - 1, "opendir(%s)", dirname); 640 td_verror(td, errno, buf); 641 return 1; 642 } 643 644 while ((dir = readdir(D)) != NULL) { 645 char full_path[PATH_MAX]; 646 struct stat sb; 647 648 if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..")) 649 continue; 650 651 sprintf(full_path, "%s/%s", dirname, dir->d_name); 652 653 if (lstat(full_path, &sb) == -1) { 654 if (errno != ENOENT) { 655 td_verror(td, errno, "stat"); 656 return 1; 657 } 658 } 659 660 if (S_ISREG(sb.st_mode)) { 661 add_file(td, full_path); 662 td->o.nr_files++; 663 continue; 664 } 665 if (!S_ISDIR(sb.st_mode)) 666 continue; 667 668 if ((ret = recurse_dir(td, full_path)) != 0) 669 break; 670 } 671 672 closedir(D); 673 return ret; 674} 675 676int add_dir_files(struct thread_data *td, const char *path) 677{ 678 int ret = recurse_dir(td, path); 679 680 if (!ret) 681 log_info("fio: opendir added %d files\n", td->o.nr_files); 682 683 return ret; 684} 685 686void dup_files(struct thread_data *td, struct thread_data *org) 687{ 688 struct fio_file *f; 689 unsigned int i; 690 size_t bytes; 691 692 if (!org->files) 693 return; 694 695 bytes = org->files_index * sizeof(*f); 696 td->files = malloc(bytes); 697 memcpy(td->files, org->files, bytes); 698 699 for_each_file(td, f, i) { 700 if (f->file_name) 701 f->file_name = strdup(f->file_name); 702 } 703} 704 705/* 706 * Returns the index that matches the filename, or -1 if not there 707 */ 708int get_fileno(struct thread_data *td, const char *fname) 709{ 710 struct fio_file *f; 711 unsigned int i; 712 713 for_each_file(td, f, i) 714 if (!strcmp(f->file_name, fname)) 715 return i; 716 717 return -1; 718} 719 720/* 721 * For log usage, where we add/open/close files automatically 722 */ 723void free_release_files(struct thread_data *td) 724{ 725 close_files(td); 726 td->files_index = 0; 727 td->nr_normal_files = 0; 728} 729