aboutsummaryrefslogtreecommitdiffstats
path: root/cmd/zpios
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/zpios')
-rw-r--r--cmd/zpios/.gitignore1
-rw-r--r--cmd/zpios/Makefile.am11
-rw-r--r--cmd/zpios/zpios.h127
-rw-r--r--cmd/zpios/zpios_main.c680
-rw-r--r--cmd/zpios/zpios_util.c476
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);
-}