Motr  M0
rconfc.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_UT
24 #include "lib/trace.h"
25 
26 #define M0_UT_TRACE 0
27 
28 #include <unistd.h> /* usleep */
29 #include "conf/rconfc.h"
30 #include "conf/rconfc_internal.h" /* rlock_ctx */
31 #include "conf/confd.h" /* m0_confd_stype */
32 #include "conf/helpers.h" /* m0_confc_expired_cb */
33 #include "conf/ut/common.h" /* SERVER_ENDPOINT */
34 #include "conf/ut/confc.h" /* m0_ut_conf_fids */
35 #include "conf/ut/rpc_helpers.h" /* m0_ut_rpc_machine_start */
36 #include "rpc/rpclib.h" /* m0_rpc_server_ctx */
37 #include "lib/finject.h"
38 #include "lib/fs.h" /* m0_file_read */
39 #include "module/instance.h" /* m0_get */
40 #include "ut/misc.h" /* M0_UT_PATH, M0_UT_CONF_PROCESS */
41 #include "ut/ut.h"
42 
44 static struct m0_semaphore g_ready_sem;
45 static struct m0_semaphore g_fatal_sem;
46 static struct m0_reqh *ut_reqh;
48 
49 static struct m0_fid profile = M0_FID_TINIT('p', 1, 0);
50 static bool (*ha_clink_cb_orig)(struct m0_clink *clink);
51 
52 
55 
56 enum {
60 };
61 
62 struct root_object {
63  struct m0_conf_root *root;
64  struct m0_clink clink_x;
65  struct m0_clink clink_r;
66  struct m0_confc *confc;
67 };
68 
69 static struct m0_rpc_client_ctx cctx = {
71  .rcx_local_addr = CLIENT_ENDPOINT_ADDR,
72  .rcx_remote_addr = SERVER_ENDPOINT_ADDR,
73  .rcx_max_rpcs_in_flight = MAX_RPCS_IN_FLIGHT,
74  .rcx_fid = &g_process_fid,
75 };
76 
78  struct m0_rpc_server_ctx *rctx)
79 {
80  int rc;
81 #define NAME(ext) "rconfc-ut" ext
82  char *argv[] = {
83  NAME(""), "-T", "AD", "-D", NAME(".db"),
84  "-S", NAME(".stob"), "-A", "linuxstob:"NAME("-addb.stob"),
85  "-w", "10", "-e", SERVER_ENDPOINT, "-H", SERVER_ENDPOINT_ADDR,
86  "-f", M0_UT_CONF_PROCESS,
87  "-c", M0_UT_PATH("diter.xc")
88  };
89  *rctx = (struct m0_rpc_server_ctx) {
90  .rsx_xprts = m0_net_all_xprt_get(),
91  .rsx_xprts_nr = m0_net_xprt_nr(),
92  .rsx_argv = argv,
93  .rsx_argc = ARRAY_SIZE(argv),
94  .rsx_log_file_name = NAME(".log")
95  };
96 #undef NAME
97 
98  M0_SET0(mach);
100  M0_UT_ASSERT(rc == 0);
101 
104  M0_UT_ASSERT(rc == 0);
105  ut_reqh = mach->rm_reqh;
106  mach->rm_reqh = &rctx->rsx_motr_ctx.cc_reqh_ctx.rc_reqh;
107  return rc;
108 }
109 
111  struct m0_rpc_server_ctx *rctx)
112 {
113  mach->rm_reqh = ut_reqh;
116 }
117 
118 static void test_null_exp_cb(struct m0_rconfc *rconfc)
119 {
120  /*
121  * Test expiration callback that shouldn't be called, because
122  * test doesn't expect reelection.
123  */
124  M0_UT_ASSERT(0);
125 }
126 
127 static void conflict_exp_cb(struct m0_rconfc *rconfc)
128 {
129  M0_UT_ENTER();
131  M0_UT_RETURN();
132 }
133 
134 static void conflict_ready_cb(struct m0_rconfc *rconfc)
135 {
136  M0_UT_ENTER();
138  M0_UT_RETURN();
139 }
140 
141 static void test_init_fini(void)
142 {
143  struct m0_rpc_machine mach;
144  struct m0_rpc_server_ctx rctx;
145  struct m0_rconfc rconfc;
146  int rc;
147 
149  M0_UT_ASSERT(rc == 0);
152  M0_UT_ASSERT(rc == 0);
155 }
156 
157 static void test_start_stop(void)
158 {
159  struct m0_rpc_machine mach;
160  struct m0_rpc_server_ctx rctx;
161  int rc;
162  struct m0_rconfc rconfc;
163  uint64_t ver;
164 
166  M0_UT_ASSERT(rc == 0);
168  NULL);
169  M0_UT_ASSERT(rc == 0);
172  M0_UT_ASSERT(rc == 0);
173  M0_UT_ASSERT(rconfc.rc_ver != 0);
175  M0_UT_ASSERT(ver == rconfc.rc_ver);
180 }
181 
182 static void test_start_stop_local(void)
183 {
184  struct m0_rpc_machine mach;
185  struct m0_rpc_server_ctx rctx;
186  int rc;
187  struct m0_rconfc rconfc;
188 
190  M0_UT_ASSERT(rc == 0);
192  NULL);
193  M0_UT_ASSERT(rc == 0);
195  M0_UT_ASSERT(rc == 0);
197  M0_UT_ASSERT(rc == 0);
199  M0_UT_ASSERT(rconfc.rc_ver != 0);
203 }
204 
205 static void test_local_load_fail(void)
206 {
207  struct m0_rpc_machine mach;
208  struct m0_rpc_server_ctx rctx;
209  int rc;
210  struct m0_rconfc rconfc;
211 
213  M0_UT_ASSERT(rc == 0);
215  M0_UT_ASSERT(rc == 0);
216  rconfc.rc_local_conf = m0_strdup("abracadabra");
218  M0_UT_ASSERT(rc != 0);
220  M0_UT_ASSERT(rconfc.rc_ver == 0);
224 }
225 
226 static void test_start_failures(void)
227 {
228  struct m0_rpc_machine mach;
229  struct m0_rpc_server_ctx rctx;
230  int rc;
231  struct m0_rconfc rconfc;
232 
234  M0_UT_ASSERT(rc == 0);
235  m0_fi_enable_once("rlock_ctx_connect", "rm_conn_failed");
237  NULL);
238  M0_UT_ASSERT(rc == 0);
240  /*
241  * If connection to RM fails, then rconfc will try to start from
242  * beginning, because it is possible that RM creditor has changed during
243  * connection. Second attempt will succeed.
244  */
245  M0_UT_ASSERT(rc == 0);
248 
249  m0_fi_enable_once("rconfc_read_lock_complete", "rlock_req_failed");
250  m0_fi_enable_once("_failure_ast_cb", "rlock_req_failed");
252  NULL);
253  M0_UT_ASSERT(rc == 0);
255  M0_UT_ASSERT(rc == -ESRCH);
258 
260 }
261 
262 static void rconfc_ut_fatal_cb(struct m0_rconfc *rconfc)
263 {
266 }
267 
268 static bool ha_clink_cb_suppress(struct m0_clink *clink)
269 {
271 
274  if (rconfc->rc_fatal_cb == NULL)
276  else /* installed previously */
279  /* do nothing as if HA client went dead */
280  return true;
281 }
282 
283 /*
284  * The test is to check timeout expiration during rconfc synchronous start with
285  * limited timeout. As well, fatal callback passage is checked due to rconfc
286  * failure. The callback is installed in the course of rconfc start.
287  */
288 static void test_fail_abort(void)
289 {
290  struct m0_rpc_machine mach;
291  struct m0_rpc_server_ctx rctx;
292  int rc;
293  struct m0_rconfc rconfc;
294 
296  M0_UT_ASSERT(rc == 0);
297 
299  NULL);
300  M0_UT_ASSERT(rc == 0);
301  /*
302  * Suppress ha entrypoint response to cause timeout. Imitation of not
303  * responding HA.
304  */
311  M0_UT_ASSERT(rc == -ETIMEDOUT);
314  /* restore original callback */
318 
320 }
321 
322 static char *suffix_subst(const char *src, char delim, const char *suffix)
323 {
324  const size_t len = strlen(src) + 1 + strlen(suffix) + 1;
325  char *s;
326  char *p;
327 
328  s = m0_alloc(len);
329  M0_ASSERT(s != NULL);
330  strncpy(s, src, len);
331  p = strrchr(s, delim);
332  M0_ASSERT(p != NULL);
333  strncpy(p, suffix, strlen(suffix) + 1);
334  return s;
335 }
336 
337 static bool do_fake = true;
338 static bool ha_clink_cb_bad_rm(struct m0_clink *clink)
339 {
340  struct m0_rconfc *rconfc = M0_AMB(rconfc, clink,
342  struct m0_ha_entrypoint_client *ecl =
344 
348  char *rm_addr = ecl->ecl_rep.hae_active_rm_ep;
349  char *rm_fake = NULL;
350  /*
351  * The test is to fake the rm addr only once to provide that the
352  * next time correct rm addr reaches rconfc non-distorted, which
353  * guarantees successful connection to RM.
354  */
355  if (do_fake) {
356  rm_fake = suffix_subst(rm_addr, ':', ":999");
357  ecl->ecl_rep.hae_active_rm_ep = rm_fake;
358  do_fake = false; /* not next time */
359  }
360  /*
361  * call original handler to let rconfc copy this version of
362  * response and go on with connection
363  */
365  /*
366  * get real active rm address back to entrypoint response
367  */
369  m0_free(rm_fake);
370  }
371  return true;
372 }
373 
374 static void test_fail_retry_rm(void)
375 {
376  struct m0_rpc_machine mach;
377  struct m0_rpc_server_ctx rctx;
378  int rc;
379  struct m0_rconfc rconfc;
380 
381  M0_SET0(&rconfc);
383  M0_UT_ASSERT(rc == 0);
384 
386  NULL);
387  M0_UT_ASSERT(rc == 0);
388  /*
389  * Distort ha entrypoint response (active rm) to cause HA request
390  * retry. Imitation of the situation when HA reports dead active RM
391  * endpoint and later reports a connectable one.
392  */
393  do_fake = true;
397  M0_UT_ASSERT(rc == 0);
399  /* restore original callback */
403 
405 }
406 
408 {
409  struct m0_rconfc *rconfc = M0_AMB(rconfc, clink,
411  struct m0_ha_entrypoint_client *ecl =
413 
417  const char *confd_addr = ecl->ecl_rep.hae_confd_eps[0];
418  char *confd_fake = NULL;
419  /*
420  * The test is to fake the confd addr only once to provide that
421  * the next time correct confd addr reaches rconfc
422  * non-distorted, which guarantees successful connection to it.
423  */
424  if (do_fake) {
425  do_fake = false;
426  confd_fake = suffix_subst(confd_addr, ':', ":999");
427  *(char **)&ecl->ecl_rep.hae_confd_eps[0] = confd_fake;
428  }
429  /*
430  * call original handler to let rconfc copy this version of
431  * response and go on with connection
432  */
434  /*
435  * get real active rm address back to entrypoint response
436  */
437  ecl->ecl_rep.hae_confd_eps[0] = confd_addr;
438  m0_free(confd_fake);
439  }
440  return true;
441 }
442 
443 static void test_fail_retry_confd(void)
444 {
445  struct m0_rpc_machine mach;
446  struct m0_rpc_server_ctx rctx;
447  int rc;
448  struct m0_rconfc rconfc;
449 
451  M0_UT_ASSERT(rc == 0);
452 
454  NULL);
455  M0_UT_ASSERT(rc == 0);
456  /*
457  * Distort ha entrypoint response (confd) to cause HA request
458  * retry. Imitation of the situation when HA reports dead confd
459  * endpoint and later reports a connectable one.
460  */
461  do_fake = true;
465  M0_UT_ASSERT(rc == 0);
467  /* restore original callback */
471 
473 }
474 
475 static void _stop_rms(struct m0_rpc_machine *rmach)
476 {
477  struct m0_reqh_service *service;
478  struct m0_reqh *reqh = rmach->rm_reqh;
479  struct m0_fid rm_fid = M0_FID_TINIT('s', 1, 2);
480 
481  service = m0_reqh_service_lookup(reqh, &rm_fid);
483  M0_UT_ASSERT(m0_streq(service->rs_type->rst_name, "M0_CST_RMS"));
487 }
488 
489 static void test_no_rms(void)
490 {
491  struct m0_rpc_machine mach;
492  struct m0_rpc_server_ctx rctx;
493  int rc;
494  struct m0_rconfc rconfc;
495 
497  M0_UT_ASSERT(rc == 0);
498 
499  /* quit on command from HA */
500  m0_fi_enable_once("motr_ha_entrypoint_rep_rm_fill", "no_rms_fid");
502  NULL);
503  M0_UT_ASSERT(rc == 0);
505  M0_UT_ASSERT(rc == -EPERM);
506  /* see if we can stop after start failure */
509 
510  /* start with rms up and running */
512  NULL);
513  M0_UT_ASSERT(rc == 0);
515  M0_UT_ASSERT(rc == 0);
516  /* see if we can stop when there is no rms around */
517  _stop_rms(&mach);
520 
521  /* repeat with no rms around */
523  NULL);
524  M0_UT_ASSERT(rc == 0);
526  M0_UT_ASSERT(rc == -ECONNREFUSED);
527  /* see if we can stop after start failure */
530 
532 }
533 
534 static void rconfc_ut_ha_state_set(const struct m0_fid *fid, uint32_t state)
535 {
536  struct m0_ha_note note = { .no_id = *fid, .no_state = state };
537  struct m0_ha_nvec nvec = { .nv_nr = 1, .nv_note = &note };
538 
539  m0_ha_state_set(&nvec);
540 }
541 
542 static struct m0_semaphore sem_death;
544 
545 M0_TL_DESCR_DECLARE(rpc_conn, M0_EXTERN);
546 M0_TL_DECLARE(rpc_conn, M0_INTERNAL, struct m0_rpc_conn);
547 
548 static void _on_death_cb(struct rconfc_link *lnk)
549 {
551  if (lnk->rl_fom_queued) {
553  /* herd link confc not connected */
555  /* herd link confc uninitialised */
557  }
559  M0_LOG(M0_DEBUG, "Done %s waiting for FOM fini",
560  lnk->rl_fom_queued ? "after" : "with no");
562  }
563 }
564 
565 M0_TL_DESCR_DECLARE(rcnf_herd, M0_EXTERN);
566 M0_TL_DECLARE(rcnf_herd, M0_INTERNAL, struct rconfc_link);
567 
572 };
573 
575  enum ut_confc_control ctrl)
576 {
577  struct rconfc_link *lnk;
578 
579  m0_tl_for(rcnf_herd, &rconfc->rc_herd, lnk) {
581  switch (ctrl) {
582  case UT_CC_KEEP_AS_IS:
583  break;
584  case UT_CC_DISCONNECT:
586  break;
587  case UT_CC_DEINITIALISE:
589  m0_confc_fini(&lnk->rl_confc);
590  break;
591  }
592  } m0_tl_endfor;
593 }
594 
595 /*
596  * The test is to verify rconfc_herd_link__on_death_cb() passage as well as
597  * ability for rconfc to stop while having herd link dead.
598  *
599  * Rconfc gets successfully started with a single confd in conf. Later the confd
600  * is announced M0_NC_FAILED that invokes the corresponding herd link callback.
601  * When notification is successfully processed, rconfc is tested for shutting
602  * down with the herd link being in CONFC_DEAD state.
603  *
604  * As the death notification may arrive when the link's confc can be in any
605  * state, all the states (online, disconnected, finalised) must be tested for
606  * safe going down.
607  */
608 static void test_dead_down(void)
609 {
610  struct m0_rpc_machine mach;
611  struct m0_rpc_server_ctx rctx;
612  int rc;
613  struct m0_rconfc rconfc;
614  struct m0_fid confd_fid = M0_FID_TINIT('s', 1, 6);
615 
616  /*
617  * The tests below are going to wait for FOM being queued and finalised
618  * regular way.
619  */
621 
623  M0_UT_ASSERT(rc == 0);
624 
625  /* 1. Normal case */
628  NULL);
629  M0_UT_ASSERT(rc == 0);
631  M0_UT_ASSERT(rc == 0);
641 
642  /* 2. Notification jitters */
645  NULL);
646  M0_UT_ASSERT(rc == 0);
648  M0_UT_ASSERT(rc == 0);
653  rconfc_ut_ha_state_set(&confd_fid, M0_NC_FAILED); /* legal tap */
654  rconfc_ut_ha_state_set(&confd_fid, M0_NC_FAILED); /* double tap */
659 
660  /* 3. Deal with already disconnected confc */
663  NULL);
664  M0_UT_ASSERT(rc == 0);
666  M0_UT_ASSERT(rc == 0);
676 
677  /* 4. Deal with already finalised confc */
680  NULL);
681  M0_UT_ASSERT(rc == 0);
683  M0_UT_ASSERT(rc == 0);
693 
694  /*
695  * Test error paths in fom tick
696  *
697  * 5. Survive from session failure
698  */
701  NULL);
702  M0_UT_ASSERT(rc == 0);
704  M0_UT_ASSERT(rc == 0);
709  m0_fi_enable("rconfc_link_fom_tick", "sess_fail");
713  m0_fi_disable("rconfc_link_fom_tick", "sess_fail");
716 
717  /* 6. Survive from connection failure */
720  NULL);
721  M0_UT_ASSERT(rc == 0);
723  M0_UT_ASSERT(rc == 0);
728  m0_fi_enable("rconfc_link_fom_tick", "conn_fail");
732  m0_fi_disable("rconfc_link_fom_tick", "conn_fail");
735 
736  /* 7. Survive from both session and connection failures */
739  NULL);
740  M0_UT_ASSERT(rc == 0);
742  M0_UT_ASSERT(rc == 0);
747  m0_fi_enable("rconfc_link_fom_tick", "sess_fail");
748  m0_fi_enable("rconfc_link_fom_tick", "conn_fail");
752  m0_fi_disable("rconfc_link_fom_tick", "conn_fail");
753  m0_fi_disable("rconfc_link_fom_tick", "sess_fail");
756 
758 }
759 
760 /*
761  * The test is to verify rconfc_herd_link__on_death_cb() passing safe being
762  * concurrent with rconfc stopping.
763  */
764 static void test_dead_stop(void)
765 {
766  struct m0_rpc_machine mach;
767  struct m0_rpc_server_ctx rctx;
768  int rc;
769  struct m0_rconfc rconfc;
770  struct m0_fid confd_fid = M0_FID_TINIT('s', 1, 6);
771 
772  /*
773  * Run link FOM concurrent with stopping.
774  *
775  * The concurrent execution is achieved by releasing sem_dead right
776  * before queueing FOM in rconfc_herd_link__on_death_cb().
777  */
779 
781  M0_UT_ASSERT(rc == 0);
782 
785  NULL);
786  M0_UT_ASSERT(rc == 0);
788  M0_UT_ASSERT(rc == 0);
798 
800 }
801 
802 static void test_reading(void)
803 {
804  struct m0_rpc_machine mach;
805  struct m0_rpc_server_ctx rctx;
806  int rc;
807  struct m0_rconfc rconfc;
808  uint64_t ver;
809  struct m0_conf_obj *cobj;
810 
812  M0_UT_ASSERT(rc == 0);
814  NULL);
815  M0_UT_ASSERT(rc == 0);
817  M0_UT_ASSERT(rc == 0);
819  M0_UT_ASSERT(ver == rconfc.rc_ver);
820  /* do regular path opening */
822  M0_CONF_ROOT_PROFILES_FID,
824  M0_UT_ASSERT(rc == 0);
825  m0_confc_close(cobj);
829 }
830 
831 static bool quorum_impossible_clink_cb(struct m0_clink *cl)
832 {
833  struct m0_rconfc *rconfc = container_of(cl->cl_chan, struct m0_rconfc,
834  rc_sm.sm_chan);
835  static bool do_override = true;
836 
837  if (do_override && rconfc->rc_sm.sm_state == M0_RCS_GET_RLOCK) {
838  /*
839  * Override required quorum value to be greater then number of
840  * confd, so quorum is impossible.
841  */
842  M0_PRE(rconfc->rc_quorum != 0);
843  rconfc->rc_quorum *= 2;
844  m0_clink_del(cl);
845  /*
846  * Overridden once, next time entrypoint re-tried it must remain
847  * untouched to let rconfc start successfully.
848  */
849  do_override = false;
850  }
851  return true;
852 }
853 
854 static void test_quorum_impossible(void)
855 {
856  struct m0_rconfc rconfc;
857  struct m0_rpc_machine mach;
858  int rc;
859  uint64_t ver;
860  struct m0_rpc_server_ctx rctx;
861  struct m0_clink clink;
862 
864  /*
865  * Have the number of online herd links less than required to reach the
866  * quorum. Once failed, next re-election succeeds.
867  */
868  M0_UT_ASSERT(rc == 0);
869  M0_SET0(&rconfc);
871  NULL);
872  M0_UT_ASSERT(rc == 0);
876  M0_UT_ASSERT(rc == 0);
879  if (m0_clink_is_armed(&clink))
885 }
886 
887 static void test_quorum_retry(void)
888 {
889  struct m0_rpc_machine mach;
890  struct m0_rpc_server_ctx rctx;
891  int rc;
892  struct m0_rconfc rconfc;
893  uint64_t ver;
894 
896  M0_UT_ASSERT(rc == 0);
897 
898  /*
899  * 1. Have herd link online, but fetching bad version number. Once
900  * failed, next re-election succeeds.
901  */
903  NULL);
904  M0_UT_ASSERT(rc == 0);
906  m0_fi_enable_once("rconfc__cb_quorum_test", "read_ver_failed");
908  M0_UT_ASSERT(rc == 0);
909  M0_UT_ASSERT(rconfc.rc_ver != 0);
911  M0_UT_ASSERT(ver == rconfc.rc_ver);
915 
916  /*
917  * 2. Have all herd links CONFC_DEAD. Once failed, next re-election
918  * succeeds.
919  */
921  NULL);
922  M0_UT_ASSERT(rc == 0);
924  m0_fi_enable_once("rconfc_herd_link_init", "confc_init");
926  M0_UT_ASSERT(rc == 0);
927  M0_UT_ASSERT(rconfc.rc_ver != 0);
929  M0_UT_ASSERT(ver == rconfc.rc_ver);
933 
934  /*
935  * 3. Have conductor failed to engage. Once failed, next re-election
936  * succeeds.
937  */
939  NULL);
940  M0_UT_ASSERT(rc == 0);
942  m0_fi_enable_once("rconfc_conductor_iterate", "conductor_conn_fail");
944  M0_UT_ASSERT(rc == 0);
945  M0_UT_ASSERT(rconfc.rc_ver != 0);
947  M0_UT_ASSERT(ver == rconfc.rc_ver);
951 
953 }
954 
956 
957 static void test_gops(void)
958 {
959  struct m0_rconfc rconfc;
960  struct m0_rpc_machine mach;
961  int rc;
962  struct m0_rpc_server_ctx rctx;
963  bool check_res;
964 
966  M0_UT_ASSERT(rc == 0);
967  M0_SET0(&rconfc);
969  NULL);
970  M0_UT_ASSERT(rc == 0);
972  M0_UT_ASSERT(rc == 0);
973 
974  /* imitate check op */
976  check_res = rconfc.rc_gops.go_check(&rconfc.rc_confc);
977  M0_UT_ASSERT(check_res == true);
979 
980  /* imitate skip op */
982  M0_UT_ASSERT(rc == -ENOENT);
987 }
988 
990  uint64_t new_ver)
991 {
992  struct m0_reqh *reqh;
993  struct m0_reqh_service *svc;
994  struct m0_confd *confd = NULL;
995  struct m0_conf_cache *cc;
996  struct m0_conf_root *root;
997 
998  /* Find confd instance through corresponding confd service */
999  reqh = &rctx->rsx_motr_ctx.cc_reqh_ctx.rc_reqh;
1000  m0_tl_for(m0_reqh_svc, &reqh->rh_services, svc) {
1001  if (svc->rs_type == &m0_confd_stype) {
1002  confd = container_of(svc, struct m0_confd, d_reqh);
1003  break;
1004  }
1005  } m0_tl_endfor;
1006  M0_UT_ASSERT(confd != NULL);
1007 
1008  cc = confd->d_cache;
1009  cc->ca_ver = new_ver;
1011  m0_conf_root);
1012  M0_UT_ASSERT(root != NULL);
1013  root->rt_verno = new_ver;
1014  root->rt_mdredundancy = 51212;
1015 }
1016 
1017 static void test_version_change(void)
1018 {
1019  struct m0_rconfc rconfc;
1020  struct m0_rpc_machine mach;
1021  int rc;
1022  struct m0_rpc_server_ctx rctx;
1023  struct rlock_ctx *rlx;
1024  struct m0_conf_obj *root_obj;
1025 
1027  M0_UT_ASSERT(rc == 0);
1029 
1030  M0_SET0(&rconfc);
1033  M0_UT_ASSERT(rc == 0);
1035  M0_UT_ASSERT(rc == 0);
1036 
1037  /* Check that version 1 in use */
1038  M0_UT_ASSERT(rconfc.rc_ver == 1);
1040  M0_UT_ASSERT(rc == 0);
1041  M0_UT_ASSERT(M0_CONF_CAST(root_obj, m0_conf_root)->rt_verno == 1);
1042  m0_confc_close(root_obj);
1043 
1044  /* Update conf DB version and immitate read lock conflict */
1046  rlx = rconfc.rc_rlock_ctx;
1048 
1049  /* Wait till version reelection is finished */
1053  M0_TIME_NEVER);
1056 
1057  /* Check that version in use is 2 */
1058  M0_UT_ASSERT(rconfc.rc_ver == 2);
1060  M0_UT_ASSERT(rc == 0);
1061  M0_UT_ASSERT(M0_CONF_CAST(root_obj, m0_conf_root)->rt_verno == 2);
1062  m0_confc_close(root_obj);
1063 
1068 }
1069 
1070 static void test_cache_drop(void)
1071 {
1072  struct m0_rconfc rconfc;
1073  struct m0_rpc_machine mach;
1074  int rc;
1075  struct m0_rpc_server_ctx rctx;
1076  struct rlock_ctx *rlx;
1077  struct m0_conf_obj *root_obj;
1078  struct m0_confc *confc;
1079 
1081  M0_UT_ASSERT(rc == 0);
1083  M0_SET0(&rconfc);
1086  M0_UT_ASSERT(rc == 0);
1088  M0_UT_ASSERT(rc == 0);
1089  /* Open root conf object */
1090  confc = &rconfc.rc_confc;
1091  rc = m0_confc_open_sync(&root_obj, confc->cc_root, M0_FID0);
1092  M0_UT_ASSERT(rc == 0);
1093  /*
1094  * Imitate conflict for read lock, so rconfc asks its
1095  * user to put all opened conf objects.
1096  */
1097  rlx = rconfc.rc_rlock_ctx;
1100  /* Sleep to make sure rconfc wait for us */
1101  while (usleep(200) == -1);
1102  /*
1103  * Close root conf object, expecting rconfc to release
1104  * read lock and start reelection process.
1105  */
1106  m0_confc_close(root_obj);
1111 }
1112 
1113 static void test_confc_ctx_block(void)
1114 {
1115  struct m0_rconfc rconfc;
1116  struct m0_rpc_machine mach;
1117  int rc;
1118  struct m0_rpc_server_ctx rctx;
1119  struct rlock_ctx *rlx;
1120  struct m0_confc_ctx confc_ctx;
1121 
1123  M0_UT_ASSERT(rc == 0);
1124  M0_SET0(&rconfc);
1126  NULL);
1127  M0_UT_ASSERT(rc == 0);
1129  M0_UT_ASSERT(rc == 0);
1130  rlx = rconfc.rc_rlock_ctx;
1132 
1133  m0_confc_ctx_init(&confc_ctx, &rconfc.rc_confc);
1134  m0_confc_ctx_fini(&confc_ctx);
1135 
1139 }
1140 
1141 static int _skip(struct m0_confc *confc)
1142 {
1143  m0_fi_disable("on_replied", "fail_rpc_reply");
1145 }
1146 
1147 static void test_reconnect_success(void)
1148 {
1149  struct m0_rpc_machine mach;
1150  struct m0_rpc_server_ctx rctx;
1151  int rc;
1152  struct m0_rconfc rconfc;
1153  uint64_t ver;
1154  struct m0_conf_obj *cobj;
1155 
1157  M0_UT_ASSERT(rc == 0);
1159  NULL);
1160  M0_UT_ASSERT(rc == 0);
1162  M0_UT_ASSERT(rc == 0);
1164  M0_UT_ASSERT(ver == rconfc.rc_ver);
1165  /* imitate successful reconnection */
1166  m0_fi_enable_off_n_on_m("skip_confd_st_in", "force_reconnect_success",
1167  0, 1);
1168  m0_fi_enable_off_n_on_m("on_replied", "fail_rpc_reply", 0, 1);
1172  /* do regular path opening with disconnected confc */
1174  M0_CONF_ROOT_PROFILES_FID,
1176  M0_UT_ASSERT(rc == 0);
1177  m0_confc_close(cobj);
1178  m0_fi_disable("skip_confd_st_in", "force_reconnect_success");
1179  m0_fi_disable("on_replied", "fail_rpc_reply");
1183 }
1184 
1186  struct m0_fid *fid,
1187  struct m0_clink *clink)
1188 {
1189  struct m0_conf_obj *obj;
1190  struct m0_confc *phony = &rconfc->rc_phony;
1191  struct m0_conf_cache *cache = &phony->cc_cache;
1192 
1194  M0_UT_ASSERT(obj != NULL);
1195 
1196  m0_clink_add_lock(&obj->co_ha_chan, clink);
1197 }
1198 
1200  struct m0_clink clink;
1202  struct m0_fid fid;
1203 };
1204 
1205 static void _notify_cb(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1206 {
1207  struct _ha_notify_ctx *x = ast->sa_datum;
1208  struct m0_ha_note n1[] = { { x->fid, M0_NC_FAILED } };
1209  struct m0_ha_nvec nvec = { ARRAY_SIZE(n1), n1 };
1210 
1211  m0_ha_state_accept(&nvec, false);
1212 }
1213 
1214 static bool _clink_cb(struct m0_clink *link)
1215 {
1216  struct _ha_notify_ctx *x =
1217  container_of(link, struct _ha_notify_ctx, clink);
1218  struct m0_conf_obj *obj =
1219  container_of(link->cl_chan, struct m0_conf_obj, co_ha_chan);
1220 
1221  /* now make sure the signal came from the right object ... */
1222  M0_UT_ASSERT(m0_fid_eq(&x->fid, &obj->co_id));
1223  M0_UT_ASSERT(obj->co_ha_state == M0_NC_FAILED);
1224  /* ... and let the test move on */
1225  m0_semaphore_up(&x->sem);
1226  return false;
1227 }
1228 
1229 M0_UNUSED static void test_ha_notify(void)
1230 {
1231  struct m0_rpc_machine mach;
1232  struct m0_rpc_server_ctx rctx;
1233  int rc;
1234  struct m0_rconfc rconfc;
1235  struct m0_fid rm_fid = M0_FID_TINIT('s', 1, 2);
1236  struct m0_sm_ast notify_ast = {0};
1237  struct _ha_notify_ctx hnx;
1238 
1240  M0_UT_ASSERT(rc == 0);
1242  NULL);
1243  M0_UT_ASSERT(rc == 0);
1245  M0_UT_ASSERT(rc == 0);
1246  M0_UT_ASSERT(rconfc.rc_ver != 0);
1247 
1248  /* make sure rconfc is ready */
1250  /* prepare notification context */
1251  m0_semaphore_init(&hnx.sem, 0);
1252  m0_clink_init(&hnx.clink, _clink_cb);
1253  _subscribe_to_service(&rconfc, &rm_fid, &hnx.clink);
1254  hnx.fid = rm_fid;
1255 
1256  /* imitate HA note arrived from outside */
1257  notify_ast.sa_datum = &hnx;
1258  notify_ast.sa_cb = _notify_cb;
1259  m0_sm_ast_post(&m0_conf_ut_grp, &notify_ast);
1260 
1261  /* now wait for notification fired ... */
1262  m0_semaphore_down(&hnx.sem);
1263  m0_semaphore_fini(&hnx.sem);
1264  /* ... unsubscribe ... */
1265  m0_clink_del_lock(&hnx.clink);
1266  m0_clink_fini(&hnx.clink);
1267  /* ... and leave */
1273  /*
1274  * rconfc RM owner didn't return credits to creditor and now
1275  * this owner is finalised. Drop this loan on creditor side.
1276  */
1277  m0_fi_enable_once("owner_finalisation_check", "drop_loans");
1279 }
1280 
1282 
1283 static void drain_expired_cb(struct m0_rconfc *rconfc)
1284 {
1286  struct m0_conf_obj *obj;
1287 
1288  M0_UT_ENTER();
1289  if (m0_fid_is_set(&drain_fs_fid)) {
1291  M0_UT_ASSERT(obj != NULL);
1293  }
1294  M0_UT_RETURN();
1295 }
1296 
1297 static bool fs_expired(struct m0_clink *clink)
1298 {
1299  struct root_object *root_obj =
1301  struct m0_rconfc *rconfc =
1302  container_of(root_obj->confc, struct m0_rconfc, rc_confc);
1303 
1304  M0_UT_ENTER();
1306  M0_UT_RETURN();
1307 
1308  return true;
1309 }
1310 
1311 static void drain_ready_cb(struct m0_rconfc *rconfc)
1312 {
1313  M0_UT_ENTER();
1316  M0_UT_RETURN();
1317 }
1318 
1319 static bool fs_ready(struct m0_clink *clink)
1320 {
1321  struct root_object *root_obj =
1323  struct m0_rconfc *rconfc =
1324  container_of(root_obj->confc, struct m0_rconfc, rc_confc);
1325 
1326  M0_UT_ENTER();
1328  M0_UT_RETURN();
1329 
1330  return true;
1331 }
1332 
1333 static void test_drain(void)
1334 {
1335  struct m0_rpc_machine mach;
1336  int rc;
1337  struct m0_rpc_server_ctx rctx;
1338  struct rlock_ctx *rlx;
1339  struct m0_rconfc *rconfc;
1340  struct root_object root_obj;
1341 
1343  M0_UT_ASSERT(rc == 0);
1345 
1347  M0_UT_ASSERT(rc == 0);
1349  M0_UT_ASSERT(rc == 0);
1350 
1351  M0_UT_LOG("\n\n\t@reqh %p", &cctx.rcx_reqh);
1355  M0_UT_ASSERT(rc == 0);
1357  M0_UT_ASSERT(rc == 0);
1358 
1359  rc = m0_confc_root_open(&rconfc->rc_confc, &root_obj.root);
1360  M0_UT_ASSERT(rc == 0);
1361  M0_UT_ASSERT(root_obj.root->rt_mdredundancy == 1);
1362  M0_UT_ASSERT(root_obj.root->rt_obj.co_nrefs != 0);
1363  drain_fs_fid = root_obj.root->rt_obj.co_id;
1364  /*
1365  * Here we intentionally leave root object pinned simulating working
1366  * rconfc environment. It is expected to be closed later during expired
1367  * callback processing being found by fs_fid (see drain_expired_cb()).
1368  */
1369 
1370  root_obj.confc = &rconfc->rc_confc;
1371  m0_clink_init(&root_obj.clink_x, fs_expired);
1372  m0_clink_init(&root_obj.clink_r, fs_ready);
1375 
1376  /* Update conf DB version and immitate read lock conflict */
1378  rlx = rconfc->rc_rlock_ctx;
1380 
1381  /* Wait till version reelection is finished */
1383  /* Here we are to disable waiting for ready as not needed anymore */
1385 
1388  M0_TIME_NEVER);
1391 
1392  rc = m0_confc_root_open(&rconfc->rc_confc, &root_obj.root);
1393  M0_UT_ASSERT(rc == 0);
1394  M0_UT_ASSERT(root_obj.root->rt_mdredundancy == 51212);
1395  m0_confc_close(&root_obj.root->rt_obj);
1396 
1397  m0_clink_del_lock(&root_obj.clink_x);
1398  m0_clink_del_lock(&root_obj.clink_r);
1399  m0_clink_fini(&root_obj.clink_x);
1400  m0_clink_fini(&root_obj.clink_r);
1406 }
1407 
1408 static int rconfc_ut_init(void)
1409 {
1410 
1412  M0_SET0(&g_ready_sem);
1413  M0_SET0(&g_fatal_sem);
1414  ut_reqh = NULL;
1417 
1418  return m0_conf_ut_ast_thread_init();
1419 }
1420 
1421 static int rconfc_ut_fini(void)
1422 {
1423  return m0_conf_ut_ast_thread_fini();
1424 }
1425 
1427  .ts_name = "rconfc-ut",
1428  .ts_init = rconfc_ut_init,
1429  .ts_fini = rconfc_ut_fini,
1430  .ts_tests = {
1431  { "init-fini", test_init_fini },
1432  { "start-stop", test_start_stop },
1433  { "local-conf", test_start_stop_local },
1434  { "local-load-fail", test_local_load_fail },
1435  { "start-fail", test_start_failures },
1436  { "fail-abort", test_fail_abort },
1437  { "fail-retry-rm", test_fail_retry_rm },
1438  { "fail-retry-confd", test_fail_retry_confd },
1439  { "no-rms", test_no_rms },
1440  { "dead-down", test_dead_down },
1441  { "dead-stop", test_dead_stop },
1442  { "reading", test_reading },
1443  { "impossible", test_quorum_impossible },
1444  { "quorum-retry", test_quorum_retry },
1445  { "gate-ops", test_gops },
1446  { "change-ver", test_version_change },
1447  { "cache-drop", test_cache_drop },
1448  { "ctx-block", test_confc_ctx_block },
1449  { "reconnect", test_reconnect_success },
1450  /*
1451  * Temporary disabled because now rconfc entrypoint request
1452  * can't fail. Will be fixed somehow in MOTR-1774 patch.
1453  */
1454  /* { "ha-notify", test_ha_notify }, */
1455  { "test-drain", test_drain },
1456  { NULL, NULL }
1457  }
1458 };
1459 
1460 #undef M0_TRACE_SUBSYSTEM
1461 
1462 /*
1463  * Local variables:
1464  * c-indentation-style: "K&R"
1465  * c-basic-offset: 8
1466  * tab-width: 8
1467  * fill-column: 80
1468  * scroll-step: 1
1469  * End:
1470  */
#define M0_UT_ENTER(...)
Definition: ut.h:56
struct m0_fid co_id
Definition: obj.h:208
struct m0_sm rc_sm
Definition: rconfc.h:247
static struct m0_reqh * ut_reqh
Definition: rconfc.c:46
static struct ctx cc
Definition: beck.c:235
const char * rm_addr
static void _notify_cb(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: rconfc.c:1205
struct m0_tl rc_herd
Definition: rconfc.h:333
m0_rconfc_cb_t rc_fatal_cb
Definition: rconfc.h:315
static struct m0_addb2_philter p
Definition: consumer.c:40
struct m0_conf_obj * cc_root
Definition: confc.h:404
void(* rio_conflict)(struct m0_rm_incoming *in)
Definition: rm.h:1498
#define M0_PRE(cond)
struct m0_ha_entrypoint_client h_entrypoint_client
Definition: ha.h:303
struct m0_clink clink
Definition: rconfc.c:1200
M0_INTERNAL struct m0_reqh_service * m0_reqh_service_lookup(const struct m0_reqh *reqh, const struct m0_fid *fid)
Definition: reqh_service.c:551
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
static void test_quorum_retry(void)
Definition: rconfc.c:887
static void conflict_ready_cb(struct m0_rconfc *rconfc)
Definition: rconfc.c:134
#define m0_strdup(s)
Definition: string.h:43
#define M0_UT_LOG(...)
Definition: ut.h:57
struct m0_clink clink_x
Definition: rconfc.c:64
struct m0_clink rc_ha_entrypoint_cl
Definition: rconfc.h:339
char * rc_local_conf
Definition: rconfc.h:390
static void test_no_rms(void)
Definition: rconfc.c:489
M0_INTERNAL void m0_reqh_service_stop(struct m0_reqh_service *service)
Definition: reqh_service.c:402
#define NULL
Definition: misc.h:38
M0_INTERNAL void m0_clink_init(struct m0_clink *link, m0_chan_cb_t cb)
Definition: chan.c:201
M0_INTERNAL void m0_clink_del(struct m0_clink *link)
Definition: chan.c:267
static int _skip(struct m0_confc *confc)
Definition: rconfc.c:1141
M0_INTERNAL void m0_clink_del_lock(struct m0_clink *link)
Definition: chan.c:293
void(* sa_cb)(struct m0_sm_group *grp, struct m0_sm_ast *)
Definition: sm.h:506
static bool x
Definition: sm.c:168
const m0_time_t M0_TIME_NEVER
Definition: time.c:108
M0_TL_DECLARE(rpc_conn, M0_INTERNAL, struct m0_rpc_conn)
static bool fs_ready(struct m0_clink *clink)
Definition: rconfc.c:1319
static struct m0_sm_group * grp
Definition: bytecount.c:38
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
M0_INTERNAL void m0_reqh_service_prepare_to_stop(struct m0_reqh_service *service)
Definition: reqh_service.c:375
static void test_dead_down(void)
Definition: rconfc.c:608
M0_INTERNAL int m0_file_read(const char *path, char **out)
Definition: fs.c:61
const char ** hae_confd_eps
M0_INTERNAL void m0_sm_ast_post(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: sm.c:135
bool(* go_check)(struct m0_confc *confc)
Definition: confc.h:462
int m0_rpc_server_start(struct m0_rpc_server_ctx *sctx)
Definition: rpclib.c:50
uint32_t rc_ha_entrypoint_retries
Definition: rconfc.h:425
int(* go_skip)(struct m0_confc *confc)
Definition: confc.h:474
struct m0_ha * i_ha
Definition: instance.h:108
static void rconfc_ut_fatal_cb(struct m0_rconfc *rconfc)
Definition: rconfc.c:262
static void rconfc_ut_ha_state_set(const struct m0_fid *fid, uint32_t state)
Definition: rconfc.c:534
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
uint32_t rc_quorum
Definition: rconfc.h:258
static bool do_fake
Definition: rconfc.c:337
ut_confc_control
Definition: rconfc.c:568
static void test_drain(void)
Definition: rconfc.c:1333
M0_INTERNAL void m0_rconfc_stop_sync(struct m0_rconfc *rconfc)
Definition: rconfc.c:2995
struct m0_chan rh_conf_cache_ready
Definition: reqh.h:205
static void test_quorum_impossible(void)
Definition: rconfc.c:854
static struct m0_rpc_client_ctx cctx
Definition: rconfc.c:69
M0_INTERNAL enum m0_ha_entrypoint_client_state m0_ha_entrypoint_client_state_get(struct m0_ha_entrypoint_client *ecl)
Definition: entrypoint.c:829
M0_INTERNAL void m0_rconfc_fatal_cb_set(struct m0_rconfc *rconfc, m0_rconfc_cb_t cb)
Definition: rconfc.c:3067
M0_INTERNAL void m0_confc_fini(struct m0_confc *confc)
Definition: confc.c:570
M0_INTERNAL bool m0_clink_is_armed(const struct m0_clink *link)
Definition: chan.c:303
static struct m0_addb2_mach * mach
Definition: storage.c:42
struct m0_ut_suite rconfc_ut
Definition: rconfc.c:1426
#define M0_BITS(...)
Definition: misc.h:236
static bool ha_clink_cb_suppress(struct m0_clink *clink)
Definition: rconfc.c:268
struct m0_confc_gate_ops rc_gops
Definition: rconfc.h:323
static void test_gops(void)
Definition: rconfc.c:957
struct m0_tl rh_services
Definition: reqh.h:127
M0_INTERNAL struct m0 * m0_get(void)
Definition: instance.c:41
Definition: sm.h:504
uint32_t rc_sm_state_on_abort
Definition: rconfc.h:431
#define container_of(ptr, type, member)
Definition: misc.h:33
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
struct m0_semaphore gops_sem
Definition: rconfc.c:955
#define CLIENT_ENDPOINT_ADDR
Definition: common.h:32
static void drain_expired_cb(struct m0_rconfc *rconfc)
Definition: rconfc.c:1283
Definition: ut.h:77
M0_INTERNAL bool m0_fid_is_set(const struct m0_fid *fid)
Definition: fid.c:106
M0_INTERNAL void m0_ha_state_set(const struct m0_ha_nvec *note)
Definition: note.c:95
M0_INTERNAL int m0_confc_reconnect(struct m0_confc *confc, struct m0_rpc_machine *rpc_mach, const char *confd_addr)
Definition: confc.c:484
static struct foo * obj
Definition: tlist.c:302
static int rconfc_ut_fini(void)
Definition: rconfc.c:1421
struct m0_conf_root * root
Definition: rconfc.c:63
static void test_fail_abort(void)
Definition: rconfc.c:288
#define m0_tl_endfor
Definition: tlist.h:700
M0_INTERNAL int m0_sm_timedwait(struct m0_sm *mach, uint64_t states, m0_time_t deadline)
Definition: sm.c:387
struct m0_fid fid
Definition: di.c:46
static void test_init_fini(void)
Definition: rconfc.c:141
struct m0_reqh_service_type m0_confd_stype
Definition: confd.c:453
M0_INTERNAL int m0_confc_root_open(struct m0_confc *confc, struct m0_conf_root **root)
Definition: helpers.c:219
#define NAME(ext)
struct m0_reqh_context rctx
static struct m0_sm_ast ast[NR]
Definition: locality.c:44
M0_INTERNAL void m0_sm_group_unlock(struct m0_sm_group *grp)
Definition: sm.c:96
static int rconfc_ut_init(void)
Definition: rconfc.c:1408
static void _subscribe_to_service(struct m0_rconfc *rconfc, struct m0_fid *fid, struct m0_clink *clink)
Definition: rconfc.c:1185
uint64_t rc_ver
Definition: rconfc.h:253
uint64_t co_nrefs
Definition: obj.h:231
static void test_null_exp_cb(struct m0_rconfc *rconfc)
Definition: rconfc.c:118
struct m0_conf_root * root
Definition: note.c:50
int32_t nv_nr
Definition: note.h:196
void * sa_datum
Definition: sm.h:508
struct m0_confc rc_phony
Definition: rconfc.h:378
#define M0_FID_TINIT(type, container, key)
Definition: fid.h:90
static struct m0_semaphore g_fatal_sem
Definition: rconfc.c:45
#define M0_AMB(obj, ptr, field)
Definition: misc.h:320
static M0_UNUSED void test_ha_notify(void)
Definition: rconfc.c:1229
M0_INTERNAL void m0_confc_ctx_fini(struct m0_confc_ctx *ctx)
Definition: confc.c:716
M0_INTERNAL void m0_fi_disable(const char *fp_func, const char *fp_tag)
Definition: finject.c:485
struct m0_fid drain_fs_fid
Definition: rconfc.c:1281
M0_INTERNAL int m0_conf_ut_ast_thread_fini(void)
Definition: common.c:96
static void m0_fi_enable(const char *func, const char *tag)
Definition: finject.h:276
static bool _clink_cb(struct m0_clink *link)
Definition: rconfc.c:1214
#define M0_ASSERT(cond)
struct m0_rm_incoming rlc_req
static struct m0_confc * confc
Definition: file.c:94
M0_INTERNAL bool m0_mutex_is_locked(const struct m0_mutex *mutex)
Definition: mutex.c:95
static void conflict_exp_cb(struct m0_rconfc *rconfc)
Definition: rconfc.c:127
struct m0_mutex rc_herd_lock
Definition: rconfc.h:410
const char * rst_name
Definition: reqh_service.h:447
M0_TL_DESCR_DECLARE(rpc_conn, M0_EXTERN)
#define m0_streq(a, b)
Definition: string.h:34
static struct m0_semaphore g_ready_sem
Definition: rconfc.c:44
struct m0_reqh rc_reqh
Definition: setup.h:312
static bool ha_clink_cb_bad_confd(struct m0_clink *clink)
Definition: rconfc.c:407
int m0_net_xprt_nr(void)
Definition: net.c:168
M0_INTERNAL bool m0_confc_is_online(const struct m0_confc *confc)
Definition: confc.c:453
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
int m0_rpc_client_stop(struct m0_rpc_client_ctx *cctx)
Definition: rpclib.c:217
M0_INTERNAL bool m0_rconfc_is_preloaded(struct m0_rconfc *rconfc)
Definition: rconfc.c:3135
const char * confd_addr[]
struct m0_net_xprt * m0_net_xprt_default_get(void)
Definition: net.c:151
int m0_rpc_client_start(struct m0_rpc_client_ctx *cctx)
Definition: rpclib.c:160
M0_INTERNAL int m0_semaphore_init(struct m0_semaphore *semaphore, unsigned value)
Definition: semaphore.c:38
void * m0_alloc(size_t size)
Definition: memory.c:126
struct m0_sm_group * sm_grp
Definition: sm.h:321
struct m0_fid rc_profile
Definition: rconfc.h:392
static struct m0_net_domain client_net_dom
Definition: rconfc.c:47
static int m0_rconfc_start_sync(struct m0_rconfc *rconfc)
Definition: rconfc.h:502
struct m0_confc_gate_ops m0_rconfc_gate_ops
Definition: rconfc.c:566
static const struct m0_fid m0_ut_conf_fids[]
Definition: confc.h:54
uint32_t rt_mdredundancy
Definition: obj.h:405
#define SERVER_ENDPOINT
Definition: common.h:31
struct m0_chan co_ha_chan
Definition: obj.h:248
M0_INTERNAL void m0_rconfc_lock(struct m0_rconfc *rconfc)
Definition: rconfc.c:2841
struct m0_rm_incoming_ops m0_rconfc_ri_ops
Definition: rconfc.c:576
Definition: reqh.h:94
static void on_death_cb_install(struct m0_rconfc *rconfc, enum ut_confc_control ctrl)
Definition: rconfc.c:574
struct m0_sm_group m0_conf_ut_grp
Definition: common.c:32
struct m0_clink clink_r
Definition: rconfc.c:65
static bool(* ha_clink_cb_orig)(struct m0_clink *clink)
Definition: rconfc.c:50
uint64_t rt_verno
Definition: obj.h:390
#define M0_CONF_CAST(ptr, type)
Definition: obj.h:780
M0_INTERNAL bool m0_confc_is_inited(const struct m0_confc *confc)
Definition: confc.c:448
static struct m0_clink clink[RDWR_REQUEST_MAX]
static void test_reading(void)
Definition: rconfc.c:802
#define m0_confc_open_sync(result, origin,...)
Definition: confc.h:707
static bool ha_clink_cb_bad_rm(struct m0_clink *clink)
Definition: rconfc.c:338
struct m0_net_domain * rcx_net_dom
Definition: rpclib.h:128
struct m0_fid no_id
Definition: note.h:180
static bool fs_expired(struct m0_clink *clink)
Definition: rconfc.c:1297
enum m0_ha_entrypoint_control hae_control
struct m0_mutex cc_lock
Definition: confc.h:391
M0_INTERNAL int m0_conf_ut_ast_thread_init(void)
Definition: common.c:86
M0_INTERNAL void m0_rconfc_fini(struct m0_rconfc *rconfc)
Definition: rconfc.c:3009
static void test_start_stop_local(void)
Definition: rconfc.c:182
static void m0_fi_enable_off_n_on_m(const char *func, const char *tag, uint32_t n, uint32_t m)
Definition: finject.h:346
struct m0_conf_cache * d_cache
Definition: confd.h:163
static void rconfc_ut_motr_stop(struct m0_rpc_machine *mach, struct m0_rpc_server_ctx *rctx)
Definition: rconfc.c:110
M0_INTERNAL bool m0_fid_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: fid.c:164
void m0_clink_add_lock(struct m0_chan *chan, struct m0_clink *link)
Definition: chan.c:255
#define M0_UT_RETURN(...)
Definition: ut.h:58
static void test_cache_drop(void)
Definition: rconfc.c:1070
const char * ts_name
Definition: ut.h:99
M0_INTERNAL void m0_rconfc_unlock(struct m0_rconfc *rconfc)
Definition: rconfc.c:2855
struct m0_reqh reqh
Definition: rm_foms.c:48
static struct m0_fid profile
Definition: rconfc.c:49
static void _stop_rms(struct m0_rpc_machine *rmach)
Definition: rconfc.c:475
int m0_net_domain_init(struct m0_net_domain *dom, const struct m0_net_xprt *xprt)
Definition: domain.c:36
static void test_local_load_fail(void)
Definition: rconfc.c:205
static char * suffix_subst(const char *src, char delim, const char *suffix)
Definition: rconfc.c:322
Definition: fid.h:38
struct m0_confc rc_confc
Definition: rconfc.h:235
const struct m0_reqh_service_type * rs_type
Definition: reqh_service.h:227
static bool expected_fom_queued_value
Definition: rconfc.c:543
struct m0_chan rh_conf_cache_exp
Definition: reqh.h:194
struct m0_chan sm_chan
Definition: sm.h:331
M0_INTERNAL void m0_semaphore_fini(struct m0_semaphore *semaphore)
Definition: semaphore.c:45
#define M0_UT_CONF_PROCESS
Definition: misc.h:45
struct m0_net_xprt ** m0_net_all_xprt_get(void)
Definition: net.c:161
const struct m0_fid M0_CONF_ROOT_FID
Definition: root.c:226
static void test_reconnect_success(void)
Definition: rconfc.c:1147
static void test_fail_retry_confd(void)
Definition: rconfc.c:443
static struct m0_net_test_service svc
Definition: service.c:34
M0_INTERNAL void m0_clink_fini(struct m0_clink *link)
Definition: chan.c:208
static bool quorum_impossible_clink_cb(struct m0_clink *cl)
Definition: rconfc.c:831
M0_INTERNAL uint64_t m0_rconfc_ver_max_read(struct m0_rconfc *rconfc)
Definition: rconfc.c:3052
void * rc_rlock_ctx
Definition: rconfc.h:353
M0_INTERNAL void m0_reqh_idle_wait_for(struct m0_reqh *reqh, struct m0_reqh_service *service)
Definition: reqh.c:591
M0_INTERNAL void m0_sm_group_lock(struct m0_sm_group *grp)
Definition: sm.c:83
static void m0_fi_enable_once(const char *func, const char *tag)
Definition: finject.h:301
static void test_dead_stop(void)
Definition: rconfc.c:764
static void test_confc_ctx_block(void)
Definition: rconfc.c:1113
static struct m0_rconfc * rconfc(struct m0_client *m0c)
Definition: client_init.c:310
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
struct m0_rconfc rh_rconfc
Definition: reqh.h:166
void m0_rpc_server_stop(struct m0_rpc_server_ctx *sctx)
Definition: rpclib.c:85
M0_INTERNAL void m0_confc_ready_cb(struct m0_rconfc *rconfc)
Definition: helpers.c:488
struct m0_confc * confc
Definition: rconfc.c:66
#define SERVER_ENDPOINT_ADDR
Definition: common.h:30
static int rconfc_ut_motr_start(struct m0_rpc_machine *mach, struct m0_rpc_server_ctx *rctx)
Definition: rconfc.c:77
M0_INTERNAL int m0_rconfc_init(struct m0_rconfc *rconfc, const struct m0_fid *profile, struct m0_sm_group *sm_group, struct m0_rpc_machine *rmach, m0_rconfc_cb_t expired_cb, m0_rconfc_cb_t ready_cb)
Definition: rconfc.c:2860
M0_INTERNAL void m0_semaphore_down(struct m0_semaphore *semaphore)
Definition: semaphore.c:49
#define M0_UT_PATH(name)
Definition: misc.h:41
static void _on_death_cb(struct rconfc_link *lnk)
Definition: rconfc.c:548
M0_INTERNAL void m0_confc_expired_cb(struct m0_rconfc *rconfc)
Definition: helpers.c:465
M0_INTERNAL void m0_semaphore_up(struct m0_semaphore *semaphore)
Definition: semaphore.c:65
#define M0_FID0
Definition: fid.h:93
M0_INTERNAL void m0_ha_state_accept(const struct m0_ha_nvec *note, bool ignore_same_state)
Definition: note.c:189
static void drain_ready_cb(struct m0_rconfc *rconfc)
Definition: rconfc.c:1311
static struct m0_semaphore g_expired_sem
Definition: rconfc.c:43
struct m0_reqh rcx_reqh
Definition: rpclib.h:144
#define m0_tl_for(name, head, obj)
Definition: tlist.h:695
void m0_free(void *data)
Definition: memory.c:146
static struct m0_addb2_source * s
Definition: consumer.c:39
static struct m0_semaphore sem_death
Definition: rconfc.c:542
uint32_t sm_state
Definition: sm.h:307
static void test_version_change(void)
Definition: rconfc.c:1017
static struct m0_reqh_service * service[REQH_IN_UT_MAX]
Definition: long_lock_ut.c:46
struct m0_ha_entrypoint_rep ecl_rep
Definition: entrypoint.h:114
struct m0_pdclust_src_addr src
Definition: fd.c:108
struct m0_semaphore sem
Definition: rconfc.c:1201
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
struct m0_fid g_process_fid
Definition: ut.c:689
#define M0_UT_ASSERT(a)
Definition: ut.h:46
struct m0_fid fid
Definition: rconfc.c:1202
static void test_fail_retry_rm(void)
Definition: rconfc.c:374
struct m0_reqh * rm_reqh
Definition: rpc_machine.h:105
static void update_confd_version(struct m0_rpc_server_ctx *rctx, uint64_t new_ver)
Definition: rconfc.c:989
static void test_start_failures(void)
Definition: rconfc.c:226
static void test_start_stop(void)
Definition: rconfc.c:157
#define M0_UNUSED
Definition: misc.h:380
M0_INTERNAL int m0_rconfc_start_wait(struct m0_rconfc *rconfc, uint64_t timeout_ns)
Definition: rconfc.c:2942