]>
git.proxmox.com Git - mirror_zfs-debian.git/blob - cmd/zpios/zpios_util.c
2 * ZPIOS is a heavily modified version of the original PIOS test code.
3 * It is designed to have the test code running in the Linux kernel
4 * against ZFS while still being flexibly controlled from user space.
6 * Copyright (C) 2008-2010 Lawrence Livermore National Security, LLC.
7 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
8 * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
11 * Original PIOS Test Code
12 * Copyright (C) 2004 Cluster File Systems, Inc.
13 * Written by Peter Braam <braam@clusterfs.com>
14 * Atul Vidwansa <atul@clusterfs.com>
15 * Milind Dumbare <milind@clusterfs.com>
17 * This file is part of ZFS on Linux.
18 * For details, see <http://zfsonlinux.org/>.
20 * ZPIOS is free software; you can redistribute it and/or modify it
21 * under the terms of the GNU General Public License as published by the
22 * Free Software Foundation; either version 2 of the License, or (at your
23 * option) any later version.
25 * ZPIOS is distributed in the hope that it will be useful, but WITHOUT
26 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
27 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
30 * You should have received a copy of the GNU General Public License along
31 * with ZPIOS. If not, see <http://www.gnu.org/licenses/>.
33 * Copyright (c) 2015, Intel Corporation.
44 /* extracts an unsigned int (64) and K,M,G,T from the string */
45 /* and returns a 64 bit value converted to the proper units */
47 kmgt_to_uint64(const char *str
, uint64_t *val
)
52 *val
= strtoll(str
, &endptr
, 0);
53 if ((str
== endptr
) && (*val
== 0))
79 uint64_to_kmgt(char *str
, uint64_t val
)
81 char postfix
[] = "kmgt";
84 while ((val
>= KB
) && (i
< 4)) {
90 (void) snprintf(str
, KMGT_SIZE
-1, "inf");
92 (void) snprintf(str
, KMGT_SIZE
-1, "%lu%c", (unsigned long)val
,
93 (i
== -1) ? '\0' : postfix
[i
]);
99 kmgt_per_sec(char *str
, uint64_t v
, double t
)
101 char postfix
[] = "kmgt";
102 double val
= ((double)v
) / t
;
105 while ((val
>= (double)KB
) && (i
< 4)) {
111 (void) snprintf(str
, KMGT_SIZE
-1, "inf");
113 (void) snprintf(str
, KMGT_SIZE
-1, "%.2f%c", val
,
114 (i
== -1) ? '\0' : postfix
[i
]);
120 print_flags(char *str
, uint32_t flags
)
122 str
[0] = (flags
& DMU_WRITE
) ? 'w' : '-';
123 str
[1] = (flags
& DMU_READ
) ? 'r' : '-';
124 str
[2] = (flags
& DMU_VERIFY
) ? 'v' : '-';
125 str
[3] = (flags
& DMU_REMOVE
) ? 'c' : '-';
126 str
[4] = (flags
& DMU_FPP
) ? 'p' : 's';
127 str
[5] = (flags
& (DMU_WRITE_ZC
| DMU_READ_ZC
)) ? 'z' : '-';
128 str
[6] = (flags
& DMU_WRITE_NOWAIT
) ? 'O' : '-';
135 regex_match(const char *string
, char *pattern
)
140 rc
= regcomp(&re
, pattern
, REG_EXTENDED
| REG_NOSUB
| REG_ICASE
);
142 fprintf(stderr
, "Error: Couldn't do regcomp, %d\n", rc
);
146 rc
= regexec(&re
, string
, (size_t)0, NULL
, 0);
152 /* fills the pios_range_repeat structure of comma separated values */
154 split_string(const char *optarg
, char *pattern
, range_repeat_t
*range
)
156 const char comma
[] = ",";
157 char *cp
, *token
[32];
160 if ((rc
= regex_match(optarg
, pattern
)))
169 * STRTOK(3) Each subsequent call, with a null pointer as the
170 * value of the * first argument, starts searching from the
171 * saved pointer and behaves as described above.
174 token
[i
] = strtok(cp
, comma
);
176 token
[i
] = strtok(NULL
, comma
);
178 } while ((token
[i
++] != NULL
) && (i
< 32));
180 range
->val_count
= i
- 1;
182 for (i
= 0; i
< range
->val_count
; i
++)
183 kmgt_to_uint64(token
[i
], &range
->val
[i
]);
190 set_count(char *pattern1
, char *pattern2
, range_repeat_t
*range
,
191 char *optarg
, uint32_t *flags
, char *arg
)
193 uint64_t count
= range
->val_count
;
200 if (regex_match(optarg
, pattern1
) == 0) {
201 kmgt_to_uint64(optarg
, &range
->val
[0]);
202 range
->val_count
= 1;
203 } else if (split_string(optarg
, pattern2
, range
) < 0) {
204 fprintf(stderr
, "Error: Incorrect pattern for %s, '%s'\n",
207 } else if (count
== range
->val_count
) {
208 fprintf(stderr
, "Error: input ignored for %s, '%s'\n",
216 * Validates the value with regular expression and sets low, high, incr
217 * according to value at which flag will be set. Sets the flag after.
220 set_lhi(char *pattern
, range_repeat_t
*range
, char *optarg
,
221 int flag
, uint32_t *flag_thread
, char *arg
)
225 if ((rc
= regex_match(optarg
, pattern
))) {
226 fprintf(stderr
, "Error: Wrong pattern in %s, '%s'\n",
233 kmgt_to_uint64(optarg
, &range
->val_low
);
236 kmgt_to_uint64(optarg
, &range
->val_high
);
239 kmgt_to_uint64(optarg
, &range
->val_inc_perc
);
245 *flag_thread
|= flag
;
251 set_noise(uint64_t *noise
, char *optarg
, char *arg
)
253 if (regex_match(optarg
, REGEX_NUMBERS
) == 0) {
254 kmgt_to_uint64(optarg
, noise
);
256 fprintf(stderr
, "Error: Incorrect pattern for %s\n", arg
);
264 set_load_params(cmd_args_t
*args
, char *optarg
)
266 char *param
, *search
, *searchdup
, comma
[] = ",";
269 search
= strdup(optarg
);
274 while ((param
= strtok(search
, comma
)) != NULL
) {
277 if (strcmp("fpp", param
) == 0) {
278 args
->flags
|= DMU_FPP
; /* File Per Process/Thread */
279 } else if (strcmp("ssf", param
) == 0) {
280 args
->flags
&= ~DMU_FPP
; /* Single Shared File */
281 } else if (strcmp("dmuio", param
) == 0) {
282 args
->io_type
|= DMU_IO
;
283 args
->flags
|= (DMU_WRITE
| DMU_READ
);
285 fprintf(stderr
, "Invalid load: %s\n", param
);
297 * Checks the low, high, increment values against the single value for
298 * mutual exclusion, for e.g threadcount is mutually exclusive to
299 * threadcount_low, ..._high, ..._incr
302 check_mutual_exclusive_command_lines(uint32_t flag
, char *arg
)
304 if ((flag
& FLAG_SET
) && (flag
& (FLAG_LOW
| FLAG_HIGH
| FLAG_INCR
))) {
305 fprintf(stderr
, "Error: --%s can not be given with --%s_low, "
306 "--%s_high or --%s_incr.\n", arg
, arg
, arg
, arg
);
310 if ((flag
& (FLAG_LOW
| FLAG_HIGH
| FLAG_INCR
)) && !(flag
& FLAG_SET
)) {
311 if (flag
!= (FLAG_LOW
| FLAG_HIGH
| FLAG_INCR
)) {
312 fprintf(stderr
, "Error: One or more values missing "
313 "from --%s_low, --%s_high, --%s_incr.\n",
323 print_stats_header(cmd_args_t
*args
)
327 "status name id\tth-cnt\trg-cnt\trg-sz\t"
328 "ch-sz\toffset\trg-no\tch-no\tth-dly\tflags\tblksz\ttime\t"
329 "cr-time\trm-time\twr-time\trd-time\twr-data\twr-ch\t"
330 "wr-bw\trd-data\trd-ch\trd-bw\n");
332 "-------------------------------------------------"
333 "-------------------------------------------------"
334 "-------------------------------------------------"
335 "--------------------------------------------------\n");
339 "wr-data\twr-ch\twr-bw\t"
340 "rd-data\trd-ch\trd-bw\n");
342 "-----------------------------------------"
343 "--------------------------------------\n");
348 print_stats_human_readable(cmd_args_t
*args
, zpios_cmd_t
*cmd
)
350 zpios_stats_t
*summary_stats
;
351 double t_time
, wr_time
, rd_time
, cr_time
, rm_time
;
355 printf("FAIL: %3d ", args
->rc
);
359 printf("%-12s", args
->name
? args
->name
: ZPIOS_NAME
);
360 printf("%2u\t", cmd
->cmd_id
);
363 printf("%u\t", cmd
->cmd_thread_count
);
364 printf("%u\t", cmd
->cmd_region_count
);
365 printf("%s\t", uint64_to_kmgt(str
, cmd
->cmd_region_size
));
366 printf("%s\t", uint64_to_kmgt(str
, cmd
->cmd_chunk_size
));
367 printf("%s\t", uint64_to_kmgt(str
, cmd
->cmd_offset
));
368 printf("%s\t", uint64_to_kmgt(str
, cmd
->cmd_region_noise
));
369 printf("%s\t", uint64_to_kmgt(str
, cmd
->cmd_chunk_noise
));
370 printf("%s\t", uint64_to_kmgt(str
, cmd
->cmd_thread_delay
));
371 printf("%s\t", print_flags(str
, cmd
->cmd_flags
));
372 printf("%s\t", uint64_to_kmgt(str
, cmd
->cmd_block_size
));
380 summary_stats
= (zpios_stats_t
*)cmd
->cmd_data_str
;
381 t_time
= zpios_timespec_to_double(summary_stats
->total_time
.delta
);
382 wr_time
= zpios_timespec_to_double(summary_stats
->wr_time
.delta
);
383 rd_time
= zpios_timespec_to_double(summary_stats
->rd_time
.delta
);
384 cr_time
= zpios_timespec_to_double(summary_stats
->cr_time
.delta
);
385 rm_time
= zpios_timespec_to_double(summary_stats
->rm_time
.delta
);
388 printf("%.2f\t", t_time
);
389 printf("%.3f\t", cr_time
);
390 printf("%.3f\t", rm_time
);
391 printf("%.2f\t", wr_time
);
392 printf("%.2f\t", rd_time
);
395 printf("%s\t", uint64_to_kmgt(str
, summary_stats
->wr_data
));
396 printf("%s\t", uint64_to_kmgt(str
, summary_stats
->wr_chunks
));
397 printf("%s\t", kmgt_per_sec(str
, summary_stats
->wr_data
, wr_time
));
399 printf("%s\t", uint64_to_kmgt(str
, summary_stats
->rd_data
));
400 printf("%s\t", uint64_to_kmgt(str
, summary_stats
->rd_chunks
));
401 printf("%s\n", kmgt_per_sec(str
, summary_stats
->rd_data
, rd_time
));
406 print_stats_table(cmd_args_t
*args
, zpios_cmd_t
*cmd
)
408 zpios_stats_t
*summary_stats
;
409 double wr_time
, rd_time
;
412 printf("FAIL: %3d ", args
->rc
);
416 printf("%-12s", args
->name
? args
->name
: ZPIOS_NAME
);
417 printf("%2u\t", cmd
->cmd_id
);
420 printf("%u\t", cmd
->cmd_thread_count
);
421 printf("%u\t", cmd
->cmd_region_count
);
422 printf("%llu\t", (long long unsigned)cmd
->cmd_region_size
);
423 printf("%llu\t", (long long unsigned)cmd
->cmd_chunk_size
);
424 printf("%llu\t", (long long unsigned)cmd
->cmd_offset
);
425 printf("%u\t", cmd
->cmd_region_noise
);
426 printf("%u\t", cmd
->cmd_chunk_noise
);
427 printf("%u\t", cmd
->cmd_thread_delay
);
428 printf("0x%x\t", cmd
->cmd_flags
);
429 printf("%u\t", cmd
->cmd_block_size
);
437 summary_stats
= (zpios_stats_t
*)cmd
->cmd_data_str
;
438 wr_time
= zpios_timespec_to_double(summary_stats
->wr_time
.delta
);
439 rd_time
= zpios_timespec_to_double(summary_stats
->rd_time
.delta
);
442 printf("%ld.%02ld\t",
443 (long)summary_stats
->total_time
.delta
.ts_sec
,
444 (long)summary_stats
->total_time
.delta
.ts_nsec
);
445 printf("%ld.%02ld\t",
446 (long)summary_stats
->cr_time
.delta
.ts_sec
,
447 (long)summary_stats
->cr_time
.delta
.ts_nsec
);
448 printf("%ld.%02ld\t",
449 (long)summary_stats
->rm_time
.delta
.ts_sec
,
450 (long)summary_stats
->rm_time
.delta
.ts_nsec
);
451 printf("%ld.%02ld\t",
452 (long)summary_stats
->wr_time
.delta
.ts_sec
,
453 (long)summary_stats
->wr_time
.delta
.ts_nsec
);
454 printf("%ld.%02ld\t",
455 (long)summary_stats
->rd_time
.delta
.ts_sec
,
456 (long)summary_stats
->rd_time
.delta
.ts_nsec
);
459 printf("%lld\t", (long long unsigned)summary_stats
->wr_data
);
460 printf("%lld\t", (long long unsigned)summary_stats
->wr_chunks
);
461 printf("%.4f\t", (double)summary_stats
->wr_data
/ wr_time
);
463 printf("%lld\t", (long long unsigned)summary_stats
->rd_data
);
464 printf("%lld\t", (long long unsigned)summary_stats
->rd_chunks
);
465 printf("%.4f\n", (double)summary_stats
->rd_data
/ rd_time
);
470 print_stats(cmd_args_t
*args
, zpios_cmd_t
*cmd
)
472 if (args
->human_readable
)
473 print_stats_human_readable(args
, cmd
);
475 print_stats_table(args
, cmd
);