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