init.c revision 9c574af285b40eb3eed470dc86dc909219cc9ea0
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 if (o->pre_read) { 641 o->invalidate_cache = 0; 642 if (td->io_ops->flags & FIO_PIPEIO) { 643 log_info("fio: cannot pre-read files with an IO engine" 644 " that isn't seekable. Pre-read disabled.\n"); 645 ret = warnings_fatal; 646 } 647 } 648 649 if (!o->unit_base) { 650 if (td->io_ops->flags & FIO_BIT_BASED) 651 o->unit_base = 1; 652 else 653 o->unit_base = 8; 654 } 655 656#ifndef CONFIG_FDATASYNC 657 if (o->fdatasync_blocks) { 658 log_info("fio: this platform does not support fdatasync()" 659 " falling back to using fsync(). Use the 'fsync'" 660 " option instead of 'fdatasync' to get rid of" 661 " this warning\n"); 662 o->fsync_blocks = o->fdatasync_blocks; 663 o->fdatasync_blocks = 0; 664 ret = warnings_fatal; 665 } 666#endif 667 668#ifdef WIN32 669 /* 670 * Windows doesn't support O_DIRECT or O_SYNC with the _open interface, 671 * so fail if we're passed those flags 672 */ 673 if ((td->io_ops->flags & FIO_SYNCIO) && (td->o.odirect || td->o.sync_io)) { 674 log_err("fio: Windows does not support direct or non-buffered io with" 675 " the synchronous ioengines. Use the 'windowsaio' ioengine" 676 " with 'direct=1' and 'iodepth=1' instead.\n"); 677 ret = 1; 678 } 679#endif 680 681 /* 682 * For fully compressible data, just zero them at init time. 683 * It's faster than repeatedly filling it. 684 */ 685 if (td->o.compress_percentage == 100) { 686 td->o.zero_buffers = 1; 687 td->o.compress_percentage = 0; 688 } 689 690 /* 691 * Using a non-uniform random distribution excludes usage of 692 * a random map 693 */ 694 if (td->o.random_distribution != FIO_RAND_DIST_RANDOM) 695 td->o.norandommap = 1; 696 697 /* 698 * If size is set but less than the min block size, complain 699 */ 700 if (o->size && o->size < td_min_bs(td)) { 701 log_err("fio: size too small, must be larger than the IO size: %llu\n", (unsigned long long) o->size); 702 ret = 1; 703 } 704 705 /* 706 * O_ATOMIC implies O_DIRECT 707 */ 708 if (td->o.oatomic) 709 td->o.odirect = 1; 710 711 /* 712 * If randseed is set, that overrides randrepeat 713 */ 714 if (td->o.rand_seed) 715 td->o.rand_repeatable = 0; 716 717 if ((td->io_ops->flags & FIO_NOEXTEND) && td->o.file_append) { 718 log_err("fio: can't append/extent with IO engine %s\n", td->io_ops->name); 719 ret = 1; 720 } 721 722 return ret; 723} 724 725/* 726 * This function leaks the buffer 727 */ 728char *fio_uint_to_kmg(unsigned int val) 729{ 730 char *buf = malloc(32); 731 char post[] = { 0, 'K', 'M', 'G', 'P', 'E', 0 }; 732 char *p = post; 733 734 do { 735 if (val & 1023) 736 break; 737 738 val >>= 10; 739 p++; 740 } while (*p); 741 742 snprintf(buf, 32, "%u%c", val, *p); 743 return buf; 744} 745 746/* External engines are specified by "external:name.o") */ 747static const char *get_engine_name(const char *str) 748{ 749 char *p = strstr(str, ":"); 750 751 if (!p) 752 return str; 753 754 p++; 755 strip_blank_front(&p); 756 strip_blank_end(p); 757 return p; 758} 759 760static int exists_and_not_file(const char *filename) 761{ 762 struct stat sb; 763 764 if (lstat(filename, &sb) == -1) 765 return 0; 766 767 /* \\.\ is the device namespace in Windows, where every file 768 * is a device node */ 769 if (S_ISREG(sb.st_mode) && strncmp(filename, "\\\\.\\", 4) != 0) 770 return 0; 771 772 return 1; 773} 774 775static void td_fill_rand_seeds_os(struct thread_data *td) 776{ 777 os_random_seed(td->rand_seeds[FIO_RAND_BS_OFF], &td->bsrange_state); 778 os_random_seed(td->rand_seeds[FIO_RAND_VER_OFF], &td->verify_state); 779 os_random_seed(td->rand_seeds[FIO_RAND_MIX_OFF], &td->rwmix_state); 780 781 if (td->o.file_service_type == FIO_FSERVICE_RANDOM) 782 os_random_seed(td->rand_seeds[FIO_RAND_FILE_OFF], &td->next_file_state); 783 784 os_random_seed(td->rand_seeds[FIO_RAND_FILE_SIZE_OFF], &td->file_size_state); 785 os_random_seed(td->rand_seeds[FIO_RAND_TRIM_OFF], &td->trim_state); 786 os_random_seed(td->rand_seeds[FIO_RAND_START_DELAY], &td->delay_state); 787 788 if (!td_random(td)) 789 return; 790 791 if (td->o.rand_repeatable) 792 td->rand_seeds[FIO_RAND_BLOCK_OFF] = FIO_RANDSEED * td->thread_number; 793 794 os_random_seed(td->rand_seeds[FIO_RAND_BLOCK_OFF], &td->random_state); 795 796 os_random_seed(td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF], &td->seq_rand_state[DDIR_READ]); 797 os_random_seed(td->rand_seeds[FIO_RAND_SEQ_RAND_WRITE_OFF], &td->seq_rand_state[DDIR_WRITE]); 798 os_random_seed(td->rand_seeds[FIO_RAND_SEQ_RAND_TRIM_OFF], &td->seq_rand_state[DDIR_TRIM]); 799} 800 801static void td_fill_rand_seeds_internal(struct thread_data *td) 802{ 803 init_rand_seed(&td->__bsrange_state, td->rand_seeds[FIO_RAND_BS_OFF]); 804 init_rand_seed(&td->__verify_state, td->rand_seeds[FIO_RAND_VER_OFF]); 805 init_rand_seed(&td->__rwmix_state, td->rand_seeds[FIO_RAND_MIX_OFF]); 806 807 if (td->o.file_service_type == FIO_FSERVICE_RANDOM) 808 init_rand_seed(&td->__next_file_state, td->rand_seeds[FIO_RAND_FILE_OFF]); 809 810 init_rand_seed(&td->__file_size_state, td->rand_seeds[FIO_RAND_FILE_SIZE_OFF]); 811 init_rand_seed(&td->__trim_state, td->rand_seeds[FIO_RAND_TRIM_OFF]); 812 init_rand_seed(&td->__delay_state, td->rand_seeds[FIO_RAND_START_DELAY]); 813 814 if (!td_random(td)) 815 return; 816 817 if (td->o.rand_repeatable) 818 td->rand_seeds[FIO_RAND_BLOCK_OFF] = FIO_RANDSEED * td->thread_number; 819 820 init_rand_seed(&td->__random_state, td->rand_seeds[FIO_RAND_BLOCK_OFF]); 821 init_rand_seed(&td->__seq_rand_state[DDIR_READ], td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF]); 822 init_rand_seed(&td->__seq_rand_state[DDIR_WRITE], td->rand_seeds[FIO_RAND_SEQ_RAND_WRITE_OFF]); 823 init_rand_seed(&td->__seq_rand_state[DDIR_TRIM], td->rand_seeds[FIO_RAND_SEQ_RAND_TRIM_OFF]); 824} 825 826void td_fill_rand_seeds(struct thread_data *td) 827{ 828 if (td->o.allrand_repeatable) { 829 for (int i = 0; i < FIO_RAND_NR_OFFS; i++) 830 td->rand_seeds[i] = FIO_RANDSEED * td->thread_number 831 + i; 832 } 833 834 if (td->o.use_os_rand) 835 td_fill_rand_seeds_os(td); 836 else 837 td_fill_rand_seeds_internal(td); 838 839 init_rand_seed(&td->buf_state, td->rand_seeds[FIO_RAND_BUF_OFF]); 840} 841 842/* 843 * Initializes the ioengine configured for a job, if it has not been done so 844 * already. 845 */ 846int ioengine_load(struct thread_data *td) 847{ 848 const char *engine; 849 850 /* 851 * Engine has already been loaded. 852 */ 853 if (td->io_ops) 854 return 0; 855 if (!td->o.ioengine) { 856 log_err("fio: internal fault, no IO engine specified\n"); 857 return 1; 858 } 859 860 engine = get_engine_name(td->o.ioengine); 861 td->io_ops = load_ioengine(td, engine); 862 if (!td->io_ops) { 863 log_err("fio: failed to load engine %s\n", engine); 864 return 1; 865 } 866 867 if (td->io_ops->option_struct_size && td->io_ops->options) { 868 /* 869 * In cases where td->eo is set, clone it for a child thread. 870 * This requires that the parent thread has the same ioengine, 871 * but that requirement must be enforced by the code which 872 * cloned the thread. 873 */ 874 void *origeo = td->eo; 875 /* 876 * Otherwise use the default thread options. 877 */ 878 if (!origeo && td != &def_thread && def_thread.eo && 879 def_thread.io_ops->options == td->io_ops->options) 880 origeo = def_thread.eo; 881 882 options_init(td->io_ops->options); 883 td->eo = malloc(td->io_ops->option_struct_size); 884 /* 885 * Use the default thread as an option template if this uses the 886 * same options structure and there are non-default options 887 * used. 888 */ 889 if (origeo) { 890 memcpy(td->eo, origeo, td->io_ops->option_struct_size); 891 options_mem_dupe(td->eo, td->io_ops->options); 892 } else { 893 memset(td->eo, 0, td->io_ops->option_struct_size); 894 fill_default_options(td->eo, td->io_ops->options); 895 } 896 *(struct thread_data **)td->eo = td; 897 } 898 899 return 0; 900} 901 902static void init_flags(struct thread_data *td) 903{ 904 struct thread_options *o = &td->o; 905 906 if (o->verify_backlog) 907 td->flags |= TD_F_VER_BACKLOG; 908 if (o->trim_backlog) 909 td->flags |= TD_F_TRIM_BACKLOG; 910 if (o->read_iolog_file) 911 td->flags |= TD_F_READ_IOLOG; 912 if (o->refill_buffers) 913 td->flags |= TD_F_REFILL_BUFFERS; 914 if (o->scramble_buffers) 915 td->flags |= TD_F_SCRAMBLE_BUFFERS; 916 if (o->verify != VERIFY_NONE) 917 td->flags |= TD_F_VER_NONE; 918} 919 920static int setup_random_seeds(struct thread_data *td) 921{ 922 unsigned long seed; 923 unsigned int i; 924 925 if (!td->o.rand_repeatable && !td->o.rand_seed) 926 return init_random_state(td, td->rand_seeds, sizeof(td->rand_seeds)); 927 928 if (!td->o.rand_seed) 929 seed = 0x89; 930 else 931 seed = td->o.rand_seed; 932 933 for (i = 0; i < 4; i++) 934 seed *= 0x9e370001UL; 935 936 for (i = 0; i < FIO_RAND_NR_OFFS; i++) { 937 td->rand_seeds[i] = seed; 938 seed *= 0x9e370001UL; 939 } 940 941 td_fill_rand_seeds(td); 942 return 0; 943} 944 945enum { 946 FPRE_NONE = 0, 947 FPRE_JOBNAME, 948 FPRE_JOBNUM, 949 FPRE_FILENUM 950}; 951 952static struct fpre_keyword { 953 const char *keyword; 954 size_t strlen; 955 int key; 956} fpre_keywords[] = { 957 { .keyword = "$jobname", .key = FPRE_JOBNAME, }, 958 { .keyword = "$jobnum", .key = FPRE_JOBNUM, }, 959 { .keyword = "$filenum", .key = FPRE_FILENUM, }, 960 { .keyword = NULL, }, 961 }; 962 963static char *make_filename(char *buf, size_t buf_size,struct thread_options *o, 964 const char *jobname, int jobnum, int filenum) 965{ 966 struct fpre_keyword *f; 967 char copy[PATH_MAX]; 968 size_t dst_left = PATH_MAX - 1; 969 970 if (!o->filename_format || !strlen(o->filename_format)) { 971 sprintf(buf, "%s.%d.%d", jobname, jobnum, filenum); 972 return NULL; 973 } 974 975 for (f = &fpre_keywords[0]; f->keyword; f++) 976 f->strlen = strlen(f->keyword); 977 978 buf[buf_size - 1] = '\0'; 979 strncpy(buf, o->filename_format, buf_size - 1); 980 981 memset(copy, 0, sizeof(copy)); 982 for (f = &fpre_keywords[0]; f->keyword; f++) { 983 do { 984 size_t pre_len, post_start = 0; 985 char *str, *dst = copy; 986 987 str = strcasestr(buf, f->keyword); 988 if (!str) 989 break; 990 991 pre_len = str - buf; 992 if (strlen(str) != f->strlen) 993 post_start = pre_len + f->strlen; 994 995 if (pre_len) { 996 strncpy(dst, buf, pre_len); 997 dst += pre_len; 998 dst_left -= pre_len; 999 } 1000 1001 switch (f->key) { 1002 case FPRE_JOBNAME: { 1003 int ret; 1004 1005 ret = snprintf(dst, dst_left, "%s", jobname); 1006 if (ret < 0) 1007 break; 1008 dst += ret; 1009 dst_left -= ret; 1010 break; 1011 } 1012 case FPRE_JOBNUM: { 1013 int ret; 1014 1015 ret = snprintf(dst, dst_left, "%d", jobnum); 1016 if (ret < 0) 1017 break; 1018 dst += ret; 1019 dst_left -= ret; 1020 break; 1021 } 1022 case FPRE_FILENUM: { 1023 int ret; 1024 1025 ret = snprintf(dst, dst_left, "%d", filenum); 1026 if (ret < 0) 1027 break; 1028 dst += ret; 1029 dst_left -= ret; 1030 break; 1031 } 1032 default: 1033 assert(0); 1034 break; 1035 } 1036 1037 if (post_start) 1038 strncpy(dst, buf + post_start, dst_left); 1039 1040 strncpy(buf, copy, buf_size - 1); 1041 } while (1); 1042 } 1043 1044 return buf; 1045} 1046 1047int parse_dryrun(void) 1048{ 1049 return dump_cmdline || parse_only; 1050} 1051 1052/* 1053 * Adds a job to the list of things todo. Sanitizes the various options 1054 * to make sure we don't have conflicts, and initializes various 1055 * members of td. 1056 */ 1057static int add_job(struct thread_data *td, const char *jobname, int job_add_num, 1058 int recursed, int client_type) 1059{ 1060 unsigned int i; 1061 char fname[PATH_MAX]; 1062 int numjobs, file_alloced; 1063 struct thread_options *o = &td->o; 1064 char logname[PATH_MAX + 32]; 1065 1066 /* 1067 * the def_thread is just for options, it's not a real job 1068 */ 1069 if (td == &def_thread) 1070 return 0; 1071 1072 init_flags(td); 1073 1074 /* 1075 * if we are just dumping the output command line, don't add the job 1076 */ 1077 if (parse_dryrun()) { 1078 put_job(td); 1079 return 0; 1080 } 1081 1082 td->client_type = client_type; 1083 1084 if (profile_td_init(td)) 1085 goto err; 1086 1087 if (ioengine_load(td)) 1088 goto err; 1089 1090 if (o->odirect) 1091 td->io_ops->flags |= FIO_RAWIO; 1092 1093 file_alloced = 0; 1094 if (!o->filename && !td->files_index && !o->read_iolog_file) { 1095 file_alloced = 1; 1096 1097 if (o->nr_files == 1 && exists_and_not_file(jobname)) 1098 add_file(td, jobname, job_add_num, 0); 1099 else { 1100 for (i = 0; i < o->nr_files; i++) 1101 add_file(td, make_filename(fname, sizeof(fname), o, jobname, job_add_num, i), job_add_num, 0); 1102 } 1103 } 1104 1105 if (fixup_options(td)) 1106 goto err; 1107 1108 flow_init_job(td); 1109 1110 /* 1111 * IO engines only need this for option callbacks, and the address may 1112 * change in subprocesses. 1113 */ 1114 if (td->eo) 1115 *(struct thread_data **)td->eo = NULL; 1116 1117 if (td->io_ops->flags & FIO_DISKLESSIO) { 1118 struct fio_file *f; 1119 1120 for_each_file(td, f, i) 1121 f->real_file_size = -1ULL; 1122 } 1123 1124 td->mutex = fio_mutex_init(FIO_MUTEX_LOCKED); 1125 1126 td->ts.clat_percentiles = o->clat_percentiles; 1127 td->ts.percentile_precision = o->percentile_precision; 1128 memcpy(td->ts.percentile_list, o->percentile_list, sizeof(o->percentile_list)); 1129 1130 for (i = 0; i < DDIR_RWDIR_CNT; i++) { 1131 td->ts.clat_stat[i].min_val = ULONG_MAX; 1132 td->ts.slat_stat[i].min_val = ULONG_MAX; 1133 td->ts.lat_stat[i].min_val = ULONG_MAX; 1134 td->ts.bw_stat[i].min_val = ULONG_MAX; 1135 } 1136 td->ddir_seq_nr = o->ddir_seq_nr; 1137 1138 if ((o->stonewall || o->new_group) && prev_group_jobs) { 1139 prev_group_jobs = 0; 1140 groupid++; 1141 } 1142 1143 td->groupid = groupid; 1144 prev_group_jobs++; 1145 1146 if (setup_random_seeds(td)) { 1147 td_verror(td, errno, "init_random_state"); 1148 goto err; 1149 } 1150 1151 if (setup_rate(td)) 1152 goto err; 1153 1154 if (o->lat_log_file) { 1155 struct log_params p = { 1156 .td = td, 1157 .avg_msec = o->log_avg_msec, 1158 .log_type = IO_LOG_TYPE_LAT, 1159 .log_offset = o->log_offset, 1160 .log_gz = o->log_gz, 1161 .log_gz_store = o->log_gz_store, 1162 }; 1163 const char *suf; 1164 1165 if (p.log_gz_store) 1166 suf = "log.fz"; 1167 else 1168 suf = "log"; 1169 1170 snprintf(logname, sizeof(logname), "%s_lat.%s", 1171 o->lat_log_file, suf); 1172 setup_log(&td->lat_log, &p, logname); 1173 snprintf(logname, sizeof(logname), "%s_slat.%s", 1174 o->lat_log_file, suf); 1175 setup_log(&td->slat_log, &p, logname); 1176 snprintf(logname, sizeof(logname), "%s_clat.%s", 1177 o->lat_log_file, suf); 1178 setup_log(&td->clat_log, &p, logname); 1179 } 1180 if (o->bw_log_file) { 1181 struct log_params p = { 1182 .td = td, 1183 .avg_msec = o->log_avg_msec, 1184 .log_type = IO_LOG_TYPE_BW, 1185 .log_offset = o->log_offset, 1186 .log_gz = o->log_gz, 1187 .log_gz_store = o->log_gz_store, 1188 }; 1189 const char *suf; 1190 1191 if (p.log_gz_store) 1192 suf = "log.fz"; 1193 else 1194 suf = "log"; 1195 1196 snprintf(logname, sizeof(logname), "%s_bw.%s", 1197 o->bw_log_file, suf); 1198 setup_log(&td->bw_log, &p, logname); 1199 } 1200 if (o->iops_log_file) { 1201 struct log_params p = { 1202 .td = td, 1203 .avg_msec = o->log_avg_msec, 1204 .log_type = IO_LOG_TYPE_IOPS, 1205 .log_offset = o->log_offset, 1206 .log_gz = o->log_gz, 1207 .log_gz_store = o->log_gz_store, 1208 }; 1209 const char *suf; 1210 1211 if (p.log_gz_store) 1212 suf = "log.fz"; 1213 else 1214 suf = "log"; 1215 1216 snprintf(logname, sizeof(logname), "%s_iops.%s", 1217 o->iops_log_file, suf); 1218 setup_log(&td->iops_log, &p, logname); 1219 } 1220 1221 if (!o->name) 1222 o->name = strdup(jobname); 1223 1224 if (output_format == FIO_OUTPUT_NORMAL) { 1225 if (!job_add_num) { 1226 if (is_backend && !recursed) 1227 fio_server_send_add_job(td); 1228 1229 if (!(td->io_ops->flags & FIO_NOIO)) { 1230 char *c1, *c2, *c3, *c4; 1231 char *c5 = NULL, *c6 = NULL; 1232 1233 c1 = fio_uint_to_kmg(o->min_bs[DDIR_READ]); 1234 c2 = fio_uint_to_kmg(o->max_bs[DDIR_READ]); 1235 c3 = fio_uint_to_kmg(o->min_bs[DDIR_WRITE]); 1236 c4 = fio_uint_to_kmg(o->max_bs[DDIR_WRITE]); 1237 1238 if (!o->bs_is_seq_rand) { 1239 c5 = fio_uint_to_kmg(o->min_bs[DDIR_TRIM]); 1240 c6 = fio_uint_to_kmg(o->max_bs[DDIR_TRIM]); 1241 } 1242 1243 log_info("%s: (g=%d): rw=%s, ", td->o.name, 1244 td->groupid, 1245 ddir_str(o->td_ddir)); 1246 1247 if (o->bs_is_seq_rand) 1248 log_info("bs(seq/rand)=%s-%s/%s-%s, ", 1249 c1, c2, c3, c4); 1250 else 1251 log_info("bs=%s-%s/%s-%s/%s-%s, ", 1252 c1, c2, c3, c4, c5, c6); 1253 1254 log_info("ioengine=%s, iodepth=%u\n", 1255 td->io_ops->name, o->iodepth); 1256 1257 free(c1); 1258 free(c2); 1259 free(c3); 1260 free(c4); 1261 free(c5); 1262 free(c6); 1263 } 1264 } else if (job_add_num == 1) 1265 log_info("...\n"); 1266 } 1267 1268 /* 1269 * recurse add identical jobs, clear numjobs and stonewall options 1270 * as they don't apply to sub-jobs 1271 */ 1272 numjobs = o->numjobs; 1273 while (--numjobs) { 1274 struct thread_data *td_new = get_new_job(0, td, 1, jobname); 1275 1276 if (!td_new) 1277 goto err; 1278 1279 td_new->o.numjobs = 1; 1280 td_new->o.stonewall = 0; 1281 td_new->o.new_group = 0; 1282 1283 if (file_alloced) { 1284 if (td_new->files) { 1285 struct fio_file *f; 1286 for_each_file(td_new, f, i) { 1287 if (f->file_name) 1288 sfree(f->file_name); 1289 sfree(f); 1290 } 1291 free(td_new->files); 1292 td_new->files = NULL; 1293 } 1294 td_new->files_index = 0; 1295 td_new->files_size = 0; 1296 if (td_new->o.filename) { 1297 free(td_new->o.filename); 1298 td_new->o.filename = NULL; 1299 } 1300 } 1301 1302 if (add_job(td_new, jobname, numjobs, 1, client_type)) 1303 goto err; 1304 } 1305 1306 return 0; 1307err: 1308 put_job(td); 1309 return -1; 1310} 1311 1312/* 1313 * Parse as if 'o' was a command line 1314 */ 1315void add_job_opts(const char **o, int client_type) 1316{ 1317 struct thread_data *td, *td_parent; 1318 int i, in_global = 1; 1319 char jobname[32]; 1320 1321 i = 0; 1322 td_parent = td = NULL; 1323 while (o[i]) { 1324 if (!strncmp(o[i], "name", 4)) { 1325 in_global = 0; 1326 if (td) 1327 add_job(td, jobname, 0, 0, client_type); 1328 td = NULL; 1329 sprintf(jobname, "%s", o[i] + 5); 1330 } 1331 if (in_global && !td_parent) 1332 td_parent = get_new_job(1, &def_thread, 0, jobname); 1333 else if (!in_global && !td) { 1334 if (!td_parent) 1335 td_parent = &def_thread; 1336 td = get_new_job(0, td_parent, 0, jobname); 1337 } 1338 if (in_global) 1339 fio_options_parse(td_parent, (char **) &o[i], 1, 0); 1340 else 1341 fio_options_parse(td, (char **) &o[i], 1, 0); 1342 i++; 1343 } 1344 1345 if (td) 1346 add_job(td, jobname, 0, 0, client_type); 1347} 1348 1349static int skip_this_section(const char *name) 1350{ 1351 int i; 1352 1353 if (!nr_job_sections) 1354 return 0; 1355 if (!strncmp(name, "global", 6)) 1356 return 0; 1357 1358 for (i = 0; i < nr_job_sections; i++) 1359 if (!strcmp(job_sections[i], name)) 1360 return 0; 1361 1362 return 1; 1363} 1364 1365static int is_empty_or_comment(char *line) 1366{ 1367 unsigned int i; 1368 1369 for (i = 0; i < strlen(line); i++) { 1370 if (line[i] == ';') 1371 return 1; 1372 if (line[i] == '#') 1373 return 1; 1374 if (!isspace((int) line[i]) && !iscntrl((int) line[i])) 1375 return 0; 1376 } 1377 1378 return 1; 1379} 1380 1381/* 1382 * This is our [ini] type file parser. 1383 */ 1384int parse_jobs_ini(char *file, int is_buf, int stonewall_flag, int type) 1385{ 1386 unsigned int global; 1387 struct thread_data *td; 1388 char *string, *name; 1389 FILE *f; 1390 char *p; 1391 int ret = 0, stonewall; 1392 int first_sect = 1; 1393 int skip_fgets = 0; 1394 int inside_skip = 0; 1395 char **opts; 1396 int i, alloc_opts, num_opts; 1397 1398 if (is_buf) 1399 f = NULL; 1400 else { 1401 if (!strcmp(file, "-")) 1402 f = stdin; 1403 else 1404 f = fopen(file, "r"); 1405 1406 if (!f) { 1407 perror("fopen job file"); 1408 return 1; 1409 } 1410 } 1411 1412 string = malloc(4096); 1413 1414 /* 1415 * it's really 256 + small bit, 280 should suffice 1416 */ 1417 name = malloc(280); 1418 memset(name, 0, 280); 1419 1420 alloc_opts = 8; 1421 opts = malloc(sizeof(char *) * alloc_opts); 1422 num_opts = 0; 1423 1424 stonewall = stonewall_flag; 1425 do { 1426 /* 1427 * if skip_fgets is set, we already have loaded a line we 1428 * haven't handled. 1429 */ 1430 if (!skip_fgets) { 1431 if (is_buf) 1432 p = strsep(&file, "\n"); 1433 else 1434 p = fgets(string, 4096, f); 1435 if (!p) 1436 break; 1437 } 1438 1439 skip_fgets = 0; 1440 strip_blank_front(&p); 1441 strip_blank_end(p); 1442 1443 if (is_empty_or_comment(p)) 1444 continue; 1445 if (sscanf(p, "[%255[^\n]]", name) != 1) { 1446 if (inside_skip) 1447 continue; 1448 log_err("fio: option <%s> outside of [] job section\n", 1449 p); 1450 break; 1451 } 1452 1453 name[strlen(name) - 1] = '\0'; 1454 1455 if (skip_this_section(name)) { 1456 inside_skip = 1; 1457 continue; 1458 } else 1459 inside_skip = 0; 1460 1461 global = !strncmp(name, "global", 6); 1462 1463 if (dump_cmdline) { 1464 if (first_sect) 1465 log_info("fio "); 1466 if (!global) 1467 log_info("--name=%s ", name); 1468 first_sect = 0; 1469 } 1470 1471 td = get_new_job(global, &def_thread, 0, name); 1472 if (!td) { 1473 ret = 1; 1474 break; 1475 } 1476 1477 /* 1478 * Separate multiple job files by a stonewall 1479 */ 1480 if (!global && stonewall) { 1481 td->o.stonewall = stonewall; 1482 stonewall = 0; 1483 } 1484 1485 num_opts = 0; 1486 memset(opts, 0, alloc_opts * sizeof(char *)); 1487 1488 while (1) { 1489 if (is_buf) 1490 p = strsep(&file, "\n"); 1491 else 1492 p = fgets(string, 4096, f); 1493 if (!p) 1494 break; 1495 1496 if (is_empty_or_comment(p)) 1497 continue; 1498 1499 strip_blank_front(&p); 1500 1501 /* 1502 * new section, break out and make sure we don't 1503 * fgets() a new line at the top. 1504 */ 1505 if (p[0] == '[') { 1506 skip_fgets = 1; 1507 break; 1508 } 1509 1510 strip_blank_end(p); 1511 1512 if (num_opts == alloc_opts) { 1513 alloc_opts <<= 1; 1514 opts = realloc(opts, 1515 alloc_opts * sizeof(char *)); 1516 } 1517 1518 opts[num_opts] = strdup(p); 1519 num_opts++; 1520 } 1521 1522 ret = fio_options_parse(td, opts, num_opts, dump_cmdline); 1523 if (!ret) 1524 ret = add_job(td, name, 0, 0, type); 1525 else { 1526 log_err("fio: job %s dropped\n", name); 1527 put_job(td); 1528 } 1529 1530 for (i = 0; i < num_opts; i++) 1531 free(opts[i]); 1532 num_opts = 0; 1533 } while (!ret); 1534 1535 if (dump_cmdline) 1536 log_info("\n"); 1537 1538 i = 0; 1539 while (i < nr_job_sections) { 1540 free(job_sections[i]); 1541 i++; 1542 } 1543 1544 free(string); 1545 free(name); 1546 free(opts); 1547 if (!is_buf && f != stdin) 1548 fclose(f); 1549 return ret; 1550} 1551 1552static int fill_def_thread(void) 1553{ 1554 memset(&def_thread, 0, sizeof(def_thread)); 1555 1556 fio_getaffinity(getpid(), &def_thread.o.cpumask); 1557 def_thread.o.error_dump = 1; 1558 1559 /* 1560 * fill default options 1561 */ 1562 fio_fill_default_options(&def_thread); 1563 return 0; 1564} 1565 1566static void usage(const char *name) 1567{ 1568 printf("%s\n", fio_version_string); 1569 printf("%s [options] [job options] <job file(s)>\n", name); 1570 printf(" --debug=options\tEnable debug logging. May be one/more of:\n" 1571 "\t\t\tprocess,file,io,mem,blktrace,verify,random,parse,\n" 1572 "\t\t\tdiskutil,job,mutex,profile,time,net,rate\n"); 1573 printf(" --parse-only\t\tParse options only, don't start any IO\n"); 1574 printf(" --output\t\tWrite output to file\n"); 1575 printf(" --runtime\t\tRuntime in seconds\n"); 1576 printf(" --bandwidth-log\tGenerate per-job bandwidth logs\n"); 1577 printf(" --minimal\t\tMinimal (terse) output\n"); 1578 printf(" --output-format=x\tOutput format (terse,json,normal)\n"); 1579 printf(" --terse-version=x\tSet terse version output format to 'x'\n"); 1580 printf(" --version\t\tPrint version info and exit\n"); 1581 printf(" --help\t\tPrint this page\n"); 1582 printf(" --cpuclock-test\tPerform test/validation of CPU clock\n"); 1583 printf(" --crctest\t\tTest speed of checksum functions\n"); 1584 printf(" --cmdhelp=cmd\t\tPrint command help, \"all\" for all of" 1585 " them\n"); 1586 printf(" --enghelp=engine\tPrint ioengine help, or list" 1587 " available ioengines\n"); 1588 printf(" --enghelp=engine,cmd\tPrint help for an ioengine" 1589 " cmd\n"); 1590 printf(" --showcmd\t\tTurn a job file into command line options\n"); 1591 printf(" --eta=when\t\tWhen ETA estimate should be printed\n"); 1592 printf(" \t\tMay be \"always\", \"never\" or \"auto\"\n"); 1593 printf(" --eta-newline=time\tForce a new line for every 'time'"); 1594 printf(" period passed\n"); 1595 printf(" --status-interval=t\tForce full status dump every"); 1596 printf(" 't' period passed\n"); 1597 printf(" --readonly\t\tTurn on safety read-only checks, preventing" 1598 " writes\n"); 1599 printf(" --section=name\tOnly run specified section in job file\n"); 1600 printf(" --alloc-size=kb\tSet smalloc pool to this size in kb" 1601 " (def 1024)\n"); 1602 printf(" --warnings-fatal\tFio parser warnings are fatal\n"); 1603 printf(" --max-jobs=nr\t\tMaximum number of threads/processes to support\n"); 1604 printf(" --server=args\t\tStart a backend fio server\n"); 1605 printf(" --daemonize=pidfile\tBackground fio server, write pid to file\n"); 1606 printf(" --client=hostname\tTalk to remote backend fio server at hostname\n"); 1607 printf(" --idle-prof=option\tReport cpu idleness on a system or percpu basis\n" 1608 "\t\t\t(option=system,percpu) or run unit work\n" 1609 "\t\t\tcalibration only (option=calibrate)\n"); 1610#ifdef CONFIG_ZLIB 1611 printf(" --inflate-log=log\tInflate and output compressed log\n"); 1612#endif 1613 printf("\nFio was written by Jens Axboe <jens.axboe@oracle.com>"); 1614 printf("\n Jens Axboe <jaxboe@fusionio.com>"); 1615 printf("\n Jens Axboe <axboe@fb.com>\n"); 1616} 1617 1618#ifdef FIO_INC_DEBUG 1619struct debug_level debug_levels[] = { 1620 { .name = "process", 1621 .help = "Process creation/exit logging", 1622 .shift = FD_PROCESS, 1623 }, 1624 { .name = "file", 1625 .help = "File related action logging", 1626 .shift = FD_FILE, 1627 }, 1628 { .name = "io", 1629 .help = "IO and IO engine action logging (offsets, queue, completions, etc)", 1630 .shift = FD_IO, 1631 }, 1632 { .name = "mem", 1633 .help = "Memory allocation/freeing logging", 1634 .shift = FD_MEM, 1635 }, 1636 { .name = "blktrace", 1637 .help = "blktrace action logging", 1638 .shift = FD_BLKTRACE, 1639 }, 1640 { .name = "verify", 1641 .help = "IO verification action logging", 1642 .shift = FD_VERIFY, 1643 }, 1644 { .name = "random", 1645 .help = "Random generation logging", 1646 .shift = FD_RANDOM, 1647 }, 1648 { .name = "parse", 1649 .help = "Parser logging", 1650 .shift = FD_PARSE, 1651 }, 1652 { .name = "diskutil", 1653 .help = "Disk utility logging actions", 1654 .shift = FD_DISKUTIL, 1655 }, 1656 { .name = "job", 1657 .help = "Logging related to creating/destroying jobs", 1658 .shift = FD_JOB, 1659 }, 1660 { .name = "mutex", 1661 .help = "Mutex logging", 1662 .shift = FD_MUTEX 1663 }, 1664 { .name = "profile", 1665 .help = "Logging related to profiles", 1666 .shift = FD_PROFILE, 1667 }, 1668 { .name = "time", 1669 .help = "Logging related to time keeping functions", 1670 .shift = FD_TIME, 1671 }, 1672 { .name = "net", 1673 .help = "Network logging", 1674 .shift = FD_NET, 1675 }, 1676 { .name = "rate", 1677 .help = "Rate logging", 1678 .shift = FD_RATE, 1679 }, 1680 { .name = NULL, }, 1681}; 1682 1683static int set_debug(const char *string) 1684{ 1685 struct debug_level *dl; 1686 char *p = (char *) string; 1687 char *opt; 1688 int i; 1689 1690 if (!strcmp(string, "?") || !strcmp(string, "help")) { 1691 log_info("fio: dumping debug options:"); 1692 for (i = 0; debug_levels[i].name; i++) { 1693 dl = &debug_levels[i]; 1694 log_info("%s,", dl->name); 1695 } 1696 log_info("all\n"); 1697 return 1; 1698 } 1699 1700 while ((opt = strsep(&p, ",")) != NULL) { 1701 int found = 0; 1702 1703 if (!strncmp(opt, "all", 3)) { 1704 log_info("fio: set all debug options\n"); 1705 fio_debug = ~0UL; 1706 continue; 1707 } 1708 1709 for (i = 0; debug_levels[i].name; i++) { 1710 dl = &debug_levels[i]; 1711 found = !strncmp(opt, dl->name, strlen(dl->name)); 1712 if (!found) 1713 continue; 1714 1715 if (dl->shift == FD_JOB) { 1716 opt = strchr(opt, ':'); 1717 if (!opt) { 1718 log_err("fio: missing job number\n"); 1719 break; 1720 } 1721 opt++; 1722 fio_debug_jobno = atoi(opt); 1723 log_info("fio: set debug jobno %d\n", 1724 fio_debug_jobno); 1725 } else { 1726 log_info("fio: set debug option %s\n", opt); 1727 fio_debug |= (1UL << dl->shift); 1728 } 1729 break; 1730 } 1731 1732 if (!found) 1733 log_err("fio: debug mask %s not found\n", opt); 1734 } 1735 return 0; 1736} 1737#else 1738static int set_debug(const char *string) 1739{ 1740 log_err("fio: debug tracing not included in build\n"); 1741 return 1; 1742} 1743#endif 1744 1745static void fio_options_fill_optstring(void) 1746{ 1747 char *ostr = cmd_optstr; 1748 int i, c; 1749 1750 c = i = 0; 1751 while (l_opts[i].name) { 1752 ostr[c++] = l_opts[i].val; 1753 if (l_opts[i].has_arg == required_argument) 1754 ostr[c++] = ':'; 1755 else if (l_opts[i].has_arg == optional_argument) { 1756 ostr[c++] = ':'; 1757 ostr[c++] = ':'; 1758 } 1759 i++; 1760 } 1761 ostr[c] = '\0'; 1762} 1763 1764static int client_flag_set(char c) 1765{ 1766 int i; 1767 1768 i = 0; 1769 while (l_opts[i].name) { 1770 int val = l_opts[i].val; 1771 1772 if (c == (val & 0xff)) 1773 return (val & FIO_CLIENT_FLAG); 1774 1775 i++; 1776 } 1777 1778 return 0; 1779} 1780 1781static void parse_cmd_client(void *client, char *opt) 1782{ 1783 fio_client_add_cmd_option(client, opt); 1784} 1785 1786int parse_cmd_line(int argc, char *argv[], int client_type) 1787{ 1788 struct thread_data *td = NULL; 1789 int c, ini_idx = 0, lidx, ret = 0, do_exit = 0, exit_val = 0; 1790 char *ostr = cmd_optstr; 1791 void *pid_file = NULL; 1792 void *cur_client = NULL; 1793 int backend = 0; 1794 1795 /* 1796 * Reset optind handling, since we may call this multiple times 1797 * for the backend. 1798 */ 1799 optind = 1; 1800 1801 while ((c = getopt_long_only(argc, argv, ostr, l_opts, &lidx)) != -1) { 1802 if ((c & FIO_CLIENT_FLAG) || client_flag_set(c)) { 1803 parse_cmd_client(cur_client, argv[optind - 1]); 1804 c &= ~FIO_CLIENT_FLAG; 1805 } 1806 1807 switch (c) { 1808 case 'a': 1809 smalloc_pool_size = atoi(optarg); 1810 break; 1811 case 't': 1812 if (check_str_time(optarg, &def_timeout, 1)) { 1813 log_err("fio: failed parsing time %s\n", optarg); 1814 do_exit++; 1815 exit_val = 1; 1816 } 1817 break; 1818 case 'l': 1819 log_err("fio: --latency-log is deprecated. Use per-job latency log options.\n"); 1820 do_exit++; 1821 exit_val = 1; 1822 break; 1823 case 'b': 1824 write_bw_log = 1; 1825 break; 1826 case 'o': 1827 if (f_out && f_out != stdout) 1828 fclose(f_out); 1829 1830 f_out = fopen(optarg, "w+"); 1831 if (!f_out) { 1832 perror("fopen output"); 1833 exit(1); 1834 } 1835 f_err = f_out; 1836 break; 1837 case 'm': 1838 output_format = FIO_OUTPUT_TERSE; 1839 break; 1840 case 'F': 1841 if (!optarg) { 1842 log_err("fio: missing --output-format argument\n"); 1843 exit_val = 1; 1844 do_exit++; 1845 break; 1846 } 1847 if (!strcmp(optarg, "minimal") || 1848 !strcmp(optarg, "terse") || 1849 !strcmp(optarg, "csv")) 1850 output_format = FIO_OUTPUT_TERSE; 1851 else if (!strcmp(optarg, "json")) 1852 output_format = FIO_OUTPUT_JSON; 1853 else 1854 output_format = FIO_OUTPUT_NORMAL; 1855 break; 1856 case 'f': 1857 append_terse_output = 1; 1858 break; 1859 case 'h': 1860 did_arg = 1; 1861 if (!cur_client) { 1862 usage(argv[0]); 1863 do_exit++; 1864 } 1865 break; 1866 case 'c': 1867 did_arg = 1; 1868 if (!cur_client) { 1869 fio_show_option_help(optarg); 1870 do_exit++; 1871 } 1872 break; 1873 case 'i': 1874 did_arg = 1; 1875 if (!cur_client) { 1876 fio_show_ioengine_help(optarg); 1877 do_exit++; 1878 } 1879 break; 1880 case 's': 1881 did_arg = 1; 1882 dump_cmdline = 1; 1883 break; 1884 case 'r': 1885 read_only = 1; 1886 break; 1887 case 'v': 1888 did_arg = 1; 1889 if (!cur_client) { 1890 log_info("%s\n", fio_version_string); 1891 do_exit++; 1892 } 1893 break; 1894 case 'V': 1895 terse_version = atoi(optarg); 1896 if (!(terse_version == 2 || terse_version == 3 || 1897 terse_version == 4)) { 1898 log_err("fio: bad terse version format\n"); 1899 exit_val = 1; 1900 do_exit++; 1901 } 1902 break; 1903 case 'e': 1904 if (!strcmp("always", optarg)) 1905 eta_print = FIO_ETA_ALWAYS; 1906 else if (!strcmp("never", optarg)) 1907 eta_print = FIO_ETA_NEVER; 1908 break; 1909 case 'E': { 1910 long long t = 0; 1911 1912 if (str_to_decimal(optarg, &t, 0, NULL, 1)) { 1913 log_err("fio: failed parsing eta time %s\n", optarg); 1914 exit_val = 1; 1915 do_exit++; 1916 } 1917 eta_new_line = t; 1918 break; 1919 } 1920 case 'd': 1921 if (set_debug(optarg)) 1922 do_exit++; 1923 break; 1924 case 'P': 1925 did_arg = 1; 1926 parse_only = 1; 1927 break; 1928 case 'x': { 1929 size_t new_size; 1930 1931 if (!strcmp(optarg, "global")) { 1932 log_err("fio: can't use global as only " 1933 "section\n"); 1934 do_exit++; 1935 exit_val = 1; 1936 break; 1937 } 1938 new_size = (nr_job_sections + 1) * sizeof(char *); 1939 job_sections = realloc(job_sections, new_size); 1940 job_sections[nr_job_sections] = strdup(optarg); 1941 nr_job_sections++; 1942 break; 1943 } 1944#ifdef CONFIG_ZLIB 1945 case 'X': 1946 exit_val = iolog_file_inflate(optarg); 1947 did_arg++; 1948 do_exit++; 1949 break; 1950#endif 1951 case 'p': 1952 did_arg = 1; 1953 if (exec_profile) 1954 free(exec_profile); 1955 exec_profile = strdup(optarg); 1956 break; 1957 case FIO_GETOPT_JOB: { 1958 const char *opt = l_opts[lidx].name; 1959 char *val = optarg; 1960 1961 if (!strncmp(opt, "name", 4) && td) { 1962 ret = add_job(td, td->o.name ?: "fio", 0, 0, client_type); 1963 if (ret) 1964 goto out_free; 1965 td = NULL; 1966 did_arg = 1; 1967 } 1968 if (!td) { 1969 int is_section = !strncmp(opt, "name", 4); 1970 int global = 0; 1971 1972 if (!is_section || !strncmp(val, "global", 6)) 1973 global = 1; 1974 1975 if (is_section && skip_this_section(val)) 1976 continue; 1977 1978 td = get_new_job(global, &def_thread, 1, NULL); 1979 if (!td || ioengine_load(td)) { 1980 if (td) { 1981 put_job(td); 1982 td = NULL; 1983 } 1984 do_exit++; 1985 break; 1986 } 1987 fio_options_set_ioengine_opts(l_opts, td); 1988 } 1989 1990 if ((!val || !strlen(val)) && 1991 l_opts[lidx].has_arg == required_argument) { 1992 log_err("fio: option %s requires an argument\n", opt); 1993 ret = 1; 1994 } else 1995 ret = fio_cmd_option_parse(td, opt, val); 1996 1997 if (ret) { 1998 if (td) { 1999 put_job(td); 2000 td = NULL; 2001 } 2002 do_exit++; 2003 } 2004 2005 if (!ret && !strcmp(opt, "ioengine")) { 2006 free_ioengine(td); 2007 if (ioengine_load(td)) { 2008 put_job(td); 2009 td = NULL; 2010 do_exit++; 2011 break; 2012 } 2013 fio_options_set_ioengine_opts(l_opts, td); 2014 } 2015 break; 2016 } 2017 case FIO_GETOPT_IOENGINE: { 2018 const char *opt = l_opts[lidx].name; 2019 char *val = optarg; 2020 2021 if (!td) 2022 break; 2023 2024 ret = fio_cmd_ioengine_option_parse(td, opt, val); 2025 break; 2026 } 2027 case 'w': 2028 warnings_fatal = 1; 2029 break; 2030 case 'j': 2031 max_jobs = atoi(optarg); 2032 if (!max_jobs || max_jobs > REAL_MAX_JOBS) { 2033 log_err("fio: invalid max jobs: %d\n", max_jobs); 2034 do_exit++; 2035 exit_val = 1; 2036 } 2037 break; 2038 case 'S': 2039 did_arg = 1; 2040#ifndef CONFIG_NO_SHM 2041 if (nr_clients) { 2042 log_err("fio: can't be both client and server\n"); 2043 do_exit++; 2044 exit_val = 1; 2045 break; 2046 } 2047 if (optarg) 2048 fio_server_set_arg(optarg); 2049 is_backend = 1; 2050 backend = 1; 2051#else 2052 log_err("fio: client/server requires SHM support\n"); 2053 do_exit++; 2054 exit_val = 1; 2055#endif 2056 break; 2057 case 'D': 2058 if (pid_file) 2059 free(pid_file); 2060 pid_file = strdup(optarg); 2061 break; 2062 case 'I': 2063 if ((ret = fio_idle_prof_parse_opt(optarg))) { 2064 /* exit on error and calibration only */ 2065 did_arg = 1; 2066 do_exit++; 2067 if (ret == -1) 2068 exit_val = 1; 2069 } 2070 break; 2071 case 'C': 2072 did_arg = 1; 2073 if (is_backend) { 2074 log_err("fio: can't be both client and server\n"); 2075 do_exit++; 2076 exit_val = 1; 2077 break; 2078 } 2079 if (fio_client_add(&fio_client_ops, optarg, &cur_client)) { 2080 log_err("fio: failed adding client %s\n", optarg); 2081 do_exit++; 2082 exit_val = 1; 2083 break; 2084 } 2085 /* 2086 * If the next argument exists and isn't an option, 2087 * assume it's a job file for this client only. 2088 */ 2089 while (optind < argc) { 2090 if (!strncmp(argv[optind], "--", 2) || 2091 !strncmp(argv[optind], "-", 1)) 2092 break; 2093 2094 fio_client_add_ini_file(cur_client, argv[optind]); 2095 optind++; 2096 } 2097 break; 2098 case 'T': 2099 did_arg = 1; 2100 do_exit++; 2101 exit_val = fio_monotonic_clocktest(); 2102 break; 2103 case 'G': 2104 did_arg = 1; 2105 do_exit++; 2106 exit_val = fio_crctest(optarg); 2107 break; 2108 case 'L': { 2109 long long val; 2110 2111 if (check_str_time(optarg, &val, 0)) { 2112 log_err("fio: failed parsing time %s\n", optarg); 2113 do_exit++; 2114 exit_val = 1; 2115 break; 2116 } 2117 status_interval = val * 1000; 2118 break; 2119 } 2120 case '?': 2121 log_err("%s: unrecognized option '%s'\n", argv[0], 2122 argv[optind - 1]); 2123 default: 2124 do_exit++; 2125 exit_val = 1; 2126 break; 2127 } 2128 if (do_exit) 2129 break; 2130 } 2131 2132 if (do_exit && !(is_backend || nr_clients)) 2133 exit(exit_val); 2134 2135 if (nr_clients && fio_clients_connect()) 2136 exit(1); 2137 2138 if (is_backend && backend) 2139 return fio_start_server(pid_file); 2140 else if (pid_file) 2141 free(pid_file); 2142 2143 if (td) { 2144 if (!ret) { 2145 ret = add_job(td, td->o.name ?: "fio", 0, 0, client_type); 2146 if (ret) 2147 did_arg = 1; 2148 } 2149 } 2150 2151 while (!ret && optind < argc) { 2152 ini_idx++; 2153 ini_file = realloc(ini_file, ini_idx * sizeof(char *)); 2154 ini_file[ini_idx - 1] = strdup(argv[optind]); 2155 optind++; 2156 } 2157 2158out_free: 2159 if (pid_file) 2160 free(pid_file); 2161 2162 return ini_idx; 2163} 2164 2165int fio_init_options(void) 2166{ 2167 f_out = stdout; 2168 f_err = stderr; 2169 2170 fio_options_fill_optstring(); 2171 fio_options_dup_and_init(l_opts); 2172 2173 atexit(free_shm); 2174 2175 if (fill_def_thread()) 2176 return 1; 2177 2178 return 0; 2179} 2180 2181extern int fio_check_options(struct thread_options *); 2182 2183int parse_options(int argc, char *argv[]) 2184{ 2185 const int type = FIO_CLIENT_TYPE_CLI; 2186 int job_files, i; 2187 2188 if (fio_init_options()) 2189 return 1; 2190 if (fio_test_cconv(&def_thread.o)) 2191 log_err("fio: failed internal cconv test\n"); 2192 2193 job_files = parse_cmd_line(argc, argv, type); 2194 2195 if (job_files > 0) { 2196 for (i = 0; i < job_files; i++) { 2197 if (i && fill_def_thread()) 2198 return 1; 2199 if (nr_clients) { 2200 if (fio_clients_send_ini(ini_file[i])) 2201 return 1; 2202 free(ini_file[i]); 2203 } else if (!is_backend) { 2204 if (parse_jobs_ini(ini_file[i], 0, i, type)) 2205 return 1; 2206 free(ini_file[i]); 2207 } 2208 } 2209 } else if (nr_clients) { 2210 if (fill_def_thread()) 2211 return 1; 2212 if (fio_clients_send_ini(NULL)) 2213 return 1; 2214 } 2215 2216 free(ini_file); 2217 fio_options_free(&def_thread); 2218 filesetup_mem_free(); 2219 2220 if (!thread_number) { 2221 if (parse_dryrun()) 2222 return 0; 2223 if (exec_profile) 2224 return 0; 2225 if (is_backend || nr_clients) 2226 return 0; 2227 if (did_arg) 2228 return 0; 2229 2230 log_err("No jobs(s) defined\n\n"); 2231 2232 if (!did_arg) { 2233 usage(argv[0]); 2234 return 1; 2235 } 2236 2237 return 0; 2238 } 2239 2240 if (def_thread.o.gtod_offload) { 2241 fio_gtod_init(); 2242 fio_gtod_offload = 1; 2243 fio_gtod_cpu = def_thread.o.gtod_cpu; 2244 } 2245 2246 if (output_format == FIO_OUTPUT_NORMAL) 2247 log_info("%s\n", fio_version_string); 2248 2249 return 0; 2250} 2251 2252void options_default_fill(struct thread_options *o) 2253{ 2254 memcpy(o, &def_thread.o, sizeof(*o)); 2255} 2256