• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 
fill_cld_args(int argc,char ** argv,child_args_t * args)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 
make_assumptions(child_args_t * args)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  */
check_conclusions(child_args_t * args)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