Motr  M0
module.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2014-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 "module/instance.h"
24 #include "lib/misc.h" /* m0_forall */
25 #include "lib/errno.h" /* EAGAIN */
26 #include "lib/arith.h" /* M0_CNT_INC */
27 
35 static bool moddeps_are_unique(const struct m0_moddep *arr, unsigned n)
36 {
38  return m0_elems_are_unique(arr, n, sizeof *arr);
39 }
40 
41 static bool module_invariant(const struct m0_module *mod)
42 {
43  const struct m0_moddep *md;
44 
45  return _0C(mod->m_m0 != NULL) &&
46  _0C(0 < mod->m_level_nr && mod->m_level_nr < M0_MODLEV_MAX) &&
47  _0C(mod->m_cur >= M0_MODLEV_NONE &&
48  mod->m_cur < mod->m_level_nr) &&
49  _0C(m0_forall(i, mod->m_level_nr,
50  ergo(mod->m_level_nrefs[i] > 0,
51  mod->m_cur >= i) &&
52  mod->m_level_nrefs[i] == m0_count(
53  j, mod->m_inv_nr,
54  mod->m_inv[j].md_dst == i &&
55  mod->m_inv[j].md_other->m_cur >=
56  mod->m_inv[j].md_src))) &&
57  _0C(mod->m_dep_nr <= ARRAY_SIZE(mod->m_dep)) &&
58  _0C(mod->m_inv_nr <= ARRAY_SIZE(mod->m_inv)) &&
59  _0C(moddeps_are_unique(mod->m_dep, mod->m_dep_nr)) &&
60  _0C(moddeps_are_unique(mod->m_inv, mod->m_inv_nr)) &&
61  m0_forall(i, mod->m_dep_nr,
62  (md = &mod->m_dep[i]) &&
63  _0C(md->md_other != NULL) &&
64  _0C(md->md_other != mod) &&
65  _0C(md->md_src > M0_MODLEV_NONE &&
66  md->md_src < mod->m_level_nr) &&
67  _0C(md->md_dst > M0_MODLEV_NONE &&
68  md->md_dst < md->md_other->m_level_nr) &&
69  /* Check that dependencies are satisfied. */
70  _0C(ergo(mod->m_cur >= md->md_src,
71  md->md_other->m_cur >= md->md_dst)) &&
72  /* Check that there is a matching inverse
73  * dependency. */
74  _0C(m0_exists(j, md->md_other->m_inv_nr,
75  ({
76  const struct m0_moddep *md1 =
77  &md->md_other->m_inv[j];
78 
79  md1->md_other == mod &&
80  md1->md_src == md->md_src &&
81  md1->md_dst == md->md_dst;
82  }))));
83 }
84 
85 static int module_up(struct m0_module *module, int level)
86 {
87  int result = 0;
88  const uint64_t gen = module->m_m0->i_dep_gen;
89 
90  M0_PRE(level < module->m_level_nr);
91  M0_PRE(module_invariant(module));
92 
93  while (module->m_cur < level && result == 0) {
94  int next = module->m_cur + 1;
95  unsigned i;
96  struct m0_moddep *md;
97 
98  for (i = 0; i < module->m_dep_nr && result == 0; ++i) {
99  md = &module->m_dep[i];
100  if (md->md_src == next) {
101  result = module_up(md->md_other, md->md_dst);
102  if (result == 0 &&
103  module->m_m0->i_dep_gen != gen)
104  /*
105  * If generation changed, restart the
106  * initialisation.
107  */
108  result = -EAGAIN;
109  if (result == 0)
110  M0_CNT_INC(md->md_other->m_level_nrefs[
111  md->md_dst]);
112  /*
113  * If dependencies failed, don't attempt any
114  * form of cleanup, because it is impossible:
115  * the original levels of the modules we
116  * (transitively) depend on are no longer known.
117  */
118  }
119  }
120  if (result == 0 && module->m_level[next].ml_enter != NULL) {
121  result = module->m_level[next].ml_enter(module);
122  M0_ASSERT(result != -EAGAIN);
123  }
124  if (result == 0)
125  module->m_cur = next;
126  }
127  M0_POST(module_invariant(module));
128  return result;
129 }
130 
131 M0_INTERNAL int m0_module_init(struct m0_module *module, int level)
132 {
133  int result;
135 
136  /* Repeat initialisation if a new module or dependency were added. */
137  while ((result = module_up(module, level)) == -EAGAIN)
138  ;
139  return result;
140 }
141 
142 M0_INTERNAL void m0_module_fini(struct m0_module *module, int level)
143 {
144  M0_PRE(M0_MODLEV_NONE <= level && level < module->m_level_nr);
145  M0_PRE(module_invariant(module));
146 
147  while (level < module->m_cur &&
148  module->m_level_nrefs[module->m_cur] == 0) {
149  int cur = module->m_cur;
150  int i;
151  struct m0_moddep *md;
152 
153  if (module->m_level[cur].ml_leave != NULL)
154  module->m_level[cur].ml_leave(module);
155  --module->m_cur;
156  for (i = module->m_dep_nr - 1; i >= 0; --i) {
157  md = &module->m_dep[i];
158  if (md->md_src == cur) {
159  M0_CNT_DEC(md->md_other->m_level_nrefs[
160  md->md_dst]);
161  m0_module_fini(md->md_other, M0_MODLEV_NONE);
162  }
163  }
164  }
165  M0_POST(module_invariant(module));
166 }
167 
168 M0_INTERNAL void m0_module_dep_add(struct m0_module *m0, int l0,
169  struct m0_module *m1, int l1)
170 {
171  M0_PRE(m0 != m1);
172  M0_PRE(m0->m_m0 == m1->m_m0);
175  M0_PRE(l0 > M0_MODLEV_NONE && l1 > M0_MODLEV_NONE);
176  M0_PRE(m0->m_cur < l0); /* Otherwise it is too late to enforce the
177  * dependency. */
178 
179  M0_ASSERT(m0->m_dep_nr < ARRAY_SIZE(m0->m_dep));
180  m0->m_dep[m0->m_dep_nr++] =
181  (struct m0_moddep)M0_MODDEP_INIT(m1, l0, l1);
182 
183  M0_ASSERT(m1->m_inv_nr < ARRAY_SIZE(m1->m_inv));
184  m1->m_inv[m1->m_inv_nr++] =
185  (struct m0_moddep)M0_MODDEP_INIT(m0, l0, l1);
186 
187  M0_CNT_INC(m0->m_m0->i_dep_gen);
188 
191 }
192 
193 M0_INTERNAL void m0_module_setup(struct m0_module *module, const char *name,
194  const struct m0_modlev *level, int level_nr,
195  struct m0 *instance)
196 {
197  *module = (struct m0_module){
198  .m_name = name,
199  .m_m0 = instance,
200  .m_cur = M0_MODLEV_NONE,
201  .m_level = level,
202  .m_level_nr = level_nr
203  };
204  M0_POST(module_invariant(module));
205 }
206 
209 /*
210  * Local variables:
211  * c-indentation-style: "K&R"
212  * c-basic-offset: 8
213  * tab-width: 8
214  * fill-column: 80
215  * scroll-step: 1
216  * End:
217  */
218 /*
219  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
220  */
static bool module_invariant(const struct m0_module *mod)
Definition: module.c:41
#define M0_PRE(cond)
#define NULL
Definition: misc.h:38
#define ergo(a, b)
Definition: misc.h:293
static int module_up(struct m0_module *module, int level)
Definition: module.c:85
Definition: beck.c:170
static bool moddeps_are_unique(const struct m0_moddep *arr, unsigned n)
Definition: module.c:35
#define m0_count(var, nr,...)
Definition: misc.h:79
enum m0_trace_level level
Definition: trace.c:111
static struct m0_mdstore md
Definition: sd_common.c:42
unsigned m_dep_nr
Definition: module.h:177
#define m0_exists(var, nr,...)
Definition: misc.h:134
const char * name
Definition: module.c:60
static int cur(enum module_id id)
Definition: module.c:191
M0_INTERNAL bool m0_elems_are_unique(const void *array, unsigned nr_elems, size_t elem_size)
Definition: misc.c:257
void(* ml_leave)(struct m0_module *module)
Definition: module.h:121
struct m0_moddep m_inv[M0_MODDEP_MAX]
Definition: module.h:179
struct m0 * m_m0
Definition: module.h:153
const char * m_name
Definition: module.h:152
int i
Definition: dir.c:1033
unsigned m_inv_nr
Definition: module.h:180
struct m0_module * md_other
Definition: module.h:132
int md_dst
Definition: module.h:134
#define M0_ASSERT(cond)
unsigned m_level_nrefs[M0_MODLEV_MAX]
Definition: module.h:174
int(* ml_enter)(struct m0_module *module)
Definition: module.h:119
static int next[]
Definition: cp.c:248
M0_INTERNAL void m0_module_setup(struct m0_module *module, const char *name, const struct m0_modlev *level, int level_nr, struct m0 *instance)
Definition: module.c:193
Definition: instance.h:80
#define M0_POST(cond)
int md_src
Definition: module.h:133
int m_level_nr
Definition: module.h:168
#define m0_forall(var, nr,...)
Definition: misc.h:112
M0_INTERNAL void m0_module_dep_add(struct m0_module *m0, int l0, struct m0_module *m1, int l1)
Definition: module.c:168
#define M0_MODDEP_INIT(other, src, dst)
Definition: module.h:137
uint64_t n
Definition: fops.h:107
#define M0_CNT_INC(cnt)
Definition: arith.h:226
int m_cur
Definition: module.h:160
#define _0C(exp)
Definition: assert.h:311
static struct m0 instance
Definition: main.c:78
#define M0_CNT_DEC(cnt)
Definition: arith.h:219
uint64_t i_dep_gen
Definition: instance.h:86
#define ARRAY_SIZE(a)
Definition: misc.h:45
M0_INTERNAL void m0_module_fini(struct m0_module *module, int level)
Definition: module.c:142
const struct m0_modlev * m_level
Definition: module.h:167
struct m0_moddep m_dep[M0_MODDEP_MAX]
Definition: module.h:176
M0_INTERNAL int m0_module_init(struct m0_module *module, int level)
Definition: module.c:131