Motr  M0
alloc.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2013-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_UT
24 #include "lib/trace.h"
25 
26 #include "be/alloc.h"
27 
28 #include "lib/memory.h" /* m0_addr_is_aligned */
29 #include "lib/misc.h" /* M0_SET_ARR0 */
30 #include "lib/thread.h" /* m0_thread */
31 #include "lib/arith.h" /* m0_rnd64 */
32 #include "lib/finject.h" /* m0_fi_enable_once */
33 
34 #include "ut/ut.h" /* M0_UT_ASSERT */
35 
36 #include "be/ut/helper.h" /* m0_be_ut_backend */
37 #include "be/op.h" /* m0_be_op */
38 #include "be/alloc_internal.h" /* be_alloc_chunk */
39 
40 enum {
45  BE_UT_ALLOC_NR = 0x800,
48 };
49 
55  int ats_nr;
56 };
57 
61 
62 M0_INTERNAL void m0_be_ut_alloc_init_fini(void)
63 {
64  struct m0_be_ut_seg ut_seg = {};
65  struct m0_be_seg *seg;
66  struct m0_be_allocator *a;
67  int rc;
68 
70  seg = ut_seg.bus_seg;
73  M0_UT_ASSERT(rc == 0);
76 }
77 
78 M0_INTERNAL void m0_be_ut_alloc_create_destroy(void)
79 {
80  struct m0_be_ut_seg ut_seg;
81 
84 
86 
88 
92 }
93 
95  void **p,
96  uint64_t *seed)
97 {
100  unsigned shift;
101 
103  shift = m0_rnd64(seed) % BE_UT_ALLOC_SHIFT;
104 
105  if (*p == NULL) {
106  M0_BE_UT_TRANSACT(ut_be, tx, cred,
108  size, shift, &cred),
109  m0_be_alloc_stats_credit(a, &cred)),
110  (M0_BE_OP_SYNC(op,
111  m0_be_alloc_aligned(a, tx, &op, p, size,
112  shift,
114  m0_be_alloc_stats_capture(a, tx)));
115  M0_UT_ASSERT(*p != NULL);
117  } else {
118  M0_BE_UT_TRANSACT(ut_be, tx, cred,
120  size, shift, &cred),
121  m0_be_alloc_stats_credit(a, &cred)),
122  (M0_BE_OP_SYNC(op,
123  m0_be_free_aligned(a, tx, &op, *p)),
124  m0_be_alloc_stats_capture(a, tx)));
125  *p = NULL;
126  }
127 }
128 
129 static void be_ut_alloc_thread(int index)
130 {
131  struct be_ut_alloc_thread_state *ts = &be_ut_ts[index];
132  struct m0_be_allocator *a;
133  uint64_t seed = index;
134  int i;
135  int j;
136 
138  M0_UT_ASSERT(a != NULL);
139  M0_SET_ARR0(ts->ats_ptr);
140  for (j = 0; j < ts->ats_nr; ++j) {
141  i = m0_rnd64(&seed) % ARRAY_SIZE(ts->ats_ptr);
142  be_ut_alloc_ptr_handle(a, &ts->ats_ptr[i], &seed);
143  }
144  for (i = 0; i < BE_UT_ALLOC_PTR_NR; ++i) {
145  if (ts->ats_ptr[i] != NULL) {
146  be_ut_alloc_ptr_handle(a, &ts->ats_ptr[i], &seed);
147  }
148  }
150 }
151 
152 static void be_ut_alloc_mt(int nr)
153 {
156  int rc;
157  int i;
158 
160  for (i = 0; i < nr; ++i) {
161  be_ut_ts[i].ats_nr = nr == 1 ? BE_UT_ALLOC_NR :
163  }
164 
168  for (i = 0; i < nr; ++i) {
169  rc = M0_THREAD_INIT(&be_ut_ts[i].ats_thread, int, NULL,
171  "#%dbe_ut_alloc", i);
172  M0_UT_ASSERT(rc == 0);
173  }
174  for (i = 0; i < nr; ++i) {
175  m0_thread_join(&be_ut_ts[i].ats_thread);
176  m0_thread_fini(&be_ut_ts[i].ats_thread);
177  }
181  M0_SET0(ut_be);
182 }
183 
184 M0_INTERNAL void m0_be_ut_alloc_multiple(void)
185 {
186  be_ut_alloc_mt(1);
187 }
188 
189 M0_INTERNAL void m0_be_ut_alloc_concurrent(void)
190 {
192 }
193 
195  enum m0_be_allocator_op optype,
196  const char *optype_str,
198  unsigned shift)
199 {
200  struct m0_be_tx_credit cred = {};
201 
202  m0_be_allocator_credit(a, optype, size, shift, &cred);
203  M0_LOG(M0_INFO,
204  "m0_be_allocator_credit(): "
205  "optype = %d (%s), size = %" PRIi64 ", shift = %d, "
206  "credit = "BETXCR_F,
207  optype, optype_str, size, shift, BETXCR_P(&cred));
208 }
209 
210 M0_INTERNAL void m0_be_ut_alloc_info(void)
211 {
212  struct m0_be_allocator *a;
213  struct m0_be_ut_seg ut_seg;
215  unsigned shift;
216 
221 
222  be_ut_alloc_credit_log(a, M0_BAO_CREATE, "create", 0, 0);
223  be_ut_alloc_credit_log(a, M0_BAO_DESTROY, "destroy", 0, 0);
224  be_ut_alloc_credit_log(a, M0_BAO_FREE, "free", 0, 0);
225  be_ut_alloc_credit_log(a, M0_BAO_FREE_ALIGNED, "free_aligned", 0, 0);
226 
227  for (size = 1; size <= 0x1000; size *= 4)
228  be_ut_alloc_credit_log(a, M0_BAO_ALLOC, "alloc", size, 0);
229  for (shift = 0; shift <= 12; shift += 1) {
230  be_ut_alloc_credit_log(a, M0_BAO_ALLOC_ALIGNED, "alloc_aligned",
231  0x100, shift);
232  }
233 
238 }
239 
240 /* segment and memory allocation sizes to test */
241 enum {
248 };
249 
250 static void be_ut_alloc_oom_case(struct m0_be_allocator *a,
251  m0_bcount_t alloc_size)
252 {
253  uint64_t ptrs_nr_max = a->ba_seg->bs_size / alloc_size + 1;
254  uint64_t ptrs_nr = 0;
255  uint64_t i;
256  void **ptrs;
257 
258  M0_ALLOC_ARR(ptrs, ptrs_nr_max);
259  M0_UT_ASSERT(ptrs != NULL);
260 
261  while (true) {
262  M0_UT_ASSERT(ptrs_nr < ptrs_nr_max);
264  m0_be_allocator_credit(a, M0_BAO_ALLOC, alloc_size, 0, &cred),
265  M0_BE_OP_SYNC(op, m0_be_alloc(a, tx, &op,
266  &ptrs[ptrs_nr], alloc_size)));
267  if (ptrs[ptrs_nr] == NULL)
268  break;
269 
270  ++ptrs_nr;
271  }
272 
273  M0_UT_ASSERT(ptrs_nr > 1);
274 
275  for (i = 0; i < ptrs_nr; ++i) {
277  m0_be_allocator_credit(a, M0_BAO_FREE, 0, 0, &cred),
278  M0_BE_OP_SYNC(op, m0_be_free(a, tx, &op, ptrs[i])));
279  }
280 
281  m0_free(ptrs);
282 }
283 
284 M0_INTERNAL void m0_be_ut_alloc_oom(void)
285 {
286  struct m0_be_allocator *a;
287  struct m0_be_ut_seg ut_seg;
288  int seg_size_start;
289  int seg_step;
290  int alloc_step;
291 
293 
295  seg_size_start = m0_be_seg_reserved(ut_seg.bus_seg) +
298 
299  for (seg_step = 0; seg_step < BE_UT_OOM_SEG_STEP_NR; ++seg_step) {
301  m0_round_up(seg_size_start +
302  seg_step * BE_UT_OOM_SEG_STEP,
303  m0_pagesize_get()));
306 
307  for (alloc_step = 0; alloc_step < BE_UT_OOM_ALLOC_STEP_NR;
308  ++alloc_step) {
310  alloc_step * BE_UT_OOM_ALLOC_STEP);
311  }
314  }
317 }
318 
319 M0_INTERNAL void m0_be_ut_alloc_spare(void)
320 {
321  struct {
322  bool do_free;
323  uint64_t zonemask;
324  bool should_fail;
325  int fi;
326  } scenario[] = {
327  { false, M0_BITS(M0_BAP_NORMAL), false, 0 },
328  { false, M0_BITS(M0_BAP_NORMAL), true , 0 },
329  { true, M0_BITS(M0_BAP_NORMAL), false, 0 },
330  { false, M0_BITS(M0_BAP_NORMAL), false, 0 },
331  { false, M0_BITS(M0_BAP_REPAIR), false, 0 },
332  { false, M0_BITS(M0_BAP_NORMAL), true, 0 },
333  { true, M0_BITS(M0_BAP_NORMAL), false, 3 },
334  { true, M0_BITS(M0_BAP_REPAIR), false, 4 }
335  };
336  struct m0_be_ut_backend ut_be = {};
337  struct m0_be_ut_seg ut_seg;
338  struct m0_be_allocator *a;
340  void *ptrs[ARRAY_SIZE(scenario)] = {};
341  struct m0_be_allocator_stats stats_before = {};
342  struct m0_be_allocator_stats stats_after = {};
343  int i;
344 
345  M0_ENTRY();
346 
348 
349  /* Reserve 50% for M0_BAP_REPAIR zone. */
350  m0_fi_enable_once("be_ut_seg_allocator_initfini", "repair_zone_50");
354  M0_UT_ASSERT(a != NULL);
355 
357 
358  for (i = 0 ; i < ARRAY_SIZE(scenario) ; ++i) {
359  m0_be_alloc_stats(a, &stats_before);
360 
361  if (scenario[i].do_free) {
362  M0_LOG(M0_INFO,
363  "ut_alloc_spare #%d do free ptrs[%d] %p",
364  i, scenario[i].fi, ptrs[scenario[i].fi]);
365 
366  M0_BE_UT_TRANSACT(&ut_be, tx, cred,
367  m0_be_allocator_credit(a, M0_BAO_FREE, 0, 0, &cred),
368  M0_BE_OP_SYNC(op, m0_be_free(a, tx, &op,
369  ptrs[scenario[i].fi])));
370  } else {
371  M0_BE_UT_TRANSACT(&ut_be, tx, cred,
374  &cred),
375  m0_be_alloc_stats_credit(a, &cred)),
376  (M0_BE_OP_SYNC(op,
377  m0_be_alloc_aligned(a, tx, &op,
378  &ptrs[i], size,
380  scenario[i].zonemask)),
381  m0_be_alloc_stats_capture(a, tx)));
382  M0_UT_ASSERT(
383  (ptrs[i] == NULL) == scenario[i].should_fail);
384  }
385  m0_be_alloc_stats(a, &stats_after);
386 
388  (stats_before.bas_space_used == stats_after.bas_space_used) &&
389  (stats_before.bas_space_free == stats_after.bas_space_free)));
390  }
391 
393  M0_SET0(&ut_be);
394  M0_LOG(M0_INFO, "m0_be_ut_alloc_spare OK");
395 
396  M0_LEAVE();
397 }
398 
399 
400 #undef M0_TRACE_SUBSYSTEM
401 
402 /*
403  * Local variables:
404  * c-indentation-style: "K&R"
405  * c-basic-offset: 8
406  * tab-width: 8
407  * fill-column: 80
408  * scroll-step: 1
409  * End:
410  */
411 /*
412  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
413  */
void m0_be_ut_seg_fini(struct m0_be_ut_seg *ut_seg)
Definition: stubs.c:267
static struct m0_addb2_philter p
Definition: consumer.c:40
static size_t nr
Definition: dump.c:1505
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
struct m0t1fs_fsync_interactions fi
Definition: fsync.c:55
#define BETXCR_F
Definition: tx_credit.h:102
M0_INTERNAL void m0_be_ut_alloc_init_fini(void)
Definition: alloc.c:62
#define NULL
Definition: misc.h:38
static bool m0_addr_is_aligned(const void *addr, unsigned shift)
Definition: memory.h:107
#define ergo(a, b)
Definition: misc.h:293
int m0_thread_join(struct m0_thread *q)
Definition: kthread.c:169
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
M0_INTERNAL void m0_be_alloc_stats_capture(struct m0_be_allocator *a, struct m0_be_tx *tx)
Definition: alloc.c:1175
struct m0_be_seg * bus_seg
Definition: helper.h:119
m0_bcount_t bs_size
Definition: seg.h:69
Allocator.
Definition: alloc.h:132
M0_INTERNAL void m0_be_ut_alloc_spare(void)
Definition: alloc.c:319
#define M0_BE_OP_SYNC(op_obj, action)
Definition: op.h:190
M0_INTERNAL void m0_be_alloc_stats(struct m0_be_allocator *a, struct m0_be_allocator_stats *out)
Definition: alloc.c:1159
Allocator statistics.
Definition: alloc.h:114
struct m0_be_ut_seg ut_seg
Definition: ad.c:73
void m0_be_ut_seg_init(struct m0_be_ut_seg *ut_seg, struct m0_be_ut_backend *ut_be, m0_bcount_t size)
Definition: stubs.c:256
#define M0_BITS(...)
Definition: misc.h:236
uint64_t m0_bcount_t
Definition: types.h:77
#define M0_THREAD_INIT(thread, TYPE, init, func, arg, namefmt,...)
Definition: thread.h:139
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL void m0_be_alloc_aligned(struct m0_be_allocator *a, struct m0_be_tx *tx, struct m0_be_op *op, void **ptr, m0_bcount_t size, unsigned shift, uint64_t zonemask)
Definition: alloc.c:1020
M0_INTERNAL uint64_t m0_round_up(uint64_t val, uint64_t size)
Definition: misc.c:181
m0_bcount_t bas_space_used
Definition: alloc.h:117
void * ats_ptr[BE_UT_ALLOC_PTR_NR]
Definition: alloc.c:53
op
Definition: libdemo.c:64
void m0_be_ut_seg_allocator_fini(struct m0_be_ut_seg *ut_seg, struct m0_be_ut_backend *ut_be)
Definition: stubs.c:251
#define M0_ENTRY(...)
Definition: trace.h:170
struct m0_thread ats_thread
Definition: alloc.c:51
M0_INTERNAL int m0_pagesize_get(void)
Definition: memory.c:233
static void be_ut_alloc_mt(int nr)
Definition: alloc.c:152
static struct m0_be_ut_seg be_ut_alloc_seg
Definition: alloc.c:59
M0_INTERNAL m0_bcount_t m0_be_seg_reserved(const struct m0_be_seg *seg)
Definition: seg.c:430
int i
Definition: dir.c:1033
#define M0_SET_ARR0(arr)
Definition: misc.h:72
M0_INTERNAL void m0_be_alloc_stats_credit(struct m0_be_allocator *a, struct m0_be_tx_credit *accum)
Definition: alloc.c:1168
static struct m0_be_ut_backend be_ut_alloc_backend
Definition: alloc.c:58
struct m0_be_ut_backend ut_be
Definition: ad.c:72
Definition: trace.h:482
scenario
Definition: ub.c:58
M0_INTERNAL struct m0_be_allocator * m0_be_seg_allocator(struct m0_be_seg *seg)
Definition: stubs.c:113
M0_INTERNAL void m0_be_alloc(struct m0_be_allocator *a, struct m0_be_tx *tx, struct m0_be_op *op, void **ptr, m0_bcount_t size)
Definition: alloc.c:1091
void m0_thread_fini(struct m0_thread *q)
Definition: thread.c:92
static struct be_ut_alloc_thread_state be_ut_ts[BE_UT_ALLOC_THR_NR]
Definition: alloc.c:60
m0_be_allocator_op
Definition: alloc.h:196
void m0_be_ut_backend_init(struct m0_be_ut_backend *ut_be)
Definition: stubs.c:238
void m0_be_ut_seg_allocator_init(struct m0_be_ut_seg *ut_seg, struct m0_be_ut_backend *ut_be)
Definition: stubs.c:246
static void be_ut_alloc_credit_log(struct m0_be_allocator *a, enum m0_be_allocator_op optype, const char *optype_str, m0_bcount_t size, unsigned shift)
Definition: alloc.c:194
M0_INTERNAL void m0_be_ut_alloc_create_destroy(void)
Definition: alloc.c:78
#define BETXCR_P(c)
Definition: tx_credit.h:113
Definition: seg.h:66
M0_INTERNAL void m0_be_ut_alloc_concurrent(void)
Definition: alloc.c:189
static void be_ut_alloc_oom_case(struct m0_be_allocator *a, m0_bcount_t alloc_size)
Definition: alloc.c:250
struct m0_be_seg * ba_seg
Definition: alloc.h:138
M0_INTERNAL void m0_be_ut_alloc_info(void)
Definition: alloc.c:210
M0_INTERNAL uint64_t m0_rnd64(uint64_t *seed)
Definition: misc.c:100
M0_INTERNAL void m0_be_free(struct m0_be_allocator *a, struct m0_be_tx *tx, struct m0_be_op *op, void *ptr)
Definition: alloc.c:1151
#define M0_BE_UT_TRANSACT(__ut_be, __tx, __cred, __credit_func, __action_func)
Definition: helper.h:159
M0_INTERNAL void m0_be_ut_alloc_multiple(void)
Definition: alloc.c:184
#define PRIi64
Definition: types.h:59
static void be_ut_alloc_ptr_handle(struct m0_be_allocator *a, void **p, uint64_t *seed)
Definition: alloc.c:94
m0_bcount_t size
Definition: di.c:39
static void be_ut_alloc_thread(int index)
Definition: alloc.c:129
void m0_be_ut_backend_fini(struct m0_be_ut_backend *ut_be)
Definition: stubs.c:242
M0_INTERNAL void m0_be_free_aligned(struct m0_be_allocator *a, struct m0_be_tx *tx, struct m0_be_op *op, void *ptr)
Definition: alloc.c:1101
static void m0_fi_enable_once(const char *func, const char *tag)
Definition: finject.h:301
static struct m0_be_seg * seg
Definition: btree.c:40
M0_INTERNAL void m0_be_ut_alloc_oom(void)
Definition: alloc.c:284
M0_INTERNAL int m0_be_allocator_init(struct m0_be_allocator *a, struct m0_be_seg *seg)
Definition: alloc.c:719
M0_INTERNAL void m0_be_allocator_credit(struct m0_be_allocator *a, enum m0_be_allocator_op optype, m0_bcount_t size, unsigned shift, struct m0_be_tx_credit *accum)
Definition: alloc.c:900
void m0_free(void *data)
Definition: memory.c:146
m0_bcount_t bas_space_free
Definition: alloc.h:118
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
#define M0_UT_ASSERT(a)
Definition: ut.h:46
void m0_be_ut_backend_thread_exit(struct m0_be_ut_backend *ut_be)
Definition: stubs.c:282
M0_INTERNAL void m0_be_allocator_fini(struct m0_be_allocator *a)
Definition: alloc.c:745