1 /* 2 * Disktest 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 * 20 * Please send e-mail to yardleyb (at) us.ibm.com if you have 21 * questions or comments. 22 * 23 * Project Website: TBD 24 * 25 * $Id: parse.c,v 1.8 2009/02/26 12:02:23 subrata_modak Exp $ 26 * 27 */ 28 #include <sys/types.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <stdarg.h> 32 #include <signal.h> 33 #include <time.h> 34 #include <errno.h> 35 #include <fcntl.h> 36 #include <string.h> 37 #include <ctype.h> 38 #include <sys/stat.h> 39 40 #include "globals.h" 41 #include "threading.h" 42 #include "main.h" 43 #include "usage.h" 44 #include "sfunc.h" 45 #include "parse.h" 46 47 int fill_cld_args(int argc, char **argv, child_args_t * args) 48 { 49 extern char *optarg; 50 extern int optind; 51 extern unsigned long glb_flags; 52 53 signed char c; 54 char *leftovers; 55 56 while ((c = 57 getopt(argc, argv, 58 "?a:A:B:cC:dD:E:f:Fh:I:K:L:m:M:nN:o:p:P:qQrR:s:S:t:T:wvV:z")) 59 != -1) { 60 switch (c) { 61 case ':': 62 pMsg(WARN, args, "Missing argument for perameter.\n"); 63 usage(); 64 return (-1); 65 case 'V': 66 #ifdef _DEBUG 67 if (optarg == NULL) { 68 pMsg(WARN, args, 69 "-%c option requires an argument.\n", c); 70 exit(1); 71 } 72 if (!isdigit(optarg[0])) { 73 pMsg(WARN, args, 74 "-%c argument is non numeric.\n", c); 75 exit(1); 76 } 77 gbl_dbg_lvl = atoi(optarg); 78 #else 79 pMsg(ERR, args, 80 "Debug code not compiled in, recompile with _DEBUG directive.\n", 81 c); 82 exit(1); 83 #endif 84 break; 85 case 'd': 86 glb_flags |= GLB_FLG_QUIET; 87 args->flags |= CLD_FLG_DUMP; 88 break; 89 case 'a': 90 if (optarg == NULL) { 91 pMsg(WARN, args, 92 "-%c option requires an argument.\n", c); 93 return (-1); 94 } 95 if (!isdigit(optarg[0])) { 96 pMsg(WARN, args, 97 "-%c arguments is non numeric.\n", c); 98 return (-1); 99 } 100 args->seed = (unsigned int)strtol(optarg, NULL, 0); 101 break; 102 case 'A': 103 if (optarg == NULL) { 104 pMsg(WARN, args, 105 "-%c option requires an argument.\n", c); 106 exit(1); 107 } 108 if (strchr(optarg, 'g')) { 109 glb_flags |= GLB_FLG_KILL; 110 } 111 if (strchr(optarg, 'c')) { 112 args->flags &= ~CLD_FLG_ALLDIE; 113 } 114 if (strchr(optarg, 'm')) { 115 args->flags |= CLD_FLG_ERR_MARK; 116 } 117 if (strchr(optarg, 'r')) { 118 args->flags &= ~CLD_FLG_ERR_REREAD; 119 } 120 if (strchr(optarg, 's')) { 121 args->flags &= ~CLD_FLG_LBA_SYNC; 122 } 123 if (strchr(optarg, 'S')) { 124 args->flags |= CLD_FLG_IO_SERIAL; 125 } 126 if (strchr(optarg, 'w')) { 127 args->flags |= CLD_FLG_WRITE_ONCE; 128 } 129 if (strchr(optarg, 'W')) { 130 args->flags |= CLD_FLG_UNIQ_WRT; 131 } 132 if (strchr(optarg, 't')) { 133 args->flags |= CLD_FLG_TMO_ERROR; 134 } 135 break; 136 case 'q': 137 glb_flags |= GLB_FLG_QUIET; 138 break; 139 case 'Q': 140 glb_flags |= GLB_FLG_SUPRESS; 141 break; 142 case 'v': 143 pMsg(INFO, args, "Version %s\n", VER_STR); 144 exit(0); 145 case 'p': 146 if (optarg == NULL) { 147 pMsg(WARN, args, 148 "-%c option requires an argument.\n", c); 149 return (-1); 150 } 151 if (args->flags & (CLD_FLG_LINEAR | CLD_FLG_RANDOM)) { 152 pMsg(WARN, args, 153 "Only one seek type, -p, can be specified.\n"); 154 return (-1); 155 } 156 /* seek pattern type */ 157 if (strchr(optarg, 'L')) 158 args->flags |= CLD_FLG_LINEAR; 159 else if (strchr(optarg, 'l')) 160 args->flags |= 161 (CLD_FLG_LINEAR | CLD_FLG_NTRLVD); 162 else if (strchr(optarg, 'R')) 163 args->flags |= CLD_FLG_RANDOM; 164 else if (strchr(optarg, 'r')) 165 args->flags |= 166 (CLD_FLG_RANDOM | CLD_FLG_NTRLVD); 167 else { 168 pMsg(WARN, args, "Unknown Seek pattern\n"); 169 usage(); 170 return (-1); 171 } 172 if (strchr(optarg, 'U') || strchr(optarg, 'u')) 173 if ((args->flags & (CLD_FLG_LINEAR)) && 174 !(args->flags & CLD_FLG_LUND)) 175 args->flags |= CLD_FLG_LUNU; 176 if (strchr(optarg, 'D') || strchr(optarg, 'd')) 177 if ((args->flags & (CLD_FLG_LINEAR)) && 178 !(args->flags & CLD_FLG_LUNU)) 179 args->flags |= CLD_FLG_LUND; 180 break; 181 case 'B': 182 if (!isdigit(optarg[0])) { 183 pMsg(WARN, args, 184 "-%c arguments is non numeric.\n", c); 185 return (-1); 186 } 187 if (strchr(optarg, ':') != NULL) { /* we are given a range of transfer sizes */ 188 args->flags |= CLD_FLG_RTRSIZ; 189 args->ltrsiz = strtoul(optarg, &leftovers, 10); 190 if (leftovers == strchr(leftovers, 'k')) { /* first value had a 'k' */ 191 args->ltrsiz *= 2; 192 leftovers++; 193 } else if (leftovers == strchr(leftovers, 'm')) { /* first value had a 'm' */ 194 args->ltrsiz *= (2 * 1024); 195 leftovers++; 196 } else { 197 if (args->ltrsiz > 256) 198 args->ltrsiz /= BLK_SIZE; 199 } 200 if (!isdigit(leftovers[1])) { 201 pMsg(WARN, args, 202 "-%c arguments is non numeric.\n", 203 c); 204 return (-1); 205 } 206 args->htrsiz = 207 atol((char *)strchr(leftovers, ':') + 1); 208 if ((strchr(leftovers, 'k')) != NULL) { /* second value had a 'k' */ 209 args->htrsiz *= 2; 210 } else if ((strchr(leftovers, 'm')) != NULL) { /* second value had a 'm' */ 211 args->htrsiz *= (2 * 1024); 212 } else { 213 if (args->htrsiz > 256) 214 args->htrsiz /= BLK_SIZE; 215 } 216 } else { /* only a single value given for transfer size */ 217 args->ltrsiz = atoi(optarg); 218 if (strchr(optarg, 'k')) { 219 args->ltrsiz *= 2; 220 } else if (strchr(optarg, 'm')) { 221 args->ltrsiz *= (2 * 1024); 222 } else { 223 if (args->ltrsiz > 256) 224 args->ltrsiz /= BLK_SIZE; 225 } 226 args->htrsiz = args->ltrsiz; 227 } 228 #ifdef _DEBUG 229 PDBG5(DBUG, args, "Parsed Transfer size: %ld\n", 230 args->htrsiz); 231 #endif 232 break; 233 case 'c': 234 if (args->flags & CLD_FLG_PTYPS) { 235 pMsg(WARN, args, 236 "Please specify only one pattern type\n"); 237 usage(); 238 return (-1); 239 } 240 args->flags |= CLD_FLG_CPTYPE; 241 break; 242 case 'n': 243 if (args->flags & CLD_FLG_PTYPS) { 244 pMsg(WARN, args, 245 "Please specify only one pattern type\n"); 246 usage(); 247 return (-1); 248 } 249 args->flags |= CLD_FLG_LPTYPE; 250 break; 251 case 'f': 252 if (optarg == NULL) { 253 pMsg(WARN, args, 254 "-%c option requires an argument.\n", c); 255 return (-1); 256 } 257 if (args->flags & CLD_FLG_PTYPS) { 258 pMsg(WARN, args, 259 "Please specify only one pattern type\n"); 260 usage(); 261 return (-1); 262 } 263 args->pattern = my_strtofft(optarg); 264 args->flags |= CLD_FLG_FPTYPE; 265 break; 266 case 'F': 267 /* the filespec is a list of filespecs in a file */ 268 args->flags |= CLD_FLG_FSLIST; 269 break; 270 case 'z': 271 if (args->flags & CLD_FLG_PTYPS) { 272 pMsg(WARN, args, 273 "Please specify only one pattern type\n"); 274 usage(); 275 return (-1); 276 } 277 args->flags |= CLD_FLG_RPTYPE; 278 break; 279 case 'h': 280 if (optarg == NULL) { 281 pMsg(WARN, args, 282 "-%c option requires an argument.\n", c); 283 return (-1); 284 } 285 if (!isdigit(optarg[0])) { 286 pMsg(WARN, args, 287 "-%c arguments is non numeric.\n", c); 288 usage(); 289 return (-1); 290 } 291 args->flags |= CLD_FLG_HBEAT; 292 args->hbeat = atoi(optarg); 293 if (strchr(optarg, 'm')) { /* multiply by sec */ 294 args->hbeat *= 60; 295 } else if (strchr(optarg, 'h')) { /* multiply sec*min */ 296 args->hbeat *= (time_t) (60 * 60); 297 } else if (strchr(optarg, 'd')) { /* multiply by sec*min*hours */ 298 args->hbeat *= (time_t) (60 * 60 * 24); 299 } 300 break; 301 case 'D': 302 if (optarg == NULL) { 303 pMsg(WARN, args, 304 "-%c option requires an argument.\n", c); 305 return (-1); 306 } 307 if (!isdigit(optarg[0])) { 308 pMsg(WARN, args, 309 "-%c arguments is non numeric.\n", c); 310 usage(); 311 return (-1); 312 } 313 args->rperc = atoi(optarg); 314 args->wperc = atoi((char *)(strchr(optarg, ':') + 1)); 315 args->flags |= CLD_FLG_DUTY; 316 break; 317 case 'r': 318 args->flags |= CLD_FLG_R; 319 break; 320 case 'w': 321 args->flags |= CLD_FLG_W; 322 break; 323 case 'o': 324 if (optarg == NULL) { 325 pMsg(WARN, args, 326 "-%c option requires an argument.\n", c); 327 return (-1); 328 } 329 args->offset = atol(optarg); 330 args->flags |= CLD_FLG_OFFSET; 331 break; 332 case 'R': 333 if (optarg == NULL) { 334 pMsg(WARN, args, 335 "-%c option requires an argument.\n", c); 336 return (-1); 337 } 338 if (strchr(optarg, ':') != NULL) { /* we are given a retry delay */ 339 args->retries = strtol(optarg, &leftovers, 10); 340 args->retry_delay = 341 (time_t) atol((char *)strchr(leftovers, ':') 342 + 1); 343 } else { /* only a retry count given */ 344 args->retries = atoi(optarg); 345 } 346 break; 347 case 'M': 348 if (optarg == NULL) { 349 pMsg(WARN, args, 350 "-%c option requires an argument.\n", c); 351 return (-1); 352 } 353 args->flags |= CLD_FLG_ALT_MARK; 354 args->alt_mark = my_strtofft(optarg); 355 break; 356 case 'm': 357 args->flags |= CLD_FLG_MBLK; 358 if (optarg == NULL) { 359 pMsg(WARN, args, 360 "-%c option requires an argument.\n", c); 361 return (-1); 362 } 363 if (strchr(optarg, 'l')) { /* returns NULL if char is not found */ 364 args->flags |= CLD_FLG_MRK_LBA; 365 } 366 if (strchr(optarg, 'p')) { 367 args->flags |= CLD_FLG_MRK_PASS; 368 } 369 if (strchr(optarg, 't')) { 370 args->flags |= CLD_FLG_MRK_TIME; 371 } 372 if (strchr(optarg, 's')) { 373 args->flags |= CLD_FLG_MRK_SEED; 374 } 375 if (strchr(optarg, 'h')) { 376 args->flags |= CLD_FLG_MRK_HOST; 377 } 378 if (strchr(optarg, 'f')) { 379 args->flags |= CLD_FLG_MRK_TARGET; 380 } 381 if (strchr(optarg, 'a')) { 382 args->flags |= CLD_FLG_MRK_ALL; 383 } 384 if (!strchr(optarg, 'l') && 385 !strchr(optarg, 'p') && 386 !strchr(optarg, 't') && 387 !strchr(optarg, 's') && 388 !strchr(optarg, 'h') && 389 !strchr(optarg, 'f') && !strchr(optarg, 'a')) { 390 pMsg(WARN, args, 391 "Unknown header mark option\n"); 392 return (-1); 393 } 394 break; 395 case 'E': 396 if (optarg == NULL) { 397 pMsg(WARN, args, 398 "-%c option requires an argument.\n", c); 399 return (-1); 400 } 401 if (!isdigit(optarg[0])) { 402 pMsg(WARN, args, 403 "-%c arguments are non numeric.\n", c); 404 usage(); 405 return (-1); 406 } 407 args->flags |= CLD_FLG_CMPR; 408 args->cmp_lng = strtol(optarg, NULL, 0); 409 if (strchr(optarg, 'k')) { /* multiply by 2^10 */ 410 args->cmp_lng <<= 10; 411 } else if (strchr(optarg, 'K')) { /* multiply 10^3 */ 412 args->cmp_lng *= 1000; 413 } else if (strchr(optarg, 'm')) { /* multiply by 2^20 */ 414 args->cmp_lng <<= 20; 415 } else if (strchr(optarg, 'M')) { /* multiply by 10^6 */ 416 args->cmp_lng *= 1000000; 417 } 418 break; 419 case 'N': 420 if (optarg == NULL) { 421 pMsg(WARN, args, 422 "-%c option requires an argument.\n", c); 423 return (-1); 424 } 425 if (!isdigit(optarg[0])) { 426 pMsg(WARN, args, 427 "-%c arguments are non numeric.\n", c); 428 return (-1); 429 } 430 args->flags |= CLD_FLG_VSIZ; 431 args->vsiz = my_strtofft(optarg); 432 if (strchr(optarg, 'k')) { /* multiply by 2^10 */ 433 args->vsiz <<= 10; 434 } else if (strchr(optarg, 'K')) { /* multiply 10^3 */ 435 args->vsiz *= 1000; 436 } else if (strchr(optarg, 'm')) { /* multiply by 2^20 */ 437 args->vsiz <<= 20; 438 } else if (strchr(optarg, 'M')) { /* multiply by 10^6 */ 439 args->vsiz *= 1000000; 440 } else if (strchr(optarg, 'g')) { /* multiply by 2^30 */ 441 args->vsiz <<= 30; 442 } else if (strchr(optarg, 'G')) { /* multiply by 10^9 */ 443 args->vsiz *= 1000000000; 444 } 445 break; 446 case 'I': 447 if (optarg == NULL) { 448 pMsg(WARN, args, 449 "-%c option requires an argument.\n", c); 450 return (-1); 451 } 452 if (strchr(optarg, 'R') || strchr(optarg, 'r')) { 453 if (!(args->flags & CLD_FLG_BLK) && 454 !(args->flags & CLD_FLG_FILE)) { 455 args->flags |= CLD_FLG_RAW; 456 } else { 457 pMsg(WARN, args, 458 "Can only specify one IO type\n"); 459 return (-1); 460 } 461 } 462 if (strchr(optarg, 'B') || strchr(optarg, 'b')) { 463 if (!(args->flags & CLD_FLG_RAW) && 464 !(args->flags & CLD_FLG_FILE)) { 465 args->flags |= CLD_FLG_BLK; 466 } else { 467 pMsg(WARN, args, 468 "Can only specify one IO type\n"); 469 return (-1); 470 } 471 } 472 if (strchr(optarg, 'F') || strchr(optarg, 'f')) { 473 if (!(args->flags & CLD_FLG_RAW) && 474 !(args->flags & CLD_FLG_BLK)) { 475 args->flags |= CLD_FLG_FILE; 476 } else { 477 pMsg(WARN, args, 478 "Can only specify one IO type\n"); 479 return (-1); 480 } 481 } 482 if (strchr(optarg, 'D') || strchr(optarg, 'd')) { 483 args->flags |= CLD_FLG_DIRECT; 484 } 485 if (strchr(optarg, 's')) { 486 args->sync_interval = 487 strtoul((char *)strchr(optarg, 's') + 1, 488 NULL, 10); 489 #ifdef _DEBUG 490 PDBG3(DBUG, args, "Parsed sync interval: %ld\n", 491 args->sync_interval); 492 #endif 493 if ((args->flags & CLD_FLG_DIRECT)) { 494 pMsg(ERR, args, 495 "Can't specify sync with Direct IO\n"); 496 return (-1); 497 } 498 args->flags |= CLD_FLG_WFSYNC; 499 } 500 break; 501 case 't': 502 if (optarg == NULL) { 503 pMsg(WARN, args, 504 "-%c option requires an argument.\n", c); 505 return (-1); 506 } 507 508 if (strchr(optarg, ':') != NULL) { /* we are given a option for delay & timeout */ 509 args->delayTimeMin = 510 strtoul(optarg, &leftovers, 10); 511 /* check to see if we have one or more then one ':' */ 512 if ((char *)strchr(optarg, ':') == 513 (char *)strrchr(optarg, ':')) { 514 /* only one ':', assume no random delayTime, and ioTimeout */ 515 args->delayTimeMax = args->delayTimeMin; 516 args->ioTimeout = 517 (time_t) atol((char *) 518 strchr(leftovers, 519 ':') + 1); 520 } else { 521 /* more then one ':', assume random delayTime, and ioTimeout */ 522 args->delayTimeMax = 523 strtoul(leftovers + 1, &leftovers, 524 10); 525 args->ioTimeout = 526 (time_t) atol((char *) 527 strchr(leftovers, 528 ':') + 1); 529 } 530 if (strchr(leftovers, 'm')) { /* multiply by sec */ 531 args->ioTimeout *= 60; 532 } else if (strchr(leftovers, 'h')) { /* multiply sec*min */ 533 args->ioTimeout *= (time_t) (60 * 60); 534 } else if (strchr(leftovers, 'd')) { /* multiply by sec*min*hours */ 535 args->ioTimeout *= 536 (time_t) (60 * 60 * 24); 537 } 538 } else { 539 args->delayTimeMin = 540 strtoul(optarg, NULL, 10); 541 args->delayTimeMax = args->delayTimeMin; 542 } 543 break; 544 case 'T': 545 if (optarg == NULL) { 546 pMsg(WARN, args, 547 "-%c option requires an argument.\n", c); 548 return (-1); 549 } 550 args->run_time = atoi(optarg); 551 args->flags |= CLD_FLG_TMD; 552 if (strchr(optarg, 'm')) { /* multiply by sec */ 553 args->run_time *= 60; 554 } else if (strchr(optarg, 'h')) { /* multiply sec*min */ 555 args->run_time *= (time_t) (60 * 60); 556 } else if (strchr(optarg, 'd')) { /* multiply by sec*min*hours */ 557 args->run_time *= (time_t) (60 * 60 * 24); 558 } 559 break; 560 case 'L': 561 if (optarg == NULL) { 562 pMsg(WARN, args, 563 "-%c option requires an argument.\n", c); 564 return (-1); 565 } 566 args->seeks = atoi(optarg); 567 args->flags |= CLD_FLG_SKS; 568 if (strchr(optarg, 'k')) { /* multiply by 2^10 */ 569 args->seeks <<= 10; 570 } else if (strchr(optarg, 'K')) { /* multiply 10^3 */ 571 args->seeks *= 1000; 572 } else if (strchr(optarg, 'm')) { /* multiply by 2^20 */ 573 args->seeks <<= 20; 574 } else if (strchr(optarg, 'M')) { /* multiply by 10^6 */ 575 args->seeks *= 1000000; 576 } else if (strchr(optarg, 'g')) { /* multiply by 2^30 */ 577 args->seeks <<= 30; 578 } else if (strchr(optarg, 'G')) { /* multiply by 10^9 */ 579 args->seeks *= 1000000000; 580 } 581 break; 582 case 'C': 583 if (optarg == NULL) { 584 pMsg(WARN, args, 585 "-%c option requires an argument.\n", c); 586 return (-1); 587 } 588 if (!isdigit(optarg[0])) { 589 pMsg(WARN, args, 590 "-%c arguments is non numeric.\n", c); 591 usage(); 592 return (-1); 593 } 594 args->flags |= CLD_FLG_CYC; 595 args->cycles = atol(optarg); 596 break; 597 case 'K': 598 if (optarg == NULL) { 599 pMsg(WARN, args, 600 "-%c option requires an argument.\n", c); 601 return (-1); 602 } 603 if (!isdigit(optarg[0])) { 604 pMsg(WARN, args, 605 "-%c arguments is non numeric.\n", c); 606 usage(); 607 return (-1); 608 } 609 if (atoi(optarg) > MAX_THREADS) { 610 pMsg(WARN, args, 611 "%u exceeds max of %u threads.\n", 612 atoi(optarg), MAX_THREADS); 613 return (-1); 614 } 615 args->t_kids = atoi(optarg); 616 break; 617 case 'P': 618 if (optarg == NULL) { 619 pMsg(WARN, args, 620 "-%c option requires an argument.\n", c); 621 return (-1); 622 } 623 if (strchr(optarg, 'X')) { /* returns NULL if char is not found */ 624 args->flags |= CLD_FLG_XFERS; 625 } 626 if (strchr(optarg, 'T')) { 627 args->flags |= CLD_FLG_TPUTS; 628 } 629 if (strchr(optarg, 'P')) { 630 glb_flags |= GLB_FLG_PERFP; 631 } 632 if (strchr(optarg, 'R')) { 633 args->flags |= CLD_FLG_RUNT; 634 } 635 if (strchr(optarg, 'C')) { 636 args->flags |= CLD_FLG_PCYC; 637 } 638 if (strchr(optarg, 'A')) { 639 args->flags |= CLD_FLG_PRFTYPS; 640 } 641 if (!strchr(optarg, 'P') && 642 !strchr(optarg, 'A') && 643 !strchr(optarg, 'X') && 644 !strchr(optarg, 'R') && 645 !strchr(optarg, 'C') && !strchr(optarg, 'T')) { 646 pMsg(WARN, args, 647 "Unknown performance option\n"); 648 return (-1); 649 } 650 break; 651 case 'S': 652 if (!isdigit((int)optarg[0])) { 653 pMsg(WARN, args, 654 "-%c arguments is non numeric.\n", c); 655 return (-1); 656 } 657 args->flags |= CLD_FLG_BLK_RNG; 658 if (strchr(optarg, ':') != NULL) { /* we are given a range */ 659 args->start_blk = 660 (OFF_T) strtoul(optarg, &leftovers, 0); 661 if (leftovers == strchr(leftovers, 'k')) { /* multiply by 2^10 */ 662 args->start_blk <<= 10; 663 leftovers++; /* at the ':' */ 664 } else if (leftovers == strchr(leftovers, 'K')) { /* multiply 10^3 */ 665 args->start_blk *= 1000; 666 leftovers++; /* at the ':' */ 667 } else if (leftovers == strchr(leftovers, 'm')) { /* multiply by 2^20 */ 668 args->start_blk <<= 20; 669 leftovers++; /* at the ':' */ 670 } else if (leftovers == strchr(leftovers, 'M')) { /* multiply by 10^6 */ 671 args->start_blk *= 1000000; 672 leftovers++; /* at the ':' */ 673 } else if (leftovers == strchr(leftovers, 'g')) { /* multiply by 2^30 */ 674 args->start_blk <<= 30; 675 leftovers++; /* at the ':' */ 676 } else if (leftovers == strchr(leftovers, 'G')) { /* multiply by 10^9 */ 677 args->start_blk *= 1000000000; 678 leftovers++; /* at the ':' */ 679 } 680 leftovers++; /* should be at the next value */ 681 if (!isdigit((int)leftovers[0])) { 682 pMsg(WARN, args, 683 "-%c arguments is non numeric.\n", 684 c); 685 return (-1); 686 } 687 args->stop_blk = 688 (OFF_T) strtoul(leftovers, &leftovers, 0); 689 if (leftovers == strchr(leftovers, 'k')) { /* multiply by 2^10 */ 690 args->stop_blk <<= 10; 691 } else if (leftovers == strchr(leftovers, 'K')) { /* multiply 10^3 */ 692 args->stop_blk *= 1000; 693 } else if (leftovers == strchr(leftovers, 'm')) { /* multiply by 2^20 */ 694 args->stop_blk <<= 20; 695 } else if (leftovers == strchr(leftovers, 'M')) { /* multiply by 10^6 */ 696 args->stop_blk *= 1000000; 697 } else if (leftovers == strchr(leftovers, 'g')) { /* multiply by 2^30 */ 698 args->stop_blk <<= 30; 699 } else if (leftovers == strchr(leftovers, 'G')) { /* multiply by 10^9 */ 700 args->stop_blk *= 1000000000; 701 } 702 } else { /* only a single value given */ 703 args->start_blk = 704 (OFF_T) strtoul(optarg, &leftovers, 0); 705 if (leftovers == strchr(leftovers, 'k')) { /* multiply by 2^10 */ 706 args->start_blk <<= 10; 707 } else if (leftovers == strchr(leftovers, 'K')) { /* multiply 10^3 */ 708 args->start_blk *= 1000; 709 } else if (leftovers == strchr(leftovers, 'm')) { /* multiply by 2^20 */ 710 args->start_blk <<= 20; 711 } else if (leftovers == strchr(leftovers, 'M')) { /* multiply by 10^6 */ 712 args->start_blk *= 1000000; 713 } else if (leftovers == strchr(leftovers, 'g')) { /* multiply by 2^30 */ 714 args->start_blk <<= 30; 715 } else if (leftovers == strchr(leftovers, 'G')) { /* multiply by 10^9 */ 716 args->start_blk *= 1000000000; 717 } 718 } 719 break; 720 case 's': 721 if (!isdigit((int)optarg[0])) { 722 pMsg(WARN, args, 723 "-%c argument is non numeric.\n", c); 724 return (-1); 725 } 726 args->flags |= CLD_FLG_LBA_RNG; 727 if (strchr(optarg, ':') != NULL) { /* we are given a range */ 728 args->start_lba = 729 (OFF_T) strtoul(optarg, &leftovers, 0); 730 if (leftovers == strchr(leftovers, 'k')) { /* multiply by 2^10 */ 731 args->start_lba <<= 10; 732 leftovers++; /* at the ':' */ 733 } else if (leftovers == strchr(leftovers, 'K')) { /* multiply 10^3 */ 734 args->start_lba *= 1000; 735 leftovers++; /* at the ':' */ 736 } else if (leftovers == strchr(leftovers, 'm')) { /* multiply by 2^20 */ 737 args->start_lba <<= 20; 738 leftovers++; /* at the ':' */ 739 } else if (leftovers == strchr(leftovers, 'M')) { /* multiply by 10^6 */ 740 args->start_lba *= 1000000; 741 leftovers++; /* at the ':' */ 742 } else if (leftovers == strchr(leftovers, 'g')) { /* multiply by 2^30 */ 743 args->start_lba <<= 30; 744 leftovers++; /* at the ':' */ 745 } else if (leftovers == strchr(leftovers, 'G')) { /* multiply by 10^9 */ 746 args->start_lba *= 1000000000; 747 leftovers++; /* at the ':' */ 748 } 749 leftovers++; /* should be at the next value */ 750 if (!isdigit((int)leftovers[0])) { 751 pMsg(WARN, args, 752 "-%c second argument is non numeric.\n", 753 c); 754 return (-1); 755 } 756 args->stop_lba = 757 (OFF_T) strtoul(leftovers, &leftovers, 0); 758 if (leftovers == strchr(leftovers, 'k')) { /* multiply by 2^10 */ 759 args->stop_lba <<= 10; 760 } else if (leftovers == strchr(leftovers, 'K')) { /* multiply 10^3 */ 761 args->stop_lba *= 1000; 762 } else if (leftovers == strchr(leftovers, 'm')) { /* multiply by 2^20 */ 763 args->stop_lba <<= 20; 764 } else if (leftovers == strchr(leftovers, 'M')) { /* multiply by 10^6 */ 765 args->stop_lba *= 1000000; 766 } else if (leftovers == strchr(leftovers, 'g')) { /* multiply by 2^30 */ 767 args->stop_lba <<= 30; 768 } else if (leftovers == strchr(leftovers, 'G')) { /* multiply by 10^9 */ 769 args->stop_lba *= 1000000000; 770 } 771 } else { /* only a single value given */ 772 args->start_lba = 773 (OFF_T) strtoul(optarg, &leftovers, 0); 774 if (leftovers == strchr(leftovers, 'k')) { /* multiply by 2^10 */ 775 args->start_lba <<= 10; 776 } else if (leftovers == strchr(leftovers, 'K')) { /* multiply 10^3 */ 777 args->start_lba *= 1000; 778 } else if (leftovers == strchr(leftovers, 'm')) { /* multiply by 2^20 */ 779 args->start_lba <<= 20; 780 } else if (leftovers == strchr(leftovers, 'M')) { /* multiply by 10^6 */ 781 args->start_lba *= 1000000; 782 } else if (leftovers == strchr(leftovers, 'g')) { /* multiply by 2^30 */ 783 args->start_lba <<= 30; 784 } else if (leftovers == strchr(leftovers, 'G')) { /* multiply by 10^9 */ 785 args->start_lba *= 1000000000; 786 } 787 } 788 break; 789 case '?': 790 default: 791 usage(); 792 return (-1); 793 } 794 } 795 if (argv[optind] == NULL) { 796 pMsg(WARN, args, "Unspecified target.\n"); 797 return (-1); 798 } 799 strncpy(args->device, argv[optind], (DEV_NAME_LEN - 1)); 800 return 0; 801 } 802 803 int make_assumptions(child_args_t * args) 804 { 805 char TmpStr[80]; 806 struct stat stat_buf; 807 int rv; 808 809 if (!(args->flags & CLD_FLG_IOTYPS)) { 810 /* use stat to get file properties, and use to set -I */ 811 rv = stat(args->device, &stat_buf); 812 if (0 == rv) { 813 if (IS_FILE(stat_buf.st_mode)) { 814 strncat(args->argstr, "(-I f) ", 815 (MAX_ARG_LEN - 1) - 816 strlen(args->argstr)); 817 args->flags |= CLD_FLG_FILE; 818 } else if (IS_BLK(stat_buf.st_mode)) { 819 strncat(args->argstr, "(-I b) ", 820 (MAX_ARG_LEN - 1) - 821 strlen(args->argstr)); 822 args->flags |= CLD_FLG_BLK; 823 #ifndef WINDOWS 824 } else if (S_ISCHR(stat_buf.st_mode)) { 825 strncat(args->argstr, "(-I r) ", 826 (MAX_ARG_LEN - 1) - 827 strlen(args->argstr)); 828 args->flags |= CLD_FLG_RAW; 829 #endif 830 } 831 } else { 832 pMsg(WARN, args, 833 "Can't get status on %s, defaulting to file, errno = %d\n", 834 args->device, GETLASTERROR()); 835 strncat(args->argstr, "(-I f) ", 836 (MAX_ARG_LEN - 1) - strlen(args->argstr)); 837 args->flags |= CLD_FLG_FILE; 838 } 839 } 840 if ((args->flags & CLD_FLG_WFSYNC) && (0 == args->sync_interval)) { 841 pMsg(INFO, args, 842 "Sync interval set to zero, assuming interval of 1.\n"); 843 args->sync_interval = 1; 844 } 845 846 if (args->ltrsiz <= 0) { 847 sprintf(TmpStr, "(-B %d) ", TRSIZ * BLK_SIZE); 848 strncat(args->argstr, TmpStr, 849 (MAX_ARG_LEN - 1) - strlen(args->argstr)); 850 args->ltrsiz = TRSIZ; 851 args->htrsiz = TRSIZ; 852 } 853 if (args->flags & CLD_FLG_LBA_RNG) { 854 args->start_blk = args->start_lba / args->htrsiz; 855 if (!(args->stop_lba < 0)) 856 args->stop_blk = args->stop_lba / args->htrsiz; 857 } 858 if (args->flags & CLD_FLG_BLK_RNG) { 859 args->start_lba = args->start_blk * args->htrsiz; 860 if (!(args->stop_blk < 0)) 861 args->stop_lba = 862 (args->stop_blk * args->htrsiz) + (args->htrsiz - 863 1); 864 } 865 /* if vsiz is still not set, try and get it from the file */ 866 if ((args->vsiz <= 0) && (args->flags & CLD_FLG_FILE)) { 867 if (0 != get_file_size(args->device)) { /* file size retrieved */ 868 args->vsiz = get_file_size(args->device); 869 } 870 } 871 /* if vsiz is still not set, try and get it from the device */ 872 if ((args->vsiz <= 0) && !(args->flags & CLD_FLG_FILE)) { 873 args->vsiz = get_vsiz(args->device); 874 } 875 /* if vsiz is still not set, set based on given range */ 876 if ((args->vsiz <= 0) 877 && (args->flags & (CLD_FLG_LBA_RNG | CLD_FLG_BLK_RNG))) { 878 if (!(args->stop_lba < 0)) 879 args->vsiz = args->stop_lba + 1; 880 else 881 args->vsiz = args->start_lba + 1; 882 } 883 /* if vsiz is still not set, then set it to the default size */ 884 if (args->vsiz <= 0) { 885 args->vsiz = VSIZ; 886 } 887 if (!(args->flags & CLD_FLG_VSIZ)) { 888 sprintf(TmpStr, N_ASSUME, args->vsiz); 889 strncat(args->argstr, TmpStr, 890 (MAX_ARG_LEN - 1) - strlen(args->argstr)); 891 } 892 893 if (args->stop_lba == -1) { 894 args->stop_lba = args->vsiz - 1; 895 } 896 if (args->stop_blk == -1) { 897 args->stop_blk = (args->stop_lba / (OFF_T) args->htrsiz); 898 } 899 if (args->t_kids == 0) { 900 sprintf(TmpStr, "(-K %d) ", KIDS); 901 strncat(args->argstr, TmpStr, 902 (MAX_ARG_LEN - 1) - strlen(args->argstr)); 903 args->t_kids = KIDS; 904 } 905 if ((args->flags & (CLD_FLG_W | CLD_FLG_R)) == 0) { 906 if (args->flags & CLD_FLG_DUTY) { /* no read/write but duty cycle specified */ 907 if (args->rperc > 0) { 908 args->flags |= CLD_FLG_R; 909 strncat(args->argstr, "(-r) ", 910 (MAX_ARG_LEN - 1) - 911 strlen(args->argstr)); 912 } 913 if (args->wperc > 0) { 914 args->flags |= CLD_FLG_W; 915 strncat(args->argstr, "(-w) ", 916 (MAX_ARG_LEN - 1) - 917 strlen(args->argstr)); 918 } 919 } else { 920 strncat(args->argstr, "(-r) ", 921 (MAX_ARG_LEN - 1) - strlen(args->argstr)); 922 args->flags |= CLD_FLG_R; 923 } 924 } 925 if (!(args->flags & CLD_FLG_PTYPS)) { 926 strncat(args->argstr, "(-c) ", 927 (MAX_ARG_LEN - 1) - strlen(args->argstr)); 928 args->flags |= CLD_FLG_CPTYPE; 929 } 930 if (!(args->flags & CLD_FLG_SKTYPS)) { 931 strncat(args->argstr, "(-p R) ", 932 (MAX_ARG_LEN - 1) - strlen(args->argstr)); 933 args->flags |= CLD_FLG_RANDOM; 934 } 935 if (!(args->flags & CLD_FLG_SKS)) { 936 if (args->start_blk == args->stop_blk) { /* diskcache test, w/ no seek count set */ 937 args->seeks = SEEKS; 938 } else if (args->flags & (CLD_FLG_BLK_RNG | CLD_FLG_LBA_RNG)) { /* range set, w/ no seek count */ 939 args->seeks = args->stop_blk - args->start_blk + 1; 940 } else { 941 /* if vsiz is available, calculated seeks are in terms of the largest transfer size */ 942 args->seeks = 943 (args->vsiz > 944 0) ? (args->vsiz / args->htrsiz) : SEEKS; 945 } 946 if ((args->flags & CLD_FLG_LINEAR) && (args->flags & CLD_FLG_R) 947 && (args->flags & CLD_FLG_W)) { 948 args->seeks *= 2; 949 } 950 951 if (!(args->flags & CLD_FLG_TMD)) { 952 sprintf(TmpStr, L_ASSUME, args->seeks); 953 strncat(args->argstr, TmpStr, 954 (MAX_ARG_LEN - 1) - strlen(args->argstr)); 955 } 956 } 957 if (!(args->flags & (CLD_FLG_SKS | CLD_FLG_TMD)) 958 || ((args->flags & CLD_FLG_CYC) 959 && !(args->flags & (CLD_FLG_SKS | CLD_FLG_TMD)))) { 960 args->flags |= CLD_FLG_SKS; 961 } 962 if (args->flags & (CLD_FLG_LINEAR)) { 963 if (!(args->flags & (CLD_FLG_LUNU | CLD_FLG_LUND))) { 964 strncat(args->argstr, "(-p u) ", 965 (MAX_ARG_LEN - 1) - strlen(args->argstr)); 966 args->flags |= CLD_FLG_LUNU; 967 } 968 } 969 normalize_percs(args); 970 if (!(args->flags & CLD_FLG_DUTY) && (args->flags & CLD_FLG_RANDOM) 971 && !(args->flags & CLD_FLG_NTRLVD)) { 972 sprintf(TmpStr, "(-D %d:%d) ", args->rperc, args->wperc); 973 strncat(args->argstr, TmpStr, 974 (MAX_ARG_LEN - 1) - strlen(args->argstr)); 975 args->flags |= CLD_FLG_DUTY; 976 } 977 if ((args->delayTimeMin == 0) && (args->delayTimeMax == 0) 978 && (args->ioTimeout == DEFAULT_IO_TIMEOUT)) { 979 strncat(args->argstr, "(-t 0:2m) ", 980 (MAX_ARG_LEN - 1) - strlen(args->argstr)); 981 } 982 if (!(args->flags & CLD_FLG_OFFSET)) { 983 strncat(args->argstr, "(-o 0) ", 984 (MAX_ARG_LEN - 1) - strlen(args->argstr)); 985 } 986 987 return 0; 988 } 989 990 /* 991 * checks validity of data after parsing 992 * args and make assumtions. returns 0 on 993 * success and -1 on failure. 994 */ 995 int check_conclusions(child_args_t * args) 996 { 997 extern unsigned long glb_flags; 998 struct stat stat_buf; 999 int rv; 1000 1001 if ((args->flags & CLD_FLG_DUTY) 1002 && ((args->flags & CLD_FLG_LINEAR) 1003 || (args->flags & CLD_FLG_NTRLVD))) { 1004 pMsg(WARN, args, 1005 "Duty cycle testing is supported for random (-pR) tests only.\n"); 1006 return (-1); 1007 } 1008 if ((args->flags & CLD_FLG_BLK_RNG) && (args->flags & CLD_FLG_RTRSIZ)) { 1009 pMsg(WARN, args, 1010 "Can't have unfixed block sizes and specify seek range in terms of blocks.\n"); 1011 return (-1); 1012 } 1013 if ((args->vsiz < 0) || (args->ltrsiz < 1) || (args->htrsiz < 1)) { 1014 pMsg(WARN, args, 1015 "Bounds exceeded for transfer size and/or volume size.\n"); 1016 pMsg(WARN, args, MAXTRSIZ, (args->htrsiz * BLK_SIZE), 1017 args->vsiz); 1018 return (-1); 1019 } 1020 if (args->htrsiz < args->ltrsiz) { 1021 pMsg(ERR, args, 1022 "Min transfer size, %lu, greater then Max transfer size, %lu.\n", 1023 args->ltrsiz, args->htrsiz); 1024 return (-1); 1025 } 1026 if (args->vsiz < (args->stop_lba - args->start_lba + 1)) { 1027 pMsg(ERR, args, "Volume stop block/lba exceeds volume size.\n"); 1028 return (-1); 1029 } 1030 if (args->vsiz < args->htrsiz) { 1031 pMsg(WARN, args, VSIZETS, args->vsiz, args->htrsiz); 1032 return (-1); 1033 } 1034 if ((args->flags & CLD_FLG_TMD) == 0 && (args->seeks <= 0)) { 1035 pMsg(WARN, args, TSEEK, args->seeks); 1036 return (-1); 1037 } 1038 if ((args->flags & CLD_FLG_SKS) && (args->t_kids > args->seeks)) { 1039 pMsg(WARN, args, 1040 "Can't have more children then max number of seeks, use -K/-L to adjust.\n"); 1041 return (-1); 1042 } 1043 if ((args->start_blk > args->vsiz) 1044 && !(args->flags & (CLD_FLG_BLK_RNG | CLD_FLG_LBA_RNG))) { 1045 pMsg(WARN, args, STBGTTLBA, args->start_blk, 1046 (args->vsiz / args->htrsiz)); 1047 return (-1); 1048 } 1049 if ((args->stop_blk > args->vsiz) 1050 && !(args->flags & (CLD_FLG_BLK_RNG | CLD_FLG_LBA_RNG))) { 1051 pMsg(WARN, args, SBGTTLBA, args->stop_blk, 1052 (args->vsiz / args->htrsiz)); 1053 return (-1); 1054 } 1055 if ((args->start_lba > args->vsiz) 1056 && !(args->flags & (CLD_FLG_BLK_RNG | CLD_FLG_LBA_RNG))) { 1057 pMsg(WARN, args, STLBAGTLBA, args->start_lba, args->vsiz); 1058 return (-1); 1059 } 1060 if ((args->stop_lba > args->vsiz) 1061 && !(args->flags & (CLD_FLG_BLK_RNG | CLD_FLG_LBA_RNG))) { 1062 pMsg(WARN, args, SLBAGTLBA, args->stop_lba, args->vsiz); 1063 return (-1); 1064 } 1065 if (args->start_blk > args->stop_blk) { 1066 pMsg(WARN, args, SBRSB, args->stop_blk, args->start_blk); 1067 return (-1); 1068 } 1069 if (args->start_lba > args->stop_lba) { 1070 pMsg(ERR, args, SLBARSLBA, args->stop_lba, args->start_lba); 1071 return (-1); 1072 } 1073 if ((args->flags & CLD_FLG_LBA_RNG) && (args->flags & CLD_FLG_BLK_RNG)) { 1074 pMsg(ERR, args, 1075 "Can't specify range in both block and LBA, use -s or -S.\n"); 1076 return (-1); 1077 } 1078 1079 /* use stat to get file properties, and test then agains specified -I */ 1080 rv = stat(args->device, &stat_buf); 1081 if (0 == rv) { /* no error on call to stat, compare against -I option */ 1082 /* files are usually file type */ 1083 if ((args->flags & CLD_FLG_FILE) && !IS_FILE(stat_buf.st_mode)) { 1084 pMsg(ERR, args, 1085 "Can't open non-file filespec with file device type, -If.\n"); 1086 return (-1); 1087 } 1088 /* block devices, are usually block type */ 1089 if ((args->flags & CLD_FLG_BLK) && !IS_BLK(stat_buf.st_mode)) { 1090 pMsg(ERR, args, 1091 "Can't open non-block filespec with block device type, -Ib.\n"); 1092 return (-1); 1093 } 1094 #ifndef WINDOWS 1095 /* raw devices, are usually character type */ 1096 if ((args->flags & CLD_FLG_RAW) && !S_ISCHR(stat_buf.st_mode)) { 1097 pMsg(ERR, args, 1098 "Can't open non-raw filespec with raw device type, -Ir.\n"); 1099 return (-1); 1100 } 1101 #else 1102 if (args->flags & CLD_FLG_RAW) { 1103 pMsg(ERR, args, 1104 "RAW IO type not supported in Windows, use direct IO instead.\n"); 1105 return (-1); 1106 } 1107 #endif 1108 #ifdef _DEBUG 1109 } else { 1110 PDBG1(DBUG, args, 1111 "Can't get status on %s, assuming a new file, errno = %d\n", 1112 args->device, GETLASTERROR()); 1113 #endif 1114 } 1115 1116 if ((args->hbeat > 0) && (args->flags & CLD_FLG_TMD) 1117 && (args->hbeat > args->run_time)) { 1118 pMsg(ERR, args, 1119 "Heartbeat should be at least equal to runtime, use -h/-T to adjust.\n"); 1120 return (-1); 1121 } 1122 if ((args->hbeat > 0) && !(args->flags & CLD_FLG_PRFTYPS)) { 1123 pMsg(ERR, args, 1124 "At least one performance option, -P, must be specified when using -h.\n"); 1125 return (-1); 1126 } 1127 if ((args->flags & CLD_FLG_W) && !(args->flags & CLD_FLG_R) 1128 && (args->flags & CLD_FLG_CMPR)) { 1129 pMsg(ERR, args, "Write only, ignoring option -E.\n"); 1130 } 1131 if ((args->flags & CLD_FLG_TMD) && (args->flags & CLD_FLG_SKS)) { 1132 pMsg(ERR, args, 1133 "Can't specify both -L and -T they are mutually exclusive.\n"); 1134 return (-1); 1135 } 1136 if (((args->flags & CLD_FLG_R) && !(args->flags & CLD_FLG_W)) 1137 && (args->flags & CLD_FLG_ERR_MARK)) { 1138 pMsg(ERR, args, 1139 "Can't specify mark on error, -Am, in read only mode.\n"); 1140 return (-1); 1141 } 1142 if (!(args->flags & CLD_FLG_ALLDIE) && (args->flags & CLD_FLG_ERR_MARK)) { 1143 pMsg(ERR, args, 1144 "Can't specify mark on error, -Am, when continue on error is set.\n"); 1145 return (-1); 1146 } 1147 if ((glb_flags & GLB_FLG_KILL) && !(args->flags & CLD_FLG_ALLDIE)) { 1148 pMsg(ERR, args, 1149 "Can't specify global kill, -Ag, when continue on error is set, -Ac.\n"); 1150 return (-1); 1151 } 1152 if ((args->flags & CLD_FLG_LINEAR) && !(args->flags & CLD_FLG_NTRLVD) 1153 && (args->flags & CLD_FLG_TMD)) { 1154 pMsg(ERR, args, "Linear read / write test can not be timed.\n"); 1155 return (-1); 1156 } 1157 if ((args->flags & CLD_FLG_CMPR) 1158 && (args->cmp_lng > (args->ltrsiz * BLK_SIZE))) { 1159 pMsg(ERR, args, 1160 "Compare length, %lu, is greater then transfer size, %lu\n", 1161 args->cmp_lng, args->ltrsiz * BLK_SIZE); 1162 return (-1); 1163 } 1164 if ((args->flags & CLD_FLG_OFFSET) && (args->offset > args->stop_lba)) { 1165 pMsg(ERR, args, LBAOFFGSLBA, args->offset, args->stop_lba); 1166 return (-1); 1167 } 1168 if ((args->flags & CLD_FLG_OFFSET) 1169 && ((args->offset + args->ltrsiz - 1) > args->stop_lba)) { 1170 pMsg(ERR, args, LBAOTSGSLBA, args->offset, args->ltrsiz, 1171 args->stop_lba); 1172 return (-1); 1173 } 1174 return 0; 1175 } 1176