Motr  M0
confc.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_UT
24 #include "lib/trace.h"
25 
26 #include "conf/confc.h"
27 #include "conf/obj_ops.h" /* M0_CONF_DIREND */
28 #include "conf/helpers.h" /* m0_confc_root_open */
29 #include "conf/ut/confc.h" /* m0_ut_conf_fids */
30 #include "conf/ut/common.h" /* m0_conf_ut_waiter */
31 #include "conf/ut/rpc_helpers.h" /* m0_ut_rpc_machine_start */
32 #include "rpc/rpclib.h" /* m0_rpc_server_ctx */
33 #include "lib/finject.h" /* m0_fi_enable_once */
34 #include "lib/errno.h" /* ENOENT */
35 #include "lib/fs.h" /* m0_file_read */
36 #include "lib/memory.h" /* m0_free */
37 #include "ut/misc.h" /* M0_UT_PATH */
38 #include "ut/ut.h"
39 
40 static uint8_t g_num;
41 static uint8_t g_num_normal[] = {4, 2, 2};
42 static uint8_t *g_num_expected = g_num_normal;
43 
44 static void root_open_test(struct m0_confc *confc)
45 {
46  struct m0_conf_root *root_obj;
47  int rc;
48 
49  rc = m0_confc_root_open(confc, &root_obj);
50  M0_UT_ASSERT(rc == 0);
53  M0_UT_ASSERT(root_obj->rt_verno == 1);
54 
55  m0_confc_close(&root_obj->rt_obj);
56 }
57 
58 static void sync_open_test(struct m0_conf_obj *nodes_dir)
59 {
60  struct m0_conf_obj *obj;
61  struct m0_conf_node *node;
62  int rc;
63 
65 
66  rc = m0_confc_open_sync(&obj, nodes_dir,
68  M0_UT_ASSERT(rc == -ENOENT);
69 
70  rc = m0_confc_open_sync(&obj, nodes_dir,
72  M0_UT_ASSERT(rc == 0);
73  M0_UT_ASSERT(obj->co_status == M0_CS_READY);
74  M0_UT_ASSERT(obj->co_cache == nodes_dir->co_cache);
76 
78  M0_UT_ASSERT(node->cn_memsize == 16000);
79  M0_UT_ASSERT(node->cn_nr_cpu == 2);
80  M0_UT_ASSERT(node->cn_last_state == 3);
81  M0_UT_ASSERT(node->cn_flags == 2);
82 
83  M0_UT_ASSERT(obj == &node->cn_obj);
85 
86  m0_fi_enable_once("m0_confc__open", "invalid-origin");
87  rc = m0_confc_open_sync(&obj, nodes_dir,
89  M0_UT_ASSERT(rc == -EAGAIN);
90 }
91 
92 static void sdev_disk_check(struct m0_confc *confc)
93 {
94  struct m0_conf_obj *sdev_obj;
95  struct m0_conf_obj *disk_obj;
96  struct m0_conf_sdev *sdev;
97  int rc;
98 
99  /* Verify disk fid from sdev object, if disk object defined. */
100  rc = m0_confc_open_sync(&sdev_obj, confc->cc_root,
101  M0_CONF_ROOT_NODES_FID,
103  M0_CONF_NODE_PROCESSES_FID,
105  M0_CONF_PROCESS_SERVICES_FID,
107  M0_CONF_SERVICE_SDEVS_FID,
109  M0_UT_ASSERT(rc == 0);
110  M0_UT_ASSERT(sdev_obj->co_status == M0_CS_READY);
111  sdev = M0_CONF_CAST(sdev_obj, m0_conf_sdev);
112 
113  rc = m0_confc_open_sync(&disk_obj, confc->cc_root,
114  M0_CONF_ROOT_SITES_FID,
116  M0_CONF_SITE_RACKS_FID,
118  M0_CONF_RACK_ENCLS_FID,
120  M0_CONF_ENCLOSURE_CTRLS_FID,
122  M0_CONF_CONTROLLER_DRIVES_FID,
124  M0_UT_ASSERT(rc == 0);
125  M0_UT_ASSERT(disk_obj->co_status == M0_CS_READY);
126 
127  M0_UT_ASSERT(m0_fid_eq(&sdev->sd_drive, &disk_obj->co_id));
128 
129  m0_confc_close(sdev_obj);
130  m0_confc_close(disk_obj);
131 
132  /* Verify disk fid from sdev object, if disk object not defined. */
133  rc = m0_confc_open_sync(&sdev_obj, confc->cc_root,
134  M0_CONF_ROOT_NODES_FID,
136  M0_CONF_NODE_PROCESSES_FID,
138  M0_CONF_PROCESS_SERVICES_FID,
140  M0_CONF_SERVICE_SDEVS_FID,
142  M0_UT_ASSERT(rc == 0);
143  M0_UT_ASSERT(sdev_obj->co_status == M0_CS_READY);
144  sdev = M0_CONF_CAST(sdev_obj, m0_conf_sdev);
146 
147  m0_confc_close(sdev_obj);
148 
149 }
150 
151 static void nodes_open(struct m0_conf_obj **result,
152  struct m0_confc *confc)
153 {
154  struct m0_conf_ut_waiter w;
155  int rc;
156 
158  m0_confc_open(&w.w_ctx, NULL, M0_CONF_ROOT_NODES_FID);
159  rc = m0_conf_ut_waiter_wait(&w, result);
160  M0_UT_ASSERT(rc == 0);
162 
163  M0_UT_ASSERT((*result)->co_status == M0_CS_READY);
164  M0_UT_ASSERT((*result)->co_cache == &confc->cc_cache);
165 }
166 
167 static void _proc_cores_add(const struct m0_conf_obj *obj)
168 {
170  &M0_CONF_CAST(obj, m0_conf_process)->pc_cores);
171 }
172 
173 static bool _proc_has_services(const struct m0_conf_obj *obj)
174 {
175  return M0_CONF_CAST(obj, m0_conf_process)->pc_services != NULL;
176 }
177 
179 
180 /* This code originates from `confc-fspec-recipe4' in conf/confc.h. */
181 static int dir_entries_use(struct m0_conf_obj *dir,
182  void (*use)(const struct m0_conf_obj *),
183  bool (*stop_at)(const struct m0_conf_obj *))
184 {
185  struct m0_conf_ut_waiter w;
186  struct m0_conf_obj *entry = NULL;
187  int rc;
188 
190 
191  while ((rc = m0_confc_readdir(&w.w_ctx, dir, &entry)) > 0) {
192  if (rc == M0_CONF_DIRNEXT) {
193  /* The entry is available immediately. */
194  M0_ASSERT(entry != NULL);
195 
196  use(entry);
197  if (stop_at != NULL && stop_at(entry)) {
198  rc = 0;
199  break;
200  }
201  continue; /* Note, that `entry' will be closed
202  * by m0_confc_readdir(). */
203  }
204 
205  /* Cache miss. */
207  rc = m0_conf_ut_waiter_wait(&w, &entry);
208  if (rc != 0 /* error */ || entry == NULL /* end of directory */)
209  break;
210 
211  use(entry);
212  if (stop_at != NULL && stop_at(entry))
213  break;
214 
215  /* Re-initialise m0_confc_ctx. */
218  }
219 
220  m0_confc_close(entry);
222  return rc;
223 }
224 
225 static void dir_test(struct m0_confc *confc)
226 {
227  struct m0_conf_obj *procs_dir;
228  struct m0_conf_obj *entry = NULL;
229  int rc;
230 
231  rc = m0_confc_open_sync(&procs_dir, confc->cc_root,
232  M0_CONF_ROOT_NODES_FID,
234  M0_CONF_NODE_PROCESSES_FID);
235  M0_UT_ASSERT(rc == 0);
236 
237  g_num = 0;
238  rc = dir_entries_use(procs_dir, _proc_cores_add, NULL);
239  M0_UT_ASSERT(rc == 0);
241 
242  g_num = 0;
244  M0_UT_ASSERT(rc == 0);
246 
247  g_num = 0;
248  while (m0_confc_readdir_sync(procs_dir, &entry) > 0)
249  ++g_num;
251 
252  m0_confc_close(entry);
253  m0_confc_close(procs_dir);
254 }
255 
256 /*
257  * We need this function in order for m0_confc_open() to be called in
258  * a separate stack frame.
259  */
261 {
263  M0_CONF_ROOT_NODES_FID,
265  M0_CONF_NODE_PROCESSES_FID,
267 }
268 
269 static void misc_test(struct m0_confc *confc)
270 {
271  struct m0_conf_obj *obj;
272  struct m0_conf_ut_waiter w;
273  struct m0_fid fids[M0_CONF_PATH_MAX + 2];
274  int i;
275  int rc;
276  struct m0_conf_obj *result;
277 
278  /*
279  * We should be able to call m0_confc_ctx_fini() right after
280  * m0_confc_ctx_init().
281  *
282  * Application code may depend on this ability (e.g.,
283  * dir_entries_use() does).
284  */
287 
288  /*
289  * A path to configuration object is created on stack (see the
290  * definition of m0_confc_open()). We need to allow this
291  * stack frame to be destructed even before the result of
292  * configuration retrieval operation is obtained.
293  *
294  * In other words, m0_confc_ctx::fc_path should be able to
295  * outlive the array of path components, constructed by
296  * m0_confc_open().
297  */
300  (void)m0_conf_ut_waiter_wait(&w, &obj);
303 
304  /*
305  * Check for too long path requested by user.
306  */
307  for (i = 0; i < ARRAY_SIZE(fids) - 1; i++)
308  fids[i] = M0_FID_INIT(1, 1);
309 
310  /* Terminate array with M0_FID0 */
311  fids[ARRAY_SIZE(fids) - 1] = M0_FID_INIT(0, 0);
312 
315  rc = m0_conf_ut_waiter_wait(&w, &result);
316  M0_UT_ASSERT(rc == -E2BIG);
318 }
319 
320 static void open_by_fid_test(struct m0_confc *confc)
321 {
322  struct m0_conf_ut_waiter w;
323  struct m0_conf_obj *obj;
324  struct m0_conf_node *node;
325  int rc;
326 
329  rc = m0_conf_ut_waiter_wait(&w, &obj);
330  M0_UT_ASSERT(rc == 0);
332  M0_UT_ASSERT(node->cn_memsize == 16000);
333  M0_UT_ASSERT(node->cn_nr_cpu == 2);
336 
337  obj = NULL;
339  &obj);
340  M0_UT_ASSERT(rc == 0);
341  M0_UT_ASSERT(obj != NULL);
343 }
344 
345 static void confc_test(const char *confd_addr, struct m0_rpc_machine *rpc_mach,
346  const char *conf_str)
347 {
348  struct m0_confc confc = {};
349  struct m0_conf_obj *nodes_dir;
350  int rc;
351 
353  conf_str);
354  M0_UT_ASSERT(rc == 0);
355 
357  dir_test(&confc);
358  misc_test(&confc);
359  nodes_open(&nodes_dir, &confc); /* tests asynchronous interface */
360  sync_open_test(nodes_dir);
363 
364  m0_confc_close(nodes_dir);
366 }
367 
368 static void test_confc_local(void)
369 {
370  struct m0_confc confc = {};
371  struct m0_conf_obj *obj;
372  char *confstr = NULL;
373  int rc;
374 
376  "bad configuration string");
377  M0_UT_ASSERT(rc == -EPROTO);
378 
379  rc = m0_file_read(M0_UT_PATH("conf.xc"), &confstr);
380  M0_UT_ASSERT(rc == 0);
381  rc = m0_confc_init(&confc, &m0_conf_ut_grp, NULL, NULL, confstr);
382  M0_UT_ASSERT(rc == 0);
383 
384  /* normal case - profile exists in conf */
386  M0_CONF_ROOT_PROFILES_FID,
388  M0_UT_ASSERT(rc == 0);
390 
391  /* fail case - profile does not exist */
393  M0_CONF_ROOT_PROFILES_FID,
394  M0_FID_TINIT('p', 7, 7));
395  M0_UT_ASSERT(rc == -ENOENT);
397 
398  confc_test(NULL, NULL, confstr);
399  m0_free(confstr);
400 }
401 
403 {
404  struct m0_confc confc = {};
405  struct m0_conf_obj *obj;
406  char *confstr = NULL;
407  int rc;
408  uint8_t mw_core_num[] = {12, 10, 2};
409 
410  /* load conf with a process having multi-word core mask */
411  rc = m0_file_read(M0_SRC_PATH("conf/ut/multiword-core-mask.xc"),
412  &confstr);
413  M0_UT_ASSERT(rc == 0);
414  rc = m0_confc_init(&confc, &m0_conf_ut_grp, NULL, NULL, confstr);
415  M0_UT_ASSERT(rc == 0);
416 
418  M0_CONF_ROOT_PROFILES_FID,
420  M0_UT_ASSERT(rc == 0);
423 
424  g_num_expected = mw_core_num;
425  confc_test(NULL, NULL, confstr);
427  m0_free(confstr);
428 }
429 
430 static void test_confc_net(void)
431 {
432  struct m0_rpc_machine mach;
433  int rc;
434 #define NAME(ext) "ut_confd" ext
435  char *argv[] = {
436  NAME(""), "-T", "AD", "-D", NAME(".db"),
437  "-S", NAME(".stob"), "-A", "linuxstob:"NAME("-addb_stob"),
438  "-w", "10", "-e", SERVER_ENDPOINT, "-H", SERVER_ENDPOINT_ADDR,
439  "-f", M0_UT_CONF_PROCESS,
440  "-c", M0_UT_PATH("conf.xc")
441  };
442  struct m0_rpc_server_ctx confd = {
444  .rsx_xprts_nr = m0_net_xprt_nr(),
445  .rsx_argv = argv,
446  .rsx_argc = ARRAY_SIZE(argv),
447  .rsx_log_file_name = NAME(".log")
448  };
449 #undef NAME
450 
451  rc = m0_rpc_server_start(&confd);
452  M0_UT_ASSERT(rc == 0);
453 
456  M0_UT_ASSERT(rc == 0);
457 
459 
461  m0_rpc_server_stop(&confd);
462 }
463 
464 static void test_confc_invalid_input(void)
465 {
466  struct m0_confc confc = {};
467  char *confstr = NULL;
468  int rc;
469 
470  rc = m0_file_read(M0_SRC_PATH("conf/ut/duplicated-ids.xc"), &confstr);
471  M0_UT_ASSERT(rc == 0);
472  rc = m0_confc_init(&confc, &m0_conf_ut_grp, NULL, NULL, confstr);
473  M0_UT_ASSERT(rc == -EEXIST);
474  m0_free(confstr);
475 }
476 
478  .ts_name = "confc-ut",
479  .ts_init = m0_conf_ut_ast_thread_init,
480  .ts_fini = m0_conf_ut_ast_thread_fini,
481  .ts_tests = {
482  { "local", test_confc_local },
483  { "mw-core-mask", test_confc_multiword_core_mask },
484  { "net", test_confc_net },
485  { "bad-input", test_confc_invalid_input },
486  { NULL, NULL }
487  }
488 };
489 
490 #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
static void misc_test(struct m0_confc *confc)
Definition: confc.c:269
static void sync_open_test(struct m0_conf_obj *nodes_dir)
Definition: confc.c:58
static void open_by_fid_test(struct m0_confc *confc)
Definition: confc.c:320
struct m0_conf_obj * cc_root
Definition: confc.h:404
#define M0_PRE(cond)
#define NULL
Definition: misc.h:38
static void nodes_open(struct m0_conf_obj **result, struct m0_confc *confc)
Definition: confc.c:151
static void dir_test(struct m0_confc *confc)
Definition: confc.c:225
struct m0_conf_obj rt_obj
Definition: obj.h:372
M0_INTERNAL int m0_file_read(const char *path, char **out)
Definition: fs.c:61
M0_INTERNAL void m0_conf_ut_waiter_fini(struct m0_conf_ut_waiter *w)
Definition: common.c:49
M0_BASSERT(M0_CONF_DIREND==0)
int m0_rpc_server_start(struct m0_rpc_server_ctx *sctx)
Definition: rpclib.c:50
#define M0_FID_INIT(container, key)
Definition: fid.h:84
static struct net_test_cmd_node * node
Definition: commands.c:72
M0_INTERNAL int m0_ut_rpc_machine_start(struct m0_rpc_machine *mach, struct m0_net_xprt *xprt, const char *ep_addr)
Definition: rpc_helpers.c:46
M0_INTERNAL int m0_conf_ut_waiter_wait(struct m0_conf_ut_waiter *w, struct m0_conf_obj **result)
Definition: common.c:56
M0_INTERNAL int m0_confc_init(struct m0_confc *confc, struct m0_sm_group *sm_group, const char *confd_addr, struct m0_rpc_machine *rpc_mach, const char *local_conf)
Definition: confc.c:560
M0_INTERNAL void m0_confc_fini(struct m0_confc *confc)
Definition: confc.c:570
static int dir_entries_use(struct m0_conf_obj *dir, void(*use)(const struct m0_conf_obj *), bool(*stop_at)(const struct m0_conf_obj *))
Definition: confc.c:181
static struct m0_addb2_mach * mach
Definition: storage.c:42
M0_INTERNAL size_t m0_bitmap_set_nr(const struct m0_bitmap *map)
Definition: bitmap.c:172
static uint8_t * g_num_expected
Definition: confc.c:42
struct m0_conf_cache * co_cache
Definition: obj.h:251
#define M0_SRC_PATH(name)
Definition: misc.h:48
M0_INTERNAL void m0_confc_open_by_fid(struct m0_confc_ctx *ctx, const struct m0_fid *fid)
Definition: confc.c:930
#define CLIENT_ENDPOINT_ADDR
Definition: common.h:32
Definition: ut.h:77
M0_INTERNAL bool m0_fid_is_set(const struct m0_fid *fid)
Definition: fid.c:106
static struct foo * obj
Definition: tlist.c:302
#define m0_confc_open(ctx, origin,...)
Definition: confc.h:678
M0_INTERNAL int m0_confc_root_open(struct m0_confc *confc, struct m0_conf_root **root)
Definition: helpers.c:219
static bool _proc_has_services(const struct m0_conf_obj *obj)
Definition: confc.c:173
static void test_confc_net(void)
Definition: confc.c:430
static uint8_t g_num
Definition: confc.c:40
int i
Definition: dir.c:1033
struct m0_confc_ctx w_ctx
Definition: common.h:38
static void confc_test(const char *confd_addr, struct m0_rpc_machine *rpc_mach, const char *conf_str)
Definition: confc.c:345
#define M0_FID_TINIT(type, container, key)
Definition: fid.h:90
static void sdev_disk_check(struct m0_confc *confc)
Definition: confc.c:92
M0_INTERNAL void m0_confc_ctx_fini(struct m0_confc_ctx *ctx)
Definition: confc.c:716
static void test_confc_local(void)
Definition: confc.c:368
M0_INTERNAL int m0_conf_ut_ast_thread_fini(void)
Definition: common.c:96
#define M0_ASSERT(cond)
static struct m0_confc * confc
Definition: file.c:94
int m0_net_xprt_nr(void)
Definition: net.c:168
M0_INTERNAL int m0_confc_ctx_init(struct m0_confc_ctx *ctx, struct m0_confc *confc)
Definition: confc.c:643
struct m0_conf_cache cc_cache
Definition: confc.h:394
const char * confd_addr[]
struct m0_net_xprt * m0_net_xprt_default_get(void)
Definition: net.c:151
struct m0_net_xprt ** rsx_xprts
Definition: rpclib.h:69
static const struct m0_fid m0_ut_conf_fids[]
Definition: confc.h:54
#define SERVER_ENDPOINT
Definition: common.h:31
struct m0_sm_group m0_conf_ut_grp
Definition: common.c:32
static const struct m0_fid fids[]
Definition: diter.c:76
uint64_t rt_verno
Definition: obj.h:390
#define M0_CONF_CAST(ptr, type)
Definition: obj.h:780
#define m0_confc_open_sync(result, origin,...)
Definition: confc.h:707
static uint8_t g_num_normal[]
Definition: confc.c:41
M0_INTERNAL int m0_conf_ut_ast_thread_init(void)
Definition: common.c:86
M0_INTERNAL bool m0_fid_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: fid.c:164
const char * ts_name
Definition: ut.h:99
Definition: fid.h:38
M0_INTERNAL void m0_confc__open(struct m0_confc_ctx *ctx, struct m0_conf_obj *origin, const struct m0_fid *path)
Definition: confc.c:850
M0_INTERNAL void m0_conf_ut_waiter_init(struct m0_conf_ut_waiter *w, struct m0_confc *confc)
Definition: common.c:41
#define M0_UT_CONF_PROCESS
Definition: misc.h:45
struct m0_net_xprt ** m0_net_all_xprt_get(void)
Definition: net.c:161
static void _proc_cores_add(const struct m0_conf_obj *obj)
Definition: confc.c:167
enum m0_conf_status co_status
Definition: obj.h:210
static void m0_fi_enable_once(const char *func, const char *tag)
Definition: finject.h:301
M0_INTERNAL struct m0_confc * m0_confc_from_obj(const struct m0_conf_obj *obj)
Definition: confc.c:592
M0_INTERNAL void m0_confc_close(struct m0_conf_obj *obj)
Definition: confc.c:921
M0_INTERNAL void m0_ut_rpc_machine_stop(struct m0_rpc_machine *mach)
Definition: rpc_helpers.c:93
void m0_rpc_server_stop(struct m0_rpc_server_ctx *sctx)
Definition: rpclib.c:85
#define SERVER_ENDPOINT_ADDR
Definition: common.h:30
static void root_open_test(struct m0_confc *confc)
Definition: confc.c:44
struct m0_fid sd_drive
Definition: obj.h:628
struct inode * dir
Definition: dir.c:1028
Definition: nucleus.c:42
#define M0_UT_PATH(name)
Definition: misc.h:41
const struct m0_conf_obj_type M0_CONF_DIR_TYPE
Definition: dir.c:206
static void test_confc_invalid_input(void)
Definition: confc.c:464
void m0_free(void *data)
Definition: memory.c:146
M0_INTERNAL int m0_confc_readdir_sync(struct m0_conf_obj *dir, struct m0_conf_obj **pptr)
Definition: confc.c:1020
#define NAME(ext)
M0_INTERNAL int m0_confc_open_by_fid_sync(struct m0_confc *confc, const struct m0_fid *fid, struct m0_conf_obj **result)
Definition: confc.c:943
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
static void test_confc_multiword_core_mask(void)
Definition: confc.c:402
#define M0_UT_ASSERT(a)
Definition: ut.h:46
static void _retrieval_initiate(struct m0_confc_ctx *ctx)
Definition: confc.c:260
struct m0_ut_suite confc_ut
Definition: confc.c:477
M0_INTERNAL int m0_confc_readdir(struct m0_confc_ctx *ctx, struct m0_conf_obj *dir, struct m0_conf_obj **pptr)
Definition: confc.c:990