Motr  M0
helper.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2019-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 #include <stdlib.h>
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <sys/time.h>
28 #include <getopt.h>
29 
30 #include "lib/trace.h"
31 #include "conf/obj.h"
32 #include "fid/fid.h"
33 #include "motr/client.h"
34 #include "motr/client_internal.h"
35 #include "motr/idx.h"
36 #include "motr/st/utils/helper.h"
37 #include "lib/getopts.h"
38 #include "motr/client_internal.h"
39 
40 extern struct m0_addb_ctx m0_addb_ctx;
41 
42 static int noop_lock_init(struct m0_obj *obj)
43 {
44  /* Do nothing */
45  return 0;
46 }
47 
48 static void noop_lock_fini(struct m0_obj *obj)
49 {
50  /* Do nothing */
51 }
52 
53 static int noop_lock_get(struct m0_obj *obj,
54  struct m0_rm_lock_req *req,
55  struct m0_clink *clink)
56 {
57  /* Do nothing */
58  return 0;
59 }
60 
61 static int noop_lock_get_sync(struct m0_obj *obj,
62  struct m0_rm_lock_req *req)
63 {
64  /* Do nothing */
65  return 0;
66 }
67 
68 static void noop_lock_put(struct m0_rm_lock_req *req)
69 {
70  /* Do nothing */
71 }
72 
75  .olo_lock_fini = m0_obj_lock_fini,
76  .olo_write_lock_get = m0_obj_write_lock_get,
77  .olo_write_lock_get_sync = m0_obj_write_lock_get_sync,
78  .olo_read_lock_get = m0_obj_read_lock_get,
79  .olo_read_lock_get_sync = m0_obj_read_lock_get_sync,
80  .olo_lock_put = m0_obj_lock_put
81 };
82 
85  .olo_lock_fini = noop_lock_fini,
86  .olo_write_lock_get = noop_lock_get,
87  .olo_write_lock_get_sync = noop_lock_get_sync,
88  .olo_read_lock_get = noop_lock_get,
89  .olo_read_lock_get_sync = noop_lock_get_sync,
90  .olo_lock_put = noop_lock_put
91 };
92 
93 static inline uint32_t entity_sm_state(struct m0_obj *obj)
94 {
95  return obj->ob_entity.en_sm.sm_state;
96 }
97 
98 static int alloc_vecs(struct m0_indexvec *ext, struct m0_bufvec *data,
99  struct m0_bufvec *attr, uint32_t block_count,
100  uint32_t block_size)
101 {
102  int rc;
103 
104  rc = m0_indexvec_alloc(ext, block_count);
105  if (rc != 0)
106  return rc;
107 
108  /*
109  * this allocates <block_count> * <block_size> buffers for data,
110  * and initialises the bufvec for us.
111  */
112 
113  rc = m0_bufvec_alloc_aligned(data, block_count, block_size,
114  m0_pageshift_get());
115  if (rc != 0) {
116  m0_indexvec_free(ext);
117  return rc;
118  }
119  rc = m0_bufvec_alloc(attr, block_count, 1);
120  if (rc != 0) {
121  m0_indexvec_free(ext);
123  return rc;
124  }
125  return rc;
126 }
127 
128 static void prepare_ext_vecs(struct m0_indexvec *ext,
129  struct m0_bufvec *attr,
130  uint32_t block_count, uint32_t block_size,
131  uint64_t *last_index)
132 {
133  int i;
134 
135  for (i = 0; i < block_count; ++i) {
136  ext->iv_index[i] = *last_index;
137  ext->iv_vec.v_count[i] = block_size;
138  *last_index += block_size;
139 
140  /* we don't want any attributes */
141  attr->ov_vec.v_count[i] = 0;
142  }
143 }
144 
145 static int alloc_prepare_vecs(struct m0_indexvec *ext,
146  struct m0_bufvec *data,
147  struct m0_bufvec *attr,
148  uint32_t block_count, uint32_t block_size,
149  uint64_t *last_index)
150 {
151  int rc;
152 
153  rc = alloc_vecs(ext, data, attr, block_count, block_size);
154  if (rc == 0) {
155  prepare_ext_vecs(ext, attr, block_count,
156  block_size, last_index);
157  }
158  return rc;
159 }
160 
161 static void cleanup_vecs(struct m0_bufvec *data, struct m0_bufvec *attr,
162  struct m0_indexvec *ext)
163 {
164  /* Free bufvec's and indexvec's */
165  m0_indexvec_free(ext);
168 }
169 
171  struct m0_container *container,
172  struct m0_client **instance)
173 {
174  int rc;
175 
176  if (config->mc_local_addr == NULL || config->mc_ha_addr == NULL ||
177  config->mc_profile == NULL || config->mc_process_fid == NULL) {
178  rc = M0_ERR(-EINVAL);
179  fprintf(stderr, "config parameters not initialized.\n");
180  goto err_exit;
181  }
182 
183  rc = m0_client_init(instance, config, true);
184  if (rc != 0)
185  goto err_exit;
186 
189 
190 err_exit:
191  return rc;
192 }
193 
195 {
196  m0_client_fini(instance, true);
197 }
198 
199 int m0_obj_id_sscanf(char *idstr, struct m0_uint128 *obj_id)
200 {
201  int rc;
202 
203  if (strchr(idstr, ':') == NULL) {
204  obj_id->u_lo = atoi(idstr);
205  return 0;
206  }
207 
208  rc = m0_fid_sscanf(idstr, (struct m0_fid *)obj_id);
209  if (rc != 0)
210  fprintf(stderr, "can't m0_fid_sscanf() %s, rc:%d", idstr, rc);
211 
212  return rc;
213 }
214 
215 static int open_entity(struct m0_entity *entity)
216 {
217  int rc;
218  struct m0_op *ops[1] = {NULL};
219 
220  rc = m0_entity_open(entity, &ops[0]);
221  if (rc != 0)
222  return M0_ERR(rc);
223 
224  m0_op_launch(ops, 1);
227  if (rc == 0)
228  rc = m0_rc(ops[0]);
229 
230  m0_op_fini(ops[0]);
231  m0_op_free(ops[0]);
232 
233  return rc;
234 }
235 
236 static int create_object(struct m0_entity *entity)
237 {
238  int rc;
239  struct m0_op *ops[1] = {NULL};
240  struct m0_obj *obj;
241  struct m0_op_common *oc;
242  struct m0_op_obj *oo;
243 
244  rc = m0_entity_create(NULL, entity, &ops[0]);
245  if (rc != 0)
246  return M0_ERR(rc);
247 
248  m0_op_launch(ops, 1);
251  if (rc == 0)
252  rc = ops[0]->op_rc;
253 
254  oc = M0_AMB(oc, ops[0], oc_op);
255  oo = M0_AMB(oo, oc, oo_oc);
257  M0_LOG(M0_DEBUG, "post create object, obj->ob_attr.oa_pver :"FID_F,
258  FID_P(&obj->ob_attr.oa_pver));
259 
260  m0_op_fini(ops[0]);
261  m0_op_free(ops[0]);
262 
263  return rc;
264 }
265 
266 static int read_data_from_file(FILE *fp, struct m0_bufvec *data)
267 {
268  int i;
269  int rc;
270  int nr_blocks;
271 
272  nr_blocks = data->ov_vec.v_nr;
273  for (i = 0; i < nr_blocks; ++i) {
274  rc = fread(data->ov_buf[i], data->ov_vec.v_count[i], 1, fp);
275  if (rc != 1 || feof(fp))
276  break;
277  }
278 
279  return i;
280 }
281 
282 static int write_data_to_object(struct m0_obj *obj,
283  struct m0_indexvec *ext,
284  struct m0_bufvec *data,
285  struct m0_bufvec *attr)
286 {
287  int rc;
288  struct m0_op *ops[1] = {NULL};
289 
294  rc = m0_obj_op(obj, M0_OC_WRITE, ext, data, NULL, 0, 0, &ops[0]);
295  if (rc != 0)
296  return M0_ERR(rc);
297 
298  m0_op_launch(ops, 1);
301  if (rc == 0)
302  rc = m0_rc(ops[0]);
303 
304  m0_op_fini(ops[0]);
305  m0_op_free(ops[0]);
306 
307  return rc;
308 }
309 
311  struct m0_uint128 id, bool take_locks)
312 {
313  int rc = 0;
314  struct m0_obj obj;
315  struct m0_client *instance;
316  struct m0_rm_lock_req req;
317  const struct m0_obj_lock_ops *lock_ops;
318  struct m0_clink clink;
319 
320  M0_SET0(&obj);
321  M0_SET0(&req);
322  lock_ops = take_locks ? &lock_enabled_ops : &lock_disabled_ops;
326  rc = lock_ops->olo_lock_init(&obj);
327  if (rc != 0)
328  goto init_error;
329 
331  clink.cl_is_oneshot = true;
332  lock_ops->olo_write_lock_get(&obj, &req, &clink);
333  if (take_locks)
336  rc = req.rlr_rc;
337  if (rc != 0)
338  goto get_error;
339 
340  rc = create_object(&obj.ob_entity);
341 
342  /* fini and release */
343  lock_ops->olo_lock_put(&req);
344 get_error:
345  lock_ops->olo_lock_fini(&obj);
346 init_error:
347  m0_entity_fini(&obj.ob_entity);
348 
349  return rc;
350 }
351 
352 int m0_write(struct m0_container *container, char *src,
353  struct m0_uint128 id, uint32_t block_size,
354  uint32_t block_count, uint64_t update_offset,
355  int blks_per_io, bool take_locks, bool update_mode)
356 {
357  int rc;
358  struct m0_indexvec ext;
359  struct m0_bufvec data;
360  struct m0_bufvec attr;
361  uint32_t bcount;
362  uint64_t last_index;
363  FILE *fp;
364  struct m0_obj obj;
365  struct m0_client *instance;
366  struct m0_rm_lock_req req;
367  const struct m0_obj_lock_ops *lock_ops;
368 
369  /* Open source file */
370  fp = fopen(src, "r");
371  if (fp == NULL)
372  return -EPERM;
373  M0_SET0(&obj);
374  lock_ops = take_locks ? &lock_enabled_ops : &lock_disabled_ops;
378  rc = lock_ops->olo_lock_init(&obj);
379  if (rc != 0)
380  goto init_error;
381  rc = lock_ops->olo_write_lock_get_sync(&obj, &req);
382  if (rc != 0)
383  goto get_error;
384 
385  if (update_mode)
386  rc = open_entity(&obj.ob_entity);
387  else {
388  rc = create_object(&obj.ob_entity);
389  update_offset = 0;
390  }
391  if (entity_sm_state(&obj) != M0_ES_OPEN || rc != 0)
392  goto cleanup;
393 
394  last_index = update_offset;
395 
396  if (blks_per_io == 0)
397  blks_per_io = M0_MAX_BLOCK_COUNT;
398 
399  rc = alloc_vecs(&ext, &data, &attr, blks_per_io, block_size);
400  if (rc != 0)
401  goto cleanup;
402 
403  while (block_count > 0) {
404  bcount = (block_count > blks_per_io)?
405  blks_per_io:block_count;
406  if (bcount < blks_per_io) {
407  cleanup_vecs(&data, &attr, &ext);
408  rc = alloc_vecs(&ext, &data, &attr, bcount,
409  block_size);
410  if (rc != 0)
411  goto cleanup;
412  }
413  prepare_ext_vecs(&ext, &attr, bcount,
414  block_size, &last_index);
415 
416  /* Read data from source file. */
418  M0_ASSERT(rc == bcount);
419 
420  /* Copy data to the object*/
421  rc = write_data_to_object(&obj, &ext, &data, NULL);
422  if (rc != 0) {
423  fprintf(stderr, "Writing to object failed!\n");
424  break;
425  }
426  block_count -= bcount;
427  }
428  cleanup_vecs(&data, &attr, &ext);
429  /* fini and release */
430 cleanup:
431  lock_ops->olo_lock_put(&req);
432 get_error:
433  lock_ops->olo_lock_fini(&obj);
434 init_error:
435  m0_entity_fini(&obj.ob_entity);
436  fclose(fp);
437  return rc;
438 }
439 
440 static int read_data_from_object(struct m0_obj *obj,
441  struct m0_indexvec *ext,
442  struct m0_bufvec *data,
443  struct m0_bufvec *attr,
444  uint32_t flags)
445 {
446  int rc;
447  struct m0_op *ops[1] = {NULL};
448 
449  /* Create read operation */
450  rc = m0_obj_op(obj, M0_OC_READ, ext, data, attr, 0, flags, &ops[0]);
451  if (rc != 0)
452  return M0_ERR(rc);
453 
454  m0_op_launch(ops, 1);
457  if (rc == 0)
458  rc = m0_rc(ops[0]);
459 
460  m0_op_fini(ops[0]);
461  m0_op_free(ops[0]);
462 
463  return rc;
464 }
465 
467  struct m0_uint128 id, char *dest,
468  uint32_t block_size, uint32_t block_count,
469  uint64_t offset, int blks_per_io, bool take_locks,
470  uint32_t flags, struct m0_fid *read_pver)
471 {
472  int i;
473  int j;
474  int rc;
475  uint64_t last_index = 0;
476  struct m0_obj obj;
477  struct m0_indexvec ext;
478  struct m0_bufvec data;
479  struct m0_bufvec attr;
480  FILE *fp = NULL;
481  struct m0_client *instance;
482  struct m0_rm_lock_req req;
483  uint32_t bcount;
484  const struct m0_obj_lock_ops *lock_ops;
485  uint64_t bytes_read;
486 
487  lock_ops = take_locks ? &lock_enabled_ops : &lock_disabled_ops;
488 
489  /* If input file is not given, write to stdout */
490  if (dest != NULL) {
491  fp = fopen(dest, "w");
492  if (fp == NULL)
493  return -EPERM;
494  }
496 
497  /* Read the requisite number of blocks from the entity */
498  M0_SET0(&obj);
501  rc = lock_ops->olo_lock_init(&obj);
502  if (rc != 0)
503  goto init_error;
504  rc = lock_ops->olo_read_lock_get_sync(&obj, &req);
505  if (rc != 0)
506  goto get_error;
507 
508  /* Setting pver here to read_pver received as parameter to this func.
509  * Caller of this function is expected to pass pver of object to be
510  * read, if he knows pver of object.
511  * */
512  if (read_pver != NULL && m0_fid_is_set(read_pver)) {
513  obj.ob_attr.oa_pver = *read_pver;
514  M0_LOG(M0_DEBUG, "obj->ob_attr.oa_pver is set to:"FID_F,
515  FID_P(&obj.ob_attr.oa_pver));
516  }
517 
518  rc = open_entity(&obj.ob_entity);
519  if (entity_sm_state(&obj) != M0_ES_OPEN || rc != 0)
520  goto cleanup;
521 
522  last_index = offset;
523 
524  if (blks_per_io == 0)
525  blks_per_io = M0_MAX_BLOCK_COUNT;
526  rc = alloc_vecs(&ext, &data, &attr, blks_per_io, block_size);
527  if (rc != 0)
528  goto cleanup;
529  while (block_count > 0) {
530  bytes_read = 0;
531  bcount = (block_count > blks_per_io) ?
532  blks_per_io : block_count;
533  if (bcount < blks_per_io) {
534  cleanup_vecs(&data, &attr, &ext);
535  rc = alloc_vecs(&ext, &data, &attr, bcount,
536  block_size);
537  if (rc != 0)
538  goto cleanup;
539  }
540  prepare_ext_vecs(&ext, &attr, bcount,
541  block_size, &last_index);
542 
543  rc = read_data_from_object(&obj, &ext, &data, NULL, flags);
544  if (rc != 0) {
545  fprintf(stderr, "Reading from object failed!\n");
546  break;
547  }
548 
549  if (fp != NULL) {
550  for (i = 0; i < bcount; ++i) {
551  bytes_read += fwrite(data.ov_buf[i], sizeof(char),
552  data.ov_vec.v_count[i], fp);
553  }
554  if (bytes_read != bcount * block_size) {
555  rc = -EIO;
556  fprintf(stderr, "Writing to destination "
557  "file failed!\n");
558  break;
559  }
560  } else {
561  /* putchar the output */
562  for (i = 0; i < bcount; ++i) {
563  for (j = 0; j < data.ov_vec.v_count[i]; ++j)
564  putchar(((char *)data.ov_buf[i])[j]);
565  }
566  }
567  block_count -= bcount;
568  }
569 
570  cleanup_vecs(&data, &attr, &ext);
571 
572 cleanup:
573  if (fp != NULL) {
574  fclose(fp);
575  }
576  lock_ops->olo_lock_put(&req);
577 get_error:
578  lock_ops->olo_lock_fini(&obj);
579 init_error:
580  m0_entity_fini(&obj.ob_entity);
581  return rc;
582 }
583 
584 static int punch_data_from_object(struct m0_obj *obj,
585  struct m0_indexvec *ext)
586 {
587  int rc;
588  struct m0_op *ops[1] = {NULL};
589 
590  /* Create free operation */
591  rc = m0_obj_op(obj, M0_OC_FREE, ext, NULL, NULL, 0, 0, &ops[0]);
592  if (rc != 0)
593  return M0_ERR(rc);
594 
595  m0_op_launch(ops, 1);
598  if (rc == 0)
599  rc = m0_rc(ops[0]);
600 
601  m0_op_fini(ops[0]);
602  m0_op_free(ops[0]);
603 
604  return rc;
605 }
606 
608  struct m0_uint128 id, uint32_t block_size,
609  uint32_t trunc_count, uint32_t trunc_len, int blks_per_io,
610  bool take_locks)
611 {
612  int i;
613  int rc;
614  struct m0_obj obj;
615  uint64_t last_index;
616  struct m0_indexvec ext;
617  struct m0_client *instance;
618  struct m0_rm_lock_req req;
619  uint32_t bcount;
620  const struct m0_obj_lock_ops *lock_ops;
621 
622  lock_ops = take_locks ? &lock_enabled_ops : &lock_disabled_ops;
623 
625  /* Read the requisite number of blocks from the entity */
626  M0_SET0(&obj);
629 
630  rc = lock_ops->olo_lock_init(&obj);
631  if (rc != 0)
632  goto init_error;
633  rc = lock_ops->olo_write_lock_get_sync(&obj, &req);
634  if (rc != 0)
635  goto get_error;
636  rc = open_entity(&obj.ob_entity);
637  if (entity_sm_state(&obj) != M0_ES_OPEN || rc != 0)
638  goto open_entity_error;
639 
640  if (blks_per_io == 0)
641  blks_per_io = M0_MAX_BLOCK_COUNT;
642 
643  rc = m0_indexvec_alloc(&ext, blks_per_io);
644  if (rc != 0)
645  goto open_entity_error;
646 
647  last_index = trunc_count * block_size;
648  while (trunc_len > 0) {
649  bcount = (trunc_len > blks_per_io) ?
650  blks_per_io : trunc_len;
651 
652  if (bcount < blks_per_io) {
653  m0_indexvec_free(&ext);
654  rc = m0_indexvec_alloc(&ext, bcount);
655  if (rc != 0)
656  goto open_entity_error;
657  }
658  for (i = 0; i < bcount; ++i) {
659  ext.iv_index[i] = last_index;
660  ext.iv_vec.v_count[i] = block_size;
661  last_index += block_size;
662  }
663  rc = punch_data_from_object(&obj, &ext);
664  if (rc != 0) {
665  fprintf(stderr, "Truncate failed!\n");
666  break;
667  }
668  trunc_len -= bcount;
669  }
670 
671  /*To free last allocated buff*/
672  m0_indexvec_free(&ext);
673 
674 open_entity_error:
675  lock_ops->olo_lock_put(&req);
676 get_error:
677  lock_ops->olo_lock_fini(&obj);
678 init_error:
679  m0_entity_fini(&obj.ob_entity);
680  return rc;
681 }
682 
684  struct m0_uint128 id, bool take_locks)
685 {
686  int rc;
687  struct m0_op *ops[1] = {NULL};
688  struct m0_obj obj;
689  struct m0_client *instance;
690  struct m0_rm_lock_req req;
691  const struct m0_obj_lock_ops *lock_ops;
692 
694  lock_ops = take_locks ? &lock_enabled_ops : &lock_disabled_ops;
695 
696  /* Delete an entity */
697  M0_SET0(&obj);
700 
701  rc = lock_ops->olo_lock_init(&obj);
702  if (rc != 0)
703  goto init_error;
704  rc = lock_ops->olo_write_lock_get_sync(&obj, &req);
705  if (rc != 0)
706  goto get_error;
707 
708  rc = open_entity(&obj.ob_entity);
709  if (entity_sm_state(&obj) != M0_ES_OPEN || rc != 0)
710  goto open_entity_error;
711 
712  m0_entity_delete(&obj.ob_entity, &ops[0]);
713 
714  m0_op_launch(ops, 1);
717  if (rc == 0)
718  rc = m0_rc(ops[0]);
719 
720  m0_op_fini(ops[0]);
721  m0_op_free(ops[0]);
722 open_entity_error:
723  lock_ops->olo_lock_put(&req);
724 get_error:
725  lock_ops->olo_lock_fini(&obj);
726 init_error:
727  m0_entity_fini(&obj.ob_entity);
728 
729  return rc;
730 }
731 
732 /*
733  * XXX:The following functions are used by cc_cp_cat.c
734  * to perform concurrent IO.
735  * An array of files are passed and the threads use the files in the
736  * order in which they get the locks.
737  * TODO:Reduce code duplication caused by the following functions.
738  * Find a way to incorporate the functionalities of the following
739  * functions, into existing helper functions.
740  */
742  char **src, struct m0_uint128 id, int *index,
743  uint32_t block_size, uint32_t block_count)
744 {
745  int rc;
746  struct m0_indexvec ext;
747  struct m0_bufvec data;
748  struct m0_bufvec attr;
749  uint32_t bcount;
750  uint64_t last_index;
751  FILE *fp;
752  struct m0_obj obj;
753  struct m0_client *instance;
754  struct m0_rm_lock_req req;
755 
756  M0_SET0(&obj);
760 
761  rc = m0_obj_lock_init(&obj);
762  if (rc != 0)
763  goto init_error;
764 
766  if (rc != 0)
767  goto get_error;
768 
769  fp = fopen(src[(*index)++], "r");
770  if (fp == NULL) {
771  rc = -EPERM;
772  goto file_error;
773  }
774 
775  rc = create_object(&obj.ob_entity);
776  if (rc != 0)
777  goto cleanup;
778 
779  last_index = 0;
780  while (block_count > 0) {
781  bcount = (block_count > M0_MAX_BLOCK_COUNT) ?
782  M0_MAX_BLOCK_COUNT : block_count;
783  rc = alloc_prepare_vecs(&ext, &data, &attr, bcount,
784  block_size, &last_index);
785  if (rc != 0)
786  goto cleanup;
787 
788  /* Read data from source file. */
790  M0_ASSERT(rc == bcount);
791 
792  /* Copy data to the object*/
793  rc = write_data_to_object(&obj, &ext, &data, &attr);
794  if (rc != 0) {
795  fprintf(stderr, "Writing to object failed!\n");
796  cleanup_vecs(&data, &attr, &ext);
797  goto cleanup;
798  }
799  cleanup_vecs(&data, &attr, &ext);
800  block_count -= bcount;
801  }
802 cleanup:
803  fclose(fp);
804 file_error:
806 get_error:
808 init_error:
809  m0_entity_fini(&obj.ob_entity);
810 
811  return rc;
812 }
813 
815  struct m0_uint128 id, char **dest, int *index,
816  uint32_t block_size, uint32_t block_count)
817 {
818  int i;
819  int j;
820  int rc;
821  uint64_t last_index = 0;
822  struct m0_op *ops[1] = {NULL};
823  struct m0_obj obj;
824  struct m0_indexvec ext;
825  struct m0_bufvec data;
826  struct m0_bufvec attr;
827  FILE *fp = NULL;
828  struct m0_client *instance;
829  struct m0_rm_lock_req req;
830 
831  rc = alloc_prepare_vecs(&ext, &data, &attr, block_count,
832  block_size, &last_index);
833  if (rc != 0)
834  return rc;
836 
837  /* Read the requisite number of blocks from the entity */
838  M0_SET0(&obj);
841 
842  rc = m0_obj_lock_init(&obj);
843  if (rc != 0)
844  goto init_error;
845 
847  if (rc != 0)
848  goto get_error;
849 
850  rc = open_entity(&obj.ob_entity);
851  if (entity_sm_state(&obj) != M0_ES_OPEN || rc != 0) {
853  goto get_error;
854  }
855 
856  /* Create read operation */
857  rc = m0_obj_op(&obj, M0_OC_READ, &ext, &data, &attr, 0, 0, &ops[0]);
858  if (rc != 0) {
860  goto get_error;
861  }
862 
863  m0_op_launch(ops, 1);
866  if (rc == 0)
867  rc = m0_rc(ops[0]);
868 
870 
871  if (rc != 0)
872  goto cleanup;
873 
874  if (dest != NULL) {
875  fp = fopen(dest[(*index)++], "w");
876  if (fp == NULL) {
877  rc = -EPERM;
878  goto cleanup;
879  }
880  for (i = 0; i < block_count; ++i) {
881  rc = fwrite(data.ov_buf[i], sizeof(char),
882  data.ov_vec.v_count[i], fp);
883  }
884  fclose(fp);
885  if (rc != block_count) {
886  rc = -1;
887  goto cleanup;
888  }
889  } else {
890  /* putchar the output */
891  for (i = 0; i < block_count; ++i) {
892  for (j = 0; j < data.ov_vec.v_count[i]; ++j)
893  putchar(((char *)data.ov_buf[i])[j]);
894  }
895  }
896 
897 cleanup:
898  m0_op_fini(ops[0]);
899  m0_op_free(ops[0]);
900 get_error:
902 init_error:
903  m0_entity_fini(&obj.ob_entity);
904  cleanup_vecs(&data, &attr, &ext);
905 
906  return rc;
907 }
908 
909 static bool bsize_valid(uint64_t blk_size)
910 {
911  return ((blk_size >= BLK_SIZE_4k && blk_size <= BLK_SIZE_32m) &&
912  !(blk_size % BLK_SIZE_4k));
913 }
914 
915 int m0_utility_args_init(int argc, char **argv,
916  struct m0_utility_param *params,
917  struct m0_idx_dix_config *dix_conf,
918  struct m0_config *conf,
919  void (*utility_usage) (FILE*, char*))
920 {
921  int option_index = 0;
922  uint32_t temp;
923  int c;
924 
925  M0_SET0(params);
926  params->cup_id = M0_ID_APP;
927  params->cup_n_obj = 1;
928  params->cup_take_locks = false;
929  params->cup_update_mode = false;
930  params->cup_offset = 0;
931  params->flags = 0;
932  conf->mc_is_read_verify = false;
933  conf->mc_tm_recv_queue_min_len = M0_NET_TM_RECV_QUEUE_DEF_LEN;
934  conf->mc_max_rpc_msg_size = M0_RPC_DEF_MAX_RPC_MSG_SIZE;
935 
936  /*
937  * TODO This arguments parsing is common for all the client utilities.
938  * Every option here is not supported by every utility, for ex-
939  * block_count and block_size are not supported by m0unlink and
940  * m0touch. So if someone uses '-c' or '-s' with either of those
941  * without referring to help, (s)he won't get any error regarding
942  * 'unsupported option'.
943  * This need to be handle.
944  */
945  static struct option l_opts[] = {
946  {"local", required_argument, NULL, 'l'},
947  {"ha", required_argument, NULL, 'H'},
948  {"profile", required_argument, NULL, 'p'},
949  {"process", required_argument, NULL, 'P'},
950  {"object", required_argument, NULL, 'o'},
951  {"block-size", required_argument, NULL, 's'},
952  {"block-count", required_argument, NULL, 'c'},
953  {"trunc-len", required_argument, NULL, 't'},
954  {"layout-id", required_argument, NULL, 'L'},
955  {"pver", required_argument, NULL, 'v'},
956  {"n_obj", required_argument, NULL, 'n'},
957  {"msg_size", required_argument, NULL, 'S'},
958  {"min_queue", required_argument, NULL, 'q'},
959  {"blks-per-io", required_argument, NULL, 'b'},
960  {"offset", required_argument, NULL, 'O'},
961  {"update_mode", no_argument, NULL, 'u'},
962  {"enable-locks", no_argument, NULL, 'e'},
963  {"read-verify", no_argument, NULL, 'r'},
964  {"help", no_argument, NULL, 'h'},
965  {"no-hole", no_argument, NULL, 'N'},
966  {0, 0, 0, 0 }};
967 
968  while ((c = getopt_long(argc, argv, ":l:H:p:P:o:s:c:t:L:v:n:S:q:b:O:uerhN",
969  l_opts, &option_index)) != -1)
970  {
971  switch (c) {
972  case 'l': conf->mc_local_addr = optarg;
973  continue;
974  case 'H': conf->mc_ha_addr = optarg;
975  continue;
976  case 'p': conf->mc_profile = optarg;
977  continue;
978  case 'P': conf->mc_process_fid = optarg;
979  continue;
980  case 'o': if (m0_obj_id_sscanf(optarg,
981  &params->cup_id) < 0) {
982  utility_usage(stderr, basename(argv[0]));
983  exit(EXIT_FAILURE);
984  } else if (!entity_id_is_valid(
985  &params->cup_id)) {
986  utility_usage(stderr, basename(argv[0]));
987  exit(EXIT_FAILURE);
988  }
989  continue;
990  case 's': if (m0_bcount_get(optarg,
991  &params->cup_block_size) ==
992  0) {
993  if (bsize_valid(params->cup_block_size))
994  continue;
995  fprintf(stderr, "Invalid value for -%c."
996  " Block size "
997  "should be multiple of "
998  "4k and in the range of"
999  " (4k,32m)\n", c);
1000  utility_usage(stderr,
1001  basename(argv[0]));
1002  exit(EXIT_FAILURE);
1003  }
1004  utility_usage(stderr, basename(argv[0]));
1005  exit(EXIT_FAILURE);
1006  case 'b': if ((params->cup_blks_per_io = atoi(optarg)) < 0)
1007  {
1008  fprintf(stderr, "Invalid value "
1009  "for option -%c. "
1010  "Blocks per io should "
1011  "be (>= 0)\n", c);
1012  utility_usage(stderr,
1013  basename(argv[0]));
1014  exit(EXIT_FAILURE);
1015  }
1016  continue;
1017  case 'c': if (m0_bcount_get(optarg,
1018  &params->cup_block_count) ==
1019  0) {
1020  if (params->cup_block_count < 0) {
1021  fprintf(stderr, "Invalid value "
1022  "%lu for -%c. Block "
1023  "count should be > 0\n",
1024  params->cup_block_count,
1025  c);
1026  utility_usage(stderr,
1027  basename(argv[0])
1028  );
1029  exit(EXIT_FAILURE);
1030  }
1031  continue;
1032  }
1033  utility_usage(stderr, basename(argv[0]));
1034  exit(EXIT_FAILURE);
1035  case 't': if (m0_bcount_get(optarg,
1036  &params->cup_trunc_len) ==
1037  0) {
1038  if (params->cup_trunc_len <= 0) {
1039  fprintf(stderr, "Invalid value "
1040  "%lu for -%c. Truncate "
1041  "length should be "
1042  "> 0\n",
1043  params->cup_trunc_len,
1044  c);
1045  utility_usage(stderr,
1046  basename(argv[0])
1047  );
1048  exit(EXIT_FAILURE);
1049  }
1050  continue;
1051  }
1052  utility_usage(stderr, basename(argv[0]));
1053  exit(EXIT_FAILURE);
1054  case 'L': conf->mc_layout_id = atoi(optarg);
1055  if (conf->mc_layout_id <= 0 ||
1056  conf->mc_layout_id >= 15) {
1057  fprintf(stderr, "Invalid layout id"
1058  " for -%c. Valid "
1059  "range: [1-14]\n", c);
1060  utility_usage(stderr,
1061  basename(argv[0]));
1062  exit(EXIT_FAILURE);
1063  }
1064  continue;
1065  case 'v': if (m0_fid_sscanf(optarg,
1066  &params->cup_pver) < 0) {
1067  utility_usage(stderr, basename(argv[0]));
1068  exit(EXIT_FAILURE);
1069  }
1070  continue;
1071  case 'n': params->cup_n_obj = atoi(optarg);
1072  continue;
1073  case 'e': params->cup_take_locks = true;
1074  continue;
1075  /* Update offset should be in multiple of 4k. */
1076  case 'O': if (!m0_bcount_get(optarg,
1077  &params->cup_offset))
1078  {
1079  if (params->cup_offset %
1080  BLK_SIZE_4k == 0)
1081  continue;
1082  fprintf(stderr, "Invalid value for "
1083  "-%c. offset should be "
1084  "multiple of 4k\n", c);
1085  utility_usage(stderr,
1086  basename(argv[0]));
1087  exit(EXIT_FAILURE);
1088  }
1089  utility_usage(stderr, basename(argv[0]));
1090  exit(EXIT_FAILURE);
1091  case 'r': conf->mc_is_read_verify = true;
1092  continue;
1093  case 'S': temp = atoi(optarg);
1094  conf->mc_max_rpc_msg_size = temp;
1095  continue;
1096  case 'q': temp = atoi(optarg);
1097  conf->mc_tm_recv_queue_min_len = temp;
1098  continue;
1099  case 'u': params->cup_update_mode = true;
1100  continue;
1101  case 'h': utility_usage(stderr, basename(argv[0]));
1102  exit(EXIT_FAILURE);
1103  case 'N': params->flags |= M0_OOF_NOHOLE;
1104  continue;
1105  case '?': fprintf(stderr, "Unsupported option '%c'\n",
1106  optopt);
1107  utility_usage(stderr, basename(argv[0]));
1108  exit(EXIT_FAILURE);
1109  case ':': fprintf(stderr, "No argument given for '%c'\n",
1110  optopt);
1111  utility_usage(stderr, basename(argv[0]));
1112  exit(EXIT_FAILURE);
1113  default: fprintf(stderr, "Unsupported option '%c'\n", c);
1114  }
1115  }
1116  conf->mc_is_oostore = true;
1117  conf->mc_idx_service_conf = dix_conf;
1118  dix_conf->kc_create_meta = false;
1119  conf->mc_idx_service_id = M0_IDX_DIX;
1120 
1121  return 0;
1122 }
1123 /*
1124  * Local variables:
1125  * c-indentation-style: "K&R"
1126  * c-basic-offset: 8
1127  * tab-width: 8
1128  * fill-column: 80
1129  * scroll-step: 1
1130  * End:
1131  */
M0_INTERNAL void m0_chan_wait(struct m0_clink *link)
Definition: chan.c:336
void m0_entity_fini(struct m0_entity *entity)
Definition: client.c:438
Definition: client.h:788
M0_INTERNAL int m0_indexvec_alloc(struct m0_indexvec *ivec, uint32_t len)
Definition: vec.c:532
void m0_obj_lock_put(struct m0_rm_lock_req *req)
Definition: obj_lock.c:267
int const char const void size_t int flags
Definition: dir.c:328
static void cleanup_vecs(struct m0_bufvec *data, struct m0_bufvec *attr, struct m0_indexvec *ext)
Definition: helper.c:161
#define NULL
Definition: misc.h:38
M0_INTERNAL void m0_clink_init(struct m0_clink *link, m0_chan_cb_t cb)
Definition: chan.c:201
const struct m0_obj_lock_ops lock_enabled_ops
Definition: helper.c:73
M0_INTERNAL bool entity_id_is_valid(const struct m0_uint128 *id)
Definition: client.c:354
static int open_entity(struct m0_entity *entity)
Definition: helper.c:215
const m0_time_t M0_TIME_NEVER
Definition: time.c:108
void m0_op_fini(struct m0_op *op)
Definition: client.c:847
static struct io_request req
Definition: file.c:100
static int punch_data_from_object(struct m0_obj *obj, struct m0_indexvec *ext)
Definition: helper.c:584
int m0_obj_read_lock_get(struct m0_obj *obj, struct m0_rm_lock_req *req, struct m0_clink *clink)
Definition: obj_lock.c:250
#define M0_LOG(level,...)
Definition: trace.h:167
struct m0_container container
static int alloc_vecs(struct m0_indexvec *ext, struct m0_bufvec *data, struct m0_bufvec *attr, uint32_t block_count, uint32_t block_size)
Definition: helper.c:98
void(* olo_lock_fini)(struct m0_obj *obj)
Definition: helper.h:90
int m0_obj_id_sscanf(char *idstr, struct m0_uint128 *obj_id)
Definition: helper.c:199
int m0_write(struct m0_container *container, char *src, struct m0_uint128 id, uint32_t block_size, uint32_t block_count, uint64_t update_offset, int blks_per_io, bool take_locks, bool update_mode)
Definition: helper.c:352
int m0_obj_write_lock_get_sync(struct m0_obj *obj, struct m0_rm_lock_req *req)
Definition: obj_lock.c:242
struct m0_vec ov_vec
Definition: vec.h:147
int32_t m0_rc(const struct m0_op *op)
Definition: client.c:943
void m0_client_fini(struct m0_client *m0c, bool fini_m0)
Definition: client_init.c:1711
void(* olo_lock_put)(struct m0_rm_lock_req *req)
Definition: helper.h:106
int m0_obj_lock_init(struct m0_obj *obj)
Definition: obj_lock.c:82
Definition: idx.h:70
int m0_obj_write_lock_get(struct m0_obj *obj, struct m0_rm_lock_req *req, struct m0_clink *clink)
Definition: obj_lock.c:233
struct m0_bufvec data
Definition: di.c:40
struct m0_op oc_op
uint64_t m0_client_layout_id(const struct m0_client *instance)
Definition: obj.c:859
static bool bsize_valid(uint64_t blk_size)
Definition: helper.c:909
M0_INTERNAL void m0_indexvec_free(struct m0_indexvec *ivec)
Definition: vec.c:553
Definition: conf.py:1
char * optarg
#define M0_BITS(...)
Definition: misc.h:236
M0_INTERNAL int m0_pageshift_get(void)
Definition: memory.c:238
int m0_read_cc(struct m0_container *container, struct m0_uint128 id, char **dest, int *index, uint32_t block_size, uint32_t block_count)
Definition: helper.c:814
static void prepare_ext_vecs(struct m0_indexvec *ext, struct m0_bufvec *attr, uint32_t block_count, uint32_t block_size, uint64_t *last_index)
Definition: helper.c:128
#define M0_SET0(obj)
Definition: misc.h:64
int m0_client_init(struct m0_client **m0c, struct m0_config *conf, bool init_m0)
Definition: client_init.c:1533
const struct m0_uint128 M0_UBER_REALM
Definition: client.c:85
Definition: config.py:1
void m0_obj_lock_fini(struct m0_obj *obj)
Definition: obj_lock.c:144
M0_INTERNAL bool m0_fid_is_set(const struct m0_fid *fid)
Definition: fid.c:106
void ** ov_buf
Definition: vec.h:149
static struct foo * obj
Definition: tlist.c:302
const struct m0_uint128 M0_ID_APP
Definition: client.c:92
int m0_bufvec_alloc_aligned(struct m0_bufvec *bufvec, uint32_t num_segs, m0_bcount_t seg_size, unsigned shift)
Definition: vec.c:355
M0_INTERNAL int m0_bufvec_alloc(struct m0_bufvec *bufvec, uint32_t num_segs, m0_bcount_t seg_size)
Definition: vec.c:220
int32_t m0_op_wait(struct m0_op *op, uint64_t bits, m0_time_t to)
Definition: client.c:739
struct m0_vec iv_vec
Definition: vec.h:139
static int noop_lock_get(struct m0_obj *obj, struct m0_rm_lock_req *req, struct m0_clink *clink)
Definition: helper.c:53
struct m0_addb_ctx m0_addb_ctx
int m0_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: io.c:717
M0_INTERNAL struct m0_obj * m0__obj_entity(struct m0_entity *entity)
Definition: obj.c:51
M0_INTERNAL void m0_bufvec_free(struct m0_bufvec *bufvec)
Definition: vec.c:395
m0_bindex_t * iv_index
Definition: vec.h:141
int(* olo_write_lock_get)(struct m0_obj *obj, struct m0_rm_lock_req *req, struct m0_clink *clink)
Definition: helper.h:92
int(* olo_read_lock_get_sync)(struct m0_obj *obj, struct m0_rm_lock_req *req)
Definition: helper.h:103
int i
Definition: dir.c:1033
struct m0_realm co_realm
Definition: client.h:881
Definition: client.h:641
int m0_obj_read_lock_get_sync(struct m0_obj *obj, struct m0_rm_lock_req *req)
Definition: obj_lock.c:259
return M0_ERR(-EOPNOTSUPP)
int m0_write_cc(struct m0_container *container, char **src, struct m0_uint128 id, int *index, uint32_t block_size, uint32_t block_count)
Definition: helper.c:741
#define M0_AMB(obj, ptr, field)
Definition: misc.h:320
static void attr(struct m0_addb2__context *ctx, const uint64_t *v, char *buf)
Definition: dump.c:949
struct m0_entity re_entity
Definition: client.h:871
int m0_utility_args_init(int argc, char **argv, struct m0_utility_param *params, struct m0_idx_dix_config *dix_conf, struct m0_config *conf, void(*utility_usage)(FILE *, char *))
Definition: helper.c:915
int touch(struct m0_container *container, struct m0_uint128 id, bool take_locks)
Definition: helper.c:310
#define M0_ASSERT(cond)
int client_init(struct m0_config *config, struct m0_container *container, struct m0_client **instance)
Definition: helper.c:170
static struct m0_addb2_callback c
Definition: consumer.c:41
static int create_object(struct m0_entity *entity)
Definition: helper.c:236
void m0_op_launch(struct m0_op **op, uint32_t nr)
Definition: client.c:725
static int read_data_from_object(struct m0_obj *obj, struct m0_indexvec *ext, struct m0_bufvec *data, struct m0_bufvec *attr, uint32_t flags)
Definition: helper.c:440
static struct m0_idx_dix_config dix_conf
Definition: m0hsm.c:51
uint32_t v_nr
Definition: vec.h:51
int32_t sm_rc
Definition: sm.h:336
static m0_bindex_t offset
Definition: dump.c:173
struct m0_uint128 obj_id
Definition: example1.c:53
m0_bcount_t * v_count
Definition: vec.h:53
void client_fini(struct m0_client *instance)
Definition: helper.c:194
static struct m0_clink clink[RDWR_REQUEST_MAX]
M0_INTERNAL int m0_fid_sscanf(const char *s, struct m0_fid *fid)
Definition: fid.c:227
int(* olo_lock_init)(struct m0_obj *obj)
Definition: helper.h:88
struct m0_op_common oo_oc
#define FID_P(f)
Definition: fid.h:77
static void noop_lock_put(struct m0_rm_lock_req *req)
Definition: helper.c:68
int m0_entity_create(struct m0_fid *pool, struct m0_entity *entity, struct m0_op **op)
Definition: obj.c:801
static int noop_lock_get_sync(struct m0_obj *obj, struct m0_rm_lock_req *req)
Definition: helper.c:61
Definition: fid.h:38
static int alloc_prepare_vecs(struct m0_indexvec *ext, struct m0_bufvec *data, struct m0_bufvec *attr, uint32_t block_count, uint32_t block_size, uint64_t *last_index)
Definition: helper.c:145
static void noop_lock_fini(struct m0_obj *obj)
Definition: helper.c:48
struct m0_entity * op_entity
Definition: client.h:660
M0_INTERNAL int m0_bcount_get(const char *arg, m0_bcount_t *out)
Definition: getopts.c:35
bool kc_create_meta
Definition: idx.h:183
Definition: common.h:34
int(* olo_write_lock_get_sync)(struct m0_obj *obj, struct m0_rm_lock_req *req)
Definition: helper.h:96
static int noop_lock_init(struct m0_obj *obj)
Definition: helper.c:42
M0_INTERNAL void m0_clink_fini(struct m0_clink *link)
Definition: chan.c:208
void m0_obj_init(struct m0_obj *obj, struct m0_realm *parent, const struct m0_uint128 *id, uint64_t layout_id)
Definition: client.c:403
static struct m0 instance
Definition: main.c:78
int m0_entity_delete(struct m0_entity *entity, struct m0_op **op)
Definition: obj.c:824
void m0_container_init(struct m0_container *con, struct m0_realm *parent, const struct m0_uint128 *id, struct m0_client *instance)
Definition: realm.c:31
struct m0_client * re_instance
Definition: client.h:873
void m0_op_free(struct m0_op *op)
Definition: client.c:885
struct m0_sm en_sm
Definition: client.h:732
Definition: rcv_session.c:58
int m0_entity_open(struct m0_entity *entity, struct m0_op **op)
Definition: obj.c:885
struct m0_fom_ops ops
Definition: io_foms.c:623
uint64_t u_lo
Definition: types.h:37
int optopt
static uint32_t entity_sm_state(struct m0_obj *obj)
Definition: helper.c:93
int m0_read(struct m0_container *container, struct m0_uint128 id, char *dest, uint32_t block_size, uint32_t block_count, uint64_t offset, int blks_per_io, bool take_locks, uint32_t flags, struct m0_fid *read_pver)
Definition: helper.c:466
int m0_unlink(struct m0_container *container, struct m0_uint128 id, bool take_locks)
Definition: helper.c:683
struct m0_pdclust_src_addr src
Definition: fd.c:108
int32_t rc
Definition: trigger_fop.h:47
static int write_data_to_object(struct m0_obj *obj, struct m0_indexvec *ext, struct m0_bufvec *data, struct m0_bufvec *attr)
Definition: helper.c:282
int m0_truncate(struct m0_container *container, struct m0_uint128 id, uint32_t block_size, uint32_t trunc_count, uint32_t trunc_len, int blks_per_io, bool take_locks)
Definition: helper.c:607
static int read_data_from_file(FILE *fp, struct m0_bufvec *data)
Definition: helper.c:266
const struct m0_obj_lock_ops lock_disabled_ops
Definition: helper.c:83
#define FID_F
Definition: fid.h:75
Definition: vec.h:145