Motr  M0
fd_tree.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 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_LIB
24 #include "lib/trace.h" /* M0_ERR() */
25 
26 #include "lib/finject.h" /* m0_fi_enable() */
27 #include "lib/memory.h" /* m0_alloc() */
28 #include "lib/misc.h" /* M0_SET0() */
29 #include "fd/fd_internal.h"
30 #include "fd/fd.h"
31 #include "fd/ut/common.h"
32 #include "ut/ut.h" /* M0_UT_ASSERT() */
33 #include "lib/errno.h" /* ENOMEM */
34 
35 static int tree_populate(struct m0_fd_tree *tree, enum tree_type param_type);
36 static uint32_t geometric_sum(uint16_t r, uint16_t k);
37 static uint32_t int_pow(uint32_t num, uint32_t exp);
38 
39 static void test_cache_init_fini(void)
40 {
41  struct m0_fd_tree tree;
42  uint32_t children_nr;
43  uint32_t i;
44  uint32_t unique_chld_nr[TP_NR];
45  uint32_t list_chld_nr[TP_NR];
46  uint64_t cache_len;
48  int rc;
49 
50  M0_SET0(&unique_chld_nr);
51  M0_SET0(&list_chld_nr);
52  seed = m0_time_now();
53  children_nr = m0_rnd(TP_QUATERNARY, &seed);
54  children_nr = TP_QUATERNARY - children_nr;
56  M0_UT_ASSERT(rc == 0);
57  rc = m0_fd__tree_root_create(&tree, children_nr);
58  M0_UT_ASSERT(rc == 0);
59  unique_chld_nr[children_nr] = 1;
60  for (i = 1; i < M0_CONF_PVER_HEIGHT; ++i) {
61  children_nr = m0_rnd(TP_QUATERNARY, &seed);
62  children_nr = TP_QUATERNARY - children_nr;
63  children_nr = i == tree.ft_depth ? 0 : children_nr;
64  rc = fd_ut_tree_level_populate(&tree, children_nr, i, TA_SYMM);
65  M0_UT_ASSERT(rc == 0);
66  if (i < M0_CONF_PVER_HEIGHT - 1)
67  unique_chld_nr[children_nr] = 1;
68  }
70  for (i = 0; i < tree.ft_cache_info.fci_nr; ++i) {
71  cache_len = tree.ft_cache_info.fci_info[i];
72  M0_UT_ASSERT(unique_chld_nr[cache_len] == 1);
73  list_chld_nr[cache_len] = 1;
74  }
75  M0_UT_ASSERT(!memcmp(unique_chld_nr, list_chld_nr,
76  sizeof unique_chld_nr));
77  m0_fd_tree_destroy(&tree);
78 }
79 
80 static void test_init_fini(void)
81 {
82  struct m0_fd_tree tree;
83  uint16_t i;
84  uint16_t j;
85  int rc;
86 
87  for (j = TP_BINARY; j < TP_QUATERNARY + 1; ++j) {
88  for (i = 1; i < M0_CONF_PVER_HEIGHT; ++i) {
89  rc = fd_ut_tree_init(&tree, i);
90  M0_UT_ASSERT(rc == 0);
91  rc = m0_fd__tree_root_create(&tree, j);
92  M0_UT_ASSERT(rc == 0);
93  rc = tree_populate(&tree, j);
94  M0_UT_ASSERT(rc == 0);
95  M0_UT_ASSERT(geometric_sum(j, i) == tree.ft_cnt);
96  m0_fd_tree_destroy(&tree);
97  M0_UT_ASSERT(tree.ft_cnt == 0);
98  }
99  }
100 }
101 
102 static void test_fault_inj(void)
103 {
104  struct m0_fd_tree tree;
105  m0_time_t seed;
106  uint64_t n;
107  int rc;
108 
109  M0_SET0(&tree);
110  rc = fd_ut_tree_init(&tree, M0_CONF_PVER_HEIGHT - 1);
111  M0_UT_ASSERT(rc == 0);
113  M0_UT_ASSERT(rc == 0);
114  rc = tree_populate(&tree, TP_BINARY);
115  M0_UT_ASSERT(rc == 0);
116  m0_fd_tree_destroy(&tree);
117 
118  /* Fault injection. */
119  seed = m0_time_now();
120  /* Maximum nodes in a tree. */
122  &seed);
123  m0_fi_enable_off_n_on_m("m0_alloc", "fail_allocation", n, 1);
124  M0_SET0(&tree);
125  rc = fd_ut_tree_init(&tree, M0_CONF_PVER_HEIGHT - 1) ?:
127  tree_populate(&tree, TP_BINARY);
128  m0_fi_disable("m0_alloc","fail_allocation");
129  M0_UT_ASSERT(rc == -ENOMEM);
130  /*
131  * NOTE: m0_fd__tree_root_create and tree_populate call
132  * m0_alloc two times per node, but m0_alloc may be recursively:
133  * m0_alloc call alloc_tail, but alloc_tail may call m0_alloc
134  */
135  M0_UT_ASSERT((n >> 1) >= tree.ft_cnt);
136  m0_fd_tree_destroy(&tree);
137  M0_UT_ASSERT(tree.ft_cnt == 0);
138 }
139 
140 static uint32_t geometric_sum(uint16_t r, uint16_t k)
141 {
142  return (int_pow(r, k + 1) - 1) / (r - 1);
143 }
144 
145 static uint32_t int_pow(uint32_t num, uint32_t exp)
146 {
147  uint32_t ret = 1;
148  uint32_t i;
149 
150  for (i = 0; i < exp; ++i) {
151  ret *= num;
152  }
153  return ret;
154 }
155 
156 static int tree_populate(struct m0_fd_tree *tree, enum tree_type param_type)
157 {
158  uint16_t i;
159  int rc;
160  uint64_t children_nr;
161 
162  for (i = 1; i <= tree->ft_depth; ++i) {
163  children_nr = i == tree->ft_depth ? 0 : param_type;
164  rc = fd_ut_tree_level_populate(tree, children_nr, i, TA_SYMM);
165  if (rc != 0)
166  return rc;
167  }
168  rc = m0_fd__perm_cache_build(tree);
169  return rc;
170 }
171 
172 static void test_perm_cache(void)
173 {
175 }
176 static void test_fd_tree(void)
177 {
178  test_init_fini();
179  test_fault_inj();
180 }
181 
183  .ts_name = "failure_domains_tree-ut",
184  .ts_init = NULL,
185  .ts_fini = NULL,
186  .ts_tests = {
187  {"test_fd_tree", test_fd_tree},
188  {"test_perm_cache", test_perm_cache},
189  { NULL, NULL }
190  }
191 };
static void test_init_fini(void)
Definition: fd_tree.c:80
#define NULL
Definition: misc.h:38
struct m0_ut_suite failure_domains_tree_ut
Definition: fd_tree.c:182
uint64_t m0_time_t
Definition: time.h:37
static void test_fault_inj(void)
Definition: fd_tree.c:102
uint16_t ft_depth
Definition: fd.h:201
#define M0_SET0(obj)
Definition: misc.h:64
Definition: ut.h:77
Definition: common.h:71
int i
Definition: dir.c:1033
M0_INTERNAL uint64_t m0_rnd(uint64_t max, uint64_t *seed)
Definition: misc.c:115
M0_INTERNAL void m0_fi_disable(const char *fp_func, const char *fp_tag)
Definition: finject.c:485
m0_time_t m0_time_now(void)
Definition: time.c:134
M0_INTERNAL void m0_fd_tree_destroy(struct m0_fd_tree *tree)
Definition: fd.c:785
struct m0_fd_cache_info ft_cache_info
Definition: fd.h:209
static void test_fd_tree(void)
Definition: fd_tree.c:176
tree_type
Definition: common.h:52
uint64_t fci_nr
Definition: fd.h:188
static uint32_t int_pow(uint32_t num, uint32_t exp)
Definition: fd_tree.c:145
static int tree_populate(struct m0_fd_tree *tree, enum tree_type param_type)
Definition: fd_tree.c:156
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
uint64_t ft_cnt
Definition: fd.h:207
const char * ts_name
Definition: ut.h:99
uint64_t n
Definition: fops.h:107
static int r[NR]
Definition: thread.c:46
static uint32_t geometric_sum(uint16_t r, uint16_t k)
Definition: fd_tree.c:140
Definition: common.h:58
M0_INTERNAL int m0_fd__perm_cache_build(struct m0_fd_tree *tree)
Definition: fd.c:683
M0_INTERNAL int fd_ut_tree_level_populate(struct m0_fd_tree *tree, uint64_t max_children, uint16_t level, enum tree_attr ta)
Definition: common.c:69
uint64_t * fci_info
Definition: fd.h:196
Definition: fd.h:199
M0_INTERNAL int m0_fd__tree_root_create(struct m0_fd_tree *tree, uint64_t root_children)
Definition: fd_tree.c:181
int num
Definition: bulk_if.c:54
M0_INTERNAL int fd_ut_tree_init(struct m0_fd_tree *tree, uint64_t tree_depth)
Definition: common.c:114
int32_t rc
Definition: trigger_fop.h:47
static void test_cache_init_fini(void)
Definition: fd_tree.c:39
#define M0_UT_ASSERT(a)
Definition: ut.h:46
static void test_perm_cache(void)
Definition: fd_tree.c:172