Motr  M0
cache.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2015-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/cache.h"
27 #include "conf/obj_ops.h" /* m0_conf_obj_delete */
28 #include "conf/preload.h" /* m0_confx_to_string */
29 #include "motr/magic.h" /* M0_CONF_OBJ_MAGIC, M0_CONF_CACHE_MAGIC */
30 #include "conf/onwire.h" /* m0_confx */
31 #include "lib/errno.h" /* EEXIST */
32 #include "lib/memory.h" /* M0_ALLOC_PTR, M0_ALLOC_ARR */
33 
45 M0_TL_DESCR_DEFINE(m0_conf_cache, "registered m0_conf_obj-s", ,
46  struct m0_conf_obj, co_cache_link, co_gen_magic,
48 M0_TL_DEFINE(m0_conf_cache, M0_INTERNAL, struct m0_conf_obj);
49 
50 M0_INTERNAL void m0_conf_cache_lock(struct m0_conf_cache *cache)
51 {
52  m0_mutex_lock(cache->ca_lock);
53 }
54 
55 M0_INTERNAL void m0_conf_cache_unlock(struct m0_conf_cache *cache)
56 {
57  m0_mutex_unlock(cache->ca_lock);
58 }
59 
60 M0_INTERNAL bool m0_conf_cache_is_locked(const struct m0_conf_cache *cache)
61 {
62  return m0_mutex_is_locked(cache->ca_lock);
63 }
64 
65 M0_INTERNAL void
67 {
68  M0_ENTRY();
69 
70  m0_conf_cache_tlist_init(&cache->ca_registry);
71  cache->ca_lock = lock;
72  cache->ca_ver = 0;
73  cache->ca_fid_counter = 0;
74 
75  M0_LEAVE();
76 }
77 
78 M0_INTERNAL int
80 {
81  const struct m0_conf_obj *x;
82 
83  M0_ENTRY();
85  M0_PRE(!m0_conf_cache_tlink_is_in(obj));
86 
87  x = m0_conf_cache_lookup(cache, &obj->co_id);
88  if (x != NULL)
89  return M0_ERR(-EEXIST);
90  m0_conf_cache_tlist_add(&cache->ca_registry, obj);
91  return M0_RC(0);
92 }
93 
94 M0_INTERNAL bool m0_conf_cache_contains(struct m0_conf_cache *cache,
95  const struct m0_fid *fid)
96 {
97  bool ret;
98 
100  ret = m0_conf_cache_lookup(cache, fid) != NULL;
102  return ret;
103 }
104 
105 M0_INTERNAL struct m0_conf_obj *
107  const struct m0_fid *id)
108 {
109  return m0_tl_find(m0_conf_cache, obj, &cache->ca_registry,
110  m0_fid_eq(&obj->co_id, id));
111 }
112 
113 static void _obj_del(struct m0_conf_obj *obj)
114 {
115  M0_ENTRY("obj="FID_F, FID_P(&obj->co_id));
116 
117  m0_conf_cache_tlist_del(obj);
119 
120  M0_LEAVE();
121 }
122 
123 M0_INTERNAL void
125 {
126  M0_ENTRY();
128  M0_PRE(m0_conf_cache_tlist_contains(&cache->ca_registry, obj));
129 
130  _obj_del(obj);
131 
132  M0_LEAVE();
133 }
134 
136  const struct m0_conf_obj_type *type,
137  bool gc)
138 {
139  struct m0_conf_obj *obj;
140 
141  M0_ENTRY();
143 
144  if (type == NULL)
145  /*
146  * m0_conf_dirs are intermixed with other objects in
147  * cache->ca_registry. m0_conf_obj_delete() of a non-dir
148  * object will fail if this object is still linked to some
149  * dir --- there is m0_conf_dir_tlink_fini() in
150  * m0_conf_obj_delete(), and m0_tlink_fini() asserts
151  * that the entry does not belong any list.
152  *
153  * Delete dir objects first.
154  */
156 
157  m0_tl_for(m0_conf_cache, &cache->ca_registry, obj) {
158  M0_ASSERT(gc || !obj->co_deleted);
159  if (type == NULL || m0_conf_obj_type(obj) == type) {
160  if (gc && !obj->co_deleted)
161  continue;
162  _obj_del(obj);
163  }
164  } m0_tl_endfor;
165  M0_LEAVE();
166 }
167 
168 M0_INTERNAL void m0_conf_cache_clean(struct m0_conf_cache *cache,
169  const struct m0_conf_obj_type *type)
170 {
171  M0_ENTRY();
172  conf_cache_clean(cache, type, false);
173  M0_LEAVE();
174 }
175 
176 M0_INTERNAL void m0_conf_cache_gc(struct m0_conf_cache *cache)
177 {
178  M0_ENTRY();
179  conf_cache_clean(cache, NULL, true);
180  M0_LEAVE();
181 }
182 
183 M0_INTERNAL void m0_conf_cache_fini(struct m0_conf_cache *cache)
184 {
185  M0_ENTRY();
186 
189  m0_conf_cache_tlist_fini(&cache->ca_registry);
191 
192  M0_LEAVE();
193 }
194 
195 static int
196 conf_encode(struct m0_confx *enc, const struct m0_conf_obj *obj, bool debug)
197 {
198  int rc;
199 
200  M0_PRE(debug ||
201  (m0_conf_obj_invariant(obj) && obj->co_status == M0_CS_READY));
202 
203  rc = obj->co_ops->coo_encode(M0_CONFX_AT(enc, enc->cx_nr), obj);
204  if (rc == 0)
205  ++enc->cx_nr;
206  return M0_RC(rc);
207 }
208 
209 static int conf_cache_encode(const struct m0_conf_cache *cache,
210  struct m0_confx *dest, bool debug)
211 {
212  struct m0_conf_obj *obj = NULL;
213  int rc = 0;
214  size_t nr;
215  char *data;
216 
217  M0_ENTRY();
219 
220  M0_SET0(dest);
221 
222  if (!debug && !m0_tl_forall(m0_conf_cache, scan, &cache->ca_registry,
224  scan->co_status == M0_CS_READY))
225  return M0_ERR_INFO(-EINVAL, FID_F" status=%u",
226  FID_P(&obj->co_id), obj->co_status);
227 
228  nr = m0_tl_reduce(m0_conf_cache, scan, &cache->ca_registry, 0,
230 
232  if (data == NULL)
233  return M0_ERR(-ENOMEM);
234  /* "data" is freed by m0_confx_free(dest). */
235  dest->cx__objs = (void *)data;
236 
237  M0_LOG(M0_DEBUG, "Will encode %zu configuration objects", nr);
238  m0_tl_for(m0_conf_cache, &cache->ca_registry, obj) {
240  rc = conf_encode(dest, obj, debug);
241  if (rc != 0)
242  break;
243  }
244  } m0_tl_endfor;
245 
246  if (rc == 0) {
247  M0_ASSERT(nr == dest->cx_nr);
248  } else {
249  m0_free(data);
250  dest->cx__objs = NULL;
251  }
252 
253  return M0_RC(rc);
254 }
255 
256 M0_INTERNAL int
257 m0_conf_cache_to_string(struct m0_conf_cache *cache, char **str, bool debug)
258 {
259  struct m0_confx *confx;
260  int rc;
261 
262  M0_ENTRY();
263 
264  M0_ALLOC_PTR(confx);
265  if (confx == NULL)
266  return M0_ERR(-ENOMEM);
267 
269  rc = conf_cache_encode(cache, confx, debug);
271  if (rc == 0)
272  rc = m0_confx_to_string(confx, str);
273  m0_confx_free(confx);
274  return M0_RC(rc);
275 }
276 
277 M0_INTERNAL int
279 {
280  struct m0_confx *enc;
281  uint32_t i;
282  int rc;
283 
284  M0_ENTRY();
285 
286  M0_PRE(str != NULL);
288 
289  rc = m0_confstr_parse(str, &enc);
290  if (rc != 0)
291  return M0_ERR(rc);
292 
293  for (i = 0; i < enc->cx_nr && rc == 0; ++i) {
294  struct m0_conf_obj *obj;
295  const struct m0_confx_obj *xobj = M0_CONFX_AT(enc, i);
296 
298  m0_conf_obj_fill(obj, xobj);
299  }
300  m0_confx_free(enc);
301  return M0_RC(rc);
302 }
303 
304 M0_INTERNAL int m0_conf_version(struct m0_conf_cache *cache)
305 {
306  struct m0_conf_obj *obj;
307  int ver = 0;
308 
309  M0_ENTRY();
310 
313  if (obj != NULL)
314  ver = M0_CONF_CAST(obj, m0_conf_root)->rt_verno;
316  return M0_RC(ver);
317 }
318 
319 M0_INTERNAL struct m0_conf_obj *
321 {
323  return m0_tl_find(m0_conf_cache, obj, &cache->ca_registry,
324  obj->co_nrefs != 0);
325 }
326 
328 #undef M0_TRACE_SUBSYSTEM
const struct m0_conf_obj_type * m0_conf_obj_type(const struct m0_conf_obj *obj)
Definition: obj.c:363
Definition: beck.c:235
static struct m0_mutex lock
Definition: transmit.c:326
static size_t nr
Definition: dump.c:1505
#define M0_PRE(cond)
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
M0_INTERNAL struct m0_conf_obj * m0_conf_cache_pinned(const struct m0_conf_cache *cache)
Definition: cache.c:320
M0_INTERNAL void m0_confx_free(struct m0_confx *enc)
Definition: preload.c:33
static struct cgc_context gc
Definition: index_gc.c:132
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
#define NULL
Definition: misc.h:38
static bool x
Definition: sm.c:168
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()
static void conf_cache_clean(struct m0_conf_cache *cache, const struct m0_conf_obj_type *type, bool gc)
Definition: cache.c:135
struct m0_bufvec data
Definition: di.c:40
#define M0_CONFX_AT(cx, idx)
Definition: onwire.h:271
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
static struct foo * obj
Definition: tlist.c:302
#define m0_tl_endfor
Definition: tlist.h:700
struct m0_fid fid
Definition: di.c:46
return M0_RC(rc)
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_TL_DEFINE(m0_conf_cache, M0_INTERNAL, struct m0_conf_obj)
int i
Definition: dir.c:1033
#define M0_ERR_INFO(rc, fmt,...)
Definition: trace.h:215
return M0_ERR(-EOPNOTSUPP)
uint32_t cx_nr
Definition: onwire.h:259
#define M0_ASSERT(cond)
M0_INTERNAL int m0_conf_cache_to_string(struct m0_conf_cache *cache, char **str, bool debug)
Definition: cache.c:257
M0_INTERNAL bool m0_mutex_is_locked(const struct m0_mutex *mutex)
Definition: mutex.c:95
M0_INTERNAL int m0_confx_to_string(struct m0_confx *confx, char **out)
Definition: preload.c:60
M0_INTERNAL void m0_conf_cache_init(struct m0_conf_cache *cache, struct m0_mutex *lock)
Definition: cache.c:66
M0_TL_DESCR_DEFINE(m0_conf_cache, "registered m0_conf_obj-s",, struct m0_conf_obj, co_cache_link, co_gen_magic, M0_CONF_OBJ_MAGIC, M0_CONF_CACHE_MAGIC)
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(struct m0_conf_cache *cache, const struct m0_fid *id, struct m0_conf_obj **out)
Definition: obj_ops.c:136
#define M0_CONF_CAST(ptr, type)
Definition: obj.h:780
M0_INTERNAL int m0_conf_cache_add(struct m0_conf_cache *cache, struct m0_conf_obj *obj)
Definition: cache.c:79
#define FID_P(f)
Definition: fid.h:77
M0_INTERNAL size_t m0_confx_sizeof(void)
Definition: db.c:61
M0_INTERNAL bool m0_fid_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: fid.c:164
static int conf_cache_encode(const struct m0_conf_cache *cache, struct m0_confx *dest, bool debug)
Definition: cache.c:209
M0_INTERNAL int m0_confstr_parse(const char *str, struct m0_confx **out)
Definition: preload.c:41
Definition: fid.h:38
M0_INTERNAL void m0_conf_cache_del(const struct m0_conf_cache *cache, struct m0_conf_obj *obj)
Definition: cache.c:124
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
M0_INTERNAL int m0_conf_cache_from_string(struct m0_conf_cache *cache, const char *str)
Definition: cache.c:278
const struct m0_fid M0_CONF_ROOT_FID
Definition: root.c:226
M0_INTERNAL int m0_conf_version(struct m0_conf_cache *cache)
Definition: cache.c:304
M0_INTERNAL void m0_conf_obj_delete(struct m0_conf_obj *obj)
Definition: obj_ops.c:167
M0_INTERNAL void m0_conf_cache_clean(struct m0_conf_cache *cache, const struct m0_conf_obj_type *type)
Definition: cache.c:168
M0_INTERNAL void m0_conf_cache_gc(struct m0_conf_cache *cache)
Definition: cache.c:176
M0_INTERNAL bool m0_conf_cache_contains(struct m0_conf_cache *cache, const struct m0_fid *fid)
Definition: cache.c:94
int type
Definition: dir.c:1031
M0_INTERNAL void m0_conf_cache_fini(struct m0_conf_cache *cache)
Definition: cache.c:183
M0_INTERNAL void m0_conf_cache_lock(struct m0_conf_cache *cache)
Definition: cache.c:50
static int scan(struct scanner *s)
Definition: beck.c:963
#define m0_tl_find(name, var, head,...)
Definition: tlist.h:757
const struct m0_conf_obj_type M0_CONF_DIR_TYPE
Definition: dir.c:206
#define m0_tl_for(name, head, obj)
Definition: tlist.h:695
static void _obj_del(struct m0_conf_obj *obj)
Definition: cache.c:113
void m0_free(void *data)
Definition: memory.c:146
Definition: mutex.h:47
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
static int conf_encode(struct m0_confx *enc, const struct m0_conf_obj *obj, bool debug)
Definition: cache.c:196
#define FID_F
Definition: fid.h:75
const struct m0_fid * m0_conf_objx_fid(const struct m0_confx_obj *obj)
Definition: obj_ops.c:266
#define m0_tl_forall(name, var, head,...)
Definition: tlist.h:735