Motr  M0
balloc.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2012-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 #include <stdlib.h> /* srand, rand */
24 #include <errno.h>
25 #include <sys/time.h>
26 #include <err.h>
27 
28 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_BALLOC
29 #include "lib/trace.h"
30 #include "lib/arith.h" /* M0_3WAY, m0_uint128 */
31 #include "lib/misc.h" /* M0_SET0 */
32 #include "lib/assert.h"
33 #include "lib/memory.h"
34 #include "lib/thread.h"
35 #include "lib/getopts.h"
36 #include "dtm/dtm.h" /* m0_dtx */
37 #include "motr/magic.h"
38 #include "ut/ut.h"
39 #include "ut/be.h"
40 #include "balloc/balloc.h"
41 #include "be/ut/helper.h"
42 #include "stob/ad.h" /* m0_stob_ad_spares_calc */
43 
44 #define BALLOC_DBNAME "./__balloc_db"
45 
46 #define GROUP_SIZE (BALLOC_DEF_CONTAINER_SIZE / (BALLOC_DEF_BLOCKS_PER_GROUP * \
47  (1 << BALLOC_DEF_BLOCK_SHIFT)))
48 
49 #define BALLOC_DEBUG
50 
51 static const int MAX = 10;
54 
58 };
59 
60 bool balloc_ut_invariant(struct m0_balloc *motr_balloc,
61  struct m0_ext alloc_ext,
62  int balloc_invariant_flag)
63 {
64  m0_bcount_t len = m0_ext_length(&alloc_ext);
66 
67  group = alloc_ext.e_start >> motr_balloc->cb_sb.bsb_gsbits;
68 
69  if (motr_balloc->cb_sb.bsb_magic != M0_BALLOC_SB_MAGIC)
70  return false;
71 
72  switch (balloc_invariant_flag) {
73  case INVAR_ALLOC:
74  prev_free_blocks -= len;
76  break;
77  case INVAR_FREE:
78  prev_free_blocks += len;
80  break;
81  default:
82  return false;
83  }
84 
85  return motr_balloc->cb_group_info[group].bgi_normal.bzp_freeblocks ==
87  motr_balloc->cb_sb.bsb_freeblocks ==
89 }
90 
100  bool is_reserve)
101 {
102  struct m0_sm_group *grp;
103  struct m0_balloc *motr_balloc;
104  struct m0_dtx dtx = {};
105  struct m0_be_tx *tx = &dtx.tx_betx;
106  struct m0_be_tx_credit cred;
107  struct m0_ext ext[MAX];
108  struct m0_ext tmp = {};
109  m0_bcount_t count = 539;
110  m0_bcount_t spare_size;
111  int i = 0;
112  int rc;
113  time_t now;
114 
115  time(&now);
116  srand(now);
117 
119  rc = m0_balloc_create(0, seg, grp, &motr_balloc, &M0_FID_INIT(0, 1));
120  M0_UT_ASSERT(rc == 0);
121 
122  rc = motr_balloc->cb_ballroom.ab_ops->bo_init
123  (&motr_balloc->cb_ballroom, seg, BALLOC_DEF_BLOCK_SHIFT,
126 
127  if (rc != 0)
128  goto out;
129 
130  prev_free_blocks = motr_balloc->cb_sb.bsb_freeblocks;
132 
133  for (i = 0; i < GROUP_SIZE; ++i) {
136  }
137 
138  for (i = 0; i < MAX; ++i) {
139  count = rand() % 1500 + 1;
140 
141  cred = M0_BE_TX_CREDIT(0, 0);
142  motr_balloc->cb_ballroom.ab_ops->bo_alloc_credit(
143  &motr_balloc->cb_ballroom, 1, &cred);
144  m0_ut_be_tx_begin(tx, ut_be, &cred);
145 
146  if (is_reserve) {
147  tmp.e_start = tmp.e_end;
148  tmp.e_end = tmp.e_start + count;
149  rc = motr_balloc->cb_ballroom.ab_ops->bo_reserve_extent(
150  &motr_balloc->cb_ballroom, tx, &tmp,
152  } else {
153  rc = motr_balloc->cb_ballroom.ab_ops->bo_alloc(
154  &motr_balloc->cb_ballroom, &dtx,
156  }
157 
158  M0_UT_ASSERT(rc == 0);
159  if (rc < 0) {
160  M0_LOG(M0_ERROR, "Error in allocation");
161  return rc;
162  }
163 
164  ext[i] = tmp;
165 
166  /* The result extent length should be less than or equal to the
167  * requested length. */
168  M0_UT_ASSERT(m0_ext_length(&ext[i]) <= count);
169  M0_UT_ASSERT(balloc_ut_invariant(motr_balloc, ext[i],
170  INVAR_ALLOC));
171  M0_LOG(M0_INFO, "%3d:rc=%d: req=%5d, got=%5d: "
172  "[%08llx,%08llx)=[%8llu,%8llu)",
173  i, rc, (int)count,
174  (int)m0_ext_length(&ext[i]),
175  (unsigned long long)ext[i].e_start,
176  (unsigned long long)ext[i].e_end,
177  (unsigned long long)ext[i].e_start,
178  (unsigned long long)ext[i].e_end);
179  m0_ut_be_tx_end(tx);
180  }
181 
182  spare_size = m0_stob_ad_spares_calc(motr_balloc->cb_sb.bsb_groupsize);
183 
184  for (i = 0; i < motr_balloc->cb_sb.bsb_groupcount && rc == 0; ++i) {
186  motr_balloc, i);
187  if (grp) {
189  rc = m0_balloc_load_extents(motr_balloc, grp);
190  if (rc == 0)
192  "balloc ut", grp);
195  }
196  }
197 
198  /* randomize the array */
199  for (i = 0; i < MAX; ++i) {
200  int a;
201  int b;
202  a = rand() % MAX;
203  b = rand() % MAX;
204  M0_SWAP(ext[a], ext[b]);
205  }
206 
207  for (i = 0; i < MAX && rc == 0; ++i) {
208  cred = M0_BE_TX_CREDIT(0, 0);
209  motr_balloc->cb_ballroom.ab_ops->bo_free_credit(
210  &motr_balloc->cb_ballroom, 1, &cred);
211  m0_ut_be_tx_begin(tx, ut_be, &cred);
212 
213  rc = motr_balloc->cb_ballroom.ab_ops->bo_free(
214  &motr_balloc->cb_ballroom, &dtx, &ext[i]);
215 
216  M0_UT_ASSERT(rc == 0);
217  if (rc < 0) {
218  M0_LOG(M0_ERROR, "Error during free for size %5d",
219  (int)m0_ext_length(&ext[i]));
220  return rc;
221  }
222 
223  M0_UT_ASSERT(balloc_ut_invariant(motr_balloc, ext[i],
224  INVAR_FREE));
225  M0_LOG(M0_INFO, "%3d:rc=%d: freed= %5d: "
226  "[%08llx,%08llx)=[%8llu,%8llu)",
227  i, rc, (int)m0_ext_length(&ext[i]),
228  (unsigned long long)ext[i].e_start,
229  (unsigned long long)ext[i].e_end,
230  (unsigned long long)ext[i].e_start,
231  (unsigned long long)ext[i].e_end);
232  m0_ut_be_tx_end(tx);
233  }
234 
236  if (motr_balloc->cb_sb.bsb_freeblocks != prev_free_blocks) {
237  M0_LOG(M0_ERROR, "Size mismatch during block reclaim");
238  rc = -EINVAL;
239  }
240 
241  for (i = 0; i < motr_balloc->cb_sb.bsb_groupcount && rc == 0; ++i) {
243  motr_balloc, i);
244 
245  if (grp) {
247  rc = m0_balloc_load_extents(motr_balloc, grp);
248  if (rc == 0)
250  "balloc ut", grp);
251  M0_UT_ASSERT(grp->bgi_normal.bzp_freeblocks ==
252  motr_balloc->cb_sb.bsb_groupsize -
253  spare_size);
256  }
257  }
258 
259  motr_balloc->cb_ballroom.ab_ops->bo_fini(&motr_balloc->cb_ballroom);
260 
261 out:
263 
264  M0_LOG(M0_INFO, "done. status = %d", rc);
265  return rc;
266 }
267 
269 {
270  struct m0_be_ut_backend ut_be;
271  struct m0_be_ut_seg ut_seg;
272  int rc;
273 
274  M0_SET0(&ut_be);
275  /* Init BE */
277  m0_be_ut_seg_init(&ut_seg, &ut_be, 1ULL << 24);
279  M0_UT_ASSERT(rc == 0);
280 
283 }
284 
286 {
287  struct m0_be_ut_backend ut_be;
288  struct m0_be_ut_seg ut_seg;
289  int rc;
290 
291  M0_SET0(&ut_be);
292  /* Init BE */
294  m0_be_ut_seg_init(&ut_seg, &ut_be, 1ULL << 24);
296  M0_UT_ASSERT(rc == 0);
297 
300 }
301 
303  .ts_name = "balloc-ut",
304  .ts_init = NULL,
305  .ts_fini = NULL,
306  .ts_tests = {
307  { "balloc", test_balloc},
308  { "reserve blocks for extmap", test_reserve_extent},
309  { NULL, NULL }
310  }
311 };
312 
313 /*
314  * Local variables:
315  * c-indentation-style: "K&R"
316  * c-basic-offset: 8
317  * tab-width: 8
318  * fill-column: 80
319  * scroll-step: 1
320  * End:
321  */
void m0_be_ut_seg_fini(struct m0_be_ut_seg *ut_seg)
Definition: stubs.c:267
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
Definition: dtm.h:554
M0_INTERNAL m0_bcount_t m0_ext_length(const struct m0_ext *ext)
Definition: ext.c:42
struct m0_ut_suite balloc_ut
Definition: balloc.c:302
m0_bcount_t bsb_freeblocks
Definition: balloc.h:181
int(* bo_alloc)(struct m0_ad_balloc *ballroom, struct m0_dtx *dtx, m0_bcount_t count, struct m0_ext *out, uint64_t alloc_zone)
Definition: ad.h:85
m0_bindex_t e_end
Definition: ext.h:40
struct m0_ad_balloc cb_ballroom
Definition: balloc.h:231
M0_INTERNAL int m0_balloc_load_extents(struct m0_balloc *cb, struct m0_balloc_group_info *grp)
Definition: balloc.c:1273
#define NULL
Definition: misc.h:38
void test_balloc()
Definition: balloc.c:268
static const int MAX
Definition: balloc.c:51
int test_balloc_ut_ops(struct m0_be_ut_backend *ut_be, struct m0_be_seg *seg, bool is_reserve)
Definition: balloc.c:99
static struct m0_sm_group * grp
Definition: bytecount.c:38
#define GROUP_SIZE
Definition: balloc.c:46
#define M0_LOG(level,...)
Definition: trace.h:167
m0_bindex_t e_start
Definition: ext.h:96
m0_bcount_t bzp_freeblocks
Definition: balloc.h:134
struct m0_balloc_group_info * cb_group_info
Definition: balloc.h:248
struct m0_be_seg * bus_seg
Definition: helper.h:119
#define M0_FID_INIT(container, key)
Definition: fid.h:84
int(* bo_init)(struct m0_ad_balloc *ballroom, struct m0_be_seg *db, uint32_t bshift, m0_bcount_t container_size, m0_bcount_t blocks_per_group, m0_bcount_t spare_blocks_per_group)
Definition: ad.h:77
M0_INTERNAL void m0_ut_be_tx_end(struct m0_be_tx *tx)
Definition: be.c:82
const struct m0_ad_balloc_ops * ab_ops
Definition: ad.h:65
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
uint64_t m0_bcount_t
Definition: types.h:77
M0_INTERNAL int m0_balloc_create(uint64_t cid, struct m0_be_seg *seg, struct m0_sm_group *grp, struct m0_balloc **out, const struct m0_fid *fid)
Definition: balloc.c:3015
#define M0_SET0(obj)
Definition: misc.h:64
Definition: ut.h:77
#define M0_SWAP(v0, v1)
Definition: arith.h:207
static m0_bcount_t count
Definition: xcode.c:167
bool balloc_ut_invariant(struct m0_balloc *motr_balloc, struct m0_ext alloc_ext, int balloc_invariant_flag)
Definition: balloc.c:60
m0_bcount_t bsb_groupsize
Definition: balloc.h:187
#define M0_BE_TX_CREDIT(nr, size)
Definition: tx_credit.h:94
int i
Definition: dir.c:1033
struct m0_be_ut_backend ut_be
Definition: ad.c:72
M0_INTERNAL void m0_balloc_lock_group(struct m0_balloc_group_info *grp)
Definition: balloc.c:324
Definition: trace.h:482
M0_INTERNAL void m0_ut_be_tx_begin(struct m0_be_tx *tx, struct m0_be_ut_backend *ut_be, struct m0_be_tx_credit *cred)
Definition: be.c:56
struct m0_balloc_zone_param bgi_normal
Definition: balloc.h:156
M0_INTERNAL void m0_balloc_unlock_group(struct m0_balloc_group_info *grp)
Definition: balloc.c:334
int rand(void)
void m0_be_ut_backend_init(struct m0_be_ut_backend *ut_be)
Definition: stubs.c:238
M0_INTERNAL void m0_balloc_debug_dump_group_extent(const char *tag, struct m0_balloc_group_info *grp)
Definition: balloc.c:192
void(* bo_free_credit)(const struct m0_ad_balloc *ballroom, int nr, struct m0_be_tx_credit *accum)
Definition: ad.h:94
struct m0_sm_group * m0_be_ut_backend_sm_group_lookup(struct m0_be_ut_backend *ut_be)
Definition: stubs.c:277
static void group(void)
Definition: sm.c:386
uint32_t bsb_gsbits
Definition: balloc.h:189
void test_reserve_extent()
Definition: balloc.c:285
int(* bo_free)(struct m0_ad_balloc *ballroom, struct m0_dtx *dtx, struct m0_ext *ext)
Definition: ad.h:90
void(* bo_fini)(struct m0_ad_balloc *ballroom)
Definition: ad.h:82
Definition: seg.h:66
uint64_t bsb_magic
Definition: balloc.h:175
balloc_invariant_enum
Definition: balloc.c:55
m0_bcount_t bsb_groupcount
Definition: balloc.h:190
M0_INTERNAL int m0_balloc_release_extents(struct m0_balloc_group_info *grp)
Definition: balloc.c:312
const char * ts_name
Definition: ut.h:99
Definition: ext.h:37
m0_bindex_t e_start
Definition: ext.h:39
struct m0_be_tx tx_betx
Definition: dtm.h:559
static m0_bcount_t prev_free_blocks
Definition: balloc.c:52
int(* bo_reserve_extent)(struct m0_ad_balloc *ballroom, struct m0_be_tx *tx, struct m0_ext *ext, uint64_t alloc_zone)
Definition: ad.h:104
m0_bindex_t e_end
Definition: ext.h:97
M0_INTERNAL m0_bcount_t m0_stob_ad_spares_calc(m0_bcount_t grp_blocks)
Definition: ad.c:313
void m0_be_ut_backend_fini(struct m0_be_ut_backend *ut_be)
Definition: stubs.c:242
static struct m0_be_seg * seg
Definition: btree.c:40
struct m0_balloc_super_block cb_sb
Definition: balloc.h:227
m0_bcount_t * prev_group_info_free_blocks
Definition: balloc.c:53
#define out(...)
Definition: gen.c:41
M0_INTERNAL struct m0_balloc_group_info * m0_balloc_gn2info(struct m0_balloc *cb, m0_bindex_t groupno)
Definition: balloc.c:260
void m0_free(void *data)
Definition: memory.c:146
void(* bo_alloc_credit)(const struct m0_ad_balloc *ballroom, int nr, struct m0_be_tx_credit *accum)
Definition: ad.h:92
int32_t rc
Definition: trigger_fop.h:47
#define M0_UT_ASSERT(a)
Definition: ut.h:46
Definition: tx.h:280