liberasurecode 1.8.0
Erasure Code API library
Loading...
Searching...
No Matches
isa_l_common.c
Go to the documentation of this file.
1/*
2 * Copyright 2014 Kevin M Greenan
3 * Copyright 2014 Tushar Gohad
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * Redistributions in binary form must reproduce the above copyright notice, this
12 * list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY
14 * THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17 * EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * isa_l_rs_vand backend implementation
26 *
27 * vi: set noai tw=79 ts=4 sw=4:
28 */
29
30#include <stdio.h>
31#include <stdlib.h>
32
33#include "erasurecode.h"
34#include "erasurecode_backend.h"
35#include "erasurecode_helpers.h"
36#include "erasurecode_helpers_ext.h"
37#include "isa_l_common.h"
38
39__attribute__ ((visibility ("internal")))
40int isa_l_encode(void *desc, char **data, char **parity,
41 int blocksize)
42{
43 isa_l_descriptor *isa_l_desc = (isa_l_descriptor*) desc;
44
45 unsigned char *g_tbls = isa_l_desc->encode_tables;
46 int k = isa_l_desc->k;
47 int m = isa_l_desc->m;
48
49 /* FIXME - make ec_encode_data return a value */
50 isa_l_desc->ec_encode_data(blocksize, k, m, g_tbls, (unsigned char**)data,
51 (unsigned char**)parity);
52 return 0;
53}
54
55static unsigned char* isa_l_get_decode_matrix(int k, int m, unsigned char *encode_matrix, int *missing_idxs)
56{
57 int i = 0, j = 0, l = 0;
58 int n = k + m;
59 unsigned char *decode_matrix = malloc(sizeof(unsigned char) * k * k);
60 struct ec_bm missing_bm = NEW_BM;
61 convert_list_to_bitmap(missing_idxs, &missing_bm);
62
63 while (i < k && l < n) {
64 if (!bm_get_value(&missing_bm, l)) {
65 for (j = 0; j < k; j++) {
66 decode_matrix[(k * i) + j] = encode_matrix[(k * l) + j];
67 }
68 i++;
69 }
70 l++;
71 }
72 if (i != k) {
73 free(decode_matrix);
74 decode_matrix = NULL;
75 }
76
77 return decode_matrix;
78}
79
80/*
81 * TODO: Add in missing parity rows and adjust the inverse_rows to
82 * be used for parity.
83 */
84static unsigned char* get_inverse_rows(int k,
85 int m,
86 unsigned char *decode_inverse,
87 unsigned char* encode_matrix,
88 int *missing_idxs,
89 gf_mul_func gf_mul)
90{
91 struct ec_bm missing_bm = NEW_BM;
92 convert_list_to_bitmap(missing_idxs, &missing_bm);
93 int num_missing_elements = get_num_missing_elements(missing_idxs);
94 unsigned char *inverse_rows = (unsigned char*)malloc(sizeof(unsigned
95 char*) * k * num_missing_elements);
96 int i, j, l = 0;
97 int n = k + m;
98
99 if (NULL == inverse_rows) {
100 return NULL;
101 }
102
103 memset(inverse_rows, 0, sizeof(unsigned
104 char*) * k * num_missing_elements);
105
106 /*
107 * Fill in rows for missing data
108 */
109 for (i = 0; i < k; i++) {
110 if (bm_get_value(&missing_bm, i)) {
111 for (j = 0; j < k; j++) {
112 inverse_rows[(l * k) + j] = decode_inverse[(i * k) + j];
113 }
114 l++;
115 }
116 }
117
118 /*
119 * Process missing parity.
120 *
121 * Start with an all-zero row.
122 *
123 * For each data element, if the data element is:
124 *
125 * Available: XOR the corresponding coefficient from the
126 * encoding matrix.
127 *
128 * Unavailable: multiply corresponding coefficient with
129 * the row that corresponds to the missing data in inverse_rows
130 * and XOR the resulting row with this row.
131 */
132 for (i = k; i < n; i++) {
133 // Parity is missing
134 if (bm_get_value(&missing_bm, i)) {
135 int d_idx_avail = 0;
136 int d_idx_unavail = 0;
137 for (j = 0; j < k; j++) {
138 // This data is available, so we can use the encode matrix
139 if (!bm_get_value(&missing_bm, j)) {
140 inverse_rows[(l * k) + d_idx_avail] ^= encode_matrix[(i * k) + j];
141 d_idx_avail++;
142 } else {
143 mult_and_xor_row(&inverse_rows[l * k],
144 &inverse_rows[d_idx_unavail * k],
145 encode_matrix[(i * k) + j],
146 k,
147 gf_mul);
148 d_idx_unavail++;
149 }
150 }
151 l++;
152 }
153 }
154 return inverse_rows;
155}
156
157__attribute__ ((visibility ("internal")))
158int isa_l_decode(void *desc, char **data, char **parity,
159 int *missing_idxs, int blocksize)
160{
161 isa_l_descriptor *isa_l_desc = (isa_l_descriptor*)desc;
162
163 unsigned char *g_tbls = NULL;
164 unsigned char *decode_matrix = NULL;
165 unsigned char *decode_inverse = NULL;
166 unsigned char *inverse_rows = NULL;
167 unsigned char **decoded_elements = NULL;
168 unsigned char **available_fragments = NULL;
169 int k = isa_l_desc->k;
170 int m = isa_l_desc->m;
171 int n = k + m;
172 int ret = -1;
173 int i, j;
174
175 int num_missing_elements = get_num_missing_elements(missing_idxs);
176 struct ec_bm missing_bm = NEW_BM;
177 convert_list_to_bitmap(missing_idxs, &missing_bm);
178
179 decode_matrix = isa_l_get_decode_matrix(k, m, isa_l_desc->matrix, missing_idxs);
180
181 if (NULL == decode_matrix) {
182 goto out;
183 }
184
185 decode_inverse = (unsigned char*)malloc(sizeof(unsigned char) * k * k);
186
187 if (NULL == decode_inverse) {
188 goto out;
189 }
190
191 int im_ret = isa_l_desc->gf_invert_matrix(decode_matrix, decode_inverse, k);
192 if (im_ret < 0) {
193 goto out;
194 }
195
196 // Generate g_tbls from computed decode matrix (k x k) matrix
197 g_tbls = malloc(sizeof(unsigned char) * (k * m * 32));
198 if (NULL == g_tbls) {
199 goto out;
200 }
201
202 inverse_rows = get_inverse_rows(k, m, decode_inverse, isa_l_desc->matrix, missing_idxs, isa_l_desc->gf_mul);
203
204 decoded_elements = (unsigned char**)malloc(sizeof(unsigned char*)*num_missing_elements);
205 if (NULL == decoded_elements) {
206 goto out;
207 }
208
209 available_fragments = (unsigned char**)malloc(sizeof(unsigned char*)*k);
210 if (NULL == available_fragments) {
211 goto out;
212 }
213
214 j = 0;
215 for (i = 0; i < n; i++) {
216 if (bm_get_value(&missing_bm, i)) {
217 continue;
218 }
219 if (j == k) {
220 break;
221 }
222 if (i < k) {
223 available_fragments[j] = (unsigned char*)data[i];
224 } else {
225 available_fragments[j] = (unsigned char*)parity[i-k];
226 }
227 j++;
228 }
229
230 // Grab pointers to memory needed for missing data fragments
231 j = 0;
232 for (i = 0; i < k; i++) {
233 if (bm_get_value(&missing_bm, i)) {
234 decoded_elements[j] = (unsigned char*)data[i];
235 j++;
236 }
237 }
238 for (i = k; i < n; i++) {
239 if (bm_get_value(&missing_bm, i)) {
240 decoded_elements[j] = (unsigned char*)parity[i - k];
241 j++;
242 }
243 }
244
245 isa_l_desc->ec_init_tables(k, num_missing_elements, inverse_rows, g_tbls);
246
247 isa_l_desc->ec_encode_data(blocksize, k, num_missing_elements, g_tbls, (unsigned char**)available_fragments,
248 (unsigned char**)decoded_elements);
249
250 ret = 0;
251
252out:
253 free(g_tbls);
254 free(decode_matrix);
255 free(decode_inverse);
256 free(inverse_rows);
257 free(decoded_elements);
258 free(available_fragments);
259
260 return ret;
261}
262
263__attribute__ ((visibility ("internal")))
264int isa_l_reconstruct(void *desc, char **data, char **parity,
265 int *missing_idxs, int destination_idx, int blocksize)
266{
267 isa_l_descriptor *isa_l_desc = (isa_l_descriptor*) desc;
268 unsigned char *g_tbls = NULL;
269 unsigned char *decode_matrix = NULL;
270 unsigned char *decode_inverse = NULL;
271 unsigned char *inverse_rows = NULL;
272 unsigned char *reconstruct_buf = NULL;
273 unsigned char **available_fragments = NULL;
274 int k = isa_l_desc->k;
275 int m = isa_l_desc->m;
276 int n = k + m;
277 int ret = -1;
278 int i, j;
279 struct ec_bm missing_bm = NEW_BM;
280 convert_list_to_bitmap(missing_idxs, &missing_bm);
281 int inverse_row = -1;
282
287 decode_matrix = isa_l_get_decode_matrix(k, m, isa_l_desc->matrix, missing_idxs);
288
289 if (NULL == decode_matrix) {
290 goto out;
291 }
292
293 decode_inverse = (unsigned char*)malloc(sizeof(unsigned char) * k * k);
294
295 if (NULL == decode_inverse) {
296 goto out;
297 }
298
299 int im_ret = isa_l_desc->gf_invert_matrix(decode_matrix, decode_inverse, k);
300 if (im_ret < 0) {
301 goto out;
302 }
303
307 inverse_rows = get_inverse_rows(k, m, decode_inverse, isa_l_desc->matrix, missing_idxs, isa_l_desc->gf_mul);
308
309 // Generate g_tbls from computed decode matrix (k x k) matrix
310 g_tbls = malloc(sizeof(unsigned char) * (k * m * 32));
311 if (NULL == g_tbls) {
312 goto out;
313 }
314
318 available_fragments = (unsigned char**)malloc(sizeof(unsigned char*)*k);
319 if (NULL == available_fragments) {
320 goto out;
321 }
322
323 j = 0;
324 for (i = 0; i < n; i++) {
325 if (bm_get_value(&missing_bm, i)) {
326 continue;
327 }
328 if (j == k) {
329 break;
330 }
331 if (i < k) {
332 available_fragments[j] = (unsigned char*)data[i];
333 } else {
334 available_fragments[j] = (unsigned char*)parity[i-k];
335 }
336 j++;
337 }
338
342 j = 0;
343 for (i = 0; i < n; i++) {
344 if (bm_get_value(&missing_bm, i)) {
345 if (i == destination_idx) {
346 if (i < k) {
347 reconstruct_buf = (unsigned char*)data[i];
348 } else {
349 reconstruct_buf = (unsigned char*)parity[i-k];
350 }
351 inverse_row = j;
352 break;
353 }
354 j++;
355 }
356 }
357
361 isa_l_desc->ec_init_tables(k, 1, &inverse_rows[inverse_row * k], g_tbls);
362
363 isa_l_desc->ec_encode_data(blocksize, k, 1, g_tbls, (unsigned char**)available_fragments,
364 (unsigned char**)&reconstruct_buf);
365
366 ret = 0;
367out:
368 free(g_tbls);
369 free(decode_matrix);
370 free(decode_inverse);
371 free(inverse_rows);
372 free(available_fragments);
373
374 return ret;
375}
376
377__attribute__ ((visibility ("internal")))
378int isa_l_min_fragments(void *desc, int *missing_idxs,
379 int *fragments_to_exclude, int *fragments_needed)
380{
381 isa_l_descriptor *isa_l_desc = (isa_l_descriptor*)desc;
382
383 struct ec_bm exclude_bm = NEW_BM, missing_bm = NEW_BM;
384 convert_list_to_bitmap(fragments_to_exclude, &exclude_bm);
385 convert_list_to_bitmap(missing_idxs, &missing_bm);
386 bm_combine_or(&exclude_bm, &missing_bm);
387 int i;
388 int j = 0;
389 int ret = -1;
390
391 for (i = 0; i < (isa_l_desc->k + isa_l_desc->m); i++) {
392 if (!bm_get_value(&missing_bm, i)) {
393 fragments_needed[j] = i;
394 j++;
395 }
396 if (j == isa_l_desc->k) {
397 ret = 0;
398 fragments_needed[j] = -1;
399 break;
400 }
401 }
402
403 return ret;
404}
405
412__attribute__ ((visibility ("internal")))
413int isa_l_element_size(void* desc)
414{
415 return 8;
416}
417
418__attribute__ ((visibility ("internal")))
419int isa_l_exit(void *desc)
420{
421 isa_l_descriptor *isa_l_desc = NULL;
422
423 isa_l_desc = (isa_l_descriptor*) desc;
424
425 free(isa_l_desc->encode_tables);
426 free(isa_l_desc->matrix);
427 free(isa_l_desc);
428
429 return 0;
430}
431
432
433__attribute__ ((visibility ("internal")))
434void * isa_l_common_init(struct ec_backend_args *args, void *backend_sohandle,
435 const char* gen_matrix_func_name)
436{
437 isa_l_descriptor *desc = NULL;
438
439 desc = (isa_l_descriptor *)malloc(sizeof(isa_l_descriptor));
440 if (NULL == desc) {
441 return NULL;
442 }
443
444 desc->k = args->uargs.k;
445 desc->m = args->uargs.m;
446 if (args->uargs.w <= 0)
447 args->uargs.w = ISA_L_W;
448 desc->w = args->uargs.w;
449
450 /* validate EC arguments */
451 {
452 long long max_symbols = 1LL << desc->w;
453 if ((desc->k + desc->m) > max_symbols) {
454 goto error;
455 }
456 }
457
458 /*
459 * ISO C forbids casting a void* to a function pointer.
460 * Since dlsym return returns a void*, we use this union to
461 * "transform" the void* to a function pointer.
462 */
463 union {
464 ec_encode_data_func encodep;
465 ec_init_tables_func init_tablesp;
466 gf_gen_encoding_matrix_func gen_matrixp;
467 gf_invert_matrix_func invert_matrixp;
468 gf_mul_func gf_mulp;
469 void *vptr;
470 } func_handle = {.vptr = NULL};
471
472 /* fill in function addresses */
473 func_handle.vptr = NULL;
474 func_handle.vptr = dlsym(backend_sohandle, "ec_encode_data");
475 desc->ec_encode_data = func_handle.encodep;
476 if (NULL == desc->ec_encode_data) {
477 goto error;
478 }
479
480 func_handle.vptr = NULL;
481 func_handle.vptr = dlsym(backend_sohandle, "ec_init_tables");
482 desc->ec_init_tables = func_handle.init_tablesp;
483 if (NULL == desc->ec_init_tables) {
484 goto error;
485 }
486
487 func_handle.vptr = NULL;
488 func_handle.vptr = dlsym(backend_sohandle, gen_matrix_func_name);
489 desc->gf_gen_encoding_matrix = func_handle.gen_matrixp;
490 if (NULL == desc->gf_gen_encoding_matrix) {
491 goto error;
492 }
493
494 func_handle.vptr = NULL;
495 func_handle.vptr = dlsym(backend_sohandle, "gf_invert_matrix");
496 desc->gf_invert_matrix = func_handle.invert_matrixp;
497 if (NULL == desc->gf_invert_matrix) {
498 goto error;
499 }
500
501 func_handle.vptr = NULL;
502 func_handle.vptr = dlsym(backend_sohandle, "gf_mul");
503 desc->gf_mul = func_handle.gf_mulp;
504 if (NULL == desc->gf_mul) {
505 goto error;
506 }
507
508 desc->matrix = malloc(sizeof(char) * desc->k * (desc->k + desc->m));
509 if (NULL == desc->matrix) {
510 goto error;
511 }
512
517 desc->gf_gen_encoding_matrix(desc->matrix, desc->k + desc->m, desc->k);
518
519
523 desc->encode_tables = malloc(sizeof(unsigned char) *
524 (desc->k * desc->m * 32));
525 if (NULL == desc->encode_tables) {
526 goto error_free;
527 }
528
529 desc->ec_init_tables(desc->k, desc->m,
530 &desc->matrix[desc->k * desc->k],
531 desc->encode_tables);
532
533 return desc;
534
535error_free:
536 free(desc->matrix);
537error:
538 free(desc);
539
540 return NULL;
541}
static unsigned char * isa_l_get_decode_matrix(int k, int m, unsigned char *encode_matrix, int *missing_idxs)
Definition: isa_l_common.c:55
__attribute__((visibility("internal")))
Return the element-size, which is the number of bits stored on a given device, per codeword.
Definition: isa_l_common.c:39
static unsigned char * get_inverse_rows(int k, int m, unsigned char *decode_inverse, unsigned char *encode_matrix, int *missing_idxs, gf_mul_func gf_mul)
Definition: isa_l_common.c:84