Motr  M0
validation.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-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 
28 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_CONF
29 #include "lib/trace.h"
30 
31 #include "conf/validation.h"
32 #include "conf/glob.h"
33 #include "conf/dir.h" /* m0_conf_dir_tl */
34 #include "conf/walk.h"
35 #include "conf/pvers.h" /* m0_conf_pver_level */
36 #include "lib/string.h" /* m0_vsnprintf */
37 #include "lib/errno.h" /* ENOENT */
38 #include "lib/memory.h" /* M0_ALLOC_ARR */
39 #include "net/net.h" /* m0_net_endpoint_is_valid */
40 
41 enum { CONF_GLOB_BATCH = 16 }; /* the value is arbitrary */
42 
44 struct conf_io_stats {
45  uint32_t cs_nr_ioservices;
46  uint32_t cs_nr_iodevices; /* pool width */
47 };
48 
49 static const struct m0_conf_ruleset conf_rules;
50 
51 static const struct m0_conf_ruleset *conf_validity_checks[] = {
52  &conf_rules,
53  /*
54  * Motr modules may define their own conf validation rules and add
55  * them here.
56  */
57 };
58 
59 char *
60 m0_conf_validation_error(struct m0_conf_cache *cache, char *buf, size_t buflen)
61 {
62  char *err;
63  M0_PRE(buf != NULL && buflen != 0);
64 
68  return err;
69 }
70 
71 M0_INTERNAL char *
73  char *buf, size_t buflen)
74 {
75  unsigned i;
76  const struct m0_conf_rule *rule;
77  int rc;
78  char *_buf;
79  size_t _buflen;
80  char *err;
81 
82  M0_PRE(buf != NULL && buflen != 0);
84 
85  for (i = 0; i < ARRAY_SIZE(conf_validity_checks); ++i) {
86  for (rule = &conf_validity_checks[i]->cv_rules[0];
87  rule->cvr_name != NULL;
88  ++rule) {
89  rc = snprintf(buf, buflen, "[%s.%s] ",
90  conf_validity_checks[i]->cv_name,
91  rule->cvr_name);
92  M0_ASSERT(rc > 0 && (size_t)rc < buflen);
93  _buflen = strlen(buf);
94  _buf = buf + _buflen;
95  err = rule->cvr_error(cache, _buf, buflen - _buflen);
96  if (err == NULL)
97  continue;
98  return err == _buf ? buf : m0_vsnprintf(
99  buf, buflen, "[%s.%s] %s",
100  conf_validity_checks[i]->cv_name,
101  rule->cvr_name, err);
102  }
103  }
104  return NULL;
105 }
106 
107 static char *conf_orphans_error(const struct m0_conf_cache *cache,
108  char *buf, size_t buflen)
109 {
110  const struct m0_conf_obj *obj;
111 
112  m0_tl_for(m0_conf_cache, &cache->ca_registry, obj) {
113  if (obj->co_status != M0_CS_READY)
114  return m0_vsnprintf(buf, buflen, FID_F" is not defined",
115  FID_P(&obj->co_id));
116  if (obj->co_parent == NULL &&
118  return m0_vsnprintf(buf, buflen, "Dangling object: "
119  FID_F, FID_P(&obj->co_id));
120  } m0_tl_endfor;
121 
122  return NULL;
123 }
124 
125 /*
126  * XXX FIXME: conf_io_stats_get() counts _all_ IO services and sdevs.
127  * This information is not very useful. The function should be modified
128  * to count IO services and sdevs associated with a particular pool.
129  */
130 static char *conf_io_stats_get(const struct m0_conf_cache *cache,
131  struct conf_io_stats *stats,
132  char *buf, size_t buflen)
133 {
134  struct m0_conf_glob glob;
135  const struct m0_conf_obj *objv[CONF_GLOB_BATCH];
136  const struct m0_conf_service *svc;
137  int i;
138  int rc;
139 
140  M0_SET0(stats);
141 
143  M0_CONF_ROOT_NODES_FID, M0_CONF_ANY_FID,
144  M0_CONF_NODE_PROCESSES_FID, M0_CONF_ANY_FID,
145  M0_CONF_PROCESS_SERVICES_FID, M0_CONF_ANY_FID);
146 
147  while ((rc = m0_conf_glob(&glob, ARRAY_SIZE(objv), objv)) > 0) {
148  for (i = 0; i < rc; ++i) {
149  svc = M0_CONF_CAST(objv[i], m0_conf_service);
150  if (svc->cs_type == M0_CST_IOS) {
151  ++stats->cs_nr_ioservices;
152  stats->cs_nr_iodevices +=
153  m0_conf_dir_len(svc->cs_sdevs);
154  }
155  }
156  }
157  return rc < 0 ? m0_conf_glob_error(&glob, buf, buflen) : NULL;
158 }
159 
160 static bool conf_oostore_mode(const struct m0_conf_root *r)
161 {
162  bool result = r->rt_mdredundancy > 0;
163  M0_LOG(M0_INFO, FID_F": mdredundancy=%"PRIu32" ==> oostore_mode=%s",
164  FID_P(&r->rt_obj.co_id), r->rt_mdredundancy,
165  result ? "true" : "false");
166  return result;
167 }
168 
169 static char *_conf_root_error(const struct m0_conf_root *root,
170  char *buf, size_t buflen,
171  struct conf_io_stats *stats)
172 {
173  const struct m0_conf_obj *obj;
174 
175  if (!conf_oostore_mode(root))
176  /*
177  * Meta-data is stored at MD services, not IO services.
178  * No special MD pool is required.
179  */
180  return NULL;
181 
182  if (root->rt_mdredundancy > stats->cs_nr_ioservices)
183  return m0_vsnprintf(buf, buflen,
184  FID_F": metadata redundancy (%u) exceeds"
185  " the number of IO services (%u)",
186  FID_P(&root->rt_obj.co_id),
188  stats->cs_nr_ioservices);
190  if (obj == NULL)
191  return m0_vsnprintf(buf, buflen,
192  FID_F": `mdpool' "FID_F" is missing",
193  FID_P(&root->rt_obj.co_id),
194  FID_P(&root->rt_mdpool));
196  return m0_vsnprintf(buf, buflen,
197  FID_F": `mdpool' "FID_F" belongs another"
198  " profile", FID_P(&root->rt_obj.co_id),
199  FID_P(&root->rt_mdpool));
200  return NULL;
201 }
202 
203 static char *conf_root_error(const struct m0_conf_cache *cache,
204  char *buf, size_t buflen)
205 {
206  struct conf_io_stats stats;
207  struct m0_conf_glob glob;
208  const struct m0_conf_obj *obj;
209  char *err;
210  int rc;
211 
212  err = conf_io_stats_get(cache, &stats, buf, buflen);
213  if (err != NULL)
214  return err;
215 
216  if (stats.cs_nr_ioservices == 0)
217  return m0_vsnprintf(buf, buflen, "No IO services");
218 
220 
221  while ((rc = m0_conf_glob(&glob, 1, &obj)) > 0) {
223  buf, buflen, &stats);
224  if (err != NULL)
225  return err;
226  }
227  return rc < 0 ? m0_conf_glob_error(&glob, buf, buflen) : NULL;
228 }
229 
230 static const struct m0_conf_node *
232 {
233  return M0_CONF_CAST(
237  m0_conf_node);
238 }
239 
240 static char *conf_iodev_error(const struct m0_conf_sdev *sdev,
241  const struct m0_conf_sdev **iodevs,
242  uint32_t nr_iodevs, char *buf, size_t buflen)
243 {
244  uint32_t j;
245 
247  m0_conf_service)->cs_type != M0_CST_IOS)
248  return NULL;
249  if (sdev->sd_dev_idx >= nr_iodevs)
250  return m0_vsnprintf(buf, buflen, FID_F": dev_idx (%u) does not"
251  " belong [0, P) range; P=%u",
252  FID_P(&sdev->sd_obj.co_id),
253  sdev->sd_dev_idx, nr_iodevs);
254  if (iodevs[sdev->sd_dev_idx] != sdev) {
255  if (iodevs[sdev->sd_dev_idx] != NULL)
256  return m0_vsnprintf(
257  buf, buflen, FID_F": dev_idx is not unique,"
258  " duplicates that of "FID_F,
259  FID_P(&sdev->sd_obj.co_id),
260  FID_P(&iodevs[sdev->sd_dev_idx]->sd_obj.co_id));
261  /*
262  * XXX TODO: Check that sdev->sd_filename is not empty.
263  */
264  if (m0_exists(i, nr_iodevs, iodevs[j = i] != NULL &&
265  m0_streq(iodevs[i]->sd_filename,
266  sdev->sd_filename) &&
267  conf_node_from_sdev(sdev) ==
268  conf_node_from_sdev(iodevs[i])))
269  return m0_vsnprintf(
270  buf, buflen, FID_F": filename is not unique,"
271  " duplicates that of "FID_F,
272  FID_P(&sdev->sd_obj.co_id),
273  FID_P(&iodevs[j]->sd_obj.co_id));
274  iodevs[sdev->sd_dev_idx] = sdev;
275  }
276  return NULL;
277 }
278 
280  uint32_t *ws_width;
281  char *ws_buf;
282  size_t ws_buflen;
283  char *ws_err;
284 };
285 
287  struct conf_pver_width_st *st)
288 {
289  const struct m0_tl *dir;
290  const struct m0_conf_obj *child;
291  uint32_t children_level;
292 
294 
295  dir = &M0_CONF_CAST(obj, m0_conf_dir)->cd_items;
296  if (m0_conf_dir_tlist_is_empty(dir)) {
297  st->ws_err = m0_vsnprintf(st->ws_buf, st->ws_buflen,
298  FID_F": Missing children",
299  FID_P(&obj->co_parent->co_id));
300  return M0_CW_STOP;
301  }
304  children_level =
305  m0_conf_obj_type(obj->co_parent) == &M0_CONF_PVER_TYPE ?
307  m0_conf_pver_level(obj->co_parent) + 1;
308  if (m0_tl_exists(m0_conf_dir, x, dir, child = x,
309  m0_conf_pver_level(x) != children_level)) {
310  st->ws_err = m0_vsnprintf(st->ws_buf, st->ws_buflen,
311  FID_F": Cannot adopt "FID_F,
312  FID_P(&obj->co_parent->co_id),
313  FID_P(&child->co_id));
314  return M0_CW_STOP;
315  }
316  return M0_CW_CONTINUE;
317 }
318 
319 static int conf_pver_width_measure_w(struct m0_conf_obj *obj, void *args)
320 {
321  struct conf_pver_width_st *st = args;
322  const struct m0_conf_objv *objv;
323  unsigned level;
324 
326 
328  return conf_pver_width_measure__dir(obj, st);
329 
330  objv = M0_CONF_CAST(obj, m0_conf_objv);
332  if ((level == M0_CONF_PVER_LVL_DRIVES) != (objv->cv_children == NULL)) {
333  st->ws_err = m0_vsnprintf(st->ws_buf, st->ws_buflen,
334  FID_F": %s children",
335  FID_P(&obj->co_id),
336  objv->cv_children == NULL ?
337  "Missing" : "Unexpected");
338  return M0_CW_STOP;
339  }
340  M0_CNT_INC(st->ws_width[level]);
341  return M0_CW_CONTINUE;
342 }
343 
350 static char *conf_pver_width_error(const struct m0_conf_pver *pver,
351  uint32_t *pver_width,
352  size_t pver_width_nr,
353  char *buf, size_t buflen)
354 {
355  struct conf_pver_width_st st = {
356  .ws_width = pver_width,
357  .ws_buf = buf,
358  .ws_buflen = buflen
359  };
360  int rc;
361 
362  M0_PRE(pver->pv_kind == M0_CONF_PVER_ACTUAL);
363 
365  &pver->pv_u.subtree.pvs_sitevs->cd_obj, &st);
366  M0_ASSERT(rc == 0); /* conf_pver_width_measure_w() cannot fail */
367  M0_POST(ergo(st.ws_err == NULL,
368  m0_forall(i, pver_width_nr, (pver_width[i] > 0))));
369  return st.ws_err;
370 }
371 
377 static char *conf_pver_formulaic_base_error(const struct m0_conf_pver *fpver,
378  const struct m0_conf_pver **out,
379  char *buf, size_t buflen)
380 {
381  const struct m0_conf_obj *base;
382 
384 
386  &fpver->pv_u.formulaic.pvf_base);
387  if (base == NULL)
388  return m0_vsnprintf(buf, buflen,
389  "Base "FID_F" of formulaic pver "FID_F
390  " is missing",
391  FID_P(&fpver->pv_u.formulaic.pvf_base),
392  FID_P(&fpver->pv_obj.co_id));
394  return (*out)->pv_kind == M0_CONF_PVER_ACTUAL ? NULL :
395  m0_vsnprintf(buf, buflen, "Base "FID_F" of formulaic pver "FID_F
396  " is not actual", FID_P(&base->co_id),
397  FID_P(&fpver->pv_obj.co_id));
398 }
399 
400 static char *conf_pver_formulaic_error(const struct m0_conf_pver *fpver,
401  char *buf, size_t buflen)
402 {
403  const struct m0_conf_pver_formulaic *form = &fpver->pv_u.formulaic;
404  const struct m0_conf_obj *pool;
405  const struct m0_conf_pver *base = NULL;
406  const struct m0_pdclust_attr *base_attr;
407  uint32_t pver_width[M0_CONF_PVER_HEIGHT] = {};
408  char *err;
409  int i;
410 
413  m0_conf_root)->rt_mdpool))
414  return m0_vsnprintf(buf, buflen, FID_F": MD pool may not have"
415  " formulaic pvers", FID_P(&pool->co_id));
416  err = conf_pver_formulaic_base_error(fpver, &base, buf, buflen) ?:
417  conf_pver_width_error(base, pver_width, ARRAY_SIZE(pver_width),
418  buf, buflen);
419  if (err != NULL)
420  return err;
421  if (M0_IS0(&form->pvf_allowance))
422  return m0_vsnprintf(buf, buflen, FID_F": Zeroed allowance",
423  FID_P(&fpver->pv_obj.co_id));
424  if (m0_exists(j, ARRAY_SIZE(pver_width),
425  form->pvf_allowance[i = j] > pver_width[j]))
426  return m0_vsnprintf(buf, buflen, FID_F": Allowing more"
427  " failures (%u) than there are objects (%u)"
428  " at level %d of base pver subtree",
429  FID_P(&fpver->pv_obj.co_id),
430  form->pvf_allowance[i], pver_width[i], i);
431  base_attr = &base->pv_u.subtree.pvs_attr;
432  /* Guaranteed by pver_check(). */
433  M0_ASSERT(m0_pdclust_attr_check(base_attr));
434  if (form->pvf_allowance[M0_CONF_PVER_LVL_DRIVES] > base_attr->pa_P -
435  base_attr->pa_N - base_attr->pa_K - base_attr->pa_S)
436  return m0_vsnprintf(buf, buflen, FID_F": Number of allowed disk"
437  " failures (%u) > P - N - K - S of base pver",
438  FID_P(&fpver->pv_obj.co_id),
439  form->pvf_allowance[
441  /*
442  * XXX TODO: Check if form->pvf_id is unique per cluster.
443  */
444  return NULL;
445 }
446 
447 static char *conf_pver_actual_error(const struct m0_conf_pver *pver,
448  const struct m0_conf_sdev **iodevs,
449  uint32_t nr_iodevs,
450  char *buf, size_t buflen)
451 {
452  const struct m0_conf_pver_subtree *sub = &pver->pv_u.subtree;
453  uint32_t pver_width[M0_CONF_PVER_HEIGHT] = {};
454  struct m0_conf_glob glob;
455  const struct m0_conf_obj *objs[CONF_GLOB_BATCH];
456  const struct m0_conf_objv *diskv;
457  char *err;
458  int i;
459  int rc;
460 
461  err = conf_pver_width_error(pver, pver_width, ARRAY_SIZE(pver_width),
462  buf, buflen);
463  if (err != NULL)
464  return err;
465  if (M0_IS0(&sub->pvs_tolerance) && sub->pvs_attr.pa_N != 1)
466  return m0_vsnprintf(buf, buflen, FID_F": Zeroed tolerance is"
467  " supported only with N = 1",
468  FID_P(&pver->pv_obj.co_id));
469  if (m0_exists(j, ARRAY_SIZE(pver_width),
470  sub->pvs_tolerance[i = j] > pver_width[j]))
471  return m0_vsnprintf(buf, buflen, FID_F": Tolerating more"
472  " failures (%u) than there are objects (%u)"
473  " at level %d of pver subtree",
474  FID_P(&pver->pv_obj.co_id),
475  sub->pvs_tolerance[i], pver_width[i], i);
476  if (!m0_pdclust_attr_check(&sub->pvs_attr))
477  return m0_vsnprintf(buf, buflen, FID_F": P < N + 2K",
478  FID_P(&pver->pv_obj.co_id));
479  /*
480  * XXX TODO: Check if m0_conf_objv::cv_real pointers are unique.
481  */
482  if (sub->pvs_attr.pa_P > nr_iodevs)
483  return m0_vsnprintf(buf, buflen,
484  FID_F": Pool width (%u) exceeds total"
485  " number of IO devices (%u)",
486  FID_P(&pver->pv_obj.co_id),
487  sub->pvs_attr.pa_P, nr_iodevs);
488 
489  m0_conf_glob_init(&glob, M0_CONF_GLOB_ERR, NULL, NULL, &pver->pv_obj,
490  M0_CONF_PVER_SITEVS_FID, M0_CONF_ANY_FID,
491  M0_CONF_SITEV_RACKVS_FID, M0_CONF_ANY_FID,
492  M0_CONF_RACKV_ENCLVS_FID, M0_CONF_ANY_FID,
493  M0_CONF_ENCLV_CTRLVS_FID, M0_CONF_ANY_FID,
494  M0_CONF_CTRLV_DRIVEVS_FID, M0_CONF_ANY_FID);
495 
496  while ((rc = m0_conf_glob(&glob, ARRAY_SIZE(objs), objs)) > 0) {
497  for (i = 0; i < rc; ++i) {
498  diskv = M0_CONF_CAST(objs[i], m0_conf_objv);
499  err = conf_iodev_error(
500  M0_CONF_CAST(diskv->cv_real,
501  m0_conf_drive)->ck_sdev,
502  iodevs, nr_iodevs, buf, buflen);
503  if (err != NULL)
504  return err;
505  }
506  }
507  return rc < 0 ? m0_conf_glob_error(&glob, buf, buflen) : NULL;
508 }
509 
510 static char *
511 conf_pvers_error(const struct m0_conf_cache *cache, char *buf, size_t buflen)
512 {
513  struct conf_io_stats stats;
514  const struct m0_conf_sdev **iodevs;
515  struct m0_conf_glob glob;
516  const struct m0_conf_obj *objv[CONF_GLOB_BATCH];
517  const struct m0_conf_pver *pver;
518  char *err;
519  int i;
520  int rc;
521 
522  err = conf_io_stats_get(cache, &stats, buf, buflen);
523  if (err != NULL)
524  return err;
525  /*
526  * XXX FIXME: Check the number of IO devices associated with a
527  * particular pool, not the total number of IO devices in cluster.
528  */
529  if (stats.cs_nr_iodevices == 0)
530  return m0_vsnprintf(buf, buflen, "No IO devices");
531 
532  M0_ALLOC_ARR(iodevs, stats.cs_nr_iodevices);
533  if (iodevs == NULL)
534  return m0_vsnprintf(buf, buflen, "Insufficient memory");
535 
537  M0_CONF_ROOT_POOLS_FID, M0_CONF_ANY_FID,
538  M0_CONF_POOL_PVERS_FID, M0_CONF_ANY_FID);
539 
540  while ((rc = m0_conf_glob(&glob, ARRAY_SIZE(objv), objv)) > 0) {
541  for (i = 0; i < rc; ++i) {
542  pver = M0_CONF_CAST(objv[i], m0_conf_pver);
543  err = pver->pv_kind == M0_CONF_PVER_ACTUAL ?
545  stats.cs_nr_iodevices,
546  buf, buflen) :
548  if (err != NULL)
549  break;
550  }
551  }
552  m0_free(iodevs);
553  if (err != NULL)
554  return err;
555 
556  return rc < 0 ? m0_conf_glob_error(&glob, buf, buflen) : NULL;
557 }
558 
559 static char *conf_process_endpoint_error(const struct m0_conf_process *proc,
560  char *buf, size_t buflen)
561 {
562  struct m0_conf_glob glob;
563  const struct m0_conf_obj *objv[CONF_GLOB_BATCH];
564  const char **epp;
565  int i;
566  int rc;
567 
569  return m0_vsnprintf(buf, buflen, FID_F": Invalid endpoint: %s",
570  FID_P(&proc->pc_obj.co_id),
571  proc->pc_endpoint);
572 
574  M0_CONF_PROCESS_SERVICES_FID, M0_CONF_ANY_FID);
575 
576  while ((rc = m0_conf_glob(&glob, ARRAY_SIZE(objv), objv)) > 0) {
577  for (i = 0; i < rc; ++i) {
578  for (epp = M0_CONF_CAST(objv[i],
579  m0_conf_service)->cs_endpoints;
580  *epp != NULL; ++epp) {
581  if (!m0_net_endpoint_is_valid(*epp))
582  return m0_vsnprintf(
583  buf, buflen,
584  FID_F": Invalid endpoint: %s",
585  FID_P(&objv[i]->co_id), *epp);
586  }
587  }
588  }
589  return rc < 0 ? m0_conf_glob_error(&glob, buf, buflen) : NULL;
590 }
591 
592 static char *
593 conf_endpoint_error(const struct m0_conf_cache *cache, char *buf, size_t buflen)
594 {
595  struct m0_conf_glob glob;
596  const struct m0_conf_obj *objv[CONF_GLOB_BATCH];
597  char *err;
598  int i;
599  int rc;
600 
602  M0_CONF_ROOT_NODES_FID, M0_CONF_ANY_FID,
603  M0_CONF_NODE_PROCESSES_FID, M0_CONF_ANY_FID);
604 
605  while ((rc = m0_conf_glob(&glob, ARRAY_SIZE(objv), objv)) > 0) {
606  for (i = 0; i < rc; ++i) {
609  buf, buflen);
610  if (err != NULL)
611  return err;
612  }
613  }
614  return rc < 0 ? m0_conf_glob_error(&glob, buf, buflen) : NULL;
615 }
616 
617 static char *conf_service_type_error(const struct m0_conf_cache *cache,
618  char *buf, size_t buflen)
619 {
620  struct m0_conf_glob glob;
621  const struct m0_conf_obj *objv[CONF_GLOB_BATCH];
622  enum m0_conf_service_type svc_type;
623  bool confd_p = false;
624  int i;
625  int rc;
626 
628  M0_CONF_ROOT_NODES_FID, M0_CONF_ANY_FID,
629  M0_CONF_NODE_PROCESSES_FID, M0_CONF_ANY_FID,
630  M0_CONF_PROCESS_SERVICES_FID, M0_CONF_ANY_FID);
631 
632  while ((rc = m0_conf_glob(&glob, ARRAY_SIZE(objv), objv)) > 0) {
633  for (i = 0; i < rc; ++i) {
634  svc_type = M0_CONF_CAST(objv[i],
635  m0_conf_service)->cs_type;
636  if (!m0_conf_service_type_is_valid(svc_type))
637  return m0_vsnprintf(
638  buf, buflen,
639  FID_F": Invalid service type: %d",
640  FID_P(&objv[i]->co_id), svc_type);
641  if (svc_type == M0_CST_CONFD)
642  confd_p = true;
643  }
644  }
645  if (rc < 0)
646  return m0_conf_glob_error(&glob, buf, buflen);
647  if (confd_p)
648  return NULL;
649  return m0_vsnprintf(buf, buflen, "No confd service defined");
650 }
651 
652 static char *_conf_service_sdevs_error(const struct m0_conf_service *svc,
653  char *buf, size_t buflen)
654 {
655  bool has_sdevs = !m0_conf_dir_tlist_is_empty(&svc->cs_sdevs->cd_items);
656 
657  if (M0_IN(svc->cs_type, (M0_CST_IOS, M0_CST_CAS)))
658  return has_sdevs ? NULL : m0_vsnprintf(
659  buf, buflen,
660  FID_F": `sdevs' of %s service must not be empty",
661  FID_P(&svc->cs_obj.co_id),
662  svc->cs_type == M0_CST_IOS ? "an IO" : "a CAS");
663  return has_sdevs ? m0_vsnprintf(
664  buf, buflen,
665  FID_F": `sdevs' must be empty (neither IOS nor CAS)",
666  FID_P(&svc->cs_obj.co_id)) : NULL;
667 }
668 
669 static char *conf_service_sdevs_error(const struct m0_conf_cache *cache,
670  char *buf, size_t buflen)
671 {
672  struct m0_conf_glob glob;
673  const struct m0_conf_obj *objv[CONF_GLOB_BATCH];
674  char *err;
675  int i;
676  int rc;
677 
679  M0_CONF_ROOT_NODES_FID, M0_CONF_ANY_FID,
680  M0_CONF_NODE_PROCESSES_FID, M0_CONF_ANY_FID,
681  M0_CONF_PROCESS_SERVICES_FID, M0_CONF_ANY_FID);
682 
683  while ((rc = m0_conf_glob(&glob, ARRAY_SIZE(objv), objv)) > 0) {
684  for (i = 0; i < rc; ++i) {
687  buf, buflen);
688  if (err != NULL)
689  return err;
690  }
691  }
692  return rc < 0 ? m0_conf_glob_error(&glob, buf, buflen) : NULL;
693 }
694 
695 static const struct m0_conf_ruleset conf_rules = {
696  .cv_name = "m0_conf_rules",
697  .cv_rules = {
698 #define _ENTRY(name) { #name, name }
705 #undef _ENTRY
706  { NULL, NULL }
707  }
708 };
709 
710 #undef M0_TRACE_SUBSYSTEM
711 
713 /*
714  * Local variables:
715  * c-indentation-style: "K&R"
716  * c-basic-offset: 8
717  * tab-width: 8
718  * fill-column: 80
719  * scroll-step: 1
720  * End:
721  */
722 /*
723  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
724  */
const struct m0_conf_obj_type * m0_conf_obj_type(const struct m0_conf_obj *obj)
Definition: obj.c:363
const char * sd_filename
Definition: obj.h:649
struct m0_fid co_id
Definition: obj.h:208
Definition: beck.c:235
static char * conf_pver_width_error(const struct m0_conf_pver *pver, uint32_t *pver_width, size_t pver_width_nr, char *buf, size_t buflen)
Definition: validation.c:350
const char * pc_endpoint
Definition: obj.h:590
M0_INTERNAL bool m0_net_endpoint_is_valid(const char *endpoint)
Definition: net.c:99
#define M0_PRE(cond)
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
const struct m0_conf_obj_type M0_CONF_OBJV_TYPE
Definition: objv.c:151
#define m0_conf_glob_init(glob, flags, errfunc, cache, origin,...)
Definition: glob.h:142
static char * _conf_root_error(const struct m0_conf_root *root, char *buf, size_t buflen, struct conf_io_stats *stats)
Definition: validation.c:169
struct m0_pdclust_attr pvs_attr
Definition: obj.h:481
#define NULL
Definition: misc.h:38
m0_conf_service_type
Definition: schema.h:194
static int conf_pver_width_measure_w(struct m0_conf_obj *obj, void *args)
Definition: validation.c:319
#define ergo(a, b)
Definition: misc.h:293
static bool x
Definition: sm.c:168
uint32_t pa_N
Definition: pdclust.h:104
struct m0_conf_obj rt_obj
Definition: obj.h:372
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
enum m0_trace_level level
Definition: trace.c:111
const struct m0_conf_obj_type M0_CONF_PVER_TYPE
Definition: pver.c:260
uint32_t pa_K
Definition: pdclust.h:107
const struct m0_conf_obj_type M0_CONF_ROOT_TYPE
Definition: root.c:214
struct m0_conf_obj pv_obj
Definition: obj.h:533
static const struct m0_conf_ruleset * conf_validity_checks[]
Definition: validation.c:51
#define m0_exists(var, nr,...)
Definition: misc.h:134
uint32_t pa_S
Definition: pdclust.h:110
uint32_t cs_nr_ioservices
Definition: validation.c:45
struct m0_conf_cache * co_cache
Definition: obj.h:251
static int void * buf
Definition: dir.c:1019
static char * _conf_service_sdevs_error(const struct m0_conf_service *svc, char *buf, size_t buflen)
Definition: validation.c:652
#define M0_SET0(obj)
Definition: misc.h:64
Definition: ub.c:49
M0_INTERNAL unsigned m0_conf_pver_level(const struct m0_conf_obj *obj)
Definition: pvers.c:394
static const struct m0_conf_node * conf_node_from_sdev(const struct m0_conf_sdev *sdev)
Definition: validation.c:231
uint32_t pvf_allowance[M0_CONF_PVER_HEIGHT]
Definition: obj.h:512
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
Definition: sock.c:887
static char * conf_iodev_error(const struct m0_conf_sdev *sdev, const struct m0_conf_sdev **iodevs, uint32_t nr_iodevs, char *buf, size_t buflen)
Definition: validation.c:240
enum m0_conf_pver_kind pv_kind
Definition: obj.h:535
#define m0_tl_endfor
Definition: tlist.h:700
struct m0_fid pvf_base
Definition: obj.h:501
uint32_t sd_dev_idx
Definition: obj.h:635
int i
Definition: dir.c:1033
def args
Definition: addb2db.py:716
M0_INTERNAL int m0_conf_walk(int(*fn)(struct m0_conf_obj *obj, void *args), struct m0_conf_obj *origin, void *args)
Definition: walk.c:49
struct m0_conf_root * root
Definition: note.c:50
Definition: trace.h:482
static char * conf_pver_formulaic_error(const struct m0_conf_pver *fpver, char *buf, size_t buflen)
Definition: validation.c:400
static bool m0_conf_service_type_is_valid(enum m0_conf_service_type t)
Definition: schema.h:204
M0_INTERNAL char * m0_conf_glob_error(const struct m0_conf_glob *glob, char *buf, size_t buflen)
Definition: glob.c:115
#define M0_ASSERT(cond)
struct m0_fid pver
Definition: idx_dix.c:74
union m0_conf_pver::@122 pv_u
struct m0_conf_obj * m0_conf_obj_grandparent(const struct m0_conf_obj *obj)
Definition: obj.c:384
Definition: tlist.h:251
uint32_t pvs_tolerance[M0_CONF_PVER_HEIGHT]
Definition: obj.h:487
#define m0_streq(a, b)
Definition: string.h:34
static uint32_t m0_conf_dir_len(const struct m0_conf_dir *dir)
Definition: dir.h:59
static char * conf_service_sdevs_error(const struct m0_conf_cache *cache, char *buf, size_t buflen)
Definition: validation.c:669
uint32_t cs_nr_iodevices
Definition: validation.c:46
static int conf_pver_width_measure__dir(const struct m0_conf_obj *obj, struct conf_pver_width_st *st)
Definition: validation.c:286
M0_INTERNAL bool m0_conf_cache_is_locked(const struct m0_conf_cache *cache)
Definition: cache.c:60
#define M0_POST(cond)
uint32_t rt_mdredundancy
Definition: obj.h:405
static char * conf_pver_actual_error(const struct m0_conf_pver *pver, const struct m0_conf_sdev **iodevs, uint32_t nr_iodevs, char *buf, size_t buflen)
Definition: validation.c:447
static char * conf_process_endpoint_error(const struct m0_conf_process *proc, char *buf, size_t buflen)
Definition: validation.c:559
struct m0_fid rt_mdpool
Definition: obj.h:394
const char * cv_name
Definition: validation.h:98
char * m0_conf_validation_error(struct m0_conf_cache *cache, char *buf, size_t buflen)
Definition: validation.c:60
static char * conf_root_error(const struct m0_conf_cache *cache, char *buf, size_t buflen)
Definition: validation.c:203
#define M0_CONF_CAST(ptr, type)
Definition: obj.h:780
#define FID_P(f)
Definition: fid.h:77
char *(* cvr_error)(const struct m0_conf_cache *cache, char *buf, size_t buflen)
Definition: validation.h:85
static struct m0_pool pool
Definition: iter_ut.c:58
M0_INTERNAL bool m0_fid_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: fid.c:164
#define m0_forall(var, nr,...)
Definition: misc.h:112
struct m0_conf_obj pc_obj
Definition: obj.h:581
#define PRIu32
Definition: types.h:66
static const struct m0_conf_ruleset conf_rules
Definition: validation.c:49
#define _ENTRY(name)
static char * conf_io_stats_get(const struct m0_conf_cache *cache, struct conf_io_stats *stats, char *buf, size_t buflen)
Definition: validation.c:130
#define M0_CNT_INC(cnt)
Definition: arith.h:226
#define M0_IS0(obj)
Definition: misc.h:70
M0_INTERNAL char * m0_conf_validation_error_locked(const struct m0_conf_cache *cache, char *buf, size_t buflen)
Definition: validation.c:72
static char * conf_endpoint_error(const struct m0_conf_cache *cache, char *buf, size_t buflen)
Definition: validation.c:593
Definition: beck.c:130
static int r[NR]
Definition: thread.c:46
uint32_t pa_P
Definition: pdclust.h:115
static bool conf_oostore_mode(const struct m0_conf_root *r)
Definition: validation.c:160
struct m0_conf_pver_formulaic formulaic
Definition: obj.h:538
static struct m0_net_test_service svc
Definition: service.c:34
struct m0_conf_obj sd_obj
Definition: obj.h:616
static char * conf_pvers_error(const struct m0_conf_cache *cache, char *buf, size_t buflen)
Definition: validation.c:511
static char * conf_orphans_error(const struct m0_conf_cache *cache, char *buf, size_t buflen)
Definition: validation.c:107
struct m0_conf_dir * cv_children
Definition: obj.h:545
M0_INTERNAL int m0_conf_glob(struct m0_conf_glob *glob, uint32_t nr, const struct m0_conf_obj **objv)
Definition: glob.c:92
static uint64_t base
Definition: dump.c:1504
struct inode * dir
Definition: dir.c:1028
uint32_t * ws_width
Definition: validation.c:280
#define out(...)
Definition: gen.c:41
#define M0_FID0
Definition: fid.h:93
M0_INTERNAL void m0_conf_cache_lock(struct m0_conf_cache *cache)
Definition: cache.c:50
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
void m0_free(void *data)
Definition: memory.c:146
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
M0_INTERNAL void m0_conf_cache_unlock(struct m0_conf_cache *cache)
Definition: cache.c:55
#define m0_tl_exists(name, var, head,...)
Definition: tlist.h:774
const char * cvr_name
Definition: validation.h:78
struct m0_conf_obj * cv_real
Definition: obj.h:558
static char * conf_pver_formulaic_base_error(const struct m0_conf_pver *fpver, const struct m0_conf_pver **out, char *buf, size_t buflen)
Definition: validation.c:377
#define FID_F
Definition: fid.h:75
static char * conf_service_type_error(const struct m0_conf_cache *cache, char *buf, size_t buflen)
Definition: validation.c:617
M0_INTERNAL char * m0_vsnprintf(char *buf, size_t buflen, const char *format,...)
Definition: string.c:84
#define m0_tl_forall(name, var, head,...)
Definition: tlist.h:735
M0_INTERNAL bool m0_pdclust_attr_check(const struct m0_pdclust_attr *attr)
Definition: pdclust.c:340