Motr  M0
fd.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2015-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_FD
24 #include "lib/trace.h"
25 
26 #include "fd/fd.h"
27 #include "fd/fd_internal.h"
28 
29 #include "conf/walk.h"
30 #include "conf/obj.h"
31 #include "conf/obj_ops.h" /* M0_CONF_DIRNEXT */
32 #include "conf/dir.h" /* m0_conf_dir_len */
33 #include "conf/diter.h" /* m0_conf_diter */
34 #include "conf/confc.h" /* m0_confc_from_obj */
35 #include "pool/pool_machine.h" /* m0_poolmach */
36 #include "pool/pool.h"
37 
38 #include "fid/fid.h" /* m0_fid_eq m0_fid_set */
39 #include "lib/errno.h" /* EINVAL */
40 #include "lib/memory.h" /* M0_ALLOC_ARR M0_ALLOC_PTR m0_free */
41 #include "lib/arith.h" /* m0_gcd64 m0_enc m0_dec */
42 #include "lib/hash.h" /* m0_hash */
43 
44 /*
45  * A structure that summarizes information about a level
46  * in pver subtree.
47  */
49  uint32_t psi_level;
50  uint32_t psi_nr_objs;
51 };
52 
53 static uint64_t parity_group_size(const struct m0_pdclust_attr *la_attr);
54 
59 static uint64_t fault_tolerant_idx_get(uint64_t idx, uint64_t *children_nr,
60  uint64_t depth);
61 
66 static int symm_tree_attr_get(const struct m0_conf_pver *pv, uint32_t *depth,
67  uint64_t *children_nr);
68 
69 static inline bool fd_tile_invariant(const struct m0_fd_tile *tile);
70 
75 static int tolerance_check(const struct m0_conf_pver *pv,
76  uint64_t *children_nr,
77  uint32_t first_level, uint32_t *failure_level);
78 
82 static void uniform_distribute(uint64_t **units, uint64_t level,
83  uint64_t parent_nr, uint64_t child_nr);
84 
90 static uint64_t units_calc(uint64_t **units, uint64_t level, uint64_t parent_nr,
91  uint64_t child_nr, uint64_t tol);
92 
93 
95 static uint64_t pool_width_calc(uint64_t *children_nr, uint64_t depth);
96 
97 
99 static void permuted_tgt_get(struct m0_pdclust_instance *pi, uint64_t omega,
100  uint64_t *rel_vidx, uint64_t *tgt_idx);
101 
104  uint64_t omega, uint64_t perm_idx,
105  uint64_t *rel_idx);
110 static struct m0_fd_perm_cache *cache_get(struct m0_pdclust_instance *pi,
111  struct m0_fd_tree_node *node);
113 static void fd_permute(struct m0_fd_perm_cache *cache,
114  struct m0_uint128 *seed, struct m0_fid *gfid,
115  uint64_t omega);
120 static void cache_info_update(struct m0_fd_cache_info *cache_info,
121  uint64_t cnt);
122 static bool is_cache_valid(const struct m0_fd_perm_cache *cache,
123  uint64_t omega, const struct m0_fid *gfid);
124 
125 static uint64_t tree2pv_level_conv(uint64_t level, uint64_t tree_depth);
126 
127 static bool is_objv(const struct m0_conf_obj *obj,
128  const struct m0_conf_obj_type *type)
129 {
130  return m0_conf_obj_type(obj) == &M0_CONF_OBJV_TYPE &&
131  (type == NULL ||
133  m0_conf_objv)->cv_real) ==
134  type);
135 }
136 
137 static bool is_objv_site(const struct m0_conf_obj *obj)
138 {
139  return is_objv(obj, &M0_CONF_SITE_TYPE);
140 }
141 
142 static bool is_objv_rack(const struct m0_conf_obj *obj)
143 {
144  return is_objv(obj, &M0_CONF_RACK_TYPE);
145 }
146 
147 static bool is_objv_encl(const struct m0_conf_obj *obj)
148 {
150 }
151 
152 static bool is_objv_ctrl(const struct m0_conf_obj *obj)
153 {
155 }
156 
157 static bool is_objv_disk(const struct m0_conf_obj *obj)
158 {
159  return is_objv(obj, &M0_CONF_DRIVE_TYPE);
160 }
161 
162 static bool
164  is_objv_site,
165  is_objv_rack,
166  is_objv_encl,
167  is_objv_ctrl,
169 };
170 
171 #define pv_for(pv, level, obj, rc) \
172 ({ \
173  struct m0_confc *__confc; \
174  struct m0_conf_pver *__pv = (struct m0_conf_pver *)(pv); \
175  uint64_t __level = (level); \
176  struct m0_conf_diter __it; \
177  struct m0_fid conf_path[M0_CONF_PVER_HEIGHT][M0_CONF_PVER_HEIGHT] = { \
178  { M0_CONF_PVER_SITEVS_FID }, \
179  { M0_CONF_PVER_SITEVS_FID, M0_CONF_SITEV_RACKVS_FID }, \
180  { M0_CONF_PVER_SITEVS_FID, M0_CONF_SITEV_RACKVS_FID, \
181  M0_CONF_RACKV_ENCLVS_FID }, \
182  { M0_CONF_PVER_SITEVS_FID, M0_CONF_SITEV_RACKVS_FID, \
183  M0_CONF_RACKV_ENCLVS_FID, M0_CONF_ENCLV_CTRLVS_FID }, \
184  { M0_CONF_PVER_SITEVS_FID, M0_CONF_SITEV_RACKVS_FID, \
185  M0_CONF_RACKV_ENCLVS_FID, M0_CONF_ENCLV_CTRLVS_FID, \
186  M0_CONF_CTRLV_DRIVEVS_FID }, \
187  }; \
188  __confc = (struct m0_confc *)m0_confc_from_obj(&__pv->pv_obj); \
189  M0_ASSERT(__confc != NULL); \
190  rc = m0_conf__diter_init(&__it, __confc, &__pv->pv_obj, \
191  __level + 1, conf_path[__level]); \
192  while (rc >= 0 && \
193  (rc = m0_conf_diter_next_sync(&__it, \
194  is_obj_at_level[__level])) != \
195  M0_CONF_DIRNEXT) {;} \
196  for (obj = m0_conf_diter_result(&__it); \
197  rc > 0 && (obj = m0_conf_diter_result(&__it)); \
198  rc = m0_conf_diter_next_sync(&__it, \
199  is_obj_at_level[__level])) { \
200 
201 #define pv_endfor } if (rc >= 0) m0_conf_diter_fini(&__it); })
202 
203 
204 M0_INTERNAL int m0_fd__tile_init(struct m0_fd_tile *tile,
205  const struct m0_pdclust_attr *la_attr,
206  uint64_t *children, uint64_t depth)
207 {
208  M0_PRE(tile != NULL && la_attr != NULL && children != NULL);
209  M0_PRE(depth > 0);
210 
211  tile->ft_G = parity_group_size(la_attr);
212  tile->ft_cols = pool_width_calc(children, depth);
213  tile->ft_rows = tile->ft_G / m0_gcd64(tile->ft_G, tile->ft_cols);
214  tile->ft_depth = depth;
215  M0_ALLOC_ARR(tile->ft_cell, tile->ft_rows * tile->ft_cols);
216  if (tile->ft_cell == NULL)
217  return M0_ERR(-ENOMEM);
218  memcpy(tile->ft_child, children,
219  M0_CONF_PVER_HEIGHT * sizeof tile->ft_child[0]);
220 
221  M0_POST(parity_group_size(la_attr) <= tile->ft_cols);
222  return M0_RC(0);
223 }
224 
225 static int objs_of_level_count(struct m0_conf_obj *obj, void *arg)
226 {
227  struct pv_subtree_info *level_info = (struct pv_subtree_info *)arg;
228 
229  if (is_obj_at_level[level_info->psi_level](obj))
230  ++level_info->psi_nr_objs;
231  return M0_CW_CONTINUE;
232 }
233 
234 static int min_children_get(struct m0_conf_obj *obj, void *arg)
235 {
236  struct pv_subtree_info *level_info = (struct pv_subtree_info *)arg;
237  struct m0_conf_objv *objv;
238 
239  if (level_info->psi_level == M0_CONF_PVER_LVL_DRIVES)
240  level_info->psi_nr_objs = 0;
241  else if (is_obj_at_level[level_info->psi_level](obj)) {
242  objv = M0_CONF_CAST(obj, m0_conf_objv);
243  level_info->psi_nr_objs =
244  min_type(uint32_t, level_info->psi_nr_objs,
246  }
247  return M0_CW_CONTINUE;
248 }
249 
250 M0_INTERNAL int m0_fd_tolerance_check(struct m0_conf_pver *pv,
251  uint32_t *failure_level)
252 {
253  uint64_t children_nr[M0_CONF_PVER_HEIGHT];
254  int rc;
255 
256  rc = symm_tree_attr_get(pv, failure_level, children_nr);
257  return M0_RC(rc);
258 }
259 
260 M0_INTERNAL int m0_fd_tile_build(const struct m0_conf_pver *pv,
261  struct m0_pool_version *pool_ver,
262  uint32_t *failure_level)
263 {
264  uint64_t children_nr[M0_CONF_PVER_HEIGHT];
265  int rc;
266 
267  M0_PRE(pv != NULL && pool_ver != NULL && failure_level != NULL);
268 
269  /*
270  * Override the disk level tolerance in pool-version
271  * with layout parameter K.
272  */
275 
276  m0_conf_cache_lock(pv->pv_obj.co_cache);
277  rc = symm_tree_attr_get(pv, failure_level, children_nr);
278  m0_conf_cache_unlock(pv->pv_obj.co_cache);
279  if (rc != 0)
280  return M0_RC(rc);
281  rc = m0_fd__tile_init(&pool_ver->pv_fd_tile, &pv->pv_u.subtree.pvs_attr,
282  children_nr, *failure_level);
283  if (rc != 0)
284  return M0_RC(rc);
286 
287  M0_LEAVE("Symm tree pool width = %d\tFD tree depth = %d",
288  (int)pool_ver->pv_fd_tile.ft_cols, (int)*failure_level);
289  return M0_RC(rc);
290 }
291 
292 static uint64_t tree2pv_level_conv(uint64_t level, uint64_t tree_depth)
293 {
294  M0_PRE(tree_depth < M0_CONF_PVER_HEIGHT);
295  return level + (M0_CONF_PVER_HEIGHT - tree_depth);
296 }
297 
298 static int symm_tree_attr_get(const struct m0_conf_pver *pv, uint32_t *depth,
299  uint64_t *children_nr)
300 {
301  uint32_t pver_level;
302  uint32_t i;
303  uint32_t j;
304  struct pv_subtree_info level_info = {0};
305  /* drop const */
306  struct m0_conf_obj *pver = (struct m0_conf_obj *)&pv->pv_obj;
307  int rc;
308 
309  M0_PRE(pv != NULL && depth != NULL);
310  M0_PRE(m0_conf_cache_is_locked(pv->pv_obj.co_cache));
311 
312  pver_level = M0_CONF_PVER_LVL_SITES;
313  /* Get the first level having a non-zero tolerance. */
314  while (pver_level < M0_CONF_PVER_HEIGHT &&
315  pv->pv_u.subtree.pvs_tolerance[pver_level] == 0)
316  ++pver_level;
317 
318  if (pver_level == M0_CONF_PVER_HEIGHT)
319  pver_level = M0_CONF_PVER_LVL_DRIVES;
320  level_info.psi_level = pver_level;
321  rc = m0_conf_walk(objs_of_level_count, pver, &level_info);
322  if (rc < 0)
323  return M0_RC(rc);
324  *depth = M0_CONF_PVER_HEIGHT - pver_level;
325  children_nr[0] = level_info.psi_nr_objs;
326  M0_LOG(M0_DEBUG, FID_F": pver_level=%u psi_nr_objs=%u",
327  FID_P(&pver->co_id), pver_level, level_info.psi_nr_objs);
328  /*
329  * Extract the attributes of the symmetric tree associated with
330  * the pool version.
331  */
332  for (i = 1, j = pver_level; i < *depth; ++i, ++j) {
333  level_info.psi_nr_objs = UINT32_MAX;
334  level_info.psi_level = j;
335  /*
336  * Calculate the degree of nodes at level 'i' in the
337  * symmetric tree associated with a given pool version.
338  */
339  rc = m0_conf_walk(min_children_get, pver, &level_info);
340  if (rc < 0)
341  return M0_RC(rc);
342  children_nr[i] = level_info.psi_nr_objs;
343  }
344  /*
345  * Total number of leaf nodes can be calculated by reducing elements of
346  * children_nr using multiplication. In order to enable this operation,
347  * children count for leaf-nodes is stored as unity,
348  */
349  children_nr[*depth] = 1;
350  /*
351  * Check if the skeleton tree (a.k.a. symmetric tree) meets the
352  * required tolerance at all the levels.
353  */
354  if (pv->pv_u.subtree.pvs_tolerance[M0_CONF_PVER_LVL_DRIVES] > 0)
355  rc = tolerance_check(pv, children_nr, pver_level, depth);
356  return M0_RC(rc);
357 }
358 
359 /*
360  * We are distributing units of a parity group across tree,
361  * one level at a time. The root receives all `G = N + 2K` units.
362  * uniform_distribute() calculates how many units each node
363  * (conf-tree node, not a cluster node) from subsequent level
364  * will get, when units of each node are distributed _uniformly_
365  * among its children. In uniform distribution if a parent has
366  * `p` units and has `c` children, each child gets at least `p/c`
367  * units, and `r = p % c` children get one extra unit.
368  *
369  * Suppose level L, has tolerance of K_L, then units_calc() calculates
370  * the sum of units held by first K_L nodes of that level, when arranged
371  * in descending order of units they hold. And if this sum is more than
372  * `K` it means K_L failures at that level are not feasible to support.
373  * (Note: tree slightly differs from actual conf tree. It's a subtree of
374  * conf tree. Here two nodes at same level have same number of children.)
375  *
376  * Idea is that we can support K disk failures, when each unit of
377  * a parity group goes to different disk. So at any level we distribute
378  * units uniformly, and check: maximum how many units of a parity group
379  * are lost when K_L nodes of that level are taken down. This shall not
380  * be more than K as then data is not recoverable.
381  *
382  * (Nachiket)
383  */
384 static int tolerance_check(const struct m0_conf_pver *pv, uint64_t *children_nr,
385  uint32_t first_level, uint32_t *failure_level)
386 {
387  int rc = 0;
388  int i;
389  uint64_t G;
390  uint64_t K;
391  uint64_t nodes = 1;
392  uint64_t sum;
393  uint64_t *units[M0_CONF_PVER_HEIGHT];
394  uint32_t depth = *failure_level;
395 
396  M0_ENTRY("pv="FID_F" depth=%u", FID_P(&pv->pv_obj.co_id), depth);
397 
398  G = parity_group_size(&pv->pv_u.subtree.pvs_attr);
399  K = pv->pv_u.subtree.pvs_attr.pa_K;
400 
401  /* total nodes at given level. */
402  for (i = 0; i <= depth; ++i) {
403  M0_ALLOC_ARR(units[i], nodes);
404  if (units[i] == NULL) {
405  *failure_level = i;
406  for (i = i - 1; i >= 0; --i)
407  m0_free(units[i]);
408  return M0_ERR(-ENOMEM);
409  }
410  nodes *= children_nr[i];
411 
412  }
413  units[0][0] = G;
414  for (i = 1, nodes = 1; i < depth; ++i) {
415  /* Distribute units from parents to children. */
416  uniform_distribute(units, i, nodes, children_nr[i - 1]);
417  /* Calculate the sum of units held by top five nodes. */
418  sum = units_calc(units, i, nodes, children_nr[i - 1],
419  pv->pv_u.subtree.pvs_tolerance[first_level +
420  i - 1]);
421  M0_LOG(M0_DEBUG, "%d: sum=%d K=%d children_nr=%d",
422  i, (int)sum, (int)K, (int)children_nr[i - 1]);
423  if (sum > K) {
424  *failure_level = first_level + i - 1;
425  rc = M0_ERR(-EINVAL);
426  break;
427  }
428  nodes *= children_nr[i - 1];
429  }
430  for (i = 0; i <= depth; ++i) {
431  m0_free(units[i]);
432  }
433  return M0_RC(rc);
434 }
435 
436 static void uniform_distribute(uint64_t **units, uint64_t level,
437  uint64_t parent_nr, uint64_t child_nr)
438 {
439  uint64_t pid;
440  uint64_t cid;
441  uint64_t g_cid;
442  uint64_t u_nr;
443 
444  for (pid = 0; pid < parent_nr; ++pid) {
445  u_nr = units[level - 1][pid];
446  for (cid = 0; cid < child_nr; ++cid) {
447  g_cid = pid * child_nr + cid;
448  units[level][g_cid] = (uint64_t)(u_nr / child_nr);
449  }
450  for (cid = 0; cid < (u_nr % child_nr); ++cid) {
451  g_cid = pid * child_nr + cid;
452  units[level][g_cid] += 1;
453  }
454  }
455 }
456 
457 static uint64_t units_calc(uint64_t **units, uint64_t level, uint64_t parent_nr,
458  uint64_t child_nr, uint64_t tol)
459 {
460  uint64_t pid;
461  uint64_t cid;
462  uint64_t sum = 0;
463  uint64_t cnt = 0;
464 
465  for (cid = 0; cnt < tol && cid < child_nr; ++cid) {
466  for (pid = 0; cnt < tol && pid < parent_nr; ++pid) {
467  sum += units[level][pid * child_nr + cid];
468  ++cnt;
469  }
470  }
471  return sum;
472 }
473 
474 static uint64_t parity_group_size(const struct m0_pdclust_attr *la_attr)
475 {
476  return la_attr->pa_N + la_attr->pa_K + la_attr->pa_S;
477 }
478 
479 static uint64_t pool_width_calc(uint64_t *children_nr, uint64_t depth)
480 {
481  M0_PRE(children_nr != NULL);
482  M0_PRE(m0_forall(i, depth, children_nr[i] != 0));
483 
484  return m0_reduce(i, depth, 1, * children_nr[i]);
485 }
486 
487 M0_INTERNAL void m0_fd__tile_populate(struct m0_fd_tile *tile)
488 {
489  uint64_t row;
490  uint64_t col;
491  uint64_t idx;
492  uint64_t fidx;
493  uint64_t tidx;
494  uint64_t *children_nr;
495 
496  M0_PRE(fd_tile_invariant(tile));
497 
498  children_nr = tile->ft_child;
499  for (row = 0; row < tile->ft_rows; ++row) {
500  for (col = 0; col < tile->ft_cols; ++col) {
501  idx = m0_enc(tile->ft_cols, row, col);
502  tidx = fault_tolerant_idx_get(idx, children_nr,
503  tile->ft_depth);
504  tile->ft_cell[idx].ftc_tgt.ta_frame = row;
505  tile->ft_cell[idx].ftc_tgt.ta_obj = tidx;
506  fidx = m0_enc(tile->ft_cols, row, tidx);
507  m0_dec(tile->ft_G, idx,
508  &tile->ft_cell[fidx].ftc_src.sa_group,
509  &tile->ft_cell[fidx].ftc_src.sa_unit);
510  }
511  }
512 }
513 
514 static inline bool fd_tile_invariant(const struct m0_fd_tile *tile)
515 {
516  return _0C(tile != NULL) && _0C(tile->ft_rows > 0) &&
517  _0C(tile->ft_cols > 0) &&
518  _0C(tile->ft_G > 0) &&
519  _0C(tile->ft_cell != NULL);
520 }
521 
522 static uint64_t fault_tolerant_idx_get(uint64_t idx, uint64_t *children_nr,
523  uint64_t depth)
524 {
525  uint64_t i;
526  uint64_t prev;
527  uint64_t r;
528  uint64_t fd_idx[M0_CONF_PVER_HEIGHT];
529  uint64_t tidx;
530 
531  M0_SET0(&fd_idx);
532  for (prev = 1, i = 1; i <= depth; ++i) {
533  r = idx % (prev * children_nr[i - 1]);
534  idx -= r;
535  fd_idx[i] = r / prev;
536  prev *= children_nr[i - 1];
537  }
538  tidx = fd_idx[depth];
539  prev = 1;
540  for (i = depth; i > 0; --i) {
541  tidx += fd_idx[i - 1] * children_nr[i - 1] * prev;
542  prev *= children_nr[i - 1];
543  }
544  return tidx;
545 }
546 
547 M0_INTERNAL void m0_fd_src_to_tgt(const struct m0_fd_tile *tile,
548  const struct m0_pdclust_src_addr *src,
549  struct m0_pdclust_tgt_addr *tgt)
550 {
551  /* A parity group normalized to the first tile. */
552  struct m0_pdclust_src_addr src_norm;
553  uint64_t idx;
554  uint64_t C;
555  uint64_t omega;
556 
557  M0_PRE(tile != NULL && src != NULL && tgt != NULL);
558  M0_PRE(fd_tile_invariant(tile));
559  C = tile->ft_rows * tile->ft_cols / tile->ft_G;
560 
561  /* Get normalized location. */
562  m0_dec(C, src->sa_group, &omega, &src_norm.sa_group);
563  src_norm.sa_unit = src->sa_unit;
564  M0_ASSERT(src_norm.sa_group < C);
565  idx = m0_enc(tile->ft_G, src_norm.sa_group, src_norm.sa_unit);
566  *tgt = tile->ft_cell[idx].ftc_tgt;
567  /* Denormalize the frame location. */
568  tgt->ta_frame += omega * tile->ft_rows;
569 }
570 
571 M0_INTERNAL void m0_fd_tgt_to_src(const struct m0_fd_tile *tile,
572  const struct m0_pdclust_tgt_addr *tgt,
573  struct m0_pdclust_src_addr *src)
574 {
575  struct m0_pdclust_tgt_addr tgt_norm;
576  uint64_t idx;
577  uint64_t C;
578  uint64_t omega;
579 
580  M0_PRE(tile != NULL && src != NULL && tgt != NULL);
581  M0_PRE(fd_tile_invariant(tile));
582 
583  C = (tile->ft_rows * tile->ft_cols) / tile->ft_G;
584  m0_dec(tile->ft_rows, tgt->ta_frame, &omega, &tgt_norm.ta_frame);
585  idx = m0_enc(tile->ft_cols, tgt_norm.ta_frame, tgt->ta_obj);
586  *src = tile->ft_cell[idx].ftc_src;
587  src->sa_group += omega * C;
588 }
589 
590 M0_INTERNAL void m0_fd_tile_destroy(struct m0_fd_tile *tile)
591 {
592  M0_PRE(tile != NULL);
593 
594  m0_free0(&tile->ft_cell);
595  M0_SET0(&tile);
596 }
597 
598 M0_INTERNAL int m0_fd_tree_build(const struct m0_conf_pver *pv,
599  struct m0_fd_tree *tree)
600 {
601  int rc;
602  uint64_t children_nr[M0_CONF_PVER_HEIGHT];
603  uint32_t depth;
604  uint32_t level;
605 
606  M0_PRE(pv != NULL && tree != NULL);
607 
608  m0_conf_cache_lock(pv->pv_obj.co_cache);
609  rc = symm_tree_attr_get(pv, &depth, children_nr);
610  m0_conf_cache_unlock(pv->pv_obj.co_cache);
611  if (rc != 0)
612  return M0_RC(rc);
613  tree->ft_depth = depth;
614  tree->ft_cnt = 0;
615  tree->ft_root = m0_alloc(sizeof tree->ft_root[0]);
616  if (tree->ft_root == NULL)
617  return M0_ERR(-ENOMEM);
618  rc = m0_fd__tree_root_create(tree, children_nr[0]);
619  if (rc != 0)
620  return M0_RC(rc);
621  for (level = 0; level < tree->ft_depth; ++level) {
623  if (rc != 0)
624  return M0_RC(rc);
625  }
626  rc = m0_fd__perm_cache_build(tree);
627  return M0_RC(rc);
628 }
629 
630 M0_INTERNAL int m0_fd__tree_level_populate(const struct m0_conf_pver *pv,
631  struct m0_fd_tree *tree,
632  uint32_t level)
633 {
634  struct m0_conf_objv *objv;
635  struct m0_conf_obj *obj;
636  struct m0_fd__tree_cursor cursor;
637  struct m0_fd_tree_node **node;
638  uint64_t children_nr;
639  uint64_t pv_level;
640  int rc;
641 
642  M0_PRE(pv != NULL && tree != NULL);
643  M0_PRE(tree->ft_root != NULL);
644  M0_PRE(level < tree->ft_depth);
645 
646  /* Initialize the cursor for failure-domain tree. */
647  rc = m0_fd__tree_cursor_init(&cursor, tree, level + 1);
648  if (rc != 0)
649  return M0_RC(rc);
650  pv_level = tree2pv_level_conv(level, tree->ft_depth);
651  M0_LOG(M0_DEBUG, "depth=%u level=%u pv_level=%u",
652  (unsigned)tree->ft_depth, level, (unsigned)pv_level);
653  pv_for (pv, pv_level, obj, rc) {
655  M0_LOG(M0_DEBUG, FID_F, FID_P(&obj->co_id));
656  objv = M0_CONF_CAST(obj, m0_conf_objv);
657  children_nr = level < tree->ft_depth - 1 ?
658  m0_conf_dir_len(objv->cv_children) : 0;
659  node = m0_fd__tree_cursor_get(&cursor);
660  *node = m0_alloc(sizeof node[0][0]);
661  if (*node == NULL)
662  goto rewind;
663  rc = m0_fd__tree_node_init(tree, *node, children_nr, &cursor);
664  if (rc != 0)
665  goto rewind;
666  m0_fd__tree_cursor_next(&cursor);
667  } pv_endfor;
668  M0_ASSERT(ergo(rc == 0, !m0_fd__tree_cursor_next(&cursor)));
669 
670  return M0_RC(rc);
671 rewind:
672  if (*node != NULL) {
673  m0_fd__tree_node_fini(tree, *node);
674  m0_free(*node);
675  *node = NULL;
676  }
677  --cursor.ftc_child_abs_idx;
678  tree->ft_depth = cursor.ftc_child_abs_idx > -1 ? cursor.ftc_depth :
679  cursor.ftc_depth - 1;
680  return M0_ERR(rc);
681 }
682 
683 M0_INTERNAL int m0_fd__perm_cache_build(struct m0_fd_tree *tree)
684 {
685  struct m0_fd__tree_cursor cursor;
686  struct m0_fd_tree_node *node;
687  uint64_t children_nr;
688  uint64_t *cache_len;
689  uint64_t *cache_info;
690  uint64_t level;
691  int rc;
692 
693  M0_ALLOC_ARR(cache_info, tree->ft_cnt);
694  if (cache_info == NULL)
695  return M0_ERR(-ENOMEM);
696  tree->ft_cache_info.fci_info = cache_info;
697  tree->ft_cache_info.fci_nr = 0;
698  for (level = 0; level < tree->ft_depth; ++level) {
699  rc = m0_fd__tree_cursor_init(&cursor, tree, level);
700  if (rc != 0) {
702  return M0_RC(rc);
703  }
704  do {
705  node = *(m0_fd__tree_cursor_get(&cursor));
706  children_nr = node->ftn_child_nr;
707  cache_info_update(&tree->ft_cache_info, children_nr);
708  } while (m0_fd__tree_cursor_next(&cursor));
709  }
710  m0_array_sort(cache_info, tree->ft_cache_info.fci_nr);
711  /*
712  * Since tree->ft_cnt is likely to be much greater than actual length
713  * of tree->ft_cache_info.fci_info, we reallocate
714  * tree->ft_cache_info.fci_info once the actual length is obtained.
715  */
716  M0_ALLOC_ARR(cache_len, tree->ft_cache_info.fci_nr);
717  if (cache_len == NULL) {
719  return M0_ERR(-ENOMEM);
720  }
721  memcpy(cache_len, tree->ft_cache_info.fci_info,
722  tree->ft_cache_info.fci_nr * sizeof cache_len[0]);
724  tree->ft_cache_info.fci_info = cache_len;
725  return M0_RC(0);
726 }
727 
728 static void cache_info_update(struct m0_fd_cache_info *cache_info, uint64_t cnt)
729 {
730  uint64_t i;
731 
732  for (i = 0; i < cache_info->fci_nr; ++i)
733  if (cache_info->fci_info[i] == cnt)
734  break;
735  if (i == cache_info->fci_nr) {
736  cache_info->fci_info[i] = cnt;
737  ++cache_info->fci_nr;
738  }
739 }
740 
742  uint64_t len)
743 {
744  struct m0_uint128 seed;
745  struct m0_fid gfid;
746  uint64_t *permute;
747  uint64_t *inverse;
748  uint64_t *lcode;
749 
750 
751  M0_PRE(cache != NULL);
752 
753  M0_SET0(cache);
754  cache->fpc_len = len;
755  M0_ALLOC_ARR(permute, len);
756  if (permute == NULL)
757  goto err;
758 
759  cache->fpc_permute = permute;
760  M0_ALLOC_ARR(inverse, len);
761  if (inverse == NULL)
762  goto err;
763 
764  cache->fpc_inverse = inverse;
765  M0_ALLOC_ARR(lcode, len);
766  if (lcode == NULL)
767  goto err;
768 
769  cache->fpc_lcode = lcode;
770  /* Initialize the permutation present in the cache. */
771  cache->fpc_omega = ~(uint64_t)0;
772  m0_fid_set(&cache->fpc_gfid, ~(uint64_t)0, ~(uint64_t)0);
774  m0_fid_set(&gfid, 0, 0);
775  fd_permute(cache, &seed, &gfid, 0);
776  return M0_RC(0);
777 err:
778  m0_free0(&cache->fpc_permute);
779  m0_free0(&cache->fpc_inverse);
780  m0_free0(&cache->fpc_lcode);
781  M0_SET0(cache);
782  return M0_ERR(-ENOMEM);
783 }
784 
785 M0_INTERNAL void m0_fd_tree_destroy(struct m0_fd_tree *tree)
786 {
787  struct m0_fd__tree_cursor cursor;
788  struct m0_fd_tree_node **node;
789  uint16_t depth;
790  int32_t i;
791  int rc;
792 
793  depth = tree->ft_depth;
794  for (i = depth; i > 0; --i) {
795  rc = m0_fd__tree_cursor_init(&cursor, tree, i);
796  M0_ASSERT(rc == 0);
797  do {
798  node = m0_fd__tree_cursor_get(&cursor);
799  /*
800  * This condition will hit when
801  * m0_fd__tree_level_populate() has got terminated
802  * intermittently.
803  */
804  if (*node == NULL)
805  break;
806  m0_fd__tree_node_fini(tree, *node);
807  m0_free0(node);
808  } while (m0_fd__tree_cursor_next(&cursor));
809  }
810  if (tree->ft_root != NULL)
811  m0_fd__tree_node_fini(tree, tree->ft_root);
813  m0_free0(&tree->ft_root);
814  M0_POST(tree->ft_cnt == 0);
815  M0_SET0(tree);
816 }
817 
818 M0_INTERNAL void m0_fd__perm_cache_destroy(struct m0_fd_tree *tree)
819 {
820  M0_PRE(tree != NULL);
822  tree->ft_cache_info.fci_nr = 0;
823 }
824 
826 {
827  m0_free0(&cache->fpc_lcode);
828  m0_free0(&cache->fpc_permute);
829  m0_free0(&cache->fpc_inverse);
830 }
831 
832 static struct m0_pool_version *
833 pool_ver_get(const struct m0_pdclust_instance *pd_instance)
834 {
835  return pd_instance->pi_base.li_l->l_pver;
836 }
837 
838 M0_INTERNAL void m0_fd_fwd_map(struct m0_pdclust_instance *pi,
839  const struct m0_pdclust_src_addr *src,
840  struct m0_pdclust_tgt_addr *tgt)
841 {
842  struct m0_fd_tile *tile;
843  struct m0_pool_version *pver;
844  struct m0_pdclust_src_addr src_base;
845  uint64_t rel_vidx[M0_CONF_PVER_HEIGHT];
846  uint64_t omega;
847  uint64_t children;
848  uint64_t C;
849  uint64_t tree_depth;
850  uint64_t i;
851  uint64_t vidx;
852 
853  M0_PRE(pi != NULL);
854  M0_PRE(src != NULL && tgt != NULL);
855 
856  pver = pool_ver_get(pi);
857  tile = &pver->pv_fd_tile;
858  M0_ASSERT(tile != NULL);
859  /* Get location in fault-tolerant permutation. */
860  m0_fd_src_to_tgt(tile, src, tgt);
861  tree_depth = pver->pv_fd_tile.ft_depth;
862  for (i = 1, children = 1; i < tree_depth; ++i) {
863  children *= tile->ft_child[i];
864  }
865  for (i = 1, vidx = tgt->ta_obj; i <= tree_depth; ++i) {
866  rel_vidx[i] = vidx / children;
867  vidx %= children;
868  children /= tile->ft_child[i];
869  }
870  M0_ASSERT(tile->ft_G != 0);
871  C = tile->ft_rows * tile->ft_cols / tile->ft_G;
872  m0_dec(C, src->sa_group, &omega, &src_base.sa_group);
873  permuted_tgt_get(pi, omega, rel_vidx, &tgt->ta_obj);
874 }
875 
876 static void permuted_tgt_get(struct m0_pdclust_instance *pi, uint64_t omega,
877  uint64_t *rel_vidx, uint64_t *tgt_idx)
878 {
879  struct m0_fd_tree *tree;
880  struct m0_fd_perm_cache *cache;
881  struct m0_pool_version *pver;
882  struct m0_fd_tree_node *node;
883  struct m0_fd__tree_cursor cursor = {};
884  struct m0_pdclust_attr *attr;
885  struct m0_fid *gfid;
886  uint64_t depth;
887  uint64_t perm_idx;
888  uint64_t rel_idx;
889  int rc;
890 
891  pver = pool_ver_get(pi);
892  tree = &pver->pv_fd_tree;
893  node = tree->ft_root;
894  gfid = &pi->pi_base.li_gfid;
896 
897  for (depth = 1; depth <= tree->ft_depth; ++depth) {
898  rel_idx = rel_vidx[depth];
899  cache = cache_get(pi, node);
900  fd_permute(cache, &attr->pa_seed, gfid, omega);
901  M0_ASSERT(rel_idx < cache->fpc_len);
902  perm_idx = cache->fpc_permute[rel_idx];
903  rc = m0_fd__tree_cursor_init_at(&cursor, tree, node, perm_idx);
904  M0_ASSERT(rc == 0);
905  node = *(m0_fd__tree_cursor_get(&cursor));
906  M0_ASSERT(node != NULL);
907  }
908  *tgt_idx = node->ftn_abs_idx;
909 }
910 
912  struct m0_fd_tree_node *node)
913 {
914  uint64_t i;
915  uint64_t cache_len;
916 
917  cache_len = node->ftn_child_nr;
918  for (i = 0; i < pi->pi_cache_nr; ++i)
919  if (pi->pi_perm_cache[i].fpc_len == cache_len)
920  return &pi->pi_perm_cache[i];
921  return NULL;
922 }
923 
924 static void fd_permute(struct m0_fd_perm_cache *cache,
925  struct m0_uint128 *seed, struct m0_fid *gfid,
926  uint64_t omega)
927 {
928  uint32_t i;
929  uint64_t rstate;
930 
931 
932  if (!is_cache_valid(cache, omega, gfid)) {
933  /* Initialise columns array that will be permuted. */
934  for (i = 0; i < cache->fpc_len; ++i)
935  cache->fpc_permute[i] = i;
936 
937  /* Initialise PRNG. */
938  rstate = m0_hash(seed->u_hi + gfid->f_key) ^
939  m0_hash(seed->u_lo + omega + gfid->f_container);
940 
941  /* Generate permutation number in lexicographic ordering. */
942  for (i = 0; i < cache->fpc_len - 1; ++i)
943  cache->fpc_lcode[i] = m0_rnd(cache->fpc_len - i,
944  &rstate);
945  /* Apply the permutation. */
946  m0_permute(cache->fpc_len, cache->fpc_lcode,
947  cache->fpc_permute, cache->fpc_inverse);
948  cache->fpc_omega = omega;
949  cache->fpc_gfid = *gfid;
950  }
951 }
952 
953 static bool is_cache_valid(const struct m0_fd_perm_cache *cache,
954  uint64_t omega, const struct m0_fid *gfid)
955 {
956  return cache->fpc_omega == omega && m0_fid_eq(&cache->fpc_gfid, gfid);
957 }
958 
959 M0_INTERNAL void m0_fd_bwd_map(struct m0_pdclust_instance *pi,
960  const struct m0_pdclust_tgt_addr *tgt,
961  struct m0_pdclust_src_addr *src)
962 {
963  struct m0_pdclust_tgt_addr tgt_ft;
964  struct m0_pool_version *pver;
965  struct m0_fd_tile *tile;
966  uint64_t omega;
967  uint64_t children;
968  uint64_t i;
969  uint64_t vidx;
970  uint64_t tree_depth;
971  uint64_t rel_idx[M0_CONF_PVER_HEIGHT];
972 
973  M0_PRE(pi != NULL);
974  M0_PRE(tgt != NULL && src != NULL);
975 
976  pver = pool_ver_get(pi);
977  tile = &pver->pv_fd_tile;
978  m0_dec(pver->pv_fd_tile.ft_rows, tgt->ta_frame, &omega,
979  &tgt_ft.ta_frame);
980  inverse_permuted_idx_get(pi, omega, tgt->ta_obj, rel_idx);
981  tree_depth = pver->pv_fd_tree.ft_depth;
982  for (i = 1, children = 1; i < tree_depth; ++i) {
983  children *= tile->ft_child[i];
984  }
985  for (i = 1, vidx = 0; i <= tree_depth; ++i) {
986  vidx += rel_idx[i] * children;
987  if (rel_idx[i] >= tile->ft_child[i - 1])
988  break;
989  children /= tile->ft_child[i];
990  }
991  if (i > tree_depth) {
992  tgt_ft.ta_frame = tgt->ta_frame;
993  tgt_ft.ta_obj = vidx;
994  m0_fd_tgt_to_src(&pver->pv_fd_tile, &tgt_ft, src);
995  } else {
996  /* Input target and frame are unmapped. */
999  }
1000 }
1001 
1003  uint64_t omega, uint64_t perm_idx,
1004  uint64_t *rel_idx)
1005 {
1006  struct m0_fd_tree *tree;
1007  struct m0_pool_version *pver;
1008  struct m0_fd__tree_cursor cursor;
1009  struct m0_fd_perm_cache *cache;
1010  struct m0_fd_tree_node *node;
1011  struct m0_pdclust_attr *attr;
1012  struct m0_fid *gfid;
1013  int rc;
1014  int depth;
1015 
1016  pver = pool_ver_get(pi);
1017  tree = &pver->pv_fd_tree;
1018  gfid = &pi->pi_base.li_gfid;
1019  attr = &pool_ver_get(pi)->pv_attr;
1020 
1021  rc = m0_fd__tree_cursor_init(&cursor, tree, tree->ft_depth);
1022  M0_ASSERT(rc == 0);
1023  while (cursor.ftc_child_abs_idx < perm_idx &&
1024  m0_fd__tree_cursor_next(&cursor));
1025  M0_ASSERT(cursor.ftc_child_abs_idx == perm_idx);
1026  perm_idx = cursor.ftc_child_idx;
1027  node = cursor.ftc_node;
1028  M0_ASSERT(node != NULL);
1029  for (depth = tree->ft_depth; depth > 0; --depth) {
1030  cache = cache_get(pi, node);
1031  fd_permute(cache, &attr->pa_seed, gfid, omega);
1032  rel_idx[depth] = cache->fpc_inverse[perm_idx];
1033  perm_idx = node->ftn_rel_idx;
1034  node = node->ftn_parent;
1035  }
1036 }
1037 
1038 #undef M0_TRACE_SUBSYSTEM
const struct m0_conf_obj_type * m0_conf_obj_type(const struct m0_conf_obj *obj)
Definition: obj.c:363
Definition: beck.c:235
M0_INTERNAL int m0_fd_tile_build(const struct m0_conf_pver *pv, struct m0_pool_version *pool_ver, uint32_t *failure_level)
Definition: fd.c:260
#define M0_PRE(cond)
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
struct m0_fd_tile_cell * ft_cell
Definition: fd.h:140
const struct m0_conf_obj_type M0_CONF_OBJV_TYPE
Definition: objv.c:151
uint64_t ft_G
Definition: fd.h:134
static uint64_t units_calc(uint64_t **units, uint64_t level, uint64_t parent_nr, uint64_t child_nr, uint64_t tol)
Definition: fd.c:457
struct m0_layout * li_l
Definition: layout.h:590
uint64_t sa_group
Definition: pdclust.h:241
#define NULL
Definition: misc.h:38
struct m0_pool_version * l_pver
Definition: layout.h:261
static struct m0_fd_perm_cache * cache_get(struct m0_pdclust_instance *pi, struct m0_fd_tree_node *node)
Definition: fd.c:911
#define ergo(a, b)
Definition: misc.h:293
M0_INTERNAL int m0_fd__tree_level_populate(const struct m0_conf_pver *pv, struct m0_fd_tree *tree, uint32_t level)
Definition: fd.c:630
M0_INTERNAL void m0_fd_perm_cache_fini(struct m0_fd_perm_cache *cache)
Definition: fd.c:825
const struct m0_conf_obj_type M0_CONF_SITE_TYPE
Definition: site.c:121
static bool is_objv_ctrl(const struct m0_conf_obj *obj)
Definition: fd.c:152
M0_INTERNAL int m0_fd_tolerance_check(struct m0_conf_pver *pv, uint32_t *failure_level)
Definition: fd.c:250
uint32_t pa_N
Definition: pdclust.h:104
struct m0_pool_version * pv
Definition: dir.c:629
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
enum m0_trace_level level
Definition: trace.c:111
uint32_t pv_fd_tol_vec[M0_CONF_PVER_HEIGHT]
Definition: pool.h:141
static bool is_objv(const struct m0_conf_obj *obj, const struct m0_conf_obj_type *type)
Definition: fd.c:127
uint32_t psi_level
Definition: fd.c:49
static struct m0_pool_version * pool_ver_get(const struct m0_pdclust_instance *pd_instance)
Definition: fd.c:833
static struct net_test_cmd_node * node
Definition: commands.c:72
struct m0_layout_instance pi_base
Definition: pdclust.h:173
M0_INTERNAL void m0_uint128_init(struct m0_uint128 *u128, const char *magic)
Definition: misc.c:150
uint32_t pa_K
Definition: pdclust.h:107
struct m0_pool_version pool_ver
Definition: fd.c:111
static void inverse_permuted_idx_get(struct m0_pdclust_instance *pi, uint64_t omega, uint64_t perm_idx, uint64_t *rel_idx)
Definition: fd.c:1002
uint16_t ft_depth
Definition: fd.h:201
uint64_t ta_obj
Definition: pdclust.h:256
static bool is_objv_encl(const struct m0_conf_obj *obj)
Definition: fd.c:147
static int sum
Definition: rwlock.c:53
int32_t ftc_child_abs_idx
Definition: fd_internal.h:41
M0_INTERNAL int m0_fd__tree_cursor_next(struct m0_fd__tree_cursor *cursor)
Definition: fd_tree.c:142
M0_INTERNAL void m0_permute(uint64_t n, uint64_t *k, uint64_t *s, uint64_t *r)
Definition: misc.c:288
#define min_type(t, a, b)
Definition: arith.h:76
uint32_t pa_S
Definition: pdclust.h:110
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL int m0_fd_perm_cache_init(struct m0_fd_perm_cache *cache, uint64_t len)
Definition: fd.c:741
static int symm_tree_attr_get(const struct m0_conf_pver *pv, uint32_t *depth, uint64_t *children_nr)
Definition: fd.c:298
M0_INTERNAL int m0_fd__tree_root_create(struct m0_fd_tree *tree, uint64_t root_children)
Definition: fd_tree.c:181
#define UINT32_MAX
Definition: types.h:41
static struct foo * obj
Definition: tlist.c:302
const struct m0_conf_obj_type M0_CONF_CONTROLLER_TYPE
Definition: controller.c:131
static void uniform_distribute(uint64_t **units, uint64_t level, uint64_t parent_nr, uint64_t child_nr)
Definition: fd.c:436
uint64_t ft_child[M0_CONF_PVER_HEIGHT]
Definition: fd.h:138
return M0_RC(rc)
static int tolerance_check(const struct m0_conf_pver *pv, uint64_t *children_nr, uint32_t first_level, uint32_t *failure_level)
Definition: fd.c:384
#define M0_ENTRY(...)
Definition: trace.h:170
M0_INTERNAL void m0_fd_tgt_to_src(const struct m0_fd_tile *tile, const struct m0_pdclust_tgt_addr *tgt, struct m0_pdclust_src_addr *src)
Definition: fd.c:571
int i
Definition: dir.c:1033
M0_INTERNAL int m0_fd_tree_build(const struct m0_conf_pver *pv, struct m0_fd_tree *tree)
Definition: fd.c:598
static unsigned depth
Definition: base.c:377
static uint64_t tree2pv_level_conv(uint64_t level, uint64_t tree_depth)
Definition: fd.c:292
M0_INTERNAL void m0_fid_set(struct m0_fid *fid, uint64_t container, uint64_t key)
Definition: fid.c:116
M0_INTERNAL int m0_conf_walk(int(*fn)(struct m0_conf_obj *obj, void *args), struct m0_conf_obj *origin, void *args)
Definition: walk.c:49
return M0_ERR(-EOPNOTSUPP)
uint64_t ft_cols
Definition: fd.h:132
static void permuted_tgt_get(struct m0_pdclust_instance *pi, uint64_t omega, uint64_t *rel_vidx, uint64_t *tgt_idx)
Definition: fd.c:876
uint32_t psi_nr_objs
Definition: fd.c:50
M0_INTERNAL uint64_t m0_rnd(uint64_t max, uint64_t *seed)
Definition: misc.c:115
static bool is_objv_rack(const struct m0_conf_obj *obj)
Definition: fd.c:142
Definition: cnt.h:36
static void cache_info_update(struct m0_fd_cache_info *cache_info, uint64_t cnt)
Definition: fd.c:728
const struct m0_conf_obj_type M0_CONF_ENCLOSURE_TYPE
Definition: enclosure.c:140
static void attr(struct m0_addb2__context *ctx, const uint64_t *v, char *buf)
Definition: dump.c:949
uint64_t ft_depth
Definition: fd.h:136
#define m0_free0(pptr)
Definition: memory.h:77
#define M0_ASSERT(cond)
uint16_t ftc_depth
Definition: fd_internal.h:35
#define M0_PDCLUST_SEED
Definition: pdclust.h:76
struct m0_fid pver
Definition: idx_dix.c:74
static struct net_test_cmd_node nodes[NTC_MULTIPLE_NODES]
Definition: commands.c:74
M0_INTERNAL void m0_fd_tree_destroy(struct m0_fd_tree *tree)
Definition: fd.c:785
uint64_t ta_frame
Definition: pdclust.h:254
struct m0_fd_tree_node * ftc_node
Definition: fd_internal.h:37
struct m0_fd_tile pv_fd_tile
Definition: pool.h:136
static uint64_t fault_tolerant_idx_get(uint64_t idx, uint64_t *children_nr, uint64_t depth)
Definition: fd.c:522
struct m0_fd_cache_info ft_cache_info
Definition: fd.h:209
#define pv_endfor
Definition: fd.c:201
static uint32_t m0_conf_dir_len(const struct m0_conf_dir *dir)
Definition: dir.h:59
uint32_t fpc_len
Definition: fd.h:156
static int min_children_get(struct m0_conf_obj *obj, void *arg)
Definition: fd.c:234
void * m0_alloc(size_t size)
Definition: memory.c:126
M0_INTERNAL bool m0_conf_cache_is_locked(const struct m0_conf_cache *cache)
Definition: cache.c:60
struct m0_pdclust_instance pi
Definition: fd.c:107
uint64_t f_container
Definition: fid.h:39
#define M0_POST(cond)
const struct m0_conf_obj_type M0_CONF_DRIVE_TYPE
Definition: drive.c:108
uint64_t fci_nr
Definition: fd.h:188
static bool is_objv_disk(const struct m0_conf_obj *obj)
Definition: fd.c:157
#define UINT64_MAX
Definition: types.h:44
M0_INTERNAL void m0_fd_bwd_map(struct m0_pdclust_instance *pi, const struct m0_pdclust_tgt_addr *tgt, struct m0_pdclust_src_addr *src)
Definition: fd.c:959
#define pv_for(pv, level, obj, rc)
Definition: fd.c:171
#define M0_CONF_CAST(ptr, type)
Definition: obj.h:780
int32_t ftc_child_idx
Definition: fd_internal.h:39
#define FID_P(f)
Definition: fid.h:77
M0_INTERNAL uint64_t m0_gcd64(uint64_t p, uint64_t q)
Definition: misc.c:128
static int objs_of_level_count(struct m0_conf_obj *obj, void *arg)
Definition: fd.c:225
struct m0_fid li_gfid
Definition: layout.h:587
uint64_t ft_cnt
Definition: fd.h:207
M0_INTERNAL bool m0_fid_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: fid.c:164
#define m0_forall(var, nr,...)
Definition: misc.h:112
uint64_t sa_unit
Definition: pdclust.h:243
static uint64_t m0_enc(uint64_t width, uint64_t row, uint64_t column)
Definition: arith.h:245
struct m0_pdclust_tgt_addr tgt
Definition: fd.c:110
struct m0_fd_tree_node * ft_root
Definition: fd.h:203
static bool fd_tile_invariant(const struct m0_fd_tile *tile)
Definition: fd.c:514
static void m0_dec(uint64_t width, uint64_t pos, uint64_t *row, uint64_t *column)
Definition: arith.h:256
static bool(* is_obj_at_level[M0_CONF_PVER_HEIGHT])(const struct m0_conf_obj *obj)
Definition: fd.c:163
uint64_t pi_cache_nr
Definition: pdclust.h:220
Definition: fid.h:38
struct m0_fd_perm_cache * pi_perm_cache
Definition: pdclust.h:221
uint64_t f_key
Definition: fid.h:40
static int r[NR]
Definition: thread.c:46
M0_INTERNAL int m0_fd__tree_node_init(struct m0_fd_tree *tree, struct m0_fd_tree_node *node, uint16_t child_nr, const struct m0_fd__tree_cursor *cursor)
Definition: fd_tree.c:31
static bool is_cache_valid(const struct m0_fd_perm_cache *cache, uint64_t omega, const struct m0_fid *gfid)
Definition: fd.c:953
static void permute(uint32_t n, uint32_t *k, uint32_t *s, uint32_t *r)
Definition: pdclust.c:611
#define _0C(exp)
Definition: assert.h:311
M0_INTERNAL int m0_fd__perm_cache_build(struct m0_fd_tree *tree)
Definition: fd.c:683
M0_INTERNAL void m0_fd__tree_node_fini(struct m0_fd_tree *tree, struct m0_fd_tree_node *node)
Definition: fd_tree.c:53
struct m0_conf_dir * cv_children
Definition: obj.h:545
uint64_t * fci_info
Definition: fd.h:196
static uint64_t parity_group_size(const struct m0_pdclust_attr *la_attr)
Definition: fd.c:474
#define C(v)
M0_INTERNAL void m0_fd_tile_destroy(struct m0_fd_tile *tile)
Definition: fd.c:590
M0_INTERNAL void m0_fd__tile_populate(struct m0_fd_tile *tile)
Definition: fd.c:487
Definition: fd.h:199
M0_INTERNAL void m0_fd_src_to_tgt(const struct m0_fd_tile *tile, const struct m0_pdclust_src_addr *src, struct m0_pdclust_tgt_addr *tgt)
Definition: fd.c:547
M0_INTERNAL int m0_fd__tile_init(struct m0_fd_tile *tile, const struct m0_pdclust_attr *la_attr, uint64_t *children, uint64_t depth)
Definition: fd.c:204
M0_INTERNAL void m0_array_sort(uint64_t *arr, uint64_t arr_len)
Definition: misc.c:325
int type
Definition: dir.c:1031
Definition: fd.h:126
struct m0_fid gfid
Definition: dir.c:626
M0_INTERNAL void m0_fd_fwd_map(struct m0_pdclust_instance *pi, const struct m0_pdclust_src_addr *src, struct m0_pdclust_tgt_addr *tgt)
Definition: fd.c:838
M0_INTERNAL void m0_conf_cache_lock(struct m0_conf_cache *cache)
Definition: cache.c:50
Definition: module.c:67
void m0_free(void *data)
Definition: memory.c:146
struct m0_pdclust_tgt_addr ftc_tgt
Definition: fd.h:118
static void fd_permute(struct m0_fd_perm_cache *cache, struct m0_uint128 *seed, struct m0_fid *gfid, uint64_t omega)
Definition: fd.c:924
struct m0_pdclust_attr pv_attr
Definition: pool.h:122
M0_INTERNAL int m0_fd__tree_cursor_init_at(struct m0_fd__tree_cursor *cursor, const struct m0_fd_tree *tree, const struct m0_fd_tree_node *node, uint32_t child_idx)
Definition: fd_tree.c:97
struct m0_pdclust_src_addr src
Definition: fd.c:108
struct m0_pdclust_src_addr ftc_src
Definition: fd.h:123
int32_t rc
Definition: trigger_fop.h:47
uint64_t ft_rows
Definition: fd.h:128
static bool is_objv_site(const struct m0_conf_obj *obj)
Definition: fd.c:137
M0_INTERNAL int m0_fd__tree_cursor_init(struct m0_fd__tree_cursor *cursor, const struct m0_fd_tree *tree, uint16_t depth)
Definition: fd_tree.c:62
M0_INTERNAL void m0_conf_cache_unlock(struct m0_conf_cache *cache)
Definition: cache.c:55
const struct m0_conf_obj_type M0_CONF_RACK_TYPE
Definition: rack.c:124
M0_INTERNAL struct m0_fd_tree_node ** m0_fd__tree_cursor_get(struct m0_fd__tree_cursor *cursor)
Definition: fd_tree.c:136
#define FID_F
Definition: fid.h:75
M0_INTERNAL void m0_fd__perm_cache_destroy(struct m0_fd_tree *tree)
Definition: fd.c:818
M0_INTERNAL uint64_t m0_hash(uint64_t x)
Definition: hash.c:279
static uint64_t pool_width_calc(uint64_t *children_nr, uint64_t depth)
Definition: fd.c:479