]> granicus.if.org Git - zfs/commitdiff
Add large block support to zpios(1) benchmark
authorDon Brady <don.brady@intel.com>
Thu, 17 Sep 2015 23:55:22 +0000 (17:55 -0600)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 22 Sep 2015 16:13:20 +0000 (09:13 -0700)
As part of the large block support effort, it makes sense to add
support for large blocks to **zpios(1)**. The specifying of a zfs
block size for zpios is optional and will default to 128K if the
block size is not specified.

  `zpios ... -S size | --blocksize size ...`

This will use *size* ZFS blocks for each test, specified as a comma
delimited list with an optional unit suffix. The supported range is
powers of two from 128K through 16M. A range of block sizes can be
tested as follows: `-S 128K,256K,512K,1M`

Example run below
(non realistic results from a VM and output abbreviated for space)

```
 --regioncount=750 --regionsize=8M --chunksize=1M --offset=4K
 --threaddelay=0 --cleanup --human-readable --verbose --cleanup
 --blocksize=128K,256K,512K,1M

 th-cnt  rg-cnt  rg-sz  ch-sz  blksz  wr-data wr-bw   rd-data rd-bw
---------------------------------------------------------------------
 4       750     8m     1m     128k   5g      90.06m  5g      93.37m
 4       750     8m     1m     256k   5g      79.71m  5g      99.81m
 4       750     8m     1m     512k   5g      42.20m  5g      93.14m
 4       750     8m     1m     1m     5g      35.51m  5g      89.36m
 8       750     8m     1m     128k   5g      85.49m  5g      90.81m
 8       750     8m     1m     256k   5g      61.42m  5g      99.24m
 8       750     8m     1m     512k   5g      49.09m  5g     108.78m
 16      750     8m     1m     128k   5g      86.28m  5g      88.73m
 16      750     8m     1m     256k   5g      64.34m  5g      93.47m
 16      750     8m     1m     512k   5g      68.84m  5g     124.47m
 16      750     8m     1m     1m     5g      53.97m  5g      97.20m
---------------------------------------------------------------------
```

Signed-off-by: Don Brady <don.brady@intel.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #3795
Closes #2071

cmd/zpios/zpios.h
cmd/zpios/zpios_main.c
cmd/zpios/zpios_util.c
include/zpios-ctl.h
include/zpios-internal.h
man/man1/zpios.1
module/zpios/pios.c

index 92d96fcbe18842e5386453366bc96f69527865b7..4a69b9e54cefc1bb2eec3f33b36516fd4e03ba08 100644 (file)
@@ -29,6 +29,8 @@
  *
  *  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        VERSION_SIZE            64
 
 /* Regular expressions */
-#define        REGEX_NUMBERS           "^[0-9]*[0-9]$"
+#define        REGEX_NUMBERS           "^[0-9]+$"
 #define        REGEX_NUMBERS_COMMA     "^([0-9]+,)*[0-9]+$"
-#define        REGEX_SIZE              "^[0-9][0-9]*[kmgt]$"
-#define        REGEX_SIZE_COMMA        "^([0-9][0-9]*[kmgt]+,)*[0-9][0-9]*[kmgt]$"
+#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
@@ -82,10 +84,12 @@ typedef struct cmd_args {
        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 */
@@ -105,6 +109,7 @@ typedef struct cmd_args {
        uint64_t current_C;
        uint64_t current_S;
        uint64_t current_O;
+       uint64_t current_B;
 
        uint32_t rc;
 } cmd_args_t;
index 971a886a338eb164ffd4d8e8287405b0b8153cb8..e6e88f60d9407d88ef72a207e95507fe30151462 100644 (file)
@@ -29,6 +29,8 @@
  *
  *  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>
@@ -44,7 +46,7 @@
 
 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:"
-       "L:p:M:xP:R:G:I:N:T:VzOfHv?";
+       "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' },
@@ -66,6 +68,7 @@ static const struct option long_opt[] = {
        {"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' },
@@ -116,6 +119,7 @@ usage(void)
                "       --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"
@@ -143,6 +147,11 @@ static void args_fini(cmd_args_t *args)
        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)
 {
@@ -152,7 +161,8 @@ args_init(int argc, char **argv)
        uint32_t fl_of = 0;
        uint32_t fl_rs = 0;
        uint32_t fl_cs = 0;
-       int c, rc;
+       uint32_t fl_bs = 0;
+       int c, rc, i;
 
        if (argc == 1) {
                usage();
@@ -166,6 +176,11 @@ args_init(int argc, char **argv)
 
        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;
 
@@ -250,6 +265,10 @@ args_init(int argc, char **argv)
                        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;
@@ -339,6 +358,17 @@ args_init(int argc, char **argv)
                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);
 }
 
@@ -480,7 +510,7 @@ get_next(uint64_t *val, range_repeat_t *range)
 
 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 C, uint64_t S, uint64_t O, uint64_t B)
 {
        zpios_cmd_t *cmd;
        int rc, rc2, cmd_size;
@@ -506,6 +536,7 @@ run_one(cmd_args_t *args, uint32_t id, uint32_t T, uint32_t N,
        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;
@@ -541,7 +572,7 @@ run_offsets(cmd_args_t *args)
        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_S, args->current_O, args->current_B);
                args->current_id++;
        }
 
@@ -593,13 +624,27 @@ run_chunk_sizes(cmd_args_t *args)
        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_chunk_sizes(args);
+               rc = run_block_sizes(args);
 
        return (rc);
 }
index b226322b0b4f6192c6547a5bc656b6dfc8a87a82..2d248ed9ae9cf835c22eceb1e752867c3c5ad444 100644 (file)
@@ -29,6 +29,8 @@
  *
  *  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>
@@ -185,6 +187,8 @@ 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;
 
@@ -197,6 +201,9 @@ set_count(char *pattern1, char *pattern2, range_repeat_t *range,
                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);
@@ -314,14 +321,14 @@ 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\ttime\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");
+                   "-------------------------------------------------"
+                   "-------------------------------------------------"
+                   "-------------------------------------------------"
+                   "--------------------------------------------------\n");
        } else {
                printf(
                    "status    name        id\t"
@@ -358,6 +365,7 @@ print_stats_human_readable(cmd_args_t *args, zpios_cmd_t *cmd)
                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) {
@@ -414,6 +422,7 @@ print_stats_table(cmd_args_t *args, zpios_cmd_t *cmd)
                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) {
index 9a47ff91d55c037ed5694ddb0d989e5a7f72d7c6..aee4f0a50125ac02fe29b1800c26940cc9f4aee2 100644 (file)
@@ -29,6 +29,8 @@
  *
  *  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_CTL_H
@@ -116,6 +118,7 @@ typedef struct zpios_cmd {
        uint32_t cmd_chunk_noise;       /* Chunk noise */
        uint32_t cmd_thread_delay;      /* Thread delay */
        uint32_t cmd_flags;             /* Test flags */
+       uint32_t cmd_block_size;        /* ZFS block size */
        char cmd_pre[ZPIOS_PATH_SIZE];  /* Pre-exec hook */
        char cmd_post[ZPIOS_PATH_SIZE]; /* Post-exec hook */
        char cmd_log[ZPIOS_PATH_SIZE];  /* Requested log dir */
index 4b99b4ce31f37a3c72f7768ea1e4989d5542311b..dd2bd2343a42ed3f11babba942ab0b298ca172a2 100644 (file)
@@ -29,6 +29,8 @@
  *
  *  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_INTERNAL_H
@@ -79,6 +81,7 @@ typedef struct run_args {
        __u32 chunk_noise;
        __u32 thread_delay;
        __u32 flags;
+       __u32 block_size;
        char pre[ZPIOS_PATH_SIZE];
        char post[ZPIOS_PATH_SIZE];
        char log[ZPIOS_PATH_SIZE];
index 4b362b09d25d2686c3ff1fbf7e15b6a38a952bf5..4334c03c0436f1d3f190d0b20f31a183068420db 100644 (file)
@@ -22,6 +22,8 @@
 .\"
 .\" Copyright 2013 Darik Horn <dajhorn@vanadac.com>. All rights reserved.
 .\"
+.\" Copyright (c) 2015, Intel Corporation.
+.\"
 .TH zpios 1 "2013 FEB 28" "ZFS on Linux" "User Commands"
 
 .SH NAME
@@ -36,10 +38,10 @@ not depend on the ZFS Posix Layer ("ZPL").
 
 .SH OPTIONS
 .HP
-.BI "\-s" " regex" ", \-\-threadcount" " regex"
+.BI "\-t" " regex" ", \-\-threadcount" " regex"
 .IP
 Start this many threads for each test series, specified as a comma
-delimited regular expression. (eg: "-s 1,2,3")
+delimited regular expression. (eg: "-t 1,2,3")
 .IP
 This option is mutually exclusive with the \fBthreadcount_*\fR
 options.
@@ -120,6 +122,35 @@ chunk size for the last test.
 These three options must be specified together and are mutually
 exclusive with the \fBchunksize\fR option.
 .HP
+.BI "\-s" " size" ", \-\-regionsize" " size"
+.IP
+Use \fIsize\fR regions for each test, specified as a comma delimited
+regular expression with an optional unit suffix. (eg: "-s 1M" means
+one megabyte.)
+.IP
+This option is mutually exclusive with the \fBregionsize_*\fB options.
+.HP
+.BI "\-A" " size_low" ", \-\-regionsize_low" " size_low"
+.HP
+.BI "\-B" " size_high" ", \-\-regionsize_high" " size_high"
+.HP
+.BI "\-C" " size_incr" ", \-\-regionsize_incr" " size_incr"
+.IP
+Use a \fIsize_low\fR region size for the first test, add \fIsize_incr\fR
+to the region size for each subsequent test, and use a \fIsize_high\fR
+region size for the last test.
+.IP
+These three options must be specified together and are mutually
+exclusive with the \fBregionsize\fR option.
+.HP
+.BI "\-S" " size | sizes" ", \-\-blocksize" " size | sizes"
+.IP
+Use \fIsize\fR ZFS blocks for each test, specified as a comma delimited
+regular expression with an optional unit suffix. (eg: "-S 1M" means
+one megabyte.) The supported range is powers of two from 128K through 16M.
+A range of blocks can be tested as follows: "-S 128K,256K,512K,1M".
+.IP
+.HP
 .BI "\-L" " dmu_flags" ", \-\-load" " dmu_flags"
 .IP
 Specify \fIdmuio\fR for regular DMU_IO, \fIssf\fR for single shared
index e3a85c1686e61894f6faedb43889fed3d9917e33..8f4a8fd69b58074971f36303e6c8e0f33248ea2d 100644 (file)
  *
  *  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 <sys/zfs_context.h>
 #include <sys/dmu.h>
+#include <sys/spa.h>
 #include <sys/txg.h>
 #include <sys/dsl_destroy.h>
 #include <linux/miscdevice.h>
@@ -129,8 +132,17 @@ zpios_dmu_object_create(run_args_t *run_args, objset_t *os)
 {
        struct dmu_tx *tx;
        uint64_t obj = 0ULL;
+       uint64_t blksize = run_args->block_size;
        int rc;
 
+       if (blksize < SPA_MINBLOCKSIZE ||
+           blksize > spa_maxblocksize(dmu_objset_spa(os)) ||
+           !ISP2(blksize)) {
+               zpios_print(run_args->file,
+                   "invalid block size for pool: %d\n", (int)blksize);
+               return (obj);
+       }
+
        tx = dmu_tx_create(os);
        dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, OBJ_SIZE);
        rc = dmu_tx_assign(tx, TXG_WAIT);
@@ -142,10 +154,11 @@ zpios_dmu_object_create(run_args_t *run_args, objset_t *os)
        }
 
        obj = dmu_object_alloc(os, DMU_OT_UINT64_OTHER, 0, DMU_OT_NONE, 0, tx);
-       rc = dmu_object_set_blocksize(os, obj, 128ULL << 10, 0, tx);
+       rc = dmu_object_set_blocksize(os, obj, blksize, 0, tx);
        if (rc) {
                zpios_print(run_args->file,
-                           "dmu_object_set_blocksize() failed: %d\n", rc);
+                   "dmu_object_set_blocksize to %d failed: %d\n",
+                   (int)blksize, rc);
                dmu_tx_abort(tx);
                return (obj);
        }
@@ -295,6 +308,7 @@ zpios_setup_run(run_args_t **run_args, zpios_cmd_t *kcmd, struct file *file)
        ra->chunk_noise         = kcmd->cmd_chunk_noise;
        ra->thread_delay        = kcmd->cmd_thread_delay;
        ra->flags               = kcmd->cmd_flags;
+       ra->block_size          = kcmd->cmd_block_size;
        ra->stats.wr_data       = 0;
        ra->stats.wr_chunks     = 0;
        ra->stats.rd_data       = 0;