Motr  M0
tx_regmap.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2013-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_BE
24 #include "lib/trace.h"
25 
26 #include "be/tx_regmap.h"
27 
28 #include "be/tx.h"
29 #include "be/io.h"
30 
31 #include "lib/ext.h" /* m0_ext */
32 #include "lib/errno.h" /* ENOMEM */
33 #include "lib/memory.h" /* m0_alloc_nz */
34 #include "lib/assert.h" /* M0_POST */
35 #include "lib/misc.h" /* M0_SET0 */
36 #include "lib/arith.h" /* max_check */
37 
45 #define REGD_EXT(rd) (struct m0_ext) { \
46  .e_start = (m0_bindex_t)(rd)->rd_reg.br_addr, \
47  .e_end = (m0_bindex_t)(rd)->rd_reg.br_addr + (rd)->rd_reg.br_size \
48 }
49 
50 M0_INTERNAL bool m0_be_reg_d__invariant(const struct m0_be_reg_d *rd)
51 {
52  const struct m0_be_reg *reg = &rd->rd_reg;
53 
59  return _0C(reg->br_addr != NULL) && _0C(reg->br_size > 0);
60 }
61 
62 M0_INTERNAL bool m0_be_reg_d_is_in(const struct m0_be_reg_d *rd, void *ptr)
63 {
64  M0_CASSERT(sizeof(m0_bindex_t) >= sizeof(ptr));
65  return m0_ext_is_in(&REGD_EXT(rd), (m0_bindex_t) ptr);
66 }
67 
68 static bool be_reg_d_are_overlapping(const struct m0_be_reg_d *rd1,
69  const struct m0_be_reg_d *rd2)
70 {
71  return m0_ext_are_overlapping(&REGD_EXT(rd1), &REGD_EXT(rd2));
72 }
73 
74 static bool be_reg_d_is_partof(const struct m0_be_reg_d *super,
75  const struct m0_be_reg_d *sub)
76 {
77  return m0_ext_is_partof(&REGD_EXT(super), &REGD_EXT(sub));
78 }
79 
81 static void *be_reg_d_fb(const struct m0_be_reg_d *rd)
82 {
83  return rd->rd_reg.br_addr;
84 }
85 
87 static void *be_reg_d_fb1(const struct m0_be_reg_d *rd)
88 {
89  return (void *) ((uintptr_t) be_reg_d_fb(rd) - 1);
90 }
91 
93 static void *be_reg_d_lb(const struct m0_be_reg_d *rd)
94 {
95  return rd->rd_reg.br_addr + rd->rd_reg.br_size - 1;
96 }
97 
99 static void *be_reg_d_lb1(const struct m0_be_reg_d *rd)
100 {
101  return (void *) ((uintptr_t) be_reg_d_lb(rd) + 1);
102 }
103 
104 static m0_bcount_t be_reg_d_size(const struct m0_be_reg_d *rd)
105 {
106  return rd->rd_reg.br_size;
107 }
108 
109 static void be_reg_d_sub_make(struct m0_be_reg_d *super,
110  struct m0_be_reg_d *sub)
111 {
112  M0_ASSERT(be_reg_d_is_partof(super, sub));
113 
114  /* sub->rd_reg.br_addr and sub->rd_reg.br_size are already set */
115  sub->rd_reg.br_seg = super->rd_reg.br_seg;
116  sub->rd_buf = super->rd_buf + (be_reg_d_fb(sub) - be_reg_d_fb(super));
117  sub->rd_gen_idx = super->rd_gen_idx;
118 }
119 
120 static void be_reg_d_arr_insert2(void *arr[2], void *value)
121 {
122  M0_PRE(arr[0] != NULL && arr[1] != NULL);
123 
124  if (value < arr[0]) {
125  arr[1] = arr[0];
126  arr[0] = value;
127  } else if (arr[0] < value && value < arr[1]) {
128  arr[1] = value;
129  }
130 }
131 
132 /*
133  * The function returns the first left-most non-crossing sub-region from the
134  * given @rd_arr array of (possibly crossing) regions which starts from @start
135  * (if its value is within that sub-region).
136  *
137  * Example:
138  *
139  * rd_arr has 2 regions: R1 = (1, 5) and R2 = (4, 7) (regions (addr, size)).
140  * Given regions:
141  * | R1 |
142  * +--+-+----+
143  * | R2 |
144  * The function gives the following region depending on start:
145  * +-------+----------------+
146  * | start | (*addr, *size) |
147  * +-------+----------------+
148  * | 0 or 1| (1, 3) |
149  * | 2 | (2, 2) |
150  * | 3 | (3, 1) |
151  * | 4 | (4, 2) |
152  * | 5 | (5, 1) |
153  * +-------+----------------+
154  *
155  * @param[in] rd_arr array of reg_d
156  * @param[in] nr number of elements in rd_arr
157  * @param[in] start result region addr can't be less than start.
158  * start address must be not greater than the end of
159  * left-most region in the given @rd_arr[]
160  * @param[out] addr result region addr
161  * @param[out] size result region size
162  */
163 static void be_reg_d_arr_first_subreg(struct m0_be_reg_d **rd_arr,
164  int nr,
165  void *start,
166  void **addr,
167  m0_bcount_t *size)
168 {
169  struct m0_be_reg_d *rd;
170  void *arr[2];
171  void *fb;
172  void *lb1;
173  int i;
174 
175  arr[0] = NULL;
176  arr[1] = NULL;
177  for (i = 0; i < nr; ++i) {
178  rd = rd_arr[i];
179  if (rd != NULL) {
180  fb = be_reg_d_fb(rd);
181  lb1 = be_reg_d_lb1(rd);
182  fb = max_check(fb, start);
183  M0_ASSERT(fb < lb1);
184  if (arr[0] == NULL && arr[1] == NULL) {
185  arr[0] = fb;
186  arr[1] = lb1;
187  } else {
188  be_reg_d_arr_insert2(arr, fb);
189  be_reg_d_arr_insert2(arr, lb1);
190  }
191  }
192  }
193  M0_ASSERT(arr[0] != NULL && arr[1] != NULL);
194  M0_ASSERT(arr[0] != arr[1]);
195  *addr = arr[0];
196  *size = arr[1] - arr[0];
197 }
198 
199 static bool be_rdt_contains(const struct m0_be_reg_d_tree *rdt,
200  const struct m0_be_reg_d *rd)
201 {
202  return &rdt->brt_r[0] <= rd && rd < &rdt->brt_r[rdt->brt_size];
203 }
204 
205 #define ARRAY_ALLOC_NZ(arr, nr) ((arr) = m0_alloc_nz((nr) * sizeof ((arr)[0])))
206 
207 M0_INTERNAL int m0_be_rdt_init(struct m0_be_reg_d_tree *rdt, size_t size_max)
208 {
209  rdt->brt_size_max = size_max;
210  ARRAY_ALLOC_NZ(rdt->brt_r, rdt->brt_size_max);
211  if (rdt->brt_r == NULL)
212  return M0_ERR(-ENOMEM);
213 
215  return 0;
216 }
217 
218 M0_INTERNAL void m0_be_rdt_fini(struct m0_be_reg_d_tree *rdt)
219 {
221  m0_free(rdt->brt_r);
222 }
223 
224 M0_INTERNAL bool m0_be_rdt__invariant(const struct m0_be_reg_d_tree *rdt)
225 {
226  return _0C(rdt != NULL) &&
227  _0C(rdt->brt_r != NULL || rdt->brt_size == 0) &&
228  _0C(rdt->brt_size <= rdt->brt_size_max) &&
230  m0_be_reg_d__invariant(&rdt->brt_r[i]))) &&
232  rdt->brt_size == 0 ? 0 : rdt->brt_size - 1,
233  _0C(rdt->brt_r[i].rd_reg.br_addr <
234  rdt->brt_r[i + 1].rd_reg.br_addr))) &&
236  rdt->brt_size == 0 ? 0 : rdt->brt_size - 1,
238  &rdt->brt_r[i + 1]))));
239 }
240 
241 M0_INTERNAL size_t m0_be_rdt_size(const struct m0_be_reg_d_tree *rdt)
242 {
243  return rdt->brt_size;
244 }
245 
247 static bool be_rdt_check_i(const struct m0_be_reg_d_tree *rdt,
248  void *addr,
249  size_t index)
250 {
251  struct m0_be_reg_d *r = rdt->brt_r;
252  size_t size = m0_be_rdt_size(rdt);
253 
254  return (size == 0 && index == 0) ||
255  (size != 0 &&
256  ((index == size && !m0_be_reg_d_is_in(&r[size - 1], addr) &&
257  addr > r[size - 1].rd_reg.br_addr) ||
258  (index == 0 && (m0_be_reg_d_is_in(&r[0], addr) ||
259  addr < r[0].rd_reg.br_addr)) ||
260  (index < size && m0_be_reg_d_is_in(&r[index], addr)) ||
262  !m0_be_reg_d_is_in(&r[index - 1], addr) &&
263  addr < r[index].rd_reg.br_addr &&
264  addr > r[index - 1].rd_reg.br_addr)));
265 }
266 
268 static size_t be_rdt_find_i(const struct m0_be_reg_d_tree *rdt, void *addr)
269 {
270  size_t begin = 0;
271  size_t mid;
272  size_t end = m0_be_rdt_size(rdt);
273  size_t res = m0_be_rdt_size(rdt) + 1;
274  size_t size = m0_be_rdt_size(rdt);
275 
276  while (begin + 1 < end) {
277  mid = (begin + end) / 2;
278  M0_ASSERT_INFO(mid > begin && mid < end,
279  "begin = %zu, mid = %zu, end = %zu",
280  begin, mid, end);
281  if (rdt->brt_r[mid].rd_reg.br_addr < addr) {
282  begin = mid;
283  } else {
284  end = mid;
285  }
286  }
287  res = be_rdt_check_i(rdt, addr, begin) ? begin : res;
288  res = be_rdt_check_i(rdt, addr, end) ? end : res;
289 
290  M0_ASSERT_INFO(size == 0 || res <= size, "size = %zu, res = %zu",
291  size, res);
293  M0_POST(be_rdt_check_i(rdt, addr, res));
294  return res;
295 }
296 
297 
298 M0_INTERNAL struct m0_be_reg_d *
299 m0_be_rdt_find(const struct m0_be_reg_d_tree *rdt, void *addr)
300 {
301  struct m0_be_reg_d *rd;
302  size_t i;
303 
305 
306  i = be_rdt_find_i(rdt, addr);
307  rd = i == rdt->brt_size ? NULL : &rdt->brt_r[i];
308 
309  M0_POST(ergo(rd != NULL, be_rdt_contains(rdt, rd)));
310  return rd;
311 }
312 
313 M0_INTERNAL struct m0_be_reg_d *
314 m0_be_rdt_next(const struct m0_be_reg_d_tree *rdt, struct m0_be_reg_d *prev)
315 {
316  struct m0_be_reg_d *rd;
317 
319  M0_PRE(prev != NULL);
320  M0_PRE(be_rdt_contains(rdt, prev));
321 
322  rd = prev == &rdt->brt_r[rdt->brt_size - 1] ? NULL : ++prev;
323 
324  M0_POST(ergo(rd != NULL, be_rdt_contains(rdt, rd)));
325  return rd;
326 }
327 
328 M0_INTERNAL void m0_be_rdt_ins(struct m0_be_reg_d_tree *rdt,
329  const struct m0_be_reg_d *rd)
330 {
331  size_t index;
332  size_t i;
333 
335  M0_PRE(m0_be_rdt_size(rdt) < rdt->brt_size_max);
336  M0_PRE(rd->rd_reg.br_size > 0);
337 
338  index = be_rdt_find_i(rdt, be_reg_d_fb(rd));
339  ++rdt->brt_size;
340  for (i = rdt->brt_size - 1; i > index; --i)
341  rdt->brt_r[i] = rdt->brt_r[i - 1];
342  rdt->brt_r[index] = *rd;
343 
345 }
346 
347 M0_INTERNAL struct m0_be_reg_d *m0_be_rdt_del(struct m0_be_reg_d_tree *rdt,
348  const struct m0_be_reg_d *rd)
349 {
350  size_t index;
351  size_t i;
352 
354  M0_PRE(m0_be_rdt_size(rdt) > 0);
355 
356  index = be_rdt_find_i(rdt, be_reg_d_fb(rd));
358 
359  for (i = index; i + 1 < rdt->brt_size; ++i)
360  rdt->brt_r[i] = rdt->brt_r[i + 1];
361  --rdt->brt_size;
362 
364  return index == m0_be_rdt_size(rdt) ? NULL : &rdt->brt_r[index];
365 }
366 
367 M0_INTERNAL void m0_be_rdt_reset(struct m0_be_reg_d_tree *rdt)
368 {
370 
371  rdt->brt_size = 0;
372 
373  M0_POST(m0_be_rdt_size(rdt) == 0);
375 }
376 
377 M0_INTERNAL int
379  const struct m0_be_regmap_ops *ops,
380  void *ops_data,
381  size_t size_max,
382  bool split_on_absorb)
383 {
384  int rc;
385 
386  rc = m0_be_rdt_init(&rm->br_rdt, size_max);
387  rm->br_ops = ops;
388  rm->br_ops_data = ops_data;
389  rm->br_split_on_absorb = split_on_absorb;
390 
392  return M0_RC(rc);
393 }
394 
395 M0_INTERNAL void m0_be_regmap_fini(struct m0_be_regmap *rm)
396 {
398  m0_be_rdt_fini(&rm->br_rdt);
399 }
400 
401 M0_INTERNAL bool m0_be_regmap__invariant(const struct m0_be_regmap *rm)
402 {
403  return _0C(rm != NULL) && m0_be_rdt__invariant(&rm->br_rdt);
404 }
405 
406 static struct m0_be_reg_d *be_regmap_find_fb(struct m0_be_regmap *rm,
407  const struct m0_be_reg_d *rd)
408 {
409  return m0_be_rdt_find(&rm->br_rdt, be_reg_d_fb(rd));
410 }
411 
412 static void be_regmap_reg_d_cut(struct m0_be_regmap *rm,
413  struct m0_be_reg_d *rd,
414  m0_bcount_t cut_start,
415  m0_bcount_t cut_end)
416 {
417  struct m0_be_reg *r = &rd->rd_reg;
418 
420  M0_PRE(rd->rd_reg.br_size > cut_start + cut_end);
421 
422  rm->br_ops->rmo_cut(rm->br_ops_data, rd, cut_start, cut_end);
423 
424  r->br_size -= cut_start;
425  r->br_addr += cut_start;
426 
427  r->br_size -= cut_end;
428 
430 }
431 
432 /* rdi is splitted in 2 parts (if possible). rd is inserted between them. */
433 static void be_regmap_reg_d_split(struct m0_be_regmap *rm,
434  struct m0_be_reg_d *rdi,
435  struct m0_be_reg_d *rd,
436  struct m0_be_reg_d *rd_new)
437 {
438  /*
439  * | rdi |
440  * +---------------+------+--------------+
441  * | rdi_before_rd | rd | rdi_after_rd |
442  */
443  m0_bcount_t rdi_before_rd = be_reg_d_fb(rd) - be_reg_d_fb(rdi);
444  m0_bcount_t rdi_after_rd = be_reg_d_lb1(rdi) - be_reg_d_lb1(rd);
445 
446  M0_ASSERT(_0C(rdi_before_rd > 0) && _0C(rdi_after_rd > 0));
447 
448  rd_new->rd_reg = M0_BE_REG(NULL, rdi_after_rd, be_reg_d_lb1(rd));
449  be_regmap_reg_d_cut(rm, rdi, 0, rdi_after_rd);
450  /*
451  * | rdi | | rdi | rd_new |
452  * +-------+-------+-------+ -> +-------+-------+--------+
453  * | | rd | | | | rd | |
454  */
455  rm->br_ops->rmo_split(rm->br_ops_data, rdi, rd_new);
456 }
457 
458 M0_INTERNAL void m0_be_regmap_add(struct m0_be_regmap *rm,
459  struct m0_be_reg_d *rd)
460 {
461  struct m0_be_reg_d *rdi;
462  struct m0_be_reg_d rd_copy;
463  struct m0_be_reg_d rd_new;
464  bool copied = false;
465 
467  M0_PRE(rd != NULL);
469 
470  rdi = be_regmap_find_fb(rm, rd);
471  if (rdi != NULL &&
472  be_reg_d_fb(rdi) < be_reg_d_fb(rd) &&
473  be_reg_d_lb(rdi) > be_reg_d_lb(rd)) {
474  /* old region completely absorbs the new */
475  if (rm->br_split_on_absorb) {
476  be_regmap_reg_d_split(rm, rdi, rd, &rd_new);
477  m0_be_rdt_ins(&rm->br_rdt, &rd_new);
478  } else {
479  rm->br_ops->rmo_cpy(rm->br_ops_data, rdi, rd);
480  copied = true;
481  }
482  }
483  if (!copied) {
484  m0_be_regmap_del(rm, rd);
485  rd_copy = *rd;
486  rm->br_ops->rmo_add(rm->br_ops_data, &rd_copy);
487  m0_be_rdt_ins(&rm->br_rdt, &rd_copy);
488  }
489 
491 }
492 
493 M0_INTERNAL void m0_be_regmap_del(struct m0_be_regmap *rm,
494  const struct m0_be_reg_d *rd)
495 {
496  struct m0_be_reg_d *rdi;
498 
500  M0_PRE(rd != NULL);
502 
503  /* first intersection */
504  rdi = be_regmap_find_fb(rm, rd);
505  if (rdi != NULL && m0_be_reg_d_is_in(rdi, be_reg_d_fb(rd)) &&
506  !m0_be_reg_d_is_in(rdi, be_reg_d_lb1(rd)) &&
507  !be_reg_d_is_partof(rd, rdi)) {
508  cut = be_reg_d_size(rdi);
509  cut -= be_reg_d_fb(rd) - be_reg_d_fb(rdi);
510  be_regmap_reg_d_cut(rm, rdi, 0, cut);
511  rdi = m0_be_rdt_next(&rm->br_rdt, rdi);
512  }
513  /* delete all completely covered regions */
514  while (rdi != NULL && be_reg_d_is_partof(rd, rdi)) {
515  rm->br_ops->rmo_del(rm->br_ops_data, rdi);
516  rdi = m0_be_rdt_del(&rm->br_rdt, rdi);
517  }
518  /* last intersection */
519  if (rdi != NULL && !m0_be_reg_d_is_in(rdi, be_reg_d_fb1(rd)) &&
520  m0_be_reg_d_is_in(rdi, be_reg_d_lb(rd))) {
521  cut = be_reg_d_size(rdi);
522  cut -= be_reg_d_lb(rdi) - be_reg_d_lb(rd);
523  be_regmap_reg_d_cut(rm, rdi, cut, 0);
524  }
525 }
526 
527 M0_INTERNAL struct m0_be_reg_d *m0_be_regmap_first(struct m0_be_regmap *rm)
528 {
529  return m0_be_rdt_find(&rm->br_rdt, NULL);
530 }
531 
532 M0_INTERNAL struct m0_be_reg_d *m0_be_regmap_next(struct m0_be_regmap *rm,
533  struct m0_be_reg_d *prev)
534 {
535  return m0_be_rdt_next(&rm->br_rdt, prev);
536 }
537 
538 M0_INTERNAL size_t m0_be_regmap_size(const struct m0_be_regmap *rm)
539 {
541  return m0_be_rdt_size(&rm->br_rdt);
542 }
543 
544 M0_INTERNAL void m0_be_regmap_reset(struct m0_be_regmap *rm)
545 {
546  m0_be_rdt_reset(&rm->br_rdt);
547 }
548 
549 #undef REGD_EXT
550 
553 
554 static const struct m0_be_regmap_ops *be_reg_area_ops[] = {
557 };
558 
559 M0_INTERNAL int m0_be_reg_area_init(struct m0_be_reg_area *ra,
560  const struct m0_be_tx_credit *prepared,
562 {
563  int rc;
564 
567 
568  *ra = (struct m0_be_reg_area){
569  .bra_type = type,
570  .bra_prepared = *prepared,
571  };
572 
573  /*
574  * ra->bra_prepared.tc_reg_nr is multiplied by 2 because
575  * it's possible to have number of used regions greater than
576  * a number of captured regions due to generation index accounting.
577  */
579  ra->bra_prepared.tc_reg_nr == 0 ? 0 :
580  ra->bra_prepared.tc_reg_nr * 2 - 1, true);
581  if (rc == 0 && type == M0_BE_REG_AREA_DATA_COPY) {
583  if (ra->bra_area == NULL) {
585  rc = -ENOMEM;
586  }
587  }
588 
589  /*
590  * Invariant should work even if m0_be_reg_area_init()
591  * was not successful.
592  */
593  if (rc != 0)
594  M0_SET0(ra);
595 
597  return M0_RC(rc);
598 }
599 
600 #undef ARRAY_ALLOC_NZ
601 
602 M0_INTERNAL void m0_be_reg_area_fini(struct m0_be_reg_area *ra)
603 {
606  m0_free(ra->bra_area);
607 }
608 
609 M0_INTERNAL bool m0_be_reg_area__invariant(const struct m0_be_reg_area *ra)
610 {
611  return m0_be_regmap__invariant(&ra->bra_map) &&
614 }
615 
616 M0_INTERNAL void m0_be_reg_area_used(struct m0_be_reg_area *ra,
617  struct m0_be_tx_credit *used)
618 {
619  struct m0_be_reg_d *rd;
620 
622 
623  M0_SET0(used);
624  for (rd = m0_be_regmap_first(&ra->bra_map); rd != NULL;
625  rd = m0_be_regmap_next(&ra->bra_map, rd))
627 }
628 
629 M0_INTERNAL void m0_be_reg_area_prepared(struct m0_be_reg_area *ra,
630  struct m0_be_tx_credit *prepared)
631 {
633 
634  *prepared = ra->bra_prepared;
635 }
636 
637 M0_INTERNAL void m0_be_reg_area_captured(struct m0_be_reg_area *ra,
638  struct m0_be_tx_credit *captured)
639 {
641 
642  *captured = ra->bra_captured;
643 }
644 
645 static void be_reg_d_cpy(void *dst, const struct m0_be_reg_d *rd)
646 {
647  memcpy(dst, rd->rd_reg.br_addr, rd->rd_reg.br_size);
648 }
649 
651 {
652  void *ptr;
653 
654  ptr = ra->bra_area + ra->bra_area_used;
655  ra->bra_area_used += size;
657  return ptr;
658 }
659 
660 static void be_reg_area_add_copy(void *data, struct m0_be_reg_d *rd)
661 {
662  struct m0_be_reg_area *ra = data;
663 
665  M0_PRE(rd->rd_buf == NULL);
666 
667  rd->rd_buf = be_reg_area_alloc(ra, rd->rd_reg.br_size);
668  be_reg_d_cpy(rd->rd_buf, rd);
669 }
670 
671 static void be_reg_area_add(void *data, struct m0_be_reg_d *rd)
672 {
673  M0_PRE(rd->rd_buf != NULL);
674 }
675 
676 static void be_reg_area_del(void *data, const struct m0_be_reg_d *rd)
677 {
678  /* do nothing */
679 }
680 
681 static void be_reg_area_cpy_copy(void *data,
682  const struct m0_be_reg_d *super,
683  const struct m0_be_reg_d *rd)
684 {
685  m0_bcount_t rd_offset;
686 
688  M0_PRE(be_reg_d_is_partof(super, rd));
689  M0_PRE(super->rd_buf != NULL);
690  M0_PRE(rd->rd_buf == NULL);
691 
692  rd_offset = rd->rd_reg.br_addr - super->rd_reg.br_addr;
693  be_reg_d_cpy(super->rd_buf + rd_offset, rd);
694 }
695 
696 /* XXX copy-paste from be_reg_area_cpy_copy() */
697 static void be_reg_area_cpy(void *data,
698  const struct m0_be_reg_d *super,
699  const struct m0_be_reg_d *rd)
700 {
701  m0_bcount_t rd_offset;
702 
704  M0_PRE(be_reg_d_is_partof(super, rd));
705  M0_PRE(super->rd_buf != NULL);
706  M0_PRE(rd->rd_buf != NULL);
707 
708  rd_offset = rd->rd_reg.br_addr - super->rd_reg.br_addr;
709  memcpy(super->rd_buf + rd_offset, rd->rd_buf, rd->rd_reg.br_size);
710 }
711 
712 static void be_reg_area_cut(void *data,
713  struct m0_be_reg_d *rd,
714  m0_bcount_t cut_at_start,
715  m0_bcount_t cut_at_end)
716 {
717  rd->rd_buf += cut_at_start;
718 }
719 
720 static void be_reg_area_split(void *data,
721  struct m0_be_reg_d *rd,
722  struct m0_be_reg_d *rd_new)
723 {
724  /*
725  * | rd |
726  * +---------+-----------+
727  * | rd | rd_new | <-- rd->rd_reg is already split
728  * this function does the rest
729  */
730  rd_new->rd_reg.br_seg = rd->rd_reg.br_seg;
731  rd_new->rd_buf = rd->rd_buf + rd->rd_reg.br_size;
732  rd_new->rd_gen_idx = rd->rd_gen_idx;
733 }
734 
735 static const struct m0_be_regmap_ops be_reg_area_ops_data_copy = {
737  .rmo_del = be_reg_area_del,
738  .rmo_cpy = be_reg_area_cpy_copy,
739  .rmo_cut = be_reg_area_cut,
740  .rmo_split = be_reg_area_split,
741 };
742 
743 static const struct m0_be_regmap_ops be_reg_area_ops_data_nocopy = {
745  .rmo_del = be_reg_area_del,
746  .rmo_cpy = be_reg_area_cpy,
747  .rmo_cut = be_reg_area_cut,
748  .rmo_split = be_reg_area_split,
749 };
750 
751 M0_INTERNAL void m0_be_reg_area_capture(struct m0_be_reg_area *ra,
752  struct m0_be_reg_d *rd)
753 {
754  struct m0_be_tx_credit *captured = &ra->bra_captured;
755  struct m0_be_tx_credit *prepared = &ra->bra_prepared;
756  m0_bcount_t reg_size = rd->rd_reg.br_size;
757 
760 
761  m0_be_tx_credit_add(captured, &M0_BE_REG_D_CREDIT(rd));
762 
763  M0_ASSERT_INFO(m0_be_tx_credit_le(captured, prepared),
764  "There is not enough credits for capturing: "
765  "captured="
766  BETXCR_F" prepared="BETXCR_F" region_size=%"PRId64,
767  BETXCR_P(captured), BETXCR_P(prepared), reg_size);
768 
769  m0_be_regmap_add(&ra->bra_map, rd);
770 
773 }
774 
775 M0_INTERNAL void m0_be_reg_area_uncapture(struct m0_be_reg_area *ra,
776  const struct m0_be_reg_d *rd)
777 {
780 
781  m0_be_regmap_del(&ra->bra_map, rd);
782 
785 }
786 
787 M0_INTERNAL void m0_be_reg_area_merge_in(struct m0_be_reg_area *ra,
788  struct m0_be_reg_area *src)
789 {
790  struct m0_be_reg_d *rd;
791 
793  m0_be_reg_area_capture(ra, rd);
794  }
795 }
796 
797 M0_INTERNAL void m0_be_reg_area_reset(struct m0_be_reg_area *ra)
798 {
800 
802  ra->bra_area_used = 0;
803  M0_SET0(&ra->bra_captured);
804 
806 }
807 
808 M0_INTERNAL void m0_be_reg_area_optimize(struct m0_be_reg_area *ra)
809 {
810  /* to be implemented. */
811 }
812 
813 M0_INTERNAL struct m0_be_reg_d *
815 {
816  return m0_be_regmap_first(&ra->bra_map);
817 }
818 
819 M0_INTERNAL struct m0_be_reg_d *
821 {
822  return m0_be_regmap_next(&ra->bra_map, prev);
823 }
824 
825 M0_INTERNAL int
827  int reg_area_nr_max)
828 {
829  int rc;
830 
831  brm->brm_reg_area_nr_max = reg_area_nr_max;
832  brm->brm_reg_area_nr = 0;
833 
836  if (brm->brm_reg_areas == NULL || brm->brm_pos == NULL) {
837  m0_free(brm->brm_reg_areas);
838  m0_free(brm->brm_pos);
839  rc = -ENOMEM;
840  } else {
841  rc = 0;
842  }
843  return rc;
844 }
845 
847 {
848  m0_free(brm->brm_pos);
849  m0_free(brm->brm_reg_areas);
850 }
851 
853 {
854  brm->brm_reg_area_nr = 0;
855 }
856 
858  struct m0_be_reg_area *ra)
859 {
861 
862  brm->brm_reg_areas[brm->brm_reg_area_nr++] = ra;
863 }
864 
866  void *addr,
868  struct m0_be_reg_d *rd_new)
869 {
870  struct m0_be_reg_d *rd;
871  int i;
872  int max_i;
873 
874  *rd_new = M0_BE_REG_D(M0_BE_REG(NULL, size, addr), NULL);
875  max_i = -1;
876  for (i = 0; i < brm->brm_reg_area_nr; ++i) {
877  rd = brm->brm_pos[i];
878  M0_ASSERT(rd == NULL ||
879  be_reg_d_is_partof(rd, rd_new) ||
880  !be_reg_d_are_overlapping(rd, rd_new));
881  M0_ASSERT(ergo(rd != NULL && max_i != -1,
882  rd->rd_gen_idx != rd_new->rd_gen_idx));
883  if (rd != NULL && be_reg_d_are_overlapping(rd, rd_new) &&
884  (max_i == -1 || rd_new->rd_gen_idx < rd->rd_gen_idx)) {
885  max_i = i;
886  rd_new->rd_gen_idx = rd->rd_gen_idx;
887  }
888  }
889  M0_ASSERT(max_i != -1);
890  be_reg_d_sub_make(brm->brm_pos[max_i], rd_new);
891 }
892 
893 M0_INTERNAL void
895  struct m0_be_reg_area *ra)
896 {
897  struct m0_be_reg_d *rd;
898  struct m0_be_reg_d rd_new;
900  void *addr;
901  int i;
902 
903  for (i = 0; i < brm->brm_reg_area_nr; ++i)
905  addr = NULL;
906  while (m0_exists(j, brm->brm_reg_area_nr, brm->brm_pos[j] != NULL)) {
908  addr, &addr, &size);
909  be_reg_area_merger_max_gen_idx(brm, addr, size, &rd_new);
910  m0_be_reg_area_capture(ra, &rd_new);
911  addr += size;
912  /* pass by all stale regions by @addr */
913  for (i = 0; i < brm->brm_reg_area_nr; ++i) {
914  rd = brm->brm_pos[i];
915  if (rd != NULL && be_reg_d_lb1(rd) == addr) {
916  rd = m0_be_reg_area_next(
917  brm->brm_reg_areas[i], rd);
918  brm->brm_pos[i] = rd;
919  }
920  }
921  }
922 }
923 
924 #undef M0_TRACE_SUBSYSTEM
925 
928 /*
929  * Local variables:
930  * c-indentation-style: "K&R"
931  * c-basic-offset: 8
932  * tab-width: 8
933  * fill-column: 80
934  * scroll-step: 1
935  * End:
936  */
937 /*
938  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
939  */
static void ptr(struct m0_addb2__context *ctx, const uint64_t *v, char *buf)
Definition: dump.c:440
M0_INTERNAL struct m0_be_reg_d * m0_be_rdt_next(const struct m0_be_reg_d_tree *rdt, struct m0_be_reg_d *prev)
Definition: tx_regmap.c:314
static size_t nr
Definition: dump.c:1505
#define M0_PRE(cond)
struct m0_be_reg_d ** brm_pos
Definition: tx_regmap.h:316
static void be_reg_area_cut(void *data, struct m0_be_reg_d *rd, m0_bcount_t cut_at_start, m0_bcount_t cut_at_end)
Definition: tx_regmap.c:712
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
M0_INTERNAL struct m0_be_reg_d * m0_be_regmap_first(struct m0_be_regmap *rm)
Definition: tx_regmap.c:527
#define BETXCR_F
Definition: tx_credit.h:102
M0_INTERNAL struct m0_be_reg_d * m0_be_rdt_del(struct m0_be_reg_d_tree *rdt, const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:347
bool br_split_on_absorb
Definition: tx_regmap.h:94
#define NULL
Definition: misc.h:38
static struct m0_bufvec dst
Definition: xform.c:61
M0_INTERNAL struct m0_be_reg_d * m0_be_reg_area_first(struct m0_be_reg_area *ra)
Definition: tx_regmap.c:814
#define ergo(a, b)
Definition: misc.h:293
M0_INTERNAL int m0_be_reg_area_merger_init(struct m0_be_reg_area_merger *brm, int reg_area_nr_max)
Definition: tx_regmap.c:826
static void be_regmap_reg_d_split(struct m0_be_regmap *rm, struct m0_be_reg_d *rdi, struct m0_be_reg_d *rd, struct m0_be_reg_d *rd_new)
Definition: tx_regmap.c:433
unsigned long rd_gen_idx
Definition: tx_regmap.h:64
static void be_reg_area_split(void *data, struct m0_be_reg_d *rd, struct m0_be_reg_d *rd_new)
Definition: tx_regmap.c:720
size_t brt_size_max
Definition: tx_regmap.h:74
M0_INTERNAL void m0_be_regmap_del(struct m0_be_regmap *rm, const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:493
M0_INTERNAL bool m0_be_reg_area__invariant(const struct m0_be_reg_area *ra)
Definition: tx_regmap.c:609
struct m0_be_tx_credit bra_prepared
Definition: tx_regmap.h:242
M0_INTERNAL void m0_be_rdt_fini(struct m0_be_reg_d_tree *rdt)
Definition: tx_regmap.c:218
#define M0_CASSERT(cond)
static void be_reg_area_add_copy(void *data, struct m0_be_reg_d *rd)
Definition: tx_regmap.c:660
#define max_check(a, b)
Definition: arith.h:95
M0_INTERNAL int m0_be_regmap_init(struct m0_be_regmap *rm, const struct m0_be_regmap_ops *ops, void *ops_data, size_t size_max, bool split_on_absorb)
Definition: tx_regmap.c:378
struct m0_bufvec data
Definition: di.c:40
int const char const void * value
Definition: dir.c:325
M0_INTERNAL void m0_be_regmap_add(struct m0_be_regmap *rm, struct m0_be_reg_d *rd)
Definition: tx_regmap.c:458
m0_bcount_t br_size
Definition: seg.h:144
uint64_t m0_bindex_t
Definition: types.h:80
#define m0_exists(var, nr,...)
Definition: misc.h:134
static void be_reg_d_cpy(void *dst, const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:645
uint64_t m0_bcount_t
Definition: types.h:77
static const struct m0_be_regmap_ops be_reg_area_ops_data_nocopy
Definition: tx_regmap.c:552
M0_INTERNAL void m0_be_reg_area_merger_add(struct m0_be_reg_area_merger *brm, struct m0_be_reg_area *ra)
Definition: tx_regmap.c:857
struct m0_be_reg_d * brt_r
Definition: tx_regmap.h:75
#define M0_SET0(obj)
Definition: misc.h:64
static void * be_reg_d_fb1(const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:87
void * br_ops_data
Definition: tx_regmap.h:93
#define M0_BE_REG_D_CREDIT(rd)
Definition: tx_regmap.h:69
#define M0_BE_REG(seg, size, addr)
Definition: seg.h:148
m0_bcount_t bra_area_used
Definition: tx_regmap.h:241
#define M0_BE_REG_D(reg, buf)
Definition: tx_regmap.h:67
void(* rmo_add)(void *data, struct m0_be_reg_d *rd)
Definition: tx_regmap.h:79
M0_INTERNAL void m0_be_reg_area_capture(struct m0_be_reg_area *ra, struct m0_be_reg_d *rd)
Definition: tx_regmap.c:751
#define M0_BE_REG_AREA_FORALL(ra, rd)
Definition: tx_regmap.h:299
M0_INTERNAL void m0_be_reg_area_fini(struct m0_be_reg_area *ra)
Definition: tx_regmap.c:602
M0_INTERNAL int m0_be_reg_area_init(struct m0_be_reg_area *ra, const struct m0_be_tx_credit *prepared, enum m0_be_reg_area_type type)
Definition: tx_regmap.c:559
struct m0_be_reg rd_reg
Definition: tx_regmap.h:53
#define M0_CHECK_EX(cond)
return M0_RC(rc)
enum m0_be_reg_area_type bra_type
Definition: tx_regmap.h:238
static const struct m0_be_regmap_ops * be_reg_area_ops[]
Definition: tx_regmap.c:554
static char * addr
Definition: node_k.c:37
M0_INTERNAL size_t m0_be_regmap_size(const struct m0_be_regmap *rm)
Definition: tx_regmap.c:538
int i
Definition: dir.c:1033
M0_INTERNAL void m0_be_reg_area_reset(struct m0_be_reg_area *ra)
Definition: tx_regmap.c:797
M0_INTERNAL struct m0_be_reg_d * m0_be_reg_area_next(struct m0_be_reg_area *ra, struct m0_be_reg_d *prev)
Definition: tx_regmap.c:820
static void * be_reg_d_lb1(const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:99
return M0_ERR(-EOPNOTSUPP)
M0_INTERNAL void m0_be_reg_area_used(struct m0_be_reg_area *ra, struct m0_be_tx_credit *used)
Definition: tx_regmap.c:616
M0_INTERNAL int m0_be_rdt_init(struct m0_be_reg_d_tree *rdt, size_t size_max)
Definition: tx_regmap.c:207
M0_INTERNAL bool m0_be_reg_d__invariant(const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:50
static bool be_reg_d_is_partof(const struct m0_be_reg_d *super, const struct m0_be_reg_d *sub)
Definition: tx_regmap.c:74
char * bra_area
Definition: tx_regmap.h:240
static void be_reg_area_cpy(void *data, const struct m0_be_reg_d *super, const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:697
struct m0_be_tx_credit bra_captured
Definition: tx_regmap.h:247
static void be_reg_d_arr_first_subreg(struct m0_be_reg_d **rd_arr, int nr, void *start, void **addr, m0_bcount_t *size)
Definition: tx_regmap.c:163
static void be_reg_d_sub_make(struct m0_be_reg_d *super, struct m0_be_reg_d *sub)
Definition: tx_regmap.c:109
#define M0_ASSERT(cond)
size_t brt_size
Definition: tx_regmap.h:73
M0_INTERNAL void m0_be_reg_area_merger_merge_to(struct m0_be_reg_area_merger *brm, struct m0_be_reg_area *ra)
Definition: tx_regmap.c:894
const struct m0_be_regmap_ops * br_ops
Definition: tx_regmap.h:92
static void be_reg_area_add(void *data, struct m0_be_reg_d *rd)
Definition: tx_regmap.c:671
void(* rmo_del)(void *data, const struct m0_be_reg_d *rd)
Definition: tx_regmap.h:80
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
static void * be_reg_area_alloc(struct m0_be_reg_area *ra, m0_bcount_t size)
Definition: tx_regmap.c:650
M0_INTERNAL void m0_be_reg_area_captured(struct m0_be_reg_area *ra, struct m0_be_tx_credit *captured)
Definition: tx_regmap.c:637
#define ARRAY_ALLOC_NZ(arr, nr)
Definition: tx_regmap.c:205
M0_INTERNAL bool m0_ext_is_partof(const struct m0_ext *super, const struct m0_ext *sub)
Definition: ext.c:62
m0_bcount_t tc_reg_nr
Definition: tx_credit.h:84
static size_t be_rdt_find_i(const struct m0_be_reg_d_tree *rdt, void *addr)
Definition: tx_regmap.c:268
#define M0_POST(cond)
Definition: xcode.h:73
M0_INTERNAL bool m0_be_regmap__invariant(const struct m0_be_regmap *rm)
Definition: tx_regmap.c:401
M0_INTERNAL void m0_be_reg_area_merge_in(struct m0_be_reg_area *ra, struct m0_be_reg_area *src)
Definition: tx_regmap.c:787
M0_INTERNAL size_t m0_be_rdt_size(const struct m0_be_reg_d_tree *rdt)
Definition: tx_regmap.c:241
void(* rmo_cpy)(void *data, const struct m0_be_reg_d *super, const struct m0_be_reg_d *rd)
Definition: tx_regmap.h:81
#define BETXCR_P(c)
Definition: tx_credit.h:113
M0_INTERNAL void m0_be_reg_area_optimize(struct m0_be_reg_area *ra)
Definition: tx_regmap.c:808
struct m0_be_reg_d_tree br_rdt
Definition: tx_regmap.h:91
M0_INTERNAL void m0_be_reg_area_merger_reset(struct m0_be_reg_area_merger *brm)
Definition: tx_regmap.c:852
M0_INTERNAL struct m0_be_reg_d * m0_be_regmap_next(struct m0_be_regmap *rm, struct m0_be_reg_d *prev)
Definition: tx_regmap.c:532
M0_INTERNAL bool m0_be_rdt__invariant(const struct m0_be_reg_d_tree *rdt)
Definition: tx_regmap.c:224
static void * be_reg_d_lb(const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:93
M0_INTERNAL bool m0_ext_is_in(const struct m0_ext *ext, m0_bindex_t index)
Definition: ext.c:48
Definition: seg.h:142
#define PRId64
Definition: types.h:57
M0_INTERNAL bool m0_be_reg_eq(const struct m0_be_reg *r1, const struct m0_be_reg *r2)
Definition: seg.c:410
static int used
Definition: base.c:304
static void be_reg_area_cpy_copy(void *data, const struct m0_be_reg_d *super, const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:681
M0_INTERNAL void m0_be_reg_area_merger_fini(struct m0_be_reg_area_merger *brm)
Definition: tx_regmap.c:846
static void be_reg_area_merger_max_gen_idx(struct m0_be_reg_area_merger *brm, void *addr, m0_bcount_t size, struct m0_be_reg_d *rd_new)
Definition: tx_regmap.c:865
#define m0_forall(var, nr,...)
Definition: misc.h:112
M0_INTERNAL void m0_be_reg_area_uncapture(struct m0_be_reg_area *ra, const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:775
M0_INTERNAL void m0_be_rdt_ins(struct m0_be_reg_d_tree *rdt, const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:328
void(* rmo_split)(void *data, struct m0_be_reg_d *rd, struct m0_be_reg_d *rd_new)
Definition: tx_regmap.h:85
static struct m0_be_reg_d * be_regmap_find_fb(struct m0_be_regmap *rm, const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:406
static bool be_reg_d_are_overlapping(const struct m0_be_reg_d *rd1, const struct m0_be_reg_d *rd2)
Definition: tx_regmap.c:68
static int r[NR]
Definition: thread.c:46
M0_INTERNAL void m0_be_reg_area_prepared(struct m0_be_reg_area *ra, struct m0_be_tx_credit *prepared)
Definition: tx_regmap.c:629
static struct cobfoms_ut * cut
Definition: cob_foms.c:47
static void be_reg_d_arr_insert2(void *arr[2], void *value)
Definition: tx_regmap.c:120
void * rd_buf
Definition: tx_regmap.h:58
m0_bcount_t size
Definition: di.c:39
#define _0C(exp)
Definition: assert.h:311
static int start(struct m0_fom *fom)
Definition: trigger_fom.c:321
static m0_bcount_t be_reg_d_size(const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:104
M0_INTERNAL bool m0_ext_are_overlapping(const struct m0_ext *e0, const struct m0_ext *e1)
Definition: ext.c:53
struct m0_be_reg_area ** brm_reg_areas
Definition: tx_regmap.h:315
M0_INTERNAL bool m0_be_reg_d_is_in(const struct m0_be_reg_d *rd, void *ptr)
Definition: tx_regmap.c:62
#define M0_ASSERT_INFO(cond, fmt,...)
M0_INTERNAL void m0_be_rdt_reset(struct m0_be_reg_d_tree *rdt)
Definition: tx_regmap.c:367
m0_be_reg_area_type
Definition: tx_regmap.h:208
static void * be_reg_d_fb(const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:81
M0_INTERNAL bool m0_be_tx_credit_le(const struct m0_be_tx_credit *c0, const struct m0_be_tx_credit *c1)
Definition: tx_credit.c:98
struct m0_be_regmap bra_map
Definition: tx_regmap.h:237
M0_INTERNAL struct m0_be_reg_d * m0_be_rdt_find(const struct m0_be_reg_d_tree *rdt, void *addr)
Definition: tx_regmap.c:299
int type
Definition: dir.c:1031
struct m0_fom_ops ops
Definition: io_foms.c:623
M0_INTERNAL void m0_be_regmap_fini(struct m0_be_regmap *rm)
Definition: tx_regmap.c:395
void m0_free(void *data)
Definition: memory.c:146
struct m0_be_seg * br_seg
Definition: seg.h:143
void * br_addr
Definition: seg.h:145
struct m0_pdclust_src_addr src
Definition: fd.c:108
static bool be_rdt_check_i(const struct m0_be_reg_d_tree *rdt, void *addr, size_t index)
Definition: tx_regmap.c:247
int32_t rc
Definition: trigger_fop.h:47
static void be_reg_area_del(void *data, const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:676
static void be_regmap_reg_d_cut(struct m0_be_regmap *rm, struct m0_be_reg_d *rd, m0_bcount_t cut_start, m0_bcount_t cut_end)
Definition: tx_regmap.c:412
static bool be_rdt_contains(const struct m0_be_reg_d_tree *rdt, const struct m0_be_reg_d *rd)
Definition: tx_regmap.c:199
#define REGD_EXT(rd)
Definition: tx_regmap.c:45
void(* rmo_cut)(void *data, struct m0_be_reg_d *rd, m0_bcount_t cut_at_start, m0_bcount_t cut_at_end)
Definition: tx_regmap.h:83
M0_INTERNAL void m0_be_regmap_reset(struct m0_be_regmap *rm)
Definition: tx_regmap.c:544
m0_bcount_t tc_reg_size
Definition: tx_credit.h:86
static const struct m0_be_regmap_ops be_reg_area_ops_data_copy
Definition: tx_regmap.c:551