Motr  M0
obj_ops.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2013-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_CONF
24 #include "lib/trace.h"
25 
26 #include "conf/obj_ops.h"
27 #include "conf/cache.h"
28 #include "conf/onwire.h" /* m0_confx_obj */
29 #include "conf/dir.h" /* m0_conf_dir_tl */
30 #include "motr/magic.h" /* M0_CONF_OBJ_MAGIC */
31 #include "lib/errno.h" /* ENOMEM */
32 
41 static bool _generic_obj_invariant(const void *bob);
42 static bool _concrete_obj_invariant(const struct m0_conf_obj *obj);
43 
44 static const struct m0_bob_type generic_obj_bob = {
45  .bt_name = "m0_conf_obj",
46  .bt_magix_offset = M0_MAGIX_OFFSET(struct m0_conf_obj, co_gen_magic),
47  .bt_magix = M0_CONF_OBJ_MAGIC,
48  .bt_check = _generic_obj_invariant
49 };
51 
52 M0_INTERNAL bool m0_conf_obj_invariant(const struct m0_conf_obj *obj)
53 {
54  return _0C(m0_conf_obj_bob_check(obj)) && _concrete_obj_invariant(obj);
55 }
56 
57 static bool _generic_obj_invariant(const void *bob)
58 {
59  const struct m0_conf_obj *obj = bob;
60 
61  return _0C(m0_fid_is_set(&obj->co_id) && obj->co_ops != NULL) &&
62  _0C(m0_conf_fid_is_valid(&obj->co_id)) &&
63  _0C(obj->co_ha_state >= M0_NC_UNKNOWN) &&
64  _0C(obj->co_ha_state < M0_NC_NR &&
65  M0_IN(obj->co_status, (M0_CS_MISSING, M0_CS_LOADING,
66  M0_CS_READY))) &&
67  _0C(ergo(m0_conf_obj_is_stub(obj), obj->co_nrefs == 0));
68 }
69 
70 static bool _concrete_obj_invariant(const struct m0_conf_obj *obj)
71 {
72  bool ret = obj->co_ops->coo_invariant(obj);
73  if (unlikely(!ret))
74  M0_LOG(M0_ERROR, "Configuration object invariant does not hold:"
75  " id="FID_F, FID_P(&obj->co_id));
76  return ret;
77 }
78 
79 M0_INTERNAL struct m0_conf_obj *
80 m0_conf_obj_create(const struct m0_fid *id, struct m0_conf_cache *cache)
81 {
82  struct m0_conf_obj *obj;
83  const struct m0_conf_obj_type *type = m0_conf_fid_type(id);
84 
85  M0_PRE(cache != NULL && m0_fid_is_set(id));
86  M0_PRE(type->cot_create != NULL);
87 
88  /* Allocate concrete object; initialise concrete fields. */
89  obj = type->cot_create();
90  if (obj == NULL)
91  return NULL;
92 
93  /* Initialise generic fields. */
94  obj->co_id = *id;
95  obj->co_status = M0_CS_MISSING;
96  obj->co_cache = cache;
97  m0_conf_obj_bob_init(obj);
98  M0_ASSERT(obj->co_gen_magic == M0_CONF_OBJ_MAGIC);
99  M0_ASSERT(obj->co_con_magic == type->cot_magic);
100  m0_chan_init(&obj->co_chan, cache->ca_lock);
101  m0_chan_init(&obj->co_ha_chan, cache->ca_lock);
102  m0_conf_cache_tlink_init(obj);
103  m0_conf_dir_tlink_init(obj);
104  /*
105  * m0_ha_state_accept() does not expect .co_ha_state to be
106  * M0_NC_UNKNOWN. Initialise it to M0_NC_ONLINE.
107  */
108  obj->co_ha_state = M0_NC_ONLINE;
109  m0_conf_obj_bob_init(obj);
110  M0_ASSERT(obj->co_gen_magic == M0_CONF_OBJ_MAGIC);
111  M0_ASSERT(obj->co_con_magic == type->cot_magic);
112 
114  return obj;
115 }
116 
117 static int stub_create(struct m0_conf_cache *cache,
118  const struct m0_fid *id, struct m0_conf_obj **out)
119 {
120  int rc;
121 
122  M0_ENTRY();
123 
124  *out = m0_conf_obj_create(id, cache);
125  if (*out == NULL)
126  return M0_ERR(-ENOMEM);
127 
129  if (rc != 0) {
131  *out = NULL;
132  }
133  return M0_RC(rc);
134 }
135 
136 M0_INTERNAL int m0_conf_obj_find(struct m0_conf_cache *cache,
137  const struct m0_fid *id,
138  struct m0_conf_obj **out)
139 {
140  int rc = 0;
141 
142  M0_ENTRY(FID_F, FID_P(id));
144 
146  if (*out == NULL)
147  rc = stub_create(cache, id, out);
148 
149  M0_POST(ergo(rc == 0,
150  m0_conf_obj_invariant(*out) && (*out)->co_cache == cache));
151  return M0_RC(rc);
152 }
153 
154 M0_INTERNAL int m0_conf_obj_find_lock(struct m0_conf_cache *cache,
155  const struct m0_fid *id,
156  struct m0_conf_obj **out)
157 {
158  int rc;
159 
160  M0_ENTRY();
162  rc = m0_conf_obj_find(cache, id, out);
164  return M0_RC(rc);
165 }
166 
167 M0_INTERNAL void m0_conf_obj_delete(struct m0_conf_obj *obj)
168 {
169  M0_ENTRY("obj=%p/"FID_F, obj, FID_P(&obj->co_id));
171  M0_PRE(obj->co_nrefs == 0);
172  M0_PRE(obj->co_status != M0_CS_LOADING);
173 
174  /* Finalise generic fields. */
175  m0_conf_dir_tlink_fini(obj);
176  m0_conf_cache_tlink_fini(obj);
177  m0_chan_fini(&obj->co_ha_chan);
178  m0_chan_fini(&obj->co_chan);
179  m0_conf_obj_bob_fini(obj);
180 
181  /* Finalise concrete fields; free the object. */
182  obj->co_ops->coo_delete(obj);
183  M0_LEAVE();
184 }
185 
186 M0_INTERNAL void m0_conf_obj_get(struct m0_conf_obj *obj)
187 {
188  M0_ENTRY("obj=%p/"FID_F" nrefs: %" PRIu64 " -> %"PRIu64, obj,
189  FID_P(&obj->co_id), obj->co_nrefs, obj->co_nrefs + 1);
191  M0_PRE(m0_conf_cache_is_locked(obj->co_cache));
192  M0_PRE(obj->co_status == M0_CS_READY);
193 
194  M0_CNT_INC(obj->co_nrefs);
195  M0_LEAVE();
196 }
197 
198 M0_INTERNAL void m0_conf_obj_get_lock(struct m0_conf_obj *obj)
199 {
200  m0_conf_cache_lock(obj->co_cache);
202  m0_conf_cache_unlock(obj->co_cache);
203 }
204 
205 M0_INTERNAL void m0_conf_obj_put(struct m0_conf_obj *obj)
206 {
207  M0_ENTRY("obj=%p/"FID_F" nrefs: %" PRIu64 " -> %"PRIu64, obj,
208  FID_P(&obj->co_id), obj->co_nrefs, obj->co_nrefs - 1);
210  M0_PRE(m0_conf_cache_is_locked(obj->co_cache));
211  M0_PRE(obj->co_status == M0_CS_READY);
212 
213  M0_CNT_DEC(obj->co_nrefs);
214  if (obj->co_nrefs == 0)
215  m0_chan_broadcast(&obj->co_chan);
216  M0_LEAVE();
217 }
218 
220 static bool confx_obj_is_valid(const struct m0_confx_obj *flat)
221 {
222  /* XXX TODO
223  * - All of m0_fid-s contained in `flat' are m0_fid_is_set();
224  * - all of fid_arr-s are populated with valid m0_fid-s;
225  * - etc.
226  */
227  (void)flat; /* XXX */
228  return true;
229 }
230 
231 M0_INTERNAL int
233 {
234  int rc;
235  struct m0_conf_cache *cache = dest->co_cache;
236 
237  M0_ENTRY("dest="FID_F, FID_P(&dest->co_id));
240  M0_PRE(m0_conf_obj_is_stub(dest) && dest->co_nrefs == 0);
244 
245  rc = dest->co_ops->coo_decode(dest, src);
246  dest->co_status = rc == 0 ? M0_CS_READY : M0_CS_MISSING;
247 
250 
251  return M0_RC(rc);
252 }
253 
254 M0_INTERNAL bool m0_conf_obj_match(const struct m0_conf_obj *cached,
255  const struct m0_confx_obj *flat)
256 {
257  M0_PRE(m0_conf_obj_invariant(cached));
258  M0_PRE(confx_obj_is_valid(flat));
259 
260  return m0_conf_obj_type(cached) == m0_conf_objx_type(flat) &&
261  m0_fid_eq(&cached->co_id, m0_conf_objx_fid(flat)) &&
262  (m0_conf_obj_is_stub(cached) ||
263  cached->co_ops->coo_match(cached, flat));
264 }
265 
266 const struct m0_fid *m0_conf_objx_fid(const struct m0_confx_obj *obj)
267 {
268  return &obj->xo_u.u_header.ch_id;
269 }
270 
272 {
274 }
275 
277 #undef M0_TRACE_SUBSYSTEM
const struct m0_conf_obj_type * m0_conf_obj_type(const struct m0_conf_obj *obj)
Definition: obj.c:363
struct m0_fid co_id
Definition: obj.h:208
Definition: beck.c:235
uint64_t id
Definition: cob.h:2380
M0_BOB_DEFINE(static, &generic_obj_bob, m0_conf_obj)
#define unlikely(x)
Definition: assert.h:74
#define M0_PRE(cond)
static bool confx_obj_is_valid(const struct m0_confx_obj *flat)
Definition: obj_ops.c:220
M0_INTERNAL bool m0_conf_obj_match(const struct m0_conf_obj *cached, const struct m0_confx_obj *flat)
Definition: obj_ops.c:254
#define NULL
Definition: misc.h:38
static int stub_create(struct m0_conf_cache *cache, const struct m0_fid *id, struct m0_conf_obj **out)
Definition: obj_ops.c:117
#define ergo(a, b)
Definition: misc.h:293
static bool _concrete_obj_invariant(const struct m0_conf_obj *obj)
Definition: obj_ops.c:70
M0_INTERNAL struct m0_conf_obj * m0_conf_cache_lookup(const struct m0_conf_cache *cache, const struct m0_fid *id)
Definition: cache.c:106
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
const struct m0_conf_obj_type * m0_conf_fid_type(const struct m0_fid *fid)
Definition: obj.c:368
Definition: note.h:172
M0_INTERNAL void m0_conf_obj_put(struct m0_conf_obj *obj)
Definition: obj_ops.c:205
M0_INTERNAL bool m0_fid_is_set(const struct m0_fid *fid)
Definition: fid.c:106
M0_INTERNAL bool m0_conf_obj_is_stub(const struct m0_conf_obj *obj)
Definition: obj.c:302
static struct foo * obj
Definition: tlist.c:302
const char * bt_name
Definition: bob.h:73
static bool _generic_obj_invariant(const void *bob)
Definition: obj_ops.c:57
return M0_RC(rc)
static const struct m0_bob_type generic_obj_bob
Definition: obj_ops.c:44
M0_INTERNAL int m0_conf_obj_fill(struct m0_conf_obj *dest, const struct m0_confx_obj *src)
Definition: obj_ops.c:232
#define M0_ENTRY(...)
Definition: trace.h:170
M0_INTERNAL void m0_conf_obj_get(struct m0_conf_obj *obj)
Definition: obj_ops.c:186
#define PRIu64
Definition: types.h:58
return M0_ERR(-EOPNOTSUPP)
M0_INTERNAL void m0_chan_init(struct m0_chan *chan, struct m0_mutex *ch_guard)
Definition: chan.c:96
#define M0_ASSERT(cond)
const struct m0_fid * m0_conf_objx_fid(const struct m0_confx_obj *obj)
Definition: obj_ops.c:266
M0_INTERNAL bool m0_conf_cache_is_locked(const struct m0_conf_cache *cache)
Definition: cache.c:60
M0_INTERNAL int m0_conf_obj_find_lock(struct m0_conf_cache *cache, const struct m0_fid *id, struct m0_conf_obj **out)
Definition: obj_ops.c:154
#define M0_POST(cond)
M0_INTERNAL int m0_conf_obj_find(struct m0_conf_cache *cache, const struct m0_fid *id, struct m0_conf_obj **out)
Definition: obj_ops.c:136
M0_INTERNAL int m0_conf_cache_add(struct m0_conf_cache *cache, struct m0_conf_obj *obj)
Definition: cache.c:79
bool m0_conf_fid_is_valid(const struct m0_fid *fid)
Definition: obj.c:378
#define FID_P(f)
Definition: fid.h:77
M0_INTERNAL void m0_conf_obj_get_lock(struct m0_conf_obj *obj)
Definition: obj_ops.c:198
M0_INTERNAL bool m0_fid_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: fid.c:164
M0_INTERNAL struct m0_conf_obj * m0_conf_obj_create(const struct m0_fid *id, struct m0_conf_cache *cache)
Definition: obj_ops.c:80
#define M0_MAGIX_OFFSET(type, field)
Definition: misc.h:356
#define M0_CNT_INC(cnt)
Definition: arith.h:226
Definition: fid.h:38
M0_INTERNAL void m0_conf_obj_delete(struct m0_conf_obj *obj)
Definition: obj_ops.c:167
#define _0C(exp)
Definition: assert.h:311
#define M0_CNT_DEC(cnt)
Definition: arith.h:219
M0_INTERNAL void m0_chan_fini(struct m0_chan *chan)
Definition: chan.c:104
const struct m0_conf_obj_type * m0_conf_objx_type(const struct m0_confx_obj *obj)
Definition: obj_ops.c:271
#define out(...)
Definition: gen.c:41
bool(* coo_match)(const struct m0_conf_obj *cached, const struct m0_confx_obj *flat)
Definition: obj_ops.h:101
int type
Definition: dir.c:1031
M0_INTERNAL void m0_conf_cache_lock(struct m0_conf_cache *cache)
Definition: cache.c:50
struct m0_pdclust_src_addr src
Definition: fd.c:108
M0_INTERNAL void m0_chan_broadcast(struct m0_chan *chan)
Definition: chan.c:172
int32_t rc
Definition: trigger_fop.h:47
M0_INTERNAL void m0_conf_cache_unlock(struct m0_conf_cache *cache)
Definition: cache.c:55
M0_INTERNAL bool m0_conf_obj_invariant(const struct m0_conf_obj *obj)
Definition: obj_ops.c:52
#define FID_F
Definition: fid.h:75
const struct m0_conf_obj_ops * co_ops
Definition: obj.h:212