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  if (adom->sad_overwrite && ballroom->ab_ops->bo_free_credit != NULL) {
1179  /* for each emap_paste() seg_free() could be called 3 times */
1180  ballroom->ab_ops->bo_free_credit(ballroom, 3 * frags, accum);
1181  }
1182 
1184 }
1185 
1194 static void stob_ad_io_release(struct m0_stob_ad_io *aio)
1195 {
1196  struct m0_stob_io *back = &aio->ai_back;
1197 
1199  m0_free0(&back->si_user.ov_vec.v_count);
1200  back->si_stob.iv_vec.v_count = NULL;
1201 
1202  m0_free0(&back->si_user.ov_buf);
1203  m0_free0(&back->si_stob.iv_index);
1204 
1205  back->si_obj = NULL;
1206 }
1207 
1212  struct m0_stob_ad_domain *adom,
1213  struct m0_be_emap_cursor *it,
1214  struct m0_vec_cursor *src,
1215  struct m0_vec_cursor *dst,
1216  struct m0_be_emap_caret *map)
1217 {
1218  int rc;
1219 
1220  it->ec_recbuf.b_nob = 0;
1221  it->ec_recbuf.b_addr = NULL;
1222 
1223  rc = stob_ad_cursor(adom, io->si_obj, io->si_stob.iv_index[0], it);
1224  if (rc == 0) {
1228  }
1229  return M0_RC(rc);
1230 }
1231 
1236  struct m0_vec_cursor *src,
1237  struct m0_vec_cursor *dst,
1238  struct m0_be_emap_caret *map)
1239 {
1242 }
1243 
1249 static int stob_ad_vec_alloc(struct m0_stob *obj,
1250  struct m0_stob_io *back,
1251  uint32_t frags)
1252 {
1254  int rc = 0;
1255 
1256  M0_ASSERT(back->si_user.ov_vec.v_count == NULL);
1257 
1258  if (frags > 0) {
1259  M0_ALLOC_ARR(counts, frags);
1260  back->si_user.ov_vec.v_count = counts;
1261  back->si_stob.iv_vec.v_count = counts;
1262  M0_ALLOC_ARR(back->si_user.ov_buf, frags);
1263  M0_ALLOC_ARR(back->si_stob.iv_index, frags);
1264 
1265  back->si_user.ov_vec.v_nr = frags;
1266  back->si_stob.iv_vec.v_nr = frags;
1267 
1268  if (counts == NULL || back->si_user.ov_buf == NULL ||
1269  back->si_stob.iv_index == NULL) {
1270  m0_free(counts);
1271  m0_free(back->si_user.ov_buf);
1272  m0_free(back->si_stob.iv_index);
1273  rc = M0_ERR(-ENOMEM);
1274  }
1275  }
1276  return M0_RC(rc);
1277 }
1278 
1279 /* This function will copy the checksum for the fragment (off, frag_sz), into
1280  * the destination buffer allocated in reply FOP. It also updates si_cksum_nob_read
1281  * for tracking how many checksum nob is copied.
1282  * Note: Assumption is that overlapping fragments are not passed to this function
1283  * during multiple calls, otherwise duplicate checksum entry will get copied
1284  * and will assert.
1285  */
1287  struct m0_be_emap_cursor *it,
1288  m0_bindex_t off,
1289  m0_bindex_t frag_sz)
1290 {
1292  m0_bcount_t cksum_unit_size = io->si_cksum_sz;
1293  m0_bcount_t checksum_nob;
1294  struct m0_be_emap_seg *ext = &it->ec_seg;
1295  void * dst, *src;
1296 
1297  checksum_nob = m0_extent_get_checksum_nob(off, frag_sz, unit_size,
1298  cksum_unit_size);
1299  if (checksum_nob) {
1300  // we are looking at checksum which need to be added:
1301  // get the destination: checksum address to copy in client buffer
1303  //get the source: checksum address from segment
1305  ext->ee_ext.e_start,
1306  unit_size, cksum_unit_size);
1307 
1308  // copy from source to client buffer
1309  memcpy(dst, src, checksum_nob);
1310 
1311  // update checksum fill count for stio
1312  io->si_cksum_nob_read += checksum_nob;
1314  }
1315 }
1316 
1338  struct m0_stob_ad_domain *adom,
1339  struct m0_vec_cursor *src,
1340  struct m0_vec_cursor *dst,
1341  struct m0_be_emap_caret *car)
1342 {
1343  struct m0_be_emap_cursor *it;
1344  struct m0_be_emap_seg *seg;
1345  struct m0_stob_io *back;
1346  struct m0_stob_ad_io *aio = io->si_stob_private;
1347  uint32_t frags;
1348  uint32_t frags_not_empty;
1349  uint32_t bshift;
1350  m0_bcount_t frag_size; /* measured in blocks */
1351  m0_bindex_t off; /* measured in blocks */
1352  int rc;
1353  int i;
1354  int idx;
1355  bool eosrc;
1356  bool eodst;
1357  int eomap;
1358 
1359  M0_PRE(io->si_opcode == SIO_READ);
1360 
1361  bshift = m0_stob_block_shift(adom->sad_bstore);
1362  it = car->ct_it;
1364  back = &aio->ai_back;
1365 
1366  M0_LOG(M0_DEBUG, "ext="EXT_F" val=0x%llx",
1367  EXT_P(&seg->ee_ext), (unsigned long long)seg->ee_val);
1368 
1369  frags = frags_not_empty = 0;
1370  do {
1371  off = io->si_stob.iv_index[dst->vc_seg] + dst->vc_offset;
1372 
1373  /*
1374  * The next fragment starts at the offset off and the extents
1375  * car has to be positioned at this offset. There are two ways
1376  * to do this:
1377  *
1378  * * lookup an extent containing off (m0_emap_lookup()), or
1379  *
1380  * * iterate from the current position (m0_emap_caret_move())
1381  * until off is reached.
1382  *
1383  * Lookup incurs an overhead of tree traversal, whereas
1384  * iteration could become expensive when extents car is
1385  * fragmented and target extents are far from each other.
1386  *
1387  * Iteration is used for now, because when extents car is
1388  * fragmented or IO locality of reference is weak, performance
1389  * will be bad anyway.
1390  *
1391  * Note: the code relies on the target extents being in
1392  * increasing offset order in dst.
1393  */
1394  M0_ASSERT(off >= car->ct_index);
1395  eomap = m0_be_emap_caret_move_sync(car, off - car->ct_index);
1396  if (eomap < 0)
1397  return M0_RC(eomap);
1398  M0_ASSERT(eomap == 0);
1399  M0_ASSERT(m0_ext_is_in(&seg->ee_ext, off));
1400 
1401  frag_size = min3(m0_vec_cursor_step(src),
1403  m0_be_emap_caret_step(car));
1404  M0_ASSERT(frag_size > 0);
1405  if (frag_size > (size_t)~0ULL)
1406  return M0_ERR(-EOVERFLOW);
1407 
1408  frags++;
1409 
1410  if (seg->ee_val < AET_MIN)
1411  {
1412  /* For RMW case, ignore cksum read from fragments */
1413  if (io->si_cksum_sz && io->si_unit_sz)
1414  stob_ad_get_checksum_for_fragment(io, it, off, frag_size);
1415  frags_not_empty++;
1416  }
1417 
1418  eosrc = m0_vec_cursor_move(src, frag_size);
1419  eodst = m0_vec_cursor_move(dst, frag_size);
1420  eomap = m0_be_emap_caret_move_sync(car, frag_size);
1421  if (eomap < 0)
1422  return M0_RC(eomap);
1423  M0_ASSERT(eosrc == eodst);
1424  M0_ASSERT(!eomap);
1425  } while (!eosrc);
1426 
1427  M0_LOG(M0_DEBUG, "frags=%d frags_not_empty=%d",
1428  (int)frags, (int)frags_not_empty);
1429 
1430  stob_ad_cursors_fini(it, src, dst, car);
1431 
1432  rc = stob_ad_vec_alloc(io->si_obj, back, frags_not_empty);
1433  if (rc != 0)
1434  return M0_RC(rc);
1435 
1436  rc = stob_ad_cursors_init(io, adom, it, src, dst, car);
1437  if (rc != 0)
1438  return M0_RC(rc);
1439 
1440  for (idx = i = 0; i < frags; ++i) {
1441  void *buf;
1442  m0_bindex_t off;
1443 
1444  buf = io->si_user.ov_buf[src->vc_seg] + src->vc_offset;
1445  off = io->si_stob.iv_index[dst->vc_seg] + dst->vc_offset;
1446 
1447  M0_ASSERT(off >= car->ct_index);
1448  eomap = m0_be_emap_caret_move_sync(car, off - car->ct_index);
1449  if (eomap < 0)
1450  return M0_RC(eomap);
1451  M0_ASSERT(eomap == 0);
1452  M0_ASSERT(m0_ext_is_in(&seg->ee_ext, off));
1453 
1454  frag_size = min3(m0_vec_cursor_step(src),
1456  m0_be_emap_caret_step(car));
1457 
1458  /* that is too expensive:
1459  M0_LOG(M0_DEBUG, "%2d: sz=%lx buf=%p off=%lx "
1460  "ext="EXT_F" val=%lx",
1461  idx, (unsigned long)frag_size, buf,
1462  (unsigned long)off, EXT_P(&seg->ee_ext),
1463  (unsigned long)seg->ee_val); */
1464  if (seg->ee_val == AET_HOLE) {
1465  if (io->si_flags & SIF_NOHOLE) {
1466  rc = M0_ERR(-EIO);
1467  break;
1468  }
1469  /*
1470  * Read of a hole or unallocated space (beyond
1471  * end of the file).
1472  */
1473  memset(stob_ad_addr_open(buf, bshift),
1474  0, frag_size << bshift);
1475  io->si_count += frag_size;
1476  } else {
1477  M0_ASSERT(seg->ee_val < AET_MIN);
1478 
1479  back->si_user.ov_vec.v_count[idx] = frag_size;
1480  back->si_user.ov_buf[idx] = buf;
1481 
1482  back->si_stob.iv_index[idx] = seg->ee_val +
1483  (off - seg->ee_ext.e_start);
1484  idx++;
1485  }
1486  m0_vec_cursor_move(src, frag_size);
1487  m0_vec_cursor_move(dst, frag_size);
1488  rc = m0_be_emap_caret_move_sync(car, frag_size);
1489  if (rc < 0)
1490  break;
1491  M0_ASSERT(rc == 0);
1492  }
1493  M0_ASSERT(ergo(rc == 0, idx == frags_not_empty));
1494  return M0_RC(rc);
1495 }
1496 
1501  struct m0_ext we_ext;
1503 };
1504 
1511 };
1512 
1514  struct stob_ad_write_ext *wext)
1515 {
1516  wc->wc_wext = wext;
1517  wc->wc_done = 0;
1518 }
1519 
1521 {
1522  M0_PRE(wc->wc_wext != NULL);
1523  M0_PRE(wc->wc_done < m0_ext_length(&wc->wc_wext->we_ext));
1524 
1525  return m0_ext_length(&wc->wc_wext->we_ext) - wc->wc_done;
1526 }
1527 
1530 {
1531  while (count > 0 && wc->wc_wext != NULL) {
1532  m0_bcount_t step;
1533 
1534  step = stob_ad_wext_cursor_step(wc);
1535  if (count >= step) {
1536  wc->wc_wext = wc->wc_wext->we_next;
1537  wc->wc_done = 0;
1538  count -= step;
1539  } else {
1540  wc->wc_done += count;
1541  count = 0;
1542  }
1543  }
1544  return wc->wc_wext == NULL;
1545 }
1546 
1554 static uint32_t stob_ad_write_count(struct m0_vec_cursor *src,
1555  struct stob_ad_wext_cursor *wc)
1556 {
1557  m0_bcount_t frag_size;
1558  bool eosrc;
1559  bool eoext;
1560  uint32_t frags = 0;
1561 
1562  do {
1563  frag_size = min_check(m0_vec_cursor_step(src),
1565  M0_ASSERT(frag_size > 0);
1566  M0_ASSERT(frag_size <= (size_t)~0ULL);
1567 
1568  eosrc = m0_vec_cursor_move(src, frag_size);
1569  eoext = stob_ad_wext_cursor_move(wc, frag_size);
1570 
1571  M0_ASSERT(ergo(eosrc, eoext));
1572  ++frags;
1573  } while (!eoext);
1574  return frags;
1575 }
1576 
1581  struct m0_stob_io *back,
1582  struct m0_vec_cursor *src,
1583  struct stob_ad_wext_cursor *wc)
1584 {
1585  m0_bcount_t frag_size;
1586  uint32_t idx;
1587  bool eosrc;
1588  bool eoext;
1589 
1590  idx = 0;
1591  do {
1592  void *buf;
1593 
1594  frag_size = min_check(m0_vec_cursor_step(src),
1596 
1597  buf = io->si_user.ov_buf[src->vc_seg] + src->vc_offset;
1598 
1599  back->si_user.ov_vec.v_count[idx] = frag_size;
1600  back->si_user.ov_buf[idx] = buf;
1601 
1602  back->si_stob.iv_index[idx] =
1603  wc->wc_wext->we_ext.e_start + wc->wc_done;
1604 
1605  eosrc = m0_vec_cursor_move(src, frag_size);
1606  eoext = stob_ad_wext_cursor_move(wc, frag_size);
1607  idx++;
1608  M0_ASSERT(eosrc == eoext);
1609  } while (!eoext);
1610  M0_ASSERT(idx == back->si_stob.iv_vec.v_nr);
1611 }
1612 
1617 static int stob_ad_seg_free(struct m0_dtx *tx,
1618  struct m0_stob_ad_domain *adom,
1619  const struct m0_be_emap_seg *seg,
1620  const struct m0_ext *ext,
1621  uint64_t val)
1622 {
1623  m0_bcount_t delta = ext->e_start - seg->ee_ext.e_start;
1624  struct m0_ext tocut = {
1625  .e_start = val + delta,
1626  .e_end = val + delta + m0_ext_length(ext)
1627  };
1628  m0_ext_init(&tocut);
1629  if (val < AET_MIN) {
1630  M0_LOG(M0_DEBUG, "freeing "EXT_F"@"EXT_F,
1631  EXT_P(ext), EXT_P(&tocut));
1632  }
1633 
1634  return val < AET_MIN ? stob_ad_bfree(adom, tx, &tocut) : 0;
1635 }
1636 
1649  struct m0_stob_ad_domain *adom,
1650  m0_bindex_t off,
1651  struct m0_be_emap_cursor *orig,
1652  const struct m0_ext *ext)
1653 {
1654  int result;
1655  int rc = 0;
1656  struct m0_be_emap_cursor it = {};
1657  /* an extent in the logical name-space to be mapped to ext. */
1658  struct m0_ext todo = {
1659  .e_start = off,
1660  .e_end = off + m0_ext_length(ext)
1661  };
1662  m0_ext_init(&todo);
1663 
1664  M0_ENTRY("ext="EXT_F" val=0x%llx", EXT_P(&todo),
1665  (unsigned long long)ext->e_start);
1666 
1667  result = M0_BE_OP_SYNC_RET_WITH(
1668  &it.ec_op,
1669  m0_be_emap_lookup(orig->ec_map, &orig->ec_seg.ee_pre,
1670  off, &it),
1671  bo_u.u_emap.e_rc);
1672  if (result != 0)
1673  return M0_RC(result);
1674 
1675  /*
1676  * Insert a new segment into extent map, overwriting parts of the map.
1677  *
1678  * Some existing segments are deleted completely, others are
1679  * cut. m0_emap_paste() invokes supplied call-backs to notify the caller
1680  * about changes in the map.
1681  *
1682  * Call-backs are used to free space from overwritten parts of the file.
1683  *
1684  * Each call-back takes a segment argument, seg. seg->ee_ext is a
1685  * logical extent of the segment and seg->ee_val is the starting offset
1686  * of the corresponding physical extent.
1687  */
1688  if (io->si_cksum.b_nob != 0) {
1689 
1690  /* Compute checksum units info which belong to this extent (COB off & Sz) */
1693  io->si_unit_sz,
1694  io->si_cksum_sz);
1695  }
1696  else {
1699  }
1700 
1702 
1703  M0_SET0(&it.ec_op);
1705  m0_be_emap_paste(&it, &io->si_tx->tx_betx, &todo, ext->e_start,
1706  LAMBDA(void, (struct m0_be_emap_seg *seg) {
1707  /* handle extent deletion. */
1708  if (adom->sad_overwrite) {
1709  M0_LOG(M0_DEBUG, "del: val=0x%llx",
1710  (unsigned long long)seg->ee_val);
1711  M0_ASSERT_INFO(seg->ee_val != ext->e_start,
1712  "Delete of the same just allocated block");
1713  rc = rc ?:
1714  stob_ad_seg_free(io->si_tx, adom, seg,
1715  &seg->ee_ext, seg->ee_val);
1716  }
1717  }),
1718  LAMBDA(void, (struct m0_be_emap_seg *seg, struct m0_ext *ext,
1719  uint64_t val) {
1720  /* cut left */
1721  M0_ASSERT(ext->e_start > seg->ee_ext.e_start);
1722 
1723  seg->ee_val = val;
1724  if (adom->sad_overwrite)
1725  rc = rc ?:
1726  stob_ad_seg_free(io->si_tx, adom, seg,
1727  ext, val);
1728  }),
1729  LAMBDA(void, (struct m0_be_emap_seg *seg, struct m0_ext *ext,
1730  uint64_t val) {
1731  /* cut right */
1732  M0_ASSERT(seg->ee_ext.e_end > ext->e_end);
1733  if (val < AET_MIN) {
1734  seg->ee_val = val +
1735  (ext->e_end - seg->ee_ext.e_start);
1736  /*
1737  * Free physical sub-extent, but only when
1738  * sub-extent starts at the left boundary of the
1739  * logical extent, because otherwise "cut left"
1740  * already freed it.
1741  */
1742  if (adom->sad_overwrite &&
1743  ext->e_start == seg->ee_ext.e_start)
1744  rc = rc ?:
1745  stob_ad_seg_free(io->si_tx, adom,
1746  seg, ext, val);
1747  } else
1748  seg->ee_val = val;
1749  }));
1751  result = it.ec_op.bo_u.u_emap.e_rc;
1753  m0_be_emap_close(&it);
1754 
1755  return M0_RC(result ?: rc);
1756 }
1757 
1758 static int stob_ad_fol_frag_alloc(struct m0_fol_frag *frag, uint32_t frags)
1759 {
1760  struct stob_ad_rec_frag *arp;
1761 
1762  M0_PRE(frag != NULL);
1763 
1764  M0_ALLOC_PTR(arp);
1765  if (arp == NULL)
1766  return M0_ERR(-ENOMEM);
1767  m0_fol_frag_init(frag, arp, &stob_ad_rec_frag_type);
1768 
1769  arp->arp_seg.ps_segments = frags;
1770 
1771  M0_ALLOC_ARR(arp->arp_seg.ps_old_data, frags);
1772  if (arp->arp_seg.ps_old_data == NULL) {
1773  m0_free(arp);
1774  return M0_ERR(-ENOMEM);
1775  }
1776  return 0;
1777 }
1778 
1779 static void stob_ad_fol_frag_free(struct m0_fol_frag *frag)
1780 {
1781  struct stob_ad_rec_frag *arp = frag->rp_data;
1782 
1783  m0_free(arp->arp_seg.ps_old_data);
1784  m0_free(arp);
1785 }
1786 
1798 static int stob_ad_write_map(struct m0_stob_io *io,
1799  struct m0_stob_ad_domain *adom,
1800  struct m0_ivec_cursor *dst,
1801  struct m0_be_emap_caret *map,
1802  struct stob_ad_wext_cursor *wc,
1803  uint32_t frags)
1804 {
1805  int rc;
1806  m0_bcount_t frag_size;
1807  m0_bindex_t off;
1808  bool eodst;
1809  bool eoext;
1810  struct m0_ext todo;
1811  struct m0_fol_frag *frag = io->si_fol_frag;
1812  struct stob_ad_rec_frag *arp;
1813  uint32_t i = 0;
1814  uint32_t last_seg;
1815 
1816  M0_ENTRY("io=%p dom=%p frags=%u", io, adom, frags);
1817 
1818  rc = stob_ad_fol_frag_alloc(frag, frags);
1819  if (rc != 0)
1820  return M0_RC(rc);
1821  arp = frag->rp_data;
1822  arp->arp_stob_id = *m0_stob_id_get(io->si_obj);
1824 
1825  do {
1826  off = m0_ivec_cursor_index(dst);
1827  frag_size = min_check(m0_ivec_cursor_step(dst),
1829 
1830  todo.e_start = wc->wc_wext->we_ext.e_start + wc->wc_done;
1831  todo.e_end = todo.e_start + frag_size;
1832  m0_ext_init(&todo);
1833 
1834  M0_ASSERT(i < frags);
1835  arp->arp_seg.ps_old_data[i] = (struct m0_be_emap_seg) {
1836  .ee_ext = {
1837  .e_start = off,
1838  .e_end = off + m0_ext_length(&todo)
1839  },
1840  .ee_val = todo.e_start,
1841  .ee_pre = map->ct_it->ec_seg.ee_pre
1842  };
1844 
1845  rc = stob_ad_write_map_ext(io, adom, off, map->ct_it, &todo);
1846  if (rc != 0)
1847  break;
1848 
1849  last_seg = dst->ic_cur.vc_seg;
1850  eodst = m0_ivec_cursor_move(dst, frag_size);
1851  eoext = stob_ad_wext_cursor_move(wc, frag_size);
1852 
1853  /*
1854  * In m0_vec_cursor_move() if (count >= steps) evaluates to
1855  * false and also the segments are not empty
1856  * (m0_vec_cursor_normalize() skips empty segments) then
1857  * cur->vc_seg is not incremented. i.e. cursor is not actually
1858  * moved ahead.
1859  * In such cases index i shouldn't also be advanced. Otherwise
1860  * it will end up accessing invalid index of
1861  * arp->arp_seg.ps_old_data[].
1862  */
1863  if (last_seg != dst->ic_cur.vc_seg)
1864  ++i;
1865 
1866  M0_ASSERT(eodst == eoext);
1867  } while (!eodst);
1868 
1869  if (rc == 0)
1870  m0_fol_frag_add(&io->si_tx->tx_fol_rec, frag);
1871  else
1872  stob_ad_fol_frag_free(frag);
1873 
1874  return M0_RC(rc);
1875 }
1876 
1880 static void stob_ad_wext_fini(struct stob_ad_write_ext *wext)
1881 {
1882  struct stob_ad_write_ext *next;
1883 
1884  for (wext = wext->we_next; wext != NULL; wext = next) {
1885  next = wext->we_next;
1886  m0_free(wext);
1887  }
1888 }
1889 
1906  struct m0_stob_ad_domain *adom,
1907  struct m0_vec_cursor *src,
1908  struct m0_be_emap_caret *map)
1909 {
1910  m0_bcount_t todo;
1911  uint32_t bfrags = 0;
1912  int rc;
1913  struct stob_ad_write_ext head;
1914  struct stob_ad_write_ext *wext;
1915  struct stob_ad_write_ext *next;
1916  struct m0_stob_io *back;
1917  struct m0_stob_ad_io *aio = io->si_stob_private;
1918  struct stob_ad_wext_cursor wc;
1919 
1922  /* Get total size of buffer */
1923  todo = m0_vec_count(&io->si_user.ov_vec);
1924  M0_ENTRY("op=%d sz=%lu", io->si_opcode, (unsigned long)todo);
1925  back = &aio->ai_back;
1926  M0_SET0(&head);
1927  wext = &head;
1928  wext->we_next = NULL;
1929  while (1) {
1930  m0_bcount_t got;
1931 
1934  /* Get the balloc extent (returned in wext->we_ext) */
1935  rc = stob_ad_balloc(adom, io->si_tx, todo, &wext->we_ext,
1936  aio->ai_balloc_flags);
1939  if (rc != 0)
1940  break;
1941  /* Get balloc extent length */
1942  got = m0_ext_length(&wext->we_ext);
1943  M0_ASSERT(todo >= got);
1944  M0_LOG(M0_DEBUG, "got=%" PRId64 ": " EXT_F,
1945  got, EXT_P(&wext->we_ext));
1946  todo -= got;
1947  ++bfrags;
1948  if (todo > 0) {
1949  if (bfrags >= BALLOC_FRAGS_MAX) {
1950  rc = M0_ERR(-ENOSPC);
1951  break;
1952  }
1953  /* More balloc extent needed so allocate node stob_ad_write_ext
1954  * and add it to link list, so that stob_ad_balloc can populate it
1955  */
1956  M0_ALLOC_PTR(next);
1957  if (next != NULL) {
1958  wext->we_next = next;
1959  wext = next;
1960  } else {
1961  rc = M0_ERR(-ENOMEM);
1962  break;
1963  }
1964  } else
1965  break;
1966  }
1967 
1968  M0_LOG(M0_DEBUG, "bfrags=%u", bfrags);
1969 
1970  if (rc == 0) {
1971  uint32_t frags;
1972 
1973  /* Init cursor for balloc extents */
1975  /* Find num of frag based on boundaries of balloc-extents & buffer-extents */
1976  frags = stob_ad_write_count(src, &wc);
1977  /* Alloc and init bufvec back->si_user & si_stob based on fragment */
1978  rc = stob_ad_vec_alloc(io->si_obj, back, frags);
1979  if (rc == 0) {
1980  struct m0_ivec_cursor dst;
1981  /* reset src - buffer-extent*/
1983  /* reset wc - balloc-extent */
1985  /* Populate bufvec back->si_user & si_stob based on fragment */
1986  stob_ad_write_back_fill(io, back, src, &wc);
1987 
1988  /* Init cursor for COB-offset-extent */
1991  frags = max_check(bfrags, stob_ad_write_map_count(adom,
1992  &io->si_stob, true));
1993  rc = stob_ad_write_map(io, adom, &dst, map, &wc, frags);
1994  }
1995  }
1997  return M0_RC(rc);
1998 }
1999 
2001 {
2002  struct m0_be_emap_cursor it;
2003  struct m0_vec_cursor src;
2004  struct m0_vec_cursor dst;
2005  struct m0_be_emap_caret map;
2006  struct m0_stob_ad_domain *adom;
2007  struct m0_stob_ad_io *aio = io->si_stob_private;
2008  struct m0_stob_io *back = &aio->ai_back;
2009  int rc;
2010 
2011  M0_PRE(io->si_stob.iv_vec.v_nr > 0);
2014 
2015  /* prefix fragments execution mode is not yet supported */
2016  M0_PRE((io->si_flags & SIF_PREFIX) == 0);
2017  /* only read-write at the moment */
2019 
2020  M0_ENTRY("op=%d, stob %p, stob_id="STOB_ID_F,
2022 
2025  rc = stob_ad_cursors_init(io, adom, &it, &src, &dst, &map);
2026  if (rc != 0)
2027  return M0_RC(rc);
2028 
2029  back->si_opcode = io->si_opcode;
2030  back->si_flags = io->si_flags;
2031  back->si_fol_frag = io->si_fol_frag;
2032  back->si_id = io->si_id;
2033 
2034  switch (io->si_opcode) {
2035  case SIO_READ:
2036  rc = stob_ad_read_prepare(io, adom, &src, &dst, &map);
2037  break;
2038  case SIO_WRITE:
2039  rc = stob_ad_write_prepare(io, adom, &src, &map);
2040  break;
2041  default:
2042  M0_IMPOSSIBLE("Invalid io type.");
2043  }
2044  stob_ad_cursors_fini(&it, &src, &dst, &map);
2045 
2046  return rc;
2047 }
2048 
2055 static int stob_ad_io_launch(struct m0_stob_io *io)
2056 {
2057  struct m0_stob_ad_domain *adom;
2058  struct m0_stob_ad_io *aio = io->si_stob_private;
2059  struct m0_stob_io *back = &aio->ai_back;
2060  int rc = 0;
2061  bool wentout = false;
2062 
2063  M0_PRE(io->si_stob.iv_vec.v_nr > 0);
2065  M0_PRE(io->si_state == SIS_BUSY);
2066 
2067  /* prefix fragments execution mode is not yet supported */
2068  M0_PRE((io->si_flags & SIF_PREFIX) == 0);
2069  /* only read-write at the moment */
2071 
2072  M0_ENTRY("op=%d stob_id="STOB_ID_F,
2075 
2077 
2078  if (back->si_stob.iv_vec.v_nr > 0) {
2086  m0_stob_iovec_sort(back);
2090  io->si_tx, io->si_scope);
2091  wentout = rc == 0;
2092  } else {
2093  /*
2094  * Back IO request was constructed OK, but is empty (all
2095  * IO was satisfied from holes). Notify caller about
2096  * completion.
2097  */
2099  stob_ad_endio(&aio->ai_clink);
2100  }
2101 
2102  if (!wentout)
2103  stob_ad_io_release(aio);
2104  return M0_RC(rc);
2105 }
2106 
2107 static bool stob_ad_endio(struct m0_clink *link)
2108 {
2109  struct m0_stob_ad_io *aio;
2110  struct m0_stob_io *io;
2111 
2112  aio = container_of(link, struct m0_stob_ad_io, ai_clink);
2113  io = aio->ai_fore;
2114 
2115  M0_ENTRY("op=%di, stob %p, stob_id="STOB_ID_F,
2117 
2120 
2121  io->si_rc = aio->ai_back.si_rc;
2122  io->si_count += aio->ai_back.si_count;
2123  io->si_state = SIS_IDLE;
2128  stob_ad_io_release(aio);
2130  return true;
2131 }
2132 
2137 static void
2139  struct m0_be_tx_credit *accum)
2140 {
2141  struct stob_ad_rec_frag *arp = frag->rp_data;
2143  struct m0_stob_ad_domain *adom = stob_ad_domain2ad(dom);
2144 
2145  M0_PRE(dom != NULL);
2147  arp->arp_seg.ps_segments, accum);
2148 }
2149 
2155  struct m0_be_tx *tx)
2156 {
2157  struct stob_ad_rec_frag *arp = frag->rp_data;
2159  struct m0_stob_ad_domain *adom = stob_ad_domain2ad(dom);
2160  struct m0_be_emap_seg *old_data = arp->arp_seg.ps_old_data;
2161  struct m0_be_emap_cursor it = {};
2162  int i;
2163  int rc = 0;
2164 
2165  M0_PRE(dom != NULL);
2166 
2167  for (i = 0; rc == 0 && i < arp->arp_seg.ps_segments; ++i) {
2168  M0_SET0(&it.ec_op);
2170  &it.ec_op,
2172  &old_data[i].ee_pre,
2173  old_data[i].ee_ext.e_start,
2174  &it),
2175  bo_u.u_emap.e_rc);
2176  if (rc == 0) {
2177  M0_LOG(M0_DEBUG, "%3d: ext="EXT_F" val=0x%llx",
2178  i, EXT_P(&old_data[i].ee_ext),
2179  (unsigned long long)old_data[i].ee_val);
2180  M0_SET0(&it.ec_op);
2182  &it.ec_op,
2183  m0_be_emap_extent_update(&it, tx, &old_data[i]),
2184  bo_u.u_emap.e_rc);
2185  m0_be_emap_close(&it);
2186  }
2187  }
2188  return M0_RC(rc);
2189 }
2190 
2191 M0_INTERNAL void m0_stob_ad_balloc_set(struct m0_stob_io *io, uint64_t flags)
2192 {
2193  struct m0_stob_ad_io *aio = io->si_stob_private;
2194 
2196  M0_PRE(aio != NULL);
2197  aio->ai_balloc_flags = flags;
2198 }
2199 
2200 M0_INTERNAL void m0_stob_ad_balloc_clear(struct m0_stob_io *io)
2201 {
2202  struct m0_stob_ad_io *aio = io->si_stob_private;
2203 
2204  M0_PRE(aio != NULL);
2206  &m0_stob_ad_type));
2207 
2208  aio->ai_balloc_flags = 0;
2209 }
2210 
2211 static const struct m0_stob_io_op stob_ad_io_op = {
2213  .sio_prepare = stob_ad_io_launch_prepare,
2214  .sio_fini = stob_ad_io_fini,
2215 };
2216 
2219 #undef M0_TRACE_SUBSYSTEM
2220 /*
2221  * Local variables:
2222  * c-indentation-style: "K&R"
2223  * c-basic-offset: 8
2224  * tab-width: 8
2225  * fill-column: 80
2226  * scroll-step: 1
2227  * End:
2228  */
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:1337
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:1580
static bool stob_ad_endio(struct m0_clink *link)
Definition: ad.c:2107
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:2154
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:1554
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:1880
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:1501
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:2000
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:1509
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:1194
M0_INTERNAL void m0_stob_ad_balloc_set(struct m0_stob_io *io, uint64_t flags)
Definition: ad.c:2191
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:497
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:1513
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:1758
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:1235
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:1249
m0_bcount_t wc_done
Definition: ad.c:1510
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:1520
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:1211
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:2138
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:1798
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:1648
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:1779
#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:1528
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:2055
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:1286
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:2200
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:1617
#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:1534
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:1502
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:1905
#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