diff options
Diffstat (limited to 'cmd/zpios')
-rw-r--r-- | cmd/zpios/.gitignore | 1 | ||||
-rw-r--r-- | cmd/zpios/Makefile.am | 11 | ||||
-rw-r--r-- | cmd/zpios/zpios.h | 127 | ||||
-rw-r--r-- | cmd/zpios/zpios_main.c | 680 | ||||
-rw-r--r-- | cmd/zpios/zpios_util.c | 476 |
5 files changed, 0 insertions, 1295 deletions
diff --git a/cmd/zpios/.gitignore b/cmd/zpios/.gitignore deleted file mode 100644 index b83e1d094..000000000 --- a/cmd/zpios/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/zpios diff --git a/cmd/zpios/Makefile.am b/cmd/zpios/Makefile.am deleted file mode 100644 index 9dabb6530..000000000 --- a/cmd/zpios/Makefile.am +++ /dev/null @@ -1,11 +0,0 @@ -include $(top_srcdir)/config/Rules.am - -DEFAULT_INCLUDES += \ - -I$(top_srcdir)/include - -sbin_PROGRAMS = zpios - -zpios_SOURCES = \ - zpios_main.c \ - zpios_util.c \ - zpios.h diff --git a/cmd/zpios/zpios.h b/cmd/zpios/zpios.h deleted file mode 100644 index e670354f4..000000000 --- a/cmd/zpios/zpios.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * ZPIOS is a heavily modified version of the original PIOS test code. - * It is designed to have the test code running in the Linux kernel - * against ZFS while still being flexibly controlled from user space. - * - * Copyright (C) 2008-2010 Lawrence Livermore National Security, LLC. - * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). - * Written by Brian Behlendorf <[email protected]>. - * LLNL-CODE-403049 - * - * Original PIOS Test Code - * Copyright (C) 2004 Cluster File Systems, Inc. - * Written by Peter Braam <[email protected]> - * Atul Vidwansa <[email protected]> - * Milind Dumbare <[email protected]> - * - * This file is part of ZFS on Linux. - * For details, see <http://zfsonlinux.org/>. - * - * ZPIOS is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * ZPIOS is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with ZPIOS. If not, see <http://www.gnu.org/licenses/>. - * - * Copyright (c) 2015, Intel Corporation. - */ - -#ifndef _ZPIOS_H -#define _ZPIOS_H - -#include <zpios-ctl.h> - -#define VERSION_SIZE 64 - -/* Regular expressions */ -#define REGEX_NUMBERS "^[0-9]+$" -#define REGEX_NUMBERS_COMMA "^([0-9]+,)*[0-9]+$" -#define REGEX_SIZE "^[0-9]+[kKmMgGtT]?$" -#define REGEX_SIZE_COMMA "^([0-9]+[kKmMgGtT]?,)*[0-9]+[kKmMgGtT]?$" - -/* Flags for low, high, incr */ -#define FLAG_SET 0x01 -#define FLAG_LOW 0x02 -#define FLAG_HIGH 0x04 -#define FLAG_INCR 0x08 - -#define TRUE 1 -#define FALSE 0 - -#define KB (1024) -#define MB (KB * 1024) -#define GB (MB * 1024) -#define TB (GB * 1024) - -#define KMGT_SIZE 16 - -/* - * All offsets, sizes and counts can be passed to the application in - * multiple ways. - * 1. a value (stored in val[0], val_count will be 1) - * 2. a comma separated list of values (stored in val[], using val_count) - * 3. a range and block sizes, low, high, factor (val_count must be 0) - */ -typedef struct pios_range_repeat { - uint64_t val[32]; /* Comma sep array, or low, high, inc */ - uint64_t val_count; /* Num of values */ - uint64_t val_low; - uint64_t val_high; - uint64_t val_inc_perc; - uint64_t next_val; /* For multiple runs in get_next() */ -} range_repeat_t; - -typedef struct cmd_args { - range_repeat_t T; /* Thread count */ - range_repeat_t N; /* Region count */ - range_repeat_t O; /* Offset count */ - range_repeat_t C; /* Chunksize */ - range_repeat_t S; /* Regionsize */ - range_repeat_t B; /* Blocksize */ - - const char *pool; /* Pool */ - const char *name; /* Name */ - uint32_t flags; /* Flags */ - uint32_t block_size; /* ZFS block size */ - uint32_t io_type; /* DMUIO only */ - uint32_t verbose; /* Verbose */ - uint32_t human_readable; /* Human readable output */ - - uint64_t regionnoise; /* Region noise */ - uint64_t chunknoise; /* Chunk noise */ - uint64_t thread_delay; /* Thread delay */ - - char pre[ZPIOS_PATH_SIZE]; /* Pre-exec hook */ - char post[ZPIOS_PATH_SIZE]; /* Post-exec hook */ - char log[ZPIOS_PATH_SIZE]; /* Requested log dir */ - - /* Control */ - int current_id; - uint64_t current_T; - uint64_t current_N; - uint64_t current_C; - uint64_t current_S; - uint64_t current_O; - uint64_t current_B; - - uint32_t rc; -} cmd_args_t; - -int set_count(char *pattern1, char *pattern2, range_repeat_t *range, - char *optarg, uint32_t *flags, char *arg); -int set_lhi(char *pattern, range_repeat_t *range, char *optarg, - int flag, uint32_t *flag_thread, char *arg); -int set_noise(uint64_t *noise, char *optarg, char *arg); -int set_load_params(cmd_args_t *args, char *optarg); -int check_mutual_exclusive_command_lines(uint32_t flag, char *arg); -void print_stats_header(cmd_args_t *args); -void print_stats(cmd_args_t *args, zpios_cmd_t *cmd); - -#endif /* _ZPIOS_H */ diff --git a/cmd/zpios/zpios_main.c b/cmd/zpios/zpios_main.c deleted file mode 100644 index 01f2ce197..000000000 --- a/cmd/zpios/zpios_main.c +++ /dev/null @@ -1,680 +0,0 @@ -/* - * ZPIOS is a heavily modified version of the original PIOS test code. - * It is designed to have the test code running in the Linux kernel - * against ZFS while still being flexibly controlled from user space. - * - * Copyright (C) 2008-2010 Lawrence Livermore National Security, LLC. - * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). - * Written by Brian Behlendorf <[email protected]>. - * LLNL-CODE-403049 - * - * Original PIOS Test Code - * Copyright (C) 2004 Cluster File Systems, Inc. - * Written by Peter Braam <[email protected]> - * Atul Vidwansa <[email protected]> - * Milind Dumbare <[email protected]> - * - * This file is part of ZFS on Linux. - * For details, see <http://zfsonlinux.org/>. - * - * ZPIOS is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * ZPIOS is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with ZPIOS. If not, see <http://www.gnu.org/licenses/>. - * - * Copyright (c) 2015, Intel Corporation. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <getopt.h> -#include <assert.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include "zpios.h" - -static const char short_opt[] = - "t:l:h:e:n:i:j:k:o:m:q:r:c:a:b:g:s:A:B:C:" - "S:L:p:M:xP:R:G:I:N:T:VzOfHv?"; -static const struct option long_opt[] = { - {"threadcount", required_argument, 0, 't' }, - {"threadcount_low", required_argument, 0, 'l' }, - {"threadcount_high", required_argument, 0, 'h' }, - {"threadcount_incr", required_argument, 0, 'e' }, - {"regioncount", required_argument, 0, 'n' }, - {"regioncount_low", required_argument, 0, 'i' }, - {"regioncount_high", required_argument, 0, 'j' }, - {"regioncount_incr", required_argument, 0, 'k' }, - {"offset", required_argument, 0, 'o' }, - {"offset_low", required_argument, 0, 'm' }, - {"offset_high", required_argument, 0, 'q' }, - {"offset_incr", required_argument, 0, 'r' }, - {"chunksize", required_argument, 0, 'c' }, - {"chunksize_low", required_argument, 0, 'a' }, - {"chunksize_high", required_argument, 0, 'b' }, - {"chunksize_incr", required_argument, 0, 'g' }, - {"regionsize", required_argument, 0, 's' }, - {"regionsize_low", required_argument, 0, 'A' }, - {"regionsize_high", required_argument, 0, 'B' }, - {"regionsize_incr", required_argument, 0, 'C' }, - {"blocksize", required_argument, 0, 'S' }, - {"load", required_argument, 0, 'L' }, - {"pool", required_argument, 0, 'p' }, - {"name", required_argument, 0, 'M' }, - {"cleanup", no_argument, 0, 'x' }, - {"prerun", required_argument, 0, 'P' }, - {"postrun", required_argument, 0, 'R' }, - {"log", required_argument, 0, 'G' }, - {"regionnoise", required_argument, 0, 'I' }, - {"chunknoise", required_argument, 0, 'N' }, - {"threaddelay", required_argument, 0, 'T' }, - {"verify", no_argument, 0, 'V' }, - {"zerocopy", no_argument, 0, 'z' }, - {"nowait", no_argument, 0, 'O' }, - {"noprefetch", no_argument, 0, 'f' }, - {"human-readable", no_argument, 0, 'H' }, - {"verbose", no_argument, 0, 'v' }, - {"help", no_argument, 0, '?' }, - { 0, 0, 0, 0 }, -}; - -static int zpiosctl_fd; /* Control file descriptor */ -static char zpios_version[VERSION_SIZE]; /* Kernel version string */ -static char *zpios_buffer = NULL; /* Scratch space area */ -static int zpios_buffer_size = 0; /* Scratch space size */ - -static int -usage(void) -{ - fprintf(stderr, "Usage: zpios\n"); - fprintf(stderr, - " --threadcount -t =values\n" - " --threadcount_low -l =value\n" - " --threadcount_high -h =value\n" - " --threadcount_incr -e =value\n" - " --regioncount -n =values\n" - " --regioncount_low -i =value\n" - " --regioncount_high -j =value\n" - " --regioncount_incr -k =value\n" - " --offset -o =values\n" - " --offset_low -m =value\n" - " --offset_high -q =value\n" - " --offset_incr -r =value\n" - " --chunksize -c =values\n" - " --chunksize_low -a =value\n" - " --chunksize_high -b =value\n" - " --chunksize_incr -g =value\n" - " --regionsize -s =values\n" - " --regionsize_low -A =value\n" - " --regionsize_high -B =value\n" - " --regionsize_incr -C =value\n" - " --blocksize -S =values\n" - " --load -L =dmuio|ssf|fpp\n" - " --pool -p =pool name\n" - " --name -M =test name\n" - " --cleanup -x\n" - " --prerun -P =pre-command\n" - " --postrun -R =post-command\n" - " --log -G =log directory\n" - " --regionnoise -I =shift\n" - " --chunknoise -N =bytes\n" - " --threaddelay -T =jiffies\n" - " --verify -V\n" - " --zerocopy -z\n" - " --nowait -O\n" - " --noprefetch -f\n" - " --human-readable -H\n" - " --verbose -v =increase verbosity\n" - " --help -? =this help\n\n"); - - return (0); -} - -static void args_fini(cmd_args_t *args) -{ - assert(args != NULL); - free(args); -} - -/* block size is 128K to 16M, power of 2 */ -#define MIN_BLKSIZE (128ULL << 10) -#define MAX_BLKSIZE (16ULL << 20) -#define POW_OF_TWO(x) (((x) & ((x) - 1)) == 0) - -static cmd_args_t * -args_init(int argc, char **argv) -{ - cmd_args_t *args; - uint32_t fl_th = 0; - uint32_t fl_rc = 0; - uint32_t fl_of = 0; - uint32_t fl_rs = 0; - uint32_t fl_cs = 0; - uint32_t fl_bs = 0; - int c, rc, i; - - if (argc == 1) { - usage(); - return ((cmd_args_t *)NULL); - } - - /* Configure and populate the args structures */ - args = malloc(sizeof (*args)); - if (args == NULL) - return (NULL); - - memset(args, 0, sizeof (*args)); - - /* provide a default block size of 128K */ - args->B.next_val = 0; - args->B.val[0] = MIN_BLKSIZE; - args->B.val_count = 1; - - while ((c = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) { - rc = 0; - - switch (c) { - case 't': /* --thread count */ - rc = set_count(REGEX_NUMBERS, REGEX_NUMBERS_COMMA, - &args->T, optarg, &fl_th, "threadcount"); - break; - case 'l': /* --threadcount_low */ - rc = set_lhi(REGEX_NUMBERS, &args->T, optarg, - FLAG_LOW, &fl_th, "threadcount_low"); - break; - case 'h': /* --threadcount_high */ - rc = set_lhi(REGEX_NUMBERS, &args->T, optarg, - FLAG_HIGH, &fl_th, "threadcount_high"); - break; - case 'e': /* --threadcount_inc */ - rc = set_lhi(REGEX_NUMBERS, &args->T, optarg, - FLAG_INCR, &fl_th, "threadcount_incr"); - break; - case 'n': /* --regioncount */ - rc = set_count(REGEX_NUMBERS, REGEX_NUMBERS_COMMA, - &args->N, optarg, &fl_rc, "regioncount"); - break; - case 'i': /* --regioncount_low */ - rc = set_lhi(REGEX_NUMBERS, &args->N, optarg, - FLAG_LOW, &fl_rc, "regioncount_low"); - break; - case 'j': /* --regioncount_high */ - rc = set_lhi(REGEX_NUMBERS, &args->N, optarg, - FLAG_HIGH, &fl_rc, "regioncount_high"); - break; - case 'k': /* --regioncount_inc */ - rc = set_lhi(REGEX_NUMBERS, &args->N, optarg, - FLAG_INCR, &fl_rc, "regioncount_incr"); - break; - case 'o': /* --offset */ - rc = set_count(REGEX_SIZE, REGEX_SIZE_COMMA, - &args->O, optarg, &fl_of, "offset"); - break; - case 'm': /* --offset_low */ - rc = set_lhi(REGEX_SIZE, &args->O, optarg, - FLAG_LOW, &fl_of, "offset_low"); - break; - case 'q': /* --offset_high */ - rc = set_lhi(REGEX_SIZE, &args->O, optarg, - FLAG_HIGH, &fl_of, "offset_high"); - break; - case 'r': /* --offset_inc */ - rc = set_lhi(REGEX_NUMBERS, &args->O, optarg, - FLAG_INCR, &fl_of, "offset_incr"); - break; - case 'c': /* --chunksize */ - rc = set_count(REGEX_SIZE, REGEX_SIZE_COMMA, - &args->C, optarg, &fl_cs, "chunksize"); - break; - case 'a': /* --chunksize_low */ - rc = set_lhi(REGEX_SIZE, &args->C, optarg, - FLAG_LOW, &fl_cs, "chunksize_low"); - break; - case 'b': /* --chunksize_high */ - rc = set_lhi(REGEX_SIZE, &args->C, optarg, - FLAG_HIGH, &fl_cs, "chunksize_high"); - break; - case 'g': /* --chunksize_inc */ - rc = set_lhi(REGEX_NUMBERS, &args->C, optarg, - FLAG_INCR, &fl_cs, "chunksize_incr"); - break; - case 's': /* --regionsize */ - rc = set_count(REGEX_SIZE, REGEX_SIZE_COMMA, - &args->S, optarg, &fl_rs, "regionsize"); - break; - case 'A': /* --regionsize_low */ - rc = set_lhi(REGEX_SIZE, &args->S, optarg, - FLAG_LOW, &fl_rs, "regionsize_low"); - break; - case 'B': /* --regionsize_high */ - rc = set_lhi(REGEX_SIZE, &args->S, optarg, - FLAG_HIGH, &fl_rs, "regionsize_high"); - break; - case 'C': /* --regionsize_inc */ - rc = set_lhi(REGEX_NUMBERS, &args->S, optarg, - FLAG_INCR, &fl_rs, "regionsize_incr"); - break; - case 'S': /* --blocksize */ - rc = set_count(REGEX_SIZE, REGEX_SIZE_COMMA, - &args->B, optarg, &fl_bs, "blocksize"); - break; - case 'L': /* --load */ - rc = set_load_params(args, optarg); - break; - case 'p': /* --pool */ - args->pool = optarg; - break; - case 'M': - args->name = optarg; - break; - case 'x': /* --cleanup */ - args->flags |= DMU_REMOVE; - break; - case 'P': /* --prerun */ - strncpy(args->pre, optarg, ZPIOS_PATH_SIZE - 1); - break; - case 'R': /* --postrun */ - strncpy(args->post, optarg, ZPIOS_PATH_SIZE - 1); - break; - case 'G': /* --log */ - strncpy(args->log, optarg, ZPIOS_PATH_SIZE - 1); - break; - case 'I': /* --regionnoise */ - rc = set_noise(&args->regionnoise, optarg, - "regionnoise"); - break; - case 'N': /* --chunknoise */ - rc = set_noise(&args->chunknoise, optarg, "chunknoise"); - break; - case 'T': /* --threaddelay */ - rc = set_noise(&args->thread_delay, optarg, - "threaddelay"); - break; - case 'V': /* --verify */ - args->flags |= DMU_VERIFY; - break; - case 'z': /* --zerocopy */ - args->flags |= (DMU_WRITE_ZC | DMU_READ_ZC); - break; - case 'O': /* --nowait */ - args->flags |= DMU_WRITE_NOWAIT; - break; - case 'f': /* --noprefetch */ - args->flags |= DMU_READ_NOPF; - break; - case 'H': /* --human-readable */ - args->human_readable = 1; - break; - case 'v': /* --verbose */ - args->verbose++; - break; - case '?': - rc = 1; - break; - default: - fprintf(stderr, "Unknown option '%s'\n", - argv[optind - 1]); - rc = EINVAL; - break; - } - - if (rc) { - usage(); - args_fini(args); - return (NULL); - } - } - - check_mutual_exclusive_command_lines(fl_th, "threadcount"); - check_mutual_exclusive_command_lines(fl_rc, "regioncount"); - check_mutual_exclusive_command_lines(fl_of, "offset"); - check_mutual_exclusive_command_lines(fl_rs, "regionsize"); - check_mutual_exclusive_command_lines(fl_cs, "chunksize"); - - if (args->pool == NULL) { - fprintf(stderr, "Error: Pool not specified\n"); - usage(); - args_fini(args); - return (NULL); - } - - if ((args->flags & (DMU_WRITE_ZC | DMU_READ_ZC)) && - (args->flags & DMU_VERIFY)) { - fprintf(stderr, "Error, --zerocopy incompatible --verify, " - "used for performance analysis only\n"); - usage(); - args_fini(args); - return (NULL); - } - - /* validate block size(s) */ - for (i = 0; i < args->B.val_count; i++) { - int bs = args->B.val[i]; - - if (bs < MIN_BLKSIZE || bs > MAX_BLKSIZE || !POW_OF_TWO(bs)) { - fprintf(stderr, "Error: invalid block size %d\n", bs); - args_fini(args); - return (NULL); - } - } - - return (args); -} - -static int -dev_clear(void) -{ - zpios_cfg_t cfg; - int rc; - - memset(&cfg, 0, sizeof (cfg)); - cfg.cfg_magic = ZPIOS_CFG_MAGIC; - cfg.cfg_cmd = ZPIOS_CFG_BUFFER_CLEAR; - cfg.cfg_arg1 = 0; - - rc = ioctl(zpiosctl_fd, ZPIOS_CFG, &cfg); - if (rc) - fprintf(stderr, "Ioctl() error %lu / %d: %d\n", - (unsigned long) ZPIOS_CFG, cfg.cfg_cmd, errno); - - (void) lseek(zpiosctl_fd, 0, SEEK_SET); - - return (rc); -} - -/* Passing a size of zero simply results in querying the current size */ -static int -dev_size(int size) -{ - zpios_cfg_t cfg; - int rc; - - memset(&cfg, 0, sizeof (cfg)); - cfg.cfg_magic = ZPIOS_CFG_MAGIC; - cfg.cfg_cmd = ZPIOS_CFG_BUFFER_SIZE; - cfg.cfg_arg1 = size; - - rc = ioctl(zpiosctl_fd, ZPIOS_CFG, &cfg); - if (rc) { - fprintf(stderr, "Ioctl() error %lu / %d: %d\n", - (unsigned long) ZPIOS_CFG, cfg.cfg_cmd, errno); - return (rc); - } - - return (cfg.cfg_rc1); -} - -static void -dev_fini(void) -{ - if (zpios_buffer) - free(zpios_buffer); - - if (zpiosctl_fd != -1) { - if (close(zpiosctl_fd) == -1) { - fprintf(stderr, "Unable to close %s: %d\n", - ZPIOS_DEV, errno); - } - } -} - -static int -dev_init(void) -{ - int rc; - - zpiosctl_fd = open(ZPIOS_DEV, O_RDONLY); - if (zpiosctl_fd == -1) { - fprintf(stderr, "Unable to open %s: %d\n" - "Is the zpios module loaded?\n", ZPIOS_DEV, errno); - rc = errno; - goto error; - } - - if ((rc = dev_clear())) - goto error; - - if ((rc = dev_size(0)) < 0) - goto error; - - zpios_buffer_size = rc; - zpios_buffer = (char *)malloc(zpios_buffer_size); - if (zpios_buffer == NULL) { - rc = ENOMEM; - goto error; - } - - memset(zpios_buffer, 0, zpios_buffer_size); - return (0); -error: - if (zpiosctl_fd != -1) { - if (close(zpiosctl_fd) == -1) { - fprintf(stderr, "Unable to close %s: %d\n", - ZPIOS_DEV, errno); - } - } - - return (rc); -} - -static int -get_next(uint64_t *val, range_repeat_t *range) -{ - /* if low, incr, high is given */ - if (range->val_count == 0) { - *val = (range->val_low) + - (range->val_low * range->next_val / 100); - - if (*val > range->val_high) - return (0); /* No more values, limit exceeded */ - - if (!range->next_val) - range->next_val = range->val_inc_perc; - else - range->next_val = range->next_val + range->val_inc_perc; - - return (1); /* more values to come */ - - /* if only one val is given */ - } else if (range->val_count == 1) { - if (range->next_val) - return (0); /* No more values, we only have one */ - - *val = range->val[0]; - range->next_val = 1; - return (1); /* more values to come */ - - /* if comma separated values are given */ - } else if (range->val_count > 1) { - if (range->next_val > range->val_count - 1) - return (0); /* No more values, limit exceeded */ - - *val = range->val[range->next_val]; - range->next_val++; - return (1); /* more values to come */ - } - - return (0); -} - -static int -run_one(cmd_args_t *args, uint32_t id, uint32_t T, uint32_t N, - uint64_t C, uint64_t S, uint64_t O, uint64_t B) -{ - zpios_cmd_t *cmd; - int rc, rc2, cmd_size; - - dev_clear(); - - cmd_size = sizeof (zpios_cmd_t) + - ((T + N + 1) * sizeof (zpios_stats_t)); - cmd = (zpios_cmd_t *)malloc(cmd_size); - if (cmd == NULL) - return (ENOMEM); - - memset(cmd, 0, cmd_size); - cmd->cmd_magic = ZPIOS_CMD_MAGIC; - strncpy(cmd->cmd_pool, args->pool, ZPIOS_NAME_SIZE - 1); - strncpy(cmd->cmd_pre, args->pre, ZPIOS_PATH_SIZE - 1); - strncpy(cmd->cmd_post, args->post, ZPIOS_PATH_SIZE - 1); - strncpy(cmd->cmd_log, args->log, ZPIOS_PATH_SIZE - 1); - cmd->cmd_id = id; - cmd->cmd_chunk_size = C; - cmd->cmd_thread_count = T; - cmd->cmd_region_count = N; - cmd->cmd_region_size = S; - cmd->cmd_offset = O; - cmd->cmd_block_size = B; - cmd->cmd_region_noise = args->regionnoise; - cmd->cmd_chunk_noise = args->chunknoise; - cmd->cmd_thread_delay = args->thread_delay; - cmd->cmd_flags = args->flags; - cmd->cmd_data_size = (T + N + 1) * sizeof (zpios_stats_t); - - rc = ioctl(zpiosctl_fd, ZPIOS_CMD, cmd); - if (rc) - args->rc = errno; - - print_stats(args, cmd); - - if (args->verbose) { - rc2 = read(zpiosctl_fd, zpios_buffer, zpios_buffer_size); - zpios_buffer[zpios_buffer_size - 1] = '\0'; - if (rc2 < 0) { - fprintf(stdout, "Error reading results: %d\n", rc2); - } else if ((rc2 > 0) && (strlen(zpios_buffer) > 0)) { - fprintf(stdout, "\n%s\n", zpios_buffer); - fflush(stdout); - } - } - - free(cmd); - - return (rc); -} - -static int -run_offsets(cmd_args_t *args) -{ - int rc = 0; - - while (rc == 0 && get_next(&args->current_O, &args->O)) { - rc = run_one(args, args->current_id, - args->current_T, args->current_N, args->current_C, - args->current_S, args->current_O, args->current_B); - args->current_id++; - } - - args->O.next_val = 0; - return (rc); -} - -static int -run_region_counts(cmd_args_t *args) -{ - int rc = 0; - - while (rc == 0 && get_next((uint64_t *)&args->current_N, &args->N)) - rc = run_offsets(args); - - args->N.next_val = 0; - return (rc); -} - -static int -run_region_sizes(cmd_args_t *args) -{ - int rc = 0; - - while (rc == 0 && get_next(&args->current_S, &args->S)) { - if (args->current_S < args->current_C) { - fprintf(stderr, "Error: in any run chunksize must " - "be strictly smaller than regionsize.\n"); - return (EINVAL); - } - - rc = run_region_counts(args); - } - - args->S.next_val = 0; - return (rc); -} - -static int -run_chunk_sizes(cmd_args_t *args) -{ - int rc = 0; - - while (rc == 0 && get_next(&args->current_C, &args->C)) { - rc = run_region_sizes(args); - } - - args->C.next_val = 0; - return (rc); -} - -static int -run_block_sizes(cmd_args_t *args) -{ - int rc = 0; - - while (rc == 0 && get_next(&args->current_B, &args->B)) { - rc = run_chunk_sizes(args); - } - - args->B.next_val = 0; - return (rc); -} - - -static int -run_thread_counts(cmd_args_t *args) -{ - int rc = 0; - - while (rc == 0 && get_next((uint64_t *)&args->current_T, &args->T)) - rc = run_block_sizes(args); - - return (rc); -} - -int -main(int argc, char **argv) -{ - cmd_args_t *args; - int rc = 0; - - /* Argument init and parsing */ - if ((args = args_init(argc, argv)) == NULL) { - rc = -1; - goto out; - } - - /* Device specific init */ - if ((rc = dev_init())) - goto out; - - /* Generic kernel version string */ - if (args->verbose) - fprintf(stdout, "%s", zpios_version); - - print_stats_header(args); - rc = run_thread_counts(args); -out: - if (args != NULL) - args_fini(args); - - dev_fini(); - return (rc); -} diff --git a/cmd/zpios/zpios_util.c b/cmd/zpios/zpios_util.c deleted file mode 100644 index 77ca70f78..000000000 --- a/cmd/zpios/zpios_util.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - * ZPIOS is a heavily modified version of the original PIOS test code. - * It is designed to have the test code running in the Linux kernel - * against ZFS while still being flexibly controlled from user space. - * - * Copyright (C) 2008-2010 Lawrence Livermore National Security, LLC. - * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). - * Written by Brian Behlendorf <[email protected]>. - * LLNL-CODE-403049 - * - * Original PIOS Test Code - * Copyright (C) 2004 Cluster File Systems, Inc. - * Written by Peter Braam <[email protected]> - * Atul Vidwansa <[email protected]> - * Milind Dumbare <[email protected]> - * - * This file is part of ZFS on Linux. - * For details, see <http://zfsonlinux.org/>. - * - * ZPIOS is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * ZPIOS is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with ZPIOS. If not, see <http://www.gnu.org/licenses/>. - * - * Copyright (c) 2015, Intel Corporation. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <regex.h> -#include "zpios.h" - -/* extracts an unsigned int (64) and K,M,G,T from the string */ -/* and returns a 64 bit value converted to the proper units */ -static int -kmgt_to_uint64(const char *str, uint64_t *val) -{ - char *endptr; - int rc = 0; - - *val = strtoll(str, &endptr, 0); - if ((str == endptr) && (*val == 0)) - return (EINVAL); - - switch (endptr[0]) { - case 'k': case 'K': - *val = (*val) << 10; - break; - case 'm': case 'M': - *val = (*val) << 20; - break; - case 'g': case 'G': - *val = (*val) << 30; - break; - case 't': case 'T': - *val = (*val) << 40; - break; - case '\0': - break; - default: - rc = EINVAL; - } - - return (rc); -} - -static char * -uint64_to_kmgt(char *str, uint64_t val) -{ - char postfix[] = "kmgt"; - int i = -1; - - while ((val >= KB) && (i < 4)) { - val = (val >> 10); - i++; - } - - if (i >= 4) - (void) snprintf(str, KMGT_SIZE-1, "inf"); - else - (void) snprintf(str, KMGT_SIZE-1, "%lu%c", (unsigned long)val, - (i == -1) ? '\0' : postfix[i]); - - return (str); -} - -static char * -kmgt_per_sec(char *str, uint64_t v, double t) -{ - char postfix[] = "kmgt"; - double val = ((double)v) / t; - int i = -1; - - while ((val >= (double)KB) && (i < 4)) { - val /= (double)KB; - i++; - } - - if (i >= 4) - (void) snprintf(str, KMGT_SIZE-1, "inf"); - else - (void) snprintf(str, KMGT_SIZE-1, "%.2f%c", val, - (i == -1) ? '\0' : postfix[i]); - - return (str); -} - -static char * -print_flags(char *str, uint32_t flags) -{ - str[0] = (flags & DMU_WRITE) ? 'w' : '-'; - str[1] = (flags & DMU_READ) ? 'r' : '-'; - str[2] = (flags & DMU_VERIFY) ? 'v' : '-'; - str[3] = (flags & DMU_REMOVE) ? 'c' : '-'; - str[4] = (flags & DMU_FPP) ? 'p' : 's'; - str[5] = (flags & (DMU_WRITE_ZC | DMU_READ_ZC)) ? 'z' : '-'; - str[6] = (flags & DMU_WRITE_NOWAIT) ? 'O' : '-'; - str[7] = '\0'; - - return (str); -} - -static int -regex_match(const char *string, char *pattern) -{ - regex_t re = { 0 }; - int rc; - - rc = regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB | REG_ICASE); - if (rc) { - fprintf(stderr, "Error: Couldn't do regcomp, %d\n", rc); - return (rc); - } - - rc = regexec(&re, string, (size_t)0, NULL, 0); - regfree(&re); - - return (rc); -} - -/* fills the pios_range_repeat structure of comma separated values */ -static int -split_string(const char *optarg, char *pattern, range_repeat_t *range) -{ - const char comma[] = ","; - char *cp, *token[32]; - int rc, i = 0; - - if ((rc = regex_match(optarg, pattern))) - return (rc); - - cp = strdup(optarg); - if (cp == NULL) - return (ENOMEM); - - do { - /* - * STRTOK(3) Each subsequent call, with a null pointer as the - * value of the * first argument, starts searching from the - * saved pointer and behaves as described above. - */ - if (i == 0) { - token[i] = strtok(cp, comma); - } else { - token[i] = strtok(NULL, comma); - } - } while ((token[i++] != NULL) && (i < 32)); - - range->val_count = i - 1; - - for (i = 0; i < range->val_count; i++) - kmgt_to_uint64(token[i], &range->val[i]); - - free(cp); - return (0); -} - -int -set_count(char *pattern1, char *pattern2, range_repeat_t *range, - char *optarg, uint32_t *flags, char *arg) -{ - uint64_t count = range->val_count; - - if (flags) - *flags |= FLAG_SET; - - range->next_val = 0; - - if (regex_match(optarg, pattern1) == 0) { - kmgt_to_uint64(optarg, &range->val[0]); - range->val_count = 1; - } else if (split_string(optarg, pattern2, range) < 0) { - fprintf(stderr, "Error: Incorrect pattern for %s, '%s'\n", - arg, optarg); - return (EINVAL); - } else if (count == range->val_count) { - fprintf(stderr, "Error: input ignored for %s, '%s'\n", - arg, optarg); - } - - return (0); -} - -/* - * Validates the value with regular expression and sets low, high, incr - * according to value at which flag will be set. Sets the flag after. - */ -int -set_lhi(char *pattern, range_repeat_t *range, char *optarg, - int flag, uint32_t *flag_thread, char *arg) -{ - int rc; - - if ((rc = regex_match(optarg, pattern))) { - fprintf(stderr, "Error: Wrong pattern in %s, '%s'\n", - arg, optarg); - return (rc); - } - - switch (flag) { - case FLAG_LOW: - kmgt_to_uint64(optarg, &range->val_low); - break; - case FLAG_HIGH: - kmgt_to_uint64(optarg, &range->val_high); - break; - case FLAG_INCR: - kmgt_to_uint64(optarg, &range->val_inc_perc); - break; - default: - assert(0); - } - - *flag_thread |= flag; - - return (0); -} - -int -set_noise(uint64_t *noise, char *optarg, char *arg) -{ - if (regex_match(optarg, REGEX_NUMBERS) == 0) { - kmgt_to_uint64(optarg, noise); - } else { - fprintf(stderr, "Error: Incorrect pattern for %s\n", arg); - return (EINVAL); - } - - return (0); -} - -int -set_load_params(cmd_args_t *args, char *optarg) -{ - char *param, *search, *searchdup, comma[] = ","; - int rc = 0; - - search = strdup(optarg); - if (search == NULL) - return (ENOMEM); - searchdup = search; - - while ((param = strtok(search, comma)) != NULL) { - search = NULL; - - if (strcmp("fpp", param) == 0) { - args->flags |= DMU_FPP; /* File Per Process/Thread */ - } else if (strcmp("ssf", param) == 0) { - args->flags &= ~DMU_FPP; /* Single Shared File */ - } else if (strcmp("dmuio", param) == 0) { - args->io_type |= DMU_IO; - args->flags |= (DMU_WRITE | DMU_READ); - } else { - fprintf(stderr, "Invalid load: %s\n", param); - rc = EINVAL; - } - } - - free(searchdup); - - return (rc); -} - - -/* - * Checks the low, high, increment values against the single value for - * mutual exclusion, for e.g threadcount is mutually exclusive to - * threadcount_low, ..._high, ..._incr - */ -int -check_mutual_exclusive_command_lines(uint32_t flag, char *arg) -{ - if ((flag & FLAG_SET) && (flag & (FLAG_LOW | FLAG_HIGH | FLAG_INCR))) { - fprintf(stderr, "Error: --%s can not be given with --%s_low, " - "--%s_high or --%s_incr.\n", arg, arg, arg, arg); - return (0); - } - - if ((flag & (FLAG_LOW | FLAG_HIGH | FLAG_INCR)) && !(flag & FLAG_SET)) { - if (flag != (FLAG_LOW | FLAG_HIGH | FLAG_INCR)) { - fprintf(stderr, "Error: One or more values missing " - "from --%s_low, --%s_high, --%s_incr.\n", - arg, arg, arg); - return (0); - } - } - - return (1); -} - -void -print_stats_header(cmd_args_t *args) -{ - if (args->verbose) { - printf( - "status name id\tth-cnt\trg-cnt\trg-sz\t" - "ch-sz\toffset\trg-no\tch-no\tth-dly\tflags\tblksz\ttime\t" - "cr-time\trm-time\twr-time\trd-time\twr-data\twr-ch\t" - "wr-bw\trd-data\trd-ch\trd-bw\n"); - printf( - "-------------------------------------------------" - "-------------------------------------------------" - "-------------------------------------------------" - "--------------------------------------------------\n"); - } else { - printf( - "status name id\t" - "wr-data\twr-ch\twr-bw\t" - "rd-data\trd-ch\trd-bw\n"); - printf( - "-----------------------------------------" - "--------------------------------------\n"); - } -} - -static void -print_stats_human_readable(cmd_args_t *args, zpios_cmd_t *cmd) -{ - zpios_stats_t *summary_stats; - double t_time, wr_time, rd_time, cr_time, rm_time; - char str[KMGT_SIZE]; - - if (args->rc) - printf("FAIL: %3d ", args->rc); - else - printf("PASS: "); - - printf("%-12s", args->name ? args->name : ZPIOS_NAME); - printf("%2u\t", cmd->cmd_id); - - if (args->verbose) { - printf("%u\t", cmd->cmd_thread_count); - printf("%u\t", cmd->cmd_region_count); - printf("%s\t", uint64_to_kmgt(str, cmd->cmd_region_size)); - printf("%s\t", uint64_to_kmgt(str, cmd->cmd_chunk_size)); - printf("%s\t", uint64_to_kmgt(str, cmd->cmd_offset)); - printf("%s\t", uint64_to_kmgt(str, cmd->cmd_region_noise)); - printf("%s\t", uint64_to_kmgt(str, cmd->cmd_chunk_noise)); - printf("%s\t", uint64_to_kmgt(str, cmd->cmd_thread_delay)); - printf("%s\t", print_flags(str, cmd->cmd_flags)); - printf("%s\t", uint64_to_kmgt(str, cmd->cmd_block_size)); - } - - if (args->rc) { - printf("\n"); - return; - } - - summary_stats = (zpios_stats_t *)cmd->cmd_data_str; - t_time = zpios_timespec_to_double(summary_stats->total_time.delta); - wr_time = zpios_timespec_to_double(summary_stats->wr_time.delta); - rd_time = zpios_timespec_to_double(summary_stats->rd_time.delta); - cr_time = zpios_timespec_to_double(summary_stats->cr_time.delta); - rm_time = zpios_timespec_to_double(summary_stats->rm_time.delta); - - if (args->verbose) { - printf("%.2f\t", t_time); - printf("%.3f\t", cr_time); - printf("%.3f\t", rm_time); - printf("%.2f\t", wr_time); - printf("%.2f\t", rd_time); - } - - printf("%s\t", uint64_to_kmgt(str, summary_stats->wr_data)); - printf("%s\t", uint64_to_kmgt(str, summary_stats->wr_chunks)); - printf("%s\t", kmgt_per_sec(str, summary_stats->wr_data, wr_time)); - - printf("%s\t", uint64_to_kmgt(str, summary_stats->rd_data)); - printf("%s\t", uint64_to_kmgt(str, summary_stats->rd_chunks)); - printf("%s\n", kmgt_per_sec(str, summary_stats->rd_data, rd_time)); - fflush(stdout); -} - -static void -print_stats_table(cmd_args_t *args, zpios_cmd_t *cmd) -{ - zpios_stats_t *summary_stats; - double wr_time, rd_time; - - if (args->rc) - printf("FAIL: %3d ", args->rc); - else - printf("PASS: "); - - printf("%-12s", args->name ? args->name : ZPIOS_NAME); - printf("%2u\t", cmd->cmd_id); - - if (args->verbose) { - printf("%u\t", cmd->cmd_thread_count); - printf("%u\t", cmd->cmd_region_count); - printf("%llu\t", (long long unsigned)cmd->cmd_region_size); - printf("%llu\t", (long long unsigned)cmd->cmd_chunk_size); - printf("%llu\t", (long long unsigned)cmd->cmd_offset); - printf("%u\t", cmd->cmd_region_noise); - printf("%u\t", cmd->cmd_chunk_noise); - printf("%u\t", cmd->cmd_thread_delay); - printf("0x%x\t", cmd->cmd_flags); - printf("%u\t", cmd->cmd_block_size); - } - - if (args->rc) { - printf("\n"); - return; - } - - summary_stats = (zpios_stats_t *)cmd->cmd_data_str; - wr_time = zpios_timespec_to_double(summary_stats->wr_time.delta); - rd_time = zpios_timespec_to_double(summary_stats->rd_time.delta); - - if (args->verbose) { - printf("%ld.%02ld\t", - (long)summary_stats->total_time.delta.ts_sec, - (long)summary_stats->total_time.delta.ts_nsec); - printf("%ld.%02ld\t", - (long)summary_stats->cr_time.delta.ts_sec, - (long)summary_stats->cr_time.delta.ts_nsec); - printf("%ld.%02ld\t", - (long)summary_stats->rm_time.delta.ts_sec, - (long)summary_stats->rm_time.delta.ts_nsec); - printf("%ld.%02ld\t", - (long)summary_stats->wr_time.delta.ts_sec, - (long)summary_stats->wr_time.delta.ts_nsec); - printf("%ld.%02ld\t", - (long)summary_stats->rd_time.delta.ts_sec, - (long)summary_stats->rd_time.delta.ts_nsec); - } - - printf("%lld\t", (long long unsigned)summary_stats->wr_data); - printf("%lld\t", (long long unsigned)summary_stats->wr_chunks); - printf("%.4f\t", (double)summary_stats->wr_data / wr_time); - - printf("%lld\t", (long long unsigned)summary_stats->rd_data); - printf("%lld\t", (long long unsigned)summary_stats->rd_chunks); - printf("%.4f\n", (double)summary_stats->rd_data / rd_time); - fflush(stdout); -} - -void -print_stats(cmd_args_t *args, zpios_cmd_t *cmd) -{ - if (args->human_readable) - print_stats_human_readable(args, cmd); - else - print_stats_table(args, cmd); -} |