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