Motr  M0
confd_fom.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-2020 Seagate Technology LLC and/or its Affiliates
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * For any questions about this software or licensing,
17  * please email opensource@seagate.com or cortx-questions@seagate.com.
18  *
19  */
20 
21 
22 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_CONF
23 #include "lib/trace.h"
24 
25 #include "conf/confd_fom.h"
26 #include "conf/fop.h" /* m0_conf_fetch_resp_fopt */
27 #include "conf/confd.h" /* m0_confd, m0_confd_bob */
28 #include "conf/obj_ops.h" /* m0_conf_obj_invariant */
29 #include "conf/preload.h" /* m0_confx_free */
30 #include "conf/onwire.h"
31 #include "rpc/rpc_opcodes.h" /* M0_CONF_FETCH_OPCODE */
32 #include "fop/fom_generic.h" /* M0_FOPH_NR */
33 #include "fid/fid.h" /* m0_fid, m0_fid_arr */
34 #include "lib/memory.h" /* m0_free */
35 #include "lib/misc.h" /* M0_SET0 */
36 #include "lib/errno.h" /* ENOMEM, EOPNOTSUPP */
37 
44 static int conf_fetch_tick(struct m0_fom *fom);
45 static int conf_update_tick(struct m0_fom *fom);
46 static int confx_populate(struct m0_confx *dest, const struct m0_fid *origin,
47  const struct m0_fid_arr *path,
48  struct m0_conf_cache *cache);
49 
50 static size_t confd_fom_locality(const struct m0_fom *fom)
51 {
52  return m0_fop_opcode(fom->fo_fop);
53 }
54 
55 static void confd_fom_fini(struct m0_fom *fom)
56 {
58  m0_free(container_of(fom, struct m0_confd_fom, dm_fom));
59 }
60 
61 static const struct m0_fom_ops conf_fetch_fom_ops = {
63  .fo_tick = conf_fetch_tick,
64  .fo_fini = confd_fom_fini
65 };
66 
67 static const struct m0_fom_ops conf_update_fom_ops = {
69  .fo_tick = conf_update_tick,
70  .fo_fini = confd_fom_fini
71 };
72 
73 M0_INTERNAL int m0_confd_fom_create(struct m0_fop *fop,
74  struct m0_fom **out,
75  struct m0_reqh *reqh)
76 {
77  struct m0_confd_fom *m;
78  const struct m0_fom_ops *ops;
79  struct m0_fop *rep_fop;
80 
81  M0_ENTRY();
82 
83  M0_ALLOC_PTR(m);
84  if (m == NULL)
85  return M0_ERR(-ENOMEM);
86 
87  switch (m0_fop_opcode(fop)) {
90  break;
93  break;
94  default:
95  m0_free(m);
96  return M0_ERR(-EOPNOTSUPP);
97  }
99  if (rep_fop == NULL) {
100  m0_free(m);
101  return M0_ERR(-ENOMEM);
102  }
103  m0_fom_init(&m->dm_fom, &fop->f_type->ft_fom_type, ops, fop, rep_fop,
104  reqh);
105  *out = &m->dm_fom;
106 
107  return M0_RC(0);
108 }
109 
110 static int conf_fetch_tick(struct m0_fom *fom)
111 {
112  const struct m0_conf_fetch *q;
113  struct m0_conf_fetch_resp *r;
114  struct m0_confd *confd;
115  int rc;
116 
117  M0_ENTRY("fom = %p", fom);
118 
119  if (m0_fom_phase(fom) < M0_FOPH_NR)
120  return m0_fom_tick_generic(fom);
121 
122  q = m0_fop_data(fom->fo_fop);
123  r = m0_fop_data(fom->fo_rep_fop);
124 
125  confd = bob_of(fom->fo_service, struct m0_confd, d_reqh, &m0_confd_bob);
126  m0_conf_cache_lock(confd->d_cache);
127  rc = confx_populate(&r->fr_data, &q->f_origin, &q->f_path,
128  confd->d_cache);
130  if (rc != 0)
131  M0_ASSERT(r->fr_data.cx_nr == 0 && r->fr_data.cx__objs == NULL);
132  r->fr_rc = rc;
133  r->fr_ver = confd->d_cache->ca_ver;
134  M0_ASSERT(r->fr_ver != M0_CONF_VER_UNKNOWN);
136 
137  M0_LEAVE();
138  return M0_FSO_AGAIN;
139 }
140 
141 static int conf_update_tick(struct m0_fom *fom)
142 {
143  M0_IMPOSSIBLE("XXX Not implemented");
144 
146  return M0_FSO_AGAIN;
147 }
148 
149 static int _count(size_t *n,
150  struct m0_confx *enc M0_UNUSED,
151  const struct m0_conf_obj *obj M0_UNUSED)
152 {
153  ++*n;
154  return 0;
155 }
156 
157 static int
158 _encode(size_t *n, struct m0_confx *enc, const struct m0_conf_obj *obj)
159 {
160  int rc;
161 
162  M0_PRE(m0_conf_obj_invariant(obj) && obj->co_status == M0_CS_READY);
163 
164  M0_CNT_DEC(*n);
165  rc = obj->co_ops->coo_encode(M0_CONFX_AT(enc, enc->cx_nr), obj);
166  if (rc == 0)
167  ++enc->cx_nr;
168  return M0_RC(rc);
169 }
170 
171 static int readiness_check(const struct m0_conf_obj *obj)
172 {
173  if (m0_conf_obj_is_stub(obj)) {
174  /* All configuration is expected to be loaded already. */
175  M0_ASSERT(obj->co_status != M0_CS_LOADING);
176  return M0_ERR(-ENOENT);
177  }
178  return 0;
179 }
180 
191 static int confd_path_walk(struct m0_conf_obj *cur,
192  const struct m0_fid_arr *path,
193  int (*apply)(size_t *n, struct m0_confx *enc,
194  const struct m0_conf_obj *obj),
195  size_t *n, struct m0_confx *enc)
196 {
197  struct m0_conf_obj *entry;
198  int i;
199  int rc;
200 
201  M0_ENTRY();
202  M0_PRE(m0_conf_obj_invariant(cur) && cur->co_status == M0_CS_READY);
203 
204  for (i = 0; i < path->af_count; ++i) {
205  /* Handle intermediate object. */
207  rc = apply(n, enc, cur);
208  if (rc != 0)
209  return M0_ERR(rc);
210  }
211 
212  rc = cur->co_ops->coo_lookup(cur, &path->af_elems[i], &cur) ?:
214  if (rc != 0)
215  return M0_ERR(rc);
216  }
217 
218  /* Handle final object. */
219 
220  if (cur->co_parent != NULL && cur->co_parent != cur &&
221  m0_conf_obj_type(cur->co_parent) == &M0_CONF_DIR_TYPE)
222  /* Include siblings into the resulting set. */
223  cur = cur->co_parent;
224 
226  return M0_RC(apply(n, enc, cur));
227 
228  m0_conf_obj_get(cur); /* required by ->coo_readdir() */
229  for (entry = NULL; (rc = cur->co_ops->coo_readdir(cur, &entry)) > 0; ) {
230  /* All configuration is expected to be available. */
232 
233  rc = apply(n, enc, entry);
234  if (rc != 0)
235  return M0_ERR(rc);
236  }
238  return M0_RC(rc);
239 }
240 
241 static struct m0_conf_obj *
242 confd_cache_lookup(const struct m0_conf_cache *cache, const struct m0_fid *fid)
243 {
244  struct m0_conf_obj *obj;
245 
247  if (obj == NULL)
248  M0_LOG(M0_NOTICE, "fid=" FID_F " not found", FID_P(fid));
249  else
250  M0_POST(m0_conf_obj_invariant(obj) && obj->co_cache == cache &&
251  obj->co_status == M0_CS_READY);
252  return obj;
253 }
254 
256 {
257  struct m0_conf_obj *root;
258 
259  M0_ENTRY();
261  M0_ASSERT(root != NULL); /* conf data must be cached already */
262 
263  cache->ca_ver = M0_CONF_CAST(root, m0_conf_root)->rt_verno;
264  M0_POST(cache->ca_ver != M0_CONF_VER_UNKNOWN);
265 }
266 
267 static int confx_populate(struct m0_confx *dest,
268  const struct m0_fid *origin,
269  const struct m0_fid_arr *path,
270  struct m0_conf_cache *cache)
271 {
272  struct m0_conf_obj *org;
273  int rc;
274  size_t nr = 0;
275  char *data;
276 
277  M0_ENTRY();
279 
280  if (cache->ca_ver == M0_CONF_VER_UNKNOWN)
282 
283  M0_SET0(dest);
284 
285  org = confd_cache_lookup(cache, origin);
286  if (org == NULL)
287  return M0_ERR_INFO(-ENOENT, "origin="FID_F, FID_P(origin));
288 
289  rc = confd_path_walk(org, path, _count, &nr, NULL);
290  if (rc != 0 || nr == 0)
291  return M0_RC(rc);
292 
294  if (data == NULL)
295  return M0_ERR(-ENOMEM);
296  /* "data" is freed by m0_confx_free(dest). */
297  dest->cx__objs = (void *)data;
298 
299  M0_LOG(M0_DEBUG, "Will encode %zu configuration object%s", nr,
300  (char *)(nr > 1 ? "s" : ""));
301  rc = confd_path_walk(org, path, _encode, &nr, dest);
302  if (rc == 0)
303  M0_ASSERT(nr == 0);
304  else
306  return M0_RC(rc);
307 }
308 
310 #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
void m0_fom_phase_moveif(struct m0_fom *fom, int32_t rc, int phase0, int phase1)
Definition: fom.c:1710
uint32_t m0_fop_opcode(const struct m0_fop *fop)
Definition: fop.c:226
static size_t nr
Definition: dump.c:1505
#define M0_PRE(cond)
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
M0_INTERNAL void m0_confx_free(struct m0_confx *enc)
Definition: preload.c:33
static struct m0_semaphore q
Definition: rwlock.c:55
#define NULL
Definition: misc.h:38
static struct m0_addb2_mach * m
Definition: consumer.c:38
static struct buffer * cur(struct m0_addb2_mach *mach, m0_bcount_t space)
Definition: addb2.c:791
static const struct m0_fom_ops conf_update_fom_ops
Definition: confd_fom.c:67
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()
struct m0_reqh_service d_reqh
Definition: confd.h:153
struct m0_fid * af_elems
Definition: fid.h:45
struct m0_bufvec data
Definition: di.c:40
M0_INTERNAL void m0_conf_obj_put(struct m0_conf_obj *obj)
Definition: obj_ops.c:205
void * m0_fop_data(const struct m0_fop *fop)
Definition: fop.c:220
static int confd_path_walk(struct m0_conf_obj *cur, const struct m0_fid_arr *path, int(*apply)(size_t *n, struct m0_confx *enc, const struct m0_conf_obj *obj), size_t *n, struct m0_confx *enc)
Definition: confd_fom.c:191
#define M0_CONFX_AT(cx, idx)
Definition: onwire.h:271
#define container_of(ptr, type, member)
Definition: misc.h:33
#define M0_SET0(obj)
Definition: misc.h:64
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
m0_fom_phase
Definition: fom.h:372
struct m0_fom_type ft_fom_type
Definition: fop.h:232
struct m0_fid fid
Definition: di.c:46
return M0_RC(rc)
#define M0_ENTRY(...)
Definition: trace.h:170
void m0_fom_init(struct m0_fom *fom, const struct m0_fom_type *fom_type, const struct m0_fom_ops *ops, struct m0_fop *fop, struct m0_fop *reply, struct m0_reqh *reqh)
Definition: fom.c:1372
int i
Definition: dir.c:1033
M0_INTERNAL void m0_conf_obj_get(struct m0_conf_obj *obj)
Definition: obj_ops.c:186
struct m0_fop_type * f_type
Definition: fop.h:81
#define M0_ERR_INFO(rc, fmt,...)
Definition: trace.h:215
struct m0_conf_root * root
Definition: note.c:50
return M0_ERR(-EOPNOTSUPP)
uint32_t cx_nr
Definition: onwire.h:259
int m0_fom_tick_generic(struct m0_fom *fom)
Definition: fom_generic.c:848
void m0_fom_fini(struct m0_fom *fom)
Definition: fom.c:1324
#define M0_ASSERT(cond)
M0_INTERNAL int m0_confd_fom_create(struct m0_fop *fop, struct m0_fom **out, struct m0_reqh *reqh)
Definition: confd_fom.c:73
void m0_fom_phase_move(struct m0_fom *fom, int32_t rc, int phase)
Definition: fom.c:1699
const struct m0_bob_type m0_confd_bob
Definition: confd.c:443
#define bob_of(ptr, type, field, bt)
Definition: bob.h:140
M0_INTERNAL bool m0_conf_cache_is_locked(const struct m0_conf_cache *cache)
Definition: cache.c:60
Definition: fid.h:43
#define M0_POST(cond)
Definition: reqh.h:94
Definition: dump.c:103
#define M0_CONF_CAST(ptr, type)
Definition: obj.h:780
static size_t confd_fom_locality(const struct m0_fom *fom)
Definition: confd_fom.c:50
static int conf_update_tick(struct m0_fom *fom)
Definition: confd_fom.c:141
#define FID_P(f)
Definition: fid.h:77
M0_INTERNAL size_t m0_confx_sizeof(void)
Definition: db.c:61
static int _count(size_t *n, struct m0_confx *enc M0_UNUSED, const struct m0_conf_obj *obj M0_UNUSED)
Definition: confd_fom.c:149
struct m0_fop * m0_fop_reply_alloc(struct m0_fop *req, struct m0_fop_type *rept)
Definition: fop.c:129
struct m0_conf_cache * d_cache
Definition: confd.h:163
static struct m0_conf_obj * confd_cache_lookup(const struct m0_conf_cache *cache, const struct m0_fid *fid)
Definition: confd_fom.c:242
Definition: fom.h:481
size_t(* fo_home_locality)(const struct m0_fom *fom)
Definition: fom.h:671
uint64_t n
Definition: fops.h:107
struct m0_reqh reqh
Definition: rm_foms.c:48
Definition: fid.h:38
static int conf_fetch_tick(struct m0_fom *fom)
Definition: confd_fom.c:110
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
static int r[NR]
Definition: thread.c:46
const struct m0_fid M0_CONF_ROOT_FID
Definition: root.c:226
static const struct m0_fom_ops conf_fetch_fom_ops
Definition: confd_fom.c:61
static int _encode(size_t *n, struct m0_confx *enc, const struct m0_conf_obj *obj)
Definition: confd_fom.c:158
static void confd_fom_fini(struct m0_fom *fom)
Definition: confd_fom.c:55
static void cache_ver_update(struct m0_conf_cache *cache)
Definition: confd_fom.c:255
static struct m0_fop * fop
Definition: item.c:57
struct m0_fop_type m0_conf_fetch_resp_fopt
Definition: fop.c:43
static int confx_populate(struct m0_confx *dest, const struct m0_fid *origin, const struct m0_fid_arr *path, struct m0_conf_cache *cache)
Definition: confd_fom.c:267
#define M0_CNT_DEC(cnt)
Definition: arith.h:219
static int readiness_check(const struct m0_conf_obj *obj)
Definition: confd_fom.c:171
#define out(...)
Definition: gen.c:41
struct m0_fom_ops ops
Definition: io_foms.c:623
M0_INTERNAL void m0_conf_cache_lock(struct m0_conf_cache *cache)
Definition: cache.c:50
uint64_t ca_ver
Definition: cache.h:105
const struct m0_conf_obj_type M0_CONF_DIR_TYPE
Definition: dir.c:206
void m0_free(void *data)
Definition: memory.c:146
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
uint32_t af_count
Definition: fid.h:44
Definition: fop.h:79
#define FID_F
Definition: fid.h:75
struct m0_fop * rep_fop
Definition: dir.c:334
#define M0_IMPOSSIBLE(fmt,...)
#define M0_UNUSED
Definition: misc.h:380