Motr  M0
pdclust.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2012-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 
85 #include "lib/errno.h"
86 #include "lib/memory.h" /* M0_ALLOC_PTR(), M0_ALLOC_ARR(), m0_free() */
87 #include "lib/misc.h" /* M0_IN() */
88 #include "lib/vec.h" /* m0_bufvec_cursor_step(), m0_bufvec_cursor_addr() */
89 #include "lib/arith.h" /* m0_rnd() */
90 #include "lib/misc.h" /* m0_forall */
91 #include "lib/hash.h" /* m0_hash */
92 #include "lib/bob.h"
93 #include "lib/finject.h"
94 
95 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_LAYOUT
96 #include "lib/trace.h"
97 
98 #include "motr/magic.h"
99 #include "layout/layout_internal.h"
100 #include "layout/pdclust.h"
101 #include "pool/pool.h" /* m0_pool_version */
102 #include "fd/fd_internal.h"
103 #include "fd/fd.h" /* m0_fd_perm_cache_init m0_fd_perm_cache_fini */
104 
105 static const struct m0_bob_type pdclust_bob = {
106  .bt_name = "pdclust",
107  .bt_magix_offset = offsetof(struct m0_pdclust_layout, pl_magic),
108  .bt_magix = M0_LAYOUT_PDCLUST_MAGIC,
109  .bt_check = NULL
110 };
111 
113 
114 static const struct m0_bob_type pdclust_instance_bob = {
115  .bt_name = "pd_instance",
116  .bt_magix_offset = offsetof(struct m0_pdclust_instance, pi_magic),
118  .bt_check = NULL
119 };
120 
122 
123 M0_INTERNAL const struct m0_pdclust_src_addr M0_PDCLUST_SRC_NULL = {
124  .sa_group = UINT64_MAX,
125  .sa_unit = UINT64_MAX,
126 };
127 
128 static bool pdclust_allocated_invariant(const struct m0_pdclust_layout *pl)
129 {
130  return
131  pl != NULL &&
134 }
135 
136 static bool pdclust_invariant(const struct m0_pdclust_layout *pl)
137 {
138  struct m0_pdclust_attr attr = pl->pl_attr;
139 
140  return
141  m0_pdclust_layout_bob_check(pl) &&
143  pl->pl_C * (attr.pa_N + attr.pa_K + attr.pa_S) ==
144  pl->pl_L * attr.pa_P &&
146  attr.pa_P;
147 }
148 
150 {
151  uint32_t P;
152  struct m0_pdclust_layout *pl;
153  const struct tile_cache *tc;
154 
155  pl = bob_of(pi->pi_base.li_l, struct m0_pdclust_layout,
156  pl_base.sl_base, &pdclust_bob);
157  P = pl->pl_attr.pa_P;
158  tc = &pi->pi_tile_cache;
159 
160  return
161  m0_pdclust_instance_bob_check(pi) &&
163  pdclust_invariant(pl) &&
164  /*
165  * tc->tc_permute[] and tc->tc_inverse[] are mutually inverse
166  * bijections of {0, ..., P - 1}.
167  */
168  m0_forall(i, P,
169  tc->tc_lcode[i] + i < P &&
170  (tc->tc_permute[i] < P && tc->tc_inverse[i] < P) &&
171  tc->tc_permute[tc->tc_inverse[i]] == i &&
172  tc->tc_inverse[tc->tc_permute[i]] == i);
173 }
174 
180  const struct m0_layout_type *lt)
181 {
182  return 0;
183 }
184 
187  const struct m0_layout_type *lt)
188 {
189 }
190 
192 static void pdclust_fini(struct m0_ref *ref)
193 {
194  struct m0_layout *l;
195  struct m0_pdclust_layout *pl;
196 
197  l = container_of(ref, struct m0_layout, l_ref);
198  M0_PRE(m0_mutex_is_not_locked(&l->l_lock));
199 
200  M0_ENTRY("lid %llu", (unsigned long long)l->l_id);
201  pl = m0_layout_to_pdl(l);
202  m0_pdclust_layout_bob_fini(pl);
204  m0_free(pl);
205  M0_LEAVE();
206 }
207 
208 static const struct m0_layout_ops pdclust_ops;
211  uint64_t lid,
212  struct m0_layout **out)
213 {
214  struct m0_pdclust_layout *pl;
215 
217  M0_PRE(lid > 0);
218  M0_PRE(out != NULL);
219 
220  M0_ENTRY("lid %llu", (unsigned long long)lid);
221 
222  if (M0_FI_ENABLED("mem_err")) { pl = NULL; goto err1_injected; }
223  M0_ALLOC_PTR(pl);
224 err1_injected:
225  if (pl == NULL) {
226  m0_layout__log("pdclust_allocate", "M0_ALLOC_PTR() failed",
227  lid, -ENOMEM);
228  return M0_ERR(-ENOMEM);
229  }
230 
233  m0_pdclust_layout_bob_init(pl);
235 
236  *out = &pl->pl_base.sl_base;
238  M0_POST(m0_mutex_is_locked(&(*out)->l_lock));
239  M0_LEAVE("lid %llu, pl pointer %p", (unsigned long long)lid, pl);
240  return 0;
241 }
242 
244 static void pdclust_delete(struct m0_layout *l)
245 {
246  struct m0_pdclust_layout *pl;
247 
248  pl = bob_of(l, struct m0_pdclust_layout,
251  M0_PRE(m0_mutex_is_locked(&l->l_lock));
252 
253  M0_ENTRY("lid %llu", (unsigned long long)l->l_id);
254  m0_mutex_unlock(&l->l_lock);
255  m0_pdclust_layout_bob_fini(pl);
257  m0_free(pl);
258  M0_LEAVE();
259 }
260 
262 static int pdclust_populate(struct m0_pdclust_layout *pl,
263  const struct m0_pdclust_attr *attr,
264  struct m0_layout_enum *le,
265  uint32_t user_count)
266 {
267  uint64_t lid;
268  uint32_t B;
269  uint32_t N;
270  uint32_t K;
271  uint32_t S;
272  uint32_t P;
273 
274  N = attr->pa_N;
275  K = attr->pa_K;
276  S = attr->pa_S;
277  P = attr->pa_P;
280  M0_PRE(le != NULL);
281 
282  if (N + K + S > P) {
283  M0_LOG(M0_ERROR, "pl %p, attr %p, Invalid attributes, rc %d",
284  pl, attr, -EPROTO);
285  return M0_ERR(-EPROTO);
286  }
287 
288  lid = pl->pl_base.sl_base.l_id;
289  M0_ENTRY("lid %llu", (unsigned long long)lid);
290 
291  m0_layout__striped_populate(&pl->pl_base, le, user_count);
292  pl->pl_attr = *attr;
293 
294  /* Select minimal possible B (least common multiple of P and N+K+S). */
295  B = P*(N+K+S)/m0_gcd64(N+K+S, P);
296  pl->pl_C = B/(N+K+S);
297  pl->pl_L = B/P;
298 
301  M0_LEAVE("lid %llu", (unsigned long long)lid);
302  return 0;
303 }
304 
305 M0_INTERNAL int m0_pdclust_build(struct m0_layout_domain *dom,
306  uint64_t lid,
307  const struct m0_pdclust_attr *attr,
308  struct m0_layout_enum *le,
309  struct m0_pdclust_layout **out)
310 {
311  struct m0_layout *l;
312  struct m0_pdclust_layout *pl;
313  int rc;
314 
315  M0_PRE(out != NULL);
316 
317  M0_ENTRY("domain %p, lid %llu", dom,(unsigned long long)lid);
318  rc = pdclust_allocate(dom, lid, &l);
319  if (rc == 0) {
320  /* Here pdclust_allocate() has locked l->l_lock. */
321  pl = bob_of(l, struct m0_pdclust_layout,
324 
325  rc = pdclust_populate(pl, attr, le, 0);
326  if (rc == 0) {
327  *out = pl;
328  m0_mutex_unlock(&l->l_lock);
329  } else
330  pdclust_delete(l);
331  }
332 
333  M0_POST(ergo(rc == 0, pdclust_invariant(*out) &&
334  m0_mutex_is_not_locked(&l->l_lock)));
335  M0_LEAVE("domain %p, lid %llu, pl %p, rc %d",
336  dom, (unsigned long long)lid, *out, rc);
337  return M0_RC(rc);
338 }
339 
340 M0_INTERNAL bool m0_pdclust_attr_check(const struct m0_pdclust_attr *attr)
341 {
342  bool res = (attr->pa_S >= 0 && attr->pa_S <= attr->pa_K) &&
343  attr->pa_P >= attr->pa_N + attr->pa_K + attr->pa_S;
344  if (!res)
345  M0_LOG(M0_ERROR, "Bad pdclust attributes (P < N+K+S and S=0"
346  " or S==K): P=%"PRIu32" N=%"PRIu32" K=%"PRIu32
347  " S=%"PRIu32, attr->pa_P, attr->pa_N, attr->pa_K,
348  attr->pa_S);
349  return res;
350 }
351 
352 M0_INTERNAL uint32_t m0_pdclust_N(const struct m0_pdclust_layout *pl)
353 {
354  return pl->pl_attr.pa_N;
355 }
356 
357 M0_INTERNAL uint32_t m0_pdclust_K(const struct m0_pdclust_layout *pl)
358 {
359  return pl->pl_attr.pa_K;
360 }
361 
362 M0_INTERNAL uint32_t m0_pdclust_S(const struct m0_pdclust_layout *pl)
363 {
364  return pl->pl_attr.pa_S;
365 }
366 
367 M0_INTERNAL uint32_t m0_pdclust_P(const struct m0_pdclust_layout *pl)
368 {
369  return pl->pl_attr.pa_P;
370 }
371 
372 M0_INTERNAL uint32_t m0_pdclust_size(const struct m0_pdclust_layout *pl)
373 {
374  return m0_pdclust_N(pl) + m0_pdclust_K(pl) + m0_pdclust_S(pl);
375 }
376 
377 M0_INTERNAL uint64_t m0_pdclust_unit_size(const struct m0_pdclust_layout *pl)
378 {
379  return pl->pl_attr.pa_unit_size;
380 }
381 
382 M0_INTERNAL struct m0_pdclust_layout *m0_layout_to_pdl(const struct m0_layout
383  *l)
384 {
385  struct m0_pdclust_layout *pl;
386 
387  pl = bob_of(l, struct m0_pdclust_layout,
390  return pl;
391 }
392 
393 M0_INTERNAL struct m0_layout *m0_pdl_to_layout(struct m0_pdclust_layout *pl)
394 {
396  return &pl->pl_base.sl_base;
397 }
398 
399 M0_INTERNAL struct m0_pdclust_instance *
401 {
402  struct m0_pdclust_instance *pi = bob_of(li, struct m0_pdclust_instance,
405  return pi;
406 }
407 
409 {
410  return bob_of(pi->pi_base.li_l, struct m0_pdclust_layout,
412 }
413 
415 static struct m0_layout_enum *
417 {
418  struct m0_pdclust_instance *pdi;
419 
420  pdi = m0_layout_instance_to_pdi(li);
421  return m0_layout_to_enum(pdi->pi_base.li_l);
422 }
423 
424 M0_INTERNAL enum m0_pdclust_unit_type
425 m0_pdclust_unit_classify(const struct m0_pdclust_layout *pl, int unit)
426 {
427  if (unit < pl->pl_attr.pa_N)
428  return M0_PUT_DATA;
429  else if (unit < pl->pl_attr.pa_N + pl->pl_attr.pa_K)
430  return M0_PUT_PARITY;
431  else
432  return M0_PUT_SPARE;
433 }
434 
437 {
438  M0_PRE(dom != NULL);
439 
440  return sizeof(struct m0_layout_pdclust_rec) +
442 }
443 
445 static int pdclust_decode(struct m0_layout *l,
446  struct m0_bufvec_cursor *cur,
447  enum m0_layout_xcode_op op,
448  struct m0_be_tx *tx,
449  uint32_t user_count)
450 {
451  struct m0_pdclust_layout *pl;
452  struct m0_layout_pdclust_rec *pl_rec;
453  struct m0_layout_enum_type *et;
454  struct m0_layout_enum *e;
455  int rc;
456 
458  M0_PRE(cur != NULL);
459  M0_PRE(m0_bufvec_cursor_step(cur) >= sizeof *pl_rec);
461  M0_PRE(ergo(op == M0_LXO_DB_LOOKUP, tx != NULL));
462 
463  M0_ENTRY("lid %llu", (unsigned long long)l->l_id);
464  pl = bob_of(l, struct m0_pdclust_layout,
465  pl_base.sl_base, &pdclust_bob);
467 
468  /* pl_rec can not be NULL since the buffer size is already verified. */
469  pl_rec = m0_bufvec_cursor_addr(cur);
470  m0_bufvec_cursor_move(cur, sizeof *pl_rec);
471 
472  if (M0_FI_ENABLED("attr_err1"))
473  { pl_rec->pr_let_id = M0_LAYOUT_ENUM_TYPE_MAX - 1; }
474  if (M0_FI_ENABLED("attr_err2"))
475  { pl_rec->pr_let_id = M0_LAYOUT_ENUM_TYPE_MAX + 1; }
476  et = l->l_dom->ld_enum[pl_rec->pr_let_id];
477  if (!IS_IN_ARRAY(pl_rec->pr_let_id, l->l_dom->ld_enum) || et == NULL) {
478  rc = -EPROTO;
479  M0_LOG(M0_ERROR, "lid %llu, unregistered enum type, rc %d",
480  (unsigned long long)l->l_id, rc);
481  goto out;
482  }
483  rc = et->let_ops->leto_allocate(l->l_dom, &e);
484  if (rc != 0) {
485  M0_LOG(M0_ERROR, "lid %llu, leto_allocate() failed, rc %d",
486  (unsigned long long)l->l_id, rc);
487  goto out;
488  }
489  rc = e->le_ops->leo_decode(e, cur, op, tx, &pl->pl_base);
490  if (rc != 0) {
491  /* Finalise the allocated enum object. */
492  e->le_ops->leo_delete(e);
493  M0_LOG(M0_ERROR, "lid %llu, leo_decode() failed, rc %d",
494  (unsigned long long)l->l_id, rc);
495  goto out;
496  }
497 
498  if (M0_FI_ENABLED("attr_err3")) { pl_rec->pr_attr.pa_P = 1; }
499  rc = pdclust_populate(pl, &pl_rec->pr_attr, e, user_count);
500  if (rc != 0) {
501  /* Finalise the populated enum object. */
502  e->le_ops->leo_fini(e);
503  M0_LOG(M0_ERROR, "lid %llu, pdclust_populate() failed, rc %d",
504  (unsigned long long)l->l_id, rc);
505  }
506 out:
507  M0_POST(ergo(rc == 0, pdclust_invariant(pl)));
509  M0_LEAVE("lid %llu, rc %d", (unsigned long long)l->l_id, rc);
510  return M0_RC(rc);
511 }
512 
514 static int pdclust_encode(struct m0_layout *l,
515  enum m0_layout_xcode_op op,
516  struct m0_be_tx *tx,
517  struct m0_bufvec_cursor *out)
518 {
519  struct m0_pdclust_layout *pl;
520  struct m0_layout_pdclust_rec pl_rec;
521  struct m0_layout_enum *e;
522  m0_bcount_t nbytes;
523  int rc;
524 
525  /*
526  * m0_layout__invariant() is part of pdclust_invariant(),
527  * to be invoked little later through m0_layout_to_pdl() below.
528  */
529  M0_PRE(l != NULL);
532  M0_PRE(ergo(op != M0_LXO_BUFFER_OP, tx != NULL));
533  M0_PRE(out != NULL);
534  M0_PRE(m0_bufvec_cursor_step(out) >= sizeof pl_rec);
535 
536  M0_ENTRY("%llu", (unsigned long long)l->l_id);
537  pl = m0_layout_to_pdl(l);
538  pl_rec.pr_let_id = pl->pl_base.sl_enum->le_type->let_id;
539  pl_rec.pr_attr = pl->pl_attr;
540 
541  nbytes = m0_bufvec_cursor_copyto(out, &pl_rec, sizeof pl_rec);
542  M0_ASSERT(nbytes == sizeof pl_rec);
543 
544  e = pl->pl_base.sl_enum;
545  rc = e->le_ops->leo_encode(e, op, tx, out);
546  if (rc != 0)
547  M0_LOG(M0_ERROR, "lid %llu, leo_encode() failed, rc %d",
548  (unsigned long long)l->l_id, rc);
549 
550  M0_LEAVE("lid %llu, rc %d", (unsigned long long)l->l_id, rc);
551  return M0_RC(rc);
552 }
553 
555 static m0_bcount_t pdclust_recsize(const struct m0_layout *l)
556 {
557  struct m0_striped_layout *stl;
558  struct m0_layout_enum *e;
559  m0_bcount_t recsize;
560 
561  M0_PRE(l!= NULL);
562  stl = m0_layout_to_striped(l);
563  e = m0_striped_layout_to_enum(stl);
564  recsize = sizeof(struct m0_layout_rec) +
565  sizeof(struct m0_layout_pdclust_rec) +
566  e->le_ops->leo_recsize(e);
567  M0_POST(recsize <= m0_layout_max_recsize(l->l_dom));
568  return recsize;
569 }
570 
578 static uint64_t m_enc(uint64_t width, uint64_t row, uint64_t column)
579 {
580  M0_ASSERT(column < width);
581  return row * width + column;
582 }
583 
591 static void m_dec(uint64_t width, uint64_t pos, uint64_t *row, uint64_t *column)
592 {
593  *row = pos / width;
594  *column = pos % width;
595 }
596 
611 static void permute(uint32_t n, uint32_t *k, uint32_t *s, uint32_t *r)
612 {
613  uint32_t i;
614  uint32_t j;
615  uint32_t t;
616  uint32_t x;
617 
618  /*
619  * k[0] is an index of one of the n elements that permutation moves to
620  * the 0-th position in s[];
621  *
622  * k[1] is an index of one of the (n - 1) remaining elements that
623  * permutation moves to the 1-st position in s[], etc.
624  *
625  * To produce i-th element of s[], pick one of remaining elements, say
626  * s[t], as specified by k[i], shift elements s[i] ... s[t] to the right
627  * by one and place s[t] in s[i]. This guarantees that at beginning of
628  * the loop elements s[0] ... s[i - 1] are already selected and elements
629  * s[i] ... s[n - 1] are "remaining".
630  */
631 
632  for (i = 0; i < n - 1; ++i) {
633  t = k[i] + i;
634  M0_ASSERT(t < n);
635  x = s[t];
636  for (j = t; j > i; --j)
637  s[j] = s[j - 1];
638  s[i] = x;
639  r[x] = i;
640  }
641  /*
642  * The loop above iterates n-1 times, because the last element finds its
643  * place automatically. Complete inverse permutation.
644  */
645  r[s[n - 1]] = n - 1;
646 }
647 
652 static uint64_t permute_column(struct m0_pdclust_instance *pi,
653  uint64_t omega, uint64_t t)
654 {
655  struct tile_cache *tc;
656  struct m0_pdclust_attr attr;
657  struct m0_pdclust_layout *pl;
658  struct m0_fid *gfid;
659 
660  pl = pi_to_pl(pi);
661  attr = pl->pl_attr;
662  gfid = &pi->pi_base.li_gfid;
663 
664  M0_ENTRY("t %lu, P %lu", (unsigned long)t, (unsigned long)attr.pa_P);
665  M0_ASSERT(t < attr.pa_P);
666  tc = &pi->pi_tile_cache;
667 
668  /* If cached values are for different tile, update the cache. */
669  if (tc->tc_tile_no != omega) {
670  uint32_t i;
671  uint64_t rstate;
672 
673  /* Initialise columns array that will be permuted. */
674  for (i = 0; i < attr.pa_P; ++i)
675  tc->tc_permute[i] = i;
676 
677  /* Initialise PRNG. */
678  rstate = m0_hash(attr.pa_seed.u_hi + gfid->f_key) ^
679  m0_hash(attr.pa_seed.u_lo + omega + gfid->f_container);
680 
681  /* Generate permutation number in lexicographic ordering. */
682  for (i = 0; i < attr.pa_P - 1; ++i)
683  tc->tc_lcode[i] = m0_rnd(attr.pa_P - i, &rstate);
684 
685  /* Apply the permutation. */
686  permute(attr.pa_P, tc->tc_lcode,
687  tc->tc_permute, tc->tc_inverse);
688  tc->tc_tile_no = omega;
689  }
690 
695  M0_POST(tc->tc_permute[t] < attr.pa_P);
696  M0_POST(tc->tc_inverse[tc->tc_permute[t]] == t);
697  M0_POST(tc->tc_permute[tc->tc_inverse[t]] == t);
698  return tc->tc_permute[t];
699 }
700 
702  const struct m0_pdclust_src_addr *src,
703  struct m0_pdclust_tgt_addr *tgt)
704 {
705  struct m0_pdclust_layout *pl;
706  uint32_t N;
707  uint32_t K;
708  uint32_t S;
709  uint32_t P;
710  uint32_t C;
711  uint32_t L;
712  uint64_t omega;
713  uint64_t j;
714  uint64_t r;
715  uint64_t t;
716 
718 
719  M0_ENTRY("pi %p", pi);
720 
721  pl = pi_to_pl(pi);
722  N = pl->pl_attr.pa_N;
723  K = pl->pl_attr.pa_K;
724  S = pl->pl_attr.pa_S;
725  P = pl->pl_attr.pa_P;
726  C = pl->pl_C;
727  L = pl->pl_L;
728 
729  /*
730  * First translate source address into a tile number and parity group
731  * number in the tile.
732  */
733  m_dec(C, src->sa_group, &omega, &j);
734  /*
735  * Then, convert from C*(N+K+S) coordinates to L*P coordinates within a
736  * tile.
737  */
738  m_dec(P, m_enc(N + K + S, j, src->sa_unit), &r, &t);
739  /* Permute columns */
740  tgt->ta_obj = permute_column(pi, omega, t);
741  /* And translate back from tile to target address. */
742  tgt->ta_frame = m_enc(L, omega, r);
743  M0_LEAVE("pi %p", pi);
744 }
745 
747  const struct m0_pdclust_tgt_addr *tgt,
748  struct m0_pdclust_src_addr *src)
749 {
750  struct m0_pdclust_layout *pl;
751  uint32_t N;
752  uint32_t K;
753  uint32_t S;
754  uint32_t P;
755  uint32_t C;
756  uint32_t L;
757  uint64_t omega;
758  uint64_t j;
759  uint64_t r;
760  uint64_t t;
761 
762  pl = pi_to_pl(pi);
763  N = pl->pl_attr.pa_N;
764  K = pl->pl_attr.pa_K;
765  S = pl->pl_attr.pa_S;
766  P = pl->pl_attr.pa_P;
767  C = pl->pl_C;
768  L = pl->pl_L;
769 
770  r = tgt->ta_frame;
771  t = tgt->ta_obj;
772 
774 
775  /*
776  * Execute inverses of the steps of m0_pdclust_instance_map() in
777  * reverse order.
778  */
779  m_dec(L, tgt->ta_frame, &omega, &r);
780  permute_column(pi, omega, t); /* Force tile cache update */
782  m_dec(N + K + S, m_enc(P, r, t), &j, &src->sa_unit);
783  src->sa_group = m_enc(C, omega, j);
784 }
785 
787 M0_INTERNAL void pdclust_instance_fini(struct m0_layout_instance *li);
788 
789 M0_INTERNAL void m0_pdclust_perm_cache_destroy(struct m0_layout *layout,
790  struct m0_pdclust_instance *pi)
791 {
792  struct m0_pool_version *pool_ver;
793  uint64_t cache_cnt;
794  uint64_t i;
795 
796  pool_ver = layout->l_pver;
797  M0_ASSERT(pool_ver != NULL);
798  cache_cnt = layout->l_pver->pv_fd_tree.ft_cache_info.fci_nr;
799  for (i = 0; i < cache_cnt; ++i)
802  pi->pi_cache_nr = 0;
803 }
804 
805 M0_INTERNAL int m0_pdclust_perm_cache_build(struct m0_layout *layout,
806  struct m0_pdclust_instance *pi)
807 {
808  struct m0_fd_cache_info *cache_info;
809  uint64_t i;
810  int rc = 0;
811 
812  M0_PRE(layout != NULL && layout->l_pver != NULL);
813  cache_info = &layout->l_pver->pv_fd_tree.ft_cache_info;
814  M0_ALLOC_ARR(pi->pi_perm_cache, cache_info->fci_nr);
815  if (pi->pi_perm_cache == NULL)
816  return M0_ERR(-ENOMEM);
817  for (i = 0; i < cache_info->fci_nr; ++i) {
819  cache_info->fci_info[i]);
820  if (rc != 0)
821  break;
822  }
823  if (rc != 0)
825  pi->pi_cache_nr = cache_info->fci_nr;
826  return M0_RC(rc);
827 }
828 
829 M0_INTERNAL bool m0_pdclust_is_replicated(struct m0_pdclust_layout *play)
830 {
831  return play->pl_attr.pa_N == 1;
832 }
833 
844 static int pdclust_instance_build(struct m0_layout *l,
845  const struct m0_fid *fid,
846  struct m0_layout_instance **out)
847 {
848  struct m0_pdclust_layout *pl = m0_layout_to_pdl(l);
849  struct m0_pdclust_instance *pi;
850  struct tile_cache *tc = NULL; /* to keep gcc happy */
851  uint32_t N;
852  uint32_t K;
853  uint32_t P;
854  int rc;
855 
858  M0_PRE(out != NULL);
859 
860  M0_ENTRY("lid %llu, gfid "FID_F,
861  (unsigned long long)l->l_id, FID_P(fid));
862  N = pl->pl_attr.pa_N;
863  K = pl->pl_attr.pa_K;
864  P = pl->pl_attr.pa_P;
865 
866  if (M0_FI_ENABLED("mem_err1")) { pi = NULL; goto err1_injected; }
867  M0_ALLOC_PTR(pi);
868 err1_injected:
869  if (pi != NULL) {
871  if (rc != 0)
872  return M0_RC(rc);
873 
874  tc = &pi->pi_tile_cache;
875 
876  if (M0_FI_ENABLED("mem_err2"))
877  { tc->tc_lcode = NULL; goto err2_injected; }
878  M0_ALLOC_ARR(tc->tc_lcode, P);
879  M0_ALLOC_ARR(tc->tc_permute, P);
880  M0_ALLOC_ARR(tc->tc_inverse, P);
881 err2_injected:
882  if (tc->tc_lcode != NULL &&
883  tc->tc_permute != NULL &&
884  tc->tc_inverse != NULL) {
885  tc->tc_tile_no = 1;
886 
887  if (M0_FI_ENABLED("parity_math_err"))
888  { rc = -EPROTO; goto err3_injected; }
889  if (K > 0 && N != 1)
890  rc = m0_parity_math_init(&pi->pi_math, N, K);
891 err3_injected:
892  if (rc == 0) {
895  m0_pdclust_instance_bob_init(pi);
897  permute_column(pi, 0, 0);
898  }
899  else
900  M0_LOG(M0_ERROR, "pi %p, m0_parity_math_init()"
901  " failed, rc %d", pi, rc);
902  } else
903  rc = -ENOMEM;
904  } else
905  rc = -ENOMEM;
906 
907  if (rc == 0) {
908  *out = &pi->pi_base;
910  M0_POST(m0_ref_read(&l->l_ref) > 1);
911  } else {
912  if (rc == -ENOMEM)
913  m0_layout__log("pdclust_instance_build",
914  "M0_ALLOC() failed",
915  l->l_id, rc);
916  if (pi != NULL) {
917  m0_free(tc->tc_inverse);
918  m0_free(tc->tc_permute);
919  m0_free(tc->tc_lcode);
920  }
921  m0_free(pi);
922  }
923 
924  M0_LEAVE("rc %d", rc);
925  return M0_RC(rc);
926 }
927 
929 M0_INTERNAL void pdclust_instance_fini(struct m0_layout_instance *li)
930 {
931  struct m0_pdclust_instance *pi;
932  struct m0_pdclust_layout *pl;
933  struct m0_layout *layout;
934 
936  M0_ENTRY("pi %p", pi);
937  layout = li->li_l;
938  pl = m0_layout_to_pdl(layout);
939  if (pl->pl_attr.pa_K > 0)
944  m0_pdclust_instance_bob_fini(pi);
948  m0_free(pi);
949  M0_LEAVE();
950 }
951 
952 static const struct m0_layout_ops pdclust_ops = {
954  .lo_delete = pdclust_delete,
955  .lo_recsize = pdclust_recsize,
956  .lo_instance_build = pdclust_instance_build,
957  .lo_decode = pdclust_decode,
958  .lo_encode = pdclust_encode
959 };
960 
961 static const struct m0_layout_type_ops pdclust_type_ops = {
963  .lto_unregister = pdclust_unregister,
964  .lto_max_recsize = pdclust_max_recsize,
965  .lto_allocate = pdclust_allocate,
966 };
967 
969  .lt_name = "pdclust",
970  .lt_id = 0,
971  .lt_ref_count = 0,
972  .lt_ops = &pdclust_type_ops
973 };
974 
975 static const struct m0_layout_instance_ops pdclust_instance_ops = {
977  .lio_to_enum = pdclust_instance_to_enum
978 };
979 
980 #undef M0_TRACE_SUBSYSTEM
981 
984 /*
985  * Local variables:
986  * c-indentation-style: "K&R"
987  * c-basic-offset: 8
988  * tab-width: 8
989  * fill-column: 80
990  * scroll-step: 1
991  * End:
992  */
static void pdclust_fini(struct m0_ref *ref)
Definition: pdclust.c:192
static struct m0_layout_enum * pdclust_instance_to_enum(const struct m0_layout_instance *li)
Definition: pdclust.c:416
static const struct m0_layout_type_ops pdclust_type_ops
Definition: pdclust.c:961
M0_INTERNAL m0_bcount_t m0_layout_max_recsize(const struct m0_layout_domain *dom)
Definition: layout.c:1037
M0_INTERNAL struct m0_striped_layout * m0_layout_to_striped(const struct m0_layout *l)
Definition: layout.c:1045
static const struct m0_layout_instance_ops pdclust_instance_ops
Definition: pdclust.c:786
M0_INTERNAL void m0_parity_math_fini(struct m0_parity_math *math)
Definition: parity_math.c:325
static const struct m0_bob_type pdclust_bob
Definition: pdclust.c:105
#define M0_PRE(cond)
M0_INTERNAL bool m0_pdclust_is_replicated(struct m0_pdclust_layout *play)
Definition: pdclust.c:829
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
static int pdclust_instance_build(struct m0_layout *l, const struct m0_fid *fid, struct m0_layout_instance **out)
Definition: pdclust.c:844
struct m0_layout * li_l
Definition: layout.h:590
uint64_t sa_group
Definition: pdclust.h:241
#define NULL
Definition: misc.h:38
uint64_t pa_unit_size
Definition: pdclust.h:118
struct m0_pool_version * l_pver
Definition: layout.h:261
static struct buffer * cur(struct m0_addb2_mach *mach, m0_bcount_t space)
Definition: addb2.c:791
#define ergo(a, b)
Definition: misc.h:293
const struct m0_layout_enum_type_ops * let_ops
Definition: layout.h:540
M0_INTERNAL void m0_fd_perm_cache_fini(struct m0_fd_perm_cache *cache)
Definition: fd.c:825
static bool x
Definition: sm.c:168
uint32_t pa_N
Definition: pdclust.h:104
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
uint32_t pr_let_id
Definition: pdclust.h:131
void(* leo_fini)(struct m0_layout_enum *e)
Definition: layout.h:460
M0_INTERNAL bool m0_mutex_is_not_locked(const struct m0_mutex *mutex)
Definition: mutex.c:101
M0_INTERNAL void m0_layout__striped_init(struct m0_striped_layout *stl, struct m0_layout_domain *dom, uint64_t lid, struct m0_layout_type *type, const struct m0_layout_ops *ops)
Definition: layout.c:400
M0_INTERNAL struct m0_layout_enum * m0_striped_layout_to_enum(const struct m0_striped_layout *stl)
Definition: layout.c:1056
struct m0_layout_instance pi_base
Definition: pdclust.h:173
uint32_t pa_K
Definition: pdclust.h:107
struct m0_pool_version pool_ver
Definition: fd.c:111
M0_INTERNAL bool m0_layout__instance_invariant(const struct m0_layout_instance *li)
Definition: layout.c:198
M0_INTERNAL int m0_pdclust_perm_cache_build(struct m0_layout *layout, struct m0_pdclust_instance *pi)
Definition: pdclust.c:805
uint64_t ta_obj
Definition: pdclust.h:256
M0_INTERNAL void pdclust_instance_fini(struct m0_layout_instance *li)
Definition: pdclust.c:929
uint32_t pa_S
Definition: pdclust.h:110
M0_INTERNAL void * m0_bufvec_cursor_addr(struct m0_bufvec_cursor *cur)
Definition: vec.c:597
uint64_t m0_bcount_t
Definition: types.h:77
#define container_of(ptr, type, member)
Definition: misc.h:33
M0_INTERNAL int m0_fd_perm_cache_init(struct m0_fd_perm_cache *cache, uint64_t len)
Definition: fd.c:741
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
M0_INTERNAL bool m0_layout__striped_allocated_invariant(const struct m0_striped_layout *stl)
Definition: layout.c:181
static m0_bcount_t pdclust_max_recsize(struct m0_layout_domain *dom)
Definition: pdclust.c:436
#define N(i)
static const struct m0_layout_ops pdclust_ops
Definition: pdclust.c:208
struct m0_pdclust_attr pl_attr
Definition: pdclust.h:150
uint32_t pl_C
Definition: pdclust.h:155
struct m0_layout_enum_type * le_type
Definition: layout.h:409
int(* leo_decode)(struct m0_layout_enum *e, struct m0_bufvec_cursor *cur, enum m0_layout_xcode_op op, struct m0_be_tx *tx, struct m0_striped_layout *stl)
Definition: layout.h:482
const char * bt_name
Definition: bob.h:73
struct m0_fid fid
Definition: di.c:46
return M0_RC(rc)
op
Definition: libdemo.c:64
struct m0_pdclust_attr pr_attr
Definition: pdclust.h:133
static m0_bcount_t pdclust_recsize(const struct m0_layout *l)
Definition: pdclust.c:555
#define M0_ENTRY(...)
Definition: trace.h:170
M0_INTERNAL bool m0_bufvec_cursor_move(struct m0_bufvec_cursor *cur, m0_bcount_t count)
Definition: vec.c:574
static bool pdclust_invariant(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:136
int i
Definition: dir.c:1033
m0_pdclust_unit_type
Definition: pdclust.h:89
int(* leo_encode)(const struct m0_layout_enum *le, enum m0_layout_xcode_op op, struct m0_be_tx *tx, struct m0_bufvec_cursor *out)
Definition: layout.h:502
M0_INTERNAL const struct m0_pdclust_src_addr M0_PDCLUST_SRC_NULL
Definition: pdclust.c:123
return M0_ERR(-EOPNOTSUPP)
struct m0_layout_type m0_pdclust_layout_type
Definition: pdclust.c:968
M0_INTERNAL uint64_t m0_rnd(uint64_t max, uint64_t *seed)
Definition: misc.c:115
M0_INTERNAL void m0_layout__striped_delete(struct m0_striped_layout *stl)
Definition: layout.c:452
Definition: refs.h:34
static void attr(struct m0_addb2__context *ctx, const uint64_t *v, char *buf)
Definition: dump.c:949
if(value==NULL)
Definition: dir.c:350
const struct m0_layout_enum_ops * le_ops
Definition: layout.h:423
struct m0_parity_math pi_math
Definition: pdclust.h:223
struct m0_fd_tree pv_fd_tree
Definition: pool.h:139
M0_INTERNAL m0_bcount_t m0_bufvec_cursor_step(const struct m0_bufvec_cursor *cur)
Definition: vec.c:581
struct m0_striped_layout pl_base
Definition: pdclust.h:148
#define M0_ASSERT(cond)
M0_INTERNAL uint32_t m0_pdclust_N(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:352
M0_INTERNAL bool m0_mutex_is_locked(const struct m0_mutex *mutex)
Definition: mutex.c:95
M0_INTERNAL m0_bcount_t m0_layout__enum_max_recsize(struct m0_layout_domain *dom)
Definition: layout.c:527
uint64_t ta_frame
Definition: pdclust.h:254
static struct m0_thread t[8]
Definition: service_ut.c:1230
#define bob_of(ptr, type, field, bt)
Definition: bob.h:140
struct m0_layout_enum * sl_enum
Definition: layout.h:577
struct m0_fd_cache_info ft_cache_info
Definition: fd.h:209
static struct m0_stob_domain * dom
Definition: storage.c:38
const char * lt_name
Definition: layout.h:357
M0_INTERNAL void m0_layout__instance_init(struct m0_layout_instance *li, const struct m0_fid *gfid, struct m0_layout *l, const struct m0_layout_instance_ops *ops)
Definition: layout.c:1089
M0_INTERNAL uint32_t m0_pdclust_S(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:362
static int pdclust_encode(struct m0_layout *l, enum m0_layout_xcode_op op, struct m0_be_tx *tx, struct m0_bufvec_cursor *out)
Definition: pdclust.c:514
M0_INTERNAL void m0_layout__striped_fini(struct m0_striped_layout *str_l)
Definition: layout.c:466
M0_INTERNAL struct m0_pdclust_layout * m0_layout_to_pdl(const struct m0_layout *l)
Definition: pdclust.c:382
M0_INTERNAL int m0_parity_math_init(struct m0_parity_math *math, uint32_t data_count, uint32_t parity_count)
Definition: parity_math.c:333
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
struct m0_pdclust_instance pi
Definition: fd.c:107
M0_INTERNAL uint32_t m0_pdclust_K(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:357
uint64_t f_container
Definition: fid.h:39
#define M0_POST(cond)
uint64_t fci_nr
Definition: fd.h:188
M0_INTERNAL bool m0_layout__domain_invariant(const struct m0_layout_domain *dom)
Definition: layout.c:131
#define UINT64_MAX
Definition: types.h:44
struct m0_mutex l_lock
Definition: layout.h:247
M0_INTERNAL bool m0_layout__striped_invariant(const struct m0_striped_layout *stl)
Definition: layout.c:189
M0_INTERNAL void m0_layout__log(const char *fn_name, const char *err_msg, uint64_t lid, int rc)
Definition: layout.c:586
static bool pdclust_instance_invariant(const struct m0_pdclust_instance *pi)
Definition: pdclust.c:149
M0_INTERNAL void m0_pdclust_instance_map(struct m0_pdclust_instance *pi, const struct m0_pdclust_src_addr *src, struct m0_pdclust_tgt_addr *tgt)
Definition: pdclust.c:701
struct m0_pdclust_instance::tile_cache pi_tile_cache
#define FID_P(f)
Definition: fid.h:77
M0_INTERNAL void m0_pdclust_instance_inv(struct m0_pdclust_instance *pi, const struct m0_pdclust_tgt_addr *tgt, struct m0_pdclust_src_addr *src)
Definition: pdclust.c:746
M0_INTERNAL void m0_layout__instance_fini(struct m0_layout_instance *li)
Definition: layout.c:1106
static struct m0_clink l[NR]
Definition: chan.c:37
M0_INTERNAL uint64_t m0_gcd64(uint64_t p, uint64_t q)
Definition: misc.c:128
uint32_t pl_L
Definition: pdclust.h:160
static void pdclust_delete(struct m0_layout *l)
Definition: pdclust.c:244
struct m0_fid li_gfid
Definition: layout.h:587
M0_INTERNAL struct m0_layout * m0_pdl_to_layout(struct m0_pdclust_layout *pl)
Definition: pdclust.c:393
static void m_dec(uint64_t width, uint64_t pos, uint64_t *row, uint64_t *column)
Definition: pdclust.c:591
M0_INTERNAL void m0_layout__striped_populate(struct m0_striped_layout *str_l, struct m0_layout_enum *e, uint32_t user_count)
Definition: layout.c:427
static int pdclust_register(struct m0_layout_domain *dom, const struct m0_layout_type *lt)
Definition: pdclust.c:179
#define m0_forall(var, nr,...)
Definition: misc.h:112
M0_INTERNAL uint32_t m0_pdclust_size(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:372
uint64_t sa_unit
Definition: pdclust.h:243
M0_INTERNAL bool m0_layout__allocated_invariant(const struct m0_layout *l)
Definition: layout.c:147
#define PRIu32
Definition: types.h:66
struct m0_mutex pi_mutex
Definition: pdclust.h:230
struct m0_pdclust_tgt_addr tgt
Definition: fd.c:110
static struct m0_pdclust_layout * pi_to_pl(struct m0_pdclust_instance *pi)
Definition: pdclust.c:408
M0_INTERNAL int64_t m0_ref_read(const struct m0_ref *ref)
Definition: refs.c:44
uint64_t n
Definition: fops.h:107
uint64_t pi_cache_nr
Definition: pdclust.h:220
#define M0_FI_ENABLED(tag)
Definition: finject.h:231
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 void pdclust_unregister(struct m0_layout_domain *dom, const struct m0_layout_type *lt)
Definition: pdclust.c:186
static int pdclust_populate(struct m0_pdclust_layout *pl, const struct m0_pdclust_attr *attr, struct m0_layout_enum *le, uint32_t user_count)
Definition: pdclust.c:262
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
int(* lto_register)(struct m0_layout_domain *dom, const struct m0_layout_type *lt)
Definition: layout.h:378
static bool pdclust_allocated_invariant(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:128
static int r[NR]
Definition: thread.c:46
void(* lio_fini)(struct m0_layout_instance *li)
Definition: layout.h:607
uint32_t pa_P
Definition: pdclust.h:115
M0_BOB_DEFINE(static, &pdclust_bob, m0_pdclust_layout)
M0_INTERNAL m0_bcount_t m0_bufvec_cursor_copyto(struct m0_bufvec_cursor *dcur, void *sdata, m0_bcount_t num_bytes)
Definition: vec.c:677
M0_INTERNAL enum m0_pdclust_unit_type m0_pdclust_unit_classify(const struct m0_pdclust_layout *pl, int unit)
Definition: pdclust.c:425
static void permute(uint32_t n, uint32_t *k, uint32_t *s, uint32_t *r)
Definition: pdclust.c:611
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
struct m0_layout sl_base
Definition: layout.h:574
M0_INTERNAL int m0_pdclust_build(struct m0_layout_domain *dom, uint64_t lid, const struct m0_pdclust_attr *attr, struct m0_layout_enum *le, struct m0_pdclust_layout **out)
Definition: pdclust.c:305
#define IS_IN_ARRAY(idx, array)
Definition: misc.h:311
M0_INTERNAL struct m0_layout_enum * m0_layout_to_enum(const struct m0_layout *l)
Definition: layout.c:1064
int(* leto_allocate)(struct m0_layout_domain *dom, struct m0_layout_enum **out)
Definition: layout.h:567
uint64_t * fci_info
Definition: fd.h:196
#define C(v)
M0_INTERNAL void m0_pdclust_perm_cache_destroy(struct m0_layout *layout, struct m0_pdclust_instance *pi)
Definition: pdclust.c:789
Definition: rwlock.c:42
Definition: finject.c:60
M0_INTERNAL struct m0_pdclust_instance * m0_layout_instance_to_pdi(const struct m0_layout_instance *li)
Definition: pdclust.c:400
uint32_t(* leo_nr)(const struct m0_layout_enum *e)
Definition: layout.h:431
#define out(...)
Definition: gen.c:41
struct m0_fid gfid
Definition: dir.c:626
static uint64_t permute_column(struct m0_pdclust_instance *pi, uint64_t omega, uint64_t t)
Definition: pdclust.c:652
static const struct m0_bob_type pdclust_instance_bob
Definition: pdclust.c:114
M0_INTERNAL bool m0_fid_is_valid(const struct m0_fid *fid)
Definition: fid.c:96
static int pdclust_decode(struct m0_layout *l, struct m0_bufvec_cursor *cur, enum m0_layout_xcode_op op, struct m0_be_tx *tx, uint32_t user_count)
Definition: pdclust.c:445
void m0_free(void *data)
Definition: memory.c:146
static struct m0_addb2_source * s
Definition: consumer.c:39
struct m0_pdclust_src_addr src
Definition: fd.c:108
static int pdclust_allocate(struct m0_layout_domain *dom, uint64_t lid, struct m0_layout **out)
Definition: pdclust.c:210
int32_t rc
Definition: trigger_fop.h:47
#define offsetof(typ, memb)
Definition: misc.h:29
M0_INTERNAL uint32_t m0_pdclust_P(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:367
m0_layout_xcode_op
Definition: layout.h:161
M0_INTERNAL uint64_t m0_pdclust_unit_size(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:377
static uint64_t m_enc(uint64_t width, uint64_t row, uint64_t column)
Definition: pdclust.c:578
Definition: module.c:67
#define FID_F
Definition: fid.h:75
uint32_t let_id
Definition: layout.h:530
Definition: tx.h:280
M0_INTERNAL uint64_t m0_hash(uint64_t x)
Definition: hash.c:279
uint64_t l_id
Definition: layout.h:225
void(* leo_delete)(struct m0_layout_enum *e)
Definition: layout.h:466
void(* lo_fini)(struct m0_ref *ref)
Definition: layout.h:275
M0_INTERNAL bool m0_pdclust_attr_check(const struct m0_pdclust_attr *attr)
Definition: pdclust.c:340