init.c revision 023fa7d42359b569ba6e325ec68fbfd6ec3a9cd7
1/* 2 * This file contains job initialization and setup functions. 3 */ 4#include <stdio.h> 5#include <stdlib.h> 6#include <unistd.h> 7#include <fcntl.h> 8#include <ctype.h> 9#include <string.h> 10#include <errno.h> 11#include <sys/ipc.h> 12#include <sys/types.h> 13#include <sys/stat.h> 14 15#include "fio.h" 16#ifndef FIO_NO_HAVE_SHM_H 17#include <sys/shm.h> 18#endif 19 20#include "parse.h" 21#include "smalloc.h" 22#include "filehash.h" 23#include "verify.h" 24#include "profile.h" 25#include "server.h" 26#include "idletime.h" 27#include "filelock.h" 28 29#include "lib/getopt.h" 30#include "lib/strcasestr.h" 31 32#include "crc/test.h" 33 34const char fio_version_string[] = FIO_VERSION; 35 36#define FIO_RANDSEED (0xb1899bedUL) 37 38static char **ini_file; 39static int max_jobs = FIO_MAX_JOBS; 40static int dump_cmdline; 41static long long def_timeout; 42static int parse_only; 43 44static struct thread_data def_thread; 45struct thread_data *threads = NULL; 46static char **job_sections; 47static int nr_job_sections; 48 49int exitall_on_terminate = 0; 50int output_format = FIO_OUTPUT_NORMAL; 51int append_terse_output = 0; 52int eta_print = FIO_ETA_AUTO; 53int eta_new_line = 0; 54FILE *f_out = NULL; 55FILE *f_err = NULL; 56char *exec_profile = NULL; 57int warnings_fatal = 0; 58int terse_version = 3; 59int is_backend = 0; 60int nr_clients = 0; 61int log_syslog = 0; 62 63int write_bw_log = 0; 64int read_only = 0; 65int status_interval = 0; 66 67static int prev_group_jobs; 68 69unsigned long fio_debug = 0; 70unsigned int fio_debug_jobno = -1; 71unsigned int *fio_debug_jobp = NULL; 72 73static char cmd_optstr[256]; 74static int did_arg; 75 76#define FIO_CLIENT_FLAG (1 << 16) 77 78/* 79 * Command line options. These will contain the above, plus a few 80 * extra that only pertain to fio itself and not jobs. 81 */ 82static struct option l_opts[FIO_NR_OPTIONS] = { 83 { 84 .name = (char *) "output", 85 .has_arg = required_argument, 86 .val = 'o' | FIO_CLIENT_FLAG, 87 }, 88 { 89 .name = (char *) "timeout", 90 .has_arg = required_argument, 91 .val = 't' | FIO_CLIENT_FLAG, 92 }, 93 { 94 .name = (char *) "latency-log", 95 .has_arg = required_argument, 96 .val = 'l' | FIO_CLIENT_FLAG, 97 }, 98 { 99 .name = (char *) "bandwidth-log", 100 .has_arg = required_argument, 101 .val = 'b' | FIO_CLIENT_FLAG, 102 }, 103 { 104 .name = (char *) "minimal", 105 .has_arg = no_argument, 106 .val = 'm' | FIO_CLIENT_FLAG, 107 }, 108 { 109 .name = (char *) "output-format", 110 .has_arg = optional_argument, 111 .val = 'F' | FIO_CLIENT_FLAG, 112 }, 113 { 114 .name = (char *) "append-terse", 115 .has_arg = optional_argument, 116 .val = 'f', 117 }, 118 { 119 .name = (char *) "version", 120 .has_arg = no_argument, 121 .val = 'v' | FIO_CLIENT_FLAG, 122 }, 123 { 124 .name = (char *) "help", 125 .has_arg = no_argument, 126 .val = 'h' | FIO_CLIENT_FLAG, 127 }, 128 { 129 .name = (char *) "cmdhelp", 130 .has_arg = optional_argument, 131 .val = 'c' | FIO_CLIENT_FLAG, 132 }, 133 { 134 .name = (char *) "enghelp", 135 .has_arg = optional_argument, 136 .val = 'i' | FIO_CLIENT_FLAG, 137 }, 138 { 139 .name = (char *) "showcmd", 140 .has_arg = no_argument, 141 .val = 's' | FIO_CLIENT_FLAG, 142 }, 143 { 144 .name = (char *) "readonly", 145 .has_arg = no_argument, 146 .val = 'r' | FIO_CLIENT_FLAG, 147 }, 148 { 149 .name = (char *) "eta", 150 .has_arg = required_argument, 151 .val = 'e' | FIO_CLIENT_FLAG, 152 }, 153 { 154 .name = (char *) "eta-newline", 155 .has_arg = required_argument, 156 .val = 'E' | FIO_CLIENT_FLAG, 157 }, 158 { 159 .name = (char *) "debug", 160 .has_arg = required_argument, 161 .val = 'd' | FIO_CLIENT_FLAG, 162 }, 163 { 164 .name = (char *) "parse-only", 165 .has_arg = no_argument, 166 .val = 'P' | FIO_CLIENT_FLAG, 167 }, 168 { 169 .name = (char *) "section", 170 .has_arg = required_argument, 171 .val = 'x' | FIO_CLIENT_FLAG, 172 }, 173#ifdef CONFIG_ZLIB 174 { 175 .name = (char *) "inflate-log", 176 .has_arg = required_argument, 177 .val = 'X' | FIO_CLIENT_FLAG, 178 }, 179#endif 180 { 181 .name = (char *) "alloc-size", 182 .has_arg = required_argument, 183 .val = 'a' | FIO_CLIENT_FLAG, 184 }, 185 { 186 .name = (char *) "profile", 187 .has_arg = required_argument, 188 .val = 'p' | FIO_CLIENT_FLAG, 189 }, 190 { 191 .name = (char *) "warnings-fatal", 192 .has_arg = no_argument, 193 .val = 'w' | FIO_CLIENT_FLAG, 194 }, 195 { 196 .name = (char *) "max-jobs", 197 .has_arg = required_argument, 198 .val = 'j' | FIO_CLIENT_FLAG, 199 }, 200 { 201 .name = (char *) "terse-version", 202 .has_arg = required_argument, 203 .val = 'V' | FIO_CLIENT_FLAG, 204 }, 205 { 206 .name = (char *) "server", 207 .has_arg = optional_argument, 208 .val = 'S', 209 }, 210 { .name = (char *) "daemonize", 211 .has_arg = required_argument, 212 .val = 'D', 213 }, 214 { 215 .name = (char *) "client", 216 .has_arg = required_argument, 217 .val = 'C', 218 }, 219 { 220 .name = (char *) "cpuclock-test", 221 .has_arg = no_argument, 222 .val = 'T', 223 }, 224 { 225 .name = (char *) "crctest", 226 .has_arg = optional_argument, 227 .val = 'G', 228 }, 229 { 230 .name = (char *) "idle-prof", 231 .has_arg = required_argument, 232 .val = 'I', 233 }, 234 { 235 .name = (char *) "status-interval", 236 .has_arg = required_argument, 237 .val = 'L', 238 }, 239 { 240 .name = NULL, 241 }, 242}; 243 244void free_threads_shm(void) 245{ 246 if (threads) { 247 void *tp = threads; 248#ifndef CONFIG_NO_SHM 249 struct shmid_ds sbuf; 250 251 threads = NULL; 252 shmdt(tp); 253 shmctl(shm_id, IPC_RMID, &sbuf); 254 shm_id = -1; 255#else 256 threads = NULL; 257 free(tp); 258#endif 259 } 260} 261 262static void free_shm(void) 263{ 264 if (threads) { 265 file_hash_exit(); 266 flow_exit(); 267 fio_debug_jobp = NULL; 268 free_threads_shm(); 269 } 270 271 options_free(fio_options, &def_thread); 272 fio_filelock_exit(); 273 scleanup(); 274} 275 276/* 277 * The thread area is shared between the main process and the job 278 * threads/processes. So setup a shared memory segment that will hold 279 * all the job info. We use the end of the region for keeping track of 280 * open files across jobs, for file sharing. 281 */ 282static int setup_thread_area(void) 283{ 284 void *hash; 285 286 if (threads) 287 return 0; 288 289 /* 290 * 1024 is too much on some machines, scale max_jobs if 291 * we get a failure that looks like too large a shm segment 292 */ 293 do { 294 size_t size = max_jobs * sizeof(struct thread_data); 295 296 size += file_hash_size; 297 size += sizeof(unsigned int); 298 299#ifndef CONFIG_NO_SHM 300 shm_id = shmget(0, size, IPC_CREAT | 0600); 301 if (shm_id != -1) 302 break; 303 if (errno != EINVAL && errno != ENOMEM && errno != ENOSPC) { 304 perror("shmget"); 305 break; 306 } 307#else 308 threads = malloc(size); 309 if (threads) 310 break; 311#endif 312 313 max_jobs >>= 1; 314 } while (max_jobs); 315 316#ifndef CONFIG_NO_SHM 317 if (shm_id == -1) 318 return 1; 319 320 threads = shmat(shm_id, NULL, 0); 321 if (threads == (void *) -1) { 322 perror("shmat"); 323 return 1; 324 } 325#endif 326 327 memset(threads, 0, max_jobs * sizeof(struct thread_data)); 328 hash = (void *) threads + max_jobs * sizeof(struct thread_data); 329 fio_debug_jobp = (void *) hash + file_hash_size; 330 *fio_debug_jobp = -1; 331 file_hash_init(hash); 332 333 flow_init(); 334 335 return 0; 336} 337 338static void set_cmd_options(struct thread_data *td) 339{ 340 struct thread_options *o = &td->o; 341 342 if (!o->timeout) 343 o->timeout = def_timeout; 344} 345 346/* 347 * Return a free job structure. 348 */ 349static struct thread_data *get_new_job(int global, struct thread_data *parent, 350 int preserve_eo, const char *jobname) 351{ 352 struct thread_data *td; 353 354 if (global) { 355 set_cmd_options(&def_thread); 356 return &def_thread; 357 } 358 if (setup_thread_area()) { 359 log_err("error: failed to setup shm segment\n"); 360 return NULL; 361 } 362 if (thread_number >= max_jobs) { 363 log_err("error: maximum number of jobs (%d) reached.\n", 364 max_jobs); 365 return NULL; 366 } 367 368 td = &threads[thread_number++]; 369 *td = *parent; 370 371 td->io_ops = NULL; 372 if (!preserve_eo) 373 td->eo = NULL; 374 375 td->o.uid = td->o.gid = -1U; 376 377 dup_files(td, parent); 378 fio_options_mem_dupe(td); 379 380 profile_add_hooks(td); 381 382 td->thread_number = thread_number; 383 384 if (jobname) 385 td->o.name = strdup(jobname); 386 387 if (!parent->o.group_reporting) 388 stat_number++; 389 390 set_cmd_options(td); 391 return td; 392} 393 394static void put_job(struct thread_data *td) 395{ 396 if (td == &def_thread) 397 return; 398 399 profile_td_exit(td); 400 flow_exit_job(td); 401 402 if (td->error) 403 log_info("fio: %s\n", td->verror); 404 405 fio_options_free(td); 406 if (td->io_ops) 407 free_ioengine(td); 408 409 if (td->o.name) 410 free(td->o.name); 411 412 memset(&threads[td->thread_number - 1], 0, sizeof(*td)); 413 thread_number--; 414} 415 416static int __setup_rate(struct thread_data *td, enum fio_ddir ddir) 417{ 418 unsigned int bs = td->o.min_bs[ddir]; 419 420 assert(ddir_rw(ddir)); 421 422 if (td->o.rate[ddir]) 423 td->rate_bps[ddir] = td->o.rate[ddir]; 424 else 425 td->rate_bps[ddir] = td->o.rate_iops[ddir] * bs; 426 427 if (!td->rate_bps[ddir]) { 428 log_err("rate lower than supported\n"); 429 return -1; 430 } 431 432 td->rate_pending_usleep[ddir] = 0; 433 return 0; 434} 435 436static int setup_rate(struct thread_data *td) 437{ 438 int ret = 0; 439 440 if (td->o.rate[DDIR_READ] || td->o.rate_iops[DDIR_READ]) 441 ret = __setup_rate(td, DDIR_READ); 442 if (td->o.rate[DDIR_WRITE] || td->o.rate_iops[DDIR_WRITE]) 443 ret |= __setup_rate(td, DDIR_WRITE); 444 if (td->o.rate[DDIR_TRIM] || td->o.rate_iops[DDIR_TRIM]) 445 ret |= __setup_rate(td, DDIR_TRIM); 446 447 return ret; 448} 449 450static int fixed_block_size(struct thread_options *o) 451{ 452 return o->min_bs[DDIR_READ] == o->max_bs[DDIR_READ] && 453 o->min_bs[DDIR_WRITE] == o->max_bs[DDIR_WRITE] && 454 o->min_bs[DDIR_TRIM] == o->max_bs[DDIR_TRIM] && 455 o->min_bs[DDIR_READ] == o->min_bs[DDIR_WRITE] && 456 o->min_bs[DDIR_READ] == o->min_bs[DDIR_TRIM]; 457} 458 459 460static unsigned long long get_rand_start_delay(struct thread_data *td) 461{ 462 unsigned long long delayrange; 463 unsigned long r; 464 465 delayrange = td->o.start_delay_high - td->o.start_delay; 466 467 if (td->o.use_os_rand) { 468 r = os_random_long(&td->delay_state); 469 delayrange = (unsigned long long) ((double) delayrange * (r / (OS_RAND_MAX + 1.0))); 470 } else { 471 r = __rand(&td->__delay_state); 472 delayrange = (unsigned long long) ((double) delayrange * (r / (FRAND_MAX + 1.0))); 473 } 474 475 delayrange += td->o.start_delay; 476 return delayrange; 477} 478 479/* 480 * Lazy way of fixing up options that depend on each other. We could also 481 * define option callback handlers, but this is easier. 482 */ 483static int fixup_options(struct thread_data *td) 484{ 485 struct thread_options *o = &td->o; 486 int ret = 0; 487 488#ifndef FIO_HAVE_PSHARED_MUTEX 489 if (!o->use_thread) { 490 log_info("fio: this platform does not support process shared" 491 " mutexes, forcing use of threads. Use the 'thread'" 492 " option to get rid of this warning.\n"); 493 o->use_thread = 1; 494 ret = warnings_fatal; 495 } 496#endif 497 498 if (o->write_iolog_file && o->read_iolog_file) { 499 log_err("fio: read iolog overrides write_iolog\n"); 500 free(o->write_iolog_file); 501 o->write_iolog_file = NULL; 502 ret = warnings_fatal; 503 } 504 505 /* 506 * only really works with 1 file 507 */ 508 if (o->zone_size && o->open_files > 1) 509 o->zone_size = 0; 510 511 /* 512 * If zone_range isn't specified, backward compatibility dictates it 513 * should be made equal to zone_size. 514 */ 515 if (o->zone_size && !o->zone_range) 516 o->zone_range = o->zone_size; 517 518 /* 519 * Reads can do overwrites, we always need to pre-create the file 520 */ 521 if (td_read(td) || td_rw(td)) 522 o->overwrite = 1; 523 524 if (!o->min_bs[DDIR_READ]) 525 o->min_bs[DDIR_READ] = o->bs[DDIR_READ]; 526 if (!o->max_bs[DDIR_READ]) 527 o->max_bs[DDIR_READ] = o->bs[DDIR_READ]; 528 if (!o->min_bs[DDIR_WRITE]) 529 o->min_bs[DDIR_WRITE] = o->bs[DDIR_WRITE]; 530 if (!o->max_bs[DDIR_WRITE]) 531 o->max_bs[DDIR_WRITE] = o->bs[DDIR_WRITE]; 532 if (!o->min_bs[DDIR_TRIM]) 533 o->min_bs[DDIR_TRIM] = o->bs[DDIR_TRIM]; 534 if (!o->max_bs[DDIR_TRIM]) 535 o->max_bs[DDIR_TRIM] = o->bs[DDIR_TRIM]; 536 537 538 o->rw_min_bs = min(o->min_bs[DDIR_READ], o->min_bs[DDIR_WRITE]); 539 o->rw_min_bs = min(o->min_bs[DDIR_TRIM], o->rw_min_bs); 540 541 /* 542 * For random IO, allow blockalign offset other than min_bs. 543 */ 544 if (!o->ba[DDIR_READ] || !td_random(td)) 545 o->ba[DDIR_READ] = o->min_bs[DDIR_READ]; 546 if (!o->ba[DDIR_WRITE] || !td_random(td)) 547 o->ba[DDIR_WRITE] = o->min_bs[DDIR_WRITE]; 548 if (!o->ba[DDIR_TRIM] || !td_random(td)) 549 o->ba[DDIR_TRIM] = o->min_bs[DDIR_TRIM]; 550 551 if ((o->ba[DDIR_READ] != o->min_bs[DDIR_READ] || 552 o->ba[DDIR_WRITE] != o->min_bs[DDIR_WRITE] || 553 o->ba[DDIR_TRIM] != o->min_bs[DDIR_TRIM]) && 554 !o->norandommap) { 555 log_err("fio: Any use of blockalign= turns off randommap\n"); 556 o->norandommap = 1; 557 ret = warnings_fatal; 558 } 559 560 if (!o->file_size_high) 561 o->file_size_high = o->file_size_low; 562 563 if (o->start_delay_high) 564 o->start_delay = get_rand_start_delay(td); 565 566 if (o->norandommap && o->verify != VERIFY_NONE 567 && !fixed_block_size(o)) { 568 log_err("fio: norandommap given for variable block sizes, " 569 "verify disabled\n"); 570 o->verify = VERIFY_NONE; 571 ret = warnings_fatal; 572 } 573 if (o->bs_unaligned && (o->odirect || td->io_ops->flags & FIO_RAWIO)) 574 log_err("fio: bs_unaligned may not work with raw io\n"); 575 576 /* 577 * thinktime_spin must be less than thinktime 578 */ 579 if (o->thinktime_spin > o->thinktime) 580 o->thinktime_spin = o->thinktime; 581 582 /* 583 * The low water mark cannot be bigger than the iodepth 584 */ 585 if (o->iodepth_low > o->iodepth || !o->iodepth_low) 586 o->iodepth_low = o->iodepth; 587 588 /* 589 * If batch number isn't set, default to the same as iodepth 590 */ 591 if (o->iodepth_batch > o->iodepth || !o->iodepth_batch) 592 o->iodepth_batch = o->iodepth; 593 594 if (o->nr_files > td->files_index) 595 o->nr_files = td->files_index; 596 597 if (o->open_files > o->nr_files || !o->open_files) 598 o->open_files = o->nr_files; 599 600 if (((o->rate[DDIR_READ] + o->rate[DDIR_WRITE] + o->rate[DDIR_TRIM]) && 601 (o->rate_iops[DDIR_READ] + o->rate_iops[DDIR_WRITE] + o->rate_iops[DDIR_TRIM])) || 602 ((o->ratemin[DDIR_READ] + o->ratemin[DDIR_WRITE] + o->ratemin[DDIR_TRIM]) && 603 (o->rate_iops_min[DDIR_READ] + o->rate_iops_min[DDIR_WRITE] + o->rate_iops_min[DDIR_TRIM]))) { 604 log_err("fio: rate and rate_iops are mutually exclusive\n"); 605 ret = 1; 606 } 607 if ((o->rate[DDIR_READ] < o->ratemin[DDIR_READ]) || 608 (o->rate[DDIR_WRITE] < o->ratemin[DDIR_WRITE]) || 609 (o->rate[DDIR_TRIM] < o->ratemin[DDIR_TRIM]) || 610 (o->rate_iops[DDIR_READ] < o->rate_iops_min[DDIR_READ]) || 611 (o->rate_iops[DDIR_WRITE] < o->rate_iops_min[DDIR_WRITE]) || 612 (o->rate_iops[DDIR_TRIM] < o->rate_iops_min[DDIR_TRIM])) { 613 log_err("fio: minimum rate exceeds rate\n"); 614 ret = 1; 615 } 616 617 if (!o->timeout && o->time_based) { 618 log_err("fio: time_based requires a runtime/timeout setting\n"); 619 o->time_based = 0; 620 ret = warnings_fatal; 621 } 622 623 if (o->fill_device && !o->size) 624 o->size = -1ULL; 625 626 if (o->verify != VERIFY_NONE) { 627 if (td_write(td) && o->do_verify && o->numjobs > 1) { 628 log_info("Multiple writers may overwrite blocks that " 629 "belong to other jobs. This can cause " 630 "verification failures.\n"); 631 ret = warnings_fatal; 632 } 633 634 o->refill_buffers = 1; 635 if (o->max_bs[DDIR_WRITE] != o->min_bs[DDIR_WRITE] && 636 !o->verify_interval) 637 o->verify_interval = o->min_bs[DDIR_WRITE]; 638 639 /* 640 * Verify interval must be smaller or equal to the 641 * write size. 642 */ 643 if (o->verify_interval > o->min_bs[DDIR_WRITE]) 644 o->verify_interval = o->min_bs[DDIR_WRITE]; 645 else if (td_read(td) && o->verify_interval > o->min_bs[DDIR_READ]) 646 o->verify_interval = o->min_bs[DDIR_READ]; 647 } 648 649 if (o->pre_read) { 650 o->invalidate_cache = 0; 651 if (td->io_ops->flags & FIO_PIPEIO) { 652 log_info("fio: cannot pre-read files with an IO engine" 653 " that isn't seekable. Pre-read disabled.\n"); 654 ret = warnings_fatal; 655 } 656 } 657 658 if (!o->unit_base) { 659 if (td->io_ops->flags & FIO_BIT_BASED) 660 o->unit_base = 1; 661 else 662 o->unit_base = 8; 663 } 664 665#ifndef CONFIG_FDATASYNC 666 if (o->fdatasync_blocks) { 667 log_info("fio: this platform does not support fdatasync()" 668 " falling back to using fsync(). Use the 'fsync'" 669 " option instead of 'fdatasync' to get rid of" 670 " this warning\n"); 671 o->fsync_blocks = o->fdatasync_blocks; 672 o->fdatasync_blocks = 0; 673 ret = warnings_fatal; 674 } 675#endif 676 677#ifdef WIN32 678 /* 679 * Windows doesn't support O_DIRECT or O_SYNC with the _open interface, 680 * so fail if we're passed those flags 681 */ 682 if ((td->io_ops->flags & FIO_SYNCIO) && (td->o.odirect || td->o.sync_io)) { 683 log_err("fio: Windows does not support direct or non-buffered io with" 684 " the synchronous ioengines. Use the 'windowsaio' ioengine" 685 " with 'direct=1' and 'iodepth=1' instead.\n"); 686 ret = 1; 687 } 688#endif 689 690 /* 691 * For fully compressible data, just zero them at init time. 692 * It's faster than repeatedly filling it. 693 */ 694 if (td->o.compress_percentage == 100) { 695 td->o.zero_buffers = 1; 696 td->o.compress_percentage = 0; 697 } 698 699 /* 700 * Using a non-uniform random distribution excludes usage of 701 * a random map 702 */ 703 if (td->o.random_distribution != FIO_RAND_DIST_RANDOM) 704 td->o.norandommap = 1; 705 706 /* 707 * If size is set but less than the min block size, complain 708 */ 709 if (o->size && o->size < td_min_bs(td)) { 710 log_err("fio: size too small, must be larger than the IO size: %llu\n", (unsigned long long) o->size); 711 ret = 1; 712 } 713 714 /* 715 * O_ATOMIC implies O_DIRECT 716 */ 717 if (td->o.oatomic) 718 td->o.odirect = 1; 719 720 /* 721 * If randseed is set, that overrides randrepeat 722 */ 723 if (td->o.rand_seed) 724 td->o.rand_repeatable = 0; 725 726 if ((td->io_ops->flags & FIO_NOEXTEND) && td->o.file_append) { 727 log_err("fio: can't append/extent with IO engine %s\n", td->io_ops->name); 728 ret = 1; 729 } 730 731 return ret; 732} 733 734/* 735 * This function leaks the buffer 736 */ 737char *fio_uint_to_kmg(unsigned int val) 738{ 739 char *buf = malloc(32); 740 char post[] = { 0, 'K', 'M', 'G', 'P', 'E', 0 }; 741 char *p = post; 742 743 do { 744 if (val & 1023) 745 break; 746 747 val >>= 10; 748 p++; 749 } while (*p); 750 751 snprintf(buf, 32, "%u%c", val, *p); 752 return buf; 753} 754 755/* External engines are specified by "external:name.o") */ 756static const char *get_engine_name(const char *str) 757{ 758 char *p = strstr(str, ":"); 759 760 if (!p) 761 return str; 762 763 p++; 764 strip_blank_front(&p); 765 strip_blank_end(p); 766 return p; 767} 768 769static int exists_and_not_file(const char *filename) 770{ 771 struct stat sb; 772 773 if (lstat(filename, &sb) == -1) 774 return 0; 775 776 /* \\.\ is the device namespace in Windows, where every file 777 * is a device node */ 778 if (S_ISREG(sb.st_mode) && strncmp(filename, "\\\\.\\", 4) != 0) 779 return 0; 780 781 return 1; 782} 783 784static void td_fill_rand_seeds_os(struct thread_data *td) 785{ 786 os_random_seed(td->rand_seeds[FIO_RAND_BS_OFF], &td->bsrange_state); 787 os_random_seed(td->rand_seeds[FIO_RAND_VER_OFF], &td->verify_state); 788 os_random_seed(td->rand_seeds[FIO_RAND_MIX_OFF], &td->rwmix_state); 789 790 if (td->o.file_service_type == FIO_FSERVICE_RANDOM) 791 os_random_seed(td->rand_seeds[FIO_RAND_FILE_OFF], &td->next_file_state); 792 793 os_random_seed(td->rand_seeds[FIO_RAND_FILE_SIZE_OFF], &td->file_size_state); 794 os_random_seed(td->rand_seeds[FIO_RAND_TRIM_OFF], &td->trim_state); 795 os_random_seed(td->rand_seeds[FIO_RAND_START_DELAY], &td->delay_state); 796 797 if (!td_random(td)) 798 return; 799 800 if (td->o.rand_repeatable) 801 td->rand_seeds[FIO_RAND_BLOCK_OFF] = FIO_RANDSEED * td->thread_number; 802 803 os_random_seed(td->rand_seeds[FIO_RAND_BLOCK_OFF], &td->random_state); 804 805 os_random_seed(td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF], &td->seq_rand_state[DDIR_READ]); 806 os_random_seed(td->rand_seeds[FIO_RAND_SEQ_RAND_WRITE_OFF], &td->seq_rand_state[DDIR_WRITE]); 807 os_random_seed(td->rand_seeds[FIO_RAND_SEQ_RAND_TRIM_OFF], &td->seq_rand_state[DDIR_TRIM]); 808} 809 810static void td_fill_rand_seeds_internal(struct thread_data *td) 811{ 812 init_rand_seed(&td->__bsrange_state, td->rand_seeds[FIO_RAND_BS_OFF]); 813 init_rand_seed(&td->__verify_state, td->rand_seeds[FIO_RAND_VER_OFF]); 814 init_rand_seed(&td->__rwmix_state, td->rand_seeds[FIO_RAND_MIX_OFF]); 815 816 if (td->o.file_service_type == FIO_FSERVICE_RANDOM) 817 init_rand_seed(&td->__next_file_state, td->rand_seeds[FIO_RAND_FILE_OFF]); 818 819 init_rand_seed(&td->__file_size_state, td->rand_seeds[FIO_RAND_FILE_SIZE_OFF]); 820 init_rand_seed(&td->__trim_state, td->rand_seeds[FIO_RAND_TRIM_OFF]); 821 init_rand_seed(&td->__delay_state, td->rand_seeds[FIO_RAND_START_DELAY]); 822 823 if (!td_random(td)) 824 return; 825 826 if (td->o.rand_repeatable) 827 td->rand_seeds[FIO_RAND_BLOCK_OFF] = FIO_RANDSEED * td->thread_number; 828 829 init_rand_seed(&td->__random_state, td->rand_seeds[FIO_RAND_BLOCK_OFF]); 830 init_rand_seed(&td->__seq_rand_state[DDIR_READ], td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF]); 831 init_rand_seed(&td->__seq_rand_state[DDIR_WRITE], td->rand_seeds[FIO_RAND_SEQ_RAND_WRITE_OFF]); 832 init_rand_seed(&td->__seq_rand_state[DDIR_TRIM], td->rand_seeds[FIO_RAND_SEQ_RAND_TRIM_OFF]); 833} 834 835void td_fill_rand_seeds(struct thread_data *td) 836{ 837 if (td->o.allrand_repeatable) { 838 for (int i = 0; i < FIO_RAND_NR_OFFS; i++) 839 td->rand_seeds[i] = FIO_RANDSEED * td->thread_number 840 + i; 841 } 842 843 if (td->o.use_os_rand) 844 td_fill_rand_seeds_os(td); 845 else 846 td_fill_rand_seeds_internal(td); 847 848 init_rand_seed(&td->buf_state, td->rand_seeds[FIO_RAND_BUF_OFF]); 849} 850 851/* 852 * Initializes the ioengine configured for a job, if it has not been done so 853 * already. 854 */ 855int ioengine_load(struct thread_data *td) 856{ 857 const char *engine; 858 859 /* 860 * Engine has already been loaded. 861 */ 862 if (td->io_ops) 863 return 0; 864 if (!td->o.ioengine) { 865 log_err("fio: internal fault, no IO engine specified\n"); 866 return 1; 867 } 868 869 engine = get_engine_name(td->o.ioengine); 870 td->io_ops = load_ioengine(td, engine); 871 if (!td->io_ops) { 872 log_err("fio: failed to load engine %s\n", engine); 873 return 1; 874 } 875 876 if (td->io_ops->option_struct_size && td->io_ops->options) { 877 /* 878 * In cases where td->eo is set, clone it for a child thread. 879 * This requires that the parent thread has the same ioengine, 880 * but that requirement must be enforced by the code which 881 * cloned the thread. 882 */ 883 void *origeo = td->eo; 884 /* 885 * Otherwise use the default thread options. 886 */ 887 if (!origeo && td != &def_thread && def_thread.eo && 888 def_thread.io_ops->options == td->io_ops->options) 889 origeo = def_thread.eo; 890 891 options_init(td->io_ops->options); 892 td->eo = malloc(td->io_ops->option_struct_size); 893 /* 894 * Use the default thread as an option template if this uses the 895 * same options structure and there are non-default options 896 * used. 897 */ 898 if (origeo) { 899 memcpy(td->eo, origeo, td->io_ops->option_struct_size); 900 options_mem_dupe(td->eo, td->io_ops->options); 901 } else { 902 memset(td->eo, 0, td->io_ops->option_struct_size); 903 fill_default_options(td->eo, td->io_ops->options); 904 } 905 *(struct thread_data **)td->eo = td; 906 } 907 908 return 0; 909} 910 911static void init_flags(struct thread_data *td) 912{ 913 struct thread_options *o = &td->o; 914 915 if (o->verify_backlog) 916 td->flags |= TD_F_VER_BACKLOG; 917 if (o->trim_backlog) 918 td->flags |= TD_F_TRIM_BACKLOG; 919 if (o->read_iolog_file) 920 td->flags |= TD_F_READ_IOLOG; 921 if (o->refill_buffers) 922 td->flags |= TD_F_REFILL_BUFFERS; 923 if (o->scramble_buffers) 924 td->flags |= TD_F_SCRAMBLE_BUFFERS; 925 if (o->verify != VERIFY_NONE) 926 td->flags |= TD_F_VER_NONE; 927} 928 929static int setup_random_seeds(struct thread_data *td) 930{ 931 unsigned long seed; 932 unsigned int i; 933 934 if (!td->o.rand_repeatable && !td->o.rand_seed) 935 return init_random_state(td, td->rand_seeds, sizeof(td->rand_seeds)); 936 937 if (!td->o.rand_seed) 938 seed = 0x89; 939 else 940 seed = td->o.rand_seed; 941 942 for (i = 0; i < 4; i++) 943 seed *= 0x9e370001UL; 944 945 for (i = 0; i < FIO_RAND_NR_OFFS; i++) { 946 td->rand_seeds[i] = seed; 947 seed *= 0x9e370001UL; 948 } 949 950 td_fill_rand_seeds(td); 951 return 0; 952} 953 954enum { 955 FPRE_NONE = 0, 956 FPRE_JOBNAME, 957 FPRE_JOBNUM, 958 FPRE_FILENUM 959}; 960 961static struct fpre_keyword { 962 const char *keyword; 963 size_t strlen; 964 int key; 965} fpre_keywords[] = { 966 { .keyword = "$jobname", .key = FPRE_JOBNAME, }, 967 { .keyword = "$jobnum", .key = FPRE_JOBNUM, }, 968 { .keyword = "$filenum", .key = FPRE_FILENUM, }, 969 { .keyword = NULL, }, 970 }; 971 972static char *make_filename(char *buf, size_t buf_size,struct thread_options *o, 973 const char *jobname, int jobnum, int filenum) 974{ 975 struct fpre_keyword *f; 976 char copy[PATH_MAX]; 977 size_t dst_left = PATH_MAX - 1; 978 979 if (!o->filename_format || !strlen(o->filename_format)) { 980 sprintf(buf, "%s.%d.%d", jobname, jobnum, filenum); 981 return NULL; 982 } 983 984 for (f = &fpre_keywords[0]; f->keyword; f++) 985 f->strlen = strlen(f->keyword); 986 987 buf[buf_size - 1] = '\0'; 988 strncpy(buf, o->filename_format, buf_size - 1); 989 990 memset(copy, 0, sizeof(copy)); 991 for (f = &fpre_keywords[0]; f->keyword; f++) { 992 do { 993 size_t pre_len, post_start = 0; 994 char *str, *dst = copy; 995 996 str = strcasestr(buf, f->keyword); 997 if (!str) 998 break; 999 1000 pre_len = str - buf; 1001 if (strlen(str) != f->strlen) 1002 post_start = pre_len + f->strlen; 1003 1004 if (pre_len) { 1005 strncpy(dst, buf, pre_len); 1006 dst += pre_len; 1007 dst_left -= pre_len; 1008 } 1009 1010 switch (f->key) { 1011 case FPRE_JOBNAME: { 1012 int ret; 1013 1014 ret = snprintf(dst, dst_left, "%s", jobname); 1015 if (ret < 0) 1016 break; 1017 dst += ret; 1018 dst_left -= ret; 1019 break; 1020 } 1021 case FPRE_JOBNUM: { 1022 int ret; 1023 1024 ret = snprintf(dst, dst_left, "%d", jobnum); 1025 if (ret < 0) 1026 break; 1027 dst += ret; 1028 dst_left -= ret; 1029 break; 1030 } 1031 case FPRE_FILENUM: { 1032 int ret; 1033 1034 ret = snprintf(dst, dst_left, "%d", filenum); 1035 if (ret < 0) 1036 break; 1037 dst += ret; 1038 dst_left -= ret; 1039 break; 1040 } 1041 default: 1042 assert(0); 1043 break; 1044 } 1045 1046 if (post_start) 1047 strncpy(dst, buf + post_start, dst_left); 1048 1049 strncpy(buf, copy, buf_size - 1); 1050 } while (1); 1051 } 1052 1053 return buf; 1054} 1055 1056int parse_dryrun(void) 1057{ 1058 return dump_cmdline || parse_only; 1059} 1060 1061/* 1062 * Adds a job to the list of things todo. Sanitizes the various options 1063 * to make sure we don't have conflicts, and initializes various 1064 * members of td. 1065 */ 1066static int add_job(struct thread_data *td, const char *jobname, int job_add_num, 1067 int recursed, int client_type) 1068{ 1069 unsigned int i; 1070 char fname[PATH_MAX]; 1071 int numjobs, file_alloced; 1072 struct thread_options *o = &td->o; 1073 char logname[PATH_MAX + 32]; 1074 1075 /* 1076 * the def_thread is just for options, it's not a real job 1077 */ 1078 if (td == &def_thread) 1079 return 0; 1080 1081 init_flags(td); 1082 1083 /* 1084 * if we are just dumping the output command line, don't add the job 1085 */ 1086 if (parse_dryrun()) { 1087 put_job(td); 1088 return 0; 1089 } 1090 1091 td->client_type = client_type; 1092 1093 if (profile_td_init(td)) 1094 goto err; 1095 1096 if (ioengine_load(td)) 1097 goto err; 1098 1099 if (o->odirect) 1100 td->io_ops->flags |= FIO_RAWIO; 1101 1102 file_alloced = 0; 1103 if (!o->filename && !td->files_index && !o->read_iolog_file) { 1104 file_alloced = 1; 1105 1106 if (o->nr_files == 1 && exists_and_not_file(jobname)) 1107 add_file(td, jobname, job_add_num, 0); 1108 else { 1109 for (i = 0; i < o->nr_files; i++) 1110 add_file(td, make_filename(fname, sizeof(fname), o, jobname, job_add_num, i), job_add_num, 0); 1111 } 1112 } 1113 1114 if (fixup_options(td)) 1115 goto err; 1116 1117 flow_init_job(td); 1118 1119 /* 1120 * IO engines only need this for option callbacks, and the address may 1121 * change in subprocesses. 1122 */ 1123 if (td->eo) 1124 *(struct thread_data **)td->eo = NULL; 1125 1126 if (td->io_ops->flags & FIO_DISKLESSIO) { 1127 struct fio_file *f; 1128 1129 for_each_file(td, f, i) 1130 f->real_file_size = -1ULL; 1131 } 1132 1133 td->mutex = fio_mutex_init(FIO_MUTEX_LOCKED); 1134 1135 td->ts.clat_percentiles = o->clat_percentiles; 1136 td->ts.percentile_precision = o->percentile_precision; 1137 memcpy(td->ts.percentile_list, o->percentile_list, sizeof(o->percentile_list)); 1138 1139 for (i = 0; i < DDIR_RWDIR_CNT; i++) { 1140 td->ts.clat_stat[i].min_val = ULONG_MAX; 1141 td->ts.slat_stat[i].min_val = ULONG_MAX; 1142 td->ts.lat_stat[i].min_val = ULONG_MAX; 1143 td->ts.bw_stat[i].min_val = ULONG_MAX; 1144 } 1145 td->ddir_seq_nr = o->ddir_seq_nr; 1146 1147 if ((o->stonewall || o->new_group) && prev_group_jobs) { 1148 prev_group_jobs = 0; 1149 groupid++; 1150 } 1151 1152 td->groupid = groupid; 1153 prev_group_jobs++; 1154 1155 if (setup_random_seeds(td)) { 1156 td_verror(td, errno, "init_random_state"); 1157 goto err; 1158 } 1159 1160 if (setup_rate(td)) 1161 goto err; 1162 1163 if (o->lat_log_file) { 1164 struct log_params p = { 1165 .td = td, 1166 .avg_msec = o->log_avg_msec, 1167 .log_type = IO_LOG_TYPE_LAT, 1168 .log_offset = o->log_offset, 1169 .log_gz = o->log_gz, 1170 .log_gz_store = o->log_gz_store, 1171 }; 1172 const char *suf; 1173 1174 if (p.log_gz_store) 1175 suf = "log.fz"; 1176 else 1177 suf = "log"; 1178 1179 snprintf(logname, sizeof(logname), "%s_lat.%d.%s", 1180 o->lat_log_file, td->thread_number, suf); 1181 setup_log(&td->lat_log, &p, logname); 1182 snprintf(logname, sizeof(logname), "%s_slat.%d.%s", 1183 o->lat_log_file, td->thread_number, suf); 1184 setup_log(&td->slat_log, &p, logname); 1185 snprintf(logname, sizeof(logname), "%s_clat.%d.%s", 1186 o->lat_log_file, td->thread_number, suf); 1187 setup_log(&td->clat_log, &p, logname); 1188 } 1189 if (o->bw_log_file) { 1190 struct log_params p = { 1191 .td = td, 1192 .avg_msec = o->log_avg_msec, 1193 .log_type = IO_LOG_TYPE_BW, 1194 .log_offset = o->log_offset, 1195 .log_gz = o->log_gz, 1196 .log_gz_store = o->log_gz_store, 1197 }; 1198 const char *suf; 1199 1200 if (p.log_gz_store) 1201 suf = "log.fz"; 1202 else 1203 suf = "log"; 1204 1205 snprintf(logname, sizeof(logname), "%s_bw.%d.%s", 1206 o->bw_log_file, td->thread_number, suf); 1207 setup_log(&td->bw_log, &p, logname); 1208 } 1209 if (o->iops_log_file) { 1210 struct log_params p = { 1211 .td = td, 1212 .avg_msec = o->log_avg_msec, 1213 .log_type = IO_LOG_TYPE_IOPS, 1214 .log_offset = o->log_offset, 1215 .log_gz = o->log_gz, 1216 .log_gz_store = o->log_gz_store, 1217 }; 1218 const char *suf; 1219 1220 if (p.log_gz_store) 1221 suf = "log.fz"; 1222 else 1223 suf = "log"; 1224 1225 snprintf(logname, sizeof(logname), "%s_iops.%d.%s", 1226 o->iops_log_file, td->thread_number, suf); 1227 setup_log(&td->iops_log, &p, logname); 1228 } 1229 1230 if (!o->name) 1231 o->name = strdup(jobname); 1232 1233 if (output_format == FIO_OUTPUT_NORMAL) { 1234 if (!job_add_num) { 1235 if (is_backend && !recursed) 1236 fio_server_send_add_job(td); 1237 1238 if (!(td->io_ops->flags & FIO_NOIO)) { 1239 char *c1, *c2, *c3, *c4; 1240 char *c5 = NULL, *c6 = NULL; 1241 1242 c1 = fio_uint_to_kmg(o->min_bs[DDIR_READ]); 1243 c2 = fio_uint_to_kmg(o->max_bs[DDIR_READ]); 1244 c3 = fio_uint_to_kmg(o->min_bs[DDIR_WRITE]); 1245 c4 = fio_uint_to_kmg(o->max_bs[DDIR_WRITE]); 1246 1247 if (!o->bs_is_seq_rand) { 1248 c5 = fio_uint_to_kmg(o->min_bs[DDIR_TRIM]); 1249 c6 = fio_uint_to_kmg(o->max_bs[DDIR_TRIM]); 1250 } 1251 1252 log_info("%s: (g=%d): rw=%s, ", td->o.name, 1253 td->groupid, 1254 ddir_str(o->td_ddir)); 1255 1256 if (o->bs_is_seq_rand) 1257 log_info("bs(seq/rand)=%s-%s/%s-%s, ", 1258 c1, c2, c3, c4); 1259 else 1260 log_info("bs=%s-%s/%s-%s/%s-%s, ", 1261 c1, c2, c3, c4, c5, c6); 1262 1263 log_info("ioengine=%s, iodepth=%u\n", 1264 td->io_ops->name, o->iodepth); 1265 1266 free(c1); 1267 free(c2); 1268 free(c3); 1269 free(c4); 1270 free(c5); 1271 free(c6); 1272 } 1273 } else if (job_add_num == 1) 1274 log_info("...\n"); 1275 } 1276 1277 /* 1278 * recurse add identical jobs, clear numjobs and stonewall options 1279 * as they don't apply to sub-jobs 1280 */ 1281 numjobs = o->numjobs; 1282 while (--numjobs) { 1283 struct thread_data *td_new = get_new_job(0, td, 1, jobname); 1284 1285 if (!td_new) 1286 goto err; 1287 1288 td_new->o.numjobs = 1; 1289 td_new->o.stonewall = 0; 1290 td_new->o.new_group = 0; 1291 1292 if (file_alloced) { 1293 if (td_new->files) { 1294 struct fio_file *f; 1295 for_each_file(td_new, f, i) { 1296 if (f->file_name) 1297 sfree(f->file_name); 1298 sfree(f); 1299 } 1300 free(td_new->files); 1301 td_new->files = NULL; 1302 } 1303 td_new->files_index = 0; 1304 td_new->files_size = 0; 1305 if (td_new->o.filename) { 1306 free(td_new->o.filename); 1307 td_new->o.filename = NULL; 1308 } 1309 } 1310 1311 if (add_job(td_new, jobname, numjobs, 1, client_type)) 1312 goto err; 1313 } 1314 1315 return 0; 1316err: 1317 put_job(td); 1318 return -1; 1319} 1320 1321/* 1322 * Parse as if 'o' was a command line 1323 */ 1324void add_job_opts(const char **o, int client_type) 1325{ 1326 struct thread_data *td, *td_parent; 1327 int i, in_global = 1; 1328 char jobname[32]; 1329 1330 i = 0; 1331 td_parent = td = NULL; 1332 while (o[i]) { 1333 if (!strncmp(o[i], "name", 4)) { 1334 in_global = 0; 1335 if (td) 1336 add_job(td, jobname, 0, 0, client_type); 1337 td = NULL; 1338 sprintf(jobname, "%s", o[i] + 5); 1339 } 1340 if (in_global && !td_parent) 1341 td_parent = get_new_job(1, &def_thread, 0, jobname); 1342 else if (!in_global && !td) { 1343 if (!td_parent) 1344 td_parent = &def_thread; 1345 td = get_new_job(0, td_parent, 0, jobname); 1346 } 1347 if (in_global) 1348 fio_options_parse(td_parent, (char **) &o[i], 1, 0); 1349 else 1350 fio_options_parse(td, (char **) &o[i], 1, 0); 1351 i++; 1352 } 1353 1354 if (td) 1355 add_job(td, jobname, 0, 0, client_type); 1356} 1357 1358static int skip_this_section(const char *name) 1359{ 1360 int i; 1361 1362 if (!nr_job_sections) 1363 return 0; 1364 if (!strncmp(name, "global", 6)) 1365 return 0; 1366 1367 for (i = 0; i < nr_job_sections; i++) 1368 if (!strcmp(job_sections[i], name)) 1369 return 0; 1370 1371 return 1; 1372} 1373 1374static int is_empty_or_comment(char *line) 1375{ 1376 unsigned int i; 1377 1378 for (i = 0; i < strlen(line); i++) { 1379 if (line[i] == ';') 1380 return 1; 1381 if (line[i] == '#') 1382 return 1; 1383 if (!isspace((int) line[i]) && !iscntrl((int) line[i])) 1384 return 0; 1385 } 1386 1387 return 1; 1388} 1389 1390/* 1391 * This is our [ini] type file parser. 1392 */ 1393int parse_jobs_ini(char *file, int is_buf, int stonewall_flag, int type) 1394{ 1395 unsigned int global; 1396 struct thread_data *td; 1397 char *string, *name; 1398 FILE *f; 1399 char *p; 1400 int ret = 0, stonewall; 1401 int first_sect = 1; 1402 int skip_fgets = 0; 1403 int inside_skip = 0; 1404 char **opts; 1405 int i, alloc_opts, num_opts; 1406 1407 if (is_buf) 1408 f = NULL; 1409 else { 1410 if (!strcmp(file, "-")) 1411 f = stdin; 1412 else 1413 f = fopen(file, "r"); 1414 1415 if (!f) { 1416 perror("fopen job file"); 1417 return 1; 1418 } 1419 } 1420 1421 string = malloc(4096); 1422 1423 /* 1424 * it's really 256 + small bit, 280 should suffice 1425 */ 1426 name = malloc(280); 1427 memset(name, 0, 280); 1428 1429 alloc_opts = 8; 1430 opts = malloc(sizeof(char *) * alloc_opts); 1431 num_opts = 0; 1432 1433 stonewall = stonewall_flag; 1434 do { 1435 /* 1436 * if skip_fgets is set, we already have loaded a line we 1437 * haven't handled. 1438 */ 1439 if (!skip_fgets) { 1440 if (is_buf) 1441 p = strsep(&file, "\n"); 1442 else 1443 p = fgets(string, 4096, f); 1444 if (!p) 1445 break; 1446 } 1447 1448 skip_fgets = 0; 1449 strip_blank_front(&p); 1450 strip_blank_end(p); 1451 1452 if (is_empty_or_comment(p)) 1453 continue; 1454 if (sscanf(p, "[%255[^\n]]", name) != 1) { 1455 if (inside_skip) 1456 continue; 1457 log_err("fio: option <%s> outside of [] job section\n", 1458 p); 1459 break; 1460 } 1461 1462 name[strlen(name) - 1] = '\0'; 1463 1464 if (skip_this_section(name)) { 1465 inside_skip = 1; 1466 continue; 1467 } else 1468 inside_skip = 0; 1469 1470 global = !strncmp(name, "global", 6); 1471 1472 if (dump_cmdline) { 1473 if (first_sect) 1474 log_info("fio "); 1475 if (!global) 1476 log_info("--name=%s ", name); 1477 first_sect = 0; 1478 } 1479 1480 td = get_new_job(global, &def_thread, 0, name); 1481 if (!td) { 1482 ret = 1; 1483 break; 1484 } 1485 1486 /* 1487 * Separate multiple job files by a stonewall 1488 */ 1489 if (!global && stonewall) { 1490 td->o.stonewall = stonewall; 1491 stonewall = 0; 1492 } 1493 1494 num_opts = 0; 1495 memset(opts, 0, alloc_opts * sizeof(char *)); 1496 1497 while (1) { 1498 if (is_buf) 1499 p = strsep(&file, "\n"); 1500 else 1501 p = fgets(string, 4096, f); 1502 if (!p) 1503 break; 1504 1505 if (is_empty_or_comment(p)) 1506 continue; 1507 1508 strip_blank_front(&p); 1509 1510 /* 1511 * new section, break out and make sure we don't 1512 * fgets() a new line at the top. 1513 */ 1514 if (p[0] == '[') { 1515 skip_fgets = 1; 1516 break; 1517 } 1518 1519 strip_blank_end(p); 1520 1521 if (num_opts == alloc_opts) { 1522 alloc_opts <<= 1; 1523 opts = realloc(opts, 1524 alloc_opts * sizeof(char *)); 1525 } 1526 1527 opts[num_opts] = strdup(p); 1528 num_opts++; 1529 } 1530 1531 ret = fio_options_parse(td, opts, num_opts, dump_cmdline); 1532 if (!ret) 1533 ret = add_job(td, name, 0, 0, type); 1534 else { 1535 log_err("fio: job %s dropped\n", name); 1536 put_job(td); 1537 } 1538 1539 for (i = 0; i < num_opts; i++) 1540 free(opts[i]); 1541 num_opts = 0; 1542 } while (!ret); 1543 1544 if (dump_cmdline) 1545 log_info("\n"); 1546 1547 i = 0; 1548 while (i < nr_job_sections) { 1549 free(job_sections[i]); 1550 i++; 1551 } 1552 1553 free(string); 1554 free(name); 1555 free(opts); 1556 if (!is_buf && f != stdin) 1557 fclose(f); 1558 return ret; 1559} 1560 1561static int fill_def_thread(void) 1562{ 1563 memset(&def_thread, 0, sizeof(def_thread)); 1564 1565 fio_getaffinity(getpid(), &def_thread.o.cpumask); 1566 def_thread.o.error_dump = 1; 1567 1568 /* 1569 * fill default options 1570 */ 1571 fio_fill_default_options(&def_thread); 1572 return 0; 1573} 1574 1575static void usage(const char *name) 1576{ 1577 printf("%s\n", fio_version_string); 1578 printf("%s [options] [job options] <job file(s)>\n", name); 1579 printf(" --debug=options\tEnable debug logging. May be one/more of:\n" 1580 "\t\t\tprocess,file,io,mem,blktrace,verify,random,parse,\n" 1581 "\t\t\tdiskutil,job,mutex,profile,time,net,rate,compress\n"); 1582 printf(" --parse-only\t\tParse options only, don't start any IO\n"); 1583 printf(" --output\t\tWrite output to file\n"); 1584 printf(" --runtime\t\tRuntime in seconds\n"); 1585 printf(" --bandwidth-log\tGenerate per-job bandwidth logs\n"); 1586 printf(" --minimal\t\tMinimal (terse) output\n"); 1587 printf(" --output-format=x\tOutput format (terse,json,normal)\n"); 1588 printf(" --terse-version=x\tSet terse version output format to 'x'\n"); 1589 printf(" --version\t\tPrint version info and exit\n"); 1590 printf(" --help\t\tPrint this page\n"); 1591 printf(" --cpuclock-test\tPerform test/validation of CPU clock\n"); 1592 printf(" --crctest\t\tTest speed of checksum functions\n"); 1593 printf(" --cmdhelp=cmd\t\tPrint command help, \"all\" for all of" 1594 " them\n"); 1595 printf(" --enghelp=engine\tPrint ioengine help, or list" 1596 " available ioengines\n"); 1597 printf(" --enghelp=engine,cmd\tPrint help for an ioengine" 1598 " cmd\n"); 1599 printf(" --showcmd\t\tTurn a job file into command line options\n"); 1600 printf(" --eta=when\t\tWhen ETA estimate should be printed\n"); 1601 printf(" \t\tMay be \"always\", \"never\" or \"auto\"\n"); 1602 printf(" --eta-newline=time\tForce a new line for every 'time'"); 1603 printf(" period passed\n"); 1604 printf(" --status-interval=t\tForce full status dump every"); 1605 printf(" 't' period passed\n"); 1606 printf(" --readonly\t\tTurn on safety read-only checks, preventing" 1607 " writes\n"); 1608 printf(" --section=name\tOnly run specified section in job file\n"); 1609 printf(" --alloc-size=kb\tSet smalloc pool to this size in kb" 1610 " (def 1024)\n"); 1611 printf(" --warnings-fatal\tFio parser warnings are fatal\n"); 1612 printf(" --max-jobs=nr\t\tMaximum number of threads/processes to support\n"); 1613 printf(" --server=args\t\tStart a backend fio server\n"); 1614 printf(" --daemonize=pidfile\tBackground fio server, write pid to file\n"); 1615 printf(" --client=hostname\tTalk to remote backend fio server at hostname\n"); 1616 printf(" --idle-prof=option\tReport cpu idleness on a system or percpu basis\n" 1617 "\t\t\t(option=system,percpu) or run unit work\n" 1618 "\t\t\tcalibration only (option=calibrate)\n"); 1619#ifdef CONFIG_ZLIB 1620 printf(" --inflate-log=log\tInflate and output compressed log\n"); 1621#endif 1622 printf("\nFio was written by Jens Axboe <jens.axboe@oracle.com>"); 1623 printf("\n Jens Axboe <jaxboe@fusionio.com>"); 1624 printf("\n Jens Axboe <axboe@fb.com>\n"); 1625} 1626 1627#ifdef FIO_INC_DEBUG 1628struct debug_level debug_levels[] = { 1629 { .name = "process", 1630 .help = "Process creation/exit logging", 1631 .shift = FD_PROCESS, 1632 }, 1633 { .name = "file", 1634 .help = "File related action logging", 1635 .shift = FD_FILE, 1636 }, 1637 { .name = "io", 1638 .help = "IO and IO engine action logging (offsets, queue, completions, etc)", 1639 .shift = FD_IO, 1640 }, 1641 { .name = "mem", 1642 .help = "Memory allocation/freeing logging", 1643 .shift = FD_MEM, 1644 }, 1645 { .name = "blktrace", 1646 .help = "blktrace action logging", 1647 .shift = FD_BLKTRACE, 1648 }, 1649 { .name = "verify", 1650 .help = "IO verification action logging", 1651 .shift = FD_VERIFY, 1652 }, 1653 { .name = "random", 1654 .help = "Random generation logging", 1655 .shift = FD_RANDOM, 1656 }, 1657 { .name = "parse", 1658 .help = "Parser logging", 1659 .shift = FD_PARSE, 1660 }, 1661 { .name = "diskutil", 1662 .help = "Disk utility logging actions", 1663 .shift = FD_DISKUTIL, 1664 }, 1665 { .name = "job", 1666 .help = "Logging related to creating/destroying jobs", 1667 .shift = FD_JOB, 1668 }, 1669 { .name = "mutex", 1670 .help = "Mutex logging", 1671 .shift = FD_MUTEX 1672 }, 1673 { .name = "profile", 1674 .help = "Logging related to profiles", 1675 .shift = FD_PROFILE, 1676 }, 1677 { .name = "time", 1678 .help = "Logging related to time keeping functions", 1679 .shift = FD_TIME, 1680 }, 1681 { .name = "net", 1682 .help = "Network logging", 1683 .shift = FD_NET, 1684 }, 1685 { .name = "rate", 1686 .help = "Rate logging", 1687 .shift = FD_RATE, 1688 }, 1689 { .name = "compress", 1690 .help = "Log compression logging", 1691 .shift = FD_COMPRESS, 1692 }, 1693 { .name = NULL, }, 1694}; 1695 1696static int set_debug(const char *string) 1697{ 1698 struct debug_level *dl; 1699 char *p = (char *) string; 1700 char *opt; 1701 int i; 1702 1703 if (!strcmp(string, "?") || !strcmp(string, "help")) { 1704 log_info("fio: dumping debug options:"); 1705 for (i = 0; debug_levels[i].name; i++) { 1706 dl = &debug_levels[i]; 1707 log_info("%s,", dl->name); 1708 } 1709 log_info("all\n"); 1710 return 1; 1711 } 1712 1713 while ((opt = strsep(&p, ",")) != NULL) { 1714 int found = 0; 1715 1716 if (!strncmp(opt, "all", 3)) { 1717 log_info("fio: set all debug options\n"); 1718 fio_debug = ~0UL; 1719 continue; 1720 } 1721 1722 for (i = 0; debug_levels[i].name; i++) { 1723 dl = &debug_levels[i]; 1724 found = !strncmp(opt, dl->name, strlen(dl->name)); 1725 if (!found) 1726 continue; 1727 1728 if (dl->shift == FD_JOB) { 1729 opt = strchr(opt, ':'); 1730 if (!opt) { 1731 log_err("fio: missing job number\n"); 1732 break; 1733 } 1734 opt++; 1735 fio_debug_jobno = atoi(opt); 1736 log_info("fio: set debug jobno %d\n", 1737 fio_debug_jobno); 1738 } else { 1739 log_info("fio: set debug option %s\n", opt); 1740 fio_debug |= (1UL << dl->shift); 1741 } 1742 break; 1743 } 1744 1745 if (!found) 1746 log_err("fio: debug mask %s not found\n", opt); 1747 } 1748 return 0; 1749} 1750#else 1751static int set_debug(const char *string) 1752{ 1753 log_err("fio: debug tracing not included in build\n"); 1754 return 1; 1755} 1756#endif 1757 1758static void fio_options_fill_optstring(void) 1759{ 1760 char *ostr = cmd_optstr; 1761 int i, c; 1762 1763 c = i = 0; 1764 while (l_opts[i].name) { 1765 ostr[c++] = l_opts[i].val; 1766 if (l_opts[i].has_arg == required_argument) 1767 ostr[c++] = ':'; 1768 else if (l_opts[i].has_arg == optional_argument) { 1769 ostr[c++] = ':'; 1770 ostr[c++] = ':'; 1771 } 1772 i++; 1773 } 1774 ostr[c] = '\0'; 1775} 1776 1777static int client_flag_set(char c) 1778{ 1779 int i; 1780 1781 i = 0; 1782 while (l_opts[i].name) { 1783 int val = l_opts[i].val; 1784 1785 if (c == (val & 0xff)) 1786 return (val & FIO_CLIENT_FLAG); 1787 1788 i++; 1789 } 1790 1791 return 0; 1792} 1793 1794static void parse_cmd_client(void *client, char *opt) 1795{ 1796 fio_client_add_cmd_option(client, opt); 1797} 1798 1799int parse_cmd_line(int argc, char *argv[], int client_type) 1800{ 1801 struct thread_data *td = NULL; 1802 int c, ini_idx = 0, lidx, ret = 0, do_exit = 0, exit_val = 0; 1803 char *ostr = cmd_optstr; 1804 void *pid_file = NULL; 1805 void *cur_client = NULL; 1806 int backend = 0; 1807 1808 /* 1809 * Reset optind handling, since we may call this multiple times 1810 * for the backend. 1811 */ 1812 optind = 1; 1813 1814 while ((c = getopt_long_only(argc, argv, ostr, l_opts, &lidx)) != -1) { 1815 if ((c & FIO_CLIENT_FLAG) || client_flag_set(c)) { 1816 parse_cmd_client(cur_client, argv[optind - 1]); 1817 c &= ~FIO_CLIENT_FLAG; 1818 } 1819 1820 switch (c) { 1821 case 'a': 1822 smalloc_pool_size = atoi(optarg); 1823 break; 1824 case 't': 1825 if (check_str_time(optarg, &def_timeout, 1)) { 1826 log_err("fio: failed parsing time %s\n", optarg); 1827 do_exit++; 1828 exit_val = 1; 1829 } 1830 break; 1831 case 'l': 1832 log_err("fio: --latency-log is deprecated. Use per-job latency log options.\n"); 1833 do_exit++; 1834 exit_val = 1; 1835 break; 1836 case 'b': 1837 write_bw_log = 1; 1838 break; 1839 case 'o': 1840 if (f_out && f_out != stdout) 1841 fclose(f_out); 1842 1843 f_out = fopen(optarg, "w+"); 1844 if (!f_out) { 1845 perror("fopen output"); 1846 exit(1); 1847 } 1848 f_err = f_out; 1849 break; 1850 case 'm': 1851 output_format = FIO_OUTPUT_TERSE; 1852 break; 1853 case 'F': 1854 if (!optarg) { 1855 log_err("fio: missing --output-format argument\n"); 1856 exit_val = 1; 1857 do_exit++; 1858 break; 1859 } 1860 if (!strcmp(optarg, "minimal") || 1861 !strcmp(optarg, "terse") || 1862 !strcmp(optarg, "csv")) 1863 output_format = FIO_OUTPUT_TERSE; 1864 else if (!strcmp(optarg, "json")) 1865 output_format = FIO_OUTPUT_JSON; 1866 else 1867 output_format = FIO_OUTPUT_NORMAL; 1868 break; 1869 case 'f': 1870 append_terse_output = 1; 1871 break; 1872 case 'h': 1873 did_arg = 1; 1874 if (!cur_client) { 1875 usage(argv[0]); 1876 do_exit++; 1877 } 1878 break; 1879 case 'c': 1880 did_arg = 1; 1881 if (!cur_client) { 1882 fio_show_option_help(optarg); 1883 do_exit++; 1884 } 1885 break; 1886 case 'i': 1887 did_arg = 1; 1888 if (!cur_client) { 1889 fio_show_ioengine_help(optarg); 1890 do_exit++; 1891 } 1892 break; 1893 case 's': 1894 did_arg = 1; 1895 dump_cmdline = 1; 1896 break; 1897 case 'r': 1898 read_only = 1; 1899 break; 1900 case 'v': 1901 did_arg = 1; 1902 if (!cur_client) { 1903 log_info("%s\n", fio_version_string); 1904 do_exit++; 1905 } 1906 break; 1907 case 'V': 1908 terse_version = atoi(optarg); 1909 if (!(terse_version == 2 || terse_version == 3 || 1910 terse_version == 4)) { 1911 log_err("fio: bad terse version format\n"); 1912 exit_val = 1; 1913 do_exit++; 1914 } 1915 break; 1916 case 'e': 1917 if (!strcmp("always", optarg)) 1918 eta_print = FIO_ETA_ALWAYS; 1919 else if (!strcmp("never", optarg)) 1920 eta_print = FIO_ETA_NEVER; 1921 break; 1922 case 'E': { 1923 long long t = 0; 1924 1925 if (str_to_decimal(optarg, &t, 0, NULL, 1)) { 1926 log_err("fio: failed parsing eta time %s\n", optarg); 1927 exit_val = 1; 1928 do_exit++; 1929 } 1930 eta_new_line = t; 1931 break; 1932 } 1933 case 'd': 1934 if (set_debug(optarg)) 1935 do_exit++; 1936 break; 1937 case 'P': 1938 did_arg = 1; 1939 parse_only = 1; 1940 break; 1941 case 'x': { 1942 size_t new_size; 1943 1944 if (!strcmp(optarg, "global")) { 1945 log_err("fio: can't use global as only " 1946 "section\n"); 1947 do_exit++; 1948 exit_val = 1; 1949 break; 1950 } 1951 new_size = (nr_job_sections + 1) * sizeof(char *); 1952 job_sections = realloc(job_sections, new_size); 1953 job_sections[nr_job_sections] = strdup(optarg); 1954 nr_job_sections++; 1955 break; 1956 } 1957#ifdef CONFIG_ZLIB 1958 case 'X': 1959 exit_val = iolog_file_inflate(optarg); 1960 did_arg++; 1961 do_exit++; 1962 break; 1963#endif 1964 case 'p': 1965 did_arg = 1; 1966 if (exec_profile) 1967 free(exec_profile); 1968 exec_profile = strdup(optarg); 1969 break; 1970 case FIO_GETOPT_JOB: { 1971 const char *opt = l_opts[lidx].name; 1972 char *val = optarg; 1973 1974 if (!strncmp(opt, "name", 4) && td) { 1975 ret = add_job(td, td->o.name ?: "fio", 0, 0, client_type); 1976 if (ret) 1977 goto out_free; 1978 td = NULL; 1979 did_arg = 1; 1980 } 1981 if (!td) { 1982 int is_section = !strncmp(opt, "name", 4); 1983 int global = 0; 1984 1985 if (!is_section || !strncmp(val, "global", 6)) 1986 global = 1; 1987 1988 if (is_section && skip_this_section(val)) 1989 continue; 1990 1991 td = get_new_job(global, &def_thread, 1, NULL); 1992 if (!td || ioengine_load(td)) { 1993 if (td) { 1994 put_job(td); 1995 td = NULL; 1996 } 1997 do_exit++; 1998 break; 1999 } 2000 fio_options_set_ioengine_opts(l_opts, td); 2001 } 2002 2003 if ((!val || !strlen(val)) && 2004 l_opts[lidx].has_arg == required_argument) { 2005 log_err("fio: option %s requires an argument\n", opt); 2006 ret = 1; 2007 } else 2008 ret = fio_cmd_option_parse(td, opt, val); 2009 2010 if (ret) { 2011 if (td) { 2012 put_job(td); 2013 td = NULL; 2014 } 2015 do_exit++; 2016 } 2017 2018 if (!ret && !strcmp(opt, "ioengine")) { 2019 free_ioengine(td); 2020 if (ioengine_load(td)) { 2021 put_job(td); 2022 td = NULL; 2023 do_exit++; 2024 break; 2025 } 2026 fio_options_set_ioengine_opts(l_opts, td); 2027 } 2028 break; 2029 } 2030 case FIO_GETOPT_IOENGINE: { 2031 const char *opt = l_opts[lidx].name; 2032 char *val = optarg; 2033 2034 if (!td) 2035 break; 2036 2037 ret = fio_cmd_ioengine_option_parse(td, opt, val); 2038 break; 2039 } 2040 case 'w': 2041 warnings_fatal = 1; 2042 break; 2043 case 'j': 2044 max_jobs = atoi(optarg); 2045 if (!max_jobs || max_jobs > REAL_MAX_JOBS) { 2046 log_err("fio: invalid max jobs: %d\n", max_jobs); 2047 do_exit++; 2048 exit_val = 1; 2049 } 2050 break; 2051 case 'S': 2052 did_arg = 1; 2053#ifndef CONFIG_NO_SHM 2054 if (nr_clients) { 2055 log_err("fio: can't be both client and server\n"); 2056 do_exit++; 2057 exit_val = 1; 2058 break; 2059 } 2060 if (optarg) 2061 fio_server_set_arg(optarg); 2062 is_backend = 1; 2063 backend = 1; 2064#else 2065 log_err("fio: client/server requires SHM support\n"); 2066 do_exit++; 2067 exit_val = 1; 2068#endif 2069 break; 2070 case 'D': 2071 if (pid_file) 2072 free(pid_file); 2073 pid_file = strdup(optarg); 2074 break; 2075 case 'I': 2076 if ((ret = fio_idle_prof_parse_opt(optarg))) { 2077 /* exit on error and calibration only */ 2078 did_arg = 1; 2079 do_exit++; 2080 if (ret == -1) 2081 exit_val = 1; 2082 } 2083 break; 2084 case 'C': 2085 did_arg = 1; 2086 if (is_backend) { 2087 log_err("fio: can't be both client and server\n"); 2088 do_exit++; 2089 exit_val = 1; 2090 break; 2091 } 2092 if (fio_client_add(&fio_client_ops, optarg, &cur_client)) { 2093 log_err("fio: failed adding client %s\n", optarg); 2094 do_exit++; 2095 exit_val = 1; 2096 break; 2097 } 2098 /* 2099 * If the next argument exists and isn't an option, 2100 * assume it's a job file for this client only. 2101 */ 2102 while (optind < argc) { 2103 if (!strncmp(argv[optind], "--", 2) || 2104 !strncmp(argv[optind], "-", 1)) 2105 break; 2106 2107 fio_client_add_ini_file(cur_client, argv[optind]); 2108 optind++; 2109 } 2110 break; 2111 case 'T': 2112 did_arg = 1; 2113 do_exit++; 2114 exit_val = fio_monotonic_clocktest(); 2115 break; 2116 case 'G': 2117 did_arg = 1; 2118 do_exit++; 2119 exit_val = fio_crctest(optarg); 2120 break; 2121 case 'L': { 2122 long long val; 2123 2124 if (check_str_time(optarg, &val, 0)) { 2125 log_err("fio: failed parsing time %s\n", optarg); 2126 do_exit++; 2127 exit_val = 1; 2128 break; 2129 } 2130 status_interval = val * 1000; 2131 break; 2132 } 2133 case '?': 2134 log_err("%s: unrecognized option '%s'\n", argv[0], 2135 argv[optind - 1]); 2136 default: 2137 do_exit++; 2138 exit_val = 1; 2139 break; 2140 } 2141 if (do_exit) 2142 break; 2143 } 2144 2145 if (do_exit && !(is_backend || nr_clients)) 2146 exit(exit_val); 2147 2148 if (nr_clients && fio_clients_connect()) 2149 exit(1); 2150 2151 if (is_backend && backend) 2152 return fio_start_server(pid_file); 2153 else if (pid_file) 2154 free(pid_file); 2155 2156 if (td) { 2157 if (!ret) { 2158 ret = add_job(td, td->o.name ?: "fio", 0, 0, client_type); 2159 if (ret) 2160 did_arg = 1; 2161 } 2162 } 2163 2164 while (!ret && optind < argc) { 2165 ini_idx++; 2166 ini_file = realloc(ini_file, ini_idx * sizeof(char *)); 2167 ini_file[ini_idx - 1] = strdup(argv[optind]); 2168 optind++; 2169 } 2170 2171out_free: 2172 if (pid_file) 2173 free(pid_file); 2174 2175 return ini_idx; 2176} 2177 2178int fio_init_options(void) 2179{ 2180 f_out = stdout; 2181 f_err = stderr; 2182 2183 fio_options_fill_optstring(); 2184 fio_options_dup_and_init(l_opts); 2185 2186 atexit(free_shm); 2187 2188 if (fill_def_thread()) 2189 return 1; 2190 2191 return 0; 2192} 2193 2194extern int fio_check_options(struct thread_options *); 2195 2196int parse_options(int argc, char *argv[]) 2197{ 2198 const int type = FIO_CLIENT_TYPE_CLI; 2199 int job_files, i; 2200 2201 if (fio_init_options()) 2202 return 1; 2203 if (fio_test_cconv(&def_thread.o)) 2204 log_err("fio: failed internal cconv test\n"); 2205 2206 job_files = parse_cmd_line(argc, argv, type); 2207 2208 if (job_files > 0) { 2209 for (i = 0; i < job_files; i++) { 2210 if (i && fill_def_thread()) 2211 return 1; 2212 if (nr_clients) { 2213 if (fio_clients_send_ini(ini_file[i])) 2214 return 1; 2215 free(ini_file[i]); 2216 } else if (!is_backend) { 2217 if (parse_jobs_ini(ini_file[i], 0, i, type)) 2218 return 1; 2219 free(ini_file[i]); 2220 } 2221 } 2222 } else if (nr_clients) { 2223 if (fill_def_thread()) 2224 return 1; 2225 if (fio_clients_send_ini(NULL)) 2226 return 1; 2227 } 2228 2229 free(ini_file); 2230 fio_options_free(&def_thread); 2231 filesetup_mem_free(); 2232 2233 if (!thread_number) { 2234 if (parse_dryrun()) 2235 return 0; 2236 if (exec_profile) 2237 return 0; 2238 if (is_backend || nr_clients) 2239 return 0; 2240 if (did_arg) 2241 return 0; 2242 2243 log_err("No jobs(s) defined\n\n"); 2244 2245 if (!did_arg) { 2246 usage(argv[0]); 2247 return 1; 2248 } 2249 2250 return 0; 2251 } 2252 2253 if (def_thread.o.gtod_offload) { 2254 fio_gtod_init(); 2255 fio_gtod_offload = 1; 2256 fio_gtod_cpu = def_thread.o.gtod_cpu; 2257 } 2258 2259 if (output_format == FIO_OUTPUT_NORMAL) 2260 log_info("%s\n", fio_version_string); 2261 2262 return 0; 2263} 2264 2265void options_default_fill(struct thread_options *o) 2266{ 2267 memcpy(o, &def_thread.o, sizeof(*o)); 2268} 2269