Motr  M0
osync.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 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 /*
24  * Client API system tests to check if Client API matches its
25  * specifications.
26  */
27 
28 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_CLIENT
29 #include "lib/trace.h"
30 
31 #include "motr/client.h"
32 #include "motr/st/st.h"
33 #include "motr/st/st_misc.h"
34 #include "motr/st/st_assert.h"
35 
36 #include "lib/memory.h"
37 
39 static uint64_t layout_id;
40 
41 enum {
45  MAX_OPS = 16
46 };
47 
48 /* Parity group aligned (in units)*/
49 enum {
53 };
54 
55 static int create_obj(struct m0_uint128 *oid)
56 {
57  int rc = 0;
58  struct m0_op *ops[1] = {NULL};
59  struct m0_obj obj;
60  struct m0_uint128 id;
61 
62  /* Make sure everything in 'obj' is clean*/
63  memset(&obj, 0, sizeof(obj));
64 
65  oid_get(&id);
67  &id, layout_id);
68 
69  st_entity_create(NULL, &obj.ob_entity, &ops[0]);
70  if (ops[0] == NULL)
71  return -ENOENT;
72 
74 
75  rc = st_op_wait(
77  m0_time_from_now(3,0));
78 
79  st_op_fini(ops[0]);
80  st_op_free(ops[0]);
81  st_obj_fini(&obj);
82 
83  *oid = id;
84  return rc;
85 }
86 
87 /*
88  * We issue 'nr_ops' of WRITES in one go.
89  * stride: in units
90  */
91 static int write_obj(struct m0_obj *obj,
92  int start, int stride, int nr_ops)
93 {
94  int i;
95  int rc = 0;
96  struct m0_op **ops_w;
97  struct m0_indexvec *ext_w;
98  struct m0_bufvec *data_w;
99  struct m0_bufvec *attr_w;
100 
102 
103  if (nr_ops > MAX_OPS)
104  return -EINVAL;
105 
106  /* Setup bufvec, indexvec and ops for WRITEs */
107  MEM_ALLOC_ARR(ops_w, nr_ops);
108  MEM_ALLOC_ARR(ext_w, nr_ops);
109  MEM_ALLOC_ARR(data_w, nr_ops);
110  MEM_ALLOC_ARR(attr_w, nr_ops);
111  if (ops_w == NULL || ext_w == NULL || data_w == NULL || attr_w == NULL)
112  goto CLEANUP;
113 
114  for (i = 0; i < nr_ops; i++) {
115  if (m0_indexvec_alloc(&ext_w[i], 1) ||
116  m0_bufvec_alloc(&data_w[i], 1, 4096 * stride) ||
117  m0_bufvec_alloc(&attr_w[i], 1, 1))
118  {
119  rc = -ENOMEM;
120  goto CLEANUP;
121  }
122 
123  ext_w[i].iv_index[0] = 4096 * (start + i * stride);
124  ext_w[i].iv_vec.v_count[0] = 4096 * stride;
125  attr_w[i].ov_vec.v_count[0] = 0;
126  }
127 
128  /* Create and launch write requests */
129  for (i = 0; i < nr_ops; i++) {
130  ops_w[i] = NULL;
132  &ext_w[i], &data_w[i], NULL, 0, 0, &ops_w[i]);
133  if (ops_w[i] == NULL)
134  break;
135  }
136  if (i == 0) goto CLEANUP;
137 
138  st_op_launch(ops_w, nr_ops);
139 
140  /* Wait for write to finish */
141  for (i = 0; i < nr_ops; i++) {
142  rc = st_op_wait(ops_w[i],
144  M0_OS_STABLE),
145  M0_TIME_NEVER);
146 
147  st_op_fini(ops_w[i]);
148  st_op_free(ops_w[i]);
149  }
150 
151 CLEANUP:
152 
153  for (i = 0; i < nr_ops; i++) {
154  if (ext_w != NULL && ext_w[i].iv_vec.v_nr != 0)
155  m0_indexvec_free(&ext_w[i]);
156  if (data_w != NULL && data_w[i].ov_buf != NULL)
157  m0_bufvec_free(&data_w[i]);
158  if (attr_w != NULL && attr_w[i].ov_buf != NULL)
159  m0_bufvec_free(&attr_w[i]);
160  }
161 
162  if (ops_w != NULL) mem_free(ops_w);
163  if (ext_w != NULL) mem_free(ext_w);
164  if (data_w != NULL) mem_free(data_w);
165  if (attr_w != NULL) mem_free(attr_w);
166 
167  return rc;
168 }
169 
173 static void osync_after_each_write(void)
174 {
175  int i;
176  int rc;
177  int start;
178  int stride;
179  struct m0_uint128 oid;
180  struct m0_obj *obj_to_sync;
181 
182  MEM_ALLOC_PTR(obj_to_sync);
183  ST_ASSERT_FATAL(obj_to_sync != NULL);
184 
185  /* Create an object */
186  rc = create_obj(&oid);
187  ST_ASSERT_FATAL(rc == 0);
188 
189  /* Init obj */
190  st_obj_init(obj_to_sync,
192  &oid, layout_id);
193 
194  st_entity_open(&obj_to_sync->ob_entity);
195 
196  /* Write multiple times and sync after each write*/
197  start = 0;
198  stride = PARGRP_DATA_UNIT_NUM;
199  for (i = 0; i < 2; i++) {
200  rc = write_obj(obj_to_sync, start, stride, 1);
201  ST_ASSERT_FATAL(rc == 0)
202 
203  rc = m0_entity_sync(&obj_to_sync->ob_entity);
204  ST_ASSERT_FATAL(rc == 0);
205 
206  start += stride;
207  stride *= 2;
208  }
209 
210  st_obj_fini(obj_to_sync);
211  mem_free(obj_to_sync);
212 }
213 
217 static void osync_after_writes(void)
218 {
219  int i;
220  int rc;
221  int start;
222  int stride;
223  struct m0_uint128 oid;
224  struct m0_obj *obj_to_sync;
225 
226  MEM_ALLOC_PTR(obj_to_sync);
227  ST_ASSERT_FATAL(obj_to_sync != NULL);
228 
229  /* Create an object */
230  rc = create_obj(&oid);
231  ST_ASSERT_FATAL(rc == 0);
232 
233  /* Init obj */
234  st_obj_init(obj_to_sync,
236  &oid, layout_id);
237 
238  st_entity_open(&obj_to_sync->ob_entity);
239 
240  /* Write multiple times and sync after all writes*/
241  start = 0;
242  stride = PARGRP_DATA_UNIT_NUM;
243  for (i = 0; i < 2; i++) {
244  rc = write_obj(obj_to_sync, start, stride, 1);
245  ST_ASSERT_FATAL(rc == 0);
246 
247  start += stride;
248  stride *= 2;
249  }
250 
251  rc = m0_entity_sync(&obj_to_sync->ob_entity);
252  ST_ASSERT_FATAL (rc == 0)
253 
254  st_obj_fini(obj_to_sync);
255  mem_free(obj_to_sync);
256 }
257 
258 static void osync_by_sync_op(void)
259 {
260  int i;
261  int rc;
262  int start;
263  int stride;
264  struct m0_uint128 oid;
265  struct m0_op *sync_op = {NULL};
266  struct m0_obj *obj_to_sync;
267 
268  MEM_ALLOC_PTR(obj_to_sync);
269  ST_ASSERT_FATAL(obj_to_sync != NULL);
270 
271  /* Create an object */
272  rc = create_obj(&oid);
273  ST_ASSERT_FATAL(rc == 0);
274 
275  /* Init obj */
276  st_obj_init(obj_to_sync,
278  &oid, layout_id);
279 
280  st_entity_open(&obj_to_sync->ob_entity);
281 
282  /* Write multiple times and sync after all writes using sync op.*/
283  start = 0;
284  stride = PARGRP_DATA_UNIT_NUM;
285  for (i = 0; i < 2; i++) {
286  rc = write_obj(obj_to_sync, start, stride, 1);
287  ST_ASSERT_FATAL(rc == 0);
288 
289  start += stride;
290  stride *= 2;
291  }
292 
293  /* Launch and wait on sync op. */
294  rc = m0_sync_op_init(&sync_op);
295  M0_ASSERT(rc == 0);
296  rc = m0_sync_entity_add(sync_op, &obj_to_sync->ob_entity);
297  M0_ASSERT(rc == 0);
298 
299  st_op_launch(&sync_op, 1);
300  rc = st_op_wait(
301  sync_op, M0_BITS(M0_OS_FAILED, M0_OS_STABLE),
302  m0_time_from_now(3,0));
303  ST_ASSERT_FATAL(rc == 0);
304 
305  st_op_fini(sync_op);
306  st_op_free(sync_op);
307 
308  /* Clean up objects. */
309  st_obj_fini(obj_to_sync);
310  mem_free(obj_to_sync);
311 }
312 
316 static void osync_on_op(void)
317 {
318  int i;
319  int rc = 0;
320  int bytes_to_write;
321  int nr_objs;
322  int nr_objs_written;
323  int *sync_rcs;
324  struct m0_obj *objs_to_sync;
325  struct m0_op **ops_w;
326  struct m0_op *sync_op = {NULL};
327  struct m0_indexvec *ext_w;
328  struct m0_bufvec *data_w;
329  struct m0_bufvec *attr_w;
330  struct m0_uint128 oid;
331 
333 
334  bytes_to_write = 4096;
335  nr_objs = 1;
336 
337  /* Setup bufvec, indexvec and ops for WRITEs */
338  MEM_ALLOC_ARR(objs_to_sync, nr_objs);
339  MEM_ALLOC_ARR(ops_w, nr_objs);
340  MEM_ALLOC_ARR(ext_w, nr_objs);
341  MEM_ALLOC_ARR(data_w, nr_objs);
342  MEM_ALLOC_ARR(attr_w, nr_objs);
343  if (objs_to_sync == NULL || ops_w == NULL || ext_w == NULL ||
344  data_w == NULL || attr_w == NULL)
345  goto cleanup;
346 
347  for (i = 0; i < nr_objs; i++) {
348  if (m0_indexvec_alloc(&ext_w[i], 1) ||
349  m0_bufvec_alloc(&data_w[i], 1, bytes_to_write) ||
350  m0_bufvec_alloc(&attr_w[i], 1, 1))
351  {
352  rc = -ENOMEM;
353  goto cleanup;
354  }
355 
356  ext_w[i].iv_index[0] = 0;
357  ext_w[i].iv_vec.v_count[0] = bytes_to_write;
358  attr_w[i].ov_vec.v_count[0] = 0;
359  }
360 
361  /* Create and write objects. */
362  for (i = 0; i < nr_objs; i++) {
363  rc = create_obj(&oid);
364  ST_ASSERT_FATAL(rc == 0);
365 
366  /* Init obj */
367  st_obj_init(objs_to_sync + i,
369  &oid, layout_id);
370 
371  st_entity_open(&(objs_to_sync + i)->ob_entity);
372 
373  /* Create and launch write requests */
374  ops_w[i] = NULL;
375  st_obj_op(objs_to_sync + i, M0_OC_WRITE,
376  &ext_w[i], &data_w[i], NULL, 0, 0, &ops_w[i]);
377  if (ops_w[i] == NULL)
378  break;
379 
380  st_op_launch(ops_w, 1);
381 
382  /* Wait for write to finish */
383  rc = st_op_wait(ops_w[i],
385  M0_OS_STABLE),
386  M0_TIME_NEVER);
387  ST_ASSERT_FATAL(rc == 0);
388  }
389  nr_objs_written = i;
390 
391  /* Send an SYNC_ON_OPS op. */
392  M0_ALLOC_ARR(sync_rcs, nr_objs_written);
393  if (sync_rcs == NULL)
394  goto ops_w_fini;
395 
396  rc = m0_sync_op_init(&sync_op);
397  M0_ASSERT(rc == 0);
398  for (i = 0; i < nr_objs_written; i++) {
399  rc = m0_sync_op_add(sync_op, ops_w[i]);
400  M0_ASSERT(rc == 0);
401  }
402 
403  st_op_launch(&sync_op, 1);
404  rc = st_op_wait(
405  sync_op, M0_BITS(M0_OS_FAILED, M0_OS_STABLE),
406  M0_TIME_NEVER);
407  ST_ASSERT_FATAL(rc == 0);
408 
409  st_op_fini(sync_op);
410  st_op_free(sync_op);
411  mem_free(sync_rcs);
412 
413 ops_w_fini:
414  for (i = 0; i < nr_objs_written; i++) {
415  st_op_fini(ops_w[i]);
416  st_op_free(ops_w[i]);
417  st_obj_fini(objs_to_sync + i);
418  }
419 
420 cleanup:
421 
422  for (i = 0; i < nr_objs; i++) {
423  if (ext_w != NULL && ext_w[i].iv_vec.v_nr != 0)
424  m0_indexvec_free(&ext_w[i]);
425  if (data_w != NULL && data_w[i].ov_buf != NULL)
426  m0_bufvec_free(&data_w[i]);
427  if (attr_w != NULL && attr_w[i].ov_buf != NULL)
428  m0_bufvec_free(&attr_w[i]);
429  }
430 
431  if (ops_w != NULL) mem_free(ops_w);
432  if (ext_w != NULL) mem_free(ext_w);
433  if (data_w != NULL) mem_free(data_w);
434  if (attr_w != NULL) mem_free(attr_w);
435  if (objs_to_sync != NULL) mem_free(objs_to_sync);
436 }
437 
438 
439 /* Initialises the Client environment.*/
440 static int st_osync_init(void)
441 {
442  int rc = 0;
443 
444  /*
445  * Retrieve the uber realm. We don't need to open this,
446  * as realms are not actually implemented yet
447  */
450  st_get_instance());
452 
453  if (rc != 0)
454  console_printf("Failed to open uber realm\n");
455 
457  return rc;
458 }
459 
460 /* Finalises the Client environment.*/
461 static int st_osync_fini(void)
462 {
463  return 0;
464 }
465 
467  .ss_name = "osync_st",
468  .ss_init = st_osync_init,
469  .ss_fini = st_osync_fini,
470  .ss_tests = {
471  { "osync_after_each_write", &osync_after_each_write},
472  { "osync_after_writes", &osync_after_writes},
473  { "osync_by_sync_op", &osync_by_sync_op},
474  { "osync_on_op", &osync_on_op},
475  { NULL, NULL }
476  }
477 };
478 
479 #undef M0_TRACE_SUBSYSTEM
480 
481 /*
482  * Local variables:
483  * c-indentation-style: "K&R"
484  * c-basic-offset: 8
485  * tab-width: 8
486  * fill-column: 80
487  * scroll-step: 1
488  * End:
489  */
uint64_t id
Definition: cob.h:2380
int st_entity_create(struct m0_fid *pool, struct m0_entity *entity, struct m0_op **op)
Definition: api.c:71
struct m0_container st_osync_container
Definition: osync.c:38
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
void st_op_free(struct m0_op *op)
Definition: api.c:147
Definition: client.h:788
M0_INTERNAL int m0_indexvec_alloc(struct m0_indexvec *ivec, uint32_t len)
Definition: vec.c:532
#define NULL
Definition: misc.h:38
const m0_time_t M0_TIME_NEVER
Definition: time.c:108
void st_obj_fini(struct m0_obj *obj)
Definition: api.c:50
int m0_entity_sync(struct m0_entity *ent)
Definition: sync.c:1061
static void osync_on_op(void)
Definition: osync.c:316
#define MEM_ALLOC_PTR(arr)
Definition: st_misc.h:81
struct m0_vec ov_vec
Definition: vec.h:147
uint64_t m0_client_layout_id(const struct m0_client *instance)
Definition: obj.c:859
M0_INTERNAL void m0_indexvec_free(struct m0_indexvec *ivec)
Definition: vec.c:553
int m0_sync_op_add(struct m0_op *sop, struct m0_op *op)
Definition: sync.c:1020
#define M0_BITS(...)
Definition: misc.h:236
const struct m0_uint128 M0_UBER_REALM
Definition: client.c:85
static void osync_by_sync_op(void)
Definition: osync.c:258
#define ST_ASSERT_FATAL(a)
Definition: st_assert.h:31
void ** ov_buf
Definition: vec.h:149
static struct foo * obj
Definition: tlist.c:302
static void osync_after_writes(void)
Definition: osync.c:217
static int st_osync_init(void)
Definition: osync.c:440
M0_INTERNAL int m0_bufvec_alloc(struct m0_bufvec *bufvec, uint32_t num_segs, m0_bcount_t seg_size)
Definition: vec.c:220
struct m0_vec iv_vec
Definition: vec.h:139
M0_INTERNAL void m0_bufvec_free(struct m0_bufvec *bufvec)
Definition: vec.c:395
static int write_obj(struct m0_obj *obj, int start, int stride, int nr_ops)
Definition: osync.c:91
m0_bindex_t * iv_index
Definition: vec.h:141
int i
Definition: dir.c:1033
struct m0_realm co_realm
Definition: client.h:881
Definition: client.h:641
void st_container_init(struct m0_container *con, struct m0_realm *parent, const struct m0_uint128 *id, struct m0_client *instance)
Definition: api.c:34
struct m0_entity re_entity
Definition: client.h:871
int oid_get(struct m0_uint128 *oid)
Definition: oid.c:373
#define M0_ASSERT(cond)
Definition: st.h:83
int m0_sync_entity_add(struct m0_op *sop, struct m0_entity *ent)
Definition: sync.c:985
int32_t sm_rc
Definition: sm.h:336
m0_bcount_t * v_count
Definition: vec.h:53
int m0_sync_op_init(struct m0_op **sop)
Definition: sync.c:972
void console_printf(const char *fmt,...)
Definition: st_misc.c:155
static void mem_free(const struct m0_be_btree *btree, struct m0_be_tx *tx, void *ptr)
Definition: btree.c:102
void st_obj_init(struct m0_obj *obj, struct m0_realm *parent, const struct m0_uint128 *id, uint64_t layout_id)
Definition: api.c:42
struct st_suite st_suite_osync
Definition: osync.c:466
void st_obj_op(struct m0_obj *obj, enum m0_obj_opcode opcode, struct m0_indexvec *ext, struct m0_bufvec *data, struct m0_bufvec *attr, uint64_t mask, uint32_t flags, struct m0_op **op)
Definition: api.c:100
#define MEM_ALLOC_ARR(arr, nr)
Definition: st_misc.h:80
m0_time_t m0_time_from_now(uint64_t secs, long ns)
Definition: time.c:96
struct m0_client * st_get_instance()
Definition: st.c:57
#define M0_CLIENT_THREAD_ENTER
struct m0_entity ob_entity
Definition: client.h:789
static void osync_after_each_write(void)
Definition: osync.c:173
static int start(struct m0_fom *fom)
Definition: trigger_fom.c:321
void st_op_launch(struct m0_op **op, uint32_t nr)
Definition: api.c:129
const char * ss_name
Definition: st.h:85
static int st_osync_fini(void)
Definition: osync.c:461
Definition: osync.c:45
static uint64_t layout_id
Definition: osync.c:39
void st_entity_open(struct m0_entity *entity)
Definition: api.c:153
struct m0_sm en_sm
Definition: client.h:732
struct m0_fom_ops ops
Definition: io_foms.c:623
int32_t st_op_wait(struct m0_op *op, uint64_t bits, m0_time_t to)
Definition: api.c:136
void st_op_fini(struct m0_op *op)
Definition: api.c:142
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
static int create_obj(struct m0_uint128 *oid)
Definition: osync.c:55
Definition: vec.h:145