Motr  M0
storage.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-2020 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 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_UT
23 
24 #include "lib/trace.h"
25 #include "lib/memory.h" /* M0_ALLOC_PTR */
26 #include "lib/misc.h" /* ARRAY_SIZE */
27 #include "lib/semaphore.h"
28 #include "ut/ut.h"
29 #include "stob/stob.h"
30 #include "stob/domain.h"
31 #include "addb2/addb2.h"
32 #include "addb2/storage.h"
33 #include "addb2/internal.h"
34 #include "addb2/consumer.h"
35 #include "addb2/identifier.h" /* M0_AVI_SIT */
36 #include "addb2/ut/common.h"
37 
38 static struct m0_stob_domain *dom;
39 static struct m0_stob *stob;
40 static struct m0_addb2_sit *sit;
41 static struct m0_addb2_storage *stor;
42 static struct m0_addb2_mach *mach;
43 
44 enum {
45  DOMAIN_KEY = 76,
46  STOB_KEY = 2,
47  SIZE = 4 * 1024 * 1024 * 1024ull
48 };
49 
50 const char *location = "linuxstob:./__s";
51 
52 static void stob_get(void)
53 {
54  int result;
55  struct m0_stob_id stob_id;
56 
57  result = m0_stob_domain_init(location, "directio=true", &dom);
58  M0_UT_ASSERT(result == 0);
59  M0_UT_ASSERT(dom != NULL);
60  m0_stob_id_make(0, STOB_KEY, &dom->sd_id, &stob_id);
61  result = m0_stob_find(&stob_id, &stob);
62  M0_UT_ASSERT(result == 0);
64  result = m0_stob_locate(stob);
65  M0_UT_ASSERT(result == 0);
67 }
68 
69 static void stob_put(void)
70 {
71  int result;
72 
73  result = m0_stob_destroy(stob, NULL);
74  M0_UT_ASSERT(result == 0);
75  result = m0_stob_domain_destroy(dom);
76  M0_ASSERT(result == 0);
77  stob = NULL;
78  dom = NULL;
79 }
80 
81 static bool idled;
82 
83 static void once_idle(struct m0_addb2_storage *_stor)
84 {
85  M0_UT_ASSERT(_stor == stor);
87  idled = true;
88 }
89 
90 static struct m0_semaphore idlewait;
91 static unsigned done;
92 static unsigned committed;
94 
95 static void test_idle(struct m0_addb2_storage *stor)
96 {
97  once_idle(stor);
99 }
100 
104 static void write_init_fini(void)
105 {
106  const struct m0_addb2_storage_ops ops = {
107  .sto_idle = &test_idle
108  };
109 
110  idled = false;
113  SIZE, NULL);
114  M0_UT_ASSERT(stor != NULL);
116  /*
117  * Storage machine may not be idle at this point, because whenever the
118  * machine is initialised a special marker record is pushed onto
119  * stob. But the corresponding IO can be already completed by the time
120  * m0_addb2_storage_stop() returns, so neither "idled" nor "!idled" can
121  * be asserted.
122  */
127  stor = NULL;
128 }
129 
130 static void test_done(struct m0_addb2_storage *_stor,
131  struct m0_addb2_trace_obj *obj)
132 {
133  M0_UT_ASSERT(_stor == stor);
134  ++done;
135 }
136 
137 static void test_commit(struct m0_addb2_storage *_stor,
138  const struct m0_addb2_frame_header *_last)
139 {
140  M0_UT_ASSERT(_stor == stor);
141  ++committed;
142  last = *_last;
143 }
144 
145 static const struct m0_addb2_storage_ops test_ops = {
146  .sto_idle = &test_idle,
147  .sto_done = &test_done,
148  .sto_commit = &test_commit
149 };
150 
151 static struct m0_semaphore machwait;
152 
153 static void mach_idle(const struct m0_addb2_mach *mach)
154 {
156 }
157 
158 static unsigned traces_submitted;
159 
160 static int test_submit(const struct m0_addb2_mach *m, struct m0_addb2_trace *t)
161 {
162  struct m0_addb2_trace_obj *obj = M0_AMB(obj, t, o_tr);
163 
164  M0_UT_ASSERT(m == mach);
167 }
168 
170 
171 static void stor_init(void)
172 {
173  idled = false;
174  idle = &mach_idle;
175  done = 0;
176  traces_submitted = 0;
177  committed = 0;
181  &test_ops, stob_size, NULL);
182  M0_UT_ASSERT(stor != NULL);
184  M0_UT_ASSERT(mach != NULL);
185 }
186 
187 static void stor_fini(void)
188 {
194  mach_fini(mach);
195  mach = NULL;
197  stor = NULL;
200 }
201 
202 static void submit_one(void)
203 {
204  stor_init();
205  M0_ADDB2_ADD(18, 127, 0, 0, 1);
206  stor_fini();
207 }
208 
209 static void write_many(void)
210 {
211  stor_init();
216  stor_fini();
217 }
218 
223 static void read_one(void)
224 {
225  int result;
226  struct m0_addb2_record *rec = NULL;
227 
228  M0_SET0(&last);
229  stor_init();
230  M0_ADDB2_PUSH(1, 2);
231  M0_ADDB2_ADD(0x0011111111111111,
232  0x2222222222222222, 0x3333333333333333,
233  0x4444444444444444, 0x5555555555555555);
234  m0_addb2_pop(1);
235  stor_fini();
238  stob_get();
239  result = m0_addb2_sit_init(&sit, stob, 0);
240  M0_UT_ASSERT(result == 0);
241  M0_UT_ASSERT(sit != NULL);
242  do {
243  result = m0_addb2_sit_next(sit, &rec);
244  M0_UT_ASSERT(result > 0);
245  M0_UT_ASSERT(rec != NULL);
246  } while (rec->ar_val.va_id == M0_AVI_SIT);
247  M0_UT_ASSERT(receq(rec, &(struct small_record) {
248  .ar_val = VAL(0x0011111111111111,
249  0x2222222222222222, 0x3333333333333333,
250  0x4444444444444444, 0x5555555555555555),
251  .ar_label_nr = 1,
252  .ar_label = {
253  [0] = VAL(1, 2)
254  }
255  }));
256  result = m0_addb2_sit_next(sit, &rec);
257  M0_UT_ASSERT(result == 0);
259  stob_put();
260 }
261 
262 static unsigned issued;
263 
264 #define PAYLOAD(seq) { \
265  seq ^ 0xdead, \
266  seq << 6, \
267  74, \
268  8 - seq, \
269  0x473824622, \
270  1 + seq, \
271  2 - seq, \
272  3 + seq, \
273  4 - seq, \
274  5 + seq, \
275  6 - seq, \
276  7 + seq, \
277  8 - seq \
278 }
279 
281 
282 static void add_one(void)
283 {
284  uint64_t payload[] = PAYLOAD(issued);
285 
286  if ((issued % DEPTH_MAX) == 0 && issued > 0) {
287  int i;
288 
289  for (i = DEPTH_MAX - 1; i >= 0; --i)
290  m0_addb2_pop(2 * i);
291  }
295  ++issued;
296 }
297 
298 static unsigned checked;
299 
300 static void check_one(const struct m0_addb2_record *rec)
301 {
302  uint64_t payload[] = PAYLOAD(checked);
303  const struct m0_addb2_value ideal = {
304  .va_id = checked,
305  .va_nr = checked % ARRAY_SIZE(payload),
306  .va_data = payload
307  };
308  if (rec->ar_val.va_id == M0_AVI_SIT)
309  return;
310  M0_UT_ASSERT(valeq(&rec->ar_val, &ideal));
313  rec->ar_label[i].va_id == 2 * (i % DEPTH_MAX)));
314  ++ checked;
315 }
316 
317 enum { NR = 500 * DEPTH_MAX };
318 
323 static void read_many(void)
324 {
325  int result;
326  int i;
327  struct m0_addb2_record *rec = NULL;
328 
329  issued = 0;
330  checked = 0;
331  M0_SET0(&last);
332  stor_init();
333  for (i = 0; i <= NR; ++i)
334  add_one();
335  m0_addb2_pop(0);
336  stor_fini();
337 
338  stob_get();
339  result = m0_addb2_sit_init(&sit, stob, 0);
340  M0_UT_ASSERT(result == 0);
341  M0_UT_ASSERT(sit != NULL);
342  while (checked <= NR) {
343  result = m0_addb2_sit_next(sit, &rec);
344  M0_UT_ASSERT(result > 0);
345  M0_UT_ASSERT(rec != NULL);
346  check_one(rec);
347  }
348  result = m0_addb2_sit_next(sit, &rec);
349  M0_UT_ASSERT(result == 0);
351  stob_put();
352 }
353 
354 static void frame_fill(void)
355 {
356  uint64_t seqno = last.he_seqno;
357 
358  while (last.he_seqno == seqno) {
359  add_one();
360  while (traces_submitted - done >= 100) {
361  nanosleep(&(struct timespec) { .tv_sec = 0,
362  .tv_nsec = 100000000 }, NULL);
363  }
364  }
365 }
366 
367 static void context_clean(void)
368 {
369  while ((issued % DEPTH_MAX) != 1)
370  add_one();
371  m0_addb2_pop(0);
372 }
373 
377 static void wrap(int n)
378 {
379  int result;
380  struct m0_addb2_record *rec = NULL;
381 
382  issued = 0;
383  checked = 0;
385  M0_SET0(&last);
386  stor_init();
387  frame_fill();
388  while (last.he_offset != BSIZE)
389  frame_fill();
390  frame_fill();
391  frame_fill();
392  context_clean();
393  stor_fini();
394  stob_get();
395  result = m0_addb2_sit_init(&sit, stob, 0);
396  M0_UT_ASSERT(result == 0);
397  M0_UT_ASSERT(sit != NULL);
398  do {
399  result = m0_addb2_sit_next(sit, &rec);
400  M0_UT_ASSERT(result > 0);
401  M0_UT_ASSERT(rec != NULL);
402  } while (rec->ar_val.va_id == M0_AVI_SIT);
403  checked = rec->ar_val.va_id;
404  check_one(rec);
405  while ((result = m0_addb2_sit_next(sit, &rec)) > 0)
406  check_one(rec);
407  M0_UT_ASSERT(result == 0);
409  stob_put();
410 }
411 
415 static void wrap1(void)
416 {
417  wrap(1);
418 }
419 
423 static void wrap2(void)
424 {
425  wrap(2);
426 }
427 
431 static void wrap3(void)
432 {
433  wrap(3);
434 }
435 
439 static void wrap7(void)
440 {
441  wrap(7);
442 }
443 
444 enum { THREADS = 8, OUTER = 50, INNER = 100 };
445 
446 static struct m0_semaphore pump_start;
447 static struct m0_semaphore pump_done;
448 static bool pump_exit;
449 
450 static void io_thread(int x)
451 {
452  static uint64_t body[8100];
453  int i;
454 
455  do {
457  for (i = 0; i < INNER; ++i) {
458  struct m0_addb2_trace_obj *obj;
459 
460  M0_ALLOC_PTR(obj);
461  obj->o_tr.tr_nr = 8000;
462  obj->o_tr.tr_body = body;
463  obj->o_done = (void *)&m0_free;
465  }
467  } while (!pump_exit);
468 }
469 
470 static void io_idle(struct m0_addb2_storage *stor)
471 {
472  test_idle(stor);
473 }
474 
475 static void io_done(struct m0_addb2_storage *stor,
476  struct m0_addb2_trace_obj *obj)
477 {
478 }
479 
483 static void fini_io(void)
484 {
485  int i;
486  int j;
487  int result;
488  struct m0_thread t[THREADS] = {};
489  const struct m0_addb2_storage_ops io_ops = {
490  .sto_idle = &io_idle,
491  .sto_done = &io_done
492  };
493 
496  for (i = 0; i < ARRAY_SIZE(t); ++i) {
497  result = M0_THREAD_INIT(&t[i], int, NULL, &io_thread, 0,
498  "io_thread");
499  M0_UT_ASSERT(result == 0);
500  }
501  for (i = 0; i < OUTER; ++i) {
502  idled = false;
503  pump_exit = (i == OUTER - 1);
506  i == 0, &io_ops, SIZE, NULL);
507  M0_UT_ASSERT(stor != NULL);
508  for (j = 0; j < ARRAY_SIZE(t); ++j)
510  for (j = 0; j < ARRAY_SIZE(t); ++j)
517  }
518  for (i = 0; i < ARRAY_SIZE(t); ++i) {
519  m0_thread_join(&t[i]);
520  m0_thread_fini(&t[i]);
521  }
524 }
525 
527  .ts_name = "addb2-storage",
528  .ts_init = NULL,
529  .ts_fini = NULL,
530  .ts_tests = {
531  { "write-init-fini", &write_init_fini },
532  { "submit-one", &submit_one },
533  { "read-one", &read_one },
534  { "read-many", &read_many },
535  { "write-many", &write_many},
536  { "wrap-1", &wrap1 },
537  { "wrap-2", &wrap2 },
538  { "wrap-3", &wrap3 },
539  { "wrap-7", &wrap7 },
540  { "fini-io", &fini_io },
541  { NULL, NULL }
542  }
543 };
544 
545 #undef M0_TRACE_SUBSYSTEM
546 
547 /*
548  * Local variables:
549  * c-indentation-style: "K&R"
550  * c-basic-offset: 8
551  * tab-width: 8
552  * fill-column: 80
553  * scroll-step: 1
554  * End:
555  */
void mach_fini(struct m0_addb2_mach *m)
Definition: common.c:78
static struct m0_addb2_storage * stor
Definition: storage.c:41
static struct m0_semaphore pump_done
Definition: storage.c:447
uint64_t he_prev_offset
Definition: storage.h:135
static void test_idle(struct m0_addb2_storage *stor)
Definition: storage.c:95
static void io_idle(struct m0_addb2_storage *stor)
Definition: storage.c:470
#define NULL
Definition: misc.h:38
static struct m0_addb2_mach * m
Definition: consumer.c:38
M0_INTERNAL int m0_stob_locate(struct m0_stob *stob)
Definition: stob.c:128
int m0_thread_join(struct m0_thread *q)
Definition: kthread.c:169
static bool x
Definition: sm.c:168
M0_INTERNAL int m0_stob_domain_destroy(struct m0_stob_domain *dom)
Definition: domain.c:227
static void io_done(struct m0_addb2_storage *stor, struct m0_addb2_trace_obj *obj)
Definition: storage.c:475
static void wrap3(void)
Definition: storage.c:431
void(* sto_idle)(struct m0_addb2_storage *stor)
Definition: storage.h:74
static struct m0_semaphore machwait
Definition: storage.c:151
Definition: internal.h:78
static m0_bcount_t stob_size
Definition: storage.c:169
#define M0_ADDB2_PUSH(id,...)
Definition: addb2.h:261
static bool pump_exit
Definition: storage.c:448
static void test_commit(struct m0_addb2_storage *_stor, const struct m0_addb2_frame_header *_last)
Definition: storage.c:137
M0_INTERNAL void m0_addb2_storage_stop(struct m0_addb2_storage *stor)
Definition: kaddb2.c:66
uint64_t va_id
Definition: consumer.h:103
static void add_one(void)
Definition: storage.c:282
static struct m0_addb2_mach * mach
Definition: storage.c:42
uint64_t m0_bcount_t
Definition: types.h:77
#define M0_THREAD_INIT(thread, TYPE, init, func, arg, namefmt,...)
Definition: thread.h:139
unsigned ar_label_nr
Definition: consumer.h:116
#define M0_SET0(obj)
Definition: misc.h:64
static void wrap2(void)
Definition: storage.c:423
M0_ADDB2_ADD(M0_AVI_FS_CREATE, new_fid.f_container, new_fid.f_key, mode, rc)
Definition: ut.h:77
static struct foo * obj
Definition: tlist.c:302
const char * location
Definition: storage.c:50
struct m0_fop_cob * body
Definition: dir.c:1436
struct m0_addb2_trace o_tr
Definition: addb2.h:451
Definition: storage.c:444
static void read_many(void)
Definition: storage.c:323
static void stor_init(void)
Definition: storage.c:171
int i
Definition: dir.c:1033
static void fini_io(void)
Definition: storage.c:483
static int test_submit(const struct m0_addb2_mach *m, struct m0_addb2_trace *t)
Definition: storage.c:160
M0_INTERNAL void m0_addb2_storage_fini(struct m0_addb2_storage *stor)
Definition: kaddb2.c:63
Definition: storage.c:47
#define VAL(id,...)
Definition: common.h:62
static void wrap(int n)
Definition: storage.c:377
void m0_addb2_push(uint64_t id, int n, const uint64_t *value)
Definition: addb2.c:412
#define M0_AMB(obj, ptr, field)
Definition: misc.h:320
static void submit_one(void)
Definition: storage.c:202
static struct m0_addb2_sit * sit
Definition: storage.c:40
void(* idle)(const struct m0_addb2_mach *mach)
Definition: common.c:34
Definition: stob.h:163
static struct m0_stob * stob
Definition: storage.c:39
#define M0_ASSERT(cond)
static void stob_put(void)
Definition: storage.c:69
void m0_addb2_mach_stop(struct m0_addb2_mach *mach)
Definition: addb2.c:630
uint64_t he_offset
Definition: storage.h:134
static void check_one(const struct m0_addb2_record *rec)
Definition: storage.c:300
static void frame_fill(void)
Definition: storage.c:354
static void once_idle(struct m0_addb2_storage *_stor)
Definition: storage.c:83
Definition: storage.c:317
static struct m0_thread t[8]
Definition: service_ut.c:1230
static void read_one(void)
Definition: storage.c:223
void m0_thread_fini(struct m0_thread *q)
Definition: thread.c:92
static struct m0_stob_domain * dom
Definition: storage.c:38
M0_INTERNAL void m0_stob_id_make(uint64_t container, uint64_t key, const struct m0_fid *dom_id, struct m0_stob_id *stob_id)
Definition: stob.c:343
int m0_addb2_sit_init(struct m0_addb2_sit **out, struct m0_stob *stob, m0_bindex_t start)
Definition: sit.c:108
M0_INTERNAL int m0_semaphore_init(struct m0_semaphore *semaphore, unsigned value)
Definition: semaphore.c:38
#define PAYLOAD(seq)
Definition: storage.c:264
struct m0_addb2_value ar_label[M0_ADDB2_LABEL_MAX]
Definition: consumer.h:118
static unsigned committed
Definition: storage.c:92
bool receq(const struct m0_addb2_record *r0, const struct small_record *r1)
Definition: common.c:134
static const struct m0_addb2_storage_ops test_ops
Definition: storage.c:145
static void write_init_fini(void)
Definition: storage.c:104
void m0_addb2_add(uint64_t id, int n, const uint64_t *value)
Definition: addb2.c:466
static void write_many(void)
Definition: storage.c:209
static void test_done(struct m0_addb2_storage *_stor, struct m0_addb2_trace_obj *obj)
Definition: storage.c:130
struct m0_addb2_mach * mach_set(int(*s)(const struct m0_addb2_mach *, struct m0_addb2_trace *))
Definition: common.c:65
static struct m0_semaphore pump_start
Definition: storage.c:446
void m0_addb2_pop(uint64_t id)
Definition: addb2.c:440
#define m0_forall(var, nr,...)
Definition: misc.h:112
struct m0_fid sd_id
Definition: domain.h:96
const char * ts_name
Definition: ut.h:99
M0_INTERNAL int m0_stob_destroy(struct m0_stob *stob, struct m0_dtx *dtx)
Definition: stob.c:200
uint64_t n
Definition: fops.h:107
M0_INTERNAL enum m0_stob_state m0_stob_state_get(struct m0_stob *stob)
Definition: stob.c:265
static void context_clean(void)
Definition: storage.c:367
M0_INTERNAL struct m0_addb2_storage * m0_addb2_storage_init(const char *location, uint64_t key, bool mkfs, bool force, const struct m0_addb2_storage_ops *ops, m0_bcount_t size, void *cookie)
Definition: kaddb2.c:42
M0_INTERNAL int m0_stob_domain_init(const char *location, const char *str_cfg_init, struct m0_stob_domain **out)
Definition: domain.c:195
int m0_addb2_sit_next(struct m0_addb2_sit *it, struct m0_addb2_record **out)
Definition: sit.c:148
struct m0_addb2_value ar_val
Definition: consumer.h:114
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
static unsigned traces_submitted
Definition: storage.c:158
M0_INTERNAL void m0_semaphore_fini(struct m0_semaphore *semaphore)
Definition: semaphore.c:45
static void io_thread(int x)
Definition: storage.c:450
M0_INTERNAL int m0_addb2_storage_submit(struct m0_addb2_storage *stor, struct m0_addb2_trace_obj *obj)
Definition: kaddb2.c:50
static void stor_fini(void)
Definition: storage.c:187
static bool idled
Definition: storage.c:81
static unsigned checked
Definition: storage.c:298
bool valeq(const struct m0_addb2_value *v0, const struct m0_addb2_value *v1)
Definition: common.c:127
static struct m0_semaphore idlewait
Definition: storage.c:90
M0_INTERNAL int m0_stob_find(const struct m0_stob_id *id, struct m0_stob **out)
Definition: stob.c:92
struct m0_ut_suite addb2_storage_ut
Definition: storage.c:526
static void stob_get(void)
Definition: storage.c:52
static unsigned done
Definition: storage.c:91
static void wrap1(void)
Definition: storage.c:415
M0_INTERNAL void m0_semaphore_down(struct m0_semaphore *semaphore)
Definition: semaphore.c:49
M0_INTERNAL void m0_semaphore_up(struct m0_semaphore *semaphore)
Definition: semaphore.c:65
struct m0_fom_ops ops
Definition: io_foms.c:623
static unsigned issued
Definition: storage.c:262
static void wrap7(void)
Definition: storage.c:439
void m0_free(void *data)
Definition: memory.c:146
static void mach_idle(const struct m0_addb2_mach *mach)
Definition: storage.c:153
#define ARRAY_SIZE(a)
Definition: misc.h:45
#define M0_UT_ASSERT(a)
Definition: ut.h:46
static struct m0_addb2_frame_header last
Definition: storage.c:93
const uint64_t payload[]
Definition: base.c:65
void m0_addb2_sit_fini(struct m0_addb2_sit *it)
Definition: sit.c:139
Definition: storage.c:444