Motr  M0
parity_math_ut.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2021 Seagate Technology LLC and/or its Affiliates
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * For any questions about this software or licensing,
17  * please email opensource@seagate.com or cortx-questions@seagate.com.
18  *
19  */
20 
21 
22 #include "lib/types.h"
23 #include "lib/assert.h"
24 #include "lib/memory.h"
25 #include "lib/errno.h" /* EDOM */
26 #include "lib/arith.h" /* m0_rnd64 */
27 
28 #include "lib/ub.h"
29 #include "ut/ut.h"
30 #include "sns/parity_math.h"
31 
32 #define KB(x) ((x) * 1024)
33 #define MB(x) (KB(x) * 1024)
34 
35 enum {
37 };
38 
39 enum {
47  NODES = 15,
48 };
49 
50 enum {
51  NUM_SEG = 8,
52  SEG_SIZE = 64,
53 };
54 
59 static int32_t duc = DATA_UNIT_COUNT_MAX;
60 static int32_t puc = PARITY_UNIT_COUNT_MAX;
61 static int32_t fuc = PARITY_UNIT_COUNT_MAX;
62 static uint32_t UNIT_BUFF_SIZE = 256;
63 static int32_t fail_index_xor;
64 static uint64_t seed = 42;
65 
67  struct m0_matrix mc_mat;
71 };
72 
76 };
77 
78 struct sns_ir_node {
79  struct m0_sns_ir sin_ir;
82  uint32_t *sin_alive;
83  uint32_t sin_alive_nr;
84 };
85 
90 };
91 
93  /* Full rank Vandermonde matrix */
95  /* Matrix is generated by elementary row operations on IRM_VANDMAT. */
97  /* Singular matrix */
99 };
100 
101 static void test_matrix_inverse(void);
102 static void test_incr_recov_init(void);
103 static void test_incr_recov(void);
104 static void test_invalid_input(void);
105 static int matrix_init(struct mat_collection*);
106 static void mat_fill(struct m0_matrix *mat, int N, int K,
107  enum ir_matrix_type mt);
108 static void identity_row_set(struct m0_matrix *mat, int row);
109 static void vandermonde_row_set(struct m0_matrix *mat, int row);
110 static void null_matrix_fill(struct m0_matrix *mat, int N);
111 static void invert(int N, int K, enum ir_matrix_type mt,
112  struct mat_collection *matrices);
113 static bool mat_compare(struct m0_matrix *mat1, struct m0_matrix *mat2);
114 static void matrix_fini(struct mat_collection *matrices);
115 static void parity_calculate(struct m0_parity_math *math, struct m0_bufvec *x,
116  struct m0_bufvec *p, uint32_t num_seg,
117  uint32_t seg_size);
118 static void direct_recover(struct m0_parity_math *math, struct m0_bufvec *x,
119  struct m0_bufvec *p);
120 static uint32_t *failure_setup(struct m0_parity_math *math,
121  uint32_t total_failures, enum failure_type ft);
122 static void array_randomly_fill(uint32_t *r_arr, uint32_t size,
123  uint32_t range);
124 static void rhs_prepare(const struct m0_sns_ir *ir, struct m0_matvec *des,
125  const struct m0_bufvec *x, const struct m0_bufvec *p,
126  const uint32_t *failed_arr, uint32_t total_failures);
127 static void reconstruct(const struct m0_sns_ir *ir, const struct m0_matvec *b,
128  struct m0_matvec *r);
129 static bool compare(const struct m0_sns_ir *ir, const uint32_t *failed_arr,
130  const struct m0_bufvec *x, const struct m0_matvec *r);
131 static void incremental_recover(struct m0_parity_math *math,
132  struct m0_bufvec *x, struct m0_bufvec *p);
133 
134 /* Initializes various objects for every member of array "nodes". */
135 static void sns_ir_nodes_init(struct m0_parity_math *math,
136  struct sns_ir_node *nodes, uint32_t *failed_arr,
137  uint32_t node_nr, uint32_t alive_nr);
138 static void failure_register(struct m0_sns_ir *ir, struct m0_bufvec *recov_arr,
139  uint32_t *failed_arr, uint32_t total_failures);
140 
141 static void alive_arrays_fill(struct m0_sns_ir *ir, uint32_t *alive_blocks,
142  uint32_t start_idx, uint32_t count);
143 
144 /* Each node partially recovers blocks, using its own alive blocks. */
145 static void sns_ir_nodes_recover(struct sns_ir_node *node, uint32_t node_nr,
146  struct m0_bufvec *x, struct m0_bufvec *p);
147 
148 /* node[0] gathers partially recovered blocks from other nodes to produce the
149  * final result. */
150 static void sns_ir_nodes_gather(struct sns_ir_node *node, uint32_t node_nr,
151  struct m0_bufvec *x, struct m0_bufvec *p,
152  uint32_t *failed_arr);
153 
154 /* node[0] compares the recovered blocks with original blocks. */
155 static void sns_ir_nodes_compare(struct sns_ir_node *node, struct m0_bufvec *x,
156  struct m0_bufvec *p);
157 static void sns_ir_nodes_fini(struct sns_ir_node *node, uint32_t node_nr,
158  uint32_t total_failures);
159 static inline uint32_t block_nr(const struct m0_sns_ir *ir);
160 
161 static void bufvec_initialize(struct m0_bufvec **bvec, uint32_t count,
162  uint32_t num_seg, uint32_t size);
163 static void bufvec_fill(struct m0_bufvec *x);
164 static void bufvec_fini(struct m0_bufvec *bvec, uint32_t count);
165 static bool bufvec_eq(struct m0_bufvec *bvec1, struct m0_bufvec *bvec2);
166 static void buf_initialize(struct m0_buf *buf, uint32_t size, uint32_t len);
167 static void buf_free(struct m0_buf *buf, uint32_t count);
168 
169 /* Converts m0_bufvec to m0_buf and vice versa. Argument "dir" decides
170  * direction of conversion. */
171 static void bufvec_buf(struct m0_bufvec *bvec, struct m0_buf *buf,
172  uint32_t count, bool dir);
173 
174 static void unit_spoil(const uint32_t buff_size,
175  const uint32_t fail_count,
176  const uint32_t data_count)
177 {
178  uint32_t i;
179 
180  for (i = 0; i < fail_count; ++i)
181  if (fail[i]) {
182  if (i < data_count)
183  memset(data[i], 0xFF, buff_size);
184  else
185  memset(parity[i - data_count], 0xFF, buff_size);
186  }
187 }
188 
189 static bool expected_eq(const uint32_t data_count, const uint32_t buff_size)
190 {
191  return m0_forall(i, data_count,
192  m0_forall(j, buff_size, expected[i][j] == data[i][j]));
193 }
194 
195 static bool config_generate(uint32_t *data_count,
196  uint32_t *parity_count,
197  uint32_t *buff_size,
198  const enum m0_parity_cal_algo algo)
199 {
200  int32_t i;
201  int32_t j;
202  int32_t puc_max = PARITY_UNIT_COUNT_MAX;
203 
204  if (algo == M0_PARITY_CAL_ALGO_XOR) {
205  fuc = 1;
206  puc = 1;
207  puc_max = 1;
208  fail_index_xor--;
209  if (fail_index_xor < 0) {
210  duc --;
212  }
213  if(duc < 1)
214  return false;
215  } else if (algo == M0_PARITY_CAL_ALGO_REED_SOLOMON) {
216  if (fuc <= 1) {
217  puc-=3;
218  if (puc <= 1) {
219  duc-=9;
221  }
222  fuc = puc+duc;
223  }
224 
225  if (puc < 1)
226  return false;
227  }
228  memset(fail, 0, DATA_UNIT_COUNT_MAX + puc_max);
229 
230  for (i = 0; i < duc; ++i) {
231  for (j = 0; j < UNIT_BUFF_SIZE; ++j) {
232  data[i][j] = (uint8_t) m0_rnd64(&seed);
233  expected[i][j] = data[i][j];
234  }
235  }
236 
237  j = 0;
238 
239  if (algo == M0_PARITY_CAL_ALGO_XOR)
240  fail[fail_index_xor] = 1;
241  else if (algo == M0_PARITY_CAL_ALGO_REED_SOLOMON) {
242  for (i = 0; i < fuc; ++i) {
243  if (j >= puc)
244  break;
245  fail[i] = (data[i][0] & 1) || (data[i][0] & 2) ||
246  (data[i][0] & 3);
247  if (fail[i])
248  ++j;
249  }
250 
251  if (!j) { /* at least one fail */
252  fail[fuc/2] = 1;
253  }
254  }
255 
256  *data_count = duc;
257  *parity_count = puc;
258  *buff_size = UNIT_BUFF_SIZE;
259 
261  fuc -= 3;
262 
263  return true;
264 }
265 
266 static bool rand_rs_config_generate(uint32_t *data_count,
267  uint32_t *parity_count,
268  uint32_t *buff_size)
269 {
270  int32_t i;
271  int32_t j;
272  int32_t puc_max = PARITY_UNIT_COUNT_MAX;
273  uint32_t failed_count = 0;
274 
275  if (fuc <= 1) {
276  puc-=3;
277  if (puc <= 1) {
278  duc-=9;
280  }
281  fuc = puc+duc;
282  }
283 
284  if (puc < 1)
285  return false;
286 
287  memset(fail, 0, DATA_UNIT_COUNT_MAX + puc_max);
288 
289  /* Fill random data and create back of the data */
290  for (i = 0; i < duc; ++i) {
291  for (j = 0; j < UNIT_BUFF_SIZE; ++j) {
292  data[i][j] = (uint8_t) m0_rnd64(&seed);
293  expected[i][j] = data[i][j];
294  }
295  }
296 
297  /* Fill failure array for random indices for mixed failures */
298  failed_count = ((uint8_t)m0_rnd64(&seed) % puc) + 1;
299  for (i = 0; i < failed_count; i++) {
300  j = (uint8_t) m0_rnd64(&seed) % (duc + puc);
301  fail[j] = 1;
302  }
303 
304  *data_count = duc;
305  *parity_count = puc;
306  *buff_size = UNIT_BUFF_SIZE;
307 
308  fuc -= 3;
309 
310  return true;
311 }
312 
313 static void test_recovery(const enum m0_parity_cal_algo algo,
314  const enum recovery_type rt)
315 {
316  uint32_t i;
317  uint32_t data_count;
318  uint32_t parity_count;
319  uint32_t buff_size;
320  uint32_t fail_count;
322  struct m0_buf parity_buf[DATA_UNIT_COUNT_MAX];
323  struct m0_buf fail_buf;
324  struct m0_parity_math *math;
325  int ret;
326 
327  M0_ALLOC_PTR(math);
328  M0_UT_ASSERT(math != NULL);
329 
330  while (config_generate(&data_count, &parity_count, &buff_size, algo)) {
331  fail_count = data_count + parity_count;
332 
333  ret = m0_parity_math_init(math, data_count, parity_count);
334  M0_UT_ASSERT(ret == 0);
335 
336  for (i = 0; i < data_count; ++i) {
337  m0_buf_init(&data_buf[i], data[i], buff_size);
338  m0_buf_init(&parity_buf[i], parity[i], buff_size);
339  }
340 
341  m0_buf_init(&fail_buf, fail, buff_size);
342 
343  m0_parity_math_calculate(math, data_buf, parity_buf);
344 
345  unit_spoil(buff_size, fail_count, data_count);
346 
347  if (rt == FAIL_INDEX)
349  parity_buf,
351  else if (rt == FAIL_VECTOR) {
352  ret = m0_parity_math_recover(math, data_buf, parity_buf,
353  &fail_buf, 0);
354  M0_UT_ASSERT(ret == 0);
355  }
356 
357  m0_parity_math_fini(math);
358 
359  M0_ASSERT_INFO(expected_eq(data_count, buff_size),
360  "Recovered data is unexpected");
361  }
362 
363  m0_free(math);
364 }
365 
366 static void test_rs_fv_recover(void)
367 {
369 }
370 
371 static void test_rs_fv_rand_recover(void)
372 {
373  uint32_t i;
374  uint32_t data_count;
375  uint32_t parity_count;
376  uint32_t buff_size;
377  uint32_t fail_count;
379  struct m0_buf parity_buf[DATA_UNIT_COUNT_MAX];
380  struct m0_buf fail_buf;
381  struct m0_parity_math math;
382  int ret;
383 
387 
388  while (rand_rs_config_generate(&data_count, &parity_count, &buff_size)) {
389  fail_count = data_count + parity_count;
390 
391  ret = m0_parity_math_init(&math, data_count, parity_count);
392  M0_UT_ASSERT(ret == 0);
393 
394  for (i = 0; i < data_count; ++i) {
395  m0_buf_init(&data_buf[i], data[i], buff_size);
396  m0_buf_init(&parity_buf[i], parity[i], buff_size);
397  }
398 
399  m0_buf_init(&fail_buf, fail, buff_size);
400 
401  m0_parity_math_calculate(&math, data_buf, parity_buf);
402 
403  unit_spoil(buff_size, fail_count, data_count);
404 
405  ret = m0_parity_math_recover(&math, data_buf, parity_buf,
406  &fail_buf, 0);
407  M0_UT_ASSERT(ret == 0);
408 
409  m0_parity_math_fini(&math);
410 
411  M0_ASSERT_INFO(expected_eq(data_count, buff_size),
412  "Recovered data is unexpected");
413  }
414 }
415 
416 static void test_xor_fv_recover(void)
417 {
421 }
422 
423 static void test_xor_fail_idx_recover(void)
424 {
428 }
429 
430 static void test_buffer_xor(void)
431 {
432  bool generated;
433  uint32_t data_count;
434  uint32_t parity_count;
435  uint32_t buff_size;
436  struct m0_buf buf1;
437  struct m0_buf buf2;
438 
439  duc = 3;
440  fail_index_xor = 0;
441  generated = config_generate(&data_count, &parity_count, &buff_size,
443  M0_UT_ASSERT(generated);
444  M0_UT_ASSERT(data_count == 2);
445 
446  m0_buf_init(&buf1, data[0], buff_size);
447  m0_buf_init(&buf2, data[1], buff_size);
448 
449  /*
450  * Swap 2 buffers and then swap them back, so at the end they must
451  * contain the original values.
452  */
453  m0_parity_math_buffer_xor(&buf1, &buf2);
454  m0_parity_math_buffer_xor(&buf2, &buf1);
455  m0_parity_math_buffer_xor(&buf1, &buf2);
456  m0_parity_math_buffer_xor(&buf2, &buf1);
457  m0_parity_math_buffer_xor(&buf1, &buf2);
458  m0_parity_math_buffer_xor(&buf2, &buf1);
459 
460  M0_ASSERT_INFO(expected_eq(data_count, buff_size),
461  "Recovered data is unexpected");
462 }
463 
464 static void test_parity_math_diff(uint32_t parity_cnt)
465 {
466  uint32_t i;
467  uint32_t j;
468  uint32_t ret;
469  uint8_t *arr;
470  struct m0_buf data_buf_old[DATA_UNIT_COUNT];
471  struct m0_buf data_buf_new[DATA_UNIT_COUNT];
472  struct m0_parity_math math;
473  struct m0_buf *p_old;
474  struct m0_buf *p_new;
475 
476 
477  for (i = 0; i < DATA_UNIT_COUNT; ++i) {
478  for (j = 0; j < UNIT_BUFF_SIZE; ++j) {
479  data[i][j] = (uint8_t) m0_rnd64(&seed);
480  if (i % 2)
481  data[i + DATA_UNIT_COUNT][j] =
482  (uint8_t) m0_rnd64(&seed);
483  else
484  data[i + DATA_UNIT_COUNT][j] = data[i][j];
485  }
486  }
487 
488  for (i = 0; i < DATA_UNIT_COUNT; ++i) {
489  m0_buf_init(&data_buf_old[i], data[i], UNIT_BUFF_SIZE);
490  m0_buf_init(&data_buf_new[i], data[i + DATA_UNIT_COUNT],
492  }
493 
495  parity_cnt);
496  M0_UT_ASSERT(ret == 0);
497  M0_ALLOC_ARR(p_old, parity_cnt);
498  M0_UT_ASSERT(p_old != NULL);
499  M0_ALLOC_ARR(p_new, parity_cnt);
500  M0_UT_ASSERT(p_new != NULL);
501 
502  for(i = 0; i < parity_cnt; ++i) {
504  M0_UT_ASSERT(arr != NULL);
505  m0_buf_init(&p_old[i], arr, UNIT_BUFF_SIZE);
507  M0_UT_ASSERT(arr != NULL);
508  m0_buf_init(&p_new[i], arr, UNIT_BUFF_SIZE);
509  }
510 
511  m0_parity_math_calculate(&math, data_buf_old, p_old);
512  m0_parity_math_calculate(&math, data_buf_new, p_new);
513 
514  for (i = 0; i < DATA_UNIT_COUNT; ++i) {
515  if (i % 2) {
516  ret = m0_parity_math_diff(&math, data_buf_old,
517  data_buf_new, p_old, i);
518  M0_UT_ASSERT(ret == 0);
519  }
520  }
521 
522  for(i = 0; i < parity_cnt; ++i) {
523  M0_UT_ASSERT(m0_buf_eq(&p_old[i], &p_new[i]));
524  }
525 
526  m0_parity_math_fini(&math);
527 
528  for(i = 0; i < parity_cnt; ++i) {
529  m0_buf_free(&p_old[i]);
530  m0_buf_free(&p_new[i]);
531  }
532  m0_free(p_old);
533  m0_free(p_new);
534 }
535 
536 static void test_parity_math_diff_xor(void)
537 {
539 }
540 
541 static void test_parity_math_diff_rs(void)
542 {
543  uint32_t i;
544  for (i = 2; i <= RS_MAX_PARITY_UNIT_COUNT; ++i) {
546  }
547 }
548 
549 static void test_incr_recov_rs(void)
550 {
553  test_incr_recov();
555 }
556 
557 static void test_matrix_inverse(void)
558 {
559  uint32_t i;
560  uint32_t j;
561  uint32_t k;
562  uint32_t N;
563  struct mat_collection matrices;
564 
565  for (i = 0; i < 10; ++i) {
566  N = matrix_init(&matrices);
568  for (j = IRM_VANDMAT; j <= IRM_SINGULAR_MAT; ++j) {
569  for (k = 1; k < N; ++k) {
570  invert(N, k, j, &matrices);
571  if (j == IRM_SINGULAR_MAT)
572  continue;
573  m0_matrix_multiply(&matrices.mc_mat,
574  &matrices.mc_mat_inverse,
575  &matrices.mc_mat_result);
577  &matrices.mc_identity_mat));
578  }
579  }
580  matrix_fini(&matrices);
581  }
582 }
583 
584 static int matrix_init(struct mat_collection *matrices)
585 {
586  int N = 0;
587  int ret;
588 
589  while (N == 0)
590  N = m0_rnd64(&seed) % (MAX_NUM_ROWS + 1);
591 
592  ret = m0_matrix_init(&matrices->mc_mat, N, N);
593  M0_UT_ASSERT(ret == 0);
594 
595  ret = m0_matrix_init(&matrices->mc_mat_inverse, N, N);
596  M0_UT_ASSERT(ret == 0);
597 
598  ret = m0_matrix_init(&matrices->mc_identity_mat, N, N);
599  M0_UT_ASSERT(ret == 0);
600 
601  ret = m0_matrix_init(&matrices->mc_mat_result, N, N);
602  M0_UT_ASSERT(ret == 0);
603  return N;
604 }
605 
606 static void invert(int N, int K, enum ir_matrix_type mt,
607  struct mat_collection *matrices)
608 {
609  int ret;
610 
611  mat_fill(&matrices->mc_mat, N, K, mt);
612  null_matrix_fill(&matrices->mc_mat_result, N);
613 
614  ret = m0_matrix_invert(&matrices->mc_mat, &matrices->mc_mat_inverse);
615 
616  if (mt == IRM_SINGULAR_MAT)
617  M0_UT_ASSERT(ret == -EDOM);
618  else
619  M0_UT_ASSERT(ret == 0);
620 }
621 
622 static void mat_fill(struct m0_matrix *mat, int N, int K,
623  enum ir_matrix_type mt)
624 {
627  m0_parity_elem_t *coeff_vec;
628 
629  switch (mt) {
630  case IRM_VANDMAT:
631  for (i = 0; i < N; ++i) {
632  vandermonde_row_set(mat, i);
633  }
634  break;
635  case IRM_NORM_VANDMAT:
636  for (i = 0; i < N - K; ++i) {
637  identity_row_set(mat, i);
638  }
639 
640  for (; i < N; ++i) {
641  vandermonde_row_set(mat, i);
642  }
643  break;
644  case IRM_SINGULAR_MAT:
645  /* First N - K rows are linearly independent, rest are within
646  * the span of first N - K rows. */
647  M0_ALLOC_ARR(coeff_vec, N - K);
648  M0_UT_ASSERT(coeff_vec != NULL);
649 
650  for (i = 0; i < N - K; ++i) {
651  coeff_vec[i] = m0_rnd64(&seed)%N;
652  vandermonde_row_set(mat, i);
653  }
654  for (; i < N; ++i) {
656  for (j = 0; j < N - K; ++j) {
657  m0_matrix_rows_operate(mat, i, j,
659  1, m0_parity_mul,
660  coeff_vec[j],
661  m0_parity_add);
662  }
663  }
664  m0_free(coeff_vec);
665  break;
666  }
667 }
668 
669 static void identity_row_set(struct m0_matrix *mat, int row)
670 {
671  uint32_t i;
672 
673  M0_UT_ASSERT(mat != NULL);
674  M0_UT_ASSERT(mat->m_width != 0);
675  M0_UT_ASSERT(mat->m_width == mat->m_height);
676  M0_UT_ASSERT(row < mat->m_height);
677 
678  for (i = 0; i < mat->m_width; ++i) {
679  *m0_matrix_elem_get(mat, row, i) = !! (i == row);
680  }
681 
682 }
683 
684 static void vandermonde_row_set(struct m0_matrix *mat, int row)
685 {
686  uint32_t i;
687 
689  M0_UT_ASSERT(row < mat->m_height);
690 
691  for (i = 0; i < mat->m_width; ++i) {
692  *m0_matrix_elem_get(mat, row, i) = m0_parity_pow(row, i);
693  }
694 }
695 
696 static void null_matrix_fill(struct m0_matrix *mat, int N)
697 {
698  uint32_t i;
699 
700  for (i = 0; i < N; ++i) {
702  }
703 }
704 
705 static bool mat_compare(struct m0_matrix *mat1, struct m0_matrix *mat2)
706 {
707  M0_UT_ASSERT(mat1 != NULL);
708  M0_UT_ASSERT(mat2 != NULL);
709  M0_UT_ASSERT(mat1->m_width == mat2->m_width);
710  M0_UT_ASSERT(mat1->m_height == mat2->m_height);
711 
712  return m0_forall(i, mat1->m_width,
713  m0_forall(j, mat1->m_height,
714  *m0_matrix_elem_get(mat1, j, i) ==
715  *m0_matrix_elem_get(mat2, j, i)));
716 }
717 
718 static void matrix_fini(struct mat_collection *matrices)
719 {
720  m0_matrix_fini(&matrices->mc_mat);
721  m0_matrix_fini(&matrices->mc_mat_inverse);
722  m0_matrix_fini(&matrices->mc_identity_mat);
723  m0_matrix_fini(&matrices->mc_mat_result);
724 
725 }
726 
727 /* Recovery mechanism solves a system of equations of the form Vx = b, where
728  * x is a vector of lost blocks, V is a matrix of coefficients and b is a
729  * vector of available blocks. During test_incr_recov_init(), we solve the
730  * system by computing V^{-1}.b *directly* rather than *incrementally* In test
731  * incr_recov() we solve this system incrementally. */
732 static void test_incr_recov_init(void)
733 {
734  uint32_t parity_cnt;
735  uint32_t i;
736  int ret;
737  struct m0_bufvec *x;
738  struct m0_bufvec *p;
739  struct m0_parity_math math;
740 
741  /* m0_parity_math_init() switches to XOR algorithm when parity_cnt = 1,
742  * hence we start with parity_cnt = 2. */
743  for (parity_cnt = 2; parity_cnt < RS_MAX_PARITY_UNIT_COUNT;
744  ++parity_cnt) {
745  ret = m0_parity_math_init(&math, DATA_UNIT_COUNT, parity_cnt);
746  M0_UT_ASSERT(ret == 0);
747 
748  bufvec_initialize(&x, math.pmi_data_count, 1, 1);
749  bufvec_initialize(&p, math.pmi_parity_count, 1, 1);
750  for (i = 0; i < DATA_UNIT_COUNT; ++i) {
751  bufvec_fill(&x[i]);
752  }
753 
754  parity_calculate(&math, x, p, 1, 1);
755  direct_recover(&math, x, p);
757  bufvec_fini(p, parity_cnt);
758  m0_parity_math_fini(&math);
759  }
760 }
761 
762 static void parity_calculate(struct m0_parity_math *math, struct m0_bufvec *x,
763  struct m0_bufvec *p, uint32_t num_seg,
764  uint32_t seg_size)
765 {
766  struct m0_buf *x_ser;
767  struct m0_buf *p_ser;
768 
769  M0_ALLOC_ARR(x_ser, math->pmi_data_count);
770  M0_UT_ASSERT(x_ser != NULL);
771  M0_ALLOC_ARR(p_ser, math->pmi_parity_count);
772  M0_UT_ASSERT(p_ser != NULL);
773 
774  buf_initialize(p_ser, math->pmi_parity_count, num_seg * seg_size);
775  buf_initialize(x_ser, math->pmi_data_count, num_seg * seg_size);
776  bufvec_buf(x, x_ser, math->pmi_data_count, true);
777  m0_parity_math_calculate(math, x_ser, p_ser);
778  bufvec_buf(p, p_ser, math->pmi_parity_count, false);
779 
780  buf_free(x_ser, math->pmi_data_count);
781  buf_free(p_ser, math->pmi_parity_count);
782 
783  m0_free(x_ser);
784  m0_free(p_ser);
785 }
786 
787 static void direct_recover(struct m0_parity_math *math, struct m0_bufvec *x,
788  struct m0_bufvec *p)
789 {
790  uint32_t i;
791  uint32_t total_failures = 0;
792  uint32_t *failed_arr;
793  int ret;
794  struct m0_matvec b;
795  struct m0_matvec r;
796  struct m0_sns_ir ir;
797  struct m0_bufvec recov_arr;
798 
799  while (total_failures == 0)
800  total_failures =
801  m0_rnd64(&seed) % (math->pmi_parity_count + 1);
802 
803  failed_arr = failure_setup(math, total_failures, MIXED_FAILURE);
804  ret = m0_sns_ir_init(math, 0, &ir);
805  M0_UT_ASSERT(ret == 0);
806 
807  ret = m0_matvec_init(&b, ir.si_data_nr);
808  M0_UT_ASSERT(ret == 0);
809 
810  rhs_prepare(&ir, &b, x, p, failed_arr, total_failures);
811 
812  for (i = 0; i < total_failures; ++i) {
813  ret = m0_sns_ir_failure_register(&recov_arr,
814  failed_arr[i], &ir);
815  M0_UT_ASSERT(ret == 0);
816  }
817 
818  ret = m0_sns_ir_mat_compute(&ir);
819  M0_UT_ASSERT(ret == 0);
820 
821  ret = m0_matvec_init(&r, ir.si_rs.rs_failed_nr);
822  M0_UT_ASSERT(ret == 0);
823 
824  reconstruct(&ir, &b, &r);
825  M0_UT_ASSERT(compare(&ir, failed_arr, x, &r));
826 
827  m0_free(failed_arr);
828  m0_matvec_fini(&r);
829  m0_matvec_fini(&b);
830  m0_sns_ir_fini(&ir);
831 }
832 
833 static uint32_t *failure_setup(struct m0_parity_math *math,
834  uint32_t total_failures, enum failure_type ft)
835 {
836  uint32_t *failed_arr;
837  uint32_t i;
838  uint32_t range = math->pmi_data_count;
839 
840  M0_ALLOC_ARR(failed_arr, total_failures);
841  M0_UT_ASSERT(failed_arr != NULL);
842  if (ft == MIXED_FAILURE)
843  range = math->pmi_data_count + math->pmi_parity_count;
844  else if (ft == ALL_DATA)
845  range = math->pmi_data_count;
846  else if (ft == ALL_PARITY)
847  range = math->pmi_parity_count;
848  array_randomly_fill(failed_arr, total_failures, range);
849  if (ft == ALL_PARITY) {
850  for (i = 0; i < total_failures; ++i) {
851  failed_arr[i] += math->pmi_data_count;
852  }
853  }
854 
855  return failed_arr;
856 }
857 
858 static void array_randomly_fill(uint32_t *r_arr, uint32_t size,
859  uint32_t range)
860 {
861  uint32_t interval;
862  uint32_t i;
863 
864  M0_UT_ASSERT(size != 0);
865  M0_UT_ASSERT(size <= range);
866 
867  interval = range/size;
868  for (i = 0; i < size; ++i)
869  r_arr[i] = m0_rnd64(&seed) % interval + i * interval;
870  if (r_arr[size - 1] > range - 1)
871  r_arr[size - 1] = m0_rnd64(&seed) % (range % interval) + (size - 1) *
872  interval;
873 }
874 
875 static void rhs_prepare(const struct m0_sns_ir *ir, struct m0_matvec *des,
876  const struct m0_bufvec *x, const struct m0_bufvec *p,
877  const uint32_t *failed_arr, uint32_t total_failures)
878 {
879  uint32_t i;
880  uint32_t j;
881  uint32_t k;
882 
883  for (i = 0, j = 0, k = 0; i < ir->si_data_nr; ++i) {
884  if (failed_arr[j] != i)
885  des->mv_vector[k++] = (((uint8_t **)x[i].ov_buf)[0])[0];
886  else if (j < total_failures - 1)
887  ++j;
888  }
889  for (i = 0; i < ir->si_parity_nr && k < des->mv_size; ++i) {
890  if (failed_arr[j] != i + ir->si_data_nr)
891  des->mv_vector[k++] = (((uint8_t **)p[i].ov_buf)[0])[0];
892  else if (j < total_failures - 1)
893  ++j;
894  }
895 }
896 
897 static void reconstruct(const struct m0_sns_ir *ir, const struct m0_matvec *b,
898  struct m0_matvec *r)
899 {
900  uint8_t **src;
901  uint8_t **dest;
902  uint32_t i;
903 
904  M0_ALLOC_ARR(src, b->mv_size);
905  M0_UT_ASSERT(src != NULL);
906 
907  M0_ALLOC_ARR(dest, r->mv_size);
908  M0_UT_ASSERT(dest != NULL);
909 
910  for (i = 0; i < b->mv_size; i++)
911  src[i] = (uint8_t *)&b->mv_vector[i];
912 
913  for (i = 0; i < r->mv_size; i++)
914  dest[i] = (uint8_t *)&r->mv_vector[i];
915 
916  ec_encode_data(1, b->mv_size, r->mv_size,
917  ir->si_rs.rs_decode_tbls, src, dest);
918 
919  m0_free(src);
920  m0_free(dest);
921 }
922 
923 static bool compare(const struct m0_sns_ir *ir, const uint32_t *failed_arr,
924  const struct m0_bufvec *x, const struct m0_matvec *r)
925 {
926  uint32_t i;
927  uint32_t j;
928 
929  for (j = 0; j < ir->si_rs.rs_failed_nr; j++) {
930  i = failed_arr[j];
931  if (i < ir->si_data_nr)
932  if ((uint8_t)*m0_matvec_elem_get(r, j) !=
933  (((uint8_t **)x[i].ov_buf)[0])[0])
934  return false;
935  }
936 
937  return true;
938 }
939 
940 static void test_incr_recov(void)
941 {
942  uint32_t parity_cnt;
943  uint32_t i;
944  int ret;
945  struct m0_bufvec *x;
946  struct m0_bufvec *p;
947  struct m0_parity_math math;
948 
949  for (parity_cnt = 2; parity_cnt < RS_MAX_PARITY_UNIT_COUNT;
950  ++parity_cnt) {
951  ret = m0_parity_math_init(&math, DATA_UNIT_COUNT, parity_cnt);
952  M0_UT_ASSERT(ret == 0);
955  for (i = 0; i < DATA_UNIT_COUNT; ++i) {
956  bufvec_fill(&x[i]);
957  }
958  parity_calculate(&math, x, p, NUM_SEG, SEG_SIZE);
959  incremental_recover(&math, x, p);
962  m0_parity_math_fini(&math);
963  }
964 }
965 
966 static void incremental_recover(struct m0_parity_math *math,
967  struct m0_bufvec *x, struct m0_bufvec *p)
968 {
969  uint32_t *failed_arr;
970  uint32_t total_failures = 0;
971  uint32_t alive_nr;
972  uint32_t node_nr;
973  uint32_t ft;
974  struct sns_ir_node *node;
975 
976  /* Alive blocks are distributed over all nodes. Each node maintains its
977  * context of recovery using its private struct m0_sns_ir. In the end,
978  * node0 gathers partial results from all other nodes and completes the
979  * recovery. */
980  for (ft = ALL_DATA; ft <= MIXED_FAILURE; ++ft) {
981  for (node_nr = 4; node_nr < NODES; ++node_nr) {
982  M0_ALLOC_ARR(node, node_nr);
983  M0_UT_ASSERT(node != NULL);
984  while (total_failures == 0)
985  total_failures =
986  m0_rnd64(&seed) % (math->pmi_parity_count + 1);
987  alive_nr = math->pmi_data_count +
988  math->pmi_parity_count - total_failures;
989  failed_arr = failure_setup(math, total_failures,
990  ft);
991  sns_ir_nodes_init(math, node, failed_arr, node_nr,
992  alive_nr);
993  sns_ir_nodes_recover(node, node_nr, x, p);
994  sns_ir_nodes_gather(node, node_nr, x, p, failed_arr);
996  sns_ir_nodes_fini(node, node_nr, total_failures);
997  m0_free(node);
998  m0_free(failed_arr);
999  }
1000  }
1001 }
1002 
1003 static void sns_ir_nodes_init(struct m0_parity_math *math,
1004  struct sns_ir_node *node, uint32_t *failed_arr,
1005  uint32_t node_nr, uint32_t alive_nr)
1006 {
1007  uint32_t i;
1008  uint32_t j;
1009  /* ID for the first alive block to go to a node. */
1010  uint32_t start_idx;
1011  uint32_t total_failures;
1012  uint32_t alive_bpn;
1013  int ret;
1014 
1015  total_failures = math->pmi_data_count + math->pmi_parity_count -
1016  alive_nr;
1017  alive_bpn = alive_nr/node_nr;
1018  for (i = 0, start_idx = 0; i < node_nr; ++i) {
1019  if (i != 0)
1020  node[i].sin_alive_nr = alive_bpn;
1021  else
1022  node[i].sin_alive_nr = alive_bpn + alive_nr % node_nr;
1023  ret = m0_sns_ir_init(math, node[i].sin_alive_nr, &node[i].sin_ir);
1024  M0_UT_ASSERT(ret == 0);
1027  /* Each node has as many accumulator buffers as
1028  * total failures. */
1029  bufvec_initialize(&node[i].sin_recov_arr, total_failures,
1030  NUM_SEG, SEG_SIZE);
1031  /* A bitmap is associated with every accumulator buffer to
1032  * indicate indices of blocks that have contributed to the
1033  * given buffer. */
1034  M0_ALLOC_ARR(node[i].sin_bitmap, total_failures);
1036 
1037  for (j = 0; j < total_failures; ++j) {
1038  ret = m0_bitmap_init(&node[i].sin_bitmap[j],
1039  math->pmi_data_count +
1040  math->pmi_parity_count);
1041  M0_UT_ASSERT(ret == 0);
1042  }
1044  failed_arr, total_failures);
1046  start_idx, node[i].sin_alive_nr);
1048  M0_UT_ASSERT(ret == 0);
1049  start_idx += node[i].sin_alive_nr;
1050  }
1051 }
1052 
1053 static void failure_register(struct m0_sns_ir *ir, struct m0_bufvec *recov_arr,
1054  uint32_t *failed_arr, uint32_t total_failures)
1055 {
1056  uint32_t j;
1057  int ret;
1058 
1059  for (j = 0; j < total_failures; ++j) {
1060  ret = m0_sns_ir_failure_register(&recov_arr[j],
1061  failed_arr[j],
1062  ir);
1063  M0_UT_ASSERT(ir->si_blocks[failed_arr[j]].sib_status ==
1065  M0_UT_ASSERT(ret == 0);
1066  }
1067 }
1068 
1069 static void alive_arrays_fill(struct m0_sns_ir *ir, uint32_t *alive_blocks,
1070  uint32_t start_idx, uint32_t count)
1071 {
1072  uint32_t i = 0;
1073  uint32_t j = 0;
1074 
1075  /* get the start_index^{th} alive block. */
1076  while (i < start_idx) {
1077  if (ir->si_blocks[j].sib_status == M0_SI_BLOCK_ALIVE)
1078  ++i;
1079  ++j;
1080  }
1081  /* collect next 'count' number of alive blocks. */
1082  for (i = 0; j < ir->si_data_nr + ir->si_parity_nr && i < count; ++j) {
1083  if (ir->si_blocks[j].sib_status == M0_SI_BLOCK_ALIVE) {
1084  alive_blocks[i] = ir->si_blocks[j].sib_idx;
1085  ++i;
1086  }
1087  }
1088 }
1089 
1090 static void sns_ir_nodes_recover(struct sns_ir_node *node, uint32_t node_nr,
1091  struct m0_bufvec *x, struct m0_bufvec *p)
1092 {
1093  uint32_t i;
1094  uint32_t j;
1095  uint32_t k;
1096  uint32_t alive_idx;
1097  uint32_t total_failures;
1098  struct m0_bitmap alive_bitmap;
1099  int ret;
1100  struct m0_sns_ir ir;
1101 
1102  ret = m0_bitmap_init(&alive_bitmap,
1103  node[0].sin_ir.si_data_nr +
1104  node[0].sin_ir.si_parity_nr);
1105  M0_UT_ASSERT(ret == 0);
1106  total_failures = block_nr(&node[0].sin_ir) -
1107  node[0].sin_ir.si_alive_nr;
1108  for (i = 1; i < node_nr; ++i) {
1109  ir = node[i].sin_ir;
1110  for (j = 0; j < node[i].sin_alive_nr; ++j) {
1111  m0_bitmap_set(&alive_bitmap, node[i].sin_alive[j],
1112  true);
1113  alive_idx = node[i].sin_alive[j];
1114  if (alive_idx < ir.si_data_nr) {
1115  ret = m0_sns_ir_recover(&node[i].sin_ir,
1116  &x[alive_idx],
1117  &alive_bitmap, 0,
1119  M0_UT_ASSERT(ret == 0);
1120  }
1121  else if (alive_idx >= ir.si_data_nr &&
1122  alive_idx < ir.si_data_nr + ir.si_parity_nr) {
1123  ret = m0_sns_ir_recover(&node[i].sin_ir,
1124  &p[alive_idx -
1125  ir.si_data_nr],
1126  &alive_bitmap, 0,
1128  M0_UT_ASSERT(ret == 0);
1129  }
1130  for (k = 0; k < total_failures; ++k) {
1131  m0_bitmap_set(&node[i].sin_bitmap[k],
1132  node[i].sin_alive[j], true);
1133  }
1134  m0_bitmap_set(&alive_bitmap, node[i].sin_alive[j],
1135  false);
1136  }
1137  }
1138  m0_bitmap_fini(&alive_bitmap);
1139 }
1140 
1141 static void sns_ir_nodes_gather(struct sns_ir_node *node, uint32_t node_nr,
1142  struct m0_bufvec *x, struct m0_bufvec *p,
1143  uint32_t *failed_arr)
1144 {
1145  uint32_t i;
1146  uint32_t j;
1147  uint32_t k;
1148  uint32_t total_failures;
1149  struct m0_bitmap alive_bitmap;
1150  uint32_t alive_idx;
1151  struct m0_sns_ir ir;
1152  int ret;
1153 
1154  total_failures = block_nr(&node[0].sin_ir) - node[0].sin_ir.si_alive_nr;
1155  ir = node[0].sin_ir;
1156  ret = m0_bitmap_init(&alive_bitmap,
1157  node[0].sin_ir.si_data_nr +
1158  node[0].sin_ir.si_parity_nr);
1159  M0_UT_ASSERT(ret == 0);
1160 
1161  /* Add remote blocks */
1162  for (i = 1; i < node_nr - 2; ++i) {
1163  for (k = 0; k < total_failures; ++k) {
1164  ret = m0_sns_ir_recover(&node[0].sin_ir,
1165  &node[i].sin_recov_arr[k],
1166  &node[i].sin_bitmap[k],
1167  failed_arr[k], M0_SI_BLOCK_REMOTE);
1168  M0_UT_ASSERT(ret == 0);
1169  }
1170  }
1171 
1172  /* Add local blocks */
1173  for (j = 0; j < node[0].sin_alive_nr; ++j) {
1174  m0_bitmap_set(&alive_bitmap, node[0].sin_alive[j],
1175  true);
1176  alive_idx = node[0].sin_alive[j];
1177  if (alive_idx < ir.si_data_nr) {
1178  ret = m0_sns_ir_recover(&node[0].sin_ir,
1179  &x[alive_idx],
1180  &alive_bitmap, 0,
1182  M0_UT_ASSERT(ret == 0);
1183  }
1184  else if (alive_idx >= ir.si_data_nr &&
1185  alive_idx < ir.si_data_nr + ir.si_parity_nr) {
1186  ret = m0_sns_ir_recover(&node[0].sin_ir,
1187  &p[alive_idx -
1188  ir.si_data_nr],
1189  &alive_bitmap, 0,
1191  M0_UT_ASSERT(ret == 0);
1192  }
1193  for (k = 0; k < total_failures; ++k) {
1194  m0_bitmap_set(&node[0].sin_bitmap[k],
1195  node[0].sin_alive[j], true);
1196  }
1197  m0_bitmap_set(&alive_bitmap, node[0].sin_alive[j],
1198  false);
1199  }
1200  /* Add remote blocks */
1201  for (i = node_nr - 2; i < node_nr; ++i) {
1202  for (k = 0; k < total_failures; ++k) {
1203  ret = m0_sns_ir_recover(&node[0].sin_ir,
1204  &node[i].sin_recov_arr[k],
1205  &node[i].sin_bitmap[k],
1206  failed_arr[k], M0_SI_BLOCK_REMOTE);
1207  M0_UT_ASSERT(ret == 0);
1208  }
1209  }
1210  m0_bitmap_fini(&alive_bitmap);
1211 }
1212 
1213 static void sns_ir_nodes_compare(struct sns_ir_node *node, struct m0_bufvec *x,
1214  struct m0_bufvec *p)
1215 {
1216  uint32_t i;
1217  struct m0_sns_ir ir;
1218 
1219  ir = node[0].sin_ir;
1220  for (i = 0; i < ir.si_data_nr; ++i) {
1221  if (node[0].sin_ir.si_blocks[i].sib_status ==
1223  M0_UT_ASSERT(bufvec_eq(node[0].sin_ir.si_blocks[i].
1224  sib_addr, &x[i]));
1225  }
1226  }
1227  for (; i < ir.si_data_nr + ir.si_parity_nr; ++i) {
1228  if (node[0].sin_ir.si_blocks[i].sib_status ==
1230  M0_UT_ASSERT(bufvec_eq(node[0].sin_ir.si_blocks[i].
1231  sib_addr, &p[i -
1232  ir.si_data_nr]));
1233  }
1234  }
1235 }
1236 
1237 static void sns_ir_nodes_fini(struct sns_ir_node *node, uint32_t node_nr,
1238  uint32_t total_failures)
1239 {
1240  uint32_t i;
1241  uint32_t j;
1242 
1243  for (i = 0; i < node_nr; ++i) {
1244  m0_sns_ir_fini(&node[i].sin_ir);
1245  bufvec_fini(node[i].sin_recov_arr, total_failures);
1246  for (j = 0; j < total_failures; ++j)
1247  m0_bitmap_fini(&node[i].sin_bitmap[j]);
1248  m0_free(node[i].sin_bitmap);
1249  m0_free(node[i].sin_alive);
1250  }
1251 }
1252 
1253 static void test_invalid_input(void)
1254 {
1255  uint32_t i;
1256  uint32_t parity_cnt = 2;
1257  uint32_t total_failures;
1258  uint32_t *failed_arr;
1259  int ret;
1260  struct m0_bufvec recov_arr;
1261  struct m0_parity_math math;
1262  struct m0_sns_ir ir;
1263 
1264  ret = m0_parity_math_init(&math, DATA_UNIT_COUNT, parity_cnt);
1265  M0_UT_ASSERT(ret == 0);
1266  total_failures = math.pmi_parity_count + 1;
1267  failed_arr = failure_setup(&math, total_failures, MIXED_FAILURE);
1268  ret = m0_sns_ir_init(&math, 0, &ir);
1269  for (i = 0; i < total_failures - 1; ++i) {
1270  ret = m0_sns_ir_failure_register(&recov_arr,
1271  failed_arr[i],
1272  &ir);
1273  M0_UT_ASSERT(ret == 0);
1274  }
1275  ret = m0_sns_ir_failure_register(&recov_arr,
1276  failed_arr[i],
1277  &ir);
1278  M0_UT_ASSERT(ret == -ERANGE);
1279  m0_free(failed_arr);
1280  m0_sns_ir_fini(&ir);
1281  m0_parity_math_fini(&math);
1282 }
1283 
1284 static void bufvec_initialize(struct m0_bufvec **bvec, uint32_t count,
1285  uint32_t num_seg, uint32_t seg_size)
1286 {
1287  uint32_t i;
1288  int ret;
1289 
1290  M0_ALLOC_ARR(*bvec, count);
1291  M0_UT_ASSERT(*bvec != NULL);
1292 
1293  for (i = 0; i < count; ++i) {
1294  ret = m0_bufvec_alloc(&bvec[0][i], num_seg, seg_size);
1295  M0_UT_ASSERT(ret == 0);
1296  }
1297 }
1298 
1299 static void bufvec_fini(struct m0_bufvec *bvec, uint32_t count)
1300 {
1301  uint32_t i;
1302 
1303  for (i = 0; i < count; ++i) {
1304  m0_bufvec_free(&bvec[i]);
1305  }
1306  m0_free(bvec);
1307 }
1308 
1309 static void bufvec_fill(struct m0_bufvec *x)
1310 {
1311 
1312  uint8_t *x_buf;
1313  struct m0_bufvec_cursor x_cursor;
1314  m0_bcount_t step;
1315  uint32_t i;
1316 
1317  m0_bufvec_cursor_init(&x_cursor, x);
1318  do {
1319  x_buf = m0_bufvec_cursor_addr(&x_cursor);
1320  for (i = 0; i < x->ov_vec.v_count[0]; ++i)
1321  x_buf[i] = (uint8_t)m0_rnd64(&seed);
1322  step = m0_bufvec_cursor_step(&x_cursor);
1323  } while (!m0_bufvec_cursor_move(&x_cursor, step));
1324 }
1325 
1326 static void bufvec_buf(struct m0_bufvec *bvec, struct m0_buf *buf,
1327  uint32_t count, bool dir)
1328 {
1329  struct m0_bufvec_cursor cursor;
1330  m0_bcount_t step;
1331  uint32_t i;
1332  uint32_t j;
1333  uint8_t *buf_data;
1334 
1335  for (j = 0, i = 0; j < count; ++j, i = 0) {
1336  m0_bufvec_cursor_init(&cursor, &bvec[j]);
1337  buf_data = (uint8_t *)buf[j].b_addr;
1338  do {
1339  if (dir)
1340  memcpy(&buf_data[i * bvec[j].ov_vec.v_count[i]],
1341  m0_bufvec_cursor_addr(&cursor),
1342  bvec[j].ov_vec.v_count[i]);
1343  else
1344  memcpy(m0_bufvec_cursor_addr(&cursor),
1345  &buf_data[i * bvec[j].ov_vec.v_count[i]],
1346  bvec[j].ov_vec.v_count[i]);
1347  ++i;
1348  step = m0_bufvec_cursor_step(&cursor);
1349  } while (!m0_bufvec_cursor_move(&cursor, step));
1350  }
1351 }
1352 
1353 static void _buf_free(struct m0_buf *buf)
1354 {
1355  m0_free_aligned(buf->b_addr, buf->b_nob, 12);
1356  buf->b_nob = 0;
1357 }
1358 
1359 static void buf_initialize(struct m0_buf *buf, uint32_t size, uint32_t len)
1360 {
1361  uint32_t j;
1362  uint8_t *arr;
1363 
1364  for (j = 0; j < size; ++j) {
1365  M0_ALLOC_ARR_ALIGNED(arr, len, 12);
1366  M0_UT_ASSERT(arr != NULL);
1367  m0_buf_init(&buf[j], arr, len);
1368  }
1369 }
1370 
1371 static void buf_free(struct m0_buf *buf, uint32_t count)
1372 {
1373  uint32_t i;
1374 
1375  for (i = 0; i < count; ++i) {
1376  _buf_free(&buf[i]);
1377  }
1378 }
1379 
1380 static bool bufvec_eq(struct m0_bufvec *bvec_1, struct m0_bufvec *bvec_2)
1381 {
1382  struct m0_bufvec_cursor bvec_1_cursor;
1383  struct m0_bufvec_cursor bvec_2_cursor;
1384  m0_bcount_t step;
1385  int ret;
1386 
1387  M0_UT_ASSERT(bvec_1->ov_vec.v_nr == bvec_2->ov_vec.v_nr);
1388  m0_bufvec_cursor_init(&bvec_1_cursor, bvec_1);
1389  m0_bufvec_cursor_init(&bvec_2_cursor, bvec_2);
1390  do {
1391  ret = memcmp(m0_bufvec_cursor_addr(&bvec_1_cursor),
1392  m0_bufvec_cursor_addr(&bvec_2_cursor),
1393  bvec_1->ov_vec.v_count[0]);
1394  step = m0_bufvec_cursor_step(&bvec_1_cursor);
1395  } while (ret == 0 && !m0_bufvec_cursor_move(&bvec_1_cursor, step) &&
1396  !m0_bufvec_cursor_move(&bvec_2_cursor, step));
1397  return ret == 0;
1398 }
1399 
1400 static inline uint32_t block_nr(const struct m0_sns_ir *ir)
1401 {
1402  return ir->si_data_nr + ir->si_parity_nr;
1403 }
1404 
1405 #define _TESTS \
1406  { "reed_solomon_recover_with_fail_vec", test_rs_fv_recover }, \
1407  { "reed_solomon_recover_with_fail_vec_rand", test_rs_fv_rand_recover }, \
1408  { "xor_recover_with_fail_vec", test_xor_fv_recover }, \
1409  { "xor_recover_with_fail_index", test_xor_fail_idx_recover }, \
1410  { "buffer_xor", test_buffer_xor }, \
1411  { "parity_math_diff_xor", test_parity_math_diff_xor }, \
1412  { "parity_math_diff_rs", test_parity_math_diff_rs }, \
1413  { "incr_recov_rs", test_incr_recov_rs }, \
1414  { NULL, NULL }
1415 
1417  .ts_name = "parity_math-ut",
1418  .ts_init = NULL,
1419  .ts_fini = NULL,
1420  .ts_tests = { _TESTS }
1421 };
1422 M0_EXPORTED(parity_math_ut);
1423 
1425  .ts_name = "parity_math_ssse3-ut",
1426  .ts_tests = { _TESTS }
1427 };
1428 M0_EXPORTED(parity_math_ssse3_ut);
1429 
1430 #undef _TESTS
1431 
1432 static int ub_init(const char *opts M0_UNUSED)
1433 {
1434  return 0;
1435 }
1436 
1437 void parity_math_tb(void)
1438 {
1439  int ret = 0;
1440  uint32_t i = 0;
1441  struct m0_parity_math *math;
1442  uint32_t data_count = 0;
1443  uint32_t parity_count = 0;
1444  uint32_t buff_size = 0;
1445  uint32_t fail_count = 0;
1447  struct m0_buf parity_buf[DATA_UNIT_COUNT_MAX];
1448  struct m0_buf fail_buf;
1449 
1450  M0_ALLOC_PTR(math);
1451  M0_UT_ASSERT(math != NULL);
1452 
1453  config_generate(&data_count, &parity_count, &buff_size,
1455  {
1456  fail_count = data_count + parity_count;
1457 
1458  ret = m0_parity_math_init(math, data_count, parity_count);
1459  M0_ASSERT(ret == 0);
1460 
1461  for (i = 0; i < data_count; ++i) {
1462  m0_buf_init(&data_buf [i], data [i], buff_size);
1463  m0_buf_init(&parity_buf[i], parity[i], buff_size);
1464  }
1465 
1466  m0_buf_init(&fail_buf, fail, buff_size);
1467 
1468  m0_parity_math_calculate(math, data_buf, parity_buf);
1469 
1470  unit_spoil(buff_size, fail_count, data_count);
1471 
1472  ret = m0_parity_math_recover(math, data_buf, parity_buf,
1473  &fail_buf, 0);
1474  M0_UT_ASSERT(ret == 0);
1475 
1476  m0_parity_math_fini(math);
1477  }
1478 
1479  m0_free(math);
1480 }
1481 
1482 static void ub_small_4K(int iter)
1483 {
1484  UNIT_BUFF_SIZE = KB(4);
1485  duc = 10;
1486  puc = 5;
1487  fuc = duc+puc;
1488  parity_math_tb();
1489 }
1490 
1491 static void ub_medium_4K(int iter)
1492 {
1493  UNIT_BUFF_SIZE = KB(4);
1494  duc = 20;
1495  puc = 6;
1496  fuc = duc+puc;
1497  parity_math_tb();
1498 }
1499 
1500 static void ub_large_4K(int iter)
1501 {
1502  UNIT_BUFF_SIZE = KB(4);
1503  duc = 30;
1504  puc = 12;
1505  fuc = duc+puc;
1506  parity_math_tb();
1507 }
1508 
1509 static void ub_small_1M(int iter)
1510 {
1511  UNIT_BUFF_SIZE = MB(1);
1512  duc = 3;
1513  puc = 2;
1514  fuc = duc+puc;
1515  parity_math_tb();
1516 }
1517 
1518 static void ub_medium_1M(int iter)
1519 {
1520  UNIT_BUFF_SIZE = MB(1);
1521  duc = 6;
1522  puc = 3;
1523  fuc = duc+puc;
1524  parity_math_tb();
1525 }
1526 
1527 static void ub_large_1M(int iter)
1528 {
1529  UNIT_BUFF_SIZE = MB(1);
1530  duc = 8;
1531  puc = 4;
1532  fuc = duc+puc;
1533  parity_math_tb();
1534 }
1535 
1536 static void ub_small_32K(int iter)
1537 {
1538  UNIT_BUFF_SIZE = KB(32);
1539  duc = 10;
1540  puc = 5;
1541  fuc = duc+puc;
1542  parity_math_tb();
1543 }
1544 
1545 static void ub_medium_32K(int iter)
1546 {
1547  UNIT_BUFF_SIZE = KB(32);
1548  duc = 20;
1549  puc = 6;
1550  fuc = duc+puc;
1551  parity_math_tb();
1552 }
1553 
1554 static void ub_large_32K(int iter)
1555 {
1556  UNIT_BUFF_SIZE = KB(32);
1557  duc = 30;
1558  puc = 12;
1559  fuc = duc+puc;
1560  parity_math_tb();
1561 }
1562 static void ub_small_4_2_4K(int iter)
1563 {
1564  UNIT_BUFF_SIZE = KB(4);
1565  duc = 4;
1566  puc = 2;
1567  fuc = duc+puc;
1568  parity_math_tb();
1569 }
1570 
1571 static void ub_small_4_2_256K(int iter)
1572 {
1573  UNIT_BUFF_SIZE = KB(256);
1574  duc = 4;
1575  puc = 2;
1576  fuc = duc+puc;
1577  parity_math_tb();
1578 }
1579 
1580 static void ub_small_4_2_1M(int iter)
1581 {
1582  UNIT_BUFF_SIZE = MB(1);
1583  duc = 4;
1584  puc = 2;
1585  fuc = duc+puc;
1586  parity_math_tb();
1587 }
1588 
1589 enum { UB_ITER = 100 };
1590 
1592  .us_name = "parity-math-ub",
1593  .us_init = ub_init,
1594  .us_fini = NULL,
1595  .us_run = {
1596  { .ub_name = "s 10/05/ 4K",
1597  .ub_iter = UB_ITER,
1598  .ub_round = ub_small_4K,
1599  .ub_block_size = KB(4),
1600  .ub_blocks_per_op = 15 },
1601 
1602  { .ub_name = "m 20/06/ 4K",
1603  .ub_iter = UB_ITER,
1604  .ub_round = ub_medium_4K,
1605  .ub_block_size = KB(4),
1606  .ub_blocks_per_op = 26 },
1607 
1608  { .ub_name = "l 30/12/ 4K",
1609  .ub_iter = UB_ITER,
1610  .ub_round = ub_large_4K,
1611  .ub_block_size = KB(4),
1612  .ub_blocks_per_op = 42 },
1613 
1614  { .ub_name = "s 10/05/ 32K",
1615  .ub_iter = UB_ITER,
1616  .ub_round = ub_small_32K,
1617  .ub_block_size = KB(32),
1618  .ub_blocks_per_op = 15 },
1619 
1620  { .ub_name = "m 20/06/ 32K",
1621  .ub_iter = UB_ITER,
1622  .ub_round = ub_medium_32K,
1623  .ub_block_size = KB(32),
1624  .ub_blocks_per_op = 26 },
1625 
1626  { .ub_name = "l 30/12/ 32K",
1627  .ub_iter = UB_ITER,
1628  .ub_round = ub_large_32K,
1629  .ub_block_size = KB(32),
1630  .ub_blocks_per_op = 42 },
1631 
1632  { .ub_name = "s 03/02/ 1M",
1633  .ub_iter = UB_ITER,
1634  .ub_round = ub_small_1M,
1635  .ub_block_size = MB(1),
1636  .ub_blocks_per_op = 5 },
1637 
1638  { .ub_name = "m 06/03/ 1M",
1639  .ub_iter = UB_ITER,
1640  .ub_round = ub_medium_1M,
1641  .ub_block_size = MB(1),
1642  .ub_blocks_per_op = 9 },
1643 
1644  { .ub_name = "l 08/04/ 1M",
1645  .ub_iter = UB_ITER,
1646  .ub_round = ub_large_1M,
1647  .ub_block_size = MB(1),
1648  .ub_blocks_per_op = 12 },
1649 
1650  { .ub_name = "s 04/02/ 4K",
1651  .ub_iter = UB_ITER,
1652  .ub_round = ub_small_4_2_4K,
1653  .ub_block_size = KB(4),
1654  .ub_blocks_per_op = 6 },
1655 
1656  { .ub_name = "m 04/02/256K",
1657  .ub_iter = UB_ITER,
1658  .ub_round = ub_small_4_2_256K,
1659  .ub_block_size = KB(256),
1660  .ub_blocks_per_op = 6 },
1661 
1662  { .ub_name = "l 04/02/ 1M",
1663  .ub_iter = UB_ITER,
1664  .ub_round = ub_small_4_2_1M,
1665  .ub_block_size = MB(1),
1666  .ub_blocks_per_op = 6 },
1667 
1668  { .ub_name = NULL}
1669  }
1670 };
1671 
1672 /*
1673  * Local variables:
1674  * c-indentation-style: "K&R"
1675  * c-basic-offset: 8
1676  * tab-width: 8
1677  * fill-column: 80
1678  * scroll-step: 1
1679  * End:
1680  */
static void test_matrix_inverse(void)
static m0_bcount_t seg_size
Definition: net.c:118
enum m0_sns_ir_block_status sib_status
Definition: parity_math.h:88
struct m0_bitmap * sin_bitmap
static m0_parity_elem_t m0_parity_add(m0_parity_elem_t x, m0_parity_elem_t y)
Definition: parity_ops.h:41
static struct m0_addb2_philter p
Definition: consumer.c:40
static void ub_large_1M(int iter)
static void bufvec_initialize(struct m0_bufvec **bvec, uint32_t count, uint32_t num_seg, uint32_t size)
static void incremental_recover(struct m0_parity_math *math, struct m0_bufvec *x, struct m0_bufvec *p)
M0_INTERNAL void m0_parity_math_fini(struct m0_parity_math *math)
Definition: parity_math.c:325
static void unit_spoil(const uint32_t buff_size, const uint32_t fail_count, const uint32_t data_count)
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
M0_INTERNAL int m0_bitmap_init(struct m0_bitmap *map, size_t nr)
Definition: bitmap.c:86
uint32_t sib_idx
Definition: parity_math.h:78
recovery_type
struct m0_sns_ir sin_ir
uint32_t pmi_data_count
Definition: parity_math.h:127
#define NULL
Definition: misc.h:38
M0_INTERNAL void m0_bitmap_fini(struct m0_bitmap *map)
Definition: bitmap.c:97
static bool expected_eq(const uint32_t data_count, const uint32_t buff_size)
static void mat_fill(struct m0_matrix *mat, int N, int K, enum ir_matrix_type mt)
static void ub_small_4_2_4K(int iter)
static void test_xor_fail_idx_recover(void)
static void sns_ir_nodes_gather(struct sns_ir_node *node, uint32_t node_nr, struct m0_bufvec *x, struct m0_bufvec *p, uint32_t *failed_arr)
static bool x
Definition: sm.c:168
M0_INTERNAL bool m0_buf_eq(const struct m0_buf *x, const struct m0_buf *y)
Definition: buf.c:90
static void test_invalid_input(void)
static void _buf_free(struct m0_buf *buf)
struct m0_matrix mc_mat_result
static bool config_generate(uint32_t *data_count, uint32_t *parity_count, uint32_t *buff_size, const enum m0_parity_cal_algo algo)
static struct net_test_cmd_node * node
Definition: commands.c:72
M0_INTERNAL void m0_parity_math_buffer_xor(struct m0_buf *dest, const struct m0_buf *src)
Definition: parity_math.c:415
uint32_t m_height
Definition: matvec.h:57
static void direct_recover(struct m0_parity_math *math, struct m0_bufvec *x, struct m0_bufvec *p)
struct m0_vec ov_vec
Definition: vec.h:147
static void buf_free(struct m0_buf *buf, uint32_t count)
M0_INTERNAL void m0_buf_init(struct m0_buf *buf, void *data, uint32_t nob)
Definition: buf.c:37
M0_INTERNAL bool m0_matrix_is_init(const struct m0_matrix *mat)
Definition: matvec.c:387
M0_INTERNAL void m0_free_aligned(void *data, size_t size, unsigned shift)
Definition: memory.c:192
void parity_math_tb(void)
static void rhs_prepare(const struct m0_sns_ir *ir, struct m0_matvec *des, const struct m0_bufvec *x, const struct m0_bufvec *p, const uint32_t *failed_arr, uint32_t total_failures)
static void vandermonde_row_set(struct m0_matrix *mat, int row)
M0_INTERNAL void * m0_bufvec_cursor_addr(struct m0_bufvec_cursor *cur)
Definition: vec.c:597
uint64_t m0_bcount_t
Definition: types.h:77
m0_parity_cal_algo
Definition: parity_math.h:49
M0_INTERNAL int m0_parity_math_recover(struct m0_parity_math *math, struct m0_buf *data, struct m0_buf *parity, struct m0_buf *fails, enum m0_parity_linsys_algo algo)
Definition: parity_math.c:383
M0_INTERNAL void m0_sns_ir_fini(struct m0_sns_ir *ir)
Definition: parity_math.c:488
Definition: ut.h:77
M0_INTERNAL int m0_parity_math_diff(struct m0_parity_math *math, struct m0_buf *old, struct m0_buf *new, struct m0_buf *parity, uint32_t index)
Definition: parity_math.c:371
static bool rand_rs_config_generate(uint32_t *data_count, uint32_t *parity_count, uint32_t *buff_size)
struct m0_sns_ir_block * si_blocks
Definition: parity_math.h:141
#define N(i)
void ** ov_buf
Definition: vec.h:149
static void test_parity_math_diff_xor(void)
static void ub_medium_4K(int iter)
Definition: sock.c:887
static m0_bcount_t count
Definition: xcode.c:167
#define KB(x)
static void test_parity_math_diff_rs(void)
M0_INTERNAL int m0_sns_ir_failure_register(struct m0_bufvec *recov_addr, uint32_t failed_index, struct m0_sns_ir *ir)
Definition: parity_math.c:453
M0_INTERNAL int m0_sns_ir_init(const struct m0_parity_math *math, uint32_t local_nr, struct m0_sns_ir *ir)
Definition: parity_math.c:425
M0_INTERNAL int m0_bufvec_alloc(struct m0_bufvec *bufvec, uint32_t num_segs, m0_bcount_t seg_size)
Definition: vec.c:220
static uint64_t seed
M0_INTERNAL void m0_parity_math_calculate(struct m0_parity_math *math, struct m0_buf *data, struct m0_buf *parity)
Definition: parity_math.c:362
Definition: buf.h:37
static void bufvec_fini(struct m0_bufvec *bvec, uint32_t count)
M0_INTERNAL void m0_bufvec_free(struct m0_bufvec *bufvec)
Definition: vec.c:395
static void test_recovery(const enum m0_parity_cal_algo algo, const enum recovery_type rt)
M0_INTERNAL bool m0_bufvec_cursor_move(struct m0_bufvec_cursor *cur, m0_bcount_t count)
Definition: vec.c:574
static void test_parity_math_diff(uint32_t parity_cnt)
M0_INTERNAL void m0_matrix_row_operate(struct m0_matrix *m, uint32_t row, m0_parity_elem_t c, m0_matvec_matrix_binary_operator_t f)
Definition: matvec.c:142
int i
Definition: dir.c:1033
static void test_incr_recov_rs(void)
static void sns_ir_nodes_recover(struct sns_ir_node *node, uint32_t node_nr, struct m0_bufvec *x, struct m0_bufvec *p)
static void ub_small_4_2_256K(int iter)
void * b_addr
Definition: buf.h:231
static uint8_t data[DATA_UNIT_COUNT_MAX][UNIT_BUFF_SIZE_MAX]
m0_parity_elem_t * mv_vector
Definition: matvec.h:36
static void test_xor_fv_recover(void)
M0_INTERNAL m0_bcount_t m0_bufvec_cursor_step(const struct m0_bufvec_cursor *cur)
Definition: vec.c:581
uint32_t sin_alive_nr
uint32_t mv_size
Definition: matvec.h:35
static void ub_small_4_2_1M(int iter)
#define M0_ASSERT(cond)
static void null_matrix_fill(struct m0_matrix *mat, int N)
static void ub_medium_32K(int iter)
M0_INTERNAL void m0_matrix_rows_operate(struct m0_matrix *m, uint32_t row0, uint32_t row1, m0_matvec_matrix_binary_operator_t f0, m0_parity_elem_t c0, m0_matvec_matrix_binary_operator_t f1, m0_parity_elem_t c1, m0_matvec_matrix_binary_operator_t f)
Definition: matvec.c:165
const char * us_name
Definition: ub.h:76
static int32_t fail_index_xor
failure_type
static int32_t fuc
static int matrix_init(struct mat_collection *)
static struct net_test_cmd_node nodes[NTC_MULTIPLE_NODES]
Definition: commands.c:74
static void test_rs_fv_rand_recover(void)
M0_INTERNAL int m0_sns_ir_recover(struct m0_sns_ir *ir, struct m0_bufvec *bufvec, const struct m0_bitmap *bitmap, uint32_t failed_index, enum m0_sns_ir_block_type block_type)
Definition: parity_math.c:503
static int32_t puc
static struct m0_bufvec bvec
Definition: xcode.c:169
uint32_t * sin_alive
static void bufvec_buf(struct m0_bufvec *bvec, struct m0_buf *buf, uint32_t count, bool dir)
M0_INTERNAL void m0_bufvec_cursor_init(struct m0_bufvec_cursor *cur, const struct m0_bufvec *bvec)
Definition: vec.c:563
static struct rectype rt[]
Definition: beck.c:428
struct m0_matrix mc_identity_mat
static bool bufvec_eq(struct m0_bufvec *bvec1, struct m0_bufvec *bvec2)
M0_INTERNAL int m0_sns_ir_mat_compute(struct m0_sns_ir *ir)
Definition: parity_math.c:482
struct m0_matrix mc_mat_inverse
M0_INTERNAL int m0_parity_math_init(struct m0_parity_math *math, uint32_t data_count, uint32_t parity_count)
Definition: parity_math.c:333
static void matrix_fini(struct mat_collection *matrices)
struct m0_reed_solomon si_rs
Definition: parity_math.h:142
static uint32_t * failure_setup(struct m0_parity_math *math, uint32_t total_failures, enum failure_type ft)
static void test_incr_recov(void)
static void parity_calculate(struct m0_parity_math *math, struct m0_bufvec *x, struct m0_bufvec *p, uint32_t num_seg, uint32_t seg_size)
static void failure_register(struct m0_sns_ir *ir, struct m0_bufvec *recov_arr, uint32_t *failed_arr, uint32_t total_failures)
M0_INTERNAL void m0_bitmap_set(struct m0_bitmap *map, size_t idx, bool val)
Definition: bitmap.c:139
M0_INTERNAL void m0_matrix_multiply(const struct m0_matrix *ma, const struct m0_matrix *mb, struct m0_matrix *mc)
Definition: matvec.c:342
uint32_t v_nr
Definition: vec.h:51
static void ub_small_4K(int iter)
static void ub_large_4K(int iter)
M0_INTERNAL void m0_buf_free(struct m0_buf *buf)
Definition: buf.c:55
uint8_t * rs_decode_tbls
Definition: parity_math.h:105
static void ub_large_32K(int iter)
#define _TESTS
m0_bcount_t * v_count
Definition: vec.h:53
struct m0_ut_suite parity_math_ut
m0_parity_elem_t * m0_matrix_elem_get(const struct m0_matrix *m, uint32_t x, uint32_t y)
Definition: matvec.c:86
m0_parity_elem_t * m0_matvec_elem_get(const struct m0_matvec *v, uint32_t x)
Definition: matvec.c:80
static void bufvec_fill(struct m0_bufvec *x)
static void sns_ir_nodes_compare(struct sns_ir_node *node, struct m0_bufvec *x, struct m0_bufvec *p)
uint32_t si_data_nr
Definition: parity_math.h:134
static bool mt
Definition: service_ut.c:67
static void array_randomly_fill(uint32_t *r_arr, uint32_t size, uint32_t range)
static uint8_t expected[DATA_UNIT_COUNT_MAX][UNIT_BUFF_SIZE_MAX]
static bool compare(const struct m0_sns_ir *ir, const uint32_t *failed_arr, const struct m0_bufvec *x, const struct m0_matvec *r)
static void ub_small_1M(int iter)
#define m0_forall(var, nr,...)
Definition: misc.h:112
static bool mat_compare(struct m0_matrix *mat1, struct m0_matrix *mat2)
M0_INTERNAL void m0_matrix_fini(struct m0_matrix *m)
Definition: matvec.c:70
const char * ts_name
Definition: ut.h:99
M0_INTERNAL void m0_identity_matrix_fill(struct m0_matrix *identity_mat)
Definition: matvec.c:371
static uint8_t fail[DATA_UNIT_COUNT_MAX+PARITY_UNIT_COUNT_MAX]
M0_INTERNAL uint64_t m0_rnd64(uint64_t *seed)
Definition: misc.c:100
M0_INTERNAL int m0_matrix_init(struct m0_matrix *m, uint32_t w, uint32_t h)
Definition: matvec.c:49
static void sns_ir_nodes_init(struct m0_parity_math *math, struct sns_ir_node *nodes, uint32_t *failed_arr, uint32_t node_nr, uint32_t alive_nr)
uint32_t rs_failed_nr
Definition: parity_math.h:107
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
static int r[NR]
Definition: thread.c:46
ir_matrix_type
static void invert(int N, int K, enum ir_matrix_type mt, struct mat_collection *matrices)
M0_INTERNAL m0_parity_elem_t m0_parity_pow(m0_parity_elem_t x, m0_parity_elem_t p)
Definition: parity_ops.c:30
struct m0_ut_suite parity_math_ssse3_ut
m0_bcount_t size
Definition: di.c:39
static void test_rs_fv_recover(void)
#define M0_ALLOC_ARR_ALIGNED(arr, nr, shift)
Definition: memory.h:88
struct m0_bufvec * sin_recov_arr
int m0_parity_elem_t
Definition: parity_ops.h:36
static void buf_initialize(struct m0_buf *buf, uint32_t size, uint32_t len)
static int32_t duc
#define M0_ASSERT_INFO(cond, fmt,...)
struct m0_ub_set m0_parity_math_ub
static struct m0_fop_type * ft[]
Definition: service_ut.c:856
M0_INTERNAL int m0_matvec_init(struct m0_matvec *v, uint32_t sz)
Definition: matvec.c:36
static void sns_ir_nodes_fini(struct sns_ir_node *node, uint32_t node_nr, uint32_t total_failures)
struct inode * dir
Definition: dir.c:1028
static void test_buffer_xor(void)
M0_INTERNAL int m0_matrix_invert(const struct m0_matrix *in_mat, struct m0_matrix *mat_inverse)
Definition: ls_solve.c:136
struct m0_matrix mc_mat
static m0_parity_elem_t m0_parity_mul(m0_parity_elem_t x, m0_parity_elem_t y)
Definition: parity_ops.h:51
M0_INTERNAL void m0_matvec_fini(struct m0_matvec *v)
Definition: matvec.c:43
uint32_t m_width
Definition: matvec.h:56
static void reconstruct(const struct m0_sns_ir *ir, const struct m0_matvec *b, struct m0_matvec *r)
static void alive_arrays_fill(struct m0_sns_ir *ir, uint32_t *alive_blocks, uint32_t start_idx, uint32_t count)
void m0_free(void *data)
Definition: memory.c:146
M0_INTERNAL void m0_parity_math_fail_index_recover(struct m0_parity_math *math, struct m0_buf *data, struct m0_buf *parity, const uint32_t fidx)
Definition: parity_math.c:396
static uint32_t UNIT_BUFF_SIZE
struct m0_pdclust_src_addr src
Definition: fd.c:108
#define MB(x)
static uint32_t block_nr(const struct m0_sns_ir *ir)
static void identity_row_set(struct m0_matrix *mat, int row)
Definition: ub.h:74
#define M0_UT_ASSERT(a)
Definition: ut.h:46
uint32_t pmi_parity_count
Definition: parity_math.h:128
uint32_t si_parity_nr
Definition: parity_math.h:135
static uint8_t parity[DATA_UNIT_COUNT_MAX][UNIT_BUFF_SIZE_MAX]
static void ub_small_32K(int iter)
static int ub_init(const char *opts M0_UNUSED)
Definition: vec.h:145
static void test_incr_recov_init(void)
static void ub_medium_1M(int iter)
#define M0_UNUSED
Definition: misc.h:380