Motr  M0
beck.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 
29 #define _FILE_OFFSET_BITS 64 /* for fseeko */
30 #include <err.h>
31 #include <stdio.h>
32 #include <string.h> /* strerror */
33 #include <sysexits.h> /* EX_CONFIG, EX_OK, EX_USAGE */
34 #include <fcntl.h> /* open */
35 #include <unistd.h> /* close */
36 #include <time.h> /* localtime_r */
37 #include <pthread.h>
38 #include <signal.h> /* signal() to register ctrl + C handler */
39 #include <yaml.h>
40 #include <sys/mman.h> /* mmap() */
41 #include <unistd.h> /* getpid() */
42 
43 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_BE
44 #include "lib/trace.h"
45 
46 #include "lib/getopts.h"
47 #include "lib/memory.h"
48 #include "lib/assert.h"
49 #include "lib/string.h" /* m0_strdup */
50 #include "lib/thread.h"
51 #include "motr/version.h"
52 #include "lib/uuid.h"
53 #include "motr/magic.h" /* M0_FORMAT_HEADER_MAGIC */
54 #include "motr/init.h" /* m0_init */
55 #include "reqh/reqh.h"
56 #include "module/instance.h"
57 #include "format/format.h"
58 #include "format/format_xc.h"
59 #include "balloc/balloc.h" /* M0_BALLOC_GROUP_DESC_FORMAT_VERSION */
60 #include "be/btree_internal.h"
61 #include "be/list.h"
62 #include "be/seg_internal.h"
63 #include "be/op.h" /* m0_be_op_active */
64 #include "be/ut/helper.h" /* m0_be_ut_backend_cfg_default */
65 #include "cas/ctg_store.h"
66 #include "cob/cob.h" /* m0_cob_nsrec */
67 #include "pool/pool.h"
68 #include "stob/ad_private.h"
69 #include "dix/fid_convert.h"
70 #include "stob/ad.h" /* m0_stob_ad_domain */
71 #include "ioservice/io_service.h" /* m0_ios_cdom_get */
72 #include "ioservice/fid_convert.h" /* m0_fid_convert_cob2adstob */
73 #include "ioservice/cob_foms.h" /* m0_cc_stob_cr_credit */
74 #include "be/extmap_internal.h" /* m0_be_emap */
75 #include "be/tx_bulk.h" /* m0_be_tx_bulk */
76 
77 M0_TL_DESCR_DECLARE(ad_domains, M0_EXTERN);
78 M0_TL_DECLARE(ad_domains, M0_EXTERN, struct ad_domain_map);
79 
80 struct queue {
81  pthread_mutex_t q_lock;
82  pthread_cond_t q_cond;
83  struct action *q_head;
84  struct action *q_tail;
85  uint64_t q_nr;
86  uint64_t q_max;
87 };
88 
89 struct scanner {
90  FILE *s_file;
95  off_t s_start_off;
99  struct queue s_bnode_q;
102  struct m0_mutex s_lock;
103  off_t s_off;
104  off_t s_pos;
105  bool s_byte;
110  off_t s_size;
111  struct m0_be_seg *s_seg;
112  struct queue *s_q;
116  unsigned char s_chunk[4 * 1024 * 1024];
117  off_t s_chunk_pos;
124  /* Holds source metadata segment header generation identifier. */
125  uint64_t s_gen;
126  /* Set variable when correct generation identifier has been found */
128 };
129 
130 struct stats {
131  uint64_t s_found;
132  uint64_t s_chksum;
133  uint64_t s_align[2];
134  uint64_t s_version;
135 };
136 
137 struct recops;
138 struct rectype {
139  const char *r_name;
141  const struct recops *r_ops;
142  struct stats r_stats;
143 };
144 
145 struct recops {
146  int (*ro_proc) (struct scanner *s, struct rectype *r, char *buf);
147  int (*ro_ver) (struct scanner *s, struct rectype *r, char *buf);
148  int (*ro_check)(struct scanner *s, struct rectype *r, char *buf);
149 };
150 
151 struct bstats {
152  uint64_t c_tree;
153  uint64_t c_node;
154  uint64_t c_leaf;
155  uint64_t c_maxlevel;
156  uint64_t c_fanout;
157  uint64_t c_kv;
158  uint64_t c_kv_bad;
159 };
160 
161 struct btype { /* b-tree type */
163  const char *b_name;
164  int (*b_proc)(struct scanner *s, struct btype *b,
165  struct m0_be_bnode *node,
166  off_t node_offset);
167  struct bstats b_stats;
168 };
169 
170 struct gen {
171  uint64_t g_gen;
172  uint64_t g_count;
173 };
174 
176  AO_INIT = 1,
177  AO_DONE = 2,
178  AO_CTG = 3,
179  AO_COB = 4,
181  AO_NR = 30
182 };
183 
184 enum { MAX_WORKERS_NR = 64 };
185 
186 struct action_ops;
187 struct builder;
188 
189 struct action {
192  const struct action_ops *a_ops;
194  struct action *a_next;
195  struct action *a_prev;
196 };
197 
198 struct bnode_act {
199  struct action bna_act;
200  off_t bna_offset;
201 };
202 
203 struct cob_action {
204  struct action coa_act;
206  struct m0_buf coa_key;
208  struct m0_buf coa_val;
210  uint8_t coa_valdata[sizeof(struct m0_cob_nsrec)];
212  struct m0_fid coa_fid;
213 };
214 
215 struct action_ops {
216  int (*o_prep)(struct action *act, struct m0_be_tx_credit *cred);
217  void (*o_act) (struct action *act, struct m0_be_tx *tx);
218  void (*o_fini)(struct action *act);
219 };
220 
221 enum { CACHE_SIZE = 1000000 };
222 enum { NV_OFFSET_SAVE_DELTA_IN_BYTES = 0x40000000 }; /* 1G */
223 enum { NV_OFFSET_SAVE_ACT_DELTA = 1000 };
224 
225 struct cache_slot {
226  struct m0_fid cs_fid;
227  uint64_t cs_flags;
229 };
230 
235 struct cache {
237  int c_head;
238 };
239 
240 struct ad_dom_info{
241  /* pointer to m0_stob used by ad_domain */
242  struct m0_stob *stob;
243  /* pointer to m0_stob_domain used by ad_domain */
245 };
246 
247 struct builder {
249  struct m0_reqh b_reqh;
251  struct m0_be_seg *b_seg0;
252  struct m0_be_seg *b_seg;
253  uint64_t b_ad_dom_count;
258  struct queue *b_q;
260  struct cache b_cache;
261  uint64_t b_size;
262  const char *b_dom_path;
263  const char *b_stob_path;
264  const char *b_be_config_file;
266  uint64_t b_act;
267  uint64_t b_data;
280 };
281 
282 struct emap_action {
283  struct action emap_act;
284  struct m0_fid emap_fid;
285  struct m0_buf emap_key;
286  struct m0_buf emap_val;
289 };
290 
293  uint64_t woi_act_added[AO_NR];
294  uint64_t woi_act_done[AO_NR];
295 };
296 
298  off_t soi_offset;
301 };
302 
303 struct part_info {
304  uint64_t pi_act_added[AO_NR];
305  uint64_t pi_act_done[AO_NR];
307 };
308 
310  uint64_t noi_magic; /* header magic */
314 };
315 
316 struct offset_info {
318  uint64_t oi_workers_nr;
321 };
322 
323 static int init(void);
324 static void fini(void);
325 static int scan (struct scanner *s);
326 static void stats_print(void);
327 static int parse(struct scanner *s);
328 static int get (struct scanner *s, void *buf, size_t nob);
329 static int getat(struct scanner *s, off_t off, void *buf, size_t nob);
330 static int deref(struct scanner *s, const void *addr, void *buf, size_t nob);
331 static int recdo(struct scanner *s, const struct m0_format_tag *tag,
332  struct rectype *rt);
333 static const char *recname(const struct rectype *rt);
334 static const char *bname (const struct btype *bt);
335 
336 static int btree (struct scanner *s, struct rectype *r, char *buf);
337 static int bnode (struct scanner *s, struct rectype *r, char *buf);
338 static int seghdr(struct scanner *s, struct rectype *r, char *buf);
339 static void *scanner_action(size_t len, enum action_opcode opc,
340  const struct action_ops *ops);
341 
342 static void genadd(uint64_t gen);
343 static void generation_id_print(uint64_t gen);
344 static void generation_id_get(FILE *fp, uint64_t *gen_id);
345 static int generation_id_verify(struct scanner *s, uint64_t gen);
346 static void seg_get(FILE *fp, struct m0_be_seg *out);
347 
348 static int scanner_cache_init (struct scanner *s);
349 
350 static int scanner_init (struct scanner *s);
351 static void scanner_fini (struct scanner *s);
352 static int builder_init (struct builder *b);
353 static void builder_fini (struct builder *b);
354 static void ad_dom_fini (struct builder *b);
355 static void builder_thread (struct builder *b);
356 static void be_cfg_default_init(struct m0_be_domain_cfg *dom_cfg,
357  struct m0_be_tx_bulk_cfg *tb_cfg);
358 
359 static int format_header_verify(const struct m0_format_header *h,
360  uint16_t rtype);
361 static bool btree_node_pre_is_valid (const struct m0_be_bnode *node,
362  struct scanner *s);
363 static bool btree_node_post_is_valid (const struct m0_be_bnode *node,
364  const struct m0_be_btree_kv_ops *ops);
365 static bool btree_kv_is_valid (struct m0_be_bnode *node,
366  int index, struct m0_buf *key);
367 static void btree_bad_kv_count_update(uint64_t type, int count);
368 static void *scanner_action(size_t len, enum action_opcode opc,
369  const struct action_ops *ops);
370 static void *builder_action(struct builder *b, size_t len,
371  enum action_opcode opc,
372  const struct action_ops *ops);
373 static bool fid_without_type_eq(const struct m0_fid *fid0,
374  const struct m0_fid *fid1);
375 
376 static struct cache_slot *cache_lookup(struct cache *c, struct m0_fid *fid);
377 static struct cache_slot *cache_insert(struct cache *c,
378  const struct m0_fid *fid);
379 static void qinit(struct queue *q, uint64_t maxnr);
380 static void qfini(struct queue *q);
381 static void qput(struct queue *q, struct action *act);
382 static struct action *qget (struct queue *q);
383 static struct action *qtry (struct queue *q);
384 static struct action *qpeek(struct queue *q);
385 static bool isqempty(struct queue *q);
386 
387 static int ctg_proc(struct scanner *s, struct btype *b,
388  struct m0_be_bnode *node, off_t node_offset);
389 static int ctg_pver_fid_get(struct m0_fid *fid);
390 
391 static void test(void);
392 
393 static int cob_proc(struct scanner *s, struct btype *b,
394  struct m0_be_bnode *node, off_t node_offset);
395 
396 static int emap_proc(struct scanner *s, struct btype *b,
397  struct m0_be_bnode *node, off_t node_offset);
398 static int emap_prep(struct action *act, struct m0_be_tx_credit *cred);
399 static void emap_act(struct action *act, struct m0_be_tx *tx);
400 static void emap_fini(struct action *act);
401 static int emap_kv_get(struct scanner *s, const struct be_btree_key_val *kv,
402  struct m0_buf *key_buf, struct m0_buf *val_buf);
403 static void sig_handler(int num);
404 static int be_cfg_from_yaml_update(const char *yaml_file,
405  struct m0_be_domain_cfg *cfg);
406 static int nv_scan_offset_init(uint64_t workers_nr,
407  uint64_t partitions_nr);
408 static void nv_scan_offset_fini(void);
409 static off_t nv_scan_offset_get(off_t snapshot_size);
410 static void nv_scan_offset_update(void);
411 
412 static void scanner_thread(struct scanner *s);
413 static const struct recops btreeops;
414 static const struct recops bnodeops;
415 static const struct recops seghdrops;
416 
417 static const struct action_ops done_ops;
418 static const struct action_ops ctg_ops;
419 static const struct action_ops cob_ops;
420 
421 #define _FT(name) M0_FORMAT_TYPE_ ## name
422 #define _TAG(name) M0_ ## name ## _FORMAT_VERSION , _FT(name)
423 #define _T(name, str, field, ops) [_FT(name)] = { \
424  .r_tag = { _TAG(name), { offsetof(struct str, field) } }, \
425  .r_ops = (ops) \
426 }
427 
428 static struct rectype rt[] = {
429  _T(BALLOC_GROUP_DESC, m0_balloc_group_desc, bgd_footer, NULL),
430  _T(BALLOC, m0_balloc, cb_footer, NULL),
431  _T(BE_BTREE, m0_be_btree, bb_footer, &btreeops),
432  _T(BE_BNODE, m0_be_bnode, bt_footer, &bnodeops),
433  _T(BE_EMAP_KEY, m0_be_emap_key, ek_footer, NULL),
434  _T(BE_EMAP_REC, m0_be_emap_rec, er_footer, NULL),
435  _T(BE_EMAP, m0_be_emap, em_footer, NULL),
436  _T(BE_LIST, m0_be_list, bl_format_footer, NULL),
437  _T(BE_SEG_HDR, m0_be_seg_hdr, bh_footer, &seghdrops),
438  _T(CAS_CTG, m0_cas_ctg, cc_foot, NULL),
439  _T(CAS_STATE, m0_cas_state, cs_footer, NULL),
440  _T(COB_DOMAIN, m0_cob_domain, cd_footer, NULL),
441  _T(COB_NSREC, m0_cob_nsrec, cnr_footer, NULL),
442  _T(EXT, m0_ext, e_footer, NULL),
443  _T(POOLNODE, m0_poolnode, pn_footer, NULL),
444  _T(POOLDEV, m0_pooldev, pd_footer, NULL),
445  _T(POOL_SPARE_USAGE, m0_pool_spare_usage, psu_footer, NULL),
446  _T(STOB_AD_DOMAIN, m0_stob_ad_domain, sad_footer, NULL),
447  _T(STOB_AD_0TYPE_REC, stob_ad_0type_rec, sa0_footer, NULL),
448  [M0_FORMAT_TYPE_NR] = {}
449 };
450 
451 #undef _T
452 #undef _TAG
453 #undef _FV
454 
456 
457 #define _B(t, proc) [t] = { .b_type = (t), .b_proc = (proc) }
458 
459 static struct btype bt[] = {
476  [M0_BBT_NR] = {}
477 };
478 #undef _B
479 
480 enum {
481  MAX_GEN = 256,
482  MAX_SCAN_QUEUED = 10000000,
483  MAX_QUEUED = 1000000,
484  MAX_REC_SIZE = 64*1024,
491  MAX_KEY_LEN = 256,
493  DEFAULT_BE_SEG_LOAD_ADDR = 0x400000100000,
498  DEFAULT_BE_MAX_TX_REG_SZ = (44 * 1024 * 1024ULL)
499 };
500 
502 struct ctg_action {
503  struct action cta_act;
504  struct m0_buf cta_key;
505  struct m0_buf cta_val;
507  struct m0_fid cta_fid;
517 };
518 
519 static struct scanner beck_scanner;
520 static struct builder beck_builder;
521 static struct gen g[MAX_GEN] = {};
522 static struct m0_be_seg s_seg = {};
524 static struct offset_info off_info;
525 
526 static bool dry_run = false;
527 static bool disable_directio = false;
528 static bool signaled = false;
529 static bool resume_scan = false;
530 static bool mmap_be_segment = false;
531 
532 static const char *offset_file = NULL;
533 
539  .tbc_q_cfg = {
540  .bqc_q_size_max = 1000,
541  .bqc_producers_nr_max = 1,
542  },
543  .tbc_workers_nr = 0x40,
544  .tbc_partitions_nr = AO_NR,
545  .tbc_work_items_per_tx_max = 1,
546  };
547 #define FLOG(level, rc, s) \
548  M0_LOG(level, " rc=%d at offset: %" PRId64 " errno: %s (%i), eof: %i", \
549  (rc), (uint64_t)ftell(s->s_file), strerror(errno), \
550  errno, feof(s->s_file))
551 
552 #define RLOG(level, prefix, s, r, tag) \
553  M0_LOG(level, prefix " %" PRIu64 " %s %hu:%hu:%u", s->s_off, recname(r), \
554  (tag)->ot_version, (tag)->ot_type, (tag)->ot_size)
555 
556 static void sig_handler(int num)
557 {
558  printf("Caught Signal %d \n", num);
559  signaled = true;
560 }
561 
562 int main(int argc, char **argv)
563 {
564  struct m0 instance = {};
565  const char *spath = NULL;
566  int sfd = 0; /* Use stdin by default. */
567  bool ut = false;
568  bool version = false;
569  bool print_gen_id = false;
570  struct queue q = {};
571  int result;
572  uint64_t gen_id = 0;
573  struct m0_be_tx_credit max;
574  FILE *fp;
575 
577  result = m0_init(&instance);
578  if (result != 0)
579  errx(EX_CONFIG, "Cannot initialise motr: %d.", result);
580  result = init();
581  if (result != 0)
582  errx(EX_CONFIG, "Cannot initialise beck: %d.", result);
583  result = scanner_init(&beck_scanner);
584  if (result != 0) {
585  errx(EX_CONFIG, "Cannot initialise scanner: %d.", result);
586  }
587 
588  result = M0_GETOPTS("m0_beck", argc, argv,
589  M0_STRINGARG('s', "Path to snapshot (file or device).",
590  LAMBDA(void, (const char *path) {
591  spath = path;
592  })),
593  M0_FORMATARG('S', "Snapshot size", "%"SCNi64,
595  M0_FLAGARG('b', "Scan every byte (10x slower).",
597  M0_FLAGARG('U', "Run unit tests.", &ut),
598  M0_FLAGARG('n', "Dry Run.", &dry_run),
599  M0_FLAGARG('I', "Disable directio.", &disable_directio),
600  M0_FLAGARG('R', "resume scan.", &resume_scan),
601  M0_STRINGARG('r', "file to save scan offsets.",
602  LAMBDA(void, (const char *fname) {
603  offset_file = fname;
604  })),
605  M0_FLAGARG('p', "Print Generation Identifier.",
606  &print_gen_id),
607  M0_FORMATARG('g', "Generation Identifier.", "%"PRIu64,
609  M0_FLAGARG('V', "Version info.", &version),
610  M0_FLAGARG('e', "Print errored OIDs.",
612  M0_STRINGARG('y', "YAML file path",
613  LAMBDA(void, (const char *s) {
615  })),
616  M0_STRINGARG('a', "stob domain path",
617  LAMBDA(void, (const char *s) {
619  })),
620  M0_STRINGARG('d', "segment stob domain path path",
621  LAMBDA(void, (const char *s) {
623  })),
624  M0_FLAGARG('m', "MMAP BE segment file. Useful for "
625  "developer debugging.", &mmap_be_segment));
626  if (result != 0)
627  errx(EX_USAGE, "Wrong option: %d.", result);
628  if (ut) {
629  test();
630  return EX_OK;
631  }
632  if (version) {
634  return EX_OK;
635  }
636 
637  if (mmap_be_segment)
638  dry_run = true; /* Force dry run mode when asked to mmap. */
639 
640  if (dry_run)
641  printf("Running in read-only mode.\n");
642 
644  printf("Will not print INVALID GOB IDs if found since '-e'"
645  "option was not specified. \n");
646 
647  if (beck_builder.b_dom_path == NULL && !dry_run && !print_gen_id)
648  errx(EX_USAGE, "Specify domain path (-d).");
649  if (spath != NULL) {
650  sfd = open(spath, O_RDONLY);
651  if (sfd == -1)
652  err(EX_NOINPUT, "Cannot open snapshot \"%s\".", spath);
653  }
654  beck_scanner.s_file = fdopen(sfd, "r");
655  if (beck_scanner.s_file == NULL)
656  err(EX_NOINPUT, "Cannot open snapshot.");
657  if (beck_scanner.s_size == 0) {
658  result = fseek(beck_scanner.s_file, 0, SEEK_END);
659  if (result != 0)
660  err(EX_NOINPUT, "Cannot seek snapshot to the end.");
662  ftello(beck_scanner.s_file);
663  if (beck_scanner.s_size == -1)
664  err(EX_NOINPUT, "Cannot tell snapshot size.");
665  result = fseek(beck_scanner.s_file, 0, SEEK_SET);
666  if (result != 0)
667  err(EX_NOINPUT, "Cannot seek snapshot to the beginning.");
668  printf("Snapshot size: %" PRId64 ".\n", beck_scanner.s_size);
669  }
670 
671  if (beck_builder.b_be_config_file && !dry_run && !print_gen_id) {
672  fp = fopen(beck_builder.b_be_config_file, "r");
673  if (fp == NULL)
674  err(EX_NOINPUT, "Failed to open yaml file \"%s\".",
676  fclose(fp);
677  }
679  if (print_gen_id) {
680  generation_id_print(gen_id);
681  printf("\n");
682  fclose(beck_scanner.s_file);
683  return EX_OK;
684  }
685  if (gen_id != 0)
686  beck_scanner.s_gen_found = true;
687  if (beck_scanner.s_gen != 0) {
688  printf("\nReceived source segment header generation id\n");
690  printf("\n");
691  fflush(stdout);
692  }
693 
694  beck_scanner.s_gen = gen_id ?: beck_scanner.s_gen;
695  printf("\nSource segment header generation id to be used by beck.\n");
697  printf("\n");
698  fflush(stdout);
699  /*
700  * If both segment's generation identifier is corrupted then abort
701  * beck tool.
702  */
703  if (!dry_run && beck_scanner.s_gen == 0) {
704  printf("Cannot find any segment header generation identifer");
705  return EX_DATAERR;
706  }
707 
708  if (offset_file == NULL && !dry_run)
709  errx(EX_USAGE, "Specify file to save scan offsets (-r).");
710 
712  result = M0_THREAD_INIT(&beck_scanner.s_thread, struct scanner *,
714  "scannner");
715  if (result != 0)
716  err(EX_CONFIG, "Cannot start scanner thread.");
717  /*
718  * Skip builder related calls for dry run as we will not be building a
719  * new segment.
720  */
721  if (!dry_run) {
722  qinit(&q, MAX_QUEUED);
724  result = builder_init(&beck_builder);
727  &max, NULL);
728  beck_scanner.s_max_reg_size = max.tc_reg_size;
729  if (result != 0)
730  err(EX_CONFIG, "Cannot initialise builder.");
733  if (result != 0)
734  err(EX_CONFIG, "scan offset save/restore init failure");
735  } else {
743 
744  if (mmap_be_segment) {
745  void *ret;
746 
747  errno = 0;
748  ret = mmap(s_seg.bs_addr, s_seg.bs_size,
749  PROT_READ|PROT_WRITE,
750  MAP_FIXED | MAP_PRIVATE | MAP_NORESERVE,
751  fileno(beck_scanner.s_file),
752  s_seg.bs_offset);
753 
754  if (ret == MAP_FAILED)
755  err(EXIT_FAILURE, "Failed to mmap memory. Error");
756 
757  printf("BE segment file %s has been mmaped at "
758  "address %p for %" PRId64 " bytes.\n"
759  "Please attach to process %u to browse BE "
760  "segment data.\n", spath, s_seg.bs_addr,
761  s_seg.bs_size, getpid());
762 
763  while (1); /* Wait in endless loop for gdb connection */
764  }
765 
766  }
767 
768  result = scanner_cache_init(&beck_scanner);
769  if (result != 0)
770  err(EX_CONFIG, "Cannot initialise scanner.");
771  if (dry_run) {
772  printf("Press CTRL+C to quit.\n");
773  signal(SIGINT, sig_handler);
774  }
775  result = scan(&beck_scanner);
776  printf("\n Pending to process bnodes=%"PRIu64 " It may take some time",
779  AO_DONE, NULL));
783  if (result != 0)
784  warn("Scan failed: %d.", result);
785 
786  stats_print();
787  if (!dry_run) {
788  qput(&q, builder_action(&beck_builder, sizeof(struct action),
789  AO_DONE, &done_ops));
791  qfini(&q);
793  }
795  fini();
796  if (spath != NULL)
797  close(sfd);
798  m0_fini();
799  return EX_OK;
800 }
801 
802 static void scanner_thread(struct scanner *s)
803 {
804  struct m0_be_bnode node;
805  struct bnode_act *ba;
806  struct btype *b;
807  int rc;
808 
809  do {
810  ba = (struct bnode_act *)qget(&s->s_bnode_q);
811  if (ba->bna_act.a_opc != AO_DONE) {
812  rc = getat(s, ba->bna_offset, &node, sizeof node);
813  M0_ASSERT(rc == 0);
814  b = &bt[node.bt_backlink.bli_type];
815  b->b_proc(s, b, &node, ba->bna_offset);
816  m0_free(ba);
817  }
818  } while (ba->bna_act.a_opc != AO_DONE);
819 }
820 
821 static char iobuf[4*1024*1024];
822 
823 enum { DELTA = 60 };
824 
825 static void generation_id_print(uint64_t gen)
826 {
827  time_t ts = m0_time_seconds(gen);
828  struct tm tm;
829 
830  localtime_r(&ts, &tm);
831  printf("%04d-%02d-%02d-%02d:%02d:%02d.%09" PRIu64 " (%" PRIu64 ")",
832  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
833  tm.tm_hour, tm.tm_min, tm.tm_sec,
835 }
836 
837 static bool seg_hdr_get(FILE *fp, struct m0_be_seg_hdr *out)
838 {
839  struct m0_format_tag tag = {};
840  bool result = false;
841  struct m0_be_seg_hdr seg_hdr;
842  const char *rt_be_cksum;
843  off_t old_offset;
844 
845  old_offset = ftello(fp);
846  fseeko(fp, 0, SEEK_SET);
847 
848  if (fread(&seg_hdr, 1, sizeof(seg_hdr), fp) == sizeof(seg_hdr)) {
849 
851 
852  if (seg_hdr.bh_header.hd_magic == M0_FORMAT_HEADER_MAGIC &&
853  tag.ot_type == M0_FORMAT_TYPE_BE_SEG_HDR &&
854  memcmp(&tag, &rt[M0_FORMAT_TYPE_BE_SEG_HDR].r_tag,
855  sizeof tag) == 0 &&
856  m0_format_footer_verify(&seg_hdr, 0) == 0) {
857 
858  rt_be_cksum = m0_build_info_get()->
859  bi_xcode_protocol_be_checksum;
860  if (strncmp(seg_hdr.bh_be_version, rt_be_cksum,
862  seg_hdr.bh_items_nr == 1) {
863  *out = seg_hdr;
864  result = true;
865  }
866  }
867  }
868 
869  fseeko(fp, old_offset, SEEK_SET);
870  return (result);
871 }
872 
873 static void generation_id_get(FILE *fp, uint64_t *gen_id)
874 {
875  struct m0_be_seg_hdr seg_hdr;
876 
877  if (seg_hdr_get(fp, &seg_hdr))
878  *gen_id = seg_hdr.bh_items[0].sg_gen;
879  else
880  printf("Checksum error for segment header. "
881  "Could not extract Generation ID.\n");
882 }
883 
884 static void seg_get(FILE *fp, struct m0_be_seg *out)
885 {
886  struct m0_be_seg_hdr seg_hdr;
887  struct m0_be_seg seg;
888  const struct m0_be_seg_geom *g;
889 
891  if (seg_hdr_get(fp, &seg_hdr)) {
892  g = &seg_hdr.bh_items[0];
893 
894  seg.bs_reserved = sizeof(seg_hdr);
895  seg.bs_size = g->sg_size;
896  seg.bs_addr = g->sg_addr;
897  seg.bs_offset = g->sg_offset;
898  seg.bs_gen = g->sg_gen;
899  } else {
905  printf("Checksum error for segment header. "
906  "Could not extract Segment map information. "
907  "Using possible defaults\n");
908  seg.bs_reserved = sizeof(seg_hdr);
911  seg.bs_offset = 0;
912  }
913 
914  *out = seg;
915 
916 }
917 
918 static int generation_id_verify(struct scanner *s, uint64_t gen)
919 {
920  if (gen == s->s_gen)
921  return 0;
922  else if (s->s_gen_found)
923  return -EINVAL;
924  else if (gen > s->s_gen &&
926  return -ETIME;
927  else if (gen < s->s_gen &&
929  return -ETIME;
930  return 0;
931 }
932 
933 static int scanner_init(struct scanner *s)
934 {
935  int rc = 0;
936 
937  m0_mutex_init(&s->s_lock);
938 
939  return rc;
940 }
941 
942 static int scanner_cache_init(struct scanner *s)
943 {
944  int rc;
945 
946  m0_mutex_init(&s->s_lock);
947  rc = fseeko(s->s_file, 0, SEEK_SET);
948  if (rc != 0) {
949  M0_LOG(M0_FATAL, "Can not seek at the beginning of file");
950  return rc;
951  }
952  rc = getat(s, 0, s->s_chunk, sizeof s->s_chunk);
953  if (rc != 0)
954  M0_LOG(M0_FATAL, "Can not read first chunk");
955  return rc;
956 }
957 
958 static void scanner_fini(struct scanner *s)
959 {
960  m0_mutex_fini(&s->s_lock);
961 }
962 
963 static int scan(struct scanner *s)
964 {
965  uint64_t magic;
966  int result;
967  time_t lasttime = time(NULL);
968  off_t lastoff;
969  off_t lastnvsaveoff;
970  uint64_t lastrecord = 0;
971  uint64_t lastdata = 0;
972  if (resume_scan && !dry_run) {
973  s->s_off = nv_scan_offset_get(s->s_size);
974  M0_LOG(M0_DEBUG, "Resuming Scan from Offset = %li", s->s_off);
975  printf("Resuming Scan from Offset = %li file %s",
976  s->s_off, offset_file);
977  }
978  lastoff = s->s_off;
979  lastnvsaveoff = s->s_off;
980  setvbuf(s->s_file, iobuf, _IONBF, sizeof iobuf);
981  while (!signaled && (result = get(s, &magic, sizeof magic)) == 0) {
982  if (magic == M0_FORMAT_HEADER_MAGIC) {
983  s->s_off -= sizeof magic;
984  parse(s);
985  } else if (s->s_byte)
986  s->s_off -= sizeof magic - 1;
987  if (!s->s_byte)
988  s->s_off &= ~0x7;
989  if (time(NULL) - lasttime > DELTA) {
990  printf("\nOffset: %15lli Speed: %7.2f MB/s "
991  "Completion: %3i%% "
992  "Action: %" PRIu64 " records/s "
993  "Data Speed: %7.2f MB/s",
994  (long long)s->s_off,
995  ((double)s->s_off - lastoff) /
996  DELTA / 1024.0 / 1024.0,
997  (int)(s->s_off * 100 / s->s_size),
998  (beck_builder.b_act - lastrecord) / DELTA,
999  ((double)beck_builder.b_data - lastdata) /
1000  DELTA / 1024.0 / 1024.0);
1001  lasttime = time(NULL);
1002  lastoff = s->s_off;
1003  lastrecord = beck_builder.b_act;
1004  lastdata = beck_builder.b_data;
1005 
1006  }
1010  if (!dry_run &&
1011  (s->s_off - lastnvsaveoff >
1013  isqempty(&s->s_bnode_q) &&
1014  isqempty(s->s_q)) {
1015  lastnvsaveoff = s->s_off;
1017  }
1018  }
1019  return feof(s->s_file) ? 0 : result;
1020 }
1021 
1022 static void stats_print(void)
1023 {
1024  int i;
1025 
1026  printf("\n%25s : %9s %9s %9s %9s\n",
1027  "record", "found", "bad csum", "unaligned", "version");
1028  for (i = 0; i < ARRAY_SIZE(rt); ++i) {
1029  struct stats *s = &rt[i].r_stats;
1030  if (recname(&rt[i]) == NULL)
1031  continue;
1032  printf("%25s : %9" PRId64 " %9" PRId64 " %9" PRId64 " %9" PRId64 "\n",
1033  recname(&rt[i]), s->s_found, s->s_chksum, s->s_align[1],
1034  s->s_version);
1035  }
1036  printf("\n%25s : %9s %9s %9s %9s %9s %9s %9s\n",
1037  "btree", "tree", "node", "leaf", "maxlevel", "kv", "bad kv",
1038  "fanout");
1039  for (i = 0; i < ARRAY_SIZE(bt); ++i) {
1040  struct bstats *s = &bt[i].b_stats;
1041  if (bname(&bt[i]) == NULL)
1042  continue;
1043  printf("%25s : %9" PRId64 " %9" PRId64 " %9" PRId64 " "
1044  "%9" PRId64 " %9" PRId64 " %9" PRId64 " %9" PRId64 "\n",
1045  bname(&bt[i]),
1046  s->c_tree, s->c_node, s->c_leaf, s->c_maxlevel,
1047  s->c_kv, s->c_kv_bad, s->c_fanout);
1048  }
1049 
1050  printf("\ngenerations\n");
1051  for (i = 0; i < ARRAY_SIZE(g); ++i) {
1052  if (g[i].g_count > 0) {
1053  generation_id_print(g[i].g_gen);
1054  printf(" : %9" PRId64 "\n", g[i].g_count);
1055  }
1056  }
1057 }
1058 
1059 static int parse(struct scanner *s)
1060 {
1061  struct m0_format_header hdr = {};
1062  struct m0_format_tag tag = {};
1063  struct rectype *r;
1064  int result;
1065  int idx;
1066  off_t lastoff;
1067  result = get(s, &hdr, sizeof hdr);
1068  if (result == 0) {
1069  M0_ASSERT(hdr.hd_magic == M0_FORMAT_HEADER_MAGIC);
1070  m0_format_header_unpack(&tag, &hdr);
1071  idx = tag.ot_type;
1072  if (IS_IN_ARRAY(idx, rt) && idx >= M0_FORMAT_TYPE_BEGIN &&
1073  tag.ot_type == rt[idx].r_tag.ot_type) {
1074  r = &rt[idx];
1075  } else {
1076  r = &rt[M0_FORMAT_TYPE_NR];
1077  RLOG(M0_INFO, "U", s, r, &tag);
1078  }
1079  r->r_stats.s_found++;
1080  r->r_stats.s_align[!!(s->s_off & 07)]++;
1081  /* Only process btree, bnode and segment header records. */
1082  if (M0_IN(idx, (M0_FORMAT_TYPE_BE_BTREE,
1085  lastoff = s->s_off;
1086  s->s_off -= sizeof hdr;
1087  result = recdo(s, &tag, r);
1088  if (result != 0)
1089  s->s_off = lastoff;
1090  }
1091  } else {
1092  M0_LOG(M0_FATAL, "Cannot read hdr->hd_bits.");
1093  FLOG(M0_FATAL, result, s);
1094  result = M0_ERR(-EIO);
1095  }
1096  return M0_RC(result);
1097 }
1098 
1099 static int init(void)
1100 {
1101  int i;
1102  int j;
1103  const struct m0_xcode_enum *e = &m0_xc_m0_format_type_enum;
1104  const char fprefix[] = "M0_FORMAT_TYPE_";
1105  const char bprefix[] = "M0_BBT_";
1106 
1107  M0_ASSERT(m0_forall(i, ARRAY_SIZE(rt), ergo(rt[i].r_tag.ot_type != 0,
1108  m0_forall(j, ARRAY_SIZE(rt),
1109  (rt[i].r_tag.ot_type == rt[j].r_tag.ot_type) == (i == j)))));
1111  ergo(rt[i].r_tag.ot_type != 0,
1112  rt[i].r_tag.ot_type == i)));
1113  for (i = 0; i < ARRAY_SIZE(rt) - 1; ++i) {
1114  if (rt[i].r_tag.ot_type == 0)
1115  continue;
1116  M0_ASSERT(rt[i].r_tag.ot_size <= MAX_REC_SIZE);
1117  M0_ASSERT(m0_xcode_enum_is_valid(e, rt[i].r_tag.ot_type));
1118  for (j = 0; j < e->xe_nr; ++j) {
1119  M0_ASSERT(strncmp(fprefix, e->xe_val[j].xev_name,
1120  sizeof fprefix - 1) == 0);
1121  if (rt[i].r_tag.ot_type == e->xe_val[j].xev_val) {
1122  rt[i].r_name = e->xe_val[j].xev_name +
1123  sizeof fprefix - 1;
1124  break;
1125  }
1126  }
1127  M0_ASSERT(j < e->xe_nr);
1128  }
1129  e = &m0_xc_m0_be_btree_type_enum;
1130  for (i = 0; i < ARRAY_SIZE(bt) - 1; ++i) {
1131  if (bt[i].b_type == 0)
1132  continue;
1133  M0_ASSERT(m0_xcode_enum_is_valid(e, bt[i].b_type));
1134  for (j = 0; j < e->xe_nr; ++j) {
1135  M0_ASSERT(strncmp(bprefix, e->xe_val[j].xev_name,
1136  sizeof bprefix - 1) == 0);
1137  if (bt[i].b_type == e->xe_val[j].xev_val) {
1138  bt[i].b_name = e->xe_val[j].xev_name +
1139  sizeof bprefix - 1;
1140  break;
1141  }
1142  }
1143  M0_ASSERT(j < e->xe_nr);
1144  }
1145  return 0;
1146 }
1147 
1148 static void fini(void)
1149 {
1150 }
1151 
1152 static int recdo(struct scanner *s, const struct m0_format_tag *tag,
1153  struct rectype *r)
1154 {
1155  unsigned size = tag->ot_size + sizeof(struct m0_format_footer);
1156  void *buf;
1157  int result;
1158 
1159  if (size > MAX_REC_SIZE)
1160  return M0_RC(-EINVAL);
1161 
1162  buf = alloca(size);
1163  result = get(s, buf, size);
1164  if (result == 0) {
1165  if (memcmp(tag, &r->r_tag, sizeof *tag) == 0) {
1173  if (r->r_ops != NULL && r->r_ops->ro_check != NULL) {
1174  result = r->r_ops->ro_check(s, r, buf);
1175  }
1176  if (result != 0)
1177  return M0_RC(result);
1178  result = m0_format_footer_verify(buf, false);
1179  if (result != 0) {
1180  RLOG(M0_DEBUG, "С", s, r, tag);
1181  FLOG(M0_DEBUG, result, s);
1182  r->r_stats.s_chksum++;
1183  } else {
1184  RLOG(M0_DEBUG, "R", s, r, tag);
1185  if (r->r_ops != NULL &&
1186  r->r_ops->ro_proc != NULL)
1187  result = r->r_ops->ro_proc(s, r, buf);
1188  }
1189  } else {
1190  RLOG(M0_DEBUG, "V", s, r, tag);
1191  FLOG(M0_DEBUG, result, s);
1192  r->r_stats.s_version++;
1193  if (r->r_ops != NULL && r->r_ops->ro_ver != NULL)
1194  result = r->r_ops->ro_ver(s, r, buf);
1195  }
1196  }
1197  return M0_RC(result);
1198 }
1199 
1200 static const char *recname(const struct rectype *r)
1201 {
1202  return r->r_name ?: r == &rt[ARRAY_SIZE(rt) - 1] ? "UNKNOWN" : NULL;
1203 }
1204 
1205 static const char *bname(const struct btype *b)
1206 {
1207  return b->b_name ?: b == &bt[ARRAY_SIZE(bt) - 1] ? "UNKNOWN" : NULL;
1208 }
1209 
1210 static int getat(struct scanner *s, off_t off, void *buf, size_t nob)
1211 {
1212  int result = 0;
1213  FILE *f = s->s_file;
1214 
1215  m0_mutex_lock(&s->s_lock);
1216  if (off != s->s_pos)
1217  result = fseeko(f, off, SEEK_SET);
1218  if (result != 0) {
1219  M0_LOG(M0_FATAL, "Cannot seek to %" PRId64 ".", off);
1220  result = M0_ERR(-errno);
1221  } else if (fread(buf, 1, nob, f) != nob) {
1222  if (feof(f))
1223  result = -ENOENT;
1224  else {
1225  M0_LOG(M0_FATAL, "Cannot read %d at %" PRId64 ".",
1226  (int)nob, off);
1227  result = M0_ERR(-EIO);
1228  }
1229  } else {
1230  M0_ASSERT(ftello(f) == (off + nob));
1231  s->s_pos = off + nob;
1232  result = 0;
1233  }
1234  if (result != 0 && !feof(f)) {
1235  FLOG(M0_FATAL, result, s);
1236  s->s_pos = -1;
1237  }
1238  m0_mutex_unlock(&s->s_lock);
1239  return M0_RC(result);
1240 }
1241 
1242 static int deref(struct scanner *s, const void *addr, void *buf, size_t nob)
1243 {
1244  off_t off = addr - s->s_seg->bs_addr;
1245 
1246  if (m0_be_seg_contains(s->s_seg, addr) &&
1247  m0_be_seg_contains(s->s_seg, addr + nob - 1))
1248  return getat(s, off, buf, nob);
1249  else
1250  return M0_ERR(-EFAULT);
1251 }
1252 
1253 static int get(struct scanner *s, void *buf, size_t nob)
1254 {
1255  int result = 0;
1256  s->s_start_off = s->s_off;
1257  if (!(s->s_off >= s->s_chunk_pos &&
1258  s->s_off + nob < s->s_chunk_pos + sizeof s->s_chunk)) {
1259  result = getat(s, s->s_off, s->s_chunk, sizeof s->s_chunk);
1260  if (result == 0)
1261  s->s_chunk_pos = s->s_off;
1262  }
1263  if (result == 0) {
1264  memcpy(buf, &s->s_chunk[s->s_off - s->s_chunk_pos], nob);
1265  s->s_off += nob;
1266  }
1267  return result;
1268 }
1269 
1270 static int btree(struct scanner *s, struct rectype *r, char *buf)
1271 {
1272  struct m0_be_btree *tree = (void *)buf;
1273  int idx = tree->bb_backlink.bli_type;
1274  struct btype *b;
1275 
1276  if (!IS_IN_ARRAY(idx, bt) || bt[idx].b_type == 0)
1277  idx = ARRAY_SIZE(bt) - 1;
1278 
1279  genadd(tree->bb_backlink.bli_gen);
1280  if (!s->s_gen_found) {
1281  s->s_gen_found = true;
1282  s->s_gen = tree->bb_backlink.bli_gen;
1283  printf("\nBeck will use latest generation id found in btree\n");
1284  generation_id_print(s->s_gen);
1285  }
1286  b = &bt[idx];
1287  b->b_stats.c_tree++;
1288  return 0;
1289 }
1290 
1291 static int btree_check(struct scanner *s, struct rectype *r, char *buf)
1292 {
1293  struct m0_be_btree *tree = (void *)buf;
1294  int idx = tree->bb_backlink.bli_type;
1295 
1296  if (!IS_IN_ARRAY(idx, bt) || bt[idx].b_type == 0)
1297  return -ENOENT;
1298 
1299  return generation_id_verify(s, tree->bb_backlink.bli_gen);
1300 }
1301 
1302 static void *scanner_action(size_t len, enum action_opcode opc,
1303  const struct action_ops *ops)
1304 {
1305  struct action *act;
1306 
1307  M0_PRE(len >= sizeof *act);
1308 
1309  act = m0_alloc(len);
1310  M0_ASSERT(act != NULL); /* Can we handle this? */
1311  act->a_opc = opc;
1312  act->a_ops = ops;
1313  return act;
1314 }
1315 
1316 static int bnode(struct scanner *s, struct rectype *r, char *buf)
1317 {
1318  struct m0_be_bnode *node = (void *)buf;
1319  int idx = node->bt_backlink.bli_type;
1320  struct btype *b;
1321  struct bstats *c;
1322  struct bnode_act *ba;
1323 
1324  if (!IS_IN_ARRAY(idx, bt) || bt[idx].b_type == 0)
1325  idx = ARRAY_SIZE(bt) - 1;
1326 
1327  genadd(node->bt_backlink.bli_gen);
1328  if (!s->s_gen_found) {
1329  s->s_gen_found = true;
1330  s->s_gen = node->bt_backlink.bli_gen;
1331  printf("\nBeck will use latest generation id found in bnode\n");
1332  generation_id_print(s->s_gen);
1333  }
1334  b = &bt[idx];
1335  c = &b->b_stats;
1336  c->c_node++;
1337  if (b->b_proc != NULL) {
1338  ba = scanner_action(sizeof *ba, AO_INIT, NULL);
1339  ba->bna_offset = s->s_start_off;
1340  qput(&s->s_bnode_q, &ba->bna_act);
1341  }
1342  c->c_kv += node->bt_num_active_key;
1343  if (node->bt_isleaf) {
1344  c->c_leaf++;
1345  } else
1346  c->c_fanout += node->bt_num_active_key + 1;
1347  c->c_maxlevel = max64(c->c_maxlevel, node->bt_level);
1348  return 0;
1349 }
1350 
1351 static int bnode_check(struct scanner *s, struct rectype *r, char *buf)
1352 {
1353  struct m0_be_bnode *node = (void *)buf;
1354  int idx = node->bt_backlink.bli_type;
1355 
1356  if (!IS_IN_ARRAY(idx, bt) || bt[idx].b_type == 0)
1357  return -ENOENT;
1358 
1359  return generation_id_verify(s, node->bt_backlink.bli_gen);
1360 }
1361 
1362 static struct m0_stob_ad_domain *emap_dom_find(const struct action *act,
1363  const struct m0_fid *emap_fid,
1364  int *lockid)
1365 {
1366  struct m0_stob_ad_domain *adom = NULL;
1367  int i;
1368 
1369  for (i = 0; i < act->a_builder->b_ad_dom_count; i++) {
1370  adom = act->a_builder->b_ad_domain[i];
1371  if (m0_fid_eq(emap_fid,
1373  break;
1374  }
1375  }
1376  *lockid = i;
1377  return (i == act->a_builder->b_ad_dom_count) ? NULL: adom;
1378 }
1379 
1380 static const struct action_ops emap_ops = {
1381  .o_prep = &emap_prep,
1382  .o_act = &emap_act,
1383  .o_fini = &emap_fini
1384 };
1385 
1386 static void emap_to_gob_convert(const struct m0_uint128 *emap_prefix,
1387  struct m0_fid *out)
1388 {
1389  struct m0_fid dom_id = {};
1390  struct m0_stob_id stob_id = {};
1391  struct m0_fid cob_fid;
1392  struct m0_fid gob_fid;
1393 
1395 
1397  m0_stob_id_make(emap_prefix->u_hi, emap_prefix->u_lo, &dom_id,
1398  &stob_id);
1399 
1401  cob_fid = stob_id.si_fid;
1403 
1406 
1407  *out = gob_fid;
1408 }
1409 
1410 static int emap_proc(struct scanner *s, struct btype *btype,
1411  struct m0_be_bnode *node, off_t node_offset)
1412 {
1413  struct m0_stob_ad_domain *adom = NULL;
1414  struct emap_action *ea;
1415  int id;
1416  int i;
1417  int ret = 0;
1418  struct m0_be_emap_key *ek;
1419  struct m0_fid gob_id;
1420  uint64_t inv_emap_off;
1421 
1422  for (i = 0; i < node->bt_num_active_key; i++) {
1423  ea = scanner_action(sizeof *ea, AO_EMAP_FIRST, &emap_ops);
1424  ea->emap_fid = node->bt_backlink.bli_fid;
1427 
1428  ret = emap_kv_get(s, &node->bt_kv_arr[i],
1429  &ea->emap_key, &ea->emap_val);
1430  if (ret != 0) {
1431  if (s->s_print_invalid_oids) {
1432  ek = ea->emap_key.b_addr;
1433  inv_emap_off = node->bt_kv_arr[i].btree_key -
1434  s->s_seg->bs_addr;
1435  emap_to_gob_convert(&ek->ek_prefix, &gob_id);
1436  M0_LOG(M0_ERROR, "Found incorrect EMAP entry at"
1437  " segment offset %" PRIx64 " for GOB "
1438  FID_F, inv_emap_off, FID_P(&gob_id));
1439  }
1440  btree_bad_kv_count_update(node->bt_backlink.bli_type,
1441  1);
1442  m0_free(ea);
1443  continue;
1444  }
1445 
1446  if (!dry_run) {
1448  ea->emap_act.a_node_offset = node_offset;
1449  adom = emap_dom_find(&ea->emap_act, &ea->emap_fid, &id);
1450  if (adom != NULL) {
1451  ea->emap_act.a_opc += id;
1452  qput(s->s_q, &ea->emap_act);
1453  } else {
1455  node->bt_backlink.bli_type, 1);
1456  m0_free(ea);
1457  continue;
1458  }
1459  } else
1460  m0_free(ea);
1461  }
1462  return ret;
1463 }
1464 
1465 static int emap_entry_lookup(struct m0_stob_ad_domain *adom,
1466  struct m0_uint128 prefix,
1468  struct m0_be_emap_cursor *it)
1469 {
1470  int rc;
1471 
1475  &prefix, offset, it),
1476  bo_u.u_emap.e_rc);
1477  return rc == -ESRCH ? -ENOENT : rc;
1478 }
1479 
1480 static int emap_prep(struct action *act, struct m0_be_tx_credit *credit)
1481 {
1482  struct m0_stob_ad_domain *adom = NULL;
1483  struct emap_action *emap_ac = M0_AMB(emap_ac, act, emap_act);
1484  struct m0_be_emap_rec *emap_val;
1485  struct m0_be_emap_key *emap_key;
1486  int rc;
1487  struct m0_be_emap_cursor it = {};
1488  int id;
1489 
1490  adom = emap_dom_find(act, &emap_ac->emap_fid, &id);
1491  if (adom == NULL || id < 0 || id >= AO_NR - AO_EMAP_FIRST) {
1492  M0_LOG(M0_ERROR, "Invalid FID for emap record found !!!");
1493  m0_free(act);
1494  return M0_RC(-EINVAL);
1495  }
1496 
1498  emap_val = emap_ac->emap_val.b_addr;
1499  if (emap_val->er_value != AET_HOLE) {
1501  1, credit);
1502  emap_key = emap_ac->emap_key.b_addr;
1503  rc = emap_entry_lookup(adom, emap_key->ek_prefix, 0, &it);
1504  if (rc == 0)
1505  m0_be_emap_close(&it);
1506  else
1508  M0_BEO_INSERT, 1, credit);
1510  BALLOC_FRAGS_MAX + 1, credit);
1511  }
1513  return 0;
1514 }
1515 
1516 static void emap_act(struct action *act, struct m0_be_tx *tx)
1517 {
1518  struct emap_action *emap_ac = M0_AMB(emap_ac, act, emap_act);
1519  struct m0_stob_ad_domain *adom = NULL;
1520  int rc = 0;
1521  struct m0_ext ext;
1522  struct m0_be_emap_key *emap_key;
1523  struct m0_be_emap_rec *emap_val;
1524  struct m0_be_emap_cursor it = {};
1525  struct m0_ext in_ext;
1526  int id;
1527 
1528  adom = emap_dom_find(act, &emap_ac->emap_fid, &id);
1529  emap_val = emap_ac->emap_val.b_addr;
1530  if (emap_val->er_value != AET_HOLE) {
1531  emap_key = emap_ac->emap_key.b_addr;
1532  ext.e_start = emap_val->er_value >> adom->sad_babshift;
1533  ext.e_end = (emap_val->er_value + emap_key->ek_offset -
1534  emap_val->er_start) >> adom->sad_babshift;
1535  m0_ext_init(&ext);
1536 
1538  rc = adom->sad_ballroom->ab_ops->
1539  bo_reserve_extent(adom->sad_ballroom,
1540  tx, &ext,
1542  if (rc != 0) {
1544  M0_LOG(M0_ERROR, "Failed to reserve extent rc=%d", rc);
1545  return;
1546  }
1547 
1548  beck_builder.b_data +=
1549  ((ext.e_end - ext.e_start) << adom->sad_babshift)
1550  << adom->sad_bshift;
1551 
1552  rc = emap_entry_lookup(adom, emap_key->ek_prefix, 0, &it);
1553  /* No emap entry found for current stob, insert hole */
1554  rc = rc ? M0_BE_OP_SYNC_RET(op,
1556  tx, &op,
1557  &emap_key->ek_prefix,
1558  AET_HOLE),
1559  bo_u.u_emap.e_rc) : 0;
1560 
1561  M0_SET0(&it);
1562  rc = emap_entry_lookup(adom, emap_key->ek_prefix,
1563  emap_val->er_start, &it);
1564  if (it.ec_seg.ee_val == AET_HOLE) {
1565  in_ext.e_start = emap_val->er_start;
1566  in_ext.e_end = emap_key->ek_offset;
1567  m0_ext_init(&in_ext);
1568  M0_SET0(&it.ec_op);
1570  m0_be_emap_paste(&it, tx, &in_ext, emap_val->er_value,
1571  NULL, /*No need to delete */
1572  LAMBDA(void, (struct m0_be_emap_seg *seg,
1573  struct m0_ext *ext,
1574  uint64_t val) {
1575  /* cut left */
1576  M0_ASSERT(in_ext.e_start > seg->ee_ext.e_start);
1577 
1578  seg->ee_val = val;
1579  }),
1580  LAMBDA(void, (struct m0_be_emap_seg *seg,
1581  struct m0_ext *ext,
1582  uint64_t val) {
1583  /* cut right */
1584  M0_ASSERT(seg->ee_ext.e_end > in_ext.e_end);
1585  if (val < AET_MIN)
1586  seg->ee_val = val +
1587  (in_ext.e_end - seg->ee_ext.e_start);
1588  else
1589  seg->ee_val = val;
1590  }));
1592  rc = it.ec_op.bo_u.u_emap.e_rc;
1594  m0_be_emap_close(&it);
1595  }
1597  }
1598 
1599  if (rc != 0)
1600  M0_LOG(M0_ERROR, "Failed to insert emap record rc=%d", rc);
1601 }
1602 
1603 static void emap_fini(struct action *act)
1604 {
1605 }
1606 
1607 static int emap_kv_get(struct scanner *s, const struct be_btree_key_val *kv,
1608  struct m0_buf *key, struct m0_buf *val)
1609 {
1610  return deref(s, kv->btree_key, key->b_addr,
1611  sizeof(struct m0_be_emap_key)) ?:
1612  format_header_verify(key->b_addr,
1614  m0_format_footer_verify(key->b_addr, false) ?:
1615  deref(s, kv->btree_val, val->b_addr,
1616  sizeof(struct m0_be_emap_rec)) ?:
1617  format_header_verify(val->b_addr,
1619  m0_format_footer_verify(val->b_addr, false);
1620 }
1621 
1622 static int seghdr(struct scanner *s, struct rectype *r, char *buf)
1623 {
1624  return 0;
1625 }
1626 
1627 static int seghdr_ver(struct scanner *s, struct rectype *r, char *buf)
1628 {
1629  struct m0_be_seg_hdr *h = (void *)buf;
1630  struct m0_format_tag tag = {};
1631 
1633  M0_LOG(M0_INFO, "Segment header format: %hu:%hu:%u vs. %hu:%hu:%u.",
1634  tag.ot_version, tag.ot_version, tag.ot_footer_offset,
1635  r->r_tag.ot_version, r->r_tag.ot_version,
1636  r->r_tag.ot_footer_offset);
1637  M0_LOG(M0_INFO, "Protocol: %s", (char *)h->bh_be_version);
1638  M0_LOG(M0_INFO, " vs.: %s",
1639  m0_build_info_get()->bi_xcode_protocol_be_checksum);
1640  genadd(h->bh_gen);
1641  return 0;
1642 }
1643 
1644 static int seghdr_check(struct scanner *s, struct rectype *r, char *buf)
1645 {
1646  struct m0_be_seg_hdr *h = (void *)buf;
1647 
1648  if (s->s_gen != h->bh_gen) {
1649  genadd(h->bh_gen);
1650  printf("\nFound another segment header generation\n");
1652  return M0_ERR(-ETIME);
1653  }
1654  /*
1655  * Flush immediately to avoid losing this information within other lines
1656  * coming on the screen at the same time.
1657  */
1658  fflush(stdout);
1659 
1660  return 0;
1661 }
1662 
1663 static void genadd(uint64_t gen)
1664 {
1665  int i;
1666 
1667  for (i = 0; i < ARRAY_SIZE(g); ++i) {
1668  if (g[i].g_gen == gen || g[i].g_count == 0) {
1669  g[i].g_count++;
1670  g[i].g_gen = gen;
1671  break;
1672  }
1673  }
1674 }
1675 
1676 static int nv_scan_offset_init(uint64_t workers_nr,
1677  uint64_t partitions_nr)
1678 {
1679  uint64_t p;
1680 
1685  M0_PRE(workers_nr <= MAX_WORKERS_NR);
1686  M0_PRE(partitions_nr <= AO_NR);
1687 
1689  off_info.oi_workers_nr = workers_nr;
1690  off_info.oi_partitions_nr = partitions_nr;
1691 
1692  for (p = 0; p < off_info.oi_partitions_nr; p++)
1694  return 0;
1695 }
1696 
1697 static void nv_scan_offset_fini(void)
1698 {
1699  uint64_t p;
1700 
1701  for (p = 0; p < off_info.oi_partitions_nr; p++)
1704 }
1705 
1706 static off_t nv_scan_offset_get(off_t snapshot_size)
1707 {
1708  FILE *ofptr;
1709  int ret;
1710  off_t offset = snapshot_size;
1711  off_t max_offset = 0;
1712  uint64_t p;
1713  uint64_t w;
1714  struct part_info *pinfo;
1715  struct worker_off_info *winfo;
1716  struct scanner_off_info *sinfo;
1717 
1719  ofptr = fopen(offset_file, "r");
1720  if (ofptr == NULL) {
1722  return 0;
1723  }
1724  ret = fread(&nv_off_info, sizeof(struct nv_offset_info),
1725  1, ofptr);
1726  if ((ret == 1) &&
1729  /* look for lowest offset in active partitions */
1730  for (p = 0; p < off_info.oi_partitions_nr; p++) {
1731  /* skip idle partitions */
1732  if (pinfo->pi_act_added[p] == 0)
1733  continue;
1734  /* in case action/actions was/were added
1735  * but none of them is completed
1736  * then check for first bnode offset */
1737  if (pinfo->pi_act_done[p] == 0) {
1738  if (offset > pinfo->pi_1st_bnode_offset[p])
1739  offset = pinfo->pi_1st_bnode_offset[p];
1740  continue;
1741  }
1742  /* check for incomplete actions */
1743  for (w = 0; w < off_info.oi_workers_nr; w++) {
1744  winfo = &nv_off_info.noi_offset[w];
1745  /* discard workers which have NOT started
1746  * atleast single action for given partition
1747  * till now*/
1748  if (winfo->woi_act_added[p] == 0)
1749  continue;
1750 
1751 
1752  if (pinfo->pi_act_added[p] >
1753  pinfo->pi_act_done[p]) {
1754  if (offset > winfo->woi_offset[p])
1755  offset = winfo->woi_offset[p];
1756  } else {
1757  if (max_offset < winfo->woi_offset[p])
1758  max_offset =
1759  winfo->woi_offset[p];
1760  }
1761  printf("p=%" PRIu64 ",w=%" PRIu64 ",offset=%li\n",
1762  p, w, winfo->woi_offset[p]);
1763  }
1764  }
1765  /* all partitions were idle */
1766  if(offset == snapshot_size) {
1767  sinfo = &nv_off_info.noi_scanoff;
1768  if(sinfo->soi_scanqempty && sinfo->soi_bnodeqempty) {
1769  offset = sinfo->soi_offset;
1770  printf("partitions idle,scanner offset=%li\n",
1771  offset);
1772  } else
1773  offset = max_offset;
1774  }
1775  /* reset counters as there will NOT be any completions for
1776  * missed actions */
1777  memset(&nv_off_info.noi_pinfo.pi_act_added[0], 0,
1779  memset(&nv_off_info.noi_pinfo.pi_act_done[0], 0,
1781  for (w = 0; w < off_info.oi_workers_nr; w++) {
1782  winfo = &nv_off_info.noi_offset[w];
1783  memset(&winfo->woi_act_added[0], 0,
1784  sizeof(winfo->woi_act_added));
1785  memset(&winfo->woi_act_done[0], 0,
1786  sizeof(winfo->woi_act_done));
1787  }
1788  fclose(ofptr);
1790  } else {
1791  fclose(ofptr);
1793  return 0;
1794  }
1795  return offset;
1796 }
1797 
1798 static void nv_scan_offset_update(void)
1799 {
1800  FILE *ofptr;
1801  struct scanner_off_info *sinfo;
1802 
1804 
1805  ofptr = fopen(offset_file, "w+");
1806  if (ofptr == NULL) {
1807  printf("Cannot open seek_offset file :%s\n", offset_file);
1809  return;
1810  }
1811  sinfo = &nv_off_info.noi_scanoff;
1812 
1814  sinfo->soi_offset = beck_scanner.s_off;
1817  fwrite(&nv_off_info, sizeof(struct nv_offset_info),
1818  1, ofptr);
1819  fclose(ofptr);
1821  return;
1822 }
1823 
1824 static void builder_do(struct m0_be_tx_bulk *tb,
1825  struct m0_be_tx *tx,
1826  struct m0_be_op *op,
1827  void *datum,
1828  void *user,
1829  uint64_t worker_index,
1830  uint64_t partition)
1831 {
1832  struct action *act;
1833  struct builder *b = datum;
1834  struct worker_off_info *winfo;
1835 
1837  act = user;
1838  if (act != NULL) {
1839  b->b_act++;
1840  winfo = &nv_off_info.noi_offset[worker_index];
1841  winfo->woi_act_added[partition]++;
1842  act->a_ops->o_act(act, tx);
1843  act->a_ops->o_fini(act);
1844  }
1845  m0_be_op_done(op);
1846 }
1847 
1848 static void builder_done(struct m0_be_tx_bulk *tb,
1849  void *datum,
1850  void *user,
1851  uint64_t worker_index,
1852  uint64_t partition)
1853 {
1854  struct action *act;
1855  struct worker_off_info *winfo;
1856 
1857  act = user;
1858  if (act != NULL) {
1859  winfo = &nv_off_info.noi_offset[worker_index];
1860  winfo->woi_offset[partition] = act->a_node_offset;
1861  winfo->woi_act_done[partition]++;
1862  m0_mutex_lock(&off_info.oi_part_lock[partition]);
1863  nv_off_info.noi_pinfo.pi_act_done[partition]++;
1864  m0_mutex_unlock(&off_info.oi_part_lock[partition]);
1865 
1866  if (winfo->woi_act_done[partition] % NV_OFFSET_SAVE_ACT_DELTA ==
1867  0)
1869  m0_free(act);
1870  }
1871 }
1872 
1873 static void builder_work_put(struct m0_be_tx_bulk *tb, struct builder *b)
1874 {
1875  struct action *act;
1876  struct m0_be_tx_credit credit;
1877  struct part_info *pinfo;
1878  bool put_successful;
1879  int rc;
1880 
1881  do {
1882  act = qget(b->b_q);
1883  if (act->a_opc != AO_DONE) {
1884  credit = M0_BE_TX_CREDIT(0, 0);
1885  act->a_builder = b;
1886  rc = act->a_ops->o_prep(act, &credit);
1887  if (rc != 0)
1888  continue;
1889  M0_BE_OP_SYNC(op, put_successful =
1890  m0_be_tx_bulk_put(tb, &op, &credit, 0,
1891  act->a_opc, act));
1892  if (!put_successful)
1893  break;
1894 
1896  pinfo->pi_act_added[act->a_opc]++;
1897  /* save offset of first bnode in partitions */
1898  if (pinfo->pi_act_added[act->a_opc] == 1)
1899  pinfo->pi_1st_bnode_offset[act->a_opc] =
1900  act->a_node_offset;
1901  }
1902  } while (act->a_opc != AO_DONE);
1903  m0_be_tx_bulk_end(tb);
1904 }
1905 
1906 static void builder_thread(struct builder *b)
1907 {
1908  struct m0_be_tx_bulk_cfg tb_cfg;
1909  struct m0_be_tx_bulk tb = {};
1910  int rc;
1911 
1913  tb_cfg.tbc_dom = b->b_dom;
1914  tb_cfg.tbc_datum = b;
1915  tb_cfg.tbc_do = &builder_do,
1916  tb_cfg.tbc_done = &builder_done,
1917 
1918  rc = m0_be_tx_bulk_init(&tb, &tb_cfg);
1919  if (rc == 0) {
1920  M0_BE_OP_SYNC(op, ({
1921  m0_be_tx_bulk_run(&tb, &op);
1922  builder_work_put(&tb, b);
1923  }));
1924  rc = m0_be_tx_bulk_status(&tb);
1925  m0_be_tx_bulk_fini(&tb);
1926  }
1927 
1933  if (&b->b_backend != NULL) {
1936  }
1937 }
1938 
1939 static int ad_dom_init(struct builder *b)
1940 {
1941  int result;
1942  struct m0_stob_ad_module *module = &m0_get()->i_stob_ad_module;
1943  struct ad_domain_map *ad;
1944  char *cfg_init;
1945  char location[64];
1946  int len;
1947  struct m0_stob *stob;
1948  struct m0_stob_id stob_id;
1949  struct m0_stob_domain *dom;
1950  struct m0_stob_domain *stob_dom;
1951  char *stob_location;
1952  char *str_cfg_init = "directio=true";
1953  struct ad_dom_info *adom_info;
1954  uint64_t ad_dom_count;
1955 
1956  if (disable_directio)
1957  str_cfg_init = "directio=false";
1958 
1959  stob_location = m0_alloc(strlen(b->b_stob_path) + 20);
1960  if (stob_location == NULL)
1961  return M0_ERR(-ENOMEM);
1962 
1963  sprintf(stob_location, "linuxstob:%s%s",
1964  b->b_stob_path[0] == '/' ? "" : "./", b->b_stob_path);
1965  result = m0_stob_domain_init(stob_location, str_cfg_init, &dom);
1966  if (result != 0) {
1968  return M0_ERR(result);
1969  }
1970  b->b_ad_dom = dom;
1971 
1972  ad_dom_count = ad_domains_tlist_length(&module->sam_domains);
1973  M0_ALLOC_ARR(b->b_ad_domain, ad_dom_count);
1974  M0_ALLOC_ARR(b->b_ad_info, ad_dom_count);
1975  b->b_ad_dom_count = 0;
1976  m0_tl_for(ad_domains, &module->sam_domains, ad) {
1977  M0_ASSERT(b->b_ad_dom_count < ad_dom_count);
1978  M0_ALLOC_PTR(adom_info);
1979  if (adom_info == NULL) {
1980  result = -ENOMEM;
1981  break;
1982  }
1983  stob = NULL;
1984  stob_dom = NULL;
1985  b->b_ad_domain[b->b_ad_dom_count] = ad->adm_dom;
1986 
1988  &dom->sd_id, &stob_id);
1989  result = m0_stob_find(&stob_id, &stob);
1990  M0_ASSERT(result == 0);
1991 
1993  result = m0_stob_locate(stob);
1994  if (result != 0)
1995  break;
1996  }
1997 
1998  if (m0_stob_state_get(stob) == CSS_NOENT) {
1999  result = m0_stob_create(stob, NULL, NULL);
2000  if (result != 0)
2001  break;
2002  }
2003 
2004  len = snprintf(NULL, 0, "adstob:%"PRIu64,
2006  result = snprintf(location, len + 1, "adstob:%"PRIu64,
2008  M0_ASSERT_INFO(result == len, "result=%d", result);
2009 
2010  m0_stob_ad_init_cfg_make(&cfg_init,
2011  b->b_seg->bs_domain);
2012  result = m0_stob_domain_init(location, cfg_init, &stob_dom);
2013  if (result != 0)
2014  break;
2015 
2016  adom_info->stob = stob;
2017  adom_info->stob_dom = stob_dom;
2018  b->b_ad_info[b->b_ad_dom_count] = adom_info;
2019  b->b_ad_dom_count++;
2020  } m0_tl_endfor;
2021 
2022  /* In case of initializing ad_dom failure, cleanup meomory allocated*/
2023  if (result != 0)
2024  ad_dom_fini(b);
2026  return M0_RC(result);
2027 }
2028 
2029 static int builder_init(struct builder *b)
2030 {
2031  struct m0_be_ut_backend *ub = &b->b_backend;
2032  static struct m0_fid fid = M0_FID_TINIT('r', 1, 1);
2033  int result;
2034  int i;
2035 
2036  result = M0_REQH_INIT(&b->b_reqh,
2037  .rhia_dtm = (void *)1,
2038  .rhia_mdstore = (void *)1,
2039  .rhia_fid = &fid);
2040  if (result != 0)
2041  return M0_ERR(result);
2042  ub->but_stob_domain_location = m0_alloc(strlen(b->b_dom_path) + 20);
2043  if (ub->but_stob_domain_location == NULL)
2044  return M0_ERR(-ENOMEM); /* No cleanup, fatal anyway. */
2045  sprintf(ub->but_stob_domain_location, "linuxstob:%s%s",
2046  b->b_dom_path[0] == '/' ? "" : "./", b->b_dom_path);
2050  /* Check for any BE configuration overrides. */
2051  if (b->b_be_config_file) {
2053  &ub->but_dom_cfg);
2054  if (result != 0)
2055  return M0_ERR(result);
2056  }
2057  result = m0_be_ut_backend_init_cfg(ub, &ub->but_dom_cfg, false);
2058  if (result != 0)
2059  return M0_ERR(result);
2060  b->b_dom = &ub->but_dom;
2062  M0_ASSERT(b->b_seg0 != NULL);
2064  if (b->b_seg == NULL) {
2065  m0_be_ut_backend_seg_add2(ub, b->b_size, true, NULL, &b->b_seg);
2066  M0_ASSERT(b->b_seg != NULL);
2067  }
2068  printf("\nDestination segment header generation\n");
2070  printf("\n");
2071  /*
2072  * Flush immediately to avoid losing this information within other lines
2073  * coming on the screen at the same time.
2074  */
2075  fflush(stdout);
2076 
2077  result = m0_reqh_be_init(&b->b_reqh, b->b_seg);
2078  if (result != 0)
2079  return M0_ERR(result);
2080 
2081  result = m0_ctg_store_init(b->b_dom);
2082  if (result != 0)
2083  return M0_ERR(result);
2084 
2085  result = ctg_pver_fid_get(&b->b_pver_fid);
2086  if (result != 0)
2087  return M0_ERR(result);
2089  m0_ios_cdom_get(&b->b_reqh, &b->b_ios_cdom);
2091 
2093  b->b_mds_cdom = m0_reqh_lockers_get(&b->b_reqh,
2094  m0_get()->i_mds_cdom_key);
2096 
2097  for (i = 0; i < AO_NR - AO_EMAP_FIRST; i++)
2098  m0_mutex_init(&b->b_emaplock[i]);
2099  m0_mutex_init(&b->b_coblock);
2100  m0_mutex_init(&b->b_ctglock);
2101  result = ad_dom_init(b);
2102  if (result != 0)
2103  return M0_ERR(result);
2104  result = M0_THREAD_INIT(&b->b_thread, struct builder *,
2105  NULL, &builder_thread, b, "builder");
2106  return M0_RC(result);
2107 }
2108 
2109 static void ad_dom_fini(struct builder *b)
2110 {
2111  int i;
2112  int rc;
2113 
2114  /* Cleanup m0_stob_domains for AD domain initialized in ad_dom_init() */
2115  for (i = 0; i < b->b_ad_dom_count; ++i) {
2118  if (rc != 0)
2119  warn("Failed m0_stob_destroy for AD domain rc=%d", rc);
2120  m0_free(b->b_ad_info[i]);
2121  }
2123  m0_free(b->b_ad_info);
2124  m0_free(b->b_ad_domain);
2125 
2126 }
2127 
2128 static void builder_fini(struct builder *b)
2129 {
2130  int i;
2131 
2132  m0_thread_join(&b->b_thread);
2133  m0_thread_fini(&b->b_thread);
2134 
2135  for (i = 0; i < AO_NR - AO_EMAP_FIRST; i++)
2136  m0_mutex_fini(&b->b_emaplock[i]);
2137  m0_mutex_fini(&b->b_coblock);
2138  m0_mutex_fini(&b->b_ctglock);
2139 
2141  m0_reqh_be_fini(&b->b_reqh);
2142  ad_dom_fini(b);
2144  m0_reqh_fini(&b->b_reqh);
2146 
2147  printf("builder: actions: %9" PRId64 "\n", b->b_act);
2148 }
2149 
2154 static void be_cfg_default_init(struct m0_be_domain_cfg *dom_cfg,
2155  struct m0_be_tx_bulk_cfg *tb_cfg)
2156 {
2157  dom_cfg->bc_engine.bec_tx_active_max = 256;
2158  dom_cfg->bc_engine.bec_group_nr = 5;
2159  dom_cfg->bc_engine.bec_group_cfg.tgc_tx_nr_max = 128;
2161  M0_BE_TX_CREDIT(5621440, 961373440);
2162  dom_cfg->bc_engine.bec_group_cfg.tgc_payload_max = 367772160;
2163  dom_cfg->bc_engine.bec_tx_size_max =
2164  M0_BE_TX_CREDIT(1 << 18, 44UL << 20);
2165  dom_cfg->bc_engine.bec_tx_payload_max = 1 << 21;
2167  1ULL * M0_TIME_ONE_MSEC;
2169  50ULL * M0_TIME_ONE_MSEC;
2171  60000ULL * M0_TIME_ONE_MSEC;
2172  dom_cfg->bc_log.lc_full_threshold = 20 * (1 << 20);
2173  dom_cfg->bc_pd_cfg.bpdc_seg_io_nr = 5;
2174  dom_cfg->bc_log_discard_cfg.ldsc_items_max = 0x100;
2175  dom_cfg->bc_log_discard_cfg.ldsc_items_threshold = 0x80;
2177  M0_TIME_ONE_SECOND * 60ULL;
2178  tb_cfg->tbc_workers_nr = 64;
2179  tb_cfg->tbc_work_items_per_tx_max = 100;
2180 }
2181 
2182 static void be_cfg_update(struct m0_be_domain_cfg *cfg,
2183  const char *str_key,
2184  const char *str_value)
2185 {
2186  uint64_t value1_64;
2187  uint64_t value2_64;
2188  uint64_t value1_32;
2189  char *s1;
2190  char *s2;
2191  bool value_overridden = true;
2192 
2193  if (m0_streq(str_key, "tgc_size_max") ||
2194  m0_streq(str_key, "bec_tx_size_max")) {
2195 
2198  s1 = m0_strdup(str_value);
2199  s2 = strchr(s1, ',');
2200 
2201  *s2 = '\0';
2202  s2++;
2203 
2204  value1_64 = m0_strtou64(s1, NULL, 10);
2205  value2_64 = m0_strtou64(s2, NULL, 10);
2206 
2207  m0_free(s1);
2208 
2209  M0_ASSERT_INFO((value1_64 != ULLONG_MAX) &&
2210  (value2_64 != ULLONG_MAX),
2211  "Invalid value %s for variable %s in yaml file.",
2212  str_value, str_key);
2213 
2214  if (m0_streq(str_key, "tgc_size_max")) {
2216  M0_BE_TX_CREDIT(value1_64, value2_64);
2217  } else {
2218  cfg->bc_engine.bec_tx_size_max =
2219  M0_BE_TX_CREDIT(value1_64, value2_64);
2220  }
2221  } else if (m0_streq(str_key, "bpdc_seg_io_nr") ||
2222  m0_streq(str_key, "ldsc_items_max") ||
2223  m0_streq(str_key, "ldsc_items_threshold")) {
2224 
2227  value1_32 =m0_strtou32(str_value, NULL, 10);
2228 
2229  M0_ASSERT_INFO((value1_32 != ULONG_MAX),
2230  "Invalid value %s for variable %s in yaml file.",
2231  str_value, str_key);
2232 
2233  if (m0_streq(str_key, "bpdc_seg_io_nr")) {
2234  cfg->bc_pd_cfg.bpdc_seg_io_nr = value1_32;
2235  } else if (m0_streq(str_key, "ldsc_items_max")) {
2236  cfg->bc_log_discard_cfg.ldsc_items_max = value1_32;
2237  } else if (m0_streq(str_key, "ldsc_items_threshold")) {
2239  value1_32;
2240  }
2241  } else {
2242 
2244  value1_64 = m0_strtou64(str_value, NULL, 10);
2245 
2246  M0_ASSERT_INFO((value1_64 != ULLONG_MAX),
2247  "Invalid value %s for variable %s in yaml file.",
2248  str_value, str_key);
2249 
2250  if (m0_streq(str_key, "bec_tx_active_max"))
2251  cfg->bc_engine.bec_tx_active_max = value1_64;
2252  else if (m0_streq(str_key, "bec_group_nr"))
2253  cfg->bc_engine.bec_group_nr = value1_64;
2254  else if (m0_streq(str_key, "tgc_tx_nr_max"))
2255  cfg->bc_engine.bec_group_cfg.tgc_tx_nr_max = value1_64;
2256  else if (m0_streq(str_key, "tgc_payload_max"))
2258  value1_64;
2259  else if (m0_streq(str_key, "bec_tx_payload_max"))
2260  cfg->bc_engine.bec_tx_payload_max = value1_64;
2261  else if (m0_streq(str_key, "bec_group_freeze_timeout_min"))
2262  cfg->bc_engine.bec_group_freeze_timeout_min = value1_64;
2263  else if (m0_streq(str_key, "bec_group_freeze_timeout_max"))
2264  cfg->bc_engine.bec_group_freeze_timeout_max = value1_64;
2265  else if (m0_streq(str_key, "bec_group_freeze_timeout_limit"))
2267  value1_64;
2268  else if (m0_streq(str_key, "lc_full_threshold"))
2269  cfg->bc_log.lc_full_threshold = value1_64;
2270  else if (m0_streq(str_key, "ldsc_sync_timeout"))
2271  cfg->bc_log_discard_cfg.ldsc_sync_timeout = value1_64;
2272  else
2273  value_overridden = false;
2274  }
2275 
2276  if (value_overridden) {
2277  printf("%s = %s\n", str_key, str_value);
2278  fflush(stdout);
2279  }
2280 }
2281 
2282 static int be_cfg_from_yaml_update(const char *yaml_file,
2283  struct m0_be_domain_cfg *cfg)
2284 {
2285  FILE *fp;
2286  yaml_parser_t parser;
2287  yaml_token_t token;
2288  char *scalar_value;
2289  char key[MAX_KEY_LEN];
2290  char value[MAX_VALUE_LEN];
2291  int rc;
2292  bool is_key = false;
2293  bool key_received = false;
2294  bool value_received = false;
2295 
2296  fp = fopen(yaml_file, "r");
2297  M0_ASSERT(fp != NULL);
2298 
2299  if (!yaml_parser_initialize(&parser)) {
2300  printf("Failed to initialize yaml parser.\n");
2301  fclose(fp);
2302  return -ENOMEM;
2303  }
2304 
2305  yaml_parser_set_input_file(&parser, fp);
2306 
2307  printf("Changed following BE defaults:\n");
2308 
2309  do {
2310  rc = 0;
2311  yaml_parser_scan(&parser, &token);
2312  switch (token.type) {
2313  case YAML_KEY_TOKEN:
2314  is_key = true;
2315  break;
2316  case YAML_VALUE_TOKEN:
2317  is_key = false;
2318  break;
2319  case YAML_SCALAR_TOKEN:
2320  scalar_value = (char *)token.data.scalar.value;
2321  if (is_key) {
2322  strncpy(key, scalar_value, sizeof(key));
2323  key[sizeof(key) - 1] = '\0';
2324  key_received = true;
2325  } else {
2326  strncpy(value, scalar_value,
2327  sizeof(value));
2328  value[sizeof(value) - 1] = '\0';
2329  value_received = true;
2330  }
2331 
2332  if (key_received && value_received) {
2333  be_cfg_update(cfg, key, value);
2334  key_received = false;
2335  value_received = false;
2336  }
2337  break;
2338  case YAML_NO_TOKEN:
2339  rc = -EINVAL;
2340  break;
2341  default:
2342  break;
2343  }
2344 
2345  if (rc != 0) {
2346  fclose(fp);
2347  printf("Failed to parse %s\n", key);
2348  return rc;
2349  }
2350 
2351  if (token.type != YAML_STREAM_END_TOKEN)
2352  yaml_token_delete(&token);
2353 
2354  } while (token.type != YAML_STREAM_END_TOKEN);
2355 
2356  yaml_token_delete(&token);
2357 
2358  yaml_parser_delete(&parser);
2359 
2360  fclose(fp);
2361 
2362  return 0;
2363 }
2364 
2365 static void *builder_action(struct builder *b, size_t len,
2366  enum action_opcode opc,
2367  const struct action_ops *ops)
2368 {
2369  struct action *act;
2370 
2371  M0_PRE(len >= sizeof *act);
2372 
2373  act = m0_alloc(len);
2374  M0_ASSERT(act != NULL); /* Can we handle this? */
2375  act->a_opc = opc;
2376  act->a_ops = ops;
2377  act->a_builder = b;
2378  return act;
2379 }
2380 
2381 static int format_header_verify(const struct m0_format_header *h,
2382  uint16_t rtype)
2383 {
2384  struct m0_format_tag tag = {};
2385 
2387  if (memcmp(&tag, &rt[rtype].r_tag, sizeof tag) != 0)
2388  return M0_ERR(-EPROTO);
2389  return 0;
2390 }
2391 
2392 static bool btree_node_pre_is_valid(const struct m0_be_bnode *node,
2393  struct scanner *s)
2394 {
2395  M0_PRE(node != NULL);
2396  return
2397  (node->bt_num_active_key <= ARRAY_SIZE(node->bt_kv_arr)) &&
2398  (m0_fid_tget(&node->bt_backlink.bli_fid) == 'b') &&
2399  (node->bt_isleaf == (node->bt_level == 0)) &&
2400  m0_forall(i, node->bt_num_active_key,
2401  node->bt_kv_arr[i].btree_key != NULL &&
2402  node->bt_kv_arr[i].btree_val != NULL &&
2403  m0_be_seg_contains(s->s_seg,
2404  node->bt_kv_arr[i].btree_key) &&
2405  m0_be_seg_contains(s->s_seg,
2406  node->bt_kv_arr[i].btree_val));
2407 }
2408 
2409 static bool btree_node_post_is_valid(const struct m0_be_bnode *node,
2410  const struct m0_be_btree_kv_ops *ops)
2411 {
2412  M0_PRE(node != NULL);
2413  return ergo(node->bt_num_active_key > 1,
2414  m0_forall(i, node->bt_num_active_key - 1,
2415  ops->ko_compare(node->bt_kv_arr[i+1].btree_key,
2416  node->bt_kv_arr[i].btree_key)));
2417 }
2418 
2419 static bool btree_kv_is_valid(struct m0_be_bnode *node,
2420  int index, struct m0_buf *key)
2421 {
2422  M0_PRE(node != NULL);
2423  return m0_align(key->b_nob, sizeof(void *)) ==
2424  (uint64_t)node->bt_kv_arr[index].btree_val -
2425  (uint64_t)node->bt_kv_arr[index].btree_key;
2426 }
2427 
2428 static bool btree_kv_post_is_valid(struct scanner *s,
2429  struct m0_buf *key, struct m0_buf *val)
2430 {
2431  return s->s_max_reg_size > key->b_nob + val->b_nob;
2432 }
2433 
2434 static void btree_bad_kv_count_update(uint64_t type, int count)
2435 {
2436  M0_LOG(M0_DEBUG, "Discarded kv = %d from btree = %"PRIu64, count, type);
2438 }
2439 
2440 static bool fid_without_type_eq(const struct m0_fid *fid0,
2441  const struct m0_fid *fid1)
2442 {
2443  return m0_fid_eq(&M0_FID_TINIT(0, fid0->f_container, fid0->f_key),
2444  &M0_FID_TINIT(0, fid1->f_container, fid1->f_key));
2445 }
2446 
2447 static struct cache_slot *cache_lookup(struct cache *c, struct m0_fid *fid)
2448 {
2449  int i;
2450  int idx;
2451 
2452  for (i = 0, idx = c->c_head - 1; i < CACHE_SIZE; ++i, --idx) {
2453  if (idx < 0)
2454  idx = CACHE_SIZE - 1;
2455  if (m0_fid_eq(&c->c_slot[idx].cs_fid, fid))
2456  return &c->c_slot[idx];
2457  if (!m0_fid_is_set(&c->c_slot[idx].cs_fid))
2458  break;
2459  }
2460  return NULL;
2461 }
2462 
2463 static struct cache_slot *cache_insert(struct cache *c,
2464  const struct m0_fid *fid)
2465 {
2466  struct cache_slot *slot = &c->c_slot[c->c_head];
2467 
2468  slot->cs_fid = *fid;
2469  slot->cs_flags = 0;
2470  slot->cs_tree = NULL;
2471 
2472  if (++c->c_head == CACHE_SIZE)
2473  c->c_head = 0;
2474  return slot;
2475 }
2476 
2481 static int ctg_pver_fid_get(struct m0_fid *fid)
2482 {
2483  struct m0_buf key;
2484  struct m0_buf val;
2485  uint8_t kdata[M0_CAS_CTG_KEY_HDR_SIZE + sizeof(struct m0_fid)];
2486  uint8_t vdata[M0_CAS_CTG_VAL_HDR_SIZE +
2487  sizeof(struct m0_dix_layout)];
2488  uint64_t i;
2489  int rc;
2490 
2491  *((uint64_t *)(kdata)) = sizeof(struct m0_fid);
2492  key = M0_BUF_INIT(ARRAY_SIZE(kdata), kdata);
2493  val = M0_BUF_INIT(ARRAY_SIZE(vdata), vdata);
2494 
2496  for (i = 0; i < M0_DIX_FID_DEVICE_ID_BITS; i++) {
2497  *((struct m0_fid *)(kdata + M0_CAS_CTG_KEY_HDR_SIZE)) =
2499  0x02);
2502  cc_tree, &op,
2503  &key, &val),
2504  bo_u.u_btree.t_rc);
2505  if (rc == 0)
2506  break;
2507  }
2508  if (rc == 0) {
2509  *fid = ((struct m0_dix_layout *)
2510  (vdata + M0_CAS_CTG_VAL_HDR_SIZE))->u.dl_desc.ld_pver;
2511  } else
2512  M0_LOG(M0_ERROR, "Failed to get pool version fid, rc = %d", rc);
2513  return rc;
2514 }
2515 
2519 static int ctg_k_get(struct scanner *s, const void *addr, struct m0_buf *kbuf)
2520 {
2521  uint64_t len;
2522  int result;
2523 
2524  M0_CASSERT(sizeof len == M0_CAS_CTG_KEY_HDR_SIZE);
2525  result = deref(s, addr, &len, M0_CAS_CTG_KEY_HDR_SIZE);
2526  if (result != 0)
2527  return M0_ERR(result);
2528  if (len > s->s_max_reg_size)
2529  return M0_ERR(-EPERM);
2530  result = m0_buf_alloc(kbuf, len + M0_CAS_CTG_KEY_HDR_SIZE);
2531  if (result != 0)
2532  return M0_ERR(result);
2533  *(uint64_t *)kbuf->b_addr = len;
2534  result = deref(s, addr + M0_CAS_CTG_KEY_HDR_SIZE,
2535  kbuf->b_addr + M0_CAS_CTG_KEY_HDR_SIZE, len);
2536  if (result != 0)
2537  m0_buf_free(kbuf);
2538  return result;
2539 }
2540 
2544 static int ctg_v_get(struct scanner *s, const void *addr, struct m0_buf *vbuf)
2545 {
2546  struct hdr {
2547  uint64_t len;
2548  uint64_t ver;
2549  } hdr;
2550  int result;
2551 
2552  M0_CASSERT(sizeof(hdr) == M0_CAS_CTG_VAL_HDR_SIZE);
2553  result = deref(s, addr, &hdr, M0_CAS_CTG_VAL_HDR_SIZE);
2554  if (result != 0)
2555  return M0_ERR(result);
2556  if (hdr.len > s->s_max_reg_size)
2557  return M0_ERR(-EPERM);
2558  result = m0_buf_alloc(vbuf, hdr.len + M0_CAS_CTG_VAL_HDR_SIZE);
2559  if (result != 0)
2560  return M0_ERR(result);
2561  *(struct hdr *)vbuf->b_addr = hdr;
2562  result = deref(s, addr + M0_CAS_CTG_VAL_HDR_SIZE,
2563  vbuf->b_addr + M0_CAS_CTG_VAL_HDR_SIZE, hdr.len);
2564  if (result != 0)
2565  m0_buf_free(vbuf);
2566  return result;
2567 }
2568 
2569 static int ctg_btree_fid_get(struct m0_buf *kbuf, struct m0_fid *fid)
2570 {
2571  if (*(uint64_t *)(kbuf->b_addr) != sizeof (struct m0_fid))
2572  return -EINVAL;
2573 
2574  *fid = *(struct m0_fid *)(kbuf->b_addr + M0_CAS_CTG_KEY_HDR_SIZE);
2575  m0_fid_tchange(fid, 'b');
2576  return 0;
2577 }
2578 
2579 static int ctg_proc(struct scanner *s, struct btype *b,
2580  struct m0_be_bnode *node, off_t node_offset)
2581 {
2582  struct m0_be_bnode n = {};
2583  struct m0_be_btree_backlink *bl = &node->bt_backlink;
2584  struct m0_buf kl[ARRAY_SIZE(node->bt_kv_arr)] = {};
2585  struct m0_buf vl[ARRAY_SIZE(node->bt_kv_arr)] = {};
2586  struct ctg_action *ca;
2587  struct m0_fid fid;
2588  int i;
2589  int rc;
2590  bool ismeta;
2591 
2592  M0_PRE(bl->bli_type == M0_BBT_CAS_CTG);
2593  if (!btree_node_pre_is_valid(node, s) ||
2596  node->bt_num_active_key);
2597  return 0;
2598  }
2599  for (i = 0; i < node->bt_num_active_key; i++) {
2600  if (ctg_k_get(s, node->bt_kv_arr[i].btree_key,
2601  &kl[n.bt_num_active_key]) != 0) {
2603  continue;
2604  }
2605  if (btree_kv_is_valid(node, i, &kl[n.bt_num_active_key]) &&
2606  ctg_v_get(s, node->bt_kv_arr[i].btree_val,
2607  &vl[n.bt_num_active_key]) == 0) {
2608 
2609  if (btree_kv_post_is_valid(s, &kl[n.bt_num_active_key],
2610  &vl[n.bt_num_active_key]) &&
2611  !dry_run) {
2612  n.bt_kv_arr[n.bt_num_active_key].btree_key =
2613  kl[n.bt_num_active_key].b_addr;
2614  n.bt_num_active_key++;
2615  } else {
2616  m0_buf_free(&kl[n.bt_num_active_key]);
2617  m0_buf_free(&vl[n.bt_num_active_key]);
2618  }
2619  } else {
2621  m0_buf_free(&kl[n.bt_num_active_key]);
2622  }
2623  }
2625  btree_bad_kv_count_update(bl->bli_type, n.bt_num_active_key);
2626  for (i = 0; i < n.bt_num_active_key; i++) {
2627  m0_buf_free(&kl[i]);
2628  m0_buf_free(&vl[i]);
2629  }
2630  return 0;
2631  }
2632  ismeta = fid_without_type_eq(&bl->bli_fid, &m0_cas_meta_fid) ||
2634  for (i = 0; i < n.bt_num_active_key; i++) {
2635  if (ismeta) {
2636  rc = ctg_btree_fid_get(&kl[i], &fid);
2637  m0_buf_free(&kl[i]);
2638  m0_buf_free(&vl[i]);
2639  if (rc != 0 ||
2640  fid_without_type_eq(&fid, &M0_FID_INIT(0, 0)) ||
2644  continue;
2645  if (rc != 0)
2647  } else if (dry_run)
2648  continue;
2649  else
2650  fid = bl->bli_fid;
2651  ca = scanner_action(sizeof *ca, AO_CTG, &ctg_ops);
2652  ca->cta_fid = fid;
2653  ca->cta_key = kl[i];
2654  ca->cta_val = vl[i];
2655  ca->cta_ismeta = ismeta;
2656  ca->cta_act.a_node_offset = node_offset;
2657  qput(s->s_q, (struct action *)ca);
2658  }
2659  return 0;
2660 }
2661 
2663  struct builder *b,
2664  struct m0_fid *cas_ctg_fid,
2665  struct m0_be_tx_credit *accum)
2666 {
2667  struct cache_slot *slot;
2668 
2669  slot = cache_lookup(&b->b_cache, cas_ctg_fid);
2670  if (slot == NULL)
2671  slot = cache_insert(&b->b_cache, cas_ctg_fid);
2672  m0_ctg_create_credit(accum);
2673  ca->cta_cid.ci_fid = ca->cta_fid;
2674  m0_fid_tchange(&ca->cta_cid.ci_fid, 'T');
2676  m0_dix_ldesc_init(&ca->cta_cid.ci_layout.u.dl_desc,
2677  &(struct m0_ext) { .e_start = 0,
2678  .e_end = IMASK_INF },
2679  1, HASH_FNC_CITY, &b->b_pver_fid);
2680  m0_ctg_ctidx_insert_credits(&ca->cta_cid, accum);
2681  return slot;
2682 }
2683 
2684 static int ctg_prep(struct action *act, struct m0_be_tx_credit *accum)
2685 {
2686  struct ctg_action *ca = M0_AMB(ca, act, cta_act);
2687  struct m0_be_btree tree = {};
2688 
2690  ca->cta_slot = ctg_getslot_insertcred(ca, act->a_builder,
2691  &ca->cta_fid, accum);
2692  m0_be_btree_insert_credit(&tree, 1, ca->cta_key.b_nob,
2693  ca->cta_val.b_nob, accum);
2695  return 0;
2696 }
2697 
2698 static struct m0_cas_ctg *ctg_create_meta(struct ctg_action *ca,
2699  struct m0_be_tx *tx)
2700 {
2701  struct m0_cas_ctg *cas_ctg;
2702  int rc;
2703  struct m0_fid cfid;
2704 
2705  cfid = ca->cta_fid;
2706  m0_fid_tchange(&cfid, 'T');
2707  rc = m0_ctg_create(ca->cta_act.a_builder->b_seg, tx, &cas_ctg, &cfid);
2708  if (rc == 0) {
2710  cas_ctg, tx) ?:
2712  if (rc != 0)
2713  M0_LOG(M0_DEBUG, "Failed to insert meta record rc=%d",
2714  rc);
2715  } else {
2716  M0_LOG(M0_DEBUG, "BTree not created rc=%d", rc);
2717  return NULL;
2718  }
2719  return cas_ctg;
2720 }
2721 
2722 static void ctg_act(struct action *act, struct m0_be_tx *tx)
2723 {
2724  struct ctg_action *ca = M0_AMB(ca, act, cta_act);
2725  struct m0_cas_ctg *cc;
2726  int rc;
2727 
2729  if (ca->cta_slot->cs_tree == NULL) {
2731  &M0_FID_TINIT('T',
2732  ca->cta_fid.f_container,
2733  ca->cta_fid.f_key),
2734  &cc);
2735  if (rc == -ENOENT) {
2736  cc = ctg_create_meta(ca, tx);
2737  } else if (rc != 0) {
2738  M0_LOG(M0_DEBUG, "Btree not found rc=%d", rc);
2740  return;
2741  }
2742  if (cc != NULL) {
2744  ca->cta_slot->cs_tree = &cc->cc_tree;
2745  }
2746  }
2747  if (!ca->cta_ismeta && ca->cta_slot->cs_tree != NULL) {
2750  tx, &op, &ca->cta_key,
2751  &ca->cta_val),
2752  bo_u.u_btree.t_rc);
2753 
2754  if (rc == 0) {
2757  ca->cta_val.b_nob);
2758  } else
2759  M0_LOG(M0_DEBUG, "Failed to insert record rc=%d", rc);
2760  }
2762 }
2763 
2764 static void ctg_fini(struct action *act)
2765 {
2766  struct ctg_action *ca = M0_AMB(ca, act, cta_act);
2767 
2768  if (!ca->cta_ismeta) {
2769  m0_buf_free(&ca->cta_key);
2770  m0_buf_free(&ca->cta_val);
2771  }
2772 }
2773 
2774 static const struct action_ops ctg_ops = {
2775  .o_prep = &ctg_prep,
2776  .o_act = &ctg_act,
2777  .o_fini = &ctg_fini
2778 };
2779 
2780 static bool qinvariant(const struct queue *q)
2781 {
2782  return _0C((q->q_nr == 0) == (q->q_head == NULL &&
2783  q->q_tail == NULL)) &&
2784  _0C((q->q_nr == 1) == (q->q_head == q->q_tail &&
2785  q->q_head != NULL)) &&
2786  _0C((q->q_nr > 1) == (q->q_head != q->q_tail &&
2787  q->q_head != NULL &&
2788  q->q_tail != NULL)) &&
2789  _0C(q->q_nr <= q->q_max);
2790 }
2791 
2792 static void qinit(struct queue *q, uint64_t maxnr)
2793 {
2794  int result;
2795  M0_PRE(M0_IS0(q));
2796  result = pthread_mutex_init(&q->q_lock, NULL);
2797  M0_ASSERT(result == 0);
2798  result = pthread_cond_init(&q->q_cond, NULL);
2799  M0_ASSERT(result == 0);
2800  q->q_max = maxnr;
2801  M0_POST(qinvariant(q));
2802 }
2803 
2804 static void qfini(struct queue *q)
2805 {
2806  int result;
2807  M0_PRE(q->q_nr == 0 && qinvariant(q));
2808  result = pthread_cond_destroy(&q->q_cond);
2809  M0_ASSERT(result == 0);
2810  result = pthread_mutex_destroy(&q->q_lock);
2811  M0_ASSERT(result == 0);
2812  M0_SET0(q);
2813 }
2814 
2815 static void qput(struct queue *q, struct action *act)
2816 {
2817  M0_ASSERT(act->a_next == NULL);
2818  M0_ASSERT(act->a_prev == NULL);
2819 
2820  pthread_mutex_lock(&q->q_lock);
2821  M0_PRE(qinvariant(q));
2822  while (q->q_nr == q->q_max)
2823  pthread_cond_wait(&q->q_cond, &q->q_lock);
2824  act->a_next = q->q_head;
2825  if (q->q_head != NULL)
2826  q->q_head->a_prev = act;
2827  q->q_head = act;
2828  if (q->q_tail == NULL) {
2829  q->q_tail = act;
2830  pthread_cond_broadcast(&q->q_cond);
2831  }
2832  q->q_nr++;
2833  M0_POST(qinvariant(q));
2834  pthread_mutex_unlock(&q->q_lock);
2835 }
2836 
2837 static struct action *qpeek(struct queue *q)
2838 {
2839  struct action *act;
2840 
2841  act = q->q_tail;
2842  if (act != NULL) {
2843  q->q_tail = act->a_prev;
2844  if (q->q_tail == NULL)
2845  q->q_head = NULL;
2846  else
2847  q->q_tail->a_next = NULL;
2848  act->a_next = NULL;
2849  act->a_prev = NULL;
2850  if (q->q_nr == q->q_max)
2851  pthread_cond_broadcast(&q->q_cond);
2852  q->q_nr--;
2853  }
2854  return act;
2855 }
2856 
2857 static struct action *qget(struct queue *q)
2858 {
2859  struct action *act;
2860 
2861  pthread_mutex_lock(&q->q_lock);
2862  M0_PRE(qinvariant(q));
2863  while (q->q_nr == 0)
2864  pthread_cond_wait(&q->q_cond, &q->q_lock);
2865  act = qpeek(q);
2866  M0_POST(qinvariant(q));
2867  pthread_mutex_unlock(&q->q_lock);
2868  return act;
2869 }
2870 
2871 static struct action *qtry(struct queue *q)
2872 {
2873  struct action *act;
2874 
2875  pthread_mutex_lock(&q->q_lock);
2876  M0_PRE(qinvariant(q));
2877  act = qpeek(q);
2878  M0_POST(qinvariant(q));
2879  pthread_mutex_unlock(&q->q_lock);
2880  return act;
2881 }
2882 
2883 static bool isqempty(struct queue *q)
2884 {
2885  bool ret;
2886 
2887  pthread_mutex_lock(&q->q_lock);
2888  M0_PRE(qinvariant(q));
2889  ret = (q->q_nr == 0) ? true : false;
2890  pthread_mutex_unlock(&q->q_lock);
2891  return ret;
2892 }
2893 static const struct recops btreeops = {
2894  .ro_proc = &btree,
2895  .ro_check = &btree_check
2896 };
2897 
2898 static const struct recops bnodeops = {
2899  .ro_proc = &bnode,
2900  .ro_check = &bnode_check
2901 };
2902 
2903 static const struct recops seghdrops = {
2904  .ro_proc = &seghdr,
2905  .ro_ver = &seghdr_ver,
2906  .ro_check = &seghdr_check,
2907 };
2908 
2916 static int cob_kv_get(struct scanner *s, const struct be_btree_key_val *kv,
2917  struct m0_buf *key, struct m0_buf *val)
2918 {
2919  int result;
2920  struct m0_cob_nskey nskey;
2921 
2923  result = deref(s, kv->btree_key, &nskey, sizeof nskey);
2924  if (result != 0)
2925  return M0_ERR(result);
2926  if (m0_cob_nskey_size(&nskey) > s->s_max_reg_size)
2927  return M0_ERR(-EPERM);
2928  result = m0_buf_alloc(key, m0_cob_nskey_size(&nskey));
2929  if (result != 0)
2930  return M0_ERR(result);
2931  *(struct m0_cob_nskey *)key->b_addr = nskey;
2932  result = deref(s, kv->btree_key + sizeof nskey,
2933  key->b_addr + sizeof nskey,
2934  nskey.cnk_name.b_len);
2935  if (result != 0) {
2936  m0_buf_free(key);
2937  return M0_ERR(result);
2938  }
2940  result = deref(s, kv->btree_val,
2941  val->b_addr, sizeof(struct m0_cob_nsrec));
2942  if (result != 0)
2943  m0_buf_free(key);
2944  return result;
2945 }
2946 
2954 static int cob_proc(struct scanner *s, struct btype *b,
2955  struct m0_be_bnode *node, off_t node_offset)
2956 {
2957  struct cob_action *ca;
2958  int i;
2959  int rc;
2960  struct m0_be_btree_backlink *bb = &node->bt_backlink;
2961  struct m0_cob_nskey *nskey;
2962  uint64_t inv_cob_off;
2963 
2965 
2966  for (i = 0; i < node->bt_num_active_key; i++) {
2967  ca = scanner_action(sizeof*ca, AO_COB,&cob_ops);
2968  ca->coa_fid = bb->bli_fid;
2969  ca->coa_act.a_node_offset = node_offset;
2970 
2971  ca->coa_val = M0_BUF_INIT(sizeof(struct m0_cob_nsrec),
2972  ca->coa_valdata);
2973  rc = cob_kv_get(s, &node->bt_kv_arr[i], &ca->coa_key,
2974  &ca->coa_val);
2975  if (rc != 0) {
2977  m0_free(ca);
2978  continue;
2979  }
2980 
2982  M0_FORMAT_TYPE_COB_NSREC) == 0) &&
2983  (m0_format_footer_verify(ca->coa_valdata, false) == 0)) {
2984  if (!dry_run)
2985  qput(s->s_q, (struct action *)ca);
2986  else {
2987  m0_buf_free(&ca->coa_key);
2988  m0_free(ca);
2989  }
2990  } else {
2991  if (s->s_print_invalid_oids) {
2992  nskey = ca->coa_key.b_addr;
2993  inv_cob_off = node->bt_kv_arr[i].btree_val -
2994  s->s_seg->bs_addr;
2995  M0_LOG(M0_ERROR, "Found incorrect COB entry at "
2996  "segment offset %" PRIx64 " for GOB "
2997  FID_F, inv_cob_off,
2998  FID_P(&nskey->cnk_pfid));
2999  }
3000 
3002  m0_buf_free(&ca->coa_key);
3003  m0_free(ca);
3004  }
3005  }
3006 
3007  return 0;
3008 }
3009 
3015 static int cob_prep(struct action *act, struct m0_be_tx_credit *accum)
3016 {
3017  struct cob_action *ca = container_of(act, struct cob_action,
3018  coa_act);
3019  struct m0_cob_nsrec *nsrec = ca->coa_val.b_addr;
3020  struct m0_stob_id stob_id;
3021 
3023  if (m0_fid_validate_cob(&nsrec->cnr_fid)) {
3024  m0_fid_convert_cob2adstob(&nsrec->cnr_fid, &stob_id);
3025  m0_cc_stob_cr_credit(&stob_id, accum);
3026  }
3028  accum);
3030  accum);
3032  return 0;
3033 }
3034 
3041 static void cob_act(struct action *act, struct m0_be_tx *tx)
3042 {
3043  struct cob_action *ca = container_of(act, struct cob_action,
3044  coa_act);
3045  struct m0_be_btree *ios_ns = &act->a_builder->b_ios_cdom->
3046  cd_namespace;
3047  struct m0_be_btree *mds_ns = &act->a_builder->b_mds_cdom->
3048  cd_namespace;
3049  struct m0_cob cob = {};
3050  struct m0_cob_nskey *nskey = ca->coa_key.b_addr;
3051  struct m0_cob_nsrec *nsrec = ca->coa_val.b_addr;
3052  int rc = 0;
3053  struct m0_stob_id stob_id;
3054  struct m0_stob_domain *sdom;
3055  struct m0_stob_ad_domain *adom;
3056  struct m0_be_emap_cursor it = {};
3057  struct m0_uint128 prefix;
3058  int id;
3059 
3061 
3062  if (m0_fid_eq(&ca->coa_fid, &ios_ns->bb_backlink.bli_fid))
3064  else if (m0_fid_eq(&ca->coa_fid, &mds_ns->bb_backlink.bli_fid))
3066  else
3067  rc = -ENODATA;
3068 
3069  cob.co_nsrec = *nsrec;
3070  rc = rc ?: m0_cob_name_add(&cob, nskey, nsrec, tx);
3071 
3072  if (rc == 0 && m0_fid_validate_cob(&nsrec->cnr_fid)) {
3073  m0_fid_convert_cob2adstob(&nsrec->cnr_fid, &stob_id);
3075  adom = stob_ad_domain2ad(sdom);
3076  prefix = M0_UINT128(stob_id.si_fid.f_container,
3077  stob_id.si_fid.f_key);
3078  emap_dom_find(&ca->coa_act,
3080  &id);
3084  &prefix, 0, &it),
3085  bo_u.u_emap.e_rc);
3086  if (rc == 0)
3087  m0_be_emap_close(&it);
3088  else {
3090  m0_be_emap_obj_insert(&adom->
3091  sad_adata,
3092  tx, &op,
3093  &prefix,
3094  AET_HOLE),
3095  bo_u.u_emap.e_rc);
3096  }
3098  }
3100 }
3101 
3106 static void cob_fini(struct action *act)
3107 {
3108  struct cob_action *ca = container_of(act, struct cob_action, coa_act);
3109 
3110  m0_buf_free(&ca->coa_key);
3111 }
3112 
3113 static int noop_prep(struct action *act, struct m0_be_tx_credit *cred)
3114 {
3115  return 0;
3116 }
3117 
3118 static void noop_act(struct action *act, struct m0_be_tx *tx)
3119 {
3120 }
3121 
3122 static void noop_fini(struct action *act)
3123 {
3124 }
3125 
3126 static const struct action_ops cob_ops = {
3127  .o_prep = &cob_prep,
3128  .o_act = &cob_act,
3129  .o_fini = &cob_fini
3130 };
3131 
3132 static const struct action_ops done_ops = {
3133  .o_prep = &noop_prep,
3134  .o_act = &noop_act,
3135  .o_fini = &noop_fini
3136 };
3137 
3138 static void test_queue(void)
3139 {
3140  enum { NR = 10000, THREADS = 51, MAX = 40 };
3141  struct m0_thread tp[THREADS] = {};
3142  struct m0_thread tg[THREADS] = {};
3143  struct m0_thread tt[THREADS] = {};
3144  struct queue q = {};
3145  int i;
3146 
3147 
3148  printf("\tQueue...");
3149  qinit(&q, MAX);
3150  for (i = 0; i < THREADS; ++i) {
3151  M0_THREAD_INIT(&tp[i], void *, NULL,
3152  LAMBDA(void, (void *nonce) {
3153  int n;
3154  struct action *act;
3155 
3156  for (n = 0; n < 2 * NR; ++n) { /* Twice. */
3157  M0_ALLOC_PTR(act);
3158  M0_ASSERT(act != NULL);
3159  qput(&q, act);
3160  }
3161  printf(" +%"PRIi64, q.q_nr);
3162  }), NULL, "qp-%d", i);
3163  M0_THREAD_INIT(&tg[i], void *, NULL,
3164  LAMBDA(void, (void *nonce) {
3165  int n = NR;
3166  struct action *act;
3167 
3168  while (n > 0) {
3169  act = qget(&q);
3170  M0_ASSERT(act != NULL);
3171  n--;
3172  m0_free(act);
3173  }
3174  printf(" -%"PRIi64, q.q_nr);
3175  }), NULL, "qg-%d", i);
3176  M0_THREAD_INIT(&tt[i], void *, NULL,
3177  LAMBDA(void, (void *nonce) {
3178  int n = NR;
3179  struct action *act;
3180 
3181  while (n > 0) {
3182  act = qtry(&q);
3183  if (act != NULL) {
3184  n--;
3185  m0_free(act);
3186  }
3187  }
3188  printf(" ?%"PRIi64, q.q_nr);
3189  }), NULL, "qt-%d", i);
3190  }
3191  for (i = 0; i < THREADS; ++i) {
3192  m0_thread_join(&tp[i]);
3193  m0_thread_fini(&tp[i]);
3194  m0_thread_join(&tg[i]);
3195  m0_thread_fini(&tg[i]);
3196  m0_thread_join(&tt[i]);
3197  m0_thread_fini(&tt[i]);
3198  }
3199  M0_ASSERT(q.q_nr == 0);
3200  qfini(&q);
3201  printf(" ok.\n");
3202 }
3203 
3204 static void test(void)
3205 {
3206  test_queue();
3207 }
3208 
3209 #undef M0_TRACE_SUBSYSTEM
3210 
3213 /*
3214  * Local variables:
3215  * c-indentation-style: "K&R"
3216  * c-basic-offset: 8
3217  * tab-width: 8
3218  * fill-column: 80
3219  * scroll-step: 1
3220  * End:
3221  */
3222 /*
3223  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
3224  */
m0_bcount_t tgc_payload_max
Definition: tx_group.h:66
struct m0_cob_nsrec co_nsrec
Definition: cob.h:590
#define M0_GETOPTS(progname, argc, argv,...)
Definition: getopts.h:169
uint32_t bh_items_nr
Definition: seg_internal.h:50
static struct ctx cc
Definition: beck.c:235
static void cob_fini(struct action *act)
Definition: beck.c:3106
uint64_t id
Definition: cob.h:2380
void * bs_addr
Definition: seg.h:71
m0_bindex_t ek_offset
static struct m0_fid gob_fid
Definition: net.c:115
pthread_cond_t q_cond
Definition: beck.c:82
static const struct action_ops done_ops
Definition: beck.c:417
M0_INTERNAL void m0_reqh_be_fini(struct m0_reqh *reqh)
Definition: reqh.c:289
static struct m0_addb2_philter p
Definition: consumer.c:40
M0_INTERNAL void m0_ctg_ctidx_insert_credits(struct m0_cas_id *cid, struct m0_be_tx_credit *accum)
Definition: ctg_store.c:1962
struct m0_be_domain * bs_domain
Definition: seg.h:82
static bool btree_kv_is_valid(struct m0_be_bnode *node, int index, struct m0_buf *key)
Definition: beck.c:2419
#define M0_PRE(cond)
m0_time_t bec_group_freeze_timeout_max
Definition: engine.h:81
static struct cache_slot * ctg_getslot_insertcred(struct ctg_action *ca, struct builder *b, struct m0_fid *cas_ctg_fid, struct m0_be_tx_credit *accum)
Definition: beck.c:2662
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
uint64_t bs_gen
Definition: seg.h:76
static void nv_scan_offset_fini(void)
Definition: beck.c:1697
static int ctg_k_get(struct scanner *s, const void *addr, struct m0_buf *kbuf)
Definition: beck.c:2519
char bh_be_version[M0_BE_SEG_HDR_VERSION_LEN_MAX+1]
Definition: seg_internal.h:53
Definition: cob.h:581
M0_INTERNAL void m0_be_tx_bulk_run(struct m0_be_tx_bulk *tb, struct m0_be_op *op)
Definition: tx_bulk.c:565
M0_INTERNAL int m0_be_tx_bulk_init(struct m0_be_tx_bulk *tb, struct m0_be_tx_bulk_cfg *tb_cfg)
Definition: tx_bulk.c:136
struct m0_format_footer er_footer
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
M0_INTERNAL int m0_be_ut_backend_init_cfg(struct m0_be_ut_backend *ut_be, const struct m0_be_domain_cfg *cfg, bool mkfs)
Definition: stubs.c:231
const struct recops * r_ops
Definition: beck.c:141
int(* ro_ver)(struct scanner *s, struct rectype *r, char *buf)
Definition: beck.c:147
#define m0_strdup(s)
Definition: string.h:43
static struct m0_cas_ctg * ctg_create_meta(struct ctg_action *ca, struct m0_be_tx *tx)
Definition: beck.c:2698
m0_bindex_t e_end
Definition: ext.h:40
struct m0_be_tx_credit b_cred
Definition: beck.c:259
#define M0_FLAGARG(ch, desc, ptr)
Definition: getopts.h:232
M0_INTERNAL void m0_format_header_unpack(struct m0_format_tag *dest, const struct m0_format_header *src)
Definition: format.c:49
static struct m0_stob_ad_domain * emap_dom_find(const struct action *act, const struct m0_fid *emap_fid, int *lockid)
Definition: beck.c:1362
static struct m0_semaphore q
Definition: rwlock.c:55
M0_INTERNAL void m0_be_tx_bulk_end(struct m0_be_tx_bulk *tb)
Definition: tx_bulk.c:619
#define NULL
Definition: misc.h:38
uint64_t b_size
Definition: beck.c:261
static void generation_id_print(uint64_t gen)
Definition: beck.c:825
static struct action * qget(struct queue *q)
Definition: beck.c:2857
M0_INTERNAL int m0_stob_locate(struct m0_stob *stob)
Definition: stob.c:128
struct m0_mutex oi_lock
Definition: beck.c:320
#define _B(t, proc)
Definition: beck.c:457
Definition: idx_mock.c:52
struct cache_slot c_slot[CACHE_SIZE]
Definition: beck.c:236
void m0_fini(void)
Definition: init.c:318
#define ergo(a, b)
Definition: misc.h:293
m0_bcount_t bs_offset
Definition: seg.h:70
const struct m0_xcode_enum_val * xe_val
Definition: enum.h:67
int m0_thread_join(struct m0_thread *q)
Definition: kthread.c:169
uint64_t c_node
Definition: beck.c:153
Definition: beck.c:170
#define M0_REQH_INIT(reqh,...)
Definition: reqh.h:262
static int builder_init(struct builder *b)
Definition: beck.c:2029
void * b_addr
Definition: buf.h:39
static void builder_do(struct m0_be_tx_bulk *tb, struct m0_be_tx *tx, struct m0_be_op *op, void *datum, void *user, uint64_t worker_index, uint64_t partition)
Definition: beck.c:1824
M0_INTERNAL void m0_be_btree_lookup(struct m0_be_btree *tree, struct m0_be_op *op, const struct m0_buf *key, struct m0_buf *value)
Definition: btree.c:2033
static void stats_print(void)
Definition: beck.c:1022
uint64_t noi_magic
Definition: beck.c:310
static FILE * f
Definition: adieu.c:79
struct m0_mutex s_lock
Definition: beck.c:102
uint64_t pi_act_added[AO_NR]
Definition: beck.c:304
static int ctg_btree_fid_get(struct m0_buf *kbuf, struct m0_fid *fid)
Definition: beck.c:2569
bool cta_ismeta
Definition: beck.c:511
static uint64_t tag(uint8_t code, uint64_t id)
Definition: addb2.c:1047
M0_INTERNAL void m0_ctg_store_fini(void)
Definition: ctg_store.c:870
struct m0_stob_ad_module i_stob_ad_module
Definition: instance.h:120
static void seg_get(FILE *fp, struct m0_be_seg *out)
Definition: beck.c:884
union @126 u
int(* ro_proc)(struct scanner *s, struct rectype *r, char *buf)
Definition: beck.c:146
#define M0_LOG(level,...)
Definition: trace.h:167
static struct action * qpeek(struct queue *q)
Definition: beck.c:2837
action_opcode
Definition: beck.c:175
uint64_t woi_act_done[AO_NR]
Definition: beck.c:294
Definition: beck.c:189
uint64_t ee_val
Definition: extmap.h:193
struct m0_format_footer cs_footer
Definition: ctg_store.h:133
struct m0_buf coa_val
Definition: beck.c:208
#define M0_CASSERT(cond)
uint64_t s_align[2]
Definition: beck.c:133
static void fini(void)
Definition: beck.c:1148
Definition: beck.c:177
bool s_print_invalid_oids
Definition: beck.c:109
#define M0_FID_INIT(container, key)
Definition: fid.h:84
static void genadd(uint64_t gen)
Definition: beck.c:1663
static struct net_test_cmd_node * node
Definition: commands.c:72
static bool btree_node_post_is_valid(const struct m0_be_bnode *node, const struct m0_be_btree_kv_ops *ops)
Definition: beck.c:2409
static int ctg_v_get(struct scanner *s, const void *addr, struct m0_buf *vbuf)
Definition: beck.c:2544
static int deref(struct scanner *s, const void *addr, void *buf, size_t nob)
Definition: beck.c:1242
Definition: ad.h:190
struct m0_reqh b_reqh
Definition: beck.c:249
m0_bcount_t bs_size
Definition: seg.h:69
static int emap_prep(struct action *act, struct m0_be_tx_credit *cred)
Definition: beck.c:1480
uint64_t m0_time_nanoseconds(const m0_time_t time)
Definition: time.c:89
static void scanner_thread(struct scanner *s)
Definition: beck.c:802
static int scanner_cache_init(struct scanner *s)
Definition: beck.c:942
static struct m0_uint128 prefix
Definition: extmap.c:45
#define M0_BE_OP_SYNC(op_obj, action)
Definition: op.h:190
M0_INTERNAL void m0_ios_cdom_get(struct m0_reqh *reqh, struct m0_cob_domain **out)
Definition: io_service.c:463
m0_be_btree_type
Definition: btree.h:117
M0_INTERNAL void m0_fid_convert_cob2adstob(const struct m0_fid *cob_fid, struct m0_stob_id *stob_id)
Definition: fid_convert.c:38
struct m0_format_footer cb_footer
Definition: balloc.h:644
char * but_stob_domain_location
Definition: helper.h:58
static bool disable_directio
Definition: beck.c:527
struct action emap_act
Definition: beck.c:283
static uint64_t magic(const struct m0_tl_descr *d, const void *obj)
Definition: tlist.c:286
M0_INTERNAL void m0_be_emap_obj_insert(struct m0_be_emap *map, struct m0_be_tx *tx, struct m0_be_op *op, const struct m0_uint128 *prefix, uint64_t val)
Definition: extmap.c:744
M0_INTERNAL const struct m0_fid m0_cas_meta_fid
Definition: cas.c:146
M0_TL_DECLARE(ad_domains, M0_EXTERN, struct ad_domain_map)
const struct m0_fid_type m0_cob_fid_type
Definition: cob.c:117
struct m0_dix_layout ci_layout
Definition: cas.h:120
uint64_t sg_gen
Definition: seg.h:95
int const char const void * value
Definition: dir.c:325
const struct m0_stob_type m0_stob_ad_type
Definition: ad.c:1003
M0_INTERNAL struct m0_be_seg * m0_be_domain_seg0_get(struct m0_be_domain *dom)
Definition: domain.c:466
static const struct action_ops ctg_ops
Definition: beck.c:418
struct m0_cob_domain * b_ios_cdom
Definition: beck.c:269
M0_INTERNAL uint8_t m0_fid_tget(const struct m0_fid *fid)
Definition: fid.c:133
M0_INTERNAL void m0_be_emap_close(struct m0_be_emap_cursor *it)
Definition: extmap.c:360
static int emap_entry_lookup(struct m0_stob_ad_domain *adom, struct m0_uint128 prefix, m0_bindex_t offset, struct m0_be_emap_cursor *it)
Definition: beck.c:1465
static struct m0_be_emap_cursor it
Definition: extmap.c:46
struct m0_cob_domain * b_mds_cdom
Definition: beck.c:271
off_t a_node_offset
Definition: beck.c:193
uint64_t cs_flags
Definition: beck.c:227
const struct m0_ad_balloc_ops * ab_ops
Definition: ad.h:65
uint64_t woi_act_added[AO_NR]
Definition: beck.c:293
uint32_t sad_bshift
Definition: ad.h:117
uint64_t m0_bindex_t
Definition: types.h:80
struct m0_format_footer cd_footer
Definition: cob.h:2382
struct m0_be_seg * b_seg0
Definition: beck.c:251
uint64_t b_data
Definition: beck.c:267
static const struct action_ops cob_ops
Definition: beck.c:419
uint64_t m0_bcount_t
Definition: types.h:77
static bool fid_without_type_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: beck.c:2440
#define M0_THREAD_INIT(thread, TYPE, init, func, arg, namefmt,...)
Definition: thread.h:139
M0_INTERNAL void m0_be_ut_backend_seg_add2(struct m0_be_ut_backend *ut_be, m0_bcount_t size, bool preallocate, const char *stob_create_cfg, struct m0_be_seg **out)
Definition: helper.c:466
M0_INTERNAL struct m0 * m0_get(void)
Definition: instance.c:41
static int cob_proc(struct scanner *s, struct btype *b, struct m0_be_bnode *node, off_t node_offset)
Definition: beck.c:2954
enum action_opcode a_opc
Definition: beck.c:190
static int void * buf
Definition: dir.c:1019
static const struct recops btreeops
Definition: beck.c:413
int m0_init(struct m0 *instance)
Definition: init.c:310
struct m0_be_emap_seg ec_seg
Definition: extmap.h:206
#define container_of(ptr, type, member)
Definition: misc.h:33
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
struct m0_thread s_thread
Definition: beck.c:101
struct m0_fid emap_fid
Definition: beck.c:284
static struct cache_slot * cache_lookup(struct cache *c, struct m0_fid *fid)
Definition: beck.c:2447
static int ctg_prep(struct action *act, struct m0_be_tx_credit *accum)
Definition: beck.c:2684
static int getat(struct scanner *s, off_t off, void *buf, size_t nob)
Definition: beck.c:1210
struct m0_be_tx_credit bec_tx_size_max
Definition: engine.h:73
static int seghdr_check(struct scanner *s, struct rectype *r, char *buf)
Definition: beck.c:1644
M0_INTERNAL void m0_reqh_fini(struct m0_reqh *reqh)
Definition: reqh.c:320
struct m0_be_domain * b_dom
Definition: beck.c:250
bool soi_bnodeqempty
Definition: beck.c:300
M0_INTERNAL bool m0_fid_is_set(const struct m0_fid *fid)
Definition: fid.c:106
M0_INTERNAL void m0_stob_ad_init_cfg_make(char **str, struct m0_be_domain *dom)
Definition: ad.c:212
struct m0_be_btree_backlink bb_backlink
Definition: btree.h:66
uint64_t bec_tx_active_max
Definition: engine.h:59
#define PRIx64
Definition: types.h:61
struct bstats b_stats
Definition: beck.c:167
struct m0_format_footer cc_foot
Definition: ctg_store.h:115
Definition: sock.c:887
static m0_bcount_t count
Definition: xcode.c:167
const char * location
Definition: storage.c:50
const char * b_name
Definition: beck.c:163
M0_INTERNAL void m0_cob_init(struct m0_cob_domain *dom, struct m0_cob *cob)
Definition: cob.c:1057
static void emap_to_gob_convert(const struct m0_uint128 *emap_prefix, struct m0_fid *out)
Definition: beck.c:1386
struct action * q_tail
Definition: beck.c:84
bool m0_xcode_enum_is_valid(const struct m0_xcode_enum *en, uint64_t val)
Definition: enum.c:45
m0_bcount_t bs_reserved
Definition: seg.h:74
off_t s_start_off
Definition: beck.c:95
struct m0_fid cta_fid
Definition: beck.c:507
#define m0_tl_endfor
Definition: tlist.h:700
static void test_queue(void)
Definition: beck.c:3138
struct m0_mutex b_emaplock[AO_NR - AO_EMAP_FIRST]
Definition: beck.c:277
struct m0_fid fid
Definition: di.c:46
Definition: beck.c:481
return M0_RC(rc)
M0_INTERNAL void m0_cob_tx_credit(struct m0_cob_domain *dom, enum m0_cob_op optype, struct m0_be_tx_credit *accum)
Definition: cob.c:2281
op
Definition: libdemo.c:64
struct m0_fid cs_fid
Definition: beck.c:226
uint64_t tbc_partitions_nr
Definition: tx_bulk.h:67
struct action * q_head
Definition: beck.c:83
static int btree(struct scanner *s, struct rectype *r, char *buf)
Definition: beck.c:1270
#define M0_BE_TX_CREDIT(nr, size)
Definition: tx_credit.h:94
struct cache_slot * cta_slot
Definition: beck.c:516
struct m0_stob_ad_domain * adm_dom
Definition: ad.h:142
Definition: buf.h:37
static int ctg_pver_fid_get(struct m0_fid *fid)
Definition: beck.c:2481
struct m0_ad_balloc * sad_ballroom
Definition: ad.h:115
Definition: beck.c:80
m0_time_t bec_group_freeze_timeout_limit
Definition: engine.h:82
struct m0_reqh * bec_reqh
Definition: engine.h:84
struct m0_format_footer e_footer
Definition: ext.h:98
static struct btype bt[]
Definition: beck.c:459
struct m0_be_ut_backend b_backend
Definition: beck.c:248
#define M0_STRINGARG(ch, desc, func)
Definition: getopts.h:207
int i
Definition: dir.c:1033
void m0_build_info_print(void)
Definition: version.c:66
Definition: beck.c:145
#define PRIu64
Definition: types.h:58
static bool isqempty(struct queue *q)
Definition: beck.c:2883
uint64_t c_kv
Definition: beck.c:157
static void ctg_fini(struct action *act)
Definition: beck.c:2764
void m0_be_ut_backend_cfg_default(struct m0_be_domain_cfg *cfg)
Definition: stubs.c:227
static int64_t max64(int64_t a, int64_t b)
Definition: arith.h:51
static bool btree_node_pre_is_valid(const struct m0_be_bnode *node, struct scanner *s)
Definition: beck.c:2392
static void noop_act(struct action *act, struct m0_be_tx *tx)
Definition: beck.c:3118
static void builder_thread(struct builder *b)
Definition: beck.c:1906
return M0_ERR(-EOPNOTSUPP)
M0_INTERNAL void m0_be_emap_paste(struct m0_be_emap_cursor *it, struct m0_be_tx *tx, struct m0_ext *ext, uint64_t val, void(*del)(struct m0_be_emap_seg *), void(*cut_left)(struct m0_be_emap_seg *, struct m0_ext *, uint64_t), void(*cut_right)(struct m0_be_emap_seg *, struct m0_ext *, uint64_t))
Definition: extmap.c:517
#define LAMBDA(T,...)
Definition: thread.h:153
const struct m0_build_info * m0_build_info_get(void)
Definition: version.c:61
string version
Definition: conf.py:40
#define M0_BE_OP_SYNC_RET(op_obj, action, member)
Definition: op.h:243
struct m0_be_emap_rec emap_val_data
Definition: beck.c:288
uint64_t tbc_workers_nr
Definition: tx_bulk.h:66
M0_INTERNAL void m0_ctg_try_init(struct m0_cas_ctg *ctg)
Definition: ctg_store.c:953
void(* o_fini)(struct action *act)
Definition: beck.c:218
Definition: trace.h:482
struct be_btree_key_val bt_kv_arr[KV_NR]
M0_INTERNAL int m0_be_tx_bulk_status(struct m0_be_tx_bulk *tb)
Definition: tx_bulk.c:630
static int key
Definition: locality.c:283
uint64_t bh_gen
Definition: seg_internal.h:54
M0_INTERNAL void m0_be_btree_insert(struct m0_be_btree *tree, struct m0_be_tx *tx, struct m0_be_op *op, const struct m0_buf *key, const struct m0_buf *val)
Definition: btree.c:1932
struct m0_fid b_pver_fid
Definition: beck.c:276
M0_INTERNAL const struct m0_be_btree_kv_ops * m0_ctg_btree_ops(void)
Definition: ctg_store.c:2167
#define M0_FID_TINIT(type, container, key)
Definition: fid.h:90
#define M0_AMB(obj, ptr, field)
Definition: misc.h:320
static void sig_handler(int num)
Definition: beck.c:556
struct queue * s_q
Definition: beck.c:112
uint64_t xev_val
Definition: enum.h:90
if(value==NULL)
Definition: dir.c:350
#define M0_FORMATARG(ch, desc, fmt, ptr)
Definition: getopts.h:218
M0_INTERNAL struct m0_cas_ctg * m0_ctg_meta(void)
Definition: ctg_store.c:2130
uint64_t bqc_q_size_max
Definition: queue.h:125
Definition: stob.h:163
static const struct action_ops emap_ops
Definition: beck.c:1380
M0_INTERNAL int m0_cob_name_add(struct m0_cob *cob, struct m0_cob_nskey *nskey, struct m0_cob_nsrec *nsrec, struct m0_be_tx *tx)
Definition: cob.c:1924
M0_INTERNAL void m0_be_btree_insert_credit(const struct m0_be_btree *tree, m0_bcount_t nr, m0_bcount_t ksize, m0_bcount_t vsize, struct m0_be_tx_credit *accum)
Definition: btree.c:1720
uint64_t oi_partitions_nr
Definition: beck.c:319
uint64_t q_max
Definition: beck.c:86
static struct m0_stob * stob
Definition: storage.c:39
struct m0_buf cta_val
Definition: beck.c:505
m0_bcount_t b_nob
Definition: buf.h:38
static struct m0_cob * cob
Definition: bytecount.c:40
Definition: beck.c:823
static int ctg_proc(struct scanner *s, struct btype *b, struct m0_be_bnode *node, off_t node_offset)
Definition: beck.c:2579
struct m0_be_tx_credit tgc_size_max
Definition: tx_group.h:61
#define M0_ASSERT(cond)
struct m0_format_footer bb_footer
Definition: btree.h:63
struct m0_bitstring cnk_name
Definition: cob.h:392
static void qput(struct queue *q, struct action *act)
Definition: beck.c:2815
struct scanner_off_info noi_scanoff
Definition: beck.c:313
uint64_t s_gen
Definition: beck.c:125
struct m0_be_emap sad_adata
Definition: ad.h:1541
static void emap_fini(struct action *act)
Definition: beck.c:1603
M0_INTERNAL void m0_ext_init(struct m0_ext *ext)
Definition: ext.c:32
struct queue s_bnode_q
Definition: beck.c:99
struct m0_format_footer psu_footer
Definition: pool.h:417
#define U128_P(x)
Definition: types.h:45
static void scanner_fini(struct scanner *s)
Definition: beck.c:958
static struct m0_addb2_callback c
Definition: consumer.c:41
struct m0_be_seg * b_seg
Definition: beck.c:252
struct m0_uint128 ek_prefix
void m0_node_uuid_string_set(const char *uuid)
Definition: uuuid.c:64
Definition: storage.c:317
struct stats r_stats
Definition: beck.c:142
off_t s_off
Definition: beck.c:103
m0_bcount_t s_max_reg_size
Definition: beck.c:123
uint64_t m0_strtou64(const char *str, char **endptr, int base)
Definition: kmisc.c:26
#define RLOG(level, prefix, s, r, tag)
Definition: beck.c:552
#define m0_streq(a, b)
Definition: string.h:34
static void be_cfg_default_init(struct m0_be_domain_cfg *dom_cfg, struct m0_be_tx_bulk_cfg *tb_cfg)
Definition: beck.c:2154
static struct cache_slot * cache_insert(struct cache *c, const struct m0_fid *fid)
Definition: beck.c:2463
M0_INTERNAL int m0_ctg_store_init(struct m0_be_domain *dom)
Definition: ctg_store.c:814
void m0_thread_fini(struct m0_thread *q)
Definition: thread.c:92
uint32_t ldsc_items_threshold
Definition: log_discard.h:92
static struct m0_stob_domain * dom
Definition: storage.c:38
static long long max(long long a, long long b)
Definition: crate.c:196
struct m0_mutex b_coblock
Definition: beck.c:278
static const struct recops bnodeops
Definition: beck.c:414
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
M0_INTERNAL int m0_dix_ldesc_init(struct m0_dix_ldesc *ld, struct m0_ext *range, m0_bcount_t range_nr, enum m0_dix_hash_fnc_type htype, struct m0_fid *pver)
Definition: layout.c:171
struct part_info noi_pinfo
Definition: beck.c:311
static struct rectype rt[]
Definition: beck.c:428
static struct m0_fid cob_fid
Definition: net.c:116
struct m0_stob_ad_domain ** b_ad_domain
Definition: beck.c:254
struct m0_be_btree * cs_tree
Definition: beck.c:228
M0_INTERNAL int m0_ctg__meta_insert(struct m0_be_btree *meta, const struct m0_fid *fid, struct m0_cas_ctg *ctg, struct m0_be_tx *tx)
Definition: ctg_store.c:528
Definition: beck.c:176
struct m0_mutex b_ctglock
Definition: beck.c:279
Definition: instance.h:80
struct m0_fid si_fid
Definition: stob.h:105
Definition: beck.c:138
M0_INTERNAL struct m0_stob_ad_domain * stob_ad_domain2ad(const struct m0_stob_domain *dom)
Definition: ad.c:166
struct action cta_act
Definition: beck.c:503
parser
Definition: queues.py:206
struct m0_be_op ec_op
Definition: extmap.h:217
uint64_t c_leaf
Definition: beck.c:154
struct action coa_act
Definition: beck.c:204
bool s_gen_found
Definition: beck.c:127
unsigned long tgc_tx_nr_max
Definition: tx_group.h:57
uint64_t u_hi
Definition: types.h:36
uint64_t c_fanout
Definition: beck.c:156
static int nv_scan_offset_init(uint64_t workers_nr, uint64_t partitions_nr)
Definition: beck.c:1676
M0_INTERNAL int m0_buf_alloc(struct m0_buf *buf, size_t size)
Definition: buf.c:43
uint64_t b_act
Definition: beck.c:266
void * m0_alloc(size_t size)
Definition: memory.c:126
Definition: beck.c:151
struct m0_be_op::@39::@40 u_emap
Definition: beck.c:161
uint64_t g_count
Definition: beck.c:172
#define SCNi64
Definition: types.h:63
static char iobuf[4 *1024 *1024]
Definition: beck.c:821
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
static void be_cfg_update(struct m0_be_domain_cfg *cfg, const char *str_key, const char *str_value)
Definition: beck.c:2182
static const char * recname(const struct rectype *rt)
Definition: beck.c:1200
uint64_t b_ad_dom_count
Definition: beck.c:253
uint64_t f_container
Definition: fid.h:39
#define M0_POST(cond)
int(* ro_check)(struct scanner *s, struct rectype *r, char *buf)
Definition: beck.c:148
M0_INTERNAL void m0_ctg_create_credit(struct m0_be_tx_credit *accum)
Definition: ctg_store.c:1823
Definition: xcode.h:73
pthread_mutex_t q_lock
Definition: beck.c:81
static void test(void)
Definition: beck.c:3204
static int cob_prep(struct action *act, struct m0_be_tx_credit *accum)
Definition: beck.c:3015
uint64_t c_tree
Definition: beck.c:152
const char * stob_location
Definition: kemc.c:55
struct m0_stob_id sad_bstore_id
Definition: ad.h:114
Definition: reqh.h:94
M0_INTERNAL void m0_be_emap_lookup(struct m0_be_emap *map, const struct m0_uint128 *prefix, m0_bindex_t offset, struct m0_be_emap_cursor *it)
Definition: extmap.c:344
off_t s_chunk_pos
Definition: beck.c:117
static void token(struct ff2c_context *ctx, struct ff2c_term *term, struct ff2c_token *tok)
Definition: parser.c:66
struct m0_sm_group * m0_be_ut_backend_sm_group_lookup(struct m0_be_ut_backend *ut_be)
Definition: stubs.c:277
uint32_t dl_type
Definition: layout.h:100
M0_INTERNAL void m0_be_op_done(struct m0_be_op *op)
Definition: stubs.c:104
uint64_t hd_magic
Definition: format.h:43
M0_INTERNAL const struct m0_fid m0_cas_dead_index_fid
Definition: cas.c:156
struct m0_fid ci_fid
Definition: cas.h:113
off_t woi_offset[AO_NR]
Definition: beck.c:292
off_t s_size
Definition: beck.c:110
struct m0_buf coa_key
Definition: beck.c:206
static m0_bindex_t offset
Definition: dump.c:173
static struct builder beck_builder
Definition: beck.c:520
struct m0_be_btree cc_tree
Definition: ctg_store.h:120
static void qinit(struct queue *q, uint64_t maxnr)
Definition: beck.c:2792
struct m0_format_footer bl_format_footer
Definition: list.h:492
M0_INTERNAL void m0_buf_free(struct m0_buf *buf)
Definition: buf.c:55
M0_INTERNAL int m0_ctg_meta_find_ctg(struct m0_cas_ctg *meta, const struct m0_fid *ctg_fid, struct m0_cas_ctg **ctg)
Definition: ctg_store.c:503
uint32_t b_len
Definition: bitstring.h:36
Definition: beck.c:247
uint32_t xe_nr
Definition: enum.h:60
int c_head
Definition: beck.c:237
static void ad_dom_fini(struct builder *b)
Definition: beck.c:2109
off_t s_pos
Definition: beck.c:104
int m0_ctg_create(struct m0_be_seg *seg, struct m0_be_tx *tx, struct m0_cas_ctg **out, const struct m0_fid *cas_fid)
Definition: ctg_store.c:441
static void qfini(struct queue *q)
Definition: beck.c:2804
union m0_dix_layout::@145 u
Definition: seg.h:66
uint64_t s_version
Definition: beck.c:134
#define FID_P(f)
Definition: fid.h:77
uint64_t m0_time_seconds(const m0_time_t time)
Definition: time.c:83
struct m0_be_domain but_dom
Definition: helper.h:47
#define PRId64
Definition: types.h:57
const char * b_stob_path
Definition: beck.c:263
void(* o_act)(struct action *act, struct m0_be_tx *tx)
Definition: beck.c:217
M0_BASSERT(ARRAY_SIZE(rt)==M0_FORMAT_TYPE_NR+1)
const char * xev_name
Definition: enum.h:97
M0_INTERNAL int m0_format_footer_verify(const void *buffer, bool iem)
Definition: format.c:149
int m0_cob_domain_init(struct m0_cob_domain *dom, struct m0_be_seg *seg)
Definition: cob.c:708
M0_INTERNAL bool m0_be_seg_contains(const struct m0_be_seg *seg, const void *addr)
Definition: stubs.c:144
M0_INTERNAL struct m0_stob_domain * m0_stob_domain_find_by_stob_id(const struct m0_stob_id *stob_id)
Definition: domain.c:294
static struct nv_offset_info nv_off_info
Definition: beck.c:523
struct action bna_act
Definition: beck.c:199
M0_INTERNAL void m0_be_engine_tx_size_max(struct m0_be_engine *en, struct m0_be_tx_credit *cred, m0_bcount_t *payload_size)
Definition: engine.c:937
struct m0_fid coa_fid
Definition: beck.c:212
uint32_t m0_strtou32(const char *str, char **endptr, int base)
Definition: kmisc.c:32
struct m0_format_footer sad_footer
Definition: ad.h:1536
static void * builder_action(struct builder *b, size_t len, enum action_opcode opc, const struct action_ops *ops)
Definition: beck.c:2365
uint64_t s_chksum
Definition: beck.c:132
struct m0_be_btree em_mapping
int32_t sad_babshift
Definition: ad.h:118
M0_INTERNAL void m0_stob_domain_fini(struct m0_stob_domain *dom)
Definition: domain.c:204
#define U128X_F
Definition: types.h:42
struct m0_be_emap_key emap_key_data
Definition: beck.c:287
FILE * s_file
Definition: beck.c:90
Definition: beck.c:89
struct builder * a_builder
Definition: beck.c:191
uint64_t s_found
Definition: beck.c:131
M0_INTERNAL int m0_stob_create(struct m0_stob *stob, struct m0_dtx *dtx, const char *str_cfg)
Definition: stob.c:154
M0_INTERNAL bool m0_fid_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: fid.c:164
#define m0_forall(var, nr,...)
Definition: misc.h:112
static int seghdr_ver(struct scanner *s, struct rectype *r, char *buf)
Definition: beck.c:1627
const char * b_be_config_file
Definition: beck.c:264
struct m0_be_domain_cfg but_dom_cfg
Definition: helper.h:53
struct m0_fid sd_id
Definition: domain.h:96
static const char * bname(const struct btype *bt)
Definition: beck.c:1205
struct m0_be_pd_cfg bc_pd_cfg
Definition: domain.h:129
struct m0_be_emap sad_adata
Definition: ad.h:129
M0_INTERNAL int m0_stob_destroy(struct m0_stob *stob, struct m0_dtx *dtx)
Definition: stob.c:200
struct m0_be_log_discard_cfg bc_log_discard_cfg
Definition: domain.h:130
static void cob_act(struct action *act, struct m0_be_tx *tx)
Definition: beck.c:3041
M0_INTERNAL bool m0_be_tx_bulk_put(struct m0_be_tx_bulk *tb, struct m0_be_op *op, struct m0_be_tx_credit *credit, m0_bcount_t payload_credit, uint64_t partition, void *user)
Definition: tx_bulk.c:583
static int emap_proc(struct scanner *s, struct btype *b, struct m0_be_bnode *node, off_t node_offset)
Definition: beck.c:1410
struct queue * b_q
Definition: beck.c:258
uint64_t n
Definition: fops.h:107
uint16_t ot_type
Definition: format.h:64
M0_INTERNAL enum m0_stob_state m0_stob_state_get(struct m0_stob *stob)
Definition: stob.c:265
const char * b_dom_path
Definition: beck.c:262
M0_INTERNAL void m0_ctg_state_inc_update(struct m0_be_tx *tx, uint64_t size)
Definition: ctg_store.c:940
M0_INTERNAL void m0_be_op_active(struct m0_be_op *op)
Definition: stubs.c:100
struct m0_format_footer bt_footer
static int parse(struct scanner *s)
Definition: beck.c:1059
Definition: stob.h:91
bool soi_scanqempty
Definition: beck.c:299
M0_INTERNAL void m0_be_tx_bulk_fini(struct m0_be_tx_bulk *tb)
Definition: tx_bulk.c:288
#define M0_BUF_INIT_PTR(p)
Definition: buf.h:69
M0_INTERNAL int m0_stob_domain_init(const char *location, const char *str_cfg_init, struct m0_stob_domain **out)
Definition: domain.c:195
Definition: beck.c:179
M0_INTERNAL void m0_fid_tchange(struct m0_fid *fid, uint8_t tid)
Definition: fid.c:139
static int bnode_check(struct scanner *s, struct rectype *r, char *buf)
Definition: beck.c:1351
static const char * offset_file
Definition: beck.c:532
Definition: ext.h:37
Definition: fid.h:38
struct m0_format_footer sa0_footer
Definition: ad_private.h:211
uint64_t f_key
Definition: fid.h:40
m0_bindex_t e_start
Definition: ext.h:39
static void btree_bad_kv_count_update(uint64_t type, int count)
Definition: beck.c:2434
#define M0_IS0(obj)
Definition: misc.h:70
static struct m0_be_seg s_seg
Definition: beck.c:522
uint64_t oi_workers_nr
Definition: beck.c:318
static bool btree_kv_post_is_valid(struct scanner *s, struct m0_buf *key, struct m0_buf *val)
Definition: beck.c:2428
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
size_t bec_group_nr
Definition: engine.h:61
Definition: beck.c:130
uint64_t c_kv_bad
Definition: beck.c:158
static void builder_fini(struct builder *b)
Definition: beck.c:2128
m0_time_t bec_group_freeze_timeout_min
Definition: engine.h:80
#define PRIi64
Definition: types.h:59
static int r[NR]
Definition: thread.c:46
Definition: beck.c:181
bool s_byte
Definition: beck.c:105
struct m0_buf cta_key
Definition: beck.c:504
struct m0_stob_domain * stob_dom
Definition: beck.c:244
struct m0_format_tag r_tag
Definition: beck.c:140
M0_TL_DESCR_DECLARE(ad_domains, M0_EXTERN)
Definition: beck.c:178
m0_time_t m0_time_sub(const m0_time_t t1, const m0_time_t t2)
Definition: time.c:65
struct ad_dom_info ** b_ad_info
Definition: beck.c:256
M0_INTERNAL int m0_ctg_ctidx_insert_sync(const struct m0_cas_id *cid, struct m0_be_tx *tx)
Definition: ctg_store.c:2010
struct m0_format_footer bgd_footer
Definition: balloc.h:653
m0_bcount_t size
Definition: di.c:39
#define _0C(exp)
Definition: assert.h:311
M0_INTERNAL void m0_be_op_fini(struct m0_be_op *op)
Definition: stubs.c:92
static int generation_id_verify(struct scanner *s, uint64_t gen)
Definition: beck.c:918
struct action * a_prev
Definition: beck.c:195
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
off_t pi_1st_bnode_offset[AO_NR]
Definition: beck.c:306
M0_INTERNAL int m0_cc_stob_cr_credit(struct m0_stob_id *sid, struct m0_be_tx_credit *accum)
Definition: cob_foms.c:807
void m0_be_ut_backend_fini(struct m0_be_ut_backend *ut_be)
Definition: stubs.c:242
#define IS_IN_ARRAY(idx, array)
Definition: misc.h:311
static struct m0 instance
Definition: main.c:78
struct m0_be_log_cfg bc_log
Definition: domain.h:118
#define FLOG(level, rc, s)
Definition: beck.c:547
uint8_t coa_valdata[sizeof(struct m0_cob_nsrec)]
Definition: beck.c:210
static const char * yaml_file
Definition: console.c:43
M0_INTERNAL struct m0_cas_ctg * m0_ctg_ctidx(void)
Definition: ctg_store.c:2135
M0_INTERNAL int m0_stob_find(const struct m0_stob_id *id, struct m0_stob **out)
Definition: stob.c:92
static struct m0_be_seg * seg
Definition: btree.c:40
static struct scanner beck_scanner
Definition: beck.c:519
static bool dry_run
Definition: beck.c:526
static int emap_kv_get(struct scanner *s, const struct be_btree_key_val *kv, struct m0_buf *key_buf, struct m0_buf *val_buf)
Definition: beck.c:1607
#define M0_UINT128(hi, lo)
Definition: types.h:40
static bool resume_scan
Definition: beck.c:529
struct m0_mutex oi_part_lock[AO_NR]
Definition: beck.c:317
M0_INTERNAL void m0_fid_convert_cob2gob(const struct m0_fid *cob_fid, struct m0_fid *gob_fid)
Definition: fid_convert.c:69
struct m0_stob * stob
Definition: beck.c:242
#define M0_ASSERT_INFO(cond, fmt,...)
struct m0_be_tx_group_cfg bec_group_cfg
Definition: engine.h:71
static int recdo(struct scanner *s, const struct m0_format_tag *tag, struct rectype *rt)
Definition: beck.c:1152
M0_INTERNAL struct m0_be_seg * m0_be_domain_seg_first(const struct m0_be_domain *dom)
Definition: domain.c:486
#define _T(name, str, field, ops)
Definition: beck.c:423
union m0_be_op::@39 bo_u
int main(int argc, char **argv)
Definition: beck.c:562
#define EXT(start, end)
Definition: libdemo.c:64
struct m0_format_footer bh_footer
Definition: seg_internal.h:96
static void generation_id_get(FILE *fp, uint64_t *gen_id)
Definition: beck.c:873
int(* b_proc)(struct scanner *s, struct btype *b, struct m0_be_bnode *node, off_t node_offset)
Definition: beck.c:164
M0_INTERNAL size_t m0_cob_nskey_size(const struct m0_cob_nskey *cnk)
Definition: cob.c:175
static int format_header_verify(const struct m0_format_header *h, uint16_t rtype)
Definition: beck.c:2381
static bool signaled
Definition: beck.c:528
struct m0_format_footer ek_footer
M0_INTERNAL const struct m0_fid m0_cas_ctidx_fid
Definition: cas.c:151
#define out(...)
Definition: gen.c:41
enum m0_be_btree_type b_type
Definition: beck.c:162
static int btree_check(struct scanner *s, struct rectype *r, char *buf)
Definition: beck.c:1291
Definition: rcv_session.c:58
off_t soi_offset
Definition: beck.c:298
struct action * a_next
Definition: beck.c:194
M0_INTERNAL void m0_be_emap_credit(struct m0_be_emap *map, enum m0_be_emap_optype optype, m0_bcount_t nr, struct m0_be_tx_credit *accum)
Definition: extmap.c:886
struct m0_be_engine bd_engine
Definition: domain.h:136
struct worker_off_info noi_offset[MAX_WORKERS_NR]
Definition: beck.c:312
static void builder_done(struct m0_be_tx_bulk *tb, void *datum, void *user, uint64_t worker_index, uint64_t partition)
Definition: beck.c:1848
int type
Definition: dir.c:1031
static int init(void)
Definition: beck.c:1099
m0_bcount_t lc_full_threshold
Definition: log.h:255
static bool qinvariant(const struct queue *q)
Definition: beck.c:2780
struct m0_buf emap_val
Definition: beck.c:286
uint32_t bpdc_seg_io_nr
Definition: pd.h:59
m0_bindex_t er_start
static void * scanner_action(size_t len, enum action_opcode opc, const struct action_ops *ops)
Definition: beck.c:1302
static struct m0_be_tx_bulk_cfg default_tb_cfg
Definition: beck.c:538
struct m0_fom_ops ops
Definition: io_foms.c:623
uint64_t u_lo
Definition: types.h:37
static void noop_fini(struct action *act)
Definition: beck.c:3122
uint64_t pi_act_done[AO_NR]
Definition: beck.c:305
Definition: op.h:74
const char * r_name
Definition: beck.c:139
uint64_t q_nr
Definition: beck.c:85
const struct action_ops * a_ops
Definition: beck.c:192
static int scan(struct scanner *s)
Definition: beck.c:963
M0_INTERNAL bool m0_fid_validate_cob(const struct m0_fid *cob_fid)
Definition: fid_convert.c:99
m0_time_t ldsc_sync_timeout
Definition: log_discard.h:95
int num
Definition: bulk_if.c:54
static int noop_prep(struct action *act, struct m0_be_tx_credit *cred)
Definition: beck.c:3113
static struct gen g[MAX_GEN]
Definition: beck.c:521
#define m0_tl_for(name, head, obj)
Definition: tlist.h:695
M0_INTERNAL void m0_be_op_init(struct m0_be_op *op)
Definition: stubs.c:87
static void nv_scan_offset_update(void)
Definition: beck.c:1798
void m0_free(void *data)
Definition: memory.c:146
static int ad_dom_init(struct builder *b)
Definition: beck.c:1939
M0_INTERNAL int m0_reqh_be_init(struct m0_reqh *reqh, struct m0_be_seg *seg)
Definition: reqh.c:269
Definition: mutex.h:47
void(* bo_alloc_credit)(const struct m0_ad_balloc *ballroom, int nr, struct m0_be_tx_credit *accum)
Definition: ad.h:92
static struct m0_addb2_source * s
Definition: consumer.c:39
struct m0_thread b_thread
Definition: beck.c:257
static int scanner_init(struct scanner *s)
Definition: beck.c:933
Definition: cas.h:107
struct m0_stob_domain * b_ad_dom
Definition: beck.c:255
#define M0_BUF_INIT(size, data)
Definition: buf.h:64
static bool seg_hdr_get(FILE *fp, struct m0_be_seg_hdr *out)
Definition: beck.c:837
static void builder_work_put(struct m0_be_tx_bulk *tb, struct builder *b)
Definition: beck.c:1873
struct m0_be_engine_cfg bc_engine
Definition: domain.h:79
struct m0_be_queue_cfg tbc_q_cfg
Definition: tx_bulk.h:65
struct m0_be_seg_geom bh_items[M0_BE_SEG_HDR_GEOM_ITMES_MAX]
Definition: seg_internal.h:51
static void ctg_act(struct action *act, struct m0_be_tx *tx)
Definition: beck.c:2722
struct m0_format_header bh_header
Definition: seg_internal.h:48
off_t bna_offset
Definition: beck.c:200
int32_t rc
Definition: trigger_fop.h:47
M0_INTERNAL bool m0_be_op_is_done(struct m0_be_op *op)
Definition: stubs.c:108
static struct offset_info off_info
Definition: beck.c:524
#define ARRAY_SIZE(a)
Definition: misc.h:45
struct m0_fid cnk_pfid
Definition: cob.h:391
static int cob_kv_get(struct scanner *s, const struct be_btree_key_val *kv, struct m0_buf *key, struct m0_buf *val)
Definition: beck.c:2916
static uint64_t m0_align(uint64_t val, uint64_t alignment)
Definition: arith.h:170
struct cache b_cache
Definition: beck.c:260
static bool mmap_be_segment
Definition: beck.c:530
struct m0_format_footer em_footer
#define M0_BE_OP_SYNC_RET_WITH(op, action, member)
Definition: op.h:253
struct m0_format_footer cnr_footer
Definition: cob.h:431
static int bnode(struct scanner *s, struct rectype *r, char *buf)
Definition: beck.c:1316
void m0_be_ut_backend_thread_exit(struct m0_be_ut_backend *ut_be)
Definition: stubs.c:282
static const struct recops seghdrops
Definition: beck.c:415
uint64_t g_gen
Definition: beck.c:171
unsigned char s_chunk[4 *1024 *1024]
Definition: beck.c:116
#define FID_F
Definition: fid.h:75
uint64_t c_maxlevel
Definition: beck.c:155
static struct action * qtry(struct queue *q)
Definition: beck.c:2871
struct m0_be_seg * s_seg
Definition: beck.c:111
struct m0_fid_type st_fidt
Definition: type.h:61
static int seghdr(struct scanner *s, struct rectype *r, char *buf)
Definition: beck.c:1622
Definition: tx.h:280
Definition: idx_mock.c:47
struct m0_buf emap_key
Definition: beck.c:285
static struct m0_stob_domain * sdom
Definition: reqh_fom_ut.c:73
static off_t nv_scan_offset_get(off_t snapshot_size)
Definition: beck.c:1706
static int be_cfg_from_yaml_update(const char *yaml_file, struct m0_be_domain_cfg *cfg)
Definition: beck.c:2282
struct m0_cas_id cta_cid
Definition: beck.c:509
M0_INTERNAL void m0_fid_tassume(struct m0_fid *fid, const struct m0_fid_type *ft)
Definition: fid.c:146
struct m0_tl sam_domains
Definition: module.h:50
struct m0_be_btree cd_namespace
Definition: cob.h:2388
m0_bcount_t bec_tx_payload_max
Definition: engine.h:75
struct m0_fid cnr_fid
Definition: cob.h:419
static void emap_act(struct action *act, struct m0_be_tx *tx)
Definition: beck.c:1516
Definition: ad.h:186
int(* o_prep)(struct action *act, struct m0_be_tx_credit *cred)
Definition: beck.c:216