Motr  M0
stob.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2014-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 "ut/stob.h"
27 
28 #include "lib/misc.h" /* ARRAY_SIZE */
29 #include "lib/mutex.h" /* m0_mutex */
30 #include "lib/memory.h" /* M0_ALLOC_PTR */
31 #include "lib/errno.h" /* ENOMEM */
32 
33 #include "module/instance.h" /* m0_get */
34 #include "be/tx_credit.h" /* m0_be_tx_credit */
35 #include "be/ut/helper.h" /* m0_be_ut_backend_sm_group_lookup */
36 #include "dtm/dtm.h" /* m0_dtx */
37 
38 #include "stob/domain.h" /* m0_stob_domain */
39 #include "stob/stob.h" /* m0_stob_find */
40 
47 enum {
49 };
50 
53  uint64_t usm_stob_key;
55 };
56 
57 static int level_ut_stob_enter(struct m0_module *module);
58 static void level_ut_stob_leave(struct m0_module *module);
59 
61  [M0_LEVEL_UT_STOB] = {
62  .ml_name = "stob UT helper is initialised",
63  .ml_enter = level_ut_stob_enter,
64  .ml_leave = level_ut_stob_leave,
65  },
66 };
68 
69 /* linux stob domain configuratin */
70 static const char *ut_stob_domain_location = "linuxstob:./ut_stob";
71 static const uint64_t ut_stob_domain_key = 0x10000;
72 static const char *ut_stob_domain_init_cfg = "";
73 static const char *ut_stob_domain_create_cfg = "";
74 
75 static int level_ut_stob_enter(struct m0_module *module)
76 {
77  return m0_ut_stob_init();
78 }
79 
80 static void level_ut_stob_leave(struct m0_module *module)
81 {
83 }
84 
85 static struct ut_stob_module *ut_stob_module_get(void)
86 {
88  int rc;
89 
90  m0_mutex_lock(&usm->usm_lock);
91  if (usm->usm_dom_linux == NULL) {
96  &usm->usm_dom_linux);
97  if (rc != 0)
98  M0_LOG(M0_WARN, "rc = %d", rc);
99  } else {
100  rc = 0;
101  }
102  m0_mutex_unlock(&usm->usm_lock);
103  return rc == 0 ? usm : NULL;
104 }
105 
106 M0_INTERNAL int m0_ut_stob_init(void)
107 {
108  struct ut_stob_module *usm;
109  int rc;
110 
111  M0_ALLOC_PTR(usm);
112  rc = usm == NULL ? -ENOMEM : 0;
113  if (usm != NULL) {
114  m0_mutex_init(&usm->usm_lock);
116  usm->usm_dom_linux = NULL;
118  }
119  return rc;
120 }
121 M0_EXPORTED(m0_ut_stob_init);
122 
123 M0_INTERNAL void m0_ut_stob_fini(void)
124 {
126 
127  if (usm->usm_dom_linux != NULL)
129  m0_mutex_fini(&usm->usm_lock);
130  m0_free(usm);
131 }
132 M0_EXPORTED(m0_ut_stob_fini);
133 
134 static struct m0_stob *
135 ut_stob_linux_create_by_key(uint64_t stob_key, char *stob_create_cfg)
136 {
137  struct ut_stob_module *usm = ut_stob_module_get();
138  struct m0_stob *stob;
139  int rc;
140  struct m0_stob_id stob_id;
141 
142  m0_mutex_lock(&usm->usm_lock);
143 
144  m0_stob_id_make(0, stob_key, &usm->usm_dom_linux->sd_id, &stob_id);
145  rc = m0_stob_find(&stob_id, &stob);
146  M0_ASSERT(rc == 0);
148  M0_ASSERT_INFO(rc == 0, "rc = %d", rc);
150  m0_stob_create(stob, NULL, stob_create_cfg) : 0;
151  M0_ASSERT_INFO(rc == 0, "rc = %d", rc);
153 
154  m0_mutex_unlock(&usm->usm_lock);
155  return stob;
156 }
157 
158 static uint64_t ut_stob_linux_key_alloc(void)
159 {
160  struct ut_stob_module *usm = ut_stob_module_get();
161  uint64_t stob_key;
162 
163  m0_mutex_lock(&usm->usm_lock);
164  stob_key = usm->usm_stob_key++;
165  m0_mutex_unlock(&usm->usm_lock);
166  return stob_key;
167 }
168 
169 M0_INTERNAL struct m0_stob *m0_ut_stob_linux_get(void)
170 {
172 }
173 
174 M0_INTERNAL struct m0_stob *m0_ut_stob_linux_get_by_key(uint64_t stob_key)
175 {
176  return ut_stob_linux_create_by_key(stob_key, NULL);
177 }
178 
179 M0_INTERNAL struct m0_stob *m0_ut_stob_linux_create(char *stob_create_cfg)
180 {
182  stob_create_cfg);
183 }
184 
185 M0_INTERNAL void m0_ut_stob_put(struct m0_stob *stob, bool destroy)
186 {
187  struct ut_stob_module *usm = ut_stob_module_get();
188 
189  m0_mutex_lock(&usm->usm_lock);
190  m0_ut_stob_close(stob, destroy);
191  m0_mutex_unlock(&usm->usm_lock);
192 }
193 
194 static bool ut_stob_use_dtx(struct m0_stob_domain *dom)
195 {
197 
198  return !M0_IN(type_id, (m0_stob_type_id_by_name("nullstob"),
199  m0_stob_type_id_by_name("linuxstob")));
200 }
201 
202 M0_INTERNAL int m0_ut_stob_create(struct m0_stob *stob, const char *str_cfg,
203  struct m0_be_domain *be_dom)
204 {
205  struct m0_be_tx_credit cred = {};
207  struct m0_dtx *dtx = NULL;
208  bool use_dtx;
209  int rc;
210 
211  use_dtx = ut_stob_use_dtx(dom);
212  if (use_dtx) {
213  m0_stob_create_credit(dom, &cred);
214  dtx = m0_ut_dtx_open(&cred, be_dom);
215  }
216  rc = m0_stob_create(stob, dtx, str_cfg);
217  if (use_dtx)
218  m0_ut_dtx_close(dtx);
219  return rc;
220 }
221 
222 M0_INTERNAL int m0_ut_stob_destroy(struct m0_stob *stob,
223  struct m0_be_domain *be_dom)
224 {
225  struct m0_be_tx_credit cred = {};
226  struct m0_be_tx_credit accum;
227  struct m0_indexvec range;
228  struct m0_indexvec got;
229  struct m0_dtx *dtx = NULL;
230  bool use_dtx;
231  int rc;
232  int rc_c;
233 
235  rc = m0_indexvec_alloc(&range, 1);
236  M0_ASSERT(rc == 0);
237  range.iv_index[0] = 0;
238  range.iv_vec.v_count[0] = M0_BINDEX_MAX + 1;
239  if (use_dtx) {
240  rc = m0_indexvec_alloc(&got, 1);
241  M0_ASSERT(rc == 0);
242  do {
243  rc = m0_stob_punch_credit(stob, &range, &got, &cred);
244  M0_ASSERT(rc == 0);
245  range.iv_index[0] += got.iv_vec.v_count[0];
246  range.iv_vec.v_count[0] -= got.iv_vec.v_count[0];
247  rc_c = range.iv_vec.v_count[0] == 0 ? 0 : -EAGAIN;
248  dtx = m0_ut_dtx_open(&cred, be_dom);
249  rc = m0_stob_punch(stob, &got, dtx);
250  M0_ASSERT(rc == 0);
251  if (rc_c == 0) {
252  m0_stob_destroy_credit(stob, &accum);
253  m0_be_tx_credit_add(&cred, &accum);
254  rc = m0_stob_destroy(stob, dtx);
255  M0_ASSERT(rc == 0);
256  }
257  m0_ut_dtx_close(dtx);
258  } while (rc_c == -EAGAIN);
259  }
260  else {
261  /*
262  * m0_stob_punch() here is temporarily disabled.
263  * This is a quick fix that allows c/motr/+/18984 to land.
264  * On a jenkins node it returns -EFBIG for some reason.
265  */
266  /* rc = m0_stob_punch(stob, &range, dtx); */
267  /* M0_ASSERT(rc == 0); */
268  rc = m0_stob_destroy(stob, dtx);
269  M0_ASSERT(rc == 0);
270  }
271  return rc;
272 }
273 
274 M0_INTERNAL struct m0_stob *m0_ut_stob_open(struct m0_stob_domain *dom,
275  uint64_t stob_key,
276  const char *str_cfg)
277 {
278  struct m0_stob *stob;
279  int rc;
280  struct m0_stob_id stob_id;
281 
282  m0_stob_id_make(0, stob_key, &dom->sd_id, &stob_id);
283  rc = m0_stob_find(&stob_id, &stob);
284  M0_ASSERT(rc == 0);
286  M0_ASSERT_INFO(rc == 0, "rc = %d", rc);
288  m0_ut_stob_create(stob, str_cfg, NULL);
289  return stob;
290 }
291 
292 M0_INTERNAL void m0_ut_stob_close(struct m0_stob *stob, bool destroy)
293 {
294  if (destroy) {
296  } else {
297  m0_stob_put(stob);
298  }
299 }
300 
301 M0_INTERNAL int m0_ut_stob_create_by_stob_id(struct m0_stob_id *stob_id,
302  const char *str_cfg)
303 {
304  struct m0_stob *stob;
305  int rc;
306 
307  rc = m0_stob_find(stob_id, &stob);
308  if (rc == 0) {
310  m0_stob_locate(stob) : 0;
311  rc = rc ?: m0_ut_stob_create(stob, str_cfg, NULL);
312  m0_stob_put(stob);
313  }
314  return rc;
315 }
316 
317 M0_INTERNAL int m0_ut_stob_destroy_by_stob_id(struct m0_stob_id *stob_id)
318 {
319  struct m0_stob *stob;
320  int rc;
321 
322  rc = m0_stob_find(stob_id, &stob);
323  if (rc == 0) {
325  m0_stob_locate(stob) : 0;
327  if (rc != 0)
328  m0_stob_put(stob);
329  }
330  return rc;
331 }
332 
333 M0_INTERNAL struct m0_dtx *m0_ut_dtx_open(struct m0_be_tx_credit *cred,
334  struct m0_be_domain *be_dom)
335 {
336 #ifndef __KERNEL__
337  struct m0_sm_group *grp;
338  struct m0_dtx *dtx = NULL;
339  int rc;
340 
341  if (be_dom != NULL) {
342  struct m0_be_ut_backend *ut_be =
343  bob_of(be_dom, struct m0_be_ut_backend, but_dom,
345  M0_ALLOC_PTR(dtx);
346  M0_ASSERT(dtx != NULL);
348  m0_dtx_init(dtx, be_dom, grp);
349  m0_dtx_prep(dtx, cred);
350  rc = m0_dtx_open_sync(dtx);
351  M0_ASSERT_INFO(rc == 0, "rc = %d", rc);
352  }
353  return dtx;
354 #else
355  return NULL;
356 #endif
357 }
358 
359 M0_INTERNAL void m0_ut_dtx_close(struct m0_dtx *dtx)
360 {
361  int rc;
362 
363  if (dtx != NULL) {
364  rc = m0_dtx_done_sync(dtx);
365  M0_ASSERT_INFO(rc == 0, "rc = %d", rc);
366  m0_dtx_fini(dtx);
367  m0_free(dtx);
368  }
369 }
370 
373 #undef M0_TRACE_SUBSYSTEM
374 
375 /*
376  * Local variables:
377  * c-indentation-style: "K&R"
378  * c-basic-offset: 8
379  * tab-width: 8
380  * fill-column: 80
381  * scroll-step: 1
382  * End:
383  */
384 /*
385  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
386  */
M0_INTERNAL struct m0_stob_domain * m0_stob_dom_get(struct m0_stob *stob)
Definition: stob.c:338
uint64_t usm_stob_key
Definition: stob.c:53
Definition: dtm.h:554
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
M0_INTERNAL struct m0_stob * m0_ut_stob_open(struct m0_stob_domain *dom, uint64_t stob_key, const char *str_cfg)
Definition: stob.c:274
M0_INTERNAL int m0_indexvec_alloc(struct m0_indexvec *ivec, uint32_t len)
Definition: vec.c:532
#define NULL
Definition: misc.h:38
static uint64_t ut_stob_linux_key_alloc(void)
Definition: stob.c:158
M0_INTERNAL int m0_stob_locate(struct m0_stob *stob)
Definition: stob.c:128
M0_INTERNAL void m0_ut_stob_close(struct m0_stob *stob, bool destroy)
Definition: stob.c:292
static struct m0_sm_group * grp
Definition: bytecount.c:38
struct ut_stob_module * usm_private
Definition: stob.h:50
#define M0_LOG(level,...)
Definition: trace.h:167
struct m0_ut_stob_module i_ut_stob_module
Definition: instance.h:121
M0_INTERNAL const struct m0_fid * m0_stob_domain_id_get(const struct m0_stob_domain *dom)
Definition: domain.c:300
M0_INTERNAL int m0_ut_stob_destroy_by_stob_id(struct m0_stob_id *stob_id)
Definition: stob.c:317
M0_INTERNAL int m0_ut_stob_destroy(struct m0_stob *stob, struct m0_be_domain *be_dom)
Definition: stob.c:222
M0_INTERNAL void m0_dtx_init(struct m0_dtx *tx, struct m0_be_domain *be_domain, struct m0_sm_group *sm_group)
Definition: dtm.c:67
static struct m0_stob * ut_stob_linux_create_by_key(uint64_t stob_key, char *stob_create_cfg)
Definition: stob.c:135
const char * ml_name
Definition: module.h:114
M0_INTERNAL struct m0 * m0_get(void)
Definition: instance.c:41
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
M0_INTERNAL int m0_dtx_done_sync(struct m0_dtx *tx)
Definition: dtm.c:122
static void level_ut_stob_leave(struct m0_module *module)
Definition: stob.c:80
struct m0_vec iv_vec
Definition: vec.h:139
M0_INTERNAL struct m0_stob * m0_ut_stob_linux_get_by_key(uint64_t stob_key)
Definition: stob.c:174
m0_bindex_t * iv_index
Definition: vec.h:141
static const char * ut_stob_domain_create_cfg
Definition: stob.c:73
M0_INTERNAL struct m0_stob * m0_ut_stob_linux_get(void)
Definition: stob.c:169
static bool ut_stob_use_dtx(struct m0_stob_domain *dom)
Definition: stob.c:194
struct m0_be_ut_backend ut_be
Definition: ad.c:72
Definition: stob.h:163
static struct m0_stob * stob
Definition: storage.c:39
#define M0_ASSERT(cond)
struct m0_mutex usm_lock
Definition: stob.c:52
M0_INTERNAL void m0_stob_destroy_credit(struct m0_stob *stob, struct m0_be_tx_credit *accum)
Definition: stob.c:187
M0_INTERNAL void m0_be_tx_credit_add(struct m0_be_tx_credit *c0, const struct m0_be_tx_credit *c1)
Definition: tx_credit.c:44
#define bob_of(ptr, type, field, bt)
Definition: bob.h:140
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
static const uint64_t ut_stob_domain_key
Definition: stob.c:71
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
M0_INTERNAL uint8_t m0_stob_type_id_by_name(const char *name)
Definition: type.c:139
M0_INTERNAL void m0_dtx_fini(struct m0_dtx *tx)
Definition: dtm.c:134
struct m0_sm_group * m0_be_ut_backend_sm_group_lookup(struct m0_be_ut_backend *ut_be)
Definition: stubs.c:277
m0_bcount_t * v_count
Definition: vec.h:53
struct m0_be_domain but_dom
Definition: helper.h:47
M0_INTERNAL void m0_ut_stob_put(struct m0_stob *stob, bool destroy)
Definition: stob.c:185
const unsigned m0_levels_ut_stob_nr
Definition: stob.c:67
M0_INTERNAL int m0_ut_stob_create_by_stob_id(struct m0_stob_id *stob_id, const char *str_cfg)
Definition: stob.c:301
M0_INTERNAL void m0_stob_domain_fini(struct m0_stob_domain *dom)
Definition: domain.c:204
M0_INTERNAL int m0_stob_create(struct m0_stob *stob, struct m0_dtx *dtx, const char *str_cfg)
Definition: stob.c:154
M0_INTERNAL void m0_ut_stob_fini(void)
Definition: stob.c:123
M0_INTERNAL int m0_stob_punch_credit(struct m0_stob *stob, struct m0_indexvec *want, struct m0_indexvec *got, struct m0_be_tx_credit *accum)
Definition: stob.c:223
struct m0_fid sd_id
Definition: domain.h:96
M0_INTERNAL int m0_stob_destroy(struct m0_stob *stob, struct m0_dtx *dtx)
Definition: stob.c:200
M0_INTERNAL enum m0_stob_state m0_stob_state_get(struct m0_stob *stob)
Definition: stob.c:265
Definition: stob.h:91
M0_INTERNAL int m0_stob_domain_create_or_init(const char *location, const char *str_cfg_init, uint64_t dom_key, const char *str_cfg_create, struct m0_stob_domain **out)
Definition: domain.c:262
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
const struct m0_bob_type m0_ut_be_backend_bobtype
Definition: helper.c:49
static struct ut_stob_module * ut_stob_module_get(void)
Definition: stob.c:85
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
struct m0_stob_domain * usm_dom_linux
Definition: stob.c:54
static const char * ut_stob_domain_init_cfg
Definition: stob.c:72
M0_INTERNAL int m0_stob_find(const struct m0_stob_id *id, struct m0_stob **out)
Definition: stob.c:92
M0_INTERNAL int m0_dtx_open_sync(struct m0_dtx *tx)
Definition: dtm.c:101
M0_INTERNAL void m0_ut_dtx_close(struct m0_dtx *dtx)
Definition: stob.c:359
#define M0_ASSERT_INFO(cond, fmt,...)
M0_INTERNAL struct m0_dtx * m0_ut_dtx_open(struct m0_be_tx_credit *cred, struct m0_be_domain *be_dom)
Definition: stob.c:333
M0_INTERNAL int m0_ut_stob_create(struct m0_stob *stob, const char *str_cfg, struct m0_be_domain *be_dom)
Definition: stob.c:202
M0_INTERNAL int m0_stob_punch(struct m0_stob *stob, struct m0_indexvec *range, struct m0_dtx *dtx)
Definition: stob.c:232
M0_INTERNAL void m0_stob_create_credit(struct m0_stob_domain *dom, struct m0_be_tx_credit *accum)
Definition: stob.c:148
void m0_free(void *data)
Definition: memory.c:146
Definition: mutex.h:47
static const char * ut_stob_domain_location
Definition: stob.c:70
M0_INTERNAL int m0_ut_stob_init(void)
Definition: stob.c:106
M0_INTERNAL uint8_t m0_stob_domain__type_id(const struct m0_fid *dom_id)
Definition: domain.c:317
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
M0_INTERNAL void m0_stob_put(struct m0_stob *stob)
Definition: stob.c:291
Definition: trace.h:478
struct m0_modlev m0_levels_ut_stob[]
Definition: stob.c:60
M0_INTERNAL void m0_dtx_prep(struct m0_dtx *tx, const struct m0_be_tx_credit *cred)
Definition: dtm.c:80
static int level_ut_stob_enter(struct m0_module *module)
Definition: stob.c:75
M0_INTERNAL struct m0_stob * m0_ut_stob_linux_create(char *stob_create_cfg)
Definition: stob.c:179