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