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 * Copyright (C) 2016 Gvozden Nešković. All rights reserved.
23eda14cbcSMatt Macy */
24eda14cbcSMatt Macy
25eda14cbcSMatt Macy #ifndef _VDEV_RAIDZ_H
26eda14cbcSMatt Macy #define _VDEV_RAIDZ_H
27eda14cbcSMatt Macy
28eda14cbcSMatt Macy #include <sys/types.h>
29eda14cbcSMatt Macy #include <sys/debug.h>
30eda14cbcSMatt Macy #include <sys/kstat.h>
31eda14cbcSMatt Macy #include <sys/abd.h>
327877fdebSMatt Macy #include <sys/vdev_impl.h>
33e716630dSMartin Matuska #include <sys/abd_impl.h>
34e716630dSMartin Matuska #include <sys/zfs_rlock.h>
35eda14cbcSMatt Macy
36eda14cbcSMatt Macy #ifdef __cplusplus
37eda14cbcSMatt Macy extern "C" {
38eda14cbcSMatt Macy #endif
39eda14cbcSMatt Macy
40eda14cbcSMatt Macy #define CODE_P (0U)
41eda14cbcSMatt Macy #define CODE_Q (1U)
42eda14cbcSMatt Macy #define CODE_R (2U)
43eda14cbcSMatt Macy
44eda14cbcSMatt Macy #define PARITY_P (1U)
45eda14cbcSMatt Macy #define PARITY_PQ (2U)
46eda14cbcSMatt Macy #define PARITY_PQR (3U)
47eda14cbcSMatt Macy
48eda14cbcSMatt Macy #define TARGET_X (0U)
49eda14cbcSMatt Macy #define TARGET_Y (1U)
50eda14cbcSMatt Macy #define TARGET_Z (2U)
51eda14cbcSMatt Macy
52eda14cbcSMatt Macy /*
53eda14cbcSMatt Macy * Parity generation methods indexes
54eda14cbcSMatt Macy */
55eda14cbcSMatt Macy enum raidz_math_gen_op {
56eda14cbcSMatt Macy RAIDZ_GEN_P = 0,
57eda14cbcSMatt Macy RAIDZ_GEN_PQ,
58eda14cbcSMatt Macy RAIDZ_GEN_PQR,
59eda14cbcSMatt Macy RAIDZ_GEN_NUM = 3
60eda14cbcSMatt Macy };
61eda14cbcSMatt Macy /*
62eda14cbcSMatt Macy * Data reconstruction methods indexes
63eda14cbcSMatt Macy */
64eda14cbcSMatt Macy enum raidz_rec_op {
65eda14cbcSMatt Macy RAIDZ_REC_P = 0,
66eda14cbcSMatt Macy RAIDZ_REC_Q,
67eda14cbcSMatt Macy RAIDZ_REC_R,
68eda14cbcSMatt Macy RAIDZ_REC_PQ,
69eda14cbcSMatt Macy RAIDZ_REC_PR,
70eda14cbcSMatt Macy RAIDZ_REC_QR,
71eda14cbcSMatt Macy RAIDZ_REC_PQR,
72eda14cbcSMatt Macy RAIDZ_REC_NUM = 7
73eda14cbcSMatt Macy };
74eda14cbcSMatt Macy
75e92ffd9bSMartin Matuska extern const char *const raidz_gen_name[RAIDZ_GEN_NUM];
76e92ffd9bSMartin Matuska extern const char *const raidz_rec_name[RAIDZ_REC_NUM];
77eda14cbcSMatt Macy
78eda14cbcSMatt Macy /*
79eda14cbcSMatt Macy * Methods used to define raidz implementation
80eda14cbcSMatt Macy *
81eda14cbcSMatt Macy * @raidz_gen_f Parity generation function
82eda14cbcSMatt Macy * @par1 pointer to raidz_map
83eda14cbcSMatt Macy * @raidz_rec_f Data reconstruction function
84eda14cbcSMatt Macy * @par1 pointer to raidz_map
85eda14cbcSMatt Macy * @par2 array of reconstruction targets
86eda14cbcSMatt Macy * @will_work_f Function returns TRUE if impl. is supported on the system
87eda14cbcSMatt Macy * @init_impl_f Function is called once on init
88eda14cbcSMatt Macy * @fini_impl_f Function is called once on fini
89eda14cbcSMatt Macy */
90eda14cbcSMatt Macy typedef void (*raidz_gen_f)(void *);
91eda14cbcSMatt Macy typedef int (*raidz_rec_f)(void *, const int *);
92eda14cbcSMatt Macy typedef boolean_t (*will_work_f)(void);
93eda14cbcSMatt Macy typedef void (*init_impl_f)(void);
94eda14cbcSMatt Macy typedef void (*fini_impl_f)(void);
95eda14cbcSMatt Macy
96eda14cbcSMatt Macy #define RAIDZ_IMPL_NAME_MAX (20)
97eda14cbcSMatt Macy
98eda14cbcSMatt Macy typedef struct raidz_impl_ops {
99eda14cbcSMatt Macy init_impl_f init;
100eda14cbcSMatt Macy fini_impl_f fini;
101eda14cbcSMatt Macy raidz_gen_f gen[RAIDZ_GEN_NUM]; /* Parity generate functions */
102eda14cbcSMatt Macy raidz_rec_f rec[RAIDZ_REC_NUM]; /* Data reconstruction functions */
103eda14cbcSMatt Macy will_work_f is_supported; /* Support check function */
104eda14cbcSMatt Macy char name[RAIDZ_IMPL_NAME_MAX]; /* Name of the implementation */
105eda14cbcSMatt Macy } raidz_impl_ops_t;
106eda14cbcSMatt Macy
107e716630dSMartin Matuska
108eda14cbcSMatt Macy typedef struct raidz_col {
109e716630dSMartin Matuska int rc_devidx; /* child device index for I/O */
110e716630dSMartin Matuska uint32_t rc_size; /* I/O size */
111eda14cbcSMatt Macy uint64_t rc_offset; /* device offset */
112184c1b94SMartin Matuska abd_t rc_abdstruct; /* rc_abd probably points here */
113eda14cbcSMatt Macy abd_t *rc_abd; /* I/O data */
114f9693befSMartin Matuska abd_t *rc_orig_data; /* pre-reconstruction */
115eda14cbcSMatt Macy int rc_error; /* I/O error for this device */
116e716630dSMartin Matuska uint8_t rc_tried:1; /* Did we attempt this I/O column? */
117e716630dSMartin Matuska uint8_t rc_skipped:1; /* Did we skip this I/O column? */
118e716630dSMartin Matuska uint8_t rc_need_orig_restore:1; /* need to restore from orig_data? */
119e716630dSMartin Matuska uint8_t rc_force_repair:1; /* Write good data to this column */
120e716630dSMartin Matuska uint8_t rc_allow_repair:1; /* Allow repair I/O to this column */
121e716630dSMartin Matuska int rc_shadow_devidx; /* for double write during expansion */
122e716630dSMartin Matuska int rc_shadow_error; /* for double write during expansion */
123e716630dSMartin Matuska uint64_t rc_shadow_offset; /* for double write during expansion */
124eda14cbcSMatt Macy } raidz_col_t;
125eda14cbcSMatt Macy
1267877fdebSMatt Macy typedef struct raidz_row {
127e716630dSMartin Matuska int rr_cols; /* Regular column count */
128e716630dSMartin Matuska int rr_scols; /* Count including skipped columns */
129e716630dSMartin Matuska int rr_bigcols; /* Remainder data column count */
130e716630dSMartin Matuska int rr_missingdata; /* Count of missing data devices */
131e716630dSMartin Matuska int rr_missingparity; /* Count of missing parity devices */
132e716630dSMartin Matuska int rr_firstdatacol; /* First data column/parity count */
1337877fdebSMatt Macy abd_t *rr_abd_empty; /* dRAID empty sector buffer */
1347877fdebSMatt Macy int rr_nempty; /* empty sectors included in parity */
1357877fdebSMatt Macy #ifdef ZFS_DEBUG
1367877fdebSMatt Macy uint64_t rr_offset; /* Logical offset for *_io_verify() */
1377877fdebSMatt Macy uint64_t rr_size; /* Physical size for *_io_verify() */
1387877fdebSMatt Macy #endif
13947bb16f8SMartin Matuska raidz_col_t rr_col[]; /* Flexible array of I/O columns */
1407877fdebSMatt Macy } raidz_row_t;
1417877fdebSMatt Macy
142eda14cbcSMatt Macy typedef struct raidz_map {
1437877fdebSMatt Macy boolean_t rm_ecksuminjected; /* checksum error was injected */
1447877fdebSMatt Macy int rm_nrows; /* Regular row count */
1457877fdebSMatt Macy int rm_nskip; /* RAIDZ sectors skipped for padding */
1467877fdebSMatt Macy int rm_skipstart; /* Column index of padding start */
147e716630dSMartin Matuska int rm_original_width; /* pre-expansion width of raidz vdev */
148e716630dSMartin Matuska int rm_nphys_cols; /* num entries in rm_phys_col[] */
149e716630dSMartin Matuska zfs_locked_range_t *rm_lr;
150eda14cbcSMatt Macy const raidz_impl_ops_t *rm_ops; /* RAIDZ math operations */
151e716630dSMartin Matuska raidz_col_t *rm_phys_col; /* if non-NULL, read i/o aggregation */
15247bb16f8SMartin Matuska raidz_row_t *rm_row[]; /* flexible array of rows */
153eda14cbcSMatt Macy } raidz_map_t;
154eda14cbcSMatt Macy
155e716630dSMartin Matuska /*
156e716630dSMartin Matuska * Nodes in vdev_raidz_t:vd_expand_txgs.
157e716630dSMartin Matuska * Blocks with physical birth time of re_txg or later have the specified
158e716630dSMartin Matuska * logical width (until the next node).
159e716630dSMartin Matuska */
160e716630dSMartin Matuska typedef struct reflow_node {
161e716630dSMartin Matuska uint64_t re_txg;
162e716630dSMartin Matuska uint64_t re_logical_width;
163e716630dSMartin Matuska avl_node_t re_link;
164e716630dSMartin Matuska } reflow_node_t;
165e716630dSMartin Matuska
1667877fdebSMatt Macy
167eda14cbcSMatt Macy #define RAIDZ_ORIGINAL_IMPL (INT_MAX)
168eda14cbcSMatt Macy
169eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_scalar_impl;
170eda14cbcSMatt Macy extern boolean_t raidz_will_scalar_work(void);
171eda14cbcSMatt Macy
172eda14cbcSMatt Macy #if defined(__x86_64) && defined(HAVE_SSE2) /* only x86_64 for now */
173eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_sse2_impl;
174eda14cbcSMatt Macy #endif
175eda14cbcSMatt Macy #if defined(__x86_64) && defined(HAVE_SSSE3) /* only x86_64 for now */
176eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_ssse3_impl;
177eda14cbcSMatt Macy #endif
178eda14cbcSMatt Macy #if defined(__x86_64) && defined(HAVE_AVX2) /* only x86_64 for now */
179eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_avx2_impl;
180eda14cbcSMatt Macy #endif
181eda14cbcSMatt Macy #if defined(__x86_64) && defined(HAVE_AVX512F) /* only x86_64 for now */
182eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_avx512f_impl;
183eda14cbcSMatt Macy #endif
184eda14cbcSMatt Macy #if defined(__x86_64) && defined(HAVE_AVX512BW) /* only x86_64 for now */
185eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_avx512bw_impl;
186eda14cbcSMatt Macy #endif
187eda14cbcSMatt Macy #if defined(__aarch64__)
188eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_aarch64_neon_impl;
189eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_aarch64_neonx2_impl;
190eda14cbcSMatt Macy #endif
191eda14cbcSMatt Macy #if defined(__powerpc__)
192eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_powerpc_altivec_impl;
193eda14cbcSMatt Macy #endif
194eda14cbcSMatt Macy
195eda14cbcSMatt Macy /*
196eda14cbcSMatt Macy * Commonly used raidz_map helpers
197eda14cbcSMatt Macy *
198eda14cbcSMatt Macy * raidz_parity Returns parity of the RAIDZ block
199eda14cbcSMatt Macy * raidz_ncols Returns number of columns the block spans
2007877fdebSMatt Macy * Note, all rows have the same number of columns.
201eda14cbcSMatt Macy * raidz_nbigcols Returns number of big columns
202eda14cbcSMatt Macy * raidz_col_p Returns pointer to a column
203eda14cbcSMatt Macy * raidz_col_size Returns size of a column
204eda14cbcSMatt Macy * raidz_big_size Returns size of big columns
205eda14cbcSMatt Macy * raidz_short_size Returns size of short columns
206eda14cbcSMatt Macy */
2077877fdebSMatt Macy #define raidz_parity(rm) ((rm)->rm_row[0]->rr_firstdatacol)
2087877fdebSMatt Macy #define raidz_ncols(rm) ((rm)->rm_row[0]->rr_cols)
209eda14cbcSMatt Macy #define raidz_nbigcols(rm) ((rm)->rm_bigcols)
210eda14cbcSMatt Macy #define raidz_col_p(rm, c) ((rm)->rm_col + (c))
211eda14cbcSMatt Macy #define raidz_col_size(rm, c) ((rm)->rm_col[c].rc_size)
212eda14cbcSMatt Macy #define raidz_big_size(rm) (raidz_col_size(rm, CODE_P))
213eda14cbcSMatt Macy #define raidz_short_size(rm) (raidz_col_size(rm, raidz_ncols(rm)-1))
214eda14cbcSMatt Macy
215eda14cbcSMatt Macy /*
216eda14cbcSMatt Macy * Macro defines an RAIDZ parity generation method
217eda14cbcSMatt Macy *
218eda14cbcSMatt Macy * @code parity the function produce
219eda14cbcSMatt Macy * @impl name of the implementation
220eda14cbcSMatt Macy */
221eda14cbcSMatt Macy #define _RAIDZ_GEN_WRAP(code, impl) \
222eda14cbcSMatt Macy static void \
2237877fdebSMatt Macy impl ## _gen_ ## code(void *rrp) \
224eda14cbcSMatt Macy { \
2257877fdebSMatt Macy raidz_row_t *rr = (raidz_row_t *)rrp; \
2267877fdebSMatt Macy raidz_generate_## code ## _impl(rr); \
227eda14cbcSMatt Macy }
228eda14cbcSMatt Macy
229eda14cbcSMatt Macy /*
230eda14cbcSMatt Macy * Macro defines an RAIDZ data reconstruction method
231eda14cbcSMatt Macy *
232eda14cbcSMatt Macy * @code parity the function produce
233eda14cbcSMatt Macy * @impl name of the implementation
234eda14cbcSMatt Macy */
235eda14cbcSMatt Macy #define _RAIDZ_REC_WRAP(code, impl) \
236eda14cbcSMatt Macy static int \
2377877fdebSMatt Macy impl ## _rec_ ## code(void *rrp, const int *tgtidx) \
238eda14cbcSMatt Macy { \
2397877fdebSMatt Macy raidz_row_t *rr = (raidz_row_t *)rrp; \
2407877fdebSMatt Macy return (raidz_reconstruct_## code ## _impl(rr, tgtidx)); \
241eda14cbcSMatt Macy }
242eda14cbcSMatt Macy
243eda14cbcSMatt Macy /*
244eda14cbcSMatt Macy * Define all gen methods for an implementation
245eda14cbcSMatt Macy *
246eda14cbcSMatt Macy * @impl name of the implementation
247eda14cbcSMatt Macy */
248eda14cbcSMatt Macy #define DEFINE_GEN_METHODS(impl) \
249eda14cbcSMatt Macy _RAIDZ_GEN_WRAP(p, impl); \
250eda14cbcSMatt Macy _RAIDZ_GEN_WRAP(pq, impl); \
251eda14cbcSMatt Macy _RAIDZ_GEN_WRAP(pqr, impl)
252eda14cbcSMatt Macy
253eda14cbcSMatt Macy /*
254eda14cbcSMatt Macy * Define all rec functions for an implementation
255eda14cbcSMatt Macy *
256eda14cbcSMatt Macy * @impl name of the implementation
257eda14cbcSMatt Macy */
258eda14cbcSMatt Macy #define DEFINE_REC_METHODS(impl) \
259eda14cbcSMatt Macy _RAIDZ_REC_WRAP(p, impl); \
260eda14cbcSMatt Macy _RAIDZ_REC_WRAP(q, impl); \
261eda14cbcSMatt Macy _RAIDZ_REC_WRAP(r, impl); \
262eda14cbcSMatt Macy _RAIDZ_REC_WRAP(pq, impl); \
263eda14cbcSMatt Macy _RAIDZ_REC_WRAP(pr, impl); \
264eda14cbcSMatt Macy _RAIDZ_REC_WRAP(qr, impl); \
265eda14cbcSMatt Macy _RAIDZ_REC_WRAP(pqr, impl)
266eda14cbcSMatt Macy
267eda14cbcSMatt Macy #define RAIDZ_GEN_METHODS(impl) \
268eda14cbcSMatt Macy { \
269eda14cbcSMatt Macy [RAIDZ_GEN_P] = & impl ## _gen_p, \
270eda14cbcSMatt Macy [RAIDZ_GEN_PQ] = & impl ## _gen_pq, \
271eda14cbcSMatt Macy [RAIDZ_GEN_PQR] = & impl ## _gen_pqr \
272eda14cbcSMatt Macy }
273eda14cbcSMatt Macy
274eda14cbcSMatt Macy #define RAIDZ_REC_METHODS(impl) \
275eda14cbcSMatt Macy { \
276eda14cbcSMatt Macy [RAIDZ_REC_P] = & impl ## _rec_p, \
277eda14cbcSMatt Macy [RAIDZ_REC_Q] = & impl ## _rec_q, \
278eda14cbcSMatt Macy [RAIDZ_REC_R] = & impl ## _rec_r, \
279eda14cbcSMatt Macy [RAIDZ_REC_PQ] = & impl ## _rec_pq, \
280eda14cbcSMatt Macy [RAIDZ_REC_PR] = & impl ## _rec_pr, \
281eda14cbcSMatt Macy [RAIDZ_REC_QR] = & impl ## _rec_qr, \
282eda14cbcSMatt Macy [RAIDZ_REC_PQR] = & impl ## _rec_pqr \
283eda14cbcSMatt Macy }
284eda14cbcSMatt Macy
285eda14cbcSMatt Macy
286eda14cbcSMatt Macy typedef struct raidz_impl_kstat {
287eda14cbcSMatt Macy uint64_t gen[RAIDZ_GEN_NUM]; /* gen method speed B/s */
288eda14cbcSMatt Macy uint64_t rec[RAIDZ_REC_NUM]; /* rec method speed B/s */
289eda14cbcSMatt Macy } raidz_impl_kstat_t;
290eda14cbcSMatt Macy
291eda14cbcSMatt Macy /*
292eda14cbcSMatt Macy * Enumerate various multiplication constants
293eda14cbcSMatt Macy * used in reconstruction methods
294eda14cbcSMatt Macy */
295eda14cbcSMatt Macy typedef enum raidz_mul_info {
296eda14cbcSMatt Macy /* Reconstruct Q */
297eda14cbcSMatt Macy MUL_Q_X = 0,
298eda14cbcSMatt Macy /* Reconstruct R */
299eda14cbcSMatt Macy MUL_R_X = 0,
300eda14cbcSMatt Macy /* Reconstruct PQ */
301eda14cbcSMatt Macy MUL_PQ_X = 0,
302eda14cbcSMatt Macy MUL_PQ_Y = 1,
303eda14cbcSMatt Macy /* Reconstruct PR */
304eda14cbcSMatt Macy MUL_PR_X = 0,
305eda14cbcSMatt Macy MUL_PR_Y = 1,
306eda14cbcSMatt Macy /* Reconstruct QR */
307eda14cbcSMatt Macy MUL_QR_XQ = 0,
308eda14cbcSMatt Macy MUL_QR_X = 1,
309eda14cbcSMatt Macy MUL_QR_YQ = 2,
310eda14cbcSMatt Macy MUL_QR_Y = 3,
311eda14cbcSMatt Macy /* Reconstruct PQR */
312eda14cbcSMatt Macy MUL_PQR_XP = 0,
313eda14cbcSMatt Macy MUL_PQR_XQ = 1,
314eda14cbcSMatt Macy MUL_PQR_XR = 2,
315eda14cbcSMatt Macy MUL_PQR_YU = 3,
316eda14cbcSMatt Macy MUL_PQR_YP = 4,
317eda14cbcSMatt Macy MUL_PQR_YQ = 5,
318eda14cbcSMatt Macy
319eda14cbcSMatt Macy MUL_CNT = 6
320eda14cbcSMatt Macy } raidz_mul_info_t;
321eda14cbcSMatt Macy
322eda14cbcSMatt Macy /*
323eda14cbcSMatt Macy * Powers of 2 in the Galois field.
324eda14cbcSMatt Macy */
325eda14cbcSMatt Macy extern const uint8_t vdev_raidz_pow2[256] __attribute__((aligned(256)));
326eda14cbcSMatt Macy /* Logs of 2 in the Galois field defined above. */
327eda14cbcSMatt Macy extern const uint8_t vdev_raidz_log2[256] __attribute__((aligned(256)));
328eda14cbcSMatt Macy
329eda14cbcSMatt Macy /*
330eda14cbcSMatt Macy * Multiply a given number by 2 raised to the given power.
331eda14cbcSMatt Macy */
332eda14cbcSMatt Macy static inline uint8_t
vdev_raidz_exp2(const uint8_t a,const unsigned exp)333eda14cbcSMatt Macy vdev_raidz_exp2(const uint8_t a, const unsigned exp)
334eda14cbcSMatt Macy {
335eda14cbcSMatt Macy if (a == 0)
336eda14cbcSMatt Macy return (0);
337eda14cbcSMatt Macy
338eda14cbcSMatt Macy return (vdev_raidz_pow2[(exp + (unsigned)vdev_raidz_log2[a]) % 255]);
339eda14cbcSMatt Macy }
340eda14cbcSMatt Macy
341eda14cbcSMatt Macy /*
342eda14cbcSMatt Macy * Galois Field operations.
343eda14cbcSMatt Macy *
344eda14cbcSMatt Macy * gf_exp2 - computes 2 raised to the given power
345c7046f76SMartin Matuska * gf_exp4 - computes 4 raised to the given power
346eda14cbcSMatt Macy * gf_mul - multiplication
347eda14cbcSMatt Macy * gf_div - division
348eda14cbcSMatt Macy * gf_inv - multiplicative inverse
349eda14cbcSMatt Macy */
350eda14cbcSMatt Macy typedef unsigned gf_t;
351eda14cbcSMatt Macy typedef unsigned gf_log_t;
352eda14cbcSMatt Macy
353eda14cbcSMatt Macy static inline gf_t
gf_mul(const gf_t a,const gf_t b)354eda14cbcSMatt Macy gf_mul(const gf_t a, const gf_t b)
355eda14cbcSMatt Macy {
356eda14cbcSMatt Macy gf_log_t logsum;
357eda14cbcSMatt Macy
358eda14cbcSMatt Macy if (a == 0 || b == 0)
359eda14cbcSMatt Macy return (0);
360eda14cbcSMatt Macy
361eda14cbcSMatt Macy logsum = (gf_log_t)vdev_raidz_log2[a] + (gf_log_t)vdev_raidz_log2[b];
362eda14cbcSMatt Macy
363eda14cbcSMatt Macy return ((gf_t)vdev_raidz_pow2[logsum % 255]);
364eda14cbcSMatt Macy }
365eda14cbcSMatt Macy
366eda14cbcSMatt Macy static inline gf_t
gf_div(const gf_t a,const gf_t b)367eda14cbcSMatt Macy gf_div(const gf_t a, const gf_t b)
368eda14cbcSMatt Macy {
369eda14cbcSMatt Macy gf_log_t logsum;
370eda14cbcSMatt Macy
371eda14cbcSMatt Macy ASSERT3U(b, >, 0);
372eda14cbcSMatt Macy if (a == 0)
373eda14cbcSMatt Macy return (0);
374eda14cbcSMatt Macy
375eda14cbcSMatt Macy logsum = (gf_log_t)255 + (gf_log_t)vdev_raidz_log2[a] -
376eda14cbcSMatt Macy (gf_log_t)vdev_raidz_log2[b];
377eda14cbcSMatt Macy
378eda14cbcSMatt Macy return ((gf_t)vdev_raidz_pow2[logsum % 255]);
379eda14cbcSMatt Macy }
380eda14cbcSMatt Macy
381eda14cbcSMatt Macy static inline gf_t
gf_inv(const gf_t a)382eda14cbcSMatt Macy gf_inv(const gf_t a)
383eda14cbcSMatt Macy {
384eda14cbcSMatt Macy gf_log_t logsum;
385eda14cbcSMatt Macy
386eda14cbcSMatt Macy ASSERT3U(a, >, 0);
387eda14cbcSMatt Macy
388eda14cbcSMatt Macy logsum = (gf_log_t)255 - (gf_log_t)vdev_raidz_log2[a];
389eda14cbcSMatt Macy
390eda14cbcSMatt Macy return ((gf_t)vdev_raidz_pow2[logsum]);
391eda14cbcSMatt Macy }
392eda14cbcSMatt Macy
393eda14cbcSMatt Macy static inline gf_t
gf_exp2(gf_log_t exp)394eda14cbcSMatt Macy gf_exp2(gf_log_t exp)
395eda14cbcSMatt Macy {
396eda14cbcSMatt Macy return (vdev_raidz_pow2[exp % 255]);
397eda14cbcSMatt Macy }
398eda14cbcSMatt Macy
399eda14cbcSMatt Macy static inline gf_t
gf_exp4(gf_log_t exp)400eda14cbcSMatt Macy gf_exp4(gf_log_t exp)
401eda14cbcSMatt Macy {
402eda14cbcSMatt Macy ASSERT3U(exp, <=, 255);
403eda14cbcSMatt Macy return ((gf_t)vdev_raidz_pow2[(2 * exp) % 255]);
404eda14cbcSMatt Macy }
405eda14cbcSMatt Macy
406eda14cbcSMatt Macy #ifdef __cplusplus
407eda14cbcSMatt Macy }
408eda14cbcSMatt Macy #endif
409eda14cbcSMatt Macy
410eda14cbcSMatt Macy #endif /* _VDEV_RAIDZ_H */
411