30#include "erasurecode_backend.h"
31#include "erasurecode_helpers.h"
32#include "isa_l_common.h"
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"
42#define ISA_L_RS_LRC_SO_NAME "libisal" LIBERASURECODE_SO_SUFFIX ".so.2"
50 unsigned char p, gen = 2;
51 unsigned char *tmp = NULL;
52 unsigned char *tmp_inv_k = NULL;
58 tmp = malloc(
sizeof(
char) * n * k);
62 for (i = 0; i < n; i++) {
64 for (j = 0; j < k; j++) {
66 p = desc->gf_mul(p, gen);
69 gen = desc->gf_mul(gen, 2);
74 tmp_inv_k = malloc(
sizeof(
char) * k * k);
75 if (tmp_inv_k == NULL) {
78 int im_ret = desc->gf_invert_matrix(tmp, tmp_inv_k, k);
91 memset(desc->matrix, 0, k * n);
92 for (i = 0; i < k; i++)
93 desc->matrix[k * i + i] = 1;
96 for (i = k; i < n; i++) {
97 for (j = 0; j < k; j++) {
99 for (
int u = 0; u < k; u++) {
100 p ^= desc->gf_mul(tmp[(i*k)+u], tmp_inv_k[(u*k)+j]);
102 desc->matrix[(i*k)+j] = p;
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;
114 group_offset += group_size;
125 void *backend_sohandle)
127 isa_l_descriptor *desc = NULL;
129 desc = (isa_l_descriptor *)malloc(
sizeof(isa_l_descriptor));
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)) {
142 if (args->uargs.w <= 0)
143 args->uargs.w = ISA_L_W;
144 desc->w = args->uargs.w;
148 long long max_symbols = 1LL << desc->w;
149 if ((desc->k + desc->m) > max_symbols) {
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;
166 } func_handle = {.vptr = NULL};
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) {
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) {
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) {
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) {
197 desc->matrix = malloc(
sizeof(
char) * desc->k * (desc->k + desc->m));
198 if (NULL == desc->matrix) {
209 desc->encode_tables = malloc(
sizeof(
unsigned char) *
210 (desc->k * desc->m * 32));
211 if (NULL == desc->encode_tables) {
215 desc->ec_init_tables(desc->k, desc->m,
216 &desc->matrix[desc->k * desc->k],
217 desc->encode_tables);
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);
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);
243 if (i != destination_idx)
244 missing_locals |= bm_get_value(&missing_bm, i);
246 if (!missing_locals) {
249 }
else if (destination_idx >= d->k + d->m - d->l) {
250 local_group = destination_idx - d->k - d->m + d->l;
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);
257 missing_locals |= bm_get_value(&missing_bm, i);
259 if (!missing_locals) {
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++) {
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);
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)) {
280 if (!bm_get_value(&missing_bm, i)) {
286 if (useful_frags < d->k) {
287 return -EINSUFFFRAGS;
305 int missing_local_parity,
306 unsigned char *decode_inverse,
307 unsigned char* encode_matrix,
308 struct ec_bm *missing_bm,
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);
319 if (NULL == inverse_rows) {
323 int matrix_size = max_range - min_range;
325 int encode_matrix_size = (matrix_size == 0 ||matrix_size == k || missing_local_parity) ? k : matrix_size;
329 memset(inverse_rows, 0,
sizeof(
unsigned
330 char) * matrix_size * num_missing_elements);
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];
358 for (i = k; i < n; i++) {
360 if (bm_get_value(missing_bm, i)) {
362 int d_idx_unavail = 0;
363 for (j = min_range; j < max_range; j++) {
365 if (!bm_get_value(missing_bm, j)) {
366 inverse_rows[(l * matrix_size) + d_idx_avail] ^= encode_matrix[(i * encode_matrix_size) + j];
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],
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)
385 int i = 0, j, locate = 0;
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;
392 int total_missing = 0;
394 unsigned char *decode_matrix = malloc(
sizeof(
unsigned char) * k * k);
395 if( NULL == decode_matrix ) {
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);
406 group_offset += group_size;
408 missing_local_parity |= bm_get_value(missing_bm, k + global_parity + v);
411 for (locate = 0; i < k && locate < k + global_parity; locate++) {
412 if (bm_get_value(missing_bm, locate)) {
416 for (j = 0; j < k; j++) {
417 decode_matrix[(k * i) + j] = encode_matrix[(k * locate) + j];
419 used_idxs[locate] = 1;
423 if (i < k && !missing_local_parity && (total_missing == global_parity + 1)) {
426 *use_combined_parity = 1;
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];
434 group_offset += group_size;
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];
446 used_idxs[locate] = 1;
453 decode_matrix = NULL;
455 return decode_matrix;
460 int *missing_idxs,
int blocksize)
462 isa_l_descriptor *isa_l_desc = (isa_l_descriptor*)desc;
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;
476 unsigned char *combined_local_parities = NULL;
477 int use_combined_parity = 0;
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);
483 int *used_idxs = calloc(n,
sizeof(
int));
484 if(NULL == used_idxs) {
489 if (NULL == decode_matrix) {
493 decode_inverse = (
unsigned char*)malloc(
sizeof(
unsigned char) * k * k);
495 if (NULL == decode_inverse) {
499 int im_ret = isa_l_desc->gf_invert_matrix(decode_matrix, decode_inverse, k);
505 g_tbls = malloc(
sizeof(
unsigned char) * (k * m * 32));
506 if (NULL == g_tbls) {
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);
512 decoded_elements = (
unsigned char**)malloc(
sizeof(
unsigned char*)*num_missing_elements);
513 if (NULL == decoded_elements) {
517 available_fragments = (
unsigned char**)malloc(
sizeof(
unsigned char*)*k);
518 if (NULL == available_fragments) {
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);
527 for (i = 0, j = 0; i < n - local_parity && j < k; i++) {
528 if (bm_get_value(&missing_bm, i)) {
532 available_fragments[j] = (
unsigned char*)data[i];
536 available_fragments[j] = (
unsigned char*)parity[i - k];
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) {
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];
551 available_fragments[j] = combined_local_parities;
554 for (i = n - local_parity; i < n && j < k; i++) {
556 available_fragments[j] = (
unsigned char*)parity[i-k];
562 for (i = 0; i < k; i++) {
563 if (bm_get_value(&missing_bm, i)) {
564 decoded_elements[j] = (
unsigned char*)data[i];
568 for (i = k; i < n; i++) {
569 if (bm_get_value(&missing_bm, i)) {
570 decoded_elements[j] = (
unsigned char*)parity[i - k];
575 isa_l_desc->ec_init_tables(k, num_missing_elements, inverse_rows, g_tbls);
577 isa_l_desc->ec_encode_data(blocksize, k, num_missing_elements, g_tbls, available_fragments,
584 free(combined_local_parities);
586 free(decode_inverse);
588 free(decoded_elements);
589 free(available_fragments);
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)
600 unsigned char *decode_matrix = NULL;
601 struct ec_bm useful_mask = NEW_BM;
603 int min_range=0, max_range=0;
604 if (destination_idx < k) {
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) {
617 missing_local |= bm_get_value(missing_bm, i);
619 if (!missing_local) {
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) {
629 for (
int enc_idx = min_range; enc_idx < max_range; enc_idx++) {
630 if (enc_idx == destination_idx)
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];
635 used_idxs[enc_idx] = 1;
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];
642 used_idxs[local_parity_idx] = 1;
645 if (destination_idx >= k + m - local_parity) {
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);
655 if (!missing_local) {
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) {
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];
674 if (decode_matrix == NULL) {
676 encode_matrix, missing_bm, used_idxs, use_combined_parity);
684 *min_col = min_range;
685 *max_col = max_range;
686 return decode_matrix;
690 int *missing_idxs,
int destination_idx,
int blocksize)
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;
705 struct ec_bm missing_bm = NEW_BM;
706 convert_list_to_bitmap(missing_idxs, &missing_bm);
707 int inverse_row = -1;
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;
716 if( NULL == used_idxs) {
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) {
728 decode_inverse = (
unsigned char*)malloc(
sizeof(
unsigned char) * matrix_size * matrix_size);
730 if (NULL == decode_inverse) {
734 int im_ret = isa_l_desc->gf_invert_matrix(decode_matrix, decode_inverse, matrix_size);
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;
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);
748 g_tbls = malloc(
sizeof(
unsigned char) * (matrix_size * nb_parity * 32));
749 if (NULL == g_tbls) {
756 available_fragments = (
unsigned char**)malloc(
sizeof(
unsigned char*)*matrix_size);
757 if (NULL == available_fragments) {
762 if (matrix_size == k) {
763 for (i = 0; i < n - local_parity && j < k; i++) {
764 if (bm_get_value(&missing_bm, i)) {
768 available_fragments[j] = (
unsigned char*)data[i];
772 available_fragments[j] = (
unsigned char*)parity[i - k];
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) {
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];
787 available_fragments[j] = combined_local_parities;
790 for (i = n - local_parity; i < n && j < k; i++) {
791 if (bm_get_value(&missing_bm, i)) {
795 available_fragments[j] = (
unsigned char*)parity[i - k];
800 for (i = 0; i < n; i++) {
803 available_fragments[j] = (
unsigned char*)data[i];
805 available_fragments[j] = (
unsigned char*)parity[i - k];
816 for (i = 0; i < n; i++) {
817 if (bm_get_value(&missing_bm, i)) {
818 if (i == destination_idx) {
820 reconstruct_buf = (
unsigned char*)data[i];
822 reconstruct_buf = (
unsigned char*)parity[i - k];
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,
841 free(combined_local_parities);
843 free(decode_inverse);
845 free(available_fragments);
855 .ENCODE = isa_l_encode,
857 .FRAGSNEEDED = isa_l_min_fragments,
859 .ELEMENTSIZE = isa_l_element_size,
861 .GETMETADATASIZE = get_backend_metadata_size_zero,
862 .GETENCODEOFFSET = get_encode_offset_zero,
868 .id = EC_BACKEND_ISA_L_RS_LRC,
#define ISA_L_RS_LRC_LIB_NAME
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)
#define ISA_L_RS_LRC_SO_NAME
#define ISA_L_RS_LRC_LIB_VER_STR
static void * isa_l_rs_lrc_init(struct ec_backend_args *args, void *backend_sohandle)
struct ec_backend_common backend_isa_l_rs_lrc
static bool isa_l_rs_lrc_is_compatible_with(uint32_t version)
#define ISA_L_RS_LRC_LIB_REV
static struct ec_backend_op_stubs isa_l_rs_lrc_op_stubs
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)
static int isa_l_lrc_decode(void *desc, char **data, char **parity, int *missing_idxs, int blocksize)
__attribute__((visibility("internal")))
#define ISA_L_RS_LRC_LIB_MINOR
static int gen_encoding_matrix(isa_l_descriptor *desc, int m, int k)
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)
static int isa_l_rs_lrc_check_reconstruct_fragments(void *desc, int *missing_idxs, int destination_idx)
#define ISA_L_RS_LRC_LIB_MAJOR
static int isa_l_lrc_reconstruct(void *desc, char **data, char **parity, int *missing_idxs, int destination_idx, int blocksize)