1*22ce4affSfengbojiang /*
2*22ce4affSfengbojiang  * CDDL HEADER START
3*22ce4affSfengbojiang  *
4*22ce4affSfengbojiang  * The contents of this file are subject to the terms of the
5*22ce4affSfengbojiang  * Common Development and Distribution License (the "License").
6*22ce4affSfengbojiang  * You may not use this file except in compliance with the License.
7*22ce4affSfengbojiang  *
8*22ce4affSfengbojiang  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*22ce4affSfengbojiang  * or http://www.opensolaris.org/os/licensing.
10*22ce4affSfengbojiang  * See the License for the specific language governing permissions
11*22ce4affSfengbojiang  * and limitations under the License.
12*22ce4affSfengbojiang  *
13*22ce4affSfengbojiang  * When distributing Covered Code, include this CDDL HEADER in each
14*22ce4affSfengbojiang  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*22ce4affSfengbojiang  * If applicable, add the following below this CDDL HEADER, with the
16*22ce4affSfengbojiang  * fields enclosed by brackets "[]" replaced with your own identifying
17*22ce4affSfengbojiang  * information: Portions Copyright [yyyy] [name of copyright owner]
18*22ce4affSfengbojiang  *
19*22ce4affSfengbojiang  * CDDL HEADER END
20*22ce4affSfengbojiang  */
21*22ce4affSfengbojiang /*
22*22ce4affSfengbojiang  * Copyright (C) 2016 Gvozden Nešković. All rights reserved.
23*22ce4affSfengbojiang  */
24*22ce4affSfengbojiang 
25*22ce4affSfengbojiang #ifndef _VDEV_RAIDZ_H
26*22ce4affSfengbojiang #define	_VDEV_RAIDZ_H
27*22ce4affSfengbojiang 
28*22ce4affSfengbojiang #include <sys/types.h>
29*22ce4affSfengbojiang #include <sys/debug.h>
30*22ce4affSfengbojiang #include <sys/kstat.h>
31*22ce4affSfengbojiang #include <sys/abd.h>
32*22ce4affSfengbojiang #include <sys/vdev_impl.h>
33*22ce4affSfengbojiang 
34*22ce4affSfengbojiang #ifdef  __cplusplus
35*22ce4affSfengbojiang extern "C" {
36*22ce4affSfengbojiang #endif
37*22ce4affSfengbojiang 
38*22ce4affSfengbojiang #define	CODE_P		(0U)
39*22ce4affSfengbojiang #define	CODE_Q		(1U)
40*22ce4affSfengbojiang #define	CODE_R		(2U)
41*22ce4affSfengbojiang 
42*22ce4affSfengbojiang #define	PARITY_P	(1U)
43*22ce4affSfengbojiang #define	PARITY_PQ	(2U)
44*22ce4affSfengbojiang #define	PARITY_PQR	(3U)
45*22ce4affSfengbojiang 
46*22ce4affSfengbojiang #define	TARGET_X	(0U)
47*22ce4affSfengbojiang #define	TARGET_Y	(1U)
48*22ce4affSfengbojiang #define	TARGET_Z	(2U)
49*22ce4affSfengbojiang 
50*22ce4affSfengbojiang /*
51*22ce4affSfengbojiang  * Parity generation methods indexes
52*22ce4affSfengbojiang  */
53*22ce4affSfengbojiang enum raidz_math_gen_op {
54*22ce4affSfengbojiang 	RAIDZ_GEN_P = 0,
55*22ce4affSfengbojiang 	RAIDZ_GEN_PQ,
56*22ce4affSfengbojiang 	RAIDZ_GEN_PQR,
57*22ce4affSfengbojiang 	RAIDZ_GEN_NUM = 3
58*22ce4affSfengbojiang };
59*22ce4affSfengbojiang /*
60*22ce4affSfengbojiang  * Data reconstruction methods indexes
61*22ce4affSfengbojiang  */
62*22ce4affSfengbojiang enum raidz_rec_op {
63*22ce4affSfengbojiang 	RAIDZ_REC_P = 0,
64*22ce4affSfengbojiang 	RAIDZ_REC_Q,
65*22ce4affSfengbojiang 	RAIDZ_REC_R,
66*22ce4affSfengbojiang 	RAIDZ_REC_PQ,
67*22ce4affSfengbojiang 	RAIDZ_REC_PR,
68*22ce4affSfengbojiang 	RAIDZ_REC_QR,
69*22ce4affSfengbojiang 	RAIDZ_REC_PQR,
70*22ce4affSfengbojiang 	RAIDZ_REC_NUM = 7
71*22ce4affSfengbojiang };
72*22ce4affSfengbojiang 
73*22ce4affSfengbojiang extern const char *raidz_gen_name[RAIDZ_GEN_NUM];
74*22ce4affSfengbojiang extern const char *raidz_rec_name[RAIDZ_REC_NUM];
75*22ce4affSfengbojiang 
76*22ce4affSfengbojiang /*
77*22ce4affSfengbojiang  * Methods used to define raidz implementation
78*22ce4affSfengbojiang  *
79*22ce4affSfengbojiang  * @raidz_gen_f	Parity generation function
80*22ce4affSfengbojiang  *     @par1	pointer to raidz_map
81*22ce4affSfengbojiang  * @raidz_rec_f	Data reconstruction function
82*22ce4affSfengbojiang  *     @par1	pointer to raidz_map
83*22ce4affSfengbojiang  *     @par2	array of reconstruction targets
84*22ce4affSfengbojiang  * @will_work_f Function returns TRUE if impl. is supported on the system
85*22ce4affSfengbojiang  * @init_impl_f Function is called once on init
86*22ce4affSfengbojiang  * @fini_impl_f Function is called once on fini
87*22ce4affSfengbojiang  */
88*22ce4affSfengbojiang typedef void		(*raidz_gen_f)(void *);
89*22ce4affSfengbojiang typedef int		(*raidz_rec_f)(void *, const int *);
90*22ce4affSfengbojiang typedef boolean_t	(*will_work_f)(void);
91*22ce4affSfengbojiang typedef void		(*init_impl_f)(void);
92*22ce4affSfengbojiang typedef void		(*fini_impl_f)(void);
93*22ce4affSfengbojiang 
94*22ce4affSfengbojiang #define	RAIDZ_IMPL_NAME_MAX	(20)
95*22ce4affSfengbojiang 
96*22ce4affSfengbojiang typedef struct raidz_impl_ops {
97*22ce4affSfengbojiang 	init_impl_f init;
98*22ce4affSfengbojiang 	fini_impl_f fini;
99*22ce4affSfengbojiang 	raidz_gen_f gen[RAIDZ_GEN_NUM];	/* Parity generate functions */
100*22ce4affSfengbojiang 	raidz_rec_f rec[RAIDZ_REC_NUM];	/* Data reconstruction functions */
101*22ce4affSfengbojiang 	will_work_f is_supported;	/* Support check function */
102*22ce4affSfengbojiang 	char name[RAIDZ_IMPL_NAME_MAX];	/* Name of the implementation */
103*22ce4affSfengbojiang } raidz_impl_ops_t;
104*22ce4affSfengbojiang 
105*22ce4affSfengbojiang typedef struct raidz_col {
106*22ce4affSfengbojiang 	uint64_t rc_devidx;		/* child device index for I/O */
107*22ce4affSfengbojiang 	uint64_t rc_offset;		/* device offset */
108*22ce4affSfengbojiang 	uint64_t rc_size;		/* I/O size */
109*22ce4affSfengbojiang 	abd_t *rc_abd;			/* I/O data */
110*22ce4affSfengbojiang 	void *rc_orig_data;		/* pre-reconstruction */
111*22ce4affSfengbojiang 	abd_t *rc_gdata;		/* used to store the "good" version */
112*22ce4affSfengbojiang 	int rc_error;			/* I/O error for this device */
113*22ce4affSfengbojiang 	uint8_t rc_tried;		/* Did we attempt this I/O column? */
114*22ce4affSfengbojiang 	uint8_t rc_skipped;		/* Did we skip this I/O column? */
115*22ce4affSfengbojiang 	uint8_t rc_need_orig_restore;	/* need to restore from orig_data? */
116*22ce4affSfengbojiang 	uint8_t rc_repair;		/* Write good data to this column */
117*22ce4affSfengbojiang } raidz_col_t;
118*22ce4affSfengbojiang 
119*22ce4affSfengbojiang typedef struct raidz_row {
120*22ce4affSfengbojiang 	uint64_t rr_cols;		/* Regular column count */
121*22ce4affSfengbojiang 	uint64_t rr_scols;		/* Count including skipped columns */
122*22ce4affSfengbojiang 	uint64_t rr_bigcols;		/* Remainder data column count */
123*22ce4affSfengbojiang 	uint64_t rr_missingdata;	/* Count of missing data devices */
124*22ce4affSfengbojiang 	uint64_t rr_missingparity;	/* Count of missing parity devices */
125*22ce4affSfengbojiang 	uint64_t rr_firstdatacol;	/* First data column/parity count */
126*22ce4affSfengbojiang 	abd_t *rr_abd_copy;		/* rm_asize-buffer of copied data */
127*22ce4affSfengbojiang 	abd_t *rr_abd_empty;		/* dRAID empty sector buffer */
128*22ce4affSfengbojiang 	int rr_nempty;			/* empty sectors included in parity */
129*22ce4affSfengbojiang 	int rr_code;			/* reconstruction code (unused) */
130*22ce4affSfengbojiang #ifdef ZFS_DEBUG
131*22ce4affSfengbojiang 	uint64_t rr_offset;		/* Logical offset for *_io_verify() */
132*22ce4affSfengbojiang 	uint64_t rr_size;		/* Physical size for *_io_verify() */
133*22ce4affSfengbojiang #endif
134*22ce4affSfengbojiang 	raidz_col_t rr_col[0];		/* Flexible array of I/O columns */
135*22ce4affSfengbojiang } raidz_row_t;
136*22ce4affSfengbojiang 
137*22ce4affSfengbojiang typedef struct raidz_map {
138*22ce4affSfengbojiang 	uintptr_t rm_reports;		/* # of referencing checksum reports */
139*22ce4affSfengbojiang 	boolean_t rm_freed;		/* map no longer has referencing ZIO */
140*22ce4affSfengbojiang 	boolean_t rm_ecksuminjected;	/* checksum error was injected */
141*22ce4affSfengbojiang 	int rm_nrows;			/* Regular row count */
142*22ce4affSfengbojiang 	int rm_nskip;			/* RAIDZ sectors skipped for padding */
143*22ce4affSfengbojiang 	int rm_skipstart;		/* Column index of padding start */
144*22ce4affSfengbojiang 	const raidz_impl_ops_t *rm_ops;	/* RAIDZ math operations */
145*22ce4affSfengbojiang 	raidz_row_t *rm_row[0];		/* flexible array of rows */
146*22ce4affSfengbojiang } raidz_map_t;
147*22ce4affSfengbojiang 
148*22ce4affSfengbojiang 
149*22ce4affSfengbojiang #define	RAIDZ_ORIGINAL_IMPL	(INT_MAX)
150*22ce4affSfengbojiang 
151*22ce4affSfengbojiang extern const raidz_impl_ops_t vdev_raidz_scalar_impl;
152*22ce4affSfengbojiang extern boolean_t raidz_will_scalar_work(void);
153*22ce4affSfengbojiang 
154*22ce4affSfengbojiang #if defined(__x86_64) && defined(HAVE_SSE2)	/* only x86_64 for now */
155*22ce4affSfengbojiang extern const raidz_impl_ops_t vdev_raidz_sse2_impl;
156*22ce4affSfengbojiang #endif
157*22ce4affSfengbojiang #if defined(__x86_64) && defined(HAVE_SSSE3)	/* only x86_64 for now */
158*22ce4affSfengbojiang extern const raidz_impl_ops_t vdev_raidz_ssse3_impl;
159*22ce4affSfengbojiang #endif
160*22ce4affSfengbojiang #if defined(__x86_64) && defined(HAVE_AVX2)	/* only x86_64 for now */
161*22ce4affSfengbojiang extern const raidz_impl_ops_t vdev_raidz_avx2_impl;
162*22ce4affSfengbojiang #endif
163*22ce4affSfengbojiang #if defined(__x86_64) && defined(HAVE_AVX512F)	/* only x86_64 for now */
164*22ce4affSfengbojiang extern const raidz_impl_ops_t vdev_raidz_avx512f_impl;
165*22ce4affSfengbojiang #endif
166*22ce4affSfengbojiang #if defined(__x86_64) && defined(HAVE_AVX512BW)	/* only x86_64 for now */
167*22ce4affSfengbojiang extern const raidz_impl_ops_t vdev_raidz_avx512bw_impl;
168*22ce4affSfengbojiang #endif
169*22ce4affSfengbojiang #if defined(__aarch64__)
170*22ce4affSfengbojiang extern const raidz_impl_ops_t vdev_raidz_aarch64_neon_impl;
171*22ce4affSfengbojiang extern const raidz_impl_ops_t vdev_raidz_aarch64_neonx2_impl;
172*22ce4affSfengbojiang #endif
173*22ce4affSfengbojiang #if defined(__powerpc__)
174*22ce4affSfengbojiang extern const raidz_impl_ops_t vdev_raidz_powerpc_altivec_impl;
175*22ce4affSfengbojiang #endif
176*22ce4affSfengbojiang 
177*22ce4affSfengbojiang /*
178*22ce4affSfengbojiang  * Commonly used raidz_map helpers
179*22ce4affSfengbojiang  *
180*22ce4affSfengbojiang  * raidz_parity		Returns parity of the RAIDZ block
181*22ce4affSfengbojiang  * raidz_ncols		Returns number of columns the block spans
182*22ce4affSfengbojiang  *			Note, all rows have the same number of columns.
183*22ce4affSfengbojiang  * raidz_nbigcols	Returns number of big columns
184*22ce4affSfengbojiang  * raidz_col_p		Returns pointer to a column
185*22ce4affSfengbojiang  * raidz_col_size	Returns size of a column
186*22ce4affSfengbojiang  * raidz_big_size	Returns size of big columns
187*22ce4affSfengbojiang  * raidz_short_size	Returns size of short columns
188*22ce4affSfengbojiang  */
189*22ce4affSfengbojiang #define	raidz_parity(rm)	((rm)->rm_row[0]->rr_firstdatacol)
190*22ce4affSfengbojiang #define	raidz_ncols(rm)		((rm)->rm_row[0]->rr_cols)
191*22ce4affSfengbojiang #define	raidz_nbigcols(rm)	((rm)->rm_bigcols)
192*22ce4affSfengbojiang #define	raidz_col_p(rm, c)	((rm)->rm_col + (c))
193*22ce4affSfengbojiang #define	raidz_col_size(rm, c)	((rm)->rm_col[c].rc_size)
194*22ce4affSfengbojiang #define	raidz_big_size(rm)	(raidz_col_size(rm, CODE_P))
195*22ce4affSfengbojiang #define	raidz_short_size(rm)	(raidz_col_size(rm, raidz_ncols(rm)-1))
196*22ce4affSfengbojiang 
197*22ce4affSfengbojiang /*
198*22ce4affSfengbojiang  * Macro defines an RAIDZ parity generation method
199*22ce4affSfengbojiang  *
200*22ce4affSfengbojiang  * @code	parity the function produce
201*22ce4affSfengbojiang  * @impl	name of the implementation
202*22ce4affSfengbojiang  */
203*22ce4affSfengbojiang #define	_RAIDZ_GEN_WRAP(code, impl)					\
204*22ce4affSfengbojiang static void								\
205*22ce4affSfengbojiang impl ## _gen_ ## code(void *rrp)					\
206*22ce4affSfengbojiang {									\
207*22ce4affSfengbojiang 	raidz_row_t *rr = (raidz_row_t *)rrp;				\
208*22ce4affSfengbojiang 	raidz_generate_## code ## _impl(rr);				\
209*22ce4affSfengbojiang }
210*22ce4affSfengbojiang 
211*22ce4affSfengbojiang /*
212*22ce4affSfengbojiang  * Macro defines an RAIDZ data reconstruction method
213*22ce4affSfengbojiang  *
214*22ce4affSfengbojiang  * @code	parity the function produce
215*22ce4affSfengbojiang  * @impl	name of the implementation
216*22ce4affSfengbojiang  */
217*22ce4affSfengbojiang #define	_RAIDZ_REC_WRAP(code, impl)					\
218*22ce4affSfengbojiang static int								\
219*22ce4affSfengbojiang impl ## _rec_ ## code(void *rrp, const int *tgtidx)			\
220*22ce4affSfengbojiang {									\
221*22ce4affSfengbojiang 	raidz_row_t *rr = (raidz_row_t *)rrp;				\
222*22ce4affSfengbojiang 	return (raidz_reconstruct_## code ## _impl(rr, tgtidx));	\
223*22ce4affSfengbojiang }
224*22ce4affSfengbojiang 
225*22ce4affSfengbojiang /*
226*22ce4affSfengbojiang  * Define all gen methods for an implementation
227*22ce4affSfengbojiang  *
228*22ce4affSfengbojiang  * @impl	name of the implementation
229*22ce4affSfengbojiang  */
230*22ce4affSfengbojiang #define	DEFINE_GEN_METHODS(impl)					\
231*22ce4affSfengbojiang 	_RAIDZ_GEN_WRAP(p, impl);					\
232*22ce4affSfengbojiang 	_RAIDZ_GEN_WRAP(pq, impl);					\
233*22ce4affSfengbojiang 	_RAIDZ_GEN_WRAP(pqr, impl)
234*22ce4affSfengbojiang 
235*22ce4affSfengbojiang /*
236*22ce4affSfengbojiang  * Define all rec functions for an implementation
237*22ce4affSfengbojiang  *
238*22ce4affSfengbojiang  * @impl	name of the implementation
239*22ce4affSfengbojiang  */
240*22ce4affSfengbojiang #define	DEFINE_REC_METHODS(impl)					\
241*22ce4affSfengbojiang 	_RAIDZ_REC_WRAP(p, impl);					\
242*22ce4affSfengbojiang 	_RAIDZ_REC_WRAP(q, impl);					\
243*22ce4affSfengbojiang 	_RAIDZ_REC_WRAP(r, impl);					\
244*22ce4affSfengbojiang 	_RAIDZ_REC_WRAP(pq, impl);					\
245*22ce4affSfengbojiang 	_RAIDZ_REC_WRAP(pr, impl);					\
246*22ce4affSfengbojiang 	_RAIDZ_REC_WRAP(qr, impl);					\
247*22ce4affSfengbojiang 	_RAIDZ_REC_WRAP(pqr, impl)
248*22ce4affSfengbojiang 
249*22ce4affSfengbojiang #define	RAIDZ_GEN_METHODS(impl)						\
250*22ce4affSfengbojiang {									\
251*22ce4affSfengbojiang 	[RAIDZ_GEN_P] = & impl ## _gen_p,				\
252*22ce4affSfengbojiang 	[RAIDZ_GEN_PQ] = & impl ## _gen_pq,				\
253*22ce4affSfengbojiang 	[RAIDZ_GEN_PQR] = & impl ## _gen_pqr				\
254*22ce4affSfengbojiang }
255*22ce4affSfengbojiang 
256*22ce4affSfengbojiang #define	RAIDZ_REC_METHODS(impl)						\
257*22ce4affSfengbojiang {									\
258*22ce4affSfengbojiang 	[RAIDZ_REC_P] = & impl ## _rec_p,				\
259*22ce4affSfengbojiang 	[RAIDZ_REC_Q] = & impl ## _rec_q,				\
260*22ce4affSfengbojiang 	[RAIDZ_REC_R] = & impl ## _rec_r,				\
261*22ce4affSfengbojiang 	[RAIDZ_REC_PQ] = & impl ## _rec_pq,				\
262*22ce4affSfengbojiang 	[RAIDZ_REC_PR] = & impl ## _rec_pr,				\
263*22ce4affSfengbojiang 	[RAIDZ_REC_QR] = & impl ## _rec_qr,				\
264*22ce4affSfengbojiang 	[RAIDZ_REC_PQR] = & impl ## _rec_pqr				\
265*22ce4affSfengbojiang }
266*22ce4affSfengbojiang 
267*22ce4affSfengbojiang 
268*22ce4affSfengbojiang typedef struct raidz_impl_kstat {
269*22ce4affSfengbojiang 	uint64_t gen[RAIDZ_GEN_NUM];	/* gen method speed B/s */
270*22ce4affSfengbojiang 	uint64_t rec[RAIDZ_REC_NUM];	/* rec method speed B/s */
271*22ce4affSfengbojiang } raidz_impl_kstat_t;
272*22ce4affSfengbojiang 
273*22ce4affSfengbojiang /*
274*22ce4affSfengbojiang  * Enumerate various multiplication constants
275*22ce4affSfengbojiang  * used in reconstruction methods
276*22ce4affSfengbojiang  */
277*22ce4affSfengbojiang typedef enum raidz_mul_info {
278*22ce4affSfengbojiang 	/* Reconstruct Q */
279*22ce4affSfengbojiang 	MUL_Q_X		= 0,
280*22ce4affSfengbojiang 	/* Reconstruct R */
281*22ce4affSfengbojiang 	MUL_R_X		= 0,
282*22ce4affSfengbojiang 	/* Reconstruct PQ */
283*22ce4affSfengbojiang 	MUL_PQ_X	= 0,
284*22ce4affSfengbojiang 	MUL_PQ_Y	= 1,
285*22ce4affSfengbojiang 	/* Reconstruct PR */
286*22ce4affSfengbojiang 	MUL_PR_X	= 0,
287*22ce4affSfengbojiang 	MUL_PR_Y	= 1,
288*22ce4affSfengbojiang 	/* Reconstruct QR */
289*22ce4affSfengbojiang 	MUL_QR_XQ	= 0,
290*22ce4affSfengbojiang 	MUL_QR_X	= 1,
291*22ce4affSfengbojiang 	MUL_QR_YQ	= 2,
292*22ce4affSfengbojiang 	MUL_QR_Y	= 3,
293*22ce4affSfengbojiang 	/* Reconstruct PQR */
294*22ce4affSfengbojiang 	MUL_PQR_XP	= 0,
295*22ce4affSfengbojiang 	MUL_PQR_XQ	= 1,
296*22ce4affSfengbojiang 	MUL_PQR_XR	= 2,
297*22ce4affSfengbojiang 	MUL_PQR_YU	= 3,
298*22ce4affSfengbojiang 	MUL_PQR_YP	= 4,
299*22ce4affSfengbojiang 	MUL_PQR_YQ	= 5,
300*22ce4affSfengbojiang 
301*22ce4affSfengbojiang 	MUL_CNT		= 6
302*22ce4affSfengbojiang } raidz_mul_info_t;
303*22ce4affSfengbojiang 
304*22ce4affSfengbojiang /*
305*22ce4affSfengbojiang  * Powers of 2 in the Galois field.
306*22ce4affSfengbojiang  */
307*22ce4affSfengbojiang extern const uint8_t vdev_raidz_pow2[256] __attribute__((aligned(256)));
308*22ce4affSfengbojiang /* Logs of 2 in the Galois field defined above. */
309*22ce4affSfengbojiang extern const uint8_t vdev_raidz_log2[256] __attribute__((aligned(256)));
310*22ce4affSfengbojiang 
311*22ce4affSfengbojiang /*
312*22ce4affSfengbojiang  * Multiply a given number by 2 raised to the given power.
313*22ce4affSfengbojiang  */
314*22ce4affSfengbojiang static inline uint8_t
vdev_raidz_exp2(const uint8_t a,const unsigned exp)315*22ce4affSfengbojiang vdev_raidz_exp2(const uint8_t a, const unsigned exp)
316*22ce4affSfengbojiang {
317*22ce4affSfengbojiang 	if (a == 0)
318*22ce4affSfengbojiang 		return (0);
319*22ce4affSfengbojiang 
320*22ce4affSfengbojiang 	return (vdev_raidz_pow2[(exp + (unsigned)vdev_raidz_log2[a]) % 255]);
321*22ce4affSfengbojiang }
322*22ce4affSfengbojiang 
323*22ce4affSfengbojiang /*
324*22ce4affSfengbojiang  * Galois Field operations.
325*22ce4affSfengbojiang  *
326*22ce4affSfengbojiang  * gf_exp2	- computes 2 raised to the given power
327*22ce4affSfengbojiang  * gf_exp2	- computes 4 raised to the given power
328*22ce4affSfengbojiang  * gf_mul	- multiplication
329*22ce4affSfengbojiang  * gf_div	- division
330*22ce4affSfengbojiang  * gf_inv	- multiplicative inverse
331*22ce4affSfengbojiang  */
332*22ce4affSfengbojiang typedef unsigned gf_t;
333*22ce4affSfengbojiang typedef unsigned gf_log_t;
334*22ce4affSfengbojiang 
335*22ce4affSfengbojiang static inline gf_t
gf_mul(const gf_t a,const gf_t b)336*22ce4affSfengbojiang gf_mul(const gf_t a, const gf_t b)
337*22ce4affSfengbojiang {
338*22ce4affSfengbojiang 	gf_log_t logsum;
339*22ce4affSfengbojiang 
340*22ce4affSfengbojiang 	if (a == 0 || b == 0)
341*22ce4affSfengbojiang 		return (0);
342*22ce4affSfengbojiang 
343*22ce4affSfengbojiang 	logsum = (gf_log_t)vdev_raidz_log2[a] + (gf_log_t)vdev_raidz_log2[b];
344*22ce4affSfengbojiang 
345*22ce4affSfengbojiang 	return ((gf_t)vdev_raidz_pow2[logsum % 255]);
346*22ce4affSfengbojiang }
347*22ce4affSfengbojiang 
348*22ce4affSfengbojiang static inline gf_t
gf_div(const gf_t a,const gf_t b)349*22ce4affSfengbojiang gf_div(const gf_t  a, const gf_t b)
350*22ce4affSfengbojiang {
351*22ce4affSfengbojiang 	gf_log_t logsum;
352*22ce4affSfengbojiang 
353*22ce4affSfengbojiang 	ASSERT3U(b, >, 0);
354*22ce4affSfengbojiang 	if (a == 0)
355*22ce4affSfengbojiang 		return (0);
356*22ce4affSfengbojiang 
357*22ce4affSfengbojiang 	logsum = (gf_log_t)255 + (gf_log_t)vdev_raidz_log2[a] -
358*22ce4affSfengbojiang 	    (gf_log_t)vdev_raidz_log2[b];
359*22ce4affSfengbojiang 
360*22ce4affSfengbojiang 	return ((gf_t)vdev_raidz_pow2[logsum % 255]);
361*22ce4affSfengbojiang }
362*22ce4affSfengbojiang 
363*22ce4affSfengbojiang static inline gf_t
gf_inv(const gf_t a)364*22ce4affSfengbojiang gf_inv(const gf_t a)
365*22ce4affSfengbojiang {
366*22ce4affSfengbojiang 	gf_log_t logsum;
367*22ce4affSfengbojiang 
368*22ce4affSfengbojiang 	ASSERT3U(a, >, 0);
369*22ce4affSfengbojiang 
370*22ce4affSfengbojiang 	logsum = (gf_log_t)255 - (gf_log_t)vdev_raidz_log2[a];
371*22ce4affSfengbojiang 
372*22ce4affSfengbojiang 	return ((gf_t)vdev_raidz_pow2[logsum]);
373*22ce4affSfengbojiang }
374*22ce4affSfengbojiang 
375*22ce4affSfengbojiang static inline gf_t
gf_exp2(gf_log_t exp)376*22ce4affSfengbojiang gf_exp2(gf_log_t exp)
377*22ce4affSfengbojiang {
378*22ce4affSfengbojiang 	return (vdev_raidz_pow2[exp % 255]);
379*22ce4affSfengbojiang }
380*22ce4affSfengbojiang 
381*22ce4affSfengbojiang static inline gf_t
gf_exp4(gf_log_t exp)382*22ce4affSfengbojiang gf_exp4(gf_log_t exp)
383*22ce4affSfengbojiang {
384*22ce4affSfengbojiang 	ASSERT3U(exp, <=, 255);
385*22ce4affSfengbojiang 	return ((gf_t)vdev_raidz_pow2[(2 * exp) % 255]);
386*22ce4affSfengbojiang }
387*22ce4affSfengbojiang 
388*22ce4affSfengbojiang #ifdef  __cplusplus
389*22ce4affSfengbojiang }
390*22ce4affSfengbojiang #endif
391*22ce4affSfengbojiang 
392*22ce4affSfengbojiang #endif /* _VDEV_RAIDZ_H */
393