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