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