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