liberasurecode 1.8.0
Erasure Code API library
Loading...
Searching...
No Matches
isa_l_rs_lrc.c
Go to the documentation of this file.
1/*
2 * Copyright 2025 aitassou
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 * isa_l_rs_lrc backend implementation
25 *
26 * vi: set noai tw=79 ts=4 sw=4:
27 */
28
29#include <stdlib.h>
30#include "erasurecode_backend.h"
31#include "erasurecode_helpers.h"
32#include "isa_l_common.h"
33
34#define ISA_L_RS_LRC_LIB_MAJOR 1
35#define ISA_L_RS_LRC_LIB_MINOR 0
36#define ISA_L_RS_LRC_LIB_REV 0
37#define ISA_L_RS_LRC_LIB_VER_STR "1.0"
38#define ISA_L_RS_LRC_LIB_NAME "isa_l_rs_vand"
39#if defined(__MACOS__) || defined(__MACOSX__) || defined(__OSX__) || defined(__APPLE__)
40#define ISA_L_RS_LRC_SO_NAME "libisal" LIBERASURECODE_SO_SUFFIX ".dylib"
41#else
42#define ISA_L_RS_LRC_SO_NAME "libisal" LIBERASURECODE_SO_SUFFIX ".so.2"
43#endif
44
45/* Forward declarations */
46struct ec_backend_common backend_isa_l_rs_lrc;
47
48static int gen_encoding_matrix(isa_l_descriptor * desc, int m, int k) {
49 int i, j, ret = 1;
50 unsigned char p, gen = 2;
51 unsigned char *tmp = NULL;
52 unsigned char *tmp_inv_k = NULL;
53 int n = m + k;
54 int l = desc->l; //local parities
55 int r = m - l; //global parities
56
57 /* Build a (k+m)*k Vandermonde matrix, A */
58 tmp = malloc(sizeof(char) * n * k);
59 if (tmp == NULL) {
60 goto error_free;
61 }
62 for (i = 0; i < n; i++) {
63 p = 1;
64 for (j = 0; j < k; j++) {
65 tmp[k * i + j] = p;
66 p = desc->gf_mul(p, gen);
67 }
68 if (i < k + r) {
69 gen = desc->gf_mul(gen, 2);
70 }
71 }
72
73 /* It starts with a k*k submatrix, A'; calculate inv(A') */
74 tmp_inv_k = malloc(sizeof(char) * k * k);
75 if (tmp_inv_k == NULL) {
76 goto error_free;
77 }
78 int im_ret = desc->gf_invert_matrix(tmp, tmp_inv_k, k);
79 if (im_ret < 0) {
84 goto error_free;
85 }
86
91 memset(desc->matrix, 0, k * n);
92 for (i = 0; i < k; i++)
93 desc->matrix[k * i + i] = 1;
94
95 /* Then multiply inv(A') by the rest of A for the parities */
96 for (i = k; i < n; i++) {
97 for (j = 0; j < k; j++) {
98 p = 0;
99 for (int u = 0; u < k; u++) {
100 p ^= desc->gf_mul(tmp[(i*k)+u], tmp_inv_k[(u*k)+j]);
101 }
102 desc->matrix[(i*k)+j] = p;
103 }
104 }
105
106 int group_offset = 0;
107 for (i = 0; i < l; i++) {
108 int frag_num = k + r + i;
109 int group_size = local_group_size(k, l, i);
110 for (j = 0; j < k; j++) {
111 if ( j < group_offset || j >= group_offset + group_size)
112 desc->matrix[k * frag_num + j] = 0;
113 }
114 group_offset += group_size;
115 }
116 ret = 0;
117error_free:
118 free(tmp_inv_k);
119 free(tmp);
120
121 return ret;
122}
123
124static void * isa_l_rs_lrc_init(struct ec_backend_args *args,
125 void *backend_sohandle)
126{
127 isa_l_descriptor *desc = NULL;
128
129 desc = (isa_l_descriptor *)malloc(sizeof(isa_l_descriptor));
130 if (NULL == desc) {
131 return NULL;
132 }
133 /* Set this early so we can have a single error path */
134 desc->matrix = NULL;
135
136 desc->k = args->uargs.k;
137 desc->m = args->uargs.m;
138 desc->l = args->uargs.priv_args1.lrc_args.l;
139 if (desc->l < 1 || desc->l > desc->m || (2 * desc->l > desc->k)) {
140 goto error;
141 }
142 if (args->uargs.w <= 0)
143 args->uargs.w = ISA_L_W;
144 desc->w = args->uargs.w;
145
146 /* validate EC arguments */
147 {
148 long long max_symbols = 1LL << desc->w;
149 if ((desc->k + desc->m) > max_symbols) {
150 goto error;
151 }
152 }
153
154 /*
155 * ISO C forbids casting a void* to a function pointer.
156 * Since dlsym return returns a void*, we use this union to
157 * "transform" the void* to a function pointer.
158 */
159 union {
160 ec_encode_data_func encodep;
161 ec_init_tables_func init_tablesp;
162 gf_gen_encoding_matrix_func gen_matrixp;
163 gf_invert_matrix_func invert_matrixp;
164 gf_mul_func gf_mulp;
165 void *vptr;
166 } func_handle = {.vptr = NULL};
167
168 /* fill in function addresses */
169 func_handle.vptr = NULL;
170 func_handle.vptr = dlsym(backend_sohandle, "ec_encode_data");
171 desc->ec_encode_data = func_handle.encodep;
172 if (NULL == desc->ec_encode_data) {
173 goto error;
174 }
175
176 func_handle.vptr = NULL;
177 func_handle.vptr = dlsym(backend_sohandle, "ec_init_tables");
178 desc->ec_init_tables = func_handle.init_tablesp;
179 if (NULL == desc->ec_init_tables) {
180 goto error;
181 }
182
183 func_handle.vptr = NULL;
184 func_handle.vptr = dlsym(backend_sohandle, "gf_invert_matrix");
185 desc->gf_invert_matrix = func_handle.invert_matrixp;
186 if (NULL == desc->gf_invert_matrix) {
187 goto error;
188 }
189
190 func_handle.vptr = NULL;
191 func_handle.vptr = dlsym(backend_sohandle, "gf_mul");
192 desc->gf_mul = func_handle.gf_mulp;
193 if (NULL == desc->gf_mul) {
194 goto error;
195 }
196
197 desc->matrix = malloc(sizeof(char) * desc->k * (desc->k + desc->m));
198 if (NULL == desc->matrix) {
199 goto error;
200 }
201
202 if (0 != gen_encoding_matrix(desc, desc->m, desc->k)) {
203 goto error;
204 }
205
209 desc->encode_tables = malloc(sizeof(unsigned char) *
210 (desc->k * desc->m * 32));
211 if (NULL == desc->encode_tables) {
212 goto error;
213 }
214
215 desc->ec_init_tables(desc->k, desc->m,
216 &desc->matrix[desc->k * desc->k],
217 desc->encode_tables);
218
219 return desc;
220
221error:
222 free(desc->matrix);
223 free(desc);
224
225 return NULL;
226}
227
228
229static int isa_l_rs_lrc_check_reconstruct_fragments(void *desc, int *missing_idxs, int destination_idx) {
230 isa_l_descriptor *d = (isa_l_descriptor*)desc;
231 struct ec_bm missing_bm = NEW_BM;
232 convert_list_to_bitmap(missing_idxs, &missing_bm);
233 int missing_locals, local_group;
234 if (destination_idx < d->k) {
235 local_group = local_group_for_data(d->k, d->l, destination_idx);
236 int local_parity_index = d->k + d->m - d->l + local_group;
237 missing_locals = bm_get_value(&missing_bm, local_parity_index);
238 for (
239 int i = local_group_data_lower(d->k, d->l, local_group);
240 i < local_group_data_upper(d->k, d->l, local_group);
241 i++
242 ) {
243 if (i != destination_idx)
244 missing_locals |= bm_get_value(&missing_bm, i);
245 }
246 if (!missing_locals) {
247 return 0;
248 }
249 } else if (destination_idx >= d->k + d->m - d->l) {
250 local_group = destination_idx - d->k - d->m + d->l;
251 missing_locals = 0;
252 for (
253 int i = local_group_data_lower(d->k, d->l, local_group);
254 i < local_group_data_upper(d->k, d->l, local_group);
255 i++
256 ) {
257 missing_locals |= bm_get_value(&missing_bm, i);
258 }
259 if (!missing_locals) {
260 return 0;
261 }
262 }
263
264 // if we haven't returned yet, we can't do local-only reconstruction
265 int useful_frags = 0;
266 struct ec_bm can_use_local_parity = NEW_BM;
267 for (int i = 0; i < d->k + d->m; i++) {
268 if (i < d->k) {
269 if (bm_get_value(&missing_bm, i)) {
270 local_group = local_group_for_data(d->k, d->l, i);
271 bm_set_value(&can_use_local_parity, d->k + d->m - d->l + local_group, 1);
272 } else {
273 useful_frags++;
274 }
275 } else if (i >= d->k + d->m - d->l) {
276 if (bm_get_value(&can_use_local_parity, i) && !bm_get_value(&missing_bm, i)) {
277 useful_frags++;
278 }
279 } else {
280 if (!bm_get_value(&missing_bm, i)) {
281 useful_frags++;
282 }
283 }
284 }
285
286 if (useful_frags < d->k) {
287 return -EINSUFFFRAGS;
288 }
289 return 0;
290}
291
292
293/*
294 * For the time being, we only claim compatibility with versions that
295 * match exactly
296 */
297static bool isa_l_rs_lrc_is_compatible_with(uint32_t version) {
298 return version == backend_isa_l_rs_lrc.ec_backend_version;
299}
300
301static unsigned char* get_lrc_inverse_rows(int k,
302 int m,
303 int min_range,
304 int max_range,
305 int missing_local_parity,
306 unsigned char *decode_inverse,
307 unsigned char* encode_matrix,
308 struct ec_bm *missing_bm,
309 gf_mul_func gf_mul)
310{
311 int num_missing_elements = 0;
312 for (int i = 0; i < EC_MAX_FRAGMENTS; i++)
313 if (bm_get_value(missing_bm, i))
314 num_missing_elements++;
315 unsigned char *inverse_rows = (unsigned char*)malloc(sizeof(unsigned
316 char) * k * num_missing_elements);
317 int i, j, l = 0;
318
319 if (NULL == inverse_rows) {
320 return NULL;
321 }
322
323 int matrix_size = max_range - min_range;
324
325 int encode_matrix_size = (matrix_size == 0 ||matrix_size == k || missing_local_parity) ? k : matrix_size;
326
327 int n = k + m;
328
329 memset(inverse_rows, 0, sizeof(unsigned
330 char) * matrix_size * num_missing_elements);
331
332 /*
333 * Fill in rows for missing data
334 */
335 for (i = 0; i < matrix_size; i++) {
336 if (bm_get_value(missing_bm, i + min_range)) {
337 for (j = 0; j < matrix_size; j++) {
338 inverse_rows[(l * matrix_size) + j] = decode_inverse[(i * matrix_size) + j];
339 }
340 l++;
341 }
342 }
343
344 /*
345 * Process missing parity.
346 *
347 * Start with an all-zero row.
348 *
349 * For each data element, if the data element is:
350 *
351 * Available: XOR the corresponding coefficient from the
352 * encoding matrix.
353 *
354 * Unavailable: multiply corresponding coefficient with
355 * the row that corresponds to the missing data in inverse_rows
356 * and XOR the resulting row with this row.
357 */
358 for (i = k; i < n; i++) {
359 // Parity is missing
360 if (bm_get_value(missing_bm, i)) {
361 int d_idx_avail = 0;
362 int d_idx_unavail = 0;
363 for (j = min_range; j < max_range; j++) {
364 // This data is available, so we can use the encode matrix
365 if (!bm_get_value(missing_bm, j)) {
366 inverse_rows[(l * matrix_size) + d_idx_avail] ^= encode_matrix[(i * encode_matrix_size) + j];
367 d_idx_avail++;
368 } else {
369 mult_and_xor_row(&inverse_rows[l * matrix_size],
370 &inverse_rows[d_idx_unavail * matrix_size],
371 encode_matrix[(i * encode_matrix_size) + j],
372 k,
373 gf_mul);
374 d_idx_unavail++;
375 }
376 }
377 l++;
378 }
379 }
380 return inverse_rows;
381}
382
383static unsigned char* isa_l_lrc_get_decode_matrix(int k, int m, unsigned local_parity, unsigned char *encode_matrix, struct ec_bm *missing_bm, int *used_idxs, int *use_combined_parity)
384{
385 int i = 0, j, locate = 0;
386 int n = k + m;
387 int global_parity = m - local_parity;
388 int group_offset = 0;
389 uint64_t missing_local_parity = 0;
390 struct ec_bm use_parity = NEW_BM;
391
392 int total_missing = 0;
393
394 unsigned char *decode_matrix = malloc(sizeof(unsigned char) * k * k);
395 if( NULL == decode_matrix ) {
396 return NULL;
397 }
398
399 for (int v = 0; v < local_parity; v++) {
400 int group_size = local_group_size(k, local_parity, v);
401 for (int u = group_offset; u < group_offset + group_size; u++) {
402 if (bm_get_value(missing_bm, u)) {
403 bm_set_value(&use_parity, k + global_parity + v, 1);
404 }
405 }
406 group_offset += group_size;
407
408 missing_local_parity |= bm_get_value(missing_bm, k + global_parity + v);
409 }
410
411 for (locate = 0; i < k && locate < k + global_parity; locate++) {
412 if (bm_get_value(missing_bm, locate)) {
413 total_missing++;
414 continue;
415 }
416 for (j = 0; j < k; j++) {
417 decode_matrix[(k * i) + j] = encode_matrix[(k * locate) + j];
418 }
419 used_idxs[locate] = 1;
420 i++;
421 }
422 // we can simplify here as total_missing counts only missing data + global parity
423 if (i < k && !missing_local_parity && (total_missing == global_parity + 1)) {
424 // Set flag to indicate we can use combined parity in case of
425 // g + 1 errors and no local parity is missing
426 *use_combined_parity = 1;
427 // We can combine all the local parities into a single global parity
428 group_offset = 0;
429 for (int v = 0; v < local_parity; v++) {
430 int group_size = local_group_size(k, local_parity, v);
431 for (int u = group_offset; u < group_offset + group_size; u++) {
432 decode_matrix[(i * k) + u] = encode_matrix[((locate + v) * k) + u];
433 }
434 group_offset += group_size;
435 }
436 i++;
437 }
438 if (i < k) {
439 // Still not enough? Well, let's add what local parities we have,
440 // see if we can get lucky
441 for (locate = k + global_parity; i < k && locate < n; locate++) {
442 if (bm_get_value(&use_parity, locate) && !bm_get_value(missing_bm, locate)) {
443 for (j = 0; j < k; j++) {
444 decode_matrix[(k * i) + j] = encode_matrix[(k * locate) + j];
445 }
446 used_idxs[locate] = 1;
447 i++;
448 }
449 }
450 }
451 if (i != k) {
452 free(decode_matrix);
453 decode_matrix = NULL;
454 }
455 return decode_matrix;
456}
457
458
459static int isa_l_lrc_decode(void *desc, char **data, char **parity,
460 int *missing_idxs, int blocksize)
461{
462 isa_l_descriptor *isa_l_desc = (isa_l_descriptor*)desc;
463
464 unsigned char *g_tbls = NULL;
465 unsigned char *decode_matrix = NULL;
466 unsigned char *decode_inverse = NULL;
467 unsigned char *inverse_rows = NULL;
468 unsigned char **decoded_elements = NULL;
469 unsigned char **available_fragments = NULL;
470 int k = isa_l_desc->k;
471 int m = isa_l_desc->m;
472 int local_parity = isa_l_desc->l;
473 int n = k + m;
474 int ret = -1;
475 int i, j;
476 unsigned char *combined_local_parities = NULL;
477 int use_combined_parity = 0;
478
479 int num_missing_elements = get_num_missing_elements(missing_idxs);
480 struct ec_bm missing_bm = NEW_BM;
481 convert_list_to_bitmap(missing_idxs, &missing_bm);
482
483 int *used_idxs = calloc(n, sizeof(int));
484 if(NULL == used_idxs) {
485 goto out;
486 }
487 decode_matrix = isa_l_lrc_get_decode_matrix(k, m, local_parity, isa_l_desc->matrix, &missing_bm, used_idxs, &use_combined_parity);
488
489 if (NULL == decode_matrix) {
490 goto out;
491 }
492
493 decode_inverse = (unsigned char*)malloc(sizeof(unsigned char) * k * k);
494
495 if (NULL == decode_inverse) {
496 goto out;
497 }
498
499 int im_ret = isa_l_desc->gf_invert_matrix(decode_matrix, decode_inverse, k);
500 if (im_ret < 0) {
501 goto out;
502 }
503
504 // Generate g_tbls from computed decode matrix (k x k) matrix
505 g_tbls = malloc(sizeof(unsigned char) * (k * m * 32));
506 if (NULL == g_tbls) {
507 goto out;
508 }
509
510 inverse_rows = get_lrc_inverse_rows(k, m, 0, k, 0, decode_inverse, isa_l_desc->matrix, &missing_bm, isa_l_desc->gf_mul);
511
512 decoded_elements = (unsigned char**)malloc(sizeof(unsigned char*)*num_missing_elements);
513 if (NULL == decoded_elements) {
514 goto out;
515 }
516
517 available_fragments = (unsigned char**)malloc(sizeof(unsigned char*)*k);
518 if (NULL == available_fragments) {
519 goto out;
520 }
521
522 uint64_t missing_local_parities = 0;
523 for (j = n - local_parity; j < n; j++) {
524 missing_local_parities |= bm_get_value(&missing_bm, j);
525 }
526
527 for (i = 0, j = 0; i < n - local_parity && j < k; i++) {
528 if (bm_get_value(&missing_bm, i)) {
529 continue;
530 }
531 if (i < k) {
532 available_fragments[j] = (unsigned char*)data[i];
533 j++;
534 } else {
535 if (used_idxs[i]) {
536 available_fragments[j] = (unsigned char*)parity[i - k];
537 j++;
538 }
539 }
540 }
541 if (j < k && !missing_local_parities && use_combined_parity) {
542 combined_local_parities = calloc(blocksize, sizeof(unsigned char));
543 if (NULL == combined_local_parities) {
544 goto out;
545 }
546 for (i = n - local_parity; i < n; i++) {
547 for (int x = 0; x < blocksize; x++) {
548 combined_local_parities[x] ^= parity[i - k][x];
549 }
550 }
551 available_fragments[j] = combined_local_parities;
552 j++;
553 }
554 for (i = n - local_parity; i < n && j < k; i++) {
555 if (used_idxs[i]) {
556 available_fragments[j] = (unsigned char*)parity[i-k];
557 j++;
558 }
559 }
560 // Grab pointers to memory needed for missing data fragments
561 j = 0;
562 for (i = 0; i < k; i++) {
563 if (bm_get_value(&missing_bm, i)) {
564 decoded_elements[j] = (unsigned char*)data[i];
565 j++;
566 }
567 }
568 for (i = k; i < n; i++) {
569 if (bm_get_value(&missing_bm, i)) {
570 decoded_elements[j] = (unsigned char*)parity[i - k];
571 j++;
572 }
573 }
574
575 isa_l_desc->ec_init_tables(k, num_missing_elements, inverse_rows, g_tbls);
576
577 isa_l_desc->ec_encode_data(blocksize, k, num_missing_elements, g_tbls, available_fragments,
578 decoded_elements);
579
580 ret = 0;
581
582out:
583 free(g_tbls);
584 free(combined_local_parities);
585 free(decode_matrix);
586 free(decode_inverse);
587 free(inverse_rows);
588 free(decoded_elements);
589 free(available_fragments);
590 free(used_idxs);
591
592 return ret;
593}
594
596 int k, int m, unsigned local_parity, int destination_idx,
597 unsigned char *encode_matrix, struct ec_bm *missing_bm, int *used_idxs,
598 int *min_col, int *max_col, int *mx_size, int *missing_local_parity, int *use_combined_parity)
599{
600 unsigned char *decode_matrix = NULL;
601 struct ec_bm useful_mask = NEW_BM;
602
603 int min_range=0, max_range=0;
604 if (destination_idx < k) {
605 // reconstructing a data frag; see if we can stay local
606 int local_group = local_group_for_data(k, local_parity, destination_idx);
607 min_range = local_group_data_lower(k, local_parity, local_group);
608 max_range = local_group_data_upper(k, local_parity, local_group);
609 int local_parity_idx = k + m - local_parity + local_group;
610 uint64_t missing_local = bm_get_value(missing_bm, local_parity_idx);
611 for (int i = min_range; !missing_local && i < max_range; i++) {
612 bm_set_value(&useful_mask, i, 1);
613 if (i == destination_idx) {
614 // We already knew we were missing *that* one...
615 continue;
616 }
617 missing_local |= bm_get_value(missing_bm, i);
618 }
619 if (!missing_local) {
620 // We have everything we need!
621 bm_set_value(&useful_mask, local_parity_idx, 1);
622 bm_combine_and(&useful_mask, missing_bm);
623 *mx_size = max_range - min_range;
624 decode_matrix = malloc(sizeof(unsigned char) * (*mx_size) * (*mx_size));
625 if (NULL == decode_matrix) {
626 return NULL;
627 }
628 int col = 0;
629 for (int enc_idx = min_range; enc_idx < max_range; enc_idx++) {
630 if (enc_idx == destination_idx)
631 continue;
632 for (int j = min_range; j < max_range; j++) {
633 decode_matrix[(*mx_size * col) + j - min_range] = encode_matrix[(k * enc_idx) + j];
634 }
635 used_idxs[enc_idx] = 1;
636 col++;
637 }
638 // add local parity
639 for (int j = min_range; j < max_range; j++) {
640 decode_matrix[*mx_size * col + j - min_range] = encode_matrix[(k * local_parity_idx) + j];
641 }
642 used_idxs[local_parity_idx] = 1;
643 }
644 }
645 if (destination_idx >= k + m - local_parity) {
646 // reconstructing a local parity frag; see if we can use local data
647 int local_group = destination_idx - k - m + local_parity;
648 min_range = local_group_data_lower(k, local_parity, local_group);
649 max_range = local_group_data_upper(k, local_parity, local_group);
650 uint64_t missing_local = 0;
651 for (int i = min_range; !missing_local && i < max_range; i++) {
652 bm_set_value(&useful_mask, i, 1);
653 missing_local |= bm_get_value(missing_bm, i);
654 }
655 if (!missing_local) {
656 // We have everything we need!
657 bm_set_value(&useful_mask, destination_idx, 1);
658 bm_combine_and(&useful_mask, missing_bm);
659 *missing_local_parity = 1;
660 *mx_size = max_range - min_range;
661 decode_matrix = malloc(sizeof(unsigned char) * (*mx_size) * (*mx_size));
662 if (NULL == decode_matrix) {
663 return NULL;
664 }
665 for (int i = min_range; i < max_range; i++) {
666 for (int j = min_range; j < max_range; j++) {
667 decode_matrix[*mx_size * (i - min_range) + j - min_range] = encode_matrix[(k * i) + j];
668 }
669 used_idxs[i] = 1;
670 }
671 }
672 }
673
674 if (decode_matrix == NULL) {
675 decode_matrix = isa_l_lrc_get_decode_matrix(k, m, local_parity,
676 encode_matrix, missing_bm, used_idxs, use_combined_parity);
677 if (decode_matrix) {
678 *mx_size = k;
679 }
680 min_range = 0;
681 max_range = k;
682 }
683
684 *min_col = min_range;
685 *max_col = max_range;
686 return decode_matrix;
687}
688
689static int isa_l_lrc_reconstruct(void *desc, char **data, char **parity,
690 int *missing_idxs, int destination_idx, int blocksize)
691{
692 isa_l_descriptor *isa_l_desc = (isa_l_descriptor*) desc;
693 unsigned char *g_tbls = NULL;
694 unsigned char *decode_matrix = NULL;
695 unsigned char *decode_inverse = NULL;
696 unsigned char *inverse_rows = NULL;
697 unsigned char *reconstruct_buf = NULL;
698 unsigned char **available_fragments = NULL;
699 int k = isa_l_desc->k;
700 int m = isa_l_desc->m;
701 int local_parity = isa_l_desc->l;
702 int n = k + m;
703 int ret = -1;
704 int i, j;
705 struct ec_bm missing_bm = NEW_BM;
706 convert_list_to_bitmap(missing_idxs, &missing_bm);
707 int inverse_row = -1;
708 int min_range = 0;
709 int max_range = 0;
710 int matrix_size = k;
711 int *used_idxs = calloc(n, sizeof(int));
712 int missing_local_parity = 0;
713 unsigned char * combined_local_parities = NULL;
714 int use_combined_parity = 0;
715
716 if( NULL == used_idxs) {
717 goto out;
718 }
723 decode_matrix = isa_l_lrc_get_reconstruct_matrix(k, m, local_parity, destination_idx, isa_l_desc->matrix, &missing_bm, used_idxs, &min_range, &max_range, &matrix_size, &missing_local_parity, &use_combined_parity);
724 if (NULL == decode_matrix) {
725 goto out;
726 }
727
728 decode_inverse = (unsigned char*)malloc(sizeof(unsigned char) * matrix_size * matrix_size);
729
730 if (NULL == decode_inverse) {
731 goto out;
732 }
733
734 int im_ret = isa_l_desc->gf_invert_matrix(decode_matrix, decode_inverse, matrix_size);
735 if (im_ret < 0) {
736 goto out;
737 }
738
739 int nb_parity = (matrix_size == k)? m: 1;
740 unsigned char * encode = (matrix_size == k || missing_local_parity)? isa_l_desc->matrix:decode_matrix;
741
745 inverse_rows = get_lrc_inverse_rows(k, m, min_range, max_range, missing_local_parity, decode_inverse, encode, &missing_bm, isa_l_desc->gf_mul);
746
747 // Generate g_tbls from computed decode matrix (k x k) matrix
748 g_tbls = malloc(sizeof(unsigned char) * (matrix_size * nb_parity * 32));
749 if (NULL == g_tbls) {
750 goto out;
751 }
752
756 available_fragments = (unsigned char**)malloc(sizeof(unsigned char*)*matrix_size);
757 if (NULL == available_fragments) {
758 goto out;
759 }
760
761 j = 0;
762 if (matrix_size == k) {
763 for (i = 0; i < n - local_parity && j < k; i++) {
764 if (bm_get_value(&missing_bm, i)) {
765 continue;
766 }
767 if (i < k) {
768 available_fragments[j] = (unsigned char*)data[i];
769 j++;
770 } else {
771 if (used_idxs[i]) {
772 available_fragments[j] = (unsigned char*)parity[i - k];
773 j++;
774 }
775 }
776 }
777 if (j < k && !missing_local_parity && use_combined_parity) {
778 combined_local_parities = calloc(blocksize, sizeof(unsigned char));
779 if (NULL == combined_local_parities) {
780 goto out;
781 }
782 for (i = n - local_parity; i < n; i++) {
783 for (int x = 0; x < blocksize; x++) {
784 combined_local_parities[x] ^= parity[i - k][x];
785 }
786 }
787 available_fragments[j] = combined_local_parities;
788 j++;
789 }
790 for (i = n - local_parity; i < n && j < k; i++) {
791 if (bm_get_value(&missing_bm, i)) {
792 continue;
793 }
794 if (used_idxs[i]) {
795 available_fragments[j] = (unsigned char*)parity[i - k];
796 j++;
797 }
798 }
799 } else {
800 for (i = 0; i < n; i++) {
801 if (used_idxs[i]) {
802 if (i <k) {
803 available_fragments[j] = (unsigned char*)data[i];
804 } else {
805 available_fragments[j] = (unsigned char*)parity[i - k];
806 }
807 j++;
808 }
809 }
810 }
811
815 j = 0;
816 for (i = 0; i < n; i++) {
817 if (bm_get_value(&missing_bm, i)) {
818 if (i == destination_idx) {
819 if (i < k) {
820 reconstruct_buf = (unsigned char*)data[i];
821 } else {
822 reconstruct_buf = (unsigned char*)parity[i - k];
823 }
824 inverse_row = j;
825 break;
826 }
827 j++;
828 }
829 }
830
834 isa_l_desc->ec_init_tables(matrix_size, 1, &inverse_rows[inverse_row * matrix_size], g_tbls);
835 isa_l_desc->ec_encode_data(blocksize, matrix_size, 1, g_tbls, available_fragments,
836 &reconstruct_buf);
837
838 ret = 0;
839out:
840 free(g_tbls);
841 free(combined_local_parities);
842 free(decode_matrix);
843 free(decode_inverse);
844 free(inverse_rows);
845 free(available_fragments);
846 free(used_idxs);
847
848 return ret;
849}
850
851static struct ec_backend_op_stubs isa_l_rs_lrc_op_stubs = {
852 .INIT = isa_l_rs_lrc_init,
853 .EXIT = isa_l_exit,
854 .ISSYSTEMATIC = 1,
855 .ENCODE = isa_l_encode,
856 .DECODE = isa_l_lrc_decode,
857 .FRAGSNEEDED = isa_l_min_fragments,
858 .RECONSTRUCT = isa_l_lrc_reconstruct,
859 .ELEMENTSIZE = isa_l_element_size,
860 .ISCOMPATIBLEWITH = isa_l_rs_lrc_is_compatible_with,
861 .GETMETADATASIZE = get_backend_metadata_size_zero,
862 .GETENCODEOFFSET = get_encode_offset_zero,
863 .CHECKRECONSTRUCTFRAGMENTS = isa_l_rs_lrc_check_reconstruct_fragments,
864};
865
866__attribute__ ((visibility ("internal")))
867struct ec_backend_common backend_isa_l_rs_lrc = {
868 .id = EC_BACKEND_ISA_L_RS_LRC,
869 .name = ISA_L_RS_LRC_LIB_NAME,
870 .soname = ISA_L_RS_LRC_SO_NAME,
871 .soversion = ISA_L_RS_LRC_LIB_VER_STR,
872 .ops = &isa_l_rs_lrc_op_stubs,
873 .ec_backend_version = _VERSION(ISA_L_RS_LRC_LIB_MAJOR,
876};
#define ISA_L_RS_LRC_LIB_NAME
Definition: isa_l_rs_lrc.c:38
static unsigned char * isa_l_lrc_get_decode_matrix(int k, int m, unsigned local_parity, unsigned char *encode_matrix, struct ec_bm *missing_bm, int *used_idxs, int *use_combined_parity)
Definition: isa_l_rs_lrc.c:383
#define ISA_L_RS_LRC_SO_NAME
Definition: isa_l_rs_lrc.c:42
#define ISA_L_RS_LRC_LIB_VER_STR
Definition: isa_l_rs_lrc.c:37
static void * isa_l_rs_lrc_init(struct ec_backend_args *args, void *backend_sohandle)
Definition: isa_l_rs_lrc.c:124
struct ec_backend_common backend_isa_l_rs_lrc
Definition: isa_l_rs_lrc.c:46
static bool isa_l_rs_lrc_is_compatible_with(uint32_t version)
Definition: isa_l_rs_lrc.c:297
#define ISA_L_RS_LRC_LIB_REV
Definition: isa_l_rs_lrc.c:36
static struct ec_backend_op_stubs isa_l_rs_lrc_op_stubs
Definition: isa_l_rs_lrc.c:851
static unsigned char * isa_l_lrc_get_reconstruct_matrix(int k, int m, unsigned local_parity, int destination_idx, unsigned char *encode_matrix, struct ec_bm *missing_bm, int *used_idxs, int *min_col, int *max_col, int *mx_size, int *missing_local_parity, int *use_combined_parity)
Definition: isa_l_rs_lrc.c:595
static int isa_l_lrc_decode(void *desc, char **data, char **parity, int *missing_idxs, int blocksize)
Definition: isa_l_rs_lrc.c:459
__attribute__((visibility("internal")))
Definition: isa_l_rs_lrc.c:866
#define ISA_L_RS_LRC_LIB_MINOR
Definition: isa_l_rs_lrc.c:35
static int gen_encoding_matrix(isa_l_descriptor *desc, int m, int k)
Definition: isa_l_rs_lrc.c:48
static unsigned char * get_lrc_inverse_rows(int k, int m, int min_range, int max_range, int missing_local_parity, unsigned char *decode_inverse, unsigned char *encode_matrix, struct ec_bm *missing_bm, gf_mul_func gf_mul)
Definition: isa_l_rs_lrc.c:301
static int isa_l_rs_lrc_check_reconstruct_fragments(void *desc, int *missing_idxs, int destination_idx)
Definition: isa_l_rs_lrc.c:229
#define ISA_L_RS_LRC_LIB_MAJOR
Definition: isa_l_rs_lrc.c:34
static int isa_l_lrc_reconstruct(void *desc, char **data, char **parity, int *missing_idxs, int destination_idx, int blocksize)
Definition: isa_l_rs_lrc.c:689