Motr  M0
layout.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 
23 #include "ut/ut.h"
24 #include "lib/ub.h"
25 #include "lib/memory.h"
26 #include "lib/misc.h" /* M0_SET0 */
27 #include "lib/bitstring.h"
28 #include "lib/vec.h"
29 #include "lib/errno.h" /* ENOENT */
30 
31 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_LAYOUT
32 #include "lib/trace.h" /* M0_LOG */
33 
34 #ifdef __KERNEL__
35 # include "m0t1fs/linux_kernel/m0t1fs.h" /* m0t1fs_globals */
36 #endif
37 
38 #include "lib/finject.h"
39 
40 #include "pool/pool.h" /* m0_pool_init(), m0_pool_fini() */
41 #include "fid/fid.h" /* m0_fid_set() */
42 #include "layout/layout.h"
43 #include "layout/layout_internal.h" /* LDB_MAX_INLINE_COB_ENTRIES, *_ERR */
44 #include "layout/pdclust.h"
45 //#include "layout/list_enum.h"
46 #include "layout/linear_enum.h"
47 #include "ioservice/fid_convert.h" /* m0_fid_convert_gob2cob */
48 
49 static struct m0_layout_domain domain;
50 static struct m0_pool pool;
51 static int rc;
52 
53 enum {
54  DBFLAGS = 0, /* Flag used for dbenv and tx init */
55  LIST_ENUM_ID = 0x4C495354, /* "LIST" */
56  LINEAR_ENUM_ID = 0x4C494E45, /* "LINE" */
57  ADDITIONAL_BYTES_NONE = 0, /* For buffer initialisation */
58  ADDITIONAL_BYTES_DEFAULT = 2048, /* For buffer initialisation */
59  INLINE_NOT_APPLICABLE = 0, /* For list enumeration */
60  LESS_THAN_INLINE = 1, /* For list enumeration */
61  EXACT_INLINE = 2, /* For list enumeration */
62  MORE_THAN_INLINE = 3, /* For list enumeration */
63  EXISTING_TEST = true, /* Add a layout to the DB */
64  DUPLICATE_TEST = true, /* Try to re-add a layout */
65  FAILURE_TEST = true, /* Failure injected */
66  LAYOUT_DESTROY = true, /* Delete layout object */
67  UNIT_SIZE = 4096 /* For pdclust layout type */
68 };
69 
71 //extern struct m0_layout_enum_type m0_list_enum_type;
73 
74 static int test_init(void)
75 {
76  /*
77  * Note: In test_init() and test_fini(), need to use M0_ASSERT()
78  * as against M0_UT_ASSERT().
79  */
80 
81  /* Initialise the domain. */
83  M0_ASSERT(rc == 0);
84 
85  /* Register all the standard layout types and enum types. */
87  M0_ASSERT(rc == 0);
88 
89  return rc;
90 }
91 
92 static int test_fini(void)
93 {
96 
97  return 0;
98 }
99 
100 static void test_domain_init_fini(void)
101 {
102  struct m0_layout_domain *dom;
103 
104  M0_ENTRY();
105 
106  M0_ALLOC_PTR(dom);
107  M0_UT_ASSERT(dom != NULL);
108 
109  /* Initialise the domain. */
111  M0_UT_ASSERT(rc == 0);
112 
113  /* Finalise the domain. */
115 
116  /* Should be able to initialise the domain again after finalising it. */
118  M0_UT_ASSERT(rc == 0);
119 
120  /* Finalise the domain. */
122 
123  m0_free(dom);
124 
125  M0_LEAVE();
126 }
127 
129 {
130  struct m0_layout_domain *dom;
131 
132  M0_ENTRY();
133 
134  M0_ALLOC_PTR(dom);
135  M0_UT_ASSERT(dom != NULL);
136 
137  m0_fi_enable_once("m0_layout_domain_init", "table_init_err");
140 
141  m0_free(dom);
142 
143  M0_LEAVE();
144 }
145 
146 static int t_register(struct m0_layout_domain *dom,
147  const struct m0_layout_type *lt)
148 {
149  return 0;
150 }
151 
152 static void t_unregister(struct m0_layout_domain *dom,
153  const struct m0_layout_type *lt)
154 {
155 }
156 
158 {
159  return 0;
160 }
161 
164  .lto_unregister = t_unregister,
165  .lto_max_recsize = t_max_recsize
166 };
167 
169  .lt_name = "test",
170  .lt_id = 2,
171  .lt_ops = &test_layout_type_ops
172 };
173 
174 static void test_type_reg_unreg(void)
175 {
176  M0_ENTRY();
177 
178  /* Register a layout type. */
180  M0_UT_ASSERT(rc == 0);
183 
184  /* Unregister it. */
187 
188  M0_LEAVE();
189 }
190 
192  const struct m0_layout_enum_type *et)
193 {
194  return 0;
195 }
196 
198  const struct m0_layout_enum_type *et)
199 {
200 }
201 
203 {
204  return 0;
205 }
206 
207 static const struct m0_layout_enum_type_ops test_enum_ops = {
209  .leto_unregister = t_enum_unregister,
210  .leto_max_recsize = t_enum_max_recsize
211 };
212 
214  .let_name = "test",
215  .let_id = 2,
216  .let_ops = &test_enum_ops
217 };
218 
219 static void test_etype_reg_unreg(void)
220 {
221  M0_ENTRY();
222 
223  /* Register a layout enum type. */
225  M0_UT_ASSERT(rc == 0);
227  &test_enum_type);
228 
229  /* Unregister it. */
232 
233  M0_LEAVE();
234 }
235 
236 static void test_reg_unreg(void)
237 {
238  struct m0_layout_domain *dom;
239 
240  M0_ENTRY();
241 
242  M0_ALLOC_PTR(dom);
243  M0_UT_ASSERT(dom != NULL);
244 
245  /*
246  * A layout type can be registered with only one domain at a time.
247  * Hence, unregister all the available layout types and enum types from
248  * the domain "domain", which are registered through test_init().
249  * This also covers the test of registering with one domain,
250  * unregistering from that domain and then registering with another
251  * domain.
252  */
254 
255  /* Initialise the domain. */
257  M0_UT_ASSERT(rc == 0);
258 
259  /* Register all the available layout types and enum types. */
261  M0_UT_ASSERT(rc == 0);
262 /* M0_UT_ASSERT(dom->ld_enum[m0_list_enum_type.let_id] ==
263  &m0_list_enum_type);*/
268 
269  /* Unregister all the registered layout and enum types. */
271  //M0_UT_ASSERT(dom->ld_enum[m0_list_enum_type.let_id] == NULL);
274 
275  /*
276  * Should be able to register all the available layout types and enum
277  * types, again after unregistering those.
278  */
280  M0_UT_ASSERT(rc == 0);
281  /*M0_UT_ASSERT(dom->ld_enum[m0_list_enum_type.let_id] ==
282  &m0_list_enum_type);*/
287 
288  /* Unregister all the registered layout and enum types. */
290  //M0_UT_ASSERT(dom->ld_enum[m0_list_enum_type.let_id] == NULL);
293 
294  /* Finalise the domain. */
296 
297  /*
298  * Register back all the available layout types and enum types with
299  * the domain "domain", to undo the change done at the beginning of
300  * this function.
301  */
303  M0_ASSERT(rc == 0);
304 
305  m0_free(dom);
306 
307  M0_LEAVE();
308 }
309 
310 static void test_reg_unreg_failure(void)
311 {
312  struct m0_layout_domain *dom;
313 
314  M0_ENTRY();
315 
316  M0_ALLOC_PTR(dom);
317  M0_UT_ASSERT(dom != NULL);
318 
319  /*
320  * A layout type can be registered with only one domain at a time.
321  * Hence, unregister all the available layout types and enum types from
322  * the domain "domain", which are registered through test_init().
323  * This also covers the test of registering with one domain,
324  * unregistering from that domain and then registering with another
325  * domain.
326  */
328 
329  /* Initialise the domain. */
331  M0_UT_ASSERT(rc == 0);
332 
333  /*
334  * Try to register all the standard layout types and enum types by
335  * injecting errors.
336  */
337  m0_fi_enable_once("m0_layout_type_register", "lto_reg_err");
340 
341  /*m0_fi_enable_once("m0_layout_enum_type_register", "leto_reg_err");
342  rc = m0_layout_enum_type_register(dom, &m0_list_enum_type);
343  M0_UT_ASSERT(rc == LETO_REG_ERR);*/
344 
345  m0_fi_enable_once("m0_layout_enum_type_register", "leto_reg_err");
348 
349  /*m0_fi_enable_once("list_register", "mem_err");
350  rc = m0_layout_enum_type_register(dom, &m0_list_enum_type);
351  M0_UT_ASSERT(rc == -ENOMEM);*/
352 
353  /*m0_fi_enable_once("list_register", "table_init_err");
354  rc = m0_layout_enum_type_register(dom, &m0_list_enum_type);
355  M0_UT_ASSERT(rc == -EEXIST);*/
356 
357  /*
358  * Now cover all the error cases from
359  * m0_layout_standard_types_register().
360  */
361  m0_fi_enable_once("m0_layout_type_register", "lto_reg_err");
364 
365  m0_fi_enable_once("m0_layout_enum_type_register", "leto_reg_err");
368 
369  m0_fi_enable_once("m0_layout_enum_type_register", "leto_reg_err");
372  m0_fi_disable("m0_layout_enum_type_register", "leto_reg_err");
373 
375 
376  /*
377  * Register back all the available layout types and enum types with
378  * the domain "domain", to undo the change done at the beginning of
379  * this function.
380  */
382  M0_ASSERT(rc == 0);
383 
384  m0_free(dom);
385 
386  M0_LEAVE();
387 }
388 
389 static struct m0_layout *list_lookup(uint64_t lid)
390 {
391  struct m0_layout *l;
392 
394  l = m0_layout__list_lookup(&domain, lid, false);
396  return l;
397 }
398 
399 /*
400  * Builds a layout object with PDCLUST layout type and using the provided
401  * enumeration object.
402  */
403 static int pdclust_l_build(uint64_t lid, uint32_t N, uint32_t K,
404  uint32_t S, uint32_t P,
405  struct m0_uint128 *seed,
406  struct m0_layout_enum *le,
407  struct m0_pdclust_layout **pl,
408  bool failure_test)
409 {
410  struct m0_pdclust_attr attr;
411 
412  M0_UT_ASSERT(le != NULL);
413  M0_UT_ASSERT(pl != NULL);
414 
415  attr.pa_N = N;
416  attr.pa_K = K;
417  attr.pa_P = P;
418  attr.pa_S = S;
419  attr.pa_unit_size = UNIT_SIZE;
420  attr.pa_seed = *seed;
421 
422  if (M0_FI_ENABLED("attr_err")) { attr.pa_P = 1; }
423  rc = m0_pdclust_build(&domain, lid, &attr, le, pl);
424  if (failure_test)
425  M0_UT_ASSERT(rc == -ENOMEM || rc == -EPROTO);
426  else {
427  M0_UT_ASSERT(rc == 0);
428  M0_UT_ASSERT(list_lookup(lid) == &(*pl)->pl_base.sl_base);
429  M0_UT_ASSERT(m0_ref_read(&(*pl)->pl_base.sl_base.l_ref) == 1);
430  M0_UT_ASSERT((*pl)->pl_base.sl_base.l_user_count == 0);
431  }
432 
433  return rc;
434 }
435 
436 /*
437  * Builds a layout object with PDCLUST layout type, by first building an
438  * enumeration object with the specified enumeration type.
439  */
440 static int pdclust_layout_build(uint32_t enum_id,
441  uint64_t lid,
442  uint32_t N, uint32_t K,
443  uint32_t S, uint32_t P,
444  struct m0_uint128 *seed,
445  uint32_t A, uint32_t B,
446  struct m0_pdclust_layout **pl,
447 // struct m0_layout_list_enum **list_enum,
448  struct m0_layout_linear_enum **lin_enum,
449  bool failure_test)
450 {
451 // struct m0_fid *cob_list = NULL; /* to keep gcc happy. */
452 // int i;
453  struct m0_layout_enum *e;
454  struct m0_layout_linear_attr lin_attr;
455  struct m0_layout *l_from_pl;
456  struct m0_layout_enum *e_from_layout;
457 
459  M0_UT_ASSERT(pl != NULL);
460 
461 #if 0
462  /* Build an enumeration object with the specified enum type. */
463  if (enum_id == LIST_ENUM_ID) {
464  M0_ALLOC_ARR(cob_list, P);
465  M0_UT_ASSERT(cob_list != NULL);
466 
467  for (i = 0; i < P; ++i)
468  m0_fid_set(&cob_list[i], i * 100 + 1, i + 1);
469 
470  if (M0_FI_ENABLED("list_attr_err")) { P = 0; }
471  rc = m0_list_enum_build(&domain, cob_list, P, list_enum);
472  M0_UT_ASSERT(rc == 0 || rc == -ENOMEM || rc == -EPROTO);
473 
474  e = &(*list_enum)->lle_base;
475 
476  } else { /* LINEAR_ENUM_ID */
477 #endif
478  lin_attr.lla_nr = P;
479  lin_attr.lla_A = A;
480  lin_attr.lla_B = B;
481  if (M0_FI_ENABLED("lin_attr_err")) { lin_attr.lla_nr = 0; }
482  rc = m0_linear_enum_build(&domain, &lin_attr, lin_enum);
483  M0_UT_ASSERT(rc == 0 || rc == -ENOMEM || rc == -EPROTO);
484 
485  e = &(*lin_enum)->lle_base;
486 #if 0
487  }
488 #endif
489  if (rc != 0) {
490  M0_UT_ASSERT(failure_test);
491 #if 0
492  if (enum_id == LIST_ENUM_ID)
493  m0_free(cob_list);
494 #endif
495  return rc;
496  }
497 
498  /*
499  * Build a layout object with PDCLUST layout type and using the
500  * enumeration object built earlier here.
501  */
502  rc = pdclust_l_build(lid, N, K, S, P, seed, e, pl, failure_test);
503  if (failure_test) {
504  M0_UT_ASSERT(rc == -ENOMEM || rc == -EPROTO);
506  return rc;
507  }
508  else {
509  M0_UT_ASSERT(rc == 0);
510  M0_UT_ASSERT(list_lookup(lid) == &(*pl)->pl_base.sl_base);
511  }
512 
513  /* Verify m0_pdl_to_layout(). */
514  l_from_pl = m0_pdl_to_layout(*pl);
515  M0_UT_ASSERT(l_from_pl == &(*pl)->pl_base.sl_base);
516 
517  /* Verify m0_layout_to_enum(). */
518  e_from_layout = m0_layout_to_enum(l_from_pl);
519  M0_UT_ASSERT(e_from_layout == e);
520  return rc;
521 }
522 
523 /* Verifies generic part of the layout object. */
524 static void l_verify(struct m0_layout *l, uint64_t lid)
525 {
526  M0_UT_ASSERT(l->l_id == lid);
527  M0_UT_ASSERT(m0_ref_read(&l->l_ref) >= 0);
528  M0_UT_ASSERT(l->l_ops != NULL);
529 }
530 
531 /*
532  * Verifies generic part of the layout object and the PDCLUST layout type
533  * specific part of it.
534  */
535 static void pdclust_l_verify(struct m0_pdclust_layout *pl,
536  uint64_t lid,
537  uint32_t N, uint32_t K,
538  uint32_t S, uint32_t P,
539  struct m0_uint128 *seed)
540 {
541  /* Verify generic part of the layout object. */
542  l_verify(&pl->pl_base.sl_base, lid);
543 
544  /* Verify PDCLUST layout type specific part of the layout object. */
545  M0_UT_ASSERT(pl->pl_attr.pa_N == N);
546  M0_UT_ASSERT(pl->pl_attr.pa_K == K);
547  M0_UT_ASSERT(pl->pl_attr.pa_S == S);
548  M0_UT_ASSERT(pl->pl_attr.pa_P == P);
551 }
552 
553 /* Verifies the layout object against the various input arguments. */
554 static void pdclust_layout_verify(uint32_t enum_id,
555  struct m0_layout *l, uint64_t lid,
556  uint32_t N, uint32_t K,
557  uint32_t S, uint32_t P,
558  struct m0_uint128 *seed,
559  uint32_t A, uint32_t B)
560 {
561  struct m0_pdclust_layout *pl;
562 // struct m0_layout_list_enum *list_enum;
563  struct m0_layout_linear_enum *lin_enum;
564 // int i;
565 // struct m0_fid cob_id;
566 
567  M0_UT_ASSERT(l != NULL);
570 
571  pl = container_of(l, struct m0_pdclust_layout, pl_base.sl_base);
572 
573  /*
574  * Verify generic and PDCLUST layout type specific parts of the
575  * layout object.
576  */
577  pdclust_l_verify(pl, lid, N, K, S, P, seed);
578 
579  /* Verify enum type specific part of the layout object. */
581 
582 #if 0
583  if (enum_id == LIST_ENUM_ID) {
584  list_enum = container_of(pl->pl_base.sl_enum,
585  struct m0_layout_list_enum, lle_base);
586  for(i = 0; i < list_enum->lle_nr; ++i) {
587  m0_fid_set(&cob_id, i * 100 + 1, i + 1);
588  M0_UT_ASSERT(m0_fid_eq(&cob_id,
589  &list_enum->lle_list_of_cobs[i]));
590  }
591  M0_UT_ASSERT(list_enum->lle_nr == P);
592  } else {
593 #endif
594  lin_enum = container_of(pl->pl_base.sl_enum,
596  M0_UT_ASSERT(lin_enum->lle_attr.lla_nr == P);
597  M0_UT_ASSERT(lin_enum->lle_attr.lla_A == A);
598  M0_UT_ASSERT(lin_enum->lle_attr.lla_B == B);
599 #if 0
600  }
601 #endif
602 }
603 
604 static void NKP_assign_and_pool_init(uint32_t enum_id,
605  uint32_t inline_test,
606  uint32_t list_nr_less,
607  uint32_t list_nr_more,
608  uint32_t linear_nr,
609  uint32_t *N, uint32_t *K,
610  uint32_t *S, uint32_t *P)
611 {
613  list_nr_less < LDB_MAX_INLINE_COB_ENTRIES &&
614  list_nr_more > LDB_MAX_INLINE_COB_ENTRIES));
615 
621  if (list_nr_more > 50)
622  list_nr_more = 50;
623 
624 #if 0
625  if (enum_id == LIST_ENUM_ID) {
626  switch (inline_test) {
627  case LESS_THAN_INLINE:
628  *P = list_nr_less;
629  break;
630  case EXACT_INLINE:
632  break;
633  case MORE_THAN_INLINE:
634  *P = list_nr_more;
635  break;
636  default:
637  M0_ASSERT(0);
638  }
639  } else {
640 #endif
641  *P = linear_nr;
642 #if 0
643  }
644 #endif
645 
646  if (*P <= 20) {
647  *K = 1;
648  *S = 1;
649  } else if (*P <= 50) {
650  *K = 2;
651  *S = 2;
652  } else if (*P <= 200) {
653  *K = 6;
654  *S = 6;
655  } else if (*P <= 500) {
656  *K = 12;
657  *S = 12;
658  } else if (*P <= 1000) {
659  *K = 100;
660  *S = 100;
661  } else {
662  *K = 200;
663  *S = 200;
664  }
665 
666  if (*P <= 20)
667  *N = *P - ((*K) + (*S));
668  else if (*P <= 100)
669  *N = *P - ((*K) + (*S)) - 10;
670  else if (*P <= 1000)
671  *N = *P - ((*K) + (*S)) - 12;
672  else
673  *N = *P - ((*K) + (*S)) - 100;
674 
675  rc = m0_pool_init(&pool, &M0_FID_INIT(0, enum_id), 0);
676  M0_ASSERT(rc == 0);
677 }
678 
679 /*
680  * Tests the APIs supported for enumeration object build, layout object build
681  * and layout destruction that happens using m0_layout_put(). Verifies that the
682  * newly built layout object is added to the list of layout objects maintained
683  * in the domain object and that m0_layout_find() returns the same object.
684  */
685 static int test_build_pdclust(uint32_t enum_id, uint64_t lid,
686  uint32_t inline_test,
687  bool failure_test)
688 {
689  struct m0_uint128 seed;
690  uint32_t N;
691  uint32_t K;
692  uint32_t S;
693  uint32_t P;
694  struct m0_pdclust_layout *pl;
695 // struct m0_layout_list_enum *list_enum;
696  struct m0_layout_linear_enum *lin_enum;
697  struct m0_layout *l;
698 
700 
701  m0_uint128_init(&seed, "buildpdclustlayo");
702 
704  inline_test, 9, 109, 12000,
705  &N, &K, &S, &P);
706 
708  N, K, S, P, &seed,
709  10, 20,
710  &pl, /*&list_enum, */&lin_enum,
711  failure_test);
712  if (failure_test)
713  M0_UT_ASSERT(rc == -ENOMEM || rc == -EPROTO);
714  else {
715  M0_UT_ASSERT(rc == 0);
716  /*
717  * Verify that m0_layout_find() returns the same object by
718  * reading it from the memory.
719  */
720  l = m0_layout_find(&domain, lid);
721  M0_UT_ASSERT(l == &pl->pl_base.sl_base);
722 
723  /* Verify the layout object built earlier here. */
725  N, K, S, P, &seed,
726  10, 20);
727  /* Release the reference acquired by m0_layout_find(). */
729 
730  /* Delete the layout object by reducing the last reference. */
732  M0_UT_ASSERT(list_lookup(lid) == NULL);
733  }
734 
735  m0_pool_fini(&pool);
736  return rc;
737 }
738 
739 /*
740  * Tests the APIs supported for enumeration object build, layout object build
741  * and layout destruction that happens using m0_layout_put().
742  */
743 static void test_build(void)
744 {
745  uint64_t lid;
746 
747 #if 0
748  /*
749  * Build a layout object with PDCLUST layout type, LIST enum type
750  * with a few inline entries only and then destroy it.
751  */
752  lid = 1001;
754  !FAILURE_TEST);
755  M0_UT_ASSERT(rc == 0);
756 
757  /*
758  * Build a layout object with PDCLUST layout type, LIST enum type
759  * with a number of inline entries exactly equal to
760  * LDB_MAX_INLINE_COB_ENTRIES and then destroy it.
761  */
762  lid = 1002;
764  !FAILURE_TEST);
765  M0_UT_ASSERT(rc == 0);
766 
767  /*
768  * Build a layout object with PDCLUST layout type, LIST enum type
769  * including noninline entries and then destroy it.
770  */
771  lid = 1003;
773  !FAILURE_TEST);
774  M0_UT_ASSERT(rc == 0);
775 #endif
776 
777  /*
778  * Build a layout object with PDCLUST layout type and LINEAR enum
779  * type and then destroy it.
780  */
781  lid = 1004;
783  !FAILURE_TEST);
784  M0_UT_ASSERT(rc == 0);
785 }
786 
787 static void test_build_failure(void)
788 {
789  uint64_t lid;
790 
791 #if 0
792  /*
793  * Simulate memory allocation failure in pdclust_allocate() that is
794  * in the path of m0_pdclust_build().
795  */
796  lid = 2001;
797  m0_fi_enable_once("pdclust_allocate", "mem_err");
799  FAILURE_TEST);
800  M0_UT_ASSERT(rc == -ENOMEM);
801 #endif
802 
803  /*
804  * Simulate memory allocation failure in pdclust_allocate() that is
805  * in the path of m0_pdclust_build().
806  */
807  lid = 2002;
808  m0_fi_enable_once("pdclust_allocate", "mem_err");
810  FAILURE_TEST);
811  M0_UT_ASSERT(rc == -ENOMEM);
812 
813 #if 0
814  /*
815  * Simulate invalid attributes error in pdclust_populate() that is
816  * in the path of m0_pdclust_build().
817  */
818  lid = 2003;
819  m0_fi_enable_once("pdclust_l_build", "attr_err");
821  FAILURE_TEST);
822  M0_UT_ASSERT(rc == -EPROTO);
823 
824  /*
825  * Simulate memory allocation failure in linear_allocate() that is
826  * in the path of m0_pdclust_build().
827  */
828  lid = 2004;
829  m0_fi_enable_once("list_allocate", "mem_err");
831  FAILURE_TEST);
832  M0_UT_ASSERT(rc == -ENOMEM);
833 #endif
834 
835  /*
836  * Simulate memory allocation failure in linear_allocate() that is
837  * in the path of m0_pdclust_build().
838  */
839  lid = 2005;
840  m0_fi_enable_once("linear_allocate", "mem_err");
842  FAILURE_TEST);
843  M0_UT_ASSERT(rc == -ENOMEM);
844 
845 #if 0
846  /* Simulate attributes invalid error in m0_list_enum_build(). */
847  lid = 2006;
848  m0_fi_enable_once("pdclust_layout_build", "list_attr_err");
850  FAILURE_TEST);
851  M0_UT_ASSERT(rc == -EPROTO);
852 #endif
853 
854  /* Simulate attributes invalid error in m0_linear_enum_build(). */
855  lid = 2007;
856  m0_fi_enable_once("pdclust_layout_build", "lin_attr_err");
858  FAILURE_TEST);
859  M0_UT_ASSERT(rc == -EPROTO);
860 
861 #if 0
862  /* Simulate fid invalid error in m0_list_enum_build(). */
863  lid = 2008;
864  m0_fi_enable_once("m0_list_enum_build", "fid_invalid_err");
866  FAILURE_TEST);
867  M0_UT_ASSERT(rc == -EPROTO);
868 #endif
869 }
870 
871 
872 /* Builds part of the buffer representing generic part of the layout object. */
873 static void buf_build(uint32_t lt_id, struct m0_bufvec_cursor *dcur)
874 {
875  struct m0_layout_rec rec;
876  m0_bcount_t nbytes_copied;
877 
878  rec.lr_lt_id = lt_id;
879  rec.lr_user_count = 0;
880 
881  nbytes_copied = m0_bufvec_cursor_copyto(dcur, &rec, sizeof rec);
882  M0_UT_ASSERT(nbytes_copied == sizeof rec);
883 }
884 
885 /*
886  * Builds part of the buffer representing generic and PDCLUST layout type
887  * specific parts of the layout object.
888  */
889 static void pdclust_buf_build(uint32_t let_id, uint64_t lid,
890  uint32_t N, uint32_t K,
891  uint32_t S, uint32_t P,
892  struct m0_uint128 *seed,
893  struct m0_bufvec_cursor *dcur)
894 {
895  struct m0_layout_pdclust_rec pl_rec;
896  m0_bcount_t nbytes_copied;
897 
899 
900  pl_rec.pr_let_id = let_id;
901  pl_rec.pr_attr.pa_N = N;
902  pl_rec.pr_attr.pa_K = K;
903  pl_rec.pr_attr.pa_S = S;
904  pl_rec.pr_attr.pa_P = P;
905  pl_rec.pr_attr.pa_unit_size = UNIT_SIZE;
906  pl_rec.pr_attr.pa_seed = *seed;
907 
908  nbytes_copied = m0_bufvec_cursor_copyto(dcur, &pl_rec, sizeof pl_rec);
909  M0_UT_ASSERT(nbytes_copied == sizeof pl_rec);
910 }
911 
912 /* Builds a buffer containing serialised representation of a layout object. */
913 static int pdclust_layout_buf_build(uint32_t enum_id, uint64_t lid,
914  uint32_t N, uint32_t K,
915  uint32_t S, uint32_t P,
916  struct m0_uint128 *seed,
917  uint32_t A, uint32_t B,
918  struct m0_bufvec_cursor *dcur)
919 {
920  uint32_t let_id;
921  m0_bcount_t nbytes_copied;
922 // struct cob_entries_header ce_header;
923 /* struct m0_fid cob_id;
924  uint32_t i;*/
925  struct m0_layout_linear_attr lin_rec;
926 
928  M0_UT_ASSERT(dcur != NULL);
929 
930  /*
931  * Build part of the buffer representing generic and the PDCLUST layout
932  * type specific parts of the layout object.
933  */
934  let_id = /*enum_id == LIST_ENUM_ID ? m0_list_enum_type.let_id :*/
936  pdclust_buf_build(let_id, lid, N, K, S, P, seed, dcur);
937 
938 #if 0
939  /*
940  * Build part of the buffer representing enum type specific part of
941  * the layout object.
942  */
943  if (enum_id == LIST_ENUM_ID) {
944  ce_header.ces_nr = P;
945  nbytes_copied = m0_bufvec_cursor_copyto(dcur, &ce_header,
946  sizeof ce_header);
947  M0_UT_ASSERT(nbytes_copied == sizeof ce_header);
948 
949  for (i = 0; i < ce_header.ces_nr; ++i) {
950  m0_fid_set(&cob_id, i * 100 + 1, i + 1);
951  nbytes_copied = m0_bufvec_cursor_copyto(dcur, &cob_id,
952  sizeof cob_id);
953  M0_UT_ASSERT(nbytes_copied == sizeof cob_id);
954  }
955  } else {
956 #endif
957  lin_rec.lla_nr = P;
958  lin_rec.lla_A = A;
959  lin_rec.lla_B = B;
960 
961  nbytes_copied = m0_bufvec_cursor_copyto(dcur, &lin_rec,
962  sizeof lin_rec);
963  M0_UT_ASSERT(nbytes_copied == sizeof lin_rec);
964 #if 0
965  }
966 #endif
967  return 0;
968 }
969 
970 /*
971  * Allocates area with size returned by m0_layout_max_recsize() and with
972  * additional_bytes required if any.
973  * For example, additional_bytes are required for LIST enumeration type, and
974  * specifically when directly invoking 'm0_layout_encode() or
975  * m0_layout_decode()' (and not while invoking Layout DB APIs like
976  * m0_layout_add() etc).
977  */
978 static void allocate_area(void **area,
979  m0_bcount_t additional_bytes,
980  m0_bcount_t *num_bytes)
981 {
982  M0_UT_ASSERT(area != NULL);
983 
984  *num_bytes = m0_layout_max_recsize(&domain) + additional_bytes;
985 
986  *area = m0_alloc(*num_bytes);
987  M0_UT_ASSERT(*area != NULL);
988 }
989 
990 /* Tests the API m0_layout_decode() for PDCLUST layout type. */
991 static int test_decode_pdclust(uint32_t enum_id, uint64_t lid,
992  uint32_t inline_test,
993  bool failure_test)
994 {
995  void *area;
996  m0_bcount_t num_bytes;
997  struct m0_bufvec bv;
998  struct m0_bufvec_cursor cur;
999  struct m0_layout *l;
1000  struct m0_uint128 seed;
1001  uint32_t N;
1002  uint32_t K;
1003  uint32_t S;
1004  uint32_t P;
1005  struct m0_layout_type *lt;
1006 
1007  M0_ENTRY();
1009 
1010  m0_uint128_init(&seed, "decodepdclustlay");
1011 
1012  /* Build a layout buffer. */
1013  if (enum_id == LIST_ENUM_ID)
1014  allocate_area(&area, ADDITIONAL_BYTES_DEFAULT, &num_bytes);
1015  else
1016  allocate_area(&area, ADDITIONAL_BYTES_NONE, &num_bytes);
1017 
1018  bv = (struct m0_bufvec) M0_BUFVEC_INIT_BUF(&area, &num_bytes);
1019  m0_bufvec_cursor_init(&cur, &bv);
1020 
1022  inline_test, 5, 125, 1500,
1023  &N, &K, &S, &P);
1024 
1026  N, K, S, P, &seed,
1027  777, 888, &cur);
1028  M0_UT_ASSERT(rc == 0);
1029 
1030  /* Rewind the cursor. */
1031  m0_bufvec_cursor_init(&cur, &bv);
1032 
1033  lt = &m0_pdclust_layout_type;
1034  rc = lt->lt_ops->lto_allocate(&domain, lid, &l);
1035  M0_UT_ASSERT(rc == 0);
1037 
1038  /* Decode the layout buffer into a layout object. */
1040  if (failure_test)
1041  M0_UT_ASSERT(rc == -ENOMEM || rc == -EPROTO);
1042  else {
1043  M0_UT_ASSERT(rc == 0);
1044  M0_UT_ASSERT(list_lookup(lid) == l);
1045 
1046  /* Verify the layout object built by m0_layout_decode(). */
1048  N, K, S, P, &seed,
1049  777, 888);
1050  }
1051 
1052  /* Destroy the layout object. */
1053  if (failure_test)
1054  l->l_ops->lo_delete(l);
1055  else {
1056  /* Unlock the layout, locked by lto_allocate() */
1057  m0_mutex_unlock(&l->l_lock);
1058  m0_layout_put(l);
1059  }
1060  M0_UT_ASSERT(list_lookup(lid) == NULL);
1061 
1062  m0_free(area);
1063  m0_pool_fini(&pool);
1064  M0_LEAVE();
1065  return rc;
1066 }
1067 
1068 /* Tests the API m0_layout_decode(). */
1069 static void test_decode(void)
1070 {
1071  uint64_t lid;
1072 
1073 #if 0
1074  /*
1075  * Decode a layout object with PDCLUST layout type, LIST enum type
1076  * with a few inline entries only.
1077  */
1078  lid = 3001;
1080  !FAILURE_TEST);
1081  M0_UT_ASSERT(rc == 0);
1082 
1083  /*
1084  * Decode a layout object with PDCLUST layout type, LIST enum type
1085  * with a number of inline entries exactly equal to
1086  * LDB_MAX_INLINE_COB_ENTRIES and then destroy it.
1087  */
1088  lid = 3002;
1090  !FAILURE_TEST);
1091  M0_UT_ASSERT(rc == 0);
1092 
1093  /*
1094  * Decode a layout object with PDCLUST layout type, LIST enum type
1095  * including noninline entries and then destroy it.
1096  */
1097  lid = 3003;
1099  !FAILURE_TEST);
1100  M0_UT_ASSERT(rc == 0);
1101 #endif
1102 
1103  /*
1104  * Decode a layout object with PDCLUST layout type and LINEAR enum
1105  * type.
1106  */
1107  lid = 3004;
1109  !FAILURE_TEST);
1110  M0_UT_ASSERT(rc == 0);
1111 }
1112 
1113 static void test_decode_failure(void)
1114 {
1115  uint64_t lid;
1116 
1117 #if 0
1118  /* Simulate invalid attributes error in m0_layout_decode(). */
1119  lid = 4001;
1120  m0_fi_enable_once("m0_layout_decode", "attr_err");
1122  FAILURE_TEST);
1123  M0_UT_ASSERT(rc == -EPROTO);
1124 
1125  /* Simulate invalid attributes error in pdclust_decode(). */
1126  lid = 4002;
1127  m0_fi_enable_once("pdclust_decode", "attr_err1");
1129  FAILURE_TEST);
1130  M0_UT_ASSERT(rc == -EPROTO);
1131 
1132  /* Simulate invalid attributes error in pdclust_decode(). */
1133  lid = 4003;
1134  m0_fi_enable_once("pdclust_decode", "attr_err2");
1136  FAILURE_TEST);
1137  M0_UT_ASSERT(rc == -EPROTO);
1138 
1139  /* Simulate invalid attributes error in list_populate(). */
1140  lid = 4004;
1141  m0_fi_enable_once("list_decode", "attr_err");
1143  FAILURE_TEST);
1144  M0_UT_ASSERT(rc == -EPROTO);
1145 #endif
1146 
1147  /* Simulate invalid attributes error in linear_populate(). */
1148  lid = 4005;
1149  m0_fi_enable_once("linear_decode", "attr_err");
1151  FAILURE_TEST);
1152  M0_UT_ASSERT(rc == -EPROTO);
1153 
1154 #if 0
1155  /* Simulate memory allocation failure in list_decode(). */
1156  lid = 4006;
1157  m0_fi_enable_once("list_decode", "mem_err");
1159  FAILURE_TEST);
1160  M0_UT_ASSERT(rc == -ENOMEM);
1161 
1162  /* Simulate fid invalid error in list_decode(). */
1163  lid = 4007;
1164  m0_fi_enable_once("list_decode", "fid_invalid_err");
1166  FAILURE_TEST);
1167  M0_UT_ASSERT(rc == -EPROTO);
1168 #endif
1169 
1170  /* Simulate leto_allocate() failure in pdclust_decode(). */
1171  lid = 4008;
1172  m0_fi_enable_once("linear_allocate", "mem_err");
1174  FAILURE_TEST);
1175  M0_UT_ASSERT(rc == -ENOMEM);
1176 
1177  /* Simulate pdclust_populate() failure in pdclust_decode(). */
1178  lid = 4009;
1179  m0_fi_enable_once("pdclust_decode", "attr_err3");
1181  FAILURE_TEST);
1182  M0_UT_ASSERT(rc == -EPROTO);
1183 }
1184 
1185 /*
1186  * Verifies part of the layout buffer representing generic part of the layout
1187  * object.
1188  */
1189 static void lbuf_verify(struct m0_bufvec_cursor *cur, uint32_t *lt_id)
1190 {
1191  struct m0_layout_rec *rec;
1192 
1193  M0_UT_ASSERT(m0_bufvec_cursor_step(cur) >= sizeof *rec);
1194 
1195  rec = m0_bufvec_cursor_addr(cur);
1196  M0_UT_ASSERT(rec != NULL);
1197 
1198  *lt_id = rec->lr_lt_id;
1199 
1200  M0_UT_ASSERT(rec->lr_user_count == 0);
1201 
1202  m0_bufvec_cursor_move(cur, sizeof *rec);
1203 }
1204 
1205 /*
1206  * Verifies part of the layout buffer representing PDCLUST layout type specific
1207  * part of the layout object.
1208  */
1209 static void pdclust_lbuf_verify(uint32_t N, uint32_t K,
1210  uint32_t S, uint32_t P,
1211  struct m0_uint128 *seed,
1212  struct m0_bufvec_cursor *cur,
1213  uint32_t *let_id)
1214 {
1215  struct m0_layout_pdclust_rec *pl_rec;
1216 
1217  M0_UT_ASSERT(m0_bufvec_cursor_step(cur) >= sizeof *pl_rec);
1218 
1219  pl_rec = m0_bufvec_cursor_addr(cur);
1220 
1221  M0_UT_ASSERT(pl_rec->pr_attr.pa_N == N);
1222  M0_UT_ASSERT(pl_rec->pr_attr.pa_K == K);
1223  M0_UT_ASSERT(pl_rec->pr_attr.pa_S == S);
1224  M0_UT_ASSERT(pl_rec->pr_attr.pa_P == P);
1227 
1228  *let_id = pl_rec->pr_let_id;
1229  m0_bufvec_cursor_move(cur, sizeof *pl_rec);
1230 }
1231 
1232 /* Verifies layout buffer against the various input arguments. */
1233 static void pdclust_layout_buf_verify(uint32_t enum_id, uint64_t lid,
1234  uint32_t N, uint32_t K,
1235  uint32_t S, uint32_t P,
1236  struct m0_uint128 *seed,
1237  uint32_t A, uint32_t B,
1238  struct m0_bufvec_cursor *cur)
1239 {
1240  uint32_t lt_id;
1241  uint32_t let_id;
1242 /* uint32_t i;
1243  struct cob_entries_header *ce_header;
1244  struct m0_fid *cob_id_from_layout;
1245  struct m0_fid cob_id_calculated;*/
1246  struct m0_layout_linear_attr *lin_attr;
1247 
1248  M0_UT_ASSERT(cur != NULL);
1250 
1251  /* Verify generic part of the layout buffer. */
1252  lbuf_verify(cur, &lt_id);
1254 
1255  /* Verify PDCLUST layout type specific part of the layout buffer. */
1256  pdclust_lbuf_verify(N, K, S, P, seed, cur, &let_id);
1257 
1258  /* Verify enum type specific part of the layout buffer. */
1259 #if 0
1260  if (enum_id == LIST_ENUM_ID) {
1262 
1263  M0_UT_ASSERT(m0_bufvec_cursor_step(cur) >= sizeof *ce_header);
1264 
1265  ce_header = m0_bufvec_cursor_addr(cur);
1266  M0_UT_ASSERT(ce_header != NULL);
1267  m0_bufvec_cursor_move(cur, sizeof *ce_header);
1268 
1269  M0_UT_ASSERT(ce_header->ces_nr == P);
1271  ce_header->ces_nr * sizeof *cob_id_from_layout);
1272 
1273  for (i = 0; i < ce_header->ces_nr; ++i) {
1274  cob_id_from_layout = m0_bufvec_cursor_addr(cur);
1275  M0_UT_ASSERT(cob_id_from_layout != NULL);
1276 
1277  m0_fid_set(&cob_id_calculated, i * 100 + 1, i + 1);
1278  M0_UT_ASSERT(m0_fid_eq(cob_id_from_layout,
1279  &cob_id_calculated));
1280 
1281  m0_bufvec_cursor_move(cur, sizeof *cob_id_from_layout);
1282  }
1283  } else {
1284 #endif
1286 
1287  M0_UT_ASSERT(m0_bufvec_cursor_step(cur) >= sizeof *lin_attr);
1288 
1289  lin_attr = m0_bufvec_cursor_addr(cur);
1290  M0_UT_ASSERT(lin_attr->lla_nr == P);
1291  M0_UT_ASSERT(lin_attr->lla_A == A);
1292  M0_UT_ASSERT(lin_attr->lla_B == B);
1293 #if 0
1294  }
1295 #endif
1296 }
1297 
1298 /* Tests the API m0_layout_encode() for PDCLUST layout type. */
1299 static int test_encode_pdclust(uint32_t enum_id, uint64_t lid,
1300  uint32_t inline_test,
1301  bool failure_test)
1302 {
1303  struct m0_pdclust_layout *pl;
1304  void *area;
1305  m0_bcount_t num_bytes;
1306  struct m0_bufvec bv;
1307  struct m0_bufvec_cursor cur;
1308  struct m0_uint128 seed;
1309  uint32_t N;
1310  uint32_t K;
1311  uint32_t S;
1312  uint32_t P;
1313 // struct m0_layout_list_enum *list_enum;
1314  struct m0_layout_linear_enum *lin_enum;
1315 
1316  M0_ENTRY("lid %llu", (unsigned long long)lid);
1318 
1319  m0_uint128_init(&seed, "encodepdclustlay");
1320 
1321  /* Build a layout object. */
1322  if (enum_id == LIST_ENUM_ID)
1323  allocate_area(&area, ADDITIONAL_BYTES_DEFAULT, &num_bytes);
1324  else
1325  allocate_area(&area, ADDITIONAL_BYTES_NONE, &num_bytes);
1326 
1327  bv = (struct m0_bufvec) M0_BUFVEC_INIT_BUF(&area, &num_bytes);
1328  m0_bufvec_cursor_init(&cur, &bv);
1329 
1331  inline_test, 10, 120, 120,
1332  &N, &K, &S, &P);
1333 
1335  N, K, S, P, &seed,
1336  11, 21,
1337  &pl, /*&list_enum, */&lin_enum,
1338  !FAILURE_TEST);
1339  M0_UT_ASSERT(rc == 0);
1340 
1341  /* Encode the layout object into a layout buffer. */
1344  NULL, &cur);
1346  if (failure_test)
1348  else
1349  M0_UT_ASSERT(rc == 0);
1350 
1351  /* Rewind the cursor. */
1352  m0_bufvec_cursor_init(&cur, &bv);
1353 
1354  /* Verify the layout buffer produced by m0_layout_encode(). */
1355  if (!failure_test)
1357  N, K, S, P, &seed,
1358  11, 21, &cur);
1359 
1360  /* Delete the layout object. */
1362  M0_UT_ASSERT(list_lookup(lid) == NULL);
1363  m0_free(area);
1364 
1365  m0_pool_fini(&pool);
1366  M0_LEAVE();
1367  return rc;
1368 }
1369 
1370 /* Tests the API m0_layout_encode(). */
1371 static void test_encode(void)
1372 {
1373  uint64_t lid;
1374  int rc;
1375 
1376 #if 0
1377  /*
1378  * Encode for PDCLUST layout type and LIST enumeration type,
1379  * with a few inline entries only.
1380  */
1381  lid = 5001;
1383  !FAILURE_TEST);
1384  M0_UT_ASSERT(rc == 0);
1385 
1386  /*
1387  * Encode for PDCLUST layout type and LIST enumeration type,
1388  * with a number of inline entries exactly equal to
1389  * LDB_MAX_INLINE_COB_ENTRIES.
1390  */
1391  lid = 5002;
1393  !FAILURE_TEST);
1394  M0_UT_ASSERT(rc == 0);
1395 
1396  /*
1397  * Encode for PDCLUST layout type and LIST enumeration type,
1398  * including noninline entries and then destroy it.
1399  */
1400  lid = 5003;
1402  !FAILURE_TEST);
1403  M0_UT_ASSERT(rc == 0);
1404 #endif
1405 
1406  /* Encode for PDCLUST layout type and LINEAR enumeration type. */
1407  lid = 5004;
1409  !FAILURE_TEST);
1410  M0_UT_ASSERT(rc == 0);
1411 }
1412 
1413 static void test_encode_failure(void)
1414 {
1415  uint64_t lid;
1416  int rc;
1417 
1418 #if 0
1419  /* Simulate m0_layout_encode() failure. */
1420  lid = 6001;
1421  m0_fi_enable_once("m0_layout_encode", "lo_encode_err");
1423  FAILURE_TEST);
1425 #endif
1426 
1427  /* Simulate m0_layout_encode() failure. */
1428  lid = 6002;
1429  m0_fi_enable_once("m0_layout_encode", "lo_encode_err");
1431  FAILURE_TEST);
1433 }
1434 
1435 
1436 /* Compares generic part of the layout buffers. */
1437 static void lbuf_compare(struct m0_bufvec_cursor *cur1,
1438  struct m0_bufvec_cursor *cur2)
1439 {
1440  struct m0_layout_rec *rec1;
1441  struct m0_layout_rec *rec2;
1442 
1443  M0_UT_ASSERT(m0_bufvec_cursor_step(cur1) >= sizeof *rec2);
1444  M0_UT_ASSERT(m0_bufvec_cursor_step(cur2) >= sizeof *rec2);
1445 
1446  rec1 = m0_bufvec_cursor_addr(cur1);
1447  rec2 = m0_bufvec_cursor_addr(cur2);
1448 
1449  M0_UT_ASSERT(rec1->lr_lt_id == rec2->lr_lt_id);
1450  M0_UT_ASSERT(rec1->lr_user_count == rec2->lr_user_count);
1451 
1452  m0_bufvec_cursor_move(cur1, sizeof *rec1);
1453  m0_bufvec_cursor_move(cur2, sizeof *rec2);
1454 }
1455 
1456 /* Compares PDCLUST layout type specific part of the layout buffers. */
1457 static void pdclust_lbuf_compare(struct m0_bufvec_cursor *cur1,
1458  struct m0_bufvec_cursor *cur2)
1459 {
1460  struct m0_layout_pdclust_rec *pl_rec1;
1461  struct m0_layout_pdclust_rec *pl_rec2;
1462 
1463  M0_UT_ASSERT(m0_bufvec_cursor_step(cur1) >= sizeof *pl_rec1);
1464  M0_UT_ASSERT(m0_bufvec_cursor_step(cur2) >= sizeof *pl_rec2);
1465 
1466  pl_rec1 = m0_bufvec_cursor_addr(cur1);
1467  pl_rec2 = m0_bufvec_cursor_addr(cur2);
1468 
1469  M0_UT_ASSERT(pl_rec1->pr_attr.pa_N == pl_rec2->pr_attr.pa_N);
1470  M0_UT_ASSERT(pl_rec1->pr_attr.pa_K == pl_rec2->pr_attr.pa_K);
1471  M0_UT_ASSERT(pl_rec1->pr_attr.pa_P == pl_rec2->pr_attr.pa_P);
1473  &pl_rec2->pr_attr.pa_seed));
1474  M0_UT_ASSERT(pl_rec1->pr_attr.pa_unit_size ==
1475  pl_rec2->pr_attr.pa_unit_size);
1476 
1477  m0_bufvec_cursor_move(cur1, sizeof *pl_rec1);
1478  m0_bufvec_cursor_move(cur2, sizeof *pl_rec2);
1479 }
1480 
1481 /* Compares two layout buffers provided as input arguments. */
1483  struct m0_bufvec_cursor *cur1,
1484  struct m0_bufvec_cursor *cur2)
1485 {
1486 /* struct cob_entries_header *ce_header1;
1487  struct cob_entries_header *ce_header2;
1488  struct m0_fid *cob_id1;
1489  struct m0_fid *cob_id2;*/
1490  struct m0_layout_linear_attr *lin_attr1;
1491  struct m0_layout_linear_attr *lin_attr2;
1492  //uint32_t i;
1493 
1494  M0_UT_ASSERT(cur1 != NULL);
1495  M0_UT_ASSERT(cur2 != NULL);
1497 
1498  /* Compare generic part of the layout buffers. */
1499  lbuf_compare(cur1, cur2);
1500 
1501  /* Compare PDCLUST layout type specific part of the layout buffers. */
1502  pdclust_lbuf_compare(cur1, cur2);
1503 
1504 #if 0
1505  /* Compare enumeration type specific part of the layout buffers. */
1506  if (enum_id == LIST_ENUM_ID) {
1507  M0_UT_ASSERT(m0_bufvec_cursor_step(cur1) >= sizeof *ce_header1);
1508  M0_UT_ASSERT(m0_bufvec_cursor_step(cur2) >= sizeof *ce_header2);
1509 
1510  ce_header1 = m0_bufvec_cursor_addr(cur1);
1511  ce_header2 = m0_bufvec_cursor_addr(cur2);
1512 
1513  m0_bufvec_cursor_move(cur1, sizeof *ce_header1);
1514  m0_bufvec_cursor_move(cur2, sizeof *ce_header2);
1515 
1516  M0_UT_ASSERT(ce_header1->ces_nr == ce_header2->ces_nr);
1517 
1519  ce_header1->ces_nr * sizeof *cob_id1);
1521  ce_header2->ces_nr * sizeof *cob_id2);
1522 
1523  for (i = 0; i < ce_header1->ces_nr; ++i) {
1524  cob_id1 = m0_bufvec_cursor_addr(cur1);
1525  cob_id2 = m0_bufvec_cursor_addr(cur2);
1526 
1527  M0_UT_ASSERT(m0_fid_eq(cob_id1, cob_id2));
1528 
1529  m0_bufvec_cursor_move(cur1, sizeof *cob_id1);
1530  m0_bufvec_cursor_move(cur2, sizeof *cob_id2);
1531  }
1532  } else {
1533 #endif
1534  M0_UT_ASSERT(m0_bufvec_cursor_step(cur1) >= sizeof *lin_attr1);
1535  M0_UT_ASSERT(m0_bufvec_cursor_step(cur2) >= sizeof *lin_attr2);
1536 
1537  lin_attr1 = m0_bufvec_cursor_addr(cur1);
1538  lin_attr2 = m0_bufvec_cursor_addr(cur2);
1539 
1540  M0_UT_ASSERT(lin_attr1->lla_nr == lin_attr2->lla_nr);
1541  M0_UT_ASSERT(lin_attr1->lla_A == lin_attr2->lla_A);
1542  M0_UT_ASSERT(lin_attr1->lla_B == lin_attr2->lla_B);
1543 #if 0
1544  }
1545 #endif
1546 }
1547 
1548 /*
1549  * Tests the API sequence m0_layout_decode() followed by m0_layout_encode(),
1550  * for the PDCLUST layout type.
1551  */
1552 static int test_decode_encode_pdclust(uint32_t enum_id, uint64_t lid,
1553  uint32_t inline_test)
1554 {
1555  void *area1;
1556  struct m0_bufvec bv1;
1557  struct m0_bufvec_cursor cur1;
1558  void *area2;
1559  struct m0_bufvec bv2;
1560  struct m0_bufvec_cursor cur2;
1561  m0_bcount_t num_bytes;
1562  uint32_t N;
1563  uint32_t K;
1564  uint32_t S;
1565  uint32_t P;
1566  struct m0_uint128 seed;
1567  struct m0_layout *l;
1568  struct m0_layout_type *lt;
1569 
1570  M0_ENTRY();
1572 
1573  m0_uint128_init(&seed, "decodeencodepdcl");
1574 
1575  /* Build a layout buffer. */
1576  if (enum_id == LIST_ENUM_ID)
1577  allocate_area(&area1, ADDITIONAL_BYTES_DEFAULT, &num_bytes);
1578  else
1579  allocate_area(&area1, ADDITIONAL_BYTES_NONE, &num_bytes);
1580 
1581  bv1 = (struct m0_bufvec) M0_BUFVEC_INIT_BUF(&area1, &num_bytes);
1582  m0_bufvec_cursor_init(&cur1, &bv1);
1583 
1585  inline_test, 3, 103, 1510,
1586  &N, &K, &S, &P);
1587 
1589  N, K, S, P, &seed,
1590  777, 888, &cur1);
1591  M0_UT_ASSERT(rc == 0);
1592 
1593  /* Rewind the cursor. */
1594  m0_bufvec_cursor_init(&cur1, &bv1);
1595 
1596  lt = &m0_pdclust_layout_type;
1597  rc = lt->lt_ops->lto_allocate(&domain, lid, &l);
1599 
1600  /* Decode the layout buffer into a layout object. */
1602  M0_UT_ASSERT(rc == 0);
1603 
1604  /* Unlock the layout, locked by lto_allocate() */
1605  m0_mutex_unlock(&l->l_lock);
1606 
1607  /* Rewind the cursor. */
1608  m0_bufvec_cursor_init(&cur1, &bv1);
1609 
1610  /*
1611  * Encode the layout object produced by m0_layout_decode() into
1612  * another layout buffer.
1613  */
1614  if (enum_id == LIST_ENUM_ID)
1615  allocate_area(&area2, ADDITIONAL_BYTES_DEFAULT, &num_bytes);
1616  else
1617  allocate_area(&area2, ADDITIONAL_BYTES_NONE, &num_bytes);
1618 
1619  bv2 = (struct m0_bufvec) M0_BUFVEC_INIT_BUF(&area2, &num_bytes);
1620  m0_bufvec_cursor_init(&cur2, &bv2);
1621 
1622  m0_mutex_lock(&l->l_lock);
1624  m0_mutex_unlock(&l->l_lock);
1625  M0_UT_ASSERT(rc == 0);
1626 
1627  /* Rewind the cursor. */
1628  m0_bufvec_cursor_init(&cur2, &bv2);
1629 
1630  /*
1631  * Compare the two layout buffers - one created earlier here and
1632  * the one that is produced by m0_layout_encode().
1633  */
1634  pdclust_layout_buf_compare(enum_id, &cur1, &cur2);
1635 
1636  /* Destroy the layout. */
1637  m0_layout_put(l);
1638  M0_UT_ASSERT(list_lookup(lid) == NULL);
1639 
1640  m0_free(area1);
1641  m0_free(area2);
1642  m0_pool_fini(&pool);
1643  M0_LEAVE();
1644  return rc;
1645 }
1646 
1647 /* Tests the API sequence m0_layout_decode() followed by m0_layout_encode(). */
1648 static void test_decode_encode(void)
1649 {
1650  uint64_t lid;
1651  int rc;
1652 
1653 #if 0
1654  /*
1655  * Build a layout buffer representing a layout with PDCLUST layout type
1656  * and LIST enum type, with a few inline entries only.
1657  * Decode it into a layout object. Then encode that layout object again
1658  * into another layout buffer.
1659  * Then, compare the original layout buffer with the encoded layout
1660  * buffer.
1661  */
1662  lid = 7001;
1664  M0_UT_ASSERT(rc == 0);
1665 
1666  /*
1667  * Build a layout buffer representing a layout with PDCLUST layout type
1668  * and LIST enum type, with a number of inline entries exactly equal to
1669  * LDB_MAX_INLINE_COB_ENTRIES.
1670  * Decode it into a layout object. Then encode that layout object again
1671  * into another layout buffer.
1672  * Then, compare the original layout buffer with the encoded layout
1673  * buffer.
1674  */
1675  lid = 7002;
1677  M0_UT_ASSERT(rc == 0);
1678 
1679  /*
1680  * Build a layout buffer representing a layout with PDCLUST layout type
1681  * and LIST enum type including noninline entries.
1682  * Decode it into a layout object. Then encode that layout object again
1683  * into another layout buffer.
1684  * Then, compare the original layout buffer with the encoded layout
1685  * buffer.
1686  */
1687  lid = 7003;
1689  M0_UT_ASSERT(rc == 0);
1690 #endif
1691 
1692  /*
1693  * Build a layout buffer representing a layout with PDCLUST layout type
1694  * and LINEAR enum type.
1695  * Decode it into a layout object. Then encode that layout object again
1696  * into another layout buffer.
1697  * Then, compare the original layout buffer with the encoded layout
1698  * buffer.
1699  */
1700  lid = 7004;
1703  M0_UT_ASSERT(rc == 0);
1704 }
1705 
1706 /*
1707  * Compares two layout objects with PDCLUST layout type, provided as input
1708  * arguments.
1709  */
1710 static void pdclust_layout_compare(uint32_t enum_id,
1711  const struct m0_layout *l1,
1712  const struct m0_layout *l2,
1713  bool l2_ref_elevated)
1714 {
1715  struct m0_pdclust_layout *pl1;
1716  struct m0_pdclust_layout *pl2;
1717 /* struct m0_layout_list_enum *list_e1;
1718  struct m0_layout_list_enum *list_e2;*/
1719  struct m0_layout_linear_enum *lin_e1;
1720  struct m0_layout_linear_enum *lin_e2;
1721 // uint32_t i;
1722 
1723  M0_UT_ASSERT(l1 != NULL && l2 != NULL);
1725 
1726  /* Compare generic part of the layout objects. */
1727  M0_UT_ASSERT(l1->l_id == l2->l_id);
1728  M0_UT_ASSERT(l1->l_type == l2->l_type);
1729  M0_UT_ASSERT(l1->l_dom == l2->l_dom);
1730  if (l2_ref_elevated)
1731  M0_UT_ASSERT(m0_ref_read(&l1->l_ref) ==
1732  m0_ref_read(&l2->l_ref) - 1);
1733  else
1734  M0_UT_ASSERT(m0_ref_read(&l1->l_ref) ==
1735  m0_ref_read(&l2->l_ref));
1737  M0_UT_ASSERT(l1->l_ops == l2->l_ops);
1738 
1739  /* Compare PDCLUST layout type specific part of the layout objects. */
1740  pl1 = container_of(l1, struct m0_pdclust_layout, pl_base.sl_base);
1741  pl2 = container_of(l2, struct m0_pdclust_layout, pl_base.sl_base);
1742 
1743  M0_UT_ASSERT(pl1->pl_attr.pa_N == pl2->pl_attr.pa_N);
1744  M0_UT_ASSERT(pl1->pl_attr.pa_K == pl2->pl_attr.pa_K);
1745  M0_UT_ASSERT(pl1->pl_attr.pa_S == pl2->pl_attr.pa_S);
1746  M0_UT_ASSERT(pl1->pl_attr.pa_P == pl2->pl_attr.pa_P);
1748  &pl2->pl_attr.pa_seed));
1749 
1750  /* Compare enumeration specific part of the layout objects. */
1752  pl2->pl_base.sl_enum->le_type);
1753  M0_UT_ASSERT(pl1->pl_base.sl_enum->le_sl == &pl1->pl_base);
1755  pl2->pl_base.sl_enum->le_sl->sl_base.l_id);
1757  pl2->pl_base.sl_enum->le_ops);
1758 
1759 #if 0
1760  /* Compare enumeration type specific part of the layout objects. */
1761  if (enum_id == LIST_ENUM_ID) {
1762  list_e1 = container_of(pl1->pl_base.sl_enum,
1763  struct m0_layout_list_enum, lle_base);
1764  list_e2 = container_of(pl2->pl_base.sl_enum,
1765  struct m0_layout_list_enum, lle_base);
1766 
1767  M0_UT_ASSERT(list_e1->lle_nr == list_e2->lle_nr);
1768 
1769  for (i = 0; i < list_e1->lle_nr; ++i)
1770  M0_UT_ASSERT(m0_fid_eq(&list_e1->lle_list_of_cobs[i],
1771  &list_e2->lle_list_of_cobs[i]));
1772  } else { /* LINEAR_ENUM_ID */
1773 #endif
1774  lin_e1 = container_of(pl1->pl_base.sl_enum,
1776  lin_e2 = container_of(pl2->pl_base.sl_enum,
1778 
1779  M0_UT_ASSERT(lin_e1->lle_attr.lla_nr ==
1780  lin_e2->lle_attr.lla_nr);
1781  M0_UT_ASSERT(lin_e1->lle_attr.lla_A == lin_e2->lle_attr.lla_A);
1782  M0_UT_ASSERT(lin_e1->lle_attr.lla_B == lin_e2->lle_attr.lla_B);
1783 #if 0
1784  }
1785 #endif
1786 }
1787 
1788 /* Copies contents of one layout object to the other. */
1789 static void pdclust_layout_copy(uint32_t enum_id,
1790  const struct m0_layout *l_src,
1791  struct m0_layout **l_dest)
1792 {
1793  struct m0_pdclust_layout *pl_src;
1794  struct m0_pdclust_layout *pl_dest;
1795 // struct m0_layout_list_enum *list_src;
1796 // struct m0_layout_list_enum *list_dest;
1797  struct m0_layout_linear_enum *lin_src;
1798  struct m0_layout_linear_enum *lin_dest;
1799 // uint32_t i;
1800 
1801  M0_UT_ASSERT(l_src != NULL && l_dest != NULL);
1803 
1804  pl_src = container_of(l_src, struct m0_pdclust_layout, pl_base.sl_base);
1805  pl_dest = m0_alloc(sizeof *pl_src);
1806  M0_UT_ASSERT(pl_dest != NULL);
1807  *l_dest = &pl_dest->pl_base.sl_base;
1808 
1809  /* Copy generic part of the layout object. */
1810  (*l_dest)->l_id = l_src->l_id;
1811  (*l_dest)->l_type = l_src->l_type;
1812  (*l_dest)->l_dom = l_src->l_dom;
1813  (*l_dest)->l_user_count = l_src->l_user_count;
1814  (*l_dest)->l_ops = l_src->l_ops;
1815  m0_ref_init(&(*l_dest)->l_ref, 1, l_src->l_ops->lo_fini);
1816 
1817  /* Copy PDCLUST layout type specific part of the layout objects. */
1818  pl_dest->pl_attr = pl_src->pl_attr;
1819 
1820 #if 0
1821  /* Copy enumeration type specific part of the layout objects. */
1822  if (enum_id == LIST_ENUM_ID) {
1823  list_src = container_of(pl_src->pl_base.sl_enum,
1824  struct m0_layout_list_enum, lle_base);
1825  list_dest = m0_alloc(sizeof *list_src);
1826  M0_UT_ASSERT(list_src != NULL);
1827 
1828  list_dest->lle_nr = list_src->lle_nr;
1829  M0_ALLOC_ARR(list_dest->lle_list_of_cobs, list_dest->lle_nr);
1830 
1831  for (i = 0; i < list_src->lle_nr; ++i)
1832  list_dest->lle_list_of_cobs[i] =
1833  list_src->lle_list_of_cobs[i];
1834 
1835  pl_dest->pl_base.sl_enum = &list_dest->lle_base;
1836  } else { /* LINEAR_ENUM_ID */
1837 #endif
1838  lin_src = container_of(pl_src->pl_base.sl_enum,
1840  lin_dest = m0_alloc(sizeof *lin_src);
1841  M0_UT_ASSERT(lin_src != NULL);
1842 
1843  lin_dest->lle_attr = lin_src->lle_attr;
1844  pl_dest->pl_base.sl_enum = &lin_dest->lle_base;
1845 #if 0
1846  }
1847 #endif
1848 
1849  /* Copy enumeration specific part of the layout objects. */
1850  pl_dest->pl_base.sl_enum->le_type = pl_src->pl_base.sl_enum->le_type;
1851  pl_dest->pl_base.sl_enum->le_ops = pl_src->pl_base.sl_enum->le_ops;
1852  pl_dest->pl_base.sl_enum->le_sl = &pl_dest->pl_base;
1853 
1855  &pl_dest->pl_base.sl_base, false);
1856 }
1857 
1858 static void pdclust_layout_copy_delete(uint32_t enum_id, struct m0_layout *l)
1859 {
1860  struct m0_pdclust_layout *pl;
1861 // struct m0_layout_list_enum *list_enum;
1862  struct m0_layout_linear_enum *lin_enum;
1863 
1864  M0_UT_ASSERT(l != NULL);
1866 
1867  pl = container_of(l, struct m0_pdclust_layout, pl_base.sl_base);
1868 #if 0
1869  if (enum_id == LIST_ENUM_ID) {
1870  list_enum = container_of(pl->pl_base.sl_enum,
1871  struct m0_layout_list_enum, lle_base);
1872  m0_free(list_enum->lle_list_of_cobs);
1873  m0_free(list_enum);
1874  } else { /* LINEAR_ENUM_ID */
1875 #endif
1876  lin_enum = container_of(pl->pl_base.sl_enum,
1878  m0_free(lin_enum);
1879 #if 0
1880  }
1881 #endif
1882  m0_free(pl);
1883 }
1884 
1885 /*
1886  * Tests the API sequence m0_layout_encode() followed by m0_layout_decode(),
1887  * for the PDCLUST layout type.
1888  */
1889 static int test_encode_decode_pdclust(uint32_t enum_id, uint64_t lid,
1890  uint32_t inline_test)
1891 {
1892  struct m0_pdclust_layout *pl;
1893  void *area;
1894  m0_bcount_t num_bytes;
1895  struct m0_bufvec bv;
1896  struct m0_bufvec_cursor cur;
1897  struct m0_uint128 seed;
1898  uint32_t N;
1899  uint32_t K;
1900  uint32_t S;
1901  uint32_t P;
1902  //struct m0_layout_list_enum *list_enum;
1903  struct m0_layout_linear_enum *lin_enum;
1904  struct m0_layout *l;
1905  struct m0_layout *l_copy;
1906  struct m0_layout_type *lt;
1907 
1908  M0_ENTRY("lid %llu", (unsigned long long)lid);
1910 
1911  m0_uint128_init(&seed, "encodedecodepdcl");
1912 
1913  /* Build a layout object. */
1914  if (enum_id == LIST_ENUM_ID)
1915  allocate_area(&area, ADDITIONAL_BYTES_DEFAULT, &num_bytes);
1916  else
1917  allocate_area(&area, ADDITIONAL_BYTES_NONE, &num_bytes);
1918 
1919  bv = (struct m0_bufvec) M0_BUFVEC_INIT_BUF(&area, &num_bytes);
1920  m0_bufvec_cursor_init(&cur, &bv);
1921 
1923  inline_test, 13, 113, 1130,
1924  &N, &K, &S, &P);
1925 
1927  N, K, S, P, &seed,
1928  10, 20,
1929  &pl, /*&list_enum, */&lin_enum,
1930  !FAILURE_TEST);
1931  M0_UT_ASSERT(rc == 0);
1932 
1933  pdclust_layout_copy(enum_id, &pl->pl_base.sl_base, &l_copy);
1934  M0_UT_ASSERT(l_copy != NULL);
1935 
1936  /* Encode the layout object into a layout buffer. */
1939  NULL, &cur);
1941  M0_UT_ASSERT(rc == 0);
1942 
1943  /* Destroy the layout. */
1945  M0_UT_ASSERT(list_lookup(lid) == NULL);
1946 
1947  /* Rewind the cursor. */
1948  m0_bufvec_cursor_init(&cur, &bv);
1949 
1950  lt = &m0_pdclust_layout_type;
1951  rc = lt->lt_ops->lto_allocate(&domain, lid, &l);
1953 
1954  /*
1955  * Decode the layout buffer produced by m0_layout_encode() into another
1956  * layout object.
1957  */
1959  M0_UT_ASSERT(rc == 0);
1960 
1961  /*
1962  * Comapre the two layout objects - one created earlier here and the
1963  * one that is produced by m0_layout_decode().
1964  */
1965  pdclust_layout_compare(enum_id, l_copy, l, false);
1967 
1968  /* Unlock the layout, locked by lto_allocate() */
1969  m0_mutex_unlock(&l->l_lock);
1970 
1971  /* Destroy the layout. */
1972  m0_layout_put(l);
1973  M0_UT_ASSERT(list_lookup(lid) == NULL);
1974 
1975  m0_free(area);
1976  m0_pool_fini(&pool);
1977  M0_LEAVE();
1978  return rc;
1979 }
1980 
1981 /* Tests the API sequence m0_layout_encode() followed by m0_layout_decode(). */
1982 static void test_encode_decode(void)
1983 {
1984  uint64_t lid;
1985  int rc;
1986 
1987 #if 0
1988  /*
1989  * Build a layout object with PDCLUST layout type and LIST enum type,
1990  * with a few inline entries only.
1991  * Encode it into a layout buffer. Then decode that layout buffer again
1992  * into another layout object.
1993  * Then, compare the original layout object with the decoded layout
1994  * object.
1995  */
1996  lid = 8001;
1998  M0_UT_ASSERT(rc == 0);
1999 
2000  /*
2001  * Build a layout object with PDCLUST layout type and LIST enum type,
2002  * with a number of inline entries exactly equal to
2003  * LDB_MAX_INLINE_COB_ENTRIES.
2004  * Encode it into a layout buffer. Then decode that layout buffer again
2005  * into another layout object.
2006  * Then, compare the original layout object with the decoded layout
2007  * object.
2008  */
2009  lid = 8002;
2011  M0_UT_ASSERT(rc == 0);
2012 
2013  /*
2014  * Build a layout object with PDCLUST layout type and LIST enum type
2015  * including noninline entries.
2016  * Encode it into a layout buffer. Then decode that layout buffer again
2017  * into another layout object.
2018  * Then, compare the original layout object with the decoded layout
2019  * object.
2020  */
2021  lid = 8003;
2023  M0_UT_ASSERT(rc == 0);
2024 #endif
2025 
2026  /*
2027  * Build a layout object with PDCLUST layout type and LINEAR enum type.
2028  * Encode it into a layout buffer. Then decode that layout buffer again
2029  * into a another layout object.
2030  * Now, compare the original layout object with the decoded layout
2031  * object.
2032  */
2033  lid = 8004;
2036  M0_UT_ASSERT(rc == 0);
2037 }
2038 
2039 /*
2040  * Tests the API m0_layout_get() and m0_layout_put(), for the PDCLUST layout
2041  * type.
2042  */
2043 static int test_ref_get_put_pdclust(uint32_t enum_id, uint64_t lid)
2044 {
2045  struct m0_pdclust_layout *pl;
2046  struct m0_uint128 seed;
2047  uint32_t N;
2048  uint32_t K;
2049  uint32_t S;
2050  uint32_t P;
2051  //struct m0_layout_list_enum *list_enum;
2052  struct m0_layout_linear_enum *lin_enum;
2053  uint32_t i;
2054 
2055  M0_ENTRY("lid %llu", (unsigned long long)lid);
2056  M0_UT_ASSERT(/*enum_id == LIST_ENUM_ID || */enum_id == LINEAR_ENUM_ID);
2057 
2058  m0_uint128_init(&seed, "refgetputpdclust");
2059 
2060  /* Build a layout object. */
2062  10, 1212, 1212,
2063  &N, &K, &S, &P);
2064 
2066  N, K, S, P, &seed,
2067  10, 20,
2068  &pl, /*&list_enum, */&lin_enum,
2069  !FAILURE_TEST);
2070  M0_UT_ASSERT(rc == 0);
2071 
2072  /* Verify that the ref count is set to 1. */
2074 
2075  /* Add multiple references on the layout object. */
2076  for (i = 0; i < 123; ++i)
2078  M0_UT_ASSERT(m0_ref_read(&pl->pl_base.sl_base.l_ref) == 1 + 123);
2079 
2080  /* Release multiple references on the layout object. */
2081  for (i = 0; i < 123; ++i)
2084 
2085  /* Release the last reference so as to delete the layout. */
2087  M0_UT_ASSERT(list_lookup(lid) == NULL);
2088 
2089  M0_LEAVE();
2090  return rc;
2091 }
2092 
2093 /* Tests the APIs m0_layout_get() and m0_layout_put(). */
2094 static void test_ref_get_put(void)
2095 {
2096  uint64_t lid;
2097  int rc;
2098 
2099 #if 0
2100  /*
2101  * Reference get and put operations for PDCLUST layout type and LIST
2102  * enumeration type.
2103  */
2104  lid = 9001;
2106  M0_UT_ASSERT(rc == 0);
2107 #endif
2108 
2109  /*
2110  * Reference get and put operations for PDCLUST layout type and LINEAR
2111  * enumeration type.
2112  */
2113  lid = 9002;
2115  M0_UT_ASSERT(rc == 0);
2116 }
2117 
2118 /* Verifies the enum operations pointed by leo_nr and leo_get. */
2119 static void enum_op_verify(uint32_t enum_id, uint64_t lid,
2120  uint32_t nr, struct m0_layout *l)
2121 {
2122  struct m0_striped_layout *stl;
2123  struct m0_layout_enum *e;
2124  struct m0_layout_linear_enum *lin_enum;
2125  struct m0_fid fid_calculated;
2126  struct m0_fid fid_from_layout;
2127  struct m0_fid gfid;
2128  int i;
2129 
2130  M0_UT_ASSERT(l != NULL);
2131 
2132  stl = m0_layout_to_striped(l);
2133  e = m0_striped_layout_to_enum(stl);
2135 
2136  if (enum_id == LIST_ENUM_ID) {
2137  for(i = 0; i < nr; ++i) {
2138  m0_fid_set(&fid_calculated, i * 100 + 1, i + 1);
2139  m0_layout_enum_get(e, i, NULL, &fid_from_layout);
2140  M0_UT_ASSERT(m0_fid_eq(&fid_calculated,
2141  &fid_from_layout));
2142  }
2143  } else {
2144  /* Set gfid to some dummy value. */
2145  m0_fid_gob_make(&gfid, 0, 999);
2146  lin_enum = container_of(e, struct m0_layout_linear_enum,
2147  lle_base);
2148  M0_UT_ASSERT(lin_enum != NULL);
2149  for(i = 0; i < nr; ++i) {
2150  m0_fid_convert_gob2cob(&gfid, &fid_calculated,
2151  lin_enum->lle_attr.lla_A +
2152  i * lin_enum->lle_attr.lla_B);
2153  m0_layout_enum_get(e, i, &gfid, &fid_from_layout);
2154  M0_UT_ASSERT(m0_fid_eq(&fid_calculated,
2155  &fid_from_layout));
2156  }
2157  }
2158 }
2159 
2160 /*
2161  * Tests the enum operations pointed by leo_nr and leo_get, for the PDCLUST
2162  * layout type.
2163  */
2164 static int test_enum_ops_pdclust(uint32_t enum_id, uint64_t lid,
2165  uint32_t inline_test)
2166 {
2167  struct m0_uint128 seed;
2168  uint32_t N;
2169  uint32_t K;
2170  uint32_t S;
2171  uint32_t P;
2172  struct m0_pdclust_layout *pl;
2173  //struct m0_layout_list_enum *list_enum;
2174  struct m0_layout_linear_enum *lin_enum;
2175 
2176  M0_ENTRY();
2178 
2179  /* Build a layout object. */
2180  m0_uint128_init(&seed, "enumopspdclustla");
2181 
2183  inline_test, 14, 1014, 1014,
2184  &N, &K, &S, &P);
2185 
2187  N, K, S, P, &seed,
2188  777, 888,
2189  &pl, /*&list_enum, */&lin_enum,
2190  !FAILURE_TEST);
2191  M0_UT_ASSERT(rc == 0);
2192 
2193  /* Verify enum operations. */
2194  enum_op_verify(enum_id, lid, P, &pl->pl_base.sl_base);
2195 
2196  /* Destroy the layout object. */
2198  M0_UT_ASSERT(list_lookup(lid) == NULL);
2199 
2200  m0_pool_fini(&pool);
2201  M0_LEAVE();
2202  return rc;
2203 }
2204 
2205 /* Tests the enum operations pointed by leo_nr and leo_get. */
2206 static void test_enum_operations(void)
2207 {
2208  uint64_t lid;
2209 
2210 #if 0
2211  /*
2212  * Decode a layout with PDCLUST layout type, LIST enum type and
2213  * with a few inline entries only.
2214  * And then verify its enum ops.
2215  */
2216  lid = 10001;
2218  M0_UT_ASSERT(rc == 0);
2219 
2220  /*
2221  * Decode a layout with PDCLUST layout type, LIST enum type and
2222  * with a number of inline entries exactly equal to
2223  * LDB_MAX_INLINE_COB_ENTRIES.
2224  * And then verify its enum ops.
2225  */
2226  lid = 10002;
2228  M0_UT_ASSERT(rc == 0);
2229 
2230  /*
2231  * Decode a layout with PDCLUST layout type and LIST enum type
2232  * including noninline entries.
2233  * And then verify its enum ops.
2234  */
2235  lid = 10003;
2237  M0_UT_ASSERT(rc == 0);
2238 #endif
2239 
2240  /*
2241  * Decode a layout with PDCLUST layout type and LINEAR enum type.
2242  * And then verify its enum ops.
2243  */
2244  lid = 10004;
2246  M0_UT_ASSERT(rc == 0);
2247 }
2248 
2249 /* Tests the API m0_layout_max_recsize(). */
2250 static void test_max_recsize(void)
2251 {
2252  struct m0_layout_domain *dom;
2253  m0_bcount_t max_size_from_api;
2254  m0_bcount_t max_size_calculated;
2255 
2256  M0_ENTRY();
2257 
2258  M0_ALLOC_PTR(dom);
2259  M0_UT_ASSERT(dom != NULL);
2260 
2261  /*
2262  * A layout type can be registered with only one domain at a time.
2263  * Hence, unregister all the available layout types and enum types from
2264  * the domain "domain", which are registered through test_init().
2265  */
2267 
2268  /* Initialise the domain. */
2270  M0_UT_ASSERT(rc == 0);
2271 
2272  /* Register pdclust layout type and verify m0_layout_max_recsize(). */
2274  M0_UT_ASSERT(rc == 0);
2275 
2276  max_size_from_api = m0_layout_max_recsize(dom);
2277 
2278  max_size_calculated = sizeof(struct m0_layout_rec) +
2279  sizeof(struct m0_layout_pdclust_rec);
2280 
2281  M0_UT_ASSERT(max_size_from_api == max_size_calculated);
2282 
2283  /* Register linear enum type and verify m0_layout_max_recsize(). */
2285  M0_UT_ASSERT(rc == 0);
2286 
2287  max_size_from_api = m0_layout_max_recsize(dom);
2288 
2289  max_size_calculated = sizeof(struct m0_layout_rec) +
2290  sizeof(struct m0_layout_pdclust_rec) +
2291  sizeof(struct m0_layout_linear_attr);
2292 
2293  M0_UT_ASSERT(max_size_from_api == max_size_calculated);
2294 
2295 #if 0
2296  /* Register list enum type and verify m0_layout_max_recsize(). */
2298  M0_UT_ASSERT(rc == 0);
2299 
2300  max_size_from_api = m0_layout_max_recsize(dom);
2301 
2302  max_size_calculated = sizeof(struct m0_layout_rec) +
2303  sizeof(struct m0_layout_pdclust_rec) +
2304  sizeof(struct cob_entries_header) +
2306  sizeof(struct m0_fid);
2307 
2308  M0_UT_ASSERT(max_size_from_api == max_size_calculated);
2309 
2310  /* Unregister list enum type and verify m0_layout_max_recsize(). */
2312 
2313  max_size_from_api = m0_layout_max_recsize(dom);
2314 
2315  max_size_calculated = sizeof(struct m0_layout_rec) +
2316  sizeof(struct m0_layout_pdclust_rec) +
2317  sizeof(struct m0_layout_linear_attr);
2318 
2319  M0_UT_ASSERT(max_size_from_api == max_size_calculated);
2320 #endif
2321 
2322  /* Unregister linear enum type and verify m0_layout_max_recsize(). */
2324 
2325  max_size_from_api = m0_layout_max_recsize(dom);
2326 
2327  max_size_calculated = sizeof(struct m0_layout_rec) +
2328  sizeof(struct m0_layout_pdclust_rec);
2329 
2330  M0_UT_ASSERT(max_size_from_api == max_size_calculated);
2331 
2332  /* Unregister pdclust layout type and verify m0_layout_max_recsize(). */
2334 
2335  max_size_from_api = m0_layout_max_recsize(dom);
2336 
2337  max_size_calculated = sizeof(struct m0_layout_rec);
2338 
2339  M0_UT_ASSERT(max_size_from_api == max_size_calculated);
2340 
2341  /* Finalise the domain. */
2343 
2344  /*
2345  * Register back all the available layout types and enum types with
2346  * the domain "domain", to undo the change done at the beginning of
2347  * this function.
2348  */
2350  M0_ASSERT(rc == 0);
2351 
2352  m0_free(dom);
2353 
2354  M0_LEAVE();
2355 }
2356 
2357 /*
2358  * Calculates the recsize by considering the sizes of the internal data
2359  * structures and their values, as applicable. Then verifies that the recsize
2360  * provided as an argument matches the calcualted one.
2361  */
2362 static void pdclust_recsize_verify(uint32_t enum_id,
2363  struct m0_layout *l,
2364  m0_bcount_t recsize_to_verify)
2365 {
2366  //struct m0_pdclust_layout *pl;
2367  //struct m0_layout_list_enum *list_enum;
2368  m0_bcount_t recsize;
2369 
2370  M0_UT_ASSERT(l != NULL);
2372  M0_UT_ASSERT(l->l_type == &m0_pdclust_layout_type);
2373 
2374 #if 0
2375  pl = container_of(l, struct m0_pdclust_layout, pl_base.sl_base);
2376 
2377  /* Account for the enum type specific recsize. */
2378  if (enum_id == LIST_ENUM_ID) {
2379  list_enum = container_of(pl->pl_base.sl_enum,
2380  struct m0_layout_list_enum, lle_base);
2381  if (list_enum->lle_nr < LDB_MAX_INLINE_COB_ENTRIES)
2382  recsize = sizeof(struct cob_entries_header) +
2383  list_enum->lle_nr * sizeof(struct m0_fid);
2384  else
2385  recsize = sizeof(struct cob_entries_header) +
2387  sizeof(struct m0_fid);
2388  } else
2389 #endif
2390  recsize = sizeof(struct m0_layout_linear_attr);
2391 
2392  /*
2393  * Account for the recsize for the generic part of the layout object
2394  * and for the PDCLUST layout type specific part of it.
2395  */
2396  recsize = sizeof(struct m0_layout_rec) +
2397  sizeof(struct m0_layout_pdclust_rec) + recsize;
2398 
2399  /* Compare the two sizes. */
2400  M0_UT_ASSERT(recsize == recsize_to_verify);
2401 }
2402 
2403 /* Tests the function lo_recsize(), for the PDCLUST layout type. */
2404 static int test_recsize_pdclust(uint32_t enum_id, uint64_t lid,
2405  uint32_t inline_test)
2406 {
2407  struct m0_pdclust_layout *pl;
2408  struct m0_layout *l;
2409  struct m0_uint128 seed;
2410  uint32_t N;
2411  uint32_t K;
2412  uint32_t S;
2413  uint32_t P;
2414  //struct m0_layout_list_enum *list_enum;
2415  struct m0_layout_linear_enum *lin_enum;
2416  m0_bcount_t recsize;
2417 
2418  M0_ENTRY("lid %llu", (unsigned long long)lid);
2420 
2421  m0_uint128_init(&seed, "recsizepdclustla");
2422 
2423  /* Build a layout object. */
2425  inline_test, 1, 1200, 1111,
2426  &N, &K, &S, &P);
2427 
2429  N, K, S, P, &seed,
2430  10, 20,
2431  &pl, /*&list_enum, */&lin_enum,
2432  !FAILURE_TEST);
2433  M0_UT_ASSERT(rc == 0);
2434 
2435  /* Obtain the recsize by using the internal function lo_recsize(). */
2436  l = &pl->pl_base.sl_base;
2437  recsize = l->l_ops->lo_recsize(l);
2438 
2439  /* Verify the recsize returned by lo_recsize(). */
2441 
2442  /* Destroy the layout object. */
2443  m0_layout_put(l);
2444  M0_UT_ASSERT(list_lookup(lid) == NULL);
2445 
2446  m0_pool_fini(&pool);
2447  M0_LEAVE();
2448  return rc;
2449 }
2450 
2451 /* Tests the function lo_recsize(). */
2452 static void test_recsize(void)
2453 {
2454  uint64_t lid;
2455  int rc;
2456 
2457 #if 0
2458  /*
2459  * lo_recsize() for PDCLUST layout type and LIST enumeration type,
2460  * with a few inline entries only.
2461  */
2462  lid = 11001;
2464  M0_UT_ASSERT(rc == 0);
2465 
2466  /*
2467  * lo_recsize() for PDCLUST layout type and LIST enumeration type,
2468  * with a number of inline entries exactly equal to
2469  * LDB_MAX_INLINE_COB_ENTRIES
2470  */
2471  lid = 11002;
2473  M0_UT_ASSERT(rc == 0);
2474 
2475  /*
2476  * lo_recsize() for PDCLUST layout type and LIST enumeration type
2477  * including noninline entries.
2478  */
2479  lid = 11003;
2481  M0_UT_ASSERT(rc == 0);
2482 #endif
2483 
2484  /* lo_recsize() for PDCLUST layout type and LINEAR enumeration type. */
2485  lid = 11004;
2487  M0_UT_ASSERT(rc == 0);
2488 }
2489 
2490 static void ldemo(struct m0_pdclust_instance *pi,
2491  const struct m0_pdclust_layout *pl)
2492 {
2493  struct m0_pdclust_src_addr src;
2494  struct m0_pdclust_tgt_addr tgt;
2495  struct m0_pdclust_src_addr src1;
2496  struct m0_pdclust_attr attr = pl->pl_attr;
2497  uint32_t W;
2498  uint32_t unit;
2499 
2500  W = attr.pa_N + attr.pa_K + attr.pa_S;
2501  src.sa_group = 0;
2502  for (unit = 0; unit < W; ++unit) {
2503  src.sa_unit = unit;
2505  m0_pdclust_instance_inv(pi, &tgt, &src1);
2506  M0_ASSERT(memcmp(&src, &src1, sizeof src) == 0);
2507  }
2508 }
2509 
2510 /* Tests the APIs supported for m0_pdclust_instance object. */
2511 static int test_pdclust_instance_obj(uint32_t enum_id, uint64_t lid,
2512  bool inline_test, bool failure_test)
2513 {
2514  struct m0_uint128 seed;
2515  uint32_t N;
2516  uint32_t K;
2517  uint32_t S;
2518  uint32_t P;
2519  uint32_t i;
2520  uint32_t cache_nr;
2521  uint64_t *cache_len;
2522  struct m0_layout *l;
2523  struct m0_pdclust_layout *pl;
2524  struct m0_pool_version pool_ver;
2525  //struct m0_layout_list_enum *list_enum;
2526  struct m0_layout_linear_enum *lin_enum;
2527  struct m0_pdclust_instance *pi;
2528  struct m0_fid gfid;
2529  struct m0_layout_instance *li;
2530 
2532 
2533  m0_uint128_init(&seed, "buildpdclustlayo");
2534 
2536  inline_test, 14, 30, 30,
2537  &N, &K, &S, &P);
2538 
2540  N, K, S, P, &seed,
2541  10, 20,
2542  &pl, /*&list_enum, */&lin_enum,
2543  !FAILURE_TEST);
2544  M0_UT_ASSERT(rc == 0);
2545 
2546  /* Verify some pdclust APIs. */
2547  M0_UT_ASSERT(m0_pdclust_N(pl) == N);
2548  M0_UT_ASSERT(m0_pdclust_K(pl) == K);
2549  M0_UT_ASSERT(m0_pdclust_S(pl) == S);
2550  M0_UT_ASSERT(m0_pdclust_P(pl) == P);
2552 
2556 
2557  /* Build pdclust instance. */
2558  m0_fid_set(&gfid, 0, 999);
2559  l = m0_pdl_to_layout(pl);
2560  M0_UT_ASSERT(m0_ref_read(&l->l_ref) == 1);
2561  cache_nr = 4;
2563  M0_ALLOC_ARR(cache_len, cache_nr);
2564  M0_UT_ASSERT(cache_len != NULL);
2566  for (i = 0; i < cache_nr; ++i) {
2568  }
2569  l->l_pver = &pool_ver;
2570  rc = m0_layout_instance_build(l, &gfid, &li);
2571  if (failure_test) {
2572  M0_UT_ASSERT(rc == -ENOMEM || rc == -EPROTO);
2573  }
2574  else {
2575  M0_UT_ASSERT(rc == 0);
2576  M0_UT_ASSERT(m0_ref_read(&l->l_ref) == 2);
2578  ldemo(pi, pl);
2579 
2580  /* Verify m0_layout_instance_to_pdi(). */
2581  li = &pi->pi_base;
2583 
2584 #if 0
2585  /* Verify m0_layout_instance_to_enum */
2586  if (enum_id == LIST_ENUM_ID)
2588  &list_enum->lle_base);
2589  else
2590 #endif
2592  &lin_enum->lle_base);
2593 
2594  /* Delete the pdclust instance object. */
2596  M0_UT_ASSERT(m0_ref_read(&l->l_ref) == 1);
2597  }
2598 
2599  /* Delete the layout object. */
2601  M0_UT_ASSERT(list_lookup(lid) == NULL);
2602  m0_pool_fini(&pool);
2603  m0_free(cache_len);
2604  return rc;
2605 }
2606 
2607 /*
2608  * Tests the APIs supported for m0_pdclust_instance object, for various enum
2609  * types.
2610  */
2611 static void test_pdclust_instance(void)
2612 {
2613  uint64_t lid;
2614 
2615 #if 0
2616  /*
2617  * Build a layout object with PDCLUST layout type, LIST enum type
2618  * with a few inline entries only and then destroy it.
2619  */
2620  lid = 12001;
2622  !FAILURE_TEST);
2623  M0_UT_ASSERT(rc == 0);
2624 
2625  /*
2626  * Build a layout object with PDCLUST layout type, LIST enum type
2627  * with a number of inline entries exactly equal to
2628  * LDB_MAX_INLINE_COB_ENTRIES and then destroy it.
2629  */
2630  lid = 12002;
2632  !FAILURE_TEST);
2633  M0_UT_ASSERT(rc == 0);
2634 
2635  /*
2636  * Build a layout object with PDCLUST layout type, LIST enum type
2637  * including noninline entries and then destroy it.
2638  */
2639  lid = 12003;
2641  !FAILURE_TEST);
2642  M0_UT_ASSERT(rc == 0);
2643 #endif
2644 
2645  /*
2646  * Build a layout object with PDCLUST layout type and LINEAR enum
2647  * type and then destroy it.
2648  */
2649  lid = 12004;
2652  !FAILURE_TEST);
2653  M0_UT_ASSERT(rc == 0);
2654 }
2655 
2657 {
2658  uint64_t lid;
2659 
2660 #if 0
2661  /* Simulate memory allocation error in m0_pdclust_instance_build(). */
2662  lid = 13001;
2663  m0_fi_enable_once("pdclust_instance_build", "mem_err1");
2665  FAILURE_TEST);
2666  M0_UT_ASSERT(rc == -ENOMEM);
2667 #endif
2668 
2669  /* Simulate memory allocation error in m0_pdclust_instance_build(). */
2670  lid = 13002;
2671  m0_fi_enable_once("pdclust_instance_build", "mem_err2");
2674  FAILURE_TEST);
2675  M0_UT_ASSERT(rc == -ENOMEM);
2676 
2677  /*
2678  * Simulate m0_parity_math_init() error in
2679  * m0_pdclust_instance_build().
2680  */
2681  lid = 13003;
2682  m0_fi_enable_once("pdclust_instance_build", "parity_math_err");
2685  FAILURE_TEST);
2686  M0_UT_ASSERT(rc == -EPROTO);
2687 }
2688 
2689 #if 0
2690 #ifndef __KERNEL__
2691 /*
2692  * Sets (or resets) the pair using the area pointer and the layout id provided
2693  * as arguments.
2694  */
2695 static void pair_set(struct m0_db_pair *pair, uint64_t *lid,
2696  void *area, m0_bcount_t num_bytes)
2697 {
2698  pair->dp_key.db_buf.b_addr = lid;
2699  pair->dp_key.db_buf.b_nob = sizeof *lid;
2700  pair->dp_rec.db_buf.b_addr = area;
2701  pair->dp_rec.db_buf.b_nob = num_bytes;
2702 }
2703 
2704 static int test_add_pdclust(uint32_t enum_id, uint64_t lid,
2705  uint32_t inline_test,
2706  bool layout_destroy, struct m0_layout **l_obj,
2707  bool duplicate_test,
2708  bool failure_test);
2709 
2710 /* Tests the API m0_layout_lookup(), for the PDCLUST layout type. */
2711 static int test_lookup_pdclust(uint32_t enum_id, uint64_t lid,
2712  bool existing_test,
2713  uint32_t inline_test,
2714  bool failure_test)
2715 {
2716  m0_bcount_t num_bytes;
2717  void *area;
2718  struct m0_layout *l1;
2719  struct m0_layout *l1_copy;
2720  struct m0_layout *l2;
2721  struct m0_layout *l3;
2722  struct m0_db_pair pair;
2723  struct m0_db_tx tx;
2724  int rc_tmp;
2725 
2726  M0_ENTRY();
2728  M0_UT_ASSERT(ergo(!existing_test, failure_test));
2729 
2730  /*
2731  * If existing_test is true, then first add a layout object to the
2732  * DB.
2733  */
2734  if (existing_test) {
2735  rc = test_add_pdclust(enum_id, lid,
2736  inline_test,
2737  !LAYOUT_DESTROY, &l1,
2738  !DUPLICATE_TEST,
2739  !FAILURE_TEST);
2740  M0_UT_ASSERT(rc == 0);
2741  if (!failure_test)
2742  pdclust_layout_copy(enum_id, l1, &l1_copy);
2743 
2744  /*
2745  * Lookup for the layout object to verify that the same object
2746  * is returned from the memory, not requiring a lookup from the
2747  * DB.
2748  */
2750  &tx, &pair, &l2);
2751  M0_UT_ASSERT(rc == 0);
2752  M0_UT_ASSERT(l2 == l1);
2753 
2754  /* Release the reference acquired by m0_layout_lookup(). */
2755  m0_layout_put(l1);
2756 
2757  /* Destroy the layout object. */
2758  m0_layout_put(l1);
2759  }
2760 
2761  M0_UT_ASSERT(list_lookup(lid) == NULL);
2763 
2764  /* Lookup for the layout object from the DB. */
2765  allocate_area(&area, ADDITIONAL_BYTES_NONE, &num_bytes);
2766 
2767  rc = m0_db_tx_init(&tx, &dbenv, DBFLAGS);
2768  M0_UT_ASSERT(rc == 0);
2769 
2770  pair_set(&pair, &lid, area, num_bytes);
2771 
2773  &tx, &pair, &l3);
2774  if (failure_test)
2775  M0_UT_ASSERT(rc == -ENOENT || rc == -ENOMEM || rc == -EPROTO ||
2776  rc == LO_DECODE_ERR);
2777  else
2778  M0_UT_ASSERT(rc == 0);
2779 
2780  rc_tmp = m0_db_tx_commit(&tx);
2781  M0_UT_ASSERT(rc_tmp == 0);
2782 
2783  if (existing_test && !failure_test) {
2784  M0_UT_ASSERT(list_lookup(lid) == l3);
2785  pdclust_layout_compare(enum_id, l1_copy, l3, false);
2787 
2788  /* Destroy the layout object. */
2789  m0_layout_put(l3);
2790  M0_UT_ASSERT(list_lookup(lid) == NULL);
2791  }
2792  m0_free(area);
2793  M0_LEAVE();
2794  return rc;
2795 }
2796 
2797 struct ghost_data {
2798  uint64_t lid;
2799  struct m0_layout *l;
2800  struct m0_bufvec_cursor *cur;
2801 };
2802 
2803 static bool ghost_create(void *d)
2804 {
2805  struct ghost_data *data = d;
2806  struct m0_layout_type *lt;
2807 
2808  M0_ENTRY();
2809  M0_UT_ASSERT(list_lookup(data->lid) == NULL);
2810 
2811  lt = &m0_pdclust_layout_type;
2812  rc = lt->lt_ops->lto_allocate(&domain, data->lid, &data->l);
2813  M0_UT_ASSERT(rc == 0);
2814 
2815  /* Decode the layout buffer stored in the ghost_data. */
2817  M0_UT_ASSERT(rc == 0);
2818 
2819  /* Unlock the layout, locked by lto_allocate() */
2820  m0_mutex_unlock(&data->l->l_lock);
2821 
2822  M0_LEAVE();
2823  return rc;
2824 }
2825 
2826 static int test_lookup_with_ghost_creation(uint32_t enum_id, uint64_t lid,
2827  uint32_t inline_test)
2828 {
2829  struct m0_layout *l1;
2830  struct m0_layout *l1_copy;
2831  struct ghost_data g_data = { 0 };
2832  void *area_for_encode;
2833  m0_bcount_t num_bytes_for_encode;
2834  struct m0_bufvec bv_for_encode;
2835  struct m0_bufvec_cursor cur_for_encode;
2836  struct m0_layout *l_from_DB;
2837  m0_bcount_t num_bytes_for_lookup;
2838  void *area_for_lookup;
2839  struct m0_db_pair pair;
2840  struct m0_db_tx tx;
2841  int rc_tmp;
2842 
2843  M0_ENTRY();
2845 
2846  /* Create one layout object and add it to the LDB. */
2847  rc = test_add_pdclust(enum_id, lid,
2848  inline_test,
2849  !LAYOUT_DESTROY, &l1,
2850  !DUPLICATE_TEST,
2851  !FAILURE_TEST);
2852  M0_UT_ASSERT(rc == 0);
2853  pdclust_layout_copy(enum_id, l1, &l1_copy);
2854 
2855  /*
2856  * Encode the layout object and store its encoded representation into
2857  * the ghost_data (g_data.cur) so that the ghost can be created at a
2858  * later point.
2859  */
2860  if (enum_id == LIST_ENUM_ID)
2861  allocate_area(&area_for_encode, ADDITIONAL_BYTES_DEFAULT,
2862  &num_bytes_for_encode);
2863  else
2864  allocate_area(&area_for_encode, ADDITIONAL_BYTES_NONE,
2865  &num_bytes_for_encode);
2866  bv_for_encode = (struct m0_bufvec) M0_BUFVEC_INIT_BUF(&area_for_encode,
2867  &num_bytes_for_encode);
2868  m0_bufvec_cursor_init(&cur_for_encode, &bv_for_encode);
2869  m0_mutex_lock(&l1->l_lock);
2870  rc = m0_layout_encode(l1, M0_LXO_BUFFER_OP, NULL, &cur_for_encode);
2871  m0_mutex_unlock(&l1->l_lock);
2872  M0_UT_ASSERT(rc == 0);
2873  /* Rewind the cursor. */
2874  m0_bufvec_cursor_init(&cur_for_encode, &bv_for_encode);
2875  g_data.cur = &cur_for_encode;
2876  g_data.lid = lid;
2877 
2878  /*
2879  * Destroy the layout object, so that the next m0_layout_lookup() does
2880  * not return right away with the layout object read from memory and
2881  * instead goes to the LDB to read it.
2882  */
2883  m0_layout_put(l1);
2884  M0_UT_ASSERT(list_lookup(lid) == NULL);
2885 
2886  /*
2887  * Lookup for the layout object from the LDB, using m0_layout_lookup().
2888  * But while this m0_layout_lookup() is in progress, ghost_create()
2889  * will create another in-memory layout object using m0_layout_decode()
2890  * performed on the serialised representation of the same layout
2891  * created above and stored in g_data.cur.
2892  */
2893  if (enum_id == LIST_ENUM_ID)
2894  allocate_area(&area_for_lookup, ADDITIONAL_BYTES_DEFAULT,
2895  &num_bytes_for_lookup);
2896  else
2897  allocate_area(&area_for_lookup, ADDITIONAL_BYTES_NONE,
2898  &num_bytes_for_lookup);
2899 
2900  rc = m0_db_tx_init(&tx, &dbenv, DBFLAGS);
2901  M0_UT_ASSERT(rc == 0);
2902 
2903  pair_set(&pair, &lid, area_for_lookup, num_bytes_for_lookup);
2904  m0_fi_enable_func("m0_layout_lookup", "ghost_creation",
2905  ghost_create, &g_data);
2907  &tx, &pair, &l_from_DB);
2908  M0_UT_ASSERT(rc == 0);
2909  m0_layout_put(l_from_DB);
2910  m0_fi_disable("m0_layout_lookup", "ghost_creation");
2911  rc_tmp = m0_db_tx_commit(&tx);
2912  M0_UT_ASSERT(rc_tmp == 0);
2913 
2914  M0_UT_ASSERT(l_from_DB == g_data.l);
2915  M0_UT_ASSERT(list_lookup(lid) == l_from_DB);
2916  pdclust_layout_compare(enum_id, l1_copy, l_from_DB, false);
2918 
2919  /* Destroy the layout object. */
2920  m0_layout_put(l_from_DB);
2921  M0_UT_ASSERT(list_lookup(lid) == NULL);
2922 
2923  m0_free(area_for_encode);
2924  m0_free(area_for_lookup);
2925  M0_LEAVE();
2926  return rc;
2927 }
2928 
2929 /* Tests the API m0_layout_lookup(). */
2930 static void test_lookup(void)
2931 {
2932  uint64_t lid;
2933 
2934 #if 0
2935  /*
2936  * Lookup for a layout object with LIST enum type, that does not
2937  * exist in the DB.
2938  */
2939  lid = 14001;
2940  rc = test_lookup_pdclust(LIST_ENUM_ID, lid,
2941  !EXISTING_TEST,
2943  FAILURE_TEST);
2944  M0_UT_ASSERT(rc == -ENOENT);
2945 
2946  /*
2947  * Add a layout object with PDCLUST layout type, LIST enum type and
2948  * with a few inline entries only. Then perform lookup for it.
2949  */
2950  lid = 14002;
2951  rc = test_lookup_pdclust(LIST_ENUM_ID, lid,
2952  EXISTING_TEST,
2954  !FAILURE_TEST);
2955  M0_UT_ASSERT(rc == 0);
2956 
2957  /*
2958  * Add a layout object with PDCLUST layout type, LIST enum type and
2959  * with a number of inline entries exactly equal to
2960  * LDB_MAX_INLINE_COB_ENTRIES. Then perform lookup for it.
2961  */
2962  lid = 14003;
2963  rc = test_lookup_pdclust(LIST_ENUM_ID, lid,
2964  EXISTING_TEST,
2965  EXACT_INLINE,
2966  !FAILURE_TEST);
2967  M0_UT_ASSERT(rc == 0);
2968 
2969  /*
2970  * Add a layout object with PDCLUST layout type, LIST enum type
2971  * including noninline entries.
2972  * Then perform lookup for it.
2973  */
2974  lid = 14004;
2975  rc = test_lookup_pdclust(LIST_ENUM_ID, lid,
2976  EXISTING_TEST,
2978  !FAILURE_TEST);
2979  M0_UT_ASSERT(rc == 0);
2980 
2981  /*
2982  * Now that a few entries are added into the DB, once again, lookup
2983  * for a layout object that does not exist in the DB.
2984  */
2985  lid = 14005;
2986  rc = test_lookup_pdclust(LIST_ENUM_ID, lid,
2987  !EXISTING_TEST,
2989  FAILURE_TEST);
2990  M0_UT_ASSERT(rc == -ENOENT);
2991 #endif
2992 
2993  /*
2994  * Add a layout object with PDCLUST layout type and LINEAR enum type.
2995  * Then perform lookup for it.
2996  */
2997  lid = 14006;
2998  rc = test_lookup_pdclust(LINEAR_ENUM_ID, lid,
2999  EXISTING_TEST,
3001  !FAILURE_TEST);
3002  M0_UT_ASSERT(rc == 0);
3003 
3004  /*
3005  * Simulate that another layout object with the same layout id is
3006  * created while the first layout object is being allocated by
3007  * m0_layout_lookup() with having the domain lock released.
3008  */
3009  lid = 14007;
3010  rc = test_lookup_with_ghost_creation(LINEAR_ENUM_ID, lid,
3012  M0_UT_ASSERT(rc == 0);
3013 }
3014 
3015 /* Tests the API m0_layout_lookup(). */
3016 static void test_lookup_failure(void)
3017 {
3018  uint64_t lid;
3019  struct m0_db_tx tx;
3020  struct m0_db_pair pair;
3021  struct m0_layout *l;
3022 
3023  M0_ENTRY();
3024 
3025 #if 0
3026  /*
3027  * Lookup for a layout object with LIST enum type, that does not
3028  * exist in the DB.
3029  */
3030  lid = 15001;
3031  rc = test_lookup_pdclust(LIST_ENUM_ID, lid,
3032  !EXISTING_TEST,
3034  FAILURE_TEST);
3035  M0_UT_ASSERT(rc == -ENOENT);
3036 #endif
3037 
3038  /*
3039  * Lookup for a layout object with LINEAR enum type, that does not
3040  * exist in the DB.
3041  */
3042  lid = 15002;
3043  rc = test_lookup_pdclust(LINEAR_ENUM_ID, lid,
3044  !EXISTING_TEST,
3046  FAILURE_TEST);
3047  M0_UT_ASSERT(rc == -ENOENT);
3048 
3049  /* Simulate pdclust_allocate() failure in m0_layout_lookup(). */
3050  lid = 15003;
3051  m0_fi_enable_off_n_on_m("pdclust_allocate", "mem_err", 1, 1);
3052  rc = test_lookup_pdclust(LINEAR_ENUM_ID, lid,
3053  EXISTING_TEST,
3055  FAILURE_TEST);
3056  M0_UT_ASSERT(rc == -ENOMEM);
3057  m0_fi_disable("pdclust_allocate", "mem_err");
3058 
3059  /* Simulate m0_layout_decode() failure in m0_layout_lookup(). */
3060  lid = 15004;
3061  m0_fi_enable_once("m0_layout_decode", "lo_decode_err");
3062  rc = test_lookup_pdclust(LINEAR_ENUM_ID, lid,
3063  EXISTING_TEST,
3065  FAILURE_TEST);
3067 
3068  /* Furnish m0_layout_lookup() with unregistered layout type. */
3069  struct m0_layout_type test_layout_type = {
3070  .lt_name = "test",
3071  .lt_id = 1,
3072  .lt_ops = NULL
3073  };
3074  lid = 15005;
3075  rc = m0_layout_lookup(&domain, lid, &test_layout_type, &tx, &pair, &l);
3076  M0_UT_ASSERT(rc == -EPROTO);
3077 
3078 #if 0
3079  /*
3080  * Simulate cursor init error in noninline_read() that is in the path
3081  * of list_decode() that is in the path of m0_layout_decode().
3082  */
3083  lid = 15006;
3084  m0_fi_enable_once("noninline_read", "cursor_init_err");
3085  rc = test_lookup_pdclust(LIST_ENUM_ID, lid,
3086  EXISTING_TEST,
3088  FAILURE_TEST);
3089  M0_UT_ASSERT(rc == -ENOENT);
3090 
3091  /*
3092  * Simulate cursor get error in noninline_read() that is in the path
3093  * of list_decode() that is in the path of m0_layout_decode().
3094  */
3095  lid = 15007;
3096  m0_fi_enable_once("noninline_read", "cursor_get_err");
3097  rc = test_lookup_pdclust(LIST_ENUM_ID, lid,
3098  EXISTING_TEST,
3100  FAILURE_TEST);
3101  M0_UT_ASSERT(rc == -ENOMEM);
3102 
3103  /*
3104  * Simulate invalid fid error in noninline_read() that is in the path
3105  * of list_decode() that is in the path of m0_layout_decode().
3106  */
3107  lid = 15008;
3108  m0_fi_enable_once("noninline_read", "invalid_fid_err");
3109  rc = test_lookup_pdclust(LIST_ENUM_ID, lid,
3110  EXISTING_TEST,
3112  FAILURE_TEST);
3113  M0_UT_ASSERT(rc == -EPROTO);
3114 #endif
3115 
3116  M0_LEAVE();
3117 }
3118 
3119 /* Tests the API m0_layout_add(), for the PDCLUST layout type. */
3120 static int test_add_pdclust(uint32_t enum_id, uint64_t lid,
3121  uint32_t inline_test,
3122  bool layout_destroy, struct m0_layout **l_obj,
3123  bool duplicate_test,
3124  bool failure_test)
3125 {
3126  m0_bcount_t num_bytes;
3127  uint32_t N;
3128  uint32_t K;
3129  uint32_t S;
3130  uint32_t P;
3131  void *area;
3132  struct m0_pdclust_layout *pl;
3133  struct m0_db_pair pair;
3134  struct m0_db_tx tx;
3135  struct m0_uint128 seed;
3136  struct m0_layout_list_enum *list_enum;
3137  struct m0_layout_linear_enum *lin_enum;
3138  int rc_tmp;
3139 
3140  M0_ENTRY("lid %llu", (unsigned long long)lid);
3142  M0_UT_ASSERT(ergo(layout_destroy, l_obj == NULL));
3143  M0_UT_ASSERT(ergo(!layout_destroy, l_obj != NULL));
3144  M0_UT_ASSERT(ergo(duplicate_test, !failure_test));
3145 
3146  m0_uint128_init(&seed, "addpdclustlayout");
3147 
3148  allocate_area(&area, ADDITIONAL_BYTES_NONE, &num_bytes);
3149 
3150  /* Build a layout object. */
3152  inline_test, 7, 1900, 1900,
3153  &N, &K, &S, &P);
3154 
3156  N, K, S, P, &seed,
3157  100, 200,
3158  &pl, &list_enum, &lin_enum,
3159  !FAILURE_TEST);
3160  M0_UT_ASSERT(rc == 0);
3161 
3162  /* Add the layout object to the DB. */
3163  rc = m0_db_tx_init(&tx, &dbenv, DBFLAGS);
3164  M0_UT_ASSERT(rc == 0);
3165 
3166  pair_set(&pair, &lid, area, num_bytes);
3167 
3168  rc = m0_layout_add(&pl->pl_base.sl_base, &tx, &pair);
3169  if (failure_test)
3170  M0_UT_ASSERT(rc == -ENOENT || rc == LO_ENCODE_ERR);
3171  else
3172  M0_UT_ASSERT(rc == 0);
3173 
3174  rc_tmp = m0_db_tx_commit(&tx);
3175  M0_UT_ASSERT(rc_tmp == 0);
3176 
3177  M0_UT_ASSERT(list_lookup(lid) == &pl->pl_base.sl_base);
3178 
3179  /*
3180  * If duplicate_test is true, again try to add the same layout object
3181  * to the DB, to verify that it results into EEXIST error.
3182  */
3183  if (duplicate_test) {
3184  rc = m0_db_tx_init(&tx, &dbenv, DBFLAGS);
3185  M0_UT_ASSERT(rc == 0);
3186 
3187  pair_set(&pair, &lid, area, num_bytes);
3188 
3189  rc = m0_layout_add(&pl->pl_base.sl_base, &tx, &pair);
3190  M0_UT_ASSERT(rc == -EEXIST);
3191 
3192  rc_tmp = m0_db_tx_commit(&tx);
3193  M0_UT_ASSERT(rc_tmp == 0);
3194  }
3195 
3196  if (layout_destroy) {
3198  M0_UT_ASSERT(list_lookup(lid) == NULL);
3199  }
3200  else
3201  *l_obj = &pl->pl_base.sl_base;
3202 
3203  m0_free(area);
3204  m0_pool_fini(&pool);
3205  M0_LEAVE("lid %llu", (unsigned long long)lid);
3206  return rc;
3207 }
3208 
3209 /* Tests the API m0_layout_add(). */
3210 static void test_add(void)
3211 {
3212  uint64_t lid;
3213 
3214 #if 0
3215  /*
3216  * Add a layout object with PDCLUST layout type, LIST enum type and
3217  * with a few inline entries only.
3218  */
3219  lid = 16001;
3220  rc = test_add_pdclust(LIST_ENUM_ID, lid,
3223  !DUPLICATE_TEST,
3224  !FAILURE_TEST);
3225  M0_UT_ASSERT(rc == 0);
3226 
3227  /*
3228  * Add a layout object with PDCLUST layout type, LIST enum type and
3229  * with a number of inline entries exactly equal to
3230  * LDB_MAX_INLINE_COB_ENTRIES.
3231  */
3232  lid = 16002;
3233  rc = test_add_pdclust(LIST_ENUM_ID, lid,
3234  EXACT_INLINE,
3236  !DUPLICATE_TEST,
3237  !FAILURE_TEST);
3238  M0_UT_ASSERT(rc == 0);
3239 
3240  /*
3241  * Add a layout object with PDCLUST layout type and LIST enum type
3242  * including noninline entries.
3243  */
3244  lid = 16003;
3245  rc = test_add_pdclust(LIST_ENUM_ID, lid,
3248  !DUPLICATE_TEST,
3249  !FAILURE_TEST);
3250  M0_UT_ASSERT(rc == 0);
3251 #endif
3252 
3253  /* Add a layout object with PDCLUST layout type and LINEAR enum type. */
3254  lid = 16004;
3255  rc = test_add_pdclust(LINEAR_ENUM_ID, lid,
3258  !DUPLICATE_TEST,
3259  !FAILURE_TEST);
3260  M0_UT_ASSERT(rc == 0);
3261 }
3262 
3263 static void test_add_failure(void)
3264 {
3265  uint64_t lid;
3266 
3267 #if 0
3268  /* Simulate m0_layout_encode() failure in m0_layout_add(). */
3269  lid = 17001;
3270  m0_fi_enable_once("m0_layout_encode", "lo_encode_err");
3271  rc = test_add_pdclust(LIST_ENUM_ID, lid,
3274  !DUPLICATE_TEST,
3275  FAILURE_TEST);
3277 #endif
3278 
3279  /*
3280  * Simulate the error that entry already exists in the layout DB with
3281  * the dame layout id.
3282  */
3283  lid = 17002;
3284  rc = test_add_pdclust(LINEAR_ENUM_ID, lid,
3288  !FAILURE_TEST);
3289  M0_UT_ASSERT(rc == -EEXIST);
3290 
3291 #if 0
3292  /*
3293  * Simulate cursor init failure in noninline_write() that is in the
3294  * path of list_encode() which is in the path of m0_layout_encode().
3295  */
3296  lid = 17003;
3297  m0_fi_enable_once("noninline_write", "cursor_init_err");
3298  rc = test_add_pdclust(LIST_ENUM_ID, lid,
3301  !DUPLICATE_TEST,
3302  FAILURE_TEST);
3303  M0_UT_ASSERT(rc == -ENOENT);
3304 
3305  /*
3306  * Simulate cursor add failure in noninline_write() that is in the
3307  * path of list_encode() which is in the path of m0_layout_encode().
3308  */
3309  lid = 17004;
3310  m0_fi_enable_once("noninline_write", "cursor_add_err");
3311  rc = test_add_pdclust(LIST_ENUM_ID, lid,
3314  !DUPLICATE_TEST,
3315  FAILURE_TEST);
3316  M0_UT_ASSERT(rc == -ENOENT);
3317 #endif
3318 }
3319 
3320 /* Tests the API m0_layout_update(), for the PDCLUST layout type. */
3321 static int test_update_pdclust(uint32_t enum_id, uint64_t lid,
3322  bool existing_test,
3323  uint32_t inline_test,
3324  bool failure_test)
3325 {
3326  m0_bcount_t num_bytes;
3327  void *area;
3328  struct m0_db_pair pair;
3329  struct m0_db_tx tx;
3330  struct m0_layout *l1;
3331  struct m0_layout *l1_copy;
3332  struct m0_layout *l2;
3333  uint32_t i;
3334  struct m0_uint128 seed;
3335  uint32_t N;
3336  uint32_t K;
3337  uint32_t S;
3338  uint32_t P;
3339  struct m0_pdclust_layout *pl;
3340  struct m0_layout_list_enum *list_enum;
3341  struct m0_layout_linear_enum *lin_enum;
3342  int rc_tmp;
3343 
3344  M0_ENTRY();
3346 
3347  allocate_area(&area, ADDITIONAL_BYTES_NONE, &num_bytes);
3348 
3350  inline_test, 13, 123, 1230,
3351  &N, &K, &S, &P);
3352 
3353  if (existing_test) {
3354  /* Add a layout object to the DB. */
3355  rc = test_add_pdclust(enum_id, lid,
3356  inline_test,
3357  !LAYOUT_DESTROY, &l1,
3358  !DUPLICATE_TEST,
3359  !FAILURE_TEST);
3360  M0_UT_ASSERT(rc == 0);
3361  } else {
3362  /* Build a layout object. */
3363  m0_uint128_init(&seed, "updatepdclustlay");
3364 
3366  N, K, S, P, &seed,
3367  10, 20,
3368  &pl, &list_enum, &lin_enum,
3369  !FAILURE_TEST);
3370  M0_UT_ASSERT(rc == 0);
3371  l1 = &pl->pl_base.sl_base;
3372  }
3373 
3374  /* Verify the original user count is as expected. */
3375  M0_UT_ASSERT(l1->l_user_count == 0);
3376 
3377  /* Update the in-memory layout object - update its user count. */
3378  for (i = 0; i < 100; ++i)
3380  M0_UT_ASSERT(l1->l_user_count == 100);
3381 
3382  /* Update the layout object in the DB. */
3383  rc = m0_db_tx_init(&tx, &dbenv, DBFLAGS);
3384  M0_UT_ASSERT(rc == 0);
3385 
3386  pair_set(&pair, &lid, area, num_bytes);
3387 
3388  rc = m0_layout_update(l1, &tx, &pair);
3389  if (failure_test)
3391  else
3392  M0_UT_ASSERT(rc == 0);
3393  /*
3394  * Even a non-existing record can be written to the database using
3395  * the database update operation.
3396  */
3397  if (existing_test && !failure_test)
3398  pdclust_layout_copy(enum_id, l1, &l1_copy);
3399 
3400  rc_tmp = m0_db_tx_commit(&tx);
3401  M0_UT_ASSERT(rc_tmp == 0);
3402 
3403  /*
3404  * Update the in-memory layout object - update its user count. This is
3405  * to verify the functioning of m0_layout_user_count_dec().
3406  */
3407  for (i = 0; i < 50; ++i)
3409  M0_UT_ASSERT(l1->l_user_count == 50);
3410 
3411  /* Delete the in-memory layout. */
3412  m0_layout_put(l1);
3413  M0_UT_ASSERT(list_lookup(lid) == NULL);
3414 
3415  if (existing_test && !failure_test) {
3416  /*
3417  * Lookup for the layout object from the DB to verify that its
3418  * user count is indeed updated.
3419  */
3420  rc = m0_db_tx_init(&tx, &dbenv, DBFLAGS);
3421  M0_UT_ASSERT(rc == 0);
3422 
3423  pair_set(&pair, &lid, area, num_bytes);
3424 
3426  &tx, &pair, &l2);
3427  M0_UT_ASSERT(rc == 0);
3428  M0_UT_ASSERT(l2->l_user_count == 100);
3429  M0_UT_ASSERT(m0_ref_read(&l2->l_ref) == 1);
3430 
3431  rc = m0_db_tx_commit(&tx);
3432  M0_UT_ASSERT(rc == 0);
3433 
3434  /*
3435  * Compare the two layouts - one created earlier here and the
3436  * one that is looked up from the DB.
3437  */
3438  pdclust_layout_compare(enum_id, l1_copy, l2, false);
3440 
3441  /* Delete the in-memory layout. */
3442  m0_layout_put(l2);
3443  M0_UT_ASSERT(list_lookup(lid) == NULL);
3444  }
3445 
3446  m0_free(area);
3447  m0_pool_fini(&pool);
3448  M0_LEAVE();
3449  return rc;
3450 }
3451 
3452 /* Tests the API m0_layout_update(). */
3453 static void test_update(void)
3454 {
3455  uint64_t lid;
3456 
3457 #if 0
3458  /*
3459  * Try to update a layout object with PDCLUST layout type and LIST enum
3460  * type, that does not exist in the DB to verify that the operation
3461  * fails with the error ENOENT.
3462  */
3463  lid = 18001;
3464  rc = test_update_pdclust(LIST_ENUM_ID, lid,
3465  !EXISTING_TEST,
3467  !FAILURE_TEST);
3468  M0_UT_ASSERT(rc == 0);
3469 
3470  /*
3471  * Update a layout object with PDCLUST layout type, LIST enum type and
3472  * with a few inline entries only.
3473  */
3474  lid = 18002;
3475  rc = test_update_pdclust(LIST_ENUM_ID, lid,
3476  EXISTING_TEST,
3478  !FAILURE_TEST);
3479  M0_UT_ASSERT(rc == 0);
3480 
3481  /*
3482  * Update a layout object with PDCLUST layout type, LIST enum type and
3483  * with number of inline entries exactly equal to
3484  * LDB_MAX_INLINE_COB_ENTRIES.
3485  */
3486  lid = 18003;
3487  rc = test_update_pdclust(LIST_ENUM_ID, lid,
3488  EXISTING_TEST,
3489  EXACT_INLINE,
3490  !FAILURE_TEST);
3491  M0_UT_ASSERT(rc == 0);
3492 
3493  /*
3494  * Update a layout object with PDCLUST layout type and LIST enum
3495  * type including noninline entries.
3496  */
3497  lid = 18004;
3498  rc = test_update_pdclust(LIST_ENUM_ID, lid,
3499  EXISTING_TEST,
3501  !FAILURE_TEST);
3502  M0_UT_ASSERT(rc == 0);
3503 #endif
3504 
3505  /*
3506  * Update a layout object with PDCLUST layout type and LINEAR enum
3507  * type.
3508  */
3509  lid = 18005;
3510  rc = test_update_pdclust(LINEAR_ENUM_ID, lid,
3511  EXISTING_TEST,
3513  !FAILURE_TEST);
3514  M0_UT_ASSERT(rc == 0);
3515 }
3516 
3517 static void test_update_failure(void)
3518 {
3519  uint64_t lid;
3520 
3521 #if 0
3522  /* Simulate m0_layout_encode() failure in m0_layout_update(). */
3523  lid = 19001;
3524  m0_fi_enable_off_n_on_m("m0_layout_encode", "lo_encode_err", 1, 1);
3525  rc = test_update_pdclust(LIST_ENUM_ID, lid,
3526  EXISTING_TEST,
3528  FAILURE_TEST);
3530  m0_fi_disable("m0_layout_encode", "lo_encode_err");
3531 #endif
3532 
3533  /* Simulate m0_table_update() failure in m0_layout_update(). */
3534  lid = 19002;
3535  m0_fi_enable_once("m0_layout_update", "table_update_err");
3536  rc = test_update_pdclust(LINEAR_ENUM_ID, lid,
3537  EXISTING_TEST,
3539  FAILURE_TEST);
3541 }
3542 
3543 /* Tests the API m0_layout_delete(), for the PDCLUST layout type. */
3544 static int test_delete_pdclust(uint32_t enum_id, uint64_t lid,
3545  bool existing_test,
3546  uint32_t inline_test,
3547  uint32_t failure_test)
3548 {
3549  m0_bcount_t num_bytes;
3550  void *area;
3551  struct m0_db_pair pair;
3552  struct m0_db_tx tx;
3553  struct m0_layout *l;
3554  struct m0_uint128 seed;
3555  uint32_t N;
3556  uint32_t K;
3557  uint32_t S;
3558  uint32_t P;
3559  struct m0_pdclust_layout *pl;
3560  struct m0_layout_list_enum *list_enum;
3561  struct m0_layout_linear_enum *lin_enum;
3562  int rc_tmp;
3563 
3564  M0_ENTRY();
3566 
3567  allocate_area(&area, ADDITIONAL_BYTES_NONE, &num_bytes);
3568 
3570  inline_test, 12, 122, 1220,
3571  &N, &K, &S, &P);
3572  if (existing_test) {
3573  /* Add a layout object to the DB. */
3574  rc = test_add_pdclust(enum_id, lid,
3575  inline_test,
3576  !LAYOUT_DESTROY, &l,
3577  !DUPLICATE_TEST,
3578  !FAILURE_TEST);
3579  M0_UT_ASSERT(rc == 0);
3580  } else {
3581  /* Build a layout object. */
3582  m0_uint128_init(&seed, "deletepdclustlay");
3583 
3585  N, K, S, P, &seed,
3586  10, 20,
3587  &pl, &list_enum, &lin_enum,
3588  !FAILURE_TEST);
3589  M0_UT_ASSERT(rc == 0);
3590  l = &pl->pl_base.sl_base;
3591  }
3592 
3593  if (M0_FI_ENABLED("nonzero_user_count_err"))
3595 
3596  /* Delete the layout object from the DB. */
3597  pair_set(&pair, &lid, area, num_bytes);
3598 
3599  rc = m0_db_tx_init(&tx, &dbenv, DBFLAGS);
3600  M0_UT_ASSERT(rc == 0);
3601 
3602  rc = m0_layout_delete(l, &tx, &pair);
3603  if (failure_test)
3604  M0_UT_ASSERT(rc == -ENOENT || rc == -ENOMEM ||
3605  rc == -EPROTO || rc == LO_ENCODE_ERR);
3606  else
3607  M0_UT_ASSERT(rc == 0);
3608 
3609  rc_tmp = m0_db_tx_commit(&tx);
3610  M0_UT_ASSERT(rc_tmp == 0);
3611 
3612  /* Destroy the layout object. */
3613  m0_layout_put(l);
3614  M0_UT_ASSERT(list_lookup(lid) == NULL);
3615 
3616  if (!failure_test) {
3617  /*
3618  * Lookup for the layout object from the DB, to verify that it
3619  * does not exist there and that the lookup results into
3620  * ENOENT error.
3621  */
3622  rc = m0_db_tx_init(&tx, &dbenv, DBFLAGS);
3623  M0_UT_ASSERT(rc == 0);
3624 
3625  pair_set(&pair, &lid, area, num_bytes);
3626 
3628  &tx, &pair, &l);
3629  M0_UT_ASSERT(rc_tmp == -ENOENT);
3630 
3631  rc_tmp = m0_db_tx_commit(&tx);
3632  M0_UT_ASSERT(rc_tmp == 0);
3633  }
3634 
3635  m0_free(area);
3636  m0_pool_fini(&pool);
3637  M0_LEAVE();
3638  return rc;
3639 }
3640 
3641 /* Tests the API m0_layout_delete(). */
3642 static void test_delete(void)
3643 {
3644  uint64_t lid;
3645 
3646 #if 0
3647  /*
3648  * Delete a layout object with PDCLUST layout type, LIST enum type and
3649  * with a few inline entries only.
3650  */
3651  lid = 20001;
3652  rc = test_delete_pdclust(LIST_ENUM_ID, lid,
3653  EXISTING_TEST,
3655  !FAILURE_TEST);
3656  M0_UT_ASSERT(rc == 0);
3657 
3658  /*
3659  * Delete a layout object with PDCLUST layout type, LIST enum type and
3660  * with a number of inline entries exactly equal to
3661  * LDB_MAX_INLINE_COB_ENTRIES.
3662  */
3663  lid = 20002;
3664  rc = test_delete_pdclust(LIST_ENUM_ID, lid,
3665  EXISTING_TEST,
3666  EXACT_INLINE,
3667  !FAILURE_TEST);
3668  M0_UT_ASSERT(rc == 0);
3669 
3670  /*
3671  * Delete a layout object with PDCLUST layout type and LIST enum
3672  * type including noninline entries.
3673  */
3674  lid = 20003;
3675  rc = test_delete_pdclust(LIST_ENUM_ID, lid,
3676  EXISTING_TEST,
3678  !FAILURE_TEST);
3679  M0_UT_ASSERT(rc == 0);
3680 #endif
3681 
3682  /*
3683  * Delete a layout object with PDCLUST layout type and LINEAR enum
3684  * type.
3685  */
3686  lid = 20004;
3687  rc = test_delete_pdclust(LINEAR_ENUM_ID, lid,
3688  EXISTING_TEST,
3690  !FAILURE_TEST);
3691  M0_UT_ASSERT(rc == 0);
3692 }
3693 
3694 static void test_delete_failure(void)
3695 {
3696  uint64_t lid;
3697 
3698  /* Simulate m0_layout_encode() failure in m0_layout_delete(). */
3699  lid = 21001;
3700  m0_fi_enable_off_n_on_m("m0_layout_encode", "lo_encode_err", 1, 1);
3701  rc = test_delete_pdclust(LINEAR_ENUM_ID, lid,
3702  EXISTING_TEST,
3704  FAILURE_TEST);
3706  m0_fi_disable("m0_layout_encode", "lo_encode_err");
3707 
3708  /*
3709  * Try to delete a layout object with PDCLUST layout type and LINEAR
3710  * enum type, that does not exist in the DB, to verify that it results
3711  * into the error ENOENT.
3712  */
3713  lid = 21002;
3714  rc = test_delete_pdclust(LINEAR_ENUM_ID, lid,
3715  !EXISTING_TEST,
3717  FAILURE_TEST);
3718  M0_UT_ASSERT(rc == -ENOENT);
3719 
3720 #if 0
3721  /*
3722  * Simulate cursor get failure in noninline_write() that is in the
3723  * path of list_encode() which is in the path of m0_layout_encode().
3724  */
3725  lid = 21003;
3726  m0_fi_enable_once("noninline_write", "cursor_get_err");
3727  rc = test_delete_pdclust(LIST_ENUM_ID, lid,
3728  EXISTING_TEST,
3730  FAILURE_TEST);
3731  M0_UT_ASSERT(rc == -ENOENT);
3732 
3733  /*
3734  * Simulate cursor delete failure in noninline_write() that is in the
3735  * path of list_encode() which is in the path of m0_layout_encode().
3736  */
3737  lid = 21004;
3738  m0_fi_enable_once("noninline_write", "cursor_del_err");
3739  rc = test_delete_pdclust(LIST_ENUM_ID, lid,
3740  EXISTING_TEST,
3742  FAILURE_TEST);
3743  M0_UT_ASSERT(rc == -ENOMEM);
3744 #endif
3745 
3746  /*
3747  * Try to delete a layout with PDCLUST layout type and LINEAR
3748  * enum type, that has non-zero user count, to verify that it results
3749  * into the error -EPROTO.
3750  */
3751  lid = 21005;
3752  m0_fi_enable_once("test_delete_pdclust", "nonzero_user_count_err");
3753  rc = test_delete_pdclust(LINEAR_ENUM_ID, lid,
3754  EXISTING_TEST,
3756  FAILURE_TEST);
3757  M0_UT_ASSERT(rc == -EPROTO);
3758 }
3759 
3760 #endif /* __KERNEL__ */
3761 #endif
3762 
3764  .ts_name = "layout-ut",
3765  .ts_owners = "Trupti",
3766  .ts_init = test_init,
3767  .ts_fini = test_fini,
3768  .ts_tests = {
3769  { "layout-domain-init-fini", test_domain_init_fini },
3770  { "layout-domain-init-fini-failure",
3772  { "layout-type-register-unregister", test_type_reg_unreg },
3773  { "layout-etype-register-unregister", test_etype_reg_unreg },
3774  { "layout-register-unregister", test_reg_unreg },
3775  { "layout-register-unregister-failure",
3777  { "layout-build", test_build },
3778  { "layout-build-failure", test_build_failure },
3779  { "layout-decode", test_decode },
3780  { "layout-decode-failure", test_decode_failure },
3781  { "layout-encode", test_encode },
3782  { "layout-encode-failure", test_encode_failure },
3783  { "layout-decode-encode", test_decode_encode },
3784  { "layout-encode-decode", test_encode_decode },
3785  { "layout-ref-get-put", test_ref_get_put },
3786  { "layout-enum-ops", test_enum_operations },
3787  { "layout-max-recsize", test_max_recsize },
3788  { "layout-recsize", test_recsize },
3789  { "layout-pdclust-instance", test_pdclust_instance },
3790  { "layout-pdclust-instance-failure",
3792 /*#ifndef __KERNEL__
3793  { "layout-lookup", test_lookup },
3794  { "layout-lookup-failure", test_lookup_failure },
3795  { "layout-add", test_add },
3796  { "layout-add-failure", test_add_failure },
3797  { "layout-update", test_update },
3798  { "layout-update-failure", test_update_failure },
3799  { "layout-delete", test_delete },
3800  { "layout-delete-failure", test_delete_failure },
3801 #endif*/
3802  { NULL, NULL }
3803  }
3804 };
3805 M0_EXPORTED(layout_ut);
3806 
3807 #undef M0_TRACE_SUBSYSTEM
3808 
3809 /*
3810  * Local variables:
3811  * c-indentation-style: "K&R"
3812  * c-basic-offset: 8
3813  * tab-width: 8
3814  * fill-column: 80
3815  * scroll-step: 1
3816  * End:
3817  */
M0_INTERNAL struct m0_layout * m0_layout_find(struct m0_layout_domain *dom, uint64_t lid)
Definition: layout.c:861
static int test_build_pdclust(uint32_t enum_id, uint64_t lid, uint32_t inline_test, bool failure_test)
Definition: layout.c:685
#define M0_BUFVEC_INIT_BUF(addr_ptr, count_ptr)
Definition: vec.h:165
int(* leto_register)(struct m0_layout_domain *dom, const struct m0_layout_enum_type *et)
Definition: layout.h:548
M0_INTERNAL m0_bcount_t m0_layout_max_recsize(const struct m0_layout_domain *dom)
Definition: layout.c:1037
static void NKP_assign_and_pool_init(uint32_t enum_id, uint32_t inline_test, uint32_t list_nr_less, uint32_t list_nr_more, uint32_t linear_nr, uint32_t *N, uint32_t *K, uint32_t *S, uint32_t *P)
Definition: layout.c:604
M0_INTERNAL struct m0_striped_layout * m0_layout_to_striped(const struct m0_layout *l)
Definition: layout.c:1045
static size_t nr
Definition: dump.c:1505
static void test_decode_failure(void)
Definition: layout.c:1113
struct m0_layout_enum_type m0_linear_enum_type
Definition: linear_enum.c:342
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
static void test_max_recsize(void)
Definition: layout.c:2250
M0_INTERNAL void m0_pool_fini(struct m0_pool *pool)
Definition: pool.c:322
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
M0_INTERNAL void m0_fid_gob_make(struct m0_fid *gob_fid, uint32_t container, uint64_t key)
Definition: fid_convert.c:46
static void pdclust_recsize_verify(uint32_t enum_id, struct m0_layout *l, m0_bcount_t recsize_to_verify)
Definition: layout.c:2362
struct m0_ref l_ref
Definition: layout.h:234
uint64_t sa_group
Definition: pdclust.h:241
#define NULL
Definition: misc.h:38
uint64_t pa_unit_size
Definition: pdclust.h:118
M0_INTERNAL void m0_layout_enum_type_unregister(struct m0_layout_domain *dom, struct m0_layout_enum_type *let)
Definition: layout.c:793
M0_INTERNAL int m0_layout_update(struct m0_layout *l, struct m0_db_tx *tx, struct m0_db_pair *pair)
Definition: layout_db.c:570
static struct buffer * cur(struct m0_addb2_mach *mach, m0_bcount_t space)
Definition: addb2.c:791
static void allocate_area(void **area, m0_bcount_t additional_bytes, m0_bcount_t *num_bytes)
Definition: layout.c:978
static void test_reg_unreg_failure(void)
Definition: layout.c:310
#define ergo(a, b)
Definition: misc.h:293
static int test_fini(void)
Definition: layout.c:92
static void test_build_failure(void)
Definition: layout.c:787
M0_INTERNAL int m0_layout_domain_init(struct m0_layout_domain *dom)
Definition: layout.c:610
static void buf_build(uint32_t lt_id, struct m0_bufvec_cursor *dcur)
Definition: layout.c:873
M0_INTERNAL bool m0_uint128_eq(const struct m0_uint128 *u0, const struct m0_uint128 *u1)
Definition: misc.c:39
uint32_t pa_N
Definition: pdclust.h:104
static int t_register(struct m0_layout_domain *dom, const struct m0_layout_type *lt)
Definition: layout.c:146
M0_LEAVE()
uint32_t pr_let_id
Definition: pdclust.h:131
struct m0_layout_type test_layout_type
Definition: layout.c:168
static void test_decode(void)
Definition: layout.c:1069
#define M0_FID_INIT(container, key)
Definition: fid.h:84
static void lbuf_verify(struct m0_bufvec_cursor *cur, uint32_t *lt_id)
Definition: layout.c:1189
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
static void pdclust_lbuf_compare(struct m0_bufvec_cursor *cur1, struct m0_bufvec_cursor *cur2)
Definition: layout.c:1457
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
static void test_domain_init_fini(void)
Definition: layout.c:100
M0_INTERNAL void m0_layout_domain_fini(struct m0_layout_domain *dom)
Definition: layout.c:633
struct m0_pool_version pool_ver
Definition: fd.c:111
M0_INTERNAL int m0_linear_enum_build(struct m0_layout_domain *dom, const struct m0_layout_linear_attr *attr, struct m0_layout_linear_enum **out)
Definition: linear_enum.c:138
M0_INTERNAL void m0_layout_enum_fini(struct m0_layout_enum *le)
Definition: layout.c:518
struct m0_bufvec data
Definition: di.c:40
void test_update(void)
Definition: bytecount.c:225
Definition: layout.c:54
static int test_encode_decode_pdclust(uint32_t enum_id, uint64_t lid, uint32_t inline_test)
Definition: layout.c:1889
static void test_encode(void)
Definition: layout.c:1371
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
struct m0_layout_enum_type test_enum_type
Definition: layout.c:213
static void ldemo(struct m0_pdclust_instance *pi, const struct m0_pdclust_layout *pl)
Definition: layout.c:2490
void test_lookup(void)
Definition: bytecount.c:196
#define container_of(ptr, type, member)
Definition: misc.h:33
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
Definition: ut.h:77
static int test_decode_encode_pdclust(uint32_t enum_id, uint64_t lid, uint32_t inline_test)
Definition: layout.c:1552
#define N(i)
static int test_add(struct m0_list *list, const char *suite, const char *test, const struct m0_ut_module *m)
Definition: ut.c:193
struct m0_pdclust_attr pl_attr
Definition: pdclust.h:150
static void test_encode_failure(void)
Definition: layout.c:1413
struct m0_layout_enum_type * le_type
Definition: layout.h:409
M0_INTERNAL int m0_layout_instance_build(struct m0_layout *l, const struct m0_fid *fid, struct m0_layout_instance **out)
Definition: layout.c:1113
static void test_pdclust_instance_failure(void)
Definition: layout.c:2656
M0_INTERNAL int m0_pool_init(struct m0_pool *pool, const struct m0_fid *id, enum m0_pver_policy_code pver_policy)
Definition: pool.c:307
static void enum_op_verify(uint32_t enum_id, uint64_t lid, uint32_t nr, struct m0_layout *l)
Definition: layout.c:2119
struct m0_pdclust_attr pr_attr
Definition: pdclust.h:133
struct m0_layout_type * ld_type[M0_LAYOUT_TYPE_MAX]
Definition: layout.h:196
#define M0_ENTRY(...)
Definition: trace.h:170
static int t_enum_register(struct m0_layout_domain *dom, const struct m0_layout_enum_type *et)
Definition: layout.c:191
M0_INTERNAL int m0_layout_delete(struct m0_layout *l, struct m0_db_tx *tx, struct m0_db_pair *pair)
Definition: layout_db.c:601
M0_INTERNAL bool m0_bufvec_cursor_move(struct m0_bufvec_cursor *cur, m0_bcount_t count)
Definition: vec.c:574
M0_INTERNAL void m0_layout_add(struct m0_layout_domain *dom, struct m0_layout *l)
Definition: layout.c:262
int i
Definition: dir.c:1033
static const struct m0_layout_enum_type_ops test_enum_ops
Definition: layout.c:207
static void t_enum_unregister(struct m0_layout_domain *dom, const struct m0_layout_enum_type *et)
Definition: layout.c:197
struct m0_layout_linear_attr lle_attr
Definition: linear_enum.h:71
M0_INTERNAL void m0_fid_set(struct m0_fid *fid, uint64_t container, uint64_t key)
Definition: fid.c:116
void m0_ref_init(struct m0_ref *ref, int init_num, void(*release)(struct m0_ref *ref))
Definition: refs.c:24
int(* lto_allocate)(struct m0_layout_domain *dom, uint64_t lid, struct m0_layout **out)
Definition: layout.h:401
struct m0_layout_enum lle_base
Definition: linear_enum.h:69
static void attr(struct m0_addb2__context *ctx, const uint64_t *v, char *buf)
Definition: dump.c:949
const struct m0_layout_enum_ops * le_ops
Definition: layout.h:423
M0_INTERNAL void m0_fi_disable(const char *fp_func, const char *fp_tag)
Definition: finject.c:485
M0_INTERNAL int m0_layout_lookup(struct m0_layout_domain *dom, uint64_t lid, struct m0_layout_type *lt, struct m0_db_tx *tx, struct m0_db_pair *pair, struct m0_layout **out)
Definition: layout_db.c:428
static void lbuf_compare(struct m0_bufvec_cursor *cur1, struct m0_bufvec_cursor *cur2)
Definition: layout.c:1437
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
struct m0_layout_type * l_type
Definition: layout.h:228
static void test_reg_unreg(void)
Definition: layout.c:236
#define M0_ASSERT(cond)
M0_INTERNAL int m0_layout_encode(struct m0_layout *l, enum m0_layout_xcode_op op, struct m0_be_tx *tx, struct m0_bufvec_cursor *out)
Definition: layout.c:1000
static void pdclust_buf_build(uint32_t let_id, uint64_t lid, uint32_t N, uint32_t K, uint32_t S, uint32_t P, struct m0_uint128 *seed, struct m0_bufvec_cursor *dcur)
Definition: layout.c:889
M0_INTERNAL uint32_t m0_pdclust_N(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:352
static void m0_fi_enable_func(const char *func, const char *tag, m0_fi_fpoint_state_func_t trigger_func, void *data)
Definition: finject.h:387
static int test_ref_get_put_pdclust(uint32_t enum_id, uint64_t lid)
Definition: layout.c:2043
static void pdclust_layout_copy_delete(uint32_t enum_id, struct m0_layout *l)
Definition: layout.c:1858
static void test_domain_init_fini_failure(void)
Definition: layout.c:128
uint32_t l_user_count
Definition: layout.h:242
static void pdclust_lbuf_verify(uint32_t N, uint32_t K, uint32_t S, uint32_t P, struct m0_uint128 *seed, struct m0_bufvec_cursor *cur, uint32_t *let_id)
Definition: layout.c:1209
static int pdclust_layout_buf_build(uint32_t enum_id, uint64_t lid, uint32_t N, uint32_t K, uint32_t S, uint32_t P, struct m0_uint128 *seed, uint32_t A, uint32_t B, struct m0_bufvec_cursor *dcur)
Definition: layout.c:913
struct m0_layout_enum * sl_enum
Definition: layout.h:577
static void pdclust_layout_verify(uint32_t enum_id, struct m0_layout *l, uint64_t lid, uint32_t N, uint32_t K, uint32_t S, uint32_t P, struct m0_uint128 *seed, uint32_t A, uint32_t B)
Definition: layout.c:554
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_bufvec_cursor_init(struct m0_bufvec_cursor *cur, const struct m0_bufvec *bvec)
Definition: vec.c:563
M0_INTERNAL uint32_t m0_pdclust_S(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:362
M0_INTERNAL void m0_layout_enum_get(const struct m0_layout_enum *e, uint32_t idx, const struct m0_fid *gfid, struct m0_fid *out)
Definition: layout.c:1080
static void test_pdclust_instance(void)
Definition: layout.c:2611
void * m0_alloc(size_t size)
Definition: memory.c:126
static int test_decode_pdclust(uint32_t enum_id, uint64_t lid, uint32_t inline_test, bool failure_test)
Definition: layout.c:991
M0_INTERNAL uint32_t m0_layout_enum_nr(const struct m0_layout_enum *e)
Definition: layout.c:1074
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
M0_INTERNAL void m0_layout_user_count_dec(struct m0_layout *l)
Definition: layout.c:934
uint64_t fci_nr
Definition: fd.h:188
struct m0_mutex l_lock
Definition: layout.h:247
M0_INTERNAL int m0_list_enum_build(struct m0_layout_domain *dom, struct m0_fid *cob_list, uint32_t nr, struct m0_layout_list_enum **out)
Definition: list_enum.c:191
static int test_encode_pdclust(uint32_t enum_id, uint64_t lid, uint32_t inline_test, bool failure_test)
Definition: layout.c:1299
M0_INTERNAL int m0_layout_enum_type_register(struct m0_layout_domain *dom, struct m0_layout_enum_type *let)
Definition: layout.c:759
uint32_t lr_lt_id
Definition: layout.h:653
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
uint32_t lt_id
Definition: layout.h:360
M0_INTERNAL int m0_layout_standard_types_register(struct m0_layout_domain *dom)
Definition: layout.c:671
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 int m0_layout_decode(struct m0_layout *l, struct m0_bufvec_cursor *cur, enum m0_layout_xcode_op op, struct m0_be_tx *tx)
Definition: layout.c:947
static struct m0_clink l[NR]
Definition: chan.c:37
static m0_bcount_t t_enum_max_recsize(void)
Definition: layout.c:202
void layout_destroy(struct m0_pdclust_layout *pdlay)
Definition: cp_common.c:257
struct m0_uint128 pa_seed
Definition: pdclust.h:121
struct m0_layout_enum_type * ld_enum[M0_LAYOUT_ENUM_TYPE_MAX]
Definition: layout.h:199
static void pdclust_l_verify(struct m0_pdclust_layout *pl, uint64_t lid, uint32_t N, uint32_t K, uint32_t S, uint32_t P, struct m0_uint128 *seed)
Definition: layout.c:535
M0_INTERNAL struct m0_layout * m0_pdl_to_layout(struct m0_pdclust_layout *pl)
Definition: pdclust.c:393
static void t_unregister(struct m0_layout_domain *dom, const struct m0_layout_type *lt)
Definition: layout.c:152
const char * let_name
Definition: layout.h:527
static void m0_fi_enable_off_n_on_m(const char *func, const char *tag, uint32_t n, uint32_t m)
Definition: finject.h:346
static int test_init(void)
Definition: layout.c:74
static void pdclust_layout_copy(uint32_t enum_id, const struct m0_layout *l_src, struct m0_layout **l_dest)
Definition: layout.c:1789
M0_INTERNAL bool m0_fid_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: fid.c:164
uint64_t sa_unit
Definition: pdclust.h:243
M0_INTERNAL bool m0_layout__allocated_invariant(const struct m0_layout *l)
Definition: layout.c:147
static int pdclust_layout_build(uint32_t enum_id, uint64_t lid, uint32_t N, uint32_t K, uint32_t S, uint32_t P, struct m0_uint128 *seed, uint32_t A, uint32_t B, struct m0_pdclust_layout **pl, struct m0_layout_linear_enum **lin_enum, bool failure_test)
Definition: layout.c:440
static uint32_t linear_nr(const struct m0_layout_enum *e)
Definition: linear_enum.c:282
static int test_pdclust_instance_obj(uint32_t enum_id, uint64_t lid, bool inline_test, bool failure_test)
Definition: layout.c:2511
const struct m0_layout_type_ops * lt_ops
Definition: layout.h:370
static void pdclust_layout_buf_verify(uint32_t enum_id, uint64_t lid, uint32_t N, uint32_t K, uint32_t S, uint32_t P, struct m0_uint128 *seed, uint32_t A, uint32_t B, struct m0_bufvec_cursor *cur)
Definition: layout.c:1233
const char * ts_name
Definition: ut.h:99
static struct m0_pool pool
Definition: layout.c:50
static void l_verify(struct m0_layout *l, uint64_t lid)
Definition: layout.c:524
struct m0_pdclust_tgt_addr tgt
Definition: fd.c:110
M0_INTERNAL void m0_layout_get(struct m0_layout *l)
Definition: layout.c:880
M0_INTERNAL int64_t m0_ref_read(const struct m0_ref *ref)
Definition: refs.c:44
static int rc
Definition: layout.c:51
M0_INTERNAL void m0_layout_user_count_inc(struct m0_layout *l)
Definition: layout.c:921
struct m0_mutex ld_lock
Definition: layout.h:217
#define M0_FI_ENABLED(tag)
Definition: finject.h:231
Definition: fid.h:38
static void test_recsize(void)
Definition: layout.c:2452
struct m0_layout_type m0_pdclust_layout_type
Definition: pdclust.c:968
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
static const struct m0_layout_type_ops test_layout_type_ops
Definition: layout.c:162
int(* lto_register)(struct m0_layout_domain *dom, const struct m0_layout_type *lt)
Definition: layout.h:378
static void pdclust_layout_buf_compare(uint32_t enum_id, struct m0_bufvec_cursor *cur1, struct m0_bufvec_cursor *cur2)
Definition: layout.c:1482
static int test_enum_ops_pdclust(uint32_t enum_id, uint64_t lid, uint32_t inline_test)
Definition: layout.c:2164
M0_INTERNAL struct m0_layout_enum * m0_layout_instance_to_enum(const struct m0_layout_instance *li)
Definition: layout.c:1132
uint32_t pa_P
Definition: pdclust.h:115
static void pdclust_layout_compare(uint32_t enum_id, const struct m0_layout *l1, const struct m0_layout *l2, bool l2_ref_elevated)
Definition: layout.c:1710
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
struct m0_layout sl_base
Definition: layout.h:574
M0_INTERNAL int m0_layout_type_register(struct m0_layout_domain *dom, struct m0_layout_type *lt)
Definition: layout.c:707
Definition: xcode.c:1194
struct m0_striped_layout * le_sl
Definition: layout.h:420
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
M0_INTERNAL void m0_layout_standard_types_unregister(struct m0_layout_domain *dom)
Definition: layout.c:697
M0_INTERNAL struct m0_layout_enum * m0_layout_to_enum(const struct m0_layout *l)
Definition: layout.c:1064
static void m0_fi_enable_once(const char *func, const char *tag)
Definition: finject.h:301
static void test_ref_get_put(void)
Definition: layout.c:2094
M0_INTERNAL void m0_layout_type_unregister(struct m0_layout_domain *dom, struct m0_layout_type *lt)
Definition: layout.c:741
uint64_t * fci_info
Definition: fd.h:196
static void test_decode_encode(void)
Definition: layout.c:1648
Definition: rwlock.c:42
M0_INTERNAL void m0_layout_instance_fini(struct m0_layout_instance *li)
Definition: layout.c:1123
Definition: pool.h:80
uint32_t lr_user_count
Definition: layout.h:659
struct m0_ut_suite layout_ut
Definition: layout.c:3763
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
M0_INTERNAL void m0_layout_put(struct m0_layout *l)
Definition: layout.c:893
M0_INTERNAL void m0_fid_convert_gob2cob(const struct m0_fid *gob_fid, struct m0_fid *cob_fid, uint32_t device_id)
Definition: fid_convert.c:55
struct m0_fid gfid
Definition: dir.c:626
static int test_recsize_pdclust(uint32_t enum_id, uint64_t lid, uint32_t inline_test)
Definition: layout.c:2404
static struct m0_layout * list_lookup(uint64_t lid)
Definition: layout.c:389
static void test_type_reg_unreg(void)
Definition: layout.c:174
static const char * enum_id(const char *buf)
Definition: enum.c:209
Definition: module.c:67
static void test_etype_reg_unreg(void)
Definition: layout.c:219
static struct m0_layout_domain domain
Definition: layout.c:49
void m0_free(void *data)
Definition: memory.c:146
struct m0_layout_domain * l_dom
Definition: layout.h:231
static m0_bcount_t t_max_recsize(struct m0_layout_domain *dom)
Definition: layout.c:157
M0_INTERNAL struct m0_layout * m0_layout__list_lookup(const struct m0_layout_domain *dom, uint64_t lid, bool ref_increment)
Definition: layout.c:282
static void test_encode_decode(void)
Definition: layout.c:1982
struct m0_pdclust_src_addr src
Definition: fd.c:108
static void test_delete(void)
Definition: cob.c:316
#define M0_UT_ASSERT(a)
Definition: ut.h:46
M0_INTERNAL uint32_t m0_pdclust_P(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:367
static void test_enum_operations(void)
Definition: layout.c:2206
M0_INTERNAL uint64_t m0_pdclust_unit_size(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:377
Definition: module.c:67
Definition: vec.h:145
static int pdclust_l_build(uint64_t lid, uint32_t N, uint32_t K, uint32_t S, uint32_t P, struct m0_uint128 *seed, struct m0_layout_enum *le, struct m0_pdclust_layout **pl, bool failure_test)
Definition: layout.c:403
uint32_t let_id
Definition: layout.h:530
struct m0_layout_enum_type m0_list_enum_type
Definition: list_enum.c:706
static void test_build(void)
Definition: layout.c:743
uint64_t l_id
Definition: layout.h:225
void(* lo_fini)(struct m0_ref *ref)
Definition: layout.h:275
const struct m0_layout_ops * l_ops
Definition: layout.h:249