1*eda14cbcSMatt Macy /* 2*eda14cbcSMatt Macy * CDDL HEADER START 3*eda14cbcSMatt Macy * 4*eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5*eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6*eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7*eda14cbcSMatt Macy * 8*eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*eda14cbcSMatt Macy * or http://www.opensolaris.org/os/licensing. 10*eda14cbcSMatt Macy * See the License for the specific language governing permissions 11*eda14cbcSMatt Macy * and limitations under the License. 12*eda14cbcSMatt Macy * 13*eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14*eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16*eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17*eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18*eda14cbcSMatt Macy * 19*eda14cbcSMatt Macy * CDDL HEADER END 20*eda14cbcSMatt Macy */ 21*eda14cbcSMatt Macy 22*eda14cbcSMatt Macy /* 23*eda14cbcSMatt Macy * Copyright (C) 2016 Gvozden Nešković. All rights reserved. 24*eda14cbcSMatt Macy */ 25*eda14cbcSMatt Macy 26*eda14cbcSMatt Macy #include <sys/zfs_context.h> 27*eda14cbcSMatt Macy #include <sys/time.h> 28*eda14cbcSMatt Macy #include <sys/wait.h> 29*eda14cbcSMatt Macy #include <sys/zio.h> 30*eda14cbcSMatt Macy #include <umem.h> 31*eda14cbcSMatt Macy #include <sys/vdev_raidz.h> 32*eda14cbcSMatt Macy #include <sys/vdev_raidz_impl.h> 33*eda14cbcSMatt Macy #include <assert.h> 34*eda14cbcSMatt Macy #include <stdio.h> 35*eda14cbcSMatt Macy #include "raidz_test.h" 36*eda14cbcSMatt Macy 37*eda14cbcSMatt Macy static int *rand_data; 38*eda14cbcSMatt Macy raidz_test_opts_t rto_opts; 39*eda14cbcSMatt Macy 40*eda14cbcSMatt Macy static char gdb[256]; 41*eda14cbcSMatt Macy static const char gdb_tmpl[] = "gdb -ex \"set pagination 0\" -p %d"; 42*eda14cbcSMatt Macy 43*eda14cbcSMatt Macy static void sig_handler(int signo) 44*eda14cbcSMatt Macy { 45*eda14cbcSMatt Macy struct sigaction action; 46*eda14cbcSMatt Macy /* 47*eda14cbcSMatt Macy * Restore default action and re-raise signal so SIGSEGV and 48*eda14cbcSMatt Macy * SIGABRT can trigger a core dump. 49*eda14cbcSMatt Macy */ 50*eda14cbcSMatt Macy action.sa_handler = SIG_DFL; 51*eda14cbcSMatt Macy sigemptyset(&action.sa_mask); 52*eda14cbcSMatt Macy action.sa_flags = 0; 53*eda14cbcSMatt Macy (void) sigaction(signo, &action, NULL); 54*eda14cbcSMatt Macy 55*eda14cbcSMatt Macy if (rto_opts.rto_gdb) 56*eda14cbcSMatt Macy if (system(gdb)) { } 57*eda14cbcSMatt Macy 58*eda14cbcSMatt Macy raise(signo); 59*eda14cbcSMatt Macy } 60*eda14cbcSMatt Macy 61*eda14cbcSMatt Macy static void print_opts(raidz_test_opts_t *opts, boolean_t force) 62*eda14cbcSMatt Macy { 63*eda14cbcSMatt Macy char *verbose; 64*eda14cbcSMatt Macy switch (opts->rto_v) { 65*eda14cbcSMatt Macy case 0: 66*eda14cbcSMatt Macy verbose = "no"; 67*eda14cbcSMatt Macy break; 68*eda14cbcSMatt Macy case 1: 69*eda14cbcSMatt Macy verbose = "info"; 70*eda14cbcSMatt Macy break; 71*eda14cbcSMatt Macy default: 72*eda14cbcSMatt Macy verbose = "debug"; 73*eda14cbcSMatt Macy break; 74*eda14cbcSMatt Macy } 75*eda14cbcSMatt Macy 76*eda14cbcSMatt Macy if (force || opts->rto_v >= D_INFO) { 77*eda14cbcSMatt Macy (void) fprintf(stdout, DBLSEP "Running with options:\n" 78*eda14cbcSMatt Macy " (-a) zio ashift : %zu\n" 79*eda14cbcSMatt Macy " (-o) zio offset : 1 << %zu\n" 80*eda14cbcSMatt Macy " (-d) number of raidz data columns : %zu\n" 81*eda14cbcSMatt Macy " (-s) size of DATA : 1 << %zu\n" 82*eda14cbcSMatt Macy " (-S) sweep parameters : %s \n" 83*eda14cbcSMatt Macy " (-v) verbose : %s \n\n", 84*eda14cbcSMatt Macy opts->rto_ashift, /* -a */ 85*eda14cbcSMatt Macy ilog2(opts->rto_offset), /* -o */ 86*eda14cbcSMatt Macy opts->rto_dcols, /* -d */ 87*eda14cbcSMatt Macy ilog2(opts->rto_dsize), /* -s */ 88*eda14cbcSMatt Macy opts->rto_sweep ? "yes" : "no", /* -S */ 89*eda14cbcSMatt Macy verbose); /* -v */ 90*eda14cbcSMatt Macy } 91*eda14cbcSMatt Macy } 92*eda14cbcSMatt Macy 93*eda14cbcSMatt Macy static void usage(boolean_t requested) 94*eda14cbcSMatt Macy { 95*eda14cbcSMatt Macy const raidz_test_opts_t *o = &rto_opts_defaults; 96*eda14cbcSMatt Macy 97*eda14cbcSMatt Macy FILE *fp = requested ? stdout : stderr; 98*eda14cbcSMatt Macy 99*eda14cbcSMatt Macy (void) fprintf(fp, "Usage:\n" 100*eda14cbcSMatt Macy "\t[-a zio ashift (default: %zu)]\n" 101*eda14cbcSMatt Macy "\t[-o zio offset, exponent radix 2 (default: %zu)]\n" 102*eda14cbcSMatt Macy "\t[-d number of raidz data columns (default: %zu)]\n" 103*eda14cbcSMatt Macy "\t[-s zio size, exponent radix 2 (default: %zu)]\n" 104*eda14cbcSMatt Macy "\t[-S parameter sweep (default: %s)]\n" 105*eda14cbcSMatt Macy "\t[-t timeout for parameter sweep test]\n" 106*eda14cbcSMatt Macy "\t[-B benchmark all raidz implementations]\n" 107*eda14cbcSMatt Macy "\t[-v increase verbosity (default: %zu)]\n" 108*eda14cbcSMatt Macy "\t[-h (print help)]\n" 109*eda14cbcSMatt Macy "\t[-T test the test, see if failure would be detected]\n" 110*eda14cbcSMatt Macy "\t[-D debug (attach gdb on SIGSEGV)]\n" 111*eda14cbcSMatt Macy "", 112*eda14cbcSMatt Macy o->rto_ashift, /* -a */ 113*eda14cbcSMatt Macy ilog2(o->rto_offset), /* -o */ 114*eda14cbcSMatt Macy o->rto_dcols, /* -d */ 115*eda14cbcSMatt Macy ilog2(o->rto_dsize), /* -s */ 116*eda14cbcSMatt Macy rto_opts.rto_sweep ? "yes" : "no", /* -S */ 117*eda14cbcSMatt Macy o->rto_v); /* -d */ 118*eda14cbcSMatt Macy 119*eda14cbcSMatt Macy exit(requested ? 0 : 1); 120*eda14cbcSMatt Macy } 121*eda14cbcSMatt Macy 122*eda14cbcSMatt Macy static void process_options(int argc, char **argv) 123*eda14cbcSMatt Macy { 124*eda14cbcSMatt Macy size_t value; 125*eda14cbcSMatt Macy int opt; 126*eda14cbcSMatt Macy 127*eda14cbcSMatt Macy raidz_test_opts_t *o = &rto_opts; 128*eda14cbcSMatt Macy 129*eda14cbcSMatt Macy bcopy(&rto_opts_defaults, o, sizeof (*o)); 130*eda14cbcSMatt Macy 131*eda14cbcSMatt Macy while ((opt = getopt(argc, argv, "TDBSvha:o:d:s:t:")) != -1) { 132*eda14cbcSMatt Macy value = 0; 133*eda14cbcSMatt Macy 134*eda14cbcSMatt Macy switch (opt) { 135*eda14cbcSMatt Macy case 'a': 136*eda14cbcSMatt Macy value = strtoull(optarg, NULL, 0); 137*eda14cbcSMatt Macy o->rto_ashift = MIN(13, MAX(9, value)); 138*eda14cbcSMatt Macy break; 139*eda14cbcSMatt Macy case 'o': 140*eda14cbcSMatt Macy value = strtoull(optarg, NULL, 0); 141*eda14cbcSMatt Macy o->rto_offset = ((1ULL << MIN(12, value)) >> 9) << 9; 142*eda14cbcSMatt Macy break; 143*eda14cbcSMatt Macy case 'd': 144*eda14cbcSMatt Macy value = strtoull(optarg, NULL, 0); 145*eda14cbcSMatt Macy o->rto_dcols = MIN(255, MAX(1, value)); 146*eda14cbcSMatt Macy break; 147*eda14cbcSMatt Macy case 's': 148*eda14cbcSMatt Macy value = strtoull(optarg, NULL, 0); 149*eda14cbcSMatt Macy o->rto_dsize = 1ULL << MIN(SPA_MAXBLOCKSHIFT, 150*eda14cbcSMatt Macy MAX(SPA_MINBLOCKSHIFT, value)); 151*eda14cbcSMatt Macy break; 152*eda14cbcSMatt Macy case 't': 153*eda14cbcSMatt Macy value = strtoull(optarg, NULL, 0); 154*eda14cbcSMatt Macy o->rto_sweep_timeout = value; 155*eda14cbcSMatt Macy break; 156*eda14cbcSMatt Macy case 'v': 157*eda14cbcSMatt Macy o->rto_v++; 158*eda14cbcSMatt Macy break; 159*eda14cbcSMatt Macy case 'S': 160*eda14cbcSMatt Macy o->rto_sweep = 1; 161*eda14cbcSMatt Macy break; 162*eda14cbcSMatt Macy case 'B': 163*eda14cbcSMatt Macy o->rto_benchmark = 1; 164*eda14cbcSMatt Macy break; 165*eda14cbcSMatt Macy case 'D': 166*eda14cbcSMatt Macy o->rto_gdb = 1; 167*eda14cbcSMatt Macy break; 168*eda14cbcSMatt Macy case 'T': 169*eda14cbcSMatt Macy o->rto_sanity = 1; 170*eda14cbcSMatt Macy break; 171*eda14cbcSMatt Macy case 'h': 172*eda14cbcSMatt Macy usage(B_TRUE); 173*eda14cbcSMatt Macy break; 174*eda14cbcSMatt Macy case '?': 175*eda14cbcSMatt Macy default: 176*eda14cbcSMatt Macy usage(B_FALSE); 177*eda14cbcSMatt Macy break; 178*eda14cbcSMatt Macy } 179*eda14cbcSMatt Macy } 180*eda14cbcSMatt Macy } 181*eda14cbcSMatt Macy 182*eda14cbcSMatt Macy #define DATA_COL(rm, i) ((rm)->rm_col[raidz_parity(rm) + (i)].rc_abd) 183*eda14cbcSMatt Macy #define DATA_COL_SIZE(rm, i) ((rm)->rm_col[raidz_parity(rm) + (i)].rc_size) 184*eda14cbcSMatt Macy 185*eda14cbcSMatt Macy #define CODE_COL(rm, i) ((rm)->rm_col[(i)].rc_abd) 186*eda14cbcSMatt Macy #define CODE_COL_SIZE(rm, i) ((rm)->rm_col[(i)].rc_size) 187*eda14cbcSMatt Macy 188*eda14cbcSMatt Macy static int 189*eda14cbcSMatt Macy cmp_code(raidz_test_opts_t *opts, const raidz_map_t *rm, const int parity) 190*eda14cbcSMatt Macy { 191*eda14cbcSMatt Macy int i, ret = 0; 192*eda14cbcSMatt Macy 193*eda14cbcSMatt Macy VERIFY(parity >= 1 && parity <= 3); 194*eda14cbcSMatt Macy 195*eda14cbcSMatt Macy for (i = 0; i < parity; i++) { 196*eda14cbcSMatt Macy if (abd_cmp(CODE_COL(rm, i), CODE_COL(opts->rm_golden, i)) 197*eda14cbcSMatt Macy != 0) { 198*eda14cbcSMatt Macy ret++; 199*eda14cbcSMatt Macy LOG_OPT(D_DEBUG, opts, 200*eda14cbcSMatt Macy "\nParity block [%d] different!\n", i); 201*eda14cbcSMatt Macy } 202*eda14cbcSMatt Macy } 203*eda14cbcSMatt Macy return (ret); 204*eda14cbcSMatt Macy } 205*eda14cbcSMatt Macy 206*eda14cbcSMatt Macy static int 207*eda14cbcSMatt Macy cmp_data(raidz_test_opts_t *opts, raidz_map_t *rm) 208*eda14cbcSMatt Macy { 209*eda14cbcSMatt Macy int i, ret = 0; 210*eda14cbcSMatt Macy int dcols = opts->rm_golden->rm_cols - raidz_parity(opts->rm_golden); 211*eda14cbcSMatt Macy 212*eda14cbcSMatt Macy for (i = 0; i < dcols; i++) { 213*eda14cbcSMatt Macy if (abd_cmp(DATA_COL(opts->rm_golden, i), DATA_COL(rm, i)) 214*eda14cbcSMatt Macy != 0) { 215*eda14cbcSMatt Macy ret++; 216*eda14cbcSMatt Macy 217*eda14cbcSMatt Macy LOG_OPT(D_DEBUG, opts, 218*eda14cbcSMatt Macy "\nData block [%d] different!\n", i); 219*eda14cbcSMatt Macy } 220*eda14cbcSMatt Macy } 221*eda14cbcSMatt Macy return (ret); 222*eda14cbcSMatt Macy } 223*eda14cbcSMatt Macy 224*eda14cbcSMatt Macy static int 225*eda14cbcSMatt Macy init_rand(void *data, size_t size, void *private) 226*eda14cbcSMatt Macy { 227*eda14cbcSMatt Macy int i; 228*eda14cbcSMatt Macy int *dst = (int *)data; 229*eda14cbcSMatt Macy 230*eda14cbcSMatt Macy for (i = 0; i < size / sizeof (int); i++) 231*eda14cbcSMatt Macy dst[i] = rand_data[i]; 232*eda14cbcSMatt Macy 233*eda14cbcSMatt Macy return (0); 234*eda14cbcSMatt Macy } 235*eda14cbcSMatt Macy 236*eda14cbcSMatt Macy static void 237*eda14cbcSMatt Macy corrupt_colums(raidz_map_t *rm, const int *tgts, const int cnt) 238*eda14cbcSMatt Macy { 239*eda14cbcSMatt Macy int i; 240*eda14cbcSMatt Macy raidz_col_t *col; 241*eda14cbcSMatt Macy 242*eda14cbcSMatt Macy for (i = 0; i < cnt; i++) { 243*eda14cbcSMatt Macy col = &rm->rm_col[tgts[i]]; 244*eda14cbcSMatt Macy abd_iterate_func(col->rc_abd, 0, col->rc_size, init_rand, NULL); 245*eda14cbcSMatt Macy } 246*eda14cbcSMatt Macy } 247*eda14cbcSMatt Macy 248*eda14cbcSMatt Macy void 249*eda14cbcSMatt Macy init_zio_abd(zio_t *zio) 250*eda14cbcSMatt Macy { 251*eda14cbcSMatt Macy abd_iterate_func(zio->io_abd, 0, zio->io_size, init_rand, NULL); 252*eda14cbcSMatt Macy } 253*eda14cbcSMatt Macy 254*eda14cbcSMatt Macy static void 255*eda14cbcSMatt Macy fini_raidz_map(zio_t **zio, raidz_map_t **rm) 256*eda14cbcSMatt Macy { 257*eda14cbcSMatt Macy vdev_raidz_map_free(*rm); 258*eda14cbcSMatt Macy raidz_free((*zio)->io_abd, (*zio)->io_size); 259*eda14cbcSMatt Macy umem_free(*zio, sizeof (zio_t)); 260*eda14cbcSMatt Macy 261*eda14cbcSMatt Macy *zio = NULL; 262*eda14cbcSMatt Macy *rm = NULL; 263*eda14cbcSMatt Macy } 264*eda14cbcSMatt Macy 265*eda14cbcSMatt Macy static int 266*eda14cbcSMatt Macy init_raidz_golden_map(raidz_test_opts_t *opts, const int parity) 267*eda14cbcSMatt Macy { 268*eda14cbcSMatt Macy int err = 0; 269*eda14cbcSMatt Macy zio_t *zio_test; 270*eda14cbcSMatt Macy raidz_map_t *rm_test; 271*eda14cbcSMatt Macy const size_t total_ncols = opts->rto_dcols + parity; 272*eda14cbcSMatt Macy 273*eda14cbcSMatt Macy if (opts->rm_golden) { 274*eda14cbcSMatt Macy fini_raidz_map(&opts->zio_golden, &opts->rm_golden); 275*eda14cbcSMatt Macy } 276*eda14cbcSMatt Macy 277*eda14cbcSMatt Macy opts->zio_golden = umem_zalloc(sizeof (zio_t), UMEM_NOFAIL); 278*eda14cbcSMatt Macy zio_test = umem_zalloc(sizeof (zio_t), UMEM_NOFAIL); 279*eda14cbcSMatt Macy 280*eda14cbcSMatt Macy opts->zio_golden->io_offset = zio_test->io_offset = opts->rto_offset; 281*eda14cbcSMatt Macy opts->zio_golden->io_size = zio_test->io_size = opts->rto_dsize; 282*eda14cbcSMatt Macy 283*eda14cbcSMatt Macy opts->zio_golden->io_abd = raidz_alloc(opts->rto_dsize); 284*eda14cbcSMatt Macy zio_test->io_abd = raidz_alloc(opts->rto_dsize); 285*eda14cbcSMatt Macy 286*eda14cbcSMatt Macy init_zio_abd(opts->zio_golden); 287*eda14cbcSMatt Macy init_zio_abd(zio_test); 288*eda14cbcSMatt Macy 289*eda14cbcSMatt Macy VERIFY0(vdev_raidz_impl_set("original")); 290*eda14cbcSMatt Macy 291*eda14cbcSMatt Macy opts->rm_golden = vdev_raidz_map_alloc(opts->zio_golden, 292*eda14cbcSMatt Macy opts->rto_ashift, total_ncols, parity); 293*eda14cbcSMatt Macy rm_test = vdev_raidz_map_alloc(zio_test, 294*eda14cbcSMatt Macy opts->rto_ashift, total_ncols, parity); 295*eda14cbcSMatt Macy 296*eda14cbcSMatt Macy VERIFY(opts->zio_golden); 297*eda14cbcSMatt Macy VERIFY(opts->rm_golden); 298*eda14cbcSMatt Macy 299*eda14cbcSMatt Macy vdev_raidz_generate_parity(opts->rm_golden); 300*eda14cbcSMatt Macy vdev_raidz_generate_parity(rm_test); 301*eda14cbcSMatt Macy 302*eda14cbcSMatt Macy /* sanity check */ 303*eda14cbcSMatt Macy err |= cmp_data(opts, rm_test); 304*eda14cbcSMatt Macy err |= cmp_code(opts, rm_test, parity); 305*eda14cbcSMatt Macy 306*eda14cbcSMatt Macy if (err) 307*eda14cbcSMatt Macy ERR("initializing the golden copy ... [FAIL]!\n"); 308*eda14cbcSMatt Macy 309*eda14cbcSMatt Macy /* tear down raidz_map of test zio */ 310*eda14cbcSMatt Macy fini_raidz_map(&zio_test, &rm_test); 311*eda14cbcSMatt Macy 312*eda14cbcSMatt Macy return (err); 313*eda14cbcSMatt Macy } 314*eda14cbcSMatt Macy 315*eda14cbcSMatt Macy static raidz_map_t * 316*eda14cbcSMatt Macy init_raidz_map(raidz_test_opts_t *opts, zio_t **zio, const int parity) 317*eda14cbcSMatt Macy { 318*eda14cbcSMatt Macy raidz_map_t *rm = NULL; 319*eda14cbcSMatt Macy const size_t alloc_dsize = opts->rto_dsize; 320*eda14cbcSMatt Macy const size_t total_ncols = opts->rto_dcols + parity; 321*eda14cbcSMatt Macy const int ccols[] = { 0, 1, 2 }; 322*eda14cbcSMatt Macy 323*eda14cbcSMatt Macy VERIFY(zio); 324*eda14cbcSMatt Macy VERIFY(parity <= 3 && parity >= 1); 325*eda14cbcSMatt Macy 326*eda14cbcSMatt Macy *zio = umem_zalloc(sizeof (zio_t), UMEM_NOFAIL); 327*eda14cbcSMatt Macy 328*eda14cbcSMatt Macy (*zio)->io_offset = 0; 329*eda14cbcSMatt Macy (*zio)->io_size = alloc_dsize; 330*eda14cbcSMatt Macy (*zio)->io_abd = raidz_alloc(alloc_dsize); 331*eda14cbcSMatt Macy init_zio_abd(*zio); 332*eda14cbcSMatt Macy 333*eda14cbcSMatt Macy rm = vdev_raidz_map_alloc(*zio, opts->rto_ashift, 334*eda14cbcSMatt Macy total_ncols, parity); 335*eda14cbcSMatt Macy VERIFY(rm); 336*eda14cbcSMatt Macy 337*eda14cbcSMatt Macy /* Make sure code columns are destroyed */ 338*eda14cbcSMatt Macy corrupt_colums(rm, ccols, parity); 339*eda14cbcSMatt Macy 340*eda14cbcSMatt Macy return (rm); 341*eda14cbcSMatt Macy } 342*eda14cbcSMatt Macy 343*eda14cbcSMatt Macy static int 344*eda14cbcSMatt Macy run_gen_check(raidz_test_opts_t *opts) 345*eda14cbcSMatt Macy { 346*eda14cbcSMatt Macy char **impl_name; 347*eda14cbcSMatt Macy int fn, err = 0; 348*eda14cbcSMatt Macy zio_t *zio_test; 349*eda14cbcSMatt Macy raidz_map_t *rm_test; 350*eda14cbcSMatt Macy 351*eda14cbcSMatt Macy err = init_raidz_golden_map(opts, PARITY_PQR); 352*eda14cbcSMatt Macy if (0 != err) 353*eda14cbcSMatt Macy return (err); 354*eda14cbcSMatt Macy 355*eda14cbcSMatt Macy LOG(D_INFO, DBLSEP); 356*eda14cbcSMatt Macy LOG(D_INFO, "Testing parity generation...\n"); 357*eda14cbcSMatt Macy 358*eda14cbcSMatt Macy for (impl_name = (char **)raidz_impl_names+1; *impl_name != NULL; 359*eda14cbcSMatt Macy impl_name++) { 360*eda14cbcSMatt Macy 361*eda14cbcSMatt Macy LOG(D_INFO, SEP); 362*eda14cbcSMatt Macy LOG(D_INFO, "\tTesting [%s] implementation...", *impl_name); 363*eda14cbcSMatt Macy 364*eda14cbcSMatt Macy if (0 != vdev_raidz_impl_set(*impl_name)) { 365*eda14cbcSMatt Macy LOG(D_INFO, "[SKIP]\n"); 366*eda14cbcSMatt Macy continue; 367*eda14cbcSMatt Macy } else { 368*eda14cbcSMatt Macy LOG(D_INFO, "[SUPPORTED]\n"); 369*eda14cbcSMatt Macy } 370*eda14cbcSMatt Macy 371*eda14cbcSMatt Macy for (fn = 0; fn < RAIDZ_GEN_NUM; fn++) { 372*eda14cbcSMatt Macy 373*eda14cbcSMatt Macy /* Check if should stop */ 374*eda14cbcSMatt Macy if (rto_opts.rto_should_stop) 375*eda14cbcSMatt Macy return (err); 376*eda14cbcSMatt Macy 377*eda14cbcSMatt Macy /* create suitable raidz_map */ 378*eda14cbcSMatt Macy rm_test = init_raidz_map(opts, &zio_test, fn+1); 379*eda14cbcSMatt Macy VERIFY(rm_test); 380*eda14cbcSMatt Macy 381*eda14cbcSMatt Macy LOG(D_INFO, "\t\tTesting method [%s] ...", 382*eda14cbcSMatt Macy raidz_gen_name[fn]); 383*eda14cbcSMatt Macy 384*eda14cbcSMatt Macy if (!opts->rto_sanity) 385*eda14cbcSMatt Macy vdev_raidz_generate_parity(rm_test); 386*eda14cbcSMatt Macy 387*eda14cbcSMatt Macy if (cmp_code(opts, rm_test, fn+1) != 0) { 388*eda14cbcSMatt Macy LOG(D_INFO, "[FAIL]\n"); 389*eda14cbcSMatt Macy err++; 390*eda14cbcSMatt Macy } else 391*eda14cbcSMatt Macy LOG(D_INFO, "[PASS]\n"); 392*eda14cbcSMatt Macy 393*eda14cbcSMatt Macy fini_raidz_map(&zio_test, &rm_test); 394*eda14cbcSMatt Macy } 395*eda14cbcSMatt Macy } 396*eda14cbcSMatt Macy 397*eda14cbcSMatt Macy fini_raidz_map(&opts->zio_golden, &opts->rm_golden); 398*eda14cbcSMatt Macy 399*eda14cbcSMatt Macy return (err); 400*eda14cbcSMatt Macy } 401*eda14cbcSMatt Macy 402*eda14cbcSMatt Macy static int 403*eda14cbcSMatt Macy run_rec_check_impl(raidz_test_opts_t *opts, raidz_map_t *rm, const int fn) 404*eda14cbcSMatt Macy { 405*eda14cbcSMatt Macy int x0, x1, x2; 406*eda14cbcSMatt Macy int tgtidx[3]; 407*eda14cbcSMatt Macy int err = 0; 408*eda14cbcSMatt Macy static const int rec_tgts[7][3] = { 409*eda14cbcSMatt Macy {1, 2, 3}, /* rec_p: bad QR & D[0] */ 410*eda14cbcSMatt Macy {0, 2, 3}, /* rec_q: bad PR & D[0] */ 411*eda14cbcSMatt Macy {0, 1, 3}, /* rec_r: bad PQ & D[0] */ 412*eda14cbcSMatt Macy {2, 3, 4}, /* rec_pq: bad R & D[0][1] */ 413*eda14cbcSMatt Macy {1, 3, 4}, /* rec_pr: bad Q & D[0][1] */ 414*eda14cbcSMatt Macy {0, 3, 4}, /* rec_qr: bad P & D[0][1] */ 415*eda14cbcSMatt Macy {3, 4, 5} /* rec_pqr: bad & D[0][1][2] */ 416*eda14cbcSMatt Macy }; 417*eda14cbcSMatt Macy 418*eda14cbcSMatt Macy memcpy(tgtidx, rec_tgts[fn], sizeof (tgtidx)); 419*eda14cbcSMatt Macy 420*eda14cbcSMatt Macy if (fn < RAIDZ_REC_PQ) { 421*eda14cbcSMatt Macy /* can reconstruct 1 failed data disk */ 422*eda14cbcSMatt Macy for (x0 = 0; x0 < opts->rto_dcols; x0++) { 423*eda14cbcSMatt Macy if (x0 >= rm->rm_cols - raidz_parity(rm)) 424*eda14cbcSMatt Macy continue; 425*eda14cbcSMatt Macy 426*eda14cbcSMatt Macy /* Check if should stop */ 427*eda14cbcSMatt Macy if (rto_opts.rto_should_stop) 428*eda14cbcSMatt Macy return (err); 429*eda14cbcSMatt Macy 430*eda14cbcSMatt Macy LOG(D_DEBUG, "[%d] ", x0); 431*eda14cbcSMatt Macy 432*eda14cbcSMatt Macy tgtidx[2] = x0 + raidz_parity(rm); 433*eda14cbcSMatt Macy 434*eda14cbcSMatt Macy corrupt_colums(rm, tgtidx+2, 1); 435*eda14cbcSMatt Macy 436*eda14cbcSMatt Macy if (!opts->rto_sanity) 437*eda14cbcSMatt Macy vdev_raidz_reconstruct(rm, tgtidx, 3); 438*eda14cbcSMatt Macy 439*eda14cbcSMatt Macy if (cmp_data(opts, rm) != 0) { 440*eda14cbcSMatt Macy err++; 441*eda14cbcSMatt Macy LOG(D_DEBUG, "\nREC D[%d]... [FAIL]\n", x0); 442*eda14cbcSMatt Macy } 443*eda14cbcSMatt Macy } 444*eda14cbcSMatt Macy 445*eda14cbcSMatt Macy } else if (fn < RAIDZ_REC_PQR) { 446*eda14cbcSMatt Macy /* can reconstruct 2 failed data disk */ 447*eda14cbcSMatt Macy for (x0 = 0; x0 < opts->rto_dcols; x0++) { 448*eda14cbcSMatt Macy if (x0 >= rm->rm_cols - raidz_parity(rm)) 449*eda14cbcSMatt Macy continue; 450*eda14cbcSMatt Macy for (x1 = x0 + 1; x1 < opts->rto_dcols; x1++) { 451*eda14cbcSMatt Macy if (x1 >= rm->rm_cols - raidz_parity(rm)) 452*eda14cbcSMatt Macy continue; 453*eda14cbcSMatt Macy 454*eda14cbcSMatt Macy /* Check if should stop */ 455*eda14cbcSMatt Macy if (rto_opts.rto_should_stop) 456*eda14cbcSMatt Macy return (err); 457*eda14cbcSMatt Macy 458*eda14cbcSMatt Macy LOG(D_DEBUG, "[%d %d] ", x0, x1); 459*eda14cbcSMatt Macy 460*eda14cbcSMatt Macy tgtidx[1] = x0 + raidz_parity(rm); 461*eda14cbcSMatt Macy tgtidx[2] = x1 + raidz_parity(rm); 462*eda14cbcSMatt Macy 463*eda14cbcSMatt Macy corrupt_colums(rm, tgtidx+1, 2); 464*eda14cbcSMatt Macy 465*eda14cbcSMatt Macy if (!opts->rto_sanity) 466*eda14cbcSMatt Macy vdev_raidz_reconstruct(rm, tgtidx, 3); 467*eda14cbcSMatt Macy 468*eda14cbcSMatt Macy if (cmp_data(opts, rm) != 0) { 469*eda14cbcSMatt Macy err++; 470*eda14cbcSMatt Macy LOG(D_DEBUG, "\nREC D[%d %d]... " 471*eda14cbcSMatt Macy "[FAIL]\n", x0, x1); 472*eda14cbcSMatt Macy } 473*eda14cbcSMatt Macy } 474*eda14cbcSMatt Macy } 475*eda14cbcSMatt Macy } else { 476*eda14cbcSMatt Macy /* can reconstruct 3 failed data disk */ 477*eda14cbcSMatt Macy for (x0 = 0; x0 < opts->rto_dcols; x0++) { 478*eda14cbcSMatt Macy if (x0 >= rm->rm_cols - raidz_parity(rm)) 479*eda14cbcSMatt Macy continue; 480*eda14cbcSMatt Macy for (x1 = x0 + 1; x1 < opts->rto_dcols; x1++) { 481*eda14cbcSMatt Macy if (x1 >= rm->rm_cols - raidz_parity(rm)) 482*eda14cbcSMatt Macy continue; 483*eda14cbcSMatt Macy for (x2 = x1 + 1; x2 < opts->rto_dcols; x2++) { 484*eda14cbcSMatt Macy if (x2 >= 485*eda14cbcSMatt Macy rm->rm_cols - raidz_parity(rm)) 486*eda14cbcSMatt Macy continue; 487*eda14cbcSMatt Macy 488*eda14cbcSMatt Macy /* Check if should stop */ 489*eda14cbcSMatt Macy if (rto_opts.rto_should_stop) 490*eda14cbcSMatt Macy return (err); 491*eda14cbcSMatt Macy 492*eda14cbcSMatt Macy LOG(D_DEBUG, "[%d %d %d]", x0, x1, x2); 493*eda14cbcSMatt Macy 494*eda14cbcSMatt Macy tgtidx[0] = x0 + raidz_parity(rm); 495*eda14cbcSMatt Macy tgtidx[1] = x1 + raidz_parity(rm); 496*eda14cbcSMatt Macy tgtidx[2] = x2 + raidz_parity(rm); 497*eda14cbcSMatt Macy 498*eda14cbcSMatt Macy corrupt_colums(rm, tgtidx, 3); 499*eda14cbcSMatt Macy 500*eda14cbcSMatt Macy if (!opts->rto_sanity) 501*eda14cbcSMatt Macy vdev_raidz_reconstruct(rm, 502*eda14cbcSMatt Macy tgtidx, 3); 503*eda14cbcSMatt Macy 504*eda14cbcSMatt Macy if (cmp_data(opts, rm) != 0) { 505*eda14cbcSMatt Macy err++; 506*eda14cbcSMatt Macy LOG(D_DEBUG, 507*eda14cbcSMatt Macy "\nREC D[%d %d %d]... " 508*eda14cbcSMatt Macy "[FAIL]\n", x0, x1, x2); 509*eda14cbcSMatt Macy } 510*eda14cbcSMatt Macy } 511*eda14cbcSMatt Macy } 512*eda14cbcSMatt Macy } 513*eda14cbcSMatt Macy } 514*eda14cbcSMatt Macy return (err); 515*eda14cbcSMatt Macy } 516*eda14cbcSMatt Macy 517*eda14cbcSMatt Macy static int 518*eda14cbcSMatt Macy run_rec_check(raidz_test_opts_t *opts) 519*eda14cbcSMatt Macy { 520*eda14cbcSMatt Macy char **impl_name; 521*eda14cbcSMatt Macy unsigned fn, err = 0; 522*eda14cbcSMatt Macy zio_t *zio_test; 523*eda14cbcSMatt Macy raidz_map_t *rm_test; 524*eda14cbcSMatt Macy 525*eda14cbcSMatt Macy err = init_raidz_golden_map(opts, PARITY_PQR); 526*eda14cbcSMatt Macy if (0 != err) 527*eda14cbcSMatt Macy return (err); 528*eda14cbcSMatt Macy 529*eda14cbcSMatt Macy LOG(D_INFO, DBLSEP); 530*eda14cbcSMatt Macy LOG(D_INFO, "Testing data reconstruction...\n"); 531*eda14cbcSMatt Macy 532*eda14cbcSMatt Macy for (impl_name = (char **)raidz_impl_names+1; *impl_name != NULL; 533*eda14cbcSMatt Macy impl_name++) { 534*eda14cbcSMatt Macy 535*eda14cbcSMatt Macy LOG(D_INFO, SEP); 536*eda14cbcSMatt Macy LOG(D_INFO, "\tTesting [%s] implementation...", *impl_name); 537*eda14cbcSMatt Macy 538*eda14cbcSMatt Macy if (vdev_raidz_impl_set(*impl_name) != 0) { 539*eda14cbcSMatt Macy LOG(D_INFO, "[SKIP]\n"); 540*eda14cbcSMatt Macy continue; 541*eda14cbcSMatt Macy } else 542*eda14cbcSMatt Macy LOG(D_INFO, "[SUPPORTED]\n"); 543*eda14cbcSMatt Macy 544*eda14cbcSMatt Macy 545*eda14cbcSMatt Macy /* create suitable raidz_map */ 546*eda14cbcSMatt Macy rm_test = init_raidz_map(opts, &zio_test, PARITY_PQR); 547*eda14cbcSMatt Macy /* generate parity */ 548*eda14cbcSMatt Macy vdev_raidz_generate_parity(rm_test); 549*eda14cbcSMatt Macy 550*eda14cbcSMatt Macy for (fn = 0; fn < RAIDZ_REC_NUM; fn++) { 551*eda14cbcSMatt Macy 552*eda14cbcSMatt Macy LOG(D_INFO, "\t\tTesting method [%s] ...", 553*eda14cbcSMatt Macy raidz_rec_name[fn]); 554*eda14cbcSMatt Macy 555*eda14cbcSMatt Macy if (run_rec_check_impl(opts, rm_test, fn) != 0) { 556*eda14cbcSMatt Macy LOG(D_INFO, "[FAIL]\n"); 557*eda14cbcSMatt Macy err++; 558*eda14cbcSMatt Macy 559*eda14cbcSMatt Macy } else 560*eda14cbcSMatt Macy LOG(D_INFO, "[PASS]\n"); 561*eda14cbcSMatt Macy 562*eda14cbcSMatt Macy } 563*eda14cbcSMatt Macy /* tear down test raidz_map */ 564*eda14cbcSMatt Macy fini_raidz_map(&zio_test, &rm_test); 565*eda14cbcSMatt Macy } 566*eda14cbcSMatt Macy 567*eda14cbcSMatt Macy fini_raidz_map(&opts->zio_golden, &opts->rm_golden); 568*eda14cbcSMatt Macy 569*eda14cbcSMatt Macy return (err); 570*eda14cbcSMatt Macy } 571*eda14cbcSMatt Macy 572*eda14cbcSMatt Macy static int 573*eda14cbcSMatt Macy run_test(raidz_test_opts_t *opts) 574*eda14cbcSMatt Macy { 575*eda14cbcSMatt Macy int err = 0; 576*eda14cbcSMatt Macy 577*eda14cbcSMatt Macy if (opts == NULL) 578*eda14cbcSMatt Macy opts = &rto_opts; 579*eda14cbcSMatt Macy 580*eda14cbcSMatt Macy print_opts(opts, B_FALSE); 581*eda14cbcSMatt Macy 582*eda14cbcSMatt Macy err |= run_gen_check(opts); 583*eda14cbcSMatt Macy err |= run_rec_check(opts); 584*eda14cbcSMatt Macy 585*eda14cbcSMatt Macy return (err); 586*eda14cbcSMatt Macy } 587*eda14cbcSMatt Macy 588*eda14cbcSMatt Macy #define SWEEP_RUNNING 0 589*eda14cbcSMatt Macy #define SWEEP_FINISHED 1 590*eda14cbcSMatt Macy #define SWEEP_ERROR 2 591*eda14cbcSMatt Macy #define SWEEP_TIMEOUT 3 592*eda14cbcSMatt Macy 593*eda14cbcSMatt Macy static int sweep_state = 0; 594*eda14cbcSMatt Macy static raidz_test_opts_t failed_opts; 595*eda14cbcSMatt Macy 596*eda14cbcSMatt Macy static kmutex_t sem_mtx; 597*eda14cbcSMatt Macy static kcondvar_t sem_cv; 598*eda14cbcSMatt Macy static int max_free_slots; 599*eda14cbcSMatt Macy static int free_slots; 600*eda14cbcSMatt Macy 601*eda14cbcSMatt Macy static void 602*eda14cbcSMatt Macy sweep_thread(void *arg) 603*eda14cbcSMatt Macy { 604*eda14cbcSMatt Macy int err = 0; 605*eda14cbcSMatt Macy raidz_test_opts_t *opts = (raidz_test_opts_t *)arg; 606*eda14cbcSMatt Macy VERIFY(opts != NULL); 607*eda14cbcSMatt Macy 608*eda14cbcSMatt Macy err = run_test(opts); 609*eda14cbcSMatt Macy 610*eda14cbcSMatt Macy if (rto_opts.rto_sanity) { 611*eda14cbcSMatt Macy /* 25% chance that a sweep test fails */ 612*eda14cbcSMatt Macy if (rand() < (RAND_MAX/4)) 613*eda14cbcSMatt Macy err = 1; 614*eda14cbcSMatt Macy } 615*eda14cbcSMatt Macy 616*eda14cbcSMatt Macy if (0 != err) { 617*eda14cbcSMatt Macy mutex_enter(&sem_mtx); 618*eda14cbcSMatt Macy memcpy(&failed_opts, opts, sizeof (raidz_test_opts_t)); 619*eda14cbcSMatt Macy sweep_state = SWEEP_ERROR; 620*eda14cbcSMatt Macy mutex_exit(&sem_mtx); 621*eda14cbcSMatt Macy } 622*eda14cbcSMatt Macy 623*eda14cbcSMatt Macy umem_free(opts, sizeof (raidz_test_opts_t)); 624*eda14cbcSMatt Macy 625*eda14cbcSMatt Macy /* signal the next thread */ 626*eda14cbcSMatt Macy mutex_enter(&sem_mtx); 627*eda14cbcSMatt Macy free_slots++; 628*eda14cbcSMatt Macy cv_signal(&sem_cv); 629*eda14cbcSMatt Macy mutex_exit(&sem_mtx); 630*eda14cbcSMatt Macy 631*eda14cbcSMatt Macy thread_exit(); 632*eda14cbcSMatt Macy } 633*eda14cbcSMatt Macy 634*eda14cbcSMatt Macy static int 635*eda14cbcSMatt Macy run_sweep(void) 636*eda14cbcSMatt Macy { 637*eda14cbcSMatt Macy static const size_t dcols_v[] = { 1, 2, 3, 4, 5, 6, 7, 8, 12, 15, 16 }; 638*eda14cbcSMatt Macy static const size_t ashift_v[] = { 9, 12, 14 }; 639*eda14cbcSMatt Macy static const size_t size_v[] = { 1 << 9, 21 * (1 << 9), 13 * (1 << 12), 640*eda14cbcSMatt Macy 1 << 17, (1 << 20) - (1 << 12), SPA_MAXBLOCKSIZE }; 641*eda14cbcSMatt Macy 642*eda14cbcSMatt Macy (void) setvbuf(stdout, NULL, _IONBF, 0); 643*eda14cbcSMatt Macy 644*eda14cbcSMatt Macy ulong_t total_comb = ARRAY_SIZE(size_v) * ARRAY_SIZE(ashift_v) * 645*eda14cbcSMatt Macy ARRAY_SIZE(dcols_v); 646*eda14cbcSMatt Macy ulong_t tried_comb = 0; 647*eda14cbcSMatt Macy hrtime_t time_diff, start_time = gethrtime(); 648*eda14cbcSMatt Macy raidz_test_opts_t *opts; 649*eda14cbcSMatt Macy int a, d, s; 650*eda14cbcSMatt Macy 651*eda14cbcSMatt Macy max_free_slots = free_slots = MAX(2, boot_ncpus); 652*eda14cbcSMatt Macy 653*eda14cbcSMatt Macy mutex_init(&sem_mtx, NULL, MUTEX_DEFAULT, NULL); 654*eda14cbcSMatt Macy cv_init(&sem_cv, NULL, CV_DEFAULT, NULL); 655*eda14cbcSMatt Macy 656*eda14cbcSMatt Macy for (s = 0; s < ARRAY_SIZE(size_v); s++) 657*eda14cbcSMatt Macy for (a = 0; a < ARRAY_SIZE(ashift_v); a++) 658*eda14cbcSMatt Macy for (d = 0; d < ARRAY_SIZE(dcols_v); d++) { 659*eda14cbcSMatt Macy 660*eda14cbcSMatt Macy if (size_v[s] < (1 << ashift_v[a])) { 661*eda14cbcSMatt Macy total_comb--; 662*eda14cbcSMatt Macy continue; 663*eda14cbcSMatt Macy } 664*eda14cbcSMatt Macy 665*eda14cbcSMatt Macy if (++tried_comb % 20 == 0) 666*eda14cbcSMatt Macy LOG(D_ALL, "%lu/%lu... ", tried_comb, total_comb); 667*eda14cbcSMatt Macy 668*eda14cbcSMatt Macy /* wait for signal to start new thread */ 669*eda14cbcSMatt Macy mutex_enter(&sem_mtx); 670*eda14cbcSMatt Macy while (cv_timedwait_sig(&sem_cv, &sem_mtx, 671*eda14cbcSMatt Macy ddi_get_lbolt() + hz)) { 672*eda14cbcSMatt Macy 673*eda14cbcSMatt Macy /* check if should stop the test (timeout) */ 674*eda14cbcSMatt Macy time_diff = (gethrtime() - start_time) / NANOSEC; 675*eda14cbcSMatt Macy if (rto_opts.rto_sweep_timeout > 0 && 676*eda14cbcSMatt Macy time_diff >= rto_opts.rto_sweep_timeout) { 677*eda14cbcSMatt Macy sweep_state = SWEEP_TIMEOUT; 678*eda14cbcSMatt Macy rto_opts.rto_should_stop = B_TRUE; 679*eda14cbcSMatt Macy mutex_exit(&sem_mtx); 680*eda14cbcSMatt Macy goto exit; 681*eda14cbcSMatt Macy } 682*eda14cbcSMatt Macy 683*eda14cbcSMatt Macy /* check if should stop the test (error) */ 684*eda14cbcSMatt Macy if (sweep_state != SWEEP_RUNNING) { 685*eda14cbcSMatt Macy mutex_exit(&sem_mtx); 686*eda14cbcSMatt Macy goto exit; 687*eda14cbcSMatt Macy } 688*eda14cbcSMatt Macy 689*eda14cbcSMatt Macy /* exit loop if a slot is available */ 690*eda14cbcSMatt Macy if (free_slots > 0) { 691*eda14cbcSMatt Macy break; 692*eda14cbcSMatt Macy } 693*eda14cbcSMatt Macy } 694*eda14cbcSMatt Macy 695*eda14cbcSMatt Macy free_slots--; 696*eda14cbcSMatt Macy mutex_exit(&sem_mtx); 697*eda14cbcSMatt Macy 698*eda14cbcSMatt Macy opts = umem_zalloc(sizeof (raidz_test_opts_t), UMEM_NOFAIL); 699*eda14cbcSMatt Macy opts->rto_ashift = ashift_v[a]; 700*eda14cbcSMatt Macy opts->rto_dcols = dcols_v[d]; 701*eda14cbcSMatt Macy opts->rto_offset = (1 << ashift_v[a]) * rand(); 702*eda14cbcSMatt Macy opts->rto_dsize = size_v[s]; 703*eda14cbcSMatt Macy opts->rto_v = 0; /* be quiet */ 704*eda14cbcSMatt Macy 705*eda14cbcSMatt Macy VERIFY3P(thread_create(NULL, 0, sweep_thread, (void *) opts, 706*eda14cbcSMatt Macy 0, NULL, TS_RUN, defclsyspri), !=, NULL); 707*eda14cbcSMatt Macy } 708*eda14cbcSMatt Macy 709*eda14cbcSMatt Macy exit: 710*eda14cbcSMatt Macy LOG(D_ALL, "\nWaiting for test threads to finish...\n"); 711*eda14cbcSMatt Macy mutex_enter(&sem_mtx); 712*eda14cbcSMatt Macy VERIFY(free_slots <= max_free_slots); 713*eda14cbcSMatt Macy while (free_slots < max_free_slots) { 714*eda14cbcSMatt Macy (void) cv_wait(&sem_cv, &sem_mtx); 715*eda14cbcSMatt Macy } 716*eda14cbcSMatt Macy mutex_exit(&sem_mtx); 717*eda14cbcSMatt Macy 718*eda14cbcSMatt Macy if (sweep_state == SWEEP_ERROR) { 719*eda14cbcSMatt Macy ERR("Sweep test failed! Failed option: \n"); 720*eda14cbcSMatt Macy print_opts(&failed_opts, B_TRUE); 721*eda14cbcSMatt Macy } else { 722*eda14cbcSMatt Macy if (sweep_state == SWEEP_TIMEOUT) 723*eda14cbcSMatt Macy LOG(D_ALL, "Test timeout (%lus). Stopping...\n", 724*eda14cbcSMatt Macy (ulong_t)rto_opts.rto_sweep_timeout); 725*eda14cbcSMatt Macy 726*eda14cbcSMatt Macy LOG(D_ALL, "Sweep test succeeded on %lu raidz maps!\n", 727*eda14cbcSMatt Macy (ulong_t)tried_comb); 728*eda14cbcSMatt Macy } 729*eda14cbcSMatt Macy 730*eda14cbcSMatt Macy mutex_destroy(&sem_mtx); 731*eda14cbcSMatt Macy 732*eda14cbcSMatt Macy return (sweep_state == SWEEP_ERROR ? SWEEP_ERROR : 0); 733*eda14cbcSMatt Macy } 734*eda14cbcSMatt Macy 735*eda14cbcSMatt Macy int 736*eda14cbcSMatt Macy main(int argc, char **argv) 737*eda14cbcSMatt Macy { 738*eda14cbcSMatt Macy size_t i; 739*eda14cbcSMatt Macy struct sigaction action; 740*eda14cbcSMatt Macy int err = 0; 741*eda14cbcSMatt Macy 742*eda14cbcSMatt Macy /* init gdb string early */ 743*eda14cbcSMatt Macy (void) sprintf(gdb, gdb_tmpl, getpid()); 744*eda14cbcSMatt Macy 745*eda14cbcSMatt Macy action.sa_handler = sig_handler; 746*eda14cbcSMatt Macy sigemptyset(&action.sa_mask); 747*eda14cbcSMatt Macy action.sa_flags = 0; 748*eda14cbcSMatt Macy 749*eda14cbcSMatt Macy if (sigaction(SIGSEGV, &action, NULL) < 0) { 750*eda14cbcSMatt Macy ERR("raidz_test: cannot catch SIGSEGV: %s.\n", strerror(errno)); 751*eda14cbcSMatt Macy exit(EXIT_FAILURE); 752*eda14cbcSMatt Macy } 753*eda14cbcSMatt Macy 754*eda14cbcSMatt Macy (void) setvbuf(stdout, NULL, _IOLBF, 0); 755*eda14cbcSMatt Macy 756*eda14cbcSMatt Macy dprintf_setup(&argc, argv); 757*eda14cbcSMatt Macy 758*eda14cbcSMatt Macy process_options(argc, argv); 759*eda14cbcSMatt Macy 760*eda14cbcSMatt Macy kernel_init(SPA_MODE_READ); 761*eda14cbcSMatt Macy 762*eda14cbcSMatt Macy /* setup random data because rand() is not reentrant */ 763*eda14cbcSMatt Macy rand_data = (int *)umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL); 764*eda14cbcSMatt Macy srand((unsigned)time(NULL) * getpid()); 765*eda14cbcSMatt Macy for (i = 0; i < SPA_MAXBLOCKSIZE / sizeof (int); i++) 766*eda14cbcSMatt Macy rand_data[i] = rand(); 767*eda14cbcSMatt Macy 768*eda14cbcSMatt Macy mprotect(rand_data, SPA_MAXBLOCKSIZE, PROT_READ); 769*eda14cbcSMatt Macy 770*eda14cbcSMatt Macy if (rto_opts.rto_benchmark) { 771*eda14cbcSMatt Macy run_raidz_benchmark(); 772*eda14cbcSMatt Macy } else if (rto_opts.rto_sweep) { 773*eda14cbcSMatt Macy err = run_sweep(); 774*eda14cbcSMatt Macy } else { 775*eda14cbcSMatt Macy err = run_test(NULL); 776*eda14cbcSMatt Macy } 777*eda14cbcSMatt Macy 778*eda14cbcSMatt Macy umem_free(rand_data, SPA_MAXBLOCKSIZE); 779*eda14cbcSMatt Macy kernel_fini(); 780*eda14cbcSMatt Macy 781*eda14cbcSMatt Macy return (err); 782*eda14cbcSMatt Macy } 783