liberasurecode 1.8.0
Erasure Code API library
Loading...
Searching...
No Matches
jerasure_rs_vand.c
Go to the documentation of this file.
1/*
2 * Copyright 2014 Kevin M Greenan
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice, this
11 * list of conditions and the following disclaimer in the documentation and/or
12 * other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY
13 * THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
17 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
20 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
21 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * jerasure_rs_vand backend implementation
25 *
26 * vi: set noai tw=79 ts=4 sw=4:
27 */
28
29#include <stdio.h>
30#include <stdlib.h>
31
32#include "erasurecode.h"
33#include "erasurecode_backend.h"
34#include "erasurecode_helpers.h"
35#include "erasurecode_helpers_ext.h"
36
37#define JERASURE_RS_VAND_LIB_MAJOR 2
38#define JERASURE_RS_VAND_LIB_MINOR 0
39#define JERASURE_RS_VAND_LIB_REV 0
40#define JERASURE_RS_VAND_LIB_VER_STR "2.0"
41#define JERASURE_RS_VAND_LIB_NAME "jerasure_rs_vand"
42#if defined(__MACOS__) || defined(__MACOSX__) || defined(__OSX__) || defined(__APPLE__)
43#define JERASURE_RS_VAND_SO_NAME "libJerasure" LIBERASURECODE_SO_SUFFIX ".dylib"
44#else
45#define JERASURE_RS_VAND_SO_NAME "libJerasure" LIBERASURECODE_SO_SUFFIX ".so.2"
46#endif
47
48/* Forward declarations */
49struct ec_backend_common backend_jerasure_rs_vand;
50
51typedef int* (*reed_sol_vandermonde_coding_matrix_func)(int, int, int);
52typedef void (*jerasure_matrix_encode_func)(int, int, int, int*, char **, char **, int);
53typedef int (*jerasure_matrix_decode_func)(int, int, int, int *, int, int*, char **, char **, int);
54typedef int (*jerasure_make_decoding_matrix_func)(int, int, int, int *, int *, int *, int *);
55typedef int * (*jerasure_erasures_to_erased_func)(int, int, int *);
56typedef void (*jerasure_matrix_dotprod_func)(int, int, int *,int *, int,char **, char **, int);
57typedef void (*galois_uninit_field_func)(int);
58
60 /* calls required for init */
62
63 /* calls required for free */
65
66 /* calls required for encode */
68
69 /* calls required for decode */
71
72 /* calls required for reconstruct */
76
77 /* fields needed to hold state */
78 int *matrix;
79 int k;
80 int m;
81 int w;
82};
83
84static int jerasure_rs_vand_encode(void *desc, char **data, char **parity,
85 int blocksize)
86{
87 struct jerasure_rs_vand_descriptor *jerasure_desc =
88 (struct jerasure_rs_vand_descriptor*) desc;
89
90 /* FIXME - make jerasure_matrix_encode return a value */
91 jerasure_desc->jerasure_matrix_encode(jerasure_desc->k, jerasure_desc->m,
92 jerasure_desc->w, jerasure_desc->matrix, data, parity, blocksize);
93
94 return 0;
95}
96
97static int jerasure_rs_vand_decode(void *desc, char **data, char **parity,
98 int *missing_idxs, int blocksize)
99{
100 struct jerasure_rs_vand_descriptor *jerasure_desc =
101 (struct jerasure_rs_vand_descriptor*)desc;
102
103 /* FIXME - make jerasure_matrix_decode return a value */
104 jerasure_desc->jerasure_matrix_decode(jerasure_desc->k,
105 jerasure_desc->m, jerasure_desc->w,
106 jerasure_desc->matrix, 1, missing_idxs, data, parity, blocksize);
107
108 return 0;
109}
110
111static int jerasure_rs_vand_reconstruct(void *desc, char **data, char **parity,
112 int *missing_idxs, int destination_idx, int blocksize)
113{
114 int ret = 0; /* return code */
115 int *decoding_row; /* decoding matrix row for decode */
116 int *erased = NULL; /* k+m length list of erased frag ids */
117 int *dm_ids = NULL; /* k length list of frag ids */
118 int *decoding_matrix = NULL; /* matrix for decoding */
119
120 struct jerasure_rs_vand_descriptor *jerasure_desc =
121 (struct jerasure_rs_vand_descriptor*) desc;
122
123 if (destination_idx < jerasure_desc->k) {
124 dm_ids = (int *) alloc_zeroed_buffer(sizeof(int) * jerasure_desc->k);
125 decoding_matrix = (int *)
126 alloc_zeroed_buffer(sizeof(int*) * jerasure_desc->k * jerasure_desc->k);
127 erased = jerasure_desc->jerasure_erasures_to_erased(jerasure_desc->k,
128 jerasure_desc->m, missing_idxs);
129 if (NULL == decoding_matrix || NULL == dm_ids || NULL == erased) {
130 goto out;
131 }
132
133 ret = jerasure_desc->jerasure_make_decoding_matrix(jerasure_desc->k,
134 jerasure_desc->m, jerasure_desc->w, jerasure_desc->matrix,
135 erased, decoding_matrix, dm_ids);
136
137 decoding_row = decoding_matrix + (destination_idx * jerasure_desc->k);
138
139 if (ret == 0) {
140 jerasure_desc->jerasure_matrix_dotprod(jerasure_desc->k,
141 jerasure_desc->w, decoding_row, dm_ids, destination_idx,
142 data, parity, blocksize);
143 } else {
144 /*
145 * ToDo (KMG) I know this is not needed, but keeping to prevent future
146 * memory leaks, as this function will be better optimized for decoding
147 * missing parity
148 */
149 goto out;
150 }
151 } else {
152 /*
153 * If it is parity we are reconstructing, then just call decode.
154 * ToDo (KMG): We can do better than this, but this should perform just
155 * fine for most cases. We can adjust the decoding matrix like we
156 * did with ISA-L.
157 */
158 jerasure_desc->jerasure_matrix_decode(jerasure_desc->k,
159 jerasure_desc->m, jerasure_desc->w,
160 jerasure_desc->matrix, 1, missing_idxs, data, parity, blocksize);
161 goto parity_reconstr_out;
162 }
163
164out:
165 free(erased);
166 free(decoding_matrix);
167 free(dm_ids);
168
169parity_reconstr_out:
170 return ret;
171}
172
173static int jerasure_rs_vand_min_fragments(void *desc, int *missing_idxs,
174 int *fragments_to_exclude, int *fragments_needed)
175{
176 struct jerasure_rs_vand_descriptor *jerasure_desc =
177 (struct jerasure_rs_vand_descriptor*)desc;
178
179 struct ec_bm exclude_bm = NEW_BM, missing_bm = NEW_BM;
180 convert_list_to_bitmap(fragments_to_exclude, &exclude_bm);
181 convert_list_to_bitmap(missing_idxs, &missing_bm);
182 bm_combine_or(&exclude_bm, &missing_bm);
183 int i;
184 int j = 0;
185 int ret = -1;
186
187 for (i = 0; i < (jerasure_desc->k + jerasure_desc->m); i++) {
188 if (!bm_get_value(&missing_bm, i)) {
189 fragments_needed[j] = i;
190 j++;
191 }
192 if (j == jerasure_desc->k) {
193 ret = 0;
194 fragments_needed[j] = -1;
195 break;
196 }
197 }
198
199 return ret;
200}
201
202#define DEFAULT_W 16
203static void * jerasure_rs_vand_init(struct ec_backend_args *args,
204 void *backend_sohandle)
205{
206 struct jerasure_rs_vand_descriptor *desc = NULL;
207
208 desc = (struct jerasure_rs_vand_descriptor *)
209 malloc(sizeof(struct jerasure_rs_vand_descriptor));
210 if (NULL == desc) {
211 return NULL;
212 }
213
214 desc->k = args->uargs.k;
215 desc->m = args->uargs.m;
216
217 if (args->uargs.w <= 0)
218 args->uargs.w = DEFAULT_W;
219
220 /* store w back in args so upper layer can get to it */
221 desc->w = args->uargs.w;
222
223 /* validate EC arguments */
224 {
225 long long max_symbols;
226 if (desc->w != 8 && desc->w != 16 && desc->w != 32) {
227 goto error;
228 }
229 max_symbols = 1LL << desc->w;
230 if ((desc->k + desc->m) > max_symbols) {
231 goto error;
232 }
233 }
234
235 /*
236 * ISO C forbids casting a void* to a function pointer.
237 * Since dlsym return returns a void*, we use this union to
238 * "transform" the void* to a function pointer.
239 */
240 union {
248 void *vptr;
249 } func_handle = {.vptr = NULL};
250
251
252 /* fill in function addresses */
253 func_handle.vptr = NULL;
254 func_handle.vptr = dlsym(backend_sohandle, "jerasure_matrix_encode");
255 desc->jerasure_matrix_encode = func_handle.encodep;
256 if (NULL == desc->jerasure_matrix_encode) {
257 goto error;
258 }
259
260 func_handle.vptr = NULL;
261 func_handle.vptr = dlsym(backend_sohandle, "jerasure_matrix_decode");
262 desc->jerasure_matrix_decode = func_handle.decodep;
263 if (NULL == desc->jerasure_matrix_decode) {
264 goto error;
265 }
266
267 func_handle.vptr = NULL;
268 func_handle.vptr = dlsym(backend_sohandle, "jerasure_make_decoding_matrix");
269 desc->jerasure_make_decoding_matrix = func_handle.decodematrixp;
270 if (NULL == desc->jerasure_make_decoding_matrix) {
271 goto error;
272 }
273
274 func_handle.vptr = NULL;
275 func_handle.vptr = dlsym(backend_sohandle, "jerasure_matrix_dotprod");
276 desc->jerasure_matrix_dotprod = func_handle.dotprodp;
277 if (NULL == desc->jerasure_matrix_dotprod) {
278 goto error;
279 }
280
281 func_handle.vptr = NULL;
282 func_handle.vptr = dlsym(backend_sohandle, "jerasure_erasures_to_erased");
283 desc->jerasure_erasures_to_erased = func_handle.erasep;
284 if (NULL == desc->jerasure_erasures_to_erased) {
285 goto error;
286 }
287
288 func_handle.vptr = NULL;
289 func_handle.vptr = dlsym(backend_sohandle, "reed_sol_vandermonde_coding_matrix");
290 desc->reed_sol_vandermonde_coding_matrix = func_handle.initp;
291 if (NULL == desc->reed_sol_vandermonde_coding_matrix) {
292 goto error;
293 }
294
295 func_handle.vptr = NULL;
296 func_handle.vptr = dlsym(backend_sohandle, "galois_uninit_field");
297 desc->galois_uninit_field = func_handle.uninitp;
298 if (NULL == desc->galois_uninit_field) {
299 goto error;
300 }
301
303 desc->k, desc->m, desc->w);
304 if (NULL == desc->matrix) {
305 goto error;
306 }
307
308 return desc;
309
310error:
311 free(desc);
312
313 return NULL;
314}
315
323static int
325{
326 struct jerasure_rs_vand_descriptor *jerasure_desc =
327 (struct jerasure_rs_vand_descriptor*)desc;
328
329 /* Note that cauchy will return pyeclib_handle->w * PYECC_CAUCHY_PACKETSIZE * 8 */
330 return jerasure_desc->w;
331}
332
333static int jerasure_rs_vand_exit(void *desc)
334{
335 struct jerasure_rs_vand_descriptor *jerasure_desc = NULL;
336
337 jerasure_desc = (struct jerasure_rs_vand_descriptor*) desc;
338
339 /*
340 * jerasure allocates some internal data structures for caching
341 * fields. It will allocate one for w, and if we do anything that
342 * needs to xor a region >= 16 bytes, it will also allocate one
343 * for 32. Fortunately we can safely uninit any value; if it
344 * wasn't inited it will be ignored.
345 */
346 jerasure_desc->galois_uninit_field(jerasure_desc->w);
347 jerasure_desc->galois_uninit_field(32);
348 free(jerasure_desc->matrix);
349 free(jerasure_desc);
350
351 return 0;
352}
353
354/*
355 * For the time being, we only claim compatibility with versions that
356 * match exactly
357 */
358static bool jerasure_rs_vand_is_compatible_with(uint32_t version) {
359 return version == backend_jerasure_rs_vand.ec_backend_version;
360}
361
362static struct ec_backend_op_stubs jerasure_rs_vand_op_stubs = {
363 .INIT = jerasure_rs_vand_init,
364 .EXIT = jerasure_rs_vand_exit,
365 .ISSYSTEMATIC = 1,
366 .ENCODE = jerasure_rs_vand_encode,
367 .DECODE = jerasure_rs_vand_decode,
368 .FRAGSNEEDED = jerasure_rs_vand_min_fragments,
369 .RECONSTRUCT = jerasure_rs_vand_reconstruct,
370 .ELEMENTSIZE = jerasure_rs_vand_element_size,
371 .ISCOMPATIBLEWITH = jerasure_rs_vand_is_compatible_with,
372 .GETMETADATASIZE = get_backend_metadata_size_zero,
373 .GETENCODEOFFSET = get_encode_offset_zero,
374};
375
376__attribute__ ((visibility ("internal")))
377struct ec_backend_common backend_jerasure_rs_vand = {
378 .id = EC_BACKEND_JERASURE_RS_VAND,
380 .soname = JERASURE_RS_VAND_SO_NAME,
381 .soversion = JERASURE_RS_VAND_LIB_VER_STR,
383 .ec_backend_version = _VERSION(JERASURE_RS_VAND_LIB_MAJOR,
386};
int(* jerasure_matrix_decode_func)(int, int, int, int *, int, int *, char **, char **, int)
#define JERASURE_RS_VAND_LIB_NAME
#define JERASURE_RS_VAND_LIB_VER_STR
#define JERASURE_RS_VAND_LIB_MINOR
static int jerasure_rs_vand_min_fragments(void *desc, int *missing_idxs, int *fragments_to_exclude, int *fragments_needed)
static bool jerasure_rs_vand_is_compatible_with(uint32_t version)
void(* galois_uninit_field_func)(int)
void(* jerasure_matrix_encode_func)(int, int, int, int *, char **, char **, int)
static int jerasure_rs_vand_exit(void *desc)
static int jerasure_rs_vand_element_size(void *desc)
Return the element-size, which is the number of bits stored on a given device, per codeword.
int *(* jerasure_erasures_to_erased_func)(int, int, int *)
int *(* reed_sol_vandermonde_coding_matrix_func)(int, int, int)
#define JERASURE_RS_VAND_LIB_MAJOR
__attribute__((visibility("internal")))
#define JERASURE_RS_VAND_SO_NAME
static void * jerasure_rs_vand_init(struct ec_backend_args *args, void *backend_sohandle)
int(* jerasure_make_decoding_matrix_func)(int, int, int, int *, int *, int *, int *)
#define JERASURE_RS_VAND_LIB_REV
static int jerasure_rs_vand_reconstruct(void *desc, char **data, char **parity, int *missing_idxs, int destination_idx, int blocksize)
struct ec_backend_common backend_jerasure_rs_vand
void(* jerasure_matrix_dotprod_func)(int, int, int *, int *, int, char **, char **, int)
static int jerasure_rs_vand_encode(void *desc, char **data, char **parity, int blocksize)
static struct ec_backend_op_stubs jerasure_rs_vand_op_stubs
#define DEFAULT_W
static int jerasure_rs_vand_decode(void *desc, char **data, char **parity, int *missing_idxs, int blocksize)
jerasure_matrix_dotprod_func jerasure_matrix_dotprod
reed_sol_vandermonde_coding_matrix_func reed_sol_vandermonde_coding_matrix
galois_uninit_field_func galois_uninit_field
jerasure_make_decoding_matrix_func jerasure_make_decoding_matrix
jerasure_erasures_to_erased_func jerasure_erasures_to_erased
jerasure_matrix_encode_func jerasure_matrix_encode
jerasure_matrix_decode_func jerasure_matrix_decode