Motr  M0
parity_math_mt_ub.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-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 <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 
27 #include "lib/types.h"
28 #include "lib/assert.h"
29 #include "lib/memory.h"
30 #include "lib/thread.h"
31 #include "lib/arith.h" /* m0_rnd64 */
32 
33 #include "lib/ub.h"
34 #include "ut/ut.h"
35 
36 #include "sns/matvec.h"
37 #include "sns/ls_solve.h"
38 #include "sns/parity_math.h"
39 
40 #define MAX_NUM_THREADS 30
41 #define KB(x) ((x) * 1024)
42 #define MB(x) (KB(x) * 1024)
43 
44 static uint64_t seed = 42;
45 
46 struct tb_cfg {
47  uint32_t tc_data_count;
48  uint32_t tc_parity_count;
49  uint32_t tc_fail_count;
50 
51  uint32_t tc_block_size;
52 
53  uint8_t **tc_data;
54  uint8_t **tc_backup;
55  uint8_t **tc_parity;
56  uint8_t *tc_fail;
57 };
58 
59 static int ub_init(const char *opts M0_UNUSED)
60 {
61  return 0;
62 }
63 
64 void tb_cfg_init(struct tb_cfg *cfg, uint32_t data_count, uint32_t parity_count,
65  uint32_t block_size, uint32_t th_num)
66 {
67  uint32_t i;
68  uint32_t fail_count;
69 
70  cfg->tc_data_count = data_count;
71  cfg->tc_parity_count = parity_count;
72  cfg->tc_fail_count = data_count + parity_count;
73  cfg->tc_block_size = block_size;
74 
75 
76  /* allocate data */
77  M0_ALLOC_ARR(cfg->tc_data, data_count);
78  M0_UT_ASSERT(cfg->tc_data != NULL);
79 
80  for (i = 0; i < data_count; ++i) {
81  M0_ALLOC_ARR(cfg->tc_data[i], block_size);
82  M0_UT_ASSERT(cfg->tc_data[i] != NULL);
83  }
84 
85  /* allocate parity */
86  M0_ALLOC_ARR(cfg->tc_parity, parity_count);
87  M0_UT_ASSERT(cfg->tc_parity != NULL);
88 
89  /* allocate memory for backup */
90  M0_ALLOC_ARR(cfg->tc_backup, parity_count);
91  M0_UT_ASSERT(cfg->tc_backup != NULL);
92 
93  for (i = 0; i < parity_count; ++i) {
94  M0_ALLOC_ARR(cfg->tc_parity[i], block_size);
95  M0_UT_ASSERT(cfg->tc_parity[i] != NULL);
96 
97  M0_ALLOC_ARR(cfg->tc_backup[i], block_size);
98  M0_UT_ASSERT(cfg->tc_backup[i] != NULL);
99  }
100 
101  /* allocate and set fail info */
102  M0_ALLOC_ARR(cfg->tc_fail, cfg->tc_fail_count);
103  M0_UT_ASSERT(cfg->tc_fail != NULL);
104 
105  fail_count = (th_num % parity_count) + 1;
106  for (i = 0; i < fail_count;) {
107  uint32_t idx = m0_rnd64(&seed) % cfg->tc_fail_count;
108  if (cfg->tc_fail[idx] == 0) {
109  cfg->tc_fail[idx] = 1;
110  i++;
111  }
112  }
113 }
114 
115 void tb_cfg_fini(struct tb_cfg *cfg)
116 {
117  uint32_t i;
118 
119  for (i = 0; i < cfg->tc_data_count; ++i)
120  m0_free(cfg->tc_data[i]);
121  m0_free(cfg->tc_data);
122 
123  for (i = 0; i < cfg->tc_parity_count; ++i){
124  m0_free(cfg->tc_parity[i]);
125  m0_free(cfg->tc_backup[i]);
126  }
127  m0_free(cfg->tc_parity);
128  m0_free(cfg->tc_backup);
129 
130  m0_free(cfg->tc_fail);
131 }
132 
133 static void unit_spoil(struct tb_cfg *cfg)
134 {
135  uint32_t i;
136  uint32_t j;
137  uint8_t *addr;
138 
139  for (i = 0, j = 0; i < cfg->tc_fail_count; i++) {
140  if (cfg->tc_fail[i]) {
141  if (i < cfg->tc_data_count)
142  addr = cfg->tc_data[i];
143  else
144  addr = cfg->tc_parity[i - cfg->tc_data_count];
145 
146  memcpy(cfg->tc_backup[j++], addr, cfg->tc_block_size);
147  memset(addr, 0xFF, cfg->tc_block_size);
148  }
149  }
150 }
151 
152 static void unit_compare(struct tb_cfg *cfg)
153 {
154  uint32_t i, j;
155  uint8_t *addr;
156 
157  for (i = 0, j = 0; i < cfg->tc_fail_count; i++) {
158  if (cfg->tc_fail[i]) {
159  if (i < cfg->tc_data_count)
160  addr = cfg->tc_data[i];
161  else
162  addr = cfg->tc_parity[i - cfg->tc_data_count];
163 
164  M0_UT_ASSERT(memcmp(cfg->tc_backup[j++], addr, cfg->tc_block_size) == 0);
165  }
166  }
167 }
168 
169 void tb_thread(struct tb_cfg *cfg)
170 {
171  int ret = 0;
172  uint32_t i = 0;
173 
174  uint32_t data_count = cfg->tc_data_count;
175  uint32_t parity_count = cfg->tc_parity_count;
176  uint32_t buff_size = cfg->tc_block_size;
177  uint32_t fail_count = data_count + parity_count;
178 
179  struct m0_parity_math math;
180  struct m0_buf *data_buf = 0;
181  struct m0_buf *parity_buf = 0;
182  struct m0_buf fail_buf;
183 
184  data_buf = m0_alloc(data_count * sizeof(struct m0_buf));
186 
187  parity_buf = m0_alloc(parity_count * sizeof(struct m0_buf));
188  M0_UT_ASSERT(parity_buf);
189 
190 
191  ret = m0_parity_math_init(&math, data_count, parity_count);
192  M0_UT_ASSERT(ret == 0);
193 
194  for (i = 0; i < data_count; ++i)
195  m0_buf_init(&data_buf [i], cfg->tc_data [i], buff_size);
196 
197  for (i = 0; i < parity_count; ++i)
198  m0_buf_init(&parity_buf[i], cfg->tc_parity[i], buff_size);
199 
200 
201  m0_parity_math_calculate(&math, data_buf, parity_buf);
202 
203  m0_buf_init(&fail_buf, cfg->tc_fail, fail_count);
204  unit_spoil(cfg);
205 
206  ret = m0_parity_math_recover(&math, data_buf, parity_buf, &fail_buf, 0);
207  M0_UT_ASSERT(ret == 0);
208 
209  unit_compare(cfg);
210 
211  m0_parity_math_fini(&math);
212  m0_free(data_buf);
213  m0_free(parity_buf);
214 }
215 
216 static void ub_mt_test(uint32_t data_count,
217  uint32_t parity_count,
218  uint32_t block_size)
219 {
220  uint32_t num_threads = MAX_NUM_THREADS;
221  uint32_t i;
222  int result = 0;
223 
224  struct tb_cfg *cfg;
225  struct m0_thread *threads;
226 
227  threads = m0_alloc(num_threads * sizeof(struct m0_thread));
228  M0_UT_ASSERT(threads != NULL);
229 
230  cfg = m0_alloc(num_threads * sizeof(struct tb_cfg));
231  M0_UT_ASSERT(cfg != NULL);
232 
233  for (i = 0; i < num_threads; i++) {
234  tb_cfg_init(&cfg[i], data_count, parity_count, block_size, i);
235  result = M0_THREAD_INIT(&threads[i], struct tb_cfg*, NULL,
236  &tb_thread, &cfg[i],
237  "tb_thread%d", i);
238  M0_UT_ASSERT(result == 0);
239  }
240 
241  for (i = 0; i < num_threads; i++) {
242  result = m0_thread_join(&threads[i]);
243  M0_UT_ASSERT(result == 0);
244  tb_cfg_fini(&cfg[i]);
245  }
246 
247  m0_free(cfg);
248  m0_free(threads);
249 }
250 
251 void ub_small_4K() {
252  ub_mt_test(10, 3, KB(4));
253 }
254 
255 void ub_medium_4K() {
256  ub_mt_test(20, 4, KB(4));
257 }
258 
259 void ub_large_4K() {
260  ub_mt_test(30, 4, KB(4));
261 }
262 
263 void ub_small_1M() {
264  ub_mt_test(10, 3, MB(1));
265 }
266 
267 void ub_medium_1M() {
268  ub_mt_test(20, 4, MB(1));
269 }
270 
271 void ub_large_1M() {
272  ub_mt_test(30, 4, MB(1));
273 }
274 
275 void ub_small_32K() {
276  ub_mt_test(10, 3, KB(32));
277 }
278 
280  ub_mt_test(20, 4, KB(32));
281 }
282 
283 void ub_large_32K() {
284  ub_mt_test(30, 4, KB(32));
285 }
286 
287 static void ub_small_4_2_4K(int iter) {
288  ub_mt_test(4, 2, KB(4));
289 }
290 
291 static void ub_small_4_2_256K(int iter) {
292  ub_mt_test(4, 2, KB(256));
293 }
294 
295 static void ub_small_4_2_1M(int iter) {
296  ub_mt_test(4, 2, MB(1));
297 }
298 
299 enum { UB_ITER = 1 };
300 
302  .us_name = "parity-math-mt-ub",
303  .us_init = ub_init,
304  .us_fini = NULL,
305  .us_run = {
306  /* parity_math-: */
307  { .ub_name = "s 10/03/ 4K",
308  .ub_iter = UB_ITER,
309  .ub_round = ub_small_4K,
310  .ub_block_size = KB(4),
311  .ub_blocks_per_op = 13 * MAX_NUM_THREADS },
312 
313  { .ub_name = "m 20/04/ 4K",
314  .ub_iter = UB_ITER,
315  .ub_round = ub_medium_4K,
316  .ub_block_size = KB(4),
317  .ub_blocks_per_op = 24 * MAX_NUM_THREADS },
318 
319  { .ub_name = "l 30/04/ 4K",
320  .ub_iter = UB_ITER,
321  .ub_round = ub_large_4K,
322  .ub_block_size = KB(4),
323  .ub_blocks_per_op = 34 * MAX_NUM_THREADS },
324 
325  { .ub_name = "s 10/03/ 32K",
326  .ub_iter = UB_ITER,
327  .ub_round = ub_small_32K,
328  .ub_block_size = KB(32),
329  .ub_blocks_per_op = 13 * MAX_NUM_THREADS },
330 
331  { .ub_name = "m 20/04/ 32K",
332  .ub_iter = UB_ITER,
333  .ub_round = ub_medium_32K,
334  .ub_block_size = KB(32),
335  .ub_blocks_per_op = 24 * MAX_NUM_THREADS },
336 
337  { .ub_name = "l 30/04/ 32K",
338  .ub_iter = UB_ITER,
339  .ub_round = ub_large_32K,
340  .ub_block_size = KB(32),
341  .ub_blocks_per_op = 34 * MAX_NUM_THREADS },
342 
343  { .ub_name = "s 10/05/ 1M",
344  .ub_iter = UB_ITER,
345  .ub_round = ub_small_1M,
346  .ub_block_size = MB(1),
347  .ub_blocks_per_op = 15 * MAX_NUM_THREADS },
348 
349  { .ub_name = "m 20/04/ 1M",
350  .ub_iter = UB_ITER,
351  .ub_round = ub_medium_1M,
352  .ub_block_size = MB(1),
353  .ub_blocks_per_op = 24 * MAX_NUM_THREADS },
354 
355  { .ub_name = "l 30/04/ 1M",
356  .ub_iter = UB_ITER,
357  .ub_round = ub_large_1M,
358  .ub_block_size = MB(1),
359  .ub_blocks_per_op = 34 * MAX_NUM_THREADS },
360 
361  { .ub_name = "s 04/02/ 4K",
362  .ub_iter = UB_ITER,
363  .ub_round = ub_small_4_2_4K,
364  .ub_block_size = 4096,
365  .ub_blocks_per_op = 6 * MAX_NUM_THREADS },
366 
367  { .ub_name = "m 04/02/256K",
368  .ub_iter = UB_ITER,
369  .ub_round = ub_small_4_2_256K,
370  .ub_block_size = 262144,
371  .ub_blocks_per_op = 6 * MAX_NUM_THREADS },
372 
373  { .ub_name = "l 04/02/ 1M",
374  .ub_iter = UB_ITER,
375  .ub_round = ub_small_4_2_1M,
376  .ub_block_size = 1048576,
377  .ub_blocks_per_op = 6 * MAX_NUM_THREADS },
378 
379  { .ub_name = NULL}
380  }
381 };
382 
383 
384 /*
385  * Local variables:
386  * c-indentation-style: "K&R"
387  * c-basic-offset: 8
388  * tab-width: 8
389  * fill-column: 80
390  * scroll-step: 1
391  * End:
392  */
M0_INTERNAL void m0_parity_math_fini(struct m0_parity_math *math)
Definition: parity_math.c:325
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
void tb_thread(struct tb_cfg *cfg)
#define NULL
Definition: misc.h:38
void ub_medium_32K()
int m0_thread_join(struct m0_thread *q)
Definition: kthread.c:169
struct m0_ub_set m0_parity_math_mt_ub
uint8_t ** tc_backup
static int ub_init(const char *opts M0_UNUSED)
void tb_cfg_init(struct tb_cfg *cfg, uint32_t data_count, uint32_t parity_count, uint32_t block_size, uint32_t th_num)
M0_INTERNAL void m0_buf_init(struct m0_buf *buf, void *data, uint32_t nob)
Definition: buf.c:37
void ub_large_1M()
static void ub_small_4_2_256K(int iter)
void ub_small_32K()
#define MB(x)
#define M0_THREAD_INIT(thread, TYPE, init, func, arg, namefmt,...)
Definition: thread.h:139
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
uint32_t tc_data_count
static void ub_small_4_2_4K(int iter)
uint32_t tc_fail_count
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
void ub_small_4K()
static char * addr
Definition: node_k.c:37
int i
Definition: dir.c:1033
void ub_large_4K()
void ub_large_32K()
const char * us_name
Definition: ub.h:76
#define MAX_NUM_THREADS
void tb_cfg_fini(struct tb_cfg *cfg)
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
void * m0_alloc(size_t size)
Definition: memory.c:126
static void ub_mt_test(uint32_t data_count, uint32_t parity_count, uint32_t block_size)
Definition: xcode.h:73
void ub_medium_1M()
void ub_small_1M()
M0_INTERNAL uint64_t m0_rnd64(uint64_t *seed)
Definition: misc.c:100
uint8_t ** tc_data
#define KB(x)
static uint64_t seed
static void ub_small_4_2_1M(int iter)
uint32_t tc_block_size
uint8_t ** tc_parity
void m0_free(void *data)
Definition: memory.c:146
void ub_medium_4K()
uint32_t tc_parity_count
Definition: ub.h:74
#define M0_UT_ASSERT(a)
Definition: ut.h:46
static void unit_spoil(struct tb_cfg *cfg)
uint8_t * tc_fail
static void unit_compare(struct tb_cfg *cfg)
#define M0_UNUSED
Definition: misc.h:380