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