Motr  M0
ad.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2020 Seagate Technology LLC and/or its Affiliates
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * For any questions about this software or licensing,
17  * please email opensource@seagate.com or cortx-questions@seagate.com.
18  *
19  */
20 
21 
22 #include "balloc/balloc.h"
23 
24 #include "be/extmap.h"
25 #include "be/seg.h"
26 #include "be/seg0.h" /* m0_be_0type */
27 
28 #include "dtm/dtm.h" /* m0_dtx */
29 
30 #include "fid/fid.h" /* m0_fid */
31 
32 #include "lib/finject.h"
33 #include "lib/errno.h"
34 #include "lib/locality.h" /* m0_locality0_get */
35 #include "lib/memory.h"
36 #include "lib/string.h"
37 #include "lib/cksum_utils.h"
38 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_ADSTOB
39 #include "lib/trace.h" /* M0_LOG */
40 
41 #include "addb2/addb2.h"
42 #include "module/instance.h" /* m0_get */
43 
44 #include "stob/ad.h"
45 #include "stob/ad_private.h"
46 #include "stob/ad_private_xc.h"
47 #include "stob/addb2.h"
48 #include "stob/domain.h"
49 #include "stob/io.h"
50 #include "stob/module.h" /* m0_stob_ad_module */
51 #include "stob/stob.h"
52 #include "stob/stob_internal.h" /* m0_stob__fid_set */
53 #include "stob/type.h" /* m0_stob_type */
54 #include "be/domain.h"
55 
64 };
65 
66 struct ad_domain_cfg {
68  struct m0_be_seg *adg_seg;
70  uint32_t adg_bshift;
73 };
74 
75 static const struct m0_bob_type stob_ad_domain_bob_type = {
76  .bt_name = "m0_stob_ad_domain",
77  .bt_magix_offset = M0_MAGIX_OFFSET(struct m0_stob_ad_domain, sad_magix),
78  .bt_magix = M0_STOB_AD_DOMAIN_MAGIC,
79 };
81 
83 static struct m0_stob_ops stob_ad_ops;
84 
85 static int stob_ad_io_init(struct m0_stob *stob, struct m0_stob_io *io);
86 static void stob_ad_write_credit(const struct m0_stob_domain *dom,
87  const struct m0_stob_io *iv,
88  struct m0_be_tx_credit *accum);
89 static void
91  struct m0_be_tx_credit *accum);
92 static int stob_ad_rec_frag_undo_redo_op(struct m0_fol_frag *frag,
93  struct m0_be_tx *tx);
94 
100 static int stob_ad_seg_free(struct m0_dtx *tx,
101  struct m0_stob_ad_domain *adom,
102  const struct m0_be_emap_seg *seg,
103  const struct m0_ext *ext,
104  uint64_t val);
105 static int stob_ad_punch(struct m0_stob *stob, struct m0_indexvec *range,
106  struct m0_dtx *tx);
107 
108 M0_TL_DESCR_DEFINE(ad_domains, "ad stob domains", M0_INTERNAL,
109  struct ad_domain_map, adm_linkage, adm_magic,
111 M0_TL_DEFINE(ad_domains, M0_INTERNAL, struct ad_domain_map);
112 
114  const char *suffix,
115  const struct m0_buf *data)
116 {
117  struct m0_stob_ad_module *module = &m0_get()->i_stob_ad_module;
118  struct stob_ad_0type_rec *rec = data->b_addr;
119  struct ad_domain_map *ad;
120  int rc;
121 
122  M0_PRE(rec != NULL && data->b_nob == sizeof(*rec));
123  M0_PRE(strlen(suffix) < ARRAY_SIZE(ad->adm_path));
124 
125  M0_ALLOC_PTR(ad);
126  rc = ad == NULL ? -ENOMEM : 0;
127 
128  if (rc == 0) {
129  /* XXX won't be stored as pointer */
130  ad->adm_dom = rec->sa0_ad_domain;
131  strncpy(ad->adm_path, suffix, sizeof(ad->adm_path) - 1);
132  m0_mutex_lock(&module->sam_lock);
133  ad_domains_tlink_init_at_tail(ad, &module->sam_domains);
134  m0_mutex_unlock(&module->sam_lock);
135  }
136 
137  return M0_RC(rc);
138 }
139 
140 static void stob_ad_0type_fini(struct m0_be_domain *dom,
141  const char *suffix,
142  const struct m0_buf *data)
143 {
144  struct m0_stob_ad_module *module = &m0_get()->i_stob_ad_module;
145  struct stob_ad_0type_rec *rec = data->b_addr;
146  struct ad_domain_map *ad;
147 
148  M0_PRE(rec != NULL && data->b_nob == sizeof(*rec));
149 
150  m0_mutex_lock(&module->sam_lock);
151  ad = m0_tl_find(ad_domains, ad, &module->sam_domains,
152  m0_streq(suffix, ad->adm_path));
153  M0_ASSERT(ad != NULL);
154  ad_domains_tlink_del_fini(ad);
155  m0_free(ad);
156  m0_mutex_unlock(&module->sam_lock);
157 }
158 
160  .b0_name = "M0_BE:AD",
161  .b0_init = stob_ad_0type_init,
162  .b0_fini = stob_ad_0type_fini
163 };
164 
165 M0_INTERNAL struct m0_stob_ad_domain *
167 {
168  struct m0_stob_ad_domain *adom;
169 
170  adom = (struct m0_stob_ad_domain *)dom->sd_private;
171  m0_stob_ad_domain_bob_check(adom);
173  adom->sad_dom_key);
174 
175  return adom;
176 }
177 
178 M0_INTERNAL struct m0_balloc *
180 {
181  struct m0_stob_ad_domain *adom = stob_ad_domain2ad(dom);
182 
183  return b2m0(adom->sad_ballroom);
184 }
185 
186 static struct m0_stob_ad *stob_ad_stob2ad(const struct m0_stob *stob)
187 {
188  return container_of(stob, struct m0_stob_ad, ad_stob);
189 }
190 
192 {
193  struct m0_stob_ad_module *module = &m0_get()->i_stob_ad_module;
194  int rc;
195 
196  M0_FOL_FRAG_TYPE_INIT(stob_ad_rec_frag, "AD record fragment");
197  rc = m0_fol_frag_type_register(&stob_ad_rec_frag_type);
198  M0_ASSERT(rc == 0); /* XXX void */
199  m0_mutex_init(&module->sam_lock);
200  ad_domains_tlist_init(&module->sam_domains);
201 }
202 
204 {
205  struct m0_stob_ad_module *module = &m0_get()->i_stob_ad_module;
206 
207  ad_domains_tlist_fini(&module->sam_domains);
208  m0_mutex_fini(&module->sam_lock);
209  m0_fol_frag_type_deregister(&stob_ad_rec_frag_type);
210 }
211 
212 M0_INTERNAL void m0_stob_ad_init_cfg_make(char **str, struct m0_be_domain *dom)
213 {
214  char buf[0x40];
215 
216  snprintf(buf, ARRAY_SIZE(buf), "%p", dom);
217  *str = m0_strdup(buf);
218 }
219 
220 M0_INTERNAL void m0_stob_ad_cfg_make(char **str,
221  const struct m0_be_seg *seg,
222  const struct m0_stob_id *bstore_id,
223  const m0_bcount_t size)
224 {
225  char buf[0x400];
226 
227  snprintf(buf, ARRAY_SIZE(buf), "%p:"FID_F":"FID_F":%"PRId64, seg,
228  FID_P(&bstore_id->si_domain_fid),
229  FID_P(&bstore_id->si_fid), size);
230  *str = m0_strdup(buf);
231 }
232 
233 static int stob_ad_domain_cfg_init_parse(const char *str_cfg_init,
234  void **cfg_init)
235 {
236  struct ad_domain_init_cfg *cfg;
237  int rc;
238 
239  M0_ASSERT(str_cfg_init != NULL); /* TODO: remove this assert */
240  if (str_cfg_init == NULL)
241  return M0_ERR(-EINVAL);
242 
243  M0_ALLOC_PTR(cfg);
244  if (cfg == NULL)
245  return M0_ERR(-ENOMEM);
246 
247  rc = sscanf(str_cfg_init, "%p", (void **)&cfg->dic_dom);
248  *cfg_init = cfg;
249  M0_ASSERT(rc == 1); /* TODO: remove this assert */
250  return rc == 1 ? 0 : -EINVAL;
251 }
252 
253 static void stob_ad_domain_cfg_init_free(void *cfg_init)
254 {
255  m0_free(cfg_init);
256 }
257 
258 static int stob_ad_domain_cfg_create_parse(const char *str_cfg_create,
259  void **cfg_create)
260 {
261  struct ad_domain_cfg *cfg;
262  m0_bcount_t grp_blocks;
263  int rc;
264 
265  if (str_cfg_create == NULL)
266  return M0_ERR(-EINVAL);
267 
268  M0_ALLOC_PTR(cfg);
269  if (cfg != NULL) {
270  /* format = seg:domain_fid:fid:container_size */
271  rc = sscanf(str_cfg_create, "%p:"FID_SF":"FID_SF":%"SCNd64"",
272  (void **)&cfg->adg_seg,
273  FID_S(&cfg->adg_id.si_domain_fid),
274  FID_S(&cfg->adg_id.si_fid),
275  &cfg->adg_container_size);
276  rc = rc == 6 ? 0 : -EINVAL;
277  } else
278  rc = -ENOMEM;
279 
280  if (rc == 0) {
281  if (cfg->adg_container_size == 0)
284  /*
285  * Big number of groups slows balloc initialisation. Therefore,
286  * group size is counted depending on BALLOC_DEF_GROUPS_NR.
287  * Group size must be power of 2.
288  */
289  grp_blocks = (cfg->adg_container_size >> cfg->adg_bshift) /
291  grp_blocks = 1 << m0_log2(grp_blocks);
292  grp_blocks = max64u(grp_blocks, BALLOC_DEF_BLOCKS_PER_GROUP);
293  cfg->adg_blocks_per_group = grp_blocks;
295  m0_stob_ad_spares_calc(grp_blocks);
296  M0_LOG(M0_DEBUG, "device size %"PRId64, cfg->adg_container_size);
297  *cfg_create = cfg;
298  }
299  return M0_RC(rc);
300 }
301 
302 /*
303  * XXX @todo: A more sophisticated version of this function is necessary,
304  * that will take into account the number of pool versions that the disk
305  * belongs to, along with parameters of pdclust. The following module will
306  * return a value around 20 % of blocks per group.
307  *
308  * On other note, reserving a fraction K / (N + K) is too conservative as
309  * it takes into consideration the case when on failure all parity groups
310  * need to be repaired (which is true only when N + 2K == P).
311  * Probably K / P is the right ratio.
312  */
314 {
315 #ifdef __SPARE__SPACE__
316 
317  return grp_blocks % 5 == 0 ? grp_blocks / 5 : grp_blocks / 5 + 1;
318 #else
319  return 0;
320 #endif
321 }
322 
323 /* This function will go through si_stob vector
324  * Checksum is stored in contigious buffer: si_cksum, while COB extents may not be
325  * contigious e.g.
326  * Assuming each extent has two DU, so two checksum.
327  * | CS0 | CS1 | CS2 | CS3 | CS4 | CS5 | CS6 |
328  * | iv_index[0] | | iv_index[1] | iv_index[2] | | iv_index[3] |
329  * Now if we have an offset for CS3 then after first travesal b_addr will poin to
330  * start of CS2 and then it will land in m0_ext_is_in and will compute correct
331  * addr for CS3.
332  */
333 M0_INTERNAL void * m0_stob_ad_get_checksum_addr(struct m0_stob_io *io, m0_bindex_t off )
334 {
335  void *b_addr = io->si_cksum.b_addr;
336  void *cksum_addr = NULL;
337  struct m0_ext ext;
338  int i;
339 
340  /* Get the checksum nobs consumed till reaching the off in given io */
341  for (i = 0; i < io->si_stob.iv_vec.v_nr; i++)
342  {
343  ext.e_start = io->si_stob.iv_index[i];
345 
346  if (m0_ext_is_in(&ext, off)) {
347  cksum_addr = m0_extent_get_checksum_addr(b_addr, off,
348  ext.e_start,
349  io->si_unit_sz,
350  io->si_cksum_sz);
351  break;
352  }
353  else {
354  /* off is beyond the current extent, increment the b_addr */
357  M0_ASSERT(b_addr <=io->si_cksum.b_addr + io->si_cksum.b_nob );
358  }
359  }
360 
363  return cksum_addr;
364 }
365 
366 static void stob_ad_domain_cfg_create_free(void *cfg_create)
367 {
368  m0_free(cfg_create);
369 }
370 
371 M0_INTERNAL bool m0_stob_ad_domain__invariant(struct m0_stob_ad_domain *adom)
372 {
373  return _0C(adom->sad_ballroom != NULL);
374 }
375 
376 static struct m0_sm_group *stob_ad_sm_group(void)
377 {
378  return m0_locality0_get()->lo_grp;
379 }
380 
381 static int stob_ad_bstore(struct m0_stob_id *stob_id, struct m0_stob **out)
382 {
383  struct m0_stob *stob;
384  int rc;
385 
386  rc = m0_stob_find(stob_id, &stob);
387  if (rc == 0) {
390  if (rc != 0 || m0_stob_state_get(stob) != CSS_EXISTS) {
391  m0_stob_put(stob);
392  rc = rc ?: -ENOENT;
393  }
394  }
395  *out = rc == 0 ? stob : NULL;
396  return M0_RC(rc);
397 }
398 
399 static struct m0_stob_ad_domain *
400 stob_ad_domain_locate(const char *location_data)
401 {
402  struct m0_stob_ad_module *module = &m0_get()->i_stob_ad_module;
403  struct ad_domain_map *ad;
404 
405  m0_mutex_lock(&module->sam_lock);
406  ad = m0_tl_find(ad_domains, ad, &module->sam_domains,
407  m0_streq(location_data, ad->adm_path));
408  m0_mutex_unlock(&module->sam_lock);
409  return ad == NULL ? NULL : ad->adm_dom;
410 }
411 
413  const char *location_data,
414  void *cfg_init,
415  struct m0_stob_domain **out)
416 {
417  struct ad_domain_init_cfg *cfg = cfg_init;
418  struct m0_stob_ad_domain *adom;
419  struct m0_stob_domain *dom;
420  struct m0_be_seg *seg;
421  struct m0_ad_balloc *ballroom;
422  bool balloc_inited;
423  int rc = 0;
424 
425  adom = stob_ad_domain_locate(location_data);
426  if (adom == NULL)
427  return M0_RC(-ENOENT);
428  else
429  seg = m0_be_domain_seg(cfg->dic_dom, adom);
430 
431  if (seg == NULL) {
432  M0_LOG(M0_ERROR, "segment doesn't exist for addr=%p", adom);
433  return M0_ERR(-EINVAL);
434  }
435 
437 
438  M0_ALLOC_PTR(dom);
439  if (dom == NULL)
440  return M0_ERR(-ENOMEM);
441 
444  0, adom->sad_dom_key);
445  dom->sd_private = adom;
447  m0_be_emap_init(&adom->sad_adata, seg);
448 
449  ballroom = adom->sad_ballroom;
450  m0_balloc_init(b2m0(ballroom));
451  rc = ballroom->ab_ops->bo_init(ballroom, seg,
452  adom->sad_bshift,
453  adom->sad_container_size,
454  adom->sad_blocks_per_group,
455 #ifdef __SPARE_SPACE__
457 #else
458  0);
459 #endif
460  balloc_inited = rc == 0;
461 
462  rc = rc ?: stob_ad_bstore(&adom->sad_bstore_id,
463  &adom->sad_bstore);
464  if (rc != 0) {
465  if (balloc_inited)
466  ballroom->ab_ops->bo_fini(ballroom);
467  m0_be_emap_fini(&adom->sad_adata);
468  m0_free(dom);
469  } else {
470  m0_stob_ad_domain_bob_init(adom);
471  adom->sad_be_seg = seg;
472  adom->sad_babshift = adom->sad_bshift -
474  M0_LOG(M0_DEBUG, "sad_bshift = %lu\tstob bshift=%lu",
475  (unsigned long)adom->sad_bshift,
476  (unsigned long)m0_stob_block_shift(adom->sad_bstore));
477  M0_ASSERT(adom->sad_babshift >= 0);
478  }
479 
480  if (rc == 0)
481  *out = dom;
482  return rc == 0 ? M0_RC(rc) : M0_ERR(rc);
483 }
484 
486 {
487  struct m0_stob_ad_domain *adom = stob_ad_domain2ad(dom);
488  struct m0_ad_balloc *ballroom = adom->sad_ballroom;
489 
490  ballroom->ab_ops->bo_fini(ballroom);
491  m0_be_emap_fini(&adom->sad_adata);
492  m0_stob_put(adom->sad_bstore);
493  m0_stob_ad_domain_bob_fini(adom);
494  m0_free(dom);
495 }
496 
498  const char *location_data,
499  struct m0_be_tx_credit *accum)
500 {
501  struct m0_be_emap map = {};
502  struct m0_buf data = { .b_nob = sizeof(struct stob_ad_0type_rec) };
503 
506  m0_be_emap_credit(&map, M0_BEO_CREATE, 1, accum);
509  location_data, &data, accum);
510 }
511 
513  const char *location_data,
514  struct m0_be_tx_credit *accum)
515 {
516  struct m0_be_emap map = {};
517 
518  M0_BE_FREE_CREDIT_PTR((struct m0_stob_ad_domain *)NULL, seg, accum);
520  m0_be_emap_credit(&map, M0_BEO_DESTROY, 1, accum);
523  location_data, accum);
524 }
525 
526 /* TODO Make cleanup on fail. */
528  const char *location_data,
529  uint64_t dom_key,
530  void *cfg_create)
531 {
532  struct ad_domain_cfg *cfg = (struct ad_domain_cfg *)cfg_create;
533  struct m0_be_seg *seg = cfg->adg_seg;
534  struct m0_sm_group *grp = stob_ad_sm_group();
535  struct m0_stob_ad_domain *adom;
536  struct m0_be_emap *emap;
537  struct m0_balloc *cb = NULL;
538  struct m0_be_tx tx = {};
539  struct m0_be_tx_credit cred = M0_BE_TX_CREDIT(0, 0);
540  struct stob_ad_0type_rec seg0_ad_rec;
541  struct m0_buf seg0_data;
542  int rc;
543 
544  M0_PRE(seg != NULL);
545  M0_PRE(strlen(location_data) < ARRAY_SIZE(adom->sad_path));
546 
547  adom = stob_ad_domain_locate(location_data);
548  if (adom != NULL)
549  return M0_ERR(-EEXIST);
550 
552  m0_be_tx_init(&tx, 0, seg->bs_domain, grp, NULL, NULL, NULL, NULL);
553  stob_ad_domain_create_credit(seg, location_data, &cred);
554  m0_be_tx_prep(&tx, &cred);
555  /* m0_balloc_create() makes own local transaction thereby must be called
556  * before openning of exclusive transaction. m0_balloc_destroy() is not
557  * implemented, so balloc won't be cleaned up on a further fail.
558  */
559  rc = m0_balloc_create(dom_key, seg, grp, &cb,
560  &cfg->adg_id.si_fid);
562 
563  M0_ASSERT(adom == NULL);
564  if (rc == 0)
565  M0_BE_ALLOC_PTR_SYNC(adom, seg, &tx);
566  if (adom != NULL) {
568  .ot_version = M0_STOB_AD_DOMAIN_FORMAT_VERSION,
569  .ot_type = M0_FORMAT_TYPE_STOB_AD_DOMAIN,
570  .ot_footer_offset =
571  offsetof(struct m0_stob_ad_domain, sad_footer)
572  });
573  adom->sad_dom_key = dom_key;
575  adom->sad_bshift = cfg->adg_bshift;
577 #ifdef __SPARE_SPACE__
580 #endif
581  adom->sad_bstore_id = cfg->adg_id;
582  if (M0_FI_ENABLED("write_undo"))
583  adom->sad_overwrite = false;
584  else
585  adom->sad_overwrite = true;
586  strcpy(adom->sad_path, location_data);
588  emap = &adom->sad_adata;
591  op,
592  m0_be_emap_create(emap, &tx, &op,
593  &cfg->adg_id.si_fid),
594  bo_u.u_emap.e_rc);
596 
597  seg0_ad_rec = (struct stob_ad_0type_rec){.sa0_ad_domain = adom}; /* XXX won't be a pointer */
598  m0_format_header_pack(&seg0_ad_rec.sa0_header, &(struct m0_format_tag){
599  .ot_version = M0_STOB_AD_0TYPE_REC_FORMAT_VERSION,
600  .ot_type = M0_FORMAT_TYPE_STOB_AD_0TYPE_REC,
601  .ot_footer_offset = offsetof(struct stob_ad_0type_rec, sa0_footer)
602  });
603  m0_format_footer_update(&seg0_ad_rec);
604  seg0_data = M0_BUF_INIT_PTR(&seg0_ad_rec);
606  &tx, location_data, &seg0_data);
607  if (rc == 0) {
608  adom->sad_ballroom = &cb->cb_ballroom;
610  M0_BE_TX_CAPTURE_PTR(seg, &tx, adom);
611  }
612 
613  m0_be_tx_close_sync(&tx);
614  }
615 
616  m0_be_tx_fini(&tx);
618 
619  if (adom == NULL && rc == 0)
620  rc = M0_ERR(-ENOMEM);
621 
622  return M0_RC(rc);
623 }
624 
626  const char *location_data)
627 {
628  struct m0_stob_ad_domain *adom = stob_ad_domain_locate(location_data);
629  struct m0_sm_group *grp = stob_ad_sm_group();
630  struct m0_be_emap *emap = &adom->sad_adata;
631  struct m0_be_seg *seg;
632  struct m0_be_tx tx = {};
633  struct m0_be_tx_credit cred = M0_BE_TX_CREDIT(0, 0);
634  int rc;
635 
636  if (adom == NULL)
637  return 0;
638 
639  seg = adom->sad_be_seg;
641  m0_be_tx_init(&tx, 0, seg->bs_domain, grp, NULL, NULL, NULL, NULL);
642  stob_ad_domain_destroy_credit(seg, location_data, &cred);
643  m0_be_tx_prep(&tx, &cred);
645  if (rc == 0) {
648  bo_u.u_emap.e_rc);
650  &tx, location_data);
651  if (rc == 0)
652  M0_BE_FREE_PTR_SYNC(adom, seg, &tx);
653  m0_be_tx_close_sync(&tx);
654  }
655  m0_be_tx_fini(&tx);
657 
658  /* m0_balloc_destroy() isn't implemented */
659 
660  return M0_RC(rc);
661 }
662 
663 static struct m0_stob *stob_ad_alloc(struct m0_stob_domain *dom,
664  const struct m0_fid *stob_fid)
665 {
666  struct m0_stob_ad *adstob;
667 
668  M0_ALLOC_PTR(adstob);
669  return adstob == NULL ? NULL : &adstob->ad_stob;
670 }
671 
672 static void stob_ad_free(struct m0_stob_domain *dom,
673  struct m0_stob *stob)
674 {
675  struct m0_stob_ad *adstob = stob_ad_stob2ad(stob);
676  m0_free(adstob);
677 }
678 
679 static int stob_ad_cfg_parse(const char *str_cfg_create, void **cfg_create)
680 {
681  return 0;
682 }
683 
684 static void stob_ad_cfg_free(void *cfg_create)
685 {
686 }
687 
688 static int stob_ad_init(struct m0_stob *stob,
689  struct m0_stob_domain *dom,
690  const struct m0_fid *stob_fid)
691 {
692  struct m0_stob_ad_domain *adom = stob_ad_domain2ad(dom);
693  struct m0_be_emap_cursor it = {};
694  struct m0_uint128 prefix;
695  int rc;
696 
697  prefix = M0_UINT128(stob_fid->f_container, stob_fid->f_key);
699  stob->so_ops = &stob_ad_ops;
701  &it.ec_op,
702  m0_be_emap_lookup(&adom->sad_adata, &prefix, 0, &it),
703  bo_u.u_emap.e_rc);
704  if (rc == 0) {
706  }
707  return rc == -ESRCH ? -ENOENT : rc;
708 }
709 
710 static void stob_ad_fini(struct m0_stob *stob)
711 {
712 }
713 
715  struct m0_be_tx_credit *accum)
716 {
717  struct m0_stob_ad_domain *adom = stob_ad_domain2ad(dom);
718  m0_be_emap_credit(&adom->sad_adata, M0_BEO_INSERT, 1, accum);
719 }
720 
721 static int stob_ad_create(struct m0_stob *stob,
722  struct m0_stob_domain *dom,
723  struct m0_dtx *dtx,
724  const struct m0_fid *stob_fid,
725  void *cfg)
726 {
727  struct m0_stob_ad_domain *adom = stob_ad_domain2ad(dom);
728  struct m0_uint128 prefix;
729 
730  M0_PRE(dtx != NULL);
731  prefix = M0_UINT128(stob_fid->f_container, stob_fid->f_key);
733  return M0_BE_OP_SYNC_RET(op,
735  &dtx->tx_betx, &op,
736  &prefix, AET_HOLE),
737  bo_u.u_emap.e_rc);
738 }
739 
756 static int stob_ad_punch_credit(struct m0_stob *stob,
757  struct m0_indexvec *want,
758  struct m0_indexvec *got,
759  struct m0_be_tx_credit *accum)
760 {
763  m0_bcount_t segs = 0;
764  struct m0_ivec_cursor cur;
765  int rc = 0;
766  struct m0_be_tx_credit cred;
767  struct m0_be_emap_cursor it = {};
768  struct m0_be_emap_seg *seg = NULL;
769  struct m0_be_engine *eng;
770  struct m0_stob_ad_domain *adom;
771  struct m0_ad_balloc *ballroom;
772  struct m0_ext todo = {
773  .e_start = 0,
774  .e_end = M0_BCOUNT_MAX
775  };
776 
777  M0_ENTRY("stob:%p, want:%p", stob, want);
779  ballroom = adom->sad_ballroom;
780  m0_ivec_cursor_init(&cur, want);
781  rc = stob_ad_cursor(adom, stob, 0, &it);
782  if (rc != 0) {
783  return M0_ERR(rc);
784  }
786  count = 0;
787  while (!m0_ivec_cursor_move(&cur, count)) {
790  todo.e_start = offset;
791  todo.e_end = offset + count;
792  rc = stob_ad_cursor(adom, stob, offset, &it);
793  if (rc != 0)
794  return M0_ERR(rc);
795 
797  M0_ASSERT(m0_ext_is_valid(&seg->ee_ext) &&
798  !m0_ext_is_empty(&seg->ee_ext));
799  M0_LOG(M0_DEBUG, "stob:%p todo:"EXT_F ", existing ext:"EXT_F,
800  stob, EXT_P(&todo), EXT_P(&seg->ee_ext));
801  M0_SET0(&cred);
802  m0_be_emap_credit(&adom->sad_adata, M0_BEO_PASTE, 1, &cred);
803  ballroom->ab_ops->bo_free_credit(ballroom, 3, &cred);
804  if (m0_be_should_break(eng, accum, &cred))
805  break;
806  count = seg->ee_ext.e_end - offset;
807  M0_CNT_INC(segs);
808  m0_be_tx_credit_add(accum, &cred);
809  if (m0_be_emap_ext_is_last(&seg->ee_ext))
810  break;
811  }
813 
814  if (segs == 0)
815  return M0_RC(-EBUSY);
816  got->iv_index[0] = want->iv_index[0];
817  if (m0_be_emap_ext_is_last(&seg->ee_ext) ||
818  want->iv_vec.v_count[0] < seg->ee_ext.e_end)
819  got->iv_vec.v_count[0] = want->iv_vec.v_count[0];
820  else
821  got->iv_vec.v_count[0] = seg->ee_ext.e_end;
822  return M0_RC(0);
823 }
824 
831 static int ext_punch(struct m0_stob *stob, struct m0_dtx *tx,
832  struct m0_ext *todo)
833 {
834  struct m0_stob_ad_domain *adom;
835  struct m0_be_emap_cursor it = {};
836  struct m0_be_op *it_op;
837  struct m0_ext *ext;
838  int rc;
839 
841  rc = stob_ad_cursor(adom, stob, todo->e_start, &it);
842  if (rc != 0)
843  return M0_ERR(rc);
844  ext = &it.ec_seg.ee_ext;
845  if (M0_FI_ENABLED("test-ext-release")) {
846  /*
847  * Assert the target and existing extents are same, this
848  * ensures that existing extent at this offset is released
849  * (punched) before new extent is allocated and data is written
850  * at the same offset.
851  */
852  M0_ASSERT(m0_ext_equal(todo, ext));
853  }
854 
855  it_op = &it.ec_op;
856  M0_SET0(it_op);
858  M0_LOG(M0_DEBUG, "ext ="EXT_F, EXT_P(todo));
859  m0_be_emap_paste(&it, &tx->tx_betx, todo, AET_HOLE,
860  LAMBDA(void, (struct m0_be_emap_seg *__seg) {
861  /* handle extent deletion. */
862  rc = rc ?: stob_ad_seg_free(tx, adom, __seg,
863  &__seg->ee_ext,
864  __seg->ee_val);
865  }),
866  LAMBDA(void, (struct m0_be_emap_seg *__seg,
867  struct m0_ext *__ext,
868  uint64_t __val) {
869  /* cut left */
870  M0_ASSERT(__ext->e_start > __seg->ee_ext.e_start);
871 
872  __seg->ee_val = __val;
873  rc = rc ?: stob_ad_seg_free(tx, adom, __seg,
874  __ext, __val);
875  }),
876  LAMBDA(void, (struct m0_be_emap_seg *__seg,
877  struct m0_ext *__ext,
878  uint64_t __val) {
879  /* cut right */
880  M0_ASSERT(__seg->ee_ext.e_end > __ext->e_end);
881  if (__val < AET_MIN) {
882  __seg->ee_val = __val +
883  (__ext->e_end - __seg->ee_ext.e_start);
884  /*
885  * Free physical sub-extent, but only when
886  * sub-extent starts at the left boundary of
887  * the logical extent, because otherwise
888  * "cut left" already freed it.
889  */
890  if (__ext->e_start == __seg->ee_ext.e_start)
891  rc = rc ?: stob_ad_seg_free(tx, adom,
892  __seg,
893  __ext,
894  __val);
895  } else
896  __seg->ee_val = __val;
897  }));
898 
900  rc = m0_be_emap_op_rc(&it);
902  return M0_RC(rc);
903 }
904 
905 static void stob_ad_destroy_credit(struct m0_stob *stob,
906  struct m0_be_tx_credit *accum)
907 {
908  struct m0_stob_ad_domain *adom;
909 
911  m0_be_emap_credit(&adom->sad_adata, M0_BEO_DELETE, 1, accum);
912 }
913 
914 static int stob_ad_destroy(struct m0_stob *stob, struct m0_dtx *tx)
915 {
916  struct m0_stob_ad_domain *adom;
917  struct m0_uint128 prefix;
918  int rc;
919  const struct m0_fid *fid = m0_stob_fid_get(stob);
920 
925  &tx->tx_betx, &op,
926  &prefix),
927  bo_u.u_emap.e_rc);
928 
929  return M0_RC(rc);
930 }
931 
937 static int stob_ad_punch(struct m0_stob *stob, struct m0_indexvec *range,
938  struct m0_dtx *tx)
939 {
940  struct m0_ext todo;
943  struct m0_ivec_cursor cur;
944  int rc = 0;
945 
946  m0_ivec_cursor_init(&cur, range);
947  count = 0;
948  while (!m0_ivec_cursor_move(&cur, count)) {
951  todo.e_start = offset;
952  todo.e_end = offset + count;
953  M0_LOG(M0_DEBUG, "stob %p, punching"EXT_F, stob, EXT_P(&todo));
954  rc = ext_punch(stob, tx, &todo);
955  if (rc != 0)
956  return M0_ERR(rc);
957  }
958  return M0_RC(0);
959 }
960 
961 static uint32_t stob_ad_block_shift(struct m0_stob *stob)
962 {
963  struct m0_stob_ad_domain *adom;
964 
966  return m0_stob_block_shift(adom->sad_bstore);
967 }
968 
971  .sto_deregister = &stob_ad_type_deregister,
972  .sto_domain_cfg_init_parse = &stob_ad_domain_cfg_init_parse,
973  .sto_domain_cfg_init_free = &stob_ad_domain_cfg_init_free,
974  .sto_domain_cfg_create_parse = &stob_ad_domain_cfg_create_parse,
975  .sto_domain_cfg_create_free = &stob_ad_domain_cfg_create_free,
976  .sto_domain_init = &stob_ad_domain_init,
977  .sto_domain_create = &stob_ad_domain_create,
978  .sto_domain_destroy = &stob_ad_domain_destroy,
979 };
980 
981 static struct m0_stob_domain_ops stob_ad_domain_ops = {
983  .sdo_stob_alloc = &stob_ad_alloc,
984  .sdo_stob_free = &stob_ad_free,
985  .sdo_stob_cfg_parse = &stob_ad_cfg_parse,
986  .sdo_stob_cfg_free = &stob_ad_cfg_free,
987  .sdo_stob_init = &stob_ad_init,
988  .sdo_stob_create_credit = &stob_ad_create_credit,
989  .sdo_stob_create = &stob_ad_create,
990  .sdo_stob_write_credit = &stob_ad_write_credit,
991 };
992 
993 static struct m0_stob_ops stob_ad_ops = {
995  .sop_destroy_credit = &stob_ad_destroy_credit,
996  .sop_destroy = &stob_ad_destroy,
997  .sop_punch_credit = &stob_ad_punch_credit,
998  .sop_punch = &stob_ad_punch,
999  .sop_io_init = &stob_ad_io_init,
1000  .sop_block_shift = &stob_ad_block_shift,
1001 };
1002 
1005  .st_fidt = {
1006  .ft_id = STOB_TYPE_AD,
1007  .ft_name = "adstob",
1008  },
1009 };
1010 
1011 /*
1012  * Adieu
1013  */
1014 
1015 static const struct m0_stob_io_op stob_ad_io_op;
1016 
1017 static bool stob_ad_endio(struct m0_clink *link);
1018 static void stob_ad_io_release(struct m0_stob_ad_io *aio);
1019 
1020 static int stob_ad_io_init(struct m0_stob *stob, struct m0_stob_io *io)
1021 {
1022  struct m0_stob_ad_io *aio;
1023  int rc;
1024 
1025  M0_PRE(io->si_state == SIS_IDLE);
1026 
1027  M0_ALLOC_PTR(aio);
1028  if (aio != NULL) {
1029  io->si_stob_private = aio;
1030  io->si_op = &stob_ad_io_op;
1031  aio->ai_fore = io;
1032  m0_stob_io_init(&aio->ai_back);
1034  m0_clink_add_lock(&aio->ai_back.si_wait, &aio->ai_clink);
1035  rc = 0;
1036  } else {
1037  rc = M0_ERR(-ENOMEM);
1038  }
1039  return M0_RC(rc);
1040 }
1041 
1042 static void stob_ad_io_fini(struct m0_stob_io *io)
1043 {
1044  struct m0_stob_ad_io *aio = io->si_stob_private;
1045  stob_ad_io_release(aio);
1046  m0_clink_del_lock(&aio->ai_clink);
1047  m0_clink_fini(&aio->ai_clink);
1048  m0_stob_io_fini(&aio->ai_back);
1049  m0_free(aio);
1050 }
1051 
1052 static void *stob_ad_addr_open(const void *buf, uint32_t shift)
1053 {
1054  uint64_t addr = (uint64_t)buf;
1055 
1056  M0_PRE(((addr << shift) >> shift) == addr);
1057  return (void *)(addr << shift);
1058 }
1059 
1064 static int stob_ad_balloc(struct m0_stob_ad_domain *adom, struct m0_dtx *tx,
1065  m0_bcount_t count, struct m0_ext *out,
1066  uint64_t alloc_type)
1067 {
1068  struct m0_ad_balloc *ballroom = adom->sad_ballroom;
1069  int rc;
1070 
1071  count >>= adom->sad_babshift;
1072  M0_LOG(M0_DEBUG, "count=%lu", (unsigned long)count);
1073  M0_ASSERT(count > 0);
1074  rc = ballroom->ab_ops->bo_alloc(ballroom, tx, count, out, alloc_type);
1075  out->e_start <<= adom->sad_babshift;
1076  out->e_end <<= adom->sad_babshift;
1077  m0_ext_init(out);
1078 
1079  return M0_RC(rc);
1080 }
1081 
1086 static int stob_ad_bfree(struct m0_stob_ad_domain *adom, struct m0_dtx *tx,
1087  struct m0_ext *ext)
1088 {
1089  struct m0_ad_balloc *ballroom = adom->sad_ballroom;
1090  struct m0_ext tgt;
1091 
1092  M0_PRE((ext->e_start & ((1ULL << adom->sad_babshift) - 1)) == 0);
1093  M0_PRE((ext->e_end & ((1ULL << adom->sad_babshift) - 1)) == 0);
1094 
1095  tgt.e_start = ext->e_start >> adom->sad_babshift;
1096  tgt.e_end = ext->e_end >> adom->sad_babshift;
1097  m0_ext_init(&tgt);
1098  return ballroom->ab_ops->bo_free(ballroom, tx, &tgt);
1099 }
1100 
1101 M0_INTERNAL int stob_ad_cursor(struct m0_stob_ad_domain *adom,
1102  struct m0_stob *obj,
1103  uint64_t offset,
1104  struct m0_be_emap_cursor *it)
1105 {
1106  const struct m0_fid *fid = m0_stob_fid_get(obj);
1107  struct m0_uint128 prefix;
1108  int rc;
1109 
1112  M0_SET0(&it->ec_op);
1114  &it->ec_op,
1116  bo_u.u_emap.e_rc);
1117  return M0_RC(rc);
1118 }
1119 
1120 static uint32_t stob_ad_write_map_count(struct m0_stob_ad_domain *adom,
1121  struct m0_indexvec *iv, bool pack)
1122 {
1123  uint32_t frags;
1124  m0_bcount_t frag_size;
1125  m0_bcount_t grp_size;
1126  bool eov;
1127  struct m0_ivec_cursor it;
1128 
1129  M0_ENTRY("dom=%p bshift=%u babshift=%d pack=%#x", adom,
1130  adom->sad_bshift, adom->sad_babshift, (int)pack);
1131 
1132  frags = 0;
1133  m0_ivec_cursor_init(&it, iv);
1134  grp_size = adom->sad_blocks_per_group << adom->sad_babshift;
1135 
1136  if (pack)
1137  m0_indexvec_pack(iv);
1138  do {
1139  frag_size = min_check(m0_ivec_cursor_step(&it), grp_size);
1140  M0_ASSERT(frag_size > 0);
1141  M0_ASSERT(frag_size <= (size_t)~0ULL);
1142  M0_LOG(M0_DEBUG, "frag_size=0x%"PRIx64, frag_size);
1143 
1144  eov = m0_ivec_cursor_move(&it, frag_size);
1145 
1146  M0_CNT_INC(frags);
1147  } while (!eov);
1148 
1149  M0_LEAVE("dom=%p frags=%u", adom, frags);
1150  return frags;
1151 }
1152 
1153 static void stob_ad_write_credit(const struct m0_stob_domain *dom,
1154  const struct m0_stob_io *io,
1155  struct m0_be_tx_credit *accum)
1156 {
1157  struct m0_stob_ad_domain *adom = stob_ad_domain2ad(dom);
1158  struct m0_ad_balloc *ballroom = adom->sad_ballroom;
1159  /* XXX discard const, because stob_ad_write_map_count() changes iv */
1160  struct m0_indexvec *iv = (struct m0_indexvec *) &io->si_stob;
1161  int bfrags = BALLOC_FRAGS_MAX;
1162  int frags;
1163 
1164  frags = stob_ad_write_map_count(adom, iv, false);
1165  M0_LOG(M0_DEBUG, "frags=%d", frags);
1166  frags = max_check(frags, bfrags);
1167 
1168  if (ballroom->ab_ops->bo_alloc_credit != NULL)
1169  ballroom->ab_ops->bo_alloc_credit(ballroom, bfrags, accum);
1170 
1171  /*
1172  * XXX We don't know if MOTR-2099 is triggered by miscalulating of
1173  * emap credit (BETREE_DELETE epecially). Adding one more extra credit
1174  * of 'emap paste' (that is frags + 1) to verify this idea.
1175  */
1176  m0_be_emap_credit(&adom->sad_adata, M0_BEO_PASTE, frags + 1, accum);
1177 
1178  /*
1179  * Commenting out below part of code with #if 0, earlier it was based
1180  * on assumption that that adom->sad_overwrite will be always false,
1181  * Now we have set it to True by default to fix EOS-25302 hence
1182  * disabling it with "#if 0"
1183  * TODO: Probably sad_overwrite is introduced for COW(Copy on Write) and
1184  * for Object versioning in Motr, which is not implemented yet. Need to
1185  * revisit this part while implementing COW and object versioning.
1186  * We do not know whether bo_free_credit should be commented out or not,
1187  * but this is done to maintain existing behavior as the code was
1188  * anyway redundant earlier.
1189  */
1190 #if 0
1191  if (adom->sad_overwrite && ballroom->ab_ops->bo_free_credit != NULL) {
1192  /* for each emap_paste() seg_free() could be called 3 times */
1193  ballroom->ab_ops->bo_free_credit(ballroom, 3 * frags, accum);
1194  }
1195 #endif
1197 }
1198 
1207 static void stob_ad_io_release(struct m0_stob_ad_io *aio)
1208 {
1209  struct m0_stob_io *back = &aio->ai_back;
1210 
1212  m0_free0(&back->si_user.ov_vec.v_count);
1213  back->si_stob.iv_vec.v_count = NULL;
1214 
1215  m0_free0(&back->si_user.ov_buf);
1216  m0_free0(&back->si_stob.iv_index);
1217 
1218  back->si_obj = NULL;
1219 }
1220 
1225  struct m0_stob_ad_domain *adom,
1226  struct m0_be_emap_cursor *it,
1227  struct m0_vec_cursor *src,
1228  struct m0_vec_cursor *dst,
1229  struct m0_be_emap_caret *map)
1230 {
1231  int rc;
1232 
1233  it->ec_recbuf.b_nob = 0;
1234  it->ec_recbuf.b_addr = NULL;
1235 
1236  rc = stob_ad_cursor(adom, io->si_obj, io->si_stob.iv_index[0], it);
1237  if (rc == 0) {
1241  }
1242  return M0_RC(rc);
1243 }
1244 
1249  struct m0_vec_cursor *src,
1250  struct m0_vec_cursor *dst,
1251  struct m0_be_emap_caret *map)
1252 {
1255 }
1256 
1262 static int stob_ad_vec_alloc(struct m0_stob *obj,
1263  struct m0_stob_io *back,
1264  uint32_t frags)
1265 {
1267  int rc = 0;
1268 
1269  M0_ASSERT(back->si_user.ov_vec.v_count == NULL);
1270 
1271  if (frags > 0) {
1272  M0_ALLOC_ARR(counts, frags);
1273  back->si_user.ov_vec.v_count = counts;
1274  back->si_stob.iv_vec.v_count = counts;
1275  M0_ALLOC_ARR(back->si_user.ov_buf, frags);
1276  M0_ALLOC_ARR(back->si_stob.iv_index, frags);
1277 
1278  back->si_user.ov_vec.v_nr = frags;
1279  back->si_stob.iv_vec.v_nr = frags;
1280 
1281  if (counts == NULL || back->si_user.ov_buf == NULL ||
1282  back->si_stob.iv_index == NULL) {
1283  m0_free(counts);
1284  m0_free(back->si_user.ov_buf);
1285  m0_free(back->si_stob.iv_index);
1286  rc = M0_ERR(-ENOMEM);
1287  }
1288  }
1289  return M0_RC(rc);
1290 }
1291 
1292 /* This function will copy the checksum for the fragment (off, frag_sz), into
1293  * the destination buffer allocated in reply FOP. It also updates si_cksum_nob_read
1294  * for tracking how many checksum nob is copied.
1295  * Note: Assumption is that overlapping fragments are not passed to this function
1296  * during multiple calls, otherwise duplicate checksum entry will get copied
1297  * and will assert.
1298  */
1300  struct m0_be_emap_cursor *it,
1301  m0_bindex_t off,
1302  m0_bindex_t frag_sz)
1303 {
1305  m0_bcount_t cksum_unit_size = io->si_cksum_sz;
1306  m0_bcount_t checksum_nob;
1307  struct m0_be_emap_seg *ext = &it->ec_seg;
1308  void * dst, *src;
1309 
1310  checksum_nob = m0_extent_get_checksum_nob(off, frag_sz, unit_size,
1311  cksum_unit_size);
1312  if (checksum_nob) {
1313  // we are looking at checksum which need to be added:
1314  // get the destination: checksum address to copy in client buffer
1316  //get the source: checksum address from segment
1318  ext->ee_ext.e_start,
1319  unit_size, cksum_unit_size);
1320 
1321  // copy from source to client buffer
1322  memcpy(dst, src, checksum_nob);
1323 
1324  // update checksum fill count for stio
1325  io->si_cksum_nob_read += checksum_nob;
1327  }
1328 }
1329 
1351  struct m0_stob_ad_domain *adom,
1352  struct m0_vec_cursor *src,
1353  struct m0_vec_cursor *dst,
1354  struct m0_be_emap_caret *car)
1355 {
1356  struct m0_be_emap_cursor *it;
1357  struct m0_be_emap_seg *seg;
1358  struct m0_stob_io *back;
1359  struct m0_stob_ad_io *aio = io->si_stob_private;
1360  uint32_t frags;
1361  uint32_t frags_not_empty;
1362  uint32_t bshift;
1363  m0_bcount_t frag_size; /* measured in blocks */
1364  m0_bindex_t off; /* measured in blocks */
1365  int rc;
1366  int i;
1367  int idx;
1368  bool eosrc;
1369  bool eodst;
1370  int eomap;
1371 
1372  M0_PRE(io->si_opcode == SIO_READ);
1373 
1374  bshift = m0_stob_block_shift(adom->sad_bstore);
1375  it = car->ct_it;
1377  back = &aio->ai_back;
1378 
1379  M0_LOG(M0_DEBUG, "ext="EXT_F" val=0x%llx",
1380  EXT_P(&seg->ee_ext), (unsigned long long)seg->ee_val);
1381 
1382  frags = frags_not_empty = 0;
1383  do {
1384  off = io->si_stob.iv_index[dst->vc_seg] + dst->vc_offset;
1385 
1386  /*
1387  * The next fragment starts at the offset off and the extents
1388  * car has to be positioned at this offset. There are two ways
1389  * to do this:
1390  *
1391  * * lookup an extent containing off (m0_emap_lookup()), or
1392  *
1393  * * iterate from the current position (m0_emap_caret_move())
1394  * until off is reached.
1395  *
1396  * Lookup incurs an overhead of tree traversal, whereas
1397  * iteration could become expensive when extents car is
1398  * fragmented and target extents are far from each other.
1399  *
1400  * Iteration is used for now, because when extents car is
1401  * fragmented or IO locality of reference is weak, performance
1402  * will be bad anyway.
1403  *
1404  * Note: the code relies on the target extents being in
1405  * increasing offset order in dst.
1406  */
1407  M0_ASSERT(off >= car->ct_index);
1408  eomap = m0_be_emap_caret_move_sync(car, off - car->ct_index);
1409  if (eomap < 0)
1410  return M0_RC(eomap);
1411  M0_ASSERT(eomap == 0);
1412  M0_ASSERT(m0_ext_is_in(&seg->ee_ext, off));
1413 
1414  frag_size = min3(m0_vec_cursor_step(src),
1416  m0_be_emap_caret_step(car));
1417  M0_ASSERT(frag_size > 0);
1418  if (frag_size > (size_t)~0ULL)
1419  return M0_ERR(-EOVERFLOW);
1420 
1421  frags++;
1422 
1423  if (seg->ee_val < AET_MIN)
1424  {
1425  /* For RMW case, ignore cksum read from fragments */
1426  if (io->si_cksum_sz && io->si_unit_sz)
1427  stob_ad_get_checksum_for_fragment(io, it, off, frag_size);
1428  frags_not_empty++;
1429  }
1430 
1431  eosrc = m0_vec_cursor_move(src, frag_size);
1432  eodst = m0_vec_cursor_move(dst, frag_size);
1433  eomap = m0_be_emap_caret_move_sync(car, frag_size);
1434  if (eomap < 0)
1435  return M0_RC(eomap);
1436  M0_ASSERT(eosrc == eodst);
1437  M0_ASSERT(!eomap);
1438  } while (!eosrc);
1439 
1440  M0_LOG(M0_DEBUG, "frags=%d frags_not_empty=%d",
1441  (int)frags, (int)frags_not_empty);
1442 
1443  stob_ad_cursors_fini(it, src, dst, car);
1444 
1445  rc = stob_ad_vec_alloc(io->si_obj, back, frags_not_empty);
1446  if (rc != 0)
1447  return M0_RC(rc);
1448 
1449  rc = stob_ad_cursors_init(io, adom, it, src, dst, car);
1450  if (rc != 0)
1451  return M0_RC(rc);
1452 
1453  for (idx = i = 0; i < frags; ++i) {
1454  void *buf;
1455  m0_bindex_t off;
1456 
1457  buf = io->si_user.ov_buf[src->vc_seg] + src->vc_offset;
1458  off = io->si_stob.iv_index[dst->vc_seg] + dst->vc_offset;
1459 
1460  M0_ASSERT(off >= car->ct_index);
1461  eomap = m0_be_emap_caret_move_sync(car, off - car->ct_index);
1462  if (eomap < 0)
1463  return M0_RC(eomap);
1464  M0_ASSERT(eomap == 0);
1465  M0_ASSERT(m0_ext_is_in(&seg->ee_ext, off));
1466 
1467  frag_size = min3(m0_vec_cursor_step(src),
1469  m0_be_emap_caret_step(car));
1470 
1471  /* that is too expensive:
1472  M0_LOG(M0_DEBUG, "%2d: sz=%lx buf=%p off=%lx "
1473  "ext="EXT_F" val=%lx",
1474  idx, (unsigned long)frag_size, buf,
1475  (unsigned long)off, EXT_P(&seg->ee_ext),
1476  (unsigned long)seg->ee_val); */
1477  if (seg->ee_val == AET_HOLE) {
1478  if (io->si_flags & SIF_NOHOLE) {
1479  rc = M0_ERR(-EIO);
1480  break;
1481  }
1482  /*
1483  * Read of a hole or unallocated space (beyond
1484  * end of the file).
1485  */
1486  memset(stob_ad_addr_open(buf, bshift),
1487  0, frag_size << bshift);
1488  io->si_count += frag_size;
1489  } else {
1490  M0_ASSERT(seg->ee_val < AET_MIN);
1491 
1492  back->si_user.ov_vec.v_count[idx] = frag_size;
1493  back->si_user.ov_buf[idx] = buf;
1494 
1495  back->si_stob.iv_index[idx] = seg->ee_val +
1496  (off - seg->ee_ext.e_start);
1497  idx++;
1498  }
1499  m0_vec_cursor_move(src, frag_size);
1500  m0_vec_cursor_move(dst, frag_size);
1501  rc = m0_be_emap_caret_move_sync(car, frag_size);
1502  if (rc < 0)
1503  break;
1504  M0_ASSERT(rc == 0);
1505  }
1506  M0_ASSERT(ergo(rc == 0, idx == frags_not_empty));
1507  return M0_RC(rc);
1508 }
1509 
1514  struct m0_ext we_ext;
1516 };
1517 
1524 };
1525 
1527  struct stob_ad_write_ext *wext)
1528 {
1529  wc->wc_wext = wext;
1530  wc->wc_done = 0;
1531 }
1532 
1534 {
1535  M0_PRE(wc->wc_wext != NULL);
1536  M0_PRE(wc->wc_done < m0_ext_length(&wc->wc_wext->we_ext));
1537 
1538  return m0_ext_length(&wc->wc_wext->we_ext) - wc->wc_done;
1539 }
1540 
1543 {
1544  while (count > 0 && wc->wc_wext != NULL) {
1545  m0_bcount_t step;
1546 
1547  step = stob_ad_wext_cursor_step(wc);
1548  if (count >= step) {
1549  wc->wc_wext = wc->wc_wext->we_next;
1550  wc->wc_done = 0;
1551  count -= step;
1552  } else {
1553  wc->wc_done += count;
1554  count = 0;
1555  }
1556  }
1557  return wc->wc_wext == NULL;
1558 }
1559 
1567 static uint32_t stob_ad_write_count(struct m0_vec_cursor *src,
1568  struct stob_ad_wext_cursor *wc)
1569 {
1570  m0_bcount_t frag_size;
1571  bool eosrc;
1572  bool eoext;
1573  uint32_t frags = 0;
1574 
1575  do {
1576  frag_size = min_check(m0_vec_cursor_step(src),
1578  M0_ASSERT(frag_size > 0);
1579  M0_ASSERT(frag_size <= (size_t)~0ULL);
1580 
1581  eosrc = m0_vec_cursor_move(src, frag_size);
1582  eoext = stob_ad_wext_cursor_move(wc, frag_size);
1583 
1584  M0_ASSERT(ergo(eosrc, eoext));
1585  ++frags;
1586  } while (!eoext);
1587  return frags;
1588 }
1589 
1594  struct m0_stob_io *back,
1595  struct m0_vec_cursor *src,
1596  struct stob_ad_wext_cursor *wc)
1597 {
1598  m0_bcount_t frag_size;
1599  uint32_t idx;
1600  bool eosrc;
1601  bool eoext;
1602 
1603  idx = 0;
1604  do {
1605  void *buf;
1606 
1607  frag_size = min_check(m0_vec_cursor_step(src),
1609 
1610  buf = io->si_user.ov_buf[src->vc_seg] + src->vc_offset;
1611 
1612  back->si_user.ov_vec.v_count[idx] = frag_size;
1613  back->si_user.ov_buf[idx] = buf;
1614 
1615  back->si_stob.iv_index[idx] =
1616  wc->wc_wext->we_ext.e_start + wc->wc_done;
1617 
1618  eosrc = m0_vec_cursor_move(src, frag_size);
1619  eoext = stob_ad_wext_cursor_move(wc, frag_size);
1620  idx++;
1621  M0_ASSERT(eosrc == eoext);
1622  } while (!eoext);
1623  M0_ASSERT(idx == back->si_stob.iv_vec.v_nr);
1624 }
1625 
1630 static int stob_ad_seg_free(struct m0_dtx *tx,
1631  struct m0_stob_ad_domain *adom,
1632  const struct m0_be_emap_seg *seg,
1633  const struct m0_ext *ext,
1634  uint64_t val)
1635 {
1636  m0_bcount_t delta = ext->e_start - seg->ee_ext.e_start;
1637  struct m0_ext tocut = {
1638  .e_start = val + delta,
1639  .e_end = val + delta + m0_ext_length(ext)
1640  };
1641  m0_ext_init(&tocut);
1642  if (val < AET_MIN) {
1643  M0_LOG(M0_DEBUG, "freeing "EXT_F"@"EXT_F,
1644  EXT_P(ext), EXT_P(&tocut));
1645  }
1646 
1647  return val < AET_MIN ? stob_ad_bfree(adom, tx, &tocut) : 0;
1648 }
1649 
1662  struct m0_stob_ad_domain *adom,
1663  m0_bindex_t off,
1664  struct m0_be_emap_cursor *orig,
1665  const struct m0_ext *ext)
1666 {
1667  int result;
1668  int rc = 0;
1669  struct m0_be_emap_cursor it = {};
1670  /* an extent in the logical name-space to be mapped to ext. */
1671  struct m0_ext todo = {
1672  .e_start = off,
1673  .e_end = off + m0_ext_length(ext)
1674  };
1675  m0_ext_init(&todo);
1676 
1677  M0_ENTRY("ext="EXT_F" val=0x%llx", EXT_P(&todo),
1678  (unsigned long long)ext->e_start);
1679 
1680  result = M0_BE_OP_SYNC_RET_WITH(
1681  &it.ec_op,
1682  m0_be_emap_lookup(orig->ec_map, &orig->ec_seg.ee_pre,
1683  off, &it),
1684  bo_u.u_emap.e_rc);
1685  if (result != 0)
1686  return M0_RC(result);
1687 
1688  /*
1689  * Insert a new segment into extent map, overwriting parts of the map.
1690  *
1691  * Some existing segments are deleted completely, others are
1692  * cut. m0_emap_paste() invokes supplied call-backs to notify the caller
1693  * about changes in the map.
1694  *
1695  * Call-backs are used to free space from overwritten parts of the file.
1696  *
1697  * Each call-back takes a segment argument, seg. seg->ee_ext is a
1698  * logical extent of the segment and seg->ee_val is the starting offset
1699  * of the corresponding physical extent.
1700  */
1701  if (io->si_cksum.b_nob != 0) {
1702 
1703  /* Compute checksum units info which belong to this extent (COB off & Sz) */
1706  io->si_unit_sz,
1707  io->si_cksum_sz);
1708  }
1709  else {
1712  }
1713 
1715 
1716  M0_SET0(&it.ec_op);
1718  m0_be_emap_paste(&it, &io->si_tx->tx_betx, &todo, ext->e_start,
1719  LAMBDA(void, (struct m0_be_emap_seg *seg) {
1720  /* handle extent deletion. */
1721  if (adom->sad_overwrite) {
1722  M0_LOG(M0_DEBUG, "del: val=0x%llx",
1723  (unsigned long long)seg->ee_val);
1724  M0_ASSERT_INFO(seg->ee_val != ext->e_start,
1725  "Delete of the same just allocated block");
1726  rc = rc ?:
1727  stob_ad_seg_free(io->si_tx, adom, seg,
1728  &seg->ee_ext, seg->ee_val);
1729  }
1730  }),
1731  LAMBDA(void, (struct m0_be_emap_seg *seg, struct m0_ext *ext,
1732  uint64_t val) {
1733  /* cut left */
1734  M0_ASSERT(ext->e_start > seg->ee_ext.e_start);
1735 
1736  seg->ee_val = val;
1737  if (adom->sad_overwrite)
1738  rc = rc ?:
1739  stob_ad_seg_free(io->si_tx, adom, seg,
1740  ext, val);
1741  }),
1742  LAMBDA(void, (struct m0_be_emap_seg *seg, struct m0_ext *ext,
1743  uint64_t val) {
1744  /* cut right */
1745  M0_ASSERT(seg->ee_ext.e_end > ext->e_end);
1746  if (val < AET_MIN) {
1747  seg->ee_val = val +
1748  (ext->e_end - seg->ee_ext.e_start);
1749  /*
1750  * Free physical sub-extent, but only when
1751  * sub-extent starts at the left boundary of the
1752  * logical extent, because otherwise "cut left"
1753  * already freed it.
1754  */
1755  if (adom->sad_overwrite &&
1756  ext->e_start == seg->ee_ext.e_start)
1757  rc = rc ?:
1758  stob_ad_seg_free(io->si_tx, adom,
1759  seg, ext, val);
1760  } else
1761  seg->ee_val = val;
1762  }));
1764  result = it.ec_op.bo_u.u_emap.e_rc;
1766  m0_be_emap_close(&it);
1767 
1768  return M0_RC(result ?: rc);
1769 }
1770 
1771 static int stob_ad_fol_frag_alloc(struct m0_fol_frag *frag, uint32_t frags)
1772 {
1773  struct stob_ad_rec_frag *arp;
1774 
1775  M0_PRE(frag != NULL);
1776 
1777  M0_ALLOC_PTR(arp);
1778  if (arp == NULL)
1779  return M0_ERR(-ENOMEM);
1780  m0_fol_frag_init(frag, arp, &stob_ad_rec_frag_type);
1781 
1782  arp->arp_seg.ps_segments = frags;
1783 
1784  M0_ALLOC_ARR(arp->arp_seg.ps_old_data, frags);
1785  if (arp->arp_seg.ps_old_data == NULL) {
1786  m0_free(arp);
1787  return M0_ERR(-ENOMEM);
1788  }
1789  return 0;
1790 }
1791 
1792 static void stob_ad_fol_frag_free(struct m0_fol_frag *frag)
1793 {
1794  struct stob_ad_rec_frag *arp = frag->rp_data;
1795 
1796  m0_free(arp->arp_seg.ps_old_data);
1797  m0_free(arp);
1798 }
1799 
1811 static int stob_ad_write_map(struct m0_stob_io *io,
1812  struct m0_stob_ad_domain *adom,
1813  struct m0_ivec_cursor *dst,
1814  struct m0_be_emap_caret *map,
1815  struct stob_ad_wext_cursor *wc,
1816  uint32_t frags)
1817 {
1818  int rc;
1819  m0_bcount_t frag_size;
1820  m0_bindex_t off;
1821  bool eodst;
1822  bool eoext;
1823  struct m0_ext todo;
1824  struct m0_fol_frag *frag = io->si_fol_frag;
1825  struct stob_ad_rec_frag *arp;
1826  uint32_t i = 0;
1827  uint32_t last_seg;
1828 
1829  M0_ENTRY("io=%p dom=%p frags=%u", io, adom, frags);
1830 
1831  rc = stob_ad_fol_frag_alloc(frag, frags);
1832  if (rc != 0)
1833  return M0_RC(rc);
1834  arp = frag->rp_data;
1835  arp->arp_stob_id = *m0_stob_id_get(io->si_obj);
1837 
1838  do {
1839  off = m0_ivec_cursor_index(dst);
1840  frag_size = min_check(m0_ivec_cursor_step(dst),
1842 
1843  todo.e_start = wc->wc_wext->we_ext.e_start + wc->wc_done;
1844  todo.e_end = todo.e_start + frag_size;
1845  m0_ext_init(&todo);
1846 
1847  M0_ASSERT(i < frags);
1848  arp->arp_seg.ps_old_data[i] = (struct m0_be_emap_seg) {
1849  .ee_ext = {
1850  .e_start = off,
1851  .e_end = off + m0_ext_length(&todo)
1852  },
1853  .ee_val = todo.e_start,
1854  .ee_pre = map->ct_it->ec_seg.ee_pre
1855  };
1857 
1858  rc = stob_ad_write_map_ext(io, adom, off, map->ct_it, &todo);
1859  if (rc != 0)
1860  break;
1861 
1862  last_seg = dst->ic_cur.vc_seg;
1863  eodst = m0_ivec_cursor_move(dst, frag_size);
1864  eoext = stob_ad_wext_cursor_move(wc, frag_size);
1865 
1866  /*
1867  * In m0_vec_cursor_move() if (count >= steps) evaluates to
1868  * false and also the segments are not empty
1869  * (m0_vec_cursor_normalize() skips empty segments) then
1870  * cur->vc_seg is not incremented. i.e. cursor is not actually
1871  * moved ahead.
1872  * In such cases index i shouldn't also be advanced. Otherwise
1873  * it will end up accessing invalid index of
1874  * arp->arp_seg.ps_old_data[].
1875  */
1876  if (last_seg != dst->ic_cur.vc_seg)
1877  ++i;
1878 
1879  M0_ASSERT(eodst == eoext);
1880  } while (!eodst);
1881 
1882  if (rc == 0)
1883  m0_fol_frag_add(&io->si_tx->tx_fol_rec, frag);
1884  else
1885  stob_ad_fol_frag_free(frag);
1886 
1887  return M0_RC(rc);
1888 }
1889 
1893 static void stob_ad_wext_fini(struct stob_ad_write_ext *wext)
1894 {
1895  struct stob_ad_write_ext *next;
1896 
1897  for (wext = wext->we_next; wext != NULL; wext = next) {
1898  next = wext->we_next;
1899  m0_free(wext);
1900  }
1901 }
1902 
1919  struct m0_stob_ad_domain *adom,
1920  struct m0_vec_cursor *src,
1921  struct m0_be_emap_caret *map)
1922 {
1923  m0_bcount_t todo;
1924  uint32_t bfrags = 0;
1925  int rc;
1926  struct stob_ad_write_ext head;
1927  struct stob_ad_write_ext *wext;
1928  struct stob_ad_write_ext *next;
1929  struct m0_stob_io *back;
1930  struct m0_stob_ad_io *aio = io->si_stob_private;
1931  struct stob_ad_wext_cursor wc;
1932 
1935  /* Get total size of buffer */
1936  todo = m0_vec_count(&io->si_user.ov_vec);
1937  M0_ENTRY("op=%d sz=%lu", io->si_opcode, (unsigned long)todo);
1938  back = &aio->ai_back;
1939  M0_SET0(&head);
1940  wext = &head;
1941  wext->we_next = NULL;
1942  while (1) {
1943  m0_bcount_t got;
1944 
1947  /* Get the balloc extent (returned in wext->we_ext) */
1948  rc = stob_ad_balloc(adom, io->si_tx, todo, &wext->we_ext,
1949  aio->ai_balloc_flags);
1952  if (rc != 0)
1953  break;
1954  /* Get balloc extent length */
1955  got = m0_ext_length(&wext->we_ext);
1956  M0_ASSERT(todo >= got);
1957  M0_LOG(M0_DEBUG, "got=%" PRId64 ": " EXT_F,
1958  got, EXT_P(&wext->we_ext));
1959  todo -= got;
1960  ++bfrags;
1961  if (todo > 0) {
1962  if (bfrags >= BALLOC_FRAGS_MAX) {
1963  rc = M0_ERR(-ENOSPC);
1964  break;
1965  }
1966  /* More balloc extent needed so allocate node stob_ad_write_ext
1967  * and add it to link list, so that stob_ad_balloc can populate it
1968  */
1969  M0_ALLOC_PTR(next);
1970  if (next != NULL) {
1971  wext->we_next = next;
1972  wext = next;
1973  } else {
1974  rc = M0_ERR(-ENOMEM);
1975  break;
1976  }
1977  } else
1978  break;
1979  }
1980 
1981  M0_LOG(M0_DEBUG, "bfrags=%u", bfrags);
1982 
1983  if (rc == 0) {
1984  uint32_t frags;
1985 
1986  /* Init cursor for balloc extents */
1988  /* Find num of frag based on boundaries of balloc-extents & buffer-extents */
1989  frags = stob_ad_write_count(src, &wc);
1990  /* Alloc and init bufvec back->si_user & si_stob based on fragment */
1991  rc = stob_ad_vec_alloc(io->si_obj, back, frags);
1992  if (rc == 0) {
1993  struct m0_ivec_cursor dst;
1994  /* reset src - buffer-extent*/
1996  /* reset wc - balloc-extent */
1998  /* Populate bufvec back->si_user & si_stob based on fragment */
1999  stob_ad_write_back_fill(io, back, src, &wc);
2000 
2001  /* Init cursor for COB-offset-extent */
2004  frags = max_check(bfrags, stob_ad_write_map_count(adom,
2005  &io->si_stob, true));
2006  rc = stob_ad_write_map(io, adom, &dst, map, &wc, frags);
2007  }
2008  }
2010  return M0_RC(rc);
2011 }
2012 
2014 {
2015  struct m0_be_emap_cursor it;
2016  struct m0_vec_cursor src;
2017  struct m0_vec_cursor dst;
2018  struct m0_be_emap_caret map;
2019  struct m0_stob_ad_domain *adom;
2020  struct m0_stob_ad_io *aio = io->si_stob_private;
2021  struct m0_stob_io *back = &aio->ai_back;
2022  int rc;
2023 
2024  M0_PRE(io->si_stob.iv_vec.v_nr > 0);
2027 
2028  /* prefix fragments execution mode is not yet supported */
2029  M0_PRE((io->si_flags & SIF_PREFIX) == 0);
2030  /* only read-write at the moment */
2032 
2033  M0_ENTRY("op=%d, stob %p, stob_id="STOB_ID_F,
2035 
2038  rc = stob_ad_cursors_init(io, adom, &it, &src, &dst, &map);
2039  if (rc != 0)
2040  return M0_RC(rc);
2041 
2042  back->si_opcode = io->si_opcode;
2043  back->si_flags = io->si_flags;
2044  back->si_fol_frag = io->si_fol_frag;
2045  back->si_id = io->si_id;
2046 
2047  switch (io->si_opcode) {
2048  case SIO_READ:
2049  rc = stob_ad_read_prepare(io, adom, &src, &dst, &map);
2050  break;
2051  case SIO_WRITE:
2052  rc = stob_ad_write_prepare(io, adom, &src, &map);
2053  break;
2054  default:
2055  M0_IMPOSSIBLE("Invalid io type.");
2056  }
2057  stob_ad_cursors_fini(&it, &src, &dst, &map);
2058 
2059  return rc;
2060 }
2061 
2068 static int stob_ad_io_launch(struct m0_stob_io *io)
2069 {
2070  struct m0_stob_ad_domain *adom;
2071  struct m0_stob_ad_io *aio = io->si_stob_private;
2072  struct m0_stob_io *back = &aio->ai_back;
2073  int rc = 0;
2074  bool wentout = false;
2075 
2076  M0_PRE(io->si_stob.iv_vec.v_nr > 0);
2078  M0_PRE(io->si_state == SIS_BUSY);
2079 
2080  /* prefix fragments execution mode is not yet supported */
2081  M0_PRE((io->si_flags & SIF_PREFIX) == 0);
2082  /* only read-write at the moment */
2084 
2085  M0_ENTRY("op=%d stob_id="STOB_ID_F,
2088 
2090 
2091  if (back->si_stob.iv_vec.v_nr > 0) {
2099  m0_stob_iovec_sort(back);
2103  io->si_tx, io->si_scope);
2104  wentout = rc == 0;
2105  } else {
2106  /*
2107  * Back IO request was constructed OK, but is empty (all
2108  * IO was satisfied from holes). Notify caller about
2109  * completion.
2110  */
2112  stob_ad_endio(&aio->ai_clink);
2113  }
2114 
2115  if (!wentout)
2116  stob_ad_io_release(aio);
2117  return M0_RC(rc);
2118 }
2119 
2120 static bool stob_ad_endio(struct m0_clink *link)
2121 {
2122  struct m0_stob_ad_io *aio;
2123  struct m0_stob_io *io;
2124 
2125  aio = container_of(link, struct m0_stob_ad_io, ai_clink);
2126  io = aio->ai_fore;
2127 
2128  M0_ENTRY("op=%di, stob %p, stob_id="STOB_ID_F,
2130 
2133 
2134  io->si_rc = aio->ai_back.si_rc;
2135  io->si_count += aio->ai_back.si_count;
2136  io->si_state = SIS_IDLE;
2141  stob_ad_io_release(aio);
2143  return true;
2144 }
2145 
2150 static void
2152  struct m0_be_tx_credit *accum)
2153 {
2154  struct stob_ad_rec_frag *arp = frag->rp_data;
2156  struct m0_stob_ad_domain *adom = stob_ad_domain2ad(dom);
2157 
2158  M0_PRE(dom != NULL);
2160  arp->arp_seg.ps_segments, accum);
2161 }
2162 
2168  struct m0_be_tx *tx)
2169 {
2170  struct stob_ad_rec_frag *arp = frag->rp_data;
2172  struct m0_stob_ad_domain *adom = stob_ad_domain2ad(dom);
2173  struct m0_be_emap_seg *old_data = arp->arp_seg.ps_old_data;
2174  struct m0_be_emap_cursor it = {};
2175  int i;
2176  int rc = 0;
2177 
2178  M0_PRE(dom != NULL);
2179 
2180  for (i = 0; rc == 0 && i < arp->arp_seg.ps_segments; ++i) {
2181  M0_SET0(&it.ec_op);
2183  &it.ec_op,
2185  &old_data[i].ee_pre,
2186  old_data[i].ee_ext.e_start,
2187  &it),
2188  bo_u.u_emap.e_rc);
2189  if (rc == 0) {
2190  M0_LOG(M0_DEBUG, "%3d: ext="EXT_F" val=0x%llx",
2191  i, EXT_P(&old_data[i].ee_ext),
2192  (unsigned long long)old_data[i].ee_val);
2193  M0_SET0(&it.ec_op);
2195  &it.ec_op,
2196  m0_be_emap_extent_update(&it, tx, &old_data[i]),
2197  bo_u.u_emap.e_rc);
2198  m0_be_emap_close(&it);
2199  }
2200  }
2201  return M0_RC(rc);
2202 }
2203 
2204 M0_INTERNAL void m0_stob_ad_balloc_set(struct m0_stob_io *io, uint64_t flags)
2205 {
2206  struct m0_stob_ad_io *aio = io->si_stob_private;
2207 
2209  M0_PRE(aio != NULL);
2210  aio->ai_balloc_flags = flags;
2211 }
2212 
2213 M0_INTERNAL void m0_stob_ad_balloc_clear(struct m0_stob_io *io)
2214 {
2215  struct m0_stob_ad_io *aio = io->si_stob_private;
2216 
2217  M0_PRE(aio != NULL);
2219  &m0_stob_ad_type));
2220 
2221  aio->ai_balloc_flags = 0;
2222 }
2223 
2224 static const struct m0_stob_io_op stob_ad_io_op = {
2226  .sio_prepare = stob_ad_io_launch_prepare,
2227  .sio_fini = stob_ad_io_fini,
2228 };
2229 
2232 #undef M0_TRACE_SUBSYSTEM
2233 /*
2234  * Local variables:
2235  * c-indentation-style: "K&R"
2236  * c-basic-offset: 8
2237  * tab-width: 8
2238  * fill-column: 80
2239  * scroll-step: 1
2240  * End:
2241  */
M0_INTERNAL struct m0_be_domain * m0_be_emap_seg_domain(const struct m0_be_emap *map)
Definition: extmap.c:339
M0_INTERNAL void m0_ivec_cursor_init(struct m0_ivec_cursor *cur, const struct m0_indexvec *ivec)
Definition: vec.c:707
M0_INTERNAL struct m0_stob_domain * m0_stob_dom_get(struct m0_stob *stob)
Definition: stob.c:338
#define M0_BE_ALLOC_CREDIT_PTR(ptr, seg, accum)
Definition: alloc.h:355
static int stob_ad_read_prepare(struct m0_stob_io *io, struct m0_stob_ad_domain *adom, struct m0_vec_cursor *src, struct m0_vec_cursor *dst, struct m0_be_emap_caret *car)
Definition: ad.c:1350
struct m0_be_domain * bs_domain
Definition: seg.h:82
struct m0_be_emap_seg * ps_old_data
Definition: ad_private.h:47
#define M0_PRE(cond)
#define M0_BE_ALLOC_PTR_SYNC(ptr, seg, tx)
Definition: alloc.h:339
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
Definition: dtm.h:554
enum m0_stob_io_flags si_flags
Definition: io.h:290
Definition: ad.h:193
M0_INTERNAL m0_bcount_t m0_ext_length(const struct m0_ext *ext)
Definition: ext.c:42
#define FID_SF
Definition: fid.h:76
static void stob_ad_write_back_fill(struct m0_stob_io *io, struct m0_stob_io *back, struct m0_vec_cursor *src, struct stob_ad_wext_cursor *wc)
Definition: ad.c:1593
static bool stob_ad_endio(struct m0_clink *link)
Definition: ad.c:2120
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
static int stob_ad_rec_frag_undo_redo_op(struct m0_fol_frag *frag, struct m0_be_tx *tx)
Definition: ad.c:2167
M0_INTERNAL uint64_t m0_stob_domain__dom_key(const struct m0_fid *dom_id)
Definition: domain.c:322
#define m0_strdup(s)
Definition: string.h:43
static uint32_t stob_ad_write_count(struct m0_vec_cursor *src, struct stob_ad_wext_cursor *wc)
Definition: ad.c:1567
void(* sto_register)(struct m0_stob_type *type)
Definition: type.h:73
M0_INTERNAL void m0_chan_broadcast_lock(struct m0_chan *chan)
Definition: chan.c:178
M0_INTERNAL struct m0_stob_domain * m0_stob_domain_find(const struct m0_fid *dom_id)
Definition: domain.c:278
M0_INTERNAL void m0_stob_io_fini(struct m0_stob_io *io)
Definition: io.c:122
m0_bindex_t si_unit_sz
Definition: io.h:414
M0_INTERNAL void m0_format_header_pack(struct m0_format_header *dest, const struct m0_format_tag *src)
Definition: format.c:40
int(* bo_alloc)(struct m0_ad_balloc *ballroom, struct m0_dtx *dtx, m0_bcount_t count, struct m0_ext *out, uint64_t alloc_zone)
Definition: ad.h:85
M0_INTERNAL void m0_stob_domain__dom_id_make(struct m0_fid *dom_id, uint8_t type_id, uint64_t dom_container, uint64_t dom_key)
Definition: domain.c:327
m0_bindex_t e_end
Definition: ext.h:40
#define M0_FOL_FRAG_TYPE_INIT(frag, name)
Definition: fol.h:349
int const char const void size_t int flags
Definition: dir.c:328
struct m0_ad_balloc cb_ballroom
Definition: balloc.h:231
void m0_be_0type_add_credit(struct m0_be_domain *dom, const struct m0_be_0type *zt, const char *suffix, const struct m0_buf *data, struct m0_be_tx_credit *credit)
Definition: seg0.c:139
static int stob_ad_domain_init(struct m0_stob_type *type, const char *location_data, void *cfg_init, struct m0_stob_domain **out)
Definition: ad.c:412
#define NULL
Definition: misc.h:38
const char * b0_name
Definition: seg0.h:44
M0_INTERNAL void m0_clink_init(struct m0_clink *link, m0_chan_cb_t cb)
Definition: chan.c:201
M0_INTERNAL m0_bcount_t m0_be_emap_caret_step(const struct m0_be_emap_caret *car)
Definition: extmap.c:834
struct m0_be_seg * adg_seg
Definition: ad.c:68
static struct m0_bufvec dst
Definition: xform.c:61
map
Definition: processor.c:112
M0_INTERNAL m0_bcount_t m0_ivec_cursor_step(const struct m0_ivec_cursor *cur)
Definition: vec.c:726
Definition: io.h:230
M0_INTERNAL int m0_stob_locate(struct m0_stob *stob)
Definition: stob.c:128
M0_INTERNAL void m0_clink_del_lock(struct m0_clink *link)
Definition: chan.c:293
static struct buffer * cur(struct m0_addb2_mach *mach, m0_bcount_t space)
Definition: addb2.c:791
uint64_t ai_balloc_flags
Definition: ad.h:207
Definition: idx_mock.c:52
struct m0_fid si_domain_fid
Definition: stob.h:103
const struct m0_stob_ops * so_ops
Definition: stob.h:164
#define ergo(a, b)
Definition: misc.h:293
M0_INTERNAL void m0_stob_io_credit(const struct m0_stob_io *io, const struct m0_stob_domain *dom, struct m0_be_tx_credit *accum)
Definition: io.c:130
static void stob_ad_wext_fini(struct stob_ad_write_ext *wext)
Definition: ad.c:1893
static uint32_t stob_ad_block_shift(struct m0_stob *stob)
Definition: ad.c:961
static void * stob_ad_addr_open(const void *buf, uint32_t shift)
Definition: ad.c:1052
static void stob_ad_domain_destroy_credit(struct m0_be_seg *seg, const char *location_data, struct m0_be_tx_credit *accum)
Definition: ad.c:512
void * b_addr
Definition: buf.h:39
M0_INTERNAL int m0_fol_frag_type_register(struct m0_fol_frag_type *type)
Definition: fol.c:178
struct m0_ext we_ext
Definition: ad.c:1514
struct m0_stob_ad_module i_stob_ad_module
Definition: instance.h:120
static struct m0_sm_group * grp
Definition: bytecount.c:38
struct m0_stob_io * ai_fore
Definition: ad.h:198
#define M0_LOG(level,...)
Definition: trace.h:167
static int stob_ad_balloc(struct m0_stob_ad_domain *adom, struct m0_dtx *tx, m0_bcount_t count, struct m0_ext *out, uint64_t alloc_type)
Definition: ad.c:1064
M0_LEAVE()
#define min_check(a, b)
Definition: arith.h:88
M0_INTERNAL const struct m0_fid * m0_stob_domain_id_get(const struct m0_stob_domain *dom)
Definition: domain.c:300
uint64_t ee_val
Definition: extmap.h:193
void m0_be_0type_del_credit(struct m0_be_domain *dom, const struct m0_be_0type *zt, const char *suffix, struct m0_be_tx_credit *credit)
Definition: seg0.c:156
struct m0_fid arp_dom_id
Definition: ad_private.h:51
static int stob_ad_io_launch_prepare(struct m0_stob_io *io)
Definition: ad.c:2013
static void stob_ad_domain_cfg_init_free(void *cfg_init)
Definition: ad.c:253
M0_INTERNAL void m0_be_tx_fini(struct m0_be_tx *tx)
Definition: stubs.c:163
struct m0_ext ee_ext
Definition: extmap.h:185
M0_INTERNAL void m0_fol_frag_init(struct m0_fol_frag *frag, void *data, const struct m0_fol_frag_type *type)
Definition: fol.c:121
Definition: ad.h:190
struct m0_vec ov_vec
Definition: vec.h:147
#define max_check(a, b)
Definition: arith.h:95
static struct m0_uint128 prefix
Definition: extmap.c:45
Definition: io.h:274
int(* bo_init)(struct m0_ad_balloc *ballroom, struct m0_be_seg *db, uint32_t bshift, m0_bcount_t container_size, m0_bcount_t blocks_per_group, m0_bcount_t spare_blocks_per_group)
Definition: ad.h:77
M0_INTERNAL bool m0_stob_ad_domain__invariant(struct m0_stob_ad_domain *adom)
Definition: ad.c:371
static m0_bcount_t segs[NR *IT]
Definition: vec.c:45
static uint32_t stob_ad_write_map_count(struct m0_stob_ad_domain *adom, struct m0_indexvec *iv, bool pack)
Definition: ad.c:1120
static int stob_ad_bfree(struct m0_stob_ad_domain *adom, struct m0_dtx *tx, struct m0_ext *ext)
Definition: ad.c:1086
struct m0_bufvec data
Definition: di.c:40
M0_INTERNAL void m0_be_emap_destroy(struct m0_be_emap *map, struct m0_be_tx *tx, struct m0_be_op *op)
Definition: extmap.c:300
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_bcount_t sad_container_size
Definition: ad.h:116
const struct m0_stob_io_op * si_op
Definition: io.h:328
M0_INTERNAL bool m0_stob_domain_is_of_type(const struct m0_stob_domain *dom, const struct m0_stob_type *dt)
Definition: domain.c:349
struct m0_be_0type m0_stob_ad_0type
Definition: ad.c:159
const struct m0_stob_type m0_stob_ad_type
Definition: ad.c:1003
const struct stob_ad_write_ext * wc_wext
Definition: ad.c:1522
static void stob_ad_type_deregister(struct m0_stob_type *type)
Definition: ad.c:203
M0_INTERNAL uint8_t m0_stob_type_id_get(const struct m0_stob_type *type)
Definition: type.c:164
M0_INTERNAL void m0_be_emap_close(struct m0_be_emap_cursor *it)
Definition: extmap.c:360
static struct m0_be_emap_cursor it
Definition: extmap.c:46
struct m0_buf ec_recbuf
Definition: extmap.h:212
static void stob_ad_io_release(struct m0_stob_ad_io *aio)
Definition: ad.c:1207
M0_INTERNAL void m0_stob_ad_balloc_set(struct m0_stob_io *io, uint64_t flags)
Definition: ad.c:2204
static void stob_ad_domain_fini(struct m0_stob_domain *dom)
Definition: ad.c:485
M0_INTERNAL void m0_be_tx_prep(struct m0_be_tx *tx, const struct m0_be_tx_credit *credit)
Definition: stubs.c:175
const struct m0_ad_balloc_ops * ab_ops
Definition: ad.h:65
#define M0_BE_TX_CAPTURE_PTR(seg, tx, ptr)
Definition: tx.h:505
static void pack(struct m0_addb2_mach *mach)
Definition: addb2.c:966
uint32_t sad_bshift
Definition: ad.h:117
uint64_t m0_bindex_t
Definition: types.h:80
char adm_path[MAXPATHLEN]
Definition: ad.h:141
struct m0_chan si_wait
Definition: io.h:318
uint64_t m0_bcount_t
Definition: types.h:77
M0_INTERNAL struct m0 * m0_get(void)
Definition: instance.c:41
M0_INTERNAL const struct m0_fid * m0_stob_fid_get(struct m0_stob *stob)
Definition: stob.c:255
M0_INTERNAL void * m0_extent_get_checksum_addr(void *b_addr, m0_bindex_t off, m0_bindex_t base_off, m0_bindex_t unit_sz, m0_bcount_t cs_size)
Definition: cksum_utils.c:74
M0_INTERNAL int m0_balloc_create(uint64_t cid, struct m0_be_seg *seg, struct m0_sm_group *grp, struct m0_balloc **out, const struct m0_fid *fid)
Definition: balloc.c:3015
static int void * buf
Definition: dir.c:1019
m0_bindex_t ec_unit_size
Definition: extmap.h:214
void * rp_data
Definition: fol.h:249
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
void(* sdo_fini)(struct m0_stob_domain *dom)
Definition: domain.h:111
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
M0_INTERNAL m0_bcount_t m0_extent_get_checksum_nob(m0_bindex_t ext_start, m0_bindex_t ext_length, m0_bindex_t unit_sz, m0_bcount_t cs_size)
Definition: cksum_utils.c:85
M0_ADDB2_ADD(M0_AVI_FS_CREATE, new_fid.f_container, new_fid.f_key, mode, rc)
M0_INTERNAL int stob_ad_cursor(struct m0_stob_ad_domain *adom, struct m0_stob *obj, uint64_t offset, struct m0_be_emap_cursor *it)
Definition: ad.c:1101
M0_INTERNAL void m0_stob_ad_init_cfg_make(char **str, struct m0_be_domain *dom)
Definition: ad.c:212
int(* sio_launch)(struct m0_stob_io *io)
Definition: io.h:439
void ** ov_buf
Definition: vec.h:149
bool sad_overwrite
Definition: ad.h:122
static void stob_ad_wext_cursor_init(struct stob_ad_wext_cursor *wc, struct stob_ad_write_ext *wext)
Definition: ad.c:1526
static struct foo * obj
Definition: tlist.c:302
#define PRIx64
Definition: types.h:61
static void stob_ad_io_fini(struct m0_stob_io *io)
Definition: ad.c:1042
const char * bt_name
Definition: bob.h:73
Definition: sock.c:887
static m0_bcount_t count
Definition: xcode.c:167
static void stob_ad_write_credit(const struct m0_stob_domain *dom, const struct m0_stob_io *iv, struct m0_be_tx_credit *accum)
Definition: ad.c:1153
static void stob_ad_0type_fini(struct m0_be_domain *dom, const char *suffix, const struct m0_buf *data)
Definition: ad.c:140
struct m0_stob_domain * so_domain
Definition: stob.h:165
struct m0_buf ee_cksum_buf
Definition: extmap.h:194
struct m0_fid fid
Definition: di.c:46
static int stob_ad_init(struct m0_stob *stob, struct m0_stob_domain *dom, const struct m0_fid *stob_fid)
Definition: ad.c:688
struct m0_vec iv_vec
Definition: vec.h:139
return M0_RC(rc)
op
Definition: libdemo.c:64
M0_INTERNAL uint32_t m0_stob_block_shift(struct m0_stob *stob)
Definition: stob.c:270
static int stob_ad_fol_frag_alloc(struct m0_fol_frag *frag, uint32_t frags)
Definition: ad.c:1771
static int head(struct m0_sm *mach)
Definition: sm.c:468
#define M0_BE_TX_CREDIT(nr, size)
Definition: tx_credit.h:94
static uint32_t unit_size
Definition: layout.c:53
struct m0_bufvec si_user
Definition: io.h:300
#define M0_ENTRY(...)
Definition: trace.h:170
struct m0_stob_ad_domain * adm_dom
Definition: ad.h:142
Definition: buf.h:37
struct m0_ad_balloc * sad_ballroom
Definition: ad.h:115
M0_INTERNAL void m0_sm_group_unlock(struct m0_sm_group *grp)
Definition: sm.c:96
m0_bindex_t * iv_index
Definition: vec.h:141
M0_INTERNAL bool m0_ext_equal(const struct m0_ext *a, const struct m0_ext *b)
Definition: ext.c:70
int i
Definition: dir.c:1033
M0_INTERNAL struct m0_be_engine * m0_be_domain_engine(struct m0_be_domain *dom)
Definition: domain.c:461
struct m0_be_seg * sad_be_seg
Definition: ad.h:134
M0_INTERNAL bool m0_vec_is_empty(const struct m0_vec *vec)
Definition: vec.c:58
#define FID_S(f)
Definition: fid.h:78
static void stob_ad_cursors_fini(struct m0_be_emap_cursor *it, struct m0_vec_cursor *src, struct m0_vec_cursor *dst, struct m0_be_emap_caret *map)
Definition: ad.c:1248
M0_INTERNAL bool m0_ext_is_valid(const struct m0_ext *ext)
Definition: ext.c:90
struct m0_dtx * si_tx
Definition: io.h:351
M0_INTERNAL int m0_be_emap_op_rc(const struct m0_be_emap_cursor *it)
Definition: extmap.c:333
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
#define M0_BE_OP_SYNC_RET(op_obj, action, member)
Definition: op.h:243
static int stob_ad_cfg_parse(const char *str_cfg_create, void **cfg_create)
Definition: ad.c:679
void * b_addr
Definition: buf.h:231
m0_bindex_t ct_index
Definition: extmap.h:386
M0_INTERNAL void m0_be_emap_init(struct m0_be_emap *map, struct m0_be_seg *db)
Definition: extmap.c:258
static int stob_ad_vec_alloc(struct m0_stob *obj, struct m0_stob_io *back, uint32_t frags)
Definition: ad.c:1262
m0_bcount_t wc_done
Definition: ad.c:1523
struct m0_format_header sa0_header
Definition: ad_private.h:39
M0_INTERNAL int m0_stob_io_prepare_and_launch(struct m0_stob_io *io, struct m0_stob *obj, struct m0_dtx *tx, struct m0_io_scope *scope)
Definition: io.c:219
M0_INTERNAL const struct m0_stob_id * m0_stob_id_get(struct m0_stob *stob)
Definition: stob.c:250
struct m0_buf si_cksum
Definition: io.h:412
Definition: stob.h:163
M0_INTERNAL void m0_vec_cursor_init(struct m0_vec_cursor *cur, const struct m0_vec *vec)
Definition: vec.c:92
struct m0_indexvec si_stob
Definition: io.h:311
int32_t si_rc
Definition: io.h:334
static struct m0_stob * stob
Definition: storage.c:39
#define m0_free0(pptr)
Definition: memory.h:77
static m0_bcount_t stob_ad_wext_cursor_step(struct stob_ad_wext_cursor *wc)
Definition: ad.c:1533
m0_bcount_t b_nob
Definition: buf.h:38
static int stob_ad_destroy(struct m0_stob *stob, struct m0_dtx *tx)
Definition: ad.c:914
struct m0_be_emap * ec_map
Definition: extmap.h:202
#define M0_ASSERT(cond)
static void stob_ad_destroy_credit(struct m0_stob *stob, struct m0_be_tx_credit *accum)
Definition: ad.c:905
uint64_t ee_val
Definition: extmap.h:187
static int stob_ad_cursors_init(struct m0_stob_io *io, struct m0_stob_ad_domain *adom, struct m0_be_emap_cursor *it, struct m0_vec_cursor *src, struct m0_vec_cursor *dst, struct m0_be_emap_caret *map)
Definition: ad.c:1224
static struct m0_be_op * it_op
Definition: extmap.c:49
static void stob_ad_rec_frag_undo_redo_op_cred(const struct m0_fol_frag *frag, struct m0_be_tx_credit *accum)
Definition: ad.c:2151
M0_INTERNAL void m0_ext_init(struct m0_ext *ext)
Definition: ext.c:32
#define STOB_ID_P(si)
Definition: stob.h:109
struct m0_be_domain * dic_dom
Definition: ad.c:63
#define U128_P(x)
Definition: types.h:45
static int stob_ad_write_map(struct m0_stob_io *io, struct m0_stob_ad_domain *adom, struct m0_ivec_cursor *dst, struct m0_be_emap_caret *map, struct stob_ad_wext_cursor *wc, uint32_t frags)
Definition: ad.c:1811
m0_time_t m0_time_now(void)
Definition: time.c:134
static struct m0_balloc * b2m0(const struct m0_ad_balloc *ballroom)
Definition: balloc.h:265
static int stob_ad_domain_destroy(struct m0_stob_type *type, const char *location_data)
Definition: ad.c:625
uint32_t adg_bshift
Definition: ad.c:70
struct m0_mutex sam_lock
Definition: module.h:51
M0_INTERNAL void m0_be_tx_credit_add(struct m0_be_tx_credit *c0, const struct m0_be_tx_credit *c1)
Definition: tx_credit.c:44
M0_INTERNAL void m0_be_emap_caret_init(struct m0_be_emap_caret *car, struct m0_be_emap_cursor *it, m0_bindex_t index)
Definition: extmap.c:817
#define m0_streq(a, b)
Definition: string.h:34
M0_INTERNAL struct m0_be_seg * m0_be_domain_seg(const struct m0_be_domain *dom, const void *addr)
Definition: domain.c:476
m0_time_t si_start
Definition: io.h:405
static struct m0_stob_domain * dom
Definition: storage.c:38
static int next[]
Definition: cp.c:248
Definition: io.h:244
M0_INTERNAL void m0_balloc_init(struct m0_balloc *cb)
Definition: balloc.c:3010
M0_INTERNAL bool m0_be_emap_ext_is_last(const struct m0_ext *ext)
Definition: extmap.c:318
M0_INTERNAL void m0_be_emap_extent_update(struct m0_be_emap_cursor *it, struct m0_be_tx *tx, const struct m0_be_emap_seg *es)
Definition: extmap.c:405
struct m0_fid si_fid
Definition: stob.h:105
M0_TL_DEFINE(ad_domains, M0_INTERNAL, struct ad_domain_map)
M0_INTERNAL struct m0_stob_ad_domain * stob_ad_domain2ad(const struct m0_stob_domain *dom)
Definition: ad.c:166
struct m0_be_op ec_op
Definition: extmap.h:217
static int stob_ad_0type_init(struct m0_be_domain *dom, const char *suffix, const struct m0_buf *data)
Definition: ad.c:113
struct m0_uint128 ee_pre
Definition: extmap.h:189
uint32_t si_stob_magic
Definition: io.h:388
M0_INTERNAL void * m0_stob_ad_get_checksum_addr(struct m0_stob_io *io, m0_bindex_t off)
Definition: ad.c:333
struct m0_be_op::@39::@40 u_emap
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
static int stob_ad_punch(struct m0_stob *stob, struct m0_indexvec *range, struct m0_dtx *tx)
Definition: ad.c:937
M0_INTERNAL int m0_be_tx_exclusive_open_sync(struct m0_be_tx *tx)
Definition: tx.c:594
struct m0_fol_frag * si_fol_frag
Definition: io.h:390
void(* bo_free_credit)(const struct m0_ad_balloc *ballroom, int nr, struct m0_be_tx_credit *accum)
Definition: ad.h:94
uint64_t f_container
Definition: fid.h:39
static int stob_ad_write_map_ext(struct m0_stob_io *io, struct m0_stob_ad_domain *adom, m0_bindex_t off, struct m0_be_emap_cursor *orig, const struct m0_ext *ext)
Definition: ad.c:1661
Definition: xcode.h:73
uint64_t si_id
Definition: io.h:406
M0_INTERNAL void m0_be_emap_fini(struct m0_be_emap *map)
Definition: extmap.c:276
m0_bcount_t counts[SEGS_NR]
Definition: di.c:44
struct m0_stob_id sad_bstore_id
Definition: ad.h:114
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
uint32_t v_nr
Definition: vec.h:51
uint64_t sad_dom_key
Definition: ad.h:113
struct m0_sm_group * lo_grp
Definition: locality.h:67
enum m0_stob_io_state si_state
Definition: io.h:345
Definition: io.h:255
static m0_bindex_t offset
Definition: dump.c:173
Definition: io.h:285
struct m0_fol_rec tx_fol_rec
Definition: dtm.h:561
M0_INTERNAL void m0_be_emap_obj_delete(struct m0_be_emap *map, struct m0_be_tx *tx, struct m0_be_op *op, const struct m0_uint128 *prefix)
Definition: extmap.c:774
static struct m0_stob_type_ops stob_ad_type_ops
Definition: ad.c:969
m0_bcount_t * v_count
Definition: vec.h:53
m0_bcount_t si_cksum_sz
Definition: io.h:416
int(* bo_free)(struct m0_ad_balloc *ballroom, struct m0_dtx *dtx, struct m0_ext *ext)
Definition: ad.h:90
M0_INTERNAL bool m0_ivec_cursor_move(struct m0_ivec_cursor *cur, m0_bcount_t count)
Definition: vec.c:718
void(* bo_fini)(struct m0_ad_balloc *ballroom)
Definition: ad.h:82
static int stob_ad_domain_cfg_create_parse(const char *str_cfg_create, void **cfg_create)
Definition: ad.c:258
#define M0_BE_FREE_PTR_SYNC(ptr, seg, tx)
Definition: alloc.h:345
Definition: seg.h:66
M0_INTERNAL bool m0_ext_is_in(const struct m0_ext *ext, m0_bindex_t index)
Definition: ext.c:48
static const struct m0_stob_io_op stob_ad_io_op
Definition: ad.c:1015
static int stob_ad_domain_cfg_init_parse(const char *str_cfg_init, void **cfg_init)
Definition: ad.c:233
#define FID_P(f)
Definition: fid.h:77
static struct m0_stob_io io
Definition: ad.c:59
static void stob_ad_fol_frag_free(struct m0_fol_frag *frag)
Definition: ad.c:1792
#define PRId64
Definition: types.h:57
m0_bcount_t si_count
Definition: io.h:340
#define EXT_P(x)
Definition: ext.h:86
static struct m0_stob_domain_ops stob_ad_domain_ops
Definition: ad.c:82
M0_INTERNAL m0_bcount_t m0_vec_count(const struct m0_vec *vec)
Definition: vec.c:53
M0_INTERNAL bool m0_ext_is_empty(const struct m0_ext *ext)
Definition: ext.c:76
struct m0_stob * si_obj
Definition: io.h:326
m0_bcount_t adg_blocks_per_group
Definition: ad.c:71
char sad_path[AD_PATHLEN]
Definition: ad.h:121
static int stob_ad_io_init(struct m0_stob *stob, struct m0_stob_io *io)
Definition: ad.c:1020
static struct m0_be_emap * emap
Definition: extmap.c:44
struct m0_be_emap_cursor * ct_it
Definition: extmap.h:385
int32_t sad_babshift
Definition: ad.h:118
int m0_be_0type_add(struct m0_be_0type *zt, struct m0_be_domain *dom, struct m0_be_tx *tx, const char *suffix, const struct m0_buf *data)
Definition: seg0.c:79
#define U128X_F
Definition: types.h:42
m0_bcount_t adg_container_size
Definition: ad.c:69
M0_INTERNAL void m0_be_tx_init(struct m0_be_tx *tx, uint64_t tid, struct m0_be_domain *dom, struct m0_sm_group *sm_group, m0_be_tx_cb_t persistent, m0_be_tx_cb_t discarded, void(*filler)(struct m0_be_tx *tx, void *payload), void *datum)
Definition: stubs.c:150
struct m0_stob * sad_bstore
Definition: ad.h:133
void m0_clink_add_lock(struct m0_chan *chan, struct m0_clink *link)
Definition: chan.c:255
struct m0_ext ee_ext
Definition: extmap.h:191
M0_INTERNAL uint32_t m0_indexvec_pack(struct m0_indexvec *iv)
Definition: vec.c:521
static bool stob_ad_wext_cursor_move(struct stob_ad_wext_cursor *wc, m0_bcount_t count)
Definition: ad.c:1541
struct m0_stob_id adg_id
Definition: ad.c:67
struct m0_fid sd_id
Definition: domain.h:96
static int stob_ad_io_launch(struct m0_stob_io *io)
Definition: ad.c:2068
struct m0_be_emap sad_adata
Definition: ad.h:129
struct m0_pdclust_tgt_addr tgt
Definition: fd.c:110
#define EXT_F
Definition: ext.h:85
M0_INTERNAL enum m0_stob_state m0_stob_state_get(struct m0_stob *stob)
Definition: stob.c:265
void(* sop_fini)(struct m0_stob *stob)
Definition: stob.h:187
struct m0_clink ai_clink
Definition: ad.h:200
#define M0_MAGIX_OFFSET(type, field)
Definition: misc.h:356
struct m0_stob_id arp_stob_id
Definition: ad_private.h:52
M0_INTERNAL m0_bcount_t m0_vec_cursor_step(const struct m0_vec_cursor *cur)
Definition: vec.c:125
static void stob_ad_get_checksum_for_fragment(struct m0_stob_io *io, struct m0_be_emap_cursor *it, m0_bindex_t off, m0_bindex_t frag_sz)
Definition: ad.c:1299
Definition: io.h:279
#define M0_BUF_INIT_PTR(p)
Definition: buf.h:69
void * si_stob_private
Definition: io.h:367
M0_INTERNAL void m0_stob_ad_balloc_clear(struct m0_stob_io *io)
Definition: ad.c:2213
m0_bcount_t sad_spare_blocks_per_group
Definition: ad.h:120
M0_INTERNAL struct m0_locality * m0_locality0_get(void)
Definition: locality.c:169
struct m0_stob_ad_domain * sa0_ad_domain
Definition: ad_private.h:41
#define M0_CNT_INC(cnt)
Definition: arith.h:226
static void stob_ad_create_credit(struct m0_stob_domain *dom, struct m0_be_tx_credit *accum)
Definition: ad.c:714
static int stob_ad_seg_free(struct m0_dtx *tx, struct m0_stob_ad_domain *adom, const struct m0_be_emap_seg *seg, const struct m0_ext *ext, uint64_t val)
Definition: ad.c:1630
#define M0_FI_ENABLED(tag)
Definition: finject.h:231
Definition: fid.h:38
Definition: ext.h:37
static int stob_ad_punch_credit(struct m0_stob *stob, struct m0_indexvec *want, struct m0_indexvec *got, struct m0_be_tx_credit *accum)
Definition: ad.c:756
static struct m0_stob_ad * stob_ad_stob2ad(const struct m0_stob *stob)
Definition: ad.c:186
static const struct m0_bob_type stob_ad_domain_bob_type
Definition: ad.c:75
uint64_t f_key
Definition: fid.h:40
m0_bindex_t e_start
Definition: ext.h:39
M0_INTERNAL void m0_format_footer_update(const void *buffer)
Definition: format.c:95
struct m0_be_tx tx_betx
Definition: dtm.h:559
void * sd_private
Definition: domain.h:105
int m0_be_0type_del(struct m0_be_0type *zt, struct m0_be_domain *dom, struct m0_be_tx *tx, const char *suffix)
Definition: seg0.c:112
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
static int stob_ad_bstore(struct m0_stob_id *stob_id, struct m0_stob **out)
Definition: ad.c:381
M0_INTERNAL void m0_stob_iovec_sort(struct m0_stob_io *stob)
Definition: io.c:311
static struct m0_stob_ops stob_ad_ops
Definition: ad.c:83
M0_INTERNAL void m0_fol_frag_add(struct m0_fol_rec *rec, struct m0_fol_frag *frag)
Definition: fol.c:468
static int ext_punch(struct m0_stob *stob, struct m0_dtx *tx, struct m0_ext *todo)
Definition: ad.c:831
M0_INTERNAL bool m0_vec_cursor_move(struct m0_vec_cursor *cur, m0_bcount_t count)
Definition: vec.c:102
uint64_t sad_magix
Definition: ad.h:1547
m0_time_t m0_time_sub(const m0_time_t t1, const m0_time_t t2)
Definition: time.c:65
struct stob_ad_write_ext * we_next
Definition: ad.c:1515
static void stob_ad_domain_cfg_create_free(void *cfg_create)
Definition: ad.c:366
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
M0_INTERNAL m0_bindex_t m0_ivec_cursor_index(const struct m0_ivec_cursor *cur)
Definition: vec.c:733
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
M0_INTERNAL void m0_clink_fini(struct m0_clink *link)
Definition: chan.c:208
M0_INTERNAL bool m0_be_should_break(struct m0_be_engine *eng, const struct m0_be_tx_credit *accum, const struct m0_be_tx_credit *delta)
Definition: tx.c:714
M0_INTERNAL m0_bcount_t m0_stob_ad_spares_calc(m0_bcount_t grp_blocks)
Definition: ad.c:313
struct m0_format_header sad_header
Definition: ad.h:112
M0_INTERNAL int m0_be_emap_caret_move_sync(struct m0_be_emap_caret *car, m0_bcount_t count)
Definition: extmap.c:872
static struct m0_sm_group * stob_ad_sm_group(void)
Definition: ad.c:376
M0_INTERNAL struct m0_balloc * m0_stob_ad_domain2balloc(const struct m0_stob_domain *dom)
Definition: ad.c:179
M0_INTERNAL void m0_sm_group_lock(struct m0_sm_group *grp)
Definition: sm.c:83
static int stob_ad_domain_create(struct m0_stob_type *type, const char *location_data, uint64_t dom_key, void *cfg_create)
Definition: ad.c:527
struct m0_stob ad_stob
Definition: ad.h:194
M0_INTERNAL void m0_stob_io_init(struct m0_stob_io *io)
Definition: io.c:111
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 void stob_ad_domain_create_credit(struct m0_be_seg *seg, const char *location_data, struct m0_be_tx_credit *accum)
Definition: ad.c:497
#define M0_UINT128(hi, lo)
Definition: types.h:40
M0_INTERNAL void m0_fol_frag_type_deregister(struct m0_fol_frag_type *type)
Definition: fol.c:201
const struct m0_stob_domain_ops * sd_ops
Definition: domain.h:94
uint32_t ps_segments
Definition: ad_private.h:46
static unsigned m0_log2(uint64_t val)
Definition: arith.h:161
m0_bcount_t si_cksum_nob_read
Definition: io.h:418
union m0_be_op::@39 bo_u
static struct m0_stob * stob_ad_alloc(struct m0_stob_domain *dom, const struct m0_fid *stob_fid)
Definition: ad.c:663
#define STOB_ID_F
Definition: stob.h:108
M0_FOL_FRAG_TYPE_DECLARE(stob_ad_rec_frag, static, stob_ad_rec_frag_undo_redo_op, stob_ad_rec_frag_undo_redo_op, stob_ad_rec_frag_undo_redo_op_cred, stob_ad_rec_frag_undo_redo_op_cred)
struct stob_ad_rec_frag_seg arp_seg
Definition: ad_private.h:53
#define out(...)
Definition: gen.c:41
M0_INTERNAL void m0_stob_ad_cfg_make(char **str, const struct m0_be_seg *seg, const struct m0_stob_id *bstore_id, const m0_bcount_t size)
Definition: ad.c:220
#define min3(a, b, c)
Definition: arith.h:103
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_buf ec_app_cksum_buf
Definition: extmap.h:216
int type
Definition: dir.c:1031
const struct m0_stob_type_ops * st_ops
Definition: type.h:60
Definition: io.h:229
static void stob_ad_free(struct m0_stob_domain *dom, struct m0_stob *stob)
Definition: ad.c:672
m0_bcount_t sad_blocks_per_group
Definition: ad.h:119
Definition: op.h:74
struct m0_stob_io ai_back
Definition: ad.h:199
#define m0_tl_find(name, var, head,...)
Definition: tlist.h:757
M0_INTERNAL void m0_be_op_init(struct m0_be_op *op)
Definition: stubs.c:87
void m0_free(void *data)
Definition: memory.c:146
void(* bo_alloc_credit)(const struct m0_ad_balloc *ballroom, int nr, struct m0_be_tx_credit *accum)
Definition: ad.h:92
M0_BOB_DEFINE(static, &stob_ad_domain_bob_type, m0_stob_ad_domain)
struct m0_io_scope * si_scope
Definition: io.h:355
M0_TL_DESCR_DEFINE(ad_domains, "ad stob domains", M0_INTERNAL, struct ad_domain_map, adm_linkage, adm_magic, M0_AD_DOMAINS_MAGIC, M0_AD_DOMAINS_HEAD_MAGIC)
struct m0_pdclust_src_addr src
Definition: fd.c:108
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
#define ARRAY_SIZE(a)
Definition: misc.h:45
static int stob_ad_create(struct m0_stob *stob, struct m0_stob_domain *dom, struct m0_dtx *dtx, const struct m0_fid *stob_fid, void *cfg)
Definition: ad.c:721
struct m0_stob_id so_id
Definition: stob.h:166
#define M0_BE_OP_SYNC_RET_WITH(op, action, member)
Definition: op.h:253
M0_INTERNAL void m0_be_emap_create(struct m0_be_emap *map, struct m0_be_tx *tx, struct m0_be_op *op, const struct m0_fid *fid)
Definition: extmap.c:283
M0_INTERNAL void m0_stob_put(struct m0_stob *stob)
Definition: stob.c:291
m0_bcount_t adg_spare_blocks_per_group
Definition: ad.c:72
#define M0_BE_FREE_CREDIT_PTR(ptr, seg, accum)
Definition: alloc.h:359
static void stob_ad_fini(struct m0_stob *stob)
Definition: ad.c:710
static uint64_t max64u(uint64_t a, uint64_t b)
Definition: arith.h:71
static int stob_ad_write_prepare(struct m0_stob_io *io, struct m0_stob_ad_domain *adom, struct m0_vec_cursor *src, struct m0_be_emap_caret *map)
Definition: ad.c:1918
#define FID_F
Definition: fid.h:75
M0_INTERNAL struct m0_be_emap_seg * m0_be_emap_seg_get(struct m0_be_emap_cursor *it)
Definition: extmap.c:313
static struct m0_stob_ad_domain * stob_ad_domain_locate(const char *location_data)
Definition: ad.c:400
M0_INTERNAL void m0_be_tx_close_sync(struct m0_be_tx *tx)
Definition: stubs.c:205
static void stob_ad_type_register(struct m0_stob_type *type)
Definition: ad.c:191
Definition: tx.h:280
M0_INTERNAL void m0_be_emap_caret_fini(struct m0_be_emap_caret *car)
Definition: extmap.c:828
struct m0_tl sam_domains
Definition: module.h:50
#define M0_IMPOSSIBLE(fmt,...)
enum m0_stob_io_opcode si_opcode
Definition: io.h:286
Definition: ad.h:186
static void stob_ad_cfg_free(void *cfg_create)
Definition: ad.c:684