Motr  M0
entrypoint.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2016-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 
37 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_HA
38 #include "lib/trace.h"
39 
40 #include "ha/entrypoint.h"
41 #include "ha/entrypoint_xc.h"
42 
43 #include "lib/memory.h" /* m0_free */
44 #include "lib/time.h" /* M0_TIME_IMMEDIATELY */
45 #include "lib/mutex.h" /* m0_mutex */
46 #include "lib/thread.h" /* m0_process */
47 
48 #include "fop/fom.h" /* m0_fom */
49 #include "fop/fop.h" /* m0_fop_opcode */
50 #include "fop/fom_generic.h" /* m0_rpc_item_generic_reply_rc */
51 #include "reqh/reqh_service.h" /* m0_reqh_service */
52 #include "rpc/rpc.h" /* m0_rpc_reply_post */
53 #include "rpc/rpc_opcodes.h" /* M0_HA_ENTRYPOINT_CLIENT_OPCODE */
54 #include "motr/version.h" /* m0_build_info_get */
55 
56 
57 struct m0_reqh;
58 
61  struct m0_reqh *hsv_reqh;
63  /* protects hsv_server */
65 };
66 
67 enum {
68  /* timeout for rpc_link operations */
71 };
72 
73 static struct ha_entrypoint_service *
75 {
77 }
78 
80 {
81  struct ha_entrypoint_service *he_service;
82 
84  M0_ENTRY("service=%p he_service=%p", service, he_service);
85  m0_mutex_init(&he_service->hsv_lock);
86  M0_LEAVE();
87 }
88 
90 {
91  struct ha_entrypoint_service *he_service;
92 
94  M0_ENTRY("service=%p he_service=%p", service, he_service);
95  m0_mutex_fini(&he_service->hsv_lock);
96  /* allocated in ha_entrypoint_service_allocate() */
98  M0_LEAVE();
99 }
100 
102 {
103  M0_ENTRY();
104  return M0_RC(0);
105 }
106 
108  struct m0_fop *fop)
109 {
110  M0_ENTRY();
111  return M0_RC(0);
112 }
113 
115 {
116  M0_ENTRY();
117  M0_LEAVE();
118 }
119 
122  .rso_fop_accept = ha_entrypoint_service_fop_accept,
123  .rso_stop = ha_entrypoint_service_stop,
124  .rso_fini = ha_entrypoint_service_fini,
125 };
126 
127 static int
129  const struct m0_reqh_service_type *stype);
130 
133 };
134 
136  .rst_name = "ha-entrypoint-service",
137  .rst_ops = &ha_entrypoint_stype_ops,
138  .rst_level = M0_HA_ENTRYPOINT_SVC_LEVEL,
139  .rst_keep_alive = true,
140 };
141 
142 static int
144  const struct m0_reqh_service_type *stype)
145 {
146  struct ha_entrypoint_service *he_service;
147 
148  M0_ENTRY();
150 
151  M0_ALLOC_PTR(he_service);
152  if (he_service == NULL)
153  return M0_RC(-ENOMEM);
154 
156  *service = &he_service->hsv_service;
157  (*service)->rs_ops = &ha_entrypoint_service_ops;
158 
159  return M0_RC(0);
160 }
161 
163  struct m0_fom esf_gen;
167  uint64_t esf_magic;
168 };
169 
171  [M0_HES_INIT] = {
173  .sd_name = "M0_HES_INIT",
174  .sd_allowed = M0_BITS(M0_HES_REPLY_WAIT),
175  },
176  [M0_HES_REPLY_WAIT] = {
177  .sd_flags = 0,
178  .sd_name = "M0_HES_REPLY_WAIT",
179  .sd_allowed = M0_BITS(M0_HES_FINI),
180  },
181  [M0_HES_FINI] = {
182  .sd_flags = M0_SDF_TERMINAL,
183  .sd_name = "M0_HES_FINI",
184  .sd_allowed = 0,
185  },
186 };
187 
189  .scf_name = "entrypoint server fom",
191  .scf_state = ha_entrypoint_server_fom_states,
192 };
193 
194 /*
195  * TODO Either move the service to another file or make these functions static.
196  */
198  struct m0_reqh *reqh)
199 {
200  M0_ENTRY("reqh=%p", reqh);
203  reqh, NULL, NULL));
204 }
205 
206 M0_INTERNAL void
208 {
209  M0_ENTRY();
210  m0_reqh_service_quit(he_service);
211  M0_LEAVE();
212 }
213 
214 M0_TL_DESCR_DEFINE(hes_req, "m0_ha_entrypoint_server::hes_requests", static,
215  struct ha_entrypoint_server_fom, esf_tlink, esf_magic,
216  10, 11);
217 M0_TL_DEFINE(hes_req, static, struct ha_entrypoint_server_fom);
218 
219 M0_INTERNAL int
221  struct m0_ha_entrypoint_server_cfg *hes_cfg)
222 {
223  hes->hes_cfg = *hes_cfg;
224  hes_req_tlist_init(&hes->hes_requests);
225  hes->hes_next_id = (struct m0_uint128){
226  .u_hi = 0,
227  .u_lo = 1,
228  };
229  m0_mutex_init(&hes->hes_lock);
230  return 0;
231 }
232 
233 M0_INTERNAL void
235 {
236  m0_mutex_fini(&hes->hes_lock);
237  hes_req_tlist_fini(&hes->hes_requests);
238 }
239 
240 M0_INTERNAL void
242 {
243  struct ha_entrypoint_service *he_service;
244  int rc;
245 
246  M0_ENTRY();
248  hes->hes_cfg.hesc_reqh);
249  M0_ASSERT(rc == 0);
251  m0_mutex_lock(&he_service->hsv_lock);
252  he_service->hsv_server = hes;
253  m0_mutex_unlock(&he_service->hsv_lock);
254  M0_LEAVE();
255 }
256 
257 M0_INTERNAL void
259 {
261 }
262 
263 static struct ha_entrypoint_server_fom *
265  const struct m0_uint128 *req_id)
266 {
267  struct ha_entrypoint_server_fom *server_fom;
268 
269  M0_ENTRY("hes=%p req_id="U128X_F, hes, U128_P(req_id));
270  m0_mutex_lock(&hes->hes_lock);
271  server_fom = m0_tl_find(hes_req, server_fom1, &hes->hes_requests,
272  m0_uint128_eq(&server_fom1->esf_req_id, req_id));
273  m0_mutex_unlock(&hes->hes_lock);
274  M0_LEAVE("hes=%p server_fom=%p req_id="U128X_F,
275  hes, server_fom, U128_P(req_id));
276  return server_fom;
277 }
278 
279 static void
281  struct ha_entrypoint_server_fom *server_fom)
282 {
283  M0_ENTRY("hes=%p server_fom=%p", hes, server_fom);
284  m0_mutex_lock(&hes->hes_lock);
285  server_fom->esf_req_id = hes->hes_next_id;
286  ++hes->hes_next_id.u_lo;
287  hes_req_tlist_add_tail(&hes->hes_requests, server_fom);
288  m0_mutex_unlock(&hes->hes_lock);
289  M0_LEAVE("hes=%p server_fom=%p esf_req_id="U128X_F,
290  hes, server_fom, U128_P(&server_fom->esf_req_id));
291 }
292 
293 static void
295  struct ha_entrypoint_server_fom *server_fom)
296 {
297  M0_ENTRY("hes=%p server_fom=%p esf_req_id="U128X_F,
298  hes, server_fom, U128_P(&server_fom->esf_req_id));
299  m0_mutex_lock(&hes->hes_lock);
300  hes_req_tlist_del(server_fom);
301  m0_mutex_unlock(&hes->hes_lock);
302  M0_LEAVE("hes=%p server_fom=%p", hes, server_fom);
303 }
304 
305 M0_INTERNAL void
307  const struct m0_uint128 *req_id,
308  const struct m0_ha_entrypoint_rep *rep)
309 {
310  struct ha_entrypoint_server_fom *server_fom;
311  struct m0_fom *fom;
312  int rc;
313 
314  server_fom = ha_entrypoint_server_find(hes, req_id);
315  fom = &server_fom->esf_gen;
316  rc = m0_ha_entrypoint_rep2fop(rep, m0_fop_data(fom->fo_rep_fop));
317  M0_ASSERT(rc == 0);
319 }
320 
321 M0_INTERNAL const struct m0_ha_entrypoint_req *
323  const struct m0_uint128 *req_id)
324 {
325  return M0_MEMBER_PTR(ha_entrypoint_server_find(hes, req_id), esf_req);
326 }
327 
329  [M0_HEC_INIT] = {
331  .sd_name = "M0_HEC_INIT",
332  .sd_allowed = M0_BITS(M0_HEC_STOPPED),
333  },
334  [M0_HEC_STOPPED] = {
335  .sd_flags = 0,
336  .sd_name = "M0_HEC_STOPPED",
337  .sd_allowed = M0_BITS(M0_HEC_UNAVAILABLE, M0_HEC_FINI),
338  },
339  [M0_HEC_UNAVAILABLE] = {
340  .sd_flags = 0,
341  .sd_name = "M0_HEC_UNAVAILABLE",
342  .sd_allowed = M0_BITS(M0_HEC_CONNECT, M0_HEC_STOPPED,
344  },
345  [M0_HEC_CONNECT] = {
346  .sd_flags = 0,
347  .sd_name = "M0_HEC_CONNECT",
348  .sd_allowed = M0_BITS(M0_HEC_CONNECT_WAIT),
349  },
350  [M0_HEC_CONNECT_WAIT] = {
351  .sd_flags = 0,
352  .sd_name = "M0_HEC_CONNECT_WAIT",
353  .sd_allowed = M0_BITS(M0_HEC_FILL, M0_HEC_UNAVAILABLE),
354  },
355  [M0_HEC_FILL] = {
356  .sd_flags = 0,
357  .sd_name = "M0_HEC_FILL",
358  .sd_allowed = M0_BITS(M0_HEC_SEND),
359  },
360  [M0_HEC_SEND] = {
361  .sd_flags = 0,
362  .sd_name = "M0_HEC_SEND",
363  .sd_allowed = M0_BITS(M0_HEC_SEND_WAIT),
364  },
365  [M0_HEC_SEND_WAIT] = {
366  .sd_flags = 0,
367  .sd_name = "M0_HEC_SEND_WAIT",
368  .sd_allowed = M0_BITS(M0_HEC_DISCONNECT),
369  },
370  [M0_HEC_DISCONNECT] = {
371  .sd_flags = 0,
372  .sd_name = "M0_HEC_DISCONNECT",
373  .sd_allowed = M0_BITS(M0_HEC_DISCONNECT_WAIT),
374  },
376  .sd_flags = 0,
377  .sd_name = "M0_HEC_DISCONNECT_WAIT",
379  },
380  [M0_HEC_AVAILABLE] = {
381  .sd_flags = 0,
382  .sd_name = "M0_HEC_AVAILABLE",
383  .sd_allowed = M0_BITS(M0_HEC_UNAVAILABLE, M0_HEC_STOPPED),
384  },
385  [M0_HEC_FINI] = {
386  .sd_flags = M0_SDF_TERMINAL,
387  .sd_name = "M0_HEC_FINI",
388  .sd_allowed = 0,
389  },
390 };
391 
393  .scf_name = "m0_ha_entrypoint_client::ecl_sm",
394  .scf_nr_states = ARRAY_SIZE(ha_entrypoint_client_states),
395  .scf_state = ha_entrypoint_client_states,
396 };
397 
398 enum {
401 };
402 
404  [HEC_FOM_INIT] = {
406  .sd_name = "HEC_FOM_INIT",
407  .sd_allowed = M0_BITS(HEC_FOM_FINI),
408  },
409  [HEC_FOM_FINI] = {
410  .sd_flags = M0_SDF_TERMINAL,
411  .sd_name = "HEC_FOM_FINI",
412  .sd_allowed = 0,
413  },
414 };
415 
417  .scf_name = "entrypoint client fom",
419  .scf_state = ha_entrypoint_client_fom_states,
420 };
421 
423 {
424  struct m0_ha_entrypoint_client *ecl;
425 
428  m0_fom_wakeup(&ecl->ecl_fom);
429 
430  return true;
431 }
432 
433 M0_INTERNAL int
435  const char *ep,
437 {
438  int rc;
439 
440  ecl->ecl_cfg = *ecl_cfg;
443  if (rc == 0) {
446  ecl->ecl_rlink_wait.cl_is_oneshot = true;
450  M0_HEC_INIT, &ecl->ecl_sm_group);
451  ecl->ecl_reply = NULL;
452  M0_SET0(&ecl->ecl_fom);
453  M0_SET0(&ecl->ecl_req_fop);
454  ecl->ecl_fom_running = false;
456  ecl->ecl_stopping = false;
459  }
460  return M0_RC(rc);
461 }
462 
463 M0_INTERNAL void
465 {
468  m0_sm_fini(&ecl->ecl_sm);
474 }
475 
477 {
478  struct m0_fop *fop = m0_rpc_item_to_fop(item);
479  struct m0_ha_entrypoint_client *ecl = fop->f_opaque;
480  int rc;
481 
482  M0_ENTRY();
483  M0_PRE(ecl->ecl_reply == NULL);
484 
486  if (rc == 0) {
488  ecl->ecl_reply = item->ri_reply;
489  }
490  /* XXX TODO Handle rpc errors. */
491  m0_fom_wakeup(&ecl->ecl_fom);
493 
494  M0_LEAVE("rc=%d", rc);
495 }
496 
499 };
500 
501 static void ha_entrypoint_client_fop_release(struct m0_ref *ref)
502 {
503  struct m0_fop *fop;
504 
505  M0_ENTRY();
506  M0_PRE(ref != NULL);
507  fop = container_of(ref, struct m0_fop, f_ref);
508  fop->f_data.fd_data = NULL;
509  m0_fop_fini(fop);
510  M0_SET0(fop);
511  M0_LEAVE();
512 }
513 
515 {
517  enum m0_ha_entrypoint_client_state next_state;
518  struct m0_ha_entrypoint_req_fop *req_fop_data;
519  struct m0_rpc_item *item;
520  struct m0_fop *fop;
521  m0_time_t deadline;
522  bool stopping;
523  struct m0_ha_entrypoint_client *ecl = M0_AMB(ecl, fom, ecl_fom);
524  int rc = 0;
525 
526  M0_ENTRY();
527 
529  state = ecl->ecl_sm.sm_state;
530  stopping = ecl->ecl_stopping;
532  M0_LOG(M0_DEBUG, "state=%s", m0_sm_state_name(&ecl->ecl_sm, state));
533 
534  switch (state) {
535  case M0_HEC_AVAILABLE:
536  next_state = M0_HEC_UNAVAILABLE;
537  rc = M0_FSO_AGAIN;
538  break;
539 
540  case M0_HEC_UNAVAILABLE:
541  if (stopping) {
543  return M0_RC(M0_FSO_WAIT);
544  }
545  next_state = M0_HEC_CONNECT;
546  rc = M0_FSO_AGAIN;
547  break;
548 
549  case M0_HEC_CONNECT:
553  &ecl->ecl_rlink_wait);
554  next_state = M0_HEC_CONNECT_WAIT;
555  rc = M0_FSO_WAIT;
556  break;
557 
558  case M0_HEC_CONNECT_WAIT:
559  if (ecl->ecl_rlink.rlk_rc == 0) {
560  next_state = M0_HEC_FILL;
561  } else {
562  next_state = M0_HEC_UNAVAILABLE;
563  M0_LOG(M0_WARN, "rlk_rc=%d", ecl->ecl_rlink.rlk_rc);
564  }
565  rc = M0_FSO_AGAIN;
566  break;
567 
568  case M0_HEC_FILL:
569  /*
570  * TODO XXX make M0_HEC_FILL state asynchronous - user should
571  * call some function before client transitions to the WAIT
572  * state. It would be similar to
573  * m0_ha_entrypoint_server_reply().
574  */
575 
578  ecl->ecl_req.heq_pid = m0_process();
579  next_state = M0_HEC_SEND;
580  rc = M0_FSO_AGAIN;
581  break;
582 
583  case M0_HEC_SEND:
584  ecl->ecl_send_error = false;
585  req_fop_data = &ecl->ecl_req_fop_data;
586  M0_SET0(req_fop_data);
587  rc = m0_ha_entrypoint_req2fop(&ecl->ecl_req, req_fop_data);
588  M0_ASSERT(rc == 0);
589  fop = &ecl->ecl_req_fop;
593  fop->f_data.fd_data = req_fop_data;
594  item = &fop->f_item;
600  fop->f_opaque = ecl;
601  next_state = M0_HEC_SEND_WAIT;
603  break;
604 
605  case M0_HEC_SEND_WAIT:
606  item = ecl->ecl_reply;
607  if (item == NULL) {
608  M0_LOG(M0_DEBUG, "RPC error occured, resending fop");
609  ecl->ecl_send_error = true;
610  next_state = M0_HEC_DISCONNECT;
611  rc = M0_FSO_AGAIN;
612  break;
613  }
618  &ecl->ecl_rep);
619  M0_ASSERT_INFO(rc == 0, "rc=%d", rc);
621  ecl->ecl_reply = NULL;
622  next_state = M0_HEC_DISCONNECT;
623  rc = M0_FSO_AGAIN;
624  break;
625 
626  case M0_HEC_DISCONNECT:
627  deadline = stopping || ecl->ecl_send_error ?
630  m0_rpc_link_disconnect_async(&ecl->ecl_rlink, deadline,
631  &ecl->ecl_rlink_wait);
632  next_state = M0_HEC_DISCONNECT_WAIT;
633  rc = M0_FSO_WAIT;
634  break;
635 
637  if (ecl->ecl_send_error) {
638  next_state = M0_HEC_UNAVAILABLE;
639  rc = M0_FSO_AGAIN;
640  break;
641  }
642  /* transit to M0_HEC_AVAILABLE in the fom fini callback */
644  return M0_RC(M0_FSO_WAIT);
645 
646  default:
647  M0_IMPOSSIBLE("Unexpected state: %d", state);
648  }
649 
650  M0_LOG(M0_DEBUG, "%s -> %s",
651  m0_sm_state_name(&ecl->ecl_sm, state),
652  m0_sm_state_name(&ecl->ecl_sm, next_state));
654  M0_ASSERT(ecl->ecl_sm.sm_state == state);
655  m0_sm_state_set(&ecl->ecl_sm, next_state);
657 
658  M0_POST(M0_IN(rc, (M0_FSO_AGAIN, M0_FSO_WAIT)));
659  return M0_RC(rc);
660 }
661 
663 {
665  struct m0_ha_entrypoint_client *ecl =
667 
668  M0_ENTRY();
669 
670  m0_fom_fini(fom);
671  M0_SET0(fom);
673  ecl->ecl_fom_running = false;
676  state = ecl->ecl_sm.sm_state;
678  if (state == M0_HEC_DISCONNECT_WAIT) {
679  M0_LOG(M0_DEBUG, "M0_HEC_DISCONNECT_WAIT -> M0_HEC_AVAILABLE");
681  } else {
682  /* to signal with ecl_fom_running == false */
684  }
686 
687  M0_LEAVE();
688 }
689 
690 static size_t ha_entrypoint_client_fom_locality(const struct m0_fom *fom)
691 {
692  return 0;
693 }
694 
696 
698  .fto_create = NULL,
699 };
700 
704  .fo_home_locality = ha_entrypoint_client_fom_locality,
705 };
706 
707 M0_INTERNAL void
709 {
710  M0_ENTRY();
711 
713  if (!ecl->ecl_fom_running) {
714  ecl->ecl_fom_running = true;
715  M0_ASSERT_EX(M0_IS0(&ecl->ecl_fom));
718  ecl->ecl_cfg.hecc_reqh);
719  m0_fom_queue(&ecl->ecl_fom);
720  }
722 
723  M0_LEAVE();
724 }
725 
726 M0_INTERNAL void
728 {
729  M0_ENTRY();
731  ecl->ecl_stopping = false;
735  M0_LEAVE();
736 }
737 
739 {
740  struct m0_ha_entrypoint_client *ecl =
742 
744  M0_ENTRY("state=%s",
745  m0_sm_state_name(&ecl->ecl_sm, ecl->ecl_sm.sm_state));
746 
747  if (ecl->ecl_sm.sm_state == M0_HEC_AVAILABLE) {
748  /* let m0_chan_wait wake up */
749  return false;
750  }
751  return true;
752 }
753 
755 {
756  struct m0_ha_entrypoint_client *ecl =
758  bool consumed;
759 
761  M0_ENTRY("state=%s",
762  m0_sm_state_name(&ecl->ecl_sm, ecl->ecl_sm.sm_state));
763 
765  consumed = ecl->ecl_fom_running;
767 
768  return consumed;
769 }
770 
771 M0_INTERNAL void
773 {
774  M0_ENTRY();
778  m0_chan_wait(&ecl->ecl_clink);
780  m0_clink_fini(&ecl->ecl_clink);
781  M0_LEAVE();
782 }
783 
784 M0_INTERNAL void
786 {
787  bool fom_running;
788 
789  M0_ENTRY();
790 
791  /* wait for fom */
793  fom_running = ecl->ecl_fom_running;
796  ecl->ecl_stopping = true;
797  if (fom_running) {
798  m0_clink_init(&ecl->ecl_clink,
801  &ecl->ecl_clink);
802  }
804  if (fom_running) {
805  m0_chan_wait(&ecl->ecl_clink);
807  m0_clink_fini(&ecl->ecl_clink);
808  }
809 
812  M0_ASSERT(!ecl->ecl_fom_running);
814  if (ecl->ecl_reply != NULL)
816  ecl->ecl_reply = NULL;
818 
819  M0_LEAVE();
820 }
821 
822 M0_INTERNAL struct m0_chan *
824 {
825  return &ecl->ecl_sm.sm_chan;
826 }
827 
828 M0_INTERNAL enum m0_ha_entrypoint_client_state
830 {
832  return ecl->ecl_sm.sm_state;
833 }
834 
835 M0_INTERNAL int m0_ha_entrypoint_mod_init(void)
836 {
837  int rc;
838 
840  M0_ASSERT(rc == 0);
847  return 0;
848 }
849 
850 M0_INTERNAL void m0_ha_entrypoint_mod_fini(void)
851 {
854 }
855 
856 static size_t ha_entrypoint_home_locality(const struct m0_fom *fom)
857 {
858  return 0;
859 }
860 
861 static void ha_entrypoint_fom_fini(struct m0_fom *fom)
862 {
863  struct ha_entrypoint_server_fom *server_fom;
864 
865  server_fom = container_of(fom, struct ha_entrypoint_server_fom,
866  esf_gen);
867  hes_req_tlink_fini(server_fom);
868  m0_fom_fini(fom);
869  m0_free(server_fom);
870 }
871 
873 {
874  struct ha_entrypoint_server_fom *server_fom;
875  struct m0_ha_entrypoint_server *hes;
876  struct ha_entrypoint_service *he_service;
877  int rc;
878 
879  he_service = ha_entrypoint_service_container(fom->fo_service);
880  M0_ENTRY("fom=%p he_service=%p", fom, he_service);
881 
882  m0_mutex_lock(&he_service->hsv_lock);
883  hes = he_service->hsv_server;
884  m0_mutex_unlock(&he_service->hsv_lock);
885 
886  M0_ASSERT(hes != NULL); /* XXX handle it, reply -EBUSY */
888 
889  server_fom = container_of(fom, struct ha_entrypoint_server_fom,
890  esf_gen);
891  if (m0_fom_phase(fom) == M0_HES_INIT) {
893 
895  m0_rpc_item_remote_ep_addr(&fom->fo_fop->f_item),
896  &server_fom->esf_req);
897  M0_ASSERT(rc == 0);
898  ha_entrypoint_server_register(hes, server_fom);
899  hes->hes_cfg.hesc_request_received(hes, &server_fom->esf_req,
900  &server_fom->esf_req_id);
901  M0_LEAVE();
902  return M0_FSO_WAIT;
903  } else {
904  ha_entrypoint_server_deregister(hes, server_fom);
905  m0_ha_entrypoint_req_free(&server_fom->esf_req);
906  m0_rpc_reply_post(&fom->fo_fop->f_item,
907  &fom->fo_rep_fop->f_item);
909  }
910  M0_LEAVE();
911  return M0_FSO_WAIT;
912 }
913 
916  .fo_fini = ha_entrypoint_fom_fini,
917  .fo_home_locality = ha_entrypoint_home_locality,
918 };
919 
921  struct m0_fom **m,
922  struct m0_reqh *reqh)
923 {
924  struct ha_entrypoint_server_fom *server_fom;
926  struct m0_fom *fom;
927 
928  M0_PRE(fop != NULL);
929  M0_PRE(m != NULL);
930 
931  M0_ALLOC_PTR(server_fom);
932  if (server_fom == NULL)
933  return M0_ERR(-ENOMEM);
934 
936  if (reply == NULL){
937  m0_free(server_fom);
938  return M0_ERR(-ENOMEM);
939  }
940 
941  fom = &server_fom->esf_gen;
944  if (fom->fo_rep_fop == NULL) {
945  m0_free(reply);
946  m0_free(server_fom);
947  return M0_ERR(-ENOMEM);
948  }
949 
951  fop, fom->fo_rep_fop, reqh);
952 
953  hes_req_tlink_init(server_fom);
954 
955  *m = &server_fom->esf_gen;
956  return M0_RC(0);
957 }
958 
961 };
962 
963 #undef M0_TRACE_SUBSYSTEM
964 
967 /*
968  * Local variables:
969  * c-indentation-style: "K&R"
970  * c-basic-offset: 8
971  * tab-width: 8
972  * fill-column: 80
973  * scroll-step: 1
974  * End:
975  */
976 /*
977  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
978  */
void * fd_data
Definition: fop.h:75
struct m0_fid heq_process_fid
M0_INTERNAL uint64_t m0_process(void)
Definition: kthread.c:295
static int ha_entrypoint_service_start(struct m0_reqh_service *service)
Definition: entrypoint.c:101
M0_INTERNAL int m0_rpc_post(struct m0_rpc_item *item)
Definition: rpc.c:63
struct m0_mutex ecl_fom_running_lock
Definition: entrypoint.h:118
static void ha_entrypoint_service_stop(struct m0_reqh_service *service)
Definition: entrypoint.c:114
M0_INTERNAL void m0_chan_wait(struct m0_clink *link)
Definition: chan.c:336
struct m0_reqh_service hsv_service
Definition: entrypoint.c:60
M0_INTERNAL void m0_fom_wakeup(struct m0_fom *fom)
Definition: fom.c:532
#define M0_PRE(cond)
struct m0_fom esf_gen
Definition: entrypoint.c:163
M0_INTERNAL const struct m0_ha_entrypoint_req * m0_ha_entrypoint_server_request_find(struct m0_ha_entrypoint_server *hes, const struct m0_uint128 *req_id)
Definition: entrypoint.c:322
static int ha_entrypoint_get_fom_tick(struct m0_fom *fom)
Definition: entrypoint.c:872
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
int(* rso_start)(struct m0_reqh_service *service)
Definition: reqh_service.h:360
M0_TL_DEFINE(hes_req, static, struct ha_entrypoint_server_fom)
enum m0_rpc_item_priority ri_prio
Definition: item.h:133
struct m0_ha_entrypoint_req_fop ecl_req_fop_data
Definition: entrypoint.h:113
#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
static struct m0_addb2_mach * m
Definition: consumer.c:38
M0_INTERNAL void m0_clink_del_lock(struct m0_clink *link)
Definition: chan.c:293
struct m0_tlink esf_tlink
Definition: entrypoint.c:166
Definition: sm.h:350
int(* fo_tick)(struct m0_fom *fom)
Definition: fom.h:663
M0_INTERNAL bool m0_uint128_eq(const struct m0_uint128 *u0, const struct m0_uint128 *u1)
Definition: misc.c:39
M0_INTERNAL void m0_fop_init(struct m0_fop *fop, struct m0_fop_type *fopt, void *data, void(*fop_release)(struct m0_ref *))
Definition: fop.c:79
void m0_rpc_item_put(struct m0_rpc_item *item)
Definition: item.c:443
uint64_t m0_time_t
Definition: time.h:37
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
M0_INTERNAL void m0_ha_entrypoint_server_start(struct m0_ha_entrypoint_server *hes)
Definition: entrypoint.c:241
struct m0_fid hecc_process_fid
Definition: entrypoint.h:104
static struct m0_sm_state_descr ha_entrypoint_server_fom_states[]
Definition: entrypoint.c:170
int(* fto_create)(struct m0_fop *fop, struct m0_fom **out, struct m0_reqh *reqh)
Definition: fom.h:650
void m0_rpc_item_get(struct m0_rpc_item *item)
Definition: item.c:434
M0_INTERNAL void m0_ha_entrypoint_mod_fini(void)
Definition: entrypoint.c:850
struct m0_ha_entrypoint_server * hsv_server
Definition: entrypoint.c:62
M0_INTERNAL void m0_ha_entrypoint_client_stop(struct m0_ha_entrypoint_client *ecl)
Definition: entrypoint.c:785
struct m0_ha_entrypoint_client_cfg ecl_cfg
Definition: entrypoint.h:108
static bool ha_entrypoint_client_rlink_cb(struct m0_clink *clink)
Definition: entrypoint.c:422
void * m0_fop_data(const struct m0_fop *fop)
Definition: fop.c:220
M0_INTERNAL int m0_ha_entrypoint_fop2req(const struct m0_ha_entrypoint_req_fop *req_fop, const char *rpc_endpoint, struct m0_ha_entrypoint_req *req)
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 const char * m0_sm_state_name(const struct m0_sm *mach, int state)
Definition: sm.c:781
static struct m0_fom_type ha_entrypoint_client_fom_type
Definition: entrypoint.c:695
static struct m0_sm_state_descr ha_entrypoint_client_fom_states[]
Definition: entrypoint.c:403
static bool ha_entrypoint_client_stop_check(struct m0_clink *clink)
Definition: entrypoint.c:754
const struct m0_fom_ops ha_entrypoint_get_fom_ops
Definition: entrypoint.c:914
#define M0_BITS(...)
Definition: misc.h:236
static const struct m0_reqh_service_type_ops ha_entrypoint_stype_ops
Definition: entrypoint.c:131
static int ha_entrypoint_service_fop_accept(struct m0_reqh_service *service, struct m0_fop *fop)
Definition: entrypoint.c:107
#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
M0_INTERNAL void m0_ha_entrypoint_client_request(struct m0_ha_entrypoint_client *ecl)
Definition: entrypoint.c:708
M0_INTERNAL void m0_ha_entrypoint_service_fini(struct m0_reqh_service *he_service)
Definition: entrypoint.c:207
static struct m0_rpc_item_ops ha_entrypoint_client_item_ops
Definition: entrypoint.c:497
#define M0_MEMBER_PTR(ptr, member)
Definition: misc.h:323
M0_INTERNAL void m0_ha_entrypoint_server_reply(struct m0_ha_entrypoint_server *hes, const struct m0_uint128 *req_id, const struct m0_ha_entrypoint_rep *rep)
Definition: entrypoint.c:306
static bool ha_entrypoint_client_start_check(struct m0_clink *clink)
Definition: entrypoint.c:738
static struct m0_rpc_item * item
Definition: item.c:56
struct m0_fop_getxattr_rep * rep
Definition: dir.c:455
static size_t ha_entrypoint_home_locality(const struct m0_fom *fom)
Definition: entrypoint.c:856
M0_INTERNAL void m0_sm_group_fini(struct m0_sm_group *grp)
Definition: sm.c:65
int m0_reqh_service_type_register(struct m0_reqh_service_type *rstype)
Definition: reqh_service.c:473
m0_fom_phase
Definition: fom.h:372
static struct m0_sm_state_descr ha_entrypoint_client_states[]
Definition: entrypoint.c:328
struct m0_fom_type ft_fom_type
Definition: fop.h:232
struct m0_fop_type m0_ha_entrypoint_rep_fopt
struct m0_reqh * hecc_reqh
Definition: entrypoint.h:102
static struct m0_sm_conf ha_entrypoint_client_fom_states_conf
Definition: entrypoint.c:416
return M0_RC(rc)
struct m0_fop_type m0_ha_entrypoint_req_fopt
Definition: sock.c:754
#define M0_ASSERT_EX(cond)
#define M0_ENTRY(...)
Definition: trace.h:170
struct m0_fop ecl_req_fop
Definition: entrypoint.h:112
M0_INTERNAL void m0_sm_group_unlock(struct m0_sm_group *grp)
Definition: sm.c:96
void m0_fom_init(struct m0_fom *fom, const struct m0_fom_type *fom_type, const struct m0_fom_ops *ops, struct m0_fop *fop, struct m0_fop *reply, struct m0_reqh *reqh)
Definition: fom.c:1372
struct m0_fop_type * f_type
Definition: fop.h:81
M0_INTERNAL int m0_ha_entrypoint_mod_init(void)
Definition: entrypoint.c:835
struct m0_rpc_machine * m0_fop_rpc_machine(const struct m0_fop *fop)
Definition: fop.c:360
return M0_ERR(-EOPNOTSUPP)
const struct m0_build_info * m0_build_info_get(void)
Definition: version.c:61
M0_INTERNAL int m0_ha_entrypoint_req2fop(const struct m0_ha_entrypoint_req *req, struct m0_ha_entrypoint_req_fop *req_fop)
static void ha_entrypoint_fom_fini(struct m0_fom *fom)
Definition: entrypoint.c:861
M0_INTERNAL int m0_ha_entrypoint_server_init(struct m0_ha_entrypoint_server *hes, struct m0_ha_entrypoint_server_cfg *hes_cfg)
Definition: entrypoint.c:220
#define M0_AMB(obj, ptr, field)
Definition: misc.h:320
Definition: refs.h:34
static const struct socktype stype[]
Definition: sock.c:1156
M0_INTERNAL void m0_ha_entrypoint_fops_init(void)
void m0_fom_fini(struct m0_fom *fom)
Definition: fom.c:1324
struct m0_rpc_item * ecl_reply
Definition: entrypoint.h:123
static const struct m0_reqh_service_ops ha_entrypoint_service_ops
Definition: entrypoint.c:120
#define M0_ASSERT(cond)
const char * scf_name
Definition: sm.h:352
struct m0_mutex hes_lock
Definition: entrypoint.h:83
M0_INTERNAL void m0_reqh_service_quit(struct m0_reqh_service *svc)
Definition: reqh_service.c:588
M0_INTERNAL void m0_sm_group_init(struct m0_sm_group *grp)
Definition: sm.c:53
M0_INTERNAL void m0_ha_entrypoint_server_fini(struct m0_ha_entrypoint_server *hes)
Definition: entrypoint.c:234
#define U128_P(x)
Definition: types.h:45
M0_INTERNAL int m0_ha_entrypoint_client_init(struct m0_ha_entrypoint_client *ecl, const char *ep, struct m0_ha_entrypoint_client_cfg *ecl_cfg)
Definition: entrypoint.c:434
void m0_sm_state_set(struct m0_sm *mach, int state)
Definition: sm.c:478
const char * rst_name
Definition: reqh_service.h:447
struct m0_sm_group ecl_sm_group
Definition: entrypoint.h:122
void m0_fom_phase_move(struct m0_fom *fom, int32_t rc, int phase)
Definition: fom.c:1699
struct m0_ha_entrypoint_req ecl_req
Definition: entrypoint.h:111
M0_INTERNAL void m0_fom_type_init(struct m0_fom_type *type, uint64_t id, const struct m0_fom_type_ops *ops, const struct m0_reqh_service_type *svc_type, const struct m0_sm_conf *sm)
Definition: fom.c:1596
static int ha_entrypoint_client_fom_tick(struct m0_fom *fom)
Definition: entrypoint.c:514
uint64_t u_hi
Definition: types.h:36
struct m0_rpc_item * ri_reply
Definition: item.h:163
struct m0_tl hes_requests
Definition: entrypoint.h:80
static void ha_entrypoint_client_replied(struct m0_rpc_item *item)
Definition: entrypoint.c:476
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
static void ha_entrypoint_client_fom_fini(struct m0_fom *fom)
Definition: entrypoint.c:662
const char * bi_git_rev_id
Definition: version.h:34
void * f_opaque
Definition: fop.h:84
#define M0_POST(cond)
struct m0_reqh * hesc_reqh
Definition: entrypoint.h:69
static const struct m0_fom_ops ha_entrypoint_client_fom_ops
Definition: entrypoint.c:701
Definition: reqh.h:94
Definition: dump.c:103
Definition: chan.h:229
M0_INTERNAL int m0_ha_entrypoint_rep2fop(const struct m0_ha_entrypoint_rep *rep, struct m0_ha_entrypoint_rep_fop *rep_fop)
static size_t ha_entrypoint_client_fom_locality(const struct m0_fom *fom)
Definition: entrypoint.c:690
void m0_rpc_reply_post(struct m0_rpc_item *request, struct m0_rpc_item *reply)
Definition: rpc.c:135
M0_INTERNAL void m0_fop_fini(struct m0_fop *fop)
Definition: fop.c:136
struct m0_reqh_service * hes_he_service
Definition: entrypoint.h:79
static struct m0_clink clink[RDWR_REQUEST_MAX]
M0_INTERNAL int m0_reqh_service_setup(struct m0_reqh_service **out, struct m0_reqh_service_type *stype, struct m0_reqh *reqh, struct m0_reqh_context *rctx, const struct m0_fid *fid)
Definition: reqh_service.c:565
struct m0_clink ecl_rlink_wait
Definition: entrypoint.h:110
void(* hesc_request_received)(struct m0_ha_entrypoint_server *hes, const struct m0_ha_entrypoint_req *req, const struct m0_uint128 *req_id)
Definition: entrypoint.h:72
M0_INTERNAL int m0_ha_entrypoint_fop2rep(const struct m0_ha_entrypoint_rep_fop *rep_fop, struct m0_ha_entrypoint_rep *rep)
struct m0_reqh_service_type m0_ha_entrypoint_service_type
Definition: entrypoint.c:135
struct m0_ha_entrypoint_server_cfg hes_cfg
Definition: entrypoint.h:78
#define U128X_F
Definition: types.h:42
void(* rio_replied)(struct m0_rpc_item *item)
Definition: item.h:300
void m0_clink_add_lock(struct m0_chan *chan, struct m0_clink *link)
Definition: chan.c:255
uint32_t sd_flags
Definition: sm.h:378
static int ha_entrypoint_fom_create(struct m0_fop *fop, struct m0_fom **m, struct m0_reqh *reqh)
Definition: entrypoint.c:920
Definition: fom.h:481
struct m0_fop_data f_data
Definition: fop.h:82
int32_t m0_rpc_item_error(const struct m0_rpc_item *item)
Definition: item.c:973
struct m0_fom ecl_fom
Definition: entrypoint.h:115
struct m0_clink ecl_clink
Definition: entrypoint.h:126
static void ha_entrypoint_server_register(struct m0_ha_entrypoint_server *hes, struct ha_entrypoint_server_fom *server_fom)
Definition: entrypoint.c:280
static struct ha_entrypoint_server_fom * ha_entrypoint_server_find(struct m0_ha_entrypoint_server *hes, const struct m0_uint128 *req_id)
Definition: entrypoint.c:264
struct m0_reqh reqh
Definition: rm_foms.c:48
M0_INTERNAL void m0_ha_entrypoint_client_start_sync(struct m0_ha_entrypoint_client *ecl)
Definition: entrypoint.c:772
int(* rsto_service_allocate)(struct m0_reqh_service **service, const struct m0_reqh_service_type *stype)
Definition: reqh_service.h:435
m0_ha_entrypoint_client_state
Definition: entrypoint.h:86
M0_INTERNAL void m0_ha_entrypoint_req_free(struct m0_ha_entrypoint_req *req)
struct m0_rpc_link ecl_rlink
Definition: entrypoint.h:109
void m0_rpc_item_put_lock(struct m0_rpc_item *item)
Definition: item.c:454
struct m0_ref f_ref
Definition: fop.h:80
M0_INTERNAL int m0_ha_entrypoint_service_init(struct m0_reqh_service **service, struct m0_reqh *reqh)
Definition: entrypoint.c:197
static int ha_entrypoint_service_allocate(struct m0_reqh_service **service, const struct m0_reqh_service_type *stype)
Definition: entrypoint.c:143
static struct ha_entrypoint_service * ha_entrypoint_service_container(struct m0_reqh_service *service)
Definition: entrypoint.c:74
M0_INTERNAL void m0_sm_init(struct m0_sm *mach, const struct m0_sm_conf *conf, uint32_t state, struct m0_sm_group *grp)
Definition: sm.c:313
#define M0_IS0(obj)
Definition: misc.h:70
M0_INTERNAL void m0_ha_entrypoint_client_fini(struct m0_ha_entrypoint_client *ecl)
Definition: entrypoint.c:464
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
struct m0_chan sm_chan
Definition: sm.h:331
M0_INTERNAL void m0_clink_add(struct m0_chan *chan, struct m0_clink *link)
Definition: chan.c:228
struct m0_ha_entrypoint_req esf_req
Definition: entrypoint.c:164
const struct m0_rpc_item_ops * ri_ops
Definition: item.h:149
m0_time_t m0_time_from_now(uint64_t secs, long ns)
Definition: time.c:96
struct m0_reqh * hsv_reqh
Definition: entrypoint.c:61
struct m0_rpc_session * ri_session
Definition: item.h:147
M0_INTERNAL void m0_ha_entrypoint_rep_free(struct m0_ha_entrypoint_rep *rep)
static void ha_entrypoint_server_deregister(struct m0_ha_entrypoint_server *hes, struct ha_entrypoint_server_fom *server_fom)
Definition: entrypoint.c:294
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
M0_INTERNAL void m0_clink_fini(struct m0_clink *link)
Definition: chan.c:208
M0_INTERNAL void m0_ha_entrypoint_fops_fini(void)
static struct m0_fop * fop
Definition: item.c:57
M0_INTERNAL void m0_ha_entrypoint_server_stop(struct m0_ha_entrypoint_server *hes)
Definition: entrypoint.c:258
M0_INTERNAL void m0_sm_group_lock(struct m0_sm_group *grp)
Definition: sm.c:83
M0_INTERNAL struct m0_chan * m0_ha_entrypoint_client_chan(struct m0_ha_entrypoint_client *ecl)
Definition: entrypoint.c:823
struct m0_fop * m0_rpc_item_to_fop(const struct m0_rpc_item *item)
Definition: fop.c:346
M0_INTERNAL void m0_fom_queue(struct m0_fom *fom)
Definition: fom.c:624
static void ha_entrypoint_service_fini(struct m0_reqh_service *service)
Definition: entrypoint.c:89
void(* fo_fini)(struct m0_fom *fom)
Definition: fom.h:657
#define M0_ASSERT_INFO(cond, fmt,...)
M0_TL_DESCR_DEFINE(hes_req, "m0_ha_entrypoint_server::hes_requests", static, struct ha_entrypoint_server_fom, esf_tlink, esf_magic, 10, 11)
struct m0_uint128 esf_req_id
Definition: entrypoint.c:165
const struct m0_fom_type_ops m0_ha_entrypoint_fom_type_ops
Definition: entrypoint.c:959
static void ha_entrypoint_client_fop_release(struct m0_ref *ref)
Definition: entrypoint.c:501
void m0_fom_phase_set(struct m0_fom *fom, int phase)
Definition: fom.c:1688
struct m0_rpc_machine * hecc_rpc_machine
Definition: entrypoint.h:103
uint64_t u_lo
Definition: types.h:37
const char * heq_git_rev_id
struct m0_rpc_machine * ri_rmachine
Definition: item.h:160
static struct m0_dtm_oper_descr reply
Definition: transmit.c:94
#define m0_tl_find(name, var, head,...)
Definition: tlist.h:757
void m0_free(void *data)
Definition: memory.c:146
Definition: mutex.h:47
M0_INTERNAL void m0_ha_entrypoint_client_start(struct m0_ha_entrypoint_client *ecl)
Definition: entrypoint.c:727
struct m0_rpc_item f_item
Definition: fop.h:83
void m0_reqh_service_type_unregister(struct m0_reqh_service_type *rstype)
Definition: reqh_service.c:490
uint32_t sm_state
Definition: sm.h:307
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
int32_t rc
Definition: trigger_fop.h:47
struct m0_sm_conf m0_ha_entrypoint_server_fom_states_conf
Definition: entrypoint.c:188
static void ha_entrypoint_service_init(struct m0_reqh_service *service)
Definition: entrypoint.c:79
#define ARRAY_SIZE(a)
Definition: misc.h:45
struct m0_mutex hsv_lock
Definition: entrypoint.c:64
static struct m0_sm_conf ha_entrypoint_client_states_conf
Definition: entrypoint.c:392
M0_INTERNAL bool m0_sm_group_is_locked(const struct m0_sm_group *grp)
Definition: sm.c:107
static const struct m0_fom_type_ops ha_entrypoint_client_fom_type_ops
Definition: entrypoint.c:697
const m0_time_t M0_TIME_IMMEDIATELY
Definition: time.c:107
Definition: fop.h:79
struct m0_uint128 hes_next_id
Definition: entrypoint.h:81
Definition: trace.h:478
M0_INTERNAL const char * m0_rpc_item_remote_ep_addr(const struct m0_rpc_item *item)
Definition: item.c:1188
m0_time_t ri_deadline
Definition: item.h:141
struct m0_fop * m0_fop_alloc(struct m0_fop_type *fopt, void *data, struct m0_rpc_machine *mach)
Definition: fop.c:96
const struct m0_reqh_service_ops * rs_ops
Definition: reqh_service.h:254
#define M0_IMPOSSIBLE(fmt,...)
M0_INTERNAL void m0_sm_fini(struct m0_sm *mach)
Definition: sm.c:331